livekit-client 1.6.6 → 1.6.8
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/livekit-client.esm.mjs +508 -317
- package/dist/livekit-client.esm.mjs.map +1 -1
- package/dist/livekit-client.umd.js +1 -1
- package/dist/livekit-client.umd.js.map +1 -1
- package/dist/src/proto/google/protobuf/timestamp.d.ts +9 -2
- package/dist/src/proto/google/protobuf/timestamp.d.ts.map +1 -1
- package/dist/src/proto/livekit_models.d.ts +958 -58
- package/dist/src/proto/livekit_models.d.ts.map +1 -1
- package/dist/src/proto/livekit_rtc.d.ts +8394 -3725
- package/dist/src/proto/livekit_rtc.d.ts.map +1 -1
- package/dist/src/room/PCTransport.d.ts.map +1 -1
- package/dist/src/room/RTCEngine.d.ts +10 -3
- package/dist/src/room/RTCEngine.d.ts.map +1 -1
- package/dist/src/room/Room.d.ts +1 -1
- package/dist/src/room/Room.d.ts.map +1 -1
- package/dist/src/room/events.d.ts +1 -1
- package/dist/src/room/participant/LocalParticipant.d.ts +18 -0
- package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
- package/dist/src/room/participant/RemoteParticipant.d.ts.map +1 -1
- package/dist/src/room/track/RemoteTrackPublication.d.ts +1 -1
- package/dist/src/room/track/RemoteTrackPublication.d.ts.map +1 -1
- package/dist/src/room/track/RemoteVideoTrack.d.ts.map +1 -1
- package/dist/src/room/track/Track.d.ts +2 -1
- package/dist/src/room/track/Track.d.ts.map +1 -1
- package/dist/src/room/track/options.d.ts +10 -2
- package/dist/src/room/track/options.d.ts.map +1 -1
- package/dist/src/room/types.d.ts +7 -0
- package/dist/src/room/types.d.ts.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/ts4.2/src/proto/google/protobuf/timestamp.d.ts +11 -2
- package/dist/ts4.2/src/proto/livekit_models.d.ts +1199 -177
- package/dist/ts4.2/src/proto/livekit_rtc.d.ts +9260 -4023
- package/dist/ts4.2/src/room/RTCEngine.d.ts +10 -3
- package/dist/ts4.2/src/room/Room.d.ts +1 -1
- package/dist/ts4.2/src/room/events.d.ts +1 -1
- package/dist/ts4.2/src/room/participant/LocalParticipant.d.ts +18 -0
- package/dist/ts4.2/src/room/track/RemoteTrackPublication.d.ts +1 -1
- package/dist/ts4.2/src/room/track/Track.d.ts +2 -1
- package/dist/ts4.2/src/room/track/options.d.ts +10 -2
- package/dist/ts4.2/src/room/types.d.ts +7 -0
- package/dist/ts4.2/src/version.d.ts +1 -1
- package/package.json +14 -14
- package/src/proto/google/protobuf/timestamp.ts +4 -0
- package/src/proto/livekit_models.ts +128 -31
- package/src/proto/livekit_rtc.ts +262 -161
- package/src/room/PCTransport.ts +2 -0
- package/src/room/RTCEngine.ts +50 -55
- package/src/room/Room.ts +60 -43
- package/src/room/events.ts +1 -1
- package/src/room/participant/LocalParticipant.ts +118 -28
- package/src/room/participant/RemoteParticipant.ts +2 -3
- package/src/room/track/RemoteTrackPublication.ts +3 -2
- package/src/room/track/RemoteVideoTrack.ts +0 -3
- package/src/room/track/Track.ts +2 -1
- package/src/room/track/options.ts +14 -2
- package/src/room/types.ts +9 -0
- package/src/version.ts +1 -1
package/src/room/PCTransport.ts
CHANGED
package/src/room/RTCEngine.ts
CHANGED
@@ -118,8 +118,6 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
118
118
|
|
119
119
|
private clientConfiguration?: ClientConfiguration;
|
120
120
|
|
121
|
-
private connectedServerAddr?: string;
|
122
|
-
|
123
121
|
private attemptingReconnect: boolean = false;
|
124
122
|
|
125
123
|
private reconnectPolicy: ReconnectPolicy;
|
@@ -136,6 +134,8 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
136
134
|
|
137
135
|
private closingLock: Mutex;
|
138
136
|
|
137
|
+
private shouldFailNext: boolean = false;
|
138
|
+
|
139
139
|
constructor(private options: InternalRoomOptions) {
|
140
140
|
super();
|
141
141
|
this.client = new SignalClient();
|
@@ -247,7 +247,13 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
247
247
|
});
|
248
248
|
}
|
249
249
|
|
250
|
-
|
250
|
+
/**
|
251
|
+
* Removes sender from PeerConnection, returning true if it was removed successfully
|
252
|
+
* and a negotiation is necessary
|
253
|
+
* @param sender
|
254
|
+
* @returns
|
255
|
+
*/
|
256
|
+
removeTrack(sender: RTCRtpSender): boolean {
|
251
257
|
if (sender.track && this.pendingTrackResolvers[sender.track.id]) {
|
252
258
|
const { reject } = this.pendingTrackResolvers[sender.track.id];
|
253
259
|
if (reject) {
|
@@ -257,9 +263,11 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
257
263
|
}
|
258
264
|
try {
|
259
265
|
this.publisher?.pc.removeTrack(sender);
|
266
|
+
return true;
|
260
267
|
} catch (e: unknown) {
|
261
268
|
log.warn('failed to remove track', { error: e, method: 'removeTrack' });
|
262
269
|
}
|
270
|
+
return false;
|
263
271
|
}
|
264
272
|
|
265
273
|
updateMuteStatus(trackSid: string, muted: boolean) {
|
@@ -270,8 +278,11 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
270
278
|
return this.reliableDCSub?.readyState;
|
271
279
|
}
|
272
280
|
|
273
|
-
|
274
|
-
|
281
|
+
async getConnectedServerAddress(): Promise<string | undefined> {
|
282
|
+
if (this.primaryPC === undefined) {
|
283
|
+
return undefined;
|
284
|
+
}
|
285
|
+
return getConnectedAddress(this.primaryPC);
|
275
286
|
}
|
276
287
|
|
277
288
|
private configure(joinResponse: JoinResponse) {
|
@@ -317,11 +328,6 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
317
328
|
primaryPC.onconnectionstatechange = async () => {
|
318
329
|
log.debug(`primary PC state changed ${primaryPC.connectionState}`);
|
319
330
|
if (primaryPC.connectionState === 'connected') {
|
320
|
-
try {
|
321
|
-
this.connectedServerAddr = await getConnectedAddress(primaryPC);
|
322
|
-
} catch (e) {
|
323
|
-
log.warn('could not get connected server address', { error: e });
|
324
|
-
}
|
325
331
|
const shouldEmit = this.pcState === PCState.New;
|
326
332
|
this.pcState = PCState.Connected;
|
327
333
|
if (shouldEmit) {
|
@@ -334,10 +340,9 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
334
340
|
|
335
341
|
this.handleDisconnect(
|
336
342
|
'primary peerconnection',
|
337
|
-
false,
|
338
343
|
subscriberPrimary
|
339
|
-
? ReconnectReason.
|
340
|
-
: ReconnectReason.
|
344
|
+
? ReconnectReason.RR_SUBSCRIBER_FAILED
|
345
|
+
: ReconnectReason.RR_PUBLISHER_FAILED,
|
341
346
|
);
|
342
347
|
}
|
343
348
|
}
|
@@ -348,10 +353,9 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
348
353
|
if (secondaryPC.connectionState === 'failed') {
|
349
354
|
this.handleDisconnect(
|
350
355
|
'secondary peerconnection',
|
351
|
-
false,
|
352
356
|
subscriberPrimary
|
353
|
-
? ReconnectReason.
|
354
|
-
: ReconnectReason.
|
357
|
+
? ReconnectReason.RR_PUBLISHER_FAILED
|
358
|
+
: ReconnectReason.RR_SUBSCRIBER_FAILED,
|
355
359
|
);
|
356
360
|
}
|
357
361
|
};
|
@@ -419,7 +423,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
419
423
|
};
|
420
424
|
|
421
425
|
this.client.onClose = () => {
|
422
|
-
this.handleDisconnect('signal',
|
426
|
+
this.handleDisconnect('signal', ReconnectReason.RR_SIGNAL_DISCONNECTED);
|
423
427
|
};
|
424
428
|
|
425
429
|
this.client.onLeave = (leave?: LeaveRequest) => {
|
@@ -690,11 +694,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
690
694
|
// websocket reconnect behavior. if websocket is interrupted, and the PeerConnection
|
691
695
|
// continues to work, we can reconnect to websocket to continue the session
|
692
696
|
// after a number of retries, we'll close and give up permanently
|
693
|
-
private handleDisconnect = (
|
694
|
-
connection: string,
|
695
|
-
signalEvents: boolean = false,
|
696
|
-
disconnectReason?: ReconnectReason,
|
697
|
-
) => {
|
697
|
+
private handleDisconnect = (connection: string, disconnectReason?: ReconnectReason) => {
|
698
698
|
if (this._isClosed) {
|
699
699
|
return;
|
700
700
|
}
|
@@ -731,12 +731,12 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
731
731
|
|
732
732
|
this.clearReconnectTimeout();
|
733
733
|
this.reconnectTimeout = CriticalTimers.setTimeout(
|
734
|
-
() => this.attemptReconnect(
|
734
|
+
() => this.attemptReconnect(disconnectReason),
|
735
735
|
delay,
|
736
736
|
);
|
737
737
|
};
|
738
738
|
|
739
|
-
private async attemptReconnect(
|
739
|
+
private async attemptReconnect(reason?: ReconnectReason) {
|
740
740
|
if (this._isClosed) {
|
741
741
|
return;
|
742
742
|
}
|
@@ -756,35 +756,26 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
756
756
|
try {
|
757
757
|
this.attemptingReconnect = true;
|
758
758
|
if (this.fullReconnectOnNext) {
|
759
|
-
await this.restartConnection(
|
759
|
+
await this.restartConnection();
|
760
760
|
} else {
|
761
|
-
await this.resumeConnection(
|
761
|
+
await this.resumeConnection(reason);
|
762
762
|
}
|
763
763
|
this.clearPendingReconnect();
|
764
764
|
this.fullReconnectOnNext = false;
|
765
765
|
} catch (e) {
|
766
766
|
this.reconnectAttempts += 1;
|
767
|
-
let reconnectRequired = false;
|
768
767
|
let recoverable = true;
|
769
|
-
let requireSignalEvents = false;
|
770
768
|
if (e instanceof UnexpectedConnectionState) {
|
771
769
|
log.debug('received unrecoverable error', { error: e });
|
772
770
|
// unrecoverable
|
773
771
|
recoverable = false;
|
774
772
|
} else if (!(e instanceof SignalReconnectError)) {
|
775
773
|
// cannot resume
|
776
|
-
reconnectRequired = true;
|
777
|
-
}
|
778
|
-
|
779
|
-
// when we flip from resume to reconnect
|
780
|
-
// we need to fire the right reconnecting events
|
781
|
-
if (reconnectRequired && !this.fullReconnectOnNext) {
|
782
774
|
this.fullReconnectOnNext = true;
|
783
|
-
requireSignalEvents = true;
|
784
775
|
}
|
785
776
|
|
786
777
|
if (recoverable) {
|
787
|
-
this.handleDisconnect('reconnect',
|
778
|
+
this.handleDisconnect('reconnect', ReconnectReason.RR_UNKOWN);
|
788
779
|
} else {
|
789
780
|
log.info(
|
790
781
|
`could not recover connection after ${this.reconnectAttempts} attempts, ${
|
@@ -810,16 +801,14 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
810
801
|
return null;
|
811
802
|
}
|
812
803
|
|
813
|
-
private async restartConnection(
|
804
|
+
private async restartConnection() {
|
814
805
|
if (!this.url || !this.token) {
|
815
806
|
// permanent failure, don't attempt reconnection
|
816
807
|
throw new UnexpectedConnectionState('could not reconnect, url or token not saved');
|
817
808
|
}
|
818
809
|
|
819
810
|
log.info(`reconnecting, attempt: ${this.reconnectAttempts}`);
|
820
|
-
|
821
|
-
this.emit(EngineEvent.Restarting);
|
822
|
-
}
|
811
|
+
this.emit(EngineEvent.Restarting);
|
823
812
|
|
824
813
|
if (this.client.isConnected) {
|
825
814
|
await this.client.sendLeave();
|
@@ -842,6 +831,11 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
842
831
|
throw new SignalReconnectError();
|
843
832
|
}
|
844
833
|
|
834
|
+
if (this.shouldFailNext) {
|
835
|
+
this.shouldFailNext = false;
|
836
|
+
throw new Error('simulated failure');
|
837
|
+
}
|
838
|
+
|
845
839
|
await this.waitForPCConnected();
|
846
840
|
this.client.setReconnected();
|
847
841
|
|
@@ -849,10 +843,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
849
843
|
this.emit(EngineEvent.Restarted, joinResponse);
|
850
844
|
}
|
851
845
|
|
852
|
-
private async resumeConnection(
|
853
|
-
emitResuming: boolean = false,
|
854
|
-
reason?: ReconnectReason,
|
855
|
-
): Promise<void> {
|
846
|
+
private async resumeConnection(reason?: ReconnectReason): Promise<void> {
|
856
847
|
if (!this.url || !this.token) {
|
857
848
|
// permanent failure, don't attempt reconnection
|
858
849
|
throw new UnexpectedConnectionState('could not reconnect, url or token not saved');
|
@@ -863,9 +854,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
863
854
|
}
|
864
855
|
|
865
856
|
log.info(`resuming signal connection, attempt ${this.reconnectAttempts}`);
|
866
|
-
|
867
|
-
this.emit(EngineEvent.Resuming);
|
868
|
-
}
|
857
|
+
this.emit(EngineEvent.Resuming);
|
869
858
|
|
870
859
|
try {
|
871
860
|
const res = await this.client.reconnect(this.url, this.token, this.participantSid, reason);
|
@@ -883,6 +872,11 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
883
872
|
}
|
884
873
|
this.emit(EngineEvent.SignalResumed);
|
885
874
|
|
875
|
+
if (this.shouldFailNext) {
|
876
|
+
this.shouldFailNext = false;
|
877
|
+
throw new Error('simulated failure');
|
878
|
+
}
|
879
|
+
|
886
880
|
this.subscriber.restartingIce = true;
|
887
881
|
|
888
882
|
// only restart publisher if it's needed
|
@@ -921,11 +915,6 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
921
915
|
this.primaryPC?.connectionState === 'connected'
|
922
916
|
) {
|
923
917
|
this.pcState = PCState.Connected;
|
924
|
-
try {
|
925
|
-
this.connectedServerAddr = await getConnectedAddress(this.primaryPC);
|
926
|
-
} catch (e) {
|
927
|
-
log.warn('could not get connected server address', { error: e });
|
928
|
-
}
|
929
918
|
}
|
930
919
|
if (this.pcState === PCState.Connected) {
|
931
920
|
return;
|
@@ -1022,7 +1011,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
1022
1011
|
|
1023
1012
|
const negotiationTimeout = setTimeout(() => {
|
1024
1013
|
reject('negotiation timed out');
|
1025
|
-
this.handleDisconnect('negotiation',
|
1014
|
+
this.handleDisconnect('negotiation', ReconnectReason.RR_SIGNAL_DISCONNECTED);
|
1026
1015
|
}, this.peerConnectionTimeout);
|
1027
1016
|
|
1028
1017
|
const cleanup = () => {
|
@@ -1043,7 +1032,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
1043
1032
|
if (e instanceof NegotiationError) {
|
1044
1033
|
this.fullReconnectOnNext = true;
|
1045
1034
|
}
|
1046
|
-
this.handleDisconnect('negotiation',
|
1035
|
+
this.handleDisconnect('negotiation', ReconnectReason.RR_UNKOWN);
|
1047
1036
|
});
|
1048
1037
|
});
|
1049
1038
|
}
|
@@ -1066,6 +1055,12 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
1066
1055
|
}
|
1067
1056
|
}
|
1068
1057
|
|
1058
|
+
/* @internal */
|
1059
|
+
failNext() {
|
1060
|
+
// debugging method to fail the next reconnect/resume attempt
|
1061
|
+
this.shouldFailNext = true;
|
1062
|
+
}
|
1063
|
+
|
1069
1064
|
private clearReconnectTimeout() {
|
1070
1065
|
if (this.reconnectTimeout) {
|
1071
1066
|
CriticalTimers.clearTimeout(this.reconnectTimeout);
|
@@ -1081,7 +1076,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
1081
1076
|
// in case the engine is currently reconnecting, attempt a reconnect immediately after the browser state has changed to 'onLine'
|
1082
1077
|
if (this.client.isReconnecting) {
|
1083
1078
|
this.clearReconnectTimeout();
|
1084
|
-
this.attemptReconnect(
|
1079
|
+
this.attemptReconnect(ReconnectReason.RR_SIGNAL_DISCONNECTED);
|
1085
1080
|
}
|
1086
1081
|
};
|
1087
1082
|
|
package/src/room/Room.ts
CHANGED
@@ -56,8 +56,8 @@ import type { AdaptiveStreamSettings } from './track/types';
|
|
56
56
|
import { getNewAudioContext } from './track/utils';
|
57
57
|
import type { SimulationOptions } from './types';
|
58
58
|
import {
|
59
|
-
Future,
|
60
59
|
createDummyVideoStreamTrack,
|
60
|
+
Future,
|
61
61
|
getEmptyAudioStreamTrack,
|
62
62
|
isWeb,
|
63
63
|
Mutex,
|
@@ -516,6 +516,13 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
516
516
|
},
|
517
517
|
});
|
518
518
|
break;
|
519
|
+
case 'resume-reconnect':
|
520
|
+
this.engine.failNext();
|
521
|
+
await this.engine.client.close();
|
522
|
+
if (this.engine.client.onClose) {
|
523
|
+
this.engine.client.onClose('simulate resume-reconnect');
|
524
|
+
}
|
525
|
+
break;
|
519
526
|
case 'force-tcp':
|
520
527
|
case 'force-tls':
|
521
528
|
req = SimulateScenario.fromPartial({
|
@@ -751,45 +758,53 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
751
758
|
log.debug(`reconnected to server`, {
|
752
759
|
region: joinResponse.serverRegion,
|
753
760
|
});
|
754
|
-
this.setAndEmitConnectionState(ConnectionState.Connected);
|
755
|
-
this.emit(RoomEvent.Reconnected);
|
756
761
|
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
this.handleParticipantUpdates(joinResponse.otherParticipants);
|
764
|
-
|
765
|
-
// unpublish & republish tracks
|
766
|
-
const localPubs: LocalTrackPublication[] = [];
|
767
|
-
this.localParticipant.tracks.forEach((pub) => {
|
768
|
-
if (pub.track) {
|
769
|
-
localPubs.push(pub);
|
762
|
+
try {
|
763
|
+
// rehydrate participants
|
764
|
+
if (joinResponse.participant) {
|
765
|
+
// with a restart, the sid will have changed, we'll map our understanding to it
|
766
|
+
this.localParticipant.sid = joinResponse.participant.sid;
|
767
|
+
this.handleParticipantUpdates([joinResponse.participant]);
|
770
768
|
}
|
771
|
-
|
769
|
+
this.handleParticipantUpdates(joinResponse.otherParticipants);
|
772
770
|
|
773
|
-
|
774
|
-
localPubs
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
771
|
+
// unpublish & republish tracks
|
772
|
+
const localPubs: LocalTrackPublication[] = [];
|
773
|
+
this.localParticipant.tracks.forEach((pub) => {
|
774
|
+
if (pub.track) {
|
775
|
+
localPubs.push(pub);
|
776
|
+
}
|
777
|
+
});
|
778
|
+
|
779
|
+
await Promise.all(
|
780
|
+
localPubs.map(async (pub) => {
|
781
|
+
const track = pub.track!;
|
782
|
+
this.localParticipant.unpublishTrack(track, false);
|
783
|
+
if (!track.isMuted) {
|
784
|
+
if (
|
785
|
+
(track instanceof LocalAudioTrack || track instanceof LocalVideoTrack) &&
|
786
|
+
!track.isUserProvided
|
787
|
+
) {
|
788
|
+
// we need to restart the track before publishing, often a full reconnect
|
789
|
+
// is necessary because computer had gone to sleep.
|
790
|
+
log.debug('restarting existing track', {
|
791
|
+
track: pub.trackSid,
|
792
|
+
});
|
793
|
+
await track.restartTrack();
|
794
|
+
}
|
795
|
+
log.debug('publishing new track', {
|
785
796
|
track: pub.trackSid,
|
786
797
|
});
|
787
|
-
await track.
|
798
|
+
await this.localParticipant.publishTrack(track, pub.options);
|
788
799
|
}
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
800
|
+
}),
|
801
|
+
);
|
802
|
+
} catch (error) {
|
803
|
+
log.error('error trying to re-publish tracks after reconnection', { error });
|
804
|
+
} finally {
|
805
|
+
this.setAndEmitConnectionState(ConnectionState.Connected);
|
806
|
+
this.emit(RoomEvent.Reconnected);
|
807
|
+
}
|
793
808
|
};
|
794
809
|
|
795
810
|
private handleDisconnect(shouldStopTracks = true, reason?: DisconnectReason) {
|
@@ -862,15 +877,16 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
862
877
|
let remoteParticipant = this.participants.get(info.sid);
|
863
878
|
const isNewParticipant = !remoteParticipant;
|
864
879
|
|
865
|
-
// create participant if doesn't exist
|
866
|
-
remoteParticipant = this.getOrCreateParticipant(info.sid, info);
|
867
|
-
|
868
880
|
// when it's disconnected, send updates
|
869
881
|
if (info.state === ParticipantInfo_State.DISCONNECTED) {
|
870
882
|
this.handleParticipantDisconnected(info.sid, remoteParticipant);
|
871
|
-
} else
|
872
|
-
//
|
873
|
-
remoteParticipant.
|
883
|
+
} else {
|
884
|
+
// create participant if doesn't exist
|
885
|
+
remoteParticipant = this.getOrCreateParticipant(info.sid, info);
|
886
|
+
if (!isNewParticipant) {
|
887
|
+
// just update, no events
|
888
|
+
remoteParticipant.updateInfo(info);
|
889
|
+
}
|
874
890
|
}
|
875
891
|
});
|
876
892
|
};
|
@@ -886,7 +902,7 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
886
902
|
participant.tracks.forEach((publication) => {
|
887
903
|
participant.unpublishTrack(publication.trackSid, true);
|
888
904
|
});
|
889
|
-
this.
|
905
|
+
this.emit(RoomEvent.ParticipantDisconnected, participant);
|
890
906
|
}
|
891
907
|
|
892
908
|
// updates are sent only when there's a change to speaker ordering
|
@@ -991,7 +1007,7 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
991
1007
|
// find the participant
|
992
1008
|
const participant = this.participants.get(userPacket.participantSid);
|
993
1009
|
|
994
|
-
this.emit(RoomEvent.DataReceived, userPacket.payload, participant, kind);
|
1010
|
+
this.emit(RoomEvent.DataReceived, userPacket.payload, participant, kind, userPacket.topic);
|
995
1011
|
|
996
1012
|
// also emit on the participant
|
997
1013
|
participant?.emit(ParticipantEvent.DataReceived, userPacket.payload, kind);
|
@@ -1114,7 +1130,7 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
1114
1130
|
},
|
1115
1131
|
)
|
1116
1132
|
.on(ParticipantEvent.TrackUnpublished, (publication: RemoteTrackPublication) => {
|
1117
|
-
this.
|
1133
|
+
this.emit(RoomEvent.TrackUnpublished, publication, participant);
|
1118
1134
|
})
|
1119
1135
|
.on(
|
1120
1136
|
ParticipantEvent.TrackUnsubscribed,
|
@@ -1452,6 +1468,7 @@ export type RoomEventCallbacks = {
|
|
1452
1468
|
payload: Uint8Array,
|
1453
1469
|
participant?: RemoteParticipant,
|
1454
1470
|
kind?: DataPacket_Kind,
|
1471
|
+
topic?: string,
|
1455
1472
|
) => void;
|
1456
1473
|
connectionQualityChanged: (quality: ConnectionQuality, participant: Participant) => void;
|
1457
1474
|
mediaDevicesError: (error: Error) => void;
|
package/src/room/events.ts
CHANGED
@@ -175,7 +175,7 @@ export enum RoomEvent {
|
|
175
175
|
* Data packets provides the ability to use LiveKit to send/receive arbitrary payloads.
|
176
176
|
* All participants in the room will receive the messages sent to the room.
|
177
177
|
*
|
178
|
-
* args: (payload: Uint8Array, participant: [[Participant]], kind: [[DataPacket_Kind]])
|
178
|
+
* args: (payload: Uint8Array, participant: [[Participant]], kind: [[DataPacket_Kind]], topic?: string)
|
179
179
|
*/
|
180
180
|
DataReceived = 'dataReceived',
|
181
181
|
|