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

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 (111) hide show
  1. package/dist/common/errors/webex-errors.js +5 -29
  2. package/dist/common/errors/webex-errors.js.map +1 -1
  3. package/dist/constants.js +15 -74
  4. package/dist/constants.js.map +1 -1
  5. package/dist/media/index.js +68 -213
  6. package/dist/media/index.js.map +1 -1
  7. package/dist/media/internal-media-core-wrapper.js +22 -0
  8. package/dist/media/internal-media-core-wrapper.js.map +1 -0
  9. package/dist/media/properties.js +20 -25
  10. package/dist/media/properties.js.map +1 -1
  11. package/dist/media/util.js +0 -27
  12. package/dist/media/util.js.map +1 -1
  13. package/dist/meeting/index.js +694 -432
  14. package/dist/meeting/index.js.map +1 -1
  15. package/dist/meeting/request.js +1 -0
  16. package/dist/meeting/request.js.map +1 -1
  17. package/dist/meeting/util.js +3 -44
  18. package/dist/meeting/util.js.map +1 -1
  19. package/dist/meetings/index.js +64 -5
  20. package/dist/meetings/index.js.map +1 -1
  21. package/dist/meetings/util.js +24 -1
  22. package/dist/meetings/util.js.map +1 -1
  23. package/dist/members/index.js +68 -0
  24. package/dist/members/index.js.map +1 -1
  25. package/dist/multistream/mediaRequestManager.js +132 -0
  26. package/dist/multistream/mediaRequestManager.js.map +1 -0
  27. package/dist/multistream/multistreamMedia.js +116 -0
  28. package/dist/multistream/multistreamMedia.js.map +1 -0
  29. package/dist/multistream/receiveSlot.js +209 -0
  30. package/dist/multistream/receiveSlot.js.map +1 -0
  31. package/dist/multistream/receiveSlotManager.js +195 -0
  32. package/dist/multistream/receiveSlotManager.js.map +1 -0
  33. package/dist/multistream/remoteMedia.js +284 -0
  34. package/dist/multistream/remoteMedia.js.map +1 -0
  35. package/dist/multistream/remoteMediaGroup.js +243 -0
  36. package/dist/multistream/remoteMediaGroup.js.map +1 -0
  37. package/dist/multistream/remoteMediaManager.js +1113 -0
  38. package/dist/multistream/remoteMediaManager.js.map +1 -0
  39. package/dist/reconnection-manager/index.js +109 -130
  40. package/dist/reconnection-manager/index.js.map +1 -1
  41. package/dist/roap/index.js +57 -240
  42. package/dist/roap/index.js.map +1 -1
  43. package/dist/roap/request.js +2 -114
  44. package/dist/roap/request.js.map +1 -1
  45. package/dist/roap/turnDiscovery.js +11 -5
  46. package/dist/roap/turnDiscovery.js.map +1 -1
  47. package/dist/statsAnalyzer/global.js +2 -0
  48. package/dist/statsAnalyzer/global.js.map +1 -1
  49. package/dist/statsAnalyzer/index.js +39 -36
  50. package/dist/statsAnalyzer/index.js.map +1 -1
  51. package/package.json +20 -19
  52. package/src/common/errors/webex-errors.js +0 -18
  53. package/src/constants.ts +139 -180
  54. package/src/media/index.js +60 -194
  55. package/src/media/internal-media-core-wrapper.ts +9 -0
  56. package/src/media/properties.js +19 -25
  57. package/src/media/util.js +0 -22
  58. package/src/meeting/index.js +565 -320
  59. package/src/meeting/request.js +1 -0
  60. package/src/meeting/util.js +3 -46
  61. package/src/meetings/index.js +30 -1
  62. package/src/meetings/util.js +23 -2
  63. package/src/members/index.js +48 -0
  64. package/src/multistream/mediaRequestManager.ts +164 -0
  65. package/src/multistream/multistreamMedia.ts +92 -0
  66. package/src/multistream/receiveSlot.ts +141 -0
  67. package/src/multistream/receiveSlotManager.ts +142 -0
  68. package/src/multistream/remoteMedia.ts +219 -0
  69. package/src/multistream/remoteMediaGroup.ts +224 -0
  70. package/src/multistream/remoteMediaManager.ts +911 -0
  71. package/src/reconnection-manager/index.js +40 -53
  72. package/src/roap/index.js +47 -207
  73. package/src/roap/request.js +1 -72
  74. package/src/roap/turnDiscovery.ts +12 -6
  75. package/src/statsAnalyzer/global.js +2 -0
  76. package/src/statsAnalyzer/index.js +32 -46
  77. package/test/integration/spec/journey.js +1 -1
  78. package/test/unit/spec/media/index.ts +223 -0
  79. package/test/unit/spec/media/properties.ts +73 -82
  80. package/test/unit/spec/meeting/effectsState.js +1 -3
  81. package/test/unit/spec/meeting/index.js +420 -228
  82. package/test/unit/spec/meeting/muteState.js +7 -0
  83. package/test/unit/spec/meeting/utils.js +61 -2
  84. package/test/unit/spec/meetings/index.js +0 -4
  85. package/test/unit/spec/members/index.js +164 -2
  86. package/test/unit/spec/multistream/mediaRequestManager.ts +511 -0
  87. package/test/unit/spec/multistream/receiveSlot.ts +104 -0
  88. package/test/unit/spec/multistream/receiveSlotManager.ts +173 -0
  89. package/test/unit/spec/multistream/remoteMedia.ts +217 -0
  90. package/test/unit/spec/multistream/remoteMediaGroup.ts +396 -0
  91. package/test/unit/spec/multistream/remoteMediaManager.ts +1251 -0
  92. package/test/unit/spec/roap/index.ts +63 -35
  93. package/test/unit/spec/stats-analyzer/index.js +19 -22
  94. package/dist/peer-connection-manager/index.js +0 -794
  95. package/dist/peer-connection-manager/index.js.map +0 -1
  96. package/dist/roap/collection.js +0 -73
  97. package/dist/roap/collection.js.map +0 -1
  98. package/dist/roap/handler.js +0 -337
  99. package/dist/roap/handler.js.map +0 -1
  100. package/dist/roap/state.js +0 -164
  101. package/dist/roap/state.js.map +0 -1
  102. package/dist/roap/util.js +0 -102
  103. package/dist/roap/util.js.map +0 -1
  104. package/src/peer-connection-manager/index.js +0 -723
  105. package/src/roap/collection.js +0 -63
  106. package/src/roap/handler.js +0 -252
  107. package/src/roap/state.js +0 -149
  108. package/src/roap/util.js +0 -93
  109. package/test/unit/spec/peerconnection-manager/index.js +0 -188
  110. package/test/unit/spec/peerconnection-manager/utils.js +0 -48
  111. package/test/unit/spec/roap/util.js +0 -30
@@ -12,11 +12,11 @@ var _Object$getOwnPropertyDescriptors = require("@babel/runtime-corejs2/core-js/
12
12
 
13
13
  var _Object$defineProperties = require("@babel/runtime-corejs2/core-js/object/define-properties");
14
14
 
15
- var _Object$defineProperty2 = require("@babel/runtime-corejs2/core-js/object/define-property");
15
+ var _Object$defineProperty = require("@babel/runtime-corejs2/core-js/object/define-property");
16
16
 
17
17
  var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequireDefault");
18
18
 
19
- _Object$defineProperty2(exports, "__esModule", {
19
+ _Object$defineProperty(exports, "__esModule", {
20
20
  value: true
21
21
  });
22
22
 
@@ -28,10 +28,10 @@ var _keys = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/objec
28
28
 
29
29
  var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise"));
30
30
 
31
- var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/define-property"));
32
-
33
31
  var _stringify = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/json/stringify"));
34
32
 
33
+ var _values = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/values"));
34
+
35
35
  var _assign = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/assign"));
36
36
 
37
37
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/slicedToArray"));
@@ -52,7 +52,7 @@ var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime
52
52
 
53
53
  var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/getPrototypeOf"));
54
54
 
55
- var _defineProperty3 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/defineProperty"));
55
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/defineProperty"));
56
56
 
57
57
  var _isString2 = _interopRequireDefault(require("lodash/isString"));
58
58
 
@@ -92,8 +92,6 @@ var _effectsState = _interopRequireDefault(require("../meeting/effectsState"));
92
92
 
93
93
  var _locusInfo = _interopRequireDefault(require("../locus-info"));
94
94
 
95
- var _peerConnectionManager = _interopRequireDefault(require("../peer-connection-manager"));
96
-
97
95
  var _metrics = _interopRequireDefault(require("../metrics"));
98
96
 
99
97
  var _config = require("../metrics/config");
@@ -130,13 +128,19 @@ var _meetingInfoV = require("../meeting-info/meeting-info-v2");
130
128
 
131
129
  var _browserDetection = _interopRequireDefault(require("../common/browser-detection"));
132
130
 
133
- var _collection = _interopRequireDefault(require("../roap/collection"));
131
+ var _receiveSlotManager = require("../multistream/receiveSlotManager");
132
+
133
+ var _mediaRequestManager = require("../multistream/mediaRequestManager");
134
+
135
+ var _remoteMediaManager = require("../multistream/remoteMediaManager");
136
+
137
+ var _multistreamMedia = require("../multistream/multistreamMedia");
134
138
 
135
139
  var _inMeetingActions = _interopRequireDefault(require("./in-meeting-actions"));
136
140
 
137
141
  function ownKeys(object, enumerableOnly) { var keys = _Object$keys2(object); if (_Object$getOwnPropertySymbols) { var symbols = _Object$getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return _Object$getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
138
142
 
139
- function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty3.default)(target, key, source[key]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(target, _Object$getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { _Object$defineProperty2(target, key, _Object$getOwnPropertyDescriptor(source, key)); }); } return target; }
143
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(target, _Object$getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { _Object$defineProperty(target, key, _Object$getOwnPropertyDescriptor(source, key)); }); } return target; }
140
144
 
141
145
  function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2.default)(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2.default)(this).constructor; result = _Reflect$construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2.default)(this, result); }; }
142
146
 
