@webex/plugin-meetings 3.0.0-beta.13 → 3.0.0-beta.130

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 (519) hide show
  1. package/README.md +45 -1
  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 +48 -0
  7. package/dist/annotation/constants.js.map +1 -0
  8. package/dist/annotation/index.js +355 -0
  9. package/dist/annotation/index.js.map +1 -0
  10. package/dist/breakouts/breakout.js +193 -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 +43 -0
  17. package/dist/breakouts/events.js.map +1 -0
  18. package/dist/breakouts/index.js +994 -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 +5 -26
  31. package/dist/common/errors/captcha-error.js.map +1 -1
  32. package/dist/common/errors/intent-to-join.js +5 -26
  33. package/dist/common/errors/intent-to-join.js.map +1 -1
  34. package/dist/common/errors/join-meeting.js +6 -27
  35. package/dist/common/errors/join-meeting.js.map +1 -1
  36. package/dist/common/errors/media.js +5 -26
  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 +5 -26
  41. package/dist/common/errors/password-error.js.map +1 -1
  42. package/dist/common/errors/permission.js +4 -25
  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 +5 -26
  47. package/dist/common/errors/reconnection.js.map +1 -1
  48. package/dist/common/errors/stats.js +5 -26
  49. package/dist/common/errors/stats.js.map +1 -1
  50. package/dist/common/errors/webex-errors.js +6 -41
  51. package/dist/common/errors/webex-errors.js.map +1 -1
  52. package/dist/common/errors/webex-meetings-error.js +1 -24
  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 +35 -61
  67. package/dist/common/logs/request.js.map +1 -1
  68. package/dist/common/queue.js +4 -14
  69. package/dist/common/queue.js.map +1 -1
  70. package/dist/config.js +6 -6
  71. package/dist/config.js.map +1 -1
  72. package/dist/constants.js +201 -53
  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 +294 -0
  83. package/dist/controls-options-manager/util.js.map +1 -0
  84. package/dist/index.js +72 -17
  85. package/dist/index.js.map +1 -1
  86. package/dist/locus-info/controlsUtils.js +100 -29
  87. package/dist/locus-info/controlsUtils.js.map +1 -1
  88. package/dist/locus-info/embeddedAppsUtils.js +3 -26
  89. package/dist/locus-info/embeddedAppsUtils.js.map +1 -1
  90. package/dist/locus-info/fullState.js +0 -15
  91. package/dist/locus-info/fullState.js.map +1 -1
  92. package/dist/locus-info/hostUtils.js +4 -12
  93. package/dist/locus-info/hostUtils.js.map +1 -1
  94. package/dist/locus-info/index.js +392 -212
  95. package/dist/locus-info/index.js.map +1 -1
  96. package/dist/locus-info/infoUtils.js +0 -38
  97. package/dist/locus-info/infoUtils.js.map +1 -1
  98. package/dist/locus-info/mediaSharesUtils.js +54 -38
  99. package/dist/locus-info/mediaSharesUtils.js.map +1 -1
  100. package/dist/locus-info/parser.js +88 -123
  101. package/dist/locus-info/parser.js.map +1 -1
  102. package/dist/locus-info/selfUtils.js +99 -91
  103. package/dist/locus-info/selfUtils.js.map +1 -1
  104. package/dist/media/index.js +55 -165
  105. package/dist/media/index.js.map +1 -1
  106. package/dist/media/properties.js +71 -117
  107. package/dist/media/properties.js.map +1 -1
  108. package/dist/media/util.js +2 -9
  109. package/dist/media/util.js.map +1 -1
  110. package/dist/mediaQualityMetrics/config.js +505 -495
  111. package/dist/mediaQualityMetrics/config.js.map +1 -1
  112. package/dist/meeting/in-meeting-actions.js +77 -14
  113. package/dist/meeting/in-meeting-actions.js.map +1 -1
  114. package/dist/meeting/index.js +2597 -2464
  115. package/dist/meeting/index.js.map +1 -1
  116. package/dist/meeting/locusMediaRequest.js +291 -0
  117. package/dist/meeting/locusMediaRequest.js.map +1 -0
  118. package/dist/meeting/muteState.js +292 -138
  119. package/dist/meeting/muteState.js.map +1 -1
  120. package/dist/meeting/request.js +315 -336
  121. package/dist/meeting/request.js.map +1 -1
  122. package/dist/meeting/request.type.js +7 -0
  123. package/dist/meeting/request.type.js.map +1 -0
  124. package/dist/meeting/state.js +21 -31
  125. package/dist/meeting/state.js.map +1 -1
  126. package/dist/meeting/util.js +463 -583
  127. package/dist/meeting/util.js.map +1 -1
  128. package/dist/meeting-info/collection.js +3 -25
  129. package/dist/meeting-info/collection.js.map +1 -1
  130. package/dist/meeting-info/index.js +10 -33
  131. package/dist/meeting-info/index.js.map +1 -1
  132. package/dist/meeting-info/meeting-info-v2.js +305 -286
  133. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  134. package/dist/meeting-info/request.js +1 -16
  135. package/dist/meeting-info/request.js.map +1 -1
  136. package/dist/meeting-info/util.js +98 -183
  137. package/dist/meeting-info/util.js.map +1 -1
  138. package/dist/meeting-info/utilv2.js +156 -232
  139. package/dist/meeting-info/utilv2.js.map +1 -1
  140. package/dist/meetings/collection.js +24 -20
  141. package/dist/meetings/collection.js.map +1 -1
  142. package/dist/meetings/index.js +692 -593
  143. package/dist/meetings/index.js.map +1 -1
  144. package/dist/meetings/request.js +23 -42
  145. package/dist/meetings/request.js.map +1 -1
  146. package/dist/meetings/util.js +186 -155
  147. package/dist/meetings/util.js.map +1 -1
  148. package/dist/member/index.js +89 -88
  149. package/dist/member/index.js.map +1 -1
  150. package/dist/member/types.js +15 -0
  151. package/dist/member/types.js.map +1 -0
  152. package/dist/member/util.js +101 -69
  153. package/dist/member/util.js.map +1 -1
  154. package/dist/members/collection.js +12 -12
  155. package/dist/members/collection.js.map +1 -1
  156. package/dist/members/index.js +166 -205
  157. package/dist/members/index.js.map +1 -1
  158. package/dist/members/request.js +120 -85
  159. package/dist/members/request.js.map +1 -1
  160. package/dist/members/types.js +15 -0
  161. package/dist/members/types.js.map +1 -0
  162. package/dist/members/util.js +314 -260
  163. package/dist/members/util.js.map +1 -1
  164. package/dist/metrics/config.js +50 -16
  165. package/dist/metrics/config.js.map +1 -1
  166. package/dist/metrics/constants.js +4 -7
  167. package/dist/metrics/constants.js.map +1 -1
  168. package/dist/metrics/index.js +93 -162
  169. package/dist/metrics/index.js.map +1 -1
  170. package/dist/multistream/mediaRequestManager.js +167 -50
  171. package/dist/multistream/mediaRequestManager.js.map +1 -1
  172. package/dist/multistream/receiveSlot.js +58 -65
  173. package/dist/multistream/receiveSlot.js.map +1 -1
  174. package/dist/multistream/receiveSlotManager.js +74 -93
  175. package/dist/multistream/receiveSlotManager.js.map +1 -1
  176. package/dist/multistream/remoteMedia.js +55 -74
  177. package/dist/multistream/remoteMedia.js.map +1 -1
  178. package/dist/multistream/remoteMediaGroup.js +6 -40
  179. package/dist/multistream/remoteMediaGroup.js.map +1 -1
  180. package/dist/multistream/remoteMediaManager.js +466 -442
  181. package/dist/multistream/remoteMediaManager.js.map +1 -1
  182. package/dist/networkQualityMonitor/index.js +32 -59
  183. package/dist/networkQualityMonitor/index.js.map +1 -1
  184. package/dist/personal-meeting-room/index.js +10 -45
  185. package/dist/personal-meeting-room/index.js.map +1 -1
  186. package/dist/personal-meeting-room/request.js +2 -33
  187. package/dist/personal-meeting-room/request.js.map +1 -1
  188. package/dist/personal-meeting-room/util.js +0 -13
  189. package/dist/personal-meeting-room/util.js.map +1 -1
  190. package/dist/reachability/index.js +190 -199
  191. package/dist/reachability/index.js.map +1 -1
  192. package/dist/reachability/request.js +14 -23
  193. package/dist/reachability/request.js.map +1 -1
  194. package/dist/reactions/constants.js +13 -0
  195. package/dist/reactions/constants.js.map +1 -0
  196. package/dist/reactions/reactions.js +2 -4
  197. package/dist/reactions/reactions.js.map +1 -1
  198. package/dist/reactions/reactions.type.js +19 -23
  199. package/dist/reactions/reactions.type.js.map +1 -1
  200. package/dist/reconnection-manager/index.js +326 -465
  201. package/dist/reconnection-manager/index.js.map +1 -1
  202. package/dist/recording-controller/enums.js +17 -0
  203. package/dist/recording-controller/enums.js.map +1 -0
  204. package/dist/recording-controller/index.js +343 -0
  205. package/dist/recording-controller/index.js.map +1 -0
  206. package/dist/recording-controller/util.js +63 -0
  207. package/dist/recording-controller/util.js.map +1 -0
  208. package/dist/roap/index.js +31 -75
  209. package/dist/roap/index.js.map +1 -1
  210. package/dist/roap/request.js +129 -136
  211. package/dist/roap/request.js.map +1 -1
  212. package/dist/roap/turnDiscovery.js +143 -103
  213. package/dist/roap/turnDiscovery.js.map +1 -1
  214. package/dist/statsAnalyzer/global.js +1 -95
  215. package/dist/statsAnalyzer/global.js.map +1 -1
  216. package/dist/statsAnalyzer/index.js +369 -461
  217. package/dist/statsAnalyzer/index.js.map +1 -1
  218. package/dist/statsAnalyzer/mqaUtil.js +144 -94
  219. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  220. package/dist/transcription/index.js +13 -45
  221. package/dist/transcription/index.js.map +1 -1
  222. package/dist/types/annotation/annotation.types.d.ts +35 -0
  223. package/dist/types/annotation/constants.d.ts +31 -0
  224. package/dist/types/annotation/index.d.ts +124 -0
  225. package/dist/types/breakouts/breakout.d.ts +8 -0
  226. package/dist/types/breakouts/collection.d.ts +5 -0
  227. package/dist/types/breakouts/edit-lock-error.d.ts +15 -0
  228. package/dist/types/breakouts/events.d.ts +2 -0
  229. package/dist/types/breakouts/index.d.ts +5 -0
  230. package/dist/types/breakouts/request.d.ts +22 -0
  231. package/dist/types/breakouts/utils.d.ts +15 -0
  232. package/dist/types/common/browser-detection.d.ts +9 -0
  233. package/dist/types/common/collection.d.ts +48 -0
  234. package/dist/types/common/config.d.ts +2 -0
  235. package/dist/types/common/errors/captcha-error.d.ts +15 -0
  236. package/dist/types/common/errors/intent-to-join.d.ts +16 -0
  237. package/dist/types/common/errors/join-meeting.d.ts +17 -0
  238. package/dist/types/common/errors/media.d.ts +15 -0
  239. package/dist/types/common/errors/parameter.d.ts +15 -0
  240. package/dist/types/common/errors/password-error.d.ts +15 -0
  241. package/dist/types/common/errors/permission.d.ts +14 -0
  242. package/dist/types/common/errors/reconnection-in-progress.d.ts +9 -0
  243. package/dist/types/common/errors/reconnection.d.ts +15 -0
  244. package/dist/types/common/errors/stats.d.ts +15 -0
  245. package/dist/types/common/errors/webex-errors.d.ts +69 -0
  246. package/dist/types/common/errors/webex-meetings-error.d.ts +20 -0
  247. package/dist/types/common/events/events-scope.d.ts +17 -0
  248. package/dist/types/common/events/events.d.ts +12 -0
  249. package/dist/types/common/events/trigger-proxy.d.ts +2 -0
  250. package/dist/types/common/events/util.d.ts +2 -0
  251. package/dist/types/common/logs/logger-config.d.ts +2 -0
  252. package/dist/types/common/logs/logger-proxy.d.ts +2 -0
  253. package/dist/types/common/logs/request.d.ts +34 -0
  254. package/dist/types/common/queue.d.ts +32 -0
  255. package/dist/types/config.d.ts +78 -0
  256. package/dist/types/constants.d.ts +991 -0
  257. package/dist/types/controls-options-manager/constants.d.ts +4 -0
  258. package/dist/types/controls-options-manager/enums.d.ts +15 -0
  259. package/dist/types/controls-options-manager/index.d.ts +136 -0
  260. package/dist/types/controls-options-manager/types.d.ts +43 -0
  261. package/dist/types/controls-options-manager/util.d.ts +1 -0
  262. package/dist/types/index.d.ts +7 -0
  263. package/dist/types/locus-info/controlsUtils.d.ts +2 -0
  264. package/dist/types/locus-info/embeddedAppsUtils.d.ts +2 -0
  265. package/dist/types/locus-info/fullState.d.ts +2 -0
  266. package/dist/types/locus-info/hostUtils.d.ts +2 -0
  267. package/dist/types/locus-info/index.d.ts +315 -0
  268. package/dist/types/locus-info/infoUtils.d.ts +2 -0
  269. package/dist/types/locus-info/mediaSharesUtils.d.ts +2 -0
  270. package/dist/types/locus-info/parser.d.ts +212 -0
  271. package/dist/types/locus-info/selfUtils.d.ts +2 -0
  272. package/dist/types/media/index.d.ts +34 -0
  273. package/dist/types/media/properties.d.ts +108 -0
  274. package/dist/types/media/util.d.ts +2 -0
  275. package/dist/types/mediaQualityMetrics/config.d.ts +365 -0
  276. package/dist/types/meeting/in-meeting-actions.d.ts +147 -0
  277. package/dist/types/meeting/index.d.ts +1762 -0
  278. package/dist/types/meeting/locusMediaRequest.d.ts +70 -0
  279. package/dist/types/meeting/muteState.d.ts +186 -0
  280. package/dist/types/meeting/request.d.ts +269 -0
  281. package/dist/types/meeting/request.type.d.ts +11 -0
  282. package/dist/types/meeting/state.d.ts +9 -0
  283. package/dist/types/meeting/util.d.ts +76 -0
  284. package/dist/types/meeting-info/collection.d.ts +20 -0
  285. package/dist/types/meeting-info/index.d.ts +57 -0
  286. package/dist/types/meeting-info/meeting-info-v2.d.ts +122 -0
  287. package/dist/types/meeting-info/request.d.ts +22 -0
  288. package/dist/types/meeting-info/util.d.ts +2 -0
  289. package/dist/types/meeting-info/utilv2.d.ts +2 -0
  290. package/dist/types/meetings/collection.d.ts +31 -0
  291. package/dist/types/meetings/index.d.ts +345 -0
  292. package/dist/types/meetings/request.d.ts +27 -0
  293. package/dist/types/meetings/util.d.ts +18 -0
  294. package/dist/types/member/index.d.ts +157 -0
  295. package/dist/types/member/types.d.ts +21 -0
  296. package/dist/types/member/util.d.ts +2 -0
  297. package/dist/types/members/collection.d.ts +29 -0
  298. package/dist/types/members/index.d.ts +353 -0
  299. package/dist/types/members/request.d.ts +114 -0
  300. package/dist/types/members/types.d.ts +24 -0
  301. package/dist/types/members/util.d.ts +210 -0
  302. package/dist/types/metrics/config.d.ts +195 -0
  303. package/dist/types/metrics/constants.d.ts +55 -0
  304. package/dist/types/metrics/index.d.ts +169 -0
  305. package/dist/types/multistream/mediaRequestManager.d.ts +101 -0
  306. package/dist/types/multistream/receiveSlot.d.ts +68 -0
  307. package/dist/types/multistream/receiveSlotManager.d.ts +56 -0
  308. package/dist/types/multistream/remoteMedia.d.ts +72 -0
  309. package/dist/types/multistream/remoteMediaGroup.d.ts +47 -0
  310. package/dist/types/multistream/remoteMediaManager.d.ts +263 -0
  311. package/dist/types/networkQualityMonitor/index.d.ts +70 -0
  312. package/dist/types/personal-meeting-room/index.d.ts +47 -0
  313. package/dist/types/personal-meeting-room/request.d.ts +14 -0
  314. package/dist/types/personal-meeting-room/util.d.ts +2 -0
  315. package/dist/types/reachability/index.d.ts +152 -0
  316. package/dist/types/reachability/request.d.ts +37 -0
  317. package/dist/types/reactions/constants.d.ts +3 -0
  318. package/dist/types/reactions/reactions.d.ts +4 -0
  319. package/dist/types/reactions/reactions.type.d.ts +52 -0
  320. package/dist/types/reconnection-manager/index.d.ts +126 -0
  321. package/dist/types/recording-controller/enums.d.ts +7 -0
  322. package/dist/types/recording-controller/index.d.ts +193 -0
  323. package/dist/types/recording-controller/util.d.ts +13 -0
  324. package/dist/types/roap/index.d.ts +77 -0
  325. package/dist/types/roap/request.d.ts +36 -0
  326. package/dist/types/roap/turnDiscovery.d.ts +91 -0
  327. package/dist/types/statsAnalyzer/global.d.ts +36 -0
  328. package/dist/types/statsAnalyzer/index.d.ts +200 -0
  329. package/dist/types/statsAnalyzer/mqaUtil.d.ts +24 -0
  330. package/dist/types/transcription/index.d.ts +64 -0
  331. package/internal-README.md +7 -6
  332. package/package.json +28 -21
  333. package/src/annotation/annotation.types.ts +42 -0
  334. package/src/annotation/constants.ts +36 -0
  335. package/src/annotation/index.ts +339 -0
  336. package/src/breakouts/README.md +220 -0
  337. package/src/breakouts/breakout.ts +163 -0
  338. package/src/breakouts/collection.ts +19 -0
  339. package/src/breakouts/edit-lock-error.ts +25 -0
  340. package/src/breakouts/events.ts +37 -0
  341. package/src/breakouts/index.ts +860 -0
  342. package/src/breakouts/request.ts +55 -0
  343. package/src/breakouts/utils.ts +57 -0
  344. package/src/common/browser-detection.ts +9 -6
  345. package/src/common/collection.ts +3 -1
  346. package/src/common/errors/captcha-error.ts +6 -6
  347. package/src/common/errors/intent-to-join.ts +6 -6
  348. package/src/common/errors/join-meeting.ts +12 -8
  349. package/src/common/errors/media.ts +6 -6
  350. package/src/common/errors/parameter.ts +9 -6
  351. package/src/common/errors/password-error.ts +6 -6
  352. package/src/common/errors/permission.ts +5 -5
  353. package/src/common/errors/reconnection.ts +6 -6
  354. package/src/common/errors/stats.ts +6 -6
  355. package/src/common/errors/webex-errors.ts +7 -5
  356. package/src/common/errors/webex-meetings-error.ts +1 -1
  357. package/src/common/events/events-scope.ts +5 -1
  358. package/src/common/events/events.ts +5 -1
  359. package/src/common/events/trigger-proxy.ts +8 -3
  360. package/src/common/events/util.ts +1 -2
  361. package/src/common/logs/logger-proxy.ts +21 -10
  362. package/src/common/logs/request.ts +11 -8
  363. package/src/config.ts +16 -12
  364. package/src/constants.ts +151 -7
  365. package/src/controls-options-manager/constants.ts +5 -0
  366. package/src/controls-options-manager/enums.ts +18 -0
  367. package/src/controls-options-manager/index.ts +278 -0
  368. package/src/controls-options-manager/types.ts +59 -0
  369. package/src/controls-options-manager/util.ts +281 -0
  370. package/src/index.ts +33 -0
  371. package/src/locus-info/controlsUtils.ts +142 -24
  372. package/src/locus-info/fullState.ts +15 -11
  373. package/src/locus-info/hostUtils.ts +4 -3
  374. package/src/locus-info/index.ts +335 -55
  375. package/src/locus-info/infoUtils.ts +12 -4
  376. package/src/locus-info/mediaSharesUtils.ts +52 -4
  377. package/src/locus-info/parser.ts +46 -68
  378. package/src/locus-info/selfUtils.ts +187 -56
  379. package/src/media/index.ts +139 -196
  380. package/src/media/properties.ts +43 -36
  381. package/src/media/util.ts +1 -1
  382. package/src/mediaQualityMetrics/config.ts +380 -378
  383. package/src/meeting/in-meeting-actions.ts +159 -3
  384. package/src/meeting/index.ts +2789 -1584
  385. package/src/meeting/locusMediaRequest.ts +309 -0
  386. package/src/meeting/muteState.ts +290 -72
  387. package/src/meeting/request.ts +247 -178
  388. package/src/meeting/request.type.ts +13 -0
  389. package/src/meeting/state.ts +45 -30
  390. package/src/meeting/util.ts +445 -395
  391. package/src/meeting-info/collection.ts +2 -1
  392. package/src/meeting-info/index.ts +32 -30
  393. package/src/meeting-info/meeting-info-v2.ts +235 -116
  394. package/src/meeting-info/request.ts +9 -3
  395. package/src/meeting-info/util.ts +54 -46
  396. package/src/meeting-info/utilv2.ts +71 -55
  397. package/src/meetings/collection.ts +21 -1
  398. package/src/meetings/index.ts +772 -437
  399. package/src/meetings/request.ts +29 -25
  400. package/src/meetings/util.ts +132 -33
  401. package/src/member/index.ts +95 -49
  402. package/src/member/types.ts +24 -0
  403. package/src/member/util.ts +106 -13
  404. package/src/members/collection.ts +8 -1
  405. package/src/members/index.ts +288 -130
  406. package/src/members/request.ts +144 -31
  407. package/src/members/types.ts +28 -0
  408. package/src/members/util.ts +316 -235
  409. package/src/metrics/config.ts +302 -90
  410. package/src/metrics/constants.ts +2 -6
  411. package/src/metrics/index.ts +124 -95
  412. package/src/multistream/mediaRequestManager.ts +203 -45
  413. package/src/multistream/receiveSlot.ts +69 -26
  414. package/src/multistream/receiveSlotManager.ts +62 -38
  415. package/src/multistream/remoteMedia.ts +30 -4
  416. package/src/multistream/remoteMediaGroup.ts +4 -3
  417. package/src/multistream/remoteMediaManager.ts +230 -66
  418. package/src/networkQualityMonitor/index.ts +24 -27
  419. package/src/personal-meeting-room/index.ts +12 -16
  420. package/src/personal-meeting-room/request.ts +10 -3
  421. package/src/personal-meeting-room/util.ts +3 -3
  422. package/src/reachability/index.ts +131 -79
  423. package/src/reachability/request.ts +43 -34
  424. package/src/reactions/constants.ts +4 -0
  425. package/src/reactions/reactions.ts +8 -8
  426. package/src/reactions/reactions.type.ts +31 -5
  427. package/src/reconnection-manager/index.ts +193 -111
  428. package/src/recording-controller/enums.ts +8 -0
  429. package/src/recording-controller/index.ts +315 -0
  430. package/src/recording-controller/util.ts +58 -0
  431. package/src/roap/index.ts +53 -53
  432. package/src/roap/request.ts +77 -64
  433. package/src/roap/turnDiscovery.ts +101 -48
  434. package/src/statsAnalyzer/global.ts +8 -104
  435. package/src/statsAnalyzer/index.ts +624 -376
  436. package/src/statsAnalyzer/mqaUtil.ts +203 -90
  437. package/src/transcription/index.ts +34 -32
  438. package/test/integration/spec/converged-space-meetings.js +177 -0
  439. package/test/integration/spec/journey.js +670 -466
  440. package/test/integration/spec/space-meeting.js +320 -204
  441. package/test/integration/spec/transcription.js +7 -8
  442. package/test/unit/spec/annotation/index.ts +433 -0
  443. package/test/unit/spec/breakouts/breakout.ts +203 -0
  444. package/test/unit/spec/breakouts/collection.ts +15 -0
  445. package/test/unit/spec/breakouts/edit-lock-error.ts +30 -0
  446. package/test/unit/spec/breakouts/events.ts +77 -0
  447. package/test/unit/spec/breakouts/index.ts +1609 -0
  448. package/test/unit/spec/breakouts/request.ts +104 -0
  449. package/test/unit/spec/breakouts/utils.js +72 -0
  450. package/test/unit/spec/common/browser-detection.js +9 -28
  451. package/test/unit/spec/controls-options-manager/index.js +287 -0
  452. package/test/unit/spec/controls-options-manager/util.js +504 -0
  453. package/test/unit/spec/fixture/locus.js +93 -90
  454. package/test/unit/spec/locus-info/controlsUtils.js +305 -32
  455. package/test/unit/spec/locus-info/embeddedAppsUtils.js +8 -6
  456. package/test/unit/spec/locus-info/index.js +598 -5
  457. package/test/unit/spec/locus-info/infoUtils.js +26 -33
  458. package/test/unit/spec/locus-info/lib/BasicSeqCmp.json +88 -430
  459. package/test/unit/spec/locus-info/lib/SeqCmp.json +513 -685
  460. package/test/unit/spec/locus-info/mediaSharesUtils.ts +22 -0
  461. package/test/unit/spec/locus-info/parser.js +3 -9
  462. package/test/unit/spec/locus-info/selfConstant.js +110 -103
  463. package/test/unit/spec/locus-info/selfUtils.js +236 -12
  464. package/test/unit/spec/media/index.ts +104 -8
  465. package/test/unit/spec/media/properties.ts +9 -9
  466. package/test/unit/spec/meeting/in-meeting-actions.ts +76 -3
  467. package/test/unit/spec/meeting/index.js +3094 -921
  468. package/test/unit/spec/meeting/locusMediaRequest.ts +436 -0
  469. package/test/unit/spec/meeting/muteState.js +421 -94
  470. package/test/unit/spec/meeting/request.js +421 -79
  471. package/test/unit/spec/meeting/utils.js +326 -189
  472. package/test/unit/spec/meeting-info/meetinginfov2.js +481 -76
  473. package/test/unit/spec/meeting-info/request.js +7 -9
  474. package/test/unit/spec/meeting-info/util.js +11 -12
  475. package/test/unit/spec/meeting-info/utilv2.js +131 -74
  476. package/test/unit/spec/meetings/collection.js +15 -1
  477. package/test/unit/spec/meetings/index.js +1126 -328
  478. package/test/unit/spec/meetings/utils.js +220 -14
  479. package/test/unit/spec/member/index.js +24 -1
  480. package/test/unit/spec/member/util.js +383 -32
  481. package/test/unit/spec/members/index.js +424 -55
  482. package/test/unit/spec/members/request.js +228 -40
  483. package/test/unit/spec/members/utils.js +191 -4
  484. package/test/unit/spec/metrics/index.js +113 -20
  485. package/test/unit/spec/multistream/mediaRequestManager.ts +650 -105
  486. package/test/unit/spec/multistream/receiveSlot.ts +76 -17
  487. package/test/unit/spec/multistream/receiveSlotManager.ts +69 -39
  488. package/test/unit/spec/multistream/remoteMedia.ts +32 -2
  489. package/test/unit/spec/multistream/remoteMediaGroup.ts +5 -5
  490. package/test/unit/spec/multistream/remoteMediaManager.ts +549 -65
  491. package/test/unit/spec/networkQualityMonitor/index.js +24 -18
  492. package/test/unit/spec/personal-meeting-room/personal-meeting-room.js +2 -7
  493. package/test/unit/spec/reachability/index.ts +176 -27
  494. package/test/unit/spec/reachability/request.js +66 -0
  495. package/test/unit/spec/reconnection-manager/index.js +62 -31
  496. package/test/unit/spec/recording-controller/index.js +231 -0
  497. package/test/unit/spec/recording-controller/util.js +102 -0
  498. package/test/unit/spec/roap/index.ts +19 -49
  499. package/test/unit/spec/roap/request.ts +187 -0
  500. package/test/unit/spec/roap/turnDiscovery.ts +92 -50
  501. package/test/unit/spec/stats-analyzer/index.js +116 -60
  502. package/test/utils/cmr.js +44 -42
  503. package/test/utils/constants.js +9 -0
  504. package/test/utils/integrationTestUtils.js +64 -0
  505. package/test/utils/testUtils.js +63 -99
  506. package/test/utils/webex-config.js +22 -18
  507. package/test/utils/webex-test-users.js +57 -50
  508. package/tsconfig.json +6 -0
  509. package/dist/media/internal-media-core-wrapper.js +0 -22
  510. package/dist/media/internal-media-core-wrapper.js.map +0 -1
  511. package/dist/meeting/effectsState.js +0 -334
  512. package/dist/meeting/effectsState.js.map +0 -1
  513. package/dist/multistream/multistreamMedia.js +0 -116
  514. package/dist/multistream/multistreamMedia.js.map +0 -1
  515. package/src/index.js +0 -15
  516. package/src/media/internal-media-core-wrapper.ts +0 -9
  517. package/src/meeting/effectsState.ts +0 -211
  518. package/src/multistream/multistreamMedia.ts +0 -92
  519. package/test/unit/spec/meeting/effectsState.js +0 -291
