@techsee/techsee-media-service 0.1.3

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 (44) hide show
  1. package/README.md +1 -0
  2. package/lib/constants.js +20 -0
  3. package/lib/constants.js.map +1 -0
  4. package/lib/event-emitter.js +39 -0
  5. package/lib/event-emitter.js.map +1 -0
  6. package/lib/index.js +64 -0
  7. package/lib/index.js.map +1 -0
  8. package/lib/opentok/session.js +304 -0
  9. package/lib/opentok/session.js.map +1 -0
  10. package/lib/opentok/stream.js +310 -0
  11. package/lib/opentok/stream.js.map +1 -0
  12. package/lib/publisher.js +143 -0
  13. package/lib/publisher.js.map +1 -0
  14. package/lib/qos/raw-qos.js +319 -0
  15. package/lib/qos/raw-qos.js.map +1 -0
  16. package/lib/service.js +316 -0
  17. package/lib/service.js.map +1 -0
  18. package/lib/session.js +104 -0
  19. package/lib/session.js.map +1 -0
  20. package/lib/stream.js +195 -0
  21. package/lib/stream.js.map +1 -0
  22. package/lib/subscriber.js +90 -0
  23. package/lib/subscriber.js.map +1 -0
  24. package/lib/webrtc/constants.js +112 -0
  25. package/lib/webrtc/constants.js.map +1 -0
  26. package/lib/webrtc/helper.js +169 -0
  27. package/lib/webrtc/helper.js.map +1 -0
  28. package/lib/webrtc/session-kms.js +558 -0
  29. package/lib/webrtc/session-kms.js.map +1 -0
  30. package/lib/webrtc/session-loopback.js +340 -0
  31. package/lib/webrtc/session-loopback.js.map +1 -0
  32. package/lib/webrtc/session-turn.js +807 -0
  33. package/lib/webrtc/session-turn.js.map +1 -0
  34. package/lib/webrtc/session-turn.v2.js +2 -0
  35. package/lib/webrtc/session-turn.v2.js.map +1 -0
  36. package/lib/webrtc/session.js +40 -0
  37. package/lib/webrtc/session.js.map +1 -0
  38. package/lib/webrtc/stream.js +631 -0
  39. package/lib/webrtc/stream.js.map +1 -0
  40. package/lib/webrtc/temasys/adapter-loader.js +12 -0
  41. package/lib/webrtc/temasys/adapter-loader.js.map +1 -0
  42. package/lib/webrtc/temasys/adapter.js +5861 -0
  43. package/lib/webrtc/temasys/adapter.js.map +1 -0
  44. package/package.json +53 -0
