@reactoo/watchtogether-sdk-js 2.5.21 → 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.
@@ -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;
@@ -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
- config.dataChannelOpen = false;
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.onmessage = null;
742
- handle.webrtcStuff.dataChannel.onopen = null;
743
- handle.webrtcStuff.dataChannel.onclose = null;
744
- handle.webrtcStuff.dataChannel.onerror = null;
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') {
@@ -1203,22 +1207,22 @@ class RoomSession {
1203
1207
  "sdpMid": event.candidate.sdpMid,
1204
1208
  "sdpMLineIndex": event.candidate.sdpMLineIndex
1205
1209
  };
1206
-
1210
+
1207
1211
  this._sendTrickleCandidate(handleId, candidate)
1208
1212
  .catch(e => {
1209
1213
  this.emit('error', e);
1210
1214
  });
1211
1215
  }
1212
1216
  };
1213
-
1217
+
1214
1218
  if (enableOntrack) {
1215
1219
  config.pc.ontrack = (event) => {
1216
-
1220
+
1217
1221
  if(!event.streams)
1218
- return;
1222
+ return;
1219
1223
 
1220
1224
  //config.stream = event.streams[0];
1221
-
1225
+
1222
1226
  if (!config.stream) {
1223
1227
  config.stream = new MediaStream();
1224
1228
  }
@@ -1238,10 +1242,10 @@ class RoomSession {
1238
1242
  hasAudioTrack: !!(config.stream && config.stream.getAudioTracks().length),
1239
1243
  hasVideoTrack: !!(config.stream && config.stream.getVideoTracks().length)
1240
1244
  });
1241
-
1245
+
1242
1246
  if (event.track.onended)
1243
1247
  return;
1244
-
1248
+
1245
1249
  event.track.onended = (ev) => {
1246
1250
 
1247
1251
  let mid = ev.target.id;
@@ -1269,7 +1273,7 @@ class RoomSession {
1269
1273
  });
1270
1274
  }
1271
1275
  };
1272
-
1276
+
1273
1277
  event.track.onmute = (ev) => {
1274
1278
  this._log('remoteTrackMuted', 'onmute');
1275
1279
 
@@ -1290,7 +1294,7 @@ class RoomSession {
1290
1294
  muted: true
1291
1295
  });
1292
1296
  };
1293
-
1297
+
1294
1298
  event.track.onunmute = (ev) => {
1295
1299
  this._log('remoteTrackMuted', 'onunmute');
1296
1300
 
@@ -1311,55 +1315,71 @@ class RoomSession {
1311
1315
  muted: false
1312
1316
  });
1313
1317
  };
1314
-
1318
+
1315
1319
  }
1316
-
1320
+
1317
1321
  };
1318
1322
  }
1319
1323
  }
1320
-
1321
- let defaultDataChannelLabel = 'JanusDataChannel';
1322
-
1324
+
1323
1325
  if (!config.dataChannel || !config.dataChannelOpen) {
1324
-
1326
+
1327
+ config.dataChannel = {};
1328
+
1325
1329
  var onDataChannelMessage = (event) => {
1326
1330
  this._handleDataEvents(handleId, 'message', event.data);
1327
1331
  };
1328
1332
  var onDataChannelStateChange = (event) => {
1329
- this._handleDataEvents(handleId, 'state', config.dataChannel.readyState);
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} );
1330
1337
  };
1338
+ //TODO: check this
1331
1339
  var onDataChannelError = (error) => {
1332
- this._handleDataEvents(handleId, 'error', error);
1340
+ this._handleDataEvents(handleId, 'error', {label: error?.channel?.label, error});
1333
1341
  };
1334
- // Until we implement the proxying of open requests within the Janus core, we open a channel ourselves whatever the case
1335
- config.dataChannel = config.pc.createDataChannel(defaultDataChannelLabel, {ordered: true});
1336
- config.dataChannel.onmessage = onDataChannelMessage;
1337
- config.dataChannel.onopen = onDataChannelStateChange;
1338
- config.dataChannel.onclose = onDataChannelStateChange;
1339
- config.dataChannel.onerror = onDataChannelError;
1340
-
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)
1341
1362
  config.pc.ondatachannel = function (event) {
1342
- //TODO: implement this
1343
- console.log('Janus is creating data channel');
1363
+ createDataChannel(event.channel.label, event.channel.protocol, event.channel)
1344
1364
  };
1345
1365
  }
1346
1366
  }
