@webex/plugin-meetings 3.0.0-beta.21 → 3.0.0-beta.211

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 (422) hide show
  1. package/README.md +45 -7
  2. package/dist/annotation/annotation.types.js +7 -0
  3. package/dist/annotation/annotation.types.js.map +1 -0
  4. package/dist/annotation/constants.js +49 -0
  5. package/dist/annotation/constants.js.map +1 -0
  6. package/dist/annotation/index.js +342 -0
  7. package/dist/annotation/index.js.map +1 -0
  8. package/dist/breakouts/breakout.js +114 -14
  9. package/dist/breakouts/breakout.js.map +1 -1
  10. package/dist/breakouts/edit-lock-error.js +52 -0
  11. package/dist/breakouts/edit-lock-error.js.map +1 -0
  12. package/dist/breakouts/events.js +45 -0
  13. package/dist/breakouts/events.js.map +1 -0
  14. package/dist/breakouts/index.js +841 -19
  15. package/dist/breakouts/index.js.map +1 -1
  16. package/dist/breakouts/request.js +78 -0
  17. package/dist/breakouts/request.js.map +1 -0
  18. package/dist/breakouts/utils.js +67 -0
  19. package/dist/breakouts/utils.js.map +1 -0
  20. package/dist/common/errors/webex-errors.js +3 -2
  21. package/dist/common/errors/webex-errors.js.map +1 -1
  22. package/dist/common/logs/logger-proxy.js +1 -1
  23. package/dist/common/logs/logger-proxy.js.map +1 -1
  24. package/dist/common/queue.js +24 -9
  25. package/dist/common/queue.js.map +1 -1
  26. package/dist/config.js +3 -8
  27. package/dist/config.js.map +1 -1
  28. package/dist/constants.js +179 -30
  29. package/dist/constants.js.map +1 -1
  30. package/dist/controls-options-manager/constants.js +14 -0
  31. package/dist/controls-options-manager/constants.js.map +1 -0
  32. package/dist/controls-options-manager/enums.js +27 -0
  33. package/dist/controls-options-manager/enums.js.map +1 -0
  34. package/dist/controls-options-manager/index.js +297 -0
  35. package/dist/controls-options-manager/index.js.map +1 -0
  36. package/dist/controls-options-manager/types.js +7 -0
  37. package/dist/controls-options-manager/types.js.map +1 -0
  38. package/dist/controls-options-manager/util.js +319 -0
  39. package/dist/controls-options-manager/util.js.map +1 -0
  40. package/dist/index.js +106 -1
  41. package/dist/index.js.map +1 -1
  42. package/dist/interpretation/collection.js +23 -0
  43. package/dist/interpretation/collection.js.map +1 -0
  44. package/dist/interpretation/index.js +366 -0
  45. package/dist/interpretation/index.js.map +1 -0
  46. package/dist/interpretation/siLanguage.js +25 -0
  47. package/dist/interpretation/siLanguage.js.map +1 -0
  48. package/dist/locus-info/controlsUtils.js +91 -2
  49. package/dist/locus-info/controlsUtils.js.map +1 -1
  50. package/dist/locus-info/index.js +359 -64
  51. package/dist/locus-info/index.js.map +1 -1
  52. package/dist/locus-info/infoUtils.js +7 -1
  53. package/dist/locus-info/infoUtils.js.map +1 -1
  54. package/dist/locus-info/mediaSharesUtils.js +43 -1
  55. package/dist/locus-info/mediaSharesUtils.js.map +1 -1
  56. package/dist/locus-info/parser.js +219 -63
  57. package/dist/locus-info/parser.js.map +1 -1
  58. package/dist/locus-info/selfUtils.js +89 -14
  59. package/dist/locus-info/selfUtils.js.map +1 -1
  60. package/dist/media/index.js +48 -135
  61. package/dist/media/index.js.map +1 -1
  62. package/dist/media/properties.js +29 -90
  63. package/dist/media/properties.js.map +1 -1
  64. package/dist/mediaQualityMetrics/config.js +505 -493
  65. package/dist/mediaQualityMetrics/config.js.map +1 -1
  66. package/dist/meeting/in-meeting-actions.js +90 -2
  67. package/dist/meeting/in-meeting-actions.js.map +1 -1
  68. package/dist/meeting/index.js +2770 -2547
  69. package/dist/meeting/index.js.map +1 -1
  70. package/dist/meeting/locusMediaRequest.js +291 -0
  71. package/dist/meeting/locusMediaRequest.js.map +1 -0
  72. package/dist/meeting/muteState.js +229 -124
  73. package/dist/meeting/muteState.js.map +1 -1
  74. package/dist/meeting/request.js +199 -193
  75. package/dist/meeting/request.js.map +1 -1
  76. package/dist/meeting/util.js +532 -414
  77. package/dist/meeting/util.js.map +1 -1
  78. package/dist/meeting-info/index.js +48 -7
  79. package/dist/meeting-info/index.js.map +1 -1
  80. package/dist/meeting-info/meeting-info-v2.js +171 -51
  81. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  82. package/dist/meeting-info/utilv2.js +20 -5
  83. package/dist/meeting-info/utilv2.js.map +1 -1
  84. package/dist/meetings/collection.js +22 -0
  85. package/dist/meetings/collection.js.map +1 -1
  86. package/dist/meetings/index.js +357 -66
  87. package/dist/meetings/index.js.map +1 -1
  88. package/dist/meetings/meetings.types.js +7 -0
  89. package/dist/meetings/meetings.types.js.map +1 -0
  90. package/dist/meetings/request.js +2 -0
  91. package/dist/meetings/request.js.map +1 -1
  92. package/dist/meetings/util.js +88 -1
  93. package/dist/meetings/util.js.map +1 -1
  94. package/dist/member/index.js +49 -0
  95. package/dist/member/index.js.map +1 -1
  96. package/dist/member/types.js +25 -0
  97. package/dist/member/types.js.map +1 -0
  98. package/dist/member/util.js +121 -25
  99. package/dist/member/util.js.map +1 -1
  100. package/dist/members/collection.js +10 -0
  101. package/dist/members/collection.js.map +1 -1
  102. package/dist/members/index.js +86 -5
  103. package/dist/members/index.js.map +1 -1
  104. package/dist/members/request.js +106 -38
  105. package/dist/members/request.js.map +1 -1
  106. package/dist/members/types.js +15 -0
  107. package/dist/members/types.js.map +1 -0
  108. package/dist/members/util.js +316 -233
  109. package/dist/members/util.js.map +1 -1
  110. package/dist/metrics/constants.js +3 -5
  111. package/dist/metrics/constants.js.map +1 -1
  112. package/dist/metrics/index.js +1 -468
  113. package/dist/metrics/index.js.map +1 -1
  114. package/dist/multistream/mediaRequestManager.js +238 -49
  115. package/dist/multistream/mediaRequestManager.js.map +1 -1
  116. package/dist/multistream/receiveSlot.js +49 -16
  117. package/dist/multistream/receiveSlot.js.map +1 -1
  118. package/dist/multistream/receiveSlotManager.js +52 -34
  119. package/dist/multistream/receiveSlotManager.js.map +1 -1
  120. package/dist/multistream/remoteMedia.js +44 -18
  121. package/dist/multistream/remoteMedia.js.map +1 -1
  122. package/dist/multistream/remoteMediaGroup.js +60 -3
  123. package/dist/multistream/remoteMediaGroup.js.map +1 -1
  124. package/dist/multistream/remoteMediaManager.js +173 -59
  125. package/dist/multistream/remoteMediaManager.js.map +1 -1
  126. package/dist/networkQualityMonitor/index.js +4 -2
  127. package/dist/networkQualityMonitor/index.js.map +1 -1
  128. package/dist/reachability/index.js +72 -27
  129. package/dist/reachability/index.js.map +1 -1
  130. package/dist/reachability/request.js +12 -5
  131. package/dist/reachability/request.js.map +1 -1
  132. package/dist/reconnection-manager/index.js +196 -155
  133. package/dist/reconnection-manager/index.js.map +1 -1
  134. package/dist/recording-controller/index.js +21 -2
  135. package/dist/recording-controller/index.js.map +1 -1
  136. package/dist/recording-controller/util.js +9 -8
  137. package/dist/recording-controller/util.js.map +1 -1
  138. package/dist/roap/index.js +21 -29
  139. package/dist/roap/index.js.map +1 -1
  140. package/dist/roap/request.js +110 -89
  141. package/dist/roap/request.js.map +1 -1
  142. package/dist/roap/turnDiscovery.js +93 -36
  143. package/dist/roap/turnDiscovery.js.map +1 -1
  144. package/dist/rtcMetrics/constants.js +12 -0
  145. package/dist/rtcMetrics/constants.js.map +1 -0
  146. package/dist/rtcMetrics/index.js +117 -0
  147. package/dist/rtcMetrics/index.js.map +1 -0
  148. package/dist/statsAnalyzer/global.js +1 -93
  149. package/dist/statsAnalyzer/global.js.map +1 -1
  150. package/dist/statsAnalyzer/index.js +326 -311
  151. package/dist/statsAnalyzer/index.js.map +1 -1
  152. package/dist/statsAnalyzer/mqaUtil.js +90 -53
  153. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  154. package/dist/types/annotation/annotation.types.d.ts +42 -0
  155. package/dist/types/annotation/constants.d.ts +31 -0
  156. package/dist/types/annotation/index.d.ts +117 -0
  157. package/dist/types/breakouts/breakout.d.ts +8 -0
  158. package/dist/types/breakouts/collection.d.ts +5 -0
  159. package/dist/types/breakouts/edit-lock-error.d.ts +15 -0
  160. package/dist/types/breakouts/events.d.ts +8 -0
  161. package/dist/types/breakouts/index.d.ts +5 -0
  162. package/dist/types/breakouts/request.d.ts +22 -0
  163. package/dist/types/breakouts/utils.d.ts +15 -0
  164. package/dist/types/common/browser-detection.d.ts +9 -0
  165. package/dist/types/common/collection.d.ts +48 -0
  166. package/dist/types/common/config.d.ts +2 -0
  167. package/dist/types/common/errors/captcha-error.d.ts +15 -0
  168. package/dist/types/common/errors/intent-to-join.d.ts +16 -0
  169. package/dist/types/common/errors/join-meeting.d.ts +17 -0
  170. package/dist/types/common/errors/media.d.ts +15 -0
  171. package/dist/types/common/errors/parameter.d.ts +15 -0
  172. package/dist/types/common/errors/password-error.d.ts +15 -0
  173. package/dist/types/common/errors/permission.d.ts +14 -0
  174. package/dist/types/common/errors/reconnection-in-progress.d.ts +9 -0
  175. package/dist/types/common/errors/reconnection.d.ts +15 -0
  176. package/dist/types/common/errors/stats.d.ts +15 -0
  177. package/dist/types/common/errors/webex-errors.d.ts +69 -0
  178. package/dist/types/common/errors/webex-meetings-error.d.ts +20 -0
  179. package/dist/types/common/events/events-scope.d.ts +17 -0
  180. package/dist/types/common/events/events.d.ts +12 -0
  181. package/dist/types/common/events/trigger-proxy.d.ts +2 -0
  182. package/dist/types/common/events/util.d.ts +2 -0
  183. package/dist/types/common/logs/logger-config.d.ts +2 -0
  184. package/dist/types/common/logs/logger-proxy.d.ts +2 -0
  185. package/dist/types/common/logs/request.d.ts +34 -0
  186. package/dist/types/common/queue.d.ts +34 -0
  187. package/dist/types/config.d.ts +72 -0
  188. package/dist/types/constants.d.ts +1020 -0
  189. package/dist/types/controls-options-manager/constants.d.ts +4 -0
  190. package/dist/types/controls-options-manager/enums.d.ts +15 -0
  191. package/dist/types/controls-options-manager/index.d.ts +136 -0
  192. package/dist/types/controls-options-manager/types.d.ts +43 -0
  193. package/dist/types/controls-options-manager/util.d.ts +1 -0
  194. package/dist/types/index.d.ts +7 -0
  195. package/dist/types/interpretation/collection.d.ts +5 -0
  196. package/dist/types/interpretation/index.d.ts +5 -0
  197. package/dist/types/interpretation/siLanguage.d.ts +5 -0
  198. package/dist/types/locus-info/controlsUtils.d.ts +2 -0
  199. package/dist/types/locus-info/embeddedAppsUtils.d.ts +2 -0
  200. package/dist/types/locus-info/fullState.d.ts +2 -0
  201. package/dist/types/locus-info/hostUtils.d.ts +2 -0
  202. package/dist/types/locus-info/index.d.ts +322 -0
  203. package/dist/types/locus-info/infoUtils.d.ts +2 -0
  204. package/dist/types/locus-info/mediaSharesUtils.d.ts +2 -0
  205. package/dist/types/locus-info/parser.d.ts +271 -0
  206. package/dist/types/locus-info/selfUtils.d.ts +2 -0
  207. package/dist/types/media/index.d.ts +34 -0
  208. package/dist/types/media/properties.d.ts +93 -0
  209. package/dist/types/media/util.d.ts +2 -0
  210. package/dist/types/mediaQualityMetrics/config.d.ts +365 -0
  211. package/dist/types/meeting/in-meeting-actions.d.ts +163 -0
  212. package/dist/types/meeting/index.d.ts +1482 -0
  213. package/dist/types/meeting/locusMediaRequest.d.ts +72 -0
  214. package/dist/types/meeting/muteState.d.ts +184 -0
  215. package/dist/types/meeting/request.d.ts +257 -0
  216. package/dist/types/meeting/request.type.d.ts +11 -0
  217. package/dist/types/meeting/state.d.ts +9 -0
  218. package/dist/types/meeting/util.d.ts +79 -0
  219. package/dist/types/meeting-info/collection.d.ts +20 -0
  220. package/dist/types/meeting-info/index.d.ts +62 -0
  221. package/dist/types/meeting-info/meeting-info-v2.d.ts +122 -0
  222. package/dist/types/meeting-info/request.d.ts +22 -0
  223. package/dist/types/meeting-info/util.d.ts +2 -0
  224. package/dist/types/meeting-info/utilv2.d.ts +2 -0
  225. package/dist/types/meetings/collection.d.ts +31 -0
  226. package/dist/types/meetings/index.d.ts +367 -0
  227. package/dist/types/meetings/meetings.types.d.ts +4 -0
  228. package/dist/types/meetings/request.d.ts +27 -0
  229. package/dist/types/meetings/util.d.ts +18 -0
  230. package/dist/types/member/index.d.ts +159 -0
  231. package/dist/types/member/types.d.ts +32 -0
  232. package/dist/types/member/util.d.ts +2 -0
  233. package/dist/types/members/collection.d.ts +29 -0
  234. package/dist/types/members/index.d.ts +353 -0
  235. package/dist/types/members/request.d.ts +114 -0
  236. package/dist/types/members/types.d.ts +24 -0
  237. package/dist/types/members/util.d.ts +210 -0
  238. package/dist/types/metrics/constants.d.ts +55 -0
  239. package/dist/types/metrics/index.d.ts +45 -0
  240. package/dist/types/multistream/mediaRequestManager.d.ts +118 -0
  241. package/dist/types/multistream/receiveSlot.d.ts +68 -0
  242. package/dist/types/multistream/receiveSlotManager.d.ts +56 -0
  243. package/dist/types/multistream/remoteMedia.d.ts +72 -0
  244. package/dist/types/multistream/remoteMediaGroup.d.ts +47 -0
  245. package/dist/types/multistream/remoteMediaManager.d.ts +277 -0
  246. package/dist/types/networkQualityMonitor/index.d.ts +70 -0
  247. package/dist/types/personal-meeting-room/index.d.ts +47 -0
  248. package/dist/types/personal-meeting-room/request.d.ts +14 -0
  249. package/dist/types/personal-meeting-room/util.d.ts +2 -0
  250. package/dist/types/reachability/index.d.ts +152 -0
  251. package/dist/types/reachability/request.d.ts +37 -0
  252. package/dist/types/reactions/constants.d.ts +3 -0
  253. package/dist/types/reactions/reactions.d.ts +4 -0
  254. package/dist/types/reactions/reactions.type.d.ts +52 -0
  255. package/dist/types/reconnection-manager/index.d.ts +126 -0
  256. package/dist/types/recording-controller/enums.d.ts +7 -0
  257. package/dist/types/recording-controller/index.d.ts +207 -0
  258. package/dist/types/recording-controller/util.d.ts +14 -0
  259. package/dist/types/roap/index.d.ts +77 -0
  260. package/dist/types/roap/request.d.ts +36 -0
  261. package/dist/types/roap/turnDiscovery.d.ts +91 -0
  262. package/dist/types/rtcMetrics/constants.d.ts +4 -0
  263. package/dist/types/rtcMetrics/index.d.ts +46 -0
  264. package/dist/types/statsAnalyzer/global.d.ts +36 -0
  265. package/dist/types/statsAnalyzer/index.d.ts +200 -0
  266. package/dist/types/statsAnalyzer/mqaUtil.d.ts +24 -0
  267. package/dist/types/transcription/index.d.ts +64 -0
  268. package/package.json +23 -20
  269. package/src/annotation/annotation.types.ts +50 -0
  270. package/src/annotation/constants.ts +36 -0
  271. package/src/annotation/index.ts +328 -0
  272. package/src/breakouts/README.md +44 -14
  273. package/src/breakouts/breakout.ts +87 -9
  274. package/src/breakouts/edit-lock-error.ts +25 -0
  275. package/src/breakouts/events.ts +56 -0
  276. package/src/breakouts/index.ts +710 -10
  277. package/src/breakouts/request.ts +55 -0
  278. package/src/breakouts/utils.ts +57 -0
  279. package/src/common/errors/webex-errors.ts +6 -2
  280. package/src/common/logs/logger-proxy.ts +1 -1
  281. package/src/common/queue.ts +22 -8
  282. package/src/config.ts +2 -7
  283. package/src/constants.ts +165 -21
  284. package/src/controls-options-manager/constants.ts +5 -0
  285. package/src/controls-options-manager/enums.ts +18 -0
  286. package/src/controls-options-manager/index.ts +278 -0
  287. package/src/controls-options-manager/types.ts +59 -0
  288. package/src/controls-options-manager/util.ts +300 -0
  289. package/src/index.ts +39 -0
  290. package/src/interpretation/README.md +60 -0
  291. package/src/interpretation/collection.ts +19 -0
  292. package/src/interpretation/index.ts +332 -0
  293. package/src/interpretation/siLanguage.ts +18 -0
  294. package/src/locus-info/controlsUtils.ts +108 -0
  295. package/src/locus-info/index.ts +383 -61
  296. package/src/locus-info/infoUtils.ts +10 -2
  297. package/src/locus-info/mediaSharesUtils.ts +48 -0
  298. package/src/locus-info/parser.ts +224 -39
  299. package/src/locus-info/selfUtils.ts +81 -5
  300. package/src/media/index.ts +87 -140
  301. package/src/media/properties.ts +49 -90
  302. package/src/mediaQualityMetrics/config.ts +379 -377
  303. package/src/meeting/in-meeting-actions.ts +179 -3
  304. package/src/meeting/index.ts +2099 -2083
  305. package/src/meeting/locusMediaRequest.ts +311 -0
  306. package/src/meeting/muteState.ts +228 -132
  307. package/src/meeting/request.ts +105 -115
  308. package/src/meeting/util.ts +511 -397
  309. package/src/meeting-info/index.ts +54 -8
  310. package/src/meeting-info/meeting-info-v2.ts +148 -14
  311. package/src/meeting-info/utilv2.ts +13 -3
  312. package/src/meetings/collection.ts +20 -0
  313. package/src/meetings/index.ts +392 -84
  314. package/src/meetings/meetings.types.ts +12 -0
  315. package/src/meetings/request.ts +2 -0
  316. package/src/meetings/util.ts +103 -4
  317. package/src/member/index.ts +49 -0
  318. package/src/member/types.ts +38 -0
  319. package/src/member/util.ts +127 -25
  320. package/src/members/collection.ts +8 -0
  321. package/src/members/index.ts +107 -6
  322. package/src/members/request.ts +97 -17
  323. package/src/members/types.ts +28 -0
  324. package/src/members/util.ts +319 -240
  325. package/src/metrics/constants.ts +2 -4
  326. package/src/metrics/index.ts +1 -490
  327. package/src/multistream/mediaRequestManager.ts +289 -79
  328. package/src/multistream/receiveSlot.ts +55 -18
  329. package/src/multistream/receiveSlotManager.ts +46 -24
  330. package/src/multistream/remoteMedia.ts +27 -2
  331. package/src/multistream/remoteMediaGroup.ts +59 -0
  332. package/src/multistream/remoteMediaManager.ts +113 -32
  333. package/src/networkQualityMonitor/index.ts +6 -6
  334. package/src/reachability/index.ts +62 -15
  335. package/src/reachability/request.ts +10 -5
  336. package/src/reconnection-manager/index.ts +68 -43
  337. package/src/recording-controller/index.ts +20 -3
  338. package/src/recording-controller/util.ts +26 -9
  339. package/src/roap/index.ts +21 -30
  340. package/src/roap/request.ts +101 -95
  341. package/src/roap/turnDiscovery.ts +47 -25
  342. package/src/rtcMetrics/constants.ts +3 -0
  343. package/src/rtcMetrics/index.ts +100 -0
  344. package/src/statsAnalyzer/global.ts +1 -94
  345. package/src/statsAnalyzer/index.ts +376 -386
  346. package/src/statsAnalyzer/mqaUtil.ts +100 -99
  347. package/test/integration/spec/converged-space-meetings.js +233 -0
  348. package/test/integration/spec/journey.js +336 -259
  349. package/test/integration/spec/space-meeting.js +77 -4
  350. package/test/unit/spec/annotation/index.ts +418 -0
  351. package/test/unit/spec/breakouts/breakout.ts +142 -24
  352. package/test/unit/spec/breakouts/edit-lock-error.ts +30 -0
  353. package/test/unit/spec/breakouts/events.ts +89 -0
  354. package/test/unit/spec/breakouts/index.ts +1545 -48
  355. package/test/unit/spec/breakouts/request.ts +104 -0
  356. package/test/unit/spec/breakouts/utils.js +72 -0
  357. package/test/unit/spec/common/queue.js +31 -2
  358. package/test/unit/spec/controls-options-manager/index.js +287 -0
  359. package/test/unit/spec/controls-options-manager/util.js +582 -0
  360. package/test/unit/spec/fixture/locus.js +1 -0
  361. package/test/unit/spec/interpretation/collection.ts +15 -0
  362. package/test/unit/spec/interpretation/index.ts +589 -0
  363. package/test/unit/spec/interpretation/siLanguage.ts +28 -0
  364. package/test/unit/spec/locus-info/controlsUtils.js +316 -43
  365. package/test/unit/spec/locus-info/index.js +1169 -36
  366. package/test/unit/spec/locus-info/infoUtils.js +37 -15
  367. package/test/unit/spec/locus-info/mediaSharesUtils.ts +22 -0
  368. package/test/unit/spec/locus-info/parser.js +62 -22
  369. package/test/unit/spec/locus-info/selfConstant.js +27 -4
  370. package/test/unit/spec/locus-info/selfUtils.js +208 -17
  371. package/test/unit/spec/media/index.ts +138 -28
  372. package/test/unit/spec/meeting/in-meeting-actions.ts +89 -3
  373. package/test/unit/spec/meeting/index.js +3573 -1663
  374. package/test/unit/spec/meeting/locusMediaRequest.ts +438 -0
  375. package/test/unit/spec/meeting/muteState.js +370 -208
  376. package/test/unit/spec/meeting/request.js +339 -44
  377. package/test/unit/spec/meeting/utils.js +456 -53
  378. package/test/unit/spec/meeting-info/index.js +181 -0
  379. package/test/unit/spec/meeting-info/meetinginfov2.js +383 -5
  380. package/test/unit/spec/meeting-info/utilv2.js +21 -0
  381. package/test/unit/spec/meetings/collection.js +14 -0
  382. package/test/unit/spec/meetings/index.js +867 -125
  383. package/test/unit/spec/meetings/utils.js +206 -2
  384. package/test/unit/spec/member/index.js +58 -4
  385. package/test/unit/spec/member/util.js +479 -35
  386. package/test/unit/spec/members/index.js +319 -1
  387. package/test/unit/spec/members/request.js +206 -27
  388. package/test/unit/spec/members/utils.js +184 -0
  389. package/test/unit/spec/metrics/index.js +1 -50
  390. package/test/unit/spec/multistream/mediaRequestManager.ts +803 -162
  391. package/test/unit/spec/multistream/receiveSlot.ts +72 -13
  392. package/test/unit/spec/multistream/receiveSlotManager.ts +58 -28
  393. package/test/unit/spec/multistream/remoteMedia.ts +30 -0
  394. package/test/unit/spec/multistream/remoteMediaGroup.ts +266 -0
  395. package/test/unit/spec/multistream/remoteMediaManager.ts +318 -0
  396. package/test/unit/spec/networkQualityMonitor/index.js +4 -4
  397. package/test/unit/spec/reachability/index.ts +125 -8
  398. package/test/unit/spec/reachability/request.js +66 -0
  399. package/test/unit/spec/reconnection-manager/index.js +59 -6
  400. package/test/unit/spec/recording-controller/index.js +294 -218
  401. package/test/unit/spec/recording-controller/util.js +223 -96
  402. package/test/unit/spec/roap/index.ts +26 -51
  403. package/test/unit/spec/roap/request.ts +196 -85
  404. package/test/unit/spec/roap/turnDiscovery.ts +30 -7
  405. package/test/unit/spec/rtcMetrics/index.ts +60 -0
  406. package/test/unit/spec/stats-analyzer/index.js +92 -41
  407. package/test/utils/constants.js +9 -0
  408. package/test/utils/integrationTestUtils.js +46 -0
  409. package/test/utils/testUtils.js +0 -45
  410. package/test/utils/webex-config.js +4 -0
  411. package/test/utils/webex-test-users.js +6 -3
  412. package/dist/meeting/effectsState.js +0 -262
  413. package/dist/meeting/effectsState.js.map +0 -1
  414. package/dist/metrics/config.js +0 -299
  415. package/dist/metrics/config.js.map +0 -1
  416. package/dist/multistream/multistreamMedia.js +0 -110
  417. package/dist/multistream/multistreamMedia.js.map +0 -1
  418. package/src/index.js +0 -16
  419. package/src/meeting/effectsState.ts +0 -211
  420. package/src/metrics/config.ts +0 -495
  421. package/src/multistream/multistreamMedia.ts +0 -97
  422. package/test/unit/spec/meeting/effectsState.js +0 -285
