@webex/plugin-meetings 3.0.0-beta.2 → 3.0.0-beta.200

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 (576) hide show
  1. package/README.md +45 -7
  2. package/UPGRADING.md +9 -9
  3. package/browsers.js +19 -24
  4. package/dist/annotation/annotation.types.js +7 -0
  5. package/dist/annotation/annotation.types.js.map +1 -0
  6. package/dist/annotation/constants.js +49 -0
  7. package/dist/annotation/constants.js.map +1 -0
  8. package/dist/annotation/index.js +342 -0
  9. package/dist/annotation/index.js.map +1 -0
  10. package/dist/breakouts/breakout.js +216 -0
  11. package/dist/breakouts/breakout.js.map +1 -0
  12. package/dist/breakouts/collection.js +23 -0
  13. package/dist/breakouts/collection.js.map +1 -0
  14. package/dist/breakouts/edit-lock-error.js +52 -0
  15. package/dist/breakouts/edit-lock-error.js.map +1 -0
  16. package/dist/breakouts/events.js +45 -0
  17. package/dist/breakouts/events.js.map +1 -0
  18. package/dist/breakouts/index.js +1048 -0
  19. package/dist/breakouts/index.js.map +1 -0
  20. package/dist/breakouts/request.js +78 -0
  21. package/dist/breakouts/request.js.map +1 -0
  22. package/dist/breakouts/utils.js +67 -0
  23. package/dist/breakouts/utils.js.map +1 -0
  24. package/dist/common/browser-detection.js +1 -20
  25. package/dist/common/browser-detection.js.map +1 -1
  26. package/dist/common/collection.js +5 -20
  27. package/dist/common/collection.js.map +1 -1
  28. package/dist/common/config.js +0 -7
  29. package/dist/common/config.js.map +1 -1
  30. package/dist/common/errors/captcha-error.js +10 -24
  31. package/dist/common/errors/captcha-error.js.map +1 -1
  32. package/dist/common/errors/intent-to-join.js +11 -24
  33. package/dist/common/errors/intent-to-join.js.map +1 -1
  34. package/dist/common/errors/join-meeting.js +12 -25
  35. package/dist/common/errors/join-meeting.js.map +1 -1
  36. package/dist/common/errors/media.js +10 -24
  37. package/dist/common/errors/media.js.map +1 -1
  38. package/dist/common/errors/parameter.js +5 -33
  39. package/dist/common/errors/parameter.js.map +1 -1
  40. package/dist/common/errors/password-error.js +10 -24
  41. package/dist/common/errors/password-error.js.map +1 -1
  42. package/dist/common/errors/permission.js +9 -23
  43. package/dist/common/errors/permission.js.map +1 -1
  44. package/dist/common/errors/reconnection-in-progress.js +0 -17
  45. package/dist/common/errors/reconnection-in-progress.js.map +1 -1
  46. package/dist/common/errors/reconnection.js +10 -24
  47. package/dist/common/errors/reconnection.js.map +1 -1
  48. package/dist/common/errors/stats.js +10 -24
  49. package/dist/common/errors/stats.js.map +1 -1
  50. package/dist/common/errors/webex-errors.js +9 -43
  51. package/dist/common/errors/webex-errors.js.map +1 -1
  52. package/dist/common/errors/webex-meetings-error.js +5 -25
  53. package/dist/common/errors/webex-meetings-error.js.map +1 -1
  54. package/dist/common/events/events-scope.js +0 -22
  55. package/dist/common/events/events-scope.js.map +1 -1
  56. package/dist/common/events/events.js +0 -23
  57. package/dist/common/events/events.js.map +1 -1
  58. package/dist/common/events/trigger-proxy.js +0 -12
  59. package/dist/common/events/trigger-proxy.js.map +1 -1
  60. package/dist/common/events/util.js +0 -15
  61. package/dist/common/events/util.js.map +1 -1
  62. package/dist/common/logs/logger-config.js +0 -4
  63. package/dist/common/logs/logger-config.js.map +1 -1
  64. package/dist/common/logs/logger-proxy.js +1 -8
  65. package/dist/common/logs/logger-proxy.js.map +1 -1
  66. package/dist/common/logs/request.js +37 -60
  67. package/dist/common/logs/request.js.map +1 -1
  68. package/dist/common/queue.js +28 -23
  69. package/dist/common/queue.js.map +1 -1
  70. package/dist/config.js +8 -13
  71. package/dist/config.js.map +1 -1
  72. package/dist/constants.js +250 -66
  73. package/dist/constants.js.map +1 -1
  74. package/dist/controls-options-manager/constants.js +14 -0
  75. package/dist/controls-options-manager/constants.js.map +1 -0
  76. package/dist/controls-options-manager/enums.js +27 -0
  77. package/dist/controls-options-manager/enums.js.map +1 -0
  78. package/dist/controls-options-manager/index.js +297 -0
  79. package/dist/controls-options-manager/index.js.map +1 -0
  80. package/dist/controls-options-manager/types.js +7 -0
  81. package/dist/controls-options-manager/types.js.map +1 -0
  82. package/dist/controls-options-manager/util.js +319 -0
  83. package/dist/controls-options-manager/util.js.map +1 -0
  84. package/dist/index.js +108 -17
  85. package/dist/index.js.map +1 -1
  86. package/dist/interpretation/collection.js +23 -0
  87. package/dist/interpretation/collection.js.map +1 -0
  88. package/dist/interpretation/index.js +366 -0
  89. package/dist/interpretation/index.js.map +1 -0
  90. package/dist/interpretation/siLanguage.js +25 -0
  91. package/dist/interpretation/siLanguage.js.map +1 -0
  92. package/dist/locus-info/controlsUtils.js +101 -29
  93. package/dist/locus-info/controlsUtils.js.map +1 -1
  94. package/dist/locus-info/embeddedAppsUtils.js +3 -26
  95. package/dist/locus-info/embeddedAppsUtils.js.map +1 -1
  96. package/dist/locus-info/fullState.js +0 -15
  97. package/dist/locus-info/fullState.js.map +1 -1
  98. package/dist/locus-info/hostUtils.js +4 -12
  99. package/dist/locus-info/hostUtils.js.map +1 -1
  100. package/dist/locus-info/index.js +532 -240
  101. package/dist/locus-info/index.js.map +1 -1
  102. package/dist/locus-info/infoUtils.js +3 -37
  103. package/dist/locus-info/infoUtils.js.map +1 -1
  104. package/dist/locus-info/mediaSharesUtils.js +54 -38
  105. package/dist/locus-info/mediaSharesUtils.js.map +1 -1
  106. package/dist/locus-info/parser.js +284 -154
  107. package/dist/locus-info/parser.js.map +1 -1
  108. package/dist/locus-info/selfUtils.js +110 -92
  109. package/dist/locus-info/selfUtils.js.map +1 -1
  110. package/dist/media/index.js +95 -226
  111. package/dist/media/index.js.map +1 -1
  112. package/dist/media/properties.js +99 -194
  113. package/dist/media/properties.js.map +1 -1
  114. package/dist/media/util.js +2 -9
  115. package/dist/media/util.js.map +1 -1
  116. package/dist/mediaQualityMetrics/config.js +505 -495
  117. package/dist/mediaQualityMetrics/config.js.map +1 -1
  118. package/dist/meeting/in-meeting-actions.js +83 -14
  119. package/dist/meeting/in-meeting-actions.js.map +1 -1
  120. package/dist/meeting/index.js +3478 -3563
  121. package/dist/meeting/index.js.map +1 -1
  122. package/dist/meeting/locusMediaRequest.js +291 -0
  123. package/dist/meeting/locusMediaRequest.js.map +1 -0
  124. package/dist/meeting/muteState.js +247 -183
  125. package/dist/meeting/muteState.js.map +1 -1
  126. package/dist/meeting/request.js +344 -344
  127. package/dist/meeting/request.js.map +1 -1
  128. package/dist/meeting/request.type.js +7 -0
  129. package/dist/meeting/request.type.js.map +1 -0
  130. package/dist/meeting/state.js +21 -31
  131. package/dist/meeting/state.js.map +1 -1
  132. package/dist/meeting/util.js +529 -588
  133. package/dist/meeting/util.js.map +1 -1
  134. package/dist/meeting-info/collection.js +6 -25
  135. package/dist/meeting-info/collection.js.map +1 -1
  136. package/dist/meeting-info/index.js +62 -39
  137. package/dist/meeting-info/index.js.map +1 -1
  138. package/dist/meeting-info/meeting-info-v2.js +328 -283
  139. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  140. package/dist/meeting-info/request.js +3 -15
  141. package/dist/meeting-info/request.js.map +1 -1
  142. package/dist/meeting-info/util.js +98 -183
  143. package/dist/meeting-info/util.js.map +1 -1
  144. package/dist/meeting-info/utilv2.js +156 -232
  145. package/dist/meeting-info/utilv2.js.map +1 -1
  146. package/dist/meetings/collection.js +26 -19
  147. package/dist/meetings/collection.js.map +1 -1
  148. package/dist/meetings/index.js +795 -574
  149. package/dist/meetings/index.js.map +1 -1
  150. package/dist/meetings/meetings.types.js +7 -0
  151. package/dist/meetings/meetings.types.js.map +1 -0
  152. package/dist/meetings/request.js +26 -41
  153. package/dist/meetings/request.js.map +1 -1
  154. package/dist/meetings/util.js +186 -155
  155. package/dist/meetings/util.js.map +1 -1
  156. package/dist/member/index.js +126 -85
  157. package/dist/member/index.js.map +1 -1
  158. package/dist/member/types.js +25 -0
  159. package/dist/member/types.js.map +1 -0
  160. package/dist/member/util.js +147 -88
  161. package/dist/member/util.js.map +1 -1
  162. package/dist/members/collection.js +13 -12
  163. package/dist/members/collection.js.map +1 -1
  164. package/dist/members/index.js +178 -204
  165. package/dist/members/index.js.map +1 -1
  166. package/dist/members/request.js +113 -68
  167. package/dist/members/request.js.map +1 -1
  168. package/dist/members/types.js +15 -0
  169. package/dist/members/types.js.map +1 -0
  170. package/dist/members/util.js +314 -260
  171. package/dist/members/util.js.map +1 -1
  172. package/dist/metrics/constants.js +4 -7
  173. package/dist/metrics/constants.js.map +1 -1
  174. package/dist/metrics/index.js +11 -558
  175. package/dist/metrics/index.js.map +1 -1
  176. package/dist/multistream/mediaRequestManager.js +264 -50
  177. package/dist/multistream/mediaRequestManager.js.map +1 -1
  178. package/dist/multistream/receiveSlot.js +58 -65
  179. package/dist/multistream/receiveSlot.js.map +1 -1
  180. package/dist/multistream/receiveSlotManager.js +76 -95
  181. package/dist/multistream/receiveSlotManager.js.map +1 -1
  182. package/dist/multistream/remoteMedia.js +62 -76
  183. package/dist/multistream/remoteMedia.js.map +1 -1
  184. package/dist/multistream/remoteMediaGroup.js +66 -43
  185. package/dist/multistream/remoteMediaGroup.js.map +1 -1
  186. package/dist/multistream/remoteMediaManager.js +502 -442
  187. package/dist/multistream/remoteMediaManager.js.map +1 -1
  188. package/dist/networkQualityMonitor/index.js +40 -59
  189. package/dist/networkQualityMonitor/index.js.map +1 -1
  190. package/dist/personal-meeting-room/index.js +21 -45
  191. package/dist/personal-meeting-room/index.js.map +1 -1
  192. package/dist/personal-meeting-room/request.js +1 -31
  193. package/dist/personal-meeting-room/request.js.map +1 -1
  194. package/dist/personal-meeting-room/util.js +0 -13
  195. package/dist/personal-meeting-room/util.js.map +1 -1
  196. package/dist/reachability/index.js +192 -191
  197. package/dist/reachability/index.js.map +1 -1
  198. package/dist/reachability/request.js +15 -23
  199. package/dist/reachability/request.js.map +1 -1
  200. package/dist/reactions/constants.js +13 -0
  201. package/dist/reactions/constants.js.map +1 -0
  202. package/dist/reactions/reactions.js +109 -0
  203. package/dist/reactions/reactions.js.map +1 -0
  204. package/dist/reactions/reactions.type.js +36 -0
  205. package/dist/reactions/reactions.type.js.map +1 -0
  206. package/dist/reconnection-manager/index.js +384 -476
  207. package/dist/reconnection-manager/index.js.map +1 -1
  208. package/dist/recording-controller/enums.js +17 -0
  209. package/dist/recording-controller/enums.js.map +1 -0
  210. package/dist/recording-controller/index.js +363 -0
  211. package/dist/recording-controller/index.js.map +1 -0
  212. package/dist/recording-controller/util.js +64 -0
  213. package/dist/recording-controller/util.js.map +1 -0
  214. package/dist/roap/index.js +58 -91
  215. package/dist/roap/index.js.map +1 -1
  216. package/dist/roap/request.js +137 -135
  217. package/dist/roap/request.js.map +1 -1
  218. package/dist/roap/turnDiscovery.js +148 -100
  219. package/dist/roap/turnDiscovery.js.map +1 -1
  220. package/dist/rtcMetrics/constants.js +12 -0
  221. package/dist/rtcMetrics/constants.js.map +1 -0
  222. package/dist/rtcMetrics/index.js +115 -0
  223. package/dist/rtcMetrics/index.js.map +1 -0
  224. package/dist/statsAnalyzer/global.js +1 -95
  225. package/dist/statsAnalyzer/global.js.map +1 -1
  226. package/dist/statsAnalyzer/index.js +385 -460
  227. package/dist/statsAnalyzer/index.js.map +1 -1
  228. package/dist/statsAnalyzer/mqaUtil.js +143 -87
  229. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  230. package/dist/transcription/index.js +22 -47
  231. package/dist/transcription/index.js.map +1 -1
  232. package/dist/types/annotation/annotation.types.d.ts +42 -0
  233. package/dist/types/annotation/constants.d.ts +31 -0
  234. package/dist/types/annotation/index.d.ts +117 -0
  235. package/dist/types/breakouts/breakout.d.ts +8 -0
  236. package/dist/types/breakouts/collection.d.ts +5 -0
  237. package/dist/types/breakouts/edit-lock-error.d.ts +15 -0
  238. package/dist/types/breakouts/events.d.ts +8 -0
  239. package/dist/types/breakouts/index.d.ts +5 -0
  240. package/dist/types/breakouts/request.d.ts +22 -0
  241. package/dist/types/breakouts/utils.d.ts +15 -0
  242. package/dist/types/common/browser-detection.d.ts +9 -0
  243. package/dist/types/common/collection.d.ts +48 -0
  244. package/dist/types/common/config.d.ts +2 -0
  245. package/dist/types/common/errors/captcha-error.d.ts +15 -0
  246. package/dist/types/common/errors/intent-to-join.d.ts +16 -0
  247. package/dist/types/common/errors/join-meeting.d.ts +17 -0
  248. package/dist/types/common/errors/media.d.ts +15 -0
  249. package/dist/types/common/errors/parameter.d.ts +15 -0
  250. package/dist/types/common/errors/password-error.d.ts +15 -0
  251. package/dist/types/common/errors/permission.d.ts +14 -0
  252. package/dist/types/common/errors/reconnection-in-progress.d.ts +9 -0
  253. package/dist/types/common/errors/reconnection.d.ts +15 -0
  254. package/dist/types/common/errors/stats.d.ts +15 -0
  255. package/dist/types/common/errors/webex-errors.d.ts +69 -0
  256. package/dist/types/common/errors/webex-meetings-error.d.ts +20 -0
  257. package/dist/types/common/events/events-scope.d.ts +17 -0
  258. package/dist/types/common/events/events.d.ts +12 -0
  259. package/dist/types/common/events/trigger-proxy.d.ts +2 -0
  260. package/dist/types/common/events/util.d.ts +2 -0
  261. package/dist/types/common/logs/logger-config.d.ts +2 -0
  262. package/dist/types/common/logs/logger-proxy.d.ts +2 -0
  263. package/dist/types/common/logs/request.d.ts +34 -0
  264. package/dist/types/common/queue.d.ts +34 -0
  265. package/dist/types/config.d.ts +72 -0
  266. package/dist/types/constants.d.ts +1016 -0
  267. package/dist/types/controls-options-manager/constants.d.ts +4 -0
  268. package/dist/types/controls-options-manager/enums.d.ts +15 -0
  269. package/dist/types/controls-options-manager/index.d.ts +136 -0
  270. package/dist/types/controls-options-manager/types.d.ts +43 -0
  271. package/dist/types/controls-options-manager/util.d.ts +1 -0
  272. package/dist/types/index.d.ts +7 -0
  273. package/dist/types/interpretation/collection.d.ts +5 -0
  274. package/dist/types/interpretation/index.d.ts +5 -0
  275. package/dist/types/interpretation/siLanguage.d.ts +5 -0
  276. package/dist/types/locus-info/controlsUtils.d.ts +2 -0
  277. package/dist/types/locus-info/embeddedAppsUtils.d.ts +2 -0
  278. package/dist/types/locus-info/fullState.d.ts +2 -0
  279. package/dist/types/locus-info/hostUtils.d.ts +2 -0
  280. package/dist/types/locus-info/index.d.ts +322 -0
  281. package/dist/types/locus-info/infoUtils.d.ts +2 -0
  282. package/dist/types/locus-info/mediaSharesUtils.d.ts +2 -0
  283. package/dist/types/locus-info/parser.d.ts +271 -0
  284. package/dist/types/locus-info/selfUtils.d.ts +2 -0
  285. package/dist/types/media/index.d.ts +34 -0
  286. package/dist/types/media/properties.d.ts +93 -0
  287. package/dist/types/media/util.d.ts +2 -0
  288. package/dist/types/mediaQualityMetrics/config.d.ts +365 -0
  289. package/dist/types/meeting/in-meeting-actions.d.ts +153 -0
  290. package/dist/types/meeting/index.d.ts +1471 -0
  291. package/dist/types/meeting/locusMediaRequest.d.ts +70 -0
  292. package/dist/types/meeting/muteState.d.ts +184 -0
  293. package/dist/types/meeting/request.d.ts +257 -0
  294. package/dist/types/meeting/request.type.d.ts +11 -0
  295. package/dist/types/meeting/state.d.ts +9 -0
  296. package/dist/types/meeting/util.d.ts +78 -0
  297. package/dist/types/meeting-info/collection.d.ts +20 -0
  298. package/dist/types/meeting-info/index.d.ts +62 -0
  299. package/dist/types/meeting-info/meeting-info-v2.d.ts +122 -0
  300. package/dist/types/meeting-info/request.d.ts +22 -0
  301. package/dist/types/meeting-info/util.d.ts +2 -0
  302. package/dist/types/meeting-info/utilv2.d.ts +2 -0
  303. package/dist/types/meetings/collection.d.ts +31 -0
  304. package/dist/types/meetings/index.d.ts +367 -0
  305. package/dist/types/meetings/meetings.types.d.ts +4 -0
  306. package/dist/types/meetings/request.d.ts +27 -0
  307. package/dist/types/meetings/util.d.ts +18 -0
  308. package/dist/types/member/index.d.ts +159 -0
  309. package/dist/types/member/types.d.ts +32 -0
  310. package/dist/types/member/util.d.ts +2 -0
  311. package/dist/types/members/collection.d.ts +29 -0
  312. package/dist/types/members/index.d.ts +353 -0
  313. package/dist/types/members/request.d.ts +114 -0
  314. package/dist/types/members/types.d.ts +24 -0
  315. package/dist/types/members/util.d.ts +210 -0
  316. package/dist/types/metrics/constants.d.ts +55 -0
  317. package/dist/types/metrics/index.d.ts +45 -0
  318. package/dist/types/multistream/mediaRequestManager.d.ts +118 -0
  319. package/dist/types/multistream/receiveSlot.d.ts +68 -0
  320. package/dist/types/multistream/receiveSlotManager.d.ts +56 -0
  321. package/dist/types/multistream/remoteMedia.d.ts +72 -0
  322. package/dist/types/multistream/remoteMediaGroup.d.ts +47 -0
  323. package/dist/types/multistream/remoteMediaManager.d.ts +277 -0
  324. package/dist/types/networkQualityMonitor/index.d.ts +70 -0
  325. package/dist/types/personal-meeting-room/index.d.ts +47 -0
  326. package/dist/types/personal-meeting-room/request.d.ts +14 -0
  327. package/dist/types/personal-meeting-room/util.d.ts +2 -0
  328. package/dist/types/reachability/index.d.ts +152 -0
  329. package/dist/types/reachability/request.d.ts +37 -0
  330. package/dist/types/reactions/constants.d.ts +3 -0
  331. package/dist/types/reactions/reactions.d.ts +4 -0
  332. package/dist/types/reactions/reactions.type.d.ts +52 -0
  333. package/dist/types/reconnection-manager/index.d.ts +126 -0
  334. package/dist/types/recording-controller/enums.d.ts +7 -0
  335. package/dist/types/recording-controller/index.d.ts +208 -0
  336. package/dist/types/recording-controller/util.d.ts +14 -0
  337. package/dist/types/roap/index.d.ts +77 -0
  338. package/dist/types/roap/request.d.ts +36 -0
  339. package/dist/types/roap/turnDiscovery.d.ts +91 -0
  340. package/dist/types/rtcMetrics/constants.d.ts +4 -0
  341. package/dist/types/rtcMetrics/index.d.ts +46 -0
  342. package/dist/types/statsAnalyzer/global.d.ts +36 -0
  343. package/dist/types/statsAnalyzer/index.d.ts +200 -0
  344. package/dist/types/statsAnalyzer/mqaUtil.d.ts +24 -0
  345. package/dist/types/transcription/index.d.ts +64 -0
  346. package/internal-README.md +7 -6
  347. package/package.json +29 -21
  348. package/src/annotation/annotation.types.ts +50 -0
  349. package/src/annotation/constants.ts +36 -0
  350. package/src/annotation/index.ts +328 -0
  351. package/src/breakouts/README.md +220 -0
  352. package/src/breakouts/breakout.ts +188 -0
  353. package/src/breakouts/collection.ts +19 -0
  354. package/src/breakouts/edit-lock-error.ts +25 -0
  355. package/src/breakouts/events.ts +56 -0
  356. package/src/breakouts/index.ts +925 -0
  357. package/src/breakouts/request.ts +55 -0
  358. package/src/breakouts/utils.ts +57 -0
  359. package/src/common/{browser-detection.js → browser-detection.ts} +9 -6
  360. package/src/common/collection.ts +9 -7
  361. package/src/common/{config.js → config.ts} +1 -1
  362. package/src/common/errors/{captcha-error.js → captcha-error.ts} +11 -7
  363. package/src/common/errors/{intent-to-join.js → intent-to-join.ts} +12 -7
  364. package/src/common/errors/{join-meeting.js → join-meeting.ts} +17 -8
  365. package/src/common/errors/{media.js → media.ts} +11 -7
  366. package/src/common/errors/parameter.ts +11 -7
  367. package/src/common/errors/{password-error.js → password-error.ts} +11 -7
  368. package/src/common/errors/{permission.js → permission.ts} +10 -6
  369. package/src/common/errors/{reconnection.js → reconnection.ts} +11 -7
  370. package/src/common/errors/{stats.js → stats.ts} +11 -7
  371. package/src/common/errors/{webex-errors.js → webex-errors.ts} +14 -9
  372. package/src/common/errors/{webex-meetings-error.js → webex-meetings-error.ts} +4 -2
  373. package/src/common/events/{events-scope.js → events-scope.ts} +6 -2
  374. package/src/common/events/{events.js → events.ts} +5 -1
  375. package/src/common/events/{trigger-proxy.js → trigger-proxy.ts} +9 -5
  376. package/src/common/events/{util.js → util.ts} +2 -3
  377. package/src/common/logs/{logger-config.js → logger-config.ts} +1 -2
  378. package/src/common/logs/logger-proxy.ts +44 -0
  379. package/src/common/logs/{request.js → request.ts} +22 -9
  380. package/src/common/queue.ts +22 -9
  381. package/src/{config.js → config.ts} +17 -17
  382. package/src/constants.ts +197 -22
  383. package/src/controls-options-manager/constants.ts +5 -0
  384. package/src/controls-options-manager/enums.ts +18 -0
  385. package/src/controls-options-manager/index.ts +278 -0
  386. package/src/controls-options-manager/types.ts +59 -0
  387. package/src/controls-options-manager/util.ts +300 -0
  388. package/src/index.ts +39 -0
  389. package/src/interpretation/README.md +60 -0
  390. package/src/interpretation/collection.ts +19 -0
  391. package/src/interpretation/index.ts +332 -0
  392. package/src/interpretation/siLanguage.ts +18 -0
  393. package/src/locus-info/controlsUtils.ts +222 -0
  394. package/src/locus-info/{embeddedAppsUtils.js → embeddedAppsUtils.ts} +5 -6
  395. package/src/locus-info/{fullState.js → fullState.ts} +16 -12
  396. package/src/locus-info/{hostUtils.js → hostUtils.ts} +9 -8
  397. package/src/locus-info/{index.js → index.ts} +518 -111
  398. package/src/locus-info/{infoUtils.js → infoUtils.ts} +19 -8
  399. package/src/locus-info/{mediaSharesUtils.js → mediaSharesUtils.ts} +65 -17
  400. package/src/locus-info/{parser.js → parser.ts} +271 -98
  401. package/src/locus-info/{selfUtils.js → selfUtils.ts} +199 -68
  402. package/src/media/index.ts +456 -0
  403. package/src/media/{properties.js → properties.ts} +80 -102
  404. package/src/media/{util.js → util.ts} +2 -2
  405. package/src/mediaQualityMetrics/config.ts +384 -0
  406. package/src/meeting/in-meeting-actions.ts +171 -3
  407. package/src/meeting/index.ts +7070 -0
  408. package/src/meeting/locusMediaRequest.ts +309 -0
  409. package/src/meeting/muteState.ts +450 -0
  410. package/src/meeting/{request.js → request.ts} +354 -214
  411. package/src/meeting/request.type.ts +13 -0
  412. package/src/meeting/{state.js → state.ts} +50 -35
  413. package/src/meeting/util.ts +615 -0
  414. package/src/meeting-info/{collection.js → collection.ts} +6 -2
  415. package/src/meeting-info/index.ts +183 -0
  416. package/src/meeting-info/meeting-info-v2.ts +407 -0
  417. package/src/meeting-info/{request.js → request.ts} +14 -4
  418. package/src/meeting-info/{util.js → util.ts} +60 -51
  419. package/src/meeting-info/{utilv2.js → utilv2.ts} +77 -60
  420. package/src/meetings/{collection.js → collection.ts} +26 -3
  421. package/src/meetings/index.ts +1467 -0
  422. package/src/meetings/meetings.types.ts +12 -0
  423. package/src/meetings/{request.js → request.ts} +34 -25
  424. package/src/meetings/{util.js → util.ts} +137 -36
  425. package/src/member/{index.js → index.ts} +151 -56
  426. package/src/member/types.ts +38 -0
  427. package/src/member/util.ts +383 -0
  428. package/src/members/{collection.js → collection.ts} +10 -2
  429. package/src/members/{index.js → index.ts} +323 -145
  430. package/src/members/request.ts +255 -0
  431. package/src/members/types.ts +28 -0
  432. package/src/members/util.ts +339 -0
  433. package/src/metrics/{constants.js → constants.ts} +2 -6
  434. package/src/metrics/index.ts +73 -0
  435. package/src/multistream/mediaRequestManager.ts +337 -61
  436. package/src/multistream/receiveSlot.ts +69 -26
  437. package/src/multistream/receiveSlotManager.ts +66 -42
  438. package/src/multistream/remoteMedia.ts +40 -5
  439. package/src/multistream/remoteMediaGroup.ts +63 -3
  440. package/src/multistream/remoteMediaManager.ts +263 -66
  441. package/src/networkQualityMonitor/{index.js → index.ts} +41 -29
  442. package/src/personal-meeting-room/{index.js → index.ts} +28 -19
  443. package/src/personal-meeting-room/{request.js → request.ts} +13 -4
  444. package/src/personal-meeting-room/{util.js → util.ts} +4 -4
  445. package/src/reachability/{index.js → index.ts} +157 -94
  446. package/src/reachability/request.ts +46 -35
  447. package/src/reactions/constants.ts +4 -0
  448. package/src/reactions/reactions.ts +104 -0
  449. package/src/reactions/reactions.type.ts +62 -0
  450. package/src/reconnection-manager/{index.js → index.ts} +254 -136
  451. package/src/recording-controller/enums.ts +8 -0
  452. package/src/recording-controller/index.ts +333 -0
  453. package/src/recording-controller/util.ts +75 -0
  454. package/src/roap/{index.js → index.ts} +86 -78
  455. package/src/roap/request.ts +163 -0
  456. package/src/roap/turnDiscovery.ts +111 -49
  457. package/src/rtcMetrics/constants.ts +3 -0
  458. package/src/rtcMetrics/index.ts +96 -0
  459. package/src/statsAnalyzer/global.ts +37 -0
  460. package/src/statsAnalyzer/index.ts +1272 -0
  461. package/src/statsAnalyzer/mqaUtil.ts +291 -0
  462. package/src/transcription/{index.js → index.ts} +46 -39
  463. package/test/integration/spec/converged-space-meetings.js +233 -0
  464. package/test/integration/spec/journey.js +804 -526
  465. package/test/integration/spec/space-meeting.js +391 -204
  466. package/test/integration/spec/transcription.js +7 -8
  467. package/test/unit/spec/annotation/index.ts +418 -0
  468. package/test/unit/spec/breakouts/breakout.ts +237 -0
  469. package/test/unit/spec/breakouts/collection.ts +15 -0
  470. package/test/unit/spec/breakouts/edit-lock-error.ts +30 -0
  471. package/test/unit/spec/breakouts/events.ts +89 -0
  472. package/test/unit/spec/breakouts/index.ts +1790 -0
  473. package/test/unit/spec/breakouts/request.ts +104 -0
  474. package/test/unit/spec/breakouts/utils.js +72 -0
  475. package/test/unit/spec/common/browser-detection.js +9 -28
  476. package/test/unit/spec/common/queue.js +31 -2
  477. package/test/unit/spec/controls-options-manager/index.js +287 -0
  478. package/test/unit/spec/controls-options-manager/util.js +582 -0
  479. package/test/unit/spec/fixture/locus.js +93 -90
  480. package/test/unit/spec/interpretation/collection.ts +15 -0
  481. package/test/unit/spec/interpretation/index.ts +589 -0
  482. package/test/unit/spec/interpretation/siLanguage.ts +28 -0
  483. package/test/unit/spec/locus-info/controlsUtils.js +325 -32
  484. package/test/unit/spec/locus-info/embeddedAppsUtils.js +8 -6
  485. package/test/unit/spec/locus-info/index.js +1176 -18
  486. package/test/unit/spec/locus-info/infoUtils.js +41 -32
  487. package/test/unit/spec/locus-info/lib/BasicSeqCmp.json +88 -430
  488. package/test/unit/spec/locus-info/lib/SeqCmp.json +513 -685
  489. package/test/unit/spec/locus-info/mediaSharesUtils.ts +22 -0
  490. package/test/unit/spec/locus-info/parser.js +65 -31
  491. package/test/unit/spec/locus-info/selfConstant.js +120 -103
  492. package/test/unit/spec/locus-info/selfUtils.js +296 -12
  493. package/test/unit/spec/media/index.ts +162 -68
  494. package/test/unit/spec/media/properties.ts +9 -9
  495. package/test/unit/spec/meeting/in-meeting-actions.ts +82 -3
  496. package/test/unit/spec/meeting/index.js +4569 -1773
  497. package/test/unit/spec/meeting/locusMediaRequest.ts +436 -0
  498. package/test/unit/spec/meeting/muteState.js +382 -211
  499. package/test/unit/spec/meeting/request.js +444 -78
  500. package/test/unit/spec/meeting/utils.js +517 -192
  501. package/test/unit/spec/meeting-info/index.js +181 -0
  502. package/test/unit/spec/meeting-info/meetinginfov2.js +481 -76
  503. package/test/unit/spec/meeting-info/request.js +7 -9
  504. package/test/unit/spec/meeting-info/util.js +11 -12
  505. package/test/unit/spec/meeting-info/utilv2.js +131 -74
  506. package/test/unit/spec/meetings/collection.js +15 -1
  507. package/test/unit/spec/meetings/index.js +1254 -330
  508. package/test/unit/spec/meetings/utils.js +220 -14
  509. package/test/unit/spec/member/index.js +58 -5
  510. package/test/unit/spec/member/util.js +494 -26
  511. package/test/unit/spec/members/index.js +423 -55
  512. package/test/unit/spec/members/request.js +228 -40
  513. package/test/unit/spec/members/utils.js +191 -4
  514. package/test/unit/spec/metrics/index.js +12 -66
  515. package/test/unit/spec/multistream/mediaRequestManager.ts +1013 -106
  516. package/test/unit/spec/multistream/receiveSlot.ts +77 -18
  517. package/test/unit/spec/multistream/receiveSlotManager.ts +69 -39
  518. package/test/unit/spec/multistream/remoteMedia.ts +40 -2
  519. package/test/unit/spec/multistream/remoteMediaGroup.ts +271 -5
  520. package/test/unit/spec/multistream/remoteMediaManager.ts +730 -65
  521. package/test/unit/spec/networkQualityMonitor/index.js +24 -18
  522. package/test/unit/spec/personal-meeting-room/personal-meeting-room.js +2 -7
  523. package/test/unit/spec/reachability/index.ts +176 -27
  524. package/test/unit/spec/reachability/request.js +66 -0
  525. package/test/unit/spec/reconnection-manager/index.js +155 -9
  526. package/test/unit/spec/recording-controller/index.js +307 -0
  527. package/test/unit/spec/recording-controller/util.js +229 -0
  528. package/test/unit/spec/roap/index.ts +28 -52
  529. package/test/unit/spec/roap/request.ts +225 -0
  530. package/test/unit/spec/roap/turnDiscovery.ts +92 -50
  531. package/test/unit/spec/rtcMetrics/index.ts +60 -0
  532. package/test/unit/spec/stats-analyzer/index.js +116 -60
  533. package/test/utils/cmr.js +44 -42
  534. package/test/utils/constants.js +9 -0
  535. package/test/utils/integrationTestUtils.js +46 -0
  536. package/test/utils/testUtils.js +63 -99
  537. package/test/utils/webex-config.js +22 -18
  538. package/test/utils/webex-test-users.js +57 -50
  539. package/tsconfig.json +6 -0
  540. package/dist/media/internal-media-core-wrapper.js +0 -22
  541. package/dist/media/internal-media-core-wrapper.js.map +0 -1
  542. package/dist/meeting/effectsState.js +0 -327
  543. package/dist/meeting/effectsState.js.map +0 -1
  544. package/dist/metrics/config.js +0 -301
  545. package/dist/metrics/config.js.map +0 -1
  546. package/dist/multistream/multistreamMedia.js +0 -116
  547. package/dist/multistream/multistreamMedia.js.map +0 -1
  548. package/dist/peer-connection-manager/util.js +0 -124
  549. package/dist/peer-connection-manager/util.js.map +0 -1
  550. package/src/common/logs/logger-proxy.js +0 -33
  551. package/src/index.js +0 -15
  552. package/src/locus-info/controlsUtils.js +0 -102
  553. package/src/media/index.js +0 -459
  554. package/src/media/internal-media-core-wrapper.ts +0 -9
  555. package/src/mediaQualityMetrics/config.js +0 -382
  556. package/src/meeting/effectsState.js +0 -205
  557. package/src/meeting/index.js +0 -6284
  558. package/src/meeting/muteState.js +0 -318
  559. package/src/meeting/util.js +0 -506
  560. package/src/meeting-info/index.js +0 -131
  561. package/src/meeting-info/meeting-info-v2.js +0 -255
  562. package/src/meetings/index.js +0 -1015
  563. package/src/member/util.js +0 -254
  564. package/src/members/request.js +0 -131
  565. package/src/members/util.js +0 -258
  566. package/src/metrics/config.js +0 -324
  567. package/src/metrics/index.js +0 -530
  568. package/src/multistream/multistreamMedia.ts +0 -92
  569. package/src/peer-connection-manager/util.ts +0 -117
  570. package/src/roap/request.js +0 -127
  571. package/src/statsAnalyzer/global.js +0 -133
  572. package/src/statsAnalyzer/index.js +0 -1006
  573. package/src/statsAnalyzer/mqaUtil.js +0 -173
  574. package/test/unit/spec/meeting/effectsState.js +0 -291
  575. package/test/unit/spec/peerconnection-manager/utils.test-fixtures.ts +0 -389
  576. /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 {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,
@@ -15,15 +15,18 @@ 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';
18
21
 
19
22
  class FakeSlot extends EventEmitter {
20
- public mediaType: MC.MediaType;
23
+ public mediaType: MediaType;
21
24
 
22
25
  public id: string;
23
26
 
24
27
  public csi?: number;
25
28
 
26
- constructor(mediaType: MC.MediaType, id: string) {
29
+ constructor(mediaType: MediaType, id: string) {
27
30
  super();
28
31
  this.mediaType = mediaType;
29
32
  this.id = id;
@@ -32,11 +35,16 @@ class FakeSlot extends EventEmitter {
32
35
  // Calling setMaxListeners() fixes the warning.
33
36
  this.setMaxListeners(50);
34
37
  }
38
+
39
+ public get logString() {
40
+ return this.id;
41
+ }
35
42
  }
36
43
 
37
44
  const DefaultTestConfiguration: Configuration = {
38
45
  audio: {
39
46
  numOfActiveSpeakerStreams: 3,
47
+ numOfScreenShareStreams: 1,
40
48
  },
41
49
  video: {
42
50
  preferLiveVideo: true,
@@ -44,7 +52,6 @@ const DefaultTestConfiguration: Configuration = {
44
52
 
45
53
  layouts: {
46
54
  AllEqual: {
47
- screenShareVideo: {size: null},
48
55
  activeSpeakerVideoPaneGroups: [
49
56
  {
50
57
  id: 'main',
@@ -55,7 +62,6 @@ const DefaultTestConfiguration: Configuration = {
55
62
  ],
56
63
  },
57
64
  OnePlusFive: {
58
- screenShareVideo: {size: null},
59
65
  activeSpeakerVideoPaneGroups: [
60
66
  {
61
67
  id: 'mainBigOne',
@@ -72,7 +78,6 @@ const DefaultTestConfiguration: Configuration = {
72
78
  ],
73
79
  },
74
80
  Single: {
75
- screenShareVideo: {size: null},
76
81
  activeSpeakerVideoPaneGroups: [
77
82
  {
78
83
  id: 'main',
@@ -83,7 +88,6 @@ const DefaultTestConfiguration: Configuration = {
83
88
  ],
84
89
  },
85
90
  Stage: {
86
- screenShareVideo: {size: null},
87
91
  activeSpeakerVideoPaneGroups: [
88
92
  {
89
93
  id: 'thumbnails',
@@ -99,12 +103,19 @@ const DefaultTestConfiguration: Configuration = {
99
103
  {id: 'stage-4', size: 'medium', csi: undefined},
100
104
  ],
101
105
  },
106
+ ScreenShareView: {
107
+ screenShareVideo: {size: 'medium'},
108
+ activeSpeakerVideoPaneGroups: [
109
+ {
110
+ id: 'thumbnails',
111
+ numPanes: 6,
112
+ size: 'thumbnail',
113
+ priority: 255,
114
+ },
115
+ ],
116
+ },
102
117
  },
103
118
  },
104
- screenShare: {
105
- audio: true,
106
- video: true,
107
- },
108
119
  };
109
120
 
110
121
  describe('RemoteMediaManager', () => {
@@ -113,18 +124,50 @@ describe('RemoteMediaManager', () => {
113
124
  let fakeMediaRequestManagers;
114
125
  let fakeAudioSlot;
115
126
  let fakeVideoSlot;
127
+ let fakeScreenShareAudioSlot;
128
+ let fakeScreenShareVideoSlot;
129
+
130
+ const logger = {
131
+ log: sinon.fake(),
132
+ error: () => {},
133
+ warn: () => {},
134
+ trace: () => {},
135
+ debug: () => {},
136
+ };
137
+
138
+ afterEach(() => {
139
+ LoggerConfig.set({enable: false});
140
+ LoggerProxy.set();
141
+ });
116
142
 
117
143
  beforeEach(() => {
118
- fakeAudioSlot = new FakeSlot(MC.MediaType.AudioMain, 'fake audio slot');
119
- fakeVideoSlot = new FakeSlot(MC.MediaType.VideoMain, 'fake video slot');
144
+ LoggerConfig.set({enable: true});
145
+ LoggerProxy.set(logger);
146
+
147
+ fakeAudioSlot = new FakeSlot(MediaType.AudioMain, 'fake audio slot');
148
+ fakeVideoSlot = new FakeSlot(MediaType.VideoMain, 'fake video slot');
149
+ fakeScreenShareAudioSlot = new FakeSlot(
150
+ MediaType.AudioSlides,
151
+ 'fake screen share audio slot'
152
+ );
153
+ fakeScreenShareVideoSlot = new FakeSlot(
154
+ MediaType.VideoSlides,
155
+ 'fake screen share video slot'
156
+ );
120
157
 
121
158
  fakeReceiveSlotManager = {
122
159
  allocateSlot: sinon.stub().callsFake((mediaType) => {
123
- if (mediaType === MC.MediaType.AudioMain) {
124
- return Promise.resolve(fakeAudioSlot);
160
+ switch (mediaType) {
161
+ case MediaType.AudioMain:
162
+ return Promise.resolve(fakeAudioSlot);
163
+ case MediaType.VideoMain:
164
+ return Promise.resolve(fakeVideoSlot);
165
+ case MediaType.AudioSlides:
166
+ return Promise.resolve(fakeScreenShareAudioSlot);
167
+ case MediaType.VideoSlides:
168
+ return Promise.resolve(fakeScreenShareVideoSlot);
125
169
  }
126
-
127
- return Promise.resolve(fakeVideoSlot);
170
+ throw new Error(`invalid mediaType: ${mediaType}`);
128
171
  }),
129
172
  releaseSlot: sinon.stub(),
130
173
  };
@@ -140,6 +183,16 @@ describe('RemoteMediaManager', () => {
140
183
  cancelRequest: sinon.stub(),
141
184
  commit: sinon.stub(),
142
185
  },
186
+ screenShareAudio: {
187
+ addRequest: sinon.stub(),
188
+ cancelRequest: sinon.stub(),
189
+ commit: sinon.stub(),
190
+ },
191
+ screenShareVideo: {
192
+ addRequest: sinon.stub(),
193
+ cancelRequest: sinon.stub(),
194
+ commit: sinon.stub(),
195
+ },
143
196
  };
144
197
 
145
198
  // create remote media manager with default configuration
@@ -159,6 +212,9 @@ describe('RemoteMediaManager', () => {
159
212
  fakeMediaRequestManagers.video.addRequest.resetHistory();
160
213
  fakeMediaRequestManagers.video.cancelRequest.resetHistory();
161
214
  fakeMediaRequestManagers.video.commit.resetHistory();
215
+ fakeMediaRequestManagers.screenShareVideo.commit.resetHistory();
216
+ fakeMediaRequestManagers.screenShareAudio.commit.resetHistory();
217
+ logger.log.resetHistory();
162
218
  };
163
219
 
164
220
  describe('start', () => {
@@ -176,8 +232,8 @@ describe('RemoteMediaManager', () => {
176
232
  await remoteMediaManager.start();
177
233
 
178
234
  // 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);
235
+ assert.calledWith(fakeReceiveSlotManager.allocateSlot, MediaType.AudioMain);
236
+ assert.calledWith(fakeReceiveSlotManager.allocateSlot, MediaType.VideoMain);
181
237
 
182
238
  assert.called(fakeMediaRequestManagers.audio.addRequest);
183
239
  assert.called(fakeMediaRequestManagers.video.addRequest);
@@ -187,25 +243,18 @@ describe('RemoteMediaManager', () => {
187
243
  let createdAudioGroup: RemoteMediaGroup | null = null;
188
244
 
189
245
  // create a config with just audio, no video at all and no screen share
190
- const config = {
246
+ const config: Configuration = {
191
247
  audio: {
192
248
  numOfActiveSpeakerStreams: 5,
249
+ numOfScreenShareStreams: 0,
193
250
  },
194
251
  video: {
195
252
  preferLiveVideo: false,
196
253
  initialLayoutId: 'empty',
197
254
  layouts: {
198
- empty: {
199
- screenShareVideo: {
200
- size: null,
201
- },
202
- },
255
+ empty: {},
203
256
  },
204
257
  },
205
- screenShare: {
206
- audio: false,
207
- video: false,
208
- },
209
258
  };
210
259
 
211
260
  remoteMediaManager = new RemoteMediaManager(
@@ -223,7 +272,7 @@ describe('RemoteMediaManager', () => {
223
272
  await testUtils.flushPromises();
224
273
 
225
274
  assert.callCount(fakeReceiveSlotManager.allocateSlot, 5);
226
- assert.alwaysCalledWith(fakeReceiveSlotManager.allocateSlot, MC.MediaType.AudioMain);
275
+ assert.alwaysCalledWith(fakeReceiveSlotManager.allocateSlot, MediaType.AudioMain);
227
276
 
228
277
  assert.isNotNull(createdAudioGroup);
229
278
  if (createdAudioGroup) {
@@ -231,7 +280,7 @@ describe('RemoteMediaManager', () => {
231
280
  assert.isTrue(
232
281
  createdAudioGroup
233
282
  .getRemoteMedia()
234
- .every((remoteMedia) => remoteMedia.mediaType === MC.MediaType.AudioMain)
283
+ .every((remoteMedia) => remoteMedia.mediaType === MediaType.AudioMain)
235
284
  );
236
285
  assert.strictEqual(createdAudioGroup.getRemoteMedia('pinned').length, 0);
237
286
  }
@@ -255,9 +304,6 @@ describe('RemoteMediaManager', () => {
255
304
 
256
305
  config.audio.numOfActiveSpeakerStreams = 0;
257
306
  config.video.layouts.huge = {
258
- screenShareVideo: {
259
- size: null,
260
- },
261
307
  activeSpeakerVideoPaneGroups: [
262
308
  {
263
309
  id: 'big one',
@@ -267,6 +313,8 @@ describe('RemoteMediaManager', () => {
267
313
  },
268
314
  ],
269
315
  };
316
+ config.audio.numOfScreenShareStreams = 0;
317
+ delete config.video.layouts.ScreenShareView;
270
318
 
271
319
  remoteMediaManager = new RemoteMediaManager(
272
320
  fakeReceiveSlotManager,
@@ -279,7 +327,7 @@ describe('RemoteMediaManager', () => {
279
327
  // even though our "big one" layout is not the default one, the remote media manager should still
280
328
  // preallocate enough video receive slots for it up front
281
329
  assert.callCount(fakeReceiveSlotManager.allocateSlot, 99);
282
- assert.alwaysCalledWith(fakeReceiveSlotManager.allocateSlot, MC.MediaType.VideoMain);
330
+ assert.alwaysCalledWith(fakeReceiveSlotManager.allocateSlot, MediaType.VideoMain);
283
331
  });
284
332
 
285
333
  it('starts with the initial layout', async () => {
@@ -302,8 +350,128 @@ describe('RemoteMediaManager', () => {
302
350
  receivedLayoutInfo.activeSpeakerVideoPanes.main.getRemoteMedia().length,
303
351
  9
304
352
  );
353
+ assert.isUndefined(receivedLayoutInfo.screenShareVideo); // the initial layout has no screen share
354
+ }
355
+ });
356
+
357
+ it('creates RemoteMedia for screen share audio correctly', async () => {
358
+ let createdAudioGroup: RemoteMediaGroup | null = null;
359
+
360
+ const NUM_STREAMS = 2;
361
+
362
+ // create a config with just screen share audio, nothing else
363
+ const config: Configuration = {
364
+ audio: {
365
+ numOfActiveSpeakerStreams: 0,
366
+ numOfScreenShareStreams: NUM_STREAMS,
367
+ },
368
+ video: {
369
+ preferLiveVideo: false,
370
+ initialLayoutId: 'empty',
371
+ layouts: {
372
+ empty: {},
373
+ },
374
+ },
375
+ };
376
+
377
+ remoteMediaManager = new RemoteMediaManager(
378
+ fakeReceiveSlotManager,
379
+ fakeMediaRequestManagers,
380
+ config
381
+ );
382
+
383
+ remoteMediaManager.on(Event.ScreenShareAudioCreated, (audio: RemoteMediaGroup) => {
384
+ createdAudioGroup = audio;
385
+ });
386
+
387
+ remoteMediaManager.start();
388
+
389
+ await testUtils.flushPromises();
390
+
391
+ assert.callCount(fakeReceiveSlotManager.allocateSlot, NUM_STREAMS);
392
+ assert.alwaysCalledWith(fakeReceiveSlotManager.allocateSlot, MediaType.AudioSlides);
393
+
394
+ assert.isNotNull(createdAudioGroup);
395
+ if (createdAudioGroup) {
396
+ assert.strictEqual(createdAudioGroup.getRemoteMedia().length, NUM_STREAMS);
397
+ assert.isTrue(
398
+ createdAudioGroup
399
+ .getRemoteMedia()
400
+ .every((remoteMedia) => remoteMedia.mediaType === MediaType.AudioSlides)
401
+ );
402
+ assert.strictEqual(createdAudioGroup.getRemoteMedia('pinned').length, 0);
305
403
  }
404
+
405
+ assert.calledOnce(fakeMediaRequestManagers.screenShareAudio.addRequest);
406
+ assert.calledWith(
407
+ fakeMediaRequestManagers.screenShareAudio.addRequest,
408
+ sinon.match({
409
+ policyInfo: sinon.match({
410
+ policy: 'active-speaker',
411
+ priority: 255,
412
+ }),
413
+ receiveSlots: Array(NUM_STREAMS).fill(fakeScreenShareAudioSlot),
414
+ codecInfo: undefined,
415
+ })
416
+ );
417
+ });
418
+
419
+ it('creates a single receive slot for screen share video if any layout has screen share', async () => {
420
+ // create a config with 2 layouts that use screen share
421
+ const config: Configuration = {
422
+ audio: {
423
+ numOfActiveSpeakerStreams: 0,
424
+ numOfScreenShareStreams: 0,
425
+ },
426
+ video: {
427
+ preferLiveVideo: false,
428
+ initialLayoutId: 'first',
429
+ layouts: {
430
+ first: {
431
+ screenShareVideo: { size: 'small'}
432
+ },
433
+ second: {
434
+ screenShareVideo: { size: 'medium'}
435
+ }
436
+ },
437
+ },
438
+ };
439
+
440
+ remoteMediaManager = new RemoteMediaManager(
441
+ fakeReceiveSlotManager,
442
+ fakeMediaRequestManagers,
443
+ config
444
+ );
445
+
446
+ await remoteMediaManager.start();
447
+
448
+ // even though 2 layouts use screen share, only 1 video screen share slot should be created
449
+ assert.callCount(fakeReceiveSlotManager.allocateSlot, 1);
450
+ assert.alwaysCalledWith(fakeReceiveSlotManager.allocateSlot, MediaType.VideoSlides);
451
+ });
452
+
453
+ it('does not create any receive slot for screen share video if none of the layouts have screen share', async () => {
454
+ const config = cloneDeep(DefaultTestConfiguration);
455
+
456
+ config.audio.numOfActiveSpeakerStreams = 0;
457
+ config.audio.numOfScreenShareStreams = 0;
458
+
459
+ // delete the only layout that uses screen share
460
+ delete config.video.layouts.ScreenShareView;
461
+
462
+ remoteMediaManager = new RemoteMediaManager(
463
+ fakeReceiveSlotManager,
464
+ fakeMediaRequestManagers,
465
+ config
466
+ );
467
+
468
+ await remoteMediaManager.start();
469
+
470
+ // we don't expect any audio and for video there should be no VideoSlides, so all the calls should be just for VideoMain
471
+ assert.alwaysCalledWith(fakeReceiveSlotManager.allocateSlot, MediaType.VideoMain);
306
472
  });
473
+
474
+
307
475
  });
308
476
 
309
477
  describe('constructor', () => {
@@ -325,7 +493,6 @@ describe('RemoteMediaManager', () => {
325
493
  const config = cloneDeep(DefaultTestConfiguration);
326
494
 
327
495
  config.video.layouts.test = {
328
- screenShareVideo: {size: null},
329
496
  activeSpeakerVideoPaneGroups: [
330
497
  {
331
498
  id: 'someDuplicate',
@@ -361,7 +528,6 @@ describe('RemoteMediaManager', () => {
361
528
  const config = cloneDeep(DefaultTestConfiguration);
362
529
 
363
530
  config.video.layouts.test = {
364
- screenShareVideo: {size: null},
365
531
  activeSpeakerVideoPaneGroups: [
366
532
  {
367
533
  id: 'group1',
@@ -397,7 +563,6 @@ describe('RemoteMediaManager', () => {
397
563
  const config = cloneDeep(DefaultTestConfiguration);
398
564
 
399
565
  config.video.layouts.test = {
400
- screenShareVideo: {size: null},
401
566
  memberVideoPanes: [
402
567
  {id: 'paneA', size: 'best', csi: 123},
403
568
  {id: 'paneB', size: 'large', csi: 222},
@@ -414,6 +579,7 @@ describe('RemoteMediaManager', () => {
414
579
  );
415
580
  }, 'invalid config: duplicate member video pane id: paneB');
416
581
  });
582
+
417
583
  });
418
584
 
419
585
  describe('stop', () => {
@@ -421,12 +587,17 @@ describe('RemoteMediaManager', () => {
421
587
  let audioStopStub;
422
588
  let videoActiveSpeakerGroupStopStub;
423
589
  const memberVideoPaneStopStubs: any[] = [];
590
+ let screenShareAudioStopStub;
591
+ let screenShareVideoStopStub;
424
592
 
425
- // change the initial layout to one that has both active speakers and receveiver selected videos
593
+ // change the initial layout to one that has both active speakers and receiver selected videos
426
594
  const config = cloneDeep(DefaultTestConfiguration);
427
595
 
428
596
  config.video.initialLayoutId = 'Stage';
429
597
 
598
+ // and also modify it to have screen share so we can test that too
599
+ config.video.layouts['Stage'].screenShareVideo = {size: 'medium'};
600
+
430
601
  remoteMediaManager = new RemoteMediaManager(
431
602
  fakeReceiveSlotManager,
432
603
  fakeMediaRequestManagers,
@@ -437,6 +608,10 @@ describe('RemoteMediaManager', () => {
437
608
  audioStopStub = sinon.stub(audio, 'stop');
438
609
  });
439
610
 
611
+ remoteMediaManager.on(Event.ScreenShareAudioCreated, (audio: RemoteMediaGroup) => {
612
+ screenShareAudioStopStub = sinon.stub(audio, 'stop');
613
+ });
614
+
440
615
  remoteMediaManager.on(Event.VideoLayoutChanged, (layoutInfo: VideoLayoutChangedEventData) => {
441
616
  // The "Stage" layout that we're using has only 1 active speaker group called "thumbnails"
442
617
  videoActiveSpeakerGroupStopStub = sinon.stub(
@@ -447,12 +622,14 @@ describe('RemoteMediaManager', () => {
447
622
  Object.values(layoutInfo.memberVideoPanes).forEach((pane) => {
448
623
  memberVideoPaneStopStubs.push(sinon.stub(pane, 'stop'));
449
624
  });
625
+
626
+ screenShareVideoStopStub = sinon.stub(layoutInfo.screenShareVideo, 'stop');
450
627
  });
451
628
 
452
629
  await remoteMediaManager.start();
453
630
 
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);
631
+ // we're using the default config that requires 3 main audio slots, 10 video slots (for Stage2x2With6ThumbnailsLayout), 1 screenshare audio, 1 screenshare video
632
+ assert.callCount(fakeReceiveSlotManager.allocateSlot, 15);
456
633
 
457
634
  // our layout has 4 member video panes, we should have a stub for each of these panes' stop methods
458
635
  assert.strictEqual(memberVideoPaneStopStubs.length, 4);
@@ -462,16 +639,20 @@ describe('RemoteMediaManager', () => {
462
639
  remoteMediaManager.stop();
463
640
 
464
641
  // check that all slots have been released
465
- assert.callCount(fakeReceiveSlotManager.releaseSlot, 13);
642
+ assert.callCount(fakeReceiveSlotManager.releaseSlot, 15);
466
643
 
467
644
  // and that all RemoteMedia and RemoteMediaGroups have been stopped
468
645
  assert.calledOnce(audioStopStub);
469
646
  assert.calledWith(audioStopStub, true);
647
+ assert.calledOnce(screenShareAudioStopStub);
648
+ assert.calledWith(screenShareAudioStopStub, true);
470
649
  assert.calledOnce(videoActiveSpeakerGroupStopStub);
471
650
  memberVideoPaneStopStubs.forEach((stub) => {
472
651
  assert.calledOnce(stub);
473
652
  });
474
653
  assert.calledOnce(fakeMediaRequestManagers.video.commit);
654
+ assert.calledOnce(screenShareVideoStopStub);
655
+ assert.calledOnce(fakeMediaRequestManagers.screenShareVideo.commit);
475
656
  });
476
657
 
477
658
  it('can be called multiple times', async () => {
@@ -482,6 +663,41 @@ describe('RemoteMediaManager', () => {
482
663
  remoteMediaManager.stop();
483
664
  });
484
665
  });
666
+
667
+ describe('setPreferLiveVideo', () => {
668
+
669
+ it('sets preferLiveVideo', async () => {
670
+ const config = cloneDeep(DefaultTestConfiguration);
671
+ let stubs = [];
672
+
673
+ config.video.initialLayoutId = 'OnePlusFive';
674
+
675
+ remoteMediaManager = new RemoteMediaManager(
676
+ fakeReceiveSlotManager,
677
+ fakeMediaRequestManagers,
678
+ config
679
+ );
680
+
681
+ remoteMediaManager.on(Event.VideoLayoutChanged, (layoutInfo: VideoLayoutChangedEventData) => {
682
+ Object.values(layoutInfo.activeSpeakerVideoPanes).forEach((group) => stubs.push(sinon.stub(group, 'setPreferLiveVideo')));
683
+ });
684
+
685
+ await remoteMediaManager.start();
686
+ resetHistory();
687
+ assert(stubs.length > 0);
688
+ await remoteMediaManager.setPreferLiveVideo(true);
689
+
690
+
691
+ stubs.forEach((stub) => {
692
+ assert.calledWith(stub, true, false)
693
+ });
694
+
695
+ expect(config.video.preferLiveVideo).to.equal(true);
696
+
697
+ assert.calledOnce(fakeMediaRequestManagers.video.commit);
698
+ });
699
+ });
700
+
485
701
  describe('setLayout', () => {
486
702
  it('rejects if called with invalid layoutId', async () => {
487
703
  await assert.isRejected(remoteMediaManager.setLayout('invalid value'));
@@ -511,9 +727,53 @@ describe('RemoteMediaManager', () => {
511
727
  await remoteMediaManager.setLayout('Stage');
512
728
 
513
729
  assert.callCount(fakeReceiveSlotManager.allocateSlot, 9);
514
- assert.alwaysCalledWith(fakeReceiveSlotManager.allocateSlot, MC.MediaType.VideoMain);
730
+ assert.alwaysCalledWith(fakeReceiveSlotManager.allocateSlot, MediaType.VideoMain);
731
+ });
732
+
733
+ it('logs layout changes - receiver selected', async () => {
734
+ const config = cloneDeep(DefaultTestConfiguration);
735
+
736
+ remoteMediaManager = new RemoteMediaManager(
737
+ fakeReceiveSlotManager,
738
+ fakeMediaRequestManagers,
739
+ config
740
+ );
741
+
742
+ await remoteMediaManager.start();
743
+
744
+ resetHistory();
745
+
746
+ await remoteMediaManager.setLayout('Stage');
747
+
748
+ assert.calledWith(
749
+ logger.log,
750
+ 'RemoteMediaManager#updateVideoReceiveSlots --> receive slots updated: 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'
751
+ );
515
752
  });
516
753
 
754
+ it('logs layout changes - active speaker', async () => {
755
+ const config = cloneDeep(DefaultTestConfiguration);
756
+ config.video.initialLayoutId = 'OnePlusFive'
757
+
758
+ remoteMediaManager = new RemoteMediaManager(
759
+ fakeReceiveSlotManager,
760
+ fakeMediaRequestManagers,
761
+ config
762
+ );
763
+
764
+ await remoteMediaManager.start();
765
+
766
+ resetHistory();
767
+
768
+ await remoteMediaManager.setLayout('AllEqual');
769
+
770
+ assert.calledWith(
771
+ logger.log,
772
+ 'RemoteMediaManager#updateVideoReceiveSlots --> receive slots updated: 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'
773
+ );
774
+ });
775
+
776
+
517
777
  it('releases slots when switching to layout that requires less active speaker slots', async () => {
518
778
  // start with "AllEqual" layout that needs just 9 video slots
519
779
  const config = cloneDeep(DefaultTestConfiguration);
@@ -538,10 +798,293 @@ describe('RemoteMediaManager', () => {
538
798
  fakeReceiveSlotManager.releaseSlot.getCalls().forEach((call) => {
539
799
  const slot = call.args[0];
540
800
 
541
- assert.strictEqual(slot.mediaType, MC.MediaType.VideoMain);
801
+ assert.strictEqual(slot.mediaType, MediaType.VideoMain);
542
802
  });
543
803
  });
544
804
 
805
+ it('releases slots and reallocates slots when switching to layouts in correct order', async () => {
806
+
807
+ const config = cloneDeep(DefaultTestConfiguration);
808
+ let count = 0;
809
+
810
+ fakeReceiveSlotManager.allocateSlot = sinon.stub().callsFake((mediaType) => {
811
+ switch (mediaType) {
812
+ case MediaType.AudioMain:
813
+ return Promise.resolve(fakeAudioSlot);
814
+ case MediaType.VideoMain:
815
+ return Promise.resolve(new FakeSlot(MediaType.VideoMain, `fake video ${count++}`));
816
+ case MediaType.AudioSlides:
817
+ return Promise.resolve(fakeScreenShareAudioSlot);
818
+ case MediaType.VideoSlides:
819
+ return Promise.resolve(fakeScreenShareVideoSlot);
820
+ }
821
+ throw new Error(`invalid mediaType: ${mediaType}`);
822
+ })
823
+
824
+ remoteMediaManager = new RemoteMediaManager(
825
+ fakeReceiveSlotManager,
826
+ fakeMediaRequestManagers,
827
+ config
828
+ );
829
+
830
+ await remoteMediaManager.start();
831
+
832
+ resetHistory();
833
+
834
+ assert.deepEqual(remoteMediaManager.slots.video.activeSpeaker.map((slot: any) => slot.id), [
835
+ "fake video 0",
836
+ "fake video 1",
837
+ "fake video 2",
838
+ "fake video 3",
839
+ "fake video 4",
840
+ "fake video 5",
841
+ "fake video 6",
842
+ "fake video 7",
843
+ "fake video 8",
844
+ ]);
845
+
846
+ assert.deepEqual(remoteMediaManager.receiveSlotAllocations.activeSpeaker["main"].slots.map((slot: any) => slot.id), [
847
+ "fake video 0",
848
+ "fake video 1",
849
+ "fake video 2",
850
+ "fake video 3",
851
+ "fake video 4",
852
+ "fake video 5",
853
+ "fake video 6",
854
+ "fake video 7",
855
+ "fake video 8",
856
+ ])
857
+
858
+ // switch to "OnePlusFive" layout that requires 3 less video slots (6)
859
+ await remoteMediaManager.setLayout('OnePlusFive');
860
+
861
+ assert.deepEqual(remoteMediaManager.slots.video.unused, []);
862
+
863
+ assert.deepEqual(remoteMediaManager.slots.video.activeSpeaker.map((slot: any) => slot.id), [
864
+ "fake video 0",
865
+ "fake video 1",
866
+ "fake video 2",
867
+ "fake video 3",
868
+ "fake video 4",
869
+ "fake video 5"
870
+ ]);
871
+
872
+ // we're checking that the slots are in the same order as in the previous layout
873
+ // first one goes into main
874
+ assert.deepEqual(remoteMediaManager.receiveSlotAllocations.activeSpeaker["mainBigOne"].slots.map((slot: any) => slot.id), [
875
+ "fake video 0",
876
+ ])
877
+ // and rest go in the pips
878
+ assert.deepEqual(remoteMediaManager.receiveSlotAllocations.activeSpeaker["secondarySetOfSmallPanes"].slots.map((slot: any) => slot.id), [
879
+ "fake video 1",
880
+ "fake video 2",
881
+ "fake video 3",
882
+ "fake video 4",
883
+ "fake video 5"
884
+ ])
885
+
886
+ // verify that 3 main video slots were released
887
+ assert.callCount(fakeReceiveSlotManager.releaseSlot, 3);
888
+ fakeReceiveSlotManager.releaseSlot.getCalls().forEach((call) => {
889
+ const slot = call.args[0];
890
+
891
+ assert.strictEqual(slot.mediaType, MediaType.VideoMain);
892
+ });
893
+
894
+ await remoteMediaManager.setLayout('AllEqual');
895
+
896
+ assert.deepEqual(remoteMediaManager.slots.video.unused, []);
897
+
898
+ // checking that slots are in the same order as in previous layout + 3 new ones
899
+ assert.deepEqual(remoteMediaManager.slots.video.activeSpeaker.map((slot: any) => slot.id), [
900
+ "fake video 0",
901
+ "fake video 1",
902
+ "fake video 2",
903
+ "fake video 3",
904
+ "fake video 4",
905
+ "fake video 5",
906
+ "fake video 10",
907
+ "fake video 11",
908
+ "fake video 12",
909
+ ]);
910
+
911
+ assert.deepEqual(remoteMediaManager.receiveSlotAllocations.activeSpeaker["main"].slots.map((slot: any) => slot.id), [
912
+ "fake video 0",
913
+ "fake video 1",
914
+ "fake video 2",
915
+ "fake video 3",
916
+ "fake video 4",
917
+ "fake video 5",
918
+ "fake video 10",
919
+ "fake video 11",
920
+ "fake video 12"
921
+ ])
922
+
923
+ // verify that 3 main video slots were allocated
924
+ assert.callCount(fakeReceiveSlotManager.allocateSlot, 3);
925
+ fakeReceiveSlotManager.allocateSlot.getCalls().forEach((call) => {
926
+ const mediaType = call.args[0];
927
+
928
+ assert.strictEqual(mediaType, MediaType.VideoMain);
929
+ });
930
+ });
931
+
932
+ it('stops all current video remoteMedia instances when switching to new layout', async () => {
933
+ const audioStopStubs = [];
934
+ const videoStopStubs = [];
935
+
936
+ const config = cloneDeep(DefaultTestConfiguration);
937
+
938
+ // start with the stage layout because it has both active speaker and receiver selected panes
939
+ config.video.initialLayoutId = 'Stage';
940
+
941
+ remoteMediaManager = new RemoteMediaManager(
942
+ fakeReceiveSlotManager,
943
+ fakeMediaRequestManagers,
944
+ config
945
+ );
946
+
947
+ // mock all stop() methods for all remote audio objects we get with AudioCreated event
948
+ remoteMediaManager.on(Event.AudioCreated, (audio: RemoteMediaGroup) => {
949
+ audio
950
+ .getRemoteMedia()
951
+ .forEach((remoteAudio) => audioStopStubs.push(sinon.stub(remoteAudio, 'stop')));
952
+ });
953
+
954
+ // mock all stop() methods for all remote video objects we get with VideoLayoutChanged event
955
+ remoteMediaManager.on(Event.VideoLayoutChanged, (layoutInfo: VideoLayoutChangedEventData) => {
956
+ Object.values(layoutInfo.activeSpeakerVideoPanes).forEach((group) =>
957
+ group
958
+ .getRemoteMedia()
959
+ .forEach((remoteMedia) => videoStopStubs.push(sinon.stub(remoteMedia, 'stop')))
960
+ );
961
+
962
+ Object.values(layoutInfo.memberVideoPanes).forEach((pane) => {
963
+ videoStopStubs.push(sinon.stub(pane, 'stop'));
964
+ });
965
+ });
966
+
967
+ await remoteMediaManager.start();
968
+
969
+ // sanity check that we've got all our stop() mocks setup correctly
970
+ assert.strictEqual(audioStopStubs.length, 3);
971
+ assert.strictEqual(videoStopStubs.length, 10); // 10 = 6 thumbnail panes + 4 stage panes
972
+
973
+ // next, we'll change the layout, we don't care about the new video panes from the new layout, so unregister the event listeners
974
+ remoteMediaManager.removeAllListeners();
975
+
976
+ await remoteMediaManager.setLayout('AllEqual');
977
+
978
+ // check that NONE of the audio RemoteMedia instances were stopped
979
+ audioStopStubs.forEach((audioStopStub) => {
980
+ assert.notCalled(audioStopStub);
981
+ });
982
+
983
+ // check that ALL of the video RemoteMedia instances were stopped
984
+ videoStopStubs.forEach((videoStopStub) => {
985
+ assert.calledOnce(videoStopStub);
986
+ assert.calledWith(videoStopStub, false);
987
+ });
988
+ });
989
+
990
+ it('emits Event.VideoLayoutChanged with correct data', async () => {
991
+ // setup the initial layout to be empty and a testLayout that has screen share, active speaker groups and member video panes
992
+ const config: Configuration = {
993
+ audio: {
994
+ numOfActiveSpeakerStreams: 0,
995
+ numOfScreenShareStreams: 0,
996
+ },
997
+ video: {
998
+ preferLiveVideo: true,
999
+ initialLayoutId: 'empty',
1000
+ layouts: {
1001
+ empty: {},
1002
+ testLayout: {
1003
+ screenShareVideo: {size: 'very small'},
1004
+ activeSpeakerVideoPaneGroups: [
1005
+ {
1006
+ id: 'big',
1007
+ numPanes: 10,
1008
+ priority: 255,
1009
+ size: 'large',
1010
+ },
1011
+ {
1012
+ id: 'small',
1013
+ numPanes: 3,
1014
+ priority: 254,
1015
+ size: 'medium',
1016
+ },
1017
+ ],
1018
+ memberVideoPanes: [
1019
+ {id: 'pane 1', size: 'best', csi: 555},
1020
+ {id: 'pane 2', size: 'best', csi: undefined},
1021
+ ],
1022
+ },
1023
+ },
1024
+ },
1025
+ };
1026
+
1027
+ remoteMediaManager = new RemoteMediaManager(
1028
+ fakeReceiveSlotManager,
1029
+ fakeMediaRequestManagers,
1030
+ config
1031
+ );
1032
+
1033
+ await remoteMediaManager.start();
1034
+
1035
+ resetHistory();
1036
+
1037
+ let receivedLayoutInfo: VideoLayoutChangedEventData | null = null;
1038
+
1039
+ remoteMediaManager.on(Event.VideoLayoutChanged, (layoutInfo) => {
1040
+ receivedLayoutInfo = layoutInfo;
1041
+ });
1042
+
1043
+ // switch to the test layout
1044
+ await remoteMediaManager.setLayout('testLayout');
1045
+
1046
+ assert.isNotNull(receivedLayoutInfo);
1047
+
1048
+ if (receivedLayoutInfo) {
1049
+ assert.strictEqual(receivedLayoutInfo.layoutId, 'testLayout');
1050
+
1051
+ // check screen share video
1052
+ assert.isTrue(!!receivedLayoutInfo.screenShareVideo);
1053
+ assert.strictEqual(receivedLayoutInfo.screenShareVideo.mediaType, MediaType.VideoSlides);
1054
+
1055
+ // check member videos
1056
+ assert.strictEqual(Object.keys(receivedLayoutInfo.memberVideoPanes).length, 2);
1057
+ Object.values(receivedLayoutInfo.memberVideoPanes).forEach((remoteMedia) =>
1058
+ assert.strictEqual(remoteMedia.mediaType, MediaType.VideoMain)
1059
+ );
1060
+
1061
+ // check the 2 active speaker groups
1062
+ assert.strictEqual(Object.keys(receivedLayoutInfo.activeSpeakerVideoPanes).length, 2);
1063
+
1064
+ // "big" group
1065
+ assert.strictEqual(
1066
+ receivedLayoutInfo.activeSpeakerVideoPanes.big.getRemoteMedia().length,
1067
+ 10
1068
+ );
1069
+ receivedLayoutInfo.activeSpeakerVideoPanes.big
1070
+ .getRemoteMedia()
1071
+ .forEach((remoteMedia) =>
1072
+ assert.strictEqual(remoteMedia.mediaType, MediaType.VideoMain)
1073
+ );
1074
+
1075
+ // "small" group
1076
+ assert.strictEqual(
1077
+ receivedLayoutInfo.activeSpeakerVideoPanes.small.getRemoteMedia().length,
1078
+ 3
1079
+ );
1080
+ receivedLayoutInfo.activeSpeakerVideoPanes.small
1081
+ .getRemoteMedia()
1082
+ .forEach((remoteMedia) =>
1083
+ assert.strictEqual(remoteMedia.mediaType, MediaType.VideoMain)
1084
+ );
1085
+ }
1086
+ });
1087
+
545
1088
  describe('switching between different receiver selected layouts', () => {
546
1089
  let fakeSlots: {[key: ReceiveSlotId]: FakeSlot};
547
1090
  let slotCounter: number;
@@ -562,7 +1105,7 @@ describe('RemoteMediaManager', () => {
562
1105
  slotCounter += 1;
563
1106
  const newSlotId = `fake video slot ${slotCounter}`;
564
1107
 
565
- fakeSlots[newSlotId] = new FakeSlot(MC.MediaType.VideoMain, newSlotId);
1108
+ fakeSlots[newSlotId] = new FakeSlot(MediaType.VideoMain, newSlotId);
566
1109
  return fakeSlots[newSlotId];
567
1110
  });
568
1111
 
@@ -594,12 +1137,12 @@ describe('RemoteMediaManager', () => {
594
1137
  // This test starts with a layout that has 5 receiver selected video slots
595
1138
  // and switches to a different layout that has fewer slots, but 2 of them match CSIs
596
1139
  // from the initial layout. We want to verify that these 2 slots get re-used correctly.
1140
+ // There are no screen share or audio slots being used in this test.
1141
+ delete config.video.layouts.ScreenShareView;
597
1142
  config.audio.numOfActiveSpeakerStreams = 0;
598
- config.screenShare.audio = false;
599
- config.screenShare.video = false;
1143
+ config.audio.numOfScreenShareStreams = 0;
600
1144
  config.video.initialLayoutId = 'biggerLayout';
601
1145
  config.video.layouts['biggerLayout'] = {
602
- screenShareVideo: {size: null},
603
1146
  memberVideoPanes: [
604
1147
  {id: '1', size: 'best', csi: 100},
605
1148
  {id: '2', size: 'best', csi: 200},
@@ -609,7 +1152,6 @@ describe('RemoteMediaManager', () => {
609
1152
  ],
610
1153
  };
611
1154
  config.video.layouts['smallerLayout'] = {
612
- screenShareVideo: {size: null},
613
1155
  memberVideoPanes: [
614
1156
  {id: '1', size: 'medium', csi: 200}, // this csi matches pane '2' from biggerLayout
615
1157
  {id: '2', size: 'medium', csi: 123},
@@ -659,16 +1201,15 @@ describe('RemoteMediaManager', () => {
659
1201
  // This test starts with a layout that has video slot with a specific CSI
660
1202
  // and switches to a different layout that 2 panes with that same CSI.
661
1203
  // We want to verify that the slot gets reused, but also that a 2nd slot is allocated.
1204
+ // There are no screen share or audio slots being used in this test.
1205
+ delete config.video.layouts.ScreenShareView;
662
1206
  config.audio.numOfActiveSpeakerStreams = 0;
663
- config.screenShare.audio = false;
664
- config.screenShare.video = false;
1207
+ config.audio.numOfScreenShareStreams = 0;
665
1208
  config.video.initialLayoutId = 'initialEmptyLayout';
666
1209
  config.video.layouts['initialEmptyLayout'] = {
667
- screenShareVideo: {size: null},
668
1210
  memberVideoPanes: [{id: '2', size: 'medium', csi: 456}],
669
1211
  };
670
1212
  config.video.layouts['layoutWithDuplicateCSIs'] = {
671
- screenShareVideo: {size: null},
672
1213
  memberVideoPanes: [
673
1214
  {id: '1', size: 'medium', csi: 123},
674
1215
  {id: '2', size: 'medium', csi: 456},
@@ -841,16 +1382,18 @@ describe('RemoteMediaManager', () => {
841
1382
  });
842
1383
 
843
1384
  it('cancels all media requests for the previous layout when switching to a new one', async () => {
1385
+ // setup the initial layout to have screen share, active speaker groups and member video panes
844
1386
  const config: Configuration = {
845
1387
  audio: {
846
1388
  numOfActiveSpeakerStreams: 0,
1389
+ numOfScreenShareStreams: 0,
847
1390
  },
848
1391
  video: {
849
1392
  preferLiveVideo: true,
850
1393
  initialLayoutId: 'initial',
851
1394
  layouts: {
852
1395
  initial: {
853
- screenShareVideo: {size: null},
1396
+ screenShareVideo: {size: 'best'},
854
1397
  activeSpeakerVideoPaneGroups: [
855
1398
  {
856
1399
  id: 'big',
@@ -870,15 +1413,9 @@ describe('RemoteMediaManager', () => {
870
1413
  {id: 'pane 2', size: 'best', csi: 234},
871
1414
  ],
872
1415
  },
873
- other: {
874
- screenShareVideo: {size: null},
875
- },
1416
+ other: {},
876
1417
  },
877
1418
  },
878
- screenShare: {
879
- audio: false,
880
- video: false,
881
- },
882
1419
  };
883
1420
 
884
1421
  remoteMediaManager = new RemoteMediaManager(
@@ -901,9 +1438,15 @@ describe('RemoteMediaManager', () => {
901
1438
 
902
1439
  return `receiver selected request ${receiverSelectedRequestCounter}`;
903
1440
  });
1441
+ // setup the mock for screen share addRequest - this one should be called just once
1442
+ fakeMediaRequestManagers.screenShareVideo.addRequest.callsFake(() => {
1443
+ return 'video screen share request id';
1444
+ });
904
1445
 
905
1446
  await remoteMediaManager.start();
906
1447
 
1448
+ assert.calledOnce(fakeMediaRequestManagers.screenShareVideo.addRequest);
1449
+
907
1450
  resetHistory();
908
1451
 
909
1452
  // switch to "other" layout
@@ -921,11 +1464,45 @@ describe('RemoteMediaManager', () => {
921
1464
  fakeMediaRequestManagers.video.cancelRequest,
922
1465
  'receiver selected request 2'
923
1466
  );
1467
+ assert.calledOnce(fakeMediaRequestManagers.screenShareVideo.cancelRequest);
1468
+ assert.calledWith(
1469
+ fakeMediaRequestManagers.screenShareVideo.cancelRequest,
1470
+ 'video screen share request id'
1471
+ );
924
1472
 
925
1473
  // 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
1474
  assert.callCount(fakeMediaRequestManagers.video.addRequest, 0);
928
1475
  });
1476
+
1477
+ it('sends media request for screen share if layout contains screen share', async () => {
1478
+ const allEqualMediaRequestId = 'fake request id';
1479
+
1480
+ fakeMediaRequestManagers.video.addRequest.returns(allEqualMediaRequestId);
1481
+
1482
+ await remoteMediaManager.start();
1483
+
1484
+ resetHistory();
1485
+
1486
+ // switch to a layout that contains a screen share video pane
1487
+ await remoteMediaManager.setLayout('ScreenShareView');
1488
+
1489
+ // check that a correct active speaker media request for screen share has been sent out
1490
+ assert.callCount(fakeMediaRequestManagers.screenShareVideo.addRequest, 1);
1491
+ assert.calledWith(
1492
+ fakeMediaRequestManagers.screenShareVideo.addRequest,
1493
+ sinon.match({
1494
+ policyInfo: sinon.match({
1495
+ policy: 'active-speaker',
1496
+ priority: 255,
1497
+ }),
1498
+ receiveSlots: [fakeScreenShareVideoSlot],
1499
+ codecInfo: sinon.match({
1500
+ codec: 'h264',
1501
+ maxFs: 3600,
1502
+ }),
1503
+ })
1504
+ );
1505
+ });
929
1506
  });
930
1507
  });
931
1508
 
@@ -1065,7 +1642,7 @@ describe('RemoteMediaManager', () => {
1065
1642
 
1066
1643
  // new slot should be allocated
1067
1644
  assert.calledOnce(fakeReceiveSlotManager.allocateSlot);
1068
- assert.calledWith(fakeReceiveSlotManager.allocateSlot, MC.MediaType.VideoMain);
1645
+ assert.calledWith(fakeReceiveSlotManager.allocateSlot, MediaType.VideoMain);
1069
1646
 
1070
1647
  // and a media request sent out
1071
1648
  assert.calledOnce(fakeMediaRequestManagers.video.addRequest);
@@ -1094,7 +1671,7 @@ describe('RemoteMediaManager', () => {
1094
1671
 
1095
1672
  // new slot should be allocated
1096
1673
  assert.calledOnce(fakeReceiveSlotManager.allocateSlot);
1097
- assert.calledWith(fakeReceiveSlotManager.allocateSlot, MC.MediaType.VideoMain);
1674
+ assert.calledWith(fakeReceiveSlotManager.allocateSlot, MediaType.VideoMain);
1098
1675
 
1099
1676
  // but no media requests sent out
1100
1677
  assert.notCalled(fakeMediaRequestManagers.video.addRequest);
@@ -1123,7 +1700,7 @@ describe('RemoteMediaManager', () => {
1123
1700
  await remoteMediaManager.start();
1124
1701
  await remoteMediaManager.setLayout('Stage');
1125
1702
 
1126
- const fakeNewSlot = new FakeSlot(MC.MediaType.VideoMain, 'fake video slot');
1703
+ const fakeNewSlot = new FakeSlot(MediaType.VideoMain, 'fake video slot');
1127
1704
  const fakeRequestId = 'fake request id';
1128
1705
 
1129
1706
  fakeReceiveSlotManager.allocateSlot.resolves(fakeNewSlot);
@@ -1147,6 +1724,94 @@ describe('RemoteMediaManager', () => {
1147
1724
  });
1148
1725
  });
1149
1726
 
1727
+ describe('setActiveSpeakerCsis', () => {
1728
+ it('calls setActiveSpeakerCsis on the correct remote media group', async () => {
1729
+ let currentLayoutInfo: VideoLayoutChangedEventData | null = null;
1730
+ let setCsisStub;
1731
+
1732
+ remoteMediaManager.on(Event.VideoLayoutChanged, (layoutInfo: VideoLayoutChangedEventData) => {
1733
+ currentLayoutInfo = layoutInfo;
1734
+ setCsisStub = sinon.stub(layoutInfo.activeSpeakerVideoPanes.main, 'setActiveSpeakerCsis');
1735
+ });
1736
+
1737
+ await remoteMediaManager.start();
1738
+ resetHistory();
1739
+
1740
+ assert.isNotNull(currentLayoutInfo);
1741
+
1742
+ if (currentLayoutInfo) {
1743
+ const remoteVideo = currentLayoutInfo.activeSpeakerVideoPanes.main.getRemoteMedia()[0];
1744
+
1745
+ remoteMediaManager.setActiveSpeakerCsis([{remoteMedia: remoteVideo}]);
1746
+
1747
+ assert.calledOnce(setCsisStub);
1748
+ assert.calledWith(setCsisStub, [{remoteMedia: remoteVideo}], false);
1749
+ assert.calledOnce(fakeMediaRequestManagers.video.commit);
1750
+ }
1751
+ });
1752
+
1753
+ it('does not call setActiveSpeakerCsis on the incorrect media group', async () => {
1754
+ let currentLayoutInfo: VideoLayoutChangedEventData | null = null;
1755
+ let setCsisStub;
1756
+
1757
+ remoteMediaManager.on(Event.VideoLayoutChanged, (layoutInfo: VideoLayoutChangedEventData) => {
1758
+ currentLayoutInfo = layoutInfo;
1759
+ setCsisStub = sinon.stub(layoutInfo.activeSpeakerVideoPanes.main, 'setActiveSpeakerCsis');
1760
+ });
1761
+
1762
+ await remoteMediaManager.start();
1763
+ resetHistory();
1764
+
1765
+ assert.isNotNull(currentLayoutInfo);
1766
+
1767
+ if (currentLayoutInfo) {
1768
+ remoteMediaManager.setActiveSpeakerCsis([{remoteMedia: {}}]);
1769
+
1770
+ assert.notCalled(setCsisStub);
1771
+ assert.calledOnce(fakeMediaRequestManagers.video.commit);
1772
+ }
1773
+ });
1774
+
1775
+ it('checking when there is more than one group', async () => {
1776
+ let currentLayoutInfo: VideoLayoutChangedEventData | null = null;
1777
+ const config = cloneDeep(DefaultTestConfiguration);
1778
+ let stubs = [];
1779
+
1780
+ config.video.initialLayoutId = 'OnePlusFive';
1781
+
1782
+ remoteMediaManager = new RemoteMediaManager(
1783
+ fakeReceiveSlotManager,
1784
+ fakeMediaRequestManagers,
1785
+ config
1786
+ );
1787
+
1788
+ remoteMediaManager.on(Event.VideoLayoutChanged, (layoutInfo: VideoLayoutChangedEventData) => {
1789
+ currentLayoutInfo = layoutInfo;
1790
+ Object.values(layoutInfo.activeSpeakerVideoPanes).forEach((group) => stubs.push(sinon.stub(group, 'setActiveSpeakerCsis')));
1791
+ });
1792
+
1793
+ await remoteMediaManager.start();
1794
+ resetHistory();
1795
+
1796
+ assert.isNotNull(currentLayoutInfo);
1797
+
1798
+ if (currentLayoutInfo) {
1799
+
1800
+ const remoteMedia1 = currentLayoutInfo.activeSpeakerVideoPanes.mainBigOne.getRemoteMedia()[0];
1801
+ const remoteMedia2 = currentLayoutInfo.activeSpeakerVideoPanes.secondarySetOfSmallPanes.getRemoteMedia()[0];
1802
+
1803
+ const remoteMediaCsis = [{remoteMedia: remoteMedia1}, {remoteMedia: remoteMedia2}];
1804
+
1805
+ remoteMediaManager.setActiveSpeakerCsis([{remoteMedia: remoteMedia1}, {remoteMedia: remoteMedia2}]);
1806
+
1807
+ stubs.forEach((stub, index) => {
1808
+ assert.calledWith(stub, [remoteMediaCsis[index]], false)
1809
+ });
1810
+ assert.calledOnce(fakeMediaRequestManagers.video.commit);
1811
+ }
1812
+ });
1813
+ });
1814
+
1150
1815
  describe('pinActiveSpeakerVideoPane() and isPinned()', () => {
1151
1816
  it('throws if called on a pane not belonging to an active speaker group', async () => {
1152
1817
  let currentLayoutInfo: VideoLayoutChangedEventData | null = null;