@techsee/techsee-media-service 0.21.2 → 0.22.0-alphagb2

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 (97) hide show
  1. package/lib/LocalStreamManager.js +435 -317
  2. package/lib/LocalStreamManager.js.map +1 -1
  3. package/lib/MediaConstants.js +72 -44
  4. package/lib/MediaConstants.js.map +1 -1
  5. package/lib/MediaContracts.js +3 -3
  6. package/lib/MediaContracts.js.map +1 -1
  7. package/lib/MediaPublisher.js +45 -35
  8. package/lib/MediaPublisher.js.map +1 -1
  9. package/lib/MediaServiceBase.js +922 -706
  10. package/lib/MediaServiceBase.js.map +1 -1
  11. package/lib/MediaSession/MediaServer.js +512 -379
  12. package/lib/MediaSession/MediaServer.js.map +1 -1
  13. package/lib/MediaSession/MediaSessionBase.js +123 -88
  14. package/lib/MediaSession/MediaSessionBase.js.map +1 -1
  15. package/lib/MediaSession/SessionOpentok.js +499 -384
  16. package/lib/MediaSession/SessionOpentok.js.map +1 -1
  17. package/lib/MediaSession/SessionTurn.js +606 -466
  18. package/lib/MediaSession/SessionTurn.js.map +1 -1
  19. package/lib/MediaSession/TurnConstants.js +30 -30
  20. package/lib/MediaSession/TurnConstants.js.map +1 -1
  21. package/lib/MediaSubscriber.js +235 -192
  22. package/lib/MediaSubscriber.js.map +1 -1
  23. package/lib/MediaUtils/Compatibility.js +127 -90
  24. package/lib/MediaUtils/Compatibility.js.map +1 -1
  25. package/lib/MediaUtils/MediaDomUtils.js +230 -179
  26. package/lib/MediaUtils/MediaDomUtils.js.map +1 -1
  27. package/lib/MediaUtils/MediaTracer.js +8 -4
  28. package/lib/MediaUtils/MediaTracer.js.map +1 -1
  29. package/lib/MultiParty/Contracts.js +3 -3
  30. package/lib/MultiParty/Contracts.js.map +1 -1
  31. package/lib/MultiParty/DetectWebRtcService.js +66 -50
  32. package/lib/MultiParty/DetectWebRtcService.js.map +1 -1
  33. package/lib/MultiParty/MediaCapabilitiesHelper.js +258 -154
  34. package/lib/MultiParty/MediaCapabilitiesHelper.js.map +1 -1
  35. package/lib/MultiParty/MultiParty.d.ts +1 -8
  36. package/lib/MultiParty/MultiParty.d.ts.map +1 -1
  37. package/lib/MultiParty/MultiParty.js +221 -128
  38. package/lib/MultiParty/MultiParty.js.map +1 -1
  39. package/lib/MultiParty/MultipartyFactory.d.ts +1 -2
  40. package/lib/MultiParty/MultipartyFactory.d.ts.map +1 -1
  41. package/lib/MultiParty/MultipartyFactory.js +12 -7
  42. package/lib/MultiParty/MultipartyFactory.js.map +1 -1
  43. package/lib/MultiParty/OpentokMultiparty.js +611 -384
  44. package/lib/MultiParty/OpentokMultiparty.js.map +1 -1
  45. package/lib/TechseeMediaStream.js +58 -53
  46. package/lib/TechseeMediaStream.js.map +1 -1
  47. package/lib/oldCode/constants.js +20 -15
  48. package/lib/oldCode/constants.js.map +1 -1
  49. package/lib/oldCode/event-emitter.js +45 -22
  50. package/lib/oldCode/event-emitter.js.map +1 -1
  51. package/lib/oldCode/index.js +48 -52
  52. package/lib/oldCode/index.js.map +1 -1
  53. package/lib/oldCode/opentok/session.js +261 -236
  54. package/lib/oldCode/opentok/session.js.map +1 -1
  55. package/lib/oldCode/opentok/stream.js +283 -269
  56. package/lib/oldCode/opentok/stream.js.map +1 -1
  57. package/lib/oldCode/publisher.js +96 -71
  58. package/lib/oldCode/publisher.js.map +1 -1
  59. package/lib/oldCode/service.js +294 -272
  60. package/lib/oldCode/service.js.map +1 -1
  61. package/lib/oldCode/session.js +82 -60
  62. package/lib/oldCode/session.js.map +1 -1
  63. package/lib/oldCode/stream.js +153 -125
  64. package/lib/oldCode/stream.js.map +1 -1
  65. package/lib/oldCode/subscriber.js +60 -35
  66. package/lib/oldCode/subscriber.js.map +1 -1
  67. package/lib/oldCode/tracer.js +179 -138
  68. package/lib/oldCode/tracer.js.map +1 -1
  69. package/lib/oldCode/utils/ImageFixer.js +66 -44
  70. package/lib/oldCode/utils/ImageFixer.js.map +1 -1
  71. package/lib/oldCode/webrtc/constants.js +102 -110
  72. package/lib/oldCode/webrtc/constants.js.map +1 -1
  73. package/lib/oldCode/webrtc/helper.js +176 -124
  74. package/lib/oldCode/webrtc/helper.js.map +1 -1
  75. package/lib/oldCode/webrtc/session-kms.js +408 -393
  76. package/lib/oldCode/webrtc/session-kms.js.map +1 -1
  77. package/lib/oldCode/webrtc/session-loopback.js +245 -227
  78. package/lib/oldCode/webrtc/session-loopback.js.map +1 -1
  79. package/lib/oldCode/webrtc/session-turn.js +705 -658
  80. package/lib/oldCode/webrtc/session-turn.js.map +1 -1
  81. package/lib/oldCode/webrtc/session-turn.v2.js +480 -471
  82. package/lib/oldCode/webrtc/session-turn.v2.js.map +1 -1
  83. package/lib/oldCode/webrtc/session.js +12 -6
  84. package/lib/oldCode/webrtc/session.js.map +1 -1
  85. package/lib/oldCode/webrtc/stream.js +526 -504
  86. package/lib/oldCode/webrtc/stream.js.map +1 -1
  87. package/lib/oldCode/webrtc/temasys/adapter-loader.js +5 -6
  88. package/lib/oldCode/webrtc/temasys/adapter-loader.js.map +1 -1
  89. package/lib/oldCode/webrtc/temasys/adapter.js +5264 -5192
  90. package/lib/oldCode/webrtc/temasys/adapter.js.map +1 -1
  91. package/lib/oldCode/webrtc/webrtc-ie-shim.js +3357 -2927
  92. package/lib/oldCode/webrtc/webrtc-ie-shim.js.map +1 -1
  93. package/lib/qos/raw-qos.js +348 -274
  94. package/lib/qos/raw-qos.js.map +1 -1
  95. package/lib/webrtc-ie-shim.js +3386 -2985
  96. package/lib/webrtc-ie-shim.js.map +1 -1
  97. package/package.json +12 -15
@@ -1,758 +1,974 @@
1
1
  "use strict";
2
2
 
3
- var __assign = undefined && undefined.__assign || function () {
4
- __assign = Object.assign || function (t) {
5
- for (var s, i = 1, n = arguments.length; i < n; i++) {
6
- s = arguments[i];
7
- for (var p in s) {
8
- if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
9
- }
10
- }
11
- return t;
12
- };
13
- return __assign.apply(this, arguments);
3
+ var __assign = void 0 && (void 0).__assign || function () {
4
+ __assign = Object.assign || function (t) {
5
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
6
+ s = arguments[i];
7
+
8
+ for (var p in s) {
9
+ if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
10
+ }
11
+ }
12
+
13
+ return t;
14
+ };
15
+
16
+ return __assign.apply(this, arguments);
14
17
  };
