@@ -7,7 +7,7 @@ import { Panel, PanelType } from 'office-ui-fabric-react/lib/Panel';
7
7
import { Icon } from '@fluentui/react/lib/Icon' ;
8
8
import LocalVideoPreviewCard from './LocalVideoPreviewCard' ;
9
9
import { Dropdown } from 'office-ui-fabric-react/lib/Dropdown' ;
10
- import { LocalVideoStream , Features , LocalAudioStream } from '@azure/communication-calling' ;
10
+ import { LocalVideoStream , Features , LocalAudioStream , MediaAccess } from '@azure/communication-calling' ;
11
11
import { utils } from '../Utils/Utils' ;
12
12
import CustomVideoEffects from "./RawVideoAccess/CustomVideoEffects" ;
13
13
import VideoEffectsContainer from './VideoEffects/VideoEffectsContainer' ;
@@ -55,8 +55,17 @@ export default class CallCard extends React.Component {
55
55
this . pptLiveFeature = this . call . feature ( Features . PPTLive ) ;
56
56
this . pptLiveHtml = React . createRef ( ) ;
57
57
}
58
+ let meetingMediaAccess = undefined ;
59
+ let remoteParticipantsMediaAccess = undefined ;
60
+ let mediaAccessMap = undefined ;
58
61
if ( Features . MediaAccess ) {
59
62
this . mediaAccessCallFeature = this . call . feature ( Features . MediaAccess ) ;
63
+ meetingMediaAccess = this . call . feature ( Features . MediaAccess ) . getMeetingMediaAccess ( ) ;
64
+ remoteParticipantsMediaAccess = this . call . feature ( Features . MediaAccess ) . getAllOthersMediaAccess ( ) ;
65
+ mediaAccessMap = new Map ( ) ;
66
+ remoteParticipantsMediaAccess . forEach ( ( mediaAccess ) => {
67
+ mediaAccessMap . set ( mediaAccess . participant . rawId , mediaAccess ) ;
68
+ } ) ;
60
69
}
61
70
this . isTeamsUser = props . isTeamsUser ;
62
71
this . dummyStreamTimeout = undefined ;
@@ -115,7 +124,11 @@ export default class CallCard extends React.Component {
115
124
isRecordingActive : false ,
116
125
isTranscriptionActive : false ,
117
126
lobbyParticipantsCount : this . lobby ?. participants . length ,
118
- mediaAccessMap : Map
127
+ mediaAccessMap,
128
+ meetingMediaAccess : {
129
+ isAudioPermitted : meetingMediaAccess ?. isAudioPermitted ,
130
+ isVideoPermitted : meetingMediaAccess ?. isVideoPermitted ,
131
+ }
119
132
} ;
120
133
this . selectedRemoteParticipants = new Set ( ) ;
121
134
this . dataChannelRef = React . createRef ( ) ;
@@ -158,6 +171,7 @@ export default class CallCard extends React.Component {
158
171
this . dominantSpeakersFeature . off ( 'dominantSpeakersChanged' , this . dominantSpeakersChanged ) ;
159
172
if ( Features . mediaAccess ) {
160
173
this . mediaAccessCallFeature . off ( 'mediaAccessChanged' , this . mediaAccessChangedHandler ) ;
174
+ this . mediaAccessCallFeature . off ( 'meetingMediaAccessChanged' , this . meetingMediaAccessChangedHandler ) ;
161
175
}
162
176
}
163
177
@@ -248,10 +262,14 @@ export default class CallCard extends React.Component {
248
262
if ( this . call . state === 'LocalHold' || this . call . state === 'RemoteHold' ) {
249
263
this . setState ( { canRaiseHands : false } ) ;
250
264
this . setState ( { canSpotlight : false } ) ;
265
+ this . setState ( { canForbidOthersAudio : false } ) ;
266
+ this . setState ( { canForbidOthersVideo : false } ) ;
251
267
}
252
268
if ( this . call . state === 'Connected' ) {
253
269
this . setState ( { canRaiseHands : this . capabilities . raiseHand ?. isPresent || this . capabilities . raiseHand ?. reason === 'FeatureNotSupported' } ) ;
254
270
this . setState ( { canSpotlight : this . capabilities . spotlightParticipant ?. isPresent || this . capabilities . spotlightParticipant ?. reason === 'FeatureNotSupported' } ) ;
271
+ this . setState ( { canForbidOthersAudio : this . capabilities . forbidOthersAudio ?. isPresent || this . capabilities . forbidOthersAudio ?. reason === 'FeatureNotSupported' } ) ;
272
+ this . setState ( { canForbidOthersVideo : this . capabilities . forbidOthersVideo ?. isPresent || this . capabilities . forbidOthersVideo ?. reason === 'FeatureNotSupported' } ) ;
255
273
}
256
274
}
257
275
callStateChanged ( ) ;
@@ -491,6 +509,7 @@ export default class CallCard extends React.Component {
491
509
this . realTimeTextFeature ?. on ( 'realTimeTextReceived' , this . realTimeTextReceivedHandler ) ;
492
510
if ( Features . MediaAccess ) {
493
511
this . mediaAccessCallFeature . on ( 'mediaAccessChanged' , this . mediaAccessChangedHandler ) ;
512
+ this . mediaAccessCallFeature . on ( 'meetingMediaAccessChanged' , this . meetingMediaAccessChangedHandler ) ;
494
513
}
495
514
}
496
515
}
@@ -562,6 +581,15 @@ export default class CallCard extends React.Component {
562
581
this . setState ( { mediaAccessMap} ) ;
563
582
}
564
583
584
+ meetingMediaAccessChangedHandler = ( event ) => {
585
+ if ( event . meetingMediaAccess ) {
586
+ this . setState ( { meetingMediaAccess : {
587
+ isAudioPermitted : event . meetingMediaAccess . isAudioPermitted ,
588
+ isVideoPermitted : event . meetingMediaAccess . isVideoPermitted ,
589
+ } } ) ;
590
+ }
591
+ }
592
+
565
593
isRecordingActiveChangedHandler = ( event ) => {
566
594
this . setState ( { isRecordingActive : this . recordingFeature . isRecordingActive } )
567
595
}
@@ -678,6 +706,14 @@ export default class CallCard extends React.Component {
678
706
( value . isPresent ) ? this . setState ( { canReact : true } ) : this . setState ( { canReact : false } ) ;
679
707
continue ;
680
708
}
709
+ if ( key === 'forbidOthersAudio' && value . reason != 'FeatureNotSupported' ) {
710
+ ( value . isPresent ) ? this . setState ( { canForbidOthersAudio : true } ) : this . setState ( { canForbidOthersAudio : false } ) ;
711
+ continue ;
712
+ }
713
+ if ( key === 'forbidOthersVideo' && value . reason != 'FeatureNotSupported' ) {
714
+ ( value . isPresent ) ? this . setState ( { canForbidOthersVideo : true } ) : this . setState ( { canForbidOthersVideo : false } ) ;
715
+ continue ;
716
+ }
681
717
}
682
718
this . capabilities = this . capabilitiesFeature . capabilities ;
683
719
}
@@ -1182,6 +1218,34 @@ export default class CallCard extends React.Component {
1182
1218
} catch ( e ) {
1183
1219
console . error ( e ) ;
1184
1220
}
1221
+ } ,
1222
+ forbidOthersAudio : async ( ) => {
1223
+ try {
1224
+ await this . mediaAccessCallFeature . forbidOthersAudio ( ) ;
1225
+ } catch ( e ) {
1226
+ console . error ( e ) ;
1227
+ }
1228
+ } ,
1229
+ permitOthersAudio : async ( ) => {
1230
+ try {
1231
+ await this . mediaAccessCallFeature . permitOthersAudio ( ) ;
1232
+ } catch ( e ) {
1233
+ console . error ( e ) ;
1234
+ }
1235
+ } ,
1236
+ forbidOthersVideo : async ( ) => {
1237
+ try {
1238
+ await this . mediaAccessCallFeature . forbidOthersVideo ( ) ;
1239
+ } catch ( e ) {
1240
+ console . error ( e ) ;
1241
+ }
1242
+ } ,
1243
+ permitOthersVideo : async ( ) => {
1244
+ try {
1245
+ await this . mediaAccessCallFeature . permitOthersVideo ( ) ;
1246
+ } catch ( e ) {
1247
+ console . error ( e ) ;
1248
+ }
1185
1249
}
1186
1250
}
1187
1251
}
@@ -1263,6 +1327,43 @@ export default class CallCard extends React.Component {
1263
1327
onClick : ( e ) => menuCallBacks . consentToBeingRecorded ( e )
1264
1328
} ) ;
1265
1329
1330
+
1331
+ if ( this . state . canForbidOthersAudio && this . state . meetingMediaAccess . isAudioPermitted ) {
1332
+ menuItems . push ( {
1333
+ key : 'Disable mic for all attendees' ,
1334
+ iconProps : { iconName : 'Focus' } ,
1335
+ text : 'Disable mic for all attendees' ,
1336
+ onClick : ( ) => menuCallBacks . forbidOthersAudio ( )
1337
+ } ) ;
1338
+ }
1339
+
1340
+ if ( this . state . canForbidOthersAudio && ! this . state . meetingMediaAccess . isAudioPermitted ) {
1341
+ menuItems . push ( {
1342
+ key : 'Enable mic for all attendees' ,
1343
+ iconProps : { iconName : 'Focus' } ,
1344
+ text : 'Enable mic for all attendees' ,
1345
+ onClick : ( ) => menuCallBacks . permitOthersAudio ( )
1346
+ } ) ;
1347
+ }
1348
+
1349
+ if ( this . state . canForbidOthersVideo && this . state . meetingMediaAccess . isVideoPermitted ) {
1350
+ menuItems . push ( {
1351
+ key : 'Disable camera for all attendees' ,
1352
+ iconProps : { iconName : 'Focus' } ,
1353
+ text : 'Disable camera for all attendees' ,
1354
+ onClick : ( ) => menuCallBacks . forbidOthersVideo ( )
1355
+ } ) ;
1356
+ }
1357
+
1358
+ if ( this . state . canForbidOthersVideo && ! this . state . meetingMediaAccess . isVideoPermitted ) {
1359
+ menuItems . push ( {
1360
+ key : 'Enable camera for all attendees' ,
1361
+ iconProps : { iconName : 'Focus' } ,
1362
+ text : 'Enable camera for all attendees' ,
1363
+ onClick : ( ) => menuCallBacks . permitOthersVideo ( )
1364
+ } ) ;
1365
+ }
1366
+
1266
1367
return menuItems . filter ( item => item != 0 )
1267
1368
}
1268
1369
0 commit comments