Просмотр исходного кода

fix(conference) Fix different bugs with startMuted policy. (#2777)

* fix(conference) Fix different bugs with startMuted policy.
If the user changes mute state after joining the call and before the other participats join the call, make sure those state changes are honored.

* feat(startMuted) Ignore startMuted in Jingle from focus.
Apply startMuted policy based on startMuted setting in room meta data.
Moderator settings and AV moderation settings will now be propagated to new endpoints joining the call through room meta data.
Advertise a new capability 'start-muted-room-metadata' to Jicofo for feature detection.
master
Jaya Allamsetty 5 месяцев назад
Родитель
Сommit
575f6738a5
Аккаунт пользователя с таким Email не найден

+ 31
- 60
JitsiConference.js Просмотреть файл

@@ -187,8 +187,6 @@ export default function JitsiConference(options) {
187 187
     this.dtmfManager = null;
188 188
     this.somebodySupportsDTMF = false;
189 189
     this.authEnabled = false;
190
-    this.startAudioMuted = false;
191
-    this.startVideoMuted = false;
192 190
     this.startMutedPolicy = {
193 191
         audio: false,
194 192
         video: false
@@ -1238,38 +1236,6 @@ JitsiConference.prototype._fireMuteChangeEvent = function(track) {
1238 1236
     this.eventEmitter.emit(JitsiConferenceEvents.TRACK_MUTE_CHANGED, track, actorParticipant);
1239 1237
 };
1240 1238
 
1241
-/**
1242
- * Returns the list of local tracks that need to be added to the peerconnection on join.
1243
- * This takes the startAudioMuted/startVideoMuted flags into consideration since we do not
1244
- * want to add the tracks if the user joins the call audio/video muted. The tracks will be
1245
- * added when the user unmutes for the first time.
1246
- * @returns {Array<JitsiLocalTrack>} - list of local tracks that are unmuted.
1247
- */
1248
-JitsiConference.prototype._getInitialLocalTracks = function() {
1249
-    // Always add the audio track on certain platforms:
1250
-    //  * Safari / WebKit: because of a known issue where audio playout doesn't happen
1251
-    //    if the user joins audio and video muted.
1252
-    //  * React Native: after iOS 15, if a user joins muted they won't be able to unmute.
1253
-    return this.getLocalTracks()
1254
-        .filter(track => {
1255
-            const trackType = track.getType();
1256
-
1257
-            if (trackType === MediaType.AUDIO
1258
-                    && (!(this.isStartAudioMuted() || this.startMutedPolicy.audio)
1259
-                    || browser.isWebKitBased()
1260
-                    || browser.isReactNative())) {
1261
-                return true;
1262
-            } else if (trackType === MediaType.VIDEO && !this.isStartVideoMuted() && !this.startMutedPolicy.video) {
1263
-                return true;
1264
-            }
1265
-
1266
-            // Remove the track from the conference.
1267
-            this.onLocalTrackRemoved(track);
1268
-
1269
-            return false;
1270
-        });
1271
-};
1272
-
1273 1239
 /**
1274 1240
  * Clear JitsiLocalTrack properties and listeners.
1275 1241
  * @param track the JitsiLocalTrack object.
@@ -1834,6 +1800,31 @@ JitsiConference.prototype.onMemberJoined = function(
1834 1800
     }
1835 1801
 
1836 1802
     this._maybeSetSITimeout();
1803
+    const { startAudioMuted, startVideoMuted } = this.options.config;
1804
+
1805
+    // Ignore startAudio/startVideoMuted settings if the media session has already been established.
1806
+    // Apply the policy if the number of participants exceeds the startMuted thresholds.
1807
+    if ((this.jvbJingleSession && this.getActiveMediaSession() === this.jvbJingleSession)
1808
+        || ((typeof startAudioMuted === 'undefined' || startAudioMuted === -1)
1809
+            && (typeof startVideoMuted === 'undefined' || startVideoMuted === -1))) {
1810
+        return;
1811
+    }
1812
+
1813
+    let audioMuted = false;
1814
+    let videoMuted = false;
1815
+    const numberOfParticipants = this.getParticipantCount();
1816
+
1817
+    if (numberOfParticipants > this.options.config.startAudioMuted) {
1818
+        audioMuted = true;
1819
+    }
1820
+
1821
+    if (numberOfParticipants > this.options.config.startVideoMuted) {
1822
+        videoMuted = true;
1823
+    }
1824
+
1825
+    if ((audioMuted && !this.startMutedPolicy.audio) || (videoMuted && !this.startMutedPolicy.video)) {
1826
+        this._updateStartMutedPolicy(audioMuted, videoMuted);
1827
+    }
1837 1828
 };
1838 1829
 
1839 1830
 /* eslint-enable max-params */
@@ -2282,7 +2273,7 @@ JitsiConference.prototype._acceptJvbIncomingCall = function(jingleSession, jingl
2282 2273
     // Open a channel with the videobridge.
2283 2274
     this._setBridgeChannel(jingleOffer, jingleSession.peerconnection);
2284 2275
 
2285
-    const localTracks = this._getInitialLocalTracks();
2276
+    const localTracks = this.getLocalTracks();
2286 2277
 
2287 2278
     try {
2288 2279
         jingleSession.acceptOffer(
@@ -2653,11 +2644,9 @@ JitsiConference.prototype.setStartMutedPolicy = function(policy) {
2653 2644
         return;
2654 2645
     }
2655 2646
 
2656
-    // Do not apply the startMutedPolicy locally on the moderator, the moderator should join with available local
2657
-    // sources and the policy needs to be applied only on users that join the call after.
2658
-    // this.startMutedPolicy = policy;
2659
-    // TODO: to remove using presence for startmuted policy after old clients update
2660
-    // we keep presence to update UI of old clients
2647
+    logger.info(`Setting start muted policy: ${JSON.stringify(policy)} in presence and in conference metadata`);
2648
+
2649
+    // TODO: to remove using presence for startmuted policy after old clients update to using metadata always.
2661 2650
     this.room.addOrReplaceInPresence('startmuted', {
2662 2651
         attributes: {
2663 2652
             audio: policy.audio,
@@ -2666,9 +2655,6 @@ JitsiConference.prototype.setStartMutedPolicy = function(policy) {
2666 2655
         }
2667 2656
     }) && this.room.sendPresence();
2668 2657
 
2669
-    // we want to ignore applying startMutedPolicy locally when we set it
2670
-    this._ignoreFirstStartMutedPolicyUpdate = true;
2671
-
2672 2658
     this.getMetadataHandler().setMetadata('startMuted', {
2673 2659
         audio: policy.audio,
2674 2660
         video: policy.video
@@ -2682,9 +2668,8 @@ JitsiConference.prototype.setStartMutedPolicy = function(policy) {
2682 2668
  * @param {boolean} video if video should be muted.
2683 2669
  */
2684 2670
 JitsiConference.prototype._updateStartMutedPolicy = function(audio, video) {
2685
-    if (this._ignoreFirstStartMutedPolicyUpdate) {
2686
-        this._ignoreFirstStartMutedPolicyUpdate = false;
2687
-
2671
+    // Update the start muted policy for the conference only if the meta data is received before conference join.
2672
+    if (this.isJoined()) {
2688 2673
         return;
2689 2674
     }
2690 2675
 
@@ -2716,20 +2701,6 @@ JitsiConference.prototype.getStartMutedPolicy = function() {
2716 2701
     return this.startMutedPolicy;
2717 2702
 };
2718 2703
 
2719
-/**
2720
- * Check if audio is muted on join.
2721
- */
2722
-JitsiConference.prototype.isStartAudioMuted = function() {
2723
-    return this.startAudioMuted;
2724
-};
2725
-
2726
-/**
2727
- * Check if video is muted on join.
2728
- */
2729
-JitsiConference.prototype.isStartVideoMuted = function() {
2730
-    return this.startVideoMuted;
2731
-};
2732
-
2733 2704
 /**
2734 2705
  * Returns measured connectionTimes.
2735 2706
  */

+ 6
- 37
JitsiConferenceEventManager.js Просмотреть файл

@@ -406,10 +406,12 @@ JitsiConferenceEventManager.prototype.setupChatRoomListeners = function() {
406 406
     // Room metadata.
407 407
     chatRoom.addListener(XMPPEvents.ROOM_METADATA_UPDATED, metadata => {
408 408
         if (metadata.startMuted) {
409
-            conference._updateStartMutedPolicy(
410
-                metadata.startMuted.audio || false,
411
-                metadata.startMuted.video || false
412
-            );
409
+            const audio = metadata.startMuted.audio || false;
410
+            const video = metadata.startMuted.video || false;
411
+
412
+            audio && (conference.isMutedByFocus = true);
413
+            video && (conference.isVideoMutedByFocus = true);
414
+            conference._updateStartMutedPolicy(audio, video);
413 415
         }
414 416
         conference.eventEmitter.emit(JitsiConferenceEvents.METADATA_UPDATED, metadata);
415 417
     });
@@ -552,39 +554,6 @@ JitsiConferenceEventManager.prototype.setupXMPPListeners = function() {
552 554
         XMPPEvents.CALL_ENDED,
553 555
         conference.onCallEnded.bind(conference));
554 556
 
555
-    this._addConferenceXMPPListener(XMPPEvents.START_MUTED_FROM_FOCUS,
556
-        (audioMuted, videoMuted) => {
557
-            if (conference.options.config.ignoreStartMuted) {
558
-                return;
559
-            }
560
-
561
-            conference.startAudioMuted = audioMuted;
562
-            conference.startVideoMuted = videoMuted;
563
-
564
-            if (audioMuted) {
565
-                conference.isMutedByFocus = true;
566
-            }
567
-
568
-            if (videoMuted) {
569
-                conference.isVideoMutedByFocus = true;
570
-            }
571
-
572
-            // mute existing local tracks because this is initial mute from
573
-            // Jicofo
574
-            conference.getLocalTracks().forEach(track => {
575
-                switch (track.getType()) {
576
-                case MediaType.AUDIO:
577
-                    conference.startAudioMuted && track.mute();
578
-                    break;
579
-                case MediaType.VIDEO:
580
-                    conference.startVideoMuted && track.mute();
581
-                    break;
582
-                }
583
-            });
584
-
585
-            conference.eventEmitter.emit(JitsiConferenceEvents.STARTED_MUTED);
586
-        });
587
-
588 557
     this._addConferenceXMPPListener(XMPPEvents.AV_MODERATION_CHANGED,
589 558
         (value, mediaType, actorJid) => {
590 559
             const actorParticipant = conference.getParticipants().find(p => p.getJid() === actorJid);

+ 0
- 3
JitsiConferenceEvents.spec.ts Просмотреть файл

@@ -58,7 +58,6 @@ describe( "/JitsiConferenceEvents members", () => {
58 58
         VIDEO_SIP_GW_AVAILABILITY_CHANGED,
59 59
         VIDEO_SIP_GW_SESSION_STATE_CHANGED,
60 60
         START_MUTED_POLICY_CHANGED,
61
-        STARTED_MUTED,
62 61
         SUBJECT_CHANGED,
63 62
         SUSPEND_DETECTED,
64 63
         TALK_WHILE_MUTED,
@@ -146,7 +145,6 @@ describe( "/JitsiConferenceEvents members", () => {
146 145
         expect( VIDEO_SIP_GW_SESSION_STATE_CHANGED ).toBe( 'conference.videoSIPGWSessionStateChanged' );
147 146
         expect( VISITORS_SUPPORTED_CHANGED ).toBe( 'conference.visitorsSupported' );
148 147
         expect( START_MUTED_POLICY_CHANGED ).toBe( 'conference.start_muted_policy_changed' );
149
-        expect( STARTED_MUTED ).toBe( 'conference.started_muted' );
150 148
         expect( SUBJECT_CHANGED ).toBe( 'conference.subjectChanged' );
151 149
         expect( SUSPEND_DETECTED ).toBe( 'conference.suspendDetected' );
152 150
         expect( TALK_WHILE_MUTED ).toBe( 'conference.talk_while_muted' );
@@ -227,7 +225,6 @@ describe( "/JitsiConferenceEvents members", () => {
227 225
         expect( JitsiConferenceEvents.VIDEO_SIP_GW_AVAILABILITY_CHANGED ).toBe( 'conference.videoSIPGWAvailabilityChanged' );
228 226
         expect( JitsiConferenceEvents.VIDEO_SIP_GW_SESSION_STATE_CHANGED ).toBe( 'conference.videoSIPGWSessionStateChanged' );
229 227
         expect( JitsiConferenceEvents.START_MUTED_POLICY_CHANGED ).toBe( 'conference.start_muted_policy_changed' );
230
-        expect( JitsiConferenceEvents.STARTED_MUTED ).toBe( 'conference.started_muted' );
231 228
         expect( JitsiConferenceEvents.SUBJECT_CHANGED ).toBe( 'conference.subjectChanged' );
232 229
         expect( JitsiConferenceEvents.SUSPEND_DETECTED ).toBe( 'conference.suspendDetected' );
233 230
         expect( JitsiConferenceEvents.TALK_WHILE_MUTED ).toBe( 'conference.talk_while_muted' );

+ 0
- 6
JitsiConferenceEvents.ts Просмотреть файл

@@ -371,11 +371,6 @@ export enum JitsiConferenceEvents {
371 371
      */
372 372
     SILENT_STATUS_CHANGED = 'conference.silentStatusChanged',
373 373
 
374
-    /**
375
-     * Indicates that the local user has started muted.
376
-     */
377
-    STARTED_MUTED = 'conference.started_muted',
378
-
379 374
     /**
380 375
      * Indicates that start muted settings changed.
381 376
      */
@@ -582,7 +577,6 @@ export const RECORDER_STATE_CHANGED = JitsiConferenceEvents.RECORDER_STATE_CHANG
582 577
 export const SERVER_REGION_CHANGED = JitsiConferenceEvents.SERVER_REGION_CHANGED;
583 578
 export const SILENT_STATUS_CHANGED = JitsiConferenceEvents.SILENT_STATUS_CHANGED;
584 579
 export const START_MUTED_POLICY_CHANGED = JitsiConferenceEvents.START_MUTED_POLICY_CHANGED;
585
-export const STARTED_MUTED = JitsiConferenceEvents.STARTED_MUTED;
586 580
 export const SUBJECT_CHANGED = JitsiConferenceEvents.SUBJECT_CHANGED;
587 581
 export const SUSPEND_DETECTED = JitsiConferenceEvents.SUSPEND_DETECTED;
588 582
 export const TALK_WHILE_MUTED = JitsiConferenceEvents.TALK_WHILE_MUTED;

+ 1
- 0
modules/xmpp/RoomMetadata.ts Просмотреть файл

@@ -95,6 +95,7 @@ export default class RoomMetadata {
95 95
         }
96 96
 
97 97
         this._metadata = metadata;
98
+        logger.debug('Received metadata update', metadata);
98 99
         this.room.eventEmitter.emit(XMPPEvents.ROOM_METADATA_UPDATED, metadata);
99 100
     }
100 101
 

+ 0
- 11
modules/xmpp/strophe.jingle.js Просмотреть файл

@@ -3,7 +3,6 @@ import $ from 'jquery';
3 3
 import { cloneDeep } from 'lodash-es';
4 4
 import { $iq, Strophe } from 'strophe.js';
5 5
 
6
-import { MediaType } from '../../service/RTC/MediaType';
7 6
 import { XMPPEvents } from '../../service/xmpp/XMPPEvents';
8 7
 import RandomUtil from '../util/RandomUtil';
9 8
 
@@ -179,18 +178,8 @@ export default class JingleConnectionPlugin extends ConnectionPlugin {
179 178
         switch (action) {
180 179
         case 'session-initiate': {
181 180
             logger.info('(TIME) received session-initiate:\t', now);
182
-            const startMuted = $(iq).find('jingle>startmuted');
183 181
 
184 182
             isP2P && logger.debug(`Received ${action} from ${fromJid}`);
185
-            if (startMuted?.length) {
186
-                const audioMuted = startMuted.attr(MediaType.AUDIO);
187
-                const videoMuted = startMuted.attr(MediaType.VIDEO);
188
-
189
-                this.eventEmitter.emit(
190
-                    XMPPEvents.START_MUTED_FROM_FOCUS,
191
-                    audioMuted === 'true',
192
-                    videoMuted === 'true');
193
-            }
194 183
             const pcConfig = isP2P ? this.p2pIceConfig : this.jvbIceConfig;
195 184
 
196 185
             sess

+ 3
- 0
modules/xmpp/xmpp.js Просмотреть файл

@@ -284,6 +284,9 @@ export default class XMPP extends Listenable {
284 284
         // for keeping stats, since it is not made available to jocofo at
285 285
         // the time of the initial conference-request.
286 286
         this.caps.addFeature('http://jitsi.org/visitors-1');
287
+
288
+        // Advertise support for startMuted policy through room metadata.
289
+        this.caps.addFeature('http://jitsi.org/start-muted-room-metadata');
287 290
     }
288 291
 
289 292
     /**

+ 0
- 1
service/xmpp/XMPPEvents.spec.ts Просмотреть файл

@@ -96,7 +96,6 @@ describe( "/service/xmpp/XMPPEvents members", () => {
96 96
         expect( XMPPEvents.BREAKOUT_ROOMS_UPDATED ).toBe( 'xmpp.breakout-rooms.updated' );
97 97
         expect( XMPPEvents.ROOM_METADATA_EVENT ).toBe( 'xmpp.room-metadata.event' );
98 98
         expect( XMPPEvents.ROOM_METADATA_UPDATED ).toBe( 'xmpp.room-metadata.updated' );
99
-        expect( XMPPEvents.START_MUTED_FROM_FOCUS ).toBe( 'xmpp.start_muted_from_focus' );
100 99
         expect( XMPPEvents.SUBJECT_CHANGED ).toBe( 'xmpp.subject_changed' );
101 100
         expect( XMPPEvents.SUSPEND_DETECTED ).toBe( 'xmpp.suspend_detected' );
102 101
         expect( XMPPEvents.TRANSCRIPTION_STATUS_CHANGED ).toBe( 'xmpp.transcription_status_changed' );

+ 0
- 4
service/xmpp/XMPPEvents.ts Просмотреть файл

@@ -371,10 +371,6 @@ export enum XMPPEvents {
371 371
      */
372 372
     SPEAKER_STATS_RECEIVED = 'xmpp.speaker_stats_received',
373 373
 
374
-    // Designates an event indicating that we should join the conference with
375
-    // audio and/or video muted.
376
-    START_MUTED_FROM_FOCUS = 'xmpp.start_muted_from_focus',
377
-
378 374
     // Designates an event indicating that the subject of the XMPP MUC has
379 375
     // changed.
380 376
     SUBJECT_CHANGED = 'xmpp.subject_changed',

+ 0
- 2
types/hand-crafted/JitsiConference.d.ts Просмотреть файл

@@ -105,8 +105,6 @@ export default class JitsiConference {
105 105
   getConnectionState: () => string | null;
106 106
   setStartMutedPolicy: ( policy: { audio: boolean, video: boolean } ) => void;
107 107
   getStartMutedPolicy: () => { audio: boolean, video: boolean };
108
-  isStartAudioMuted: () => boolean;
109
-  isStartVideoMuted: () => boolean;
110 108
   getConnectionTimes: () => unknown;
111 109
   setLocalParticipantProperty: ( name: string, value: unknown ) => void;
112 110
   removeLocalParticipantProperty: ( name: string ) => void;

+ 0
- 1
types/hand-crafted/JitsiConferenceEvents.d.ts Просмотреть файл

@@ -41,7 +41,6 @@ export enum JitsiConferenceEvents {
41 41
   VIDEO_SIP_GW_AVAILABILITY_CHANGED = 'conference.videoSIPGWAvailabilityChanged',
42 42
   VIDEO_SIP_GW_SESSION_STATE_CHANGED = 'conference.videoSIPGWSessionStateChanged',
43 43
   START_MUTED_POLICY_CHANGED = 'conference.start_muted_policy_changed',
44
-  STARTED_MUTED = 'conference.started_muted',
45 44
   SUBJECT_CHANGED = 'conference.subjectChanged',
46 45
   SUSPEND_DETECTED = 'conference.suspendDetected',
47 46
   TALK_WHILE_MUTED = 'conference.talk_while_muted',

+ 0
- 1
types/hand-crafted/service/xmpp/XMPPEvents.d.ts Просмотреть файл

@@ -69,7 +69,6 @@
69 69
   AV_MODERATION_RECEIVED = 'xmpp.av_moderation.received',
70 70
   AV_MODERATION_CHANGED = 'xmpp.av_moderation.changed',
71 71
   AV_MODERATION_PARTICIPANT_APPROVED = 'xmpp.av_moderation.participant.approved',
72
-  START_MUTED_FROM_FOCUS = 'xmpp.start_muted_from_focus',
73 72
   SUBJECT_CHANGED = 'xmpp.subject_changed',
74 73
   SUSPEND_DETECTED = 'xmpp.suspend_detected',
75 74
   TRANSCRIPTION_STATUS_CHANGED = 'xmpp.transcription_status_changed',

Загрузка…
Отмена
Сохранить