@webex/plugin-meetings 3.0.0-beta.17 → 3.0.0-beta.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/breakouts/breakout.js +116 -0
- package/dist/breakouts/breakout.js.map +1 -0
- package/dist/breakouts/collection.js +23 -0
- package/dist/breakouts/collection.js.map +1 -0
- package/dist/breakouts/index.js +226 -0
- package/dist/breakouts/index.js.map +1 -0
- package/dist/config.js +4 -1
- package/dist/config.js.map +1 -1
- package/dist/constants.js +38 -5
- package/dist/constants.js.map +1 -1
- package/dist/locus-info/controlsUtils.js +2 -1
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/index.js +48 -0
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/parser.js +1 -0
- package/dist/locus-info/parser.js.map +1 -1
- package/dist/locus-info/selfUtils.js +19 -11
- package/dist/locus-info/selfUtils.js.map +1 -1
- package/dist/media/index.js +3 -3
- package/dist/media/index.js.map +1 -1
- package/dist/media/properties.js +4 -4
- package/dist/media/properties.js.map +1 -1
- package/dist/meeting/index.js +651 -460
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/request.js +25 -44
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/request.type.js.map +1 -1
- package/dist/meeting/util.js +4 -57
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting-info/meeting-info-v2.js +2 -0
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meetings/index.js +28 -18
- package/dist/meetings/index.js.map +1 -1
- package/dist/meetings/request.js +14 -12
- package/dist/meetings/request.js.map +1 -1
- package/dist/member/index.js +9 -0
- package/dist/member/index.js.map +1 -1
- package/dist/member/util.js +14 -1
- package/dist/member/util.js.map +1 -1
- package/dist/members/index.js +8 -6
- package/dist/members/index.js.map +1 -1
- package/dist/members/request.js +3 -1
- package/dist/members/request.js.map +1 -1
- package/dist/multistream/mediaRequestManager.js +46 -6
- package/dist/multistream/mediaRequestManager.js.map +1 -1
- package/dist/multistream/multistreamMedia.js +4 -0
- package/dist/multistream/multistreamMedia.js.map +1 -1
- package/dist/multistream/receiveSlot.js +3 -3
- package/dist/multistream/receiveSlot.js.map +1 -1
- package/dist/multistream/receiveSlotManager.js +8 -6
- package/dist/multistream/receiveSlotManager.js.map +1 -1
- package/dist/multistream/remoteMedia.js.map +1 -1
- package/dist/multistream/remoteMediaGroup.js.map +1 -1
- package/dist/multistream/remoteMediaManager.js +168 -63
- package/dist/multistream/remoteMediaManager.js.map +1 -1
- package/dist/reachability/index.js +63 -51
- package/dist/reachability/index.js.map +1 -1
- package/dist/reactions/constants.js +13 -0
- package/dist/reactions/constants.js.map +1 -0
- package/dist/reactions/reactions.type.js.map +1 -1
- package/dist/reconnection-manager/index.js +25 -12
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/recording-controller/enums.js +17 -0
- package/dist/recording-controller/enums.js.map +1 -0
- package/dist/recording-controller/index.js +343 -0
- package/dist/recording-controller/index.js.map +1 -0
- package/dist/recording-controller/util.js +63 -0
- package/dist/recording-controller/util.js.map +1 -0
- package/dist/roap/request.js +88 -68
- package/dist/roap/request.js.map +1 -1
- package/dist/roap/turnDiscovery.js +72 -47
- package/dist/roap/turnDiscovery.js.map +1 -1
- package/dist/statsAnalyzer/index.js +3 -3
- package/dist/statsAnalyzer/index.js.map +1 -1
- package/dist/statsAnalyzer/mqaUtil.js +18 -6
- package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
- package/package.json +24 -19
- package/src/breakouts/README.md +190 -0
- package/src/breakouts/breakout.ts +110 -0
- package/src/breakouts/collection.ts +19 -0
- package/src/breakouts/index.ts +225 -0
- package/src/config.ts +4 -1
- package/src/constants.ts +35 -1
- package/src/locus-info/controlsUtils.ts +2 -0
- package/src/locus-info/index.ts +59 -1
- package/src/locus-info/parser.ts +1 -0
- package/src/locus-info/selfUtils.ts +8 -0
- package/src/media/index.ts +1 -2
- package/src/media/properties.ts +6 -9
- package/src/meeting/index.ts +352 -111
- package/src/meeting/request.ts +9 -31
- package/src/meeting/request.type.ts +2 -0
- package/src/meeting/util.ts +3 -60
- package/src/meeting-info/meeting-info-v2.ts +2 -0
- package/src/meetings/index.ts +10 -5
- package/src/meetings/request.ts +1 -1
- package/src/member/index.ts +9 -0
- package/src/member/util.ts +14 -1
- package/src/members/index.ts +1 -0
- package/src/members/request.ts +1 -0
- package/src/multistream/mediaRequestManager.ts +79 -15
- package/src/multistream/multistreamMedia.ts +4 -0
- package/src/multistream/receiveSlot.ts +17 -12
- package/src/multistream/receiveSlotManager.ts +22 -21
- package/src/multistream/remoteMedia.ts +1 -1
- package/src/multistream/remoteMediaGroup.ts +2 -2
- package/src/multistream/remoteMediaManager.ts +150 -37
- package/src/reachability/index.ts +16 -13
- package/src/reactions/constants.ts +4 -0
- package/src/reactions/reactions.type.ts +25 -0
- package/src/reconnection-manager/index.ts +18 -9
- package/src/recording-controller/enums.ts +8 -0
- package/src/recording-controller/index.ts +315 -0
- package/src/recording-controller/util.ts +58 -0
- package/src/roap/request.ts +78 -73
- package/src/roap/turnDiscovery.ts +8 -6
- package/src/statsAnalyzer/index.ts +4 -4
- package/src/statsAnalyzer/mqaUtil.ts +6 -0
- package/test/unit/spec/breakouts/breakout.ts +119 -0
- package/test/unit/spec/breakouts/collection.ts +15 -0
- package/test/unit/spec/breakouts/index.ts +293 -0
- package/test/unit/spec/locus-info/controlsUtils.js +20 -0
- package/test/unit/spec/locus-info/index.js +103 -0
- package/test/unit/spec/locus-info/selfConstant.js +25 -0
- package/test/unit/spec/locus-info/selfUtils.js +84 -0
- package/test/unit/spec/media/index.ts +1 -1
- package/test/unit/spec/media/properties.ts +9 -9
- package/test/unit/spec/meeting/effectsState.js +5 -1
- package/test/unit/spec/meeting/index.js +235 -50
- package/test/unit/spec/meeting/request.js +17 -0
- package/test/unit/spec/meeting/utils.js +20 -129
- package/test/unit/spec/meetings/index.js +1 -0
- package/test/unit/spec/member/util.js +26 -1
- package/test/unit/spec/multistream/mediaRequestManager.ts +312 -50
- package/test/unit/spec/multistream/receiveSlot.ts +6 -6
- package/test/unit/spec/multistream/receiveSlotManager.ts +13 -13
- package/test/unit/spec/multistream/remoteMedia.ts +2 -2
- package/test/unit/spec/multistream/remoteMediaGroup.ts +5 -5
- package/test/unit/spec/multistream/remoteMediaManager.ts +354 -65
- package/test/unit/spec/reachability/index.ts +58 -24
- package/test/unit/spec/reconnection-manager/index.js +42 -13
- package/test/unit/spec/recording-controller/index.js +231 -0
- package/test/unit/spec/recording-controller/util.js +102 -0
- package/test/unit/spec/roap/index.ts +2 -1
- package/test/unit/spec/roap/request.ts +114 -0
- package/test/unit/spec/roap/turnDiscovery.ts +45 -29
- package/test/unit/spec/stats-analyzer/index.js +2 -2
- package/test/utils/webex-test-users.js +1 -0
- package/tsconfig.json +6 -0
- package/dist/media/internal-media-core-wrapper.js +0 -18
- package/dist/media/internal-media-core-wrapper.js.map +0 -1
- package/src/media/internal-media-core-wrapper.ts +0 -9
package/src/meeting/index.ts
CHANGED
|
@@ -2,7 +2,15 @@ import uuid from 'uuid';
|
|
|
2
2
|
import {cloneDeep, isEqual, pick, isString, defer} from 'lodash';
|
|
3
3
|
// @ts-ignore - Fix this
|
|
4
4
|
import {StatelessWebexPlugin} from '@webex/webex-core';
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
ConnectionState,
|
|
7
|
+
Errors,
|
|
8
|
+
ErrorType,
|
|
9
|
+
Event,
|
|
10
|
+
Media as WebRTCMedia,
|
|
11
|
+
MediaType,
|
|
12
|
+
RemoteTrackType,
|
|
13
|
+
} from '@webex/internal-media-core';
|
|
6
14
|
|
|
7
15
|
import {
|
|
8
16
|
MeetingNotActiveError,
|
|
@@ -28,8 +36,10 @@ import ReconnectionManager from '../reconnection-manager';
|
|
|
28
36
|
import MeetingRequest from './request';
|
|
29
37
|
import Members from '../members/index';
|
|
30
38
|
import MeetingUtil from './util';
|
|
39
|
+
import RecordingUtil from '../recording-controller/util';
|
|
31
40
|
import MediaUtil from '../media/util';
|
|
32
41
|
import Transcription from '../transcription';
|
|
42
|
+
import {Reactions, SkinTones} from '../reactions/reactions';
|
|
33
43
|
import PasswordError from '../common/errors/password-error';
|
|
34
44
|
import CaptchaError from '../common/errors/captcha-error';
|
|
35
45
|
import ReconnectionError from '../common/errors/reconnection';
|
|
@@ -44,6 +54,7 @@ import {
|
|
|
44
54
|
EVENT_TRIGGERS,
|
|
45
55
|
EVENT_TYPES,
|
|
46
56
|
EVENTS,
|
|
57
|
+
BREAKOUTS,
|
|
47
58
|
FLOOR_ACTION,
|
|
48
59
|
FULL_STATE,
|
|
49
60
|
LAYOUT_TYPES,
|
|
@@ -84,10 +95,18 @@ import {
|
|
|
84
95
|
Event as RemoteMediaManagerEvent,
|
|
85
96
|
} from '../multistream/remoteMediaManager';
|
|
86
97
|
import {MultistreamMedia} from '../multistream/multistreamMedia';
|
|
87
|
-
import {
|
|
88
|
-
|
|
98
|
+
import {
|
|
99
|
+
Reaction,
|
|
100
|
+
ReactionType,
|
|
101
|
+
SkinToneType,
|
|
102
|
+
ProcessedReaction,
|
|
103
|
+
RelayEvent,
|
|
104
|
+
} from '../reactions/reactions.type';
|
|
105
|
+
import Breakouts from '../breakouts';
|
|
89
106
|
|
|
90
107
|
import InMeetingActions from './in-meeting-actions';
|
|
108
|
+
import {REACTION_RELAY_TYPES} from '../reactions/constants';
|
|
109
|
+
import RecordingController from '../recording-controller';
|
|
91
110
|
|
|
92
111
|
const {isBrowser} = BrowserDetection();
|
|
93
112
|
|
|
@@ -403,6 +422,7 @@ export const MEDIA_UPDATE_TYPE = {
|
|
|
403
422
|
export default class Meeting extends StatelessWebexPlugin {
|
|
404
423
|
attrs: any;
|
|
405
424
|
audio: any;
|
|
425
|
+
breakouts: any;
|
|
406
426
|
conversationUrl: string;
|
|
407
427
|
correlationId: string;
|
|
408
428
|
destination: string;
|
|
@@ -454,6 +474,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
454
474
|
mediaRequestManagers: {
|
|
455
475
|
audio: MediaRequestManager;
|
|
456
476
|
video: MediaRequestManager;
|
|
477
|
+
screenShareAudio: MediaRequestManager;
|
|
478
|
+
screenShareVideo: MediaRequestManager;
|
|
457
479
|
};
|
|
458
480
|
|
|
459
481
|
meetingInfoFailureReason: string;
|
|
@@ -463,6 +485,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
463
485
|
queuedMediaUpdates: any[];
|
|
464
486
|
recording: any;
|
|
465
487
|
remoteMediaManager: RemoteMediaManager | null;
|
|
488
|
+
recordingController: RecordingController;
|
|
466
489
|
requiredCaptcha: any;
|
|
467
490
|
receiveSlotManager: ReceiveSlotManager;
|
|
468
491
|
shareStatus: string;
|
|
@@ -573,16 +596,25 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
573
596
|
*/
|
|
574
597
|
// TODO: needs to be defined as a class
|
|
575
598
|
this.meetingInfo = {};
|
|
599
|
+
/**
|
|
600
|
+
* @instance
|
|
601
|
+
* @type {Breakouts}
|
|
602
|
+
* @public
|
|
603
|
+
* @memberof Meeting
|
|
604
|
+
*/
|
|
605
|
+
// @ts-ignore
|
|
606
|
+
this.breakouts = new Breakouts({}, {parent: this.webex});
|
|
576
607
|
/**
|
|
577
608
|
* helper class for managing receive slots (for multistream media connections)
|
|
578
609
|
*/
|
|
579
610
|
this.receiveSlotManager = new ReceiveSlotManager(this);
|
|
580
611
|
/**
|
|
581
|
-
*
|
|
582
|
-
* All media requests sent out for
|
|
612
|
+
* Object containing helper classes for managing media requests for audio/video/screenshare (for multistream media connections)
|
|
613
|
+
* All multistream media requests sent out for this meeting have to go through them.
|
|
583
614
|
*/
|
|
584
615
|
this.mediaRequestManagers = {
|
|
585
|
-
|
|
616
|
+
// @ts-ignore - config coming from registerPlugin
|
|
617
|
+
audio: new MediaRequestManager(this.config.degradationPreferences, (mediaRequests) => {
|
|
586
618
|
if (!this.mediaProperties.webrtcMediaConnection) {
|
|
587
619
|
LoggerProxy.logger.warn(
|
|
588
620
|
'Meeting:index#mediaRequestManager --> trying to send audio media request before media connection was created'
|
|
@@ -590,12 +622,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
590
622
|
|
|
591
623
|
return;
|
|
592
624
|
}
|
|
593
|
-
this.mediaProperties.webrtcMediaConnection.requestMedia(
|
|
594
|
-
MC.MediaType.AudioMain,
|
|
595
|
-
mediaRequests
|
|
596
|
-
);
|
|
625
|
+
this.mediaProperties.webrtcMediaConnection.requestMedia(MediaType.AudioMain, mediaRequests);
|
|
597
626
|
}),
|
|
598
|
-
|
|
627
|
+
// @ts-ignore - config coming from registerPlugin
|
|
628
|
+
video: new MediaRequestManager(this.config.degradationPreferences, (mediaRequests) => {
|
|
599
629
|
if (!this.mediaProperties.webrtcMediaConnection) {
|
|
600
630
|
LoggerProxy.logger.warn(
|
|
601
631
|
'Meeting:index#mediaRequestManager --> trying to send video media request before media connection was created'
|
|
@@ -603,11 +633,42 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
603
633
|
|
|
604
634
|
return;
|
|
605
635
|
}
|
|
606
|
-
this.mediaProperties.webrtcMediaConnection.requestMedia(
|
|
607
|
-
MC.MediaType.VideoMain,
|
|
608
|
-
mediaRequests
|
|
609
|
-
);
|
|
636
|
+
this.mediaProperties.webrtcMediaConnection.requestMedia(MediaType.VideoMain, mediaRequests);
|
|
610
637
|
}),
|
|
638
|
+
screenShareAudio: new MediaRequestManager(
|
|
639
|
+
// @ts-ignore - config coming from registerPlugin
|
|
640
|
+
this.config.degradationPreferences,
|
|
641
|
+
(mediaRequests) => {
|
|
642
|
+
if (!this.mediaProperties.webrtcMediaConnection) {
|
|
643
|
+
LoggerProxy.logger.warn(
|
|
644
|
+
'Meeting:index#mediaRequestManager --> trying to send screenshare audio media request before media connection was created'
|
|
645
|
+
);
|
|
646
|
+
|
|
647
|
+
return;
|
|
648
|
+
}
|
|
649
|
+
this.mediaProperties.webrtcMediaConnection.requestMedia(
|
|
650
|
+
MediaType.AudioSlides,
|
|
651
|
+
mediaRequests
|
|
652
|
+
);
|
|
653
|
+
}
|
|
654
|
+
),
|
|
655
|
+
screenShareVideo: new MediaRequestManager(
|
|
656
|
+
// @ts-ignore - config coming from registerPlugin
|
|
657
|
+
this.config.degradationPreferences,
|
|
658
|
+
(mediaRequests) => {
|
|
659
|
+
if (!this.mediaProperties.webrtcMediaConnection) {
|
|
660
|
+
LoggerProxy.logger.warn(
|
|
661
|
+
'Meeting:index#mediaRequestManager --> trying to send screenshare video media request before media connection was created'
|
|
662
|
+
);
|
|
663
|
+
|
|
664
|
+
return;
|
|
665
|
+
}
|
|
666
|
+
this.mediaProperties.webrtcMediaConnection.requestMedia(
|
|
667
|
+
MediaType.VideoSlides,
|
|
668
|
+
mediaRequests
|
|
669
|
+
);
|
|
670
|
+
}
|
|
671
|
+
),
|
|
611
672
|
};
|
|
612
673
|
/**
|
|
613
674
|
* @instance
|
|
@@ -620,8 +681,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
620
681
|
locusUrl: attrs.locus && attrs.locus.url,
|
|
621
682
|
receiveSlotManager: this.receiveSlotManager,
|
|
622
683
|
mediaRequestManagers: this.mediaRequestManagers,
|
|
623
|
-
// @ts-ignore - Fix type
|
|
624
684
|
},
|
|
685
|
+
// @ts-ignore - Fix type
|
|
625
686
|
{parent: this.webex}
|
|
626
687
|
);
|
|
627
688
|
/**
|
|
@@ -924,6 +985,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
924
985
|
*/
|
|
925
986
|
// @ts-ignore - Fix type
|
|
926
987
|
this.locusInfo = new LocusInfo(this.updateMeetingObject.bind(this), this.webex, this.id);
|
|
988
|
+
|
|
927
989
|
// We had to add listeners first before setting up the locus instance
|
|
928
990
|
/**
|
|
929
991
|
* @instance
|
|
@@ -1023,6 +1085,20 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1023
1085
|
*/
|
|
1024
1086
|
this.keepAliveTimerId = null;
|
|
1025
1087
|
|
|
1088
|
+
/**
|
|
1089
|
+
* The class that helps to control recording functions: start, stop, pause, resume, etc
|
|
1090
|
+
* @instance
|
|
1091
|
+
* @type {RecordingController}
|
|
1092
|
+
* @public
|
|
1093
|
+
* @memberof Meeting
|
|
1094
|
+
*/
|
|
1095
|
+
this.recordingController = new RecordingController(this.meetingRequest, {
|
|
1096
|
+
serviceUrl: this.locusInfo?.links?.services?.record?.url,
|
|
1097
|
+
sessionId: this.locusInfo?.fullState?.sessionId,
|
|
1098
|
+
locusUrl: this.locusInfo?.url,
|
|
1099
|
+
displayHints: [],
|
|
1100
|
+
});
|
|
1101
|
+
|
|
1026
1102
|
this.setUpLocusInfoListeners();
|
|
1027
1103
|
this.locusInfo.init(attrs.locus ? attrs.locus : {});
|
|
1028
1104
|
this.hasJoinedOnce = false;
|
|
@@ -1108,8 +1184,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1108
1184
|
return Promise.resolve();
|
|
1109
1185
|
} catch (err) {
|
|
1110
1186
|
if (err instanceof MeetingInfoV2PasswordError) {
|
|
1111
|
-
// @ts-ignore
|
|
1112
1187
|
LoggerProxy.logger.info(
|
|
1188
|
+
// @ts-ignore
|
|
1113
1189
|
`Meeting:index#fetchMeetingInfo --> Info Unable to fetch meeting info for ${this.destination} - password required (code=${err?.body?.code}).`
|
|
1114
1190
|
);
|
|
1115
1191
|
|
|
@@ -1128,8 +1204,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1128
1204
|
|
|
1129
1205
|
throw new PasswordError();
|
|
1130
1206
|
} else if (err instanceof MeetingInfoV2CaptchaError) {
|
|
1131
|
-
// @ts-ignore
|
|
1132
1207
|
LoggerProxy.logger.info(
|
|
1208
|
+
// @ts-ignore
|
|
1133
1209
|
`Meeting:index#fetchMeetingInfo --> Info Unable to fetch meeting info for ${this.destination} - captcha required (code=${err?.body?.code}).`
|
|
1134
1210
|
);
|
|
1135
1211
|
|
|
@@ -1201,22 +1277,25 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1201
1277
|
// we have to pass the wbxappapi hostname as the siteFullName parameter
|
|
1202
1278
|
const {hostname} = new URL(this.requiredCaptcha.refreshURL);
|
|
1203
1279
|
|
|
1204
|
-
return
|
|
1205
|
-
.
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1280
|
+
return (
|
|
1281
|
+
this.meetingRequest
|
|
1282
|
+
// @ts-ignore
|
|
1283
|
+
.refreshCaptcha({
|
|
1284
|
+
captchaRefreshUrl: `${this.requiredCaptcha.refreshURL}&siteFullName=${hostname}`,
|
|
1285
|
+
captchaId: this.requiredCaptcha.captchaId,
|
|
1286
|
+
})
|
|
1287
|
+
.then((response) => {
|
|
1288
|
+
this.requiredCaptcha.captchaId = response.body.captchaID;
|
|
1289
|
+
this.requiredCaptcha.verificationImageURL = response.body.verificationImageURL;
|
|
1290
|
+
this.requiredCaptcha.verificationAudioURL = response.body.verificationAudioURL;
|
|
1291
|
+
})
|
|
1292
|
+
.catch((error) => {
|
|
1293
|
+
LoggerProxy.logger.error(
|
|
1294
|
+
`Meeting:index#refreshCaptcha --> Error Unable to refresh captcha for ${this.destination} - ${error}`
|
|
1295
|
+
);
|
|
1296
|
+
throw error;
|
|
1297
|
+
})
|
|
1298
|
+
);
|
|
1220
1299
|
}
|
|
1221
1300
|
|
|
1222
1301
|
/**
|
|
@@ -1229,6 +1308,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1229
1308
|
// meeting update listeners
|
|
1230
1309
|
this.setUpLocusInfoSelfListener();
|
|
1231
1310
|
this.setUpLocusInfoMeetingListener();
|
|
1311
|
+
this.setUpLocusServicesListener();
|
|
1232
1312
|
// members update listeners
|
|
1233
1313
|
this.setUpLocusFullStateListener();
|
|
1234
1314
|
this.setUpLocusUrlListener();
|
|
@@ -1241,6 +1321,49 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1241
1321
|
this.setUpLocusInfoMeetingInfoListener();
|
|
1242
1322
|
this.setUpLocusInfoAssignHostListener();
|
|
1243
1323
|
this.setUpLocusInfoMediaInactiveListener();
|
|
1324
|
+
this.setUpBreakoutsListener();
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
/**
|
|
1328
|
+
* Set up the listeners for breakouts
|
|
1329
|
+
* @returns {undefined}
|
|
1330
|
+
* @private
|
|
1331
|
+
* @memberof Meeting
|
|
1332
|
+
*/
|
|
1333
|
+
setUpBreakoutsListener() {
|
|
1334
|
+
this.breakouts.on(BREAKOUTS.EVENTS.BREAKOUTS_CLOSING, () => {
|
|
1335
|
+
Trigger.trigger(
|
|
1336
|
+
this,
|
|
1337
|
+
{
|
|
1338
|
+
file: 'meeting/index',
|
|
1339
|
+
function: 'setUpBreakoutsListener',
|
|
1340
|
+
},
|
|
1341
|
+
EVENT_TRIGGERS.MEETING_BREAKOUTS_CLOSING
|
|
1342
|
+
);
|
|
1343
|
+
});
|
|
1344
|
+
|
|
1345
|
+
this.breakouts.on(BREAKOUTS.EVENTS.MESSAGE, (messageEvent) => {
|
|
1346
|
+
Trigger.trigger(
|
|
1347
|
+
this,
|
|
1348
|
+
{
|
|
1349
|
+
file: 'meeting/index',
|
|
1350
|
+
function: 'setUpBreakoutsListener',
|
|
1351
|
+
},
|
|
1352
|
+
EVENT_TRIGGERS.MEETING_BREAKOUTS_MESSAGE,
|
|
1353
|
+
messageEvent
|
|
1354
|
+
);
|
|
1355
|
+
});
|
|
1356
|
+
|
|
1357
|
+
this.breakouts.on(BREAKOUTS.EVENTS.MEMBERS_UPDATE, () => {
|
|
1358
|
+
Trigger.trigger(
|
|
1359
|
+
this,
|
|
1360
|
+
{
|
|
1361
|
+
file: 'meeting/index',
|
|
1362
|
+
function: 'setUpBreakoutsListener',
|
|
1363
|
+
},
|
|
1364
|
+
EVENT_TRIGGERS.MEETING_BREAKOUTS_UPDATE
|
|
1365
|
+
);
|
|
1366
|
+
});
|
|
1244
1367
|
}
|
|
1245
1368
|
|
|
1246
1369
|
/**
|
|
@@ -1786,6 +1909,18 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1786
1909
|
}
|
|
1787
1910
|
);
|
|
1788
1911
|
|
|
1912
|
+
this.locusInfo.on(LOCUSINFO.EVENTS.CONTROLS_MEETING_BREAKOUT_UPDATED, ({breakout}) => {
|
|
1913
|
+
this.breakouts.updateBreakout(breakout);
|
|
1914
|
+
Trigger.trigger(
|
|
1915
|
+
this,
|
|
1916
|
+
{
|
|
1917
|
+
file: 'meeting/index',
|
|
1918
|
+
function: 'setupLocusControlsListener',
|
|
1919
|
+
},
|
|
1920
|
+
EVENT_TRIGGERS.MEETING_BREAKOUTS_UPDATE
|
|
1921
|
+
);
|
|
1922
|
+
});
|
|
1923
|
+
|
|
1789
1924
|
this.locusInfo.on(LOCUSINFO.EVENTS.CONTROLS_ENTRY_EXIT_TONE_UPDATED, ({entryExitTone}) => {
|
|
1790
1925
|
Trigger.trigger(
|
|
1791
1926
|
this,
|
|
@@ -2041,8 +2176,26 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2041
2176
|
private setUpLocusUrlListener() {
|
|
2042
2177
|
this.locusInfo.on(EVENTS.LOCUS_INFO_UPDATE_URL, (payload) => {
|
|
2043
2178
|
this.members.locusUrlUpdate(payload);
|
|
2179
|
+
this.breakouts.locusUrlUpdate(payload);
|
|
2044
2180
|
this.locusUrl = payload;
|
|
2045
2181
|
this.locusId = this.locusUrl?.split('/').pop();
|
|
2182
|
+
this.recordingController.setLocusUrl(this.locusUrl);
|
|
2183
|
+
});
|
|
2184
|
+
}
|
|
2185
|
+
|
|
2186
|
+
/**
|
|
2187
|
+
* Set up the locus info service link listener
|
|
2188
|
+
* update the locusInfo for recording controller
|
|
2189
|
+
* does not currently re-emit the event as it's internal only
|
|
2190
|
+
* payload is unused
|
|
2191
|
+
* @returns {undefined}
|
|
2192
|
+
* @private
|
|
2193
|
+
* @memberof Meeting
|
|
2194
|
+
*/
|
|
2195
|
+
private setUpLocusServicesListener() {
|
|
2196
|
+
this.locusInfo.on(LOCUSINFO.EVENTS.LINKS_SERVICES, (payload) => {
|
|
2197
|
+
this.recordingController.setServiceUrl(payload?.services?.record?.url);
|
|
2198
|
+
this.recordingController.setSessionId(this.locusInfo?.fullState?.sessionId);
|
|
2046
2199
|
});
|
|
2047
2200
|
}
|
|
2048
2201
|
|
|
@@ -2092,10 +2245,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2092
2245
|
canAdmitParticipant: MeetingUtil.canAdmitParticipant(payload.info.userDisplayHints),
|
|
2093
2246
|
canLock: MeetingUtil.canUserLock(payload.info.userDisplayHints),
|
|
2094
2247
|
canUnlock: MeetingUtil.canUserUnlock(payload.info.userDisplayHints),
|
|
2095
|
-
canStartRecording:
|
|
2096
|
-
canStopRecording:
|
|
2097
|
-
canPauseRecording:
|
|
2098
|
-
canResumeRecording:
|
|
2248
|
+
canStartRecording: RecordingUtil.canUserStart(payload.info.userDisplayHints),
|
|
2249
|
+
canStopRecording: RecordingUtil.canUserStop(payload.info.userDisplayHints),
|
|
2250
|
+
canPauseRecording: RecordingUtil.canUserPause(payload.info.userDisplayHints),
|
|
2251
|
+
canResumeRecording: RecordingUtil.canUserResume(payload.info.userDisplayHints),
|
|
2099
2252
|
canRaiseHand: MeetingUtil.canUserRaiseHand(payload.info.userDisplayHints),
|
|
2100
2253
|
canLowerAllHands: MeetingUtil.canUserLowerAllHands(payload.info.userDisplayHints),
|
|
2101
2254
|
canLowerSomeoneElsesHand: MeetingUtil.canUserLowerSomeoneElsesHand(
|
|
@@ -2127,6 +2280,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2127
2280
|
),
|
|
2128
2281
|
});
|
|
2129
2282
|
|
|
2283
|
+
this.recordingController.setDisplayHints(payload.info.userDisplayHints);
|
|
2284
|
+
|
|
2130
2285
|
if (changed) {
|
|
2131
2286
|
Trigger.trigger(
|
|
2132
2287
|
this,
|
|
@@ -2150,6 +2305,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2150
2305
|
* @returns {void}
|
|
2151
2306
|
*/
|
|
2152
2307
|
handleDataChannelUrlChange(datachannelUrl) {
|
|
2308
|
+
// @ts-ignore - config coming from registerPlugin
|
|
2153
2309
|
if (datachannelUrl && this.config.enableAutomaticLLM) {
|
|
2154
2310
|
// Defer this as updateLLMConnection relies upon this.locusInfo.url which is only set
|
|
2155
2311
|
// after the MEETING_INFO_UPDATED callback finishes
|
|
@@ -2330,6 +2486,18 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2330
2486
|
);
|
|
2331
2487
|
});
|
|
2332
2488
|
|
|
2489
|
+
this.locusInfo.on(LOCUSINFO.EVENTS.SELF_MEETING_BREAKOUTS_CHANGED, (payload) => {
|
|
2490
|
+
this.breakouts.updateBreakoutSessions(payload);
|
|
2491
|
+
Trigger.trigger(
|
|
2492
|
+
this,
|
|
2493
|
+
{
|
|
2494
|
+
file: 'meeting/index',
|
|
2495
|
+
function: 'setUpLocusInfoSelfListener',
|
|
2496
|
+
},
|
|
2497
|
+
EVENT_TRIGGERS.MEETING_BREAKOUTS_UPDATE
|
|
2498
|
+
);
|
|
2499
|
+
});
|
|
2500
|
+
|
|
2333
2501
|
this.locusInfo.on(LOCUSINFO.EVENTS.SELF_IS_SHARING_BLOCKED_CHANGE, (payload) => {
|
|
2334
2502
|
Trigger.trigger(
|
|
2335
2503
|
this,
|
|
@@ -2365,7 +2533,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2365
2533
|
.catch((error) => {
|
|
2366
2534
|
// @ts-ignore
|
|
2367
2535
|
LoggerProxy.logger.error(
|
|
2368
|
-
`Meeting:index#setUpLocusInfoMeetingListener --> REMOTE_RESPONSE. Issue with leave for meeting, meeting still in collection: ${this
|
|
2536
|
+
`Meeting:index#setUpLocusInfoMeetingListener --> REMOTE_RESPONSE. Issue with leave for meeting, meeting still in collection: ${this}, error: ${error}`
|
|
2369
2537
|
);
|
|
2370
2538
|
});
|
|
2371
2539
|
}
|
|
@@ -2400,7 +2568,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2400
2568
|
.catch((error) => {
|
|
2401
2569
|
// @ts-ignore
|
|
2402
2570
|
LoggerProxy.logger.error(
|
|
2403
|
-
`Meeting:index#setUpLocusInfoMeetingListener --> DESTROY_MEETING. Issue with leave for meeting, meeting still in collection: ${this
|
|
2571
|
+
`Meeting:index#setUpLocusInfoMeetingListener --> DESTROY_MEETING. Issue with leave for meeting, meeting still in collection: ${this}, error: ${error}`
|
|
2404
2572
|
);
|
|
2405
2573
|
});
|
|
2406
2574
|
} else {
|
|
@@ -2642,6 +2810,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2642
2810
|
this.locusUrl = locusMeetingObject?.url || webexMeetingInfo?.locusUrl || this.locusUrl;
|
|
2643
2811
|
// @ts-ignore - config coming from registerPlugin
|
|
2644
2812
|
this.setSipUri(
|
|
2813
|
+
// @ts-ignore
|
|
2645
2814
|
this.config.experimental.enableUnifiedMeetings
|
|
2646
2815
|
? locusMeetingObject?.info.sipUri || webexMeetingInfo?.sipUrl
|
|
2647
2816
|
: locusMeetingObject?.info.sipUri || webexMeetingInfo?.sipMeetingUri || this.sipUri
|
|
@@ -3590,6 +3759,20 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3590
3759
|
return false;
|
|
3591
3760
|
}
|
|
3592
3761
|
|
|
3762
|
+
/**
|
|
3763
|
+
* Check if the meeting supports the Reactions
|
|
3764
|
+
* @returns {boolean}
|
|
3765
|
+
*/
|
|
3766
|
+
isReactionsSupported() {
|
|
3767
|
+
if (this.locusInfo?.controls?.reactions.enabled) {
|
|
3768
|
+
return true;
|
|
3769
|
+
}
|
|
3770
|
+
|
|
3771
|
+
LoggerProxy.logger.error('Meeting:index#isReactionsSupported --> Reactions is not supported');
|
|
3772
|
+
|
|
3773
|
+
return false;
|
|
3774
|
+
}
|
|
3775
|
+
|
|
3593
3776
|
/**
|
|
3594
3777
|
* Monitor the Low-Latency Mercury (LLM) web socket connection on `onError` and `onClose` states
|
|
3595
3778
|
* @private
|
|
@@ -3641,6 +3824,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3641
3824
|
// @ts-ignore - fix type
|
|
3642
3825
|
const {
|
|
3643
3826
|
body: {webSocketUrl},
|
|
3827
|
+
// @ts-ignore
|
|
3644
3828
|
} = await this.request({
|
|
3645
3829
|
method: HTTP_VERBS.POST,
|
|
3646
3830
|
uri: datachannelUrl,
|
|
@@ -3690,6 +3874,44 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3690
3874
|
}
|
|
3691
3875
|
}
|
|
3692
3876
|
|
|
3877
|
+
/**
|
|
3878
|
+
* Callback called when a relay event is received from meeting LLM Connection
|
|
3879
|
+
* @param {RelayEvent} e Event object coming from LLM Connection
|
|
3880
|
+
* @private
|
|
3881
|
+
* @returns {void}
|
|
3882
|
+
*/
|
|
3883
|
+
private processRelayEvent = (e: RelayEvent): void => {
|
|
3884
|
+
switch (e.data.relayType) {
|
|
3885
|
+
case REACTION_RELAY_TYPES.REACTION:
|
|
3886
|
+
if (
|
|
3887
|
+
// @ts-ignore - config coming from registerPlugin
|
|
3888
|
+
(this.config.receiveReactions || options.receiveReactions) &&
|
|
3889
|
+
this.isReactionsSupported()
|
|
3890
|
+
) {
|
|
3891
|
+
const {name} = this.members.membersCollection.get(e.data.sender.participantId);
|
|
3892
|
+
const processedReaction: ProcessedReaction = {
|
|
3893
|
+
reaction: e.data.reaction,
|
|
3894
|
+
sender: {
|
|
3895
|
+
id: e.data.sender.participantId,
|
|
3896
|
+
name,
|
|
3897
|
+
},
|
|
3898
|
+
};
|
|
3899
|
+
Trigger.trigger(
|
|
3900
|
+
this,
|
|
3901
|
+
{
|
|
3902
|
+
file: 'meeting/index',
|
|
3903
|
+
function: 'join',
|
|
3904
|
+
},
|
|
3905
|
+
EVENT_TRIGGERS.MEETING_RECEIVE_REACTIONS,
|
|
3906
|
+
processedReaction
|
|
3907
|
+
);
|
|
3908
|
+
}
|
|
3909
|
+
break;
|
|
3910
|
+
default:
|
|
3911
|
+
break;
|
|
3912
|
+
}
|
|
3913
|
+
};
|
|
3914
|
+
|
|
3693
3915
|
/**
|
|
3694
3916
|
* stop recieving Transcription by closing
|
|
3695
3917
|
* the web socket connection properly
|
|
@@ -3863,8 +4085,12 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3863
4085
|
return join;
|
|
3864
4086
|
})
|
|
3865
4087
|
.then(async (join) => {
|
|
4088
|
+
// @ts-ignore - config coming from registerPlugin
|
|
3866
4089
|
if (this.config.enableAutomaticLLM) {
|
|
3867
4090
|
await this.updateLLMConnection();
|
|
4091
|
+
// @ts-ignore - Fix type
|
|
4092
|
+
this.webex.internal.llm.on('event:relay.event', this.processRelayEvent);
|
|
4093
|
+
LoggerProxy.logger.info('Meeting:index#join --> enabled to receive relay events!');
|
|
3868
4094
|
}
|
|
3869
4095
|
|
|
3870
4096
|
return join;
|
|
@@ -3931,21 +4157,28 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3931
4157
|
* @returns {Promise}
|
|
3932
4158
|
*/
|
|
3933
4159
|
async updateLLMConnection() {
|
|
4160
|
+
// @ts-ignore - Fix type
|
|
3934
4161
|
const {url, info: {datachannelUrl} = {}} = this.locusInfo;
|
|
3935
4162
|
|
|
3936
4163
|
const isJoined = this.joinedWith && this.joinedWith.state === 'JOINED';
|
|
3937
4164
|
|
|
4165
|
+
// @ts-ignore - Fix type
|
|
3938
4166
|
if (this.webex.internal.llm.isConnected()) {
|
|
4167
|
+
// @ts-ignore - Fix type
|
|
3939
4168
|
if (url === this.webex.internal.llm.getLocusUrl() && isJoined) {
|
|
3940
4169
|
return undefined;
|
|
3941
4170
|
}
|
|
4171
|
+
// @ts-ignore - Fix type
|
|
3942
4172
|
await this.webex.internal.llm.disconnectLLM();
|
|
4173
|
+
// @ts-ignore - Fix type
|
|
4174
|
+
this.webex.internal.llm.off('event:relay.event', this.processRelayEvent);
|
|
3943
4175
|
}
|
|
3944
4176
|
|
|
3945
4177
|
if (!isJoined) {
|
|
3946
4178
|
return undefined;
|
|
3947
4179
|
}
|
|
3948
4180
|
|
|
4181
|
+
// @ts-ignore - Fix type
|
|
3949
4182
|
return this.webex.internal.llm.registerAndConnect(url, datachannelUrl);
|
|
3950
4183
|
}
|
|
3951
4184
|
|
|
@@ -3988,28 +4221,31 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3988
4221
|
|
|
3989
4222
|
if (!this.dialInUrl) this.dialInUrl = `dialin:///${uuid.v4()}`;
|
|
3990
4223
|
|
|
3991
|
-
return
|
|
3992
|
-
.
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4224
|
+
return (
|
|
4225
|
+
this.meetingRequest
|
|
4226
|
+
// @ts-ignore
|
|
4227
|
+
.dialIn({
|
|
4228
|
+
correlationId,
|
|
4229
|
+
dialInUrl: this.dialInUrl,
|
|
4230
|
+
locusUrl,
|
|
4231
|
+
clientUrl: this.deviceUrl,
|
|
4232
|
+
})
|
|
4233
|
+
.then((res) => {
|
|
4234
|
+
this.locusInfo.onFullLocus(res.body.locus);
|
|
4235
|
+
})
|
|
4236
|
+
.catch((error) => {
|
|
4237
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ADD_DIAL_IN_FAILURE, {
|
|
4238
|
+
correlation_id: this.correlationId,
|
|
4239
|
+
dial_in_url: this.dialInUrl,
|
|
4240
|
+
locus_id: locusUrl.split('/').pop(),
|
|
4241
|
+
client_url: this.deviceUrl,
|
|
4242
|
+
reason: error.error?.message,
|
|
4243
|
+
stack: error.stack,
|
|
4244
|
+
});
|
|
4010
4245
|
|
|
4011
|
-
|
|
4012
|
-
|
|
4246
|
+
return Promise.reject(error);
|
|
4247
|
+
})
|
|
4248
|
+
);
|
|
4013
4249
|
}
|
|
4014
4250
|
|
|
4015
4251
|
/**
|
|
@@ -4026,29 +4262,32 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4026
4262
|
|
|
4027
4263
|
if (!this.dialOutUrl) this.dialOutUrl = `dialout:///${uuid.v4()}`;
|
|
4028
4264
|
|
|
4029
|
-
return
|
|
4030
|
-
.
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
|
|
4265
|
+
return (
|
|
4266
|
+
this.meetingRequest
|
|
4267
|
+
// @ts-ignore
|
|
4268
|
+
.dialOut({
|
|
4269
|
+
correlationId,
|
|
4270
|
+
dialOutUrl: this.dialOutUrl,
|
|
4271
|
+
phoneNumber,
|
|
4272
|
+
locusUrl,
|
|
4273
|
+
clientUrl: this.deviceUrl,
|
|
4274
|
+
})
|
|
4275
|
+
.then((res) => {
|
|
4276
|
+
this.locusInfo.onFullLocus(res.body.locus);
|
|
4277
|
+
})
|
|
4278
|
+
.catch((error) => {
|
|
4279
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ADD_DIAL_OUT_FAILURE, {
|
|
4280
|
+
correlation_id: this.correlationId,
|
|
4281
|
+
dial_out_url: this.dialOutUrl,
|
|
4282
|
+
locus_id: locusUrl.split('/').pop(),
|
|
4283
|
+
client_url: this.deviceUrl,
|
|
4284
|
+
reason: error.error?.message,
|
|
4285
|
+
stack: error.stack,
|
|
4286
|
+
});
|
|
4049
4287
|
|
|
4050
|
-
|
|
4051
|
-
|
|
4288
|
+
return Promise.reject(error);
|
|
4289
|
+
})
|
|
4290
|
+
);
|
|
4052
4291
|
}
|
|
4053
4292
|
|
|
4054
4293
|
/**
|
|
@@ -4395,7 +4634,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4395
4634
|
Metrics.sendBehavioralMetric(metricName, data, metadata);
|
|
4396
4635
|
};
|
|
4397
4636
|
|
|
4398
|
-
if (error instanceof
|
|
4637
|
+
if (error instanceof Errors.SdpOfferCreationError) {
|
|
4399
4638
|
sendBehavioralMetric(BEHAVIORAL_METRICS.PEERCONNECTION_FAILURE, error, this.id);
|
|
4400
4639
|
|
|
4401
4640
|
Metrics.postEvent({
|
|
@@ -4409,8 +4648,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4409
4648
|
},
|
|
4410
4649
|
});
|
|
4411
4650
|
} else if (
|
|
4412
|
-
error instanceof
|
|
4413
|
-
error instanceof
|
|
4651
|
+
error instanceof Errors.SdpOfferHandlingError ||
|
|
4652
|
+
error instanceof Errors.SdpAnswerHandlingError
|
|
4414
4653
|
) {
|
|
4415
4654
|
sendBehavioralMetric(BEHAVIORAL_METRICS.PEERCONNECTION_FAILURE, error, this.id);
|
|
4416
4655
|
|
|
@@ -4424,8 +4663,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4424
4663
|
],
|
|
4425
4664
|
},
|
|
4426
4665
|
});
|
|
4427
|
-
} else if (error instanceof
|
|
4428
|
-
// this covers also the case of
|
|
4666
|
+
} else if (error instanceof Errors.SdpError) {
|
|
4667
|
+
// this covers also the case of Errors.IceGatheringError which extends Errors.SdpError
|
|
4429
4668
|
sendBehavioralMetric(BEHAVIORAL_METRICS.INVALID_ICE_CANDIDATE, error, this.id);
|
|
4430
4669
|
|
|
4431
4670
|
Metrics.postEvent({
|
|
@@ -4442,19 +4681,19 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4442
4681
|
};
|
|
4443
4682
|
|
|
4444
4683
|
setupMediaConnectionListeners = () => {
|
|
4445
|
-
this.mediaProperties.webrtcMediaConnection.on(
|
|
4684
|
+
this.mediaProperties.webrtcMediaConnection.on(Event.ROAP_STARTED, () => {
|
|
4446
4685
|
this.isRoapInProgress = true;
|
|
4447
4686
|
});
|
|
4448
4687
|
|
|
4449
|
-
this.mediaProperties.webrtcMediaConnection.on(
|
|
4688
|
+
this.mediaProperties.webrtcMediaConnection.on(Event.ROAP_DONE, () => {
|
|
4450
4689
|
this.mediaNegotiatedEvent();
|
|
4451
4690
|
this.isRoapInProgress = false;
|
|
4452
4691
|
this.processNextQueuedMediaUpdate();
|
|
4453
4692
|
});
|
|
4454
4693
|
|
|
4455
|
-
this.mediaProperties.webrtcMediaConnection.on(
|
|
4694
|
+
this.mediaProperties.webrtcMediaConnection.on(Event.ROAP_FAILURE, this.handleRoapFailure);
|
|
4456
4695
|
|
|
4457
|
-
this.mediaProperties.webrtcMediaConnection.on(
|
|
4696
|
+
this.mediaProperties.webrtcMediaConnection.on(Event.ROAP_MESSAGE_TO_SEND, (event) => {
|
|
4458
4697
|
const LOG_HEADER = 'Meeting:index#setupMediaConnectionListeners.ROAP_MESSAGE_TO_SEND -->';
|
|
4459
4698
|
|
|
4460
4699
|
switch (event.roapMessage.messageType) {
|
|
@@ -4536,8 +4775,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4536
4775
|
|
|
4537
4776
|
case 'ERROR':
|
|
4538
4777
|
if (
|
|
4539
|
-
event.roapMessage.errorType ===
|
|
4540
|
-
event.roapMessage.errorType ===
|
|
4778
|
+
event.roapMessage.errorType === ErrorType.CONFLICT ||
|
|
4779
|
+
event.roapMessage.errorType === ErrorType.DOUBLECONFLICT
|
|
4541
4780
|
) {
|
|
4542
4781
|
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ROAP_GLARE_CONDITION, {
|
|
4543
4782
|
correlation_id: this.correlationId,
|
|
@@ -4569,7 +4808,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4569
4808
|
});
|
|
4570
4809
|
|
|
4571
4810
|
// eslint-disable-next-line no-param-reassign
|
|
4572
|
-
this.mediaProperties.webrtcMediaConnection.on(
|
|
4811
|
+
this.mediaProperties.webrtcMediaConnection.on(Event.REMOTE_TRACK_ADDED, (event) => {
|
|
4573
4812
|
LoggerProxy.logger.log(
|
|
4574
4813
|
`Meeting:index#setupMediaConnectionListeners --> REMOTE_TRACK_ADDED event received for webrtcMediaConnection: ${JSON.stringify(
|
|
4575
4814
|
event
|
|
@@ -4582,15 +4821,15 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4582
4821
|
let eventType;
|
|
4583
4822
|
|
|
4584
4823
|
switch (event.type) {
|
|
4585
|
-
case
|
|
4824
|
+
case RemoteTrackType.AUDIO:
|
|
4586
4825
|
eventType = EVENT_TYPES.REMOTE_AUDIO;
|
|
4587
4826
|
this.mediaProperties.setRemoteAudioTrack(event.track);
|
|
4588
4827
|
break;
|
|
4589
|
-
case
|
|
4828
|
+
case RemoteTrackType.VIDEO:
|
|
4590
4829
|
eventType = EVENT_TYPES.REMOTE_VIDEO;
|
|
4591
4830
|
this.mediaProperties.setRemoteVideoTrack(event.track);
|
|
4592
4831
|
break;
|
|
4593
|
-
case
|
|
4832
|
+
case RemoteTrackType.SCREENSHARE_VIDEO:
|
|
4594
4833
|
if (event.track) {
|
|
4595
4834
|
eventType = EVENT_TYPES.REMOTE_SHARE;
|
|
4596
4835
|
this.mediaProperties.setRemoteShare(event.track);
|
|
@@ -4623,7 +4862,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4623
4862
|
}
|
|
4624
4863
|
});
|
|
4625
4864
|
|
|
4626
|
-
this.mediaProperties.webrtcMediaConnection.on(
|
|
4865
|
+
this.mediaProperties.webrtcMediaConnection.on(Event.CONNECTION_STATE_CHANGED, (event) => {
|
|
4627
4866
|
const connectionFailed = () => {
|
|
4628
4867
|
// we know the media connection failed and browser will not attempt to recover it any more
|
|
4629
4868
|
// so reset the timer as it's not needed anymore, we want to reconnect immediately
|
|
@@ -4656,10 +4895,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4656
4895
|
`Meeting:index#setupMediaConnectionListeners --> connection state changed to ${event.state}`
|
|
4657
4896
|
);
|
|
4658
4897
|
switch (event.state) {
|
|
4659
|
-
case
|
|
4898
|
+
case ConnectionState.Connecting:
|
|
4660
4899
|
Metrics.postEvent({event: eventType.ICE_START, meeting: this});
|
|
4661
4900
|
break;
|
|
4662
|
-
case
|
|
4901
|
+
case ConnectionState.Connected:
|
|
4663
4902
|
Metrics.postEvent({event: eventType.ICE_END, meeting: this});
|
|
4664
4903
|
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.CONNECTION_SUCCESS, {
|
|
4665
4904
|
correlation_id: this.correlationId,
|
|
@@ -4668,7 +4907,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4668
4907
|
this.setNetworkStatus(NETWORK_STATUS.CONNECTED);
|
|
4669
4908
|
this.reconnectionManager.iceReconnected();
|
|
4670
4909
|
break;
|
|
4671
|
-
case
|
|
4910
|
+
case ConnectionState.Disconnected:
|
|
4672
4911
|
this.setNetworkStatus(NETWORK_STATUS.DISCONNECTED);
|
|
4673
4912
|
this.reconnectionManager.waitForIceReconnect().catch(() => {
|
|
4674
4913
|
LoggerProxy.logger.info(
|
|
@@ -4678,7 +4917,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4678
4917
|
connectionFailed();
|
|
4679
4918
|
});
|
|
4680
4919
|
break;
|
|
4681
|
-
case
|
|
4920
|
+
case ConnectionState.Failed:
|
|
4682
4921
|
connectionFailed();
|
|
4683
4922
|
break;
|
|
4684
4923
|
default:
|
|
@@ -4686,7 +4925,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4686
4925
|
}
|
|
4687
4926
|
});
|
|
4688
4927
|
|
|
4689
|
-
this.mediaProperties.webrtcMediaConnection.on(
|
|
4928
|
+
this.mediaProperties.webrtcMediaConnection.on(Event.ACTIVE_SPEAKERS_CHANGED, (msg) => {
|
|
4690
4929
|
Trigger.trigger(
|
|
4691
4930
|
this,
|
|
4692
4931
|
{
|
|
@@ -4697,6 +4936,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4697
4936
|
{
|
|
4698
4937
|
seqNum: msg.seqNum,
|
|
4699
4938
|
memberIds: msg.csis
|
|
4939
|
+
// @ts-ignore
|
|
4700
4940
|
.map((csi) => this.members.findMemberByCsi(csi)?.id)
|
|
4701
4941
|
.filter((item) => item !== undefined),
|
|
4702
4942
|
}
|
|
@@ -4704,7 +4944,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4704
4944
|
});
|
|
4705
4945
|
|
|
4706
4946
|
this.mediaProperties.webrtcMediaConnection.on(
|
|
4707
|
-
|
|
4947
|
+
Event.VIDEO_SOURCES_COUNT_CHANGED,
|
|
4708
4948
|
(numTotalSources, numLiveSources) => {
|
|
4709
4949
|
Trigger.trigger(
|
|
4710
4950
|
this,
|
|
@@ -4722,7 +4962,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4722
4962
|
);
|
|
4723
4963
|
|
|
4724
4964
|
this.mediaProperties.webrtcMediaConnection.on(
|
|
4725
|
-
|
|
4965
|
+
Event.AUDIO_SOURCES_COUNT_CHANGED,
|
|
4726
4966
|
(numTotalSources, numLiveSources) => {
|
|
4727
4967
|
Trigger.trigger(
|
|
4728
4968
|
this,
|
|
@@ -4752,6 +4992,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4752
4992
|
// Add ip address info if geo hint is present
|
|
4753
4993
|
// @ts-ignore fix type
|
|
4754
4994
|
options.data.intervalMetadata.peerReflexiveIP =
|
|
4995
|
+
// @ts-ignore
|
|
4755
4996
|
this.webex.meetings.geoHintInfo?.clientAddress ||
|
|
4756
4997
|
options.data.intervalMetadata.peerReflexiveIP ||
|
|
4757
4998
|
MQA_STATS.DEFAULT_IP;
|
|
@@ -5082,7 +5323,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5082
5323
|
this
|
|
5083
5324
|
);
|
|
5084
5325
|
|
|
5085
|
-
if (error instanceof
|
|
5326
|
+
if (error instanceof Errors.SdpError) {
|
|
5086
5327
|
this.leave({reason: MEETING_REMOVED_REASON.MEETING_CONNECTION_FAILED});
|
|
5087
5328
|
}
|
|
5088
5329
|
|
|
@@ -5852,7 +6093,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5852
6093
|
* @memberof Meeting
|
|
5853
6094
|
*/
|
|
5854
6095
|
public startRecording() {
|
|
5855
|
-
return
|
|
6096
|
+
return this.recordingController.startRecording();
|
|
5856
6097
|
}
|
|
5857
6098
|
|
|
5858
6099
|
/**
|
|
@@ -5862,7 +6103,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5862
6103
|
* @memberof Meeting
|
|
5863
6104
|
*/
|
|
5864
6105
|
public stopRecording() {
|
|
5865
|
-
return
|
|
6106
|
+
return this.recordingController.stopRecording();
|
|
5866
6107
|
}
|
|
5867
6108
|
|
|
5868
6109
|
/**
|
|
@@ -5872,7 +6113,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5872
6113
|
* @memberof Meeting
|
|
5873
6114
|
*/
|
|
5874
6115
|
public pauseRecording() {
|
|
5875
|
-
return
|
|
6116
|
+
return this.recordingController.pauseRecording();
|
|
5876
6117
|
}
|
|
5877
6118
|
|
|
5878
6119
|
/**
|
|
@@ -5882,7 +6123,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5882
6123
|
* @memberof Meeting
|
|
5883
6124
|
*/
|
|
5884
6125
|
public resumeRecording() {
|
|
5885
|
-
return
|
|
6126
|
+
return this.recordingController.resumeRecording();
|
|
5886
6127
|
}
|
|
5887
6128
|
|
|
5888
6129
|
/**
|