@webex/plugin-meetings 3.0.0-beta.3 → 3.0.0-beta.300

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