Browse Source

fix(tracks): Do not signal muted audio tracks.

Do not add the muted audio tracks to peerconnection until the user unmutes the first time. This applies to startSilent, startWithAudioMuted and startAudioMuted/startVideoMuted config.js settings.
j8
Jaya Allamsetty 4 years ago
parent
commit
dcda89012e
No account linked to committer's email address
3 changed files with 62 additions and 32 deletions
  1. 36
    14
      conference.js
  2. 18
    10
      react/features/base/conference/actions.js
  3. 8
    8
      react/features/prejoin/middleware.js

+ 36
- 14
conference.js View File

@@ -99,6 +99,7 @@ import {
99 99
     destroyLocalTracks,
100 100
     getLocalJitsiAudioTrack,
101 101
     getLocalJitsiVideoTrack,
102
+    getLocalTracks,
102 103
     isLocalCameraTrackMuted,
103 104
     isLocalTrackMuted,
104 105
     isUserInteractionRequiredForUnmute,
@@ -473,18 +474,13 @@ export default {
473 474
      */
474 475
     createInitialLocalTracks(options = {}) {
475 476
         const errors = {};
477
+
478
+        // Always get a handle on the audio input device so that we have statistics (such as "No audio input" or
479
+        // "Are you trying to speak?" ) even if the user joins the conference muted.
476 480
         const initialDevices = config.disableInitialGUM ? [] : [ 'audio' ];
477 481
         const requestedAudio = !config.disableInitialGUM;
478 482
         let requestedVideo = false;
479 483
 
480
-        // Always get a handle on the audio input device so that we have statistics even if the user joins the
481
-        // conference muted. Previous implementation would only acquire the handle when the user first unmuted,
482
-        // which would results in statistics ( such as "No audio input" or "Are you trying to speak?") being available
483
-        // only after that point.
484
-        if (options.startWithAudioMuted) {
485
-            this.muteAudio(true, true);
486
-        }
487
-
488 484
         if (!config.disableInitialGUM
489 485
                 && !options.startWithVideoMuted
490 486
                 && !options.startAudioOnly
@@ -824,12 +820,16 @@ export default {
824 820
             return this._setLocalAudioVideoStreams(tracks);
825 821
         }
826 822
 
827
-        const [ tracks, con ] = await this.createInitialLocalTracksAndConnect(
828
-            roomName, initialOptions);
823
+        const [ tracks, con ] = await this.createInitialLocalTracksAndConnect(roomName, initialOptions);
824
+        let localTracks = tracks;
829 825
 
830 826
         this._initDeviceList(true);
831 827
 
832
-        return this.startConference(con, tracks);
828
+        if (initialOptions.startWithAudioMuted) {
829
+            localTracks = localTracks.filter(track => track.getType() !== MEDIA_TYPE.AUDIO);
830
+        }
831
+
832
+        return this.startConference(con, localTracks);
833 833
     },
834 834
 
835 835
     /**
@@ -1320,7 +1320,11 @@ export default {
1320 1320
                 this._getConferenceOptions());
1321 1321
 
1322 1322
         APP.store.dispatch(conferenceWillJoin(room));
1323
-        this._setLocalAudioVideoStreams(localTracks);
1323
+
1324
+        // Filter out the tracks that are muted.
1325
+        const tracks = localTracks.filter(track => !track.isMuted());
1326
+
1327
+        this._setLocalAudioVideoStreams(tracks);
1324 1328
         this._room = room; // FIXME do not use this
1325 1329
 
1326 1330
         sendLocalParticipant(APP.store, room);
@@ -2163,8 +2167,26 @@ export default {
2163 2167
             }
2164 2168
         );
2165 2169
         room.on(JitsiConferenceEvents.STARTED_MUTED, () => {
2166
-            (room.isStartAudioMuted() || room.isStartVideoMuted())
2167
-                && APP.UI.notifyInitiallyMuted();
2170
+            const audioMuted = room.isStartAudioMuted();
2171
+            const videoMuted = room.isStartVideoMuted();
2172
+            const localTracks = getLocalTracks(APP.store.getState()['features/base/tracks']);
2173
+            const promises = [];
2174
+
2175
+            APP.store.dispatch(setAudioMuted(audioMuted));
2176
+            APP.store.dispatch(setVideoMuted(videoMuted));
2177
+
2178
+            // Remove the tracks from the peerconnection.
2179
+            for (const track of localTracks) {
2180
+                if (audioMuted && track.jitsiTrack?.getType() === MEDIA_TYPE.AUDIO) {
2181
+                    promises.push(this.useAudioStream(null));
2182
+                }
2183
+                if (videoMuted && track.jitsiTrack?.getType() === MEDIA_TYPE.VIDEO) {
2184
+                    promises.push(this.useVideoStream(null));
2185
+                }
2186
+            }
2187
+
2188
+            Promise.allSettled(promises)
2189
+                .then(() => APP.UI.notifyInitiallyMuted());
2168 2190
         });
2169 2191
 
2170 2192
         room.on(

+ 18
- 10
react/features/base/conference/actions.js View File

@@ -10,7 +10,7 @@ import { getName } from '../../app/functions';
10 10
 import { endpointMessageReceived } from '../../subtitles';
11 11
 import { JITSI_CONNECTION_CONFERENCE_KEY } from '../connection';
12 12
 import { JitsiConferenceEvents } from '../lib-jitsi-meet';
13
-import { setAudioMuted, setVideoMuted } from '../media';
13
+import { MEDIA_TYPE, setAudioMuted, setVideoMuted } from '../media';
14 14
 import {
15 15
     dominantSpeakerChanged,
16 16
     getLocalParticipant,
@@ -22,7 +22,7 @@ import {
22 22
     participantRoleChanged,
23 23
     participantUpdated
24 24
 } from '../participants';
25
-import { getLocalTracks, trackAdded, trackRemoved } from '../tracks';
25
+import { getLocalTracks, replaceLocalTrack, trackAdded, trackRemoved } from '../tracks';
26 26
 import {
27 27
     getBackendSafePath,
28 28
     getBackendSafeRoomName,
@@ -72,10 +72,11 @@ declare var APP: Object;
72 72
  *
73 73
  * @param {JitsiConference} conference - The JitsiConference instance.
74 74
  * @param {Dispatch} dispatch - The Redux dispatch function.
75
+ * @param {Object} state - The Redux state.
75 76
  * @private
76 77
  * @returns {void}
77 78
  */
78
-function _addConferenceListeners(conference, dispatch) {
79
+function _addConferenceListeners(conference, dispatch, state) {
79 80
     // A simple logger for conference errors received through
80 81
     // the listener. These errors are not handled now, but logged.
81 82
     conference.on(JitsiConferenceEvents.CONFERENCE_ERROR,
@@ -118,13 +119,12 @@ function _addConferenceListeners(conference, dispatch) {
118 119
     conference.on(
119 120
         JitsiConferenceEvents.STARTED_MUTED,
120 121
         () => {
121
-            const audioMuted = Boolean(conference.startAudioMuted);
122
-            const videoMuted = Boolean(conference.startVideoMuted);
122
+            const audioMuted = Boolean(conference.isStartAudioMuted());
123
+            const videoMuted = Boolean(conference.isStartVideoMuted());
124
+            const localTracks = getLocalTracks(state['features/base/tracks']);
123 125
 
124
-            sendAnalytics(createStartMutedConfigurationEvent(
125
-                'remote', audioMuted, videoMuted));
126
-            logger.log(`Start muted: ${audioMuted ? 'audio, ' : ''}${
127
-                videoMuted ? 'video' : ''}`);
126
+            sendAnalytics(createStartMutedConfigurationEvent('remote', audioMuted, videoMuted));
127
+            logger.log(`Start muted: ${audioMuted ? 'audio, ' : ''}${videoMuted ? 'video' : ''}`);
128 128
 
129 129
             // XXX Jicofo tells lib-jitsi-meet to start with audio and/or video
130 130
             // muted i.e. Jicofo expresses an intent. Lib-jitsi-meet has turned
@@ -136,6 +136,14 @@ function _addConferenceListeners(conference, dispatch) {
136 136
             // acting on Jicofo's intent without the app's knowledge.
137 137
             dispatch(setAudioMuted(audioMuted));
138 138
             dispatch(setVideoMuted(videoMuted));
139
+
140
+            // Remove the tracks from peerconnection as well.
141
+            for (const track of localTracks) {
142
+                if ((audioMuted && track.jitsiTrack.getType() === MEDIA_TYPE.AUDIO)
143
+                    || (videoMuted && track.jitsiTrack.getType() === MEDIA_TYPE.VIDEO)) {
144
+                    replaceLocalTrack(track.jitsiTrack, null, conference);
145
+                }
146
+            }
139 147
         });
140 148
 
141 149
     // Dispatches into features/base/tracks follow:
@@ -448,7 +456,7 @@ export function createConference() {
448 456
 
449 457
         dispatch(_conferenceWillJoin(conference));
450 458
 
451
-        _addConferenceListeners(conference, dispatch);
459
+        _addConferenceListeners(conference, dispatch, state);
452 460
 
453 461
         sendLocalParticipant(state, conference);
454 462
 

+ 8
- 8
react/features/prejoin/middleware.js View File

@@ -5,7 +5,7 @@ import { SET_AUDIO_MUTED, SET_VIDEO_MUTED } from '../base/media';
5 5
 import { MiddlewareRegistry } from '../base/redux';
6 6
 import { updateSettings } from '../base/settings';
7 7
 import {
8
-    getLocalVideoTrack,
8
+    getLocalTracks,
9 9
     replaceLocalTrack,
10 10
     TRACK_ADDED,
11 11
     TRACK_NO_DATA_FROM_SOURCE
@@ -33,7 +33,7 @@ MiddlewareRegistry.register(store => next => async action => {
33 33
         const { getState, dispatch } = store;
34 34
         const state = getState();
35 35
         const { userSelectedSkipPrejoin } = state['features/prejoin'];
36
-        const localVideoTrack = getLocalVideoTrack(state['features/base/tracks']);
36
+        const localTracks = getLocalTracks(state['features/base/tracks']);
37 37
         const { options } = action;
38 38
 
39 39
         options && store.dispatch(updateConfig(options));
@@ -42,13 +42,13 @@ MiddlewareRegistry.register(store => next => async action => {
42 42
             userSelectedSkipPrejoin
43 43
         }));
44 44
 
45
-        if (localVideoTrack?.muted) {
46
-            await dispatch(replaceLocalTrack(localVideoTrack.jitsiTrack, null));
45
+        // Do not signal audio/video tracks if the user joins muted.
46
+        for (const track of localTracks) {
47
+            if (track.muted) {
48
+                await dispatch(replaceLocalTrack(track.jitsiTrack, null));
49
+            }
47 50
         }
48
-
49
-        const jitsiTracks = getState()['features/base/tracks']
50
-            .map(t => t.jitsiTrack)
51
-            .filter(t => Boolean(t)); // Filter out GUM in progress tracks...
51
+        const jitsiTracks = localTracks.map(t => t.jitsiTrack);
52 52
 
53 53
         dispatch(setPrejoinPageVisibility(false));
54 54
         APP.conference.prejoinStart(jitsiTracks);

Loading…
Cancel
Save