@reactoo/watchtogether-sdk-js 2.5.31 → 2.5.37
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 +241 -128
- 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].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,44 +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;
|
|
1053
|
+
this.emit('publishing', false);
|
|
984
1054
|
this.emit('published', {status: false, hasStream: false});
|
|
1055
|
+
this.emit('joining', false);
|
|
985
1056
|
this.emit('joined', false);
|
|
986
|
-
this.emit('disconnect',
|
|
1057
|
+
this.emit('disconnect', isConnected);
|
|
987
1058
|
return Promise.resolve('Disconnected');
|
|
988
1059
|
})
|
|
989
|
-
return this.disconnectingPromise;
|
|
990
1060
|
}
|
|
991
1061
|
|
|
992
1062
|
startStream(streamId, server, iceServers, token, userId) {
|
|
993
1063
|
|
|
994
|
-
if (this.
|
|
995
|
-
return
|
|
1064
|
+
if (this.isConnecting) {
|
|
1065
|
+
return Promise.reject({type: 'warning', id: 16, message: 'connection error', data: 'Connection is in progress'});
|
|
996
1066
|
}
|
|
997
1067
|
|
|
998
|
-
this.emit('streaming', false);
|
|
999
1068
|
if (this.ws) {
|
|
1000
1069
|
this._wipeListeners();
|
|
1001
1070
|
}
|
|
1071
|
+
|
|
1002
1072
|
this._stopKeepAlive();
|
|
1003
|
-
this.
|
|
1004
|
-
this.sessionId = null;
|
|
1073
|
+
this._abortController = new AbortController();
|
|
1005
1074
|
this.server = server;
|
|
1006
1075
|
this.iceServers = iceServers;
|
|
1007
1076
|
this.token = token;
|
|
1008
1077
|
this.streamId = streamId;
|
|
1009
1078
|
this.userId = userId;
|
|
1079
|
+
this.sessionId = null;
|
|
1080
|
+
this.isConnecting = true;
|
|
1081
|
+
this.emit('streamStarting', true);
|
|
1082
|
+
return new Promise((resolve, reject) => {
|
|
1010
1083
|
|
|
1011
|
-
this.connectingPromise = new Promise((resolve, reject) => {
|
|
1012
|
-
this.emit('streamStarting', true);
|
|
1013
1084
|
this.ws = new WebSocket(this.server, 'janus-protocol');
|
|
1014
1085
|
this.__connectionClosedBoundFn = this._connectionClosed.bind(this);
|
|
1015
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
|
+
|
|
1016
1099
|
this.ws.addEventListener('close', this.__connectionClosedBoundFn);
|
|
1017
1100
|
this.ws.addEventListener('message', this.__handleWsEventsBoundFn);
|
|
1018
1101
|
this.ws.onopen = () => {
|
|
1102
|
+
this._abortController.signal.removeEventListener('abort', abortConnect);
|
|
1019
1103
|
this._retries = 0;
|
|
1020
1104
|
this._send({"janus": "create"})
|
|
1021
1105
|
.then(json => {
|
|
@@ -1030,38 +1114,39 @@ class RoomSession {
|
|
|
1030
1114
|
})
|
|
1031
1115
|
.then(() => this._watchStream(streamId))
|
|
1032
1116
|
.then(() => {
|
|
1033
|
-
this.
|
|
1117
|
+
this.isConnecting = false;
|
|
1034
1118
|
this.emit('streamStarting', false);
|
|
1035
1119
|
resolve(this);
|
|
1036
1120
|
})
|
|
1037
1121
|
.catch(error => {
|
|
1038
|
-
this.
|
|
1122
|
+
this.isConnecting = false;
|
|
1039
1123
|
this.emit('streamStarting', false);
|
|
1040
1124
|
reject({type: 'error', id: 13, message: 'connection error', data: error})
|
|
1041
1125
|
});
|
|
1042
1126
|
};
|
|
1043
1127
|
this.ws.onerror = (e) => {
|
|
1044
|
-
this.
|
|
1128
|
+
this._abortController.signal.removeEventListener('abort', abortConnect);
|
|
1129
|
+
this.isConnecting = false;
|
|
1045
1130
|
this.emit('streamStarting', false);
|
|
1046
1131
|
reject({type: 'error', id: 14, message: 'ws connection error', data: e});
|
|
1047
1132
|
}
|
|
1133
|
+
|
|
1134
|
+
this._abortController.signal.addEventListener('abort', abortConnect);
|
|
1048
1135
|
});
|
|
1049
|
-
return this.connectingPromise;
|
|
1050
1136
|
}
|
|
1051
1137
|
|
|
1052
1138
|
stopStream() {
|
|
1053
|
-
if (this.disconnectingPromise) {
|
|
1054
|
-
return this.disconnectingPromise;
|
|
1055
|
-
}
|
|
1056
1139
|
|
|
1057
|
-
|
|
1140
|
+
if (this.isDisconnecting) {
|
|
1141
|
+
return Promise.resolve();
|
|
1142
|
+
}
|
|
1058
1143
|
|
|
1144
|
+
this._abortController?.abort?.();
|
|
1059
1145
|
this._stopKeepAlive();
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
}, false, true)
|
|
1146
|
+
|
|
1147
|
+
let isStreaming = this.isStreaming;
|
|
1148
|
+
this.isDisconnecting = true;
|
|
1149
|
+
return this.sendMessage(this.handleId, {body: {"request": "stop"}}, false, true)
|
|
1065
1150
|
.then(() => this._removeParticipant(this.handleId))
|
|
1066
1151
|
.finally(() => {
|
|
1067
1152
|
this._wipeListeners();
|
|
@@ -1070,15 +1155,13 @@ class RoomSession {
|
|
|
1070
1155
|
this.ws.close();
|
|
1071
1156
|
}
|
|
1072
1157
|
this.sessionId = null;
|
|
1073
|
-
this.
|
|
1158
|
+
this.isDisconnecting = false;
|
|
1159
|
+
this.isStreaming = false;
|
|
1160
|
+
this.emit('streamStarting', false);
|
|
1074
1161
|
this.emit('streaming', false);
|
|
1075
|
-
|
|
1076
|
-
this.emit('disconnect', _isStreaming);
|
|
1077
|
-
this.disconnectingPromise = null;
|
|
1162
|
+
this.emit('disconnect', isStreaming);
|
|
1078
1163
|
return Promise.resolve('Disconnected');
|
|
1079
1164
|
});
|
|
1080
|
-
|
|
1081
|
-
return this.disconnectingPromise;
|
|
1082
1165
|
}
|
|
1083
1166
|
|
|
1084
1167
|
destroy() {
|
|
@@ -1169,7 +1252,7 @@ class RoomSession {
|
|
|
1169
1252
|
this.emit(this._getAddParticipantEventName(handle.handleId), {
|
|
1170
1253
|
tid: generateUUID(),
|
|
1171
1254
|
id: handle.handleId,
|
|
1172
|
-
userId: handle.userId,
|
|
1255
|
+
userId: decodeJanusDisplay(handle.userId)?.userId,
|
|
1173
1256
|
stream: config.stream,
|
|
1174
1257
|
track: null,
|
|
1175
1258
|
optional: true,
|
|
@@ -1190,7 +1273,7 @@ class RoomSession {
|
|
|
1190
1273
|
this.emit(this._getAddParticipantEventName(handle.handleId), {
|
|
1191
1274
|
tid: generateUUID(),
|
|
1192
1275
|
id: handle.handleId,
|
|
1193
|
-
userId: handle.userId,
|
|
1276
|
+
userId: decodeJanusDisplay(handle.userId)?.userId,
|
|
1194
1277
|
stream: config.stream,
|
|
1195
1278
|
track: null,
|
|
1196
1279
|
optional: true,
|
|
@@ -1243,7 +1326,7 @@ class RoomSession {
|
|
|
1243
1326
|
tid: generateUUID(),
|
|
1244
1327
|
mid,
|
|
1245
1328
|
id: handle.handleId,
|
|
1246
|
-
userId: handle.userId,
|
|
1329
|
+
userId: decodeJanusDisplay(handle.userId)?.userId,
|
|
1247
1330
|
stream: config.stream,
|
|
1248
1331
|
track: event.track,
|
|
1249
1332
|
constructId: this.constructId,
|
|
@@ -1271,7 +1354,7 @@ class RoomSession {
|
|
|
1271
1354
|
tid: generateUUID(),
|
|
1272
1355
|
id: handle.handleId,
|
|
1273
1356
|
mid,
|
|
1274
|
-
userId: handle.userId,
|
|
1357
|
+
userId: decodeJanusDisplay(handle.userId)?.userId,
|
|
1275
1358
|
stream: config.stream,
|
|
1276
1359
|
track: ev.target,
|
|
1277
1360
|
constructId: this.constructId,
|
|
@@ -1297,7 +1380,7 @@ class RoomSession {
|
|
|
1297
1380
|
this.emit('remoteTrackMuted', {
|
|
1298
1381
|
id: handle.handleId,
|
|
1299
1382
|
mid,
|
|
1300
|
-
userId: handle.userId,
|
|
1383
|
+
userId: decodeJanusDisplay(handle.userId)?.userId,
|
|
1301
1384
|
stream: config.stream,
|
|
1302
1385
|
kind: ev.target.kind,
|
|
1303
1386
|
track: ev.target,
|
|
@@ -1318,7 +1401,7 @@ class RoomSession {
|
|
|
1318
1401
|
this.emit('remoteTrackMuted', {
|
|
1319
1402
|
id: handle.handleId,
|
|
1320
1403
|
mid,
|
|
1321
|
-
userId: handle.userId,
|
|
1404
|
+
userId: decodeJanusDisplay(handle.userId)?.userId,
|
|
1322
1405
|
stream: config.stream,
|
|
1323
1406
|
kind: ev.target.kind,
|
|
1324
1407
|
track: ev.target,
|
|
@@ -1708,6 +1791,14 @@ class RoomSession {
|
|
|
1708
1791
|
|
|
1709
1792
|
publishLocal(stream, {keepAudio = false, keepVideo = false} = {}) {
|
|
1710
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
|
+
|
|
1711
1802
|
this.emit('publishing', true);
|
|
1712
1803
|
|
|
1713
1804
|
let handle = this._getHandle(this.handleId);
|
|
@@ -1872,23 +1963,40 @@ class RoomSession {
|
|
|
1872
1963
|
return Promise.resolve(r)
|
|
1873
1964
|
} else {
|
|
1874
1965
|
return new Promise((resolve, reject) => {
|
|
1875
|
-
|
|
1966
|
+
|
|
1967
|
+
let dataChannelTimeoutId = null;
|
|
1968
|
+
|
|
1969
|
+
let _resolve = (val) => {
|
|
1876
1970
|
if (val) {
|
|
1877
|
-
clearTimeout(
|
|
1878
|
-
this.
|
|
1971
|
+
clearTimeout(dataChannelTimeoutId);
|
|
1972
|
+
this._abortController.signal.removeEventListener('abort', _rejectAbort);
|
|
1973
|
+
this.off('dataChannel', _resolve, this);
|
|
1879
1974
|
resolve(this);
|
|
1880
1975
|
}
|
|
1881
1976
|
};
|
|
1882
|
-
|
|
1883
|
-
|
|
1977
|
+
|
|
1978
|
+
let _rejectTimeout = () => {
|
|
1979
|
+
this.off('dataChannel', _resolve, this);
|
|
1980
|
+
this._abortController.signal.removeEventListener('abort', _rejectAbort);
|
|
1884
1981
|
reject({type: 'error', id: 27, message: 'Data channel did not open', data: null});
|
|
1885
|
-
}
|
|
1886
|
-
|
|
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);
|
|
1887
1995
|
});
|
|
1888
1996
|
}
|
|
1889
1997
|
})
|
|
1890
1998
|
.then(r => {
|
|
1891
|
-
this.
|
|
1999
|
+
this.isPublished = true;
|
|
1892
2000
|
if(config.stream) {
|
|
1893
2001
|
let tracks = config.stream.getTracks();
|
|
1894
2002
|
tracks.forEach(track => {
|
|
@@ -1897,7 +2005,7 @@ class RoomSession {
|
|
|
1897
2005
|
this.emit('addLocalParticipant', {
|
|
1898
2006
|
tid: generateUUID(),
|
|
1899
2007
|
id: handle.handleId,
|
|
1900
|
-
userId: handle.userId,
|
|
2008
|
+
userId: decodeJanusDisplay(handle.userId)?.userId,
|
|
1901
2009
|
track,
|
|
1902
2010
|
stream: config.stream,
|
|
1903
2011
|
adding: true,
|
|
@@ -1910,7 +2018,7 @@ class RoomSession {
|
|
|
1910
2018
|
this.emit('addLocalParticipant', {
|
|
1911
2019
|
tid:generateUUID(),
|
|
1912
2020
|
id: handle.handleId,
|
|
1913
|
-
userId: handle.userId,
|
|
2021
|
+
userId: decodeJanusDisplay(handle.userId)?.userId,
|
|
1914
2022
|
track: ev.target,
|
|
1915
2023
|
stream: config.stream,
|
|
1916
2024
|
adding: false,
|
|
@@ -1927,7 +2035,7 @@ class RoomSession {
|
|
|
1927
2035
|
this.emit('addLocalParticipant', {
|
|
1928
2036
|
tid: generateUUID(),
|
|
1929
2037
|
id: handle.handleId,
|
|
1930
|
-
userId: handle.userId,
|
|
2038
|
+
userId: decodeJanusDisplay(handle.userId)?.userId,
|
|
1931
2039
|
stream: null,
|
|
1932
2040
|
adding: false,
|
|
1933
2041
|
constructId: this.constructId,
|
|
@@ -1952,10 +2060,10 @@ class RoomSession {
|
|
|
1952
2060
|
}
|
|
1953
2061
|
|
|
1954
2062
|
unpublishLocal(dontWait = false) {
|
|
1955
|
-
return this.
|
|
2063
|
+
return this.isPublished
|
|
1956
2064
|
? this.sendMessage(this.handleId, {body: {"request": "unpublish"}}, dontWait)
|
|
1957
2065
|
.finally(r => {
|
|
1958
|
-
this.
|
|
2066
|
+
this.isPublished = false;
|
|
1959
2067
|
this.emit('published', {status: false, hasStream: false});
|
|
1960
2068
|
return r
|
|
1961
2069
|
})
|
|
@@ -2026,6 +2134,11 @@ class RoomSession {
|
|
|
2026
2134
|
return this._talkbackIds;
|
|
2027
2135
|
}
|
|
2028
2136
|
|
|
2137
|
+
setRoomType(type = 'watchparty') {
|
|
2138
|
+
this._roomType = type;
|
|
2139
|
+
return this._roomType;
|
|
2140
|
+
}
|
|
2141
|
+
|
|
2029
2142
|
}
|
|
2030
2143
|
|
|
2031
2144
|
export default Room;
|