1347
-
1367
+
1348
1368
  _webrtcPeer(handleId, jsep) {
1349
-
1369
+
1350
1370
  let handle = this._getHandle(handleId);
1351
1371
  if (!handle) {
1352
1372
  return Promise.reject({type: 'warning', id: 15, message: 'id non-existent', data: [handleId, 'rtc peer']});
1353
1373
  }
1354
-
1374
+
1355
1375
  var config = handle.webrtcStuff;
1356
-
1376
+
1357
1377
  if (jsep !== undefined && jsep !== null) {
1358
1378
  if (config.pc === null) {
1359
1379
  this._log("No PeerConnection: if this is an answer, use createAnswer and not _webrtcPeer");
1360
1380
  return Promise.resolve(null);
1361
1381
  }
1362
-
1382
+
1363
1383
  return config.pc.setRemoteDescription(jsep)
1364
1384
  .then(() => {
1365
1385
  config.remoteSdp = jsep.sdp;
@@ -1382,20 +1402,20 @@ class RoomSession {
1382
1402
  return Promise.reject({type: 'warning', id: 22, message: 'rtc peer', data: [handleId, 'invalid jsep']});
1383
1403
  }
1384
1404
  }
1385
-
1405
+
1386
1406
  _iceRestart(handleId) {
1387
-
1407
+
1388
1408
  let handle = this._getHandle(handleId);
1389
1409
  if (!handle) {
1390
1410
  return;
1391
1411
  }
1392
1412
  var config = handle.webrtcStuff;
1393
-
1413
+
1394
1414
  // Already restarting;
1395
1415
  if (config.isIceRestarting) {
1396
1416
  return;
1397
1417
  }
1398
-
1418
+
1399
1419
  if (this.handleId === handleId) {
1400
1420
  this._log('Performing local ICE restart');
1401
1421
  config.isIceRestarting = true;
@@ -1430,11 +1450,11 @@ class RoomSession {
1430
1450
  config.isIceRestarting = false;
1431
1451
  });
1432
1452
  }
1433
-
1453
+
1434
1454
  }
1435
-
1455
+
1436
1456
  _createAO(type = 'offer', handleId, iceRestart = false, [audioSend, audioRecv, videoSend, videoRecv]) {
1437
-
1457
+
1438
1458
  let handle = this._getHandle(handleId);
1439
1459
  if (!handle) {
1440
1460
  return Promise.reject({
@@ -1444,16 +1464,16 @@ class RoomSession {
1444
1464
  data: [handleId, 'createAO', type]
1445
1465
  });
1446
1466
  }
1447
-
1467
+
1448
1468
  let methodName = null;
1449
1469
  if (type === 'offer') {
1450
1470
  methodName = 'createOffer'
1451
1471
  } else {
1452
1472
  methodName = 'createAnswer'
1453
1473
  }
1454
-
1474
+
1455
1475
  var config = handle.webrtcStuff;
1456
-
1476
+
1457
1477
  // https://code.google.com/p/webrtc/issues/detail?id=3508
1458
1478
  var mediaConstraints = {};
1459
1479
  if (this.isUnifiedPlan) {
@@ -1476,7 +1496,7 @@ class RoomSession {
1476
1496
  }
1477
1497
  }
1478
1498
  }
1479
-
1499
+
1480
1500
  // Handle audio (and related changes, if any)
1481
1501
  if (!audioSend && !audioRecv) {
1482
1502
  // Audio disabled: have we removed it?
@@ -1559,7 +1579,7 @@ class RoomSession {
1559
1579
  }
1560
1580
  }
1561
1581
  } else {
1562
-
1582
+
1563
1583
  if (adapter.browserDetails.browser === "firefox" || adapter.browserDetails.browser === "edge") {
1564
1584
  mediaConstraints = {
1565
1585
  offerToReceiveAudio: audioRecv,
@@ -1574,11 +1594,11 @@ class RoomSession {
1574
1594
  };
1575
1595
  }
1576
1596
  }
1577
-
1597
+
1578
1598
  if (iceRestart) {
1579
1599
  mediaConstraints["iceRestart"] = true;
1580
1600
  }
1581
-
1601
+
1582
1602
  return config.pc[methodName](mediaConstraints)
1583
1603
  .then(function (response) {
1584
1604
  config.mySdp = response.sdp;
@@ -1596,21 +1616,21 @@ class RoomSession {
1596
1616
  // Don't do anything until we have all candidates
1597
1617
  return Promise.resolve(null);
1598
1618
  }
1599
-
1619
+
1600
1620
  // JSON.stringify doesn't work on some WebRTC objects anymore
1601
1621
  // See https://code.google.com/p/chromium/issues/detail?id=467366
1602
1622
  var jsep = {
1603
1623
  "type": response.type,
1604
1624
  "sdp": response.sdp
1605
1625
  };
1606
-
1626
+
1607
1627
  return _p.then(() => jsep)
1608
1628
  }, (e) => {
1609
1629
  return Promise.reject({type: 'warning', id: 25, message: methodName, data: [handleId, e]})
1610
1630
  });
1611
-
1631
+
1612
1632
  }
1613
-
1633
+
1614
1634
  _publishRemote(handleId, jsep) {
1615
1635
  let handle = this._getHandle(handleId);
1616
1636
  if (!handle) {
@@ -1621,11 +1641,11 @@ class RoomSession {
1621
1641
  data: [handleId, 'publish remote participant']
1622
1642
  })
1623
1643
  }
1624
-
1644
+
1625
1645
  this._webrtc(handleId, true);
1626
-
1646
+
1627
1647
  let config = handle.webrtcStuff;
1628
-
1648
+
1629
1649
  if (jsep) {
1630
1650
  return config.pc.setRemoteDescription(jsep)
1631
1651
  .then(() => {
@@ -1667,19 +1687,19 @@ class RoomSession {
1667
1687
  message: 'setRemoteDescription',
1668
1688
  data: [handleId, e]
1669
1689
  }));
1670
-
1690
+
1671
1691
  } else {
1672
1692
  return Promise.resolve();
1673
1693
  }
1674
-
1694
+
1675
1695
  }
1676
-
1696
+
1677
1697
  //Public methods
1678
-
1698
+
1679
1699
  publishLocal(stream, {keepAudio = false, keepVideo = false} = {}) {
1680
-
1700
+
1681
1701
  this.emit('publishing', true);
1682
-
1702
+
1683
1703
  let handle = this._getHandle(this.handleId);
1684
1704
  if (!handle) {
1685
1705
  return Promise.reject({
@@ -1689,24 +1709,24 @@ class RoomSession {
1689
1709
  data: null
1690
1710
  })
1691
1711
  }
1692
-
1712
+
1693
1713
  this._webrtc(this.handleId);
1694
-
1714
+
1695
1715
  let config = handle.webrtcStuff;
1696
-
1716
+
1697
1717
  if (stream) {
1698
1718
  if (!config.stream) {
1699
1719
  config.stream = stream;
1700
1720
  stream.getTracks().forEach(function (track) {
1701
1721
  config.pc.addTrack(track, stream);
1702
1722
  });
1703
-
1723
+
1704
1724
  } else {
1705
-
1725
+
1706
1726
  /* UPDATE Audio */
1707
-
1727
+
1708
1728
  let replaceAudio = stream.getAudioTracks().length;
1709
-
1729
+
1710
1730
  if (replaceAudio || !keepAudio) {
1711
1731
  //this will stop existing tracks
1712
1732
  let oldAudioStream = config.stream.getAudioTracks()[0];
@@ -1719,7 +1739,7 @@ class RoomSession {
1719
1739
  }
1720
1740
  }
1721
1741
  }
1722
-
1742
+
1723
1743
  if (config.pc.getSenders() && config.pc.getSenders().length) {
1724
1744
  if (replaceAudio && this.isUnifiedPlan) {
1725
1745
  //using replace
@@ -1732,7 +1752,7 @@ class RoomSession {
1732
1752
  }
1733
1753
  }
1734
1754
  }
1735
-
1755
+
1736
1756
  if (replaceAudio) {
1737
1757
  config.stream.addTrack(stream.getAudioTracks()[0]);
1738
1758
  var audioTransceiver = null;
@@ -1749,19 +1769,19 @@ class RoomSession {
1749
1769
  }
1750
1770
  }
1751
1771
  }
1752
-
1772
+
1753
1773
  if (audioTransceiver && audioTransceiver.sender) {
1754
1774
  audioTransceiver.sender.replaceTrack(stream.getAudioTracks()[0]);
1755
1775
  } else {
1756
1776
  config.pc.addTrack(stream.getAudioTracks()[0], stream);
1757
1777
  }
1758
-
1778
+
1759
1779
  }
1760
-
1780
+
1761
1781
  /* UPDATE Video */
1762
-
1782
+
1763
1783
  let replaceVideo = stream.getVideoTracks().length;
1764
-
1784
+
1765
1785
  if (replaceVideo || !keepVideo) {
1766
1786
  let oldVideoStream = config.stream.getVideoTracks()[0];
1767
1787
  if (oldVideoStream) {
@@ -1773,7 +1793,7 @@ class RoomSession {
1773
1793
  }
1774
1794
  }
1775
1795
  }
1776
-
1796
+
1777
1797
  if (config.pc.getSenders() && config.pc.getSenders().length) {
1778
1798
  if (replaceVideo && this.isUnifiedPlan) {
1779
1799
  //using replace
@@ -1786,7 +1806,7 @@ class RoomSession {
1786
1806
  }
1787
1807
  }
1788
1808
  }
1789
-
1809
+
1790
1810
  if (replaceVideo) {
1791
1811
  config.stream.addTrack(stream.getVideoTracks()[0]);
1792
1812
  var videoTransceiver = null;
@@ -1812,17 +1832,17 @@ class RoomSession {
1812
1832
  }
1813
1833
  }
1814
1834
  }
1815
-
1835
+
1816
1836
  let hasAudio = !!(stream && stream.getAudioTracks().length > 0);
1817
1837
  let hasVideo = !!(stream && stream.getVideoTracks().length > 0);
1818
1838
  let isAudioMuted = !stream || stream.getAudioTracks().length === 0 || !stream.getAudioTracks()[0].enabled;
1819
1839
  let isVideoMuted = !stream || stream.getVideoTracks().length === 0 || !stream.getVideoTracks()[0].enabled;
1820
-
1840
+
1821
1841
  this.isAudioEnabed = hasAudio;
1822
1842
  this.isVideoEnabled = hasVideo;
1823
1843
  this.isAudioMuted = isAudioMuted;
1824
1844
  this.isVideoMuted = isVideoMuted;
1825
-
1845
+
1826
1846
  return this._createAO('offer', this.handleId, false, [hasAudio, false, hasVideo, false])
1827
1847
  .then((jsep) => {
1828
1848
  if (!jsep) {
@@ -1920,7 +1940,7 @@ class RoomSession {
1920
1940
  return Promise.reject(e);
1921
1941
  })
1922
1942
  }
1923
-
1943
+
1924
1944
  unpublishLocal(dontWait = false) {
1925
1945
  return this._isPublished
1926
1946
  ? this.sendMessage(this.handleId, {body: {"request": "unpublish"}}, dontWait)
@@ -1931,7 +1951,7 @@ class RoomSession {
1931
1951
  })
1932
1952
  : Promise.resolve()
1933
1953
  }
1934
-
1954
+
1935
1955
  toggleAudio(value = null, mid) {
1936
1956
  let handle = this._getHandle(this.handleId);
1937
1957
  if (!handle) {
@@ -1953,14 +1973,14 @@ class RoomSession {
1953
1973
  }
1954
1974
  this.emit('localMuted', {type: 'audio', value: this.isAudioMuted, mid});
1955
1975
  }
1956
-
1976
+
1957
1977
  toggleVideo(value = null, mid) {
1958
1978
  let handle = this._getHandle(this.handleId);
1959
1979
  if (!handle) {
1960
1980
  return Promise.reject({type: 'error', id: 21, message: 'no local id, connect first', data: null})
1961
1981
  }
1962
1982
  let config = handle.webrtcStuff;
1963
-
1983
+
1964
1984
  if (this.isUnifiedPlan) {
1965
1985
  let transceiver = config.pc.getTransceivers()
1966
1986
  .find(t => t.sender && t.sender.track && t.receiver.track.kind === "video" && t.stopped === false && (mid ? t.mid === mid : true));
@@ -1977,25 +1997,25 @@ class RoomSession {
1977
1997
  }
1978
1998
  this.emit('localMuted', {type: 'video', value: this.isVideoMuted, mid});
1979
1999
  }
1980
-
2000
+
1981
2001
  setInstructorId(instructorId = null) {
1982
2002
  this._instuctorId = instructorId;
1983
2003
  this.emit('instructorId', this._instuctorId);
1984
2004
  return this._instuctorId;
1985
2005
  }
1986
-
2006
+
1987
2007
  setObserverIds(observerIds = []) {
1988
2008
  this._observerIds = observerIds;
1989
2009
  this.emit('observerIds', this._observerIds);
1990
2010
  return this._observerIds;
1991
2011
  }
1992
-
2012
+
1993
2013
  setTalkbackIds(talkbackIds = []) {
1994
2014
  this._talkbackIds = talkbackIds;
1995
2015
  this.emit('talkbackIds', this._talkbackIds);
1996
2016
  return this._talkbackIds;
1997
2017
  }
1998
-
2018
+
1999
2019
  }
2000
2020
 
2001
2021
  export default Room;