@reactoo/watchtogether-sdk-js 2.5.32 → 2.5.38
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 +20 -20
- package/dist/watchtogether-sdk.min.js +2 -2
- package/example/bulk_join_room/bulk_join_room_2.css +57 -0
- package/example/bulk_join_room/bulk_join_room_2.html +528 -0
- package/example/bulk_join_room/sound_2.mp3 +0 -0
- package/example/index.html +7 -4
- package/package.json +1 -1
- package/src/models/room-session.js +32 -14
- package/src/models/room.js +13 -11
- package/src/modules/sync-modules/sync-dash-vod.js +1 -1
- package/src/modules/sync-modules/sync-dash.js +1 -1
- package/src/modules/sync-modules/sync-dazn-dash.js +1 -1
- package/src/modules/sync-modules/sync-doris.js +1 -1
- package/src/modules/sync-modules/sync-hls-vod.js +1 -1
- package/src/modules/sync-modules/sync-hls.js +1 -1
- package/src/modules/sync-modules/sync-native-hls-vod.js +1 -1
- package/src/modules/sync-modules/sync-native-hls.js +1 -1
- package/src/modules/sync-modules/sync-shaka-dash-vod.js +1 -1
- package/src/modules/sync-modules/sync-shaka-dash.js +1 -1
- package/src/modules/sync-modules/sync-universal.js +1 -1
- package/src/modules/wt-iot.js +14 -7
- package/src/modules/wt-room.js +238 -127
- package/src/modules/wt-utils.js +23 -1
package/src/modules/wt-room.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import adapter from 'webrtc-adapter';
|
|
4
4
|
import emitter from './wt-emitter';
|
|
5
|
-
import {generateUUID} from "./wt-utils";
|
|
5
|
+
import {decodeJanusDisplay, generateUUID} from "./wt-utils";
|
|
6
6
|
|
|
7
7
|
class Room {
|
|
8
8
|
|
|
@@ -96,24 +96,39 @@ class RoomSession {
|
|
|
96
96
|
|
|
97
97
|
static subscriptionRules = {
|
|
98
98
|
participant: {
|
|
99
|
-
|
|
100
|
-
|
|
99
|
+
"watchparty": ['participant', 'talkback'],
|
|
100
|
+
"commentary": ['participant', 'talkback'],
|
|
101
|
+
"videowall": ['instructor', 'observer', 'talkback'],
|
|
102
|
+
"videowall-queue": ['instructor', 'observer', 'talkback'],
|
|
103
|
+
"videowall-queue-video": ['instructor', 'observer', 'talkback']
|
|
101
104
|
},
|
|
102
105
|
monitor: {
|
|
103
|
-
|
|
104
|
-
|
|
106
|
+
"watchparty": ['participant'],
|
|
107
|
+
"commentary": ['participant'],
|
|
108
|
+
"videowall": ['instructor', 'participant'],
|
|
109
|
+
"videowall-queue": ['instructor', 'participant'],
|
|
110
|
+
"videowall-queue-video": ['instructor', 'participant'],
|
|
105
111
|
},
|
|
106
112
|
talkback: {
|
|
107
|
-
|
|
108
|
-
|
|
113
|
+
"watchparty": ['participant'],
|
|
114
|
+
"commentary": ['participant'],
|
|
115
|
+
"videowall": ['instructor', 'participant'],
|
|
116
|
+
"videowall-queue": ['instructor', 'participant'],
|
|
117
|
+
"videowall-queue-video": ['instructor', 'participant'],
|
|
109
118
|
},
|
|
110
119
|
observer: {
|
|
111
|
-
|
|
112
|
-
|
|
120
|
+
"watchparty": ['participant'],
|
|
121
|
+
"commentary": ['participant'],
|
|
122
|
+
"videowall": ['participant'],
|
|
123
|
+
"videowall-queue": ['participant'],
|
|
124
|
+
"videowall-queue-video": ['participant'],
|
|
113
125
|
},
|
|
114
126
|
instructor: {
|
|
115
|
-
|
|
116
|
-
|
|
127
|
+
"watchparty": [],
|
|
128
|
+
"commentary": [],
|
|
129
|
+
"videowall": [],
|
|
130
|
+
"videowall-queue": [],
|
|
131
|
+
"videowall-queue-video": [],
|
|
117
132
|
},
|
|
118
133
|
};
|
|
119
134
|
|
|
@@ -130,8 +145,6 @@ class RoomSession {
|
|
|
130
145
|
this.userId = null;
|
|
131
146
|
this.sessiontype = type;
|
|
132
147
|
this.initialBitrate = 0;
|
|
133
|
-
//TODO: remove this
|
|
134
|
-
this.isMonitor = false; // currently used just for classroom context so monitor user only subscribes to participants and not trainer (for other monitor this flag is not necessary)
|
|
135
148
|
this.recordingFilename = null;
|
|
136
149
|
this.pluginName = RoomSession.sessionTypes[type];
|
|
137
150
|
this.options = options;
|
|
@@ -143,10 +156,12 @@ class RoomSession {
|
|
|
143
156
|
this.ws = null;
|
|
144
157
|
this.isRestarting = false;
|
|
145
158
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
this.
|
|
149
|
-
this.
|
|
159
|
+
this.isConnecting = false;
|
|
160
|
+
this.isDisconnecting = false;
|
|
161
|
+
this.isConnected = false;
|
|
162
|
+
this.isPublished = false;
|
|
163
|
+
this.isReclaiming = false;
|
|
164
|
+
this.isStreaming = false;
|
|
150
165
|
|
|
151
166
|
this._ipv6Support = false;
|
|
152
167
|
this._retries = 0;
|
|
@@ -156,12 +171,10 @@ class RoomSession {
|
|
|
156
171
|
this._observerIds = [];
|
|
157
172
|
this._talkbackIds = [];
|
|
158
173
|
this._instuctorId = null;
|
|
159
|
-
this.
|
|
160
|
-
this._isStreaming = false;
|
|
161
|
-
this._isPublished = false;
|
|
174
|
+
this._roomType = 'watchparty';
|
|
162
175
|
this._isDataChannelOpen = false;
|
|
163
|
-
this.
|
|
164
|
-
|
|
176
|
+
this._abortController = null;
|
|
177
|
+
|
|
165
178
|
this.isAudioMuted = false;
|
|
166
179
|
this.isVideoMuted = false;
|
|
167
180
|
this.isVideoEnabled = false;
|
|
@@ -210,29 +223,29 @@ class RoomSession {
|
|
|
210
223
|
}
|
|
211
224
|
|
|
212
225
|
_participantShouldSubscribe(userId) {
|
|
226
|
+
const myUserId = decodeJanusDisplay(this.userId)?.userId;
|
|
227
|
+
const remoteUserId = decodeJanusDisplay(userId)?.userId;
|
|
228
|
+
|
|
213
229
|
let allowedObservers = this._observerIds || [];
|
|
214
230
|
let allowedTalkback = this._talkbackIds || [];
|
|
215
231
|
let allowedInstructor = this._instuctorId || null;
|
|
216
232
|
let localUserRole = 'participant';
|
|
217
|
-
if(
|
|
218
|
-
localUserRole = 'monitor';
|
|
219
|
-
} else if(allowedObservers.indexOf(this.userId) > -1) {
|
|
233
|
+
if(allowedObservers.indexOf(myUserId) > -1) {
|
|
220
234
|
localUserRole = 'observer';
|
|
221
|
-
} else if(allowedTalkback.indexOf(
|
|
235
|
+
} else if(allowedTalkback.indexOf(myUserId) > -1) {
|
|
222
236
|
localUserRole = 'talkback';
|
|
223
|
-
} else if(
|
|
237
|
+
} else if(myUserId === allowedInstructor) {
|
|
224
238
|
localUserRole = 'instructor';
|
|
225
239
|
}
|
|
226
240
|
let remoteUserRole = 'participant';
|
|
227
|
-
if(allowedObservers.indexOf(
|
|
241
|
+
if(allowedObservers.indexOf(remoteUserId) > -1) {
|
|
228
242
|
remoteUserRole = 'observer';
|
|
229
|
-
} else if(allowedTalkback.indexOf(
|
|
243
|
+
} else if(allowedTalkback.indexOf(remoteUserId) > -1) {
|
|
230
244
|
remoteUserRole = 'talkback';
|
|
231
|
-
} else if(
|
|
245
|
+
} else if(remoteUserId === allowedInstructor) {
|
|
232
246
|
remoteUserRole = 'instructor';
|
|
233
247
|
}
|
|
234
|
-
|
|
235
|
-
return this.subscriptionRules[localUserRole][mode].indexOf(remoteUserRole) > -1;
|
|
248
|
+
return this.subscriptionRules[localUserRole][(this._roomType || 'watchparty')].indexOf(remoteUserRole) > -1;
|
|
236
249
|
}
|
|
237
250
|
|
|
238
251
|
_getAddParticipantEventName(handleId) {
|
|
@@ -247,17 +260,19 @@ class RoomSession {
|
|
|
247
260
|
});
|
|
248
261
|
}
|
|
249
262
|
|
|
263
|
+
const decodedUserId = decodeJanusDisplay(handle.userId)?.userId;
|
|
264
|
+
|
|
250
265
|
let allowedTalkback = this._talkbackIds || [];
|
|
251
266
|
let allowedObservers = this._observerIds || [];
|
|
252
267
|
let allowedInstructor = this._instuctorId || null;
|
|
253
268
|
let eventName = 'addRemoteParticipant';
|
|
254
|
-
if(
|
|
269
|
+
if(decodedUserId === allowedInstructor) {
|
|
255
270
|
eventName = 'addRemoteInstructor';
|
|
256
271
|
}
|
|
257
|
-
if (allowedTalkback.indexOf(
|
|
272
|
+
if (allowedTalkback.indexOf(decodedUserId) > -1) {
|
|
258
273
|
eventName = 'addRemoteTalkback';
|
|
259
274
|
}
|
|
260
|
-
if (allowedObservers.indexOf(
|
|
275
|
+
if (allowedObservers.indexOf(decodedUserId) > -1) {
|
|
261
276
|
eventName = 'addRemoteObserver';
|
|
262
277
|
}
|
|
263
278
|
return eventName
|
|
@@ -275,17 +290,19 @@ class RoomSession {
|
|
|
275
290
|
});
|
|
276
291
|
}
|
|
277
292
|
|
|
293
|
+
const decodedUserId = decodeJanusDisplay(handle.userId)?.userId;
|
|
294
|
+
|
|
278
295
|
let allowedTalkback = this._talkbackIds || [];
|
|
279
296
|
let allowedObservers = this._observerIds || [];
|
|
280
297
|
let allowedInstructor = this._instuctorId || null;
|
|
281
298
|
let eventName = 'removeRemoteParticipant';
|
|
282
|
-
if(
|
|
299
|
+
if(decodedUserId === allowedInstructor) {
|
|
283
300
|
eventName = 'removeRemoteInstructor';
|
|
284
301
|
}
|
|
285
|
-
if (allowedTalkback.indexOf(
|
|
302
|
+
if (allowedTalkback.indexOf(decodedUserId) > -1) {
|
|
286
303
|
eventName = 'removeRemoteTalkback';
|
|
287
304
|
}
|
|
288
|
-
if (allowedObservers.indexOf(
|
|
305
|
+
if (allowedObservers.indexOf(decodedUserId) > -1) {
|
|
289
306
|
eventName = 'removeRemoteObserver';
|
|
290
307
|
}
|
|
291
308
|
return eventName
|
|
@@ -321,12 +338,25 @@ class RoomSession {
|
|
|
321
338
|
transaction,
|
|
322
339
|
token: this.token, ...((this.sessionId && {'session_id': this.sessionId}) || {})
|
|
323
340
|
};
|
|
341
|
+
|
|
342
|
+
this._log(requestData);
|
|
343
|
+
|
|
324
344
|
return new Promise((resolve, reject) => {
|
|
345
|
+
let messageTimeoutId = null;
|
|
346
|
+
|
|
347
|
+
let abortResponse = () => {
|
|
348
|
+
this._abortController.signal.removeEventListener('abort', abortResponse);
|
|
349
|
+
clearTimeout(messageTimeoutId);
|
|
350
|
+
this.ws.removeEventListener('message', parseResponse);
|
|
351
|
+
reject({type: 'warning', id: 17, message: 'connection cancelled'})
|
|
352
|
+
};
|
|
353
|
+
|
|
325
354
|
let parseResponse = (event) => {
|
|
326
355
|
let json = JSON.parse(event.data);
|
|
327
356
|
let r_transaction = json['transaction'];
|
|
328
357
|
if (r_transaction === transaction && (!dontResolveOnAck || json['janus'] !== 'ack')) {
|
|
329
|
-
clearTimeout(
|
|
358
|
+
clearTimeout(messageTimeoutId);
|
|
359
|
+
this._abortController.signal.removeEventListener('abort', abortResponse);
|
|
330
360
|
this.ws.removeEventListener('message', parseResponse);
|
|
331
361
|
if (json['janus'] === 'error') {
|
|
332
362
|
if (json?.error?.code == 403) {
|
|
@@ -347,11 +377,16 @@ class RoomSession {
|
|
|
347
377
|
|
|
348
378
|
} else {
|
|
349
379
|
if (this.ws && this.ws.readyState === 1) {
|
|
380
|
+
|
|
350
381
|
this.ws.addEventListener('message', parseResponse);
|
|
351
|
-
|
|
382
|
+
|
|
383
|
+
messageTimeoutId = setTimeout(() => {
|
|
352
384
|
this.ws.removeEventListener('message', parseResponse);
|
|
385
|
+
this._abortController.signal.removeEventListener('abort', abortResponse);
|
|
353
386
|
reject({type: 'error', id: 3, message: 'send timeout', data: requestData});
|
|
354
387
|
}, 10000);
|
|
388
|
+
|
|
389
|
+
this._abortController.signal.addEventListener('abort', abortResponse);
|
|
355
390
|
this.ws.send(JSON.stringify(requestData));
|
|
356
391
|
} else {
|
|
357
392
|
reject({type: 'warning', id: 29, message: 'No connection to WebSockets', data: requestData});
|
|
@@ -361,7 +396,8 @@ class RoomSession {
|
|
|
361
396
|
}
|
|
362
397
|
|
|
363
398
|
_connectionClosed() {
|
|
364
|
-
|
|
399
|
+
|
|
400
|
+
if (!this.isConnected || this.isConnecting || this.isDisconnecting) {
|
|
365
401
|
return;
|
|
366
402
|
}
|
|
367
403
|
|
|
@@ -484,7 +520,7 @@ class RoomSession {
|
|
|
484
520
|
if (event === "joined") {
|
|
485
521
|
this.id = msg["id"];
|
|
486
522
|
this.privateId = msg["private_id"];
|
|
487
|
-
this.
|
|
523
|
+
this.isConnected = true;
|
|
488
524
|
this.emit('joined', true);
|
|
489
525
|
this._log('We have successfully joined Room');
|
|
490
526
|
for (let f in list) {
|
|
@@ -593,7 +629,7 @@ class RoomSession {
|
|
|
593
629
|
}
|
|
594
630
|
if (result["status"] === 'started') {
|
|
595
631
|
this.emit('streaming', true);
|
|
596
|
-
this.
|
|
632
|
+
this.isStreaming = true;
|
|
597
633
|
}
|
|
598
634
|
}
|
|
599
635
|
|
|
@@ -640,7 +676,7 @@ class RoomSession {
|
|
|
640
676
|
this.emit(this._getAddParticipantEventName(handle.handleId), {
|
|
641
677
|
tid: generateUUID(),
|
|
642
678
|
id: handle.handleId,
|
|
643
|
-
userId: handle.userId,
|
|
679
|
+
userId: decodeJanusDisplay(handle.userId)?.userId,
|
|
644
680
|
stream: null,
|
|
645
681
|
track: null,
|
|
646
682
|
adding: false,
|
|
@@ -775,11 +811,11 @@ class RoomSession {
|
|
|
775
811
|
|
|
776
812
|
if (handleId === this.handleId) {
|
|
777
813
|
this._isDataChannelOpen = false;
|
|
778
|
-
this.
|
|
814
|
+
this.isPublished = false;
|
|
779
815
|
this.emit('published', {status: false, hasStream: false});
|
|
780
|
-
this.emit('removeLocalParticipant', {id: handleId, userId: handle.userId});
|
|
816
|
+
this.emit('removeLocalParticipant', {id: handleId, userId: decodeJanusDisplay(handle.userId)?.userId});
|
|
781
817
|
} else {
|
|
782
|
-
this.emit(this._getRemoveParticipantEventName(handleId), {id: handleId, userId: handle.userId});
|
|
818
|
+
this.emit(this._getRemoveParticipantEventName(handleId), {id: handleId, userId: decodeJanusDisplay(handle.userId)?.userId});
|
|
783
819
|
}
|
|
784
820
|
|
|
785
821
|
if (removeHandle) {
|
|
@@ -836,10 +872,10 @@ class RoomSession {
|
|
|
836
872
|
}
|
|
837
873
|
|
|
838
874
|
_leaveRoom(dontWait = false) {
|
|
839
|
-
return this.
|
|
875
|
+
return this.isConnected
|
|
840
876
|
? this.sendMessage(this.handleId, {body: {"request": "leave"}}, dontWait)
|
|
841
877
|
.finally(() => {
|
|
842
|
-
this.
|
|
878
|
+
this.isConnected = false;
|
|
843
879
|
this.emit('joined', false);
|
|
844
880
|
})
|
|
845
881
|
: Promise.resolve();
|
|
@@ -849,8 +885,8 @@ class RoomSession {
|
|
|
849
885
|
|
|
850
886
|
_reconnect() {
|
|
851
887
|
|
|
852
|
-
if (this.
|
|
853
|
-
return
|
|
888
|
+
if (this.isReclaiming) {
|
|
889
|
+
return Promise.resolve();
|
|
854
890
|
}
|
|
855
891
|
|
|
856
892
|
if (this.ws) {
|
|
@@ -860,25 +896,39 @@ class RoomSession {
|
|
|
860
896
|
}
|
|
861
897
|
}
|
|
862
898
|
this._stopKeepAlive();
|
|
863
|
-
this.
|
|
864
|
-
|
|
899
|
+
this.isReclaiming = true;
|
|
900
|
+
this.emit('joining', true);
|
|
901
|
+
return new Promise((resolve, reject) => {
|
|
902
|
+
|
|
903
|
+
let abortReconnect = () => {
|
|
904
|
+
this._abortController.signal.removeEventListener('abort', abortReconnect);
|
|
905
|
+
this.ws.removeEventListener('close', this.__connectionClosedBoundFn);
|
|
906
|
+
this.ws.removeEventListener('message', this.__handleWsEventsBoundFn);
|
|
907
|
+
this.ws.onopen = null;
|
|
908
|
+
this.ws.onerror = null;
|
|
909
|
+
this.isReclaiming = false;
|
|
910
|
+
this.emit('joining', false);
|
|
911
|
+
reject({type: 'warning', id: 17, message: 'Connection cancelled', data: e});
|
|
912
|
+
};
|
|
913
|
+
|
|
865
914
|
this.ws = new WebSocket(this.server, 'janus-protocol');
|
|
866
915
|
this.__connectionClosedBoundFn = this._connectionClosed.bind(this);
|
|
867
916
|
this.__handleWsEventsBoundFn = this._handleWsEvents.bind(this);
|
|
868
917
|
this.ws.addEventListener('close', this.__connectionClosedBoundFn);
|
|
869
918
|
this.ws.addEventListener('message', this.__handleWsEventsBoundFn);
|
|
870
919
|
this.ws.onopen = () => {
|
|
920
|
+
this._abortController.signal.removeEventListener('abort', abortReconnect);
|
|
871
921
|
this._send({"janus": "claim"})
|
|
872
922
|
.then(json => {
|
|
873
923
|
this.sessionId = json["session_id"] ? json["session_id"] : json.data["id"];
|
|
874
924
|
this._startKeepAlive();
|
|
875
|
-
this.
|
|
925
|
+
this.isReclaiming = false;
|
|
876
926
|
this.emit('joining', false);
|
|
877
927
|
this._retries = 0;
|
|
878
928
|
resolve(json);
|
|
879
929
|
})
|
|
880
930
|
.catch(error => {
|
|
881
|
-
this.
|
|
931
|
+
this.isReclaiming = false;
|
|
882
932
|
this.emit('joining', false);
|
|
883
933
|
reject({type: 'error', id: 11, message: 'reconnection error', data: error})
|
|
884
934
|
});
|
|
@@ -886,26 +936,27 @@ class RoomSession {
|
|
|
886
936
|
|
|
887
937
|
// this is called before 'close' event callback so it doesn't break reconnect loop
|
|
888
938
|
this.ws.onerror = (e) => {
|
|
889
|
-
this.
|
|
939
|
+
this._abortController.signal.removeEventListener('abort', abortReconnect);
|
|
940
|
+
this.isReclaiming = false;
|
|
890
941
|
this.emit('joining', false);
|
|
891
942
|
reject({type: 'warning', id: 12, message: 'ws reconnection error', data: e});
|
|
892
943
|
}
|
|
944
|
+
|
|
945
|
+
this._abortController.signal.addEventListener('abort', abortReconnect);
|
|
893
946
|
});
|
|
894
|
-
return this.connectingPromise;
|
|
895
947
|
}
|
|
896
948
|
|
|
897
|
-
connect(roomId, pin, server, iceServers, token, display, userId, webrtcVersion = 0, initialBitrate = 0,
|
|
949
|
+
connect(roomId, pin, server, iceServers, token, display, userId, webrtcVersion = 0, initialBitrate = 0, recordingFilename) {
|
|
898
950
|
|
|
899
|
-
if (this.
|
|
900
|
-
return
|
|
951
|
+
if (this.isConnecting) {
|
|
952
|
+
return Promise.reject({type: 'warning', id: 16, message: 'connection already in progress'});
|
|
901
953
|
}
|
|
902
954
|
|
|
903
|
-
this.emit('joined', false);
|
|
904
955
|
if (this.ws) {
|
|
905
956
|
this._wipeListeners();
|
|
906
957
|
}
|
|
907
958
|
this._stopKeepAlive();
|
|
908
|
-
this.
|
|
959
|
+
this._abortController = new AbortController();
|
|
909
960
|
this.sessionId = null;
|
|
910
961
|
this.server = server;
|
|
911
962
|
this.iceServers = iceServers;
|
|
@@ -916,17 +967,30 @@ class RoomSession {
|
|
|
916
967
|
this.userId = userId;
|
|
917
968
|
this.webrtcVersion = webrtcVersion;
|
|
918
969
|
this.initialBitrate = initialBitrate;
|
|
919
|
-
this.isMonitor = isMonitor;
|
|
920
970
|
this.recordingFilename = recordingFilename;
|
|
921
|
-
this.
|
|
922
|
-
this.
|
|
923
|
-
|
|
971
|
+
this.isConnecting = true;
|
|
972
|
+
this.emit('joining', true);
|
|
973
|
+
return new Promise((resolve, reject) => {
|
|
974
|
+
|
|
924
975
|
this.ws = new WebSocket(this.server, 'janus-protocol');
|
|
925
976
|
this.__connectionClosedBoundFn = this._connectionClosed.bind(this);
|
|
926
977
|
this.__handleWsEventsBoundFn = this._handleWsEvents.bind(this);
|
|
978
|
+
|
|
979
|
+
let abortConnect = () => {
|
|
980
|
+
this._abortController.signal.removeEventListener('abort', abortConnect);
|
|
981
|
+
this.ws.removeEventListener('close', this.__connectionClosedBoundFn);
|
|
982
|
+
this.ws.removeEventListener('message', this.__handleWsEventsBoundFn);
|
|
983
|
+
this.ws.onopen = null;
|
|
984
|
+
this.ws.onerror = null;
|
|
985
|
+
this.isConnecting = false;
|
|
986
|
+
this.emit('joining', false);
|
|
987
|
+
reject({type: 'warning', id: 17, message: 'Connection cancelled'});
|
|
988
|
+
};
|
|
989
|
+
|
|
927
990
|
this.ws.addEventListener('close', this.__connectionClosedBoundFn);
|
|
928
991
|
this.ws.addEventListener('message', this.__handleWsEventsBoundFn);
|
|
929
992
|
this.ws.onopen = () => {
|
|
993
|
+
this._abortController.signal.removeEventListener('abort', abortConnect);
|
|
930
994
|
this._retries = 0;
|
|
931
995
|
this._send({"janus": "create"})
|
|
932
996
|
.then(json => {
|
|
@@ -941,36 +1005,41 @@ class RoomSession {
|
|
|
941
1005
|
})
|
|
942
1006
|
.then(() => this._joinRoom(roomId, pin, userId, display))
|
|
943
1007
|
.then(() => {
|
|
944
|
-
this.
|
|
1008
|
+
this.isConnecting = false;
|
|
945
1009
|
this.emit('joining', false);
|
|
946
1010
|
resolve(this);
|
|
947
1011
|
})
|
|
948
1012
|
.catch(error => {
|
|
949
|
-
this.
|
|
1013
|
+
this.isConnecting = false;
|
|
950
1014
|
this.emit('joining', false);
|
|
951
|
-
reject({type: 'error', id: 13, message: 'connection error', data: error})
|
|
1015
|
+
reject({type: error?.type === 'warning' ? 'warning' : 'error', id: 13, message: 'connection error', data: error})
|
|
952
1016
|
});
|
|
953
1017
|
};
|
|
1018
|
+
|
|
954
1019
|
this.ws.onerror = (e) => {
|
|
955
|
-
this.
|
|
1020
|
+
this._abortController.signal.removeEventListener('abort', abortConnect);
|
|
1021
|
+
this.isConnecting = false;
|
|
956
1022
|
this.emit('joining', false);
|
|
957
1023
|
reject({type: 'error', id: 14, message: 'ws connection error', data: e});
|
|
958
1024
|
}
|
|
1025
|
+
|
|
1026
|
+
this._abortController.signal.addEventListener('abort', abortConnect);
|
|
1027
|
+
|
|
959
1028
|
});
|
|
960
|
-
return this.connectingPromise;
|
|
961
1029
|
}
|
|
962
1030
|
|
|
963
1031
|
disconnect() {
|
|
964
|
-
|
|
965
|
-
|
|
1032
|
+
|
|
1033
|
+
if (this.isDisconnecting) {
|
|
1034
|
+
return Promise.resolve();
|
|
966
1035
|
}
|
|
967
1036
|
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
clearTimeout(this._messageTimeoutId);
|
|
971
|
-
clearTimeout(this._dataChannelTimeoutId);
|
|
1037
|
+
this._abortController?.abort?.();
|
|
972
1038
|
this._stopKeepAlive();
|
|
973
|
-
|
|
1039
|
+
|
|
1040
|
+
let isConnected = this.isConnected;
|
|
1041
|
+
this.isDisconnecting = true;
|
|
1042
|
+
return Promise.all(this._participants.map(p => this._removeParticipant(p.handleId)))
|
|
974
1043
|
.finally(() => {
|
|
975
1044
|
this._wipeListeners();
|
|
976
1045
|
if (this.ws && this.ws.readyState === 1) {
|
|
@@ -978,46 +1047,59 @@ class RoomSession {
|
|
|
978
1047
|
this.ws.close();
|
|
979
1048
|
}
|
|
980
1049
|
this.sessionId = null;
|
|
981
|
-
|
|
982
|
-
this.
|
|
983
|
-
this.
|
|
1050
|
+
this.isPublished = false;
|
|
1051
|
+
this.isConnected = false;
|
|
1052
|
+
this.isDisconnecting = false;
|
|
984
1053
|
this.emit('publishing', false);
|
|
985
1054
|
this.emit('published', {status: false, hasStream: false});
|
|
986
1055
|
this.emit('joining', false);
|
|
987
1056
|
this.emit('joined', false);
|
|
988
|
-
this.emit('disconnect',
|
|
1057
|
+
this.emit('disconnect', isConnected);
|
|
989
1058
|
return Promise.resolve('Disconnected');
|
|
990
1059
|
})
|
|
991
|
-
return this.disconnectingPromise;
|
|
992
1060
|
}
|
|
993
1061
|
|
|
994
1062
|
startStream(streamId, server, iceServers, token, userId) {
|
|
995
1063
|
|
|
996
|
-
if (this.
|
|
997
|
-
return
|
|
1064
|
+
if (this.isConnecting) {
|
|
1065
|
+
return Promise.reject({type: 'warning', id: 16, message: 'connection error', data: 'Connection is in progress'});
|
|
998
1066
|
}
|
|
999
1067
|
|
|
1000
|
-
this.emit('streaming', false);
|
|
1001
1068
|
if (this.ws) {
|
|
1002
1069
|
this._wipeListeners();
|
|
1003
1070
|
}
|
|
1071
|
+
|
|
1004
1072
|
this._stopKeepAlive();
|
|
1005
|
-
this.
|
|
1006
|
-
this.sessionId = null;
|
|
1073
|
+
this._abortController = new AbortController();
|
|
1007
1074
|
this.server = server;
|
|
1008
1075
|
this.iceServers = iceServers;
|
|
1009
1076
|
this.token = token;
|
|
1010
1077
|
this.streamId = streamId;
|
|
1011
1078
|
this.userId = userId;
|
|
1079
|
+
this.sessionId = null;
|
|
1080
|
+
this.isConnecting = true;
|
|
1081
|
+
this.emit('streamStarting', true);
|
|
1082
|
+
return new Promise((resolve, reject) => {
|
|
1012
1083
|
|
|
1013
|
-
this.connectingPromise = new Promise((resolve, reject) => {
|
|
1014
|
-
this.emit('streamStarting', true);
|
|
1015
1084
|
this.ws = new WebSocket(this.server, 'janus-protocol');
|
|
1016
1085
|
this.__connectionClosedBoundFn = this._connectionClosed.bind(this);
|
|
1017
1086
|
this.__handleWsEventsBoundFn = this._handleWsEvents.bind(this);
|
|
1087
|
+
|
|
1088
|
+
let abortConnect = () => {
|
|
1089
|
+
this._abortController.signal.removeEventListener('abort', abortConnect);
|
|
1090
|
+
this.ws.removeEventListener('close', this.__connectionClosedBoundFn);
|
|
1091
|
+
this.ws.removeEventListener('message', this.__handleWsEventsBoundFn);
|
|
1092
|
+
this.ws.onopen = null;
|
|
1093
|
+
this.ws.onerror = null;
|
|
1094
|
+
this.isConnecting = false;
|
|
1095
|
+
this.emit('streamStarting', false);
|
|
1096
|
+
reject({type: 'warning', id: 17, message: 'Connection cancelled'});
|
|
1097
|
+
};
|
|
1098
|
+
|
|
1018
1099
|
this.ws.addEventListener('close', this.__connectionClosedBoundFn);
|
|
1019
1100
|
this.ws.addEventListener('message', this.__handleWsEventsBoundFn);
|
|
1020
1101
|
this.ws.onopen = () => {
|
|
1102
|
+
this._abortController.signal.removeEventListener('abort', abortConnect);
|
|
1021
1103
|
this._retries = 0;
|
|
1022
1104
|
this._send({"janus": "create"})
|
|
1023
1105
|
.then(json => {
|
|
@@ -1032,38 +1114,39 @@ class RoomSession {
|
|
|
1032
1114
|
})
|
|
1033
1115
|
.then(() => this._watchStream(streamId))
|
|
1034
1116
|
.then(() => {
|
|
1035
|
-
this.
|
|
1117
|
+
this.isConnecting = false;
|
|
1036
1118
|
this.emit('streamStarting', false);
|
|
1037
1119
|
resolve(this);
|
|
1038
1120
|
})
|
|
1039
1121
|
.catch(error => {
|
|
1040
|
-
this.
|
|
1122
|
+
this.isConnecting = false;
|
|
1041
1123
|
this.emit('streamStarting', false);
|
|
1042
1124
|
reject({type: 'error', id: 13, message: 'connection error', data: error})
|
|
1043
1125
|
});
|
|
1044
1126
|
};
|
|
1045
1127
|
this.ws.onerror = (e) => {
|
|
1046
|
-
this.
|
|
1128
|
+
this._abortController.signal.removeEventListener('abort', abortConnect);
|
|
1129
|
+
this.isConnecting = false;
|
|
1047
1130
|
this.emit('streamStarting', false);
|
|
1048
1131
|
reject({type: 'error', id: 14, message: 'ws connection error', data: e});
|
|
1049
1132
|
}
|
|
1133
|
+
|
|
1134
|
+
this._abortController.signal.addEventListener('abort', abortConnect);
|
|
1050
1135
|
});
|
|
1051
|
-
return this.connectingPromise;
|
|
1052
1136
|
}
|
|
1053
1137
|
|
|
1054
1138
|
stopStream() {
|
|
1055
|
-
if (this.disconnectingPromise) {
|
|
1056
|
-
return this.disconnectingPromise;
|
|
1057
|
-
}
|
|
1058
1139
|
|
|
1059
|
-
|
|
1140
|
+
if (this.isDisconnecting) {
|
|
1141
|
+
return Promise.resolve();
|
|
1142
|
+
}
|
|
1060
1143
|
|
|
1144
|
+
this._abortController?.abort?.();
|
|
1061
1145
|
this._stopKeepAlive();
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
}, false, true)
|
|
1146
|
+
|
|
1147
|
+
let isStreaming = this.isStreaming;
|
|
1148
|
+
this.isDisconnecting = true;
|
|
1149
|
+
return this.sendMessage(this.handleId, {body: {"request": "stop"}}, false, true)
|
|
1067
1150
|
.then(() => this._removeParticipant(this.handleId))
|
|
1068
1151
|
.finally(() => {
|
|
1069
1152
|
this._wipeListeners();
|
|
@@ -1072,15 +1155,13 @@ class RoomSession {
|
|
|
1072
1155
|
this.ws.close();
|
|
1073
1156
|
}
|
|
1074
1157
|
this.sessionId = null;
|
|
1075
|
-
this.
|
|
1158
|
+
this.isDisconnecting = false;
|
|
1159
|
+
this.isStreaming = false;
|
|
1076
1160
|
this.emit('streamStarting', false);
|
|
1077
1161
|
this.emit('streaming', false);
|
|
1078
|
-
this.emit('disconnect',
|
|
1079
|
-
this.disconnectingPromise = null;
|
|
1162
|
+
this.emit('disconnect', isStreaming);
|
|
1080
1163
|
return Promise.resolve('Disconnected');
|
|
1081
1164
|
});
|
|
1082
|
-
|
|
1083
|
-
return this.disconnectingPromise;
|
|
1084
1165
|
}
|
|
1085
1166
|
|
|
1086
1167
|
destroy() {
|
|
@@ -1171,7 +1252,7 @@ class RoomSession {
|
|
|
1171
1252
|
this.emit(this._getAddParticipantEventName(handle.handleId), {
|
|
1172
1253
|
tid: generateUUID(),
|
|
1173
1254
|
id: handle.handleId,
|
|
1174
|
-
userId: handle.userId,
|
|
1255
|
+
userId: decodeJanusDisplay(handle.userId)?.userId,
|
|
1175
1256
|
stream: config.stream,
|
|
1176
1257
|
track: null,
|
|
1177
1258
|
optional: true,
|
|
@@ -1192,7 +1273,7 @@ class RoomSession {
|
|
|
1192
1273
|
this.emit(this._getAddParticipantEventName(handle.handleId), {
|
|
1193
1274
|
tid: generateUUID(),
|
|
1194
1275
|
id: handle.handleId,
|
|
1195
|
-
userId: handle.userId,
|
|
1276
|
+
userId: decodeJanusDisplay(handle.userId)?.userId,
|
|
1196
1277
|
stream: config.stream,
|
|
1197
1278
|
track: null,
|
|
1198
1279
|
optional: true,
|
|
@@ -1245,7 +1326,7 @@ class RoomSession {
|
|
|
1245
1326
|
tid: generateUUID(),
|
|
1246
1327
|
mid,
|
|
1247
1328
|
id: handle.handleId,
|
|
1248
|
-
userId: handle.userId,
|
|
1329
|
+
userId: decodeJanusDisplay(handle.userId)?.userId,
|
|
1249
1330
|
stream: config.stream,
|
|
1250
1331
|
track: event.track,
|
|
1251
1332
|
constructId: this.constructId,
|
|
@@ -1273,7 +1354,7 @@ class RoomSession {
|
|
|
1273
1354
|
tid: generateUUID(),
|
|
1274
1355
|
id: handle.handleId,
|
|
1275
1356
|
mid,
|
|
1276
|
-
userId: handle.userId,
|
|
1357
|
+
userId: decodeJanusDisplay(handle.userId)?.userId,
|
|
1277
1358
|
stream: config.stream,
|
|
1278
1359
|
track: ev.target,
|
|
1279
1360
|
constructId: this.constructId,
|
|
@@ -1299,7 +1380,7 @@ class RoomSession {
|
|
|
1299
1380
|
this.emit('remoteTrackMuted', {
|
|
1300
1381
|
id: handle.handleId,
|
|
1301
1382
|
mid,
|
|
1302
|
-
userId: handle.userId,
|
|
1383
|
+
userId: decodeJanusDisplay(handle.userId)?.userId,
|
|
1303
1384
|
stream: config.stream,
|
|
1304
1385
|
kind: ev.target.kind,
|
|
1305
1386
|
track: ev.target,
|
|
@@ -1320,7 +1401,7 @@ class RoomSession {
|
|
|
1320
1401
|
this.emit('remoteTrackMuted', {
|
|
1321
1402
|
id: handle.handleId,
|
|
1322
1403
|
mid,
|
|
1323
|
-
userId: handle.userId,
|
|
1404
|
+
userId: decodeJanusDisplay(handle.userId)?.userId,
|
|
1324
1405
|
stream: config.stream,
|
|
1325
1406
|
kind: ev.target.kind,
|
|
1326
1407
|
track: ev.target,
|
|
@@ -1710,6 +1791,14 @@ class RoomSession {
|
|
|
1710
1791
|
|
|
1711
1792
|
publishLocal(stream, {keepAudio = false, keepVideo = false} = {}) {
|
|
1712
1793
|
|
|
1794
|
+
if(this.isDisconnecting || !this.isConnected) {
|
|
1795
|
+
return Promise.reject({
|
|
1796
|
+
type: 'warning',
|
|
1797
|
+
id: 18,
|
|
1798
|
+
message: 'Either not connected or disconnecting',
|
|
1799
|
+
})
|
|
1800
|
+
}
|
|
1801
|
+
|
|
1713
1802
|
this.emit('publishing', true);
|
|
1714
1803
|
|
|
1715
1804
|
let handle = this._getHandle(this.handleId);
|
|
@@ -1874,23 +1963,40 @@ class RoomSession {
|
|
|
1874
1963
|
return Promise.resolve(r)
|
|
1875
1964
|
} else {
|
|
1876
1965
|
return new Promise((resolve, reject) => {
|
|
1877
|
-
|
|
1966
|
+
|
|
1967
|
+
let dataChannelTimeoutId = null;
|
|
1968
|
+
|
|
1969
|
+
let _resolve = (val) => {
|
|
1878
1970
|
if (val) {
|
|
1879
|
-
clearTimeout(
|
|
1880
|
-
this.
|
|
1971
|
+
clearTimeout(dataChannelTimeoutId);
|
|
1972
|
+
this._abortController.signal.removeEventListener('abort', _rejectAbort);
|
|
1973
|
+
this.off('dataChannel', _resolve, this);
|
|
1881
1974
|
resolve(this);
|
|
1882
1975
|
}
|
|
1883
1976
|
};
|
|
1884
|
-
|
|
1885
|
-
|
|
1977
|
+
|
|
1978
|
+
let _rejectTimeout = () => {
|
|
1979
|
+
this.off('dataChannel', _resolve, this);
|
|
1980
|
+
this._abortController.signal.removeEventListener('abort', _rejectAbort);
|
|
1886
1981
|
reject({type: 'error', id: 27, message: 'Data channel did not open', data: null});
|
|
1887
|
-
}
|
|
1888
|
-
|
|
1982
|
+
}
|
|
1983
|
+
|
|
1984
|
+
let _rejectAbort = () => {
|
|
1985
|
+
this._abortController.signal.removeEventListener('abort', _rejectAbort);
|
|
1986
|
+
clearTimeout(dataChannelTimeoutId);
|
|
1987
|
+
this.off('dataChannel', _resolve, this);
|
|
1988
|
+
reject({type: 'warning', id: 17, message: 'Connection cancelled'})
|
|
1989
|
+
}
|
|
1990
|
+
|
|
1991
|
+
dataChannelTimeoutId = setTimeout(_rejectTimeout, 5000);
|
|
1992
|
+
this._abortController.signal.addEventListener('abort', _rejectAbort);
|
|
1993
|
+
|
|
1994
|
+
this.on('dataChannel', _resolve, this);
|
|
1889
1995
|
});
|
|
1890
1996
|
}
|
|
1891
1997
|
})
|
|
1892
1998
|
.then(r => {
|
|
1893
|
-
this.
|
|
1999
|
+
this.isPublished = true;
|
|
1894
2000
|
if(config.stream) {
|
|
1895
2001
|
let tracks = config.stream.getTracks();
|
|
1896
2002
|
tracks.forEach(track => {
|
|
@@ -1899,7 +2005,7 @@ class RoomSession {
|
|
|
1899
2005
|
this.emit('addLocalParticipant', {
|
|
1900
2006
|
tid: generateUUID(),
|
|
1901
2007
|
id: handle.handleId,
|
|
1902
|
-
userId: handle.userId,
|
|
2008
|
+
userId: decodeJanusDisplay(handle.userId)?.userId,
|
|
1903
2009
|
track,
|
|
1904
2010
|
stream: config.stream,
|
|
1905
2011
|
adding: true,
|
|
@@ -1912,7 +2018,7 @@ class RoomSession {
|
|
|
1912
2018
|
this.emit('addLocalParticipant', {
|
|
1913
2019
|
tid:generateUUID(),
|
|
1914
2020
|
id: handle.handleId,
|
|
1915
|
-
userId: handle.userId,
|
|
2021
|
+
userId: decodeJanusDisplay(handle.userId)?.userId,
|
|
1916
2022
|
track: ev.target,
|
|
1917
2023
|
stream: config.stream,
|
|
1918
2024
|
adding: false,
|
|
@@ -1929,7 +2035,7 @@ class RoomSession {
|
|
|
1929
2035
|
this.emit('addLocalParticipant', {
|
|
1930
2036
|
tid: generateUUID(),
|
|
1931
2037
|
id: handle.handleId,
|
|
1932
|
-
userId: handle.userId,
|
|
2038
|
+
userId: decodeJanusDisplay(handle.userId)?.userId,
|
|
1933
2039
|
stream: null,
|
|
1934
2040
|
adding: false,
|
|
1935
2041
|
constructId: this.constructId,
|
|
@@ -1954,10 +2060,10 @@ class RoomSession {
|
|
|
1954
2060
|
}
|
|
1955
2061
|
|
|
1956
2062
|
unpublishLocal(dontWait = false) {
|
|
1957
|
-
return this.
|
|
2063
|
+
return this.isPublished
|
|
1958
2064
|
? this.sendMessage(this.handleId, {body: {"request": "unpublish"}}, dontWait)
|
|
1959
2065
|
.finally(r => {
|
|
1960
|
-
this.
|
|
2066
|
+
this.isPublished = false;
|
|
1961
2067
|
this.emit('published', {status: false, hasStream: false});
|
|
1962
2068
|
return r
|
|
1963
2069
|
})
|
|
@@ -2028,6 +2134,11 @@ class RoomSession {
|
|
|
2028
2134
|
return this._talkbackIds;
|
|
2029
2135
|
}
|
|
2030
2136
|
|
|
2137
|
+
setRoomType(type = 'watchparty') {
|
|
2138
|
+
this._roomType = type;
|
|
2139
|
+
return this._roomType;
|
|
2140
|
+
}
|
|
2141
|
+
|
|
2031
2142
|
}
|
|
2032
2143
|
|
|
2033
2144
|
export default Room;
|