@@ -0,0 +1,807 @@
1
+ 'use strict';
2
+
3
+ exports.__esModule = true;
4
+ exports.TurnWebRTCSession = undefined;
5
+
6
+ var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
7
+
8
+ var _session = require('../session');
9
+
10
+ var _publisher = require('../publisher');
11
+
12
+ var _stream = require('./stream');
13
+
14
+ var _socket = require('socket.io-client');
15
+
16
+ var io = _interopRequireWildcard(_socket);
17
+
18
+ var _tsEnvironmentDetect = require('techsee-common/lib/helpers/ts-environment-detect');
19
+
20
+ var _constants = require('./constants');
21
+
22
+ var _helper = require('./helper');
23
+
24
+ function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
25
+
26
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
27
+
28
+ function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
29
+
30
+ function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
31
+
32
+ var isIE11 = new _tsEnvironmentDetect.TsEnvironmentDetect().isIE11();
33
+
34
+ var _ref = isIE11 ? require('kurento-utils-temasys-mod') : require('kurento-utils'),
35
+ WebRtcPeer = _ref.WebRtcPeer; // eslint-disable-line global-require
36
+
37
+ var AdapterJS = void 0;
38
+
39
+ if (isIE11) {
40
+ AdapterJS = require('./temasys/adapter-loader')(); // eslint-disable-line global-require
41
+ }
42
+
43
+ /**
44
+ * WebRTC-specific implementation of TsMediaSession.
45
+ *
46
+ * Instance of this class is returned by TsMediaService.initSession call
47
+ * with 'TURN_SERVER' as desired mediaType.
48
+ *
49
+ * @class
50
+ * @extends TsMediaSession
51
+ *
52
+ * @see TsMediaSession
53
+ */
54
+ var TurnWebRTCSession = exports.TurnWebRTCSession = function (_TsMediaSession) {
55
+ _inherits(TurnWebRTCSession, _TsMediaSession);
56
+
57
+ function TurnWebRTCSession(_ref2, localStreamFactory) {
58
+ var credentials = _ref2.credentials,
59
+ isMobile = _ref2.isMobile,
60
+ resolution = _ref2.resolution,
61
+ deviceOpts = _ref2.deviceOpts;
62
+
63
+ _classCallCheck(this, TurnWebRTCSession);
64
+
65
+ var _this = _possibleConstructorReturn(this, _TsMediaSession.call(this));
66
+
67
+ _this._credentials = credentials;
68
+ _this._isMobile = isMobile;
69
+ _this._resolution = resolution;
70
+ _this._deviceOpts = deviceOpts;
71
+ _this._incomingIce = [];
72
+ _this._localStreamFactory = localStreamFactory;
73
+
74
+ var iceServers = credentials.ice.map(function (item) {
75
+ return {
76
+ urls: item.url,
77
+ username: item.login,
78
+ credential: item.password
79
+ };
80
+ });
81
+
82
+ _this._configuration = {
83
+ iceServers: iceServers,
84
+
85
+ iceTransportPolicy: 'relay'
86
+ };
87
+
88
+ /**
89
+ * Socket.io connection to the signaling server
90
+ *
91
+ * @private
92
+ * @member { Object }
93
+ */
94
+ _this._socket = null;
95
+
96
+ /**
97
+ * RTCPeerConnection to the media server.
98
+ *
99
+ * For now kurento-utils is used for connection establishment.
100
+ *
101
+ * @private
102
+ * @member { Object }
103
+ */
104
+ _this._pcs = {};
105
+ return _this;
106
+ }
107
+
108
+ /**
109
+ * Id of the session.
110
+ *
111
+ * @member { String }
112
+ *
113
+ * @type { String }
114
+ */
115
+
116
+
117
+ /**
118
+ *
119
+ * @member { String }
120
+ *
121
+ * @type { String }
122
+ */
123
+ TurnWebRTCSession.prototype._connectSocket = function _connectSocket(url) {
124
+ var _this2 = this;
125
+
126
+ return new Promise(function (resolve, reject) {
127
+ var socket = io.connect(url, {
128
+ 'forceNew': true,
129
+ 'reconnectionDelay': _constants.SOCKET_RECONNECTION_DELAY,
130
+ 'reconnectionDelayMax': _constants.SOCKET_RECONNECTION_DELAY_MAX,
131
+ 'reconnectionAttempts': _constants.SOCKET_RECONNECTION_ATTEMPTS,
132
+ 'path': _constants.SOCKET_PATH
133
+ });
134
+
135
+ var done = _.once(function (err) {
136
+ err ? reject(err) : resolve();
137
+ });
138
+
139
+ //
140
+ // When connection is established
141
+ //
142
+ socket.once('connect', function () {
143
+ return done();
144
+ });
145
+ //
146
+ // errorOccured is ts-media-client signal
147
+ //
148
+ socket.on(_constants.SOCKET_EVENTS.INCOMING.ERROR, done);
149
+ //
150
+ // And these 2 are socket.io connection failed events
151
+ //
152
+ socket.on('connect_error', done);
153
+ socket.on('connect_timeout', done);
154
+
155
+ socket.on(_constants.SOCKET_EVENTS.INCOMING.JOIN_RESPONSE, function (_ref3) {
156
+ var sdpAnswer = _ref3.sdpAnswer,
157
+ uid = _ref3.uid,
158
+ peerId = _ref3.peerId;
159
+
160
+ var pc = _this2._pcs[peerId];
161
+
162
+ if (!pc) {
163
+ var error = 'pc not found. peer=' + peerId + ' uid=' + uid;
164
+
165
+ _this2.emit(_session.EVENTS.EXCEPTION, { source: 'JOIN_RESPONSE', error: error });
166
+
167
+ return done(error);
168
+ }
169
+
170
+ pc.processAnswer(sdpAnswer, function (error) {
171
+ if (error) {
172
+ _this2.emit(_session.EVENTS.EXCEPTION, { source: 'processAnswer', error: error });
173
+
174
+ return done(error);
175
+ }
176
+
177
+ // FIXME why don't we have _incomingIce per PC? current assumes we don't have parallel connections, not good
178
+ _.forEach(_this2._incomingIce, function (candidate) {
179
+ pc.addIceCandidate(candidate, function (error) {
180
+ if (error) {
181
+ _this2.emit(_session.EVENTS.EXCEPTION, { source: 'JOIN_RESPONSE addIceCandidate', error: error });
182
+ }
183
+ });
184
+ });
185
+
186
+ _this2._incomingIce.length = 0;
187
+ });
188
+
189
+ _this2.emit(_session.EVENTS.CONNECTED);
190
+
191
+ _this2.publish(_this2.publisher).catch(function (error) {
192
+ _this2.emit(_session.EVENTS.EXCEPTION, { source: 'publish', error: error });
193
+ });
194
+ });
195
+
196
+ socket.on(_constants.SOCKET_EVENTS.INCOMING.ICE_CANDIDATE, function (_ref4) {
197
+ var candidate = _ref4.candidate,
198
+ peerId = _ref4.peerId;
199
+
200
+ var pc = _this2._pcs[peerId];
201
+
202
+ if (!pc) {
203
+ _this2._incomingIce.push(candidate);
204
+
205
+ return;
206
+ }
207
+
208
+ pc.addIceCandidate(candidate, function (error) {
209
+ if (error) {
210
+ _this2.emit(_session.EVENTS.EXCEPTION, { source: 'ICE_CANDIDATE addIceCandidate', error: error });
211
+ }
212
+ });
213
+ });
214
+
215
+ // Received by publisher, causing him to emit SDP_OFFER
216
+ socket.on(_constants.SOCKET_EVENTS.INCOMING.SEND_OFFER, function (_ref5) {
217
+ var uid = _ref5.uid,
218
+ peerId = _ref5.peerId;
219
+
220
+ _this2._createRTCPeerConnection(peerId).then(function (pc) {
221
+ pc.generateOffer(function (error, offer) {
222
+ if (error) {
223
+ return done(error);
224
+ }
225
+
226
+ socket.emit(_constants.SOCKET_EVENTS.OUTGOING.SDP_OFFER, {
227
+ uid: uid,
228
+ peerId: peerId,
229
+ sessionId: _this2._credentials.sessionId,
230
+ sdpOffer: offer
231
+ });
232
+ });
233
+ }).catch(function (error) {
234
+ _this2.emit(_session.EVENTS.EXCEPTION, { source: '_createRTCPeerConnection', error: error });
235
+ if (error && error.name) {
236
+ _this2.lastError = error.name;
237
+ }
238
+ });
239
+ });
240
+
241
+ // Received by subscriber, causing him to emit SDP_ANSWER
242
+ socket.on(_constants.SOCKET_EVENTS.INCOMING.SDP_OFFER, function (_ref6) {
243
+ var sdpOffer = _ref6.sdpOffer,
244
+ peerId = _ref6.peerId,
245
+ uid = _ref6.uid;
246
+
247
+ Promise.resolve().then(function () {
248
+ var pc = _this2._pcs[peerId];
249
+
250
+ if (pc) {
251
+ return pc;
252
+ }
253
+
254
+ return _this2._createRTCPeerConnection(peerId);
255
+ }).then(function (pc) {
256
+ pc.processOffer(sdpOffer, function (error, sdpAnswer) {
257
+ if (error) {
258
+ return done(error);
259
+ }
260
+
261
+ socket.emit(_constants.SOCKET_EVENTS.OUTGOING.SDP_ANSWER, {
262
+ uid: uid,
263
+ peerId: peerId,
264
+ sessionId: _this2._credentials.sessionId,
265
+ sdpAnswer: sdpAnswer
266
+ });
267
+ });
268
+ }).catch(function (error) {
269
+ _this2.emit(_session.EVENTS.EXCEPTION, { source: 'response on INCOMING.SDP_OFFER', error: error });
270
+ if (error && error.name) {
271
+ _this2.lastError = error.name;
272
+ }
273
+ });
274
+ });
275
+
276
+ // Received by subscriber after a publisher reconnects to room
277
+ socket.on(_constants.SOCKET_EVENTS.INCOMING.PUBLISHER_RECONNECT, function () {
278
+ // Clean up and reconnect with a new peer-connection,
279
+ // to prevent reconnection issues
280
+
281
+ _this2._streams.clear();
282
+ socket.off();
283
+ _.forEach(_this2._pcs, function (_ref7) {
284
+ var peerConnection = _ref7.peerConnection;
285
+ return peerConnection.close();
286
+ });
287
+ _this2._pcs = {};
288
+
289
+ _this2.emit(_session.EVENTS.RECONNECT_TURN_SERVER);
290
+ });
291
+
292
+ // Received by publisher after a subscriber's socket has been disconnected
293
+ socket.on(_constants.SOCKET_EVENTS.INCOMING.PEER_DISCONNECTED, function () {
294
+ var _ref8 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
295
+ peerId = _ref8.peerId;
296
+
297
+ if (peerId && _this2._pcs[peerId]) {
298
+ if (_this2._lastPc === _this2._pcs[peerId]) {
299
+ _this2._lastPc = null;
300
+ }
301
+
302
+ if (Object.getOwnPropertyNames(_this2._pcs).length === 1) {
303
+ _this2._toggleAllStreams(false);
304
+ }
305
+
306
+ _this2._pcs[peerId].peerConnection.close();
307
+
308
+ delete _this2._pcs[peerId];
309
+ }
310
+ });
311
+
312
+ _this2._socket = socket;
313
+ });
314
+ };
315
+
316
+ TurnWebRTCSession.prototype._setupConnection = function _setupConnection(pc) {
317
+ var _this3 = this;
318
+
319
+ return new Promise(function (resolve) {
320
+ pc.peerConnection.oniceconnectionstatechange = function (e) {
321
+ if (_this3.iceCheckingTimeout) {
322
+ clearTimeout(_this3.iceCheckingTimeout);
323
+ _this3.iceCheckingTimeout = null;
324
+ }
325
+
326
+ if (e.target.iceConnectionState === 'failed') {
327
+ // if this is one of many in the publisher, skip
328
+
329
+ // already attempting a reconnect
330
+ if (_this3._turnServerReconnectInterval) {
331
+ return;
332
+ }
333
+
334
+ _this3._turnServerReconnectInterval = setInterval(function () {
335
+ if (!navigator.onLine) {
336
+ return;
337
+ }
338
+
339
+ clearInterval(_this3._turnServerReconnectInterval);
340
+ _this3._turnServerReconnectInterval = null;
341
+
342
+ if (!_this3._socket.connected) {
343
+ _this3.disconnected = false;
344
+ _this3._socket.connect();
345
+ }
346
+
347
+ _this3.emit(_session.EVENTS.RECONNECT_TURN_SERVER);
348
+ }, _constants.RECONNECT_TURN_SERVER_INTERVAL);
349
+ } else if (e.target.iceConnectionState === 'checking') {
350
+ _this3.iceCheckingTimeout = setTimeout(function () {
351
+ _this3.emit(_session.EVENTS.TURN_SERVER_CONNECTION_FAILED);
352
+ }, _constants.FAILED_CONNECTING_TURN_SERVER_INTERVAL);
353
+ }
354
+ };
355
+
356
+ pc.peerConnection.onremovestream = function (_ref9) {
357
+ var stream = _ref9.stream;
358
+
359
+ _this3._streams.delete(stream.id);
360
+ };
361
+
362
+ resolve();
363
+ });
364
+ };
365
+
366
+ TurnWebRTCSession.prototype._getPeerType = function _getPeerType(constraints, isMobile) {
367
+ if (isMobile || constraints.audio) {
368
+ return _constants.PEER_CONNECTION_TYPES.SEND_RECV;
369
+ }
370
+
371
+ return _constants.PEER_CONNECTION_TYPES.RECV_ONLY;
372
+ };
373
+
374
+ TurnWebRTCSession.prototype._connectRTCPeer = function _connectRTCPeer(_ref10) {
375
+ var _this4 = this;
376
+
377
+ var constraints = _ref10.constraints,
378
+ configuration = _ref10.configuration,
379
+ sessionId = _ref10.sessionId,
380
+ isMobile = _ref10.isMobile,
381
+ peerId = _ref10.peerId;
382
+
383
+ return new Promise(function (resolve, reject) {
384
+ var done = _.once(function (err, pc) {
385
+ err ? reject(err) : resolve(pc);
386
+ });
387
+ var setupWebRtcPeer = function setupWebRtcPeer(stream) {
388
+ var peerConnectionType = _this4._getPeerType(constraints, isMobile);
389
+ var peerConfig = {
390
+ configuration: configuration,
391
+ videoStream: stream,
392
+ mediaConstraints: constraints,
393
+ onicecandidate: function onicecandidate(candidate) {
394
+ _this4._socket.emit(_constants.SOCKET_EVENTS.OUTGOING.ICE_CANDIDATE, {
395
+ sessionId: sessionId,
396
+ peerId: peerId,
397
+ candidate: candidate,
398
+ clientType: isMobile ? _constants.CLIENT_TYPES.PUBLISHER : _constants.CLIENT_TYPES.SUBSCRIBER
399
+ });
400
+ },
401
+ AdapterJS: AdapterJS
402
+ };
403
+ var pc = WebRtcPeer[peerConnectionType](peerConfig, function (error) {
404
+ if (error) {
405
+ return done(error);
406
+ }
407
+
408
+ _this4._setupConnection(pc).then(function () {
409
+ return done(null, pc);
410
+ }).catch(done);
411
+ });
412
+
413
+ _this4._pcs[peerId] = pc;
414
+ _this4._lastPc = pc;
415
+ };
416
+
417
+ _this4._localStreamFactory(constraints).then(function (localStream) {
418
+ setupWebRtcPeer(localStream);
419
+ }).catch(function () {
420
+ setupWebRtcPeer(undefined);
421
+ });
422
+ });
423
+ };
424
+
425
+ TurnWebRTCSession.prototype._setTrackStateTo = function _setTrackStateTo(state) {
426
+ return function (track) {
427
+ if (track.setEnabled) {
428
+ track.setEnabled(state);
429
+ } else {
430
+ track.enabled = state;
431
+ }
432
+ };
433
+ };
434
+
435
+ /**
436
+ * Establish socket and peer connection to the media server.
437
+ *
438
+ * @method
439
+ * @returns { Promise }
440
+ *
441
+ * @fires SESSION_EVENTS#CONNECTED
442
+ */
443
+
444
+
445
+ TurnWebRTCSession.prototype.connect = function connect() {
446
+ var _this5 = this;
447
+
448
+ return this._connectSocket(this._credentials.url).then(function () {
449
+ return (0, _helper.getMediaConstraints)({
450
+ resolution: _this5._resolution,
451
+ deviceOpts: _this5._deviceOpts
452
+ });
453
+ }).then(function (constraints) {
454
+ // streaming from dashboard is not supported and we
455
+ // don't want to access the camera without a reason
456
+ if (!_this5._isMobile && constraints.video) {
457
+ delete constraints.video;
458
+ }
459
+
460
+ _this5._constraints = constraints;
461
+
462
+ var clientType = _this5._isMobile ? _constants.CLIENT_TYPES.PUBLISHER : _constants.CLIENT_TYPES.SUBSCRIBER;
463
+
464
+ _this5._socket.emit(_constants.SOCKET_EVENTS.OUTGOING.JOIN_ROOM, {
465
+ clientType: clientType,
466
+ sessionId: _this5._credentials.sessionId
467
+ });
468
+ }).catch(function (error) {
469
+ _this5.emit(_session.EVENTS.EXCEPTION, { source: 'connect', error: error });
470
+ throw error;
471
+ });
472
+ };
473
+
474
+ TurnWebRTCSession.prototype._createRTCPeerConnection = function _createRTCPeerConnection(peerId) {
475
+ var _this6 = this;
476
+
477
+ return this._connectRTCPeer({
478
+ constraints: this._constraints,
479
+ configuration: this._configuration,
480
+ sessionId: this._credentials.sessionId,
481
+ isMobile: this._isMobile,
482
+ peerId: peerId
483
+ }).then(function (pc) {
484
+ pc.peerConnection.getLocalStreams().forEach(function (stream) {
485
+ if (!_this6.publisher) {
486
+ stream.getTracks().forEach(_this6._setTrackStateTo(false));
487
+ }
488
+ });
489
+
490
+ pc.peerConnection.onaddstream = function (_ref11) {
491
+ var stream = _ref11.stream;
492
+
493
+ var tsStream = new _stream.TsWebRTCStream(_this6, stream);
494
+
495
+ _this6.emit(_session.EVENTS.STREAM_CREATED, tsStream);
496
+ };
497
+
498
+ return pc;
499
+ });
500
+ };
501
+
502
+ TurnWebRTCSession.prototype._toggleAllStreams = function _toggleAllStreams(state) {
503
+ var _this7 = this;
504
+
505
+ _.forEach(this._pcs, function (pc) {
506
+ pc.peerConnection.getLocalStreams().forEach(function (stream) {
507
+ stream.getTracks().forEach(_this7._setTrackStateTo(state));
508
+ });
509
+ });
510
+ };
511
+
512
+ TurnWebRTCSession.prototype._stopStream = function _stopStream(pc) {
513
+ pc.peerConnection.getLocalStreams().forEach(function (stream) {
514
+ stream.getTracks().forEach(function (track) {
515
+ return track.stop();
516
+ });
517
+ });
518
+ };
519
+
520
+ TurnWebRTCSession.prototype._stopAllStreams = function _stopAllStreams() {
521
+ var _this8 = this;
522
+
523
+ _.forEach(this._pcs, function (pc) {
524
+ return _this8._stopStream(pc);
525
+ });
526
+ };
527
+
528
+ /**
529
+ * Close all media streams, disconnect RTCPeerConnection and socket.io
530
+ *
531
+ * @method
532
+ * @returns { Promise }
533
+ *
534
+ * @fires SESSION_EVENTS#DISCONNECTED
535
+ */
536
+
537
+
538
+ TurnWebRTCSession.prototype.disconnect = function disconnect() {
539
+ var _this9 = this;
540
+
541
+ return Promise.resolve().then(function () {
542
+ if (_this9.destroyed) {
543
+ return null;
544
+ }
545
+
546
+ _this9._stopAllStreams();
547
+
548
+ _.forEach(_this9._pcs, function (_ref12) {
549
+ var peerConnection = _ref12.peerConnection;
550
+ return peerConnection.close();
551
+ });
552
+ _this9._pcs = {};
553
+ _this9._socket.disconnect();
554
+
555
+ var event = { reason: 'disconnected' };
556
+
557
+ _this9.emit(_session.EVENTS.DISCONNECTED, event);
558
+
559
+ return event;
560
+ });
561
+ };
562
+
563
+ TurnWebRTCSession.prototype._waitForPublishingApproval = function _waitForPublishingApproval(caller, cb) {
564
+ try {
565
+ var pc = _.get(caller, '_lastPc.peerConnection');
566
+
567
+ if (!pc) {
568
+ throw new Error('No peer connection for publishing');
569
+ }
570
+
571
+ //
572
+ // Get media streams that were created on session initialization
573
+ //
574
+ var mediaStream = pc.getLocalStreams()[0];
575
+
576
+ if (mediaStream) {
577
+ return cb(null, mediaStream);
578
+ }
579
+
580
+ if (caller.lastError === 'NotAllowedError') {
581
+ return cb({ code: 1500, name: 'NotAllowedError' });
582
+ } else if (caller.lastError === 'PermissionDismissedError') {
583
+ return cb({ code: 8, name: 'PermissionDismissedError' });
584
+ }
585
+
586
+ setTimeout(caller._waitForPublishingApproval, _constants.PUBLISH_APPROVAL_CHECK_INTERVAL, caller, cb);
587
+ } catch (err) {
588
+ return cb(err);
589
+ }
590
+ };
591
+
592
+ /**
593
+ * Create new TsMediaPublisher instance
594
+ *
595
+ * @method
596
+ *
597
+ * @param { DOMElement } [target] Video element
598
+ * that will be used to render publishing video stream
599
+ * @param { Object } params
600
+ * @param { String } [params.videoDevice] Video device id
601
+ * @param { String } [params.videoParams] Video device id
602
+ * @param { String } [params.videoParams.fitMode] Video fit mode
603
+ * @param { Number|String } [params.videoParams.width] Video element width
604
+ * @param { Number|String } [params.videoParams.height] Video element height
605
+ * @param { String } [params.audioDevice] Video device id
606
+ *
607
+ * @returns { Promise<TsMediaPublisher> } publisher
608
+ *
609
+ * @see TsMediaPublisher
610
+ */
611
+
612
+
613
+ TurnWebRTCSession.prototype.createPublisher = function createPublisher(target, params) {
614
+ var _this10 = this;
615
+
616
+ if (!params) {
617
+ params = target;
618
+ target = null;
619
+ }
620
+
621
+ return (this._lastPc ? Promise.resolve() : Promise.delay(_constants.WAIT_FOR_PC_INTERVAL)).then(function () {
622
+ return new Promise(function (resolve, reject) {
623
+ _this10._waitForPublishingApproval(_this10, function (err, mediaStream) {
624
+ if (err) {
625
+ return reject(err);
626
+ }
627
+
628
+ return resolve(mediaStream);
629
+ });
630
+ });
631
+ }).then(function (mediaStream) {
632
+ //
633
+ // Get tracks that are related to the publisher (audio or video)
634
+ //
635
+ var tracks = _this10._lastPc.peerConnection.getLocalStreams().reduce(function (result, mediaStream) {
636
+ mediaStream.getTracks().filter(function (track) {
637
+ return track.kind === 'video' && params.videoDevice || track.kind === 'audio' && params.audioDevice;
638
+ }).forEach(function (track) {
639
+ return result.push(track);
640
+ });
641
+
642
+ return result;
643
+ }, []);
644
+
645
+ var tsstream = new _stream.TsWebRTCStream(_this10, mediaStream, params.name);
646
+
647
+ tsstream.remote = false;
648
+
649
+ var publisher = new _publisher.TsMediaPublisher(_this10, {
650
+ stream: tsstream,
651
+ tracks: tracks,
652
+ videoParams: params.videoParams,
653
+
654
+ videoHeight: tsstream.videoDimensions.height,
655
+ videoWidth: tsstream.videoDimensions.width,
656
+
657
+ _target: target
658
+ });
659
+
660
+ tsstream.publisher = publisher;
661
+ _this10.publisher = publisher;
662
+
663
+ return publisher;
664
+ });
665
+ };
666
+
667
+ /**
668
+ * Publish stream from previously create TsMediaPublisher instance.
669
+ *
670
+ * Used internally by TsMediaPublisher.publish
671
+ *
672
+ * @method
673
+ *
674
+ * @param { TsMediaPublisher } publisher
675
+ *
676
+ * @returns { Promise }
677
+ *
678
+ * @fires PUBLISHER_EVENTS#STREAM_CREATED
679
+ * @fires SESSION_EVENTS#STREAM_PROPERTY_CHANGED
680
+ * @fires STREAM_EVENTS#PROPERTY_CHANGED
681
+ *
682
+ * @see TsMediaPublisher#publish
683
+ */
684
+
685
+
686
+ TurnWebRTCSession.prototype.publish = function publish(publisher) {
687
+ var _this11 = this;
688
+
689
+ return Promise.resolve().then(function () {
690
+ if (!publisher) {
691
+ return;
692
+ }
693
+
694
+ publisher.emit(_publisher.EVENTS.STREAM_CREATED, publisher.stream);
695
+ _this11.emit(_session.EVENTS.STREAM_PROPERTY_CHANGED, {
696
+ stream: publisher.stream,
697
+ property: 'hasVideo',
698
+ value: publisher.stream.hasVideo
699
+ });
700
+ _this11.emit(_session.EVENTS.STREAM_PROPERTY_CHANGED, {
701
+ stream: publisher.stream,
702
+ property: 'hasAudio',
703
+ value: publisher.stream.hasAudio
704
+ });
705
+
706
+ if (_this11.publisher._element) {
707
+ return;
708
+ }
709
+
710
+ if (publisher._target) {
711
+ //
712
+ // New video element where publishing video stream will be rendered
713
+ //
714
+ var video = document.createElement('video');
715
+
716
+ if (!isIE11) {
717
+ video.src = URL.createObjectURL(publisher.stream._mediaStream);
718
+ }
719
+
720
+ video.playsInline = true;
721
+ video.autoplay = true;
722
+
723
+ if (isIE11) {
724
+ publisher._target.appendChild(video);
725
+ publisher._element = attachMediaStream(video, publisher.stream._mediaStream);
726
+ }
727
+
728
+ var params = _.assign({}, {
729
+ fitMode: 'contain',
730
+ insertMode: 'append',
731
+ mirror: false,
732
+ resolution: '480x640',
733
+ width: '100%',
734
+ height: '100%'
735
+ }, publisher.videoParams);
736
+
737
+ var elementHeight = typeof params.height === 'string' ? params.height : params.height + 'px';
738
+ var elementWidth = typeof params.width === 'string' ? params.width : params.width + 'px';
739
+
740
+ _.assign((isIE11 ? publisher._element : video).style, {
741
+ height: elementHeight,
742
+ width: elementWidth,
743
+
744
+ position: 'relative',
745
+ 'object-fit': params.fitMode
746
+ });
747
+
748
+ if (!isIE11) {
749
+ publisher._target.appendChild(video);
750
+ publisher._element = video;
751
+ }
752
+
753
+ publisher.stream.setupDimensionsListener(video);
754
+ }
755
+
756
+ //
757
+ // Enable (unpause) all media tracks related to publisher.
758
+ // They are sending data to the server from this moment.
759
+ //
760
+ _this11._toggleAllStreams(true);
761
+ });
762
+ };
763
+
764
+ /**
765
+ * Unpublish stream and destroy publisher's view.
766
+ *
767
+ * Used internally by TsMediaPublisher.destroy
768
+ *
769
+ * @method
770
+ *
771
+ * @param { TsMediaPublisher } publisher
772
+ *
773
+ * @returns { Promise }
774
+ *
775
+ * @fires PUBLISHER_EVENTS#DESTROYED
776
+ *
777
+ * @see TsMediaPublisher#destroy
778
+ */
779
+
780
+
781
+ TurnWebRTCSession.prototype.destroyPublisher = function destroyPublisher(publisher) {
782
+ var _this12 = this;
783
+
784
+ return new Promise(function (resolve) {
785
+ _this12._toggleAllStreams(false);
786
+
787
+ if (publisher._element) {
788
+ publisher._element.remove();
789
+ }
790
+
791
+ _this12.publisher = null;
792
+ publisher.emit(_publisher.EVENTS.DESTROYED);
793
+
794
+ return resolve();
795
+ });
796
+ };
797
+
798
+ _createClass(TurnWebRTCSession, [{
799
+ key: 'id',
800
+ get: function get() {
801
+ return this._credentials.sessionId;
802
+ }
803
+ }]);
804
+
805
+ return TurnWebRTCSession;
806
+ }(_session.TsMediaSession);
807
+ //# sourceMappingURL=session-turn.js.map