@webex/plugin-meetings 3.0.0-test.1 → 3.1.0

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 (431) hide show
  1. package/.eslintrc.js +6 -0
  2. package/babel.config.js +3 -0
  3. package/dist/annotation/constants.js +12 -20
  4. package/dist/annotation/constants.js.map +1 -1
  5. package/dist/annotation/index.js +25 -10
  6. package/dist/annotation/index.js.map +1 -1
  7. package/dist/breakouts/breakout.js +2 -3
  8. package/dist/breakouts/breakout.js.map +1 -1
  9. package/dist/breakouts/collection.js +1 -2
  10. package/dist/breakouts/collection.js.map +1 -1
  11. package/dist/breakouts/edit-lock-error.js +1 -2
  12. package/dist/breakouts/edit-lock-error.js.map +1 -1
  13. package/dist/breakouts/events.js +1 -2
  14. package/dist/breakouts/events.js.map +1 -1
  15. package/dist/breakouts/index.js +13 -14
  16. package/dist/breakouts/index.js.map +1 -1
  17. package/dist/breakouts/request.js +1 -2
  18. package/dist/breakouts/request.js.map +1 -1
  19. package/dist/breakouts/utils.js +3 -6
  20. package/dist/breakouts/utils.js.map +1 -1
  21. package/dist/common/browser-detection.js +2 -3
  22. package/dist/common/browser-detection.js.map +1 -1
  23. package/dist/common/collection.js +3 -4
  24. package/dist/common/collection.js.map +1 -1
  25. package/dist/common/config.js +1 -2
  26. package/dist/common/config.js.map +1 -1
  27. package/dist/common/errors/captcha-error.js +1 -2
  28. package/dist/common/errors/captcha-error.js.map +1 -1
  29. package/dist/common/errors/intent-to-join.js +1 -2
  30. package/dist/common/errors/intent-to-join.js.map +1 -1
  31. package/dist/common/errors/join-meeting.js +1 -2
  32. package/dist/common/errors/join-meeting.js.map +1 -1
  33. package/dist/common/errors/media.js +1 -2
  34. package/dist/common/errors/media.js.map +1 -1
  35. package/dist/common/errors/no-meeting-info.js +1 -2
  36. package/dist/common/errors/no-meeting-info.js.map +1 -1
  37. package/dist/common/errors/parameter.js +3 -4
  38. package/dist/common/errors/parameter.js.map +1 -1
  39. package/dist/common/errors/password-error.js +1 -2
  40. package/dist/common/errors/password-error.js.map +1 -1
  41. package/dist/common/errors/permission.js +1 -2
  42. package/dist/common/errors/permission.js.map +1 -1
  43. package/dist/common/errors/reclaim-host-role-errors.js +6 -10
  44. package/dist/common/errors/reclaim-host-role-errors.js.map +1 -1
  45. package/dist/common/errors/reconnection-in-progress.js +1 -2
  46. package/dist/common/errors/reconnection-in-progress.js.map +1 -1
  47. package/dist/common/errors/reconnection.js +1 -2
  48. package/dist/common/errors/reconnection.js.map +1 -1
  49. package/dist/common/errors/stats.js +1 -2
  50. package/dist/common/errors/stats.js.map +1 -1
  51. package/dist/common/errors/webex-errors.js +14 -15
  52. package/dist/common/errors/webex-errors.js.map +1 -1
  53. package/dist/common/errors/webex-meetings-error.js +1 -2
  54. package/dist/common/errors/webex-meetings-error.js.map +1 -1
  55. package/dist/common/events/events-scope.js +1 -2
  56. package/dist/common/events/events-scope.js.map +1 -1
  57. package/dist/common/events/events.js +1 -2
  58. package/dist/common/events/events.js.map +1 -1
  59. package/dist/common/events/trigger-proxy.js +1 -2
  60. package/dist/common/events/trigger-proxy.js.map +1 -1
  61. package/dist/common/events/util.js +1 -2
  62. package/dist/common/events/util.js.map +1 -1
  63. package/dist/common/logs/logger-config.js +1 -2
  64. package/dist/common/logs/logger-config.js.map +1 -1
  65. package/dist/common/logs/logger-proxy.js +1 -2
  66. package/dist/common/logs/logger-proxy.js.map +1 -1
  67. package/dist/{types/common → common}/logs/request.d.ts +1 -1
  68. package/dist/common/logs/request.js +3 -4
  69. package/dist/common/logs/request.js.map +1 -1
  70. package/dist/common/queue.js +2 -4
  71. package/dist/common/queue.js.map +1 -1
  72. package/dist/{types/config.d.ts → config.d.ts} +1 -0
  73. package/dist/config.js +4 -3
  74. package/dist/config.js.map +1 -1
  75. package/dist/{types/constants.d.ts → constants.d.ts} +10 -5
  76. package/dist/constants.js +207 -380
  77. package/dist/constants.js.map +1 -1
  78. package/dist/controls-options-manager/constants.js +3 -6
  79. package/dist/controls-options-manager/constants.js.map +1 -1
  80. package/dist/controls-options-manager/enums.js +7 -10
  81. package/dist/controls-options-manager/enums.js.map +1 -1
  82. package/dist/controls-options-manager/index.js +27 -32
  83. package/dist/controls-options-manager/index.js.map +1 -1
  84. package/dist/controls-options-manager/util.js +1 -2
  85. package/dist/controls-options-manager/util.js.map +1 -1
  86. package/dist/index.js +3 -4
  87. package/dist/index.js.map +1 -1
  88. package/dist/interceptors/index.js.map +1 -1
  89. package/dist/interceptors/locusRetry.js +4 -3
  90. package/dist/interceptors/locusRetry.js.map +1 -1
  91. package/dist/interpretation/collection.js +1 -2
  92. package/dist/interpretation/collection.js.map +1 -1
  93. package/dist/interpretation/index.js +4 -5
  94. package/dist/interpretation/index.js.map +1 -1
  95. package/dist/interpretation/siLanguage.js +2 -3
  96. package/dist/interpretation/siLanguage.js.map +1 -1
  97. package/dist/locus-info/controlsUtils.js +12 -13
  98. package/dist/locus-info/controlsUtils.js.map +1 -1
  99. package/dist/locus-info/embeddedAppsUtils.js +3 -4
  100. package/dist/locus-info/embeddedAppsUtils.js.map +1 -1
  101. package/dist/locus-info/fullState.js +1 -2
  102. package/dist/locus-info/fullState.js.map +1 -1
  103. package/dist/locus-info/hostUtils.js +1 -2
  104. package/dist/locus-info/hostUtils.js.map +1 -1
  105. package/dist/locus-info/index.js +23 -27
  106. package/dist/locus-info/index.js.map +1 -1
  107. package/dist/locus-info/infoUtils.js +3 -4
  108. package/dist/locus-info/infoUtils.js.map +1 -1
  109. package/dist/locus-info/mediaSharesUtils.js +16 -3
  110. package/dist/locus-info/mediaSharesUtils.js.map +1 -1
  111. package/dist/locus-info/parser.js +6 -10
  112. package/dist/locus-info/parser.js.map +1 -1
  113. package/dist/locus-info/selfUtils.js +12 -6
  114. package/dist/locus-info/selfUtils.js.map +1 -1
  115. package/dist/media/MediaConnectionAwaiter.d.ts +61 -0
  116. package/dist/media/MediaConnectionAwaiter.js +163 -0
  117. package/dist/media/MediaConnectionAwaiter.js.map +1 -0
  118. package/dist/media/index.js +9 -5
  119. package/dist/media/index.js.map +1 -1
  120. package/dist/media/properties.js +7 -28
  121. package/dist/media/properties.js.map +1 -1
  122. package/dist/media/util.js +1 -2
  123. package/dist/media/util.js.map +1 -1
  124. package/dist/mediaQualityMetrics/config.js +9 -18
  125. package/dist/mediaQualityMetrics/config.js.map +1 -1
  126. package/dist/meeting/in-meeting-actions.js +14 -2
  127. package/dist/meeting/in-meeting-actions.js.map +1 -1
  128. package/dist/{types/meeting → meeting}/index.d.ts +71 -16
  129. package/dist/meeting/index.js +1411 -1036
  130. package/dist/meeting/index.js.map +1 -1
  131. package/dist/meeting/locusMediaRequest.js +4 -5
  132. package/dist/meeting/locusMediaRequest.js.map +1 -1
  133. package/dist/meeting/muteState.js +2 -4
  134. package/dist/meeting/muteState.js.map +1 -1
  135. package/dist/{types/meeting → meeting}/request.d.ts +3 -0
  136. package/dist/meeting/request.js +45 -36
  137. package/dist/meeting/request.js.map +1 -1
  138. package/dist/meeting/state.js +1 -2
  139. package/dist/meeting/state.js.map +1 -1
  140. package/dist/{types/meeting → meeting}/util.d.ts +1 -0
  141. package/dist/meeting/util.js +13 -10
  142. package/dist/meeting/util.js.map +1 -1
  143. package/dist/meeting/voicea-meeting.d.ts +16 -0
  144. package/dist/meeting/voicea-meeting.js +169 -0
  145. package/dist/meeting/voicea-meeting.js.map +1 -0
  146. package/dist/meeting-info/collection.js +3 -4
  147. package/dist/meeting-info/collection.js.map +1 -1
  148. package/dist/meeting-info/index.js +5 -4
  149. package/dist/meeting-info/index.js.map +1 -1
  150. package/dist/meeting-info/meeting-info-v2.js +27 -29
  151. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  152. package/dist/meeting-info/request.js +1 -2
  153. package/dist/meeting-info/request.js.map +1 -1
  154. package/dist/meeting-info/util.js +8 -8
  155. package/dist/meeting-info/util.js.map +1 -1
  156. package/dist/meeting-info/utilv2.js +15 -9
  157. package/dist/meeting-info/utilv2.js.map +1 -1
  158. package/dist/meetings/collection.js +5 -6
  159. package/dist/meetings/collection.js.map +1 -1
  160. package/dist/{types/meetings → meetings}/index.d.ts +11 -2
  161. package/dist/meetings/index.js +44 -17
  162. package/dist/meetings/index.js.map +1 -1
  163. package/dist/meetings/request.js +2 -3
  164. package/dist/meetings/request.js.map +1 -1
  165. package/dist/meetings/util.js +1 -4
  166. package/dist/meetings/util.js.map +1 -1
  167. package/dist/member/index.js +1 -3
  168. package/dist/member/index.js.map +1 -1
  169. package/dist/member/types.js +6 -8
  170. package/dist/member/types.js.map +1 -1
  171. package/dist/member/util.js +1 -2
  172. package/dist/member/util.js.map +1 -1
  173. package/dist/members/collection.js +1 -2
  174. package/dist/members/collection.js.map +1 -1
  175. package/dist/members/index.js +8 -7
  176. package/dist/members/index.js.map +1 -1
  177. package/dist/members/request.js +2 -3
  178. package/dist/members/request.js.map +1 -1
  179. package/dist/members/types.js +3 -4
  180. package/dist/members/types.js.map +1 -1
  181. package/dist/{types/members → members}/util.d.ts +1 -1
  182. package/dist/members/util.js +3 -4
  183. package/dist/members/util.js.map +1 -1
  184. package/dist/metrics/constants.js +1 -2
  185. package/dist/metrics/constants.js.map +1 -1
  186. package/dist/metrics/index.js +3 -2
  187. package/dist/metrics/index.js.map +1 -1
  188. package/dist/{types/multistream → multistream}/mediaRequestManager.d.ts +1 -2
  189. package/dist/multistream/mediaRequestManager.js +9 -11
  190. package/dist/multistream/mediaRequestManager.js.map +1 -1
  191. package/dist/multistream/receiveSlot.js +3 -5
  192. package/dist/multistream/receiveSlot.js.map +1 -1
  193. package/dist/multistream/receiveSlotManager.js +7 -9
  194. package/dist/multistream/receiveSlotManager.js.map +1 -1
  195. package/dist/multistream/remoteMedia.js +3 -5
  196. package/dist/multistream/remoteMedia.js.map +1 -1
  197. package/dist/{types/multistream → multistream}/remoteMediaGroup.d.ts +1 -1
  198. package/dist/multistream/remoteMediaGroup.js +7 -6
  199. package/dist/multistream/remoteMediaGroup.js.map +1 -1
  200. package/dist/{types/multistream → multistream}/remoteMediaManager.d.ts +1 -2
  201. package/dist/multistream/remoteMediaManager.js +32 -29
  202. package/dist/multistream/remoteMediaManager.js.map +1 -1
  203. package/dist/{types/multistream → multistream}/sendSlotManager.d.ts +1 -2
  204. package/dist/multistream/sendSlotManager.js +9 -6
  205. package/dist/multistream/sendSlotManager.js.map +1 -1
  206. package/dist/networkQualityMonitor/index.js +1 -2
  207. package/dist/networkQualityMonitor/index.js.map +1 -1
  208. package/dist/personal-meeting-room/index.js +2 -3
  209. package/dist/personal-meeting-room/index.js.map +1 -1
  210. package/dist/personal-meeting-room/request.js +2 -3
  211. package/dist/personal-meeting-room/request.js.map +1 -1
  212. package/dist/personal-meeting-room/util.js +1 -2
  213. package/dist/personal-meeting-room/util.js.map +1 -1
  214. package/dist/{types/reachability → reachability}/clusterReachability.d.ts +1 -0
  215. package/dist/reachability/clusterReachability.js +35 -20
  216. package/dist/reachability/clusterReachability.js.map +1 -1
  217. package/dist/{types/reachability → reachability}/index.d.ts +4 -0
  218. package/dist/reachability/index.js +41 -12
  219. package/dist/reachability/index.js.map +1 -1
  220. package/dist/reachability/request.js +25 -20
  221. package/dist/reachability/request.js.map +1 -1
  222. package/dist/{types/reachability → reachability}/util.d.ts +7 -0
  223. package/dist/reachability/util.js +19 -0
  224. package/dist/reachability/util.js.map +1 -1
  225. package/dist/reactions/constants.js +1 -2
  226. package/dist/reactions/constants.js.map +1 -1
  227. package/dist/reactions/reactions.js +2 -4
  228. package/dist/reactions/reactions.js.map +1 -1
  229. package/dist/reactions/reactions.type.js +6 -8
  230. package/dist/reactions/reactions.type.js.map +1 -1
  231. package/dist/reconnection-manager/index.js +18 -11
  232. package/dist/reconnection-manager/index.js.map +1 -1
  233. package/dist/recording-controller/enums.js +4 -5
  234. package/dist/recording-controller/enums.js.map +1 -1
  235. package/dist/recording-controller/index.js +43 -51
  236. package/dist/recording-controller/index.js.map +1 -1
  237. package/dist/recording-controller/util.js +1 -2
  238. package/dist/recording-controller/util.js.map +1 -1
  239. package/dist/{types/roap → roap}/index.d.ts +10 -2
  240. package/dist/roap/index.js +17 -3
  241. package/dist/roap/index.js.map +1 -1
  242. package/dist/roap/request.js +10 -10
  243. package/dist/roap/request.js.map +1 -1
  244. package/dist/{types/roap → roap}/turnDiscovery.d.ts +64 -17
  245. package/dist/roap/turnDiscovery.js +316 -134
  246. package/dist/roap/turnDiscovery.js.map +1 -1
  247. package/dist/rtcMetrics/constants.js +1 -2
  248. package/dist/rtcMetrics/constants.js.map +1 -1
  249. package/dist/rtcMetrics/index.js +4 -6
  250. package/dist/rtcMetrics/index.js.map +1 -1
  251. package/dist/statsAnalyzer/global.js +1 -2
  252. package/dist/statsAnalyzer/global.js.map +1 -1
  253. package/dist/statsAnalyzer/index.js +123 -96
  254. package/dist/statsAnalyzer/index.js.map +1 -1
  255. package/dist/statsAnalyzer/mqaUtil.js +24 -31
  256. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  257. package/dist/transcription/index.js +1 -2
  258. package/dist/transcription/index.js.map +1 -1
  259. package/dist/webinar/collection.js +1 -2
  260. package/dist/webinar/collection.js.map +1 -1
  261. package/dist/webinar/index.js +2 -3
  262. package/dist/webinar/index.js.map +1 -1
  263. package/jest.config.js +3 -0
  264. package/package.json +44 -25
  265. package/process +1 -0
  266. package/src/config.ts +3 -4
  267. package/src/constants.ts +13 -4
  268. package/src/interpretation/index.ts +2 -2
  269. package/src/locus-info/mediaSharesUtils.ts +16 -0
  270. package/src/locus-info/selfUtils.ts +5 -0
  271. package/src/media/MediaConnectionAwaiter.ts +174 -0
  272. package/src/media/index.ts +3 -1
  273. package/src/media/properties.ts +6 -31
  274. package/src/meeting/index.ts +526 -227
  275. package/src/meeting/request.ts +18 -2
  276. package/src/meeting/util.ts +6 -1
  277. package/src/meeting/voicea-meeting.ts +122 -0
  278. package/src/meeting-info/meeting-info-v2.ts +5 -11
  279. package/src/meeting-info/util.ts +12 -9
  280. package/src/meeting-info/utilv2.ts +26 -15
  281. package/src/meetings/index.ts +18 -0
  282. package/src/member/index.ts +0 -1
  283. package/src/multistream/mediaRequestManager.ts +1 -1
  284. package/src/multistream/remoteMediaGroup.ts +1 -1
  285. package/src/multistream/remoteMediaManager.ts +1 -2
  286. package/src/multistream/sendSlotManager.ts +1 -2
  287. package/src/reachability/clusterReachability.ts +20 -5
  288. package/src/reachability/index.ts +24 -1
  289. package/src/reachability/request.ts +15 -11
  290. package/src/reachability/util.ts +21 -0
  291. package/src/reconnection-manager/index.ts +1 -1
  292. package/src/roap/index.ts +25 -3
  293. package/src/roap/request.ts +2 -2
  294. package/src/roap/turnDiscovery.ts +244 -78
  295. package/src/statsAnalyzer/index.ts +63 -27
  296. package/test/integration/spec/journey.js +2 -2
  297. package/test/unit/spec/breakouts/breakout.ts +2 -1
  298. package/test/unit/spec/breakouts/index.ts +7 -4
  299. package/test/unit/spec/interpretation/index.ts +4 -1
  300. package/test/unit/spec/locus-info/index.js +27 -18
  301. package/test/unit/spec/locus-info/mediaSharesUtils.ts +9 -0
  302. package/test/unit/spec/locus-info/selfUtils.js +41 -11
  303. package/test/unit/spec/media/MediaConnectionAwaiter.ts +344 -0
  304. package/test/unit/spec/media/index.ts +94 -78
  305. package/test/unit/spec/media/properties.ts +16 -70
  306. package/test/unit/spec/meeting/index.js +757 -141
  307. package/test/unit/spec/meeting/request.js +21 -0
  308. package/test/unit/spec/meeting/utils.js +58 -11
  309. package/test/unit/spec/meeting/voicea-meeting.ts +266 -0
  310. package/test/unit/spec/meeting-info/meetinginfov2.js +20 -15
  311. package/test/unit/spec/meeting-info/utilv2.js +6 -0
  312. package/test/unit/spec/meetings/index.js +101 -13
  313. package/test/unit/spec/metrics/index.js +1 -2
  314. package/test/unit/spec/multistream/mediaRequestManager.ts +1 -0
  315. package/test/unit/spec/multistream/remoteMediaGroup.ts +0 -1
  316. package/test/unit/spec/multistream/remoteMediaManager.ts +0 -1
  317. package/test/unit/spec/reachability/clusterReachability.ts +86 -22
  318. package/test/unit/spec/reachability/index.ts +197 -60
  319. package/test/unit/spec/reachability/request.js +15 -7
  320. package/test/unit/spec/reachability/util.ts +32 -2
  321. package/test/unit/spec/reconnection-manager/index.js +28 -0
  322. package/test/unit/spec/recording-controller/index.js +0 -1
  323. package/test/unit/spec/roap/index.ts +61 -6
  324. package/test/unit/spec/roap/turnDiscovery.ts +299 -17
  325. package/test/unit/spec/stats-analyzer/index.js +179 -0
  326. /package/dist/{types/annotation → annotation}/annotation.types.d.ts +0 -0
  327. /package/dist/{types/annotation → annotation}/constants.d.ts +0 -0
  328. /package/dist/{types/annotation → annotation}/index.d.ts +0 -0
  329. /package/dist/{types/breakouts → breakouts}/breakout.d.ts +0 -0
  330. /package/dist/{types/breakouts → breakouts}/collection.d.ts +0 -0
  331. /package/dist/{types/breakouts → breakouts}/edit-lock-error.d.ts +0 -0
  332. /package/dist/{types/breakouts → breakouts}/events.d.ts +0 -0
  333. /package/dist/{types/breakouts → breakouts}/index.d.ts +0 -0
  334. /package/dist/{types/breakouts → breakouts}/request.d.ts +0 -0
  335. /package/dist/{types/breakouts → breakouts}/utils.d.ts +0 -0
  336. /package/dist/{types/common → common}/browser-detection.d.ts +0 -0
  337. /package/dist/{types/common → common}/collection.d.ts +0 -0
  338. /package/dist/{types/common → common}/config.d.ts +0 -0
  339. /package/dist/{types/common → common}/errors/captcha-error.d.ts +0 -0
  340. /package/dist/{types/common → common}/errors/intent-to-join.d.ts +0 -0
  341. /package/dist/{types/common → common}/errors/join-meeting.d.ts +0 -0
  342. /package/dist/{types/common → common}/errors/media.d.ts +0 -0
  343. /package/dist/{types/common → common}/errors/no-meeting-info.d.ts +0 -0
  344. /package/dist/{types/common → common}/errors/parameter.d.ts +0 -0
  345. /package/dist/{types/common → common}/errors/password-error.d.ts +0 -0
  346. /package/dist/{types/common → common}/errors/permission.d.ts +0 -0
  347. /package/dist/{types/common → common}/errors/reclaim-host-role-errors.d.ts +0 -0
  348. /package/dist/{types/common → common}/errors/reconnection-in-progress.d.ts +0 -0
  349. /package/dist/{types/common → common}/errors/reconnection.d.ts +0 -0
  350. /package/dist/{types/common → common}/errors/stats.d.ts +0 -0
  351. /package/dist/{types/common → common}/errors/webex-errors.d.ts +0 -0
  352. /package/dist/{types/common → common}/errors/webex-meetings-error.d.ts +0 -0
  353. /package/dist/{types/common → common}/events/events-scope.d.ts +0 -0
  354. /package/dist/{types/common → common}/events/events.d.ts +0 -0
  355. /package/dist/{types/common → common}/events/trigger-proxy.d.ts +0 -0
  356. /package/dist/{types/common → common}/events/util.d.ts +0 -0
  357. /package/dist/{types/common → common}/logs/logger-config.d.ts +0 -0
  358. /package/dist/{types/common → common}/logs/logger-proxy.d.ts +0 -0
  359. /package/dist/{types/common → common}/queue.d.ts +0 -0
  360. /package/dist/{types/controls-options-manager → controls-options-manager}/constants.d.ts +0 -0
  361. /package/dist/{types/controls-options-manager → controls-options-manager}/enums.d.ts +0 -0
  362. /package/dist/{types/controls-options-manager → controls-options-manager}/index.d.ts +0 -0
  363. /package/dist/{types/controls-options-manager → controls-options-manager}/types.d.ts +0 -0
  364. /package/dist/{types/controls-options-manager → controls-options-manager}/util.d.ts +0 -0
  365. /package/dist/{types/index.d.ts → index.d.ts} +0 -0
  366. /package/dist/{types/interceptors → interceptors}/index.d.ts +0 -0
  367. /package/dist/{types/interceptors → interceptors}/locusRetry.d.ts +0 -0
  368. /package/dist/{types/interpretation → interpretation}/collection.d.ts +0 -0
  369. /package/dist/{types/interpretation → interpretation}/index.d.ts +0 -0
  370. /package/dist/{types/interpretation → interpretation}/siLanguage.d.ts +0 -0
  371. /package/dist/{types/locus-info → locus-info}/controlsUtils.d.ts +0 -0
  372. /package/dist/{types/locus-info → locus-info}/embeddedAppsUtils.d.ts +0 -0
  373. /package/dist/{types/locus-info → locus-info}/fullState.d.ts +0 -0
  374. /package/dist/{types/locus-info → locus-info}/hostUtils.d.ts +0 -0
  375. /package/dist/{types/locus-info → locus-info}/index.d.ts +0 -0
  376. /package/dist/{types/locus-info → locus-info}/infoUtils.d.ts +0 -0
  377. /package/dist/{types/locus-info → locus-info}/mediaSharesUtils.d.ts +0 -0
  378. /package/dist/{types/locus-info → locus-info}/parser.d.ts +0 -0
  379. /package/dist/{types/locus-info → locus-info}/selfUtils.d.ts +0 -0
  380. /package/dist/{types/media → media}/index.d.ts +0 -0
  381. /package/dist/{types/media → media}/properties.d.ts +0 -0
  382. /package/dist/{types/media → media}/util.d.ts +0 -0
  383. /package/dist/{types/mediaQualityMetrics → mediaQualityMetrics}/config.d.ts +0 -0
  384. /package/dist/{types/meeting → meeting}/in-meeting-actions.d.ts +0 -0
  385. /package/dist/{types/meeting → meeting}/locusMediaRequest.d.ts +0 -0
  386. /package/dist/{types/meeting → meeting}/muteState.d.ts +0 -0
  387. /package/dist/{types/meeting → meeting}/request.type.d.ts +0 -0
  388. /package/dist/{types/meeting → meeting}/state.d.ts +0 -0
  389. /package/dist/{types/meeting-info → meeting-info}/collection.d.ts +0 -0
  390. /package/dist/{types/meeting-info → meeting-info}/index.d.ts +0 -0
  391. /package/dist/{types/meeting-info → meeting-info}/meeting-info-v2.d.ts +0 -0
  392. /package/dist/{types/meeting-info → meeting-info}/request.d.ts +0 -0
  393. /package/dist/{types/meeting-info → meeting-info}/util.d.ts +0 -0
  394. /package/dist/{types/meeting-info → meeting-info}/utilv2.d.ts +0 -0
  395. /package/dist/{types/meetings → meetings}/collection.d.ts +0 -0
  396. /package/dist/{types/meetings → meetings}/meetings.types.d.ts +0 -0
  397. /package/dist/{types/meetings → meetings}/request.d.ts +0 -0
  398. /package/dist/{types/meetings → meetings}/util.d.ts +0 -0
  399. /package/dist/{types/member → member}/index.d.ts +0 -0
  400. /package/dist/{types/member → member}/types.d.ts +0 -0
  401. /package/dist/{types/member → member}/util.d.ts +0 -0
  402. /package/dist/{types/members → members}/collection.d.ts +0 -0
  403. /package/dist/{types/members → members}/index.d.ts +0 -0
  404. /package/dist/{types/members → members}/request.d.ts +0 -0
  405. /package/dist/{types/members → members}/types.d.ts +0 -0
  406. /package/dist/{types/metrics → metrics}/constants.d.ts +0 -0
  407. /package/dist/{types/metrics → metrics}/index.d.ts +0 -0
  408. /package/dist/{types/multistream → multistream}/receiveSlot.d.ts +0 -0
  409. /package/dist/{types/multistream → multistream}/receiveSlotManager.d.ts +0 -0
  410. /package/dist/{types/multistream → multistream}/remoteMedia.d.ts +0 -0
  411. /package/dist/{types/networkQualityMonitor → networkQualityMonitor}/index.d.ts +0 -0
  412. /package/dist/{types/personal-meeting-room → personal-meeting-room}/index.d.ts +0 -0
  413. /package/dist/{types/personal-meeting-room → personal-meeting-room}/request.d.ts +0 -0
  414. /package/dist/{types/personal-meeting-room → personal-meeting-room}/util.d.ts +0 -0
  415. /package/dist/{types/reachability → reachability}/request.d.ts +0 -0
  416. /package/dist/{types/reactions → reactions}/constants.d.ts +0 -0
  417. /package/dist/{types/reactions → reactions}/reactions.d.ts +0 -0
  418. /package/dist/{types/reactions → reactions}/reactions.type.d.ts +0 -0
  419. /package/dist/{types/reconnection-manager → reconnection-manager}/index.d.ts +0 -0
  420. /package/dist/{types/recording-controller → recording-controller}/enums.d.ts +0 -0
  421. /package/dist/{types/recording-controller → recording-controller}/index.d.ts +0 -0
  422. /package/dist/{types/recording-controller → recording-controller}/util.d.ts +0 -0
  423. /package/dist/{types/roap → roap}/request.d.ts +0 -0
  424. /package/dist/{types/rtcMetrics → rtcMetrics}/constants.d.ts +0 -0
  425. /package/dist/{types/rtcMetrics → rtcMetrics}/index.d.ts +0 -0
  426. /package/dist/{types/statsAnalyzer → statsAnalyzer}/global.d.ts +0 -0
  427. /package/dist/{types/statsAnalyzer → statsAnalyzer}/index.d.ts +0 -0
  428. /package/dist/{types/statsAnalyzer → statsAnalyzer}/mqaUtil.d.ts +0 -0
  429. /package/dist/{types/transcription → transcription}/index.d.ts +0 -0
  430. /package/dist/{types/webinar → webinar}/collection.d.ts +0 -0
  431. /package/dist/{types/webinar → webinar}/index.d.ts +0 -0
