@reactoo/watchtogether-sdk-js 2.5.19 → 2.5.22
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.
- package/dist/watchtogether-sdk.js +4 -4
- package/dist/watchtogether-sdk.min.js +2 -2
- package/example/index.html +2 -1
- package/package.json +1 -1
- package/src/modules/wt-config.js +2 -2
- package/src/modules/wt-room.js +306 -208
package/src/modules/wt-room.js
CHANGED
|
@@ -5,7 +5,7 @@ import emitter from './wt-emitter';
|
|
|
5
5
|
import {generateUUID} from "./wt-utils";
|
|
6
6
|
|
|
7
7
|
class Room {
|
|
8
|
-
|
|
8
|
+
|
|
9
9
|
constructor(debug) {
|
|
10
10
|
this.debug = debug;
|
|
11
11
|
this.sessions = [];
|
|
@@ -22,16 +22,16 @@ class Room {
|
|
|
22
22
|
// Let's get it started
|
|
23
23
|
this.whenInitialized = this.initialize();
|
|
24
24
|
}
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
initialize() {
|
|
27
27
|
return this.safariVp8TestPromise
|
|
28
28
|
.then(() => this);
|
|
29
29
|
}
|
|
30
|
-
|
|
30
|
+
|
|
31
31
|
createSession(constructId = null, type = 'reactooroom', options = {}) {
|
|
32
32
|
return new RoomSession(constructId, type, {debug: this.debug, ...options});
|
|
33
33
|
}
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
static testSafariVp8() {
|
|
36
36
|
return new Promise(resolve => {
|
|
37
37
|
if (adapter.browserDetails.browser === 'safari' &&
|
|
@@ -61,7 +61,7 @@ class Room {
|
|
|
61
61
|
} else resolve(false);
|
|
62
62
|
});
|
|
63
63
|
}
|
|
64
|
-
|
|
64
|
+
|
|
65
65
|
static isWebrtcSupported() {
|
|
66
66
|
return window.RTCPeerConnection !== undefined && window.RTCPeerConnection !== null &&
|
|
67
67
|
navigator.mediaDevices !== undefined && navigator.mediaDevices !== null &&
|
|
@@ -70,9 +70,9 @@ class Room {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
class RoomSession {
|
|
73
|
-
|
|
73
|
+
|
|
74
74
|
static noop() {
|
|
75
|
-
|
|
75
|
+
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
static randomString(len) {
|
|
@@ -84,11 +84,11 @@ class RoomSession {
|
|
|
84
84
|
}
|
|
85
85
|
return randomString;
|
|
86
86
|
}
|
|
87
|
-
|
|
87
|
+
|
|
88
88
|
//TODO: solve
|
|
89
89
|
// #eventList = ['error', 'kicked', 'addLocalParticipant', ,'addRemoteInstructor','addRemoteParticipant','addRemoteTalkback', 'addRemoteObserver', 'removeRemoteInstructor', 'removeLocalParticipant', 'removeRemoteParticipant', 'removeRemoteTalkback', 'removeRemoteObserver', 'localMuted', 'localHasVideo', 'localHasAudio', 'data', 'iceState', 'connectionState', 'joined', 'joining', 'dataChannel', 'disconnect', 'observerIds', 'talkbackIds', 'instructorId', 'published', 'publishing', 'remoteTrackMuted', 'streamingStatus', 'streaming', 'streamStarting'];
|
|
90
90
|
//
|
|
91
|
-
|
|
91
|
+
|
|
92
92
|
static sessionTypes = {
|
|
93
93
|
'reactooroom': 'janus.plugin.reactooroom',
|
|
94
94
|
'streaming': 'janus.plugin.streaming'
|
|
@@ -116,11 +116,11 @@ class RoomSession {
|
|
|
116
116
|
videoWall: [],
|
|
117
117
|
},
|
|
118
118
|
};
|
|
119
|
-
|
|
119
|
+
|
|
120
120
|
constructor(constructId = null, type = 'reactooroom', options = {}) {
|
|
121
121
|
|
|
122
122
|
Object.assign(this, emitter());
|
|
123
|
-
|
|
123
|
+
this.defaultDataChannelLabel = 'JanusDataChannel'
|
|
124
124
|
this.server = null;
|
|
125
125
|
this.iceServers = null;
|
|
126
126
|
this.token = null;
|
|
@@ -147,7 +147,7 @@ class RoomSession {
|
|
|
147
147
|
// double click prevention
|
|
148
148
|
this.connectingPromise = null;
|
|
149
149
|
this.disconnectingPromise = null;
|
|
150
|
-
|
|
150
|
+
|
|
151
151
|
this._ipv6Support = false;
|
|
152
152
|
this._retries = 0;
|
|
153
153
|
this._maxRetries = 3;
|
|
@@ -177,7 +177,7 @@ class RoomSession {
|
|
|
177
177
|
}
|
|
178
178
|
|
|
179
179
|
}
|
|
180
|
-
|
|
180
|
+
|
|
181
181
|
// Check if this browser supports Unified Plan and transceivers
|
|
182
182
|
// Based on https://codepen.io/anon/pen/ZqLwWV?editors=0010
|
|
183
183
|
static checkUnifiedPlan() {
|
|
@@ -288,7 +288,7 @@ class RoomSession {
|
|
|
288
288
|
}
|
|
289
289
|
return eventName
|
|
290
290
|
}
|
|
291
|
-
|
|
291
|
+
|
|
292
292
|
sendMessage(handleId, message = {body: 'Example Body'}, dontWait = false, dontResolveOnAck = false) {
|
|
293
293
|
return this._send({
|
|
294
294
|
"janus": "message",
|
|
@@ -311,7 +311,7 @@ class RoomSession {
|
|
|
311
311
|
}
|
|
312
312
|
})
|
|
313
313
|
}
|
|
314
|
-
|
|
314
|
+
|
|
315
315
|
_send(request = {}, ignoreResponse = false, dontResolveOnAck = false) {
|
|
316
316
|
let transaction = RoomSession.randomString(12);
|
|
317
317
|
let requestData = {
|
|
@@ -320,7 +320,7 @@ class RoomSession {
|
|
|
320
320
|
token: this.token, ...((this.sessionId && {'session_id': this.sessionId}) || {})
|
|
321
321
|
};
|
|
322
322
|
let timeouId = null;
|
|
323
|
-
|
|
323
|
+
|
|
324
324
|
return new Promise((resolve, reject) => {
|
|
325
325
|
let parseResponse = (event) => {
|
|
326
326
|
let json = JSON.parse(event.data);
|
|
@@ -338,13 +338,13 @@ class RoomSession {
|
|
|
338
338
|
}
|
|
339
339
|
}
|
|
340
340
|
};
|
|
341
|
-
|
|
341
|
+
|
|
342
342
|
if (ignoreResponse) {
|
|
343
343
|
if (this.ws && this.ws.readyState === 1) {
|
|
344
344
|
this.ws.send(JSON.stringify(requestData));
|
|
345
345
|
}
|
|
346
346
|
resolve();
|
|
347
|
-
|
|
347
|
+
|
|
348
348
|
} else {
|
|
349
349
|
if (this.ws && this.ws.readyState === 1) {
|
|
350
350
|
this.ws.addEventListener('message', parseResponse);
|
|
@@ -359,12 +359,12 @@ class RoomSession {
|
|
|
359
359
|
}
|
|
360
360
|
})
|
|
361
361
|
}
|
|
362
|
-
|
|
362
|
+
|
|
363
363
|
_connectionClosed() {
|
|
364
364
|
if (this.disconnectingPromise || this.connectingPromise) {
|
|
365
365
|
return;
|
|
366
366
|
}
|
|
367
|
-
|
|
367
|
+
|
|
368
368
|
if (this._retries < this._maxRetries) {
|
|
369
369
|
setTimeout(() => {
|
|
370
370
|
this._retries++;
|
|
@@ -378,18 +378,18 @@ class RoomSession {
|
|
|
378
378
|
} else if (this.sessiontype === 'streaming') {
|
|
379
379
|
this.stopStream();
|
|
380
380
|
}
|
|
381
|
-
|
|
381
|
+
|
|
382
382
|
this.emit('error', {type: 'error', id: 4, message: 'Lost connection to WebSockets', data: null});
|
|
383
383
|
}
|
|
384
384
|
}
|
|
385
|
-
|
|
385
|
+
|
|
386
386
|
_wipeListeners() {
|
|
387
387
|
if (this.ws) {
|
|
388
388
|
this.ws.removeEventListener('close', this.__connectionClosedBoundFn);
|
|
389
389
|
this.ws.removeEventListener('message', this.__handleWsEventsBoundFn);
|
|
390
390
|
}
|
|
391
391
|
}
|
|
392
|
-
|
|
392
|
+
|
|
393
393
|
_startKeepAlive() {
|
|
394
394
|
this._send({"janus": "keepalive"})
|
|
395
395
|
.then(json => {
|
|
@@ -406,27 +406,27 @@ class RoomSession {
|
|
|
406
406
|
this.emit('error', {type: 'warning', id: 6, message: 'keepalive dead', data: e});
|
|
407
407
|
this._connectionClosed();
|
|
408
408
|
});
|
|
409
|
-
|
|
409
|
+
|
|
410
410
|
this._keepAliveId = setTimeout(() => {
|
|
411
411
|
this._startKeepAlive();
|
|
412
412
|
}, 30000);
|
|
413
413
|
}
|
|
414
|
-
|
|
414
|
+
|
|
415
415
|
_stopKeepAlive() {
|
|
416
416
|
clearTimeout(this._keepAliveId);
|
|
417
417
|
}
|
|
418
418
|
|
|
419
419
|
_handleWsEvents(event) {
|
|
420
|
-
|
|
420
|
+
|
|
421
421
|
let json = JSON.parse(event.data);
|
|
422
422
|
var sender = json["sender"];
|
|
423
423
|
var type = json["janus"];
|
|
424
|
-
|
|
424
|
+
|
|
425
425
|
let handle = this._getHandle(sender);
|
|
426
426
|
if (!handle) {
|
|
427
427
|
return;
|
|
428
428
|
}
|
|
429
|
-
|
|
429
|
+
|
|
430
430
|
if (type === "trickle") {
|
|
431
431
|
let candidate = json["candidate"];
|
|
432
432
|
let config = handle.webrtcStuff;
|
|
@@ -451,9 +451,9 @@ class RoomSession {
|
|
|
451
451
|
this._log('detached on', handle.handleId);
|
|
452
452
|
this._removeParticipant(handle.handleId, null, true);
|
|
453
453
|
} else if (type === "media") {
|
|
454
|
-
this._log('Media event:', handle.handleId, json["type"], json["receiving"]);
|
|
454
|
+
this._log('Media event:', handle.handleId, json["type"], json["receiving"], json["mid"]);
|
|
455
455
|
} else if (type === "slowlink") {
|
|
456
|
-
this._log('Slowlink', handle.handleId, json["uplink"], json["
|
|
456
|
+
this._log('Slowlink', handle.handleId, json["uplink"], json["lost"], json["mid"]);
|
|
457
457
|
} else if (type === "event") {
|
|
458
458
|
//none universal
|
|
459
459
|
} else if (type === 'timeout') {
|
|
@@ -463,16 +463,16 @@ class RoomSession {
|
|
|
463
463
|
} else {
|
|
464
464
|
this._log(`Unknown event: ${type} on session: ${this.sessionId}`);
|
|
465
465
|
}
|
|
466
|
-
|
|
467
|
-
|
|
466
|
+
|
|
467
|
+
|
|
468
468
|
// LOCAL
|
|
469
|
-
|
|
469
|
+
|
|
470
470
|
if (sender === this.handleId) {
|
|
471
471
|
if (type === "event") {
|
|
472
472
|
var plugindata = json["plugindata"] || {};
|
|
473
473
|
var msg = plugindata["data"] || {};
|
|
474
474
|
var jsep = json["jsep"];
|
|
475
|
-
|
|
475
|
+
|
|
476
476
|
let result = msg["result"] || null;
|
|
477
477
|
let event = msg["videoroom"] || null;
|
|
478
478
|
let list = msg["publishers"] || {};
|
|
@@ -480,7 +480,7 @@ class RoomSession {
|
|
|
480
480
|
//let joining = msg["joining"];
|
|
481
481
|
let unpublished = msg["unpublished"];
|
|
482
482
|
let error = msg["error"];
|
|
483
|
-
|
|
483
|
+
|
|
484
484
|
if (event === "joined") {
|
|
485
485
|
this.id = msg["id"];
|
|
486
486
|
this.privateId = msg["private_id"];
|
|
@@ -517,11 +517,11 @@ class RoomSession {
|
|
|
517
517
|
}
|
|
518
518
|
}
|
|
519
519
|
} else if (event === "event") {
|
|
520
|
-
|
|
520
|
+
|
|
521
521
|
if (msg["streams"] !== undefined && msg["streams"] !== null) {
|
|
522
522
|
this._log('Got my own streams back', msg["streams"]);
|
|
523
523
|
}
|
|
524
|
-
|
|
524
|
+
|
|
525
525
|
for (let f in list) {
|
|
526
526
|
let userId = list[f]["display"];
|
|
527
527
|
let streams = list[f]["streams"] || [];
|
|
@@ -551,7 +551,7 @@ class RoomSession {
|
|
|
551
551
|
})
|
|
552
552
|
}
|
|
553
553
|
}
|
|
554
|
-
|
|
554
|
+
|
|
555
555
|
if (leaving === 'ok') {
|
|
556
556
|
this._log('leaving', this.handleId, 'this is us');
|
|
557
557
|
this._removeParticipant(this.handleId);
|
|
@@ -564,7 +564,7 @@ class RoomSession {
|
|
|
564
564
|
this._log('leaving', leaving);
|
|
565
565
|
this._removeParticipant(null, leaving);
|
|
566
566
|
}
|
|
567
|
-
|
|
567
|
+
|
|
568
568
|
if (unpublished === 'ok') {
|
|
569
569
|
this._log('unpublished', this.handleId, 'this is us');
|
|
570
570
|
this._removeParticipant(this.handleId, null, false); // we do just hangup
|
|
@@ -572,7 +572,7 @@ class RoomSession {
|
|
|
572
572
|
this._log('unpublished', unpublished);
|
|
573
573
|
this._removeParticipant(null, unpublished, true); // we do hangup and detach
|
|
574
574
|
}
|
|
575
|
-
|
|
575
|
+
|
|
576
576
|
if (error) {
|
|
577
577
|
this.emit('error', {
|
|
578
578
|
type: 'error',
|
|
@@ -582,7 +582,7 @@ class RoomSession {
|
|
|
582
582
|
});
|
|
583
583
|
}
|
|
584
584
|
}
|
|
585
|
-
|
|
585
|
+
|
|
586
586
|
// Streaming related
|
|
587
587
|
else if (result && result["status"]) {
|
|
588
588
|
this.emit('streamingStatus', result["status"]);
|
|
@@ -594,9 +594,9 @@ class RoomSession {
|
|
|
594
594
|
this._isStreaming = true;
|
|
595
595
|
}
|
|
596
596
|
}
|
|
597
|
-
|
|
597
|
+
|
|
598
598
|
if (jsep !== undefined && jsep !== null) {
|
|
599
|
-
|
|
599
|
+
|
|
600
600
|
if (this.sessiontype === 'reactooroom') {
|
|
601
601
|
this._webrtcPeer(this.handleId, jsep)
|
|
602
602
|
.catch(err => {
|
|
@@ -608,7 +608,7 @@ class RoomSession {
|
|
|
608
608
|
this.emit('error', err);
|
|
609
609
|
});
|
|
610
610
|
}
|
|
611
|
-
|
|
611
|
+
|
|
612
612
|
}
|
|
613
613
|
} else if (type === "webrtcup") {
|
|
614
614
|
this._log('Configuring bitrate: ' + this.initialBitrate);
|
|
@@ -622,17 +622,17 @@ class RoomSession {
|
|
|
622
622
|
}
|
|
623
623
|
}
|
|
624
624
|
}
|
|
625
|
-
|
|
625
|
+
|
|
626
626
|
//REMOTE
|
|
627
|
-
|
|
627
|
+
|
|
628
628
|
else {
|
|
629
|
-
|
|
629
|
+
|
|
630
630
|
let plugindata = json["plugindata"] || {};
|
|
631
631
|
let msg = plugindata["data"] || {};
|
|
632
632
|
let jsep = json["jsep"];
|
|
633
633
|
let event = msg["videoroom"];
|
|
634
634
|
let error = msg["error"];
|
|
635
|
-
|
|
635
|
+
|
|
636
636
|
if (event === "attached") {
|
|
637
637
|
this._log('Remote have successfully joined Room', msg);
|
|
638
638
|
this.emit(this._getAddParticipantEventName(handle.handleId), {
|
|
@@ -648,11 +648,11 @@ class RoomSession {
|
|
|
648
648
|
hasVideoTrack: false
|
|
649
649
|
});
|
|
650
650
|
}
|
|
651
|
-
|
|
651
|
+
|
|
652
652
|
if (error) {
|
|
653
653
|
this.emit('error', {type: 'warning', id: 8, message: 'remote participant error', data: [sender, msg]});
|
|
654
654
|
}
|
|
655
|
-
|
|
655
|
+
|
|
656
656
|
if (jsep) {
|
|
657
657
|
this._publishRemote(handle.handleId, jsep)
|
|
658
658
|
.catch(err => {
|
|
@@ -661,24 +661,24 @@ class RoomSession {
|
|
|
661
661
|
}
|
|
662
662
|
}
|
|
663
663
|
}
|
|
664
|
-
|
|
664
|
+
|
|
665
665
|
_handleDataEvents(handleId, type, data) {
|
|
666
|
-
|
|
666
|
+
|
|
667
667
|
let handle = this._getHandle(handleId);
|
|
668
|
-
|
|
668
|
+
|
|
669
669
|
if (type === 'state') {
|
|
670
|
-
this._log(` - Data channel status - `, `UID: ${handleId}`, `STATUS: ${data}`, `ME: ${handleId === this.handleId}`)
|
|
670
|
+
this._log(` - Data channel status - `, `UID: ${handleId}`, `STATUS: ${JSON.stringify(data)}`, `ME: ${handleId === this.handleId}`)
|
|
671
671
|
if (handle) {
|
|
672
672
|
let config = handle.webrtcStuff;
|
|
673
|
-
config.dataChannelOpen = data === 'open';
|
|
673
|
+
config.dataChannelOpen = this.defaultDataChannelLabel === data?.label && data?.state === 'open';
|
|
674
674
|
}
|
|
675
|
-
|
|
675
|
+
|
|
676
676
|
if (handleId === this.handleId) {
|
|
677
|
-
this._isDataChannelOpen = data === 'open';
|
|
678
|
-
this.emit('dataChannel', data === 'open');
|
|
677
|
+
this._isDataChannelOpen = this.defaultDataChannelLabel === data?.label && data?.state === 'open';
|
|
678
|
+
this.emit('dataChannel', this.defaultDataChannelLabel === data?.label && data?.state === 'open');
|
|
679
679
|
}
|
|
680
680
|
}
|
|
681
|
-
|
|
681
|
+
|
|
682
682
|
if (type === 'error') {
|
|
683
683
|
|
|
684
684
|
this.emit('error', {
|
|
@@ -687,21 +687,23 @@ class RoomSession {
|
|
|
687
687
|
message: 'data event warning',
|
|
688
688
|
data: [handleId, data]
|
|
689
689
|
});
|
|
690
|
-
|
|
690
|
+
|
|
691
691
|
if (handle) {
|
|
692
692
|
let config = handle.webrtcStuff;
|
|
693
|
-
|
|
693
|
+
if(this.defaultDataChannelLabel === data.label) {
|
|
694
|
+
config.dataChannelOpen = false;
|
|
695
|
+
}
|
|
694
696
|
}
|
|
695
|
-
if (handleId === this.handleId) {
|
|
697
|
+
if (handleId === this.handleId && this.defaultDataChannelLabel === data.label) {
|
|
696
698
|
this._isDataChannelOpen = false;
|
|
697
699
|
this.emit('dataChannel', false);
|
|
698
700
|
}
|
|
699
701
|
}
|
|
700
|
-
|
|
702
|
+
|
|
701
703
|
if (handleId === this.handleId && type === 'message') {
|
|
702
|
-
|
|
704
|
+
|
|
703
705
|
let d = null;
|
|
704
|
-
|
|
706
|
+
|
|
705
707
|
try {
|
|
706
708
|
d = JSON.parse(data)
|
|
707
709
|
} catch (e) {
|
|
@@ -710,19 +712,19 @@ class RoomSession {
|
|
|
710
712
|
}
|
|
711
713
|
this.emit('data', d);
|
|
712
714
|
}
|
|
713
|
-
|
|
715
|
+
|
|
714
716
|
}
|
|
715
|
-
|
|
717
|
+
|
|
716
718
|
//removeHandle === true -> hangup, detach, removeHandle === false -> hangup
|
|
717
719
|
_removeParticipant(handleId, rfid, removeHandle = true) {
|
|
718
720
|
let handle = this._getHandle(handleId, rfid);
|
|
719
|
-
|
|
721
|
+
|
|
720
722
|
if (!handle) {
|
|
721
723
|
return Promise.resolve();
|
|
722
724
|
} else {
|
|
723
725
|
handleId = handle.handleId;
|
|
724
726
|
}
|
|
725
|
-
|
|
727
|
+
|
|
726
728
|
return this._send({"janus": "hangup", "handle_id": handleId,}, true)
|
|
727
729
|
.then(() => (removeHandle ? this._send({
|
|
728
730
|
"janus": "detach",
|
|
@@ -738,10 +740,12 @@ class RoomSession {
|
|
|
738
740
|
}
|
|
739
741
|
handle.webrtcStuff.stream = null;
|
|
740
742
|
if (handle.webrtcStuff.dataChannel) {
|
|
741
|
-
handle.webrtcStuff.dataChannel.
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
743
|
+
Object.keys(handle.webrtcStuff.dataChannel).forEach(label => {
|
|
744
|
+
handle.webrtcStuff.dataChannel[label].onmessage = null;
|
|
745
|
+
handle.webrtcStuff.dataChannel[label].onopen = null;
|
|
746
|
+
handle.webrtcStuff.dataChannel[label].onclose = null;
|
|
747
|
+
handle.webrtcStuff.dataChannel[label].onerror = null;
|
|
748
|
+
})
|
|
745
749
|
}
|
|
746
750
|
if (handle.webrtcStuff.pc) {
|
|
747
751
|
handle.webrtcStuff.pc.onicecandidate = null;
|
|
@@ -766,7 +770,7 @@ class RoomSession {
|
|
|
766
770
|
trickle: true,
|
|
767
771
|
iceDone: false,
|
|
768
772
|
};
|
|
769
|
-
|
|
773
|
+
|
|
770
774
|
if (handleId === this.handleId) {
|
|
771
775
|
this._isDataChannelOpen = false;
|
|
772
776
|
this._isPublished = false;
|
|
@@ -780,12 +784,12 @@ class RoomSession {
|
|
|
780
784
|
let handleIndex = this._participants.findIndex(p => p.handleId === handleId);
|
|
781
785
|
this._participants.splice(handleIndex, 1);
|
|
782
786
|
}
|
|
783
|
-
|
|
787
|
+
|
|
784
788
|
return true;
|
|
785
789
|
});
|
|
786
|
-
|
|
790
|
+
|
|
787
791
|
}
|
|
788
|
-
|
|
792
|
+
|
|
789
793
|
_createParticipant(userId = null, rfid = null) {
|
|
790
794
|
return this._send({
|
|
791
795
|
"janus": "attach",
|
|
@@ -812,7 +816,7 @@ class RoomSession {
|
|
|
812
816
|
return handle;
|
|
813
817
|
})
|
|
814
818
|
}
|
|
815
|
-
|
|
819
|
+
|
|
816
820
|
_joinRoom(roomId, pin, userId) {
|
|
817
821
|
return this.sendMessage(this.handleId, {
|
|
818
822
|
body: {
|
|
@@ -820,7 +824,7 @@ class RoomSession {
|
|
|
820
824
|
}
|
|
821
825
|
}, false, true)
|
|
822
826
|
}
|
|
823
|
-
|
|
827
|
+
|
|
824
828
|
_watchStream(id) {
|
|
825
829
|
return this.sendMessage(this.handleId, {
|
|
826
830
|
body: {
|
|
@@ -828,7 +832,7 @@ class RoomSession {
|
|
|
828
832
|
}
|
|
829
833
|
}, false, true)
|
|
830
834
|
}
|
|
831
|
-
|
|
835
|
+
|
|
832
836
|
_leaveRoom(dontWait = false) {
|
|
833
837
|
return this._hasJoined
|
|
834
838
|
? this.sendMessage(this.handleId, {body: {"request": "leave"}}, dontWait)
|
|
@@ -838,15 +842,15 @@ class RoomSession {
|
|
|
838
842
|
})
|
|
839
843
|
: Promise.resolve();
|
|
840
844
|
}
|
|
841
|
-
|
|
845
|
+
|
|
842
846
|
// internal reconnect
|
|
843
|
-
|
|
847
|
+
|
|
844
848
|
_reconnect() {
|
|
845
|
-
|
|
849
|
+
|
|
846
850
|
if (this.connectingPromise) {
|
|
847
851
|
return this.connectingPromise;
|
|
848
852
|
}
|
|
849
|
-
|
|
853
|
+
|
|
850
854
|
if (this.ws) {
|
|
851
855
|
this._wipeListeners();
|
|
852
856
|
if (this.ws.readyState === 1) {
|
|
@@ -877,7 +881,7 @@ class RoomSession {
|
|
|
877
881
|
reject({type: 'error', id: 11, message: 'reconnection error', data: error})
|
|
878
882
|
});
|
|
879
883
|
};
|
|
880
|
-
|
|
884
|
+
|
|
881
885
|
// this is called before 'close' event callback so it doesn't break reconnect loop
|
|
882
886
|
this.ws.onerror = (e) => {
|
|
883
887
|
this.connectingPromise = null;
|
|
@@ -887,13 +891,13 @@ class RoomSession {
|
|
|
887
891
|
});
|
|
888
892
|
return this.connectingPromise;
|
|
889
893
|
}
|
|
890
|
-
|
|
894
|
+
|
|
891
895
|
connect(roomId, pin, server, iceServers, token, userId, webrtcVersion = 0, initialBitrate = 0, isMonitor, recordingFilename) {
|
|
892
|
-
|
|
896
|
+
|
|
893
897
|
if (this.connectingPromise) {
|
|
894
898
|
return this.connectingPromise;
|
|
895
899
|
}
|
|
896
|
-
|
|
900
|
+
|
|
897
901
|
this.emit('joined', false);
|
|
898
902
|
if (this.ws) {
|
|
899
903
|
this._wipeListeners();
|
|
@@ -951,12 +955,12 @@ class RoomSession {
|
|
|
951
955
|
});
|
|
952
956
|
return this.connectingPromise;
|
|
953
957
|
}
|
|
954
|
-
|
|
958
|
+
|
|
955
959
|
disconnect() {
|
|
956
960
|
if (this.disconnectingPromise) {
|
|
957
961
|
return this.disconnectingPromise;
|
|
958
962
|
}
|
|
959
|
-
|
|
963
|
+
|
|
960
964
|
this._stopKeepAlive();
|
|
961
965
|
this.disconnectingPromise = Promise.all(this._participants.map(p => this._removeParticipant(p.handleId)))
|
|
962
966
|
.finally(() => {
|
|
@@ -976,13 +980,13 @@ class RoomSession {
|
|
|
976
980
|
})
|
|
977
981
|
return this.disconnectingPromise;
|
|
978
982
|
}
|
|
979
|
-
|
|
983
|
+
|
|
980
984
|
startStream(streamId, server, iceServers, token, userId) {
|
|
981
|
-
|
|
985
|
+
|
|
982
986
|
if (this.connectingPromise) {
|
|
983
987
|
return this.connectingPromise
|
|
984
988
|
}
|
|
985
|
-
|
|
989
|
+
|
|
986
990
|
this.emit('streaming', false);
|
|
987
991
|
if (this.ws) {
|
|
988
992
|
this._wipeListeners();
|
|
@@ -995,7 +999,7 @@ class RoomSession {
|
|
|
995
999
|
this.token = token;
|
|
996
1000
|
this.streamId = streamId;
|
|
997
1001
|
this.userId = userId;
|
|
998
|
-
|
|
1002
|
+
|
|
999
1003
|
this.connectingPromise = new Promise((resolve, reject) => {
|
|
1000
1004
|
this.emit('streamStarting', true);
|
|
1001
1005
|
this.ws = new WebSocket(this.server, 'janus-protocol');
|
|
@@ -1036,7 +1040,7 @@ class RoomSession {
|
|
|
1036
1040
|
});
|
|
1037
1041
|
return this.connectingPromise;
|
|
1038
1042
|
}
|
|
1039
|
-
|
|
1043
|
+
|
|
1040
1044
|
stopStream() {
|
|
1041
1045
|
if (this.disconnectingPromise) {
|
|
1042
1046
|
return this.disconnectingPromise;
|
|
@@ -1062,13 +1066,13 @@ class RoomSession {
|
|
|
1062
1066
|
this.disconnectingPromise = null;
|
|
1063
1067
|
return Promise.resolve('Disconnected');
|
|
1064
1068
|
});
|
|
1065
|
-
|
|
1069
|
+
|
|
1066
1070
|
return this.disconnectingPromise;
|
|
1067
1071
|
}
|
|
1068
|
-
|
|
1069
|
-
|
|
1072
|
+
|
|
1073
|
+
|
|
1070
1074
|
destroy() {
|
|
1071
|
-
|
|
1075
|
+
|
|
1072
1076
|
if (this.sessiontype === 'reactooroom') {
|
|
1073
1077
|
return this.disconnect()
|
|
1074
1078
|
.then(() => {
|
|
@@ -1083,7 +1087,7 @@ class RoomSession {
|
|
|
1083
1087
|
})
|
|
1084
1088
|
}
|
|
1085
1089
|
}
|
|
1086
|
-
|
|
1090
|
+
|
|
1087
1091
|
_enableDebug() {
|
|
1088
1092
|
this._log = console.log.bind(console);
|
|
1089
1093
|
}
|
|
@@ -1091,7 +1095,7 @@ class RoomSession {
|
|
|
1091
1095
|
_getHandle(handleId, rfid = null) {
|
|
1092
1096
|
return this._participants.find(p => p.handleId === handleId || (rfid && p.rfid === rfid));
|
|
1093
1097
|
}
|
|
1094
|
-
|
|
1098
|
+
|
|
1095
1099
|
_getStats(type = null) {
|
|
1096
1100
|
return Promise.all(this._participants.map(participant => {
|
|
1097
1101
|
let mediaTrack = null;
|
|
@@ -1105,7 +1109,7 @@ class RoomSession {
|
|
|
1105
1109
|
.catch(e => Promise.resolve({handle: participant, stats: e}))
|
|
1106
1110
|
}))
|
|
1107
1111
|
}
|
|
1108
|
-
|
|
1112
|
+
|
|
1109
1113
|
_sendTrickleCandidate(handleId, candidate) {
|
|
1110
1114
|
return this._send({
|
|
1111
1115
|
"janus": "trickle",
|
|
@@ -1113,9 +1117,9 @@ class RoomSession {
|
|
|
1113
1117
|
"handle_id": handleId
|
|
1114
1118
|
})
|
|
1115
1119
|
}
|
|
1116
|
-
|
|
1120
|
+
|
|
1117
1121
|
_webrtc(handleId, enableOntrack = false) {
|
|
1118
|
-
|
|
1122
|
+
|
|
1119
1123
|
let handle = this._getHandle(handleId);
|
|
1120
1124
|
if (!handle) {
|
|
1121
1125
|
this.emit('error', {
|
|
@@ -1125,13 +1129,13 @@ class RoomSession {
|
|
|
1125
1129
|
data: [handleId, 'create rtc connection']
|
|
1126
1130
|
});
|
|
1127
1131
|
}
|
|
1128
|
-
|
|
1132
|
+
|
|
1129
1133
|
let config = handle.webrtcStuff;
|
|
1130
1134
|
if (!config.pc) {
|
|
1131
1135
|
let pc_config = {"iceServers": this.iceServers, "iceTransportPolicy": 'all', "bundlePolicy": undefined};
|
|
1132
|
-
|
|
1136
|
+
|
|
1133
1137
|
pc_config["sdpSemantics"] = this.isUnifiedPlan ? "unified-plan" : "plan-b";
|
|
1134
|
-
|
|
1138
|
+
|
|
1135
1139
|
let pc_constraints = {
|
|
1136
1140
|
"optional": [{"DtlsSrtpKeyAgreement": true}]
|
|
1137
1141
|
};
|
|
@@ -1142,9 +1146,9 @@ class RoomSession {
|
|
|
1142
1146
|
// This is Edge, enable BUNDLE explicitly
|
|
1143
1147
|
pc_config.bundlePolicy = "max-bundle";
|
|
1144
1148
|
}
|
|
1145
|
-
|
|
1149
|
+
|
|
1146
1150
|
this._log('new RTCPeerConnection', pc_config, pc_constraints);
|
|
1147
|
-
|
|
1151
|
+
|
|
1148
1152
|
config.pc = new RTCPeerConnection(pc_config, pc_constraints);
|
|
1149
1153
|
config.pc.onconnectionstatechange = () => {
|
|
1150
1154
|
if (config.pc.connectionState === 'failed') {
|
|
@@ -1157,10 +1161,11 @@ class RoomSession {
|
|
|
1157
1161
|
id: handle.handleId,
|
|
1158
1162
|
userId: handle.userId,
|
|
1159
1163
|
stream: config.stream,
|
|
1164
|
+
track: null,
|
|
1160
1165
|
optional: true,
|
|
1161
1166
|
constructId: this.constructId,
|
|
1162
1167
|
metaData: this.options.metaData,
|
|
1163
|
-
adding:
|
|
1168
|
+
adding: false,
|
|
1164
1169
|
hasAudioTrack: !!(config.stream && config.stream.getAudioTracks().length),
|
|
1165
1170
|
hasVideoTrack: !!(config.stream && config.stream.getVideoTracks().length)
|
|
1166
1171
|
})
|
|
@@ -1177,10 +1182,11 @@ class RoomSession {
|
|
|
1177
1182
|
id: handle.handleId,
|
|
1178
1183
|
userId: handle.userId,
|
|
1179
1184
|
stream: config.stream,
|
|
1185
|
+
track: null,
|
|
1180
1186
|
optional: true,
|
|
1181
1187
|
constructId: this.constructId,
|
|
1182
1188
|
metaData: this.options.metaData,
|
|
1183
|
-
adding:
|
|
1189
|
+
adding: false,
|
|
1184
1190
|
hasAudioTrack: !!(config.stream && config.stream.getAudioTracks().length),
|
|
1185
1191
|
hasVideoTrack: !!(config.stream && config.stream.getVideoTracks().length)
|
|
1186
1192
|
})
|
|
@@ -1201,30 +1207,31 @@ class RoomSession {
|
|
|
1201
1207
|
"sdpMid": event.candidate.sdpMid,
|
|
1202
1208
|
"sdpMLineIndex": event.candidate.sdpMLineIndex
|
|
1203
1209
|
};
|
|
1204
|
-
|
|
1210
|
+
|
|
1205
1211
|
this._sendTrickleCandidate(handleId, candidate)
|
|
1206
1212
|
.catch(e => {
|
|
1207
1213
|
this.emit('error', e);
|
|
1208
1214
|
});
|
|
1209
1215
|
}
|
|
1210
1216
|
};
|
|
1211
|
-
|
|
1217
|
+
|
|
1212
1218
|
if (enableOntrack) {
|
|
1213
1219
|
config.pc.ontrack = (event) => {
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1220
|
+
|
|
1221
|
+
if(!event.streams)
|
|
1222
|
+
return;
|
|
1223
|
+
|
|
1218
1224
|
//config.stream = event.streams[0];
|
|
1219
|
-
|
|
1225
|
+
|
|
1220
1226
|
if (!config.stream) {
|
|
1221
1227
|
config.stream = new MediaStream();
|
|
1222
1228
|
}
|
|
1223
|
-
|
|
1224
1229
|
if (event.track) {
|
|
1230
|
+
let mid = event.transceiver ? event.transceiver.mid : event.track.id;
|
|
1225
1231
|
config.stream.addTrack(event.track);
|
|
1226
1232
|
this.emit(this._getAddParticipantEventName(handle.handleId), {
|
|
1227
1233
|
tid: generateUUID(),
|
|
1234
|
+
mid,
|
|
1228
1235
|
id: handle.handleId,
|
|
1229
1236
|
userId: handle.userId,
|
|
1230
1237
|
stream: config.stream,
|
|
@@ -1235,32 +1242,51 @@ class RoomSession {
|
|
|
1235
1242
|
hasAudioTrack: !!(config.stream && config.stream.getAudioTracks().length),
|
|
1236
1243
|
hasVideoTrack: !!(config.stream && config.stream.getVideoTracks().length)
|
|
1237
1244
|
});
|
|
1238
|
-
|
|
1245
|
+
|
|
1239
1246
|
if (event.track.onended)
|
|
1240
1247
|
return;
|
|
1241
|
-
|
|
1248
|
+
|
|
1242
1249
|
event.track.onended = (ev) => {
|
|
1250
|
+
|
|
1251
|
+
let mid = ev.target.id;
|
|
1252
|
+
if(this.isUnifiedPlan) {
|
|
1253
|
+
let transceiver = config.pc.getTransceivers().find(
|
|
1254
|
+
t => t.receiver.track === ev.target);
|
|
1255
|
+
mid = transceiver.mid;
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1243
1258
|
if (config.stream) {
|
|
1244
1259
|
config.stream && config.stream.removeTrack(ev.target);
|
|
1245
1260
|
this.emit(this._getAddParticipantEventName(handle.handleId), {
|
|
1246
1261
|
tid: generateUUID(),
|
|
1247
1262
|
id: handle.handleId,
|
|
1263
|
+
mid,
|
|
1248
1264
|
userId: handle.userId,
|
|
1249
1265
|
stream: config.stream,
|
|
1250
1266
|
track: ev.target,
|
|
1251
1267
|
constructId: this.constructId,
|
|
1252
1268
|
metaData: this.options.metaData,
|
|
1253
1269
|
adding: false,
|
|
1270
|
+
removing: true,
|
|
1254
1271
|
hasAudioTrack: !!(config.stream && config.stream.getAudioTracks().length),
|
|
1255
1272
|
hasVideoTrack: !!(config.stream && config.stream.getVideoTracks().length)
|
|
1256
1273
|
});
|
|
1257
1274
|
}
|
|
1258
1275
|
};
|
|
1259
|
-
|
|
1276
|
+
|
|
1260
1277
|
event.track.onmute = (ev) => {
|
|
1261
1278
|
this._log('remoteTrackMuted', 'onmute');
|
|
1279
|
+
|
|
1280
|
+
let mid = ev.target.id;
|
|
1281
|
+
if(this.isUnifiedPlan) {
|
|
1282
|
+
let transceiver = config.pc.getTransceivers().find(
|
|
1283
|
+
t => t.receiver.track === ev.target);
|
|
1284
|
+
mid = transceiver.mid;
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1262
1287
|
this.emit('remoteTrackMuted', {
|
|
1263
1288
|
id: handle.handleId,
|
|
1289
|
+
mid,
|
|
1264
1290
|
userId: handle.userId,
|
|
1265
1291
|
stream: config.stream,
|
|
1266
1292
|
kind: ev.target.kind,
|
|
@@ -1268,11 +1294,20 @@ class RoomSession {
|
|
|
1268
1294
|
muted: true
|
|
1269
1295
|
});
|
|
1270
1296
|
};
|
|
1271
|
-
|
|
1297
|
+
|
|
1272
1298
|
event.track.onunmute = (ev) => {
|
|
1273
1299
|
this._log('remoteTrackMuted', 'onunmute');
|
|
1300
|
+
|
|
1301
|
+
let mid = ev.target.id;
|
|
1302
|
+
if(this.isUnifiedPlan) {
|
|
1303
|
+
let transceiver = config.pc.getTransceivers().find(
|
|
1304
|
+
t => t.receiver.track === ev.target);
|
|
1305
|
+
mid = transceiver.mid;
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1274
1308
|
this.emit('remoteTrackMuted', {
|
|
1275
1309
|
id: handle.handleId,
|
|
1310
|
+
mid,
|
|
1276
1311
|
userId: handle.userId,
|
|
1277
1312
|
stream: config.stream,
|
|
1278
1313
|
kind: ev.target.kind,
|
|
@@ -1280,55 +1315,71 @@ class RoomSession {
|
|
|
1280
1315
|
muted: false
|
|
1281
1316
|
});
|
|
1282
1317
|
};
|
|
1283
|
-
|
|
1318
|
+
|
|
1284
1319
|
}
|
|
1285
|
-
|
|
1320
|
+
|
|
1286
1321
|
};
|
|
1287
1322
|
}
|
|
1288
1323
|
}
|
|
1289
|
-
|
|
1290
|
-
let defaultDataChannelLabel = 'JanusDataChannel';
|
|
1291
|
-
|
|
1324
|
+
|
|
1292
1325
|
if (!config.dataChannel || !config.dataChannelOpen) {
|
|
1293
|
-
|
|
1326
|
+
|
|
1327
|
+
config.dataChannel = {};
|
|
1328
|
+
|
|
1294
1329
|
var onDataChannelMessage = (event) => {
|
|
1295
1330
|
this._handleDataEvents(handleId, 'message', event.data);
|
|
1296
1331
|
};
|
|
1297
1332
|
var onDataChannelStateChange = (event) => {
|
|
1298
|
-
|
|
1333
|
+
let label = event.target.label;
|
|
1334
|
+
let protocol = event.target.protocol;
|
|
1335
|
+
let state = config.dataChannel[label] ? config.dataChannel[label].readyState : "null";
|
|
1336
|
+
this._handleDataEvents(handleId, 'state', {state, label} );
|
|
1299
1337
|
};
|
|
1338
|
+
//TODO: check this
|
|
1300
1339
|
var onDataChannelError = (error) => {
|
|
1301
|
-
this._handleDataEvents(handleId, 'error', error);
|
|
1340
|
+
this._handleDataEvents(handleId, 'error', {label: error?.channel?.label, error});
|
|
1302
1341
|
};
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1342
|
+
|
|
1343
|
+
const createDataChannel = (label, protocol, incoming) => {
|
|
1344
|
+
let options = {ordered: true};
|
|
1345
|
+
if(!incoming) {
|
|
1346
|
+
if(protocol) {
|
|
1347
|
+
options = {...options, protocol}
|
|
1348
|
+
}
|
|
1349
|
+
config.dataChannel[label] = config.pc.createDataChannel(label, options);
|
|
1350
|
+
}
|
|
1351
|
+
else {
|
|
1352
|
+
config.dataChannel[label] = incoming;
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1355
|
+
config.dataChannel[label].onmessage = onDataChannelMessage;
|
|
1356
|
+
config.dataChannel[label].onopen = onDataChannelStateChange;
|
|
1357
|
+
config.dataChannel[label].onclose = onDataChannelStateChange;
|
|
1358
|
+
config.dataChannel[label].onerror = onDataChannelError;
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1361
|
+
createDataChannel(this.defaultDataChannelLabel, null, null)
|
|
1310
1362
|
config.pc.ondatachannel = function (event) {
|
|
1311
|
-
|
|
1312
|
-
console.log('Janus is creating data channel');
|
|
1363
|
+
createDataChannel(event.channel.label, event.channel.protocol, event.channel)
|
|
1313
1364
|
};
|
|
1314
1365
|
}
|
|
1315
1366
|
}
|
|
1316
|
-
|
|
1367
|
+
|
|
1317
1368
|
_webrtcPeer(handleId, jsep) {
|
|
1318
|
-
|
|
1369
|
+
|
|
1319
1370
|
let handle = this._getHandle(handleId);
|
|
1320
1371
|
if (!handle) {
|
|
1321
1372
|
return Promise.reject({type: 'warning', id: 15, message: 'id non-existent', data: [handleId, 'rtc peer']});
|
|
1322
1373
|
}
|
|
1323
|
-
|
|
1374
|
+
|
|
1324
1375
|
var config = handle.webrtcStuff;
|
|
1325
|
-
|
|
1376
|
+
|
|
1326
1377
|
if (jsep !== undefined && jsep !== null) {
|
|
1327
1378
|
if (config.pc === null) {
|
|
1328
1379
|
this._log("No PeerConnection: if this is an answer, use createAnswer and not _webrtcPeer");
|
|
1329
1380
|
return Promise.resolve(null);
|
|
1330
1381
|
}
|
|
1331
|
-
|
|
1382
|
+
|
|
1332
1383
|
return config.pc.setRemoteDescription(jsep)
|
|
1333
1384
|
.then(() => {
|
|
1334
1385
|
config.remoteSdp = jsep.sdp;
|
|
@@ -1351,20 +1402,20 @@ class RoomSession {
|
|
|
1351
1402
|
return Promise.reject({type: 'warning', id: 22, message: 'rtc peer', data: [handleId, 'invalid jsep']});
|
|
1352
1403
|
}
|
|
1353
1404
|
}
|
|
1354
|
-
|
|
1405
|
+
|
|
1355
1406
|
_iceRestart(handleId) {
|
|
1356
|
-
|
|
1407
|
+
|
|
1357
1408
|
let handle = this._getHandle(handleId);
|
|
1358
1409
|
if (!handle) {
|
|
1359
1410
|
return;
|
|
1360
1411
|
}
|
|
1361
1412
|
var config = handle.webrtcStuff;
|
|
1362
|
-
|
|
1413
|
+
|
|
1363
1414
|
// Already restarting;
|
|
1364
1415
|
if (config.isIceRestarting) {
|
|
1365
1416
|
return;
|
|
1366
1417
|
}
|
|
1367
|
-
|
|
1418
|
+
|
|
1368
1419
|
if (this.handleId === handleId) {
|
|
1369
1420
|
this._log('Performing local ICE restart');
|
|
1370
1421
|
config.isIceRestarting = true;
|
|
@@ -1399,11 +1450,11 @@ class RoomSession {
|
|
|
1399
1450
|
config.isIceRestarting = false;
|
|
1400
1451
|
});
|
|
1401
1452
|
}
|
|
1402
|
-
|
|
1453
|
+
|
|
1403
1454
|
}
|
|
1404
|
-
|
|
1455
|
+
|
|
1405
1456
|
_createAO(type = 'offer', handleId, iceRestart = false, [audioSend, audioRecv, videoSend, videoRecv]) {
|
|
1406
|
-
|
|
1457
|
+
|
|
1407
1458
|
let handle = this._getHandle(handleId);
|
|
1408
1459
|
if (!handle) {
|
|
1409
1460
|
return Promise.reject({
|
|
@@ -1413,16 +1464,16 @@ class RoomSession {
|
|
|
1413
1464
|
data: [handleId, 'createAO', type]
|
|
1414
1465
|
});
|
|
1415
1466
|
}
|
|
1416
|
-
|
|
1467
|
+
|
|
1417
1468
|
let methodName = null;
|
|
1418
1469
|
if (type === 'offer') {
|
|
1419
1470
|
methodName = 'createOffer'
|
|
1420
1471
|
} else {
|
|
1421
1472
|
methodName = 'createAnswer'
|
|
1422
1473
|
}
|
|
1423
|
-
|
|
1474
|
+
|
|
1424
1475
|
var config = handle.webrtcStuff;
|
|
1425
|
-
|
|
1476
|
+
|
|
1426
1477
|
// https://code.google.com/p/webrtc/issues/detail?id=3508
|
|
1427
1478
|
var mediaConstraints = {};
|
|
1428
1479
|
if (this.isUnifiedPlan) {
|
|
@@ -1445,7 +1496,7 @@ class RoomSession {
|
|
|
1445
1496
|
}
|
|
1446
1497
|
}
|
|
1447
1498
|
}
|
|
1448
|
-
|
|
1499
|
+
|
|
1449
1500
|
// Handle audio (and related changes, if any)
|
|
1450
1501
|
if (!audioSend && !audioRecv) {
|
|
1451
1502
|
// Audio disabled: have we removed it?
|
|
@@ -1528,7 +1579,7 @@ class RoomSession {
|
|
|
1528
1579
|
}
|
|
1529
1580
|
}
|
|
1530
1581
|
} else {
|
|
1531
|
-
|
|
1582
|
+
|
|
1532
1583
|
if (adapter.browserDetails.browser === "firefox" || adapter.browserDetails.browser === "edge") {
|
|
1533
1584
|
mediaConstraints = {
|
|
1534
1585
|
offerToReceiveAudio: audioRecv,
|
|
@@ -1543,11 +1594,11 @@ class RoomSession {
|
|
|
1543
1594
|
};
|
|
1544
1595
|
}
|
|
1545
1596
|
}
|
|
1546
|
-
|
|
1597
|
+
|
|
1547
1598
|
if (iceRestart) {
|
|
1548
1599
|
mediaConstraints["iceRestart"] = true;
|
|
1549
1600
|
}
|
|
1550
|
-
|
|
1601
|
+
|
|
1551
1602
|
return config.pc[methodName](mediaConstraints)
|
|
1552
1603
|
.then(function (response) {
|
|
1553
1604
|
config.mySdp = response.sdp;
|
|
@@ -1565,21 +1616,21 @@ class RoomSession {
|
|
|
1565
1616
|
// Don't do anything until we have all candidates
|
|
1566
1617
|
return Promise.resolve(null);
|
|
1567
1618
|
}
|
|
1568
|
-
|
|
1619
|
+
|
|
1569
1620
|
// JSON.stringify doesn't work on some WebRTC objects anymore
|
|
1570
1621
|
// See https://code.google.com/p/chromium/issues/detail?id=467366
|
|
1571
1622
|
var jsep = {
|
|
1572
1623
|
"type": response.type,
|
|
1573
1624
|
"sdp": response.sdp
|
|
1574
1625
|
};
|
|
1575
|
-
|
|
1626
|
+
|
|
1576
1627
|
return _p.then(() => jsep)
|
|
1577
1628
|
}, (e) => {
|
|
1578
1629
|
return Promise.reject({type: 'warning', id: 25, message: methodName, data: [handleId, e]})
|
|
1579
1630
|
});
|
|
1580
|
-
|
|
1631
|
+
|
|
1581
1632
|
}
|
|
1582
|
-
|
|
1633
|
+
|
|
1583
1634
|
_publishRemote(handleId, jsep) {
|
|
1584
1635
|
let handle = this._getHandle(handleId);
|
|
1585
1636
|
if (!handle) {
|
|
@@ -1590,11 +1641,11 @@ class RoomSession {
|
|
|
1590
1641
|
data: [handleId, 'publish remote participant']
|
|
1591
1642
|
})
|
|
1592
1643
|
}
|
|
1593
|
-
|
|
1644
|
+
|
|
1594
1645
|
this._webrtc(handleId, true);
|
|
1595
|
-
|
|
1646
|
+
|
|
1596
1647
|
let config = handle.webrtcStuff;
|
|
1597
|
-
|
|
1648
|
+
|
|
1598
1649
|
if (jsep) {
|
|
1599
1650
|
return config.pc.setRemoteDescription(jsep)
|
|
1600
1651
|
.then(() => {
|
|
@@ -1636,19 +1687,19 @@ class RoomSession {
|
|
|
1636
1687
|
message: 'setRemoteDescription',
|
|
1637
1688
|
data: [handleId, e]
|
|
1638
1689
|
}));
|
|
1639
|
-
|
|
1690
|
+
|
|
1640
1691
|
} else {
|
|
1641
1692
|
return Promise.resolve();
|
|
1642
1693
|
}
|
|
1643
|
-
|
|
1694
|
+
|
|
1644
1695
|
}
|
|
1645
|
-
|
|
1696
|
+
|
|
1646
1697
|
//Public methods
|
|
1647
|
-
|
|
1698
|
+
|
|
1648
1699
|
publishLocal(stream, {keepAudio = false, keepVideo = false} = {}) {
|
|
1649
|
-
|
|
1700
|
+
|
|
1650
1701
|
this.emit('publishing', true);
|
|
1651
|
-
|
|
1702
|
+
|
|
1652
1703
|
let handle = this._getHandle(this.handleId);
|
|
1653
1704
|
if (!handle) {
|
|
1654
1705
|
return Promise.reject({
|
|
@@ -1658,24 +1709,24 @@ class RoomSession {
|
|
|
1658
1709
|
data: null
|
|
1659
1710
|
})
|
|
1660
1711
|
}
|
|
1661
|
-
|
|
1712
|
+
|
|
1662
1713
|
this._webrtc(this.handleId);
|
|
1663
|
-
|
|
1714
|
+
|
|
1664
1715
|
let config = handle.webrtcStuff;
|
|
1665
|
-
|
|
1716
|
+
|
|
1666
1717
|
if (stream) {
|
|
1667
1718
|
if (!config.stream) {
|
|
1668
1719
|
config.stream = stream;
|
|
1669
1720
|
stream.getTracks().forEach(function (track) {
|
|
1670
1721
|
config.pc.addTrack(track, stream);
|
|
1671
1722
|
});
|
|
1672
|
-
|
|
1723
|
+
|
|
1673
1724
|
} else {
|
|
1674
|
-
|
|
1725
|
+
|
|
1675
1726
|
/* UPDATE Audio */
|
|
1676
|
-
|
|
1727
|
+
|
|
1677
1728
|
let replaceAudio = stream.getAudioTracks().length;
|
|
1678
|
-
|
|
1729
|
+
|
|
1679
1730
|
if (replaceAudio || !keepAudio) {
|
|
1680
1731
|
//this will stop existing tracks
|
|
1681
1732
|
let oldAudioStream = config.stream.getAudioTracks()[0];
|
|
@@ -1688,7 +1739,7 @@ class RoomSession {
|
|
|
1688
1739
|
}
|
|
1689
1740
|
}
|
|
1690
1741
|
}
|
|
1691
|
-
|
|
1742
|
+
|
|
1692
1743
|
if (config.pc.getSenders() && config.pc.getSenders().length) {
|
|
1693
1744
|
if (replaceAudio && this.isUnifiedPlan) {
|
|
1694
1745
|
//using replace
|
|
@@ -1701,7 +1752,7 @@ class RoomSession {
|
|
|
1701
1752
|
}
|
|
1702
1753
|
}
|
|
1703
1754
|
}
|
|
1704
|
-
|
|
1755
|
+
|
|
1705
1756
|
if (replaceAudio) {
|
|
1706
1757
|
config.stream.addTrack(stream.getAudioTracks()[0]);
|
|
1707
1758
|
var audioTransceiver = null;
|
|
@@ -1718,19 +1769,19 @@ class RoomSession {
|
|
|
1718
1769
|
}
|
|
1719
1770
|
}
|
|
1720
1771
|
}
|
|
1721
|
-
|
|
1772
|
+
|
|
1722
1773
|
if (audioTransceiver && audioTransceiver.sender) {
|
|
1723
1774
|
audioTransceiver.sender.replaceTrack(stream.getAudioTracks()[0]);
|
|
1724
1775
|
} else {
|
|
1725
1776
|
config.pc.addTrack(stream.getAudioTracks()[0], stream);
|
|
1726
1777
|
}
|
|
1727
|
-
|
|
1778
|
+
|
|
1728
1779
|
}
|
|
1729
|
-
|
|
1780
|
+
|
|
1730
1781
|
/* UPDATE Video */
|
|
1731
|
-
|
|
1782
|
+
|
|
1732
1783
|
let replaceVideo = stream.getVideoTracks().length;
|
|
1733
|
-
|
|
1784
|
+
|
|
1734
1785
|
if (replaceVideo || !keepVideo) {
|
|
1735
1786
|
let oldVideoStream = config.stream.getVideoTracks()[0];
|
|
1736
1787
|
if (oldVideoStream) {
|
|
@@ -1742,7 +1793,7 @@ class RoomSession {
|
|
|
1742
1793
|
}
|
|
1743
1794
|
}
|
|
1744
1795
|
}
|
|
1745
|
-
|
|
1796
|
+
|
|
1746
1797
|
if (config.pc.getSenders() && config.pc.getSenders().length) {
|
|
1747
1798
|
if (replaceVideo && this.isUnifiedPlan) {
|
|
1748
1799
|
//using replace
|
|
@@ -1755,7 +1806,7 @@ class RoomSession {
|
|
|
1755
1806
|
}
|
|
1756
1807
|
}
|
|
1757
1808
|
}
|
|
1758
|
-
|
|
1809
|
+
|
|
1759
1810
|
if (replaceVideo) {
|
|
1760
1811
|
config.stream.addTrack(stream.getVideoTracks()[0]);
|
|
1761
1812
|
var videoTransceiver = null;
|
|
@@ -1781,17 +1832,17 @@ class RoomSession {
|
|
|
1781
1832
|
}
|
|
1782
1833
|
}
|
|
1783
1834
|
}
|
|
1784
|
-
|
|
1835
|
+
|
|
1785
1836
|
let hasAudio = !!(stream && stream.getAudioTracks().length > 0);
|
|
1786
1837
|
let hasVideo = !!(stream && stream.getVideoTracks().length > 0);
|
|
1787
1838
|
let isAudioMuted = !stream || stream.getAudioTracks().length === 0 || !stream.getAudioTracks()[0].enabled;
|
|
1788
1839
|
let isVideoMuted = !stream || stream.getVideoTracks().length === 0 || !stream.getVideoTracks()[0].enabled;
|
|
1789
|
-
|
|
1840
|
+
|
|
1790
1841
|
this.isAudioEnabed = hasAudio;
|
|
1791
1842
|
this.isVideoEnabled = hasVideo;
|
|
1792
1843
|
this.isAudioMuted = isAudioMuted;
|
|
1793
1844
|
this.isVideoMuted = isVideoMuted;
|
|
1794
|
-
|
|
1845
|
+
|
|
1795
1846
|
return this._createAO('offer', this.handleId, false, [hasAudio, false, hasVideo, false])
|
|
1796
1847
|
.then((jsep) => {
|
|
1797
1848
|
if (!jsep) {
|
|
@@ -1828,7 +1879,54 @@ class RoomSession {
|
|
|
1828
1879
|
})
|
|
1829
1880
|
.then(r => {
|
|
1830
1881
|
this._isPublished = true;
|
|
1831
|
-
|
|
1882
|
+
if(config.stream) {
|
|
1883
|
+
let tracks = config.stream.getTracks();
|
|
1884
|
+
tracks.forEach(track => {
|
|
1885
|
+
// used as a flag to not emit tracks that been already emitted
|
|
1886
|
+
if(!track.onended) {
|
|
1887
|
+
this.emit('addLocalParticipant', {
|
|
1888
|
+
tid: generateUUID(),
|
|
1889
|
+
id: handle.handleId,
|
|
1890
|
+
userId: handle.userId,
|
|
1891
|
+
track,
|
|
1892
|
+
stream: config.stream,
|
|
1893
|
+
adding: true,
|
|
1894
|
+
constructId: this.constructId,
|
|
1895
|
+
metaData: this.options.metaData,
|
|
1896
|
+
hasAudioTrack: hasAudio,
|
|
1897
|
+
hasVideoTrack: hasVideo
|
|
1898
|
+
});
|
|
1899
|
+
track.onended = (ev) => {
|
|
1900
|
+
this.emit('addLocalParticipant', {
|
|
1901
|
+
tid:generateUUID(),
|
|
1902
|
+
id: handle.handleId,
|
|
1903
|
+
userId: handle.userId,
|
|
1904
|
+
track: ev.target,
|
|
1905
|
+
stream: config.stream,
|
|
1906
|
+
adding: false,
|
|
1907
|
+
removing: true,
|
|
1908
|
+
constructId: this.constructId,
|
|
1909
|
+
metaData: this.options.metaData,
|
|
1910
|
+
hasAudioTrack: hasAudio,
|
|
1911
|
+
hasVideoTrack: hasVideo
|
|
1912
|
+
});
|
|
1913
|
+
}
|
|
1914
|
+
}
|
|
1915
|
+
})
|
|
1916
|
+
} else {
|
|
1917
|
+
this.emit('addLocalParticipant', {
|
|
1918
|
+
tid: generateUUID(),
|
|
1919
|
+
id: handle.handleId,
|
|
1920
|
+
userId: handle.userId,
|
|
1921
|
+
stream: null,
|
|
1922
|
+
adding: false,
|
|
1923
|
+
constructId: this.constructId,
|
|
1924
|
+
metaData: this.options.metaData,
|
|
1925
|
+
hasAudioTrack: hasAudio,
|
|
1926
|
+
hasVideoTrack: hasVideo
|
|
1927
|
+
});
|
|
1928
|
+
}
|
|
1929
|
+
|
|
1832
1930
|
this.emit('published', {status: true, hasStream: !!config.stream});
|
|
1833
1931
|
this.emit('publishing', false);
|
|
1834
1932
|
this.emit('localHasVideo', hasVideo);
|
|
@@ -1842,7 +1940,7 @@ class RoomSession {
|
|
|
1842
1940
|
return Promise.reject(e);
|
|
1843
1941
|
})
|
|
1844
1942
|
}
|
|
1845
|
-
|
|
1943
|
+
|
|
1846
1944
|
unpublishLocal(dontWait = false) {
|
|
1847
1945
|
return this._isPublished
|
|
1848
1946
|
? this.sendMessage(this.handleId, {body: {"request": "unpublish"}}, dontWait)
|
|
@@ -1853,8 +1951,8 @@ class RoomSession {
|
|
|
1853
1951
|
})
|
|
1854
1952
|
: Promise.resolve()
|
|
1855
1953
|
}
|
|
1856
|
-
|
|
1857
|
-
toggleAudio(value = null) {
|
|
1954
|
+
|
|
1955
|
+
toggleAudio(value = null, mid) {
|
|
1858
1956
|
let handle = this._getHandle(this.handleId);
|
|
1859
1957
|
if (!handle) {
|
|
1860
1958
|
return Promise.reject({type: 'error', id: 21, message: 'no local id, connect first', data: null})
|
|
@@ -1862,7 +1960,7 @@ class RoomSession {
|
|
|
1862
1960
|
let config = handle.webrtcStuff;
|
|
1863
1961
|
if (this.isUnifiedPlan) {
|
|
1864
1962
|
let transceiver = config.pc.getTransceivers()
|
|
1865
|
-
.find(t => t.sender && t.sender.track && t.receiver.track.kind === "audio" && t.stopped === false);
|
|
1963
|
+
.find(t => t.sender && t.sender.track && t.receiver.track.kind === "audio" && t.stopped === false && (mid ? t.mid === mid : true));
|
|
1866
1964
|
if (transceiver) {
|
|
1867
1965
|
transceiver.sender.track.enabled = value !== null ? !!value : !transceiver.sender.track.enabled;
|
|
1868
1966
|
}
|
|
@@ -1873,51 +1971,51 @@ class RoomSession {
|
|
|
1873
1971
|
}
|
|
1874
1972
|
this.isAudioMuted = config.stream.getAudioTracks().length === 0 || !config.stream.getAudioTracks()[0].enabled;
|
|
1875
1973
|
}
|
|
1876
|
-
this.emit('localMuted', {type: 'audio', value: this.isAudioMuted});
|
|
1974
|
+
this.emit('localMuted', {type: 'audio', value: this.isAudioMuted, mid});
|
|
1877
1975
|
}
|
|
1878
|
-
|
|
1879
|
-
toggleVideo() {
|
|
1976
|
+
|
|
1977
|
+
toggleVideo(value = null, mid) {
|
|
1880
1978
|
let handle = this._getHandle(this.handleId);
|
|
1881
1979
|
if (!handle) {
|
|
1882
1980
|
return Promise.reject({type: 'error', id: 21, message: 'no local id, connect first', data: null})
|
|
1883
1981
|
}
|
|
1884
1982
|
let config = handle.webrtcStuff;
|
|
1885
|
-
|
|
1983
|
+
|
|
1886
1984
|
if (this.isUnifiedPlan) {
|
|
1887
1985
|
let transceiver = config.pc.getTransceivers()
|
|
1888
|
-
.find(t => t.sender && t.sender.track && t.receiver.track.kind === "video" && t.stopped === false);
|
|
1986
|
+
.find(t => t.sender && t.sender.track && t.receiver.track.kind === "video" && t.stopped === false && (mid ? t.mid === mid : true));
|
|
1889
1987
|
if (transceiver) {
|
|
1890
|
-
transceiver.sender.track.enabled = !transceiver.sender.track.enabled;
|
|
1988
|
+
transceiver.sender.track.enabled = value !== null ? !!value : !transceiver.sender.track.enabled;
|
|
1891
1989
|
}
|
|
1892
1990
|
this.isVideoMuted = !transceiver || !transceiver.sender.track.enabled;
|
|
1893
1991
|
}
|
|
1894
1992
|
else {
|
|
1895
1993
|
if (config.stream && config.stream.getVideoTracks().length) {
|
|
1896
|
-
config.stream.getVideoTracks()[0].enabled = !config.stream.getVideoTracks()[0].enabled;
|
|
1994
|
+
config.stream.getVideoTracks()[0].enabled = value !== null ? !!value : !config.stream.getVideoTracks()[0].enabled;
|
|
1897
1995
|
}
|
|
1898
1996
|
this.isVideoMuted = config.stream.getVideoTracks().length === 0 || !config.stream.getVideoTracks()[0].enabled;
|
|
1899
1997
|
}
|
|
1900
|
-
this.emit('localMuted', {type: 'video', value: this.isVideoMuted});
|
|
1998
|
+
this.emit('localMuted', {type: 'video', value: this.isVideoMuted, mid});
|
|
1901
1999
|
}
|
|
1902
|
-
|
|
2000
|
+
|
|
1903
2001
|
setInstructorId(instructorId = null) {
|
|
1904
2002
|
this._instuctorId = instructorId;
|
|
1905
2003
|
this.emit('instructorId', this._instuctorId);
|
|
1906
2004
|
return this._instuctorId;
|
|
1907
2005
|
}
|
|
1908
|
-
|
|
2006
|
+
|
|
1909
2007
|
setObserverIds(observerIds = []) {
|
|
1910
2008
|
this._observerIds = observerIds;
|
|
1911
2009
|
this.emit('observerIds', this._observerIds);
|
|
1912
2010
|
return this._observerIds;
|
|
1913
2011
|
}
|
|
1914
|
-
|
|
2012
|
+
|
|
1915
2013
|
setTalkbackIds(talkbackIds = []) {
|
|
1916
2014
|
this._talkbackIds = talkbackIds;
|
|
1917
2015
|
this.emit('talkbackIds', this._talkbackIds);
|
|
1918
2016
|
return this._talkbackIds;
|
|
1919
2017
|
}
|
|
1920
|
-
|
|
2018
|
+
|
|
1921
2019
|
}
|
|
1922
2020
|
|
|
1923
2021
|
export default Room;
|