|
@@ -2,7 +2,6 @@
|
2
|
2
|
|
3
|
3
|
import { jitsiLocalStorage } from '@jitsi/js-utils';
|
4
|
4
|
import Logger from '@jitsi/logger';
|
5
|
|
-import EventEmitter from 'events';
|
6
|
5
|
|
7
|
6
|
import { ENDPOINT_TEXT_MESSAGE_NAME } from './modules/API/constants';
|
8
|
7
|
import { AUDIO_ONLY_SCREEN_SHARE_NO_TRACK } from './modules/UI/UIErrors';
|
|
@@ -165,12 +164,9 @@ import { AudioMixerEffect } from './react/features/stream-effects/audio-mixer/Au
|
165
|
164
|
import { createRnnoiseProcessor } from './react/features/stream-effects/rnnoise';
|
166
|
165
|
import { handleToggleVideoMuted } from './react/features/toolbox/actions.any';
|
167
|
166
|
import { muteLocal } from './react/features/video-menu/actions.any';
|
168
|
|
-import UIEvents from './service/UI/UIEvents';
|
169
|
167
|
|
170
|
168
|
const logger = Logger.getLogger(__filename);
|
171
|
169
|
|
172
|
|
-const eventEmitter = new EventEmitter();
|
173
|
|
-
|
174
|
170
|
let room;
|
175
|
171
|
|
176
|
172
|
/*
|
|
@@ -1916,21 +1912,12 @@ export default {
|
1916
|
1912
|
JitsiE2ePingEvents.E2E_RTT_CHANGED,
|
1917
|
1913
|
(...args) => APP.store.dispatch(e2eRttChanged(...args)));
|
1918
|
1914
|
|
1919
|
|
- APP.UI.addListener(UIEvents.AUDIO_MUTED, muted => {
|
1920
|
|
- this.muteAudio(muted);
|
1921
|
|
- });
|
1922
|
|
- APP.UI.addListener(UIEvents.VIDEO_MUTED, (muted, showUI = false) => {
|
1923
|
|
- this.muteVideo(muted, showUI);
|
1924
|
|
- });
|
1925
|
|
-
|
1926
|
1915
|
room.addCommandListener(this.commands.defaults.ETHERPAD,
|
1927
|
1916
|
({ value }) => {
|
1928
|
1917
|
APP.UI.initEtherpad(value);
|
1929
|
1918
|
}
|
1930
|
1919
|
);
|
1931
|
1920
|
|
1932
|
|
- APP.UI.addListener(UIEvents.EMAIL_CHANGED,
|
1933
|
|
- this.changeLocalEmail.bind(this));
|
1934
|
1921
|
room.addCommandListener(this.commands.defaults.EMAIL, (data, from) => {
|
1935
|
1922
|
APP.store.dispatch(participantUpdated({
|
1936
|
1923
|
conference: room,
|
|
@@ -1950,9 +1937,6 @@ export default {
|
1950
|
1937
|
}));
|
1951
|
1938
|
});
|
1952
|
1939
|
|
1953
|
|
- APP.UI.addListener(UIEvents.NICKNAME_CHANGED,
|
1954
|
|
- this.changeLocalDisplayName.bind(this));
|
1955
|
|
-
|
1956
|
1940
|
room.on(
|
1957
|
1941
|
JitsiConferenceEvents.START_MUTED_POLICY_CHANGED,
|
1958
|
1942
|
({ audio, video }) => {
|
|
@@ -2007,113 +1991,117 @@ export default {
|
2007
|
1991
|
}, NOTIFICATION_TIMEOUT_TYPE.STICKY));
|
2008
|
1992
|
}
|
2009
|
1993
|
);
|
|
1994
|
+ },
|
2010
|
1995
|
|
2011
|
|
- // call hangup
|
2012
|
|
- APP.UI.addListener(UIEvents.HANGUP, () => {
|
2013
|
|
- this.hangup(true);
|
2014
|
|
- });
|
2015
|
|
-
|
2016
|
|
- APP.UI.addListener(
|
2017
|
|
- UIEvents.VIDEO_DEVICE_CHANGED,
|
2018
|
|
- cameraDeviceId => {
|
2019
|
|
- const videoWasMuted = this.isLocalVideoMuted();
|
2020
|
|
- const localVideoTrack = getLocalJitsiVideoTrack(APP.store.getState());
|
|
1996
|
+ /**
|
|
1997
|
+ * Handles audio device changes.
|
|
1998
|
+ *
|
|
1999
|
+ * @param {string} cameraDeviceId - The new device id.
|
|
2000
|
+ * @returns {Promise}
|
|
2001
|
+ */
|
|
2002
|
+ async onAudioDeviceChanged(micDeviceId) {
|
|
2003
|
+ const audioWasMuted = this.isLocalAudioMuted();
|
|
2004
|
+
|
|
2005
|
+ // Disable noise suppression if it was enabled on the previous track.
|
|
2006
|
+ await APP.store.dispatch(setNoiseSuppressionEnabled(false));
|
|
2007
|
+
|
|
2008
|
+ // When the 'default' mic needs to be selected, we need to pass the real device id to gUM instead of
|
|
2009
|
+ // 'default' in order to get the correct MediaStreamTrack from chrome because of the following bug.
|
|
2010
|
+ // https://bugs.chromium.org/p/chromium/issues/detail?id=997689.
|
|
2011
|
+ const isDefaultMicSelected = micDeviceId === 'default';
|
|
2012
|
+ const selectedDeviceId = isDefaultMicSelected
|
|
2013
|
+ ? getDefaultDeviceId(APP.store.getState(), 'audioInput')
|
|
2014
|
+ : micDeviceId;
|
|
2015
|
+
|
|
2016
|
+ logger.info(`Switching audio input device to ${selectedDeviceId}`);
|
|
2017
|
+ sendAnalytics(createDeviceChangedEvent('audio', 'input'));
|
|
2018
|
+ createLocalTracksF({
|
|
2019
|
+ devices: [ 'audio' ],
|
|
2020
|
+ micDeviceId: selectedDeviceId
|
|
2021
|
+ })
|
|
2022
|
+ .then(([ stream ]) => {
|
|
2023
|
+ // if audio was muted before changing the device, mute
|
|
2024
|
+ // with the new device
|
|
2025
|
+ if (audioWasMuted) {
|
|
2026
|
+ return stream.mute()
|
|
2027
|
+ .then(() => stream);
|
|
2028
|
+ }
|
2021
|
2029
|
|
2022
|
|
- if (localVideoTrack?.getDeviceId() === cameraDeviceId) {
|
2023
|
|
- return;
|
2024
|
|
- }
|
|
2030
|
+ return stream;
|
|
2031
|
+ })
|
|
2032
|
+ .then(async stream => {
|
|
2033
|
+ await this._maybeApplyAudioMixerEffect(stream);
|
2025
|
2034
|
|
2026
|
|
- sendAnalytics(createDeviceChangedEvent('video', 'input'));
|
|
2035
|
+ return this.useAudioStream(stream);
|
|
2036
|
+ })
|
|
2037
|
+ .then(() => {
|
|
2038
|
+ const localAudio = getLocalJitsiAudioTrack(APP.store.getState());
|
2027
|
2039
|
|
2028
|
|
- createLocalTracksF({
|
2029
|
|
- devices: [ 'video' ],
|
2030
|
|
- cameraDeviceId
|
2031
|
|
- })
|
2032
|
|
- .then(([ stream ]) => {
|
2033
|
|
- // if we are in audio only mode or video was muted before
|
2034
|
|
- // changing device, then mute
|
2035
|
|
- if (this.isAudioOnly() || videoWasMuted) {
|
2036
|
|
- return stream.mute()
|
2037
|
|
- .then(() => stream);
|
2038
|
|
- }
|
|
2040
|
+ if (localAudio && isDefaultMicSelected) {
|
|
2041
|
+ // workaround for the default device to be shown as selected in the
|
|
2042
|
+ // settings even when the real device id was passed to gUM because of the
|
|
2043
|
+ // above mentioned chrome bug.
|
|
2044
|
+ localAudio._realDeviceId = localAudio.deviceId = 'default';
|
|
2045
|
+ }
|
|
2046
|
+ })
|
|
2047
|
+ .catch(err => {
|
|
2048
|
+ logger.error(`Failed to switch to selected audio input device ${selectedDeviceId}, error=${err}`);
|
|
2049
|
+ APP.store.dispatch(notifyMicError(err));
|
|
2050
|
+ });
|
|
2051
|
+ },
|
2039
|
2052
|
|
2040
|
|
- return stream;
|
2041
|
|
- })
|
2042
|
|
- .then(stream => {
|
2043
|
|
- logger.info(`Switching the local video device to ${cameraDeviceId}.`);
|
|
2053
|
+ /**
|
|
2054
|
+ * Handles video device changes.
|
|
2055
|
+ *
|
|
2056
|
+ * @param {string} cameraDeviceId - The new device id.
|
|
2057
|
+ * @returns {void}
|
|
2058
|
+ */
|
|
2059
|
+ onVideoDeviceChanged(cameraDeviceId) {
|
|
2060
|
+ const videoWasMuted = this.isLocalVideoMuted();
|
|
2061
|
+ const localVideoTrack = getLocalJitsiVideoTrack(APP.store.getState());
|
2044
|
2062
|
|
2045
|
|
- return this.useVideoStream(stream);
|
2046
|
|
- })
|
2047
|
|
- .catch(error => {
|
2048
|
|
- logger.error(`Failed to switch to selected camera:${cameraDeviceId}, error:${error}`);
|
|
2063
|
+ if (localVideoTrack?.getDeviceId() === cameraDeviceId) {
|
|
2064
|
+ return;
|
|
2065
|
+ }
|
2049
|
2066
|
|
2050
|
|
- return APP.store.dispatch(notifyCameraError(error));
|
2051
|
|
- });
|
|
2067
|
+ sendAnalytics(createDeviceChangedEvent('video', 'input'));
|
|
2068
|
+
|
|
2069
|
+ createLocalTracksF({
|
|
2070
|
+ devices: [ 'video' ],
|
|
2071
|
+ cameraDeviceId
|
|
2072
|
+ })
|
|
2073
|
+ .then(([ stream ]) => {
|
|
2074
|
+ // if we are in audio only mode or video was muted before
|
|
2075
|
+ // changing device, then mute
|
|
2076
|
+ if (this.isAudioOnly() || videoWasMuted) {
|
|
2077
|
+ return stream.mute()
|
|
2078
|
+ .then(() => stream);
|
2052
|
2079
|
}
|
2053
|
|
- );
|
2054
|
2080
|
|
2055
|
|
- APP.UI.addListener(
|
2056
|
|
- UIEvents.AUDIO_DEVICE_CHANGED,
|
2057
|
|
- async micDeviceId => {
|
2058
|
|
- const audioWasMuted = this.isLocalAudioMuted();
|
2059
|
|
-
|
2060
|
|
- // Disable noise suppression if it was enabled on the previous track.
|
2061
|
|
- await APP.store.dispatch(setNoiseSuppressionEnabled(false));
|
2062
|
|
-
|
2063
|
|
- // When the 'default' mic needs to be selected, we need to pass the real device id to gUM instead of
|
2064
|
|
- // 'default' in order to get the correct MediaStreamTrack from chrome because of the following bug.
|
2065
|
|
- // https://bugs.chromium.org/p/chromium/issues/detail?id=997689.
|
2066
|
|
- const isDefaultMicSelected = micDeviceId === 'default';
|
2067
|
|
- const selectedDeviceId = isDefaultMicSelected
|
2068
|
|
- ? getDefaultDeviceId(APP.store.getState(), 'audioInput')
|
2069
|
|
- : micDeviceId;
|
2070
|
|
-
|
2071
|
|
- logger.info(`Switching audio input device to ${selectedDeviceId}`);
|
2072
|
|
- sendAnalytics(createDeviceChangedEvent('audio', 'input'));
|
2073
|
|
- createLocalTracksF({
|
2074
|
|
- devices: [ 'audio' ],
|
2075
|
|
- micDeviceId: selectedDeviceId
|
2076
|
|
- })
|
2077
|
|
- .then(([ stream ]) => {
|
2078
|
|
- // if audio was muted before changing the device, mute
|
2079
|
|
- // with the new device
|
2080
|
|
- if (audioWasMuted) {
|
2081
|
|
- return stream.mute()
|
2082
|
|
- .then(() => stream);
|
2083
|
|
- }
|
|
2081
|
+ return stream;
|
|
2082
|
+ })
|
|
2083
|
+ .then(stream => {
|
|
2084
|
+ logger.info(`Switching the local video device to ${cameraDeviceId}.`);
|
2084
|
2085
|
|
2085
|
|
- return stream;
|
2086
|
|
- })
|
2087
|
|
- .then(async stream => {
|
2088
|
|
- await this._maybeApplyAudioMixerEffect(stream);
|
|
2086
|
+ return this.useVideoStream(stream);
|
|
2087
|
+ })
|
|
2088
|
+ .catch(error => {
|
|
2089
|
+ logger.error(`Failed to switch to selected camera:${cameraDeviceId}, error:${error}`);
|
2089
|
2090
|
|
2090
|
|
- return this.useAudioStream(stream);
|
2091
|
|
- })
|
2092
|
|
- .then(() => {
|
2093
|
|
- const localAudio = getLocalJitsiAudioTrack(APP.store.getState());
|
2094
|
|
-
|
2095
|
|
- if (localAudio && isDefaultMicSelected) {
|
2096
|
|
- // workaround for the default device to be shown as selected in the
|
2097
|
|
- // settings even when the real device id was passed to gUM because of the
|
2098
|
|
- // above mentioned chrome bug.
|
2099
|
|
- localAudio._realDeviceId = localAudio.deviceId = 'default';
|
2100
|
|
- }
|
2101
|
|
- })
|
2102
|
|
- .catch(err => {
|
2103
|
|
- logger.error(`Failed to switch to selected audio input device ${selectedDeviceId}, error=${err}`);
|
2104
|
|
- APP.store.dispatch(notifyMicError(err));
|
2105
|
|
- });
|
2106
|
|
- }
|
2107
|
|
- );
|
|
2091
|
+ return APP.store.dispatch(notifyCameraError(error));
|
|
2092
|
+ });
|
|
2093
|
+ },
|
2108
|
2094
|
|
2109
|
|
- APP.UI.addListener(UIEvents.TOGGLE_AUDIO_ONLY, () => {
|
2110
|
|
- // Immediately update the UI by having remote videos and the large video update themselves.
|
2111
|
|
- const displayedUserId = APP.UI.getLargeVideoID();
|
|
2095
|
+ /**
|
|
2096
|
+ * Handles audio only changes.
|
|
2097
|
+ */
|
|
2098
|
+ onToggleAudioOnly() {
|
|
2099
|
+ // Immediately update the UI by having remote videos and the large video update themselves.
|
|
2100
|
+ const displayedUserId = APP.UI.getLargeVideoID();
|
2112
|
2101
|
|
2113
|
|
- if (displayedUserId) {
|
2114
|
|
- APP.UI.updateLargeVideo(displayedUserId, true);
|
2115
|
|
- }
|
2116
|
|
- });
|
|
2102
|
+ if (displayedUserId) {
|
|
2103
|
+ APP.UI.updateLargeVideo(displayedUserId, true);
|
|
2104
|
+ }
|
2117
|
2105
|
},
|
2118
|
2106
|
|
2119
|
2107
|
/**
|
|
@@ -2408,8 +2396,6 @@ export default {
|
2408
|
2396
|
this.deviceChangeListener);
|
2409
|
2397
|
}
|
2410
|
2398
|
|
2411
|
|
- APP.UI.removeAllListeners();
|
2412
|
|
-
|
2413
|
2399
|
let feedbackResultPromise = Promise.resolve({});
|
2414
|
2400
|
|
2415
|
2401
|
if (requestFeedback) {
|
|
@@ -2516,37 +2502,6 @@ export default {
|
2516
|
2502
|
room.sendEndpointMessage(to, payload);
|
2517
|
2503
|
},
|
2518
|
2504
|
|
2519
|
|
- /**
|
2520
|
|
- * Adds new listener.
|
2521
|
|
- * @param {String} eventName the name of the event
|
2522
|
|
- * @param {Function} listener the listener.
|
2523
|
|
- */
|
2524
|
|
- addListener(eventName, listener) {
|
2525
|
|
- eventEmitter.addListener(eventName, listener);
|
2526
|
|
- },
|
2527
|
|
-
|
2528
|
|
- /**
|
2529
|
|
- * Removes listener.
|
2530
|
|
- * @param {String} eventName the name of the event that triggers the
|
2531
|
|
- * listener
|
2532
|
|
- * @param {Function} listener the listener.
|
2533
|
|
- */
|
2534
|
|
- removeListener(eventName, listener) {
|
2535
|
|
- eventEmitter.removeListener(eventName, listener);
|
2536
|
|
- },
|
2537
|
|
-
|
2538
|
|
- /**
|
2539
|
|
- * Changes the display name for the local user
|
2540
|
|
- * @param nickname {string} the new display name
|
2541
|
|
- */
|
2542
|
|
- changeLocalDisplayName(nickname = '') {
|
2543
|
|
- const formattedNickname = getNormalizedDisplayName(nickname);
|
2544
|
|
-
|
2545
|
|
- APP.store.dispatch(updateSettings({
|
2546
|
|
- displayName: formattedNickname
|
2547
|
|
- }));
|
2548
|
|
- },
|
2549
|
|
-
|
2550
|
2505
|
/**
|
2551
|
2506
|
* Callback invoked by the external api create or update a direct connection
|
2552
|
2507
|
* from the local client to an external client.
|