@@ -1,6 +1,6 @@
1
1
  import uuid from 'uuid';
2
2
  import {cloneDeep, isEqual, isEmpty} from 'lodash';
3
- import jwt from 'jsonwebtoken';
3
+ import jwtDecode from 'jwt-decode';
4
4
  // @ts-ignore - Fix this
5
5
  import {StatelessWebexPlugin} from '@webex/webex-core';
6
6
  // @ts-ignore - Types not available for @webex/common
@@ -10,6 +10,8 @@ import {
10
10
  ClientEventLeaveReason,
11
11
  CallDiagnosticUtils,
12
12
  } from '@webex/internal-plugin-metrics';
13
+ import {ClientEvent as RawClientEvent} from '@webex/event-dictionary-ts';
14
+
13
15
  import {
14
16
  ConnectionState,
15
17
  Errors,
@@ -33,6 +35,12 @@ import {
33
35
  RemoteStream,
34
36
  } from '@webex/media-helpers';
35
37
 
38
+ import {
39
+ EVENT_TRIGGERS as VOICEAEVENTS,
40
+ TURN_ON_CAPTION_STATUS,
41
+ } from '@webex/internal-plugin-voicea';
42
+ import {processNewCaptions} from './voicea-meeting';
43
+
36
44
  import {
37
45
  MeetingNotActiveError,
38
46
  UserInLobbyError,
@@ -40,11 +48,17 @@ import {
40
48
  UserNotJoinedError,
41
49
  AddMediaFailed,
42
50
  } from '../common/errors/webex-errors';
51
+
43
52
  import {StatsAnalyzer, EVENTS as StatsAnalyzerEvents} from '../statsAnalyzer';
44
53
  import NetworkQualityMonitor from '../networkQualityMonitor';
45
54
  import LoggerProxy from '../common/logs/logger-proxy';
55
+ import EventsUtil from '../common/events/util';
46
56
  import Trigger from '../common/events/trigger-proxy';
47
- import Roap from '../roap/index';
57
+ import Roap, {
58
+ type TurnDiscoveryResult,
59
+ type TurnServerInfo,
60
+ type TurnDiscoverySkipReason,
61
+ } from '../roap/index';
48
62
  import Media, {type BundlePolicy} from '../media';
49
63
  import MediaProperties from '../media/properties';
50
64
  import MeetingStateMachine from './state';
@@ -59,7 +73,6 @@ import MeetingsUtil from '../meetings/util';
59
73
  import RecordingUtil from '../recording-controller/util';
60
74
  import ControlsOptionsUtil from '../controls-options-manager/util';
61
75
  import MediaUtil from '../media/util';
62
- import Transcription from '../transcription';
63
76
  import {Reactions, SkinTones} from '../reactions/reactions';
64
77
  import PasswordError from '../common/errors/password-error';
65
78
  import CaptchaError from '../common/errors/captcha-error';
@@ -97,7 +110,6 @@ import {
97
110
  SHARE_STATUS,
98
111
  SHARE_STOPPED_REASON,
99
112
  VIDEO,
100
- HTTP_VERBS,
101
113
  SELF_ROLES,
102
114
  INTERPRETATION,
103
115
  SELF_POLICY,
@@ -106,6 +118,7 @@ import {
106
118
  ROAP_OFFER_ANSWER_EXCHANGE_TIMEOUT,
107
119
  RECONNECTION,
108
120
  NAMED_MEDIA_GROUP_TYPE_AUDIO,
121
+ LANGUAGE_ENGLISH,
109
122
  } from '../constants';
110
123
  import BEHAVIORAL_METRICS from '../metrics/constants';
111
124
  import ParameterError from '../common/errors/parameter';
@@ -114,7 +127,6 @@ import {
114
127
  MeetingInfoV2CaptchaError,
115
128
  MeetingInfoV2PolicyError,
116
129
  } from '../meeting-info/meeting-info-v2';
117
- import BrowserDetection from '../common/browser-detection';
118
130
  import {CSI, ReceiveSlotManager} from '../multistream/receiveSlotManager';
119
131
  import SendSlotManager from '../multistream/sendSlotManager';
120
132
  import {MediaRequestManager} from '../multistream/mediaRequestManager';
@@ -142,8 +154,6 @@ import ControlsOptionsManager from '../controls-options-manager';
142
154
  import PermissionError from '../common/errors/permission';
143
155
  import {LocusMediaRequest} from './locusMediaRequest';
144
156
 
145
- const {isBrowser} = BrowserDetection();
146
-
147
157
  const logRequest = (request: any, {logText = ''}) => {
148
158
  LoggerProxy.logger.info(`${logText} - sending request`);
149
159
 
@@ -159,6 +169,36 @@ const logRequest = (request: any, {logText = ''}) => {
159
169
  });
160
170
  };
161
171
 
172
+ export type CaptionData = {
173
+ id: string;
174
+ isFinal: boolean;
175
+ translations: Array<string>;
176
+ text: string;
177
+ currentCaptionLanguage: string;
178
+ timestamp: string;
179
+ speaker: string;
180
+ };
181
+
182
+ export type Transcription = {
183
+ languageOptions: {
184
+ captionLanguages?: string; // list of supported caption languages from backend
185
+ maxLanguages?: number;
186
+ spokenLanguages?: Array<string>; // list of supported spoken languages from backend
187
+ currentCaptionLanguage?: string; // current caption language - default is english
188
+ requestedCaptionLanguage?: string; // requested caption language
189
+ currentSpokenLanguage?: string; // current spoken language - default is english
190
+ };
191
+ status: string;
192
+ isListening: boolean;
193
+ commandText: string;
194
+ captions: Array<CaptionData>;
195
+ showCaptionBox: boolean;
196
+ transcribingRequestStatus: string;
197
+ isCaptioning: boolean;
198
+ speakerProxy: Map<string, any>;
199
+ interimCaptions: Map<string, CaptionData>;
200
+ };
201
+
162
202
  export type LocalStreams = {
163
203
  microphone?: LocalMicrophoneStream;
164
204
  camera?: LocalCameraStream;
@@ -588,8 +628,51 @@ export default class Meeting extends StatelessWebexPlugin {
588
628
  allowMediaInLobby: boolean;
589
629
  localShareInstanceId: string;
590
630
  remoteShareInstanceId: string;
591
- turnDiscoverySkippedReason: string;
631
+ turnDiscoverySkippedReason: TurnDiscoverySkipReason;
592
632
  turnServerUsed: boolean;
633
+ areVoiceaEventsSetup = false;
634
+
635
+ voiceaListenerCallbacks: object = {
636
+ [VOICEAEVENTS.VOICEA_ANNOUNCEMENT]: (payload: Transcription['languageOptions']) => {
637
+ this.transcription.languageOptions = payload;
638
+
639
+ LoggerProxy.logger.debug(
640
+ `${EventsUtil.getScopeLog({
641
+ file: 'meeting/index',
642
+ function: 'setUpVoiceaListeners',
643
+ })}event#${EVENT_TRIGGERS.MEETING_STARTED_RECEIVING_TRANSCRIPTION}`
644
+ );
645
+
646
+ // @ts-ignore
647
+ this.trigger(EVENT_TRIGGERS.MEETING_STARTED_RECEIVING_TRANSCRIPTION, payload);
648
+ },
649
+ [VOICEAEVENTS.CAPTIONS_TURNED_ON]: () => {
650
+ this.transcription.status = TURN_ON_CAPTION_STATUS.ENABLED;
651
+ },
652
+ [VOICEAEVENTS.EVA_COMMAND]: (payload) => {
653
+ const {data} = payload;
654
+
655
+ this.transcription.isListening = !!data.isListening;
656
+ this.transcription.commandText = data.text ?? '';
657
+ },
658
+ [VOICEAEVENTS.NEW_CAPTION]: (data) => {
659
+ processNewCaptions({data, meeting: this});
660
+
661
+ LoggerProxy.logger.debug(
662
+ `${EventsUtil.getScopeLog({
663
+ file: 'meeting/index',
664
+ function: 'setUpVoiceaListeners',
665
+ })}event#${EVENT_TRIGGERS.MEETING_CAPTION_RECEIVED}`
666
+ );
667
+
668
+ // @ts-ignore
669
+ this.trigger(EVENT_TRIGGERS.MEETING_CAPTION_RECEIVED, {
670
+ captions: this.transcription.captions,
671
+ interimCaptions: this.transcription.interimCaptions,
672
+ });
673
+ },
674
+ };
675
+
593
676
  private retriedWithTurnServer: boolean;
594
677
  private sendSlotManager: SendSlotManager = new SendSlotManager(LoggerProxy);
595
678
  private deferSDPAnswer?: Defer; // used for waiting for a response
@@ -1188,7 +1271,17 @@ export default class Meeting extends StatelessWebexPlugin {
1188
1271
  * @private
1189
1272
  * @memberof Meeting
1190
1273
  */
1191
- this.transcription = undefined;
1274
+ this.transcription = {
1275
+ captions: [],
1276
+ isListening: false,
1277
+ commandText: '',
1278
+ languageOptions: {},
1279
+ showCaptionBox: false,
1280
+ transcribingRequestStatus: 'INACTIVE',
1281
+ isCaptioning: false,
1282
+ interimCaptions: {} as Map<string, CaptionData>,
1283
+ speakerProxy: {} as Map<string, any>,
1284
+ } as Transcription;
1192
1285
 
1193
1286
  /**
1194
1287
  * Password status. If it's PASSWORD_STATUS.REQUIRED then verifyPassword() needs to be called
@@ -1904,6 +1997,7 @@ export default class Meeting extends StatelessWebexPlugin {
1904
1997
  * @memberof Meeting
1905
1998
  */
1906
1999
  private setUpInterpretationListener() {
2000
+ // TODO: check if its getting used or not
1907
2001
  this.simultaneousInterpretation.on(INTERPRETATION.EVENTS.SUPPORT_LANGUAGES_UPDATE, () => {
1908
2002
  Trigger.trigger(
1909
2003
  this,
@@ -1914,7 +2008,7 @@ export default class Meeting extends StatelessWebexPlugin {
1914
2008
  EVENT_TRIGGERS.MEETING_INTERPRETATION_SUPPORT_LANGUAGES_UPDATE
1915
2009
  );
1916
2010
  });
1917
-
2011
+ // TODO: check if its getting used or not
1918
2012
  this.simultaneousInterpretation.on(
1919
2013
  INTERPRETATION.EVENTS.HANDOFF_REQUESTS_ARRIVED,
1920
2014
  (payload) => {
@@ -1931,6 +2025,43 @@ export default class Meeting extends StatelessWebexPlugin {
1931
2025
  );
1932
2026
  }
1933
2027
 
2028
+ /**
2029
+ * Set up the listeners for captions
2030
+ * @returns {undefined}
2031
+ * @private
2032
+ * @memberof Meeting
2033
+ */
2034
+ private setUpVoiceaListeners() {
2035
+ // @ts-ignore
2036
+ this.webex.internal.voicea.listenToEvents();
2037
+
2038
+ // @ts-ignore
2039
+ this.webex.internal.voicea.on(
2040
+ VOICEAEVENTS.VOICEA_ANNOUNCEMENT,
2041
+ this.voiceaListenerCallbacks[VOICEAEVENTS.VOICEA_ANNOUNCEMENT]
2042
+ );
2043
+
2044
+ // @ts-ignore
2045
+ this.webex.internal.voicea.on(
2046
+ VOICEAEVENTS.CAPTIONS_TURNED_ON,
2047
+ this.voiceaListenerCallbacks[VOICEAEVENTS.CAPTIONS_TURNED_ON]
2048
+ );
2049
+
2050
+ // @ts-ignore
2051
+ this.webex.internal.voicea.on(
2052
+ VOICEAEVENTS.EVA_COMMAND,
2053
+ this.voiceaListenerCallbacks[VOICEAEVENTS.EVA_COMMAND]
2054
+ );
2055
+
2056
+ // @ts-ignore
2057
+ this.webex.internal.voicea.on(
2058
+ VOICEAEVENTS.NEW_CAPTION,
2059
+ this.voiceaListenerCallbacks[VOICEAEVENTS.NEW_CAPTION]
2060
+ );
2061
+
2062
+ this.areVoiceaEventsSetup = true;
2063
+ }
2064
+
1934
2065
  /**
1935
2066
  * Set up the locus info listener for meetings disconnected due to inactivity
1936
2067
  * @returns {undefined}
@@ -2220,7 +2351,6 @@ export default class Meeting extends StatelessWebexPlugin {
2220
2351
  modifiedBy,
2221
2352
  lastModified,
2222
2353
  };
2223
-
2224
2354
  Trigger.trigger(
2225
2355
  this,
2226
2356
  {
@@ -2251,19 +2381,22 @@ export default class Meeting extends StatelessWebexPlugin {
2251
2381
  this.locusInfo.on(
2252
2382
  LOCUSINFO.EVENTS.CONTROLS_MEETING_TRANSCRIBE_UPDATED,
2253
2383
  ({caption, transcribing}) => {
2254
- // @ts-ignore - config coming from registerPlugin
2255
- if (transcribing && this.transcription && this.config.receiveTranscription) {
2256
- this.receiveTranscription();
2257
- } else if (!transcribing && this.transcription) {
2258
- Trigger.trigger(
2259
- this,
2260
- {
2261
- file: 'meeting/index',
2262
- function: 'setupLocusControlsListener',
2263
- },
2264
- EVENT_TRIGGERS.MEETING_STOPPED_RECEIVING_TRANSCRIPTION,
2265
- {caption, transcribing}
2266
- );
2384
+ // user need to be joined to start the llm and receive transcription
2385
+ if (this.isJoined()) {
2386
+ // @ts-ignore - config coming from registerPlugin
2387
+ if (transcribing && !this.transcription) {
2388
+ this.startTranscription();
2389
+ } else if (!transcribing && this.transcription) {
2390
+ Trigger.trigger(
2391
+ this,
2392
+ {
2393
+ file: 'meeting/index',
2394
+ function: 'setupLocusControlsListener',
2395
+ },
2396
+ EVENT_TRIGGERS.MEETING_STOPPED_RECEIVING_TRANSCRIPTION,
2397
+ {caption, transcribing}
2398
+ );
2399
+ }
2267
2400
  }
2268
2401
  }
2269
2402
  );
@@ -2393,6 +2526,7 @@ export default class Meeting extends StatelessWebexPlugin {
2393
2526
  {
2394
2527
  annotationInfo: contentShare?.annotation,
2395
2528
  meetingId: this.id,
2529
+ resourceType: contentShare?.resourceType,
2396
2530
  }
2397
2531
  );
2398
2532
  }
@@ -2421,7 +2555,8 @@ export default class Meeting extends StatelessWebexPlugin {
2421
2555
  contentShare.deviceUrlSharing === previousContentShare.deviceUrlSharing &&
2422
2556
  whiteboardShare.beneficiaryId === previousWhiteboardShare?.beneficiaryId &&
2423
2557
  whiteboardShare.disposition === previousWhiteboardShare?.disposition &&
2424
- whiteboardShare.resourceUrl === previousWhiteboardShare?.resourceUrl
2558
+ whiteboardShare.resourceUrl === previousWhiteboardShare?.resourceUrl &&
2559
+ contentShare.resourceType === previousContentShare?.resourceType
2425
2560
  ) {
2426
2561
  // nothing changed, so ignore
2427
2562
  // (this happens when we steal presentation from remote)
@@ -2543,6 +2678,7 @@ export default class Meeting extends StatelessWebexPlugin {
2543
2678
  url: contentShare.url,
2544
2679
  shareInstanceId: this.remoteShareInstanceId,
2545
2680
  annotationInfo: contentShare.annotation,
2681
+ resourceType: contentShare.resourceType,
2546
2682
  }
2547
2683
  );
2548
2684
  };
@@ -2635,6 +2771,7 @@ export default class Meeting extends StatelessWebexPlugin {
2635
2771
  url: contentShare.url,
2636
2772
  shareInstanceId: this.remoteShareInstanceId,
2637
2773
  annotationInfo: contentShare.annotation,
2774
+ resourceType: contentShare.resourceType,
2638
2775
  }
2639
2776
  );
2640
2777
  this.members.locusMediaSharesUpdate(payload);
@@ -2922,7 +3059,7 @@ export default class Meeting extends StatelessWebexPlugin {
2922
3059
  });
2923
3060
  }
2924
3061
  });
2925
- this.locusInfo.on(LOCUSINFO.EVENTS.SELF_ADMITTED_GUEST, (payload) => {
3062
+ this.locusInfo.on(LOCUSINFO.EVENTS.SELF_ADMITTED_GUEST, async (payload) => {
2926
3063
  this.stopKeepAlive();
2927
3064
 
2928
3065
  if (payload) {
@@ -2944,6 +3081,7 @@ export default class Meeting extends StatelessWebexPlugin {
2944
3081
  options: {meetingId: this.id},
2945
3082
  });
2946
3083
  }
3084
+ this.updateLLMConnection();
2947
3085
  });
2948
3086
 
2949
3087
  // @ts-ignore - check if MEDIA_INACTIVITY exists
@@ -3328,8 +3466,10 @@ export default class Meeting extends StatelessWebexPlugin {
3328
3466
  this.owner =
3329
3467
  locusMeetingObject?.info.owner || meetingInfo?.owner || meetingInfo?.hostId || this.owner;
3330
3468
  this.permissionToken = meetingInfo?.permissionToken;
3331
- this.setPermissionTokenPayload(meetingInfo?.permissionToken);
3332
- this.setSelfUserPolicies();
3469
+ if (this.permissionToken) {
3470
+ this.setPermissionTokenPayload(meetingInfo?.permissionToken);
3471
+ this.setSelfUserPolicies();
3472
+ }
3333
3473
  // Need to populate environment when sending CA event
3334
3474
  this.environment = locusMeetingObject?.info.channel || meetingInfo?.channel;
3335
3475
  }
@@ -3616,7 +3756,7 @@ export default class Meeting extends StatelessWebexPlugin {
3616
3756
  * @returns {void}
3617
3757
  */
3618
3758
  public setPermissionTokenPayload(permissionToken: string) {
3619
- this.permissionTokenPayload = jwt.decode(permissionToken);
3759
+ this.permissionTokenPayload = jwtDecode(permissionToken);
3620
3760
  this.permissionTokenReceivedLocalTime = new Date().getTime();
3621
3761
  }
3622
3762
 
@@ -4365,47 +4505,90 @@ export default class Meeting extends StatelessWebexPlugin {
4365
4505
  * }
4366
4506
  * })
4367
4507
  */
4368
- public joinWithMedia(
4508
+ public async joinWithMedia(
4369
4509
  options: {
4370
4510
  joinOptions?: any;
4371
4511
  mediaOptions?: AddMediaOptions;
4372
4512
  } = {}
4373
4513
  ) {
4374
- const {mediaOptions, joinOptions} = options;
4514
+ const {mediaOptions, joinOptions = {}} = options;
4375
4515
 
4376
4516
  if (!mediaOptions?.allowMediaInLobby) {
4377
4517
  return Promise.reject(
4378
4518
  new ParameterError('joinWithMedia() can only be used with allowMediaInLobby set to true')
4379
4519
  );
4380
4520
  }
4521
+ this.allowMediaInLobby = true;
4381
4522
 
4382
4523
  LoggerProxy.logger.info('Meeting:index#joinWithMedia called');
4383
4524
 
4384
- return this.join(joinOptions)
4385
- .then((joinResponse) =>
4386
- this.addMedia(mediaOptions).then((mediaResponse) => ({
4387
- join: joinResponse,
4388
- media: mediaResponse,
4389
- }))
4390
- )
4391
- .catch((error) => {
4392
- LoggerProxy.logger.error('Meeting:index#joinWithMedia --> ', error);
4525
+ let joined = false;
4393
4526
 
4394
- Metrics.sendBehavioralMetric(
4395
- BEHAVIORAL_METRICS.JOIN_WITH_MEDIA_FAILURE,
4396
- {
4397
- correlation_id: this.correlationId,
4398
- locus_id: this.locusUrl.split('/').pop(),
4399
- reason: error.message,
4400
- stack: error.stack,
4401
- },
4402
- {
4403
- type: error.name,
4404
- }
4405
- );
4527
+ try {
4528
+ let turnServerInfo;
4529
+ let turnDiscoverySkippedReason;
4406
4530
 
4407
- return Promise.reject(error);
4408
- });
4531
+ // @ts-ignore
4532
+ joinOptions.reachability = await this.webex.meetings.reachability.getReachabilityResults();
4533
+ const turnDiscoveryRequest = await this.roap.generateTurnDiscoveryRequestMessage(this, true);
4534
+
4535
+ ({turnDiscoverySkippedReason} = turnDiscoveryRequest);
4536
+ joinOptions.roapMessage = turnDiscoveryRequest.roapMessage;
4537
+
4538
+ const joinResponse = await this.join(joinOptions);
4539
+
4540
+ joined = true;
4541
+
4542
+ if (joinOptions.roapMessage) {
4543
+ ({turnServerInfo, turnDiscoverySkippedReason} =
4544
+ await this.roap.handleTurnDiscoveryHttpResponse(this, joinResponse));
4545
+
4546
+ this.turnDiscoverySkippedReason = turnDiscoverySkippedReason;
4547
+ this.turnServerUsed = !!turnServerInfo;
4548
+
4549
+ if (turnServerInfo === undefined) {
4550
+ this.roap.abortTurnDiscovery();
4551
+ }
4552
+ }
4553
+
4554
+ const mediaResponse = await this.addMedia(mediaOptions, turnServerInfo);
4555
+
4556
+ return {
4557
+ join: joinResponse,
4558
+ media: mediaResponse,
4559
+ };
4560
+ } catch (error) {
4561
+ LoggerProxy.logger.error('Meeting:index#joinWithMedia --> ', error);
4562
+
4563
+ let leaveError;
4564
+
4565
+ this.roap.abortTurnDiscovery();
4566
+
4567
+ if (joined) {
4568
+ try {
4569
+ await this.leave({resourceId: joinOptions?.resourceId, reason: 'joinWithMedia failure'});
4570
+ } catch (e) {
4571
+ LoggerProxy.logger.error('Meeting:index#joinWithMedia --> leave error', e);
4572
+ leaveError = e;
4573
+ }
4574
+ }
4575
+
4576
+ Metrics.sendBehavioralMetric(
4577
+ BEHAVIORAL_METRICS.JOIN_WITH_MEDIA_FAILURE,
4578
+ {
4579
+ correlation_id: this.correlationId,
4580
+ locus_id: this.locusUrl?.split('/').pop(), // if join fails, we may end up with no locusUrl
4581
+ reason: error.message,
4582
+ stack: error.stack,
4583
+ leaveErrorReason: leaveError?.message,
4584
+ },
4585
+ {
4586
+ type: error.name,
4587
+ }
4588
+ );
4589
+
4590
+ throw error;
4591
+ }
4409
4592
  }
4410
4593
 
4411
4594
  /**
@@ -4532,7 +4715,7 @@ export default class Meeting extends StatelessWebexPlugin {
4532
4715
  }
4533
4716
 
4534
4717
  LoggerProxy.logger.error(
4535
- 'Meeting:index#isTranscriptionSupported --> Webex Assistant is not supported'
4718
+ 'Meeting:index#isTranscriptionSupported --> Webex Assistant is not enabled/supported'
4536
4719
  );
4537
4720
 
4538
4721
  return false;
@@ -4553,109 +4736,139 @@ export default class Meeting extends StatelessWebexPlugin {
4553
4736
  }
4554
4737
 
4555
4738
  /**
4556
- * Monitor the Low-Latency Mercury (LLM) web socket connection on `onError` and `onClose` states
4557
- * @private
4558
- * @returns {void}
4739
+ * sets Caption language for the meeting
4740
+ * @param {string} language
4741
+ * @returns {Promise}
4559
4742
  */
4560
- private monitorTranscriptionSocketConnection() {
4561
- this.transcription.onCloseSocket((event) => {
4562
- LoggerProxy.logger.info(
4563
- `Meeting:index#onCloseSocket -->
4564
- unable to continue receiving transcription;
4565
- low-latency mercury web socket connection is closed now.
4566
- ${event}`
4567
- );
4743
+ public setCaptionLanguage(language: string) {
4744
+ return new Promise((resolve, reject) => {
4745
+ if (!this.isTranscriptionSupported()) {
4746
+ LoggerProxy.logger.error(
4747
+ 'Meeting:index#setCaptionLanguage --> Webex Assistant is not enabled/supported'
4748
+ );
4568
4749
 
4569
- this.triggerStopReceivingTranscriptionEvent();
4570
- });
4750
+ reject(new Error('Webex Assistant is not enabled/supported'));
4751
+ }
4571
4752
 
4572
- this.transcription.onErrorSocket((event) => {
4573
- LoggerProxy.logger.error(
4574
- `Meeting:index#onErrorSocket -->
4575
- unable to continue receiving transcription;
4576
- low-latency mercury web socket connection error had occured.
4577
- ${event}`
4578
- );
4753
+ try {
4754
+ const voiceaListenerCaptionUpdate = (payload) => {
4755
+ // @ts-ignore
4756
+ this.webex.internal.voicea.off(
4757
+ VOICEAEVENTS.CAPTION_LANGUAGE_UPDATE,
4758
+ voiceaListenerCaptionUpdate
4759
+ );
4760
+ const {statusCode} = payload;
4579
4761
 
4580
- this.triggerStopReceivingTranscriptionEvent();
4762
+ if (statusCode === 200) {
4763
+ this.transcription.languageOptions = {
4764
+ ...this.transcription.languageOptions,
4765
+ currentCaptionLanguage: language,
4766
+ };
4767
+ resolve(language);
4768
+ } else {
4769
+ reject(payload);
4770
+ }
4771
+ };
4772
+ // @ts-ignore
4773
+ this.webex.internal.voicea.on(
4774
+ VOICEAEVENTS.CAPTION_LANGUAGE_UPDATE,
4775
+ voiceaListenerCaptionUpdate
4776
+ );
4777
+ // @ts-ignore
4778
+ this.webex.internal.voicea.requestLanguage(language);
4779
+ } catch (error) {
4780
+ LoggerProxy.logger.error(`Meeting:index#setCaptionLanguage --> ${error}`);
4581
4781
 
4582
- Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.RECEIVE_TRANSCRIPTION_FAILURE, {
4583
- correlation_id: this.correlationId,
4584
- reason: 'unexpected error: transcription LLM web socket connection error had occured.',
4585
- event,
4586
- });
4782
+ reject(error);
4783
+ }
4587
4784
  });
4588
4785
  }
4589
4786
 
4590
4787
  /**
4591
- * Request for a WebSocket Url, open and monitor the WebSocket connection
4592
- * @private
4593
- * @returns {Promise<void>} a promise to open the WebSocket connection
4788
+ * sets Spoken language for the meeting
4789
+ * @param {string} language
4790
+ * @returns {Promise}
4594
4791
  */
4595
- private async receiveTranscription() {
4596
- LoggerProxy.logger.info(
4597
- `Meeting:index#receiveTranscription -->
4598
- Attempting to generate a web socket url.`
4599
- );
4792
+ public setSpokenLanguage(language: string) {
4793
+ return new Promise((resolve, reject) => {
4794
+ if (!this.isTranscriptionSupported()) {
4795
+ LoggerProxy.logger.error(
4796
+ 'Meeting:index#setCaptionLanguage --> Webex Assistant is not enabled/supported'
4797
+ );
4798
+
4799
+ reject(new Error('Webex Assistant is not enabled/supported'));
4800
+ }
4801
+
4802
+ try {
4803
+ const voiceaListenerLanguageUpdate = (payload) => {
4804
+ // @ts-ignore
4805
+ this.webex.internal.voicea.off(
4806
+ VOICEAEVENTS.SPOKEN_LANGUAGE_UPDATE,
4807
+ voiceaListenerLanguageUpdate
4808
+ );
4809
+ const {languageCode} = payload;
4810
+
4811
+ if (languageCode) {
4812
+ this.transcription.languageOptions = {
4813
+ ...this.transcription.languageOptions,
4814
+ currentSpokenLanguage: languageCode,
4815
+ };
4816
+ resolve(languageCode);
4817
+ } else {
4818
+ reject(payload);
4819
+ }
4820
+ };
4600
4821
 
4601
- try {
4602
- const {datachannelUrl} = this.locusInfo.info;
4603
- // @ts-ignore - fix type
4604
- const {
4605
- body: {webSocketUrl},
4606
4822
  // @ts-ignore
4607
- } = await this.request({
4608
- method: HTTP_VERBS.POST,
4609
- uri: datachannelUrl,
4610
- body: {deviceUrl: this.deviceUrl},
4611
- });
4823
+ this.webex.internal.voicea.on(
4824
+ VOICEAEVENTS.SPOKEN_LANGUAGE_UPDATE,
4825
+ voiceaListenerLanguageUpdate
4826
+ );
4612
4827
 
4613
- LoggerProxy.logger.info(
4614
- `Meeting:index#receiveTranscription -->
4615
- Generated web socket url succesfully.`
4616
- );
4828
+ // @ts-ignore
4829
+ this.webex.internal.voicea.setSpokenLanguage(language);
4830
+ } catch (error) {
4831
+ LoggerProxy.logger.error(`Meeting:index#setSpokenLanguage --> ${error}`);
4617
4832
 
4618
- this.transcription = new Transcription(
4619
- webSocketUrl,
4620
- // @ts-ignore - fix type
4621
- this.webex.sessionId,
4622
- this.members
4623
- );
4833
+ reject(error);
4834
+ }
4835
+ });
4836
+ }
4624
4837
 
4838
+ /**
4839
+ * This method will enable the transcription for the current meeting if the meeting has enabled/supports Webex Assistant
4840
+ * @param {Object} options object with spokenlanguage setting
4841
+ * @public
4842
+ * @returns {Promise<void>} a promise to open the WebSocket connection
4843
+ */
4844
+ public async startTranscription(options?: {spokenLanguage?: string}) {
4845
+ if (this.isJoined()) {
4625
4846
  LoggerProxy.logger.info(
4626
- `Meeting:index#receiveTranscription -->
4627
- opened LLM web socket connection successfully.`
4847
+ 'Meeting:index#startTranscription --> Attempting to enable transcription!'
4628
4848
  );
4629
4849
 
4630
- if (!this.inMeetingActions.isClosedCaptionActive) {
4631
- LoggerProxy.logger.error(
4632
- `Meeting:index#receiveTranscription --> Transcription cannot be started until a licensed user enables it`
4633
- );
4634
- }
4635
-
4636
- // retrieve and pass the payload
4637
- this.transcription.subscribe((payload) => {
4638
- Trigger.trigger(
4639
- this,
4640
- {
4641
- file: 'meeting/index',
4642
- function: 'join',
4643
- },
4644
- EVENT_TRIGGERS.MEETING_STARTED_RECEIVING_TRANSCRIPTION,
4645
- payload
4646
- );
4647
- });
4850
+ try {
4851
+ if (!this.areVoiceaEventsSetup) {
4852
+ this.setUpVoiceaListeners();
4853
+ }
4648
4854
 
4649
- this.monitorTranscriptionSocketConnection();
4650
- // @ts-ignore - fix type
4651
- this.transcription.connect(this.webex.credentials.supertoken.access_token);
4652
- } catch (error) {
4653
- LoggerProxy.logger.error(`Meeting:index#receiveTranscription --> ${error}`);
4654
- Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.RECEIVE_TRANSCRIPTION_FAILURE, {
4655
- correlation_id: this.correlationId,
4656
- reason: error.message,
4657
- stack: error.stack,
4658
- });
4855
+ if (this.getCurUserType() === 'host') {
4856
+ // @ts-ignore
4857
+ await this.webex.internal.voicea.toggleTranscribing(true, options?.spokenLanguage);
4858
+ }
4859
+ } catch (error) {
4860
+ LoggerProxy.logger.error(`Meeting:index#startTranscription --> ${error}`);
4861
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.RECEIVE_TRANSCRIPTION_FAILURE, {
4862
+ correlation_id: this.correlationId,
4863
+ reason: error.message,
4864
+ stack: error.stack,
4865
+ });
4866
+ }
4867
+ } else {
4868
+ LoggerProxy.logger.error(
4869
+ `Meeting:index#startTranscription --> meeting joined : ${this.isJoined()}`
4870
+ );
4871
+ throw new Error('Meeting is not joined');
4659
4872
  }
4660
4873
  }
4661
4874
 
@@ -4698,13 +4911,37 @@ export default class Meeting extends StatelessWebexPlugin {
4698
4911
  };
4699
4912
 
4700
4913
  /**
4701
- * stop recieving Transcription by closing
4702
- * the web socket connection properly
4914
+ * This method stops receiving transcription for the current meeting
4703
4915
  * @returns {void}
4704
4916
  */
4705
- stopReceivingTranscription() {
4917
+ stopTranscription() {
4706
4918
  if (this.transcription) {
4707
- this.transcription.closeSocket();
4919
+ // @ts-ignore
4920
+ this.webex.internal.voicea.off(
4921
+ VOICEAEVENTS.VOICEA_ANNOUNCEMENT,
4922
+ this.voiceaListenerCallbacks[VOICEAEVENTS.VOICEA_ANNOUNCEMENT]
4923
+ );
4924
+
4925
+ // @ts-ignore
4926
+ this.webex.internal.voicea.off(
4927
+ VOICEAEVENTS.CAPTIONS_TURNED_ON,
4928
+ this.voiceaListenerCallbacks[VOICEAEVENTS.CAPTIONS_TURNED_ON]
4929
+ );
4930
+
4931
+ // @ts-ignore
4932
+ this.webex.internal.voicea.off(
4933
+ VOICEAEVENTS.EVA_COMMAND,
4934
+ this.voiceaListenerCallbacks[VOICEAEVENTS.EVA_COMMAND]
4935
+ );
4936
+
4937
+ // @ts-ignore
4938
+ this.webex.internal.voicea.off(
4939
+ VOICEAEVENTS.NEW_CAPTION,
4940
+ this.voiceaListenerCallbacks[VOICEAEVENTS.NEW_CAPTION]
4941
+ );
4942
+
4943
+ this.areVoiceaEventsSetup = false;
4944
+ this.triggerStopReceivingTranscriptionEvent();
4708
4945
  }
4709
4946
  }
4710
4947
 
@@ -4717,12 +4954,12 @@ export default class Meeting extends StatelessWebexPlugin {
4717
4954
  private triggerStopReceivingTranscriptionEvent() {
4718
4955
  LoggerProxy.logger.info(`
4719
4956
  Meeting:index#stopReceivingTranscription -->
4720
- closed transcription LLM web socket connection successfully.`);
4957
+ closed voicea event listeners successfully.`);
4721
4958
 
4722
4959
  Trigger.trigger(
4723
4960
  this,
4724
4961
  {
4725
- file: 'meeting',
4962
+ file: 'meeting/index',
4726
4963
  function: 'triggerStopReceivingTranscriptionEvent',
4727
4964
  },
4728
4965
  EVENT_TRIGGERS.MEETING_STOPPED_RECEIVING_TRANSCRIPTION
@@ -4948,48 +5185,33 @@ export default class Meeting extends StatelessWebexPlugin {
4948
5185
  .then((join) => {
4949
5186
  // @ts-ignore - config coming from registerPlugin
4950
5187
  if (this.config.enableAutomaticLLM) {
4951
- this.updateLLMConnection().catch((error) => {
4952
- LoggerProxy.logger.error('Meeting:index#join --> Update LLM Connection Failed', error);
4953
-
4954
- Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.LLM_CONNECTION_AFTER_JOIN_FAILURE, {
4955
- correlation_id: this.correlationId,
4956
- reason: error?.message,
4957
- stack: error.stack,
4958
- });
4959
- });
4960
- }
5188
+ this.updateLLMConnection()
5189
+ .catch((error) => {
5190
+ LoggerProxy.logger.error(
5191
+ 'Meeting:index#join --> Transcription Socket Connection Failed',
5192
+ error
5193
+ );
4961
5194
 
4962
- return join;
4963
- })
4964
- .then((join) => {
4965
- if (isBrowser) {
4966
- // @ts-ignore - config coming from registerPlugin
4967
- if (this.config.receiveTranscription || options.receiveTranscription) {
4968
- if (this.isTranscriptionSupported()) {
5195
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.LLM_CONNECTION_AFTER_JOIN_FAILURE, {
5196
+ correlation_id: this.correlationId,
5197
+ reason: error?.message,
5198
+ stack: error.stack,
5199
+ });
5200
+ })
5201
+ .then(() => {
4969
5202
  LoggerProxy.logger.info(
4970
- 'Meeting:index#join --> Attempting to enabled to receive transcription!'
5203
+ 'Meeting:index#join --> Transcription Socket Connection Success'
4971
5204
  );
4972
- this.receiveTranscription().catch((error) => {
4973
- LoggerProxy.logger.error(
4974
- 'Meeting:index#join --> Receive Transcription Failed',
4975
- error
4976
- );
4977
-
4978
- Metrics.sendBehavioralMetric(
4979
- BEHAVIORAL_METRICS.RECEIVE_TRANSCRIPTION_AFTER_JOIN_FAILURE,
4980
- {
4981
- correlation_id: this.correlationId,
4982
- reason: error?.message,
4983
- stack: error.stack,
4984
- }
4985
- );
4986
- });
4987
- }
4988
- }
4989
- } else {
4990
- LoggerProxy.logger.error(
4991
- 'Meeting:index#join --> Receving transcription is not supported on this platform'
4992
- );
5205
+ Trigger.trigger(
5206
+ this,
5207
+ {
5208
+ file: 'meeting/index',
5209
+ function: 'join',
5210
+ },
5211
+ EVENT_TRIGGERS.MEETING_TRANSCRIPTION_CONNECTED,
5212
+ undefined
5213
+ );
5214
+ });
4993
5215
  }
4994
5216
 
4995
5217
  return join;
@@ -5489,7 +5711,7 @@ export default class Meeting extends StatelessWebexPlugin {
5489
5711
  logText: `${LOG_HEADER} Roap Offer`,
5490
5712
  }
5491
5713
  ).catch(() => {
5492
- this.deferSDPAnswer.reject();
5714
+ this.deferSDPAnswer.reject(new Error('failed to send ROAP SDP offer'));
5493
5715
  clearTimeout(this.sdpResponseTimer);
5494
5716
  this.sdpResponseTimer = undefined;
5495
5717
  });
@@ -5836,6 +6058,20 @@ export default class Meeting extends StatelessWebexPlugin {
5836
6058
  meetingId: this.id,
5837
6059
  },
5838
6060
  });
6061
+
6062
+ if (data.type === 'share') {
6063
+ // @ts-ignore
6064
+ this.webex.internal.newMetrics.submitClientEvent({
6065
+ name: 'client.media.render.start',
6066
+ payload: {
6067
+ mediaType: 'share',
6068
+ shareInstanceId: this.remoteShareInstanceId,
6069
+ },
6070
+ options: {
6071
+ meetingId: this.id,
6072
+ },
6073
+ });
6074
+ }
5839
6075
  });
5840
6076
  this.statsAnalyzer.on(StatsAnalyzerEvents.REMOTE_MEDIA_STOPPED, (data) => {
5841
6077
  // @ts-ignore
@@ -5849,6 +6085,20 @@ export default class Meeting extends StatelessWebexPlugin {
5849
6085
  meetingId: this.id,
5850
6086
  },
5851
6087
  });
6088
+
6089
+ if (data.type === 'share') {
6090
+ // @ts-ignore
6091
+ this.webex.internal.newMetrics.submitClientEvent({
6092
+ name: 'client.media.render.stop',
6093
+ payload: {
6094
+ mediaType: 'share',
6095
+ shareInstanceId: this.remoteShareInstanceId,
6096
+ },
6097
+ options: {
6098
+ meetingId: this.id,
6099
+ },
6100
+ });
6101
+ }
5852
6102
  });
5853
6103
  };
5854
6104
 
@@ -5955,16 +6205,22 @@ export default class Meeting extends StatelessWebexPlugin {
5955
6205
  private async setUpLocalStreamReferences(localStreams: LocalStreams) {
5956
6206
  const setUpStreamPromises = [];
5957
6207
 
5958
- if (localStreams?.microphone) {
6208
+ if (localStreams?.microphone && localStreams?.microphone?.readyState !== 'ended') {
5959
6209
  setUpStreamPromises.push(this.setLocalAudioStream(localStreams.microphone));
5960
6210
  }
5961
- if (localStreams?.camera) {
6211
+ if (localStreams?.camera && localStreams?.camera?.readyState !== 'ended') {
5962
6212
  setUpStreamPromises.push(this.setLocalVideoStream(localStreams.camera));
5963
6213
  }
5964
- if (localStreams?.screenShare?.video) {
6214
+ if (
6215
+ localStreams?.screenShare?.video &&
6216
+ localStreams?.screenShare?.video?.readyState !== 'ended'
6217
+ ) {
5965
6218
  setUpStreamPromises.push(this.setLocalShareVideoStream(localStreams.screenShare.video));
5966
6219
  }
5967
- if (localStreams?.screenShare?.audio) {
6220
+ if (
6221
+ localStreams?.screenShare?.audio &&
6222
+ localStreams?.screenShare?.audio?.readyState !== 'ended'
6223
+ ) {
5968
6224
  setUpStreamPromises.push(this.setLocalShareAudioStream(localStreams.screenShare.audio));
5969
6225
  }
5970
6226
 
@@ -6209,6 +6465,44 @@ export default class Meeting extends StatelessWebexPlugin {
6209
6465
  }
6210
6466
  }
6211
6467
 
6468
+ /**
6469
+ * Performs TURN discovery as a separate call to the Locus /media API
6470
+ *
6471
+ * @param {boolean} isRetry
6472
+ * @param {boolean} isForced
6473
+ * @returns {Promise}
6474
+ */
6475
+ private async doTurnDiscovery(isRetry: boolean, isForced: boolean): Promise<TurnDiscoveryResult> {
6476
+ // @ts-ignore
6477
+ const cdl = this.webex.internal.newMetrics.callDiagnosticLatencies;
6478
+
6479
+ // @ts-ignore
6480
+ this.webex.internal.newMetrics.submitInternalEvent({
6481
+ name: 'internal.client.add-media.turn-discovery.start',
6482
+ });
6483
+
6484
+ const turnDiscoveryResult = await this.roap.doTurnDiscovery(this, isRetry, isForced);
6485
+
6486
+ this.turnDiscoverySkippedReason = turnDiscoveryResult?.turnDiscoverySkippedReason;
6487
+ this.turnServerUsed = !this.turnDiscoverySkippedReason;
6488
+
6489
+ // @ts-ignore
6490
+ this.webex.internal.newMetrics.submitInternalEvent({
6491
+ name: 'internal.client.add-media.turn-discovery.end',
6492
+ });
6493
+
6494
+ if (this.turnServerUsed && turnDiscoveryResult.turnServerInfo) {
6495
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.TURN_DISCOVERY_LATENCY, {
6496
+ correlation_id: this.correlationId,
6497
+ latency: cdl.getTurnDiscoveryTime(),
6498
+ turnServerUsed: this.turnServerUsed,
6499
+ retriedWithTurnServer: this.retriedWithTurnServer,
6500
+ });
6501
+ }
6502
+
6503
+ return turnDiscoveryResult;
6504
+ }
6505
+
6212
6506
  /**
6213
6507
  * Does TURN discovery, SDP offer/answer exhange, establishes ICE connection and DTLS handshake.
6214
6508
  *
@@ -6216,43 +6510,21 @@ export default class Meeting extends StatelessWebexPlugin {
6216
6510
  * @param {RemoteMediaManagerConfiguration} [remoteMediaManagerConfig]
6217
6511
  * @param {BundlePolicy} [bundlePolicy]
6218
6512
  * @param {boolean} [isForced] - let isForced be true to do turn discovery regardless of reachability results
6513
+ * @param {TurnServerInfo} [turnServerInfo]
6219
6514
  * @returns {Promise<void>}
6220
6515
  */
6221
6516
  private async establishMediaConnection(
6222
6517
  remoteMediaManagerConfig?: RemoteMediaManagerConfiguration,
6223
6518
  bundlePolicy?: BundlePolicy,
6224
- isForced?: boolean
6519
+ isForced?: boolean,
6520
+ turnServerInfo?: TurnServerInfo
6225
6521
  ): Promise<void> {
6226
6522
  const LOG_HEADER = 'Meeting:index#addMedia():establishMediaConnection -->';
6227
- // @ts-ignore
6228
- const cdl = this.webex.internal.newMetrics.callDiagnosticLatencies;
6229
6523
  const isRetry = this.retriedWithTurnServer;
6230
6524
 
6231
6525
  try {
6232
- // @ts-ignore
6233
- this.webex.internal.newMetrics.submitInternalEvent({
6234
- name: 'internal.client.add-media.turn-discovery.start',
6235
- });
6236
-
6237
- const turnDiscoveryObject = await this.roap.doTurnDiscovery(this, isRetry, isForced);
6238
-
6239
- this.turnDiscoverySkippedReason = turnDiscoveryObject?.turnDiscoverySkippedReason;
6240
- this.turnServerUsed = !this.turnDiscoverySkippedReason;
6241
-
6242
- // @ts-ignore
6243
- this.webex.internal.newMetrics.submitInternalEvent({
6244
- name: 'internal.client.add-media.turn-discovery.end',
6245
- });
6246
-
6247
- const {turnServerInfo} = turnDiscoveryObject;
6248
-
6249
- if (this.turnServerUsed && turnServerInfo) {
6250
- Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.TURN_DISCOVERY_LATENCY, {
6251
- correlation_id: this.correlationId,
6252
- latency: cdl.getTurnDiscoveryTime(),
6253
- turnServerUsed: this.turnServerUsed,
6254
- retriedWithTurnServer: this.retriedWithTurnServer,
6255
- });
6526
+ if (!turnServerInfo) {
6527
+ ({turnServerInfo} = await this.doTurnDiscovery(isRetry, isForced));
6256
6528
  }
6257
6529
 
6258
6530
  const mc = await this.createMediaConnection(turnServerInfo, bundlePolicy);
@@ -6369,15 +6641,21 @@ export default class Meeting extends StatelessWebexPlugin {
6369
6641
  * Creates a media connection to the server. Media connection is required for sending or receiving any audio/video.
6370
6642
  *
6371
6643
  * @param {AddMediaOptions} options
6644
+ * @param {TurnServerInfo} turnServerInfo - TURN server information (used only internally by the SDK)
6372
6645
  * @returns {Promise<void>}
6373
6646
  * @public
6374
6647
  * @memberof Meeting
6375
6648
  */
6376
- async addMedia(options: AddMediaOptions = {}): Promise<void> {
6649
+ async addMedia(
6650
+ options: AddMediaOptions = {},
6651
+ turnServerInfo: TurnServerInfo = undefined
6652
+ ): Promise<void> {
6377
6653
  this.retriedWithTurnServer = false;
6378
6654
  this.hasMediaConnectionConnectedAtLeastOnce = false;
6379
6655
  const LOG_HEADER = 'Meeting:index#addMedia -->';
6380
- LoggerProxy.logger.info(`${LOG_HEADER} called with: ${JSON.stringify(options)}`);
6656
+ LoggerProxy.logger.info(
6657
+ `${LOG_HEADER} called with: ${JSON.stringify(options)}, ${JSON.stringify(turnServerInfo)}`
6658
+ );
6381
6659
 
6382
6660
  if (options.allowMediaInLobby !== true && this.meetingState !== FULL_STATE.ACTIVE) {
6383
6661
  throw new MeetingNotActiveError();
@@ -6395,14 +6673,13 @@ export default class Meeting extends StatelessWebexPlugin {
6395
6673
  shareVideoEnabled = true,
6396
6674
  remoteMediaManagerConfig,
6397
6675
  bundlePolicy,
6398
- allowMediaInLobby,
6399
6676
  } = options;
6400
6677
 
6401
6678
  this.allowMediaInLobby = options?.allowMediaInLobby;
6402
6679
 
6403
6680
  // If the user is unjoined or guest waiting in lobby dont allow the user to addMedia
6404
6681
  // @ts-ignore - isUserUnadmitted coming from SelfUtil
6405
- if (this.isUserUnadmitted && !this.wirelessShare && !allowMediaInLobby) {
6682
+ if (this.isUserUnadmitted && !this.wirelessShare && !this.allowMediaInLobby) {
6406
6683
  throw new UserInLobbyError();
6407
6684
  }
6408
6685
 
@@ -6471,9 +6748,18 @@ export default class Meeting extends StatelessWebexPlugin {
6471
6748
 
6472
6749
  this.createStatsAnalyzer();
6473
6750
 
6474
- await this.establishMediaConnection(remoteMediaManagerConfig, bundlePolicy, false);
6751
+ await this.establishMediaConnection(
6752
+ remoteMediaManagerConfig,
6753
+ bundlePolicy,
6754
+ false,
6755
+ turnServerInfo
6756
+ );
6475
6757
 
6476
- await Meeting.handleDeviceLogging();
6758
+ if (audioEnabled || videoEnabled) {
6759
+ await Meeting.handleDeviceLogging();
6760
+ } else {
6761
+ LoggerProxy.logger.info(`${LOG_HEADER} device logging not required`);
6762
+ }
6477
6763
 
6478
6764
  if (this.mediaProperties.hasLocalShareStream()) {
6479
6765
  await this.enqueueScreenShareFloorRequest();
@@ -7420,7 +7706,7 @@ export default class Meeting extends StatelessWebexPlugin {
7420
7706
 
7421
7707
  if (layoutType) {
7422
7708
  if (!LAYOUT_TYPES.includes(layoutType)) {
7423
- this.rejectWithErrorLog(
7709
+ return this.rejectWithErrorLog(
7424
7710
  'Meeting:index#changeVideoLayout --> cannot change video layout, invalid layoutType received.'
7425
7711
  );
7426
7712
  }
@@ -7665,9 +7951,9 @@ export default class Meeting extends StatelessWebexPlugin {
7665
7951
 
7666
7952
  /**
7667
7953
  *
7668
- * @returns {string} one of 'attendee','host','cohost', returns the user type of the current user
7954
+ * @returns {string} one of 'panelist', 'attendee', 'host', 'cohost', returns the user type of the current user
7669
7955
  */
7670
- getCurUserType() {
7956
+ getCurUserType(): RawClientEvent['userType'] | null {
7671
7957
  const {roles} = this;
7672
7958
  if (roles) {
7673
7959
  if (roles.includes(SELF_ROLES.MODERATOR)) {
@@ -7676,6 +7962,9 @@ export default class Meeting extends StatelessWebexPlugin {
7676
7962
  if (roles.includes(SELF_ROLES.COHOST)) {
7677
7963
  return 'cohost';
7678
7964
  }
7965
+ if (roles.includes(SELF_ROLES.PANELIST)) {
7966
+ return 'panelist';
7967
+ }
7679
7968
  if (roles.includes(SELF_ROLES.ATTENDEE)) {
7680
7969
  return 'attendee';
7681
7970
  }
@@ -7766,8 +8055,7 @@ export default class Meeting extends StatelessWebexPlugin {
7766
8055
  this.queuedMediaUpdates = [];
7767
8056
 
7768
8057
  if (this.transcription) {
7769
- this.transcription.closeSocket();
7770
- this.triggerStopReceivingTranscriptionEvent();
8058
+ this.stopTranscription();
7771
8059
  this.transcription = undefined;
7772
8060
  }
7773
8061
  };
@@ -8080,6 +8368,17 @@ export default class Meeting extends StatelessWebexPlugin {
8080
8368
  return;
8081
8369
  }
8082
8370
 
8371
+ if (
8372
+ streams?.microphone?.readyState === 'ended' ||
8373
+ streams?.camera?.readyState === 'ended' ||
8374
+ streams?.screenShare?.audio?.readyState === 'ended' ||
8375
+ streams?.screenShare?.video?.readyState === 'ended'
8376
+ ) {
8377
+ throw new Error(
8378
+ `Attempted to publish stream with ended readyState, correlationId=${this.correlationId}`
8379
+ );
8380
+ }
8381
+
8083
8382
  let floorRequestNeeded = false;
8084
8383
 
8085
8384
  // Screenshare Audio is supported only in multi stream. So we check for screenshare audio presence only if it's a multi stream meeting