@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.
Files changed (365) hide show
  1. package/UPGRADING.md +9 -9
  2. package/browsers.js +19 -24
  3. package/dist/breakouts/breakout.js +116 -0
  4. package/dist/breakouts/breakout.js.map +1 -0
  5. package/dist/breakouts/collection.js +23 -0
  6. package/dist/breakouts/collection.js.map +1 -0
  7. package/dist/breakouts/index.js +226 -0
  8. package/dist/breakouts/index.js.map +1 -0
  9. package/dist/common/browser-detection.js +1 -20
  10. package/dist/common/browser-detection.js.map +1 -1
  11. package/dist/common/collection.js +5 -20
  12. package/dist/common/collection.js.map +1 -1
  13. package/dist/common/config.js +0 -7
  14. package/dist/common/config.js.map +1 -1
  15. package/dist/common/errors/captcha-error.js +10 -24
  16. package/dist/common/errors/captcha-error.js.map +1 -1
  17. package/dist/common/errors/intent-to-join.js +11 -24
  18. package/dist/common/errors/intent-to-join.js.map +1 -1
  19. package/dist/common/errors/join-meeting.js +12 -25
  20. package/dist/common/errors/join-meeting.js.map +1 -1
  21. package/dist/common/errors/media.js +10 -24
  22. package/dist/common/errors/media.js.map +1 -1
  23. package/dist/common/errors/parameter.js +5 -33
  24. package/dist/common/errors/parameter.js.map +1 -1
  25. package/dist/common/errors/password-error.js +10 -24
  26. package/dist/common/errors/password-error.js.map +1 -1
  27. package/dist/common/errors/permission.js +9 -23
  28. package/dist/common/errors/permission.js.map +1 -1
  29. package/dist/common/errors/reconnection-in-progress.js +0 -17
  30. package/dist/common/errors/reconnection-in-progress.js.map +1 -1
  31. package/dist/common/errors/reconnection.js +10 -24
  32. package/dist/common/errors/reconnection.js.map +1 -1
  33. package/dist/common/errors/stats.js +10 -24
  34. package/dist/common/errors/stats.js.map +1 -1
  35. package/dist/common/errors/webex-errors.js +6 -41
  36. package/dist/common/errors/webex-errors.js.map +1 -1
  37. package/dist/common/errors/webex-meetings-error.js +5 -25
  38. package/dist/common/errors/webex-meetings-error.js.map +1 -1
  39. package/dist/common/events/events-scope.js +0 -22
  40. package/dist/common/events/events-scope.js.map +1 -1
  41. package/dist/common/events/events.js +0 -23
  42. package/dist/common/events/events.js.map +1 -1
  43. package/dist/common/events/trigger-proxy.js +0 -12
  44. package/dist/common/events/trigger-proxy.js.map +1 -1
  45. package/dist/common/events/util.js +0 -15
  46. package/dist/common/events/util.js.map +1 -1
  47. package/dist/common/logs/logger-config.js +0 -4
  48. package/dist/common/logs/logger-config.js.map +1 -1
  49. package/dist/common/logs/logger-proxy.js +1 -8
  50. package/dist/common/logs/logger-proxy.js.map +1 -1
  51. package/dist/common/logs/request.js +37 -60
  52. package/dist/common/logs/request.js.map +1 -1
  53. package/dist/common/queue.js +4 -14
  54. package/dist/common/queue.js.map +1 -1
  55. package/dist/config.js +6 -6
  56. package/dist/config.js.map +1 -1
  57. package/dist/constants.js +88 -46
  58. package/dist/constants.js.map +1 -1
  59. package/dist/index.js +1 -17
  60. package/dist/index.js.map +1 -1
  61. package/dist/locus-info/controlsUtils.js +12 -29
  62. package/dist/locus-info/controlsUtils.js.map +1 -1
  63. package/dist/locus-info/embeddedAppsUtils.js +3 -26
  64. package/dist/locus-info/embeddedAppsUtils.js.map +1 -1
  65. package/dist/locus-info/fullState.js +0 -15
  66. package/dist/locus-info/fullState.js.map +1 -1
  67. package/dist/locus-info/hostUtils.js +4 -12
  68. package/dist/locus-info/hostUtils.js.map +1 -1
  69. package/dist/locus-info/index.js +184 -190
  70. package/dist/locus-info/index.js.map +1 -1
  71. package/dist/locus-info/infoUtils.js +3 -37
  72. package/dist/locus-info/infoUtils.js.map +1 -1
  73. package/dist/locus-info/mediaSharesUtils.js +12 -38
  74. package/dist/locus-info/mediaSharesUtils.js.map +1 -1
  75. package/dist/locus-info/parser.js +92 -118
  76. package/dist/locus-info/parser.js.map +1 -1
  77. package/dist/locus-info/selfUtils.js +34 -91
  78. package/dist/locus-info/selfUtils.js.map +1 -1
  79. package/dist/media/index.js +67 -111
  80. package/dist/media/index.js.map +1 -1
  81. package/dist/media/properties.js +80 -114
  82. package/dist/media/properties.js.map +1 -1
  83. package/dist/media/util.js +2 -9
  84. package/dist/media/util.js.map +1 -1
  85. package/dist/mediaQualityMetrics/config.js +10 -12
  86. package/dist/mediaQualityMetrics/config.js.map +1 -1
  87. package/dist/meeting/effectsState.js +125 -190
  88. package/dist/meeting/effectsState.js.map +1 -1
  89. package/dist/meeting/in-meeting-actions.js +5 -14
  90. package/dist/meeting/in-meeting-actions.js.map +1 -1
  91. package/dist/meeting/index.js +1692 -1925
  92. package/dist/meeting/index.js.map +1 -1
  93. package/dist/meeting/muteState.js +36 -77
  94. package/dist/meeting/muteState.js.map +1 -1
  95. package/dist/meeting/request.js +224 -230
  96. package/dist/meeting/request.js.map +1 -1
  97. package/dist/meeting/request.type.js +7 -0
  98. package/dist/meeting/request.type.js.map +1 -0
  99. package/dist/meeting/state.js +21 -31
  100. package/dist/meeting/state.js.map +1 -1
  101. package/dist/meeting/util.js +43 -215
  102. package/dist/meeting/util.js.map +1 -1
  103. package/dist/meeting-info/collection.js +6 -25
  104. package/dist/meeting-info/collection.js.map +1 -1
  105. package/dist/meeting-info/index.js +14 -32
  106. package/dist/meeting-info/index.js.map +1 -1
  107. package/dist/meeting-info/meeting-info-v2.js +193 -268
  108. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  109. package/dist/meeting-info/request.js +3 -15
  110. package/dist/meeting-info/request.js.map +1 -1
  111. package/dist/meeting-info/util.js +98 -183
  112. package/dist/meeting-info/util.js.map +1 -1
  113. package/dist/meeting-info/utilv2.js +137 -228
  114. package/dist/meeting-info/utilv2.js.map +1 -1
  115. package/dist/meetings/collection.js +5 -20
  116. package/dist/meetings/collection.js.map +1 -1
  117. package/dist/meetings/index.js +490 -560
  118. package/dist/meetings/index.js.map +1 -1
  119. package/dist/meetings/request.js +24 -41
  120. package/dist/meetings/request.js.map +1 -1
  121. package/dist/meetings/util.js +99 -155
  122. package/dist/meetings/util.js.map +1 -1
  123. package/dist/member/index.js +78 -86
  124. package/dist/member/index.js.map +1 -1
  125. package/dist/member/util.js +31 -68
  126. package/dist/member/util.js.map +1 -1
  127. package/dist/members/collection.js +3 -12
  128. package/dist/members/collection.js.map +1 -1
  129. package/dist/members/index.js +93 -200
  130. package/dist/members/index.js.map +1 -1
  131. package/dist/members/request.js +16 -39
  132. package/dist/members/request.js.map +1 -1
  133. package/dist/members/util.js +9 -38
  134. package/dist/members/util.js.map +1 -1
  135. package/dist/metrics/config.js +0 -2
  136. package/dist/metrics/config.js.map +1 -1
  137. package/dist/metrics/constants.js +1 -2
  138. package/dist/metrics/constants.js.map +1 -1
  139. package/dist/metrics/index.js +55 -135
  140. package/dist/metrics/index.js.map +1 -1
  141. package/dist/multistream/mediaRequestManager.js +57 -32
  142. package/dist/multistream/mediaRequestManager.js.map +1 -1
  143. package/dist/multistream/multistreamMedia.js +15 -21
  144. package/dist/multistream/multistreamMedia.js.map +1 -1
  145. package/dist/multistream/receiveSlot.js +10 -50
  146. package/dist/multistream/receiveSlot.js.map +1 -1
  147. package/dist/multistream/receiveSlotManager.js +45 -82
  148. package/dist/multistream/receiveSlotManager.js.map +1 -1
  149. package/dist/multistream/remoteMedia.js +18 -58
  150. package/dist/multistream/remoteMedia.js.map +1 -1
  151. package/dist/multistream/remoteMediaGroup.js +6 -40
  152. package/dist/multistream/remoteMediaGroup.js.map +1 -1
  153. package/dist/multistream/remoteMediaManager.js +362 -416
  154. package/dist/multistream/remoteMediaManager.js.map +1 -1
  155. package/dist/networkQualityMonitor/index.js +36 -57
  156. package/dist/networkQualityMonitor/index.js.map +1 -1
  157. package/dist/personal-meeting-room/index.js +21 -45
  158. package/dist/personal-meeting-room/index.js.map +1 -1
  159. package/dist/personal-meeting-room/request.js +1 -31
  160. package/dist/personal-meeting-room/request.js.map +1 -1
  161. package/dist/personal-meeting-room/util.js +0 -13
  162. package/dist/personal-meeting-room/util.js.map +1 -1
  163. package/dist/reachability/index.js +138 -182
  164. package/dist/reachability/index.js.map +1 -1
  165. package/dist/reachability/request.js +3 -18
  166. package/dist/reachability/request.js.map +1 -1
  167. package/dist/reactions/constants.js +13 -0
  168. package/dist/reactions/constants.js.map +1 -0
  169. package/dist/reactions/reactions.js +109 -0
  170. package/dist/reactions/reactions.js.map +1 -0
  171. package/dist/reactions/reactions.type.js +36 -0
  172. package/dist/reactions/reactions.type.js.map +1 -0
  173. package/dist/reconnection-manager/index.js +322 -455
  174. package/dist/reconnection-manager/index.js.map +1 -1
  175. package/dist/recording-controller/enums.js +17 -0
  176. package/dist/recording-controller/enums.js.map +1 -0
  177. package/dist/recording-controller/index.js +343 -0
  178. package/dist/recording-controller/index.js.map +1 -0
  179. package/dist/recording-controller/util.js +63 -0
  180. package/dist/recording-controller/util.js.map +1 -0
  181. package/dist/roap/index.js +39 -64
  182. package/dist/roap/index.js.map +1 -1
  183. package/dist/roap/request.js +94 -113
  184. package/dist/roap/request.js.map +1 -1
  185. package/dist/roap/turnDiscovery.js +85 -94
  186. package/dist/roap/turnDiscovery.js.map +1 -1
  187. package/dist/statsAnalyzer/global.js +0 -2
  188. package/dist/statsAnalyzer/global.js.map +1 -1
  189. package/dist/statsAnalyzer/index.js +85 -175
  190. package/dist/statsAnalyzer/index.js.map +1 -1
  191. package/dist/statsAnalyzer/mqaUtil.js +72 -53
  192. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  193. package/dist/transcription/index.js +22 -47
  194. package/dist/transcription/index.js.map +1 -1
  195. package/internal-README.md +7 -6
  196. package/package.json +25 -20
  197. package/src/breakouts/README.md +190 -0
  198. package/src/breakouts/breakout.ts +110 -0
  199. package/src/breakouts/collection.ts +19 -0
  200. package/src/breakouts/index.ts +225 -0
  201. package/src/common/{browser-detection.js → browser-detection.ts} +9 -6
  202. package/src/common/collection.ts +9 -7
  203. package/src/common/{config.js → config.ts} +1 -1
  204. package/src/common/errors/{captcha-error.js → captcha-error.ts} +11 -7
  205. package/src/common/errors/{intent-to-join.js → intent-to-join.ts} +12 -7
  206. package/src/common/errors/{join-meeting.js → join-meeting.ts} +17 -8
  207. package/src/common/errors/{media.js → media.ts} +11 -7
  208. package/src/common/errors/parameter.ts +11 -7
  209. package/src/common/errors/{password-error.js → password-error.ts} +11 -7
  210. package/src/common/errors/{permission.js → permission.ts} +10 -6
  211. package/src/common/errors/{reconnection-in-progress.js → reconnection-in-progress.ts} +0 -0
  212. package/src/common/errors/{reconnection.js → reconnection.ts} +11 -7
  213. package/src/common/errors/{stats.js → stats.ts} +11 -7
  214. package/src/common/errors/{webex-errors.js → webex-errors.ts} +8 -7
  215. package/src/common/errors/{webex-meetings-error.js → webex-meetings-error.ts} +4 -2
  216. package/src/common/events/{events-scope.js → events-scope.ts} +6 -2
  217. package/src/common/events/{events.js → events.ts} +5 -1
  218. package/src/common/events/{trigger-proxy.js → trigger-proxy.ts} +9 -5
  219. package/src/common/events/{util.js → util.ts} +2 -3
  220. package/src/common/logs/{logger-config.js → logger-config.ts} +1 -2
  221. package/src/common/logs/logger-proxy.ts +44 -0
  222. package/src/common/logs/{request.js → request.ts} +22 -9
  223. package/src/common/queue.ts +1 -2
  224. package/src/{config.js → config.ts} +17 -12
  225. package/src/constants.ts +40 -1
  226. package/src/index.js +1 -1
  227. package/src/locus-info/controlsUtils.ts +114 -0
  228. package/src/locus-info/{embeddedAppsUtils.js → embeddedAppsUtils.ts} +5 -6
  229. package/src/locus-info/{fullState.js → fullState.ts} +16 -12
  230. package/src/locus-info/{hostUtils.js → hostUtils.ts} +9 -8
  231. package/src/locus-info/{index.js → index.ts} +148 -64
  232. package/src/locus-info/{infoUtils.js → infoUtils.ts} +19 -8
  233. package/src/locus-info/{mediaSharesUtils.js → mediaSharesUtils.ts} +17 -17
  234. package/src/locus-info/{parser.js → parser.ts} +67 -79
  235. package/src/locus-info/{selfUtils.js → selfUtils.ts} +123 -68
  236. package/src/media/{index.js → index.ts} +181 -131
  237. package/src/media/{properties.js → properties.ts} +47 -28
  238. package/src/media/{util.js → util.ts} +2 -2
  239. package/src/mediaQualityMetrics/{config.js → config.ts} +46 -46
  240. package/src/meeting/{effectsState.js → effectsState.ts} +47 -41
  241. package/src/meeting/in-meeting-actions.ts +15 -3
  242. package/src/meeting/{index.js → index.ts} +2263 -1427
  243. package/src/meeting/{muteState.js → muteState.ts} +78 -42
  244. package/src/meeting/{request.js → request.ts} +292 -142
  245. package/src/meeting/request.type.ts +13 -0
  246. package/src/meeting/{state.js → state.ts} +50 -35
  247. package/src/meeting/{util.js → util.ts} +112 -115
  248. package/src/meeting-info/{collection.js → collection.ts} +6 -2
  249. package/src/meeting-info/{index.js → index.ts} +42 -36
  250. package/src/meeting-info/meeting-info-v2.ts +273 -0
  251. package/src/meeting-info/{request.js → request.ts} +14 -4
  252. package/src/meeting-info/{util.js → util.ts} +60 -51
  253. package/src/meeting-info/{utilv2.js → utilv2.ts} +65 -58
  254. package/src/meetings/{collection.js → collection.ts} +6 -3
  255. package/src/meetings/index.ts +1159 -0
  256. package/src/meetings/{request.js → request.ts} +32 -25
  257. package/src/meetings/{util.js → util.ts} +34 -32
  258. package/src/member/{index.js → index.ts} +102 -56
  259. package/src/member/{util.js → util.ts} +52 -25
  260. package/src/members/{collection.js → collection.ts} +2 -2
  261. package/src/members/{index.js → index.ts} +219 -142
  262. package/src/members/{request.js → request.ts} +60 -16
  263. package/src/members/{util.js → util.ts} +50 -48
  264. package/src/metrics/{config.js → config.ts} +254 -83
  265. package/src/metrics/{constants.js → constants.ts} +0 -2
  266. package/src/metrics/{index.js → index.ts} +106 -74
  267. package/src/multistream/mediaRequestManager.ts +81 -15
  268. package/src/multistream/multistreamMedia.ts +5 -0
  269. package/src/multistream/receiveSlot.ts +18 -12
  270. package/src/multistream/receiveSlotManager.ts +23 -21
  271. package/src/multistream/remoteMedia.ts +15 -5
  272. package/src/multistream/remoteMediaGroup.ts +4 -3
  273. package/src/multistream/remoteMediaManager.ts +153 -37
  274. package/src/networkQualityMonitor/{index.js → index.ts} +37 -25
  275. package/src/personal-meeting-room/{index.js → index.ts} +28 -19
  276. package/src/personal-meeting-room/{request.js → request.ts} +13 -4
  277. package/src/personal-meeting-room/{util.js → util.ts} +4 -4
  278. package/src/reachability/{index.js → index.ts} +99 -83
  279. package/src/reachability/request.ts +39 -33
  280. package/src/reactions/constants.ts +4 -0
  281. package/src/reactions/reactions.ts +104 -0
  282. package/src/reactions/reactions.type.ts +62 -0
  283. package/src/reconnection-manager/{index.js → index.ts} +195 -102
  284. package/src/recording-controller/enums.ts +8 -0
  285. package/src/recording-controller/index.ts +315 -0
  286. package/src/recording-controller/util.ts +58 -0
  287. package/src/roap/{index.js → index.ts} +73 -56
  288. package/src/roap/request.ts +157 -0
  289. package/src/roap/turnDiscovery.ts +77 -37
  290. package/src/statsAnalyzer/{global.js → global.ts} +30 -33
  291. package/src/statsAnalyzer/{index.js → index.ts} +468 -192
  292. package/src/statsAnalyzer/mqaUtil.ts +290 -0
  293. package/src/transcription/{index.js → index.ts} +46 -39
  294. package/test/integration/spec/journey.js +664 -463
  295. package/test/integration/spec/space-meeting.js +320 -206
  296. package/test/integration/spec/transcription.js +7 -8
  297. package/test/unit/spec/breakouts/breakout.ts +119 -0
  298. package/test/unit/spec/breakouts/collection.ts +15 -0
  299. package/test/unit/spec/breakouts/index.ts +293 -0
  300. package/test/unit/spec/common/browser-detection.js +9 -28
  301. package/test/unit/spec/fixture/locus.js +92 -90
  302. package/test/unit/spec/locus-info/controlsUtils.js +25 -5
  303. package/test/unit/spec/locus-info/embeddedAppsUtils.js +8 -6
  304. package/test/unit/spec/locus-info/index.js +104 -2
  305. package/test/unit/spec/locus-info/infoUtils.js +41 -32
  306. package/test/unit/spec/locus-info/lib/BasicSeqCmp.json +88 -430
  307. package/test/unit/spec/locus-info/lib/SeqCmp.json +513 -685
  308. package/test/unit/spec/locus-info/parser.js +3 -9
  309. package/test/unit/spec/locus-info/selfConstant.js +97 -103
  310. package/test/unit/spec/locus-info/selfUtils.js +105 -12
  311. package/test/unit/spec/media/index.ts +31 -47
  312. package/test/unit/spec/media/properties.ts +9 -9
  313. package/test/unit/spec/meeting/effectsState.js +39 -45
  314. package/test/unit/spec/meeting/in-meeting-actions.ts +5 -2
  315. package/test/unit/spec/meeting/index.js +2017 -742
  316. package/test/unit/spec/meeting/muteState.js +42 -33
  317. package/test/unit/spec/meeting/request.js +115 -44
  318. package/test/unit/spec/meeting/utils.js +104 -171
  319. package/test/unit/spec/meeting-info/meetinginfov2.js +100 -73
  320. package/test/unit/spec/meeting-info/request.js +7 -9
  321. package/test/unit/spec/meeting-info/util.js +11 -12
  322. package/test/unit/spec/meeting-info/utilv2.js +110 -74
  323. package/test/unit/spec/meetings/collection.js +1 -1
  324. package/test/unit/spec/meetings/index.js +439 -257
  325. package/test/unit/spec/meetings/utils.js +14 -12
  326. package/test/unit/spec/member/index.js +0 -1
  327. package/test/unit/spec/member/util.js +31 -7
  328. package/test/unit/spec/members/index.js +104 -54
  329. package/test/unit/spec/members/request.js +29 -20
  330. package/test/unit/spec/members/utils.js +8 -5
  331. package/test/unit/spec/metrics/index.js +16 -21
  332. package/test/unit/spec/multistream/mediaRequestManager.ts +316 -50
  333. package/test/unit/spec/multistream/receiveSlot.ts +6 -6
  334. package/test/unit/spec/multistream/receiveSlotManager.ts +13 -13
  335. package/test/unit/spec/multistream/remoteMedia.ts +10 -2
  336. package/test/unit/spec/multistream/remoteMediaGroup.ts +5 -5
  337. package/test/unit/spec/multistream/remoteMediaManager.ts +412 -65
  338. package/test/unit/spec/networkQualityMonitor/index.js +21 -15
  339. package/test/unit/spec/personal-meeting-room/personal-meeting-room.js +2 -7
  340. package/test/unit/spec/reachability/index.ts +58 -26
  341. package/test/unit/spec/reconnection-manager/index.js +102 -9
  342. package/test/unit/spec/recording-controller/index.js +231 -0
  343. package/test/unit/spec/recording-controller/util.js +102 -0
  344. package/test/unit/spec/roap/index.ts +2 -1
  345. package/test/unit/spec/roap/request.ts +114 -0
  346. package/test/unit/spec/roap/turnDiscovery.ts +64 -45
  347. package/test/unit/spec/stats-analyzer/index.js +27 -22
  348. package/test/utils/cmr.js +44 -42
  349. package/test/utils/testUtils.js +83 -74
  350. package/test/utils/webex-config.js +18 -18
  351. package/test/utils/webex-test-users.js +54 -50
  352. package/tsconfig.json +6 -0
  353. package/dist/media/internal-media-core-wrapper.js +0 -22
  354. package/dist/media/internal-media-core-wrapper.js.map +0 -1
  355. package/dist/peer-connection-manager/util.js +0 -124
  356. package/dist/peer-connection-manager/util.js.map +0 -1
  357. package/src/common/logs/logger-proxy.js +0 -33
  358. package/src/locus-info/controlsUtils.js +0 -102
  359. package/src/media/internal-media-core-wrapper.ts +0 -9
  360. package/src/meeting-info/meeting-info-v2.js +0 -255
  361. package/src/meetings/index.js +0 -1015
  362. package/src/peer-connection-manager/util.ts +0 -117
  363. package/src/roap/request.js +0 -127
  364. package/src/statsAnalyzer/mqaUtil.js +0 -173
  365. 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 {MediaConnection as MC} from '@webex/internal-media-core';
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: MC.MediaType;
20
+ public mediaType: MediaType;
21
21
 