@@ -1,4 +1,4 @@
1
- import {SELF_ROLES, DISPLAY_HINTS} from '../constants';
1
+ import {SELF_ROLES, DISPLAY_HINTS, INTERSTITIAL_DISPLAY_HINTS} from '../constants';
2
2
 
3
3
  const InfoUtils: any = {};
4
4
 
@@ -9,7 +9,15 @@ InfoUtils.parse = (info, roles, isJoined = true) => {
9
9
  coHost: InfoUtils.parseCoHost(info),
10
10
  };
11
11
 
12
- let userDisplayHints = isJoined ? {...parsed.policy} : {};
12
+ let userDisplayHints = isJoined
13
+ ? {...parsed.policy}
14
+ : {
15
+ ...Object.fromEntries(
16
+ Object.entries(parsed.policy).filter(([hint]) =>
17
+ INTERSTITIAL_DISPLAY_HINTS.includes(hint)
18
+ )
19
+ ),
20
+ };
13
21
 
14
22
  if (roles.includes(SELF_ROLES.COHOST)) {
15
23
  userDisplayHints = {...userDisplayHints, ...parsed.coHost};
@@ -13,6 +13,9 @@ MediaSharesUtils.parse = (mediaShares: object) => {
13
13
  content: {
14
14
  beneficiaryId: MediaSharesUtils.getContentBeneficiaryId(mediaShares),
15
15
  disposition: MediaSharesUtils.getContentDisposition(mediaShares),
16
+ annotation: MediaSharesUtils.getContentAnnotation(mediaShares),
17
+ url: MediaSharesUtils.getContentUrl(mediaShares),
18
+ shareInstanceId: MediaSharesUtils.getShareInstanceId(mediaShares),
16
19
  },
17
20
  whiteboard: {
18
21
  beneficiaryId: MediaSharesUtils.getWhiteboardBeneficiaryId(mediaShares),
@@ -140,6 +143,51 @@ MediaSharesUtils.getContentBeneficiaryId = (mediaShares: object) => {
140
143
  return contentFloor.beneficiary.id;
141
144
  };
142
145
 
146
+ /**
147
+ * get live annotation is sharing from media shares (content)
148
+ * @param {Object} mediaShares
149
+ * @returns {Object}
150
+ */
151
+ MediaSharesUtils.getContentAnnotation = (mediaShares: object) => {
152
+ const extractContent = MediaSharesUtils.extractContent(mediaShares);
153
+
154
+ if (!extractContent || !extractContent.annotation) {
155
+ return undefined;
156
+ }
157
+
158
+ return extractContent.annotation;
159
+ };
160
+
161
+ /**
162
+ * get url is sharing from media shares (content)
163
+ * @param {Object} mediaShares
164
+ * @returns {Object}
165
+ */
166
+ MediaSharesUtils.getContentUrl = (mediaShares: object) => {
167
+ const extractContent = MediaSharesUtils.extractContent(mediaShares);
168
+
169
+ if (!extractContent || !extractContent.url) {
170
+ return undefined;
171
+ }
172
+
173
+ return extractContent.url;
174
+ };
175
+
176
+ /**
177
+ * get shareInstanceId is sharing from media shares (content)
178
+ * @param {Object} mediaShares
179
+ * @returns {Object}
180
+ */
181
+ MediaSharesUtils.getShareInstanceId = (mediaShares: object) => {
182
+ const extractContent = MediaSharesUtils.extractContent(mediaShares);
183
+
184
+ if (!extractContent || !extractContent.floor || !extractContent.floor.shareInstanceId) {
185
+ return undefined;
186
+ }
187
+
188
+ return extractContent.floor.shareInstanceId;
189
+ };
190
+
143
191
  /**
144
192
  * get who is sharing from media shares (whiteboard)
145
193
  * @param {Object} mediaShares
@@ -1,8 +1,26 @@
1
1
  import {difference} from 'lodash';
2
2
 
3
- import SimpleQueue from '../common/queue';
3
+ import SortedQueue from '../common/queue';
4
4
  import LoggerProxy from '../common/logs/logger-proxy';
5
5
 
6
+ const MAX_OOO_DELTA_COUNT = 5; // when we receive an out-of-order delta and the queue builds up to MAX_OOO_DELTA_COUNT, we do a sync with Locus
7
+ const OOO_DELTA_WAIT_TIME = 10000; // [ms] minimum wait time before we do a sync if we get out-of-order deltas
8
+ const OOO_DELTA_WAIT_TIME_RANDOM_DELAY = 5000; // [ms] max random delay added to OOO_DELTA_WAIT_TIME
9
+
10
+ type LocusDeltaDto = {
11
+ baseSequence: {
12
+ rangeStart: number;
13
+ rangeEnd: number;
14
+ entries: number[];
15
+ };
16
+ sequence: {
17
+ rangeStart: number;
18
+ rangeEnd: number;
19
+ entries: number[];
20
+ };
21
+ syncUrl: string;
22
+ };
23
+
6
24
  /**
7
25
  * Locus Delta Parser
8
26
  * @private
@@ -10,11 +28,11 @@ import LoggerProxy from '../common/logs/logger-proxy';
10
28
  */
11
29
  export default class Parser {
12
30
  // processing status
13
- static status = {
14
- IDLE: 'IDLE',
15
- PAUSED: 'PAUSED',
16
- WORKING: 'WORKING',
17
- };
31
+ status:
32
+ | 'IDLE' // not doing anything
33
+ | 'PAUSED' // paused, because we are doing a sync
34
+ | 'WORKING' // processing a delta event
35
+ | 'BLOCKED'; // received an out-of-order delta, so waiting for the missing one
18
36
 
19
37
  // loci comparison states
20
38
  static loci = {
@@ -24,21 +42,59 @@ export default class Parser {
24
42
  DESYNC: 'DESYNC',
25
43
  USE_INCOMING: 'USE_INCOMING',
26
44
  USE_CURRENT: 'USE_CURRENT',
45
+ WAIT: 'WAIT',
27
46
  ERROR: 'ERROR',
28
47
  };
29
48
 
30
- queue: any;
49
+ queue: SortedQueue<LocusDeltaDto>;
31
50
  workingCopy: any;
51
+ syncTimer: null | number | NodeJS.Timeout;
32
52
 
33
53
  /**
34
54
  * @constructs Parser
35
55
  */
36
56
  constructor() {
37
- this.queue = new SimpleQueue();
38
- // @ts-ignore - This is declared as static class member and again being initialized here from same
39
- this.status = Parser.status.IDLE;
57
+ const deltaCompareFunc = (left: LocusDeltaDto, right: LocusDeltaDto) => {
58
+ const {LT, GT} = Parser.loci;
59
+ const {extractComparisonState: extract} = Parser;
60
+
61
+ if (Parser.isSequenceEmpty(left)) {
62
+ return -1;
63
+ }
64
+ if (Parser.isSequenceEmpty(right)) {
65
+ return 1;
66
+ }
67
+ const result = extract(Parser.compareSequence(left.baseSequence, right.baseSequence));
68
+
69
+ if (result === LT) {
70
+ return -1;
71
+ }
72
+ if (result === GT) {
73
+ return 1;
74
+ }
75
+
76
+ return 0;
77
+ };
78
+
79
+ this.queue = new SortedQueue<LocusDeltaDto>(deltaCompareFunc);
80
+ this.status = 'IDLE';
40
81
  this.onDeltaAction = null;
41
82
  this.workingCopy = null;
83
+ this.syncTimer = null;
84
+ }
85
+
86
+ /**
87
+ * Returns a debug string representing a locus delta - useful for logging
88
+ *
89
+ * @param {LocusDeltaDto} locus Locus delta
90
+ * @returns {string}
91
+ */
92
+ static locus2string(locus: LocusDeltaDto) {
93
+ if (!locus.sequence?.entries) {
94
+ return 'invalid';
95
+ }
96
+
97
+ return locus.sequence.entries.length ? `seq=${locus.sequence.entries.at(-1)}` : 'empty';
42
98
  }
43
99
 
44
100
  /**
@@ -208,7 +264,7 @@ export default class Parser {
208
264
  * @returns {string} loci comparison state
209
265
  */
210
266
  private static compareDelta(current, incoming) {
211
- const {LT, GT, EQ, DESYNC, USE_INCOMING} = Parser.loci;
267
+ const {LT, GT, EQ, DESYNC, USE_INCOMING, WAIT} = Parser.loci;
212
268
 
213
269
  const {extractComparisonState: extract} = Parser;
214
270
  const {packComparisonResult: pack} = Parser;
@@ -228,6 +284,17 @@ export default class Parser {
228
284
  comparison = USE_INCOMING;
229
285
  break;
230
286
 
287
+ case LT:
288
+ if (extract(Parser.compareSequence(incoming.baseSequence, incoming.sequence)) === EQ) {
289
+ // special case where Locus sends a delta with baseSequence === sequence to trigger a sync,
290
+ // because the delta event is too large to be sent over mercury connection
291
+ comparison = DESYNC;
292
+ } else {
293
+ // the incoming locus has baseSequence from the future, so it is out-of-order,
294
+ // we are missing 1 or more locus that should be in front of it, we need to wait for it
295
+ comparison = WAIT;
296
+ }
297
+ break;
231
298
  default:
232
299
  comparison = DESYNC;
233
300
  }
@@ -235,6 +302,49 @@ export default class Parser {
235
302
  return pack(comparison, result);
236
303
  }
237
304
 
305
+ /**
306
+ * Compares Locus sequences - it should be called only for full Locus DTOs, not deltas
307
+ *
308
+ * @param {Types~Locus} current Current working copy
309
+ * @param {Types~Locus} incomingFullDto New Full Locus DTO
310
+ * @returns {string} either Parser.loci.USE_INCOMING or Parser.loci.USE_CURRENT
311
+ */
312
+ static compareFullDtoSequence(current, incomingFullDto) {
313
+ if (Parser.isSequenceEmpty(current) || Parser.isSequenceEmpty(incomingFullDto)) {
314
+ return Parser.loci.USE_INCOMING;
315
+ }
316
+
317
+ // the sequence.entries list will always contain at least 1 entry
318
+ // https://sqbu-github.cisco.com/WebExSquared/cloud-apps/wiki/Locus-Sequence-Comparison-Algorithm
319
+
320
+ return incomingFullDto.sequence.entries.slice(-1)[0] > current.sequence.entries.slice(-1)[0]
321
+ ? Parser.loci.USE_INCOMING
322
+ : Parser.loci.USE_CURRENT;
323
+ }
324
+
325
+ /**
326
+ * Returns true if the incoming full locus DTO is newer than the current working copy
327
+ *
328
+ * @param {Types~Locus} incomingFullDto New Full Locus DTO
329
+ * @returns {string} either Parser.loci.USE_INCOMING or Parser.loci.USE_CURRENT
330
+ */
331
+ isNewFullLocus(incomingFullDto) {
332
+ if (!Parser.isLoci(incomingFullDto)) {
333
+ LoggerProxy.logger.info('Locus-info:parser#isNewFullLocus --> Ignoring non-locus object.');
334
+
335
+ return false;
336
+ }
337
+
338
+ if (!this.workingCopy) {
339
+ // we don't have a working copy yet, so any full locus is better than nothing
340
+ return true;
341
+ }
342
+
343
+ const comparisonResult = Parser.compareFullDtoSequence(this.workingCopy, incomingFullDto);
344
+
345
+ return comparisonResult === Parser.loci.USE_INCOMING;
346
+ }
347
+
238
348
  /**
239
349
  * Compares Locus sequences
240
350
  * @param {Types~Locus} current Current working copy
@@ -393,17 +503,10 @@ export default class Parser {
393
503
  */
394
504
  isValidLocus(newLoci) {
395
505
  let isValid = false;
396
- const {IDLE} = Parser.status;
397
506
  const {isLoci} = Parser;
398
- // @ts-ignore
399
- const setStatus = (status) => {
400
- // @ts-ignore
401
- this.status = status;
402
- };
403
507
 
404
508
  // one or both objects are not locus delta events
405
509
  if (!isLoci(this.workingCopy) || !isLoci(newLoci)) {
406
- setStatus(IDLE);
407
510
  LoggerProxy.logger.info(
408
511
  'Locus-info:parser#processDeltaEvent --> Ignoring non-locus object. workingCopy:',
409
512
  this.workingCopy,
@@ -455,19 +558,25 @@ export default class Parser {
455
558
  * @returns {undefined}
456
559
  */
457
560
  nextEvent() {
458
- // @ts-ignore
459
- if (this.status === Parser.status.PAUSED) {
561
+ if (this.status === 'PAUSED') {
460
562
  LoggerProxy.logger.info('Locus-info:parser#nextEvent --> Locus parser paused.');
461
563
 
462
564
  return;
463
565
  }
464
566
 
567
+ if (this.status === 'BLOCKED') {
568
+ LoggerProxy.logger.info(
569
+ 'Locus-info:parser#nextEvent --> Locus parser blocked by out-of-order delta.'
570
+ );
571
+
572
+ return;
573
+ }
574
+
465
575
  // continue processing until queue is empty
466
576
  if (this.queue.size() > 0) {
467
577
  this.processDeltaEvent();
468
578
  } else {
469
- // @ts-ignore
470
- this.status = Parser.status.IDLE;
579
+ this.status = 'IDLE';
471
580
  }
472
581
  }
473
582
 
@@ -478,7 +587,7 @@ export default class Parser {
478
587
  * @param {Types~Locus} locus Locus delta
479
588
  * @returns {undefined}
480
589
  */
481
- // eslint-disable-next-line no-unused-vars
590
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
482
591
  onDeltaAction(action: string, locus) {}
483
592
 
484
593
  /**
@@ -489,15 +598,20 @@ export default class Parser {
489
598
  onDeltaEvent(loci) {
490
599
  // enqueue the new loci
491
600
  this.queue.enqueue(loci);
492
- // start processing events in the queue if idle
493
- // and a function handler is defined
494
- // @ts-ignore
495
- if (this.status === Parser.status.IDLE && this.onDeltaAction) {
496
- // Update status, ensure we only process one event at a time.
497
- // @ts-ignore
498
- this.status = Parser.status.WORKING;
499
601
 
500
- this.processDeltaEvent();
602
+ if (this.onDeltaAction) {
603
+ if (this.status === 'BLOCKED') {
604
+ if (this.queue.size() > MAX_OOO_DELTA_COUNT) {
605
+ this.triggerSync('queue too big, blocked on out-of-order delta');
606
+ } else {
607
+ this.processDeltaEvent();
608
+ }
609
+ } else if (this.status === 'IDLE') {
610
+ // Update status, ensure we only process one event at a time.
611
+ this.status = 'WORKING';
612
+
613
+ this.processDeltaEvent();
614
+ }
501
615
  }
502
616
  }
503
617
 
@@ -516,11 +630,55 @@ export default class Parser {
516
630
  * @returns {undefined}
517
631
  */
518
632
  pause() {
519
- // @ts-ignore
520
- this.status = Parser.status.PAUSED;
633
+ this.status = 'PAUSED';
521
634
  LoggerProxy.logger.info('Locus-info:parser#pause --> Locus parser paused.');
522
635
  }
523
636
 
637
+ /**
638
+ * Triggers a sync with Locus
639
+ *
640
+ * @param {string} reason used just for logging
641
+ * @returns {undefined}
642
+ */
643
+ private triggerSync(reason: string) {
644
+ LoggerProxy.logger.info(`Locus-info:parser#triggerSync --> doing sync, reason: ${reason}`);
645
+ this.stopSyncTimer();
646
+ this.pause();
647
+ this.onDeltaAction(Parser.loci.DESYNC, this.workingCopy);
648
+ }
649
+
650
+ /**
651
+ * Starts a timer with a random delay. When that timer expires we will do a sync.
652
+ *
653
+ * The main purpose of this timer is to handle a case when we get some out-of-order deltas,
654
+ * so we start waiting to receive the missing delta. If that delta never arrives, this timer
655
+ * will trigger a sync with Locus.
656
+ *
657
+ * @returns {undefined}
658
+ */
659
+ private startSyncTimer() {
660
+ if (this.syncTimer === null) {
661
+ const timeout = OOO_DELTA_WAIT_TIME + Math.random() * OOO_DELTA_WAIT_TIME_RANDOM_DELAY;
662
+
663
+ this.syncTimer = setTimeout(() => {
664
+ this.syncTimer = null;
665
+ this.triggerSync('timer expired, blocked on out-of-order delta');
666
+ }, timeout);
667
+ }
668
+ }
669
+
670
+ /**
671
+ * Stops the timer for triggering a sync
672
+ *
673
+ * @returns {undefined}
674
+ */
675
+ private stopSyncTimer() {
676
+ if (this.syncTimer !== null) {
677
+ clearTimeout(this.syncTimer);
678
+ this.syncTimer = null;
679
+ }
680
+ }
681
+
524
682
  /**
525
683
  * Processes next locus delta in the queue,
526
684
  * continues until the queue is empty
@@ -528,11 +686,13 @@ export default class Parser {
528
686
  * @returns {undefined}
529
687
  */
530
688
  processDeltaEvent() {
531
- const {DESYNC, USE_INCOMING} = Parser.loci;
689
+ const {DESYNC, USE_INCOMING, WAIT} = Parser.loci;
532
690
  const {extractComparisonState: extract} = Parser;
533
691
  const newLoci = this.queue.dequeue();
534
692
 
535
693
  if (!this.isValidLocus(newLoci)) {
694
+ this.nextEvent();
695
+
536
696
  return;
537
697
  }
538
698
 
@@ -543,6 +703,8 @@ export default class Parser {
543
703
  // for full debugging.
544
704
  LoggerProxy.logger.debug(`Locus-info:parser#processDeltaEvent --> Locus Debug: ${result}`);
545
705
 
706
+ let needToWait = false;
707
+
546
708
  if (lociComparison === DESYNC) {
547
709
  // wait for desync response
548
710
  this.pause();
@@ -551,15 +713,39 @@ export default class Parser {
551
713
  // Note: The working copy of parser gets updated in .onFullLocus()
552
714
  // and here when USE_INCOMING locus.
553
715
  this.workingCopy = newLoci;
716
+ } else if (lociComparison === WAIT) {
717
+ // we've taken newLoci from the front of the queue, so put it back there as we have to wait
718
+ // for the one that should be in front of it, before we can process it
719
+ this.queue.enqueue(newLoci);
720
+ needToWait = true;
721
+ }
722
+
723
+ if (needToWait) {
724
+ this.status = 'BLOCKED';
725
+ this.startSyncTimer();
726
+ } else {
727
+ this.stopSyncTimer();
728
+
729
+ if (this.status === 'BLOCKED') {
730
+ // we are not blocked anymore
731
+ this.status = 'WORKING';
732
+
733
+ LoggerProxy.logger.info(
734
+ `Locus-info:parser#processDeltaEvent --> received delta that we were waiting for ${Parser.locus2string(
735
+ newLoci
736
+ )}, not blocked anymore`
737
+ );
738
+ }
554
739
  }
555
740
 
556
741
  if (this.onDeltaAction) {
557
742
  LoggerProxy.logger.info(
558
- `Locus-info:parser#processDeltaEvent --> Locus Delta Action: ${lociComparison}`
743
+ `Locus-info:parser#processDeltaEvent --> Locus Delta ${Parser.locus2string(
744
+ newLoci
745
+ )}, Action: ${lociComparison}`
559
746
  );
560
747
 
561
- // eslint-disable-next-line no-useless-call
562
- this.onDeltaAction.call(this, lociComparison, newLoci);
748
+ this.onDeltaAction(lociComparison, newLoci);
563
749
  }
564
750
 
565
751
  this.nextEvent();
@@ -571,8 +757,7 @@ export default class Parser {
571
757
  */
572
758
  resume() {
573
759
  LoggerProxy.logger.info('Locus-info:parser#resume --> Locus parser resumed.');
574
- // @ts-ignore
575
- this.status = Parser.status.WORKING;
760
+ this.status = 'WORKING';
576
761
  this.nextEvent();
577
762
  }
578
763
 
@@ -32,9 +32,11 @@ SelfUtils.parse = (self: any, deviceId: string) => {
32
32
  const pstnDevices = self.devices.filter((device) => PSTN_DEVICE_TYPE === device.deviceType);
33
33
 
34
34
  return {
35
+ remoteVideoMuted: SelfUtils.getRemoteVideoMuted(self),
35
36
  remoteMuted: SelfUtils.getRemoteMuted(self),
36
37
  unmuteAllowed: SelfUtils.getUnmuteAllowed(self),
37
38
  localAudioUnmuteRequested: SelfUtils.getLocalAudioUnmuteRequested(self),
39
+ localAudioUnmuteRequestedTimeStamp: SelfUtils.getLocalAudioUnmuteRequestedTimeStamp(self),
38
40
  localAudioUnmuteRequired: SelfUtils.getLocalAudioUnmuteRequired(self),
39
41
  lastModified: SelfUtils.getLastModified(self),
40
42
  modifiedBy: SelfUtils.getModifiedBy(self),
@@ -61,14 +63,18 @@ SelfUtils.parse = (self: any, deviceId: string) => {
61
63
  layout: SelfUtils.getLayout(self),
62
64
  canNotViewTheParticipantList: SelfUtils.canNotViewTheParticipantList(self),
63
65
  isSharingBlocked: SelfUtils.isSharingBlocked(self),
64
- breakoutSessions: SelfUtils.getBreakouts(self),
66
+ breakoutSessions: SelfUtils.getBreakoutSessions(self),
67
+ breakout: SelfUtils.getBreakout(self),
68
+ interpretation: SelfUtils.getInterpretation(self),
65
69
  };
66
70
  }
67
71
 
68
72
  return null;
69
73
  };
70
74
 
71
- SelfUtils.getBreakouts = (self) => self?.controls?.breakout?.sessions;
75
+ SelfUtils.getBreakoutSessions = (self) => self?.controls?.breakout?.sessions;
76
+ SelfUtils.getBreakout = (self) => self?.controls?.breakout;
77
+ SelfUtils.getInterpretation = (self) => self?.controls?.interpretation;
72
78
 
73
79
  SelfUtils.getLayout = (self) =>
74
80
  Array.isArray(self?.controls?.layouts) ? self.controls.layouts[0].type : undefined;
@@ -93,6 +99,7 @@ SelfUtils.getSelves = (oldSelf, newSelf, deviceId) => {
93
99
 
94
100
  updates.isUserUnadmitted = SelfUtils.isUserUnadmitted(current);
95
101
  updates.isUserAdmitted = SelfUtils.isUserAdmitted(previous, current);
102
+ updates.isVideoMutedByOthersChanged = SelfUtils.videoMutedByOthersChanged(previous, current);
96
103
  updates.isMutedByOthersChanged = SelfUtils.mutedByOthersChanged(previous, current);
97
104
  updates.localAudioUnmuteRequestedByServer = SelfUtils.localAudioUnmuteRequestedByServer(
98
105
  previous,
@@ -103,6 +110,7 @@ SelfUtils.getSelves = (oldSelf, newSelf, deviceId) => {
103
110
  current
104
111
  );
105
112
  updates.moderatorChanged = SelfUtils.moderatorChanged(previous, current);
113
+ updates.isRolesChanged = SelfUtils.isRolesChanged(previous, current);
106
114
  updates.isMediaInactiveOrReleased = SelfUtils.wasMediaInactiveOrReleased(previous, current);
107
115
  updates.isUserObserving = SelfUtils.isDeviceObserving(previous, current);
108
116
  updates.layoutChanged = SelfUtils.layoutChanged(previous, current);
@@ -119,6 +127,7 @@ SelfUtils.getSelves = (oldSelf, newSelf, deviceId) => {
119
127
  previous?.canNotViewTheParticipantList !== current.canNotViewTheParticipantList;
120
128
  updates.isSharingBlockedChanged = previous?.isSharingBlocked !== current.isSharingBlocked;
121
129
  updates.breakoutsChanged = SelfUtils.breakoutsChanged(previous, current);
130
+ updates.interpretationChanged = SelfUtils.interpretationChanged(previous, current);
122
131
 
123
132
  return {
124
133
  previous,
@@ -139,13 +148,16 @@ SelfUtils.isJoined = (self: any) => self?.state === _JOINED_;
139
148
  *
140
149
  * @param {Self} previous - Previous self state
141
150
  * @param {Self} current - Current self state [per event]
142
- * @returns {boolean} - If the MEeting Layout Controls Layout has changed.
151
+ * @returns {boolean} - If the Meeting Layout Controls Layout has changed.
143
152
  */
144
153
  SelfUtils.layoutChanged = (previous: any, current: any) =>
145
154
  current?.layout && previous?.layout !== current?.layout;
146
155
 
147
156
  SelfUtils.breakoutsChanged = (previous, current) =>
148
- !isEqual(previous?.breakoutSessions, current?.breakoutSessions);
157
+ !isEqual(previous?.breakoutSessions, current?.breakoutSessions) && !!current?.breakout;
158
+
159
+ SelfUtils.interpretationChanged = (previous, current) =>
160
+ !isEqual(previous?.interpretation, current?.interpretation) && !!current?.interpretation;
149
161
 
150
162
  SelfUtils.isMediaInactive = (previous, current) => {
151
163
  if (
@@ -236,6 +248,19 @@ SelfUtils.getSelfIdentity = (self: any) => {
236
248
  return self.person.id;
237
249
  };
238
250
 
251
+ /**
252
+ * get the "remote video mute" property from the self object
253
+ * @param {Object} self
254
+ * @returns {Boolean}
255
+ */
256
+ SelfUtils.getRemoteVideoMuted = (self: any) => {
257
+ if (!self || !self.controls || !self.controls.video) {
258
+ return null;
259
+ }
260
+
261
+ return self.controls.video.muted;
262
+ };
263
+
239
264
  /**
240
265
  * get the "remote mute" property from the self object
241
266
  * @param {Object} self
@@ -251,6 +276,10 @@ SelfUtils.getRemoteMuted = (self: any) => {
251
276
 
252
277
  SelfUtils.getLocalAudioUnmuteRequested = (self) => !!self?.controls?.audio?.requestedToUnmute;
253
278
 
279
+ // requestedToUnmute timestamp
280
+ SelfUtils.getLocalAudioUnmuteRequestedTimeStamp = (self) =>
281
+ Date.parse(self?.controls?.audio?.lastModifiedRequestedToUnmute) || 0;
282
+
254
283
  SelfUtils.getUnmuteAllowed = (self) => {
255
284
  if (!self || !self.controls || !self.controls.audio) {
256
285
  return null;
@@ -275,6 +304,7 @@ SelfUtils.getStatus = (status) => ({
275
304
  SelfUtils.wasMediaInactiveOrReleased = (oldSelf: any = {}, changedSelf: any) =>
276
305
  oldSelf.joinedWith &&
277
306
  oldSelf.joinedWith.state === _JOINED_ &&
307
+ changedSelf.joinedWith &&
278
308
  changedSelf.joinedWith.state === _LEFT_ &&
279
309
  (changedSelf.joinedWith.reason === MEETING_END_REASON.INACTIVE ||
280
310
  changedSelf.joinedWith.reason === MEETING_END_REASON.MEDIA_RELEASED);
@@ -319,6 +349,20 @@ SelfUtils.moderatorChanged = (oldSelf, changedSelf) => {
319
349
  return oldSelf.moderator !== changedSelf.moderator;
320
350
  };
321
351
 
352
+ /**
353
+ * determine whether the roles of self is changed or not
354
+ * @param {Object} oldSelf
355
+ * @param {Object} changedSelf
356
+ * @returns {Boolean}
357
+ */
358
+ SelfUtils.isRolesChanged = (oldSelf, changedSelf) => {
359
+ if (!changedSelf) {
360
+ // no new self means no change
361
+ return false;
362
+ }
363
+
364
+ return !isEqual(oldSelf?.roles, changedSelf?.roles);
365
+ };
322
366
  /**
323
367
  * @param {Object} oldSelf
324
368
  * @param {Object} changedSelf
@@ -351,6 +395,25 @@ SelfUtils.isUserAdmitted = (oldSelf: object, changedSelf: object) => {
351
395
  return SelfUtils.isLocusUserUnadmitted(oldSelf) && SelfUtils.isLocusUserAdmitted(changedSelf);
352
396
  };
353
397
 
398
+ SelfUtils.videoMutedByOthersChanged = (oldSelf, changedSelf) => {
399
+ if (!changedSelf) {
400
+ throw new ParameterError(
401
+ 'New self must be defined to determine if self was video muted by others.'
402
+ );
403
+ }
404
+
405
+ if (!oldSelf || oldSelf.remoteVideoMuted === null) {
406
+ if (changedSelf.remoteVideoMuted) {
407
+ return true; // this happens when host disables "Allow start video"
408
+ }
409
+
410
+ // we don't want to be sending the 'meeting:self:videoUnmutedByOthers' notification on meeting join
411
+ return false;
412
+ }
413
+
414
+ return oldSelf.remoteVideoMuted !== changedSelf.remoteVideoMuted;
415
+ };
416
+
354
417
  SelfUtils.mutedByOthersChanged = (oldSelf, changedSelf) => {
355
418
  if (!changedSelf) {
356
419
  throw new ParameterError('New self must be defined to determine if self was muted by others.');
@@ -379,7 +442,10 @@ SelfUtils.localAudioUnmuteRequestedByServer = (oldSelf: any = {}, changedSelf: a
379
442
  );
380
443
  }
381
444
 
382
- return changedSelf.localAudioUnmuteRequested && !oldSelf.localAudioUnmuteRequested;
445
+ return (
446
+ changedSelf.localAudioUnmuteRequested &&
447
+ changedSelf.localAudioUnmuteRequestedTimeStamp > oldSelf.localAudioUnmuteRequestedTimeStamp
448
+ );
383
449
  };
384
450
 
385
451
  SelfUtils.localAudioUnmuteRequiredByServer = (oldSelf: any = {}, changedSelf: any) => {
@@ -432,4 +498,14 @@ SelfUtils.getMediaStatus = (mediaSessions = []) => {
432
498
  return mediaStatus;
433
499
  };
434
500
 
501
+ SelfUtils.getReplacedBreakoutMoveId = (self: any, deviceId: string) => {
502
+ if (self && Array.isArray(self.devices)) {
503
+ const joinedDevice = self.devices.find((device) => deviceId === device.url);
504
+ if (Array.isArray(joinedDevice?.replaces)) {
505
+ return joinedDevice.replaces[0]?.breakoutMoveId;
506
+ }
507
+ }
508
+
509
+ return null;
510
+ };
435
511
  export default SelfUtils;