@webex/plugin-meetings 1.149.2 → 1.151.1
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/constants.js +14 -4
- package/dist/constants.js.map +1 -1
- package/dist/locus-info/mediaSharesUtils.js +88 -11
- package/dist/locus-info/mediaSharesUtils.js.map +1 -1
- package/dist/meeting/index.js +368 -42
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/request.js +10 -4
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting-info/utilv2.js +3 -1
- package/dist/meeting-info/utilv2.js.map +1 -1
- package/dist/members/index.js +72 -11
- package/dist/members/index.js.map +1 -1
- package/dist/metrics/config.js +6 -0
- package/dist/metrics/config.js.map +1 -1
- package/dist/metrics/index.js +65 -45
- package/dist/metrics/index.js.map +1 -1
- package/dist/peer-connection-manager/index.js +1 -1
- package/dist/peer-connection-manager/index.js.map +1 -1
- package/package.json +6 -5
- package/src/constants.js +11 -2
- package/src/locus-info/mediaSharesUtils.js +84 -12
- package/src/meeting/index.js +350 -29
- package/src/meeting/request.js +10 -4
- package/src/meeting-info/utilv2.js +3 -0
- package/src/members/index.js +80 -11
- package/src/metrics/config.js +6 -0
- package/src/metrics/index.js +28 -17
- package/src/peer-connection-manager/index.js +7 -2
- package/test/integration/spec/journey.js +180 -3
- package/test/integration/spec/space-meeting.js +29 -6
- package/test/unit/spec/meeting/index.js +547 -3
- package/test/unit/spec/metrics/index.js +42 -1
- package/test/utils/testUtils.js +18 -1
- package/test/utils/webex-test-users.js +2 -0
package/src/meeting/index.js
CHANGED
|
@@ -51,6 +51,7 @@ import {
|
|
|
51
51
|
MEETING_STATE_MACHINE,
|
|
52
52
|
MEETING_STATE,
|
|
53
53
|
MEETINGS,
|
|
54
|
+
METRICS_JOIN_TIMES_MAX_DURATION,
|
|
54
55
|
METRICS_OPERATIONAL_MEASURES,
|
|
55
56
|
MQA_STATS,
|
|
56
57
|
NETWORK_STATUS,
|
|
@@ -1065,10 +1066,45 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1065
1066
|
};
|
|
1066
1067
|
}
|
|
1067
1068
|
|
|
1069
|
+
const localSDPGenRemoteSDPRecv = this.getLocalSDPGenRemoteSDPRecvDelay();
|
|
1070
|
+
|
|
1071
|
+
if (localSDPGenRemoteSDPRecv) {
|
|
1072
|
+
options.joinTimes = {
|
|
1073
|
+
...options.joinTimes,
|
|
1074
|
+
localSDPGenRemoteSDPRecv
|
|
1075
|
+
};
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
const callInitiateJoinReq = this.getCallInitiateJoinReq();
|
|
1079
|
+
|
|
1080
|
+
if (callInitiateJoinReq) {
|
|
1081
|
+
options.joinTimes = {
|
|
1082
|
+
...options.joinTimes,
|
|
1083
|
+
callInitiateJoinReq
|
|
1084
|
+
};
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
const joinReqResp = this.getJoinReqResp();
|
|
1088
|
+
|
|
1089
|
+
if (joinReqResp) {
|
|
1090
|
+
options.joinTimes = {
|
|
1091
|
+
...options.joinTimes,
|
|
1092
|
+
joinReqResp
|
|
1093
|
+
};
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
const getTotalJmt = this.getTotalJmt();
|
|
1097
|
+
|
|
1098
|
+
if (getTotalJmt) {
|
|
1099
|
+
options.joinTimes = {
|
|
1100
|
+
...options.joinTimes,
|
|
1101
|
+
getTotalJmt
|
|
1102
|
+
};
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1068
1105
|
if (options.type === MQA_STATS.CA_TYPE) {
|
|
1069
1106
|
payload = Metrics.initMediaPayload(options.event, identifiers, options);
|
|
1070
1107
|
}
|
|
1071
|
-
|
|
1072
1108
|
else {
|
|
1073
1109
|
payload = Metrics.initPayload(options.event, identifiers, options);
|
|
1074
1110
|
}
|
|
@@ -1310,7 +1346,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1310
1346
|
|
|
1311
1347
|
/**
|
|
1312
1348
|
* Set up the locus info media shares listener
|
|
1313
|
-
* update content sharing id value for members, and updates the member
|
|
1349
|
+
* update content and whiteboard sharing id value for members, and updates the member
|
|
1314
1350
|
* notifies consumer with members:content:update {activeContentSharingId, endedContentSharingId}
|
|
1315
1351
|
* @returns {undefined}
|
|
1316
1352
|
* @private
|
|
@@ -1319,11 +1355,16 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1319
1355
|
setUpLocusMediaSharesListener() {
|
|
1320
1356
|
// Will get triggered on local and remote share
|
|
1321
1357
|
this.locusInfo.on(EVENTS.LOCUS_INFO_UPDATE_MEDIA_SHARES, (payload) => {
|
|
1322
|
-
const {
|
|
1358
|
+
const {content: contentShare, whiteboard: whiteboardShare} = payload.current;
|
|
1359
|
+
const previousContentShare = payload.previous?.content;
|
|
1360
|
+
const previousWhiteboardShare = payload.previous?.whiteboard;
|
|
1323
1361
|
|
|
1324
1362
|
if (
|
|
1325
|
-
|
|
1326
|
-
|
|
1363
|
+
(contentShare.beneficiaryId === previousContentShare?.beneficiaryId &&
|
|
1364
|
+
contentShare.disposition === previousContentShare?.disposition) &&
|
|
1365
|
+
(whiteboardShare.beneficiaryId === previousWhiteboardShare?.beneficiaryId &&
|
|
1366
|
+
whiteboardShare.disposition === previousWhiteboardShare?.disposition &&
|
|
1367
|
+
whiteboardShare.resourceUrl === previousWhiteboardShare?.resourceUrl)
|
|
1327
1368
|
) {
|
|
1328
1369
|
// nothing changed, so ignore
|
|
1329
1370
|
// (this happens when we steal presentation from remote)
|
|
@@ -1334,15 +1375,16 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1334
1375
|
|
|
1335
1376
|
// REMOTE - check if remote started sharing
|
|
1336
1377
|
if (
|
|
1337
|
-
this.selfId !==
|
|
1338
|
-
disposition === FLOOR_ACTION.GRANTED
|
|
1378
|
+
this.selfId !== contentShare.beneficiaryId &&
|
|
1379
|
+
contentShare.disposition === FLOOR_ACTION.GRANTED
|
|
1339
1380
|
) {
|
|
1381
|
+
// CONTENT - sharing content remote
|
|
1340
1382
|
newShareStatus = SHARE_STATUS.REMOTE_SHARE_ACTIVE;
|
|
1341
1383
|
}
|
|
1342
|
-
// LOCAL - check if we started sharing
|
|
1384
|
+
// LOCAL - check if we started sharing content
|
|
1343
1385
|
else if (
|
|
1344
|
-
this.selfId ===
|
|
1345
|
-
disposition === FLOOR_ACTION.GRANTED
|
|
1386
|
+
this.selfId === contentShare.beneficiaryId &&
|
|
1387
|
+
contentShare.disposition === FLOOR_ACTION.GRANTED
|
|
1346
1388
|
) {
|
|
1347
1389
|
if (this.mediaProperties.shareTrack?.readyState === 'ended') {
|
|
1348
1390
|
this.stopShare({
|
|
@@ -1353,13 +1395,23 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1353
1395
|
});
|
|
1354
1396
|
}
|
|
1355
1397
|
else {
|
|
1398
|
+
// CONTENT - sharing content local
|
|
1356
1399
|
newShareStatus = SHARE_STATUS.LOCAL_SHARE_ACTIVE;
|
|
1357
1400
|
}
|
|
1358
1401
|
}
|
|
1359
|
-
//
|
|
1402
|
+
// If we did not hit the cases above, no one is sharng content, so we check if we are sharing whiteboard
|
|
1403
|
+
// There is no concept of local/remote share for whiteboard
|
|
1404
|
+
// It does not matter who requested to share the whiteboard, everyone gets the same view
|
|
1405
|
+
else if (whiteboardShare.disposition === FLOOR_ACTION.GRANTED) {
|
|
1406
|
+
// WHITEBOARD - sharing whiteboard
|
|
1407
|
+
newShareStatus = SHARE_STATUS.WHITEBOARD_SHARE_ACTIVE;
|
|
1408
|
+
}
|
|
1409
|
+
// or if content share is either released or null and whiteboard share is either released or null, no one is sharing
|
|
1360
1410
|
else if (
|
|
1361
|
-
|
|
1362
|
-
|
|
1411
|
+
(previousContentShare &&
|
|
1412
|
+
(contentShare.disposition === FLOOR_ACTION.RELEASED) || (contentShare.disposition === null)) &&
|
|
1413
|
+
(previousWhiteboardShare &&
|
|
1414
|
+
(whiteboardShare.disposition === FLOOR_ACTION.RELEASED) || (whiteboardShare.disposition === null))
|
|
1363
1415
|
) {
|
|
1364
1416
|
newShareStatus = SHARE_STATUS.NO_SHARE;
|
|
1365
1417
|
}
|
|
@@ -1397,6 +1449,17 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1397
1449
|
);
|
|
1398
1450
|
break;
|
|
1399
1451
|
|
|
1452
|
+
case SHARE_STATUS.WHITEBOARD_SHARE_ACTIVE:
|
|
1453
|
+
Trigger.trigger(
|
|
1454
|
+
this,
|
|
1455
|
+
{
|
|
1456
|
+
file: 'meeting/index',
|
|
1457
|
+
function: 'stopWhiteboardShare'
|
|
1458
|
+
},
|
|
1459
|
+
EVENT_TRIGGERS.MEETING_STOPPED_SHARING_WHITEBOARD
|
|
1460
|
+
);
|
|
1461
|
+
break;
|
|
1462
|
+
|
|
1400
1463
|
case SHARE_STATUS.NO_SHARE:
|
|
1401
1464
|
// nothing to do
|
|
1402
1465
|
break;
|
|
@@ -1417,13 +1480,16 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1417
1480
|
},
|
|
1418
1481
|
EVENT_TRIGGERS.MEETING_STARTED_SHARING_REMOTE,
|
|
1419
1482
|
{
|
|
1420
|
-
memberId:
|
|
1483
|
+
memberId: contentShare.beneficiaryId
|
|
1421
1484
|
}
|
|
1422
1485
|
);
|
|
1423
1486
|
};
|
|
1424
1487
|
|
|
1425
1488
|
// if a remote participant is stealing the presentation from us
|
|
1426
|
-
if (this.mediaProperties.mediaDirection?.sendShare) {
|
|
1489
|
+
if (!this.mediaProperties.mediaDirection?.sendShare || oldShareStatus === SHARE_STATUS.WHITEBOARD_SHARE_ACTIVE) {
|
|
1490
|
+
sendStartedSharingRemote();
|
|
1491
|
+
}
|
|
1492
|
+
else {
|
|
1427
1493
|
this.updateShare({
|
|
1428
1494
|
sendShare: false,
|
|
1429
1495
|
receiveShare: this.mediaProperties.mediaDirection.receiveShare
|
|
@@ -1432,9 +1498,6 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1432
1498
|
sendStartedSharingRemote();
|
|
1433
1499
|
});
|
|
1434
1500
|
}
|
|
1435
|
-
else {
|
|
1436
|
-
sendStartedSharingRemote();
|
|
1437
|
-
}
|
|
1438
1501
|
break;
|
|
1439
1502
|
}
|
|
1440
1503
|
|
|
@@ -1450,6 +1513,22 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1450
1513
|
Metrics.postEvent({event: eventType.LOCAL_SHARE_FLOOR_GRANTED, meeting: this});
|
|
1451
1514
|
break;
|
|
1452
1515
|
|
|
1516
|
+
case SHARE_STATUS.WHITEBOARD_SHARE_ACTIVE:
|
|
1517
|
+
Trigger.trigger(
|
|
1518
|
+
this,
|
|
1519
|
+
{
|
|
1520
|
+
file: 'meeting/index',
|
|
1521
|
+
function: 'startWhiteboardShare'
|
|
1522
|
+
},
|
|
1523
|
+
EVENT_TRIGGERS.MEETING_STARTED_SHARING_WHITEBOARD,
|
|
1524
|
+
{
|
|
1525
|
+
resourceUrl: whiteboardShare.resourceUrl,
|
|
1526
|
+
memberId: whiteboardShare.beneficiaryId
|
|
1527
|
+
}
|
|
1528
|
+
);
|
|
1529
|
+
Metrics.postEvent({event: eventType.WHITEBOARD_SHARE_FLOOR_GRANTED, meeting: this});
|
|
1530
|
+
break;
|
|
1531
|
+
|
|
1453
1532
|
case SHARE_STATUS.NO_SHARE:
|
|
1454
1533
|
// nothing to do
|
|
1455
1534
|
break;
|
|
@@ -1471,9 +1550,27 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1471
1550
|
},
|
|
1472
1551
|
EVENT_TRIGGERS.MEETING_STARTED_SHARING_REMOTE,
|
|
1473
1552
|
{
|
|
1474
|
-
memberId:
|
|
1553
|
+
memberId: contentShare.beneficiaryId
|
|
1554
|
+
}
|
|
1555
|
+
);
|
|
1556
|
+
this.members.locusMediaSharesUpdate(payload);
|
|
1557
|
+
}
|
|
1558
|
+
else if (newShareStatus === SHARE_STATUS.WHITEBOARD_SHARE_ACTIVE) {
|
|
1559
|
+
// if we got here, then some remote participant has stolen
|
|
1560
|
+
// the presentation from another remote participant
|
|
1561
|
+
Trigger.trigger(
|
|
1562
|
+
this,
|
|
1563
|
+
{
|
|
1564
|
+
file: 'meeting/index',
|
|
1565
|
+
function: 'startWhiteboardShare'
|
|
1566
|
+
},
|
|
1567
|
+
EVENT_TRIGGERS.MEETING_STARTED_SHARING_WHITEBOARD,
|
|
1568
|
+
{
|
|
1569
|
+
resourceUrl: whiteboardShare.resourceUrl,
|
|
1570
|
+
memberId: whiteboardShare.beneficiaryId
|
|
1475
1571
|
}
|
|
1476
1572
|
);
|
|
1573
|
+
Metrics.postEvent({event: eventType.WHITEBOARD_SHARE_FLOOR_GRANTED, meeting: this});
|
|
1477
1574
|
this.members.locusMediaSharesUpdate(payload);
|
|
1478
1575
|
}
|
|
1479
1576
|
});
|
|
@@ -3311,12 +3408,13 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3311
3408
|
}
|
|
3312
3409
|
}
|
|
3313
3410
|
|
|
3314
|
-
return MeetingUtil.joinMeetingOptions(this, options)
|
|
3315
|
-
|
|
3316
|
-
|
|
3411
|
+
return MeetingUtil.joinMeetingOptions(this, options)
|
|
3412
|
+
.then((join) => {
|
|
3413
|
+
this.meetingFiniteStateMachine.join();
|
|
3414
|
+
LoggerProxy.logger.log('Meeting:index#join --> Success');
|
|
3317
3415
|
|
|
3318
|
-
|
|
3319
|
-
|
|
3416
|
+
return join;
|
|
3417
|
+
})
|
|
3320
3418
|
.then((join) => {
|
|
3321
3419
|
joinSuccess(join);
|
|
3322
3420
|
this.deferJoin = undefined;
|
|
@@ -3790,7 +3888,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3790
3888
|
meetingId: this.id,
|
|
3791
3889
|
remoteQualityLevel: this.mediaProperties.remoteQualityLevel,
|
|
3792
3890
|
enableRtx: this.config.enableRtx,
|
|
3793
|
-
enableExtmap: this.config.enableExtmap
|
|
3891
|
+
enableExtmap: this.config.enableExtmap,
|
|
3892
|
+
setStartLocalSDPGenRemoteSDPRecvDelay: this.setStartLocalSDPGenRemoteSDPRecvDelay.bind(this)
|
|
3794
3893
|
})
|
|
3795
3894
|
.then((peerConnection) => this.getDevices().then((devices) => {
|
|
3796
3895
|
MeetingUtil.handleDeviceLogging(devices);
|
|
@@ -4491,6 +4590,105 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4491
4590
|
});
|
|
4492
4591
|
}
|
|
4493
4592
|
|
|
4593
|
+
/**
|
|
4594
|
+
* Start sharing whiteboard given channelUrl
|
|
4595
|
+
* @param {string} channelUrl whiteboard url
|
|
4596
|
+
* @param {String} resourceToken token created by authorize media injector
|
|
4597
|
+
* @returns {Promise}
|
|
4598
|
+
* @public
|
|
4599
|
+
* @memberof Meeting
|
|
4600
|
+
*/
|
|
4601
|
+
startWhiteboardShare(channelUrl, resourceToken) {
|
|
4602
|
+
const whiteboard = this.locusInfo.mediaShares.find((element) => element.name === 'whiteboard');
|
|
4603
|
+
|
|
4604
|
+
if (!channelUrl) {
|
|
4605
|
+
return Promise.reject(new ParameterError('Cannot share without channelUrl.'));
|
|
4606
|
+
}
|
|
4607
|
+
|
|
4608
|
+
if (whiteboard) {
|
|
4609
|
+
Metrics.postEvent({event: eventType.WHITEBOARD_SHARE_INITIATED, meeting: this});
|
|
4610
|
+
|
|
4611
|
+
const body = {
|
|
4612
|
+
disposition: FLOOR_ACTION.GRANTED,
|
|
4613
|
+
personUrl: this.locusInfo.self.url,
|
|
4614
|
+
deviceUrl: this.deviceUrl,
|
|
4615
|
+
uri: whiteboard.url,
|
|
4616
|
+
resourceUrl: channelUrl
|
|
4617
|
+
};
|
|
4618
|
+
|
|
4619
|
+
if (resourceToken) {
|
|
4620
|
+
body.resourceToken = resourceToken;
|
|
4621
|
+
}
|
|
4622
|
+
|
|
4623
|
+
return this.meetingRequest.changeMeetingFloor(body)
|
|
4624
|
+
.then(() => {
|
|
4625
|
+
this.isSharing = false;
|
|
4626
|
+
|
|
4627
|
+
return Promise.resolve();
|
|
4628
|
+
})
|
|
4629
|
+
.catch((error) => {
|
|
4630
|
+
LoggerProxy.logger.error('Meeting:index#startWhiteboardShare --> Error ', error);
|
|
4631
|
+
|
|
4632
|
+
Metrics.sendOperationalMetric(
|
|
4633
|
+
METRICS_OPERATIONAL_MEASURES.MEETING_START_WHITEBOARD_SHARE_FAILURE,
|
|
4634
|
+
{
|
|
4635
|
+
correlation_id: this.correlationId,
|
|
4636
|
+
locus_id: this.locusUrl.split('/').pop(),
|
|
4637
|
+
reason: error.message,
|
|
4638
|
+
stack: error.stack,
|
|
4639
|
+
board: {channelUrl}
|
|
4640
|
+
}
|
|
4641
|
+
);
|
|
4642
|
+
|
|
4643
|
+
return Promise.reject(error);
|
|
4644
|
+
});
|
|
4645
|
+
}
|
|
4646
|
+
|
|
4647
|
+
return Promise.reject(new ParameterError('Cannot share without whiteboard.'));
|
|
4648
|
+
}
|
|
4649
|
+
|
|
4650
|
+
/**
|
|
4651
|
+
* Stop sharing whiteboard given channelUrl
|
|
4652
|
+
* @param {string} channelUrl whiteboard url
|
|
4653
|
+
* @returns {Promise}
|
|
4654
|
+
* @public
|
|
4655
|
+
* @memberof Meeting
|
|
4656
|
+
*/
|
|
4657
|
+
stopWhiteboardShare(channelUrl) {
|
|
4658
|
+
const whiteboard = this.locusInfo.mediaShares.find((element) => element.name === 'whiteboard');
|
|
4659
|
+
|
|
4660
|
+
if (whiteboard) {
|
|
4661
|
+
Metrics.postEvent({event: eventType.WHITEBOARD_SHARE_STOPPED, meeting: this});
|
|
4662
|
+
|
|
4663
|
+
return this.meetingRequest.changeMeetingFloor({
|
|
4664
|
+
disposition: FLOOR_ACTION.RELEASED,
|
|
4665
|
+
personUrl: this.locusInfo.self.url,
|
|
4666
|
+
deviceUrl: this.deviceUrl,
|
|
4667
|
+
uri: whiteboard.url
|
|
4668
|
+
})
|
|
4669
|
+
.catch((error) => {
|
|
4670
|
+
LoggerProxy.logger.error('Meeting:index#stopWhiteboardShare --> Error ', error);
|
|
4671
|
+
|
|
4672
|
+
Metrics.sendOperationalMetric(
|
|
4673
|
+
METRICS_OPERATIONAL_MEASURES.STOP_WHITEBOARD_SHARE_FAILURE,
|
|
4674
|
+
{
|
|
4675
|
+
correlation_id: this.correlationId,
|
|
4676
|
+
locus_id: this.locusUrl.split('/').pop(),
|
|
4677
|
+
reason: error.message,
|
|
4678
|
+
stack: error.stack,
|
|
4679
|
+
board: {channelUrl}
|
|
4680
|
+
}
|
|
4681
|
+
);
|
|
4682
|
+
|
|
4683
|
+
return Promise.reject(error);
|
|
4684
|
+
})
|
|
4685
|
+
.finally(() => {
|
|
4686
|
+
});
|
|
4687
|
+
}
|
|
4688
|
+
|
|
4689
|
+
return Promise.reject(new ParameterError('Cannot stop share without whiteboard.'));
|
|
4690
|
+
}
|
|
4691
|
+
|
|
4494
4692
|
/**
|
|
4495
4693
|
* Start sharing content with server
|
|
4496
4694
|
* @returns {Promise} see #meetingRequest.changeMeetingFloor
|
|
@@ -4564,7 +4762,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4564
4762
|
Metrics.postEvent({event: eventType.SHARE_STOPPED, meeting: this});
|
|
4565
4763
|
Media.stopTracks(this.mediaProperties.shareTrack);
|
|
4566
4764
|
|
|
4567
|
-
if (
|
|
4765
|
+
if (content.floor.beneficiary.id !== this.selfId) {
|
|
4568
4766
|
// remote participant started sharing and caused our sharing to stop, we don't want to send any floor action request in that case
|
|
4569
4767
|
this.isSharing = false;
|
|
4570
4768
|
|
|
@@ -5078,9 +5276,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5078
5276
|
}
|
|
5079
5277
|
|
|
5080
5278
|
/**
|
|
5081
|
-
|
|
5082
|
-
|
|
5083
|
-
|
|
5279
|
+
* @param {string} typeMedia 'audio' or 'video'
|
|
5280
|
+
* @returns {undefined}
|
|
5281
|
+
*/
|
|
5084
5282
|
setEndSendingMediaDelay(typeMedia) {
|
|
5085
5283
|
this[`endSendingMediaDelay${typeMedia}`] = performance.now();
|
|
5086
5284
|
}
|
|
@@ -5095,4 +5293,127 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5095
5293
|
|
|
5096
5294
|
return (start && end) ? end - start : undefined;
|
|
5097
5295
|
}
|
|
5296
|
+
|
|
5297
|
+
/**
|
|
5298
|
+
*
|
|
5299
|
+
* @returns {undefined}
|
|
5300
|
+
*/
|
|
5301
|
+
setStartLocalSDPGenRemoteSDPRecvDelay() {
|
|
5302
|
+
if (!this.startLocalSDPGenRemoteSDPRecvDelay) {
|
|
5303
|
+
this.startLocalSDPGenRemoteSDPRecvDelay = performance.now();
|
|
5304
|
+
this.endLocalSDPGenRemoteSDPRecvDelay = undefined;
|
|
5305
|
+
}
|
|
5306
|
+
}
|
|
5307
|
+
|
|
5308
|
+
/**
|
|
5309
|
+
*
|
|
5310
|
+
* @returns {undefined}
|
|
5311
|
+
*/
|
|
5312
|
+
setEndLocalSDPGenRemoteSDPRecvDelay() {
|
|
5313
|
+
if (!this.endLocalSDPGenRemoteSDPRecvDelay) {
|
|
5314
|
+
this.endLocalSDPGenRemoteSDPRecvDelay = performance.now();
|
|
5315
|
+
}
|
|
5316
|
+
}
|
|
5317
|
+
|
|
5318
|
+
/**
|
|
5319
|
+
*
|
|
5320
|
+
* @returns {string} duration between local SDP generation and remote SDP reception
|
|
5321
|
+
*/
|
|
5322
|
+
getLocalSDPGenRemoteSDPRecvDelay() {
|
|
5323
|
+
const start = this.startLocalSDPGenRemoteSDPRecvDelay;
|
|
5324
|
+
const end = this.endLocalSDPGenRemoteSDPRecvDelay;
|
|
5325
|
+
|
|
5326
|
+
if (start && end) {
|
|
5327
|
+
const calculatedDelay = end - start;
|
|
5328
|
+
|
|
5329
|
+
return calculatedDelay > METRICS_JOIN_TIMES_MAX_DURATION ?
|
|
5330
|
+
undefined :
|
|
5331
|
+
calculatedDelay;
|
|
5332
|
+
}
|
|
5333
|
+
|
|
5334
|
+
return undefined;
|
|
5335
|
+
}
|
|
5336
|
+
|
|
5337
|
+
/**
|
|
5338
|
+
*
|
|
5339
|
+
* @returns {undefined}
|
|
5340
|
+
*/
|
|
5341
|
+
setStartCallInitiateJoinReq() {
|
|
5342
|
+
this.startCallInitiateJoinReq = performance.now();
|
|
5343
|
+
this.endCallInitiateJoinReq = undefined;
|
|
5344
|
+
}
|
|
5345
|
+
|
|
5346
|
+
/**
|
|
5347
|
+
*
|
|
5348
|
+
* @returns {undefined}
|
|
5349
|
+
*/
|
|
5350
|
+
setEndCallInitiateJoinReq() {
|
|
5351
|
+
this.endCallInitiateJoinReq = performance.now();
|
|
5352
|
+
}
|
|
5353
|
+
|
|
5354
|
+
/**
|
|
5355
|
+
*
|
|
5356
|
+
* @returns {string} duration between call initiate and sending join request to locus
|
|
5357
|
+
*/
|
|
5358
|
+
getCallInitiateJoinReq() {
|
|
5359
|
+
const start = this.startCallInitiateJoinReq;
|
|
5360
|
+
const end = this.endCallInitiateJoinReq;
|
|
5361
|
+
|
|
5362
|
+
if (start && end) {
|
|
5363
|
+
const calculatedDelay = end - start;
|
|
5364
|
+
|
|
5365
|
+
return calculatedDelay > METRICS_JOIN_TIMES_MAX_DURATION ?
|
|
5366
|
+
undefined :
|
|
5367
|
+
calculatedDelay;
|
|
5368
|
+
}
|
|
5369
|
+
|
|
5370
|
+
return undefined;
|
|
5371
|
+
}
|
|
5372
|
+
|
|
5373
|
+
/**
|
|
5374
|
+
*
|
|
5375
|
+
* @returns {undefined}
|
|
5376
|
+
*/
|
|
5377
|
+
setStartJoinReqResp() {
|
|
5378
|
+
this.startJoinReqResp = performance.now();
|
|
5379
|
+
this.endJoinReqResp = undefined;
|
|
5380
|
+
}
|
|
5381
|
+
|
|
5382
|
+
/**
|
|
5383
|
+
*
|
|
5384
|
+
* @returns {undefined}
|
|
5385
|
+
*/
|
|
5386
|
+
setEndJoinReqResp() {
|
|
5387
|
+
this.endJoinReqResp = performance.now();
|
|
5388
|
+
}
|
|
5389
|
+
|
|
5390
|
+
/**
|
|
5391
|
+
*
|
|
5392
|
+
* @returns {string} duration between sending locus join request and receiving join response
|
|
5393
|
+
*/
|
|
5394
|
+
getJoinReqResp() {
|
|
5395
|
+
const start = this.startJoinReqResp;
|
|
5396
|
+
const end = this.endJoinReqResp;
|
|
5397
|
+
|
|
5398
|
+
if (start && end) {
|
|
5399
|
+
const calculatedDelay = end - start;
|
|
5400
|
+
|
|
5401
|
+
return calculatedDelay > METRICS_JOIN_TIMES_MAX_DURATION ?
|
|
5402
|
+
undefined :
|
|
5403
|
+
calculatedDelay;
|
|
5404
|
+
}
|
|
5405
|
+
|
|
5406
|
+
return undefined;
|
|
5407
|
+
}
|
|
5408
|
+
|
|
5409
|
+
/**
|
|
5410
|
+
*
|
|
5411
|
+
* @returns {string} duration between call initiate and successful locus join (even if it is in lobby)
|
|
5412
|
+
*/
|
|
5413
|
+
getTotalJmt() {
|
|
5414
|
+
const start = this.startCallInitiateJoinReq;
|
|
5415
|
+
const end = this.endJoinReqResp;
|
|
5416
|
+
|
|
5417
|
+
return (start && end) ? end - start : undefined;
|
|
5418
|
+
}
|
|
5098
5419
|
}
|
package/src/meeting/request.js
CHANGED
|
@@ -523,13 +523,19 @@ export default class MeetingRequest extends StatelessWebexPlugin {
|
|
|
523
523
|
};
|
|
524
524
|
}
|
|
525
525
|
|
|
526
|
+
const body = {
|
|
527
|
+
floor: floorReq,
|
|
528
|
+
resourceUrl: options.resourceUrl
|
|
529
|
+
};
|
|
530
|
+
|
|
531
|
+
if (options?.resourceToken) {
|
|
532
|
+
body.resourceToken = options?.resourceToken;
|
|
533
|
+
}
|
|
534
|
+
|
|
526
535
|
return this.request({
|
|
527
536
|
uri: options.uri,
|
|
528
537
|
method: HTTP_VERBS.PUT,
|
|
529
|
-
body
|
|
530
|
-
floor: floorReq,
|
|
531
|
-
resourceUrl: options.resourceUrl
|
|
532
|
-
}
|
|
538
|
+
body
|
|
533
539
|
});
|
|
534
540
|
}
|
|
535
541
|
|
|
@@ -214,6 +214,9 @@ MeetingInfoUtil.getRequestBody = (options) => {
|
|
|
214
214
|
if (destination.info?.webExMeetingId) {
|
|
215
215
|
body.meetingKey = destination.info.webExMeetingId;
|
|
216
216
|
}
|
|
217
|
+
else if (destination.info?.sipUri) {
|
|
218
|
+
body.sipUrl = destination.info.sipUri;
|
|
219
|
+
}
|
|
217
220
|
break;
|
|
218
221
|
case _MEETING_LINK_:
|
|
219
222
|
body.meetingUrl = destination;
|
package/src/members/index.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import {isEmpty} from 'lodash';
|
|
5
5
|
import {StatelessWebexPlugin} from '@webex/webex-core';
|
|
6
6
|
|
|
7
|
-
import {MEETINGS, EVENT_TRIGGERS, FLOOR_ACTION, CONTENT} from '../constants';
|
|
7
|
+
import {MEETINGS, EVENT_TRIGGERS, FLOOR_ACTION, CONTENT, WHITEBOARD} from '../constants';
|
|
8
8
|
import Trigger from '../common/events/trigger-proxy';
|
|
9
9
|
import Member from '../member';
|
|
10
10
|
import LoggerProxy from '../common/logs/logger-proxy';
|
|
@@ -132,6 +132,14 @@ export default class Members extends StatelessWebexPlugin {
|
|
|
132
132
|
* @memberof Members
|
|
133
133
|
*/
|
|
134
134
|
this.mediaShareContentId = null;
|
|
135
|
+
/**
|
|
136
|
+
* The current mediaShareWhiteboardId for the meeting
|
|
137
|
+
* @instance
|
|
138
|
+
* @type {String}
|
|
139
|
+
* @private
|
|
140
|
+
* @memberof Members
|
|
141
|
+
*/
|
|
142
|
+
this.mediaShareWhiteboardId = null;
|
|
135
143
|
/**
|
|
136
144
|
* The current recordingId for the meeting, if it exists
|
|
137
145
|
* @instance
|
|
@@ -281,20 +289,49 @@ export default class Members extends StatelessWebexPlugin {
|
|
|
281
289
|
* @memberof Members
|
|
282
290
|
*/
|
|
283
291
|
locusMediaSharesUpdate(payload) {
|
|
284
|
-
const currentContent = payload.current;
|
|
285
|
-
const previousContent = payload.previous;
|
|
292
|
+
const currentContent = payload.current?.content;
|
|
293
|
+
const previousContent = payload.previous?.content;
|
|
294
|
+
const currentWhiteboard = payload.current?.whiteboard;
|
|
295
|
+
const previousWhiteboard = payload.previous?.whiteboard;
|
|
286
296
|
let whoSharing = null;
|
|
287
297
|
let whoStopped = null;
|
|
288
298
|
|
|
289
|
-
if (currentContent
|
|
299
|
+
if (currentContent?.beneficiaryId) {
|
|
290
300
|
if (currentContent.disposition === FLOOR_ACTION.GRANTED) {
|
|
291
|
-
whoSharing = currentContent.
|
|
292
|
-
|
|
301
|
+
whoSharing = currentContent.beneficiaryId;
|
|
302
|
+
this.mediaShareWhiteboardId = null;
|
|
303
|
+
this.mediaShareContentId = whoSharing;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (previousContent?.disposition === FLOOR_ACTION.GRANTED) {
|
|
307
|
+
if (currentContent.disposition === FLOOR_ACTION.RELEASED) {
|
|
308
|
+
whoStopped = currentContent.beneficiaryId;
|
|
309
|
+
this.mediaShareContentId = null;
|
|
310
|
+
}
|
|
311
|
+
else if (currentContent.disposition === FLOOR_ACTION.GRANTED && currentContent.beneficiaryId !== previousContent.beneficiaryId) {
|
|
312
|
+
whoStopped = previousContent.beneficiaryId;
|
|
313
|
+
}
|
|
293
314
|
}
|
|
294
|
-
|
|
295
|
-
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
if (currentWhiteboard?.beneficiaryId) {
|
|
318
|
+
if (currentWhiteboard.disposition === FLOOR_ACTION.GRANTED) {
|
|
319
|
+
whoSharing = currentWhiteboard.beneficiaryId;
|
|
320
|
+
this.mediaShareContentId = null;
|
|
321
|
+
this.mediaShareWhiteboardId = whoSharing;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
if (previousWhiteboard?.disposition === FLOOR_ACTION.GRANTED) {
|
|
325
|
+
if (currentWhiteboard.disposition === FLOOR_ACTION.RELEASED) {
|
|
326
|
+
whoStopped = currentWhiteboard.beneficiaryId;
|
|
327
|
+
this.mediaShareWhiteboardId = null;
|
|
328
|
+
}
|
|
329
|
+
else if (currentWhiteboard.disposition === FLOOR_ACTION.GRANTED && currentWhiteboard.beneficiaryId !== previousWhiteboard.beneficiaryId) {
|
|
330
|
+
whoStopped = previousWhiteboard.beneficiaryId;
|
|
331
|
+
}
|
|
296
332
|
}
|
|
297
333
|
}
|
|
334
|
+
|
|
298
335
|
if (whoSharing) {
|
|
299
336
|
const shareMember = this.membersCollection.get(whoSharing);
|
|
300
337
|
|
|
@@ -309,7 +346,7 @@ export default class Members extends StatelessWebexPlugin {
|
|
|
309
346
|
stopMember.setIsContentSharing(false);
|
|
310
347
|
}
|
|
311
348
|
}
|
|
312
|
-
|
|
349
|
+
|
|
313
350
|
Trigger.trigger(
|
|
314
351
|
this,
|
|
315
352
|
{
|
|
@@ -318,8 +355,8 @@ export default class Members extends StatelessWebexPlugin {
|
|
|
318
355
|
},
|
|
319
356
|
EVENT_TRIGGERS.MEMBERS_CONTENT_UPDATE,
|
|
320
357
|
{
|
|
321
|
-
|
|
322
|
-
|
|
358
|
+
activeSharingId: whoSharing,
|
|
359
|
+
endedSharingId: whoStopped
|
|
323
360
|
}
|
|
324
361
|
);
|
|
325
362
|
}
|
|
@@ -524,6 +561,36 @@ export default class Members extends StatelessWebexPlugin {
|
|
|
524
561
|
}
|
|
525
562
|
}
|
|
526
563
|
|
|
564
|
+
/**
|
|
565
|
+
* Update the media share whiteboard id
|
|
566
|
+
* @param {Object} locus
|
|
567
|
+
* @param {String} [whiteboardId] optional, takes precedence
|
|
568
|
+
* @throws {Error}
|
|
569
|
+
* @returns {undefined}
|
|
570
|
+
* @memberof Members
|
|
571
|
+
*/
|
|
572
|
+
setMediaShareWhiteboardId(locus, whiteboardId) {
|
|
573
|
+
if (whiteboardId) {
|
|
574
|
+
this.mediaShareWhiteboardId = whiteboardId;
|
|
575
|
+
}
|
|
576
|
+
else if (locus) {
|
|
577
|
+
const whiteboardMediaShare =
|
|
578
|
+
locus.mediaShares &&
|
|
579
|
+
locus.mediaShares.length &&
|
|
580
|
+
locus.mediaShares.find((mediaShare) => mediaShare.name === WHITEBOARD);
|
|
581
|
+
|
|
582
|
+
this.mediaShareWhiteboardId =
|
|
583
|
+
(whiteboardMediaShare &&
|
|
584
|
+
whiteboardMediaShare.floor &&
|
|
585
|
+
whiteboardMediaShare.floor.beneficiary &&
|
|
586
|
+
whiteboardMediaShare.floor.beneficiary.id) ||
|
|
587
|
+
null;
|
|
588
|
+
}
|
|
589
|
+
else {
|
|
590
|
+
throw new ParameterError('Setting hostid for the Members module should be done with a locus object or hostId');
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
527
594
|
/**
|
|
528
595
|
* Find all the updates, and added members
|
|
529
596
|
* Removed/left members will end up in updates
|
|
@@ -552,6 +619,7 @@ export default class Members extends StatelessWebexPlugin {
|
|
|
552
619
|
selfId: this.selfId,
|
|
553
620
|
hostId: this.hostId,
|
|
554
621
|
contentSharingId: this.mediaShareContentId,
|
|
622
|
+
whiteboardSharingId: this.mediaShareWhiteboardId,
|
|
555
623
|
type: this.type
|
|
556
624
|
})
|
|
557
625
|
);
|
|
@@ -563,6 +631,7 @@ export default class Members extends StatelessWebexPlugin {
|
|
|
563
631
|
selfId: this.selfId,
|
|
564
632
|
hostId: this.hostId,
|
|
565
633
|
contentSharingId: this.mediaShareContentId,
|
|
634
|
+
whiteboardSharingId: this.mediaShareWhiteboardId,
|
|
566
635
|
type: this.type
|
|
567
636
|
})
|
|
568
637
|
);
|