22
22
  public id: string;
23
23
 
24
24
  public csi?: number;
25
25
 
26
- constructor(mediaType: MC.MediaType, id: string) {
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(MC.MediaType.AudioMain, 'fake audio slot');
119
- fakeVideoSlot = new FakeSlot(MC.MediaType.VideoMain, 'fake video slot');
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
- if (mediaType === MC.MediaType.AudioMain) {
124
- return Promise.resolve(fakeAudioSlot);
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, MC.MediaType.AudioMain);
180
- assert.calledWith(fakeReceiveSlotManager.allocateSlot, MC.MediaType.VideoMain);
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, MC.MediaType.AudioMain);
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 === MC.MediaType.AudioMain)
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, MC.MediaType.VideoMain);
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 receveiver selected videos
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 and 10 video slots (for Stage2x2With6ThumbnailsLayout)
455
- assert.callCount(fakeReceiveSlotManager.allocateSlot, 13);
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, 13);
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, MC.MediaType.VideoMain);
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, MC.MediaType.VideoMain);
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(MC.MediaType.VideoMain, newSlotId);
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.screenShare.audio = false;
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.screenShare.audio = false;
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: null},
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, MC.MediaType.VideoMain);
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, MC.MediaType.VideoMain);
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(MC.MediaType.VideoMain, 'fake video slot');
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);