@@ -211,6 +215,7 @@ var MEDIA_UPDATE_TYPE = {
211
215
  * @property {String} [meetingQuality.local]
212
216
  * @property {String} [meetingQuality.remote]
213
217
  * @property {Boolean} [rejoin]
218
+ * @property {Boolean} [enableMultistream]
214
219
  */
215
220
 
216
221
  /**
@@ -485,8 +490,8 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
485
490
  * @memberof Meeting
486
491
  */
487
492
 
488
- (0, _defineProperty3.default)((0, _assertThisInitialized2.default)(_this), "namespace", _constants.MEETINGS);
489
- (0, _defineProperty3.default)((0, _assertThisInitialized2.default)(_this), "getMediaStreams", function (mediaDirection) {
493
+ (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "namespace", _constants.MEETINGS);
494
+ (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "getMediaStreams", function (mediaDirection) {
490
495
  var audioVideo = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _constants.VIDEO_RESOLUTIONS[_this.mediaProperties.localQualityLevel];
491
496
  var sharePreferences = arguments.length > 2 ? arguments[2] : undefined;
492
497
 
@@ -578,7 +583,7 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
578
583
 
579
584
  return _promise.default.reject(new _media2.default('At least one of the mediaDirection value should be true'));
580
585
  });
581
- (0, _defineProperty3.default)((0, _assertThisInitialized2.default)(_this), "getSupportedDevices", function (_ref3) {
586
+ (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "getSupportedDevices", function (_ref3) {
582
587
  var _ref3$sendAudio = _ref3.sendAudio,
583
588
  sendAudio = _ref3$sendAudio === void 0 ? true : _ref3$sendAudio,
584
589
  _ref3$sendVideo = _ref3.sendVideo,
@@ -588,10 +593,343 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
588
593
  sendVideo: sendVideo
589
594
  });
590
595
  });
591
- (0, _defineProperty3.default)((0, _assertThisInitialized2.default)(_this), "getDevices", function () {
596
+ (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "getDevices", function () {
592
597
  return _media.default.getDevices();
593
598
  });
594
- (0, _defineProperty3.default)((0, _assertThisInitialized2.default)(_this), "setupStatsAnalyzerEventHandlers", function () {
599
+ (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "handleRoapFailure", function (error) {
600
+ var sendBehavioralMetric = function sendBehavioralMetric(metricName, error, correlationId) {
601
+ var _error$cause;
602
+
603
+ var data = {
604
+ code: error.code,
605
+ correlation_id: correlationId,
606
+ reason: error.message,
607
+ stack: error.stack
608
+ };
609
+ var metadata = {
610
+ type: ((_error$cause = error.cause) === null || _error$cause === void 0 ? void 0 : _error$cause.name) || error.name
611
+ };
612
+
613
+ _metrics.default.sendBehavioralMetric(metricName, data, metadata);
614
+ };
615
+
616
+ if (error instanceof _internalMediaCore.MediaConnection.Errors.SdpOfferCreationError) {
617
+ sendBehavioralMetric(_constants2.default.PEERCONNECTION_FAILURE, error, _this.id);
618
+
619
+ _metrics.default.postEvent({
620
+ event: _config.eventType.LOCAL_SDP_GENERATED,
621
+ meetingId: _this.id,
622
+ data: {
623
+ canProceed: false,
624
+ errors: [_metrics.default.generateErrorPayload(2001, true, _config.error.name.MEDIA_ENGINE)]
625
+ }
626
+ });
627
+ } else if (error instanceof _internalMediaCore.MediaConnection.Errors.SdpOfferHandlingError || error instanceof _internalMediaCore.MediaConnection.Errors.SdpAnswerHandlingError) {
628
+ sendBehavioralMetric(_constants2.default.PEERCONNECTION_FAILURE, error, _this.id);
629
+
630
+ _metrics.default.postEvent({
631
+ event: _config.eventType.REMOTE_SDP_RECEIVED,
632
+ meetingId: _this.id,
633
+ data: {
634
+ canProceed: false,
635
+ errors: [_metrics.default.generateErrorPayload(2001, true, error.name.MEDIA_ENGINE)]
636
+ }
637
+ });
638
+ } else if (error instanceof _internalMediaCore.MediaConnection.Errors.SdpError) {
639
+ // this covers also the case of MC.Errors.IceGatheringError which extends MC.Errors.SdpError
640
+ sendBehavioralMetric(_constants2.default.INVALID_ICE_CANDIDATE, error, _this.id);
641
+
642
+ _metrics.default.postEvent({
643
+ event: _config.eventType.LOCAL_SDP_GENERATED,
644
+ meetingId: _this.id,
645
+ data: {
646
+ canProceed: false,
647
+ errors: [_metrics.default.generateErrorPayload(2001, true, _config.error.name.MEDIA_ENGINE)]
648
+ }
649
+ });
650
+ }
651
+ });
652
+ (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "setupMediaConnectionListeners", function () {
653
+ _this.mediaProperties.webrtcMediaConnection.on(_internalMediaCore.MediaConnection.Event.ROAP_STARTED, function () {
654
+ _this.isRoapInProgress = true;
655
+ });
656
+
657
+ _this.mediaProperties.webrtcMediaConnection.on(_internalMediaCore.MediaConnection.Event.ROAP_DONE, function () {
658
+ _this.mediaNegotiatedEvent();
659
+
660
+ _this.isRoapInProgress = false;
661
+
662
+ _this.processNextQueuedMediaUpdate();
663
+ });
664
+
665
+ _this.mediaProperties.webrtcMediaConnection.on(_internalMediaCore.MediaConnection.Event.ROAP_FAILURE, _this.handleRoapFailure);
666
+
667
+ _this.mediaProperties.webrtcMediaConnection.on(_internalMediaCore.MediaConnection.Event.ROAP_MESSAGE_TO_SEND, function (event) {
668
+ var LOG_HEADER = 'Meeting:index#setupMediaConnectionListeners.ROAP_MESSAGE_TO_SEND -->';
669
+
670
+ switch (event.roapMessage.messageType) {
671
+ case 'OK':
672
+ _metrics.default.postEvent({
673
+ event: _config.eventType.REMOTE_SDP_RECEIVED,
674
+ meetingId: _this.id
675
+ });
676
+
677
+ logRequest(_this.roap.sendRoapOK({
678
+ seq: event.roapMessage.seq,
679
+ mediaId: _this.mediaId,
680
+ correlationId: _this.correlationId
681
+ }), {
682
+ header: "".concat(LOG_HEADER, " Send Roap OK"),
683
+ success: "".concat(LOG_HEADER, " Successfully send roap OK"),
684
+ failure: "".concat(LOG_HEADER, " Error joining the call on send roap OK, ")
685
+ });
686
+ break;
687
+
688
+ case 'OFFER':
689
+ _metrics.default.postEvent({
690
+ event: _config.eventType.LOCAL_SDP_GENERATED,
691
+ meetingId: _this.id
692
+ });
693
+
694
+ logRequest(_this.roap.sendRoapMediaRequest({
695
+ sdp: event.roapMessage.sdp,
696
+ seq: event.roapMessage.seq,
697
+ tieBreaker: event.roapMessage.tieBreaker,
698
+ meeting: (0, _assertThisInitialized2.default)(_this),
699
+ // or can pass meeting ID
700
+ reconnect: _this.reconnectionManager.isReconnectInProgress()
701
+ }), {
702
+ header: "".concat(LOG_HEADER, " Send Roap Offer"),
703
+ success: "".concat(LOG_HEADER, " Successfully send roap offer"),
704
+ failure: "".concat(LOG_HEADER, " Error joining the call on send roap offer, ")
705
+ });
706
+ break;
707
+
708
+ case 'ANSWER':
709
+ _metrics.default.postEvent({
710
+ event: _config.eventType.REMOTE_SDP_RECEIVED,
711
+ meetingId: _this.id
712
+ });
713
+
714
+ logRequest(_this.roap.sendRoapAnswer({
715
+ sdp: event.roapMessage.sdp,
716
+ seq: event.roapMessage.seq,
717
+ mediaId: _this.mediaId,
718
+ correlationId: _this.correlationId
719
+ }), {
720
+ header: "".concat(LOG_HEADER, " Send Roap Answer."),
721
+ success: "".concat(LOG_HEADER, " Successfully send roap answer"),
722
+ failure: "".concat(LOG_HEADER, " Error joining the call on send roap answer, ")
723
+ }).catch(function (error) {
724
+ var metricName = _constants2.default.ROAP_ANSWER_FAILURE;
725
+ var data = {
726
+ correlation_id: _this.correlationId,
727
+ locus_id: _this.locusUrl.split('/').pop(),
728
+ reason: error.message,
729
+ stack: error.stack
730
+ };
731
+ var metadata = {
732
+ type: error.name
733
+ };
734
+
735
+ _metrics.default.sendBehavioralMetric(metricName, data, metadata);
736
+ });
737
+ break;
738
+
739
+ case 'ERROR':
740
+ if (event.roapMessage.errorType === _internalMediaCore.MediaConnection.ErrorType.CONFLICT || event.roapMessage.errorType === _internalMediaCore.MediaConnection.ErrorType.DOUBLECONFLICT) {
741
+ _metrics.default.sendBehavioralMetric(_constants2.default.ROAP_GLARE_CONDITION, {
742
+ correlation_id: _this.correlationId,
743
+ locus_id: _this.locusUrl.split('/').pop(),
744
+ sequence: event.roapMessage.seq
745
+ });
746
+ }
747
+
748
+ logRequest(_this.roap.sendRoapError({
749
+ seq: event.roapMessage.seq,
750
+ errorType: event.roapMessage.errorType,
751
+ mediaId: _this.mediaId,
752
+ correlationId: _this.correlationId
753
+ }), {
754
+ header: "".concat(LOG_HEADER, " Send Roap Error."),
755
+ success: "".concat(LOG_HEADER, " Successfully send roap error"),
756
+ failure: "".concat(LOG_HEADER, " Failed to send roap error, ")
757
+ });
758
+ break;
759
+
760
+ default:
761
+ _loggerProxy.default.logger.error("".concat(LOG_HEADER, " Unsupported message type: ").concat(event.roapMessage.messageType));
762
+
763
+ break;
764
+ }
765
+ }); // eslint-disable-next-line no-param-reassign
766
+
767
+
768
+ _this.mediaProperties.webrtcMediaConnection.on(_internalMediaCore.MediaConnection.Event.REMOTE_TRACK_ADDED, function (event) {
769
+ _loggerProxy.default.logger.log("Meeting:index#setupMediaConnectionListeners --> REMOTE_TRACK_ADDED event received for webrtcMediaConnection: ".concat((0, _stringify.default)(event)));
770
+
771
+ var mediaTrack = event.track;
772
+ var eventType;
773
+
774
+ switch (event.type) {
775
+ case _internalMediaCore.MediaConnection.RemoteTrackType.AUDIO:
776
+ eventType = _constants.EVENT_TYPES.REMOTE_AUDIO;
777
+
778
+ _this.mediaProperties.setRemoteAudioTrack(event.track);
779
+
780
+ break;
781
+
782
+ case _internalMediaCore.MediaConnection.RemoteTrackType.VIDEO:
783
+ eventType = _constants.EVENT_TYPES.REMOTE_VIDEO;
784
+
785
+ _this.mediaProperties.setRemoteVideoTrack(event.track);
786
+
787
+ break;
788
+
789
+ case _internalMediaCore.MediaConnection.RemoteTrackType.SCREENSHARE_VIDEO:
790
+ if (event.track) {
791
+ eventType = _constants.EVENT_TYPES.REMOTE_SHARE;
792
+
793
+ _this.mediaProperties.setRemoteShare(event.track);
794
+ }
795
+
796
+ break;
797
+
798
+ default:
799
+ {
800
+ _loggerProxy.default.logger.log('Meeting:index#setupMediaConnectionListeners --> unexpected track');
801
+ }
802
+ } // start stats here the stats are coming null if you dont receive streams
803
+
804
+
805
+ _this.statsAnalyzer.startAnalyzer(_this.mediaProperties.webrtcMediaConnection);
806
+
807
+ if (eventType && mediaTrack) {
808
+ _triggerProxy.default.trigger((0, _assertThisInitialized2.default)(_this), {
809
+ file: 'meeting/index',
810
+ function: 'setupRemoteTrackListener:Event.REMOTE_TRACK_ADDED'
811
+ }, _constants.EVENT_TRIGGERS.MEDIA_READY, {
812
+ type: eventType,
813
+ stream: _util2.default.createMediaStream([mediaTrack])
814
+ });
815
+ }
816
+ });
817
+
818
+ _this.mediaProperties.webrtcMediaConnection.on(_internalMediaCore.MediaConnection.Event.CONNECTION_STATE_CHANGED, function (event) {
819
+ var connectionFailed = function connectionFailed() {
820
+ // we know the media connection failed and browser will not attempt to recover it any more
821
+ // so reset the timer as it's not needed anymore, we want to reconnect immediately
822
+ _this.reconnectionManager.resetReconnectionTimer();
823
+
824
+ _this.reconnect({
825
+ networkDisconnect: true
826
+ });
827
+
828
+ _metrics.default.postEvent({
829
+ event: _config.eventType.ICE_END,
830
+ meeting: (0, _assertThisInitialized2.default)(_this),
831
+ data: {
832
+ canProceed: false,
833
+ errors: [_metrics.default.generateErrorPayload(2004, false, _config.error.name.MEDIA_ENGINE)]
834
+ }
835
+ });
836
+
837
+ _this.uploadLogs({
838
+ file: 'peer-connection-manager/index',
839
+ function: 'connectionFailed'
840
+ });
841
+
842
+ _metrics.default.sendBehavioralMetric(_constants2.default.CONNECTION_FAILURE, {
843
+ correlation_id: _this.correlationId,
844
+ locus_id: _this.locusId
845
+ });
846
+ };
847
+
848
+ _loggerProxy.default.logger.info("Meeting:index#setupMediaConnectionListeners --> connection state changed to ".concat(event.state));
849
+
850
+ switch (event.state) {
851
+ case _internalMediaCore.MediaConnection.ConnectionState.Connecting:
852
+ _metrics.default.postEvent({
853
+ event: _config.eventType.ICE_START,
854
+ meeting: (0, _assertThisInitialized2.default)(_this)
855
+ });
856
+
857
+ break;
858
+
859
+ case _internalMediaCore.MediaConnection.ConnectionState.Connected:
860
+ _metrics.default.postEvent({
861
+ event: _config.eventType.ICE_END,
862
+ meeting: (0, _assertThisInitialized2.default)(_this)
863
+ });
864
+
865
+ _metrics.default.sendBehavioralMetric(_constants2.default.CONNECTION_SUCCESS, {
866
+ correlation_id: _this.correlationId,
867
+ locus_id: _this.locusId
868
+ });
869
+
870
+ _this.setNetworkStatus(_constants.NETWORK_STATUS.CONNECTED);
871
+
872
+ _this.reconnectionManager.iceReconnected();
873
+
874
+ break;
875
+
876
+ case _internalMediaCore.MediaConnection.ConnectionState.Disconnected:
877
+ _this.setNetworkStatus(_constants.NETWORK_STATUS.DISCONNECTED);
878
+
879
+ _this.reconnectionManager.waitForIceReconnect().catch(function () {
880
+ _loggerProxy.default.logger.info('Meeting:index#setupMediaConnectionListeners --> state DISCONNECTED, automatic reconnection timed out.');
881
+
882
+ connectionFailed();
883
+ });
884
+
885
+ break;
886
+
887
+ case _internalMediaCore.MediaConnection.ConnectionState.Failed:
888
+ connectionFailed();
889
+ break;
890
+
891
+ default:
892
+ break;
893
+ }
894
+ });
895
+
896
+ _this.mediaProperties.webrtcMediaConnection.on(_internalMediaCore.MediaConnection.Event.ACTIVE_SPEAKERS_CHANGED, function (msg) {
897
+ _triggerProxy.default.trigger((0, _assertThisInitialized2.default)(_this), {
898
+ file: 'meeting/index',
899
+ function: 'setupMediaConnectionListeners'
900
+ }, _constants.EVENT_TRIGGERS.ACTIVE_SPEAKER_CHANGED, {
901
+ seqNum: msg.seqNum,
902
+ memberIds: msg.csis.map(function (csi) {
903
+ var _this$members$findMem;
904
+
905
+ return (_this$members$findMem = _this.members.findMemberByCsi(csi)) === null || _this$members$findMem === void 0 ? void 0 : _this$members$findMem.id;
906
+ }).filter(function (item) {
907
+ return item !== undefined;
908
+ })
909
+ });
910
+ });
911
+
912
+ _this.mediaProperties.webrtcMediaConnection.on(_internalMediaCore.MediaConnection.Event.VIDEO_SOURCES_COUNT_CHANGED, function (numTotalSources, numLiveSources) {
913
+ _triggerProxy.default.trigger((0, _assertThisInitialized2.default)(_this), {
914
+ file: 'meeting/index',
915
+ function: 'setupMediaConnectionListeners'
916
+ }, _constants.EVENT_TRIGGERS.REMOTE_VIDEO_SOURCE_COUNT_CHANGED, {
917
+ numTotalSources: numTotalSources,
918
+ numLiveSources: numLiveSources
919
+ });
920
+ });
921
+
922
+ _this.mediaProperties.webrtcMediaConnection.on(_internalMediaCore.MediaConnection.Event.AUDIO_SOURCES_COUNT_CHANGED, function (numTotalSources, numLiveSources) {
923
+ _triggerProxy.default.trigger((0, _assertThisInitialized2.default)(_this), {
924
+ file: 'meeting/index',
925
+ function: 'setupMediaConnectionListeners'
926
+ }, _constants.EVENT_TRIGGERS.REMOTE_AUDIO_SOURCE_COUNT_CHANGED, {
927
+ numTotalSources: numTotalSources,
928
+ numLiveSources: numLiveSources
929
+ });
930
+ });
931
+ });
932
+ (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "setupStatsAnalyzerEventHandlers", function () {
595
933
  _this.statsAnalyzer.on(_statsAnalyzer.EVENTS.MEDIA_QUALITY, function (options) {
596
934
  var _this$webex$meetings$;
597
935
 
@@ -659,7 +997,7 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
659
997
  });
660
998
  });
661
999
  });
662
- (0, _defineProperty3.default)((0, _assertThisInitialized2.default)(_this), "mediaNegotiatedEvent", function () {
1000
+ (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "mediaNegotiatedEvent", function () {
663
1001
  if (_this.config.experimental.enableMediaNegotiatedEvent) {
664
1002
  _loggerProxy.default.logger.info('Meeting:mediaNegotiatedEvent --> Media server negotiated');
665
1003
 
@@ -669,7 +1007,7 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
669
1007
  }, _constants.EVENT_TRIGGERS.MEDIA_NEGOTIATED);
670
1008
  }
671
1009
  });
672
- (0, _defineProperty3.default)((0, _assertThisInitialized2.default)(_this), "processNextQueuedMediaUpdate", function () {
1010
+ (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "processNextQueuedMediaUpdate", function () {
673
1011
  if (_this.canUpdateMedia() && _this.queuedMediaUpdates.length > 0) {
674
1012
  var _this$queuedMediaUpda = _this.queuedMediaUpdates.shift(),
675
1013
  pendingPromiseResolve = _this$queuedMediaUpda.pendingPromiseResolve,
@@ -707,7 +1045,7 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
707
1045
  }
708
1046
  }
709
1047
  });
710
- (0, _defineProperty3.default)((0, _assertThisInitialized2.default)(_this), "clearMeetingData", function () {
1048
+ (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "clearMeetingData", function () {
711
1049
  _this.audio = null;
712
1050
  _this.video = null;
713
1051
  _this.isSharing = false;
@@ -726,7 +1064,7 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
726
1064
  _this.transcription = undefined;
727
1065
  }
728
1066
  });
729
- (0, _defineProperty3.default)((0, _assertThisInitialized2.default)(_this), "startKeepAlive", function () {
1067
+ (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "startKeepAlive", function () {
730
1068
  var _this$joinedWith, _this$joinedWith2;
731
1069
 
732
1070
  if (_this.keepAliveTimerId) {
@@ -766,7 +1104,7 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
766
1104
  });
767
1105
  }, keepAliveInterval);
768
1106
  });
769
- (0, _defineProperty3.default)((0, _assertThisInitialized2.default)(_this), "stopKeepAlive", function () {
1107
+ (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "stopKeepAlive", function () {
770
1108
  if (!_this.keepAliveTimerId) {
771
1109
  return;
772
1110
  }
@@ -840,16 +1178,6 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
840
1178
  */
841
1179
 
842
1180
  _this.deviceUrl = attrs.deviceUrl;
843
- /**
844
- * @description set you -1 as default values is 0 (used to idenfify if 1st roap request was sent)
845
- * @instance
846
- * @type {Number}
847
- * @readonly
848
- * @private
849
- * @memberof Meeting
850
- */
851
-
852
- _this.roapSeq = _constants.ROAP_SEQ_PRE;
853
1181
  /**
854
1182
  * @instance
855
1183
  * @type {Object}
@@ -860,6 +1188,36 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
860
1188
  // TODO: needs to be defined as a class
861
1189
 
862
1190
  _this.meetingInfo = {};
1191
+ /**
1192
+ * helper class for managing receive slots (for multistream media connections)
1193
+ */
1194
+
1195
+ _this.receiveSlotManager = new _receiveSlotManager.ReceiveSlotManager((0, _assertThisInitialized2.default)(_this));
1196
+ /**
1197
+ * Helper class for managing media requests for main video (for multistream media connections)
1198
+ * All media requests sent out for main video for this meeting have to go through it.
1199
+ */
1200
+
1201
+ _this.mediaRequestManagers = {
1202
+ audio: new _mediaRequestManager.MediaRequestManager(function (mediaRequests) {
1203
+ if (!_this.mediaProperties.webrtcMediaConnection) {
1204
+ _loggerProxy.default.logger.warn('Meeting:index#mediaRequestManager --> trying to send audio media request before media connection was created');
1205
+
1206
+ return;
1207
+ }
1208
+
1209
+ _this.mediaProperties.webrtcMediaConnection.requestMedia(_internalMediaCore.MediaConnection.MediaType.AudioMain, mediaRequests);
1210
+ }),
1211
+ video: new _mediaRequestManager.MediaRequestManager(function (mediaRequests) {
1212
+ if (!_this.mediaProperties.webrtcMediaConnection) {
1213
+ _loggerProxy.default.logger.warn('Meeting:index#mediaRequestManager --> trying to send video media request before media connection was created');
1214
+
1215
+ return;
1216
+ }
1217
+
1218
+ _this.mediaProperties.webrtcMediaConnection.requestMedia(_internalMediaCore.MediaConnection.MediaType.VideoMain, mediaRequests);
1219
+ })
1220
+ };
863
1221
  /**
864
1222
  * @instance
865
1223
  * @type {Members}
@@ -868,7 +1226,9 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
868
1226
  */
869
1227
 
870
1228
  _this.members = new _index2.default({
871
- locusUrl: attrs.locus && attrs.locus.url
1229
+ locusUrl: attrs.locus && attrs.locus.url,
1230
+ receiveSlotManager: _this.receiveSlotManager,
1231
+ mediaRequestManagers: _this.mediaRequestManagers
872
1232
  }, {
873
1233
  parent: _this.webex
874
1234
  });
@@ -883,6 +1243,17 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
883
1243
  _this.roap = new _index.default({}, {
884
1244
  parent: _this.webex
885
1245
  });
1246
+ /**
1247
+ * indicates if an SDP exchange is happening
1248
+ *
1249
+ * @instance
1250
+ * @type {Boolean}
1251
+ * @readonly
1252
+ * @private
1253
+ * @memberof Meeting
1254
+ */
1255
+
1256
+ _this.isRoapInProgress = false;
886
1257
  /**
887
1258
  * created later
888
1259
  * @instance
@@ -1036,6 +1407,12 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
1036
1407
  */
1037
1408
 
1038
1409
  _this.mediaConnections = null;
1410
+ /**
1411
+ * If true, then media is sent over multiple separate streams.
1412
+ * If false, then media is transcoded by the server into a single stream.
1413
+ */
1414
+
1415
+ _this.isMultistream = false;
1039
1416
  /**
1040
1417
  * Fetching meeting info can be done randomly 2-5 mins before meeting start
1041
1418
  * In case it is done before the timer expires, this timeout id is reset to cancel the timer.
@@ -1099,32 +1476,6 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
1099
1476
  */
1100
1477
 
1101
1478
  _this.shareStatus = _constants.SHARE_STATUS.NO_SHARE;
1102
- /**
1103
- * @instance
1104
- * @type {Boolean}
1105
- * @readonly
1106
- * @private
1107
- * @memberof Meeting
1108
- */
1109
-
1110
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), 'isLocalShareLive', {
1111
- get: function get() {
1112
- var _shareTransceiver$sen, _shareTransceiver$sen2;
1113
-
1114
- var shareTransceiver = _this.mediaProperties.peerConnection.shareTransceiver;
1115
- var shareDirection = shareTransceiver === null || shareTransceiver === void 0 ? void 0 : shareTransceiver.direction;
1116
- var trackReadyState = shareTransceiver === null || shareTransceiver === void 0 ? void 0 : (_shareTransceiver$sen = shareTransceiver.sender) === null || _shareTransceiver$sen === void 0 ? void 0 : (_shareTransceiver$sen2 = _shareTransceiver$sen.track) === null || _shareTransceiver$sen2 === void 0 ? void 0 : _shareTransceiver$sen2.readyState;
1117
- var activeShare = trackReadyState === _constants.LIVE;
1118
- var offersToSendData = shareDirection === _constants.SENDRECV;
1119
-
1120
- if (activeShare && offersToSendData) {
1121
- return true;
1122
- }
1123
-
1124
- return false;
1125
- },
1126
- configurable: true
1127
- });
1128
1479
  /**
1129
1480
  * @instance
1130
1481
  * @type {Array}
@@ -1323,6 +1674,12 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
1323
1674
  _this.locusInfo.init(attrs.locus ? attrs.locus : {});
1324
1675
 
1325
1676
  _this.hasJoinedOnce = false;
1677
+ _this.media = new _multistreamMedia.MultistreamMedia((0, _assertThisInitialized2.default)(_this));
1678
+ /**
1679
+ * helper class for managing remote streams
1680
+ */
1681
+
1682
+ _this.remoteMediaManager = null;
1326
1683
  return _this;
1327
1684
  }
1328
1685
  /**
@@ -2871,21 +3228,6 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
2871
3228
  // This can be tel no, device id or a sip uri, user Id
2872
3229
  this.sipUri = sipUri;
2873
3230
  }
2874
- /**
2875
- * Set the roap seq on the class instance
2876
- * @param {Number} seq
2877
- * @returns {undefined}
2878
- * @private
2879
- * @memberof Meeting
2880
- */
2881
-
2882
- }, {
2883
- key: "setRoapSeq",
2884
- value: function setRoapSeq(seq) {
2885
- if (seq >= 0) {
2886
- this.roapSeq = seq;
2887
- }
2888
- }
2889
3231
  /**
2890
3232
  * Set the locus info the class instance
2891
3233
  * @param {Object} locus
@@ -2914,111 +3256,6 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
2914
3256
  this.hostId = mtgLocus.host ? mtgLocus.host.id : this.hostId;
2915
3257
  this.locusInfo.initialSetup(mtgLocus);
2916
3258
  }
2917
- /**
2918
- * Sets the remote stream on the class instance and emits and
2919
- * event to developers
2920
- * @param {Object} pc The remote stream peer connection
2921
- * @returns {undefined}
2922
- * @public
2923
- * @memberof Meeting
2924
- */
2925
-
2926
- }, {
2927
- key: "setRemoteStream",
2928
- value: function setRemoteStream(pc) {
2929
- var _this19 = this;
2930
-
2931
- if (!pc) {
2932
- return;
2933
- } // eslint-disable-next-line no-param-reassign
2934
-
2935
-
2936
- pc.ontrack = function (event) {
2937
- // eslint-disable-next-line no-warning-comments
2938
- // TODO: It's possible for media to not be present
2939
- // so we might need to either
2940
- // A) wait until we have media flowing
2941
- // B) trigger a second event when video is flowing
2942
- _loggerProxy.default.logger.log("Meeting:index#setRemoteStream --> ontrack event received for peerConnection: ".concat(event));
2943
-
2944
- var MEDIA_ID = {
2945
- AUDIO_TRACK: '0',
2946
- VIDEO_TRACK: '1',
2947
- SHARE_TRACK: '2'
2948
- };
2949
- var eventType = null;
2950
- var mediaTrack = event.track;
2951
- var trackMediaID = null; // In case of safari some time the transceiver is not present for specific os version
2952
- // sdk tries to determine the transceive using the track id present
2953
-
2954
- if (event.transceiver && event.transceiver.mid) {
2955
- trackMediaID = event.transceiver.mid;
2956
- } else {
2957
- var _event$target = event.target,
2958
- audioTransceiver = _event$target.audioTransceiver,
2959
- videoTransceiver = _event$target.videoTransceiver,
2960
- shareTransceiver = _event$target.shareTransceiver; // audio kind indicates its a audio stream
2961
-
2962
- if (mediaTrack.id === audioTransceiver.receiver.track.id) {
2963
- trackMediaID = '0';
2964
- } else if (mediaTrack.id === videoTransceiver.receiver.track.id) {
2965
- trackMediaID = '1';
2966
- } else if (mediaTrack.id === shareTransceiver.receiver.track.id) {
2967
- trackMediaID = '2';
2968
- } else {
2969
- trackMediaID = null;
2970
-
2971
- _metrics.default.sendBehavioralMetric(_constants2.default.MUTE_AUDIO_FAILURE, {
2972
- correlation_id: _this19.correlationId,
2973
- locus_id: _this19.locusUrl.split('/').pop()
2974
- });
2975
- }
2976
- }
2977
-
2978
- switch (trackMediaID) {
2979
- case MEDIA_ID.AUDIO_TRACK:
2980
- eventType = _constants.EVENT_TYPES.REMOTE_AUDIO;
2981
-
2982
- _this19.mediaProperties.setRemoteAudioTrack(mediaTrack);
2983
-
2984
- break;
2985
-
2986
- case MEDIA_ID.VIDEO_TRACK:
2987
- eventType = _constants.EVENT_TYPES.REMOTE_VIDEO;
2988
-
2989
- _this19.mediaProperties.setRemoteVideoTrack(mediaTrack);
2990
-
2991
- break;
2992
-
2993
- case MEDIA_ID.SHARE_TRACK:
2994
- if (event.track) {
2995
- eventType = _constants.EVENT_TYPES.REMOTE_SHARE;
2996
-
2997
- _this19.mediaProperties.setRemoteShare(mediaTrack);
2998
- }
2999
-
3000
- break;
3001
-
3002
- default:
3003
- {
3004
- _loggerProxy.default.logger.log('Meeting:index#setRemoteStream --> no matching media track id');
3005
- }
3006
- } // start stats here the stats are coming null if you dont receive streams
3007
-
3008
-
3009
- _this19.statsAnalyzer.startAnalyzer(_this19.mediaProperties.peerConnection);
3010
-
3011
- if (eventType && mediaTrack) {
3012
- _triggerProxy.default.trigger(_this19, {
3013
- file: 'meeting/index',
3014
- function: 'setRemoteStream:pc.ontrack'
3015
- }, _constants.EVENT_TRIGGERS.MEDIA_READY, {
3016
- type: eventType,
3017
- stream: _util2.default.createMediaStream([mediaTrack])
3018
- });
3019
- }
3020
- };
3021
- }
3022
3259
  /**
3023
3260
  * Upload logs for the current meeting
3024
3261
  * @param {object} options file name and function name
@@ -3089,7 +3326,7 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
3089
3326
  }, {
3090
3327
  key: "closeRemoteTracks",
3091
3328
  value: function closeRemoteTracks() {
3092
- var _this20 = this;
3329
+ var _this19 = this;
3093
3330
 
3094
3331
  var _this$mediaProperties = this.mediaProperties,
3095
3332
  remoteAudioTrack = _this$mediaProperties.remoteAudioTrack,
@@ -3103,7 +3340,7 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
3103
3340
  */
3104
3341
 
3105
3342
  var triggerMediaStoppedEvent = function triggerMediaStoppedEvent(mediaType) {
3106
- _triggerProxy.default.trigger(_this20, {
3343
+ _triggerProxy.default.trigger(_this19, {
3107
3344
  file: 'meeting/index',
3108
3345
  function: 'closeRemoteTracks'
3109
3346
  }, _constants.EVENT_TRIGGERS.MEDIA_STOPPED, {
@@ -3266,7 +3503,7 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
3266
3503
  }, {
3267
3504
  key: "setLocalShareTrack",
3268
3505
  value: function setLocalShareTrack(localShare) {
3269
- var _this21 = this;
3506
+ var _this20 = this;
3270
3507
 
3271
3508
  var settings = null;
3272
3509
 
@@ -3289,7 +3526,7 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
3289
3526
  }
3290
3527
 
3291
3528
  contentTracks.onended = function () {
3292
- return _this21.handleShareTrackEnded(localShare);
3529
+ return _this20.handleShareTrackEnded(localShare);
3293
3530
  };
3294
3531
 
3295
3532
  _triggerProxy.default.trigger(this, {
@@ -3312,7 +3549,7 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
3312
3549
  }, {
3313
3550
  key: "closeLocalStream",
3314
3551
  value: function closeLocalStream() {
3315
- var _this22 = this;
3552
+ var _this21 = this;
3316
3553
 
3317
3554
  var _this$mediaProperties2 = this.mediaProperties,
3318
3555
  audioTrack = _this$mediaProperties2.audioTrack,
@@ -3324,7 +3561,7 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
3324
3561
  var videoStopped = videoTrack && videoTrack.readyState === _constants.ENDED; // triggers event for audio and video stop , sometime either audio or video one of them exists
3325
3562
 
3326
3563
  if (audioStopped || videoStopped) {
3327
- _triggerProxy.default.trigger(_this22, {
3564
+ _triggerProxy.default.trigger(_this21, {
3328
3565
  file: 'meeting/index',
3329
3566
  function: 'closeLocalStream'
3330
3567
  }, _constants.EVENT_TRIGGERS.MEDIA_STOPPED, {
@@ -3346,12 +3583,12 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
3346
3583
  }, {
3347
3584
  key: "closeLocalShare",
3348
3585
  value: function closeLocalShare() {
3349
- var _this23 = this;
3586
+ var _this22 = this;
3350
3587
 
3351
3588
  var track = this.mediaProperties.shareTrack;
3352
3589
  return _media.default.stopTracks(track).then(function () {
3353
3590
  if (track && track.readyState === _constants.ENDED) {
3354
- _triggerProxy.default.trigger(_this23, {
3591
+ _triggerProxy.default.trigger(_this22, {
3355
3592
  file: 'meeting/index',
3356
3593
  function: 'closeLocalShare'
3357
3594
  }, _constants.EVENT_TRIGGERS.MEDIA_STOPPED, {
@@ -3397,7 +3634,7 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
3397
3634
  }, {
3398
3635
  key: "setMercuryListener",
3399
3636
  value: function setMercuryListener() {
3400
- var _this24 = this;
3637
+ var _this23 = this;
3401
3638
 
3402
3639
  // Client will have a socket manager and handle reconnecting to mercury, when we reconnect to mercury
3403
3640
  // if the meeting has active peer connections, it should try to reconnect.
@@ -3405,36 +3642,37 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
3405
3642
  _loggerProxy.default.logger.info('Meeting:index#setMercuryListener --> Web socket online'); // Only send restore event when it was disconnected before and for connected later
3406
3643
 
3407
3644
 
3408
- if (!_this24.hasWebsocketConnected) {
3645
+ if (!_this23.hasWebsocketConnected) {
3409
3646
  _metrics.default.postEvent({
3410
3647
  event: _config.eventType.MERCURY_CONNECTION_RESTORED,
3411
- meeting: _this24
3648
+ meeting: _this23
3412
3649
  });
3413
3650
 
3414
3651
  _metrics.default.sendBehavioralMetric(_constants2.default.MERCURY_CONNECTION_RESTORED, {
3415
- correlation_id: _this24.correlationId
3652
+ correlation_id: _this23.correlationId
3416
3653
  });
3417
3654
  }
3418
3655
 
3419
- _this24.hasWebsocketConnected = true;
3656
+ _this23.hasWebsocketConnected = true;
3420
3657
  });
3421
3658
  this.webex.internal.mercury.on(_constants.OFFLINE, function () {
3422
3659
  _loggerProxy.default.logger.error('Meeting:index#setMercuryListener --> Web socket offline');
3423
3660
 
3424
3661
  _metrics.default.postEvent({
3425
3662
  event: _config.eventType.MERCURY_CONNECTION_LOST,
3426
- meeting: _this24
3663
+ meeting: _this23
3427
3664
  });
3428
3665
 
3429
3666
  _metrics.default.sendBehavioralMetric(_constants2.default.MERCURY_CONNECTION_FAILURE, {
3430
- correlation_id: _this24.correlationId
3667
+ correlation_id: _this23.correlationId
3431
3668
  });
3432
3669
  });
3433
3670
  }
3434
3671
  /**
3435
- * Close the peer connections and remove them from the class. Triggers an event
3436
- * when each is closed.
3437
- * @returns {Promise} returns a resolved promise with an array of closed peer connections
3672
+ * Close the peer connections and remove them from the class.
3673
+ * Cleanup any media connection related things.
3674
+ *
3675
+ * @returns {Promise}
3438
3676
  * @public
3439
3677
  * @memberof Meeting
3440
3678
  */
@@ -3442,12 +3680,24 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
3442
3680
  }, {
3443
3681
  key: "closePeerConnections",
3444
3682
  value: function closePeerConnections() {
3445
- return _peerConnectionManager.default.close(this.mediaProperties.peerConnection);
3683
+ if (this.mediaProperties.webrtcMediaConnection) {
3684
+ if (this.remoteMediaManager) {
3685
+ this.remoteMediaManager.stop();
3686
+ this.remoteMediaManager = null;
3687
+ }
3688
+
3689
+ (0, _values.default)(this.mediaRequestManagers).forEach(function (mediaRequestManager) {
3690
+ return mediaRequestManager.reset();
3691
+ });
3692
+ this.receiveSlotManager.reset();
3693
+ this.mediaProperties.webrtcMediaConnection.close();
3694
+ }
3695
+
3696
+ return _promise.default.resolve();
3446
3697
  }
3447
3698
  /**
3448
3699
  * Unsets the peer connections on the class
3449
3700
  * warning DO NOT CALL WITHOUT CLOSING PEER CONNECTIONS FIRST
3450
- * @param {PeerConnection} peerConnection
3451
3701
  * @returns {undefined}
3452
3702
  * @public
3453
3703
  * @memberof Meeting
@@ -3485,7 +3735,7 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
3485
3735
  }, {
3486
3736
  key: "muteAudio",
3487
3737
  value: function muteAudio() {
3488
- var _this25 = this;
3738
+ var _this24 = this;
3489
3739
 
3490
3740
  if (!_util.default.isUserInJoinedState(this.locusInfo)) {
3491
3741
  return _promise.default.reject(new _webexErrors.UserNotJoinedError());
@@ -3503,11 +3753,11 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
3503
3753
  var LOG_HEADER = 'Meeting:index#muteAudio -->'; // First, stop sending the local audio media
3504
3754
 
3505
3755
  return logRequest(this.audio.handleClientRequest(this, true).then(function () {
3506
- _util.default.handleAudioLogging(_this25.mediaProperties.audioTrack);
3756
+ _util.default.handleAudioLogging(_this24.mediaProperties.audioTrack);
3507
3757
 
3508
3758
  _metrics.default.postEvent({
3509
3759
  event: _config.eventType.MUTED,
3510
- meeting: _this25,
3760
+ meeting: _this24,
3511
3761
  data: {
3512
3762
  trigger: _config.trigger.USER_INTERACTION,
3513
3763
  mediaType: _config.mediaType.AUDIO
@@ -3515,8 +3765,8 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
3515
3765
  });
3516
3766
  }).catch(function (error) {
3517
3767
  _metrics.default.sendBehavioralMetric(_constants2.default.MUTE_AUDIO_FAILURE, {
3518
- correlation_id: _this25.correlationId,
3519
- locus_id: _this25.locusUrl.split('/').pop(),
3768
+ correlation_id: _this24.correlationId,
3769
+ locus_id: _this24.locusUrl.split('/').pop(),
3520
3770
  reason: error.message,
3521
3771
  stack: error.stack
3522
3772
  });
@@ -3538,7 +3788,7 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
3538
3788
  }, {
3539
3789
  key: "unmuteAudio",
3540
3790
  value: function unmuteAudio() {
3541
- var _this26 = this;
3791
+ var _this25 = this;
3542
3792
 
3543
3793
  if (!_util.default.isUserInJoinedState(this.locusInfo)) {
3544
3794
  return _promise.default.reject(new _webexErrors.UserNotJoinedError());
@@ -3556,11 +3806,11 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
3556
3806
  var LOG_HEADER = 'Meeting:index#unmuteAudio -->'; // First, send the control to unmute the participant on the server
3557
3807
 
3558
3808
  return logRequest(this.audio.handleClientRequest(this, false).then(function () {
3559
- _util.default.handleAudioLogging(_this26.mediaProperties.audioTrack);
3809
+ _util.default.handleAudioLogging(_this25.mediaProperties.audioTrack);
3560
3810
 
3561
3811
  _metrics.default.postEvent({
3562
3812
  event: _config.eventType.UNMUTED,
3563
- meeting: _this26,
3813
+ meeting: _this25,
3564
3814
  data: {
3565
3815
  trigger: _config.trigger.USER_INTERACTION,
3566
3816
  mediaType: _config.mediaType.AUDIO
@@ -3568,8 +3818,8 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
3568
3818
  });
3569
3819
  }).catch(function (error) {
3570
3820
  _metrics.default.sendBehavioralMetric(_constants2.default.UNMUTE_AUDIO_FAILURE, {
3571
- correlation_id: _this26.correlationId,
3572
- locus_id: _this26.locusUrl.split('/').pop(),
3821
+ correlation_id: _this25.correlationId,
3822
+ locus_id: _this25.locusUrl.split('/').pop(),
3573
3823
  reason: error.message,
3574
3824
  stack: error.stack
3575
3825
  });
@@ -3591,7 +3841,7 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
3591
3841
  }, {
3592
3842
  key: "muteVideo",
3593
3843
  value: function muteVideo() {
3594
- var _this27 = this;
3844
+ var _this26 = this;
3595
3845
 
3596
3846
  if (!_util.default.isUserInJoinedState(this.locusInfo)) {
3597
3847
  return _promise.default.reject(new _webexErrors.UserNotJoinedError());
@@ -3608,11 +3858,11 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
3608
3858
 
3609
3859
  var LOG_HEADER = 'Meeting:index#muteVideo -->';
3610
3860
  return logRequest(this.video.handleClientRequest(this, true).then(function () {
3611
- _util.default.handleVideoLogging(_this27.mediaProperties.videoTrack);
3861
+ _util.default.handleVideoLogging(_this26.mediaProperties.videoTrack);
3612
3862
 
3613
3863
  _metrics.default.postEvent({
3614
3864
  event: _config.eventType.MUTED,
3615
- meeting: _this27,
3865
+ meeting: _this26,
3616
3866
  data: {
3617
3867
  trigger: _config.trigger.USER_INTERACTION,
3618
3868
  mediaType: _config.mediaType.VIDEO
@@ -3620,8 +3870,8 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
3620
3870
  });
3621
3871
  }).catch(function (error) {
3622
3872
  _metrics.default.sendBehavioralMetric(_constants2.default.MUTE_VIDEO_FAILURE, {
3623
- correlation_id: _this27.correlationId,
3624
- locus_id: _this27.locusUrl.split('/').pop(),
3873
+ correlation_id: _this26.correlationId,
3874
+ locus_id: _this26.locusUrl.split('/').pop(),
3625
3875
  reason: error.message,
3626
3876
  stack: error.stack
3627
3877
  });
@@ -3643,7 +3893,7 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
3643
3893
  }, {
3644
3894
  key: "unmuteVideo",
3645
3895
  value: function unmuteVideo() {
3646
- var _this28 = this;
3896
+ var _this27 = this;
3647
3897
 
3648
3898
  if (!_util.default.isUserInJoinedState(this.locusInfo)) {
3649
3899
  return _promise.default.reject(new _webexErrors.UserNotJoinedError());
@@ -3660,11 +3910,11 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
3660
3910
 
3661
3911
  var LOG_HEADER = 'Meeting:index#unmuteVideo -->';
3662
3912
  return logRequest(this.video.handleClientRequest(this, false).then(function () {
3663
- _util.default.handleVideoLogging(_this28.mediaProperties.videoTrack);
3913
+ _util.default.handleVideoLogging(_this27.mediaProperties.videoTrack);
3664
3914
 
3665
3915
  _metrics.default.postEvent({
3666
3916
  event: _config.eventType.UNMUTED,
3667
- meeting: _this28,
3917
+ meeting: _this27,
3668
3918
  data: {
3669
3919
  trigger: _config.trigger.USER_INTERACTION,
3670
3920
  mediaType: _config.mediaType.VIDEO
@@ -3672,8 +3922,8 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
3672
3922
  });
3673
3923
  }).catch(function (error) {
3674
3924
  _metrics.default.sendBehavioralMetric(_constants2.default.UNMUTE_VIDEO_FAILURE, {
3675
- correlation_id: _this28.correlationId,
3676
- locus_id: _this28.locusUrl.split('/').pop(),
3925
+ correlation_id: _this27.correlationId,
3926
+ locus_id: _this27.locusUrl.split('/').pop(),
3677
3927
  reason: error.message,
3678
3928
  stack: error.stack
3679
3929
  });
@@ -3714,7 +3964,7 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
3714
3964
  }, {
3715
3965
  key: "joinWithMedia",
3716
3966
  value: function joinWithMedia() {
3717
- var _this29 = this;
3967
+ var _this28 = this;
3718
3968
 
3719
3969
  var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
3720
3970
  // TODO: add validations for parameters
@@ -3722,12 +3972,12 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
3722
3972
  joinOptions = options.joinOptions,
3723
3973
  audioVideoOptions = options.audioVideoOptions;
3724
3974
  return this.join(joinOptions).then(function (joinResponse) {
3725
- return _this29.getMediaStreams(mediaSettings, audioVideoOptions).then(function (_ref9) {
3975
+ return _this28.getMediaStreams(mediaSettings, audioVideoOptions).then(function (_ref9) {
3726
3976
  var _ref10 = (0, _slicedToArray2.default)(_ref9, 2),
3727
3977
  localStream = _ref10[0],
3728
3978
  localShare = _ref10[1];
3729
3979
 
3730
- return _this29.addMedia({
3980
+ return _this28.addMedia({
3731
3981
  mediaSettings: mediaSettings,
3732
3982
  localShare: localShare,
3733
3983
  localStream: localStream
@@ -3743,8 +3993,8 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
3743
3993
  _loggerProxy.default.logger.error('Meeting:index#joinWithMedia --> ', error);
3744
3994
 
3745
3995
  _metrics.default.sendBehavioralMetric(_constants2.default.JOIN_WITH_MEDIA_FAILURE, {
3746
- correlation_id: _this29.correlationId,
3747
- locus_id: _this29.locusUrl.split('/').pop(),
3996
+ correlation_id: _this28.correlationId,
3997
+ locus_id: _this28.locusUrl.split('/').pop(),
3748
3998
  reason: error.message,
3749
3999
  stack: error.stack
3750
4000
  }, {
@@ -3766,7 +4016,7 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
3766
4016
  }, {
3767
4017
  key: "reconnect",
3768
4018
  value: function reconnect(options) {
3769
- var _this30 = this;
4019
+ var _this29 = this;
3770
4020
 
3771
4021
  _loggerProxy.default.logger.log("Meeting:index#reconnect --> attempting to reconnect meeting ".concat(this.id));
3772
4022
 
@@ -3799,14 +4049,14 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
3799
4049
  }, _constants.EVENT_TRIGGERS.MEETING_RECONNECTION_STARTING);
3800
4050
 
3801
4051
  return this.reconnectionManager.reconnect(options).then(function () {
3802
- _triggerProxy.default.trigger(_this30, {
4052
+ _triggerProxy.default.trigger(_this29, {
3803
4053
  file: 'meeting/index',
3804
4054
  function: 'reconnect'
3805
4055
  }, _constants.EVENT_TRIGGERS.MEETING_RECONNECTION_SUCCESS);
3806
4056
 
3807
4057
  _loggerProxy.default.logger.log('Meeting:index#reconnect --> Meeting reconnect success');
3808
4058
  }).catch(function (error) {
3809
- _triggerProxy.default.trigger(_this30, {
4059
+ _triggerProxy.default.trigger(_this29, {
3810
4060
  file: 'meeting/index',
3811
4061
  function: 'reconnect'
3812
4062
  }, _constants.EVENT_TRIGGERS.MEETING_RECONNECTION_FAILURE, {
@@ -3816,20 +4066,20 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
3816
4066
  _loggerProxy.default.logger.error('Meeting:index#reconnect --> Meeting reconnect failed', error);
3817
4067
 
3818
4068
  _metrics.default.sendBehavioralMetric(_constants2.default.MEETING_RECONNECT_FAILURE, {
3819
- correlation_id: _this30.correlationId,
3820
- locus_id: _this30.locusUrl.split('/').pop(),
4069
+ correlation_id: _this29.correlationId,
4070
+ locus_id: _this29.locusUrl.split('/').pop(),
3821
4071
  reason: error.message,
3822
4072
  stack: error.stack
3823
4073
  });
3824
4074
 
3825
- _this30.uploadLogs({
4075
+ _this29.uploadLogs({
3826
4076
  file: 'meeting/index',
3827
4077
  function: 'reconnect'
3828
4078
  });
3829
4079
 
3830
4080
  return _promise.default.reject(new _reconnection.default('Reconnection failure event', error));
3831
4081
  }).finally(function () {
3832
- _this30.reconnectionManager.reset();
4082
+ _this29.reconnectionManager.reset();
3833
4083
  });
3834
4084
  }
3835
4085
  /**
@@ -3860,20 +4110,20 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
3860
4110
  }, {
3861
4111
  key: "monitorTranscriptionSocketConnection",
3862
4112
  value: function monitorTranscriptionSocketConnection() {
3863
- var _this31 = this;
4113
+ var _this30 = this;
3864
4114
 
3865
4115
  this.transcription.onCloseSocket(function (event) {
3866
4116
  _loggerProxy.default.logger.info("Meeting:index#onCloseSocket -->\n unable to continue receiving transcription;\n low-latency mercury web socket connection is closed now.\n ".concat(event));
3867
4117
 
3868
- _this31.triggerStopReceivingTranscriptionEvent();
4118
+ _this30.triggerStopReceivingTranscriptionEvent();
3869
4119
  });
3870
4120
  this.transcription.onErrorSocket(function (event) {
3871
4121
  _loggerProxy.default.logger.error("Meeting:index#onErrorSocket -->\n unable to continue receiving transcription;\n low-latency mercury web socket connection error had occured.\n ".concat(event));
3872
4122
 
3873
- _this31.triggerStopReceivingTranscriptionEvent();
4123
+ _this30.triggerStopReceivingTranscriptionEvent();
3874
4124
 
3875
4125
  _metrics.default.sendBehavioralMetric(_constants2.default.RECEIVE_TRANSCRIPTION_FAILURE, {
3876
- correlation_id: _this31.correlationId,
4126
+ correlation_id: _this30.correlationId,
3877
4127
  reason: 'unexpected error: transcription LLM web socket connection error had occured.',
3878
4128
  event: event
3879
4129
  });
@@ -3889,7 +4139,7 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
3889
4139
  key: "receiveTranscription",
3890
4140
  value: function () {
3891
4141
  var _receiveTranscription = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2() {
3892
- var _this32 = this;
4142
+ var _this31 = this;
3893
4143
 
3894
4144
  var datachannelUrl, _yield$this$request, webSocketUrl;
3895
4145
 
@@ -3922,7 +4172,7 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
3922
4172
 
3923
4173
 
3924
4174
  this.transcription.subscribe(function (payload) {
3925
- _triggerProxy.default.trigger(_this32, {
4175
+ _triggerProxy.default.trigger(_this31, {
3926
4176
  file: 'meeting/index',
3927
4177
  function: 'join'
3928
4178
  }, _constants.EVENT_TRIGGERS.MEETING_STARTED_RECEIVING_TRANSCRIPTION, payload);
@@ -4004,7 +4254,7 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
4004
4254
  }, {
4005
4255
  key: "join",
4006
4256
  value: function join() {
4007
- var _this33 = this;
4257
+ var _this32 = this;
4008
4258
 
4009
4259
  var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
4010
4260
 
@@ -4113,18 +4363,19 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
4113
4363
  }
4114
4364
  }
4115
4365
 
4366
+ this.isMultistream = !!options.enableMultistream;
4116
4367
  return _util.default.joinMeetingOptions(this, options).then(function (join) {
4117
- _this33.meetingFiniteStateMachine.join();
4368
+ _this32.meetingFiniteStateMachine.join();
4118
4369
 
4119
4370
  _loggerProxy.default.logger.log('Meeting:index#join --> Success');
4120
4371
 
4121
4372
  return join;
4122
4373
  }).then(function (join) {
4123
4374
  joinSuccess(join);
4124
- _this33.deferJoin = undefined;
4375
+ _this32.deferJoin = undefined;
4125
4376
 
4126
4377
  _metrics.default.sendBehavioralMetric(_constants2.default.JOIN_SUCCESS, {
4127
- correlation_id: _this33.correlationId
4378
+ correlation_id: _this32.correlationId
4128
4379
  });
4129
4380
 
4130
4381
  return join;
@@ -4139,18 +4390,18 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
4139
4390
  break;
4140
4391
  }
4141
4392
 
4142
- if (!(_this33.config.receiveTranscription || options.receiveTranscription)) {
4393
+ if (!(_this32.config.receiveTranscription || options.receiveTranscription)) {
4143
4394
  _context3.next = 6;
4144
4395
  break;
4145
4396
  }
4146
4397
 
4147
- if (!_this33.isTranscriptionSupported()) {
4398
+ if (!_this32.isTranscriptionSupported()) {
4148
4399
  _context3.next = 6;
4149
4400
  break;
4150
4401
  }
4151
4402
 
4152
4403
  _context3.next = 5;
4153
- return _this33.receiveTranscription();
4404
+ return _this32.receiveTranscription();
4154
4405
 
4155
4406
  case 5:
4156
4407
  _loggerProxy.default.logger.info('Meeting:index#join --> enabled to recieve transcription!');
@@ -4179,14 +4430,14 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
4179
4430
  }()).catch(function (error) {
4180
4431
  var _error$error;
4181
4432
 
4182
- _this33.meetingFiniteStateMachine.fail(error);
4433
+ _this32.meetingFiniteStateMachine.fail(error);
4183
4434
 
4184
4435
  _loggerProxy.default.logger.error('Meeting:index#join --> Failed', error);
4185
4436
 
4186
4437
  _metrics.default.postEvent({
4187
4438
  event: _config.eventType.LOCUS_JOIN_RESPONSE,
4188
- meeting: _this33,
4189
- meetingId: _this33.id,
4439
+ meeting: _this32,
4440
+ meetingId: _this32.id,
4190
4441
  data: {
4191
4442
  errors: [_metrics.default.parseLocusError(error.error, true)]
4192
4443
  }
@@ -4194,19 +4445,19 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
4194
4445
 
4195
4446
 
4196
4447
  _metrics.default.sendBehavioralMetric(_constants2.default.JOIN_FAILURE, {
4197
- correlation_id: _this33.correlationId,
4448
+ correlation_id: _this32.correlationId,
4198
4449
  reason: (_error$error = error.error) === null || _error$error === void 0 ? void 0 : _error$error.message,
4199
4450
  stack: error.stack
4200
4451
  }); // Upload logs on join Failure
4201
4452
 
4202
4453
 
4203
- _triggerProxy.default.trigger(_this33, {
4454
+ _triggerProxy.default.trigger(_this32, {
4204
4455
  file: 'meeting/index',
4205
4456
  function: 'join'
4206
- }, _constants.EVENTS.REQUEST_UPLOAD_LOGS, _this33);
4457
+ }, _constants.EVENTS.REQUEST_UPLOAD_LOGS, _this32);
4207
4458
 
4208
4459
  joinFailed(error);
4209
- _this33.deferJoin = undefined;
4460
+ _this32.deferJoin = undefined;
4210
4461
  return _promise.default.reject(error);
4211
4462
  });
4212
4463
  }
@@ -4250,7 +4501,7 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
4250
4501
  }, {
4251
4502
  key: "dialInPstn",
4252
4503
  value: function dialInPstn() {
4253
- var _this34 = this;
4504
+ var _this33 = this;
4254
4505
 
4255
4506
  if (this.isPhoneProvisioned(this.dialInDeviceStatus)) return _promise.default.resolve(); // prevent multiple dial in devices from being provisioned
4256
4507
 
@@ -4263,15 +4514,15 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
4263
4514
  locusUrl: locusUrl,
4264
4515
  clientUrl: this.deviceUrl
4265
4516
  }).then(function (res) {
4266
- _this34.locusInfo.onFullLocus(res.body.locus);
4517
+ _this33.locusInfo.onFullLocus(res.body.locus);
4267
4518
  }).catch(function (error) {
4268
4519
  var _error$error2;
4269
4520
 
4270
4521
  _metrics.default.sendBehavioralMetric(_constants2.default.ADD_DIAL_IN_FAILURE, {
4271
- correlation_id: _this34.correlationId,
4272
- dial_in_url: _this34.dialInUrl,
4522
+ correlation_id: _this33.correlationId,
4523
+ dial_in_url: _this33.dialInUrl,
4273
4524
  locus_id: locusUrl.split('/').pop(),
4274
- client_url: _this34.deviceUrl,
4525
+ client_url: _this33.deviceUrl,
4275
4526
  reason: (_error$error2 = error.error) === null || _error$error2 === void 0 ? void 0 : _error$error2.message,
4276
4527
  stack: error.stack
4277
4528
  });
@@ -4290,7 +4541,7 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
4290
4541
  }, {
4291
4542
  key: "dialOutPstn",
4292
4543
  value: function dialOutPstn(phoneNumber) {
4293
- var _this35 = this;
4544
+ var _this34 = this;
4294
4545
 
4295
4546
  if (this.isPhoneProvisioned(this.dialOutDeviceStatus)) return _promise.default.resolve(); // prevent multiple dial out devices from being provisioned
4296
4547
 
@@ -4304,15 +4555,15 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
4304
4555
  locusUrl: locusUrl,
4305
4556
  clientUrl: this.deviceUrl
4306
4557
  }).then(function (res) {
4307
- _this35.locusInfo.onFullLocus(res.body.locus);
4558
+ _this34.locusInfo.onFullLocus(res.body.locus);
4308
4559
  }).catch(function (error) {
4309
4560
  var _error$error3;
4310
4561
 
4311
4562
  _metrics.default.sendBehavioralMetric(_constants2.default.ADD_DIAL_OUT_FAILURE, {
4312
- correlation_id: _this35.correlationId,
4313
- dial_out_url: _this35.dialOutUrl,
4563
+ correlation_id: _this34.correlationId,
4564
+ dial_out_url: _this34.dialOutUrl,
4314
4565
  locus_id: locusUrl.split('/').pop(),
4315
- client_url: _this35.deviceUrl,
4566
+ client_url: _this34.deviceUrl,
4316
4567
  reason: (_error$error3 = error.error) === null || _error$error3 === void 0 ? void 0 : _error$error3.message,
4317
4568
  stack: error.stack
4318
4569
  });
@@ -4344,7 +4595,7 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
4344
4595
  }, {
4345
4596
  key: "moveTo",
4346
4597
  value: function moveTo(resourceId) {
4347
- var _this36 = this;
4598
+ var _this35 = this;
4348
4599
 
4349
4600
  if (!resourceId) {
4350
4601
  throw new _parameter.default('Cannot move call without a resourceId.');
@@ -4386,13 +4637,13 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
4386
4637
  case 0:
4387
4638
  _context4.prev = 0;
4388
4639
 
4389
- if (!_this36.isSharing) {
4640
+ if (!_this35.isSharing) {
4390
4641
  _context4.next = 4;
4391
4642
  break;
4392
4643
  }
4393
4644
 
4394
4645
  _context4.next = 4;
4395
- return _this36.stopFloorRequest();
4646
+ return _this35.stopFloorRequest();
4396
4647
 
4397
4648
  case 4:
4398
4649
  mediaSettings = {
@@ -4406,23 +4657,23 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
4406
4657
  }
4407
4658
  }; // clean up the local tracks
4408
4659
 
4409
- _this36.mediaProperties.setMediaDirection(mediaSettings.mediaDirection); // close the existing local tracks
4660
+ _this35.mediaProperties.setMediaDirection(mediaSettings.mediaDirection); // close the existing local tracks
4410
4661
 
4411
4662
 
4412
4663
  _context4.next = 8;
4413
- return _this36.closeLocalStream();
4664
+ return _this35.closeLocalStream();
4414
4665
 
4415
4666
  case 8:
4416
4667
  _context4.next = 10;
4417
- return _this36.closeLocalShare();
4668
+ return _this35.closeLocalShare();
4418
4669
 
4419
4670
  case 10:
4420
- _this36.mediaProperties.unsetMediaTracks(); // when a move to is intiated by the client , Locus delets the existing media node from the server as soon the DX answers the meeting
4671
+ _this35.mediaProperties.unsetMediaTracks(); // when a move to is intiated by the client , Locus delets the existing media node from the server as soon the DX answers the meeting
4421
4672
  // once the DX answers we establish connection back the media server with only receiveShare enabled
4422
4673
 
4423
4674
 
4424
4675
  _context4.next = 13;
4425
- return _this36.reconnectionManager.reconnectMedia(mediaSettings).then(function () {
4676
+ return _this35.reconnectionManager.reconnectMedia(mediaSettings).then(function () {
4426
4677
  _metrics.default.sendBehavioralMetric(_constants2.default.MOVE_TO_SUCCESS);
4427
4678
  });
4428
4679
 
@@ -4437,8 +4688,8 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
4437
4688
  _loggerProxy.default.logger.error('Meeting:index#moveTo --> Failed to moveTo resourceId', _context4.t0);
4438
4689
 
4439
4690
  _metrics.default.sendBehavioralMetric(_constants2.default.MOVE_TO_FAILURE, {
4440
- correlation_id: _this36.correlationId,
4441
- locus_id: _this36.locusUrl.split('/').pop(),
4691
+ correlation_id: _this35.correlationId,
4692
+ locus_id: _this35.locusUrl.split('/').pop(),
4442
4693
  reason: _context4.t0.message,
4443
4694
  stack: _context4.t0.stack
4444
4695
  });
@@ -4457,13 +4708,13 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
4457
4708
  resourceId: resourceId,
4458
4709
  moveToResource: true
4459
4710
  }).then(function () {
4460
- _this36.meetingFiniteStateMachine.join();
4711
+ _this35.meetingFiniteStateMachine.join();
4461
4712
  }).catch(function (error) {
4462
- _this36.meetingFiniteStateMachine.fail(error);
4713
+ _this35.meetingFiniteStateMachine.fail(error);
4463
4714
 
4464
4715
  _metrics.default.sendBehavioralMetric(_constants2.default.MOVE_TO_FAILURE, {
4465
- correlation_id: _this36.correlationId,
4466
- locus_id: _this36.locusUrl.split('/').pop(),
4716
+ correlation_id: _this35.correlationId,
4717
+ locus_id: _this35.locusUrl.split('/').pop(),
4467
4718
  reason: error.message,
4468
4719
  stack: error.stack
4469
4720
  });
@@ -4484,7 +4735,7 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
4484
4735
  }, {
4485
4736
  key: "moveFrom",
4486
4737
  value: function moveFrom(resourceId) {
4487
- var _this37 = this;
4738
+ var _this36 = this;
4488
4739
 
4489
4740
  // On moveFrom ask the developer to re capture it moveFrom then updateMedia
4490
4741
  if (!resourceId) {
@@ -4499,21 +4750,21 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
4499
4750
  });
4500
4751
 
4501
4752
  return _util.default.joinMeetingOptions(this).then(function () {
4502
- return _util.default.leaveMeeting(_this37, {
4753
+ return _util.default.leaveMeeting(_this36, {
4503
4754
  resourceId: resourceId,
4504
4755
  correlationId: oldCorrelationId,
4505
4756
  moveMeeting: true
4506
4757
  }).then(function () {
4507
- _this37.resourceId = '';
4758
+ _this36.resourceId = '';
4508
4759
 
4509
4760
  _metrics.default.sendBehavioralMetric(_constants2.default.MOVE_FROM_SUCCESS);
4510
4761
  });
4511
4762
  }).catch(function (error) {
4512
- _this37.meetingFiniteStateMachine.fail(error);
4763
+ _this36.meetingFiniteStateMachine.fail(error);
4513
4764
 
4514
4765
  _metrics.default.sendBehavioralMetric(_constants2.default.MOVE_FROM_FAILURE, {
4515
- correlation_id: _this37.correlationId,
4516
- locus_id: _this37.locusUrl.split('/').pop(),
4766
+ correlation_id: _this36.correlationId,
4767
+ locus_id: _this36.locusUrl.split('/').pop(),
4517
4768
  reason: error.message,
4518
4769
  stack: error.stack
4519
4770
  });
@@ -4525,6 +4776,9 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
4525
4776
  }
4526
4777
  /**
4527
4778
  * Get local media streams based on options passed
4779
+ *
4780
+ * NOTE: this method can only be used with transcoded meetings, not with multistream meetings
4781
+ *
4528
4782
  * @param {MediaDirection} mediaDirection A configurable options object for joining a meeting
4529
4783
  * @param {AudioVideo} [audioVideo] audio/video object to set audioinput and videoinput devices, see #Media.getUserMedia
4530
4784
  * @param {SharePreferences} [sharePreferences] audio/video object to set audioinput and videoinput devices, see #Media.getUserMedia
@@ -4535,8 +4789,43 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
4535
4789
  */
4536
4790
 
4537
4791
  }, {
4538
- key: "addMedia",
4539
- value:
4792
+ key: "createMediaConnection",
4793
+ value: function createMediaConnection(turnServerInfo) {
4794
+ var mc = _media.default.createMediaConnection(this.mediaProperties, {
4795
+ isMultistream: this.isMultistream,
4796
+ meetingId: this.id,
4797
+ remoteQualityLevel: this.mediaProperties.remoteQualityLevel,
4798
+ enableRtx: this.config.enableRtx,
4799
+ enableExtmap: this.config.enableExtmap,
4800
+ turnServerInfo: turnServerInfo
4801
+ });
4802
+
4803
+ this.mediaProperties.setMediaPeerConnection(mc);
4804
+ this.setupMediaConnectionListeners();
4805
+ return mc;
4806
+ }
4807
+ /**
4808
+ * Listens for an event emitted by eventEmitter and emits it from the meeting object
4809
+ *
4810
+ * @private
4811
+ * @param {*} eventEmitter object from which to forward the event
4812
+ * @param {*} eventTypeToForward which event type to listen on and to forward
4813
+ * @param {string} meetingEventType event type to be used in the event emitted from the meeting object
4814
+ * @returns {void}
4815
+ */
4816
+
4817
+ }, {
4818
+ key: "forwardEvent",
4819
+ value: function forwardEvent(eventEmitter, eventTypeToForward, meetingEventType) {
4820
+ var _this37 = this;
4821
+
4822
+ eventEmitter.on(eventTypeToForward, function (data) {
4823
+ return _triggerProxy.default.trigger(_this37, {
4824
+ file: 'meetings',
4825
+ function: 'addMedia'
4826
+ }, meetingEventType, data);
4827
+ });
4828
+ }
4540
4829
  /**
4541
4830
  * Specify joining via audio (option: pstn), video, screenshare
4542
4831
  * @param {Object} options A configurable options object for joining a meeting
@@ -4544,11 +4833,15 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
4544
4833
  * @param {MediaDirection} options.mediaSettings pass media options
4545
4834
  * @param {MediaStream} options.localStream
4546
4835
  * @param {MediaStream} options.localShare
4836
+ * @param {RemoteMediaManagerConfig} options.remoteMediaManagerConfig only applies if multistream is enabled
4547
4837
  * @returns {Promise}
4548
4838
  * @public
4549
4839
  * @memberof Meeting
4550
4840
  */
4551
- function addMedia() {
4841
+
4842
+ }, {
4843
+ key: "addMedia",
4844
+ value: function addMedia() {
4552
4845
  var _this38 = this;
4553
4846
 
4554
4847
  var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
@@ -4571,7 +4864,8 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
4571
4864
 
4572
4865
  var localStream = options.localStream,
4573
4866
  localShare = options.localShare,
4574
- mediaSettings = options.mediaSettings;
4867
+ mediaSettings = options.mediaSettings,
4868
+ remoteMediaManagerConfig = options.remoteMediaManagerConfig;
4575
4869
 
4576
4870
  _loggerProxy.default.logger.info("".concat(LOG_HEADER, " Adding Media."));
4577
4871
 
@@ -4605,36 +4899,37 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
4605
4899
  turnServerUsed = !turnDiscoverySkippedReason;
4606
4900
  var turnServerInfo = turnDiscoveryObject.turnServerInfo;
4607
4901
 
4608
- _this38.mediaProperties.setMediaPeerConnection(_util2.default.createPeerConnection(turnServerInfo));
4902
+ _this38.preMedia(localStream, localShare, mediaSettings);
4609
4903
 
4610
- _this38.setMercuryListener();
4904
+ var mc = _this38.createMediaConnection(turnServerInfo);
4611
4905
 
4612
- _peerConnectionManager.default.setPeerConnectionEvents(_this38);
4906
+ if (_this38.isMultistream) {
4907
+ _this38.remoteMediaManager = new _remoteMediaManager.RemoteMediaManager(_this38.receiveSlotManager, _this38.mediaRequestManagers, remoteMediaManagerConfig);
4613
4908
 
4614
- return _this38.preMedia(localStream, localShare, mediaSettings);
4909
+ _this38.forwardEvent(_this38.remoteMediaManager, _remoteMediaManager.Event.AudioCreated, _constants.EVENT_TRIGGERS.REMOTE_MEDIA_AUDIO_CREATED);
4910
+
4911
+ _this38.forwardEvent(_this38.remoteMediaManager, _remoteMediaManager.Event.ScreenShareAudioCreated, _constants.EVENT_TRIGGERS.REMOTE_MEDIA_SCREEN_SHARE_AUDIO_CREATED);
4912
+
4913
+ _this38.forwardEvent(_this38.remoteMediaManager, _remoteMediaManager.Event.VideoLayoutChanged, _constants.EVENT_TRIGGERS.REMOTE_MEDIA_VIDEO_LAYOUT_CHANGED);
4914
+
4915
+ return _this38.remoteMediaManager.start().then(function () {
4916
+ return mc.initiateOffer();
4917
+ });
4918
+ }
4919
+
4920
+ return mc.initiateOffer();
4921
+ }).then(function () {
4922
+ _this38.setMercuryListener();
4615
4923
  }).then(function () {
4616
- return _media.default.attachMedia(_this38.mediaProperties, {
4617
- meetingId: _this38.id,
4618
- remoteQualityLevel: _this38.mediaProperties.remoteQualityLevel,
4619
- enableRtx: _this38.config.enableRtx,
4620
- enableExtmap: _this38.config.enableExtmap,
4621
- setStartLocalSDPGenRemoteSDPRecvDelay: _this38.setStartLocalSDPGenRemoteSDPRecvDelay.bind(_this38)
4622
- });
4623
- }).then(function (peerConnection) {
4624
4924
  return _this38.getDevices().then(function (devices) {
4625
4925
  _util.default.handleDeviceLogging(devices);
4626
-
4627
- return peerConnection;
4628
4926
  });
4629
- }).then(function (peerConnection) {
4927
+ }).then(function () {
4630
4928
  _this38.handleMediaLogging(_this38.mediaProperties);
4631
4929
 
4632
- _loggerProxy.default.logger.info("".concat(LOG_HEADER, " PeerConnection Received from attachMedia "));
4633
-
4634
- _this38.setRemoteStream(peerConnection);
4930
+ _loggerProxy.default.logger.info("".concat(LOG_HEADER, " media connection created"));
4635
4931
 
4636
4932
  if (_this38.config.stats.enableStatsAnalyzer) {
4637
- // TODO: ** Dont re create StatsAnalyzer on reconnect or rejoin
4638
4933
  _this38.networkQualityMonitor = new _networkQualityMonitor.default(_this38.config.stats);
4639
4934
  _this38.statsAnalyzer = new _statsAnalyzer.StatsAnalyzer(_this38.config.stats, _this38.networkQualityMonitor);
4640
4935
 
@@ -4645,15 +4940,6 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
4645
4940
  }).catch(function (error) {
4646
4941
  _loggerProxy.default.logger.error("".concat(LOG_HEADER, " Error adding media , setting up peerconnection, "), error);
4647
4942
 
4648
- _metrics.default.sendBehavioralMetric(_constants2.default.ADD_MEDIA_FAILURE, {
4649
- correlation_id: _this38.correlationId,
4650
- locus_id: _this38.locusUrl.split('/').pop(),
4651
- reason: error.message,
4652
- stack: error.stack,
4653
- turnDiscoverySkippedReason: turnDiscoverySkippedReason,
4654
- turnServerUsed: turnServerUsed
4655
- });
4656
-
4657
4943
  throw error;
4658
4944
  }).then(function () {
4659
4945
  return new _promise.default(function (resolve, reject) {
@@ -4679,18 +4965,7 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
4679
4965
  }, 1000);
4680
4966
  });
4681
4967
  }).then(function () {
4682
- return logRequest(_this38.roap.sendRoapMediaRequest({
4683
- sdp: _this38.mediaProperties.peerConnection.sdp,
4684
- roapSeq: _this38.roapSeq,
4685
- meeting: _this38 // or can pass meeting ID
4686
-
4687
- }), {
4688
- header: "".concat(LOG_HEADER, " Send Roap Media Request."),
4689
- success: "".concat(LOG_HEADER, " Successfully send roap media request"),
4690
- failure: "".concat(LOG_HEADER, " Error joining the call on send roap media request, ")
4691
- });
4692
- }).then(function () {
4693
- return _this38.mediaProperties.waitForIceConnectedState().catch(function () {
4968
+ return _this38.mediaProperties.waitForMediaConnectionConnected().catch(function () {
4694
4969
  throw (0, _webexErrors.createMeetingsError)(30202, 'Meeting connection failed');
4695
4970
  });
4696
4971
  }).then(function () {
@@ -4720,7 +4995,7 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
4720
4995
  return stopStatsAnalyzer.then(function () {
4721
4996
  _this38.statsAnalyzer = null;
4722
4997
 
4723
- if (_this38.mediaProperties.peerConnection) {
4998
+ if (_this38.mediaProperties.webrtcMediaConnection) {
4724
4999
  _this38.closePeerConnections();
4725
5000
 
4726
5001
  _this38.unsetPeerConnections();
@@ -4742,12 +5017,9 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
4742
5017
  _triggerProxy.default.trigger(_this38, {
4743
5018
  file: 'meeting/index',
4744
5019
  function: 'addMedia'
4745
- }, _constants.EVENTS.REQUEST_UPLOAD_LOGS, _this38); // If addMedia failes for not establishing connection then
4746
- // leave the meeting with reson connection failed as meeting anyways will end
4747
- // and cannot be connected unless network condition is checked for firewall
4748
-
5020
+ }, _constants.EVENTS.REQUEST_UPLOAD_LOGS, _this38);
4749
5021
 
4750
- if (error.code === _webexErrors.InvalidSdpError.CODE) {
5022
+ if (error instanceof _internalMediaCore.MediaConnection.Errors.SdpError) {
4751
5023
  _this38.leave({
4752
5024
  reason: _constants.MEETING_REMOVED_REASON.MEETING_CONNECTION_FAILED
4753
5025
  });
@@ -4765,7 +5037,10 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
4765
5037
  }, {
4766
5038
  key: "canUpdateMedia",
4767
5039
  value: function canUpdateMedia() {
4768
- return this.mediaProperties.peerConnection.signalingState === _constants.SDP.STABLE && !_collection.default.isBusy(this.correlationId);
5040
+ // in theory we shouldn't need this as RoapMediaConnection handles multiple updates, glare, etc,
5041
+ // but there are some server issues, like https://jira-eng-gpk2.cisco.com/jira/browse/WEBEX-248394
5042
+ // so for now it's better to keep queuing any media updates at SDK meeting level
5043
+ return !this.isRoapInProgress;
4769
5044
  }
4770
5045
  /**
4771
5046
  * Enqueues a media update operation.
@@ -4812,7 +5087,6 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
4812
5087
  * @param {MediaStream} options.localShare
4813
5088
  * @param {MediaDirection} options.mediaSettings
4814
5089
  * @returns {Promise}
4815
- * @todo fix setRemoteStream for updateMedia
4816
5090
  * @public
4817
5091
  * @memberof Meeting
4818
5092
  */
@@ -4830,22 +5104,28 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
4830
5104
  localShare = options.localShare,
4831
5105
  mediaSettings = options.mediaSettings;
4832
5106
  var previousSendShareStatus = this.mediaProperties.mediaDirection.sendShare;
5107
+
5108
+ if (!this.mediaProperties.webrtcMediaConnection) {
5109
+ return _promise.default.reject(new Error('media connection not established, call addMedia() first'));
5110
+ }
5111
+
4833
5112
  return _util.default.validateOptions(options).then(function () {
4834
5113
  return _this40.preMedia(localStream, localShare, mediaSettings);
4835
5114
  }).then(function () {
4836
- return _media.default.updateMedia(_this40.mediaProperties, {
4837
- meetingId: _this40.id,
4838
- remoteQualityLevel: _this40.mediaProperties.remoteQualityLevel,
4839
- enableRtx: _this40.config.enableRtx,
4840
- enableExtmap: _this40.config.enableExtmap
4841
- }).then(function (peerConnection) {
4842
- _loggerProxy.default.logger.info("".concat(LOG_HEADER, " PeerConnection received from updateMedia, ").concat(peerConnection));
4843
-
4844
- _this40.setRemoteStream(peerConnection);
4845
-
4846
- if (mediaSettings.receiveShare || localShare) {
4847
- _peerConnectionManager.default.setContentSlides(peerConnection);
5115
+ return _this40.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions({
5116
+ send: {
5117
+ audio: _this40.mediaProperties.mediaDirection.sendAudio ? _this40.mediaProperties.audioTrack : null,
5118
+ video: _this40.mediaProperties.mediaDirection.sendVideo ? _this40.mediaProperties.videoTrack : null,
5119
+ screenShareVideo: _this40.mediaProperties.mediaDirection.sendShare ? _this40.mediaProperties.shareTrack : null
5120
+ },
5121
+ receive: {
5122
+ audio: _this40.mediaProperties.mediaDirection.receiveAudio,
5123
+ video: _this40.mediaProperties.mediaDirection.receiveVideo,
5124
+ screenShareVideo: _this40.mediaProperties.mediaDirection.receiveShare,
5125
+ remoteQualityLevel: _this40.mediaProperties.remoteQualityLevel
4848
5126
  }
5127
+ }).then(function () {
5128
+ _loggerProxy.default.logger.info("".concat(LOG_HEADER, " webrtcMediaConnection.updateSendReceiveOptions done"));
4849
5129
  }).catch(function (error) {
4850
5130
  _loggerProxy.default.logger.error("".concat(LOG_HEADER, " Error updatedMedia, "), error);
4851
5131
 
@@ -4857,18 +5137,11 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
4857
5137
  });
4858
5138
 
4859
5139
  throw error;
4860
- }).then(function () {
4861
- return logRequest(_this40.roap.sendRoapMediaRequest({
4862
- sdp: _this40.mediaProperties.peerConnection.sdp,
4863
- roapSeq: _this40.roapSeq,
4864
- meeting: _this40 // or can pass meeting ID
4865
-
4866
- }), {
4867
- header: "".concat(LOG_HEADER, " sendRoapMediaRequest being sent"),
4868
- success: "".concat(LOG_HEADER, " sendRoadMediaRequest successful"),
4869
- failure: "".concat(LOG_HEADER, " Error updateMedia on send roap media request, ")
4870
- });
4871
- }).then(function () {
5140
+ }) // todo: the following code used to be called always after sending the roap message with the new SDP
5141
+ // now it's called independently from the roap message (so might be before it), check if that's OK
5142
+ // if not, ensure it's called after (now it's called after roap message is sent out, but we're not
5143
+ // waiting for sendRoapMediaRequest() to be resolved)
5144
+ .then(function () {
4872
5145
  return _this40.checkForStopShare(mediaSettings.sendShare, previousSendShareStatus);
4873
5146
  }).then(function (startShare) {
4874
5147
  // This is a special case if we do an /floor grant followed by /media
@@ -4884,6 +5157,9 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
4884
5157
  }
4885
5158
  /**
4886
5159
  * Update the main audio track with new parameters
5160
+ *
5161
+ * NOTE: this method can only be used with transcoded meetings, for multistream meetings use publishTrack()
5162
+ *
4887
5163
  * @param {Object} options
4888
5164
  * @param {boolean} options.sendAudio
4889
5165
  * @param {boolean} options.receiveAudio
@@ -4899,7 +5175,7 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
4899
5175
  var _updateAudio = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee5(options) {
4900
5176
  var _this41 = this;
4901
5177
 
4902
- var sendAudio, receiveAudio, stream, audioTransceiver, track, bnrEnabled;
5178
+ var sendAudio, receiveAudio, stream, track, bnrEnabled;
4903
5179
  return _regenerator.default.wrap(function _callee5$(_context5) {
4904
5180
  while (1) {
4905
5181
  switch (_context5.prev = _context5.next) {
@@ -4913,70 +5189,65 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
4913
5189
 
4914
5190
  case 2:
4915
5191
  sendAudio = options.sendAudio, receiveAudio = options.receiveAudio, stream = options.stream;
4916
- audioTransceiver = this.mediaProperties.peerConnection.audioTransceiver;
4917
5192
  track = _util.default.getTrack(stream).audioTrack;
4918
5193
 
4919
5194
  if (!(typeof sendAudio !== 'boolean' || typeof receiveAudio !== 'boolean')) {
4920
- _context5.next = 7;
5195
+ _context5.next = 6;
4921
5196
  break;
4922
5197
  }
4923
5198
 
4924
5199
  return _context5.abrupt("return", _promise.default.reject(new _parameter.default('Pass sendAudio and receiveAudio parameter')));
4925
5200
 
4926
- case 7:
5201
+ case 6:
5202
+ if (this.mediaProperties.webrtcMediaConnection) {
5203
+ _context5.next = 8;
5204
+ break;
5205
+ }
5206
+
5207
+ return _context5.abrupt("return", _promise.default.reject(new Error('media connection not established, call addMedia() first')));
5208
+
5209
+ case 8:
4927
5210
  if (!(this.effects && this.effects.state)) {
4928
- _context5.next = 15;
5211
+ _context5.next = 16;
4929
5212
  break;
4930
5213
  }
4931
5214
 
4932
5215
  bnrEnabled = this.effects.state.bnr.enabled;
4933
5216
 
4934
5217
  if (!(sendAudio && !this.isAudioMuted() && (bnrEnabled === _constants.BNR_STATUS.ENABLED || bnrEnabled === _constants.BNR_STATUS.SHOULD_ENABLE))) {
4935
- _context5.next = 15;
5218
+ _context5.next = 16;
4936
5219
  break;
4937
5220
  }
4938
5221
 
4939
5222
  _loggerProxy.default.logger.info('Meeting:index#updateAudio. Calling WebRTC enable bnr method');
4940
5223
 
4941
- _context5.next = 13;
5224
+ _context5.next = 14;
4942
5225
  return this.internal_enableBNR(track);
4943
5226
 
4944
- case 13:
5227
+ case 14:
4945
5228
  track = _context5.sent;
4946
5229
 
4947
5230
  _loggerProxy.default.logger.info('Meeting:index#updateAudio. WebRTC enable bnr request completed');
4948
5231
 
4949
- case 15:
5232
+ case 16:
4950
5233
  return _context5.abrupt("return", _util.default.validateOptions({
4951
5234
  sendAudio: sendAudio,
4952
5235
  localStream: stream
4953
5236
  }).then(function () {
4954
- var previousMediaDirection = {};
4955
-
4956
- if (_this41.mediaProperties.mediaDirection) {
4957
- previousMediaDirection = {
4958
- sendTrack: _this41.mediaProperties.mediaDirection.sendAudio,
4959
- receiveTrack: _this41.mediaProperties.mediaDirection.receiveAudio
4960
- };
4961
- } else {
4962
- _this41.mediaProperties.mediaDirection = {};
4963
- }
4964
-
4965
- return _util.default.updateTransceiver({
4966
- type: 'audio',
4967
- sendTrack: options.sendAudio,
4968
- receiveTrack: options.receiveAudio,
4969
- track: track,
4970
- transceiver: audioTransceiver,
4971
- peerConnection: _this41.mediaProperties.peerConnection,
4972
- previousMediaDirection: previousMediaDirection
4973
- }, {
4974
- mediaProperties: _this41.mediaProperties,
4975
- meeting: _this41,
4976
- id: _this41.id
5237
+ return _this41.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions({
5238
+ send: {
5239
+ audio: track
5240
+ },
5241
+ receive: {
5242
+ audio: options.receiveAudio,
5243
+ video: _this41.mediaProperties.mediaDirection.receiveVideo,
5244
+ screenShareVideo: _this41.mediaProperties.mediaDirection.receiveShare,
5245
+ remoteQualityLevel: _this41.mediaProperties.remoteQualityLevel
5246
+ }
4977
5247
  });
4978
5248
  }).then(function () {
4979
- _this41.setLocalAudioTrack(track);
5249
+ _this41.setLocalAudioTrack(track); // todo: maybe this.mediaProperties.mediaDirection could be removed? it's duplicating stuff from webrtcMediaConnection
5250
+
4980
5251
 
4981
5252
  _this41.mediaProperties.mediaDirection.sendAudio = sendAudio;
4982
5253
  _this41.mediaProperties.mediaDirection.receiveAudio = receiveAudio; // audio state could be undefined if you have not sent audio before
@@ -4984,7 +5255,7 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
4984
5255
  _this41.audio = _this41.audio || (0, _muteState.default)(_constants.AUDIO, _this41, _this41.mediaProperties.mediaDirection);
4985
5256
  }));
4986
5257
 
4987
- case 16:
5258
+ case 17:
4988
5259
  case "end":
4989
5260
  return _context5.stop();
4990
5261
  }
@@ -5000,6 +5271,9 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
5000
5271
  }()
5001
5272
  /**
5002
5273
  * Update the main video track with new parameters
5274
+ *
5275
+ * NOTE: this method can only be used with transcoded meetings, for multistream meetings use publishTrack()
5276
+ *
5003
5277
  * @param {Object} options
5004
5278
  * @param {boolean} options.sendVideo
5005
5279
  * @param {boolean} options.receiveVideo
@@ -5021,7 +5295,6 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
5021
5295
  var sendVideo = options.sendVideo,
5022
5296
  receiveVideo = options.receiveVideo,
5023
5297
  stream = options.stream;
5024
- var videoTransceiver = this.mediaProperties.peerConnection.videoTransceiver;
5025
5298
 
5026
5299
  var track = _util.default.getTrack(stream).videoTrack;
5027
5300
 
@@ -5029,25 +5302,24 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
5029
5302
  return _promise.default.reject(new _parameter.default('Pass sendVideo and receiveVideo parameter'));
5030
5303
  }
5031
5304
 
5305
+ if (!this.mediaProperties.webrtcMediaConnection) {
5306
+ return _promise.default.reject(new Error('media connection not established, call addMedia() first'));
5307
+ }
5308
+
5032
5309
  return _util.default.validateOptions({
5033
5310
  sendVideo: sendVideo,
5034
5311
  localStream: stream
5035
5312
  }).then(function () {
5036
- return _util.default.updateTransceiver({
5037
- type: 'video',
5038
- sendTrack: options.sendVideo,
5039
- receiveTrack: options.receiveVideo,
5040
- track: track,
5041
- transceiver: videoTransceiver,
5042
- peerConnection: _this42.mediaProperties.peerConnection,
5043
- previousMediaDirection: {
5044
- sendTrack: _this42.mediaProperties.mediaDirection.sendVideo,
5045
- receiveTrack: _this42.mediaProperties.mediaDirection.receiveVideo
5313
+ return _this42.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions({
5314
+ send: {
5315
+ video: track
5316
+ },
5317
+ receive: {
5318
+ audio: _this42.mediaProperties.mediaDirection.receiveAudio,
5319
+ video: options.receiveVideo,
5320
+ screenShareVideo: _this42.mediaProperties.mediaDirection.receiveShare,
5321
+ remoteQualityLevel: _this42.mediaProperties.remoteQualityLevel
5046
5322
  }
5047
- }, {
5048
- mediaProperties: _this42.mediaProperties,
5049
- meeting: _this42,
5050
- id: _this42.id
5051
5323
  });
5052
5324
  }).then(function () {
5053
5325
  _this42.setLocalVideoTrack(track);
@@ -5086,6 +5358,9 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
5086
5358
  }
5087
5359
  /**
5088
5360
  * Update the share streams, can be used to start sharing
5361
+ *
5362
+ * NOTE: this method can only be used with transcoded meetings, for multistream meetings use publishTrack()
5363
+ *
5089
5364
  * @param {Object} options
5090
5365
  * @param {boolean} options.sendShare
5091
5366
  * @param {boolean} options.receiveShare
@@ -5106,7 +5381,6 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
5106
5381
  var sendShare = options.sendShare,
5107
5382
  receiveShare = options.receiveShare,
5108
5383
  stream = options.stream;
5109
- var shareTransceiver = this.mediaProperties.peerConnection.shareTransceiver;
5110
5384
 
5111
5385
  var track = _util.default.getTrack(stream).videoTrack;
5112
5386
 
@@ -5114,6 +5388,10 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
5114
5388
  return _promise.default.reject(new _parameter.default('Pass sendShare and receiveShare parameter'));
5115
5389
  }
5116
5390
 
5391
+ if (!this.mediaProperties.webrtcMediaConnection) {
5392
+ return _promise.default.reject(new Error('media connection not established, call addMedia() first'));
5393
+ }
5394
+
5117
5395
  var previousSendShareStatus = this.mediaProperties.mediaDirection.sendShare;
5118
5396
  this.setLocalShareTrack(stream);
5119
5397
  return _util.default.validateOptions({
@@ -5122,21 +5400,16 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
5122
5400
  }).then(function () {
5123
5401
  return _this43.checkForStopShare(sendShare, previousSendShareStatus);
5124
5402
  }).then(function (startShare) {
5125
- return _util.default.updateTransceiver({
5126
- type: 'video',
5127
- sendTrack: sendShare,
5128
- receiveTrack: receiveShare,
5129
- track: track,
5130
- transceiver: shareTransceiver,
5131
- peerConnection: _this43.mediaProperties.peerConnection,
5132
- previousMediaDirection: {
5133
- sendTrack: _this43.mediaProperties.mediaDirection.sendShare,
5134
- receiveTrack: _this43.mediaProperties.mediaDirection.receiveShare
5403
+ return _this43.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions({
5404
+ send: {
5405
+ screenShareVideo: track
5406
+ },
5407
+ receive: {
5408
+ audio: _this43.mediaProperties.mediaDirection.receiveAudio,
5409
+ video: _this43.mediaProperties.mediaDirection.receiveVideo,
5410
+ screenShareVideo: options.receiveShare,
5411
+ remoteQualityLevel: _this43.mediaProperties.remoteQualityLevel
5135
5412
  }
5136
- }, {
5137
- mediaProperties: _this43.mediaProperties,
5138
- meeting: _this43,
5139
- id: _this43.id
5140
5413
  }).then(function () {
5141
5414
  if (startShare) {
5142
5415
  return _this43.share();
@@ -5151,20 +5424,6 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
5151
5424
  _this43.unsetLocalShareTrack(stream);
5152
5425
 
5153
5426
  throw error;
5154
- }).finally(function () {
5155
- var delay = 1e3; // Check to see if share was stopped natively before onended was assigned.
5156
-
5157
- var sharingModeIsActive = _this43.mediaProperties.peerConnection.shareTransceiver.direction === _constants.SENDRECV;
5158
- var isSharingOutOfSync = sharingModeIsActive && !_this43.isLocalShareLive;
5159
-
5160
- if (isSharingOutOfSync) {
5161
- // Adding a delay to avoid a 409 from server
5162
- // which results in user still appearing as if sharing.
5163
- // Also delay give time for changes to peerConnection.
5164
- setTimeout(function () {
5165
- return _this43.handleShareTrackEnded(stream);
5166
- }, delay);
5167
- }
5168
5427
  });
5169
5428
  }
5170
5429
  /**
@@ -5934,6 +6193,9 @@ var Meeting = /*#__PURE__*/function (_StatelessWebexPlugin) {
5934
6193
  });
5935
6194
  }
5936
6195
  /**
6196
+ *
6197
+ * NOTE: this method can only be used with transcoded meetings, for multistream use publishTrack()
6198
+ *
5937
6199
  * @param {Object} options parameter
5938
6200
  * @param {Boolean} options.sendAudio send audio from the display share
5939
6201
  * @param {Boolean} options.sendShare send video from the display share