@webex/plugin-meetings 3.0.0-beta.4 → 3.0.0-beta.400
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/README.md +58 -8
- package/UPGRADING.md +9 -9
- package/browsers.js +19 -24
- package/dist/annotation/annotation.types.js +7 -0
- package/dist/annotation/annotation.types.js.map +1 -0
- package/dist/annotation/constants.js +49 -0
- package/dist/annotation/constants.js.map +1 -0
- package/dist/annotation/index.js +342 -0
- package/dist/annotation/index.js.map +1 -0
- package/dist/breakouts/breakout.js +216 -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/edit-lock-error.js +52 -0
- package/dist/breakouts/edit-lock-error.js.map +1 -0
- package/dist/breakouts/events.js +45 -0
- package/dist/breakouts/events.js.map +1 -0
- package/dist/breakouts/index.js +1048 -0
- package/dist/breakouts/index.js.map +1 -0
- package/dist/breakouts/request.js +78 -0
- package/dist/breakouts/request.js.map +1 -0
- package/dist/breakouts/utils.js +67 -0
- package/dist/breakouts/utils.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/no-meeting-info.js +51 -0
- package/dist/common/errors/no-meeting-info.js.map +1 -0
- 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/reclaim-host-role-errors.js +158 -0
- package/dist/common/errors/reclaim-host-role-errors.js.map +1 -0
- 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 +54 -48
- 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 +41 -60
- package/dist/common/logs/request.js.map +1 -1
- package/dist/common/queue.js +28 -23
- package/dist/common/queue.js.map +1 -1
- package/dist/config.js +11 -15
- package/dist/config.js.map +1 -1
- package/dist/constants.js +347 -74
- package/dist/constants.js.map +1 -1
- package/dist/controls-options-manager/constants.js +14 -0
- package/dist/controls-options-manager/constants.js.map +1 -0
- package/dist/controls-options-manager/enums.js +27 -0
- package/dist/controls-options-manager/enums.js.map +1 -0
- package/dist/controls-options-manager/index.js +297 -0
- package/dist/controls-options-manager/index.js.map +1 -0
- package/dist/controls-options-manager/types.js +7 -0
- package/dist/controls-options-manager/types.js.map +1 -0
- package/dist/controls-options-manager/util.js +319 -0
- package/dist/controls-options-manager/util.js.map +1 -0
- package/dist/index.js +125 -18
- package/dist/index.js.map +1 -1
- package/dist/interceptors/index.js +15 -0
- package/dist/interceptors/index.js.map +1 -0
- package/dist/interceptors/locusRetry.js +93 -0
- package/dist/interceptors/locusRetry.js.map +1 -0
- package/dist/interpretation/collection.js +23 -0
- package/dist/interpretation/collection.js.map +1 -0
- package/dist/interpretation/index.js +380 -0
- package/dist/interpretation/index.js.map +1 -0
- package/dist/interpretation/siLanguage.js +25 -0
- package/dist/interpretation/siLanguage.js.map +1 -0
- package/dist/locus-info/controlsUtils.js +101 -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 +564 -246
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/infoUtils.js +10 -38
- package/dist/locus-info/infoUtils.js.map +1 -1
- package/dist/locus-info/mediaSharesUtils.js +82 -38
- package/dist/locus-info/mediaSharesUtils.js.map +1 -1
- package/dist/locus-info/parser.js +314 -163
- package/dist/locus-info/parser.js.map +1 -1
- package/dist/locus-info/selfUtils.js +110 -92
- package/dist/locus-info/selfUtils.js.map +1 -1
- package/dist/media/index.js +107 -231
- package/dist/media/index.js.map +1 -1
- package/dist/media/properties.js +137 -222
- 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 +316 -501
- package/dist/mediaQualityMetrics/config.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +97 -14
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +5311 -3871
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/locusMediaRequest.js +292 -0
- package/dist/meeting/locusMediaRequest.js.map +1 -0
- package/dist/meeting/muteState.js +260 -183
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/meeting/request.js +421 -347
- 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 +672 -585
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting/voicea-meeting.js +172 -0
- package/dist/meeting/voicea-meeting.js.map +1 -0
- package/dist/meeting-info/collection.js +6 -25
- package/dist/meeting-info/collection.js.map +1 -1
- package/dist/meeting-info/index.js +87 -39
- package/dist/meeting-info/index.js.map +1 -1
- package/dist/meeting-info/meeting-info-v2.js +352 -283
- 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 +99 -183
- package/dist/meeting-info/util.js.map +1 -1
- package/dist/meeting-info/utilv2.js +147 -234
- package/dist/meeting-info/utilv2.js.map +1 -1
- package/dist/meetings/collection.js +43 -19
- package/dist/meetings/collection.js.map +1 -1
- package/dist/meetings/index.js +895 -600
- package/dist/meetings/index.js.map +1 -1
- package/dist/meetings/meetings.types.js +7 -0
- package/dist/meetings/meetings.types.js.map +1 -0
- package/dist/meetings/request.js +26 -41
- package/dist/meetings/request.js.map +1 -1
- package/dist/meetings/util.js +184 -157
- package/dist/meetings/util.js.map +1 -1
- package/dist/member/index.js +134 -85
- package/dist/member/index.js.map +1 -1
- package/dist/member/types.js +25 -0
- package/dist/member/types.js.map +1 -0
- package/dist/member/util.js +158 -88
- package/dist/member/util.js.map +1 -1
- package/dist/members/collection.js +13 -12
- package/dist/members/collection.js.map +1 -1
- package/dist/members/index.js +194 -204
- package/dist/members/index.js.map +1 -1
- package/dist/members/request.js +113 -68
- package/dist/members/request.js.map +1 -1
- package/dist/members/types.js +15 -0
- package/dist/members/types.js.map +1 -0
- package/dist/members/util.js +324 -259
- package/dist/members/util.js.map +1 -1
- package/dist/metrics/constants.js +19 -7
- package/dist/metrics/constants.js.map +1 -1
- package/dist/metrics/index.js +11 -558
- package/dist/metrics/index.js.map +1 -1
- package/dist/multistream/mediaRequestManager.js +263 -50
- package/dist/multistream/mediaRequestManager.js.map +1 -1
- package/dist/multistream/receiveSlot.js +58 -65
- package/dist/multistream/receiveSlot.js.map +1 -1
- package/dist/multistream/receiveSlotManager.js +76 -95
- package/dist/multistream/receiveSlotManager.js.map +1 -1
- package/dist/multistream/remoteMedia.js +62 -76
- package/dist/multistream/remoteMedia.js.map +1 -1
- package/dist/multistream/remoteMediaGroup.js +82 -45
- package/dist/multistream/remoteMediaGroup.js.map +1 -1
- package/dist/multistream/remoteMediaManager.js +657 -448
- package/dist/multistream/remoteMediaManager.js.map +1 -1
- package/dist/multistream/sendSlotManager.js +255 -0
- package/dist/multistream/sendSlotManager.js.map +1 -0
- package/dist/networkQualityMonitor/index.js +40 -59
- 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/clusterReachability.js +356 -0
- package/dist/reachability/clusterReachability.js.map +1 -0
- package/dist/reachability/index.js +297 -460
- package/dist/reachability/index.js.map +1 -1
- package/dist/reachability/request.js +20 -26
- package/dist/reachability/request.js.map +1 -1
- package/dist/reachability/util.js +29 -0
- package/dist/reachability/util.js.map +1 -0
- 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 +413 -483
- 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 +362 -0
- package/dist/recording-controller/index.js.map +1 -0
- package/dist/recording-controller/util.js +64 -0
- package/dist/recording-controller/util.js.map +1 -0
- package/dist/roap/index.js +102 -86
- package/dist/roap/index.js.map +1 -1
- package/dist/roap/request.js +131 -135
- package/dist/roap/request.js.map +1 -1
- package/dist/roap/turnDiscovery.js +437 -116
- package/dist/roap/turnDiscovery.js.map +1 -1
- package/dist/rtcMetrics/constants.js +12 -0
- package/dist/rtcMetrics/constants.js.map +1 -0
- package/dist/rtcMetrics/index.js +179 -0
- package/dist/rtcMetrics/index.js.map +1 -0
- package/dist/statsAnalyzer/global.js +1 -95
- package/dist/statsAnalyzer/global.js.map +1 -1
- package/dist/statsAnalyzer/index.js +557 -583
- package/dist/statsAnalyzer/index.js.map +1 -1
- package/dist/statsAnalyzer/mqaUtil.js +326 -130
- package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
- package/dist/transcription/index.js +22 -47
- package/dist/transcription/index.js.map +1 -1
- package/dist/types/annotation/annotation.types.d.ts +42 -0
- package/dist/types/annotation/constants.d.ts +31 -0
- package/dist/types/annotation/index.d.ts +117 -0
- package/dist/types/breakouts/breakout.d.ts +8 -0
- package/dist/types/breakouts/collection.d.ts +5 -0
- package/dist/types/breakouts/edit-lock-error.d.ts +15 -0
- package/dist/types/breakouts/events.d.ts +8 -0
- package/dist/types/breakouts/index.d.ts +5 -0
- package/dist/types/breakouts/request.d.ts +22 -0
- package/dist/types/breakouts/utils.d.ts +15 -0
- package/dist/types/common/browser-detection.d.ts +9 -0
- package/dist/types/common/collection.d.ts +48 -0
- package/dist/types/common/config.d.ts +2 -0
- package/dist/types/common/errors/captcha-error.d.ts +15 -0
- package/dist/types/common/errors/intent-to-join.d.ts +16 -0
- package/dist/types/common/errors/join-meeting.d.ts +17 -0
- package/dist/types/common/errors/media.d.ts +15 -0
- package/dist/types/common/errors/no-meeting-info.d.ts +14 -0
- package/dist/types/common/errors/parameter.d.ts +15 -0
- package/dist/types/common/errors/password-error.d.ts +15 -0
- package/dist/types/common/errors/permission.d.ts +14 -0
- package/dist/types/common/errors/reclaim-host-role-errors.d.ts +60 -0
- package/dist/types/common/errors/reconnection-in-progress.d.ts +9 -0
- package/dist/types/common/errors/reconnection.d.ts +15 -0
- package/dist/types/common/errors/stats.d.ts +15 -0
- package/dist/types/common/errors/webex-errors.d.ts +93 -0
- package/dist/types/common/errors/webex-meetings-error.d.ts +20 -0
- package/dist/types/common/events/events-scope.d.ts +17 -0
- package/dist/types/common/events/events.d.ts +12 -0
- package/dist/types/common/events/trigger-proxy.d.ts +2 -0
- package/dist/types/common/events/util.d.ts +2 -0
- package/dist/types/common/logs/logger-config.d.ts +2 -0
- package/dist/types/common/logs/logger-proxy.d.ts +2 -0
- package/dist/types/common/logs/request.d.ts +36 -0
- package/dist/types/common/queue.d.ts +34 -0
- package/dist/types/config.d.ts +72 -0
- package/dist/types/constants.d.ts +1088 -0
- package/dist/types/controls-options-manager/constants.d.ts +4 -0
- package/dist/types/controls-options-manager/enums.d.ts +15 -0
- package/dist/types/controls-options-manager/index.d.ts +136 -0
- package/dist/types/controls-options-manager/types.d.ts +43 -0
- package/dist/types/controls-options-manager/util.d.ts +1 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/interceptors/index.d.ts +2 -0
- package/dist/types/interceptors/locusRetry.d.ts +27 -0
- package/dist/types/interpretation/collection.d.ts +5 -0
- package/dist/types/interpretation/index.d.ts +5 -0
- package/dist/types/interpretation/siLanguage.d.ts +5 -0
- package/dist/types/locus-info/controlsUtils.d.ts +2 -0
- package/dist/types/locus-info/embeddedAppsUtils.d.ts +2 -0
- package/dist/types/locus-info/fullState.d.ts +2 -0
- package/dist/types/locus-info/hostUtils.d.ts +2 -0
- package/dist/types/locus-info/index.d.ts +322 -0
- package/dist/types/locus-info/infoUtils.d.ts +2 -0
- package/dist/types/locus-info/mediaSharesUtils.d.ts +2 -0
- package/dist/types/locus-info/parser.d.ts +272 -0
- package/dist/types/locus-info/selfUtils.d.ts +2 -0
- package/dist/types/media/index.d.ts +34 -0
- package/dist/types/media/properties.d.ts +93 -0
- package/dist/types/media/util.d.ts +2 -0
- package/dist/types/mediaQualityMetrics/config.d.ts +241 -0
- package/dist/types/meeting/in-meeting-actions.d.ts +167 -0
- package/dist/types/meeting/index.d.ts +1824 -0
- package/dist/types/meeting/locusMediaRequest.d.ts +74 -0
- package/dist/types/meeting/muteState.d.ts +178 -0
- package/dist/types/meeting/request.d.ts +293 -0
- package/dist/types/meeting/request.type.d.ts +11 -0
- package/dist/types/meeting/state.d.ts +9 -0
- package/dist/types/meeting/util.d.ts +118 -0
- package/dist/types/meeting/voicea-meeting.d.ts +16 -0
- package/dist/types/meeting-info/collection.d.ts +20 -0
- package/dist/types/meeting-info/index.d.ts +69 -0
- package/dist/types/meeting-info/meeting-info-v2.d.ts +123 -0
- package/dist/types/meeting-info/request.d.ts +22 -0
- package/dist/types/meeting-info/util.d.ts +2 -0
- package/dist/types/meeting-info/utilv2.d.ts +2 -0
- package/dist/types/meetings/collection.d.ts +40 -0
- package/dist/types/meetings/index.d.ts +389 -0
- package/dist/types/meetings/meetings.types.d.ts +4 -0
- package/dist/types/meetings/request.d.ts +27 -0
- package/dist/types/meetings/util.d.ts +18 -0
- package/dist/types/member/index.d.ts +160 -0
- package/dist/types/member/types.d.ts +32 -0
- package/dist/types/member/util.d.ts +2 -0
- package/dist/types/members/collection.d.ts +29 -0
- package/dist/types/members/index.d.ts +353 -0
- package/dist/types/members/request.d.ts +114 -0
- package/dist/types/members/types.d.ts +25 -0
- package/dist/types/members/util.d.ts +215 -0
- package/dist/types/metrics/constants.d.ts +70 -0
- package/dist/types/metrics/index.d.ts +45 -0
- package/dist/types/multistream/mediaRequestManager.d.ts +120 -0
- package/dist/types/multistream/receiveSlot.d.ts +68 -0
- package/dist/types/multistream/receiveSlotManager.d.ts +56 -0
- package/dist/types/multistream/remoteMedia.d.ts +72 -0
- package/dist/types/multistream/remoteMediaGroup.d.ts +49 -0
- package/dist/types/multistream/remoteMediaManager.d.ts +301 -0
- package/dist/types/multistream/sendSlotManager.d.ts +70 -0
- package/dist/types/networkQualityMonitor/index.d.ts +70 -0
- package/dist/types/personal-meeting-room/index.d.ts +47 -0
- package/dist/types/personal-meeting-room/request.d.ts +14 -0
- package/dist/types/personal-meeting-room/util.d.ts +2 -0
- package/dist/types/reachability/clusterReachability.d.ts +109 -0
- package/dist/types/reachability/index.d.ts +105 -0
- package/dist/types/reachability/request.d.ts +39 -0
- package/dist/types/reachability/util.d.ts +8 -0
- package/dist/types/reactions/constants.d.ts +3 -0
- package/dist/types/reactions/reactions.d.ts +4 -0
- package/dist/types/reactions/reactions.type.d.ts +52 -0
- package/dist/types/reconnection-manager/index.d.ts +136 -0
- package/dist/types/recording-controller/enums.d.ts +7 -0
- package/dist/types/recording-controller/index.d.ts +207 -0
- package/dist/types/recording-controller/util.d.ts +14 -0
- package/dist/types/roap/index.d.ts +86 -0
- package/dist/types/roap/request.d.ts +39 -0
- package/dist/types/roap/turnDiscovery.d.ts +155 -0
- package/dist/types/rtcMetrics/constants.d.ts +4 -0
- package/dist/types/rtcMetrics/index.d.ts +61 -0
- package/dist/types/statsAnalyzer/global.d.ts +36 -0
- package/dist/types/statsAnalyzer/index.d.ts +217 -0
- package/dist/types/statsAnalyzer/mqaUtil.d.ts +48 -0
- package/dist/types/transcription/index.d.ts +64 -0
- package/dist/types/webinar/collection.d.ts +16 -0
- package/dist/types/webinar/index.d.ts +5 -0
- package/dist/webinar/collection.js +44 -0
- package/dist/webinar/collection.js.map +1 -0
- package/dist/webinar/index.js +69 -0
- package/dist/webinar/index.js.map +1 -0
- package/internal-README.md +7 -6
- package/package.json +30 -21
- package/src/annotation/annotation.types.ts +50 -0
- package/src/annotation/constants.ts +36 -0
- package/src/annotation/index.ts +328 -0
- package/src/breakouts/README.md +220 -0
- package/src/breakouts/breakout.ts +188 -0
- package/src/breakouts/collection.ts +19 -0
- package/src/breakouts/edit-lock-error.ts +25 -0
- package/src/breakouts/events.ts +56 -0
- package/src/breakouts/index.ts +925 -0
- package/src/breakouts/request.ts +55 -0
- package/src/breakouts/utils.ts +57 -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/no-meeting-info.ts +24 -0
- 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/reclaim-host-role-errors.ts +134 -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} +51 -8
- 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} +26 -9
- package/src/common/queue.ts +22 -9
- package/src/{config.js → config.ts} +19 -21
- package/src/constants.ts +296 -27
- package/src/controls-options-manager/constants.ts +5 -0
- package/src/controls-options-manager/enums.ts +18 -0
- package/src/controls-options-manager/index.ts +278 -0
- package/src/controls-options-manager/types.ts +59 -0
- package/src/controls-options-manager/util.ts +300 -0
- package/src/index.ts +45 -0
- package/src/interceptors/index.ts +3 -0
- package/src/interceptors/locusRetry.ts +67 -0
- package/src/interpretation/README.md +60 -0
- package/src/interpretation/collection.ts +19 -0
- package/src/interpretation/index.ts +349 -0
- package/src/interpretation/siLanguage.ts +18 -0
- package/src/locus-info/controlsUtils.ts +222 -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} +561 -119
- package/src/locus-info/{infoUtils.js → infoUtils.ts} +29 -10
- package/src/locus-info/{mediaSharesUtils.js → mediaSharesUtils.ts} +97 -17
- package/src/locus-info/{parser.js → parser.ts} +303 -104
- package/src/locus-info/{selfUtils.js → selfUtils.ts} +199 -68
- package/src/media/index.ts +460 -0
- package/src/media/properties.ts +283 -0
- package/src/media/{util.js → util.ts} +2 -2
- package/src/mediaQualityMetrics/config.ts +249 -0
- package/src/meeting/in-meeting-actions.ts +199 -3
- package/src/meeting/index.ts +8494 -0
- package/src/meeting/locusMediaRequest.ts +313 -0
- package/src/meeting/muteState.ts +465 -0
- package/src/meeting/request.ts +912 -0
- package/src/meeting/request.type.ts +13 -0
- package/src/meeting/{state.js → state.ts} +50 -35
- package/src/meeting/util.ts +799 -0
- package/src/meeting/voicea-meeting.ts +122 -0
- package/src/meeting-info/{collection.js → collection.ts} +6 -2
- package/src/meeting-info/index.ts +210 -0
- package/src/meeting-info/meeting-info-v2.ts +423 -0
- package/src/meeting-info/{request.js → request.ts} +14 -4
- package/src/meeting-info/{util.js → util.ts} +70 -58
- package/src/meeting-info/{utilv2.js → utilv2.ts} +99 -82
- package/src/meetings/collection.ts +76 -0
- package/src/meetings/index.ts +1539 -0
- package/src/meetings/meetings.types.ts +12 -0
- package/src/meetings/{request.js → request.ts} +34 -25
- package/src/meetings/{util.js → util.ts} +133 -38
- package/src/member/{index.js → index.ts} +159 -56
- package/src/member/types.ts +38 -0
- package/src/member/util.ts +397 -0
- package/src/members/{collection.js → collection.ts} +10 -2
- package/src/members/{index.js → index.ts} +351 -146
- package/src/members/request.ts +255 -0
- package/src/members/types.ts +29 -0
- package/src/members/util.ts +353 -0
- package/src/metrics/{constants.js → constants.ts} +17 -6
- package/src/metrics/index.ts +73 -0
- package/src/multistream/mediaRequestManager.ts +341 -64
- package/src/multistream/receiveSlot.ts +69 -26
- package/src/multistream/receiveSlotManager.ts +66 -42
- package/src/multistream/remoteMedia.ts +40 -5
- package/src/multistream/remoteMediaGroup.ts +82 -3
- package/src/multistream/remoteMediaManager.ts +401 -81
- package/src/multistream/sendSlotManager.ts +199 -0
- package/src/networkQualityMonitor/{index.js → index.ts} +41 -29
- 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/clusterReachability.ts +320 -0
- package/src/reachability/index.ts +371 -0
- package/src/reachability/request.ts +50 -35
- package/src/reachability/util.ts +24 -0
- 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.ts +643 -0
- package/src/recording-controller/enums.ts +8 -0
- package/src/recording-controller/index.ts +332 -0
- package/src/recording-controller/util.ts +75 -0
- package/src/roap/index.ts +288 -0
- package/src/roap/request.ts +153 -0
- package/src/roap/turnDiscovery.ts +374 -70
- package/src/rtcMetrics/constants.ts +3 -0
- package/src/rtcMetrics/index.ts +166 -0
- package/src/statsAnalyzer/global.ts +37 -0
- package/src/statsAnalyzer/index.ts +1275 -0
- package/src/statsAnalyzer/mqaUtil.ts +440 -0
- package/src/transcription/{index.js → index.ts} +46 -39
- package/src/webinar/collection.ts +31 -0
- package/src/webinar/index.ts +62 -0
- package/test/integration/spec/converged-space-meetings.js +233 -0
- package/test/integration/spec/journey.js +791 -531
- package/test/integration/spec/space-meeting.js +391 -204
- package/test/integration/spec/transcription.js +7 -8
- package/test/unit/spec/annotation/index.ts +418 -0
- package/test/unit/spec/breakouts/breakout.ts +238 -0
- package/test/unit/spec/breakouts/collection.ts +15 -0
- package/test/unit/spec/breakouts/edit-lock-error.ts +30 -0
- package/test/unit/spec/breakouts/events.ts +89 -0
- package/test/unit/spec/breakouts/index.ts +1793 -0
- package/test/unit/spec/breakouts/request.ts +104 -0
- package/test/unit/spec/breakouts/utils.js +72 -0
- package/test/unit/spec/common/browser-detection.js +9 -28
- package/test/unit/spec/common/queue.js +31 -2
- package/test/unit/spec/controls-options-manager/index.js +287 -0
- package/test/unit/spec/controls-options-manager/util.js +582 -0
- package/test/unit/spec/fixture/locus.js +93 -90
- package/test/unit/spec/interceptors/locusRetry.ts +131 -0
- package/test/unit/spec/interpretation/collection.ts +15 -0
- package/test/unit/spec/interpretation/index.ts +625 -0
- package/test/unit/spec/interpretation/siLanguage.ts +28 -0
- package/test/unit/spec/locus-info/controlsUtils.js +325 -32
- package/test/unit/spec/locus-info/embeddedAppsUtils.js +8 -6
- package/test/unit/spec/locus-info/index.js +1458 -21
- package/test/unit/spec/locus-info/infoUtils.js +71 -40
- package/test/unit/spec/locus-info/lib/BasicSeqCmp.json +88 -430
- package/test/unit/spec/locus-info/lib/SeqCmp.json +529 -685
- package/test/unit/spec/locus-info/mediaSharesUtils.ts +41 -0
- package/test/unit/spec/locus-info/parser.js +119 -44
- package/test/unit/spec/locus-info/selfConstant.js +120 -103
- package/test/unit/spec/locus-info/selfUtils.js +291 -12
- package/test/unit/spec/media/index.ts +194 -111
- package/test/unit/spec/media/properties.ts +11 -11
- package/test/unit/spec/meeting/in-meeting-actions.ts +96 -3
- package/test/unit/spec/meeting/index.js +8616 -1921
- package/test/unit/spec/meeting/locusMediaRequest.ts +442 -0
- package/test/unit/spec/meeting/muteState.js +568 -207
- package/test/unit/spec/meeting/request.js +602 -82
- package/test/unit/spec/meeting/utils.js +867 -179
- package/test/unit/spec/meeting/voicea-meeting.ts +266 -0
- package/test/unit/spec/meeting-info/index.js +300 -0
- package/test/unit/spec/meeting-info/meetinginfov2.js +631 -78
- 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 +131 -74
- package/test/unit/spec/meetings/collection.js +27 -1
- package/test/unit/spec/meetings/index.js +1826 -374
- package/test/unit/spec/meetings/utils.js +243 -14
- package/test/unit/spec/member/index.js +61 -7
- package/test/unit/spec/member/util.js +526 -26
- package/test/unit/spec/members/index.js +536 -55
- package/test/unit/spec/members/request.js +228 -40
- package/test/unit/spec/members/utils.js +217 -4
- package/test/unit/spec/metrics/index.js +13 -68
- package/test/unit/spec/multistream/mediaRequestManager.ts +1032 -110
- package/test/unit/spec/multistream/receiveSlot.ts +77 -18
- package/test/unit/spec/multistream/receiveSlotManager.ts +69 -39
- package/test/unit/spec/multistream/remoteMedia.ts +40 -2
- package/test/unit/spec/multistream/remoteMediaGroup.ts +350 -5
- package/test/unit/spec/multistream/remoteMediaManager.ts +937 -65
- package/test/unit/spec/multistream/sendSlotManager.ts +274 -0
- package/test/unit/spec/networkQualityMonitor/index.js +24 -18
- package/test/unit/spec/personal-meeting-room/personal-meeting-room.js +2 -7
- package/test/unit/spec/reachability/clusterReachability.ts +279 -0
- package/test/unit/spec/reachability/index.ts +606 -26
- package/test/unit/spec/reachability/request.js +68 -0
- package/test/unit/spec/reachability/util.ts +40 -0
- package/test/unit/spec/reconnection-manager/index.js +222 -34
- package/test/unit/spec/recording-controller/index.js +306 -0
- package/test/unit/spec/recording-controller/util.js +229 -0
- package/test/unit/spec/roap/index.ts +238 -82
- package/test/unit/spec/roap/request.ts +255 -0
- package/test/unit/spec/roap/turnDiscovery.ts +707 -110
- package/test/unit/spec/rtcMetrics/index.ts +122 -0
- package/test/unit/spec/stats-analyzer/index.js +1331 -62
- package/test/unit/spec/webinar/collection.ts +13 -0
- package/test/unit/spec/webinar/index.ts +60 -0
- package/test/utils/cmr.js +44 -42
- package/test/utils/constants.js +9 -0
- package/test/utils/integrationTestUtils.js +46 -0
- package/test/utils/testUtils.js +63 -99
- package/test/utils/webex-config.js +22 -18
- package/test/utils/webex-test-users.js +65 -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/meeting/effectsState.js +0 -327
- package/dist/meeting/effectsState.js.map +0 -1
- package/dist/metrics/config.js +0 -301
- package/dist/metrics/config.js.map +0 -1
- package/dist/multistream/multistreamMedia.js +0 -116
- package/dist/multistream/multistreamMedia.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/index.js +0 -15
- package/src/locus-info/controlsUtils.js +0 -102
- package/src/media/index.js +0 -459
- package/src/media/internal-media-core-wrapper.ts +0 -9
- package/src/media/properties.js +0 -289
- package/src/mediaQualityMetrics/config.js +0 -382
- package/src/meeting/effectsState.js +0 -205
- package/src/meeting/index.js +0 -6284
- package/src/meeting/muteState.js +0 -318
- package/src/meeting/request.js +0 -684
- package/src/meeting/util.js +0 -506
- package/src/meeting-info/index.js +0 -131
- package/src/meeting-info/meeting-info-v2.js +0 -255
- package/src/meetings/collection.js +0 -40
- package/src/meetings/index.js +0 -1015
- package/src/member/util.js +0 -254
- package/src/members/request.js +0 -131
- package/src/members/util.js +0 -258
- package/src/metrics/config.js +0 -324
- package/src/metrics/index.js +0 -530
- package/src/multistream/multistreamMedia.ts +0 -92
- package/src/peer-connection-manager/util.ts +0 -117
- package/src/reachability/index.js +0 -464
- package/src/reconnection-manager/index.js +0 -519
- package/src/roap/index.js +0 -220
- package/src/roap/request.js +0 -127
- package/src/statsAnalyzer/global.js +0 -133
- package/src/statsAnalyzer/index.js +0 -1006
- package/src/statsAnalyzer/mqaUtil.js +0 -173
- package/test/unit/spec/meeting/effectsState.js +0 -291
- package/test/unit/spec/peerconnection-manager/utils.test-fixtures.ts +0 -389
- /package/src/common/errors/{reconnection-in-progress.js → reconnection-in-progress.ts} +0 -0
|
@@ -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,
|
|
@@ -15,15 +15,19 @@ import {cloneDeep} from 'lodash';
|
|
|
15
15
|
import {MediaRequest} from '@webex/plugin-meetings/src/multistream/mediaRequestManager';
|
|
16
16
|
import {CSI, ReceiveSlotId} from '@webex/plugin-meetings/src/multistream/receiveSlot';
|
|
17
17
|
import testUtils from '../../../utils/testUtils';
|
|
18
|
+
import LoggerProxy from '@webex/plugin-meetings/src/common/logs/logger-proxy';
|
|
19
|
+
import LoggerConfig from '@webex/plugin-meetings/src/common/logs/logger-config';
|
|
20
|
+
import { expect } from 'chai';
|
|
21
|
+
import { NamedMediaGroup } from "@webex/json-multistream";
|
|
18
22
|
|
|
19
23
|
class FakeSlot extends EventEmitter {
|
|
20
|
-
public mediaType:
|
|
24
|
+
public mediaType: MediaType;
|
|
21
25
|
|
|
22
26
|
public id: string;
|
|
23
27
|
|
|
24
28
|
public csi?: number;
|
|
25
29
|
|
|
26
|
-
constructor(mediaType:
|
|
30
|
+
constructor(mediaType: MediaType, id: string) {
|
|
27
31
|
super();
|
|
28
32
|
this.mediaType = mediaType;
|
|
29
33
|
this.id = id;
|
|
@@ -32,11 +36,16 @@ class FakeSlot extends EventEmitter {
|
|
|
32
36
|
// Calling setMaxListeners() fixes the warning.
|
|
33
37
|
this.setMaxListeners(50);
|
|
34
38
|
}
|
|
39
|
+
|
|
40
|
+
public get logString() {
|
|
41
|
+
return this.id;
|
|
42
|
+
}
|
|
35
43
|
}
|
|
36
44
|
|
|
37
45
|
const DefaultTestConfiguration: Configuration = {
|
|
38
46
|
audio: {
|
|
39
47
|
numOfActiveSpeakerStreams: 3,
|
|
48
|
+
numOfScreenShareStreams: 1,
|
|
40
49
|
},
|
|
41
50
|
video: {
|
|
42
51
|
preferLiveVideo: true,
|
|
@@ -44,7 +53,6 @@ const DefaultTestConfiguration: Configuration = {
|
|
|
44
53
|
|
|
45
54
|
layouts: {
|
|
46
55
|
AllEqual: {
|
|
47
|
-
screenShareVideo: {size: null},
|
|
48
56
|
activeSpeakerVideoPaneGroups: [
|
|
49
57
|
{
|
|
50
58
|
id: 'main',
|
|
@@ -55,7 +63,6 @@ const DefaultTestConfiguration: Configuration = {
|
|
|
55
63
|
],
|
|
56
64
|
},
|
|
57
65
|
OnePlusFive: {
|
|
58
|
-
screenShareVideo: {size: null},
|
|
59
66
|
activeSpeakerVideoPaneGroups: [
|
|
60
67
|
{
|
|
61
68
|
id: 'mainBigOne',
|
|
@@ -72,7 +79,6 @@ const DefaultTestConfiguration: Configuration = {
|
|
|
72
79
|
],
|
|
73
80
|
},
|
|
74
81
|
Single: {
|
|
75
|
-
screenShareVideo: {size: null},
|
|
76
82
|
activeSpeakerVideoPaneGroups: [
|
|
77
83
|
{
|
|
78
84
|
id: 'main',
|
|
@@ -83,7 +89,6 @@ const DefaultTestConfiguration: Configuration = {
|
|
|
83
89
|
],
|
|
84
90
|
},
|
|
85
91
|
Stage: {
|
|
86
|
-
screenShareVideo: {size: null},
|
|
87
92
|
activeSpeakerVideoPaneGroups: [
|
|
88
93
|
{
|
|
89
94
|
id: 'thumbnails',
|
|
@@ -99,12 +104,19 @@ const DefaultTestConfiguration: Configuration = {
|
|
|
99
104
|
{id: 'stage-4', size: 'medium', csi: undefined},
|
|
100
105
|
],
|
|
101
106
|
},
|
|
107
|
+
ScreenShareView: {
|
|
108
|
+
screenShareVideo: {size: 'medium'},
|
|
109
|
+
activeSpeakerVideoPaneGroups: [
|
|
110
|
+
{
|
|
111
|
+
id: 'thumbnails',
|
|
112
|
+
numPanes: 6,
|
|
113
|
+
size: 'thumbnail',
|
|
114
|
+
priority: 255,
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
},
|
|
102
118
|
},
|
|
103
119
|
},
|
|
104
|
-
screenShare: {
|
|
105
|
-
audio: true,
|
|
106
|
-
video: true,
|
|
107
|
-
},
|
|
108
120
|
};
|
|
109
121
|
|
|
110
122
|
describe('RemoteMediaManager', () => {
|
|
@@ -113,18 +125,50 @@ describe('RemoteMediaManager', () => {
|
|
|
113
125
|
let fakeMediaRequestManagers;
|
|
114
126
|
let fakeAudioSlot;
|
|
115
127
|
let fakeVideoSlot;
|
|
128
|
+
let fakeScreenShareAudioSlot;
|
|
129
|
+
let fakeScreenShareVideoSlot;
|
|
130
|
+
|
|
131
|
+
const logger = {
|
|
132
|
+
log: sinon.fake(),
|
|
133
|
+
error: () => {},
|
|
134
|
+
warn: () => {},
|
|
135
|
+
trace: () => {},
|
|
136
|
+
debug: () => {},
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
afterEach(() => {
|
|
140
|
+
LoggerConfig.set({enable: false});
|
|
141
|
+
LoggerProxy.set();
|
|
142
|
+
});
|
|
116
143
|
|
|
117
144
|
beforeEach(() => {
|
|
118
|
-
|
|
119
|
-
|
|
145
|
+
LoggerConfig.set({enable: true});
|
|
146
|
+
LoggerProxy.set(logger);
|
|
147
|
+
|
|
148
|
+
fakeAudioSlot = new FakeSlot(MediaType.AudioMain, 'fake audio slot');
|
|
149
|
+
fakeVideoSlot = new FakeSlot(MediaType.VideoMain, 'fake video slot');
|
|
150
|
+
fakeScreenShareAudioSlot = new FakeSlot(
|
|
151
|
+
MediaType.AudioSlides,
|
|
152
|
+
'fake screen share audio slot'
|
|
153
|
+
);
|
|
154
|
+
fakeScreenShareVideoSlot = new FakeSlot(
|
|
155
|
+
MediaType.VideoSlides,
|
|
156
|
+
'fake screen share video slot'
|
|
157
|
+
);
|
|
120
158
|
|
|
121
159
|
fakeReceiveSlotManager = {
|
|
122
160
|
allocateSlot: sinon.stub().callsFake((mediaType) => {
|
|
123
|
-
|
|
124
|
-
|
|
161
|
+
switch (mediaType) {
|
|
162
|
+
case MediaType.AudioMain:
|
|
163
|
+
return Promise.resolve(fakeAudioSlot);
|
|
164
|
+
case MediaType.VideoMain:
|
|
165
|
+
return Promise.resolve(fakeVideoSlot);
|
|
166
|
+
case MediaType.AudioSlides:
|
|
167
|
+
return Promise.resolve(fakeScreenShareAudioSlot);
|
|
168
|
+
case MediaType.VideoSlides:
|
|
169
|
+
return Promise.resolve(fakeScreenShareVideoSlot);
|
|
125
170
|
}
|
|
126
|
-
|
|
127
|
-
return Promise.resolve(fakeVideoSlot);
|
|
171
|
+
throw new Error(`invalid mediaType: ${mediaType}`);
|
|
128
172
|
}),
|
|
129
173
|
releaseSlot: sinon.stub(),
|
|
130
174
|
};
|
|
@@ -140,6 +184,16 @@ describe('RemoteMediaManager', () => {
|
|
|
140
184
|
cancelRequest: sinon.stub(),
|
|
141
185
|
commit: sinon.stub(),
|
|
142
186
|
},
|
|
187
|
+
screenShareAudio: {
|
|
188
|
+
addRequest: sinon.stub(),
|
|
189
|
+
cancelRequest: sinon.stub(),
|
|
190
|
+
commit: sinon.stub(),
|
|
191
|
+
},
|
|
192
|
+
screenShareVideo: {
|
|
193
|
+
addRequest: sinon.stub(),
|
|
194
|
+
cancelRequest: sinon.stub(),
|
|
195
|
+
commit: sinon.stub(),
|
|
196
|
+
},
|
|
143
197
|
};
|
|
144
198
|
|
|
145
199
|
// create remote media manager with default configuration
|
|
@@ -159,6 +213,9 @@ describe('RemoteMediaManager', () => {
|
|
|
159
213
|
fakeMediaRequestManagers.video.addRequest.resetHistory();
|
|
160
214
|
fakeMediaRequestManagers.video.cancelRequest.resetHistory();
|
|
161
215
|
fakeMediaRequestManagers.video.commit.resetHistory();
|
|
216
|
+
fakeMediaRequestManagers.screenShareVideo.commit.resetHistory();
|
|
217
|
+
fakeMediaRequestManagers.screenShareAudio.commit.resetHistory();
|
|
218
|
+
logger.log.resetHistory();
|
|
162
219
|
};
|
|
163
220
|
|
|
164
221
|
describe('start', () => {
|
|
@@ -176,8 +233,8 @@ describe('RemoteMediaManager', () => {
|
|
|
176
233
|
await remoteMediaManager.start();
|
|
177
234
|
|
|
178
235
|
// 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,
|
|
236
|
+
assert.calledWith(fakeReceiveSlotManager.allocateSlot, MediaType.AudioMain);
|
|
237
|
+
assert.calledWith(fakeReceiveSlotManager.allocateSlot, MediaType.VideoMain);
|
|
181
238
|
|
|
182
239
|
assert.called(fakeMediaRequestManagers.audio.addRequest);
|
|
183
240
|
assert.called(fakeMediaRequestManagers.video.addRequest);
|
|
@@ -187,25 +244,18 @@ describe('RemoteMediaManager', () => {
|
|
|
187
244
|
let createdAudioGroup: RemoteMediaGroup | null = null;
|
|
188
245
|
|
|
189
246
|
// create a config with just audio, no video at all and no screen share
|
|
190
|
-
const config = {
|
|
247
|
+
const config: Configuration = {
|
|
191
248
|
audio: {
|
|
192
249
|
numOfActiveSpeakerStreams: 5,
|
|
250
|
+
numOfScreenShareStreams: 0,
|
|
193
251
|
},
|
|
194
252
|
video: {
|
|
195
253
|
preferLiveVideo: false,
|
|
196
254
|
initialLayoutId: 'empty',
|
|
197
255
|
layouts: {
|
|
198
|
-
empty: {
|
|
199
|
-
screenShareVideo: {
|
|
200
|
-
size: null,
|
|
201
|
-
},
|
|
202
|
-
},
|
|
256
|
+
empty: {},
|
|
203
257
|
},
|
|
204
258
|
},
|
|
205
|
-
screenShare: {
|
|
206
|
-
audio: false,
|
|
207
|
-
video: false,
|
|
208
|
-
},
|
|
209
259
|
};
|
|
210
260
|
|
|
211
261
|
remoteMediaManager = new RemoteMediaManager(
|
|
@@ -223,7 +273,7 @@ describe('RemoteMediaManager', () => {
|
|
|
223
273
|
await testUtils.flushPromises();
|
|
224
274
|
|
|
225
275
|
assert.callCount(fakeReceiveSlotManager.allocateSlot, 5);
|
|
226
|
-
assert.alwaysCalledWith(fakeReceiveSlotManager.allocateSlot,
|
|
276
|
+
assert.alwaysCalledWith(fakeReceiveSlotManager.allocateSlot, MediaType.AudioMain);
|
|
227
277
|
|
|
228
278
|
assert.isNotNull(createdAudioGroup);
|
|
229
279
|
if (createdAudioGroup) {
|
|
@@ -231,7 +281,7 @@ describe('RemoteMediaManager', () => {
|
|
|
231
281
|
assert.isTrue(
|
|
232
282
|
createdAudioGroup
|
|
233
283
|
.getRemoteMedia()
|
|
234
|
-
.every((remoteMedia) => remoteMedia.mediaType ===
|
|
284
|
+
.every((remoteMedia) => remoteMedia.mediaType === MediaType.AudioMain)
|
|
235
285
|
);
|
|
236
286
|
assert.strictEqual(createdAudioGroup.getRemoteMedia('pinned').length, 0);
|
|
237
287
|
}
|
|
@@ -250,14 +300,209 @@ describe('RemoteMediaManager', () => {
|
|
|
250
300
|
);
|
|
251
301
|
});
|
|
252
302
|
|
|
303
|
+
it('creates a RemoteMediaGroup for named media group audio correctly', async () => {
|
|
304
|
+
let createdInterpretationAudioGroup: RemoteMediaGroup | null = null;
|
|
305
|
+
// create a config with just audio, no video at all and no screen share
|
|
306
|
+
const config: Configuration = {
|
|
307
|
+
audio: {
|
|
308
|
+
numOfActiveSpeakerStreams: 3,
|
|
309
|
+
numOfScreenShareStreams: 0,
|
|
310
|
+
},
|
|
311
|
+
video: {
|
|
312
|
+
preferLiveVideo: false,
|
|
313
|
+
initialLayoutId: 'empty',
|
|
314
|
+
layouts: {
|
|
315
|
+
empty: {},
|
|
316
|
+
},
|
|
317
|
+
},
|
|
318
|
+
namedMediaGroup: {type: 1, value: 20},
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
remoteMediaManager = new RemoteMediaManager(
|
|
322
|
+
fakeReceiveSlotManager,
|
|
323
|
+
fakeMediaRequestManagers,
|
|
324
|
+
config
|
|
325
|
+
);
|
|
326
|
+
|
|
327
|
+
remoteMediaManager.on(Event.InterpretationAudioCreated, (audio: RemoteMediaGroup) => {
|
|
328
|
+
createdInterpretationAudioGroup = audio;
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
remoteMediaManager.start();
|
|
332
|
+
|
|
333
|
+
await testUtils.flushPromises();
|
|
334
|
+
|
|
335
|
+
assert.callCount(fakeReceiveSlotManager.allocateSlot, 4);
|
|
336
|
+
assert.alwaysCalledWith(fakeReceiveSlotManager.allocateSlot, MediaType.AudioMain);
|
|
337
|
+
|
|
338
|
+
assert.isNotNull(createdInterpretationAudioGroup);
|
|
339
|
+
if (createdInterpretationAudioGroup) {
|
|
340
|
+
assert.strictEqual(createdInterpretationAudioGroup.getRemoteMedia().length, 1);
|
|
341
|
+
assert.isTrue(
|
|
342
|
+
createdInterpretationAudioGroup
|
|
343
|
+
.getRemoteMedia()
|
|
344
|
+
.every((remoteMedia) => remoteMedia.mediaType === MediaType.AudioMain)
|
|
345
|
+
);
|
|
346
|
+
assert.strictEqual(createdInterpretationAudioGroup.getRemoteMedia('pinned').length, 0);
|
|
347
|
+
assert.calledTwice(fakeMediaRequestManagers.audio.addRequest);
|
|
348
|
+
assert.calledWith(
|
|
349
|
+
fakeMediaRequestManagers.audio.addRequest,
|
|
350
|
+
sinon.match({
|
|
351
|
+
policyInfo: sinon.match({
|
|
352
|
+
policy: 'active-speaker',
|
|
353
|
+
priority: 255,
|
|
354
|
+
namedMediaGroups: sinon.match([{type: 1, value: 20}]),
|
|
355
|
+
}),
|
|
356
|
+
receiveSlots: Array(1).fill(fakeAudioSlot),
|
|
357
|
+
codecInfo: undefined,
|
|
358
|
+
}),
|
|
359
|
+
false,
|
|
360
|
+
);
|
|
361
|
+
}
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
it('creates new media request when call setReceiveNamedMediaGroup', async () => {
|
|
365
|
+
let createdInterpretationAudioGroup: RemoteMediaGroup | null = null;
|
|
366
|
+
// create a config with just audio, no video at all and no screen share
|
|
367
|
+
const config: Configuration = {
|
|
368
|
+
audio: {
|
|
369
|
+
numOfActiveSpeakerStreams: 3,
|
|
370
|
+
numOfScreenShareStreams: 0,
|
|
371
|
+
},
|
|
372
|
+
video: {
|
|
373
|
+
preferLiveVideo: false,
|
|
374
|
+
initialLayoutId: 'empty',
|
|
375
|
+
layouts: {
|
|
376
|
+
empty: {},
|
|
377
|
+
},
|
|
378
|
+
},
|
|
379
|
+
namedMediaGroup: {type: 1, value: 24},
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
remoteMediaManager = new RemoteMediaManager(
|
|
383
|
+
fakeReceiveSlotManager,
|
|
384
|
+
fakeMediaRequestManagers,
|
|
385
|
+
config
|
|
386
|
+
);
|
|
387
|
+
|
|
388
|
+
remoteMediaManager.on(Event.InterpretationAudioCreated, (audio: RemoteMediaGroup) => {
|
|
389
|
+
createdInterpretationAudioGroup = audio;
|
|
390
|
+
createdInterpretationAudioGroup.setNamedMediaGroup = sinon.stub();
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
await remoteMediaManager.start();
|
|
394
|
+
|
|
395
|
+
// requires 3 main audio slots and one interpretation audio slot
|
|
396
|
+
assert.callCount(fakeReceiveSlotManager.allocateSlot, 4);
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
resetHistory();
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
remoteMediaManager.setReceiveNamedMediaGroup(MediaType.AudioMain, 28);
|
|
403
|
+
|
|
404
|
+
// check that setNamedMediaGroup has been called
|
|
405
|
+
assert.calledOnce(createdInterpretationAudioGroup.setNamedMediaGroup);
|
|
406
|
+
assert.calledWith(
|
|
407
|
+
createdInterpretationAudioGroup.setNamedMediaGroup,
|
|
408
|
+
{type: 1, value: 28},
|
|
409
|
+
true,
|
|
410
|
+
);
|
|
411
|
+
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
it('ignore duplicated group when call setReceiveNamedMediaGroup', async () => {
|
|
415
|
+
let createdAudioGroup: RemoteMediaGroup | null = null;
|
|
416
|
+
let audioStopStub;
|
|
417
|
+
// create a config with just audio, no video at all and no screen share
|
|
418
|
+
const config: Configuration = {
|
|
419
|
+
audio: {
|
|
420
|
+
numOfActiveSpeakerStreams: 3,
|
|
421
|
+
numOfScreenShareStreams: 0,
|
|
422
|
+
},
|
|
423
|
+
video: {
|
|
424
|
+
preferLiveVideo: false,
|
|
425
|
+
initialLayoutId: 'empty',
|
|
426
|
+
layouts: {
|
|
427
|
+
empty: {},
|
|
428
|
+
},
|
|
429
|
+
},
|
|
430
|
+
namedMediaGroup: {type: 1, value: 24},
|
|
431
|
+
};
|
|
432
|
+
|
|
433
|
+
remoteMediaManager = new RemoteMediaManager(
|
|
434
|
+
fakeReceiveSlotManager,
|
|
435
|
+
fakeMediaRequestManagers,
|
|
436
|
+
config
|
|
437
|
+
);
|
|
438
|
+
|
|
439
|
+
remoteMediaManager.on(Event.AudioCreated, (audio: RemoteMediaGroup) => {
|
|
440
|
+
audioStopStub = sinon.stub(audio, 'stop');
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
await remoteMediaManager.start();
|
|
444
|
+
|
|
445
|
+
// we're using the default config that requires 3 main audio slots
|
|
446
|
+
assert.callCount(fakeReceiveSlotManager.allocateSlot, 4);
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
resetHistory();
|
|
450
|
+
|
|
451
|
+
remoteMediaManager.setReceiveNamedMediaGroup(MediaType.AudioMain, 24);
|
|
452
|
+
|
|
453
|
+
assert.notCalled(audioStopStub);
|
|
454
|
+
assert.callCount(fakeReceiveSlotManager.releaseSlot, 0);
|
|
455
|
+
|
|
456
|
+
await testUtils.flushPromises();
|
|
457
|
+
assert.callCount(fakeReceiveSlotManager.allocateSlot, 0);
|
|
458
|
+
assert.notCalled(fakeReceiveSlotManager.allocateSlot);
|
|
459
|
+
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
it('should throw error if set receive named media group which type is not audio', async () => {
|
|
464
|
+
let createdAudioGroup: RemoteMediaGroup | null = null;
|
|
465
|
+
let audioStopStub;
|
|
466
|
+
// create a config with just audio, no video at all and no screen share
|
|
467
|
+
const config: Configuration = {
|
|
468
|
+
audio: {
|
|
469
|
+
numOfActiveSpeakerStreams: 3,
|
|
470
|
+
numOfScreenShareStreams: 0,
|
|
471
|
+
},
|
|
472
|
+
video: {
|
|
473
|
+
preferLiveVideo: false,
|
|
474
|
+
initialLayoutId: 'empty',
|
|
475
|
+
layouts: {
|
|
476
|
+
empty: {},
|
|
477
|
+
},
|
|
478
|
+
},
|
|
479
|
+
namedMediaGroup: {type: 1, value: 24},
|
|
480
|
+
};
|
|
481
|
+
|
|
482
|
+
remoteMediaManager = new RemoteMediaManager(
|
|
483
|
+
fakeReceiveSlotManager,
|
|
484
|
+
fakeMediaRequestManagers,
|
|
485
|
+
config
|
|
486
|
+
);
|
|
487
|
+
|
|
488
|
+
// Assuming setReceiveNamedMediaGroup returns a promise
|
|
489
|
+
it('should throw error when media type is not audio-main', async () => {
|
|
490
|
+
try {
|
|
491
|
+
await remoteMediaManager.setReceiveNamedMediaGroup(MediaType.VideoMain, 0);
|
|
492
|
+
// If the promise resolves successfully, we should fail the test
|
|
493
|
+
throw new Error('Expected an error but none was thrown');
|
|
494
|
+
} catch (error) {
|
|
495
|
+
// Check if the error message matches the expected one
|
|
496
|
+
expect(error.message).to.equal('cannot set receive named media group which media type is not audio-main');
|
|
497
|
+
}
|
|
498
|
+
});
|
|
499
|
+
});
|
|
500
|
+
|
|
253
501
|
it('pre-allocates receive slots based on the biggest layout', async () => {
|
|
254
502
|
const config = cloneDeep(DefaultTestConfiguration);
|
|
255
503
|
|
|
256
504
|
config.audio.numOfActiveSpeakerStreams = 0;
|
|
257
505
|
config.video.layouts.huge = {
|
|
258
|
-
screenShareVideo: {
|
|
259
|
-
size: null,
|
|
260
|
-
},
|
|
261
506
|
activeSpeakerVideoPaneGroups: [
|
|
262
507
|
{
|
|
263
508
|
id: 'big one',
|
|
@@ -267,6 +512,8 @@ describe('RemoteMediaManager', () => {
|
|
|
267
512
|
},
|
|
268
513
|
],
|
|
269
514
|
};
|
|
515
|
+
config.audio.numOfScreenShareStreams = 0;
|
|
516
|
+
delete config.video.layouts.ScreenShareView;
|
|
270
517
|
|
|
271
518
|
remoteMediaManager = new RemoteMediaManager(
|
|
272
519
|
fakeReceiveSlotManager,
|
|
@@ -279,7 +526,7 @@ describe('RemoteMediaManager', () => {
|
|
|
279
526
|
// even though our "big one" layout is not the default one, the remote media manager should still
|
|
280
527
|
// preallocate enough video receive slots for it up front
|
|
281
528
|
assert.callCount(fakeReceiveSlotManager.allocateSlot, 99);
|
|
282
|
-
assert.alwaysCalledWith(fakeReceiveSlotManager.allocateSlot,
|
|
529
|
+
assert.alwaysCalledWith(fakeReceiveSlotManager.allocateSlot, MediaType.VideoMain);
|
|
283
530
|
});
|
|
284
531
|
|
|
285
532
|
it('starts with the initial layout', async () => {
|
|
@@ -302,8 +549,128 @@ describe('RemoteMediaManager', () => {
|
|
|
302
549
|
receivedLayoutInfo.activeSpeakerVideoPanes.main.getRemoteMedia().length,
|
|
303
550
|
9
|
|
304
551
|
);
|
|
552
|
+
assert.isUndefined(receivedLayoutInfo.screenShareVideo); // the initial layout has no screen share
|
|
305
553
|
}
|
|
306
554
|
});
|
|
555
|
+
|
|
556
|
+
it('creates RemoteMedia for screen share audio correctly', async () => {
|
|
557
|
+
let createdAudioGroup: RemoteMediaGroup | null = null;
|
|
558
|
+
|
|
559
|
+
const NUM_STREAMS = 2;
|
|
560
|
+
|
|
561
|
+
// create a config with just screen share audio, nothing else
|
|
562
|
+
const config: Configuration = {
|
|
563
|
+
audio: {
|
|
564
|
+
numOfActiveSpeakerStreams: 0,
|
|
565
|
+
numOfScreenShareStreams: NUM_STREAMS,
|
|
566
|
+
},
|
|
567
|
+
video: {
|
|
568
|
+
preferLiveVideo: false,
|
|
569
|
+
initialLayoutId: 'empty',
|
|
570
|
+
layouts: {
|
|
571
|
+
empty: {},
|
|
572
|
+
},
|
|
573
|
+
},
|
|
574
|
+
};
|
|
575
|
+
|
|
576
|
+
remoteMediaManager = new RemoteMediaManager(
|
|
577
|
+
fakeReceiveSlotManager,
|
|
578
|
+
fakeMediaRequestManagers,
|
|
579
|
+
config
|
|
580
|
+
);
|
|
581
|
+
|
|
582
|
+
remoteMediaManager.on(Event.ScreenShareAudioCreated, (audio: RemoteMediaGroup) => {
|
|
583
|
+
createdAudioGroup = audio;
|
|
584
|
+
});
|
|
585
|
+
|
|
586
|
+
remoteMediaManager.start();
|
|
587
|
+
|
|
588
|
+
await testUtils.flushPromises();
|
|
589
|
+
|
|
590
|
+
assert.callCount(fakeReceiveSlotManager.allocateSlot, NUM_STREAMS);
|
|
591
|
+
assert.alwaysCalledWith(fakeReceiveSlotManager.allocateSlot, MediaType.AudioSlides);
|
|
592
|
+
|
|
593
|
+
assert.isNotNull(createdAudioGroup);
|
|
594
|
+
if (createdAudioGroup) {
|
|
595
|
+
assert.strictEqual(createdAudioGroup.getRemoteMedia().length, NUM_STREAMS);
|
|
596
|
+
assert.isTrue(
|
|
597
|
+
createdAudioGroup
|
|
598
|
+
.getRemoteMedia()
|
|
599
|
+
.every((remoteMedia) => remoteMedia.mediaType === MediaType.AudioSlides)
|
|
600
|
+
);
|
|
601
|
+
assert.strictEqual(createdAudioGroup.getRemoteMedia('pinned').length, 0);
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
assert.calledOnce(fakeMediaRequestManagers.screenShareAudio.addRequest);
|
|
605
|
+
assert.calledWith(
|
|
606
|
+
fakeMediaRequestManagers.screenShareAudio.addRequest,
|
|
607
|
+
sinon.match({
|
|
608
|
+
policyInfo: sinon.match({
|
|
609
|
+
policy: 'active-speaker',
|
|
610
|
+
priority: 255,
|
|
611
|
+
}),
|
|
612
|
+
receiveSlots: Array(NUM_STREAMS).fill(fakeScreenShareAudioSlot),
|
|
613
|
+
codecInfo: undefined,
|
|
614
|
+
})
|
|
615
|
+
);
|
|
616
|
+
});
|
|
617
|
+
|
|
618
|
+
it('creates a single receive slot for screen share video if any layout has screen share', async () => {
|
|
619
|
+
// create a config with 2 layouts that use screen share
|
|
620
|
+
const config: Configuration = {
|
|
621
|
+
audio: {
|
|
622
|
+
numOfActiveSpeakerStreams: 0,
|
|
623
|
+
numOfScreenShareStreams: 0,
|
|
624
|
+
},
|
|
625
|
+
video: {
|
|
626
|
+
preferLiveVideo: false,
|
|
627
|
+
initialLayoutId: 'first',
|
|
628
|
+
layouts: {
|
|
629
|
+
first: {
|
|
630
|
+
screenShareVideo: { size: 'small'}
|
|
631
|
+
},
|
|
632
|
+
second: {
|
|
633
|
+
screenShareVideo: { size: 'medium'}
|
|
634
|
+
}
|
|
635
|
+
},
|
|
636
|
+
},
|
|
637
|
+
};
|
|
638
|
+
|
|
639
|
+
remoteMediaManager = new RemoteMediaManager(
|
|
640
|
+
fakeReceiveSlotManager,
|
|
641
|
+
fakeMediaRequestManagers,
|
|
642
|
+
config
|
|
643
|
+
);
|
|
644
|
+
|
|
645
|
+
await remoteMediaManager.start();
|
|
646
|
+
|
|
647
|
+
// even though 2 layouts use screen share, only 1 video screen share slot should be created
|
|
648
|
+
assert.callCount(fakeReceiveSlotManager.allocateSlot, 1);
|
|
649
|
+
assert.alwaysCalledWith(fakeReceiveSlotManager.allocateSlot, MediaType.VideoSlides);
|
|
650
|
+
});
|
|
651
|
+
|
|
652
|
+
it('does not create any receive slot for screen share video if none of the layouts have screen share', async () => {
|
|
653
|
+
const config = cloneDeep(DefaultTestConfiguration);
|
|
654
|
+
|
|
655
|
+
config.audio.numOfActiveSpeakerStreams = 0;
|
|
656
|
+
config.audio.numOfScreenShareStreams = 0;
|
|
657
|
+
|
|
658
|
+
// delete the only layout that uses screen share
|
|
659
|
+
delete config.video.layouts.ScreenShareView;
|
|
660
|
+
|
|
661
|
+
remoteMediaManager = new RemoteMediaManager(
|
|
662
|
+
fakeReceiveSlotManager,
|
|
663
|
+
fakeMediaRequestManagers,
|
|
664
|
+
config
|
|
665
|
+
);
|
|
666
|
+
|
|
667
|
+
await remoteMediaManager.start();
|
|
668
|
+
|
|
669
|
+
// we don't expect any audio and for video there should be no VideoSlides, so all the calls should be just for VideoMain
|
|
670
|
+
assert.alwaysCalledWith(fakeReceiveSlotManager.allocateSlot, MediaType.VideoMain);
|
|
671
|
+
});
|
|
672
|
+
|
|
673
|
+
|
|
307
674
|
});
|
|
308
675
|
|
|
309
676
|
describe('constructor', () => {
|
|
@@ -325,7 +692,6 @@ describe('RemoteMediaManager', () => {
|
|
|
325
692
|
const config = cloneDeep(DefaultTestConfiguration);
|
|
326
693
|
|
|
327
694
|
config.video.layouts.test = {
|
|
328
|
-
screenShareVideo: {size: null},
|
|
329
695
|
activeSpeakerVideoPaneGroups: [
|
|
330
696
|
{
|
|
331
697
|
id: 'someDuplicate',
|
|
@@ -361,7 +727,6 @@ describe('RemoteMediaManager', () => {
|
|
|
361
727
|
const config = cloneDeep(DefaultTestConfiguration);
|
|
362
728
|
|
|
363
729
|
config.video.layouts.test = {
|
|
364
|
-
screenShareVideo: {size: null},
|
|
365
730
|
activeSpeakerVideoPaneGroups: [
|
|
366
731
|
{
|
|
367
732
|
id: 'group1',
|
|
@@ -397,7 +762,6 @@ describe('RemoteMediaManager', () => {
|
|
|
397
762
|
const config = cloneDeep(DefaultTestConfiguration);
|
|
398
763
|
|
|
399
764
|
config.video.layouts.test = {
|
|
400
|
-
screenShareVideo: {size: null},
|
|
401
765
|
memberVideoPanes: [
|
|
402
766
|
{id: 'paneA', size: 'best', csi: 123},
|
|
403
767
|
{id: 'paneB', size: 'large', csi: 222},
|
|
@@ -414,6 +778,7 @@ describe('RemoteMediaManager', () => {
|
|
|
414
778
|
);
|
|
415
779
|
}, 'invalid config: duplicate member video pane id: paneB');
|
|
416
780
|
});
|
|
781
|
+
|
|
417
782
|
});
|
|
418
783
|
|
|
419
784
|
describe('stop', () => {
|
|
@@ -421,12 +786,17 @@ describe('RemoteMediaManager', () => {
|
|
|
421
786
|
let audioStopStub;
|
|
422
787
|
let videoActiveSpeakerGroupStopStub;
|
|
423
788
|
const memberVideoPaneStopStubs: any[] = [];
|
|
789
|
+
let screenShareAudioStopStub;
|
|
790
|
+
let screenShareVideoStopStub;
|
|
424
791
|
|
|
425
|
-
// change the initial layout to one that has both active speakers and
|
|
792
|
+
// change the initial layout to one that has both active speakers and receiver selected videos
|
|
426
793
|
const config = cloneDeep(DefaultTestConfiguration);
|
|
427
794
|
|
|
428
795
|
config.video.initialLayoutId = 'Stage';
|
|
429
796
|
|
|
797
|
+
// and also modify it to have screen share so we can test that too
|
|
798
|
+
config.video.layouts['Stage'].screenShareVideo = {size: 'medium'};
|
|
799
|
+
|
|
430
800
|
remoteMediaManager = new RemoteMediaManager(
|
|
431
801
|
fakeReceiveSlotManager,
|
|
432
802
|
fakeMediaRequestManagers,
|
|
@@ -437,6 +807,10 @@ describe('RemoteMediaManager', () => {
|
|
|
437
807
|
audioStopStub = sinon.stub(audio, 'stop');
|
|
438
808
|
});
|
|
439
809
|
|
|
810
|
+
remoteMediaManager.on(Event.ScreenShareAudioCreated, (audio: RemoteMediaGroup) => {
|
|
811
|
+
screenShareAudioStopStub = sinon.stub(audio, 'stop');
|
|
812
|
+
});
|
|
813
|
+
|
|
440
814
|
remoteMediaManager.on(Event.VideoLayoutChanged, (layoutInfo: VideoLayoutChangedEventData) => {
|
|
441
815
|
// The "Stage" layout that we're using has only 1 active speaker group called "thumbnails"
|
|
442
816
|
videoActiveSpeakerGroupStopStub = sinon.stub(
|
|
@@ -447,12 +821,14 @@ describe('RemoteMediaManager', () => {
|
|
|
447
821
|
Object.values(layoutInfo.memberVideoPanes).forEach((pane) => {
|
|
448
822
|
memberVideoPaneStopStubs.push(sinon.stub(pane, 'stop'));
|
|
449
823
|
});
|
|
824
|
+
|
|
825
|
+
screenShareVideoStopStub = sinon.stub(layoutInfo.screenShareVideo, 'stop');
|
|
450
826
|
});
|
|
451
827
|
|
|
452
828
|
await remoteMediaManager.start();
|
|
453
829
|
|
|
454
|
-
// we're using the default config that requires 3 main audio slots
|
|
455
|
-
assert.callCount(fakeReceiveSlotManager.allocateSlot,
|
|
830
|
+
// we're using the default config that requires 3 main audio slots, 10 video slots (for Stage2x2With6ThumbnailsLayout), 1 screenshare audio, 1 screenshare video
|
|
831
|
+
assert.callCount(fakeReceiveSlotManager.allocateSlot, 15);
|
|
456
832
|
|
|
457
833
|
// our layout has 4 member video panes, we should have a stub for each of these panes' stop methods
|
|
458
834
|
assert.strictEqual(memberVideoPaneStopStubs.length, 4);
|
|
@@ -462,16 +838,20 @@ describe('RemoteMediaManager', () => {
|
|
|
462
838
|
remoteMediaManager.stop();
|
|
463
839
|
|
|
464
840
|
// check that all slots have been released
|
|
465
|
-
assert.callCount(fakeReceiveSlotManager.releaseSlot,
|
|
841
|
+
assert.callCount(fakeReceiveSlotManager.releaseSlot, 15);
|
|
466
842
|
|
|
467
843
|
// and that all RemoteMedia and RemoteMediaGroups have been stopped
|
|
468
844
|
assert.calledOnce(audioStopStub);
|
|
469
845
|
assert.calledWith(audioStopStub, true);
|
|
846
|
+
assert.calledOnce(screenShareAudioStopStub);
|
|
847
|
+
assert.calledWith(screenShareAudioStopStub, true);
|
|
470
848
|
assert.calledOnce(videoActiveSpeakerGroupStopStub);
|
|
471
849
|
memberVideoPaneStopStubs.forEach((stub) => {
|
|
472
850
|
assert.calledOnce(stub);
|
|
473
851
|
});
|
|
474
852
|
assert.calledOnce(fakeMediaRequestManagers.video.commit);
|
|
853
|
+
assert.calledOnce(screenShareVideoStopStub);
|
|
854
|
+
assert.calledOnce(fakeMediaRequestManagers.screenShareVideo.commit);
|
|
475
855
|
});
|
|
476
856
|
|
|
477
857
|
it('can be called multiple times', async () => {
|
|
@@ -482,6 +862,41 @@ describe('RemoteMediaManager', () => {
|
|
|
482
862
|
remoteMediaManager.stop();
|
|
483
863
|
});
|
|
484
864
|
});
|
|
865
|
+
|
|
866
|
+
describe('setPreferLiveVideo', () => {
|
|
867
|
+
|
|
868
|
+
it('sets preferLiveVideo', async () => {
|
|
869
|
+
const config = cloneDeep(DefaultTestConfiguration);
|
|
870
|
+
let stubs = [];
|
|
871
|
+
|
|
872
|
+
config.video.initialLayoutId = 'OnePlusFive';
|
|
873
|
+
|
|
874
|
+
remoteMediaManager = new RemoteMediaManager(
|
|
875
|
+
fakeReceiveSlotManager,
|
|
876
|
+
fakeMediaRequestManagers,
|
|
877
|
+
config
|
|
878
|
+
);
|
|
879
|
+
|
|
880
|
+
remoteMediaManager.on(Event.VideoLayoutChanged, (layoutInfo: VideoLayoutChangedEventData) => {
|
|
881
|
+
Object.values(layoutInfo.activeSpeakerVideoPanes).forEach((group) => stubs.push(sinon.stub(group, 'setPreferLiveVideo')));
|
|
882
|
+
});
|
|
883
|
+
|
|
884
|
+
await remoteMediaManager.start();
|
|
885
|
+
resetHistory();
|
|
886
|
+
assert(stubs.length > 0);
|
|
887
|
+
await remoteMediaManager.setPreferLiveVideo(true);
|
|
888
|
+
|
|
889
|
+
|
|
890
|
+
stubs.forEach((stub) => {
|
|
891
|
+
assert.calledWith(stub, true, false)
|
|
892
|
+
});
|
|
893
|
+
|
|
894
|
+
expect(config.video.preferLiveVideo).to.equal(true);
|
|
895
|
+
|
|
896
|
+
assert.calledOnce(fakeMediaRequestManagers.video.commit);
|
|
897
|
+
});
|
|
898
|
+
});
|
|
899
|
+
|
|
485
900
|
describe('setLayout', () => {
|
|
486
901
|
it('rejects if called with invalid layoutId', async () => {
|
|
487
902
|
await assert.isRejected(remoteMediaManager.setLayout('invalid value'));
|
|
@@ -511,9 +926,61 @@ describe('RemoteMediaManager', () => {
|
|
|
511
926
|
await remoteMediaManager.setLayout('Stage');
|
|
512
927
|
|
|
513
928
|
assert.callCount(fakeReceiveSlotManager.allocateSlot, 9);
|
|
514
|
-
assert.alwaysCalledWith(fakeReceiveSlotManager.allocateSlot,
|
|
929
|
+
assert.alwaysCalledWith(fakeReceiveSlotManager.allocateSlot, MediaType.VideoMain);
|
|
930
|
+
});
|
|
931
|
+
|
|
932
|
+
it('logs layout changes - receiver selected', async () => {
|
|
933
|
+
const config = cloneDeep(DefaultTestConfiguration);
|
|
934
|
+
|
|
935
|
+
remoteMediaManager = new RemoteMediaManager(
|
|
936
|
+
fakeReceiveSlotManager,
|
|
937
|
+
fakeMediaRequestManagers,
|
|
938
|
+
config
|
|
939
|
+
);
|
|
940
|
+
|
|
941
|
+
await remoteMediaManager.start();
|
|
942
|
+
|
|
943
|
+
resetHistory();
|
|
944
|
+
|
|
945
|
+
await remoteMediaManager.setLayout('Stage');
|
|
946
|
+
|
|
947
|
+
assert.calledWith(
|
|
948
|
+
logger.log,
|
|
949
|
+
'RemoteMediaManager#setLayout --> new layout selected: Stage'
|
|
950
|
+
);
|
|
951
|
+
assert.calledWith(
|
|
952
|
+
logger.log,
|
|
953
|
+
'RemoteMediaManager#logMainVideoReceiveSlots --> MAIN VIDEO receive slots: unused=0, activeSpeaker=6, receiverSelected=4\ngroup: thumbnails\nfake video slot, fake video slot, fake video slot, fake video slot, fake video slot, fake video slot\nreceiverSelected:\n stage-1: fake video slot\n stage-2: fake video slot\n stage-3: fake video slot\n stage-4: fake video slot\n'
|
|
954
|
+
);
|
|
955
|
+
});
|
|
956
|
+
|
|
957
|
+
it('logs layout changes - active speaker', async () => {
|
|
958
|
+
const config = cloneDeep(DefaultTestConfiguration);
|
|
959
|
+
config.video.initialLayoutId = 'OnePlusFive'
|
|
960
|
+
|
|
961
|
+
remoteMediaManager = new RemoteMediaManager(
|
|
962
|
+
fakeReceiveSlotManager,
|
|
963
|
+
fakeMediaRequestManagers,
|
|
964
|
+
config
|
|
965
|
+
);
|
|
966
|
+
|
|
967
|
+
await remoteMediaManager.start();
|
|
968
|
+
|
|
969
|
+
resetHistory();
|
|
970
|
+
|
|
971
|
+
await remoteMediaManager.setLayout('AllEqual');
|
|
972
|
+
|
|
973
|
+
assert.calledWith(
|
|
974
|
+
logger.log,
|
|
975
|
+
'RemoteMediaManager#setLayout --> new layout selected: AllEqual'
|
|
976
|
+
);
|
|
977
|
+
assert.calledWith(
|
|
978
|
+
logger.log,
|
|
979
|
+
'RemoteMediaManager#logMainVideoReceiveSlots --> MAIN VIDEO receive slots: unused=0, activeSpeaker=9, receiverSelected=0\ngroup: main\nfake video slot, fake video slot, fake video slot, fake video slot, fake video slot, fake video slot, fake video slot, fake video slot, fake video slot\nreceiverSelected:\n'
|
|
980
|
+
);
|
|
515
981
|
});
|
|
516
982
|
|
|
983
|
+
|
|
517
984
|
it('releases slots when switching to layout that requires less active speaker slots', async () => {
|
|
518
985
|
// start with "AllEqual" layout that needs just 9 video slots
|
|
519
986
|
const config = cloneDeep(DefaultTestConfiguration);
|
|
@@ -538,8 +1005,291 @@ describe('RemoteMediaManager', () => {
|
|
|
538
1005
|
fakeReceiveSlotManager.releaseSlot.getCalls().forEach((call) => {
|
|
539
1006
|
const slot = call.args[0];
|
|
540
1007
|
|
|
541
|
-
assert.strictEqual(slot.mediaType,
|
|
1008
|
+
assert.strictEqual(slot.mediaType, MediaType.VideoMain);
|
|
1009
|
+
});
|
|
1010
|
+
});
|
|
1011
|
+
|
|
1012
|
+
it('releases slots and reallocates slots when switching to layouts in correct order', async () => {
|
|
1013
|
+
|
|
1014
|
+
const config = cloneDeep(DefaultTestConfiguration);
|
|
1015
|
+
let count = 0;
|
|
1016
|
+
|
|
1017
|
+
fakeReceiveSlotManager.allocateSlot = sinon.stub().callsFake((mediaType) => {
|
|
1018
|
+
switch (mediaType) {
|
|
1019
|
+
case MediaType.AudioMain:
|
|
1020
|
+
return Promise.resolve(fakeAudioSlot);
|
|
1021
|
+
case MediaType.VideoMain:
|
|
1022
|
+
return Promise.resolve(new FakeSlot(MediaType.VideoMain, `fake video ${count++}`));
|
|
1023
|
+
case MediaType.AudioSlides:
|
|
1024
|
+
return Promise.resolve(fakeScreenShareAudioSlot);
|
|
1025
|
+
case MediaType.VideoSlides:
|
|
1026
|
+
return Promise.resolve(fakeScreenShareVideoSlot);
|
|
1027
|
+
}
|
|
1028
|
+
throw new Error(`invalid mediaType: ${mediaType}`);
|
|
1029
|
+
})
|
|
1030
|
+
|
|
1031
|
+
remoteMediaManager = new RemoteMediaManager(
|
|
1032
|
+
fakeReceiveSlotManager,
|
|
1033
|
+
fakeMediaRequestManagers,
|
|
1034
|
+
config
|
|
1035
|
+
);
|
|
1036
|
+
|
|
1037
|
+
await remoteMediaManager.start();
|
|
1038
|
+
|
|
1039
|
+
resetHistory();
|
|
1040
|
+
|
|
1041
|
+
assert.deepEqual(remoteMediaManager.slots.video.activeSpeaker.map((slot: any) => slot.id), [
|
|
1042
|
+
"fake video 0",
|
|
1043
|
+
"fake video 1",
|
|
1044
|
+
"fake video 2",
|
|
1045
|
+
"fake video 3",
|
|
1046
|
+
"fake video 4",
|
|
1047
|
+
"fake video 5",
|
|
1048
|
+
"fake video 6",
|
|
1049
|
+
"fake video 7",
|
|
1050
|
+
"fake video 8",
|
|
1051
|
+
]);
|
|
1052
|
+
|
|
1053
|
+
assert.deepEqual(remoteMediaManager.receiveSlotAllocations.activeSpeaker["main"].slots.map((slot: any) => slot.id), [
|
|
1054
|
+
"fake video 0",
|
|
1055
|
+
"fake video 1",
|
|
1056
|
+
"fake video 2",
|
|
1057
|
+
"fake video 3",
|
|
1058
|
+
"fake video 4",
|
|
1059
|
+
"fake video 5",
|
|
1060
|
+
"fake video 6",
|
|
1061
|
+
"fake video 7",
|
|
1062
|
+
"fake video 8",
|
|
1063
|
+
])
|
|
1064
|
+
|
|
1065
|
+
// switch to "OnePlusFive" layout that requires 3 less video slots (6)
|
|
1066
|
+
await remoteMediaManager.setLayout('OnePlusFive');
|
|
1067
|
+
|
|
1068
|
+
assert.deepEqual(remoteMediaManager.slots.video.unused, []);
|
|
1069
|
+
|
|
1070
|
+
assert.deepEqual(remoteMediaManager.slots.video.activeSpeaker.map((slot: any) => slot.id), [
|
|
1071
|
+
"fake video 0",
|
|
1072
|
+
"fake video 1",
|
|
1073
|
+
"fake video 2",
|
|
1074
|
+
"fake video 3",
|
|
1075
|
+
"fake video 4",
|
|
1076
|
+
"fake video 5"
|
|
1077
|
+
]);
|
|
1078
|
+
|
|
1079
|
+
// we're checking that the slots are in the same order as in the previous layout
|
|
1080
|
+
// first one goes into main
|
|
1081
|
+
assert.deepEqual(remoteMediaManager.receiveSlotAllocations.activeSpeaker["mainBigOne"].slots.map((slot: any) => slot.id), [
|
|
1082
|
+
"fake video 0",
|
|
1083
|
+
])
|
|
1084
|
+
// and rest go in the pips
|
|
1085
|
+
assert.deepEqual(remoteMediaManager.receiveSlotAllocations.activeSpeaker["secondarySetOfSmallPanes"].slots.map((slot: any) => slot.id), [
|
|
1086
|
+
"fake video 1",
|
|
1087
|
+
"fake video 2",
|
|
1088
|
+
"fake video 3",
|
|
1089
|
+
"fake video 4",
|
|
1090
|
+
"fake video 5"
|
|
1091
|
+
])
|
|
1092
|
+
|
|
1093
|
+
// verify that 3 main video slots were released
|
|
1094
|
+
assert.callCount(fakeReceiveSlotManager.releaseSlot, 3);
|
|
1095
|
+
fakeReceiveSlotManager.releaseSlot.getCalls().forEach((call) => {
|
|
1096
|
+
const slot = call.args[0];
|
|
1097
|
+
|
|
1098
|
+
assert.strictEqual(slot.mediaType, MediaType.VideoMain);
|
|
1099
|
+
});
|
|
1100
|
+
|
|
1101
|
+
await remoteMediaManager.setLayout('AllEqual');
|
|
1102
|
+
|
|
1103
|
+
assert.deepEqual(remoteMediaManager.slots.video.unused, []);
|
|
1104
|
+
|
|
1105
|
+
// checking that slots are in the same order as in previous layout + 3 new ones
|
|
1106
|
+
assert.deepEqual(remoteMediaManager.slots.video.activeSpeaker.map((slot: any) => slot.id), [
|
|
1107
|
+
"fake video 0",
|
|
1108
|
+
"fake video 1",
|
|
1109
|
+
"fake video 2",
|
|
1110
|
+
"fake video 3",
|
|
1111
|
+
"fake video 4",
|
|
1112
|
+
"fake video 5",
|
|
1113
|
+
"fake video 10",
|
|
1114
|
+
"fake video 11",
|
|
1115
|
+
"fake video 12",
|
|
1116
|
+
]);
|
|
1117
|
+
|
|
1118
|
+
assert.deepEqual(remoteMediaManager.receiveSlotAllocations.activeSpeaker["main"].slots.map((slot: any) => slot.id), [
|
|
1119
|
+
"fake video 0",
|
|
1120
|
+
"fake video 1",
|
|
1121
|
+
"fake video 2",
|
|
1122
|
+
"fake video 3",
|
|
1123
|
+
"fake video 4",
|
|
1124
|
+
"fake video 5",
|
|
1125
|
+
"fake video 10",
|
|
1126
|
+
"fake video 11",
|
|
1127
|
+
"fake video 12"
|
|
1128
|
+
])
|
|
1129
|
+
|
|
1130
|
+
// verify that 3 main video slots were allocated
|
|
1131
|
+
assert.callCount(fakeReceiveSlotManager.allocateSlot, 3);
|
|
1132
|
+
fakeReceiveSlotManager.allocateSlot.getCalls().forEach((call) => {
|
|
1133
|
+
const mediaType = call.args[0];
|
|
1134
|
+
|
|
1135
|
+
assert.strictEqual(mediaType, MediaType.VideoMain);
|
|
1136
|
+
});
|
|
1137
|
+
});
|
|
1138
|
+
|
|
1139
|
+
it('stops all current video remoteMedia instances when switching to new layout', async () => {
|
|
1140
|
+
const audioStopStubs = [];
|
|
1141
|
+
const videoStopStubs = [];
|
|
1142
|
+
|
|
1143
|
+
const config = cloneDeep(DefaultTestConfiguration);
|
|
1144
|
+
|
|
1145
|
+
// start with the stage layout because it has both active speaker and receiver selected panes
|
|
1146
|
+
config.video.initialLayoutId = 'Stage';
|
|
1147
|
+
|
|
1148
|
+
remoteMediaManager = new RemoteMediaManager(
|
|
1149
|
+
fakeReceiveSlotManager,
|
|
1150
|
+
fakeMediaRequestManagers,
|
|
1151
|
+
config
|
|
1152
|
+
);
|
|
1153
|
+
|
|
1154
|
+
// mock all stop() methods for all remote audio objects we get with AudioCreated event
|
|
1155
|
+
remoteMediaManager.on(Event.AudioCreated, (audio: RemoteMediaGroup) => {
|
|
1156
|
+
audio
|
|
1157
|
+
.getRemoteMedia()
|
|
1158
|
+
.forEach((remoteAudio) => audioStopStubs.push(sinon.stub(remoteAudio, 'stop')));
|
|
1159
|
+
});
|
|
1160
|
+
|
|
1161
|
+
// mock all stop() methods for all remote video objects we get with VideoLayoutChanged event
|
|
1162
|
+
remoteMediaManager.on(Event.VideoLayoutChanged, (layoutInfo: VideoLayoutChangedEventData) => {
|
|
1163
|
+
Object.values(layoutInfo.activeSpeakerVideoPanes).forEach((group) =>
|
|
1164
|
+
group
|
|
1165
|
+
.getRemoteMedia()
|
|
1166
|
+
.forEach((remoteMedia) => videoStopStubs.push(sinon.stub(remoteMedia, 'stop')))
|
|
1167
|
+
);
|
|
1168
|
+
|
|
1169
|
+
Object.values(layoutInfo.memberVideoPanes).forEach((pane) => {
|
|
1170
|
+
videoStopStubs.push(sinon.stub(pane, 'stop'));
|
|
1171
|
+
});
|
|
1172
|
+
});
|
|
1173
|
+
|
|
1174
|
+
await remoteMediaManager.start();
|
|
1175
|
+
|
|
1176
|
+
// sanity check that we've got all our stop() mocks setup correctly
|
|
1177
|
+
assert.strictEqual(audioStopStubs.length, 3);
|
|
1178
|
+
assert.strictEqual(videoStopStubs.length, 10); // 10 = 6 thumbnail panes + 4 stage panes
|
|
1179
|
+
|
|
1180
|
+
// next, we'll change the layout, we don't care about the new video panes from the new layout, so unregister the event listeners
|
|
1181
|
+
remoteMediaManager.removeAllListeners();
|
|
1182
|
+
|
|
1183
|
+
await remoteMediaManager.setLayout('AllEqual');
|
|
1184
|
+
|
|
1185
|
+
// check that NONE of the audio RemoteMedia instances were stopped
|
|
1186
|
+
audioStopStubs.forEach((audioStopStub) => {
|
|
1187
|
+
assert.notCalled(audioStopStub);
|
|
1188
|
+
});
|
|
1189
|
+
|
|
1190
|
+
// check that ALL of the video RemoteMedia instances were stopped
|
|
1191
|
+
videoStopStubs.forEach((videoStopStub) => {
|
|
1192
|
+
assert.calledOnce(videoStopStub);
|
|
1193
|
+
assert.calledWith(videoStopStub, false);
|
|
1194
|
+
});
|
|
1195
|
+
});
|
|
1196
|
+
|
|
1197
|
+
it('emits Event.VideoLayoutChanged with correct data', async () => {
|
|
1198
|
+
// setup the initial layout to be empty and a testLayout that has screen share, active speaker groups and member video panes
|
|
1199
|
+
const config: Configuration = {
|
|
1200
|
+
audio: {
|
|
1201
|
+
numOfActiveSpeakerStreams: 0,
|
|
1202
|
+
numOfScreenShareStreams: 0,
|
|
1203
|
+
},
|
|
1204
|
+
video: {
|
|
1205
|
+
preferLiveVideo: true,
|
|
1206
|
+
initialLayoutId: 'empty',
|
|
1207
|
+
layouts: {
|
|
1208
|
+
empty: {},
|
|
1209
|
+
testLayout: {
|
|
1210
|
+
screenShareVideo: {size: 'very small'},
|
|
1211
|
+
activeSpeakerVideoPaneGroups: [
|
|
1212
|
+
{
|
|
1213
|
+
id: 'big',
|
|
1214
|
+
numPanes: 10,
|
|
1215
|
+
priority: 255,
|
|
1216
|
+
size: 'large',
|
|
1217
|
+
},
|
|
1218
|
+
{
|
|
1219
|
+
id: 'small',
|
|
1220
|
+
numPanes: 3,
|
|
1221
|
+
priority: 254,
|
|
1222
|
+
size: 'medium',
|
|
1223
|
+
},
|
|
1224
|
+
],
|
|
1225
|
+
memberVideoPanes: [
|
|
1226
|
+
{id: 'pane 1', size: 'best', csi: 555},
|
|
1227
|
+
{id: 'pane 2', size: 'best', csi: undefined},
|
|
1228
|
+
],
|
|
1229
|
+
},
|
|
1230
|
+
},
|
|
1231
|
+
},
|
|
1232
|
+
};
|
|
1233
|
+
|
|
1234
|
+
remoteMediaManager = new RemoteMediaManager(
|
|
1235
|
+
fakeReceiveSlotManager,
|
|
1236
|
+
fakeMediaRequestManagers,
|
|
1237
|
+
config
|
|
1238
|
+
);
|
|
1239
|
+
|
|
1240
|
+
await remoteMediaManager.start();
|
|
1241
|
+
|
|
1242
|
+
resetHistory();
|
|
1243
|
+
|
|
1244
|
+
let receivedLayoutInfo: VideoLayoutChangedEventData | null = null;
|
|
1245
|
+
|
|
1246
|
+
remoteMediaManager.on(Event.VideoLayoutChanged, (layoutInfo) => {
|
|
1247
|
+
receivedLayoutInfo = layoutInfo;
|
|
542
1248
|
});
|
|
1249
|
+
|
|
1250
|
+
// switch to the test layout
|
|
1251
|
+
await remoteMediaManager.setLayout('testLayout');
|
|
1252
|
+
|
|
1253
|
+
assert.isNotNull(receivedLayoutInfo);
|
|
1254
|
+
|
|
1255
|
+
if (receivedLayoutInfo) {
|
|
1256
|
+
assert.strictEqual(receivedLayoutInfo.layoutId, 'testLayout');
|
|
1257
|
+
|
|
1258
|
+
// check screen share video
|
|
1259
|
+
assert.isTrue(!!receivedLayoutInfo.screenShareVideo);
|
|
1260
|
+
assert.strictEqual(receivedLayoutInfo.screenShareVideo.mediaType, MediaType.VideoSlides);
|
|
1261
|
+
|
|
1262
|
+
// check member videos
|
|
1263
|
+
assert.strictEqual(Object.keys(receivedLayoutInfo.memberVideoPanes).length, 2);
|
|
1264
|
+
Object.values(receivedLayoutInfo.memberVideoPanes).forEach((remoteMedia) =>
|
|
1265
|
+
assert.strictEqual(remoteMedia.mediaType, MediaType.VideoMain)
|
|
1266
|
+
);
|
|
1267
|
+
|
|
1268
|
+
// check the 2 active speaker groups
|
|
1269
|
+
assert.strictEqual(Object.keys(receivedLayoutInfo.activeSpeakerVideoPanes).length, 2);
|
|
1270
|
+
|
|
1271
|
+
// "big" group
|
|
1272
|
+
assert.strictEqual(
|
|
1273
|
+
receivedLayoutInfo.activeSpeakerVideoPanes.big.getRemoteMedia().length,
|
|
1274
|
+
10
|
|
1275
|
+
);
|
|
1276
|
+
receivedLayoutInfo.activeSpeakerVideoPanes.big
|
|
1277
|
+
.getRemoteMedia()
|
|
1278
|
+
.forEach((remoteMedia) =>
|
|
1279
|
+
assert.strictEqual(remoteMedia.mediaType, MediaType.VideoMain)
|
|
1280
|
+
);
|
|
1281
|
+
|
|
1282
|
+
// "small" group
|
|
1283
|
+
assert.strictEqual(
|
|
1284
|
+
receivedLayoutInfo.activeSpeakerVideoPanes.small.getRemoteMedia().length,
|
|
1285
|
+
3
|
|
1286
|
+
);
|
|
1287
|
+
receivedLayoutInfo.activeSpeakerVideoPanes.small
|
|
1288
|
+
.getRemoteMedia()
|
|
1289
|
+
.forEach((remoteMedia) =>
|
|
1290
|
+
assert.strictEqual(remoteMedia.mediaType, MediaType.VideoMain)
|
|
1291
|
+
);
|
|
1292
|
+
}
|
|
543
1293
|
});
|
|
544
1294
|
|
|
545
1295
|
describe('switching between different receiver selected layouts', () => {
|
|
@@ -562,7 +1312,7 @@ describe('RemoteMediaManager', () => {
|
|
|
562
1312
|
slotCounter += 1;
|
|
563
1313
|
const newSlotId = `fake video slot ${slotCounter}`;
|
|
564
1314
|
|
|
565
|
-
fakeSlots[newSlotId] = new FakeSlot(
|
|
1315
|
+
fakeSlots[newSlotId] = new FakeSlot(MediaType.VideoMain, newSlotId);
|
|
566
1316
|
return fakeSlots[newSlotId];
|
|
567
1317
|
});
|
|
568
1318
|
|
|
@@ -594,12 +1344,12 @@ describe('RemoteMediaManager', () => {
|
|
|
594
1344
|
// This test starts with a layout that has 5 receiver selected video slots
|
|
595
1345
|
// and switches to a different layout that has fewer slots, but 2 of them match CSIs
|
|
596
1346
|
// from the initial layout. We want to verify that these 2 slots get re-used correctly.
|
|
1347
|
+
// There are no screen share or audio slots being used in this test.
|
|
1348
|
+
delete config.video.layouts.ScreenShareView;
|
|
597
1349
|
config.audio.numOfActiveSpeakerStreams = 0;
|
|
598
|
-
config.
|
|
599
|
-
config.screenShare.video = false;
|
|
1350
|
+
config.audio.numOfScreenShareStreams = 0;
|
|
600
1351
|
config.video.initialLayoutId = 'biggerLayout';
|
|
601
1352
|
config.video.layouts['biggerLayout'] = {
|
|
602
|
-
screenShareVideo: {size: null},
|
|
603
1353
|
memberVideoPanes: [
|
|
604
1354
|
{id: '1', size: 'best', csi: 100},
|
|
605
1355
|
{id: '2', size: 'best', csi: 200},
|
|
@@ -609,7 +1359,6 @@ describe('RemoteMediaManager', () => {
|
|
|
609
1359
|
],
|
|
610
1360
|
};
|
|
611
1361
|
config.video.layouts['smallerLayout'] = {
|
|
612
|
-
screenShareVideo: {size: null},
|
|
613
1362
|
memberVideoPanes: [
|
|
614
1363
|
{id: '1', size: 'medium', csi: 200}, // this csi matches pane '2' from biggerLayout
|
|
615
1364
|
{id: '2', size: 'medium', csi: 123},
|
|
@@ -659,16 +1408,15 @@ describe('RemoteMediaManager', () => {
|
|
|
659
1408
|
// This test starts with a layout that has video slot with a specific CSI
|
|
660
1409
|
// and switches to a different layout that 2 panes with that same CSI.
|
|
661
1410
|
// We want to verify that the slot gets reused, but also that a 2nd slot is allocated.
|
|
1411
|
+
// There are no screen share or audio slots being used in this test.
|
|
1412
|
+
delete config.video.layouts.ScreenShareView;
|
|
662
1413
|
config.audio.numOfActiveSpeakerStreams = 0;
|
|
663
|
-
config.
|
|
664
|
-
config.screenShare.video = false;
|
|
1414
|
+
config.audio.numOfScreenShareStreams = 0;
|
|
665
1415
|
config.video.initialLayoutId = 'initialEmptyLayout';
|
|
666
1416
|
config.video.layouts['initialEmptyLayout'] = {
|
|
667
|
-
screenShareVideo: {size: null},
|
|
668
1417
|
memberVideoPanes: [{id: '2', size: 'medium', csi: 456}],
|
|
669
1418
|
};
|
|
670
1419
|
config.video.layouts['layoutWithDuplicateCSIs'] = {
|
|
671
|
-
screenShareVideo: {size: null},
|
|
672
1420
|
memberVideoPanes: [
|
|
673
1421
|
{id: '1', size: 'medium', csi: 123},
|
|
674
1422
|
{id: '2', size: 'medium', csi: 456},
|
|
@@ -841,16 +1589,18 @@ describe('RemoteMediaManager', () => {
|
|
|
841
1589
|
});
|
|
842
1590
|
|
|
843
1591
|
it('cancels all media requests for the previous layout when switching to a new one', async () => {
|
|
1592
|
+
// setup the initial layout to have screen share, active speaker groups and member video panes
|
|
844
1593
|
const config: Configuration = {
|
|
845
1594
|
audio: {
|
|
846
1595
|
numOfActiveSpeakerStreams: 0,
|
|
1596
|
+
numOfScreenShareStreams: 0,
|
|
847
1597
|
},
|
|
848
1598
|
video: {
|
|
849
1599
|
preferLiveVideo: true,
|
|
850
1600
|
initialLayoutId: 'initial',
|
|
851
1601
|
layouts: {
|
|
852
1602
|
initial: {
|
|
853
|
-
screenShareVideo: {size:
|
|
1603
|
+
screenShareVideo: {size: 'best'},
|
|
854
1604
|
activeSpeakerVideoPaneGroups: [
|
|
855
1605
|
{
|
|
856
1606
|
id: 'big',
|
|
@@ -870,15 +1620,9 @@ describe('RemoteMediaManager', () => {
|
|
|
870
1620
|
{id: 'pane 2', size: 'best', csi: 234},
|
|
871
1621
|
],
|
|
872
1622
|
},
|
|
873
|
-
other: {
|
|
874
|
-
screenShareVideo: {size: null},
|
|
875
|
-
},
|
|
1623
|
+
other: {},
|
|
876
1624
|
},
|
|
877
1625
|
},
|
|
878
|
-
screenShare: {
|
|
879
|
-
audio: false,
|
|
880
|
-
video: false,
|
|
881
|
-
},
|
|
882
1626
|
};
|
|
883
1627
|
|
|
884
1628
|
remoteMediaManager = new RemoteMediaManager(
|
|
@@ -901,9 +1645,15 @@ describe('RemoteMediaManager', () => {
|
|
|
901
1645
|
|
|
902
1646
|
return `receiver selected request ${receiverSelectedRequestCounter}`;
|
|
903
1647
|
});
|
|
1648
|
+
// setup the mock for screen share addRequest - this one should be called just once
|
|
1649
|
+
fakeMediaRequestManagers.screenShareVideo.addRequest.callsFake(() => {
|
|
1650
|
+
return 'video screen share request id';
|
|
1651
|
+
});
|
|
904
1652
|
|
|
905
1653
|
await remoteMediaManager.start();
|
|
906
1654
|
|
|
1655
|
+
assert.calledOnce(fakeMediaRequestManagers.screenShareVideo.addRequest);
|
|
1656
|
+
|
|
907
1657
|
resetHistory();
|
|
908
1658
|
|
|
909
1659
|
// switch to "other" layout
|
|
@@ -921,11 +1671,45 @@ describe('RemoteMediaManager', () => {
|
|
|
921
1671
|
fakeMediaRequestManagers.video.cancelRequest,
|
|
922
1672
|
'receiver selected request 2'
|
|
923
1673
|
);
|
|
1674
|
+
assert.calledOnce(fakeMediaRequestManagers.screenShareVideo.cancelRequest);
|
|
1675
|
+
assert.calledWith(
|
|
1676
|
+
fakeMediaRequestManagers.screenShareVideo.cancelRequest,
|
|
1677
|
+
'video screen share request id'
|
|
1678
|
+
);
|
|
924
1679
|
|
|
925
1680
|
// 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
1681
|
assert.callCount(fakeMediaRequestManagers.video.addRequest, 0);
|
|
928
1682
|
});
|
|
1683
|
+
|
|
1684
|
+
it('sends media request for screen share if layout contains screen share', async () => {
|
|
1685
|
+
const allEqualMediaRequestId = 'fake request id';
|
|
1686
|
+
|
|
1687
|
+
fakeMediaRequestManagers.video.addRequest.returns(allEqualMediaRequestId);
|
|
1688
|
+
|
|
1689
|
+
await remoteMediaManager.start();
|
|
1690
|
+
|
|
1691
|
+
resetHistory();
|
|
1692
|
+
|
|
1693
|
+
// switch to a layout that contains a screen share video pane
|
|
1694
|
+
await remoteMediaManager.setLayout('ScreenShareView');
|
|
1695
|
+
|
|
1696
|
+
// check that a correct active speaker media request for screen share has been sent out
|
|
1697
|
+
assert.callCount(fakeMediaRequestManagers.screenShareVideo.addRequest, 1);
|
|
1698
|
+
assert.calledWith(
|
|
1699
|
+
fakeMediaRequestManagers.screenShareVideo.addRequest,
|
|
1700
|
+
sinon.match({
|
|
1701
|
+
policyInfo: sinon.match({
|
|
1702
|
+
policy: 'active-speaker',
|
|
1703
|
+
priority: 255,
|
|
1704
|
+
}),
|
|
1705
|
+
receiveSlots: [fakeScreenShareVideoSlot],
|
|
1706
|
+
codecInfo: sinon.match({
|
|
1707
|
+
codec: 'h264',
|
|
1708
|
+
maxFs: 3600,
|
|
1709
|
+
}),
|
|
1710
|
+
})
|
|
1711
|
+
);
|
|
1712
|
+
});
|
|
929
1713
|
});
|
|
930
1714
|
});
|
|
931
1715
|
|
|
@@ -1065,7 +1849,7 @@ describe('RemoteMediaManager', () => {
|
|
|
1065
1849
|
|
|
1066
1850
|
// new slot should be allocated
|
|
1067
1851
|
assert.calledOnce(fakeReceiveSlotManager.allocateSlot);
|
|
1068
|
-
assert.calledWith(fakeReceiveSlotManager.allocateSlot,
|
|
1852
|
+
assert.calledWith(fakeReceiveSlotManager.allocateSlot, MediaType.VideoMain);
|
|
1069
1853
|
|
|
1070
1854
|
// and a media request sent out
|
|
1071
1855
|
assert.calledOnce(fakeMediaRequestManagers.video.addRequest);
|
|
@@ -1094,7 +1878,7 @@ describe('RemoteMediaManager', () => {
|
|
|
1094
1878
|
|
|
1095
1879
|
// new slot should be allocated
|
|
1096
1880
|
assert.calledOnce(fakeReceiveSlotManager.allocateSlot);
|
|
1097
|
-
assert.calledWith(fakeReceiveSlotManager.allocateSlot,
|
|
1881
|
+
assert.calledWith(fakeReceiveSlotManager.allocateSlot, MediaType.VideoMain);
|
|
1098
1882
|
|
|
1099
1883
|
// but no media requests sent out
|
|
1100
1884
|
assert.notCalled(fakeMediaRequestManagers.video.addRequest);
|
|
@@ -1123,7 +1907,7 @@ describe('RemoteMediaManager', () => {
|
|
|
1123
1907
|
await remoteMediaManager.start();
|
|
1124
1908
|
await remoteMediaManager.setLayout('Stage');
|
|
1125
1909
|
|
|
1126
|
-
const fakeNewSlot = new FakeSlot(
|
|
1910
|
+
const fakeNewSlot = new FakeSlot(MediaType.VideoMain, 'fake video slot');
|
|
1127
1911
|
const fakeRequestId = 'fake request id';
|
|
1128
1912
|
|
|
1129
1913
|
fakeReceiveSlotManager.allocateSlot.resolves(fakeNewSlot);
|
|
@@ -1147,6 +1931,94 @@ describe('RemoteMediaManager', () => {
|
|
|
1147
1931
|
});
|
|
1148
1932
|
});
|
|
1149
1933
|
|
|
1934
|
+
describe('setActiveSpeakerCsis', () => {
|
|
1935
|
+
it('calls setActiveSpeakerCsis on the correct remote media group', async () => {
|
|
1936
|
+
let currentLayoutInfo: VideoLayoutChangedEventData | null = null;
|
|
1937
|
+
let setCsisStub;
|
|
1938
|
+
|
|
1939
|
+
remoteMediaManager.on(Event.VideoLayoutChanged, (layoutInfo: VideoLayoutChangedEventData) => {
|
|
1940
|
+
currentLayoutInfo = layoutInfo;
|
|
1941
|
+
setCsisStub = sinon.stub(layoutInfo.activeSpeakerVideoPanes.main, 'setActiveSpeakerCsis');
|
|
1942
|
+
});
|
|
1943
|
+
|
|
1944
|
+
await remoteMediaManager.start();
|
|
1945
|
+
resetHistory();
|
|
1946
|
+
|
|
1947
|
+
assert.isNotNull(currentLayoutInfo);
|
|
1948
|
+
|
|
1949
|
+
if (currentLayoutInfo) {
|
|
1950
|
+
const remoteVideo = currentLayoutInfo.activeSpeakerVideoPanes.main.getRemoteMedia()[0];
|
|
1951
|
+
|
|
1952
|
+
remoteMediaManager.setActiveSpeakerCsis([{remoteMedia: remoteVideo}]);
|
|
1953
|
+
|
|
1954
|
+
assert.calledOnce(setCsisStub);
|
|
1955
|
+
assert.calledWith(setCsisStub, [{remoteMedia: remoteVideo}], false);
|
|
1956
|
+
assert.calledOnce(fakeMediaRequestManagers.video.commit);
|
|
1957
|
+
}
|
|
1958
|
+
});
|
|
1959
|
+
|
|
1960
|
+
it('does not call setActiveSpeakerCsis on the incorrect media group', async () => {
|
|
1961
|
+
let currentLayoutInfo: VideoLayoutChangedEventData | null = null;
|
|
1962
|
+
let setCsisStub;
|
|
1963
|
+
|
|
1964
|
+
remoteMediaManager.on(Event.VideoLayoutChanged, (layoutInfo: VideoLayoutChangedEventData) => {
|
|
1965
|
+
currentLayoutInfo = layoutInfo;
|
|
1966
|
+
setCsisStub = sinon.stub(layoutInfo.activeSpeakerVideoPanes.main, 'setActiveSpeakerCsis');
|
|
1967
|
+
});
|
|
1968
|
+
|
|
1969
|
+
await remoteMediaManager.start();
|
|
1970
|
+
resetHistory();
|
|
1971
|
+
|
|
1972
|
+
assert.isNotNull(currentLayoutInfo);
|
|
1973
|
+
|
|
1974
|
+
if (currentLayoutInfo) {
|
|
1975
|
+
remoteMediaManager.setActiveSpeakerCsis([{remoteMedia: {}}]);
|
|
1976
|
+
|
|
1977
|
+
assert.notCalled(setCsisStub);
|
|
1978
|
+
assert.calledOnce(fakeMediaRequestManagers.video.commit);
|
|
1979
|
+
}
|
|
1980
|
+
});
|
|
1981
|
+
|
|
1982
|
+
it('checking when there is more than one group', async () => {
|
|
1983
|
+
let currentLayoutInfo: VideoLayoutChangedEventData | null = null;
|
|
1984
|
+
const config = cloneDeep(DefaultTestConfiguration);
|
|
1985
|
+
let stubs = [];
|
|
1986
|
+
|
|
1987
|
+
config.video.initialLayoutId = 'OnePlusFive';
|
|
1988
|
+
|
|
1989
|
+
remoteMediaManager = new RemoteMediaManager(
|
|
1990
|
+
fakeReceiveSlotManager,
|
|
1991
|
+
fakeMediaRequestManagers,
|
|
1992
|
+
config
|
|
1993
|
+
);
|
|
1994
|
+
|
|
1995
|
+
remoteMediaManager.on(Event.VideoLayoutChanged, (layoutInfo: VideoLayoutChangedEventData) => {
|
|
1996
|
+
currentLayoutInfo = layoutInfo;
|
|
1997
|
+
Object.values(layoutInfo.activeSpeakerVideoPanes).forEach((group) => stubs.push(sinon.stub(group, 'setActiveSpeakerCsis')));
|
|
1998
|
+
});
|
|
1999
|
+
|
|
2000
|
+
await remoteMediaManager.start();
|
|
2001
|
+
resetHistory();
|
|
2002
|
+
|
|
2003
|
+
assert.isNotNull(currentLayoutInfo);
|
|
2004
|
+
|
|
2005
|
+
if (currentLayoutInfo) {
|
|
2006
|
+
|
|
2007
|
+
const remoteMedia1 = currentLayoutInfo.activeSpeakerVideoPanes.mainBigOne.getRemoteMedia()[0];
|
|
2008
|
+
const remoteMedia2 = currentLayoutInfo.activeSpeakerVideoPanes.secondarySetOfSmallPanes.getRemoteMedia()[0];
|
|
2009
|
+
|
|
2010
|
+
const remoteMediaCsis = [{remoteMedia: remoteMedia1}, {remoteMedia: remoteMedia2}];
|
|
2011
|
+
|
|
2012
|
+
remoteMediaManager.setActiveSpeakerCsis([{remoteMedia: remoteMedia1}, {remoteMedia: remoteMedia2}]);
|
|
2013
|
+
|
|
2014
|
+
stubs.forEach((stub, index) => {
|
|
2015
|
+
assert.calledWith(stub, [remoteMediaCsis[index]], false)
|
|
2016
|
+
});
|
|
2017
|
+
assert.calledOnce(fakeMediaRequestManagers.video.commit);
|
|
2018
|
+
}
|
|
2019
|
+
});
|
|
2020
|
+
});
|
|
2021
|
+
|
|
1150
2022
|
describe('pinActiveSpeakerVideoPane() and isPinned()', () => {
|
|
1151
2023
|
it('throws if called on a pane not belonging to an active speaker group', async () => {
|
|
1152
2024
|
let currentLayoutInfo: VideoLayoutChangedEventData | null = null;
|