@webex/plugin-meetings 3.0.0-beta.16 → 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 +43 -6
- 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/in-meeting-actions.js +5 -1
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +652 -459
- 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 +22 -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 +39 -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/in-meeting-actions.ts +8 -0
- package/src/meeting/index.ts +360 -111
- package/src/meeting/request.ts +9 -31
- package/src/meeting/request.type.ts +2 -0
- package/src/meeting/util.ts +25 -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/in-meeting-actions.ts +5 -1
- package/test/unit/spec/meeting/index.js +241 -50
- package/test/unit/spec/meeting/request.js +17 -0
- package/test/unit/spec/meeting/utils.js +28 -122
- 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(
|
|
@@ -2117,8 +2270,18 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2117
2270
|
payload.info.userDisplayHints
|
|
2118
2271
|
),
|
|
2119
2272
|
waitingForOthersToJoin: MeetingUtil.waitingForOthersToJoin(payload.info.userDisplayHints),
|
|
2273
|
+
canEnableReactions: MeetingUtil.canEnableReactions(
|
|
2274
|
+
this.inMeetingActions.canEnableReactions,
|
|
2275
|
+
payload.info.userDisplayHints
|
|
2276
|
+
),
|
|
2277
|
+
canSendReactions: MeetingUtil.canSendReactions(
|
|
2278
|
+
this.inMeetingActions.canSendReactions,
|
|
2279
|
+
payload.info.userDisplayHints
|
|
2280
|
+
),
|
|
2120
2281
|
});
|
|
2121
2282
|
|
|
2283
|
+
this.recordingController.setDisplayHints(payload.info.userDisplayHints);
|
|
2284
|
+
|
|
2122
2285
|
if (changed) {
|
|
2123
2286
|
Trigger.trigger(
|
|
2124
2287
|
this,
|
|
@@ -2142,6 +2305,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2142
2305
|
* @returns {void}
|
|
2143
2306
|
*/
|
|
2144
2307
|
handleDataChannelUrlChange(datachannelUrl) {
|
|
2308
|
+
// @ts-ignore - config coming from registerPlugin
|
|
2145
2309
|
if (datachannelUrl && this.config.enableAutomaticLLM) {
|
|
2146
2310
|
// Defer this as updateLLMConnection relies upon this.locusInfo.url which is only set
|
|
2147
2311
|
// after the MEETING_INFO_UPDATED callback finishes
|
|
@@ -2322,6 +2486,18 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2322
2486
|
);
|
|
2323
2487
|
});
|
|
2324
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
|
+
|
|
2325
2501
|
this.locusInfo.on(LOCUSINFO.EVENTS.SELF_IS_SHARING_BLOCKED_CHANGE, (payload) => {
|
|
2326
2502
|
Trigger.trigger(
|
|
2327
2503
|
this,
|
|
@@ -2357,7 +2533,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2357
2533
|
.catch((error) => {
|
|
2358
2534
|
// @ts-ignore
|
|
2359
2535
|
LoggerProxy.logger.error(
|
|
2360
|
-
`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}`
|
|
2361
2537
|
);
|
|
2362
2538
|
});
|
|
2363
2539
|
}
|
|
@@ -2392,7 +2568,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2392
2568
|
.catch((error) => {
|
|
2393
2569
|
// @ts-ignore
|
|
2394
2570
|
LoggerProxy.logger.error(
|
|
2395
|
-
`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}`
|
|
2396
2572
|
);
|
|
2397
2573
|
});
|
|
2398
2574
|
} else {
|
|
@@ -2634,6 +2810,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2634
2810
|
this.locusUrl = locusMeetingObject?.url || webexMeetingInfo?.locusUrl || this.locusUrl;
|
|
2635
2811
|
// @ts-ignore - config coming from registerPlugin
|
|
2636
2812
|
this.setSipUri(
|
|
2813
|
+
// @ts-ignore
|
|
2637
2814
|
this.config.experimental.enableUnifiedMeetings
|
|
2638
2815
|
? locusMeetingObject?.info.sipUri || webexMeetingInfo?.sipUrl
|
|
2639
2816
|
: locusMeetingObject?.info.sipUri || webexMeetingInfo?.sipMeetingUri || this.sipUri
|
|
@@ -3582,6 +3759,20 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3582
3759
|
return false;
|
|
3583
3760
|
}
|
|
3584
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
|
+
|
|
3585
3776
|
/**
|
|
3586
3777
|
* Monitor the Low-Latency Mercury (LLM) web socket connection on `onError` and `onClose` states
|
|
3587
3778
|
* @private
|
|
@@ -3633,6 +3824,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3633
3824
|
// @ts-ignore - fix type
|
|
3634
3825
|
const {
|
|
3635
3826
|
body: {webSocketUrl},
|
|
3827
|
+
// @ts-ignore
|
|
3636
3828
|
} = await this.request({
|
|
3637
3829
|
method: HTTP_VERBS.POST,
|
|
3638
3830
|
uri: datachannelUrl,
|
|
@@ -3682,6 +3874,44 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3682
3874
|
}
|
|
3683
3875
|
}
|
|
3684
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
|
+
|
|
3685
3915
|
/**
|
|
3686
3916
|
* stop recieving Transcription by closing
|
|
3687
3917
|
* the web socket connection properly
|
|
@@ -3855,8 +4085,12 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3855
4085
|
return join;
|
|
3856
4086
|
})
|
|
3857
4087
|
.then(async (join) => {
|
|
4088
|
+
// @ts-ignore - config coming from registerPlugin
|
|
3858
4089
|
if (this.config.enableAutomaticLLM) {
|
|
3859
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!');
|
|
3860
4094
|
}
|
|
3861
4095
|
|
|
3862
4096
|
return join;
|
|
@@ -3923,21 +4157,28 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3923
4157
|
* @returns {Promise}
|
|
3924
4158
|
*/
|
|
3925
4159
|
async updateLLMConnection() {
|
|
4160
|
+
// @ts-ignore - Fix type
|
|
3926
4161
|
const {url, info: {datachannelUrl} = {}} = this.locusInfo;
|
|
3927
4162
|
|
|
3928
4163
|
const isJoined = this.joinedWith && this.joinedWith.state === 'JOINED';
|
|
3929
4164
|
|
|
4165
|
+
// @ts-ignore - Fix type
|
|
3930
4166
|
if (this.webex.internal.llm.isConnected()) {
|
|
4167
|
+
// @ts-ignore - Fix type
|
|
3931
4168
|
if (url === this.webex.internal.llm.getLocusUrl() && isJoined) {
|
|
3932
4169
|
return undefined;
|
|
3933
4170
|
}
|
|
4171
|
+
// @ts-ignore - Fix type
|
|
3934
4172
|
await this.webex.internal.llm.disconnectLLM();
|
|
4173
|
+
// @ts-ignore - Fix type
|
|
4174
|
+
this.webex.internal.llm.off('event:relay.event', this.processRelayEvent);
|
|
3935
4175
|
}
|
|
3936
4176
|
|
|
3937
4177
|
if (!isJoined) {
|
|
3938
4178
|
return undefined;
|
|
3939
4179
|
}
|
|
3940
4180
|
|
|
4181
|
+
// @ts-ignore - Fix type
|
|
3941
4182
|
return this.webex.internal.llm.registerAndConnect(url, datachannelUrl);
|
|
3942
4183
|
}
|
|
3943
4184
|
|
|
@@ -3980,28 +4221,31 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3980
4221
|
|
|
3981
4222
|
if (!this.dialInUrl) this.dialInUrl = `dialin:///${uuid.v4()}`;
|
|
3982
4223
|
|
|
3983
|
-
return
|
|
3984
|
-
.
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
|
|
4001
|
-
|
|
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
|
+
});
|
|
4002
4245
|
|
|
4003
|
-
|
|
4004
|
-
|
|
4246
|
+
return Promise.reject(error);
|
|
4247
|
+
})
|
|
4248
|
+
);
|
|
4005
4249
|
}
|
|
4006
4250
|
|
|
4007
4251
|
/**
|
|
@@ -4018,29 +4262,32 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4018
4262
|
|
|
4019
4263
|
if (!this.dialOutUrl) this.dialOutUrl = `dialout:///${uuid.v4()}`;
|
|
4020
4264
|
|
|
4021
|
-
return
|
|
4022
|
-
.
|
|
4023
|
-
|
|
4024
|
-
|
|
4025
|
-
|
|
4026
|
-
|
|
4027
|
-
|
|
4028
|
-
|
|
4029
|
-
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
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
|
+
});
|
|
4041
4287
|
|
|
4042
|
-
|
|
4043
|
-
|
|
4288
|
+
return Promise.reject(error);
|
|
4289
|
+
})
|
|
4290
|
+
);
|
|
4044
4291
|
}
|
|
4045
4292
|
|
|
4046
4293
|
/**
|
|
@@ -4387,7 +4634,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4387
4634
|
Metrics.sendBehavioralMetric(metricName, data, metadata);
|
|
4388
4635
|
};
|
|
4389
4636
|
|
|
4390
|
-
if (error instanceof
|
|
4637
|
+
if (error instanceof Errors.SdpOfferCreationError) {
|
|
4391
4638
|
sendBehavioralMetric(BEHAVIORAL_METRICS.PEERCONNECTION_FAILURE, error, this.id);
|
|
4392
4639
|
|
|
4393
4640
|
Metrics.postEvent({
|
|
@@ -4401,8 +4648,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4401
4648
|
},
|
|
4402
4649
|
});
|
|
4403
4650
|
} else if (
|
|
4404
|
-
error instanceof
|
|
4405
|
-
error instanceof
|
|
4651
|
+
error instanceof Errors.SdpOfferHandlingError ||
|
|
4652
|
+
error instanceof Errors.SdpAnswerHandlingError
|
|
4406
4653
|
) {
|
|
4407
4654
|
sendBehavioralMetric(BEHAVIORAL_METRICS.PEERCONNECTION_FAILURE, error, this.id);
|
|
4408
4655
|
|
|
@@ -4416,8 +4663,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4416
4663
|
],
|
|
4417
4664
|
},
|
|
4418
4665
|
});
|
|
4419
|
-
} else if (error instanceof
|
|
4420
|
-
// 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
|
|
4421
4668
|
sendBehavioralMetric(BEHAVIORAL_METRICS.INVALID_ICE_CANDIDATE, error, this.id);
|
|
4422
4669
|
|
|
4423
4670
|
Metrics.postEvent({
|
|
@@ -4434,19 +4681,19 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4434
4681
|
};
|
|
4435
4682
|
|
|
4436
4683
|
setupMediaConnectionListeners = () => {
|
|
4437
|
-
this.mediaProperties.webrtcMediaConnection.on(
|
|
4684
|
+
this.mediaProperties.webrtcMediaConnection.on(Event.ROAP_STARTED, () => {
|
|
4438
4685
|
this.isRoapInProgress = true;
|
|
4439
4686
|
});
|
|
4440
4687
|
|
|
4441
|
-
this.mediaProperties.webrtcMediaConnection.on(
|
|
4688
|
+
this.mediaProperties.webrtcMediaConnection.on(Event.ROAP_DONE, () => {
|
|
4442
4689
|
this.mediaNegotiatedEvent();
|
|
4443
4690
|
this.isRoapInProgress = false;
|
|
4444
4691
|
this.processNextQueuedMediaUpdate();
|
|
4445
4692
|
});
|
|
4446
4693
|
|
|
4447
|
-
this.mediaProperties.webrtcMediaConnection.on(
|
|
4694
|
+
this.mediaProperties.webrtcMediaConnection.on(Event.ROAP_FAILURE, this.handleRoapFailure);
|
|
4448
4695
|
|
|
4449
|
-
this.mediaProperties.webrtcMediaConnection.on(
|
|
4696
|
+
this.mediaProperties.webrtcMediaConnection.on(Event.ROAP_MESSAGE_TO_SEND, (event) => {
|
|
4450
4697
|
const LOG_HEADER = 'Meeting:index#setupMediaConnectionListeners.ROAP_MESSAGE_TO_SEND -->';
|
|
4451
4698
|
|
|
4452
4699
|
switch (event.roapMessage.messageType) {
|
|
@@ -4528,8 +4775,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4528
4775
|
|
|
4529
4776
|
case 'ERROR':
|
|
4530
4777
|
if (
|
|
4531
|
-
event.roapMessage.errorType ===
|
|
4532
|
-
event.roapMessage.errorType ===
|
|
4778
|
+
event.roapMessage.errorType === ErrorType.CONFLICT ||
|
|
4779
|
+
event.roapMessage.errorType === ErrorType.DOUBLECONFLICT
|
|
4533
4780
|
) {
|
|
4534
4781
|
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ROAP_GLARE_CONDITION, {
|
|
4535
4782
|
correlation_id: this.correlationId,
|
|
@@ -4561,7 +4808,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4561
4808
|
});
|
|
4562
4809
|
|
|
4563
4810
|
// eslint-disable-next-line no-param-reassign
|
|
4564
|
-
this.mediaProperties.webrtcMediaConnection.on(
|
|
4811
|
+
this.mediaProperties.webrtcMediaConnection.on(Event.REMOTE_TRACK_ADDED, (event) => {
|
|
4565
4812
|
LoggerProxy.logger.log(
|
|
4566
4813
|
`Meeting:index#setupMediaConnectionListeners --> REMOTE_TRACK_ADDED event received for webrtcMediaConnection: ${JSON.stringify(
|
|
4567
4814
|
event
|
|
@@ -4574,15 +4821,15 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4574
4821
|
let eventType;
|
|
4575
4822
|
|
|
4576
4823
|
switch (event.type) {
|
|
4577
|
-
case
|
|
4824
|
+
case RemoteTrackType.AUDIO:
|
|
4578
4825
|
eventType = EVENT_TYPES.REMOTE_AUDIO;
|
|
4579
4826
|
this.mediaProperties.setRemoteAudioTrack(event.track);
|
|
4580
4827
|
break;
|
|
4581
|
-
case
|
|
4828
|
+
case RemoteTrackType.VIDEO:
|
|
4582
4829
|
eventType = EVENT_TYPES.REMOTE_VIDEO;
|
|
4583
4830
|
this.mediaProperties.setRemoteVideoTrack(event.track);
|
|
4584
4831
|
break;
|
|
4585
|
-
case
|
|
4832
|
+
case RemoteTrackType.SCREENSHARE_VIDEO:
|
|
4586
4833
|
if (event.track) {
|
|
4587
4834
|
eventType = EVENT_TYPES.REMOTE_SHARE;
|
|
4588
4835
|
this.mediaProperties.setRemoteShare(event.track);
|
|
@@ -4615,7 +4862,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4615
4862
|
}
|
|
4616
4863
|
});
|
|
4617
4864
|
|
|
4618
|
-
this.mediaProperties.webrtcMediaConnection.on(
|
|
4865
|
+
this.mediaProperties.webrtcMediaConnection.on(Event.CONNECTION_STATE_CHANGED, (event) => {
|
|
4619
4866
|
const connectionFailed = () => {
|
|
4620
4867
|
// we know the media connection failed and browser will not attempt to recover it any more
|
|
4621
4868
|
// so reset the timer as it's not needed anymore, we want to reconnect immediately
|
|
@@ -4648,10 +4895,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4648
4895
|
`Meeting:index#setupMediaConnectionListeners --> connection state changed to ${event.state}`
|
|
4649
4896
|
);
|
|
4650
4897
|
switch (event.state) {
|
|
4651
|
-
case
|
|
4898
|
+
case ConnectionState.Connecting:
|
|
4652
4899
|
Metrics.postEvent({event: eventType.ICE_START, meeting: this});
|
|
4653
4900
|
break;
|
|
4654
|
-
case
|
|
4901
|
+
case ConnectionState.Connected:
|
|
4655
4902
|
Metrics.postEvent({event: eventType.ICE_END, meeting: this});
|
|
4656
4903
|
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.CONNECTION_SUCCESS, {
|
|
4657
4904
|
correlation_id: this.correlationId,
|
|
@@ -4660,7 +4907,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4660
4907
|
this.setNetworkStatus(NETWORK_STATUS.CONNECTED);
|
|
4661
4908
|
this.reconnectionManager.iceReconnected();
|
|
4662
4909
|
break;
|
|
4663
|
-
case
|
|
4910
|
+
case ConnectionState.Disconnected:
|
|
4664
4911
|
this.setNetworkStatus(NETWORK_STATUS.DISCONNECTED);
|
|
4665
4912
|
this.reconnectionManager.waitForIceReconnect().catch(() => {
|
|
4666
4913
|
LoggerProxy.logger.info(
|
|
@@ -4670,7 +4917,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4670
4917
|
connectionFailed();
|
|
4671
4918
|
});
|
|
4672
4919
|
break;
|
|
4673
|
-
case
|
|
4920
|
+
case ConnectionState.Failed:
|
|
4674
4921
|
connectionFailed();
|
|
4675
4922
|
break;
|
|
4676
4923
|
default:
|
|
@@ -4678,7 +4925,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4678
4925
|
}
|
|
4679
4926
|
});
|
|
4680
4927
|
|
|
4681
|
-
this.mediaProperties.webrtcMediaConnection.on(
|
|
4928
|
+
this.mediaProperties.webrtcMediaConnection.on(Event.ACTIVE_SPEAKERS_CHANGED, (msg) => {
|
|
4682
4929
|
Trigger.trigger(
|
|
4683
4930
|
this,
|
|
4684
4931
|
{
|
|
@@ -4689,6 +4936,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4689
4936
|
{
|
|
4690
4937
|
seqNum: msg.seqNum,
|
|
4691
4938
|
memberIds: msg.csis
|
|
4939
|
+
// @ts-ignore
|
|
4692
4940
|
.map((csi) => this.members.findMemberByCsi(csi)?.id)
|
|
4693
4941
|
.filter((item) => item !== undefined),
|
|
4694
4942
|
}
|
|
@@ -4696,7 +4944,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4696
4944
|
});
|
|
4697
4945
|
|
|
4698
4946
|
this.mediaProperties.webrtcMediaConnection.on(
|
|
4699
|
-
|
|
4947
|
+
Event.VIDEO_SOURCES_COUNT_CHANGED,
|
|
4700
4948
|
(numTotalSources, numLiveSources) => {
|
|
4701
4949
|
Trigger.trigger(
|
|
4702
4950
|
this,
|
|
@@ -4714,7 +4962,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4714
4962
|
);
|
|
4715
4963
|
|
|
4716
4964
|
this.mediaProperties.webrtcMediaConnection.on(
|
|
4717
|
-
|
|
4965
|
+
Event.AUDIO_SOURCES_COUNT_CHANGED,
|
|
4718
4966
|
(numTotalSources, numLiveSources) => {
|
|
4719
4967
|
Trigger.trigger(
|
|
4720
4968
|
this,
|
|
@@ -4744,6 +4992,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4744
4992
|
// Add ip address info if geo hint is present
|
|
4745
4993
|
// @ts-ignore fix type
|
|
4746
4994
|
options.data.intervalMetadata.peerReflexiveIP =
|
|
4995
|
+
// @ts-ignore
|
|
4747
4996
|
this.webex.meetings.geoHintInfo?.clientAddress ||
|
|
4748
4997
|
options.data.intervalMetadata.peerReflexiveIP ||
|
|
4749
4998
|
MQA_STATS.DEFAULT_IP;
|
|
@@ -5074,7 +5323,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5074
5323
|
this
|
|
5075
5324
|
);
|
|
5076
5325
|
|
|
5077
|
-
if (error instanceof
|
|
5326
|
+
if (error instanceof Errors.SdpError) {
|
|
5078
5327
|
this.leave({reason: MEETING_REMOVED_REASON.MEETING_CONNECTION_FAILED});
|
|
5079
5328
|
}
|
|
5080
5329
|
|
|
@@ -5844,7 +6093,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5844
6093
|
* @memberof Meeting
|
|
5845
6094
|
*/
|
|
5846
6095
|
public startRecording() {
|
|
5847
|
-
return
|
|
6096
|
+
return this.recordingController.startRecording();
|
|
5848
6097
|
}
|
|
5849
6098
|
|
|
5850
6099
|
/**
|
|
@@ -5854,7 +6103,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5854
6103
|
* @memberof Meeting
|
|
5855
6104
|
*/
|
|
5856
6105
|
public stopRecording() {
|
|
5857
|
-
return
|
|
6106
|
+
return this.recordingController.stopRecording();
|
|
5858
6107
|
}
|
|
5859
6108
|
|
|
5860
6109
|
/**
|
|
@@ -5864,7 +6113,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5864
6113
|
* @memberof Meeting
|
|
5865
6114
|
*/
|
|
5866
6115
|
public pauseRecording() {
|
|
5867
|
-
return
|
|
6116
|
+
return this.recordingController.pauseRecording();
|
|
5868
6117
|
}
|
|
5869
6118
|
|
|
5870
6119
|
/**
|
|
@@ -5874,7 +6123,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5874
6123
|
* @memberof Meeting
|
|
5875
6124
|
*/
|
|
5876
6125
|
public resumeRecording() {
|
|
5877
|
-
return
|
|
6126
|
+
return this.recordingController.resumeRecording();
|
|
5878
6127
|
}
|
|
5879
6128
|
|
|
5880
6129
|
/**
|