15
- var __importDefault = undefined && undefined.__importDefault || function (mod) {
16
- return mod && mod.__esModule ? mod : { "default": mod };
18
+
19
+ var __importDefault = void 0 && (void 0).__importDefault || function (mod) {
20
+ return mod && mod.__esModule ? mod : {
21
+ "default": mod
22
+ };
17
23
  };
18
- Object.defineProperty(exports, "__esModule", { value: true });
24
+
25
+ Object.defineProperty(exports, "__esModule", {
26
+ value: true
27
+ });
19
28
  exports.TechseeMediaServiceBase = void 0;
29
+
20
30
  var filter_1 = __importDefault(require("lodash/filter"));
31
+
21
32
  var cloneDeep_1 = __importDefault(require("lodash/cloneDeep"));
33
+
22
34
  var values_1 = __importDefault(require("lodash/values"));
35
+
23
36
  var debounce_1 = __importDefault(require("lodash/debounce"));
37
+
24
38
  var includes_1 = __importDefault(require("lodash/includes"));
39
+
25
40
  var events_1 = require("events");
41
+
26
42
  var MediaSubscriber_1 = require("./MediaSubscriber");
43
+
27
44
  var LocalStreamManager_1 = require("./LocalStreamManager");
45
+
28
46
  var TechseeMediaStream_1 = require("./TechseeMediaStream");
47
+
29
48
  var SessionTurn_1 = require("./MediaSession/SessionTurn");
49
+
30
50
  var MediaDomUtils_1 = require("./MediaUtils/MediaDomUtils");
51
+
31
52
  var Compatibility_1 = require("./MediaUtils/Compatibility");
53
+
32
54
  var SessionOpentok_1 = require("./MediaSession/SessionOpentok");
55
+
33
56
  var MediaConstants_1 = require("./MediaConstants");
57
+
34
58
  var guards_1 = require("@techsee/techsee-common/lib/core/guards");
59
+
35
60
  var MediaServer_1 = require("./MediaSession/MediaServer");
61
+
36
62
  var MediaTracer_1 = require("./MediaUtils/MediaTracer");
63
+
37
64
  var MediaSessionBase_1 = require("./MediaSession/MediaSessionBase");
65
+
38
66
  var trace = MediaTracer_1.getMediaTracer('MediaServiceBase');
39
- var traceStatsInfo = debounce_1.default(trace.info, 1000 * 5, { leading: true, maxWait: 1000 * 30 });
67
+ var traceStatsInfo = debounce_1["default"](trace.info, 1000 * 5, {
68
+ leading: true,
69
+ maxWait: 1000 * 30
70
+ });
40
71
  var privateEvents;
72
+
41
73
  (function (privateEvents) {
42
- privateEvents["STREAM_CREATED"] = "STREAM_CREATED";
43
- privateEvents["STREAM_DESTROYED"] = "STREAM_DESTROYED";
74
+ privateEvents["STREAM_CREATED"] = "STREAM_CREATED";
75
+ privateEvents["STREAM_DESTROYED"] = "STREAM_DESTROYED";
44
76
  })(privateEvents || (privateEvents = {}));
45
- var TechseeMediaServiceBase = /** @class */function () {
46
- function TechseeMediaServiceBase(environment, webRtcSupportInfo) {
47
- this._subscribers = new Map();
48
- this._publishers = new Map();
49
- this._publisherPromises = new Map();
50
- this._serviceOptions = null;
51
- this._isIOS_13_orLater = false;
52
- this._isIOS_14_orLater = false;
53
- this._autoReconnectEnabled = true;
54
- this._initLocalStreamsPromise = null;
55
- this._initServicePromise = null;
56
- this._registeredStreams = new Map();
57
- this._isVoipEnabled = false;
58
- this._session = null;
59
- trace.info('TechseeMediaServiceBase created');
60
- this.bindClassMethods();
61
- this._emitter = new events_1.EventEmitter();
62
- this._environment = environment;
63
- this._deviceSupportFlags = {
64
- videoPlayback: false,
65
- hasCamera: false,
66
- hasMicrophone: false,
67
- webRtcSupportInfo: webRtcSupportInfo
68
- };
69
- this._localStreamsManager = new LocalStreamManager_1.LocalStreamManager(this._environment);
70
- // TODO: Hack as IOS 13.3 and above sometimes do not return the video/audio device. This
71
- // is a hack to work around the issue until Apple resolve it
72
- this._isIOS_13_orLater = this._environment.isIOS() && (!this._environment.majorVersion() || this._environment.majorVersion() >= 13);
73
- this._isIOS_14_orLater = this._environment.isIOS() && (!this._environment.majorVersion() || this._environment.majorVersion() >= 14);
74
- trace.info("TechseeMediaServiceBase: isIOS_13_orLater: " + this._isIOS_13_orLater);
75
- trace.info("TechseeMediaServiceBase: isIOS_14_orLater: " + this._isIOS_14_orLater);
76
- this._sessionStreamsManager = {
77
- getMediaStreamForRole: this.getStreamForDestinationRole,
78
- addRemoteMediaTrack: this.registerRemoteMediaTrack,
79
- removeMediaTrack: this.unregisterRemoteMediaTrack
80
- };
77
+
78
+ var TechseeMediaServiceBase =
79
+ /** @class */
80
+ function () {
81
+ function TechseeMediaServiceBase(environment, webRtcSupportInfo) {
82
+ this._subscribers = new Map();
83
+ this._publishers = new Map();
84
+ this._publisherPromises = new Map();
85
+ this._serviceOptions = null;
86
+ this._isIOS_13_orLater = false;
87
+ this._isIOS_14_orLater = false;
88
+ this._autoReconnectEnabled = true;
89
+ this._initLocalStreamsPromise = null;
90
+ this._initServicePromise = null;
91
+ this._registeredStreams = new Map();
92
+ this._isVoipEnabled = false;
93
+ this._session = null;
94
+ trace.info('TechseeMediaServiceBase created');
95
+ this.bindClassMethods();
96
+ this._emitter = new events_1.EventEmitter();
97
+ this._environment = environment;
98
+ this._deviceSupportFlags = {
99
+ videoPlayback: false,
100
+ hasCamera: false,
101
+ hasMicrophone: false,
102
+ webRtcSupportInfo: webRtcSupportInfo
103
+ };
104
+ this._localStreamsManager = new LocalStreamManager_1.LocalStreamManager(this._environment); // TODO: Hack as IOS 13.3 and above sometimes do not return the video/audio device. This
105
+ // is a hack to work around the issue until Apple resolve it
106
+
107
+ this._isIOS_13_orLater = this._environment.isIOS() && (!this._environment.majorVersion() || this._environment.majorVersion() >= 13);
108
+ this._isIOS_14_orLater = this._environment.isIOS() && (!this._environment.majorVersion() || this._environment.majorVersion() >= 14);
109
+ trace.info("TechseeMediaServiceBase: isIOS_13_orLater: " + this._isIOS_13_orLater);
110
+ trace.info("TechseeMediaServiceBase: isIOS_14_orLater: " + this._isIOS_14_orLater);
111
+ this._sessionStreamsManager = {
112
+ getMediaStreamForRole: this.getStreamForDestinationRole,
113
+ addRemoteMediaTrack: this.registerRemoteMediaTrack,
114
+ removeMediaTrack: this.unregisterRemoteMediaTrack
115
+ };
116
+ }
117
+
118
+ Object.defineProperty(TechseeMediaServiceBase.prototype, "deviceSupportInfo", {
119
+ get: function get() {
120
+ this.serviceInitGuard(false);
121
+ return cloneDeep_1["default"](this._deviceSupportFlags);
122
+ },
123
+ enumerable: false,
124
+ configurable: true
125
+ });
126
+ Object.defineProperty(TechseeMediaServiceBase.prototype, "isVoipEnabled", {
127
+ get: function get() {
128
+ return this._isVoipEnabled;
129
+ },
130
+ enumerable: false,
131
+ configurable: true
132
+ });
133
+ Object.defineProperty(TechseeMediaServiceBase.prototype, "isSessionActive", {
134
+ get: function get() {
135
+ return this._session !== null;
136
+ },
137
+ enumerable: false,
138
+ configurable: true
139
+ });
140
+ Object.defineProperty(TechseeMediaServiceBase.prototype, "isLocalStreamInitialized", {
141
+ get: function get() {
142
+ return this._initLocalStreamsPromise !== null;
143
+ },
144
+ enumerable: false,
145
+ configurable: true
146
+ });
147
+ /*
148
+ Initializes media service. Before using anything from this service it should be initialized first.
149
+ All of serviceOptions should be retrieved from account settings and by evaluating application state.
150
+ For example, when initializing service, accountSettings is already loaded, and we know if FS session is audio enabled.
151
+ */
152
+
153
+ TechseeMediaServiceBase.prototype.initMediaService = function (serviceOptions) {
154
+ var _this = this;
155
+
156
+ trace.info('TechseeMediaServiceBase.initMediaService', serviceOptions);
157
+ var warnMessage = 'Multiple initialization does not supposed to happen. Not rejecting, but check the flow for correctness.';
158
+
159
+ if (this._initServicePromise || this._serviceOptions) {
160
+ console.warn(warnMessage);
161
+ return this._initServicePromise ? this._initServicePromise : Promise.resolve();
81
162
  }
82
- Object.defineProperty(TechseeMediaServiceBase.prototype, "deviceSupportInfo", {
83
- get: function get() {
84
- this.serviceInitGuard(false);
85
- return cloneDeep_1.default(this._deviceSupportFlags);
86
- },
87
- enumerable: false,
88
- configurable: true
89
- });
90
- Object.defineProperty(TechseeMediaServiceBase.prototype, "isVoipEnabled", {
91
- get: function get() {
92
- return this._isVoipEnabled;
93
- },
94
- enumerable: false,
95
- configurable: true
96
- });
97
- Object.defineProperty(TechseeMediaServiceBase.prototype, "isSessionActive", {
98
- get: function get() {
99
- return this._session !== null;
100
- },
101
- enumerable: false,
102
- configurable: true
103
- });
104
- Object.defineProperty(TechseeMediaServiceBase.prototype, "isLocalStreamInitialized", {
105
- get: function get() {
106
- return this._initLocalStreamsPromise !== null;
107
- },
108
- enumerable: false,
109
- configurable: true
110
- });
111
- /*
112
- Initializes media service. Before using anything from this service it should be initialized first.
113
- All of serviceOptions should be retrieved from account settings and by evaluating application state.
114
- For example, when initializing service, accountSettings is already loaded, and we know if FS session is audio enabled.
115
- */
116
- TechseeMediaServiceBase.prototype.initMediaService = function (serviceOptions) {
117
- var _this = this;
118
- trace.info('TechseeMediaServiceBase.initMediaService', serviceOptions);
119
- var warnMessage = 'Multiple initialization does not supposed to happen. Not rejecting, but check the flow for correctness.';
120
- if (this._initServicePromise || this._serviceOptions) {
121
- console.warn(warnMessage);
122
- return this._initServicePromise ? this._initServicePromise : Promise.resolve();
123
- }
124
- this._serviceOptions = cloneDeep_1.default(serviceOptions);
125
- this._initServicePromise = Promise.all([Compatibility_1.isVideoPlaySupportedOnDevice(this._serviceOptions.mediaServiceType).then(function (isSupported) {
126
- return _this._deviceSupportFlags.videoPlayback = isSupported;
127
- }), (this._isIOS_14_orLater || !this._deviceSupportFlags.webRtcSupportInfo.isWebRTCSupported ? Promise.resolve([]) : Compatibility_1.enumerateMediaDevices()).catch(function (error) {
128
- trace.warn(error);
129
- return [];
130
- }).then(function (localDevicesList) {
131
- var groupedDevices = {
132
- video: filter_1.default(localDevicesList, function (device) {
133
- return device.kind.toLowerCase() === 'videoinput';
134
- }),
135
- audio: filter_1.default(localDevicesList, function (device) {
136
- return device.kind.toLowerCase() === 'audioinput';
137
- })
138
- };
139
- _this._localStreamsManager.setGroupedDevices(groupedDevices);
140
- _this._deviceSupportFlags.hasCamera = _this._isIOS_13_orLater || groupedDevices.video.length > 0;
141
- _this._deviceSupportFlags.hasMicrophone = _this._isIOS_13_orLater || groupedDevices.audio.length > 0;
142
- })]).then(function () {
143
- return undefined;
144
- });
145
- return this._initServicePromise;
146
- };
147
- //#region Media Streams Management
148
- /*
149
- The main method to start the initialization of local media streams.
150
- This method can be executed many times and it will insure all calls are synced and only relevant stream will be created.
151
- DO NOT USE ANY OTHER METHOD THAT FORCES "navigator.getUserMedia" OTHER THAN THIS ONE.
152
- */
153
- TechseeMediaServiceBase.prototype.initLocalMediaStreams = function () {
154
- this.serviceInitGuard();
155
- var isDashboardOpentok = this._serviceOptions.mediaServiceType === MediaConstants_1.MediaServiceType.OPENTOK && (this._serviceOptions.clientRole === MediaConstants_1.SessionClientRole.AGENT || this._serviceOptions.clientRole === MediaConstants_1.SessionClientRole.OBSERVER);
156
- // This hack for IOS 14 force a recreation of stream on seemingly unnecessary occasions (like agent page refresh).
157
- // we're not sure why but the stream breaks
158
- if (!this._initLocalStreamsPromise || this._isIOS_14_orLater && !isDashboardOpentok) {
159
- trace.info('initLocalMediaStreams creating media streams');
160
- this._initLocalStreamsPromise = this.getLocalMediaImplementation().catch(function (mediaRequestFailResult) {
161
- trace.error("initLocalMediaStreams failure: " + mediaRequestFailResult);
162
- throw mediaRequestFailResult;
163
- });
164
- } else {
165
- trace.info('initLocalMediaStreams already done or in progress');
166
- }
167
- return this._initLocalStreamsPromise;
168
- };
169
- /*
170
- Creates an instance of subscriber that will "listen" to the requested stream.
171
- Whenever requested stream is available, subscriber will render it.
172
- */
173
- TechseeMediaServiceBase.prototype.createSubscriber = function (subscriberParams) {
174
- if (this._subscribers.has(subscriberParams.container)) {
175
- return Promise.reject('Subscriber for provided DIV element already exists');
176
- }
177
- var subscriber = new MediaSubscriber_1.TechseeMediaSubscriber(subscriberParams);
178
- this._subscribers.set(subscriberParams.container, subscriber);
179
- var streamForSubscriber = this.getRegisteredStreamByType(subscriber.streamType);
180
- if (streamForSubscriber) {
181
- trace.info("Stream for " + subscriberParams.streamType + " is ready.");
182
- subscriber.renderStream(streamForSubscriber);
183
- } else {
184
- trace.info("Stream for " + subscriberParams.streamType + " not created yet");
185
- }
186
- return Promise.resolve(subscriber);
187
- };
188
- /*
189
- Destroys the subscriber for provided HTML DIV container
190
- */
191
- TechseeMediaServiceBase.prototype.destroySubscriber = function (container) {
192
- if (this._subscribers.has(container)) {
193
- var subscriber = this._subscribers.get(container);
194
- subscriber.dispose();
195
- }
196
- this._subscribers.delete(container);
197
- return Promise.resolve();
198
- };
199
- TechseeMediaServiceBase.prototype.onStreamDestroyed = function (callback) {
200
- this.registerEventCallback(privateEvents.STREAM_DESTROYED, callback);
201
- };
202
- TechseeMediaServiceBase.prototype.onStreamCreated = function (callback) {
203
- this.registerEventCallback(privateEvents.STREAM_CREATED, callback);
204
- };
205
- TechseeMediaServiceBase.prototype.onRecordStarted = function (callback) {
206
- if (this._session && this._session.instance) {
207
- this._session.instance.registerEventCallback(MediaSessionBase_1.recordingEvents.RECORD_STARTED, callback);
208
- }
209
- };
210
- TechseeMediaServiceBase.prototype.onRecordStopped = function (callback) {
211
- if (this._session && this._session.instance) {
212
- this._session.instance.registerEventCallback(MediaSessionBase_1.recordingEvents.RECORD_STOPPED, callback);
213
- }
214
- };
215
- TechseeMediaServiceBase.prototype.onReconnecting = function (callback) {
216
- if (this._session && this._session.instance) {
217
- this._session.instance.registerEventCallback(MediaSessionBase_1.recordingEvents.RECONNECTING, callback);
218
- }
219
- };
220
- TechseeMediaServiceBase.prototype.getSwitchCameraConstraints = function () {
221
- var constraints = cloneDeep_1.default(window.latestLocalMediaConstraints);
222
- if (!constraints) {
223
- throw new Error('getSwitchCameraConstraints: unexpected use case constraints is null.');
224
- }
225
- trace.info('getSwitchCameraConstraints - Start switch camera with constraints:', constraints);
226
- var videoSourceType = constraints.video.videoSourceType === MediaConstants_1.LocalVideoSourceType.CAMERA ? MediaConstants_1.LocalVideoSourceType.CAMERA_FRONT : MediaConstants_1.LocalVideoSourceType.CAMERA;
227
- trace.info("getSwitchCameraConstraints - switch to videoSourceType: " + videoSourceType);
228
- constraints.video.videoSourceType = videoSourceType;
229
- return constraints;
230
- };
231
- TechseeMediaServiceBase.prototype.switchCamera = function (revertCameraWhenFailed) {
232
- var _this = this;
233
- trace.info('switchCamera: start');
234
- var latestLocalMediaConstraints = cloneDeep_1.default(window.latestLocalMediaConstraints);
235
- var constraints = !revertCameraWhenFailed ? this.getSwitchCameraConstraints() : latestLocalMediaConstraints;
236
- if (!constraints) {
237
- throw new Error('switchCamera - unexpected use case constraints is null.');
238
- }
239
- return this._localStreamsManager.destroyUserMediaStream().then(function () {
240
- return _this._localStreamsManager.getUserMediaStream(constraints).then(function (streamResult) {
241
- var stream = streamResult.mediaStream;
242
- trace.info('switchCamera: new stream: ', stream);
243
- return _this.replaceStreamTracks(stream).then(function () {
244
- return _this.registerStreamResult(constraints, streamResult, true).then(function () {
245
- return {
246
- revertCameraWhenFailed: revertCameraWhenFailed,
247
- constraints: constraints,
248
- streamResult: streamResult
249
- };
250
- });
251
- });
252
- });
253
- }).catch(function (err) {
254
- trace.error('switchCamera: Failed to switch camera: ', err);
255
- if (!revertCameraWhenFailed) {
256
- window.latestLocalMediaConstraints = latestLocalMediaConstraints;
257
- return _this.switchCamera(true);
258
- }
259
- return Promise.reject('Failed to switch camera.');
260
- });
261
- };
262
- TechseeMediaServiceBase.prototype.replaceStreamTracks = function (mediaStream) {
263
- if (this._session.instance) {
264
- return this._session.instance.replaceStreamTracks(mediaStream);
265
- }
266
- return Promise.reject('replaceStreamTracks - session instance is not exists.');
267
- };
268
- TechseeMediaServiceBase.prototype.registerStreamResult = function (constraints, streamResult, switchCamera, addStreamType) {
269
- var _this = this;
270
- var regPromises = [];
271
- var isOpentok = this._serviceOptions.mediaServiceType === MediaConstants_1.MediaServiceType.OPENTOK;
272
- if (streamResult.isNew) {
273
- trace.info('registerStreamResult: stream result from getUserMediaStream:', streamResult.mediaStream);
274
- streamResult.mediaStream.getTracks().forEach(function (mediaTrack) {
275
- trace.info('registerStreamResult: stream result from mediaTrack:', mediaTrack);
276
- var streamType = addStreamType || (mediaTrack.kind === 'video' ? MediaConstants_1.KnownMediaStream.USER_VIDEO_STREAM : MediaConstants_1.KnownMediaStream.USER_AUDIO_STREAM);
277
- var newDedicatedStream = new TechseeMediaStream_1.TechseeMediaStream(mediaTrack, streamType, false);
278
- if (isOpentok) {
279
- regPromises.push(_this.registerStream(newDedicatedStream));
280
- } else {
281
- regPromises.push(switchCamera ? _this.registerTrack(newDedicatedStream) : _this.registerLocalMediaStream(newDedicatedStream));
282
- }
283
- });
284
- }
285
- return Promise.all(regPromises);
286
- };
287
- TechseeMediaServiceBase.prototype.disconnectFromMediaSession = function () {
288
- if (this._session && this._session.instance) {
289
- return this._session.instance.sessionDisconnect();
290
- }
291
- };
292
- Object.defineProperty(TechseeMediaServiceBase.prototype, "supportSwitchCameras", {
293
- get: function get() {
294
- return this._isIOS_13_orLater || this._localStreamsManager.groupedDevices.camerasCount > 1;
295
- },
296
- enumerable: false,
297
- configurable: true
163
+
164
+ this._serviceOptions = cloneDeep_1["default"](serviceOptions);
165
+ this._initServicePromise = Promise.all([Compatibility_1.isVideoPlaySupportedOnDevice(this._serviceOptions.mediaServiceType).then(function (isSupported) {
166
+ return _this._deviceSupportFlags.videoPlayback = isSupported;
167
+ }), (this._isIOS_14_orLater || !this._deviceSupportFlags.webRtcSupportInfo.isWebRTCSupported ? Promise.resolve([]) : Compatibility_1.enumerateMediaDevices())["catch"](function (error) {
168
+ trace.warn(error);
169
+ return [];
170
+ }).then(function (localDevicesList) {
171
+ var groupedDevices = {
172
+ video: filter_1["default"](localDevicesList, function (device) {
173
+ return device.kind.toLowerCase() === 'videoinput';
174
+ }),
175
+ audio: filter_1["default"](localDevicesList, function (device) {
176
+ return device.kind.toLowerCase() === 'audioinput';
177
+ })
178
+ };
179
+
180
+ _this._localStreamsManager.setGroupedDevices(groupedDevices);
181
+
182
+ _this._deviceSupportFlags.hasCamera = _this._isIOS_13_orLater || groupedDevices.video.length > 0;
183
+ _this._deviceSupportFlags.hasMicrophone = _this._isIOS_13_orLater || groupedDevices.audio.length > 0;
184
+ })]).then(function () {
185
+ return undefined;
298
186
  });
299
- TechseeMediaServiceBase.prototype._connectToSession = function (sessionParams) {
300
- var _this = this;
301
- this.serviceInitGuard();
302
- if (!this._session) {
303
- this._session = { params: cloneDeep_1.default(sessionParams) };
304
- this._session.connectPromise = new Promise(function (resolve, reject) {
305
- var doAsyncReject = function doAsyncReject(error) {
306
- /*
307
- Reject with timeout, to change JS 'execution flow'.
308
- If timeout removed, session is assigned to null, before promise returns, and "catch" will not
309
- work on promise that is returned.
310
- */
311
- setTimeout(function () {
312
- _this._session = null;
313
- reject(error);
314
- });
315
- };
316
- var sessionHandlers = {
317
- onDisconnectedHandler: _this.onSessionDisconnectHandler
318
- };
319
- var mediaSessionParams = __assign(__assign({}, sessionParams), { peerConnectivityTimeoutSeconds: _this._serviceOptions.peerConnectivityTimeoutSeconds || MediaConstants_1.DEFAULT_PEER_CONNECTIVITY_TIMEOUT_SECONDS });
320
- trace.info('connectToSession', sessionParams);
321
- var allowedValues = values_1.default(MediaConstants_1.MediaServiceType);
322
- switch (_this._serviceOptions.mediaServiceType) {
323
- case MediaConstants_1.MediaServiceType.TURNSERVER:
324
- _this._session.instance = new SessionTurn_1.TurnWebRtcSession(mediaSessionParams, sessionHandlers, _this._sessionStreamsManager);
325
- break;
326
- case MediaConstants_1.MediaServiceType.OPENTOK:
327
- _this._session.instance = new SessionOpentok_1.OpentokSession(mediaSessionParams, _this._sessionStreamsManager);
328
- break;
329
- case MediaConstants_1.MediaServiceType.MEDIASERVER:
330
- _this._session.instance = new MediaServer_1.MediaServerSession(mediaSessionParams, _this._sessionStreamsManager);
331
- break;
332
- default:
333
- trace.error("mediaServiceType '" + _this._serviceOptions.mediaServiceType + "' is not supported.", { allowedValues: allowedValues });
334
- doAsyncReject(new Error('mediaServiceType is not supported'));
335
- }
336
- if (_this._session && _this._session.instance) {
337
- _this._session.instance.connect().then(function () {
338
- trace.info('Session is connected');
339
- resolve();
340
- }).catch(function (error) {
341
- trace.error('Failed to connect to session', error);
342
- doAsyncReject(error);
343
- });
344
- }
345
- });
346
- } else {
347
- trace.warn('Session connected already. Disconnect before connect to new session again');
348
- }
349
- //TODO - Alex: Change a structure of this function to be more safe
350
- //(when we return, there should not be case when session or promise is null)
351
- //To fix, need to return promise immediately, then execute process in setTimeout(fn, 0);
352
- return this._session.connectPromise;
353
- };
354
- //#endregion Media Streams Management
355
- //#region Session Management
356
- /*
357
- Creates instance of WebRTC session which connects to (signaling server), and begins to listen to WebRTC events.
358
- */
359
- TechseeMediaServiceBase.prototype.connectToSession = function (sessionParams) {
360
- return this._connectToSession(sessionParams);
361
- };
362
- /*
363
- Disconnects from WebRTC session.
364
- */
365
- TechseeMediaServiceBase.prototype.disconnectFromSession = function () {
366
- return this.disconnectFromSessionInternal(MediaConstants_1.MediaSessionDisconnectReason.ForcedByConsumer);
367
- };
368
- /*
369
- Updates a credentials for turn server
370
- */
371
- TechseeMediaServiceBase.prototype.updateSessionCredentials = function (credentials) {
372
- trace.info('updateSessionCredentials');
373
- if (!this.sessionExistsGuard(false)) {
374
- return Promise.reject('There no session to update credentials');
375
- }
376
- this._session.params.credentials = cloneDeep_1.default(credentials);
377
- return Promise.resolve();
378
- };
379
- TechseeMediaServiceBase.prototype.enableVoipDuringSession = function () {
380
- if (!this._isVoipEnabled && this.isLocalStreamInitialized) {
381
- this._initLocalStreamsPromise = null;
382
- }
383
- this._isVoipEnabled = true;
384
- };
385
- TechseeMediaServiceBase.prototype.disconnectFromSessionInternal = function (reason) {
386
- if (!this._session) {
387
- return Promise.resolve();
388
- }
389
- trace.info('Disconnecting from session', reason);
390
- var lastSession = this._session;
391
- this._session = null;
392
- return Promise.all([lastSession.instance.disconnect(), this.clearPublishers()]).then(function () {
393
- return undefined;
394
- });
395
- };
396
- TechseeMediaServiceBase.prototype.getStatsForRemoteTrack = function (streamType) {
397
- if (!this.sessionExistsGuard(false)) {
398
- return Promise.reject(new Error('Media session not started'));
399
- }
400
- var streamForStats = this.getRegisteredStreamByType(streamType);
401
- if (!streamForStats) {
402
- return Promise.reject(new Error('Stream for requested type was not found'));
403
- }
404
- return this._session.instance.getRemoteTrackStats(streamForStats.mediaTrack).then(function (trackStats) {
405
- traceStatsInfo("MediaTrackStats for " + streamType + ": " + JSON.stringify(trackStats));
187
+ return this._initServicePromise;
188
+ }; //#region Media Streams Management
189
+
190
+ /*
191
+ The main method to start the initialization of local media streams.
192
+ This method can be executed many times and it will insure all calls are synced and only relevant stream will be created.
193
+ DO NOT USE ANY OTHER METHOD THAT FORCES "navigator.getUserMedia" OTHER THAN THIS ONE.
194
+ */
195
+
196
+
197
+ TechseeMediaServiceBase.prototype.initLocalMediaStreams = function () {
198
+ this.serviceInitGuard();
199
+ var isDashboardOpentok = this._serviceOptions.mediaServiceType === MediaConstants_1.MediaServiceType.OPENTOK && (this._serviceOptions.clientRole === MediaConstants_1.SessionClientRole.AGENT || this._serviceOptions.clientRole === MediaConstants_1.SessionClientRole.OBSERVER); // This hack for IOS 14 force a recreation of stream on seemingly unnecessary occasions (like agent page refresh).
200
+ // we're not sure why but the stream breaks
201
+
202
+ if (!this._initLocalStreamsPromise || this._isIOS_14_orLater && !isDashboardOpentok) {
203
+ trace.info('initLocalMediaStreams creating media streams');
204
+ this._initLocalStreamsPromise = this.getLocalMediaImplementation()["catch"](function (mediaRequestFailResult) {
205
+ trace.error("initLocalMediaStreams failure: " + mediaRequestFailResult);
206
+ throw mediaRequestFailResult;
207
+ });
208
+ } else {
209
+ trace.info('initLocalMediaStreams already done or in progress');
210
+ }
211
+
212
+ return this._initLocalStreamsPromise;
213
+ };
214
+ /*
215
+ Creates an instance of subscriber that will "listen" to the requested stream.
216
+ Whenever requested stream is available, subscriber will render it.
217
+ */
218
+
219
+
220
+ TechseeMediaServiceBase.prototype.createSubscriber = function (subscriberParams) {
221
+ if (this._subscribers.has(subscriberParams.container)) {
222
+ return Promise.reject('Subscriber for provided DIV element already exists');
223
+ }
224
+
225
+ var subscriber = new MediaSubscriber_1.TechseeMediaSubscriber(subscriberParams);
226
+
227
+ this._subscribers.set(subscriberParams.container, subscriber);
228
+
229
+ var streamForSubscriber = this.getRegisteredStreamByType(subscriber.streamType);
230
+
231
+ if (streamForSubscriber) {
232
+ trace.info("Stream for " + subscriberParams.streamType + " is ready.");
233
+ subscriber.renderStream(streamForSubscriber);
234
+ } else {
235
+ trace.info("Stream for " + subscriberParams.streamType + " not created yet");
236
+ }
237
+
238
+ return Promise.resolve(subscriber);
239
+ };
240
+ /*
241
+ Destroys the subscriber for provided HTML DIV container
242
+ */
243
+
244
+
245
+ TechseeMediaServiceBase.prototype.destroySubscriber = function (container) {
246
+ if (this._subscribers.has(container)) {
247
+ var subscriber = this._subscribers.get(container);
248
+
249
+ subscriber.dispose();
250
+ }
251
+
252
+ this._subscribers["delete"](container);
253
+
254
+ return Promise.resolve();
255
+ };
256
+
257
+ TechseeMediaServiceBase.prototype.onStreamDestroyed = function (callback) {
258
+ this.registerEventCallback(privateEvents.STREAM_DESTROYED, callback);
259
+ };
260
+
261
+ TechseeMediaServiceBase.prototype.onStreamCreated = function (callback) {
262
+ this.registerEventCallback(privateEvents.STREAM_CREATED, callback);
263
+ };
264
+
265
+ TechseeMediaServiceBase.prototype.onRecordStarted = function (callback) {
266
+ if (this._session && this._session.instance) {
267
+ this._session.instance.registerEventCallback(MediaSessionBase_1.recordingEvents.RECORD_STARTED, callback);
268
+ }
269
+ };
270
+
271
+ TechseeMediaServiceBase.prototype.onRecordStopped = function (callback) {
272
+ if (this._session && this._session.instance) {
273
+ this._session.instance.registerEventCallback(MediaSessionBase_1.recordingEvents.RECORD_STOPPED, callback);
274
+ }
275
+ };
276
+
277
+ TechseeMediaServiceBase.prototype.onReconnecting = function (callback) {
278
+ if (this._session && this._session.instance) {
279
+ this._session.instance.registerEventCallback(MediaSessionBase_1.recordingEvents.RECONNECTING, callback);
280
+ }
281
+ };
282
+
283
+ TechseeMediaServiceBase.prototype.getSwitchCameraConstraints = function () {
284
+ var constraints = cloneDeep_1["default"](window.latestLocalMediaConstraints);
285
+
286
+ if (!constraints) {
287
+ throw new Error('getSwitchCameraConstraints: unexpected use case constraints is null.');
288
+ }
289
+
290
+ trace.info('getSwitchCameraConstraints - Start switch camera with constraints:', constraints);
291
+ var videoSourceType = constraints.video.videoSourceType === MediaConstants_1.LocalVideoSourceType.CAMERA ? MediaConstants_1.LocalVideoSourceType.CAMERA_FRONT : MediaConstants_1.LocalVideoSourceType.CAMERA;
292
+ trace.info("getSwitchCameraConstraints - switch to videoSourceType: " + videoSourceType);
293
+ constraints.video.videoSourceType = videoSourceType;
294
+ return constraints;
295
+ };
296
+
297
+ TechseeMediaServiceBase.prototype.switchCamera = function (revertCameraWhenFailed) {
298
+ var _this = this;
299
+
300
+ trace.info('switchCamera: start');
301
+ var latestLocalMediaConstraints = cloneDeep_1["default"](window.latestLocalMediaConstraints);
302
+ var constraints = !revertCameraWhenFailed ? this.getSwitchCameraConstraints() : latestLocalMediaConstraints;
303
+
304
+ if (!constraints) {
305
+ throw new Error('switchCamera - unexpected use case constraints is null.');
306
+ }
307
+
308
+ return this._localStreamsManager.destroyUserMediaStream().then(function () {
309
+ return _this._localStreamsManager.getUserMediaStream(constraints).then(function (streamResult) {
310
+ var stream = streamResult.mediaStream;
311
+ trace.info('switchCamera: new stream: ', stream);
312
+ return _this.replaceStreamTracks(stream).then(function () {
313
+ return _this.registerStreamResult(constraints, streamResult, true).then(function () {
406
314
  return {
407
- trackId: streamForStats.mediaTrack.id,
408
- trackStats: trackStats
315
+ revertCameraWhenFailed: revertCameraWhenFailed,
316
+ constraints: constraints,
317
+ streamResult: streamResult
409
318
  };
319
+ });
410
320
  });
411
- };
412
- TechseeMediaServiceBase.prototype.onSessionDisconnectHandler = function (reason) {
413
- var _this = this;
414
- trace.info('onSessionDisconnectHandler', reason);
415
- if (reason !== MediaConstants_1.MediaSessionDisconnectReason.ForcedByConsumer) {
416
- var lastParams_1 = this._session && this._session.params ? this._session.params : null;
417
- this.disconnectFromSessionInternal(reason).then(function () {
418
- var reconnectReasons = [MediaConstants_1.MediaSessionDisconnectReason.InitiatorPeerReconnected, MediaConstants_1.MediaSessionDisconnectReason.SignalingChannelDisconnect, MediaConstants_1.MediaSessionDisconnectReason.PeerConnectionInterrupted, MediaConstants_1.MediaSessionDisconnectReason.PeerConnectionStateChangeTimeout];
419
- if (lastParams_1 && includes_1.default(reconnectReasons, reason) && _this._autoReconnectEnabled) {
420
- _this.reconnectToSession(lastParams_1);
421
- } else if (!_this._autoReconnectEnabled) {
422
- trace.info('No reconnection- auto reconnect disabled');
423
- } else {
424
- trace.info('No params for reconnection to media session');
425
- }
426
- });
427
- } else {
428
- trace.info('Ignore Session disconnect event');
429
- }
430
- };
431
- TechseeMediaServiceBase.prototype.setAutoReconnect = function (state) {
432
- this._autoReconnectEnabled = state;
433
- trace.info('_autoReconnectEnabled:', state);
434
- if (this._autoReconnectEnabled && !this.isSessionActive) {
435
- var lastParams = this._session && this._session.params ? this._session.params : null;
436
- if (lastParams) {
437
- trace.info('setAutoReconnect - reconnect to session');
438
- this.reconnectToSession(lastParams);
439
- }
440
- }
441
- };
442
- TechseeMediaServiceBase.prototype.reconnectToSession = function (lastParams) {
443
- trace.info('Reconnecting to media session, sessionParams:', lastParams);
444
- this._connectToSession(lastParams).then(function () {
445
- trace.info('Media session reconnected');
446
- }).catch(function (error) {
447
- trace.error('Error while reconnecting to media session', error);
448
- });
449
- };
450
- //#endregion Session Management
451
- //#region Utils
452
- TechseeMediaServiceBase.prototype.getSnapshotFromKnownStream = function (sourceStream, snapshotOptions) {
453
- var _this = this;
454
- return new Promise(function (resolve, reject) {
455
- if (sourceStream !== MediaConstants_1.KnownMediaStream.USER_VIDEO_STREAM && sourceStream !== MediaConstants_1.KnownMediaStream.USER_SCREEN_SHARE_STREAM) {
456
- trace.error('The requested stream is not video stream, and cannot be used for snapshot');
457
- reject(new Error('INCOMPATIBLE_STREAM_FOR_SNAPSHOT'));
458
- return;
459
- }
460
- var snapshotStream = _this.getRegisteredStreamByType(sourceStream);
461
- if (!snapshotStream) {
462
- trace.error('Cannot make snapshot: The requested stream not exists yet.');
463
- reject(new Error('NO_REQUESTED_STREAM'));
464
- return;
465
- }
466
- MediaDomUtils_1.getSnapshotFromMediaStream(snapshotStream.mediaStream, sourceStream, snapshotOptions).then(function (imageData) {
467
- var urlComponents = imageData.split(';base64,');
468
- var mimeType = urlComponents[0].split(':')[1];
469
- var bytes = atob(urlComponents[1]);
470
- var buffer = new ArrayBuffer(bytes.length);
471
- var rawData = new Uint8Array(buffer);
472
- for (var i = 0; i < bytes.length; i++) {
473
- rawData[i] = bytes.charCodeAt(i);
474
- }
475
- var blob = new Blob([rawData], { type: mimeType });
476
- var objectUrl = window.URL.createObjectURL(blob);
477
- trace.info('Snapshot created successfully');
478
- var result = {
479
- base64img: imageData,
480
- objectUrl: objectUrl,
481
- imageBlob: blob,
482
- mimeType: mimeType
483
- };
484
- resolve(result);
485
- }).catch(function (error) {
486
- trace.error('Error creating snapshot', error);
487
- reject(error);
488
- });
489
- });
490
- };
491
- //Will clean streams, publishers and subscribers, but will not remove event listeners
492
- TechseeMediaServiceBase.prototype.clearService = function () {
493
- var _this = this;
494
- trace.info('MediaService clearing all resources');
495
- return this.disconnectFromSessionInternal(MediaConstants_1.MediaSessionDisconnectReason.ForcedByConsumer).then(this.clearSubscribers).then(this.clearRegisteredStreams).then(this._localStreamsManager.clearAllStreams).then(function () {
496
- _this._initLocalStreamsPromise = null;
497
- _this._isVoipEnabled = false;
498
- }).then(function () {
499
- return undefined;
500
- });
501
- };
502
- //Will clear the service and remove all event listeners
503
- TechseeMediaServiceBase.prototype.dispose = function () {
504
- var _this = this;
505
- return this.clearService().catch(function () {
506
- return undefined;
507
- }).then(function () {
508
- _this._emitter.removeAllListeners();
509
- });
510
- };
511
- Object.defineProperty(TechseeMediaServiceBase.prototype, "subscribers", {
512
- //#endregion
513
- //#region Protected Methods
514
- get: function get() {
515
- return this._subscribers;
516
- },
517
- enumerable: false,
518
- configurable: true
321
+ });
322
+ })["catch"](function (err) {
323
+ trace.error('switchCamera: Failed to switch camera: ', err);
324
+
325
+ if (!revertCameraWhenFailed) {
326
+ window.latestLocalMediaConstraints = latestLocalMediaConstraints;
327
+ return _this.switchCamera(true);
328
+ }
329
+
330
+ return Promise.reject('Failed to switch camera.');
519
331
  });
520
- TechseeMediaServiceBase.prototype.registerLocalMediaStream = function (tsMediaStream) {
521
- trace.info('Registering local stream', tsMediaStream.streamType);
522
- if (this._registeredStreams.has(tsMediaStream.streamType)) {
523
- return Promise.reject(new Error("Stream " + tsMediaStream.streamType + " already registered"));
524
- }
525
- return this.registerStream(tsMediaStream);
526
- };
527
- TechseeMediaServiceBase.prototype.getRegisteredStreamByType = function (streamType) {
528
- return this._registeredStreams.get(streamType) || null;
529
- };
530
- TechseeMediaServiceBase.prototype.changeEnableForKnownStream = function (streamType, isPaused) {
531
- var streamToChangeState = this.getRegisteredStreamByType(streamType);
532
- if (!streamToChangeState) {
533
- trace.warn('There no stream found to change enable state', streamType);
332
+ };
333
+
334
+ TechseeMediaServiceBase.prototype.replaceStreamTracks = function (mediaStream) {
335
+ if (this._session.instance) {
336
+ return this._session.instance.replaceStreamTracks(mediaStream);
337
+ }
338
+
339
+ return Promise.reject('replaceStreamTracks - session instance is not exists.');
340
+ };
341
+
342
+ TechseeMediaServiceBase.prototype.registerStreamResult = function (constraints, streamResult, switchCamera, addStreamType) {
343
+ var _this = this;
344
+
345
+ var regPromises = [];
346
+ var isOpentok = this._serviceOptions.mediaServiceType === MediaConstants_1.MediaServiceType.OPENTOK;
347
+
348
+ if (streamResult.isNew) {
349
+ trace.info('registerStreamResult: stream result from getUserMediaStream:', streamResult.mediaStream);
350
+ streamResult.mediaStream.getTracks().forEach(function (mediaTrack) {
351
+ trace.info('registerStreamResult: stream result from mediaTrack:', mediaTrack);
352
+ var streamType = addStreamType || (mediaTrack.kind === 'video' ? MediaConstants_1.KnownMediaStream.USER_VIDEO_STREAM : MediaConstants_1.KnownMediaStream.USER_AUDIO_STREAM);
353
+ var newDedicatedStream = new TechseeMediaStream_1.TechseeMediaStream(mediaTrack, streamType, false);
354
+
355
+ if (isOpentok) {
356
+ regPromises.push(_this.registerStream(newDedicatedStream));
534
357
  } else {
535
- streamToChangeState.mediaTrack.enabled = !isPaused;
536
- if (streamToChangeState.isRemote && streamToChangeState.streamKind === MediaConstants_1.KnownMediaStreamKind.Audio) {
537
- this.subscribers.forEach(function (subscriber) {
538
- if (subscriber.streamType === streamType) {
539
- subscriber.muteSound(isPaused);
540
- }
541
- });
542
- }
543
- trace.info('Local stream enable state is changed', { streamType: streamType, isPaused: isPaused });
544
- }
545
- };
546
- TechseeMediaServiceBase.prototype.registerEventCallback = function (event, callback) {
547
- this._emitter.on(event, callback);
548
- };
549
- TechseeMediaServiceBase.prototype.unregisterEventCallback = function (event, callback) {
550
- this._emitter.off(event, callback);
551
- };
552
- TechseeMediaServiceBase.prototype.emitEvent = function (event, eventArgs) {
553
- var _this = this;
554
- setTimeout(function () {
555
- _this._emitter.emit(event, eventArgs);
556
- });
557
- };
558
- //#endregion Protected Methods
559
- //#region Private Methods
560
- TechseeMediaServiceBase.prototype.registerRemoteMediaTrack = function (remoteMediaTrack) {
561
- trace.info("Registering remote " + remoteMediaTrack.trackType + " MediaStreamTrack", remoteMediaTrack.mediaTrack);
562
- var currentStream = this._registeredStreams.get(remoteMediaTrack.trackType);
563
- if (currentStream && !currentStream.isRemote) {
564
- return Promise.reject(new Error('Cannot register remote stream with the same type as local stream'));
358
+ regPromises.push(switchCamera ? _this.registerTrack(newDedicatedStream) : _this.registerLocalMediaStream(newDedicatedStream));
565
359
  }
566
- var newDedicatedStream = new TechseeMediaStream_1.TechseeMediaStream(remoteMediaTrack.mediaTrack, remoteMediaTrack.trackType, true);
567
- return this.registerStream(newDedicatedStream);
568
- };
569
- TechseeMediaServiceBase.prototype.registerTrack = function (mediaStream) {
570
- var _this = this;
571
- mediaStream.mediaTrack.onended = function () {
572
- return _this.unregisterTechseeMediaStream(mediaStream, MediaConstants_1.MediaStreamUnregisterReason.NativeEvent);
360
+ });
361
+ }
362
+
363
+ return Promise.all(regPromises);
364
+ };
365
+
366
+ TechseeMediaServiceBase.prototype.disconnectFromMediaSession = function () {
367
+ if (this._session && this._session.instance) {
368
+ return this._session.instance.sessionDisconnect();
369
+ }
370
+ };
371
+
372
+ Object.defineProperty(TechseeMediaServiceBase.prototype, "supportSwitchCameras", {
373
+ get: function get() {
374
+ return this._isIOS_13_orLater || this._localStreamsManager.groupedDevices.camerasCount > 1;
375
+ },
376
+ enumerable: false,
377
+ configurable: true
378
+ });
379
+
380
+ TechseeMediaServiceBase.prototype._connectToSession = function (sessionParams) {
381
+ var _this = this;
382
+
383
+ this.serviceInitGuard();
384
+
385
+ if (!this._session) {
386
+ this._session = {
387
+ params: cloneDeep_1["default"](sessionParams)
388
+ };
389
+ this._session.connectPromise = new Promise(function (resolve, reject) {
390
+ var doAsyncReject = function doAsyncReject(error) {
391
+ /*
392
+ Reject with timeout, to change JS 'execution flow'.
393
+ If timeout removed, session is assigned to null, before promise returns, and "catch" will not
394
+ work on promise that is returned.
395
+ */
396
+ setTimeout(function () {
397
+ _this._session = null;
398
+ reject(error);
399
+ });
573
400
  };
574
- this._registeredStreams.set(mediaStream.streamType, mediaStream);
575
- trace.info("TechseeMediaStream registered - " + mediaStream.streamType, TechseeMediaStream_1.TechseeMediaStream);
576
- return this.updateSubscribersWithNewStream(mediaStream).then(function () {
577
- var eventArgs = { streamType: mediaStream.streamType };
578
- _this.emitEvent(privateEvents.STREAM_CREATED, eventArgs);
579
- });
580
- };
581
- TechseeMediaServiceBase.prototype.registerStream = function (mediaStream) {
582
- var _this = this;
583
- var currentStream = this._registeredStreams.get(mediaStream.streamType);
584
- if (currentStream) {
585
- return this.unregisterTechseeMediaStream(currentStream, MediaConstants_1.MediaStreamUnregisterReason.ReplacingStream).then(function () {
586
- return _this.registerTrack(mediaStream);
587
- });
588
- }
589
- return this.registerTrack(mediaStream);
590
- };
591
- TechseeMediaServiceBase.prototype.unregisterTechseeMediaStream = function (streamToUnregister, reason) {
592
- var _this = this;
593
- var traceError = function traceError(error) {
594
- trace.warn('Unregister TechseeMediaStream error:', error);
401
+
402
+ var sessionHandlers = {
403
+ onDisconnectedHandler: _this.onSessionDisconnectHandler
595
404
  };
596
- var promises = [];
597
- trace.info('Unregister TechseeMediaStream: ', streamToUnregister.streamType);
598
- this._subscribers.forEach(function (subscriber) {
599
- if (subscriber.streamType === streamToUnregister.streamType) {
600
- promises.push(subscriber.stopRendering().catch(traceError));
601
- }
602
- });
603
- if (!streamToUnregister.isRemote) {
604
- this._publishers.forEach(function (publisher) {
605
- if (publisher.streamTypes.find(function (streamType) {
606
- return streamType === streamToUnregister.streamType;
607
- })) {
608
- if (_this._session && _this._session.instance) {
609
- promises.push(_this._session.instance.onMediaStreamDestroyed(publisher.destinationRole).catch(traceError));
610
- }
611
- }
612
- });
613
- }
614
- return Promise.all(promises).then(function () {
615
- _this._registeredStreams.delete(streamToUnregister.streamType);
616
- trace.info('Stream deleted', streamToUnregister.streamType);
617
- var eventArgs = { streamType: streamToUnregister.streamType, reason: reason };
618
- _this.emitEvent(privateEvents.STREAM_DESTROYED, eventArgs);
619
- });
620
- };
621
- TechseeMediaServiceBase.prototype.unregisterRemoteMediaTrack = function (mediaTrack) {
622
- var _this = this;
623
- var promises = [];
624
- this._registeredStreams.forEach(function (registeredStream) {
625
- if (registeredStream.mediaTrack.id === mediaTrack.id) {
626
- promises.push(_this.unregisterTechseeMediaStream(registeredStream, MediaConstants_1.MediaStreamUnregisterReason.ClosedRemotely));
627
- }
628
- });
629
- return Promise.all(promises).then(function () {
630
- return undefined;
405
+
406
+ var mediaSessionParams = __assign(__assign({}, sessionParams), {
407
+ peerConnectivityTimeoutSeconds: _this._serviceOptions.peerConnectivityTimeoutSeconds || MediaConstants_1.DEFAULT_PEER_CONNECTIVITY_TIMEOUT_SECONDS
631
408
  });
632
- };
633
- TechseeMediaServiceBase.prototype.removePublisher = function (publisher) {
634
- this._publishers.delete(publisher.destinationRole);
635
- if (this._session && this._session.instance) {
636
- trace.info('Removing publisher', publisher.destinationRole);
637
- return this._session.instance.onMediaStreamDestroyed(publisher.destinationRole).catch(function (error) {
638
- trace.warn('Error while removing publisher', error);
409
+
410
+ trace.info('connectToSession', sessionParams);
411
+ var allowedValues = values_1["default"](MediaConstants_1.MediaServiceType);
412
+
413
+ switch (_this._serviceOptions.mediaServiceType) {
414
+ case MediaConstants_1.MediaServiceType.TURNSERVER:
415
+ _this._session.instance = new SessionTurn_1.TurnWebRtcSession(mediaSessionParams, sessionHandlers, _this._sessionStreamsManager);
416
+ break;
417
+
418
+ case MediaConstants_1.MediaServiceType.OPENTOK:
419
+ _this._session.instance = new SessionOpentok_1.OpentokSession(mediaSessionParams, _this._sessionStreamsManager);
420
+ break;
421
+
422
+ case MediaConstants_1.MediaServiceType.MEDIASERVER:
423
+ _this._session.instance = new MediaServer_1.MediaServerSession(mediaSessionParams, _this._sessionStreamsManager);
424
+ break;
425
+
426
+ default:
427
+ trace.error("mediaServiceType '" + _this._serviceOptions.mediaServiceType + "' is not supported.", {
428
+ allowedValues: allowedValues
639
429
  });
430
+ doAsyncReject(new Error('mediaServiceType is not supported'));
640
431
  }
641
- return Promise.resolve();
642
- };
643
- TechseeMediaServiceBase.prototype.getStreamForDestinationRole = function (destinationRole) {
644
- var _this = this;
645
- this.serviceInitGuard();
646
- if (this._publishers.has(destinationRole)) {
647
- trace.info("Publisher for " + destinationRole + " already exists");
648
- return Promise.resolve(this._publishers.get(destinationRole).mediaStream);
649
- }
650
- if (!this._publisherPromises.get(destinationRole)) {
651
- trace.info("Creating publisher for " + destinationRole);
652
- var publisherPromise = this.initLocalMediaStreams().then(function () {
653
- return _this.createMediaPublisher(destinationRole);
654
- }).then(function (mediaPublisher) {
655
- if (mediaPublisher) {
656
- _this._publishers.set(destinationRole, mediaPublisher);
657
- }
658
- _this._publisherPromises.delete(destinationRole);
659
- return mediaPublisher ? mediaPublisher.mediaStream : null;
660
- }).catch(function (ex) {
661
- if (ex && ex.message === 'audioStreamFailed') {
662
- _this._isVoipEnabled = false;
663
- return null;
664
- }
665
- _this._publisherPromises.delete(destinationRole);
666
- throw ex;
667
- });
668
- this._publisherPromises.set(destinationRole, publisherPromise);
432
+
433
+ if (_this._session && _this._session.instance) {
434
+ _this._session.instance.connect().then(function () {
435
+ trace.info('Session is connected');
436
+ resolve();
437
+ })["catch"](function (error) {
438
+ trace.error('Failed to connect to session', error);
439
+ doAsyncReject(error);
440
+ });
441
+ }
442
+ });
443
+ } else {
444
+ trace.warn('Session connected already. Disconnect before connect to new session again');
445
+ } //TODO - Alex: Change a structure of this function to be more safe
446
+ //(when we return, there should not be case when session or promise is null)
447
+ //To fix, need to return promise immediately, then execute process in setTimeout(fn, 0);
448
+
449
+
450
+ return this._session.connectPromise;
451
+ }; //#endregion Media Streams Management
452
+ //#region Session Management
453
+
454
+ /*
455
+ Creates instance of WebRTC session which connects to (signaling server), and begins to listen to WebRTC events.
456
+ */
457
+
458
+
459
+ TechseeMediaServiceBase.prototype.connectToSession = function (sessionParams) {
460
+ return this._connectToSession(sessionParams);
461
+ };
462
+ /*
463
+ Disconnects from WebRTC session.
464
+ */
465
+
466
+
467
+ TechseeMediaServiceBase.prototype.disconnectFromSession = function () {
468
+ return this.disconnectFromSessionInternal(MediaConstants_1.MediaSessionDisconnectReason.ForcedByConsumer);
469
+ };
470
+ /*
471
+ Updates a credentials for turn server
472
+ */
473
+
474
+
475
+ TechseeMediaServiceBase.prototype.updateSessionCredentials = function (credentials) {
476
+ trace.info('updateSessionCredentials');
477
+
478
+ if (!this.sessionExistsGuard(false)) {
479
+ return Promise.reject('There no session to update credentials');
480
+ }
481
+
482
+ this._session.params.credentials = cloneDeep_1["default"](credentials);
483
+ return Promise.resolve();
484
+ };
485
+
486
+ TechseeMediaServiceBase.prototype.enableVoipDuringSession = function () {
487
+ if (!this._isVoipEnabled && this.isLocalStreamInitialized) {
488
+ this._initLocalStreamsPromise = null;
489
+ }
490
+
491
+ this._isVoipEnabled = true;
492
+ };
493
+
494
+ TechseeMediaServiceBase.prototype.disconnectFromSessionInternal = function (reason) {
495
+ if (!this._session) {
496
+ return Promise.resolve();
497
+ }
498
+
499
+ trace.info('Disconnecting from session', reason);
500
+ var lastSession = this._session;
501
+ this._session = null;
502
+ return Promise.all([lastSession.instance.disconnect(), this.clearPublishers()]).then(function () {
503
+ return undefined;
504
+ });
505
+ };
506
+
507
+ TechseeMediaServiceBase.prototype.getStatsForRemoteTrack = function (streamType) {
508
+ if (!this.sessionExistsGuard(false)) {
509
+ return Promise.reject(new Error('Media session not started'));
510
+ }
511
+
512
+ var streamForStats = this.getRegisteredStreamByType(streamType);
513
+
514
+ if (!streamForStats) {
515
+ return Promise.reject(new Error('Stream for requested type was not found'));
516
+ }
517
+
518
+ return this._session.instance.getRemoteTrackStats(streamForStats.mediaTrack).then(function (trackStats) {
519
+ traceStatsInfo("MediaTrackStats for " + streamType + ": " + JSON.stringify(trackStats));
520
+ return {
521
+ trackId: streamForStats.mediaTrack.id,
522
+ trackStats: trackStats
523
+ };
524
+ });
525
+ };
526
+
527
+ TechseeMediaServiceBase.prototype.onSessionDisconnectHandler = function (reason) {
528
+ var _this = this;
529
+
530
+ trace.info('onSessionDisconnectHandler', reason);
531
+
532
+ if (reason !== MediaConstants_1.MediaSessionDisconnectReason.ForcedByConsumer) {
533
+ var lastParams_1 = this._session && this._session.params ? this._session.params : null;
534
+ this.disconnectFromSessionInternal(reason).then(function () {
535
+ var reconnectReasons = [MediaConstants_1.MediaSessionDisconnectReason.InitiatorPeerReconnected, MediaConstants_1.MediaSessionDisconnectReason.SignalingChannelDisconnect, MediaConstants_1.MediaSessionDisconnectReason.PeerConnectionInterrupted, MediaConstants_1.MediaSessionDisconnectReason.PeerConnectionStateChangeTimeout];
536
+
537
+ if (lastParams_1 && includes_1["default"](reconnectReasons, reason) && _this._autoReconnectEnabled) {
538
+ _this.reconnectToSession(lastParams_1);
539
+ } else if (!_this._autoReconnectEnabled) {
540
+ trace.info('No reconnection- auto reconnect disabled');
669
541
  } else {
670
- trace.info("Create publisher promise for " + destinationRole + " already exists");
542
+ trace.info('No params for reconnection to media session');
671
543
  }
672
- return this._publisherPromises.get(destinationRole);
673
- };
674
- TechseeMediaServiceBase.prototype.updateSubscribersWithNewStream = function (registeredStream) {
675
- trace.info("Updating subscribers of " + registeredStream.streamType + " with new stream");
676
- if (this._subscribers.size === 0) {
677
- trace.warn("No subscribers exists for the " + registeredStream.streamType + ".");
678
- } else {
679
- trace.info("Total " + this._subscribers.size + " subscribers exists, will check if rerender needed.");
544
+ });
545
+ } else {
546
+ trace.info('Ignore Session disconnect event');
547
+ }
548
+ };
549
+
550
+ TechseeMediaServiceBase.prototype.setAutoReconnect = function (state) {
551
+ this._autoReconnectEnabled = state;
552
+ trace.info('_autoReconnectEnabled:', state);
553
+
554
+ if (this._autoReconnectEnabled && !this.isSessionActive) {
555
+ var lastParams = this._session && this._session.params ? this._session.params : null;
556
+
557
+ if (lastParams) {
558
+ trace.info('setAutoReconnect - reconnect to session');
559
+ this.reconnectToSession(lastParams);
560
+ }
561
+ }
562
+ };
563
+
564
+ TechseeMediaServiceBase.prototype.reconnectToSession = function (lastParams) {
565
+ trace.info('Reconnecting to media session, sessionParams:', lastParams);
566
+
567
+ this._connectToSession(lastParams).then(function () {
568
+ trace.info('Media session reconnected');
569
+ })["catch"](function (error) {
570
+ trace.error('Error while reconnecting to media session', error);
571
+ });
572
+ }; //#endregion Session Management
573
+ //#region Utils
574
+
575
+
576
+ TechseeMediaServiceBase.prototype.getSnapshotFromKnownStream = function (sourceStream, snapshotOptions) {
577
+ var _this = this;
578
+
579
+ return new Promise(function (resolve, reject) {
580
+ if (sourceStream !== MediaConstants_1.KnownMediaStream.USER_VIDEO_STREAM && sourceStream !== MediaConstants_1.KnownMediaStream.USER_SCREEN_SHARE_STREAM) {
581
+ trace.error('The requested stream is not video stream, and cannot be used for snapshot');
582
+ reject(new Error('INCOMPATIBLE_STREAM_FOR_SNAPSHOT'));
583
+ return;
584
+ }
585
+
586
+ var snapshotStream = _this.getRegisteredStreamByType(sourceStream);
587
+
588
+ if (!snapshotStream) {
589
+ trace.error('Cannot make snapshot: The requested stream not exists yet.');
590
+ reject(new Error('NO_REQUESTED_STREAM'));
591
+ return;
592
+ }
593
+
594
+ MediaDomUtils_1.getSnapshotFromMediaStream(snapshotStream.mediaStream, sourceStream, snapshotOptions).then(function (imageData) {
595
+ var urlComponents = imageData.split(';base64,');
596
+ var mimeType = urlComponents[0].split(':')[1];
597
+ var bytes = atob(urlComponents[1]);
598
+ var buffer = new ArrayBuffer(bytes.length);
599
+ var rawData = new Uint8Array(buffer);
600
+
601
+ for (var i = 0; i < bytes.length; i++) {
602
+ rawData[i] = bytes.charCodeAt(i);
680
603
  }
681
- this._subscribers.forEach(function (subscriber) {
682
- if (subscriber.streamType === registeredStream.streamType) {
683
- trace.info(registeredStream.streamType + " rendering on subscriber");
684
- subscriber.renderStream(registeredStream);
685
- }
686
- });
687
- return Promise.resolve();
688
- };
689
- TechseeMediaServiceBase.prototype.bindClassMethods = function () {
690
- this.updateSessionCredentials = this.updateSessionCredentials.bind(this);
691
- this.getStreamForDestinationRole = this.getStreamForDestinationRole.bind(this);
692
- this.registerRemoteMediaTrack = this.registerRemoteMediaTrack.bind(this);
693
- this.unregisterRemoteMediaTrack = this.unregisterRemoteMediaTrack.bind(this);
694
- this.createMediaPublisher = this.createMediaPublisher.bind(this);
695
- this.updateSubscribersWithNewStream = this.updateSubscribersWithNewStream.bind(this);
696
- this.initLocalMediaStreams = this.initLocalMediaStreams.bind(this);
697
- this.onSessionDisconnectHandler = this.onSessionDisconnectHandler.bind(this);
698
- this.clearService = this.clearService.bind(this);
699
- this.clearRegisteredStreams = this.clearRegisteredStreams.bind(this);
700
- this.clearPublishers = this.clearPublishers.bind(this);
701
- this.clearSubscribers = this.clearSubscribers.bind(this);
702
- this._connectToSession = this._connectToSession.bind(this);
703
- this.disconnectFromMediaSession = this.disconnectFromMediaSession.bind(this);
704
- };
705
- //region Cleanup
706
- TechseeMediaServiceBase.prototype.clearRegisteredStreams = function () {
707
- var _this = this;
708
- trace.info('Clearing registered streams');
709
- var promises = [];
710
- this._registeredStreams.forEach(function (streamToUnregister) {
711
- promises.push(_this.unregisterTechseeMediaStream(streamToUnregister, MediaConstants_1.MediaStreamUnregisterReason.ServiceCleanUp));
712
- });
713
- return Promise.all(promises).then(function () {
714
- return undefined;
715
- });
716
- };
717
- TechseeMediaServiceBase.prototype.clearSubscribers = function () {
718
- var _this = this;
719
- trace.info('Clearing subscribers');
720
- var promises = [];
721
- this._subscribers.forEach(function (subscriber) {
722
- promises.push(_this.destroySubscriber(subscriber.container));
604
+
605
+ var blob = new Blob([rawData], {
606
+ type: mimeType
723
607
  });
724
- return Promise.all(promises).then(function () {
725
- return undefined;
608
+ var objectUrl = window.URL.createObjectURL(blob);
609
+ trace.info('Snapshot created successfully');
610
+ var result = {
611
+ base64img: imageData,
612
+ objectUrl: objectUrl,
613
+ imageBlob: blob,
614
+ mimeType: mimeType
615
+ };
616
+ resolve(result);
617
+ })["catch"](function (error) {
618
+ trace.error('Error creating snapshot', error);
619
+ reject(error);
620
+ });
621
+ });
622
+ }; //Will clean streams, publishers and subscribers, but will not remove event listeners
623
+
624
+
625
+ TechseeMediaServiceBase.prototype.clearService = function () {
626
+ var _this = this;
627
+
628
+ trace.info('MediaService clearing all resources');
629
+ return this.disconnectFromSessionInternal(MediaConstants_1.MediaSessionDisconnectReason.ForcedByConsumer).then(this.clearSubscribers).then(this.clearRegisteredStreams).then(this._localStreamsManager.clearAllStreams).then(function () {
630
+ _this._initLocalStreamsPromise = null;
631
+ _this._isVoipEnabled = false;
632
+ }).then(function () {
633
+ return undefined;
634
+ });
635
+ }; //Will clear the service and remove all event listeners
636
+
637
+
638
+ TechseeMediaServiceBase.prototype.dispose = function () {
639
+ var _this = this;
640
+
641
+ return this.clearService()["catch"](function () {
642
+ return undefined;
643
+ }).then(function () {
644
+ _this._emitter.removeAllListeners();
645
+ });
646
+ };
647
+
648
+ Object.defineProperty(TechseeMediaServiceBase.prototype, "subscribers", {
649
+ //#endregion
650
+ //#region Protected Methods
651
+ get: function get() {
652
+ return this._subscribers;
653
+ },
654
+ enumerable: false,
655
+ configurable: true
656
+ });
657
+
658
+ TechseeMediaServiceBase.prototype.registerLocalMediaStream = function (tsMediaStream) {
659
+ trace.info('Registering local stream', tsMediaStream.streamType);
660
+
661
+ if (this._registeredStreams.has(tsMediaStream.streamType)) {
662
+ return Promise.reject(new Error("Stream " + tsMediaStream.streamType + " already registered"));
663
+ }
664
+
665
+ return this.registerStream(tsMediaStream);
666
+ };
667
+
668
+ TechseeMediaServiceBase.prototype.getRegisteredStreamByType = function (streamType) {
669
+ return this._registeredStreams.get(streamType) || null;
670
+ };
671
+
672
+ TechseeMediaServiceBase.prototype.changeEnableForKnownStream = function (streamType, isPaused) {
673
+ var streamToChangeState = this.getRegisteredStreamByType(streamType);
674
+
675
+ if (!streamToChangeState) {
676
+ trace.warn('There no stream found to change enable state', streamType);
677
+ } else {
678
+ streamToChangeState.mediaTrack.enabled = !isPaused;
679
+
680
+ if (streamToChangeState.isRemote && streamToChangeState.streamKind === MediaConstants_1.KnownMediaStreamKind.Audio) {
681
+ this.subscribers.forEach(function (subscriber) {
682
+ if (subscriber.streamType === streamType) {
683
+ subscriber.muteSound(isPaused);
684
+ }
726
685
  });
686
+ }
687
+
688
+ trace.info('Local stream enable state is changed', {
689
+ streamType: streamType,
690
+ isPaused: isPaused
691
+ });
692
+ }
693
+ };
694
+
695
+ TechseeMediaServiceBase.prototype.registerEventCallback = function (event, callback) {
696
+ this._emitter.on(event, callback);
697
+ };
698
+
699
+ TechseeMediaServiceBase.prototype.unregisterEventCallback = function (event, callback) {
700
+ this._emitter.off(event, callback);
701
+ };
702
+
703
+ TechseeMediaServiceBase.prototype.emitEvent = function (event, eventArgs) {
704
+ var _this = this;
705
+
706
+ setTimeout(function () {
707
+ _this._emitter.emit(event, eventArgs);
708
+ });
709
+ }; //#endregion Protected Methods
710
+ //#region Private Methods
711
+
712
+
713
+ TechseeMediaServiceBase.prototype.registerRemoteMediaTrack = function (remoteMediaTrack) {
714
+ trace.info("Registering remote " + remoteMediaTrack.trackType + " MediaStreamTrack", remoteMediaTrack.mediaTrack);
715
+
716
+ var currentStream = this._registeredStreams.get(remoteMediaTrack.trackType);
717
+
718
+ if (currentStream && !currentStream.isRemote) {
719
+ return Promise.reject(new Error('Cannot register remote stream with the same type as local stream'));
720
+ }
721
+
722
+ var newDedicatedStream = new TechseeMediaStream_1.TechseeMediaStream(remoteMediaTrack.mediaTrack, remoteMediaTrack.trackType, true);
723
+ return this.registerStream(newDedicatedStream);
724
+ };
725
+
726
+ TechseeMediaServiceBase.prototype.registerTrack = function (mediaStream) {
727
+ var _this = this;
728
+
729
+ mediaStream.mediaTrack.onended = function () {
730
+ return _this.unregisterTechseeMediaStream(mediaStream, MediaConstants_1.MediaStreamUnregisterReason.NativeEvent);
727
731
  };
728
- TechseeMediaServiceBase.prototype.clearPublishers = function () {
729
- var _this = this;
730
- trace.info('Clearing publishers');
731
- var promises = [];
732
- this._publishers.forEach(function (publisher) {
733
- promises.push(_this.removePublisher(publisher));
734
- });
735
- return Promise.all(promises).then(function () {
736
- return undefined;
737
- });
732
+
733
+ this._registeredStreams.set(mediaStream.streamType, mediaStream);
734
+
735
+ trace.info("TechseeMediaStream registered - " + mediaStream.streamType, TechseeMediaStream_1.TechseeMediaStream);
736
+ return this.updateSubscribersWithNewStream(mediaStream).then(function () {
737
+ var eventArgs = {
738
+ streamType: mediaStream.streamType
739
+ };
740
+
741
+ _this.emitEvent(privateEvents.STREAM_CREATED, eventArgs);
742
+ });
743
+ };
744
+
745
+ TechseeMediaServiceBase.prototype.registerStream = function (mediaStream) {
746
+ var _this = this;
747
+
748
+ var currentStream = this._registeredStreams.get(mediaStream.streamType);
749
+
750
+ if (currentStream) {
751
+ return this.unregisterTechseeMediaStream(currentStream, MediaConstants_1.MediaStreamUnregisterReason.ReplacingStream).then(function () {
752
+ return _this.registerTrack(mediaStream);
753
+ });
754
+ }
755
+
756
+ return this.registerTrack(mediaStream);
757
+ };
758
+
759
+ TechseeMediaServiceBase.prototype.unregisterTechseeMediaStream = function (streamToUnregister, reason) {
760
+ var _this = this;
761
+
762
+ var traceError = function traceError(error) {
763
+ trace.warn('Unregister TechseeMediaStream error:', error);
738
764
  };
739
- //#endregion Cleanup
740
- //#region Simple Validation Methods
741
- TechseeMediaServiceBase.prototype.serviceInitGuard = function (shouldThrow) {
742
- if (shouldThrow === void 0) {
743
- shouldThrow = true;
765
+
766
+ var promises = [];
767
+ trace.info('Unregister TechseeMediaStream: ', streamToUnregister.streamType);
768
+
769
+ this._subscribers.forEach(function (subscriber) {
770
+ if (subscriber.streamType === streamToUnregister.streamType) {
771
+ promises.push(subscriber.stopRendering()["catch"](traceError));
772
+ }
773
+ });
774
+
775
+ if (!streamToUnregister.isRemote) {
776
+ this._publishers.forEach(function (publisher) {
777
+ if (publisher.streamTypes.find(function (streamType) {
778
+ return streamType === streamToUnregister.streamType;
779
+ })) {
780
+ if (_this._session && _this._session.instance) {
781
+ promises.push(_this._session.instance.onMediaStreamDestroyed(publisher.destinationRole)["catch"](traceError));
782
+ }
783
+ }
784
+ });
785
+ }
786
+
787
+ return Promise.all(promises).then(function () {
788
+ _this._registeredStreams["delete"](streamToUnregister.streamType);
789
+
790
+ trace.info('Stream deleted', streamToUnregister.streamType);
791
+ var eventArgs = {
792
+ streamType: streamToUnregister.streamType,
793
+ reason: reason
794
+ };
795
+
796
+ _this.emitEvent(privateEvents.STREAM_DESTROYED, eventArgs);
797
+ });
798
+ };
799
+
800
+ TechseeMediaServiceBase.prototype.unregisterRemoteMediaTrack = function (mediaTrack) {
801
+ var _this = this;
802
+
803
+ var promises = [];
804
+
805
+ this._registeredStreams.forEach(function (registeredStream) {
806
+ if (registeredStream.mediaTrack.id === mediaTrack.id) {
807
+ promises.push(_this.unregisterTechseeMediaStream(registeredStream, MediaConstants_1.MediaStreamUnregisterReason.ClosedRemotely));
808
+ }
809
+ });
810
+
811
+ return Promise.all(promises).then(function () {
812
+ return undefined;
813
+ });
814
+ };
815
+
816
+ TechseeMediaServiceBase.prototype.removePublisher = function (publisher) {
817
+ this._publishers["delete"](publisher.destinationRole);
818
+
819
+ if (this._session && this._session.instance) {
820
+ trace.info('Removing publisher', publisher.destinationRole);
821
+ return this._session.instance.onMediaStreamDestroyed(publisher.destinationRole)["catch"](function (error) {
822
+ trace.warn('Error while removing publisher', error);
823
+ });
824
+ }
825
+
826
+ return Promise.resolve();
827
+ };
828
+
829
+ TechseeMediaServiceBase.prototype.getStreamForDestinationRole = function (destinationRole) {
830
+ var _this = this;
831
+
832
+ this.serviceInitGuard();
833
+
834
+ if (this._publishers.has(destinationRole)) {
835
+ trace.info("Publisher for " + destinationRole + " already exists");
836
+ return Promise.resolve(this._publishers.get(destinationRole).mediaStream);
837
+ }
838
+
839
+ if (!this._publisherPromises.get(destinationRole)) {
840
+ trace.info("Creating publisher for " + destinationRole);
841
+ var publisherPromise = this.initLocalMediaStreams().then(function () {
842
+ return _this.createMediaPublisher(destinationRole);
843
+ }).then(function (mediaPublisher) {
844
+ if (mediaPublisher) {
845
+ _this._publishers.set(destinationRole, mediaPublisher);
744
846
  }
745
- return guards_1.throwableGuard(!!this._serviceOptions, 'Media service is not initialized', shouldThrow);
746
- };
747
- TechseeMediaServiceBase.prototype.sessionExistsGuard = function (shouldThrow) {
748
- if (shouldThrow === void 0) {
749
- shouldThrow = true;
847
+
848
+ _this._publisherPromises["delete"](destinationRole);
849
+
850
+ return mediaPublisher ? mediaPublisher.mediaStream : null;
851
+ })["catch"](function (ex) {
852
+ if (ex && ex.message === 'audioStreamFailed') {
853
+ _this._isVoipEnabled = false;
854
+ return null;
750
855
  }
751
- return guards_1.throwableGuard(!!this._session, 'There no active session', shouldThrow);
752
- };
753
- return TechseeMediaServiceBase;
856
+
857
+ _this._publisherPromises["delete"](destinationRole);
858
+
859
+ throw ex;
860
+ });
861
+
862
+ this._publisherPromises.set(destinationRole, publisherPromise);
863
+ } else {
864
+ trace.info("Create publisher promise for " + destinationRole + " already exists");
865
+ }
866
+
867
+ return this._publisherPromises.get(destinationRole);
868
+ };
869
+
870
+ TechseeMediaServiceBase.prototype.updateSubscribersWithNewStream = function (registeredStream) {
871
+ trace.info("Updating subscribers of " + registeredStream.streamType + " with new stream");
872
+
873
+ if (this._subscribers.size === 0) {
874
+ trace.warn("No subscribers exists for the " + registeredStream.streamType + ".");
875
+ } else {
876
+ trace.info("Total " + this._subscribers.size + " subscribers exists, will check if rerender needed.");
877
+ }
878
+
879
+ this._subscribers.forEach(function (subscriber) {
880
+ if (subscriber.streamType === registeredStream.streamType) {
881
+ trace.info(registeredStream.streamType + " rendering on subscriber");
882
+ subscriber.renderStream(registeredStream);
883
+ }
884
+ });
885
+
886
+ return Promise.resolve();
887
+ };
888
+
889
+ TechseeMediaServiceBase.prototype.bindClassMethods = function () {
890
+ this.updateSessionCredentials = this.updateSessionCredentials.bind(this);
891
+ this.getStreamForDestinationRole = this.getStreamForDestinationRole.bind(this);
892
+ this.registerRemoteMediaTrack = this.registerRemoteMediaTrack.bind(this);
893
+ this.unregisterRemoteMediaTrack = this.unregisterRemoteMediaTrack.bind(this);
894
+ this.createMediaPublisher = this.createMediaPublisher.bind(this);
895
+ this.updateSubscribersWithNewStream = this.updateSubscribersWithNewStream.bind(this);
896
+ this.initLocalMediaStreams = this.initLocalMediaStreams.bind(this);
897
+ this.onSessionDisconnectHandler = this.onSessionDisconnectHandler.bind(this);
898
+ this.clearService = this.clearService.bind(this);
899
+ this.clearRegisteredStreams = this.clearRegisteredStreams.bind(this);
900
+ this.clearPublishers = this.clearPublishers.bind(this);
901
+ this.clearSubscribers = this.clearSubscribers.bind(this);
902
+ this._connectToSession = this._connectToSession.bind(this);
903
+ this.disconnectFromMediaSession = this.disconnectFromMediaSession.bind(this);
904
+ }; //region Cleanup
905
+
906
+
907
+ TechseeMediaServiceBase.prototype.clearRegisteredStreams = function () {
908
+ var _this = this;
909
+
910
+ trace.info('Clearing registered streams');
911
+ var promises = [];
912
+
913
+ this._registeredStreams.forEach(function (streamToUnregister) {
914
+ promises.push(_this.unregisterTechseeMediaStream(streamToUnregister, MediaConstants_1.MediaStreamUnregisterReason.ServiceCleanUp));
915
+ });
916
+
917
+ return Promise.all(promises).then(function () {
918
+ return undefined;
919
+ });
920
+ };
921
+
922
+ TechseeMediaServiceBase.prototype.clearSubscribers = function () {
923
+ var _this = this;
924
+
925
+ trace.info('Clearing subscribers');
926
+ var promises = [];
927
+
928
+ this._subscribers.forEach(function (subscriber) {
929
+ promises.push(_this.destroySubscriber(subscriber.container));
930
+ });
931
+
932
+ return Promise.all(promises).then(function () {
933
+ return undefined;
934
+ });
935
+ };
936
+
937
+ TechseeMediaServiceBase.prototype.clearPublishers = function () {
938
+ var _this = this;
939
+
940
+ trace.info('Clearing publishers');
941
+ var promises = [];
942
+
943
+ this._publishers.forEach(function (publisher) {
944
+ promises.push(_this.removePublisher(publisher));
945
+ });
946
+
947
+ return Promise.all(promises).then(function () {
948
+ return undefined;
949
+ });
950
+ }; //#endregion Cleanup
951
+ //#region Simple Validation Methods
952
+
953
+
954
+ TechseeMediaServiceBase.prototype.serviceInitGuard = function (shouldThrow) {
955
+ if (shouldThrow === void 0) {
956
+ shouldThrow = true;
957
+ }
958
+
959
+ return guards_1.throwableGuard(!!this._serviceOptions, 'Media service is not initialized', shouldThrow);
960
+ };
961
+
962
+ TechseeMediaServiceBase.prototype.sessionExistsGuard = function (shouldThrow) {
963
+ if (shouldThrow === void 0) {
964
+ shouldThrow = true;
965
+ }
966
+
967
+ return guards_1.throwableGuard(!!this._session, 'There no active session', shouldThrow);
968
+ };
969
+
970
+ return TechseeMediaServiceBase;
754
971
  }();
755
- exports.TechseeMediaServiceBase = TechseeMediaServiceBase;
756
972
 
757
- //# sourceMappingURL=MediaServiceBase.js.map
973
+ exports.TechseeMediaServiceBase = TechseeMediaServiceBase;
758
974
  //# sourceMappingURL=MediaServiceBase.js.map