@webex/plugin-meetings 3.0.0-beta.2 → 3.0.0-beta.20
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/UPGRADING.md +9 -9
- package/browsers.js +19 -24
- 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/common/browser-detection.js +1 -20
- package/dist/common/browser-detection.js.map +1 -1
- package/dist/common/collection.js +5 -20
- package/dist/common/collection.js.map +1 -1
- package/dist/common/config.js +0 -7
- package/dist/common/config.js.map +1 -1
- package/dist/common/errors/captcha-error.js +10 -24
- package/dist/common/errors/captcha-error.js.map +1 -1
- package/dist/common/errors/intent-to-join.js +11 -24
- package/dist/common/errors/intent-to-join.js.map +1 -1
- package/dist/common/errors/join-meeting.js +12 -25
- package/dist/common/errors/join-meeting.js.map +1 -1
- package/dist/common/errors/media.js +10 -24
- package/dist/common/errors/media.js.map +1 -1
- package/dist/common/errors/parameter.js +5 -33
- package/dist/common/errors/parameter.js.map +1 -1
- package/dist/common/errors/password-error.js +10 -24
- package/dist/common/errors/password-error.js.map +1 -1
- package/dist/common/errors/permission.js +9 -23
- package/dist/common/errors/permission.js.map +1 -1
- package/dist/common/errors/reconnection-in-progress.js +0 -17
- package/dist/common/errors/reconnection-in-progress.js.map +1 -1
- package/dist/common/errors/reconnection.js +10 -24
- package/dist/common/errors/reconnection.js.map +1 -1
- package/dist/common/errors/stats.js +10 -24
- package/dist/common/errors/stats.js.map +1 -1
- package/dist/common/errors/webex-errors.js +6 -41
- package/dist/common/errors/webex-errors.js.map +1 -1
- package/dist/common/errors/webex-meetings-error.js +5 -25
- package/dist/common/errors/webex-meetings-error.js.map +1 -1
- package/dist/common/events/events-scope.js +0 -22
- package/dist/common/events/events-scope.js.map +1 -1
- package/dist/common/events/events.js +0 -23
- package/dist/common/events/events.js.map +1 -1
- package/dist/common/events/trigger-proxy.js +0 -12
- package/dist/common/events/trigger-proxy.js.map +1 -1
- package/dist/common/events/util.js +0 -15
- package/dist/common/events/util.js.map +1 -1
- package/dist/common/logs/logger-config.js +0 -4
- package/dist/common/logs/logger-config.js.map +1 -1
- package/dist/common/logs/logger-proxy.js +1 -8
- package/dist/common/logs/logger-proxy.js.map +1 -1
- package/dist/common/logs/request.js +37 -60
- package/dist/common/logs/request.js.map +1 -1
- package/dist/common/queue.js +4 -14
- package/dist/common/queue.js.map +1 -1
- package/dist/config.js +6 -6
- package/dist/config.js.map +1 -1
- package/dist/constants.js +88 -46
- package/dist/constants.js.map +1 -1
- package/dist/index.js +1 -17
- package/dist/index.js.map +1 -1
- package/dist/locus-info/controlsUtils.js +12 -29
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/embeddedAppsUtils.js +3 -26
- package/dist/locus-info/embeddedAppsUtils.js.map +1 -1
- package/dist/locus-info/fullState.js +0 -15
- package/dist/locus-info/fullState.js.map +1 -1
- package/dist/locus-info/hostUtils.js +4 -12
- package/dist/locus-info/hostUtils.js.map +1 -1
- package/dist/locus-info/index.js +184 -190
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/infoUtils.js +3 -37
- package/dist/locus-info/infoUtils.js.map +1 -1
- package/dist/locus-info/mediaSharesUtils.js +12 -38
- package/dist/locus-info/mediaSharesUtils.js.map +1 -1
- package/dist/locus-info/parser.js +92 -118
- package/dist/locus-info/parser.js.map +1 -1
- package/dist/locus-info/selfUtils.js +34 -91
- package/dist/locus-info/selfUtils.js.map +1 -1
- package/dist/media/index.js +67 -111
- package/dist/media/index.js.map +1 -1
- package/dist/media/properties.js +80 -114
- package/dist/media/properties.js.map +1 -1
- package/dist/media/util.js +2 -9
- package/dist/media/util.js.map +1 -1
- package/dist/mediaQualityMetrics/config.js +10 -12
- package/dist/mediaQualityMetrics/config.js.map +1 -1
- package/dist/meeting/effectsState.js +125 -190
- package/dist/meeting/effectsState.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +5 -14
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +1692 -1925
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/muteState.js +36 -77
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/meeting/request.js +224 -230
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/request.type.js +7 -0
- package/dist/meeting/request.type.js.map +1 -0
- package/dist/meeting/state.js +21 -31
- package/dist/meeting/state.js.map +1 -1
- package/dist/meeting/util.js +43 -215
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting-info/collection.js +6 -25
- package/dist/meeting-info/collection.js.map +1 -1
- package/dist/meeting-info/index.js +14 -32
- package/dist/meeting-info/index.js.map +1 -1
- package/dist/meeting-info/meeting-info-v2.js +193 -268
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meeting-info/request.js +3 -15
- package/dist/meeting-info/request.js.map +1 -1
- package/dist/meeting-info/util.js +98 -183
- package/dist/meeting-info/util.js.map +1 -1
- package/dist/meeting-info/utilv2.js +137 -228
- package/dist/meeting-info/utilv2.js.map +1 -1
- package/dist/meetings/collection.js +5 -20
- package/dist/meetings/collection.js.map +1 -1
- package/dist/meetings/index.js +490 -560
- package/dist/meetings/index.js.map +1 -1
- package/dist/meetings/request.js +24 -41
- package/dist/meetings/request.js.map +1 -1
- package/dist/meetings/util.js +99 -155
- package/dist/meetings/util.js.map +1 -1
- package/dist/member/index.js +78 -86
- package/dist/member/index.js.map +1 -1
- package/dist/member/util.js +31 -68
- package/dist/member/util.js.map +1 -1
- package/dist/members/collection.js +3 -12
- package/dist/members/collection.js.map +1 -1
- package/dist/members/index.js +93 -200
- package/dist/members/index.js.map +1 -1
- package/dist/members/request.js +16 -39
- package/dist/members/request.js.map +1 -1
- package/dist/members/util.js +9 -38
- package/dist/members/util.js.map +1 -1
- package/dist/metrics/config.js +0 -2
- package/dist/metrics/config.js.map +1 -1
- package/dist/metrics/constants.js +1 -2
- package/dist/metrics/constants.js.map +1 -1
- package/dist/metrics/index.js +55 -135
- package/dist/metrics/index.js.map +1 -1
- package/dist/multistream/mediaRequestManager.js +57 -32
- package/dist/multistream/mediaRequestManager.js.map +1 -1
- package/dist/multistream/multistreamMedia.js +15 -21
- package/dist/multistream/multistreamMedia.js.map +1 -1
- package/dist/multistream/receiveSlot.js +10 -50
- package/dist/multistream/receiveSlot.js.map +1 -1
- package/dist/multistream/receiveSlotManager.js +45 -82
- package/dist/multistream/receiveSlotManager.js.map +1 -1
- package/dist/multistream/remoteMedia.js +18 -58
- package/dist/multistream/remoteMedia.js.map +1 -1
- package/dist/multistream/remoteMediaGroup.js +6 -40
- package/dist/multistream/remoteMediaGroup.js.map +1 -1
- package/dist/multistream/remoteMediaManager.js +362 -416
- package/dist/multistream/remoteMediaManager.js.map +1 -1
- package/dist/networkQualityMonitor/index.js +36 -57
- package/dist/networkQualityMonitor/index.js.map +1 -1
- package/dist/personal-meeting-room/index.js +21 -45
- package/dist/personal-meeting-room/index.js.map +1 -1
- package/dist/personal-meeting-room/request.js +1 -31
- package/dist/personal-meeting-room/request.js.map +1 -1
- package/dist/personal-meeting-room/util.js +0 -13
- package/dist/personal-meeting-room/util.js.map +1 -1
- package/dist/reachability/index.js +138 -182
- package/dist/reachability/index.js.map +1 -1
- package/dist/reachability/request.js +3 -18
- package/dist/reachability/request.js.map +1 -1
- package/dist/reactions/constants.js +13 -0
- package/dist/reactions/constants.js.map +1 -0
- package/dist/reactions/reactions.js +109 -0
- package/dist/reactions/reactions.js.map +1 -0
- package/dist/reactions/reactions.type.js +36 -0
- package/dist/reactions/reactions.type.js.map +1 -0
- package/dist/reconnection-manager/index.js +322 -455
- 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/index.js +39 -64
- package/dist/roap/index.js.map +1 -1
- package/dist/roap/request.js +94 -113
- package/dist/roap/request.js.map +1 -1
- package/dist/roap/turnDiscovery.js +85 -94
- package/dist/roap/turnDiscovery.js.map +1 -1
- package/dist/statsAnalyzer/global.js +0 -2
- package/dist/statsAnalyzer/global.js.map +1 -1
- package/dist/statsAnalyzer/index.js +85 -175
- package/dist/statsAnalyzer/index.js.map +1 -1
- package/dist/statsAnalyzer/mqaUtil.js +72 -53
- package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
- package/dist/transcription/index.js +22 -47
- package/dist/transcription/index.js.map +1 -1
- package/internal-README.md +7 -6
- package/package.json +25 -20
- 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/common/{browser-detection.js → browser-detection.ts} +9 -6
- package/src/common/collection.ts +9 -7
- package/src/common/{config.js → config.ts} +1 -1
- package/src/common/errors/{captcha-error.js → captcha-error.ts} +11 -7
- package/src/common/errors/{intent-to-join.js → intent-to-join.ts} +12 -7
- package/src/common/errors/{join-meeting.js → join-meeting.ts} +17 -8
- package/src/common/errors/{media.js → media.ts} +11 -7
- package/src/common/errors/parameter.ts +11 -7
- package/src/common/errors/{password-error.js → password-error.ts} +11 -7
- package/src/common/errors/{permission.js → permission.ts} +10 -6
- package/src/common/errors/{reconnection-in-progress.js → reconnection-in-progress.ts} +0 -0
- package/src/common/errors/{reconnection.js → reconnection.ts} +11 -7
- package/src/common/errors/{stats.js → stats.ts} +11 -7
- package/src/common/errors/{webex-errors.js → webex-errors.ts} +8 -7
- package/src/common/errors/{webex-meetings-error.js → webex-meetings-error.ts} +4 -2
- package/src/common/events/{events-scope.js → events-scope.ts} +6 -2
- package/src/common/events/{events.js → events.ts} +5 -1
- package/src/common/events/{trigger-proxy.js → trigger-proxy.ts} +9 -5
- package/src/common/events/{util.js → util.ts} +2 -3
- package/src/common/logs/{logger-config.js → logger-config.ts} +1 -2
- package/src/common/logs/logger-proxy.ts +44 -0
- package/src/common/logs/{request.js → request.ts} +22 -9
- package/src/common/queue.ts +1 -2
- package/src/{config.js → config.ts} +17 -12
- package/src/constants.ts +40 -1
- package/src/index.js +1 -1
- package/src/locus-info/controlsUtils.ts +114 -0
- package/src/locus-info/{embeddedAppsUtils.js → embeddedAppsUtils.ts} +5 -6
- package/src/locus-info/{fullState.js → fullState.ts} +16 -12
- package/src/locus-info/{hostUtils.js → hostUtils.ts} +9 -8
- package/src/locus-info/{index.js → index.ts} +148 -64
- package/src/locus-info/{infoUtils.js → infoUtils.ts} +19 -8
- package/src/locus-info/{mediaSharesUtils.js → mediaSharesUtils.ts} +17 -17
- package/src/locus-info/{parser.js → parser.ts} +67 -79
- package/src/locus-info/{selfUtils.js → selfUtils.ts} +123 -68
- package/src/media/{index.js → index.ts} +181 -131
- package/src/media/{properties.js → properties.ts} +47 -28
- package/src/media/{util.js → util.ts} +2 -2
- package/src/mediaQualityMetrics/{config.js → config.ts} +46 -46
- package/src/meeting/{effectsState.js → effectsState.ts} +47 -41
- package/src/meeting/in-meeting-actions.ts +15 -3
- package/src/meeting/{index.js → index.ts} +2263 -1427
- package/src/meeting/{muteState.js → muteState.ts} +78 -42
- package/src/meeting/{request.js → request.ts} +292 -142
- package/src/meeting/request.type.ts +13 -0
- package/src/meeting/{state.js → state.ts} +50 -35
- package/src/meeting/{util.js → util.ts} +112 -115
- package/src/meeting-info/{collection.js → collection.ts} +6 -2
- package/src/meeting-info/{index.js → index.ts} +42 -36
- package/src/meeting-info/meeting-info-v2.ts +273 -0
- package/src/meeting-info/{request.js → request.ts} +14 -4
- package/src/meeting-info/{util.js → util.ts} +60 -51
- package/src/meeting-info/{utilv2.js → utilv2.ts} +65 -58
- package/src/meetings/{collection.js → collection.ts} +6 -3
- package/src/meetings/index.ts +1159 -0
- package/src/meetings/{request.js → request.ts} +32 -25
- package/src/meetings/{util.js → util.ts} +34 -32
- package/src/member/{index.js → index.ts} +102 -56
- package/src/member/{util.js → util.ts} +52 -25
- package/src/members/{collection.js → collection.ts} +2 -2
- package/src/members/{index.js → index.ts} +219 -142
- package/src/members/{request.js → request.ts} +60 -16
- package/src/members/{util.js → util.ts} +50 -48
- package/src/metrics/{config.js → config.ts} +254 -83
- package/src/metrics/{constants.js → constants.ts} +0 -2
- package/src/metrics/{index.js → index.ts} +106 -74
- package/src/multistream/mediaRequestManager.ts +81 -15
- package/src/multistream/multistreamMedia.ts +5 -0
- package/src/multistream/receiveSlot.ts +18 -12
- package/src/multistream/receiveSlotManager.ts +23 -21
- package/src/multistream/remoteMedia.ts +15 -5
- package/src/multistream/remoteMediaGroup.ts +4 -3
- package/src/multistream/remoteMediaManager.ts +153 -37
- package/src/networkQualityMonitor/{index.js → index.ts} +37 -25
- package/src/personal-meeting-room/{index.js → index.ts} +28 -19
- package/src/personal-meeting-room/{request.js → request.ts} +13 -4
- package/src/personal-meeting-room/{util.js → util.ts} +4 -4
- package/src/reachability/{index.js → index.ts} +99 -83
- package/src/reachability/request.ts +39 -33
- package/src/reactions/constants.ts +4 -0
- package/src/reactions/reactions.ts +104 -0
- package/src/reactions/reactions.type.ts +62 -0
- package/src/reconnection-manager/{index.js → index.ts} +195 -102
- 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/{index.js → index.ts} +73 -56
- package/src/roap/request.ts +157 -0
- package/src/roap/turnDiscovery.ts +77 -37
- package/src/statsAnalyzer/{global.js → global.ts} +30 -33
- package/src/statsAnalyzer/{index.js → index.ts} +468 -192
- package/src/statsAnalyzer/mqaUtil.ts +290 -0
- package/src/transcription/{index.js → index.ts} +46 -39
- package/test/integration/spec/journey.js +664 -463
- package/test/integration/spec/space-meeting.js +320 -206
- package/test/integration/spec/transcription.js +7 -8
- 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/common/browser-detection.js +9 -28
- package/test/unit/spec/fixture/locus.js +92 -90
- package/test/unit/spec/locus-info/controlsUtils.js +25 -5
- package/test/unit/spec/locus-info/embeddedAppsUtils.js +8 -6
- package/test/unit/spec/locus-info/index.js +104 -2
- package/test/unit/spec/locus-info/infoUtils.js +41 -32
- package/test/unit/spec/locus-info/lib/BasicSeqCmp.json +88 -430
- package/test/unit/spec/locus-info/lib/SeqCmp.json +513 -685
- package/test/unit/spec/locus-info/parser.js +3 -9
- package/test/unit/spec/locus-info/selfConstant.js +97 -103
- package/test/unit/spec/locus-info/selfUtils.js +105 -12
- package/test/unit/spec/media/index.ts +31 -47
- package/test/unit/spec/media/properties.ts +9 -9
- package/test/unit/spec/meeting/effectsState.js +39 -45
- package/test/unit/spec/meeting/in-meeting-actions.ts +5 -2
- package/test/unit/spec/meeting/index.js +2017 -742
- package/test/unit/spec/meeting/muteState.js +42 -33
- package/test/unit/spec/meeting/request.js +115 -44
- package/test/unit/spec/meeting/utils.js +104 -171
- package/test/unit/spec/meeting-info/meetinginfov2.js +100 -73
- package/test/unit/spec/meeting-info/request.js +7 -9
- package/test/unit/spec/meeting-info/util.js +11 -12
- package/test/unit/spec/meeting-info/utilv2.js +110 -74
- package/test/unit/spec/meetings/collection.js +1 -1
- package/test/unit/spec/meetings/index.js +439 -257
- package/test/unit/spec/meetings/utils.js +14 -12
- package/test/unit/spec/member/index.js +0 -1
- package/test/unit/spec/member/util.js +31 -7
- package/test/unit/spec/members/index.js +104 -54
- package/test/unit/spec/members/request.js +29 -20
- package/test/unit/spec/members/utils.js +8 -5
- package/test/unit/spec/metrics/index.js +16 -21
- package/test/unit/spec/multistream/mediaRequestManager.ts +316 -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 +10 -2
- package/test/unit/spec/multistream/remoteMediaGroup.ts +5 -5
- package/test/unit/spec/multistream/remoteMediaManager.ts +412 -65
- package/test/unit/spec/networkQualityMonitor/index.js +21 -15
- package/test/unit/spec/personal-meeting-room/personal-meeting-room.js +2 -7
- package/test/unit/spec/reachability/index.ts +58 -26
- package/test/unit/spec/reconnection-manager/index.js +102 -9
- 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 +64 -45
- package/test/unit/spec/stats-analyzer/index.js +27 -22
- package/test/utils/cmr.js +44 -42
- package/test/utils/testUtils.js +83 -74
- package/test/utils/webex-config.js +18 -18
- package/test/utils/webex-test-users.js +54 -50
- package/tsconfig.json +6 -0
- package/dist/media/internal-media-core-wrapper.js +0 -22
- package/dist/media/internal-media-core-wrapper.js.map +0 -1
- package/dist/peer-connection-manager/util.js +0 -124
- package/dist/peer-connection-manager/util.js.map +0 -1
- package/src/common/logs/logger-proxy.js +0 -33
- package/src/locus-info/controlsUtils.js +0 -102
- package/src/media/internal-media-core-wrapper.ts +0 -9
- package/src/meeting-info/meeting-info-v2.js +0 -255
- package/src/meetings/index.js +0 -1015
- package/src/peer-connection-manager/util.ts +0 -117
- package/src/roap/request.js +0 -127
- package/src/statsAnalyzer/mqaUtil.js +0 -173
- package/test/unit/spec/peerconnection-manager/utils.test-fixtures.ts +0 -389
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* eslint-disable require-jsdoc */
|
|
2
2
|
import EventEmitter from 'events';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {MediaType} from '@webex/internal-media-core';
|
|
5
5
|
import {
|
|
6
6
|
Configuration,
|
|
7
7
|
Event,
|
|
@@ -17,13 +17,13 @@ import {CSI, ReceiveSlotId} from '@webex/plugin-meetings/src/multistream/receive
|
|
|
17
17
|
import testUtils from '../../../utils/testUtils';
|
|
18
18
|
|
|
19
19
|
class FakeSlot extends EventEmitter {
|
|
20
|
-
public mediaType:
|
|
20
|
+
public mediaType: MediaType;
|
|
21
21
|
|
|
22
22
|
public id: string;
|
|
23
23
|
|
|
24
24
|
public csi?: number;
|
|
25
25
|
|
|
26
|
-
constructor(mediaType:
|
|
26
|
+
constructor(mediaType: MediaType, id: string) {
|
|
27
27
|
super();
|
|
28
28
|
this.mediaType = mediaType;
|
|
29
29
|
this.id = id;
|
|
@@ -37,6 +37,7 @@ class FakeSlot extends EventEmitter {
|
|
|
37
37
|
const DefaultTestConfiguration: Configuration = {
|
|
38
38
|
audio: {
|
|
39
39
|
numOfActiveSpeakerStreams: 3,
|
|
40
|
+
numOfScreenShareStreams: 1,
|
|
40
41
|
},
|
|
41
42
|
video: {
|
|
42
43
|
preferLiveVideo: true,
|
|
@@ -44,7 +45,6 @@ const DefaultTestConfiguration: Configuration = {
|
|
|
44
45
|
|
|
45
46
|
layouts: {
|
|
46
47
|
AllEqual: {
|
|
47
|
-
screenShareVideo: {size: null},
|
|
48
48
|
activeSpeakerVideoPaneGroups: [
|
|
49
49
|
{
|
|
50
50
|
id: 'main',
|
|
@@ -55,7 +55,6 @@ const DefaultTestConfiguration: Configuration = {
|
|
|
55
55
|
],
|
|
56
56
|
},
|
|
57
57
|
OnePlusFive: {
|
|
58
|
-
screenShareVideo: {size: null},
|
|
59
58
|
activeSpeakerVideoPaneGroups: [
|
|
60
59
|
{
|
|
61
60
|
id: 'mainBigOne',
|
|
@@ -72,7 +71,6 @@ const DefaultTestConfiguration: Configuration = {
|
|
|
72
71
|
],
|
|
73
72
|
},
|
|
74
73
|
Single: {
|
|
75
|
-
screenShareVideo: {size: null},
|
|
76
74
|
activeSpeakerVideoPaneGroups: [
|
|
77
75
|
{
|
|
78
76
|
id: 'main',
|
|
@@ -83,7 +81,6 @@ const DefaultTestConfiguration: Configuration = {
|
|
|
83
81
|
],
|
|
84
82
|
},
|
|
85
83
|
Stage: {
|
|
86
|
-
screenShareVideo: {size: null},
|
|
87
84
|
activeSpeakerVideoPaneGroups: [
|
|
88
85
|
{
|
|
89
86
|
id: 'thumbnails',
|
|
@@ -99,12 +96,19 @@ const DefaultTestConfiguration: Configuration = {
|
|
|
99
96
|
{id: 'stage-4', size: 'medium', csi: undefined},
|
|
100
97
|
],
|
|
101
98
|
},
|
|
99
|
+
ScreenShareView: {
|
|
100
|
+
screenShareVideo: {size: 'medium'},
|
|
101
|
+
activeSpeakerVideoPaneGroups: [
|
|
102
|
+
{
|
|
103
|
+
id: 'thumbnails',
|
|
104
|
+
numPanes: 6,
|
|
105
|
+
size: 'thumbnail',
|
|
106
|
+
priority: 255,
|
|
107
|
+
},
|
|
108
|
+
],
|
|
109
|
+
},
|
|
102
110
|
},
|
|
103
111
|
},
|
|
104
|
-
screenShare: {
|
|
105
|
-
audio: true,
|
|
106
|
-
video: true,
|
|
107
|
-
},
|
|
108
112
|
};
|
|
109
113
|
|
|
110
114
|
describe('RemoteMediaManager', () => {
|
|
@@ -113,18 +117,34 @@ describe('RemoteMediaManager', () => {
|
|
|
113
117
|
let fakeMediaRequestManagers;
|
|
114
118
|
let fakeAudioSlot;
|
|
115
119
|
let fakeVideoSlot;
|
|
120
|
+
let fakeScreenShareAudioSlot;
|
|
121
|
+
let fakeScreenShareVideoSlot;
|
|
116
122
|
|
|
117
123
|
beforeEach(() => {
|
|
118
|
-
fakeAudioSlot = new FakeSlot(
|
|
119
|
-
fakeVideoSlot = new FakeSlot(
|
|
124
|
+
fakeAudioSlot = new FakeSlot(MediaType.AudioMain, 'fake audio slot');
|
|
125
|
+
fakeVideoSlot = new FakeSlot(MediaType.VideoMain, 'fake video slot');
|
|
126
|
+
fakeScreenShareAudioSlot = new FakeSlot(
|
|
127
|
+
MediaType.AudioSlides,
|
|
128
|
+
'fake screen share audio slot'
|
|
129
|
+
);
|
|
130
|
+
fakeScreenShareVideoSlot = new FakeSlot(
|
|
131
|
+
MediaType.VideoSlides,
|
|
132
|
+
'fake screen share video slot'
|
|
133
|
+
);
|
|
120
134
|
|
|
121
135
|
fakeReceiveSlotManager = {
|
|
122
136
|
allocateSlot: sinon.stub().callsFake((mediaType) => {
|
|
123
|
-
|
|
124
|
-
|
|
137
|
+
switch (mediaType) {
|
|
138
|
+
case MediaType.AudioMain:
|
|
139
|
+
return Promise.resolve(fakeAudioSlot);
|
|
140
|
+
case MediaType.VideoMain:
|
|
141
|
+
return Promise.resolve(fakeVideoSlot);
|
|
142
|
+
case MediaType.AudioSlides:
|
|
143
|
+
return Promise.resolve(fakeScreenShareAudioSlot);
|
|
144
|
+
case MediaType.VideoSlides:
|
|
145
|
+
return Promise.resolve(fakeScreenShareVideoSlot);
|
|
125
146
|
}
|
|
126
|
-
|
|
127
|
-
return Promise.resolve(fakeVideoSlot);
|
|
147
|
+
throw new Error(`invalid mediaType: ${mediaType}`);
|
|
128
148
|
}),
|
|
129
149
|
releaseSlot: sinon.stub(),
|
|
130
150
|
};
|
|
@@ -140,6 +160,16 @@ describe('RemoteMediaManager', () => {
|
|
|
140
160
|
cancelRequest: sinon.stub(),
|
|
141
161
|
commit: sinon.stub(),
|
|
142
162
|
},
|
|
163
|
+
screenShareAudio: {
|
|
164
|
+
addRequest: sinon.stub(),
|
|
165
|
+
cancelRequest: sinon.stub(),
|
|
166
|
+
commit: sinon.stub(),
|
|
167
|
+
},
|
|
168
|
+
screenShareVideo: {
|
|
169
|
+
addRequest: sinon.stub(),
|
|
170
|
+
cancelRequest: sinon.stub(),
|
|
171
|
+
commit: sinon.stub(),
|
|
172
|
+
},
|
|
143
173
|
};
|
|
144
174
|
|
|
145
175
|
// create remote media manager with default configuration
|
|
@@ -159,6 +189,8 @@ describe('RemoteMediaManager', () => {
|
|
|
159
189
|
fakeMediaRequestManagers.video.addRequest.resetHistory();
|
|
160
190
|
fakeMediaRequestManagers.video.cancelRequest.resetHistory();
|
|
161
191
|
fakeMediaRequestManagers.video.commit.resetHistory();
|
|
192
|
+
fakeMediaRequestManagers.screenShareVideo.commit.resetHistory();
|
|
193
|
+
fakeMediaRequestManagers.screenShareAudio.commit.resetHistory();
|
|
162
194
|
};
|
|
163
195
|
|
|
164
196
|
describe('start', () => {
|
|
@@ -176,8 +208,8 @@ describe('RemoteMediaManager', () => {
|
|
|
176
208
|
await remoteMediaManager.start();
|
|
177
209
|
|
|
178
210
|
// check that the 2nd start() creates slots and media requests and is not a no-op
|
|
179
|
-
assert.calledWith(fakeReceiveSlotManager.allocateSlot,
|
|
180
|
-
assert.calledWith(fakeReceiveSlotManager.allocateSlot,
|
|
211
|
+
assert.calledWith(fakeReceiveSlotManager.allocateSlot, MediaType.AudioMain);
|
|
212
|
+
assert.calledWith(fakeReceiveSlotManager.allocateSlot, MediaType.VideoMain);
|
|
181
213
|
|
|
182
214
|
assert.called(fakeMediaRequestManagers.audio.addRequest);
|
|
183
215
|
assert.called(fakeMediaRequestManagers.video.addRequest);
|
|
@@ -187,25 +219,18 @@ describe('RemoteMediaManager', () => {
|
|
|
187
219
|
let createdAudioGroup: RemoteMediaGroup | null = null;
|
|
188
220
|
|
|
189
221
|
// create a config with just audio, no video at all and no screen share
|
|
190
|
-
const config = {
|
|
222
|
+
const config: Configuration = {
|
|
191
223
|
audio: {
|
|
192
224
|
numOfActiveSpeakerStreams: 5,
|
|
225
|
+
numOfScreenShareStreams: 0,
|
|
193
226
|
},
|
|
194
227
|
video: {
|
|
195
228
|
preferLiveVideo: false,
|
|
196
229
|
initialLayoutId: 'empty',
|
|
197
230
|
layouts: {
|
|
198
|
-
empty: {
|
|
199
|
-
screenShareVideo: {
|
|
200
|
-
size: null,
|
|
201
|
-
},
|
|
202
|
-
},
|
|
231
|
+
empty: {},
|
|
203
232
|
},
|
|
204
233
|
},
|
|
205
|
-
screenShare: {
|
|
206
|
-
audio: false,
|
|
207
|
-
video: false,
|
|
208
|
-
},
|
|
209
234
|
};
|
|
210
235
|
|
|
211
236
|
remoteMediaManager = new RemoteMediaManager(
|
|
@@ -223,7 +248,7 @@ describe('RemoteMediaManager', () => {
|
|
|
223
248
|
await testUtils.flushPromises();
|
|
224
249
|
|
|
225
250
|
assert.callCount(fakeReceiveSlotManager.allocateSlot, 5);
|
|
226
|
-
assert.alwaysCalledWith(fakeReceiveSlotManager.allocateSlot,
|
|
251
|
+
assert.alwaysCalledWith(fakeReceiveSlotManager.allocateSlot, MediaType.AudioMain);
|
|
227
252
|
|
|
228
253
|
assert.isNotNull(createdAudioGroup);
|
|
229
254
|
if (createdAudioGroup) {
|
|
@@ -231,7 +256,7 @@ describe('RemoteMediaManager', () => {
|
|
|
231
256
|
assert.isTrue(
|
|
232
257
|
createdAudioGroup
|
|
233
258
|
.getRemoteMedia()
|
|
234
|
-
.every((remoteMedia) => remoteMedia.mediaType ===
|
|
259
|
+
.every((remoteMedia) => remoteMedia.mediaType === MediaType.AudioMain)
|
|
235
260
|
);
|
|
236
261
|
assert.strictEqual(createdAudioGroup.getRemoteMedia('pinned').length, 0);
|
|
237
262
|
}
|
|
@@ -255,9 +280,6 @@ describe('RemoteMediaManager', () => {
|
|
|
255
280
|
|
|
256
281
|
config.audio.numOfActiveSpeakerStreams = 0;
|
|
257
282
|
config.video.layouts.huge = {
|
|
258
|
-
screenShareVideo: {
|
|
259
|
-
size: null,
|
|
260
|
-
},
|
|
261
283
|
activeSpeakerVideoPaneGroups: [
|
|
262
284
|
{
|
|
263
285
|
id: 'big one',
|
|
@@ -267,6 +289,8 @@ describe('RemoteMediaManager', () => {
|
|
|
267
289
|
},
|
|
268
290
|
],
|
|
269
291
|
};
|
|
292
|
+
config.audio.numOfScreenShareStreams = 0;
|
|
293
|
+
delete config.video.layouts.ScreenShareView;
|
|
270
294
|
|
|
271
295
|
remoteMediaManager = new RemoteMediaManager(
|
|
272
296
|
fakeReceiveSlotManager,
|
|
@@ -279,7 +303,7 @@ describe('RemoteMediaManager', () => {
|
|
|
279
303
|
// even though our "big one" layout is not the default one, the remote media manager should still
|
|
280
304
|
// preallocate enough video receive slots for it up front
|
|
281
305
|
assert.callCount(fakeReceiveSlotManager.allocateSlot, 99);
|
|
282
|
-
assert.alwaysCalledWith(fakeReceiveSlotManager.allocateSlot,
|
|
306
|
+
assert.alwaysCalledWith(fakeReceiveSlotManager.allocateSlot, MediaType.VideoMain);
|
|
283
307
|
});
|
|
284
308
|
|
|
285
309
|
it('starts with the initial layout', async () => {
|
|
@@ -302,8 +326,128 @@ describe('RemoteMediaManager', () => {
|
|
|
302
326
|
receivedLayoutInfo.activeSpeakerVideoPanes.main.getRemoteMedia().length,
|
|
303
327
|
9
|
|
304
328
|
);
|
|
329
|
+
assert.isUndefined(receivedLayoutInfo.screenShareVideo); // the initial layout has no screen share
|
|
330
|
+
}
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
it('creates RemoteMedia for screen share audio correctly', async () => {
|
|
334
|
+
let createdAudioGroup: RemoteMediaGroup | null = null;
|
|
335
|
+
|
|
336
|
+
const NUM_STREAMS = 2;
|
|
337
|
+
|
|
338
|
+
// create a config with just screen share audio, nothing else
|
|
339
|
+
const config: Configuration = {
|
|
340
|
+
audio: {
|
|
341
|
+
numOfActiveSpeakerStreams: 0,
|
|
342
|
+
numOfScreenShareStreams: NUM_STREAMS,
|
|
343
|
+
},
|
|
344
|
+
video: {
|
|
345
|
+
preferLiveVideo: false,
|
|
346
|
+
initialLayoutId: 'empty',
|
|
347
|
+
layouts: {
|
|
348
|
+
empty: {},
|
|
349
|
+
},
|
|
350
|
+
},
|
|
351
|
+
};
|
|
352
|
+
|
|
353
|
+
remoteMediaManager = new RemoteMediaManager(
|
|
354
|
+
fakeReceiveSlotManager,
|
|
355
|
+
fakeMediaRequestManagers,
|
|
356
|
+
config
|
|
357
|
+
);
|
|
358
|
+
|
|
359
|
+
remoteMediaManager.on(Event.ScreenShareAudioCreated, (audio: RemoteMediaGroup) => {
|
|
360
|
+
createdAudioGroup = audio;
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
remoteMediaManager.start();
|
|
364
|
+
|
|
365
|
+
await testUtils.flushPromises();
|
|
366
|
+
|
|
367
|
+
assert.callCount(fakeReceiveSlotManager.allocateSlot, NUM_STREAMS);
|
|
368
|
+
assert.alwaysCalledWith(fakeReceiveSlotManager.allocateSlot, MediaType.AudioSlides);
|
|
369
|
+
|
|
370
|
+
assert.isNotNull(createdAudioGroup);
|
|
371
|
+
if (createdAudioGroup) {
|
|
372
|
+
assert.strictEqual(createdAudioGroup.getRemoteMedia().length, NUM_STREAMS);
|
|
373
|
+
assert.isTrue(
|
|
374
|
+
createdAudioGroup
|
|
375
|
+
.getRemoteMedia()
|
|
376
|
+
.every((remoteMedia) => remoteMedia.mediaType === MediaType.AudioSlides)
|
|
377
|
+
);
|
|
378
|
+
assert.strictEqual(createdAudioGroup.getRemoteMedia('pinned').length, 0);
|
|
305
379
|
}
|
|
380
|
+
|
|
381
|
+
assert.calledOnce(fakeMediaRequestManagers.screenShareAudio.addRequest);
|
|
382
|
+
assert.calledWith(
|
|
383
|
+
fakeMediaRequestManagers.screenShareAudio.addRequest,
|
|
384
|
+
sinon.match({
|
|
385
|
+
policyInfo: sinon.match({
|
|
386
|
+
policy: 'active-speaker',
|
|
387
|
+
priority: 255,
|
|
388
|
+
}),
|
|
389
|
+
receiveSlots: Array(NUM_STREAMS).fill(fakeScreenShareAudioSlot),
|
|
390
|
+
codecInfo: undefined,
|
|
391
|
+
})
|
|
392
|
+
);
|
|
306
393
|
});
|
|
394
|
+
|
|
395
|
+
it('creates a single receive slot for screen share video if any layout has screen share', async () => {
|
|
396
|
+
// create a config with 2 layouts that use screen share
|
|
397
|
+
const config: Configuration = {
|
|
398
|
+
audio: {
|
|
399
|
+
numOfActiveSpeakerStreams: 0,
|
|
400
|
+
numOfScreenShareStreams: 0,
|
|
401
|
+
},
|
|
402
|
+
video: {
|
|
403
|
+
preferLiveVideo: false,
|
|
404
|
+
initialLayoutId: 'first',
|
|
405
|
+
layouts: {
|
|
406
|
+
first: {
|
|
407
|
+
screenShareVideo: { size: 'small'}
|
|
408
|
+
},
|
|
409
|
+
second: {
|
|
410
|
+
screenShareVideo: { size: 'medium'}
|
|
411
|
+
}
|
|
412
|
+
},
|
|
413
|
+
},
|
|
414
|
+
};
|
|
415
|
+
|
|
416
|
+
remoteMediaManager = new RemoteMediaManager(
|
|
417
|
+
fakeReceiveSlotManager,
|
|
418
|
+
fakeMediaRequestManagers,
|
|
419
|
+
config
|
|
420
|
+
);
|
|
421
|
+
|
|
422
|
+
await remoteMediaManager.start();
|
|
423
|
+
|
|
424
|
+
// even though 2 layouts use screen share, only 1 video screen share slot should be created
|
|
425
|
+
assert.callCount(fakeReceiveSlotManager.allocateSlot, 1);
|
|
426
|
+
assert.alwaysCalledWith(fakeReceiveSlotManager.allocateSlot, MediaType.VideoSlides);
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
it('does not create any receive slot for screen share video if none of the layouts have screen share', async () => {
|
|
430
|
+
const config = cloneDeep(DefaultTestConfiguration);
|
|
431
|
+
|
|
432
|
+
config.audio.numOfActiveSpeakerStreams = 0;
|
|
433
|
+
config.audio.numOfScreenShareStreams = 0;
|
|
434
|
+
|
|
435
|
+
// delete the only layout that uses screen share
|
|
436
|
+
delete config.video.layouts.ScreenShareView;
|
|
437
|
+
|
|
438
|
+
remoteMediaManager = new RemoteMediaManager(
|
|
439
|
+
fakeReceiveSlotManager,
|
|
440
|
+
fakeMediaRequestManagers,
|
|
441
|
+
config
|
|
442
|
+
);
|
|
443
|
+
|
|
444
|
+
await remoteMediaManager.start();
|
|
445
|
+
|
|
446
|
+
// we don't expect any audio and for video there should be no VideoSlides, so all the calls should be just for VideoMain
|
|
447
|
+
assert.alwaysCalledWith(fakeReceiveSlotManager.allocateSlot, MediaType.VideoMain);
|
|
448
|
+
});
|
|
449
|
+
|
|
450
|
+
|
|
307
451
|
});
|
|
308
452
|
|
|
309
453
|
describe('constructor', () => {
|
|
@@ -325,7 +469,6 @@ describe('RemoteMediaManager', () => {
|
|
|
325
469
|
const config = cloneDeep(DefaultTestConfiguration);
|
|
326
470
|
|
|
327
471
|
config.video.layouts.test = {
|
|
328
|
-
screenShareVideo: {size: null},
|
|
329
472
|
activeSpeakerVideoPaneGroups: [
|
|
330
473
|
{
|
|
331
474
|
id: 'someDuplicate',
|
|
@@ -361,7 +504,6 @@ describe('RemoteMediaManager', () => {
|
|
|
361
504
|
const config = cloneDeep(DefaultTestConfiguration);
|
|
362
505
|
|
|
363
506
|
config.video.layouts.test = {
|
|
364
|
-
screenShareVideo: {size: null},
|
|
365
507
|
activeSpeakerVideoPaneGroups: [
|
|
366
508
|
{
|
|
367
509
|
id: 'group1',
|
|
@@ -397,7 +539,6 @@ describe('RemoteMediaManager', () => {
|
|
|
397
539
|
const config = cloneDeep(DefaultTestConfiguration);
|
|
398
540
|
|
|
399
541
|
config.video.layouts.test = {
|
|
400
|
-
screenShareVideo: {size: null},
|
|
401
542
|
memberVideoPanes: [
|
|
402
543
|
{id: 'paneA', size: 'best', csi: 123},
|
|
403
544
|
{id: 'paneB', size: 'large', csi: 222},
|
|
@@ -414,6 +555,7 @@ describe('RemoteMediaManager', () => {
|
|
|
414
555
|
);
|
|
415
556
|
}, 'invalid config: duplicate member video pane id: paneB');
|
|
416
557
|
});
|
|
558
|
+
|
|
417
559
|
});
|
|
418
560
|
|
|
419
561
|
describe('stop', () => {
|
|
@@ -421,12 +563,17 @@ describe('RemoteMediaManager', () => {
|
|
|
421
563
|
let audioStopStub;
|
|
422
564
|
let videoActiveSpeakerGroupStopStub;
|
|
423
565
|
const memberVideoPaneStopStubs: any[] = [];
|
|
566
|
+
let screenShareAudioStopStub;
|
|
567
|
+
let screenShareVideoStopStub;
|
|
424
568
|
|
|
425
|
-
// change the initial layout to one that has both active speakers and
|
|
569
|
+
// change the initial layout to one that has both active speakers and receiver selected videos
|
|
426
570
|
const config = cloneDeep(DefaultTestConfiguration);
|
|
427
571
|
|
|
428
572
|
config.video.initialLayoutId = 'Stage';
|
|
429
573
|
|
|
574
|
+
// and also modify it to have screen share so we can test that too
|
|
575
|
+
config.video.layouts['Stage'].screenShareVideo = {size: 'medium'};
|
|
576
|
+
|
|
430
577
|
remoteMediaManager = new RemoteMediaManager(
|
|
431
578
|
fakeReceiveSlotManager,
|
|
432
579
|
fakeMediaRequestManagers,
|
|
@@ -437,6 +584,10 @@ describe('RemoteMediaManager', () => {
|
|
|
437
584
|
audioStopStub = sinon.stub(audio, 'stop');
|
|
438
585
|
});
|
|
439
586
|
|
|
587
|
+
remoteMediaManager.on(Event.ScreenShareAudioCreated, (audio: RemoteMediaGroup) => {
|
|
588
|
+
screenShareAudioStopStub = sinon.stub(audio, 'stop');
|
|
589
|
+
});
|
|
590
|
+
|
|
440
591
|
remoteMediaManager.on(Event.VideoLayoutChanged, (layoutInfo: VideoLayoutChangedEventData) => {
|
|
441
592
|
// The "Stage" layout that we're using has only 1 active speaker group called "thumbnails"
|
|
442
593
|
videoActiveSpeakerGroupStopStub = sinon.stub(
|
|
@@ -447,12 +598,14 @@ describe('RemoteMediaManager', () => {
|
|
|
447
598
|
Object.values(layoutInfo.memberVideoPanes).forEach((pane) => {
|
|
448
599
|
memberVideoPaneStopStubs.push(sinon.stub(pane, 'stop'));
|
|
449
600
|
});
|
|
601
|
+
|
|
602
|
+
screenShareVideoStopStub = sinon.stub(layoutInfo.screenShareVideo, 'stop');
|
|
450
603
|
});
|
|
451
604
|
|
|
452
605
|
await remoteMediaManager.start();
|
|
453
606
|
|
|
454
|
-
// we're using the default config that requires 3 main audio slots
|
|
455
|
-
assert.callCount(fakeReceiveSlotManager.allocateSlot,
|
|
607
|
+
// we're using the default config that requires 3 main audio slots, 10 video slots (for Stage2x2With6ThumbnailsLayout), 1 screenshare audio, 1 screenshare video
|
|
608
|
+
assert.callCount(fakeReceiveSlotManager.allocateSlot, 15);
|
|
456
609
|
|
|
457
610
|
// our layout has 4 member video panes, we should have a stub for each of these panes' stop methods
|
|
458
611
|
assert.strictEqual(memberVideoPaneStopStubs.length, 4);
|
|
@@ -462,16 +615,20 @@ describe('RemoteMediaManager', () => {
|
|
|
462
615
|
remoteMediaManager.stop();
|
|
463
616
|
|
|
464
617
|
// check that all slots have been released
|
|
465
|
-
assert.callCount(fakeReceiveSlotManager.releaseSlot,
|
|
618
|
+
assert.callCount(fakeReceiveSlotManager.releaseSlot, 15);
|
|
466
619
|
|
|
467
620
|
// and that all RemoteMedia and RemoteMediaGroups have been stopped
|
|
468
621
|
assert.calledOnce(audioStopStub);
|
|
469
622
|
assert.calledWith(audioStopStub, true);
|
|
623
|
+
assert.calledOnce(screenShareAudioStopStub);
|
|
624
|
+
assert.calledWith(screenShareAudioStopStub, true);
|
|
470
625
|
assert.calledOnce(videoActiveSpeakerGroupStopStub);
|
|
471
626
|
memberVideoPaneStopStubs.forEach((stub) => {
|
|
472
627
|
assert.calledOnce(stub);
|
|
473
628
|
});
|
|
474
629
|
assert.calledOnce(fakeMediaRequestManagers.video.commit);
|
|
630
|
+
assert.calledOnce(screenShareVideoStopStub);
|
|
631
|
+
assert.calledOnce(fakeMediaRequestManagers.screenShareVideo.commit);
|
|
475
632
|
});
|
|
476
633
|
|
|
477
634
|
it('can be called multiple times', async () => {
|
|
@@ -511,7 +668,7 @@ describe('RemoteMediaManager', () => {
|
|
|
511
668
|
await remoteMediaManager.setLayout('Stage');
|
|
512
669
|
|
|
513
670
|
assert.callCount(fakeReceiveSlotManager.allocateSlot, 9);
|
|
514
|
-
assert.alwaysCalledWith(fakeReceiveSlotManager.allocateSlot,
|
|
671
|
+
assert.alwaysCalledWith(fakeReceiveSlotManager.allocateSlot, MediaType.VideoMain);
|
|
515
672
|
});
|
|
516
673
|
|
|
517
674
|
it('releases slots when switching to layout that requires less active speaker slots', async () => {
|
|
@@ -538,10 +695,166 @@ describe('RemoteMediaManager', () => {
|
|
|
538
695
|
fakeReceiveSlotManager.releaseSlot.getCalls().forEach((call) => {
|
|
539
696
|
const slot = call.args[0];
|
|
540
697
|
|
|
541
|
-
assert.strictEqual(slot.mediaType,
|
|
698
|
+
assert.strictEqual(slot.mediaType, MediaType.VideoMain);
|
|
542
699
|
});
|
|
543
700
|
});
|
|
544
701
|
|
|
702
|
+
it('stops all current video remoteMedia instances when switching to new layout', async () => {
|
|
703
|
+
const audioStopStubs = [];
|
|
704
|
+
const videoStopStubs = [];
|
|
705
|
+
|
|
706
|
+
const config = cloneDeep(DefaultTestConfiguration);
|
|
707
|
+
|
|
708
|
+
// start with the stage layout because it has both active speaker and receiver selected panes
|
|
709
|
+
config.video.initialLayoutId = 'Stage';
|
|
710
|
+
|
|
711
|
+
remoteMediaManager = new RemoteMediaManager(
|
|
712
|
+
fakeReceiveSlotManager,
|
|
713
|
+
fakeMediaRequestManagers,
|
|
714
|
+
config
|
|
715
|
+
);
|
|
716
|
+
|
|
717
|
+
// mock all stop() methods for all remote audio objects we get with AudioCreated event
|
|
718
|
+
remoteMediaManager.on(Event.AudioCreated, (audio: RemoteMediaGroup) => {
|
|
719
|
+
audio
|
|
720
|
+
.getRemoteMedia()
|
|
721
|
+
.forEach((remoteAudio) => audioStopStubs.push(sinon.stub(remoteAudio, 'stop')));
|
|
722
|
+
});
|
|
723
|
+
|
|
724
|
+
// mock all stop() methods for all remote video objects we get with VideoLayoutChanged event
|
|
725
|
+
remoteMediaManager.on(Event.VideoLayoutChanged, (layoutInfo: VideoLayoutChangedEventData) => {
|
|
726
|
+
Object.values(layoutInfo.activeSpeakerVideoPanes).forEach((group) =>
|
|
727
|
+
group
|
|
728
|
+
.getRemoteMedia()
|
|
729
|
+
.forEach((remoteMedia) => videoStopStubs.push(sinon.stub(remoteMedia, 'stop')))
|
|
730
|
+
);
|
|
731
|
+
|
|
732
|
+
Object.values(layoutInfo.memberVideoPanes).forEach((pane) => {
|
|
733
|
+
videoStopStubs.push(sinon.stub(pane, 'stop'));
|
|
734
|
+
});
|
|
735
|
+
});
|
|
736
|
+
|
|
737
|
+
await remoteMediaManager.start();
|
|
738
|
+
|
|
739
|
+
// sanity check that we've got all our stop() mocks setup correctly
|
|
740
|
+
assert.strictEqual(audioStopStubs.length, 3);
|
|
741
|
+
assert.strictEqual(videoStopStubs.length, 10); // 10 = 6 thumbnail panes + 4 stage panes
|
|
742
|
+
|
|
743
|
+
// next, we'll change the layout, we don't care about the new video panes from the new layout, so unregister the event listeners
|
|
744
|
+
remoteMediaManager.removeAllListeners();
|
|
745
|
+
|
|
746
|
+
await remoteMediaManager.setLayout('AllEqual');
|
|
747
|
+
|
|
748
|
+
// check that NONE of the audio RemoteMedia instances were stopped
|
|
749
|
+
audioStopStubs.forEach((audioStopStub) => {
|
|
750
|
+
assert.notCalled(audioStopStub);
|
|
751
|
+
});
|
|
752
|
+
|
|
753
|
+
// check that ALL of the video RemoteMedia instances were stopped
|
|
754
|
+
videoStopStubs.forEach((videoStopStub) => {
|
|
755
|
+
assert.calledOnce(videoStopStub);
|
|
756
|
+
assert.calledWith(videoStopStub, false);
|
|
757
|
+
});
|
|
758
|
+
});
|
|
759
|
+
|
|
760
|
+
it('emits Event.VideoLayoutChanged with correct data', async () => {
|
|
761
|
+
// setup the initial layout to be empty and a testLayout that has screen share, active speaker groups and member video panes
|
|
762
|
+
const config: Configuration = {
|
|
763
|
+
audio: {
|
|
764
|
+
numOfActiveSpeakerStreams: 0,
|
|
765
|
+
numOfScreenShareStreams: 0,
|
|
766
|
+
},
|
|
767
|
+
video: {
|
|
768
|
+
preferLiveVideo: true,
|
|
769
|
+
initialLayoutId: 'empty',
|
|
770
|
+
layouts: {
|
|
771
|
+
empty: {},
|
|
772
|
+
testLayout: {
|
|
773
|
+
screenShareVideo: {size: 'very small'},
|
|
774
|
+
activeSpeakerVideoPaneGroups: [
|
|
775
|
+
{
|
|
776
|
+
id: 'big',
|
|
777
|
+
numPanes: 10,
|
|
778
|
+
priority: 255,
|
|
779
|
+
size: 'large',
|
|
780
|
+
},
|
|
781
|
+
{
|
|
782
|
+
id: 'small',
|
|
783
|
+
numPanes: 3,
|
|
784
|
+
priority: 254,
|
|
785
|
+
size: 'medium',
|
|
786
|
+
},
|
|
787
|
+
],
|
|
788
|
+
memberVideoPanes: [
|
|
789
|
+
{id: 'pane 1', size: 'best', csi: 555},
|
|
790
|
+
{id: 'pane 2', size: 'best', csi: undefined},
|
|
791
|
+
],
|
|
792
|
+
},
|
|
793
|
+
},
|
|
794
|
+
},
|
|
795
|
+
};
|
|
796
|
+
|
|
797
|
+
remoteMediaManager = new RemoteMediaManager(
|
|
798
|
+
fakeReceiveSlotManager,
|
|
799
|
+
fakeMediaRequestManagers,
|
|
800
|
+
config
|
|
801
|
+
);
|
|
802
|
+
|
|
803
|
+
await remoteMediaManager.start();
|
|
804
|
+
|
|
805
|
+
resetHistory();
|
|
806
|
+
|
|
807
|
+
let receivedLayoutInfo: VideoLayoutChangedEventData | null = null;
|
|
808
|
+
|
|
809
|
+
remoteMediaManager.on(Event.VideoLayoutChanged, (layoutInfo) => {
|
|
810
|
+
receivedLayoutInfo = layoutInfo;
|
|
811
|
+
});
|
|
812
|
+
|
|
813
|
+
// switch to the test layout
|
|
814
|
+
await remoteMediaManager.setLayout('testLayout');
|
|
815
|
+
|
|
816
|
+
assert.isNotNull(receivedLayoutInfo);
|
|
817
|
+
|
|
818
|
+
if (receivedLayoutInfo) {
|
|
819
|
+
assert.strictEqual(receivedLayoutInfo.layoutId, 'testLayout');
|
|
820
|
+
|
|
821
|
+
// check screen share video
|
|
822
|
+
assert.isTrue(!!receivedLayoutInfo.screenShareVideo);
|
|
823
|
+
assert.strictEqual(receivedLayoutInfo.screenShareVideo.mediaType, MediaType.VideoSlides);
|
|
824
|
+
|
|
825
|
+
// check member videos
|
|
826
|
+
assert.strictEqual(Object.keys(receivedLayoutInfo.memberVideoPanes).length, 2);
|
|
827
|
+
Object.values(receivedLayoutInfo.memberVideoPanes).forEach((remoteMedia) =>
|
|
828
|
+
assert.strictEqual(remoteMedia.mediaType, MediaType.VideoMain)
|
|
829
|
+
);
|
|
830
|
+
|
|
831
|
+
// check the 2 active speaker groups
|
|
832
|
+
assert.strictEqual(Object.keys(receivedLayoutInfo.activeSpeakerVideoPanes).length, 2);
|
|
833
|
+
|
|
834
|
+
// "big" group
|
|
835
|
+
assert.strictEqual(
|
|
836
|
+
receivedLayoutInfo.activeSpeakerVideoPanes.big.getRemoteMedia().length,
|
|
837
|
+
10
|
|
838
|
+
);
|
|
839
|
+
receivedLayoutInfo.activeSpeakerVideoPanes.big
|
|
840
|
+
.getRemoteMedia()
|
|
841
|
+
.forEach((remoteMedia) =>
|
|
842
|
+
assert.strictEqual(remoteMedia.mediaType, MediaType.VideoMain)
|
|
843
|
+
);
|
|
844
|
+
|
|
845
|
+
// "small" group
|
|
846
|
+
assert.strictEqual(
|
|
847
|
+
receivedLayoutInfo.activeSpeakerVideoPanes.small.getRemoteMedia().length,
|
|
848
|
+
3
|
|
849
|
+
);
|
|
850
|
+
receivedLayoutInfo.activeSpeakerVideoPanes.small
|
|
851
|
+
.getRemoteMedia()
|
|
852
|
+
.forEach((remoteMedia) =>
|
|
853
|
+
assert.strictEqual(remoteMedia.mediaType, MediaType.VideoMain)
|
|
854
|
+
);
|
|
855
|
+
}
|
|
856
|
+
});
|
|
857
|
+
|
|
545
858
|
describe('switching between different receiver selected layouts', () => {
|
|
546
859
|
let fakeSlots: {[key: ReceiveSlotId]: FakeSlot};
|
|
547
860
|
let slotCounter: number;
|
|
@@ -562,7 +875,7 @@ describe('RemoteMediaManager', () => {
|
|
|
562
875
|
slotCounter += 1;
|
|
563
876
|
const newSlotId = `fake video slot ${slotCounter}`;
|
|
564
877
|
|
|
565
|
-
fakeSlots[newSlotId] = new FakeSlot(
|
|
878
|
+
fakeSlots[newSlotId] = new FakeSlot(MediaType.VideoMain, newSlotId);
|
|
566
879
|
return fakeSlots[newSlotId];
|
|
567
880
|
});
|
|
568
881
|
|
|
@@ -594,12 +907,12 @@ describe('RemoteMediaManager', () => {
|
|
|
594
907
|
// This test starts with a layout that has 5 receiver selected video slots
|
|
595
908
|
// and switches to a different layout that has fewer slots, but 2 of them match CSIs
|
|
596
909
|
// from the initial layout. We want to verify that these 2 slots get re-used correctly.
|
|
910
|
+
// There are no screen share or audio slots being used in this test.
|
|
911
|
+
delete config.video.layouts.ScreenShareView;
|
|
597
912
|
config.audio.numOfActiveSpeakerStreams = 0;
|
|
598
|
-
config.
|
|
599
|
-
config.screenShare.video = false;
|
|
913
|
+
config.audio.numOfScreenShareStreams = 0;
|
|
600
914
|
config.video.initialLayoutId = 'biggerLayout';
|
|
601
915
|
config.video.layouts['biggerLayout'] = {
|
|
602
|
-
screenShareVideo: {size: null},
|
|
603
916
|
memberVideoPanes: [
|
|
604
917
|
{id: '1', size: 'best', csi: 100},
|
|
605
918
|
{id: '2', size: 'best', csi: 200},
|
|
@@ -609,7 +922,6 @@ describe('RemoteMediaManager', () => {
|
|
|
609
922
|
],
|
|
610
923
|
};
|
|
611
924
|
config.video.layouts['smallerLayout'] = {
|
|
612
|
-
screenShareVideo: {size: null},
|
|
613
925
|
memberVideoPanes: [
|
|
614
926
|
{id: '1', size: 'medium', csi: 200}, // this csi matches pane '2' from biggerLayout
|
|
615
927
|
{id: '2', size: 'medium', csi: 123},
|
|
@@ -659,16 +971,15 @@ describe('RemoteMediaManager', () => {
|
|
|
659
971
|
// This test starts with a layout that has video slot with a specific CSI
|
|
660
972
|
// and switches to a different layout that 2 panes with that same CSI.
|
|
661
973
|
// We want to verify that the slot gets reused, but also that a 2nd slot is allocated.
|
|
974
|
+
// There are no screen share or audio slots being used in this test.
|
|
975
|
+
delete config.video.layouts.ScreenShareView;
|
|
662
976
|
config.audio.numOfActiveSpeakerStreams = 0;
|
|
663
|
-
config.
|
|
664
|
-
config.screenShare.video = false;
|
|
977
|
+
config.audio.numOfScreenShareStreams = 0;
|
|
665
978
|
config.video.initialLayoutId = 'initialEmptyLayout';
|
|
666
979
|
config.video.layouts['initialEmptyLayout'] = {
|
|
667
|
-
screenShareVideo: {size: null},
|
|
668
980
|
memberVideoPanes: [{id: '2', size: 'medium', csi: 456}],
|
|
669
981
|
};
|
|
670
982
|
config.video.layouts['layoutWithDuplicateCSIs'] = {
|
|
671
|
-
screenShareVideo: {size: null},
|
|
672
983
|
memberVideoPanes: [
|
|
673
984
|
{id: '1', size: 'medium', csi: 123},
|
|
674
985
|
{id: '2', size: 'medium', csi: 456},
|
|
@@ -841,16 +1152,18 @@ describe('RemoteMediaManager', () => {
|
|
|
841
1152
|
});
|
|
842
1153
|
|
|
843
1154
|
it('cancels all media requests for the previous layout when switching to a new one', async () => {
|
|
1155
|
+
// setup the initial layout to have screen share, active speaker groups and member video panes
|
|
844
1156
|
const config: Configuration = {
|
|
845
1157
|
audio: {
|
|
846
1158
|
numOfActiveSpeakerStreams: 0,
|
|
1159
|
+
numOfScreenShareStreams: 0,
|
|
847
1160
|
},
|
|
848
1161
|
video: {
|
|
849
1162
|
preferLiveVideo: true,
|
|
850
1163
|
initialLayoutId: 'initial',
|
|
851
1164
|
layouts: {
|
|
852
1165
|
initial: {
|
|
853
|
-
screenShareVideo: {size:
|
|
1166
|
+
screenShareVideo: {size: 'best'},
|
|
854
1167
|
activeSpeakerVideoPaneGroups: [
|
|
855
1168
|
{
|
|
856
1169
|
id: 'big',
|
|
@@ -870,15 +1183,9 @@ describe('RemoteMediaManager', () => {
|
|
|
870
1183
|
{id: 'pane 2', size: 'best', csi: 234},
|
|
871
1184
|
],
|
|
872
1185
|
},
|
|
873
|
-
other: {
|
|
874
|
-
screenShareVideo: {size: null},
|
|
875
|
-
},
|
|
1186
|
+
other: {},
|
|
876
1187
|
},
|
|
877
1188
|
},
|
|
878
|
-
screenShare: {
|
|
879
|
-
audio: false,
|
|
880
|
-
video: false,
|
|
881
|
-
},
|
|
882
1189
|
};
|
|
883
1190
|
|
|
884
1191
|
remoteMediaManager = new RemoteMediaManager(
|
|
@@ -901,9 +1208,15 @@ describe('RemoteMediaManager', () => {
|
|
|
901
1208
|
|
|
902
1209
|
return `receiver selected request ${receiverSelectedRequestCounter}`;
|
|
903
1210
|
});
|
|
1211
|
+
// setup the mock for screen share addRequest - this one should be called just once
|
|
1212
|
+
fakeMediaRequestManagers.screenShareVideo.addRequest.callsFake(() => {
|
|
1213
|
+
return 'video screen share request id';
|
|
1214
|
+
});
|
|
904
1215
|
|
|
905
1216
|
await remoteMediaManager.start();
|
|
906
1217
|
|
|
1218
|
+
assert.calledOnce(fakeMediaRequestManagers.screenShareVideo.addRequest);
|
|
1219
|
+
|
|
907
1220
|
resetHistory();
|
|
908
1221
|
|
|
909
1222
|
// switch to "other" layout
|
|
@@ -921,11 +1234,45 @@ describe('RemoteMediaManager', () => {
|
|
|
921
1234
|
fakeMediaRequestManagers.video.cancelRequest,
|
|
922
1235
|
'receiver selected request 2'
|
|
923
1236
|
);
|
|
1237
|
+
assert.calledOnce(fakeMediaRequestManagers.screenShareVideo.cancelRequest);
|
|
1238
|
+
assert.calledWith(
|
|
1239
|
+
fakeMediaRequestManagers.screenShareVideo.cancelRequest,
|
|
1240
|
+
'video screen share request id'
|
|
1241
|
+
);
|
|
924
1242
|
|
|
925
1243
|
// new layout has no videos, so no new requests should be sent out
|
|
926
|
-
// check that 2 correct active speaker media requests were sent out
|
|
927
1244
|
assert.callCount(fakeMediaRequestManagers.video.addRequest, 0);
|
|
928
1245
|
});
|
|
1246
|
+
|
|
1247
|
+
it('sends media request for screen share if layout contains screen share', async () => {
|
|
1248
|
+
const allEqualMediaRequestId = 'fake request id';
|
|
1249
|
+
|
|
1250
|
+
fakeMediaRequestManagers.video.addRequest.returns(allEqualMediaRequestId);
|
|
1251
|
+
|
|
1252
|
+
await remoteMediaManager.start();
|
|
1253
|
+
|
|
1254
|
+
resetHistory();
|
|
1255
|
+
|
|
1256
|
+
// switch to a layout that contains a screen share video pane
|
|
1257
|
+
await remoteMediaManager.setLayout('ScreenShareView');
|
|
1258
|
+
|
|
1259
|
+
// check that a correct active speaker media request for screen share has been sent out
|
|
1260
|
+
assert.callCount(fakeMediaRequestManagers.screenShareVideo.addRequest, 1);
|
|
1261
|
+
assert.calledWith(
|
|
1262
|
+
fakeMediaRequestManagers.screenShareVideo.addRequest,
|
|
1263
|
+
sinon.match({
|
|
1264
|
+
policyInfo: sinon.match({
|
|
1265
|
+
policy: 'active-speaker',
|
|
1266
|
+
priority: 255,
|
|
1267
|
+
}),
|
|
1268
|
+
receiveSlots: [fakeScreenShareVideoSlot],
|
|
1269
|
+
codecInfo: sinon.match({
|
|
1270
|
+
codec: 'h264',
|
|
1271
|
+
maxFs: 3600,
|
|
1272
|
+
}),
|
|
1273
|
+
})
|
|
1274
|
+
);
|
|
1275
|
+
});
|
|
929
1276
|
});
|
|
930
1277
|
});
|
|
931
1278
|
|
|
@@ -1065,7 +1412,7 @@ describe('RemoteMediaManager', () => {
|
|
|
1065
1412
|
|
|
1066
1413
|
// new slot should be allocated
|
|
1067
1414
|
assert.calledOnce(fakeReceiveSlotManager.allocateSlot);
|
|
1068
|
-
assert.calledWith(fakeReceiveSlotManager.allocateSlot,
|
|
1415
|
+
assert.calledWith(fakeReceiveSlotManager.allocateSlot, MediaType.VideoMain);
|
|
1069
1416
|
|
|
1070
1417
|
// and a media request sent out
|
|
1071
1418
|
assert.calledOnce(fakeMediaRequestManagers.video.addRequest);
|
|
@@ -1094,7 +1441,7 @@ describe('RemoteMediaManager', () => {
|
|
|
1094
1441
|
|
|
1095
1442
|
// new slot should be allocated
|
|
1096
1443
|
assert.calledOnce(fakeReceiveSlotManager.allocateSlot);
|
|
1097
|
-
assert.calledWith(fakeReceiveSlotManager.allocateSlot,
|
|
1444
|
+
assert.calledWith(fakeReceiveSlotManager.allocateSlot, MediaType.VideoMain);
|
|
1098
1445
|
|
|
1099
1446
|
// but no media requests sent out
|
|
1100
1447
|
assert.notCalled(fakeMediaRequestManagers.video.addRequest);
|
|
@@ -1123,7 +1470,7 @@ describe('RemoteMediaManager', () => {
|
|
|
1123
1470
|
await remoteMediaManager.start();
|
|
1124
1471
|
await remoteMediaManager.setLayout('Stage');
|
|
1125
1472
|
|
|
1126
|
-
const fakeNewSlot = new FakeSlot(
|
|
1473
|
+
const fakeNewSlot = new FakeSlot(MediaType.VideoMain, 'fake video slot');
|
|
1127
1474
|
const fakeRequestId = 'fake request id';
|
|
1128
1475
|
|
|
1129
1476
|
fakeReceiveSlotManager.allocateSlot.resolves(fakeNewSlot);
|