@@ -1,8 +1,7 @@
1
1
  import sinon from 'sinon';
2
2
  import {assert} from '@webex/test-helper-chai';
3
3
  import MeetingUtil from '@webex/plugin-meetings/src/meeting/util';
4
- import createMuteState from '@webex/plugin-meetings/src/meeting/muteState';
5
- import Media from '@webex/plugin-meetings/src/media/index';
4
+ import {createMuteState, MuteState} from '@webex/plugin-meetings/src/meeting/muteState';
6
5
  import PermissionError from '@webex/plugin-meetings/src/common/errors/permission';
7
6
  import {AUDIO, VIDEO} from '@webex/plugin-meetings/src/constants';
8
7
 
@@ -16,29 +15,43 @@ describe('plugin-meetings', () => {
16
15
 
17
16
  const fakeLocus = {info: 'this is a fake locus'};
18
17
 
19
- beforeEach(() => {
18
+ const createFakeLocalTrack = (id) => {
19
+ return {
20
+ id,
21
+ setMuted: sinon.stub(),
22
+ setServerMuted: sinon.stub(),
23
+ setUnmuteAllowed: sinon.stub(),
24
+ };
25
+ };
26
+
27
+ beforeEach(async () => {
20
28
  meeting = {
21
29
  mediaProperties: {
22
- audioTrack: 'fake audio track',
23
- videoTrack: 'fake video track'
30
+ audioTrack: createFakeLocalTrack('fake audio track'),
31
+ videoTrack: createFakeLocalTrack('fake video track'),
24
32
  },
25
33
  remoteMuted: false,
26
34
  unmuteAllowed: true,
35
+ remoteVideoMuted: false,
36
+ unmuteVideoAllowed: true,
37
+
27
38
  locusInfo: {
28
- onFullLocus: sinon.stub()
39
+ onDeltaLocus: sinon.stub(),
29
40
  },
30
41
  members: {
31
42
  selfId: 'fake self id',
32
- muteMember: sinon.stub().resolves()
33
- }
43
+ muteMember: sinon.stub().resolves(),
44
+ },
34
45
  };
35
- audio = createMuteState(AUDIO, meeting, {sendAudio: true});
36
- video = createMuteState(VIDEO, meeting, {sendVideo: true});
37
46
 
38
47
  originalRemoteUpdateAudioVideo = MeetingUtil.remoteUpdateAudioVideo;
39
48
 
40
49
  MeetingUtil.remoteUpdateAudioVideo = sinon.stub().resolves(fakeLocus);
41
- Media.setLocalTrack = sinon.stub();
50
+
51
+ audio = createMuteState(AUDIO, meeting, {sendAudio: true}, true);
52
+ video = createMuteState(VIDEO, meeting, {sendVideo: true}, true);
53
+
54
+ await testUtils.flushPromises();
42
55
  });
43
56
 
44
57
  afterEach(() => {
@@ -47,8 +60,8 @@ describe('plugin-meetings', () => {
47
60
 
48
61
  describe('mute state library', () => {
49
62
  it('does not create an audio instance if we are not sending audio', async () => {
50
- assert.isNull(createMuteState(AUDIO, meeting, {sendAudio: false}));
51
- assert.isNull(createMuteState(AUDIO, meeting, {}));
63
+ assert.isNull(createMuteState(AUDIO, meeting, {sendAudio: false}, true));
64
+ assert.isNull(createMuteState(AUDIO, meeting, {}, true));
52
65
  });
53
66
 
54
67
  it('does not create a video instance if we are not sending video', async () => {
@@ -59,8 +72,11 @@ describe('plugin-meetings', () => {
59
72
  it('takes into account current remote mute status when instantiated', async () => {
60
73
  // simulate being already remote muted
61
74
  meeting.remoteMuted = true;
62
- // create a new MuteState intance
63
- audio = createMuteState(AUDIO, meeting, {sendAudio: true});
75
+
76
+ // create a new MuteState instance
77
+ audio = createMuteState(AUDIO, meeting, {sendAudio: true}, true);
78
+
79
+ await testUtils.flushPromises();
64
80
 
65
81
  assert.isTrue(audio.isMuted());
66
82
  assert.isFalse(audio.isSelf());
@@ -68,30 +84,35 @@ describe('plugin-meetings', () => {
68
84
  // now check the opposite case
69
85
  meeting.remoteMuted = false;
70
86
 
71
- // create a new MuteState intance
72
- audio = createMuteState(AUDIO, meeting, {sendAudio: true});
87
+ // create a new MuteState instance
88
+ audio = createMuteState(AUDIO, meeting, {sendAudio: true}, true);
89
+
90
+ await testUtils.flushPromises();
73
91
 
74
92
  assert.isFalse(audio.isMuted());
75
93
  assert.isFalse(audio.isSelf());
76
94
  });
77
95
 
78
96
  it('initialises correctly for video', async () => {
79
- // setup fields related to audio remote state
80
- meeting.remoteMuted = true;
81
- meeting.unmuteAllowed = false;
82
- // create a new video MuteState intance
83
- video = createMuteState(VIDEO, meeting, {sendVideo: true});
97
+ // setup fields related to video remote state
98
+ meeting.remoteVideoMuted = false;
99
+ meeting.unmuteVideoAllowed = false;
100
+
101
+ // create a new video MuteState instance
102
+ video = createMuteState(VIDEO, meeting, {sendVideo: true}, true);
103
+
104
+ await testUtils.flushPromises();
84
105
 
85
106
  assert.isFalse(video.isMuted());
86
107
  assert.isFalse(video.state.server.remoteMute);
87
- assert.isTrue(video.state.server.unmuteAllowed);
108
+ assert.isFalse(video.state.server.unmuteAllowed);
88
109
  });
89
110
 
90
111
  it('takes remote mute into account when reporting current state', async () => {
91
112
  assert.isFalse(audio.isMuted());
92
113
 
93
114
  // simulate remote mute
94
- audio.handleServerRemoteMuteUpdate(true, true);
115
+ audio.handleServerRemoteMuteUpdate(meeting, true, true);
95
116
 
96
117
  assert.isTrue(audio.isMuted());
97
118
  assert.isFalse(audio.isSelf());
@@ -110,12 +131,12 @@ describe('plugin-meetings', () => {
110
131
  audio.handleServerLocalUnmuteRequired(meeting);
111
132
  await testUtils.flushPromises();
112
133
 
113
- // check that local track was enabled
114
- assert.calledWith(Media.setLocalTrack, true, meeting.mediaProperties.audioTrack);
134
+ // check that local track was unmuted
135
+ assert.calledWith(meeting.mediaProperties.audioTrack.setMuted, false);
115
136
 
116
137
  // and local unmute was sent to server
117
138
  assert.calledOnce(MeetingUtil.remoteUpdateAudioVideo);
118
- assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, false, undefined, meeting);
139
+ assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, false, undefined);
119
140
 
120
141
  assert.isFalse(audio.isMuted());
121
142
  assert.isFalse(audio.isSelf());
@@ -128,11 +149,14 @@ describe('plugin-meetings', () => {
128
149
  // first we need to mute and make that request last forever
129
150
  let serverResponseResolve;
130
151
 
131
- MeetingUtil.remoteUpdateAudioVideo = sinon.stub().returns(new Promise((resolve) => {
132
- serverResponseResolve = resolve;
133
- }));
152
+ MeetingUtil.remoteUpdateAudioVideo = sinon.stub().returns(
153
+ new Promise((resolve) => {
154
+ serverResponseResolve = resolve;
155
+ })
156
+ );
134
157
 
135
- audio.handleClientRequest(meeting, true)
158
+ audio
159
+ .handleClientRequest(meeting, true)
136
160
  .then(() => {
137
161
  clientPromiseResolved = true;
138
162
  })
@@ -156,50 +180,98 @@ describe('plugin-meetings', () => {
156
180
 
157
181
  // local unmute should be sent to server
158
182
  assert.calledOnce(MeetingUtil.remoteUpdateAudioVideo);
159
- assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, false, undefined, meeting);
183
+ assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, false, undefined);
160
184
 
161
- // and local track should be enabled
162
- assert.calledWith(Media.setLocalTrack, true, meeting.mediaProperties.audioTrack);
185
+ // and local track should be unmuted
186
+ assert.calledWith(meeting.mediaProperties.audioTrack.setMuted, false);
163
187
 
164
188
  assert.isFalse(audio.isMuted());
165
189
  assert.isFalse(audio.isSelf());
166
190
  });
167
191
 
192
+ it('does local video unmute if localVideoUnmuteRequired is received', async () => {
193
+ // first we need to mute
194
+ await video.handleClientRequest(meeting, true);
195
+
196
+ assert.isTrue(video.isMuted());
197
+ assert.isTrue(video.isSelf());
198
+
199
+ MeetingUtil.remoteUpdateAudioVideo.resetHistory();
200
+
201
+ // now simulate server requiring us to locally unmute
202
+ video.handleServerLocalUnmuteRequired(meeting);
203
+ await testUtils.flushPromises();
204
+
205
+ // check that local track was unmuted
206
+ assert.calledWith(meeting.mediaProperties.videoTrack.setMuted, false);
207
+
208
+ // and local unmute was sent to server
209
+ assert.calledOnce(MeetingUtil.remoteUpdateAudioVideo);
210
+ assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, undefined, false);
211
+
212
+ assert.isFalse(video.isMuted());
213
+ assert.isFalse(video.isSelf());
214
+ });
215
+
216
+ describe('#isLocallyMuted()', () => {
217
+ it('does not consider remote mute status for audio', async () => {
218
+ // simulate being already remote muted
219
+ meeting.remoteMuted = true;
220
+ // create a new MuteState instance
221
+ audio = createMuteState(AUDIO, meeting, {sendAudio: true}, true);
222
+
223
+ await testUtils.flushPromises();
224
+
225
+ assert.isFalse(audio.isLocallyMuted());
226
+ });
227
+
228
+ it('does not consider remote mute status for video', async () => {
229
+ // simulate being already remote muted
230
+ meeting.remoteVideoMuted = true;
231
+ // create a new MuteState instance
232
+ video = createMuteState(VIDEO, meeting, {sendVideo: true}, true);
233
+
234
+ await testUtils.flushPromises();
235
+
236
+ assert.isFalse(video.isLocallyMuted());
237
+ });
238
+ });
239
+
168
240
  describe('#handleClientRequest', () => {
169
241
  it('disables/enables the local audio track when audio is muted/unmuted', async () => {
170
242
  // mute
171
243
  audio.handleClientRequest(meeting, true);
172
- assert.calledWith(Media.setLocalTrack, false, meeting.mediaProperties.audioTrack);
244
+ assert.calledWith(meeting.mediaProperties.audioTrack.setMuted, true);
173
245
 
174
- // even when calling mute when it's already muted should still call setLocalTrack
246
+ // even when calling mute when it's already muted should still call setMuted
175
247
  audio.handleClientRequest(meeting, true);
176
- assert.calledWith(Media.setLocalTrack, false, meeting.mediaProperties.audioTrack);
248
+ assert.calledWith(meeting.mediaProperties.audioTrack.setMuted, true);
177
249
 
178
250
  // unmute
179
251
  audio.handleClientRequest(meeting, false);
180
- assert.calledWith(Media.setLocalTrack, true, meeting.mediaProperties.audioTrack);
252
+ assert.calledWith(meeting.mediaProperties.audioTrack.setMuted, false);
181
253
 
182
- // even when calling unmute when it's already unmuted should still call setLocalTrack
254
+ // even when calling unmute when it's already unmuted should still call setMuted
183
255
  audio.handleClientRequest(meeting, false);
184
- assert.calledWith(Media.setLocalTrack, true, meeting.mediaProperties.audioTrack);
256
+ assert.calledWith(meeting.mediaProperties.audioTrack.setMuted, false);
185
257
  });
186
258
 
187
259
  it('disables/enables the local video track when video is muted/unmuted', async () => {
188
260
  // mute
189
261
  video.handleClientRequest(meeting, true);
190
- assert.calledWith(Media.setLocalTrack, false, meeting.mediaProperties.videoTrack);
262
+ assert.calledWith(meeting.mediaProperties.videoTrack.setMuted, true);
191
263
 
192
- // even when calling mute when it's already muted should still call setLocalTrack
264
+ // even when calling mute when it's already muted should still call setMuted
193
265
  video.handleClientRequest(meeting, false);
194
- assert.calledWith(Media.setLocalTrack, false, meeting.mediaProperties.videoTrack);
266
+ assert.calledWith(meeting.mediaProperties.videoTrack.setMuted, true);
195
267
 
196
268
  // unmute
197
269
  video.handleClientRequest(meeting, false);
198
- assert.calledWith(Media.setLocalTrack, true, meeting.mediaProperties.videoTrack);
270
+ assert.calledWith(meeting.mediaProperties.videoTrack.setMuted, false);
199
271
 
200
- // even when calling unmute when it's already unmuted should still call setLocalTrack
272
+ // even when calling unmute when it's already unmuted should still call setMuted
201
273
  video.handleClientRequest(meeting, false);
202
- assert.calledWith(Media.setLocalTrack, true, meeting.mediaProperties.videoTrack);
274
+ assert.calledWith(meeting.mediaProperties.videoTrack.setMuted, false);
203
275
  });
204
276
 
205
277
  it('returns correct value in isMuted()/isSelf() methods after client mute/unmute requests', async () => {
@@ -218,55 +290,90 @@ describe('plugin-meetings', () => {
218
290
 
219
291
  it('does remote unmute when unmuting and remote mute is on', async () => {
220
292
  // simulate remote mute
221
- audio.handleServerRemoteMuteUpdate(true, true);
293
+ audio.handleServerRemoteMuteUpdate(meeting, true, true);
222
294
 
223
295
  // unmute
224
296
  await audio.handleClientRequest(meeting, false);
225
297
 
226
298
  // check that remote unmute was sent to server
227
299
  assert.calledOnce(meeting.members.muteMember);
228
- assert.calledWith(meeting.members.muteMember, meeting.members.selfId, false);
300
+ assert.calledWith(meeting.members.muteMember, meeting.members.selfId, false, true);
229
301
 
230
302
  assert.isFalse(audio.isMuted());
231
303
  assert.isFalse(audio.isSelf());
232
304
  });
233
305
 
306
+ it('does video remote unmute when unmuting and remote mute is on', async () => {
307
+ // simulate remote mute
308
+ video.handleServerRemoteMuteUpdate(meeting, true, true);
309
+
310
+ // unmute
311
+ await video.handleClientRequest(meeting, false);
312
+
313
+ // check that remote unmute was sent to server
314
+ assert.calledOnce(meeting.members.muteMember);
315
+ assert.calledWith(meeting.members.muteMember, meeting.members.selfId, false, false);
316
+
317
+ assert.isFalse(video.isMuted());
318
+ assert.isFalse(video.isSelf());
319
+ });
320
+
321
+ it('does not video remote unmute when unmuting and remote mute is off', async () => {
322
+ // simulate remote mute
323
+ video.handleServerRemoteMuteUpdate(meeting, false, true);
324
+
325
+ // unmute
326
+ await video.handleClientRequest(meeting, false);
327
+
328
+ // check that remote unmute was sent to server
329
+ assert.notCalled(meeting.members.muteMember);
330
+
331
+ assert.isFalse(video.isMuted());
332
+ assert.isFalse(video.isSelf());
333
+ });
334
+
234
335
  it('resolves client request promise once the server is updated', async () => {
235
336
  let clientPromiseResolved = false;
236
337
 
237
338
  let serverResponseResolve;
238
339
 
239
- MeetingUtil.remoteUpdateAudioVideo = sinon.stub().returns(new Promise((resolve) => {
240
- serverResponseResolve = resolve;
241
- }));
340
+ MeetingUtil.remoteUpdateAudioVideo = sinon.stub().returns(
341
+ new Promise((resolve) => {
342
+ serverResponseResolve = resolve;
343
+ })
344
+ );
242
345
 
243
- audio.handleClientRequest(meeting, true)
244
- .then(() => {
245
- clientPromiseResolved = true;
246
- });
346
+ audio.handleClientRequest(meeting, true).then(() => {
347
+ clientPromiseResolved = true;
348
+ });
247
349
 
248
350
  // do a small delay to make sure that the client promise doesn't resolve in that time
249
351
  await testUtils.waitUntil(200);
250
352
  assert.isFalse(clientPromiseResolved);
251
353
 
354
+ meeting.locusInfo.onDeltaLocus.resetHistory();
355
+
252
356
  // now allow the server response to arrive, this should trigger the client promise to get resolved
253
- serverResponseResolve();
357
+ serverResponseResolve(fakeLocus);
254
358
  await testUtils.flushPromises();
255
359
 
256
360
  assert.isTrue(clientPromiseResolved);
361
+ assert.calledOnceWithExactly(meeting.locusInfo.onDeltaLocus, fakeLocus);
257
362
  });
258
363
 
259
364
  it('rejects client request promise if server request for local mute fails', async () => {
260
- MeetingUtil.remoteUpdateAudioVideo = sinon.stub().returns(new Promise((resolve, reject) => {
261
- reject();
262
- }));
365
+ MeetingUtil.remoteUpdateAudioVideo = sinon.stub().returns(
366
+ new Promise((resolve, reject) => {
367
+ reject();
368
+ })
369
+ );
263
370
 
264
371
  assert.isRejected(audio.handleClientRequest(meeting, true));
265
372
  });
266
373
 
267
374
  it('rejects client request promise if server request for remote mute fails', async () => {
268
375
  // we only send remote mute requests when we're unmuting, so first we need to do a remote mute
269
- audio.handleServerRemoteMuteUpdate(true, true);
376
+ audio.handleServerRemoteMuteUpdate(meeting, true, true);
270
377
 
271
378
  // setup the stub to simulate server error response
272
379
  meeting.members.muteMember = sinon.stub().rejects();
@@ -282,9 +389,11 @@ describe('plugin-meetings', () => {
282
389
  it('does not send a server request if client state matches the server', async () => {
283
390
  let serverResponseResolve;
284
391
 
285
- MeetingUtil.remoteUpdateAudioVideo = sinon.stub().returns(new Promise((resolve) => {
286
- serverResponseResolve = resolve;
287
- }));
392
+ MeetingUtil.remoteUpdateAudioVideo = sinon.stub().returns(
393
+ new Promise((resolve) => {
394
+ serverResponseResolve = resolve;
395
+ })
396
+ );
288
397
 
289
398
  // simulate many client requests, with the last one matching the initial one
290
399
  audio.handleClientRequest(meeting, true);
@@ -309,27 +418,27 @@ describe('plugin-meetings', () => {
309
418
  it('queues up server requests when multiple client requests are received', async () => {
310
419
  let serverResponseResolve;
311
420
 
312
- MeetingUtil.remoteUpdateAudioVideo = sinon.stub().returns(new Promise((resolve) => {
313
- serverResponseResolve = resolve;
314
- }));
421
+ MeetingUtil.remoteUpdateAudioVideo = sinon.stub().returns(
422
+ new Promise((resolve) => {
423
+ serverResponseResolve = resolve;
424
+ })
425
+ );
315
426
 
316
427
  let firstClientPromiseResolved = false;
317
428
  let secondClientPromiseResolved = false;
318
429
 
319
430
  // 2 client requests, one after another without waiting for first one to resolve
320
- audio.handleClientRequest(meeting, true)
321
- .then(() => {
322
- firstClientPromiseResolved = true;
323
- });
324
- audio.handleClientRequest(meeting, false)
325
- .then(() => {
326
- secondClientPromiseResolved = true;
327
- });
431
+ audio.handleClientRequest(meeting, true).then(() => {
432
+ firstClientPromiseResolved = true;
433
+ });
434
+ audio.handleClientRequest(meeting, false).then(() => {
435
+ secondClientPromiseResolved = true;
436
+ });
328
437
 
329
438
  await testUtils.flushPromises();
330
439
 
331
440
  assert.calledOnce(MeetingUtil.remoteUpdateAudioVideo);
332
- assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, true, undefined, meeting);
441
+ assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, true, undefined);
333
442
 
334
443
  // now allow the first request to complete
335
444
  serverResponseResolve();
@@ -338,9 +447,7 @@ describe('plugin-meetings', () => {
338
447
 
339
448
  // that should trigger the second server request to be sent
340
449
  assert.calledTwice(MeetingUtil.remoteUpdateAudioVideo);
341
- assert.strictEqual(false, MeetingUtil.remoteUpdateAudioVideo.getCall(1).args[0]);
342
- assert.strictEqual(undefined, MeetingUtil.remoteUpdateAudioVideo.getCall(1).args[1]);
343
- assert.strictEqual(meeting, MeetingUtil.remoteUpdateAudioVideo.getCall(1).args[2]);
450
+ assert.deepEqual([meeting, false, undefined], MeetingUtil.remoteUpdateAudioVideo.getCall(1).args);
344
451
 
345
452
  serverResponseResolve();
346
453
  await testUtils.flushPromises();
@@ -349,9 +456,10 @@ describe('plugin-meetings', () => {
349
456
  });
350
457
 
351
458
  it('rejects client request to unmute if hard mute is used', (done) => {
352
- audio.handleServerRemoteMuteUpdate(true, false);
459
+ audio.handleServerRemoteMuteUpdate(meeting, true, false);
353
460
 
354
- audio.handleClientRequest(meeting, false)
461
+ audio
462
+ .handleClientRequest(meeting, false)
355
463
  .then(() => {
356
464
  done(new Error('expected handleClientRequest to fail, but it did not!'));
357
465
  })
@@ -369,11 +477,11 @@ describe('plugin-meetings', () => {
369
477
  assert.isTrue(video.isSelf());
370
478
 
371
479
  // check local mute is done, but not remote one
372
- assert.calledWith(Media.setLocalTrack, false, meeting.mediaProperties.videoTrack);
373
- assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, undefined, true, meeting);
480
+ assert.calledWith(meeting.mediaProperties.videoTrack.setMuted, true);
481
+ assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, undefined, true);
374
482
  assert.notCalled(meeting.members.muteMember);
375
483
 
376
- Media.setLocalTrack.resetHistory();
484
+ meeting.mediaProperties.videoTrack.setMuted.resetHistory();
377
485
  MeetingUtil.remoteUpdateAudioVideo.resetHistory();
378
486
  meeting.members.muteMember.resetHistory();
379
487
 
@@ -383,35 +491,254 @@ describe('plugin-meetings', () => {
383
491
  assert.isFalse(video.isMuted());
384
492
  assert.isFalse(video.isSelf());
385
493
 
386
- assert.calledWith(Media.setLocalTrack, true, meeting.mediaProperties.videoTrack);
387
- assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, undefined, false, meeting);
494
+ assert.calledWith(meeting.mediaProperties.videoTrack.setMuted, false);
495
+ assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, undefined, false);
388
496
  assert.notCalled(meeting.members.muteMember);
389
497
  });
390
498
 
391
- it('sends correct audio value when sending local mute for video', async () => {
499
+ it('sends undefined value for the other media type when sending local mute', async () => {
392
500
  // make sure the meeting object has mute state machines for both audio and video
393
501
  meeting.audio = audio;
394
502
  meeting.video = video;
395
503
 
396
- // mute audio -> request sent to server should have video unmuted
504
+ // mute audio -> the call to remoteUpdateAudioVideo should have video undefined
397
505
  await audio.handleClientRequest(meeting, true);
398
- assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, true, false, meeting);
506
+ assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, true, undefined);
399
507
  MeetingUtil.remoteUpdateAudioVideo.resetHistory();
400
508
 
401
- // now mute video -> request sent to server should have mute for both audio and video
509
+ // now mute video -> the call to remoteUpdateAudioVideo should have mute for video and undefined for audio
402
510
  await video.handleClientRequest(meeting, true);
403
- assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, true, true, meeting);
511
+ assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, undefined, true);
404
512
  MeetingUtil.remoteUpdateAudioVideo.resetHistory();
405
513
 
406
- // now unmute the audio -> request sent to server should still have video muted
514
+ // now unmute the audio -> the call to remoteUpdateAudioVideo should have video undefined
407
515
  await audio.handleClientRequest(meeting, false);
408
- assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, false, true, meeting);
516
+ assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, false, undefined);
409
517
  MeetingUtil.remoteUpdateAudioVideo.resetHistory();
410
518
 
411
- // unmute video -> request sent to server should have both audio and video unmuted
519
+ // unmute video -> the call to remoteUpdateAudioVideo should have both audio undefined
412
520
  await video.handleClientRequest(meeting, false);
413
- assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, false, false, meeting);
521
+ assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, undefined, false);
414
522
  });
415
523
  });
416
524
  });
417
525
  });
526
+
527
+ describe('#init, #handleLocalTrackChange', () => {
528
+ let meeting;
529
+ let muteState;
530
+ let setServerMutedSpy;
531
+ let setMutedSpy, setUnmuteAllowedSpy;
532
+ const fakeLocus = {info: 'this is a fake locus'};
533
+
534
+ const createFakeLocalTrack = (id, muted) => {
535
+ return {
536
+ id,
537
+ setMuted: sinon.stub(),
538
+ setServerMuted: sinon.stub(),
539
+ setUnmuteAllowed: sinon.stub(),
540
+ muted,
541
+ };
542
+ };
543
+
544
+ const setupMeeting = (mediaType, remoteMuted = false, muted = false, defineTracks = true) => {
545
+ const remoteMuteField = mediaType === AUDIO ? 'remoteMuted' : 'remoteVideoMuted';
546
+
547
+ meeting = {
548
+ mediaProperties: {
549
+ audioTrack: defineTracks ? createFakeLocalTrack('fake audio track', muted) : undefined,
550
+ videoTrack: defineTracks ? createFakeLocalTrack('fake video track', muted) : undefined,
551
+ },
552
+ [remoteMuteField]: remoteMuted,
553
+ unmuteAllowed: true,
554
+ unmuteVideoAllowed: true,
555
+
556
+ locusInfo: {
557
+ onFullLocus: sinon.stub(),
558
+ },
559
+ members: {
560
+ selfId: 'fake self id',
561
+ muteMember: sinon.stub().resolves(),
562
+ },
563
+ };
564
+ };
565
+
566
+ const setup = async (mediaType, remoteMuted = false, muted = false, defineTracks = true) => {
567
+
568
+ setupMeeting(mediaType, remoteMuted, muted, defineTracks);
569
+
570
+ const direction = mediaType === AUDIO ? {sendAudio: true} : {sendVideo: true};
571
+
572
+ muteState = createMuteState(mediaType, meeting, direction, false);
573
+
574
+ await testUtils.flushPromises();
575
+
576
+ MeetingUtil.remoteUpdateAudioVideo.resetHistory();
577
+ }
578
+
579
+ const setupSpies = (mediaType) => {
580
+ setUnmuteAllowedSpy = mediaType === AUDIO ? meeting.mediaProperties.audioTrack?.setUnmuteAllowed : meeting.mediaProperties.videoTrack?.setUnmuteAllowed;
581
+ setServerMutedSpy = mediaType === AUDIO ? meeting.mediaProperties.audioTrack?.setServerMuted : meeting.mediaProperties.videoTrack?.setServerMuted;
582
+ setMutedSpy = mediaType === AUDIO ? meeting.mediaProperties.audioTrack?.setMuted : meeting.mediaProperties.videoTrack?.setMuted;
583
+
584
+ clearSpies();
585
+ };
586
+
587
+ const clearSpies = () => {
588
+ setUnmuteAllowedSpy?.resetHistory();
589
+ setServerMutedSpy?.resetHistory();
590
+ setMutedSpy?.resetHistory();
591
+ };
592
+ const tests = [
593
+ {mediaType: AUDIO, title: 'audio'},
594
+ {mediaType: VIDEO, title: 'video'}
595
+ ];
596
+
597
+ tests.forEach(({mediaType, title}) =>
598
+ describe(title, () => {
599
+ let originalRemoteUpdateAudioVideo;
600
+
601
+ beforeEach(() => {
602
+ originalRemoteUpdateAudioVideo = MeetingUtil.remoteUpdateAudioVideo;
603
+ MeetingUtil.remoteUpdateAudioVideo = sinon.stub().resolves({info: 'fake locus'});
604
+ });
605
+
606
+ afterEach(() => {
607
+ MeetingUtil.remoteUpdateAudioVideo = originalRemoteUpdateAudioVideo;
608
+ sinon.restore();
609
+ });
610
+
611
+ describe('#handleLocalTrackChange',() => {
612
+
613
+ it('calls init()', async () => {
614
+ await setup(mediaType);
615
+ const spy = sinon.spy(muteState, 'init');
616
+ muteState.handleLocalTrackChange(meeting);
617
+ assert.calledOnceWithExactly(spy, meeting);
618
+ });
619
+ });
620
+
621
+ describe('#init', () => {
622
+
623
+ // does the setup by calling new MuteState() so that MuteState.init() doesn't get called
624
+ const setupWithoutInit = async (mediaType, remoteMuted = false, muted = false, defineTracks = true) => {
625
+
626
+ setupMeeting(mediaType, remoteMuted, muted, defineTracks);
627
+
628
+ muteState = new MuteState(mediaType, meeting, false);
629
+ }
630
+
631
+ it('nothing goes bad when track is undefined', async () => {
632
+ await setupWithoutInit(mediaType, false, false, false);
633
+ setupSpies(mediaType);
634
+
635
+ muteState.init(meeting);
636
+
637
+ assert.isFalse(muteState.state.client.localMute);
638
+ });
639
+
640
+ it('tests when track muted is true and remoteMuted is false', async () => {
641
+ await setupWithoutInit(mediaType, false, true);
642
+ setupSpies(mediaType);
643
+
644
+ muteState.init(meeting);
645
+
646
+ assert.calledWith(setUnmuteAllowedSpy, muteState.state.server.unmuteAllowed);
647
+ assert.notCalled(setServerMutedSpy);
648
+ assert.notCalled(MeetingUtil.remoteUpdateAudioVideo);
649
+ assert.isTrue(muteState.state.client.localMute);
650
+ });
651
+
652
+
653
+ it('tests when track muted is false and remoteMuted is false', async () => {
654
+ await setupWithoutInit(mediaType, false, false);
655
+ setupSpies(mediaType);
656
+ muteState.state.server.localMute = true;
657
+
658
+ muteState.init(meeting);
659
+
660
+ assert.calledWith(setUnmuteAllowedSpy, muteState.state.server.unmuteAllowed);
661
+ assert.notCalled(setServerMutedSpy);
662
+ assert.calledOnce(MeetingUtil.remoteUpdateAudioVideo);
663
+ assert.isFalse(muteState.state.client.localMute);
664
+ });
665
+
666
+ it('tests when remoteMuted is true', async () => {
667
+ // testing that muteLocalTrack is called
668
+ await setupWithoutInit(mediaType, true);
669
+ setupSpies(mediaType);
670
+
671
+ muteState.init(meeting);
672
+
673
+ assert.calledWith(setUnmuteAllowedSpy, muteState.state.server.unmuteAllowed);
674
+ assert.calledOnceWithExactly(setServerMutedSpy, true, 'remotelyMuted');
675
+ });
676
+ });
677
+
678
+ describe('#handleLocalTrackMuteStateChange', () => {
679
+
680
+ it('checks when ignoreMuteStateChange is true nothing changes', async () => {
681
+ await setup(mediaType, false, false);
682
+ muteState.ignoreMuteStateChange = true;
683
+
684
+ muteState.handleLocalTrackMuteStateChange(meeting, true);
685
+ assert.notCalled(MeetingUtil.remoteUpdateAudioVideo);
686
+
687
+ assert.isFalse(muteState.state.client.localMute);
688
+ });
689
+
690
+ it('tests localMute - true to false', async () => {
691
+ await setup(mediaType, false, true);
692
+
693
+ muteState.handleLocalTrackMuteStateChange(meeting, false);
694
+ assert.equal(muteState.state.client.localMute, false);
695
+ assert.called(MeetingUtil.remoteUpdateAudioVideo);
696
+ });
697
+
698
+ it('tests localMute - false to true', async () => {
699
+ await setup(mediaType, false, false);
700
+
701
+ muteState.handleLocalTrackMuteStateChange(meeting, true);
702
+ assert.equal(muteState.state.client.localMute, true);
703
+ assert.called(MeetingUtil.remoteUpdateAudioVideo);
704
+ });
705
+ });
706
+
707
+ describe('#applyClientStateLocally', () => {
708
+
709
+ afterEach(() => {
710
+ sinon.restore();
711
+ });
712
+
713
+ it('checks when sdkOwnsLocalTrack is false', async () => {
714
+ await setup(mediaType);
715
+ setupSpies(mediaType);
716
+ muteState.sdkOwnsLocalTrack= false;
717
+
718
+ muteState.applyClientStateLocally(meeting, 'somereason');
719
+ assert.calledOnceWithExactly(setServerMutedSpy, muteState.state.client.localMute, 'somereason');
720
+ assert.notCalled(setMutedSpy);
721
+ });
722
+
723
+ it('checks when sdkOwnsLocalTrack is true', async () => {
724
+ await setup(mediaType);
725
+ setupSpies(mediaType);
726
+ muteState.sdkOwnsLocalTrack= true;
727
+
728
+ muteState.applyClientStateLocally(meeting, 'somereason');
729
+ assert.notCalled(setServerMutedSpy);
730
+ assert.calledOnceWithExactly(setMutedSpy, muteState.state.client.localMute);
731
+ });
732
+
733
+ it('checks nothing explodes when tracks are undefined', async () => {
734
+ await setup(mediaType, false, false, false);
735
+ setupSpies(mediaType);
736
+ muteState.sdkOwnsLocalTrack= true;
737
+
738
+ muteState.applyClientStateLocally(meeting, 'somereason');
739
+ });
740
+ });
741
+
742
+ })
743
+ );
744
+ });