livekit-client 1.1.2 → 1.1.5
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 +205 -89
- 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/room/Room.d.ts +4 -1
- package/dist/src/room/Room.d.ts.map +1 -1
- package/dist/src/room/participant/LocalParticipant.d.ts +2 -1
- 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/LocalAudioTrack.d.ts +1 -1
- package/dist/src/room/track/LocalAudioTrack.d.ts.map +1 -1
- package/dist/src/room/track/LocalTrack.d.ts +4 -2
- package/dist/src/room/track/LocalTrack.d.ts.map +1 -1
- package/dist/src/room/track/LocalVideoTrack.d.ts +1 -1
- package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -1
- package/dist/src/room/track/RemoteVideoTrack.d.ts.map +1 -1
- package/dist/src/room/utils.d.ts +6 -0
- package/dist/src/room/utils.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/room/Room.ts +150 -55
- package/src/room/participant/LocalParticipant.ts +7 -6
- package/src/room/participant/RemoteParticipant.ts +5 -11
- package/src/room/participant/publishUtils.ts +2 -2
- package/src/room/track/LocalAudioTrack.ts +7 -3
- package/src/room/track/LocalTrack.ts +11 -2
- package/src/room/track/LocalVideoTrack.ts +7 -3
- package/src/room/track/RemoteVideoTrack.ts +30 -2
- package/src/room/track/create.ts +2 -2
- package/src/room/utils.ts +15 -0
@@ -10070,7 +10070,7 @@ function computeBitrate(currentStats, prevStats) {
|
|
10070
10070
|
return (bytesNow - bytesPrev) * 8 * 1000 / (currentStats.timestamp - prevStats.timestamp);
|
10071
10071
|
}
|
10072
10072
|
|
10073
|
-
var version$1 = "1.1.
|
10073
|
+
var version$1 = "1.1.5";
|
10074
10074
|
|
10075
10075
|
const version = version$1;
|
10076
10076
|
const protocolVersion = 8;
|
@@ -10180,6 +10180,15 @@ function getEmptyAudioStreamTrack() {
|
|
10180
10180
|
|
10181
10181
|
return emptyAudioStreamTrack;
|
10182
10182
|
}
|
10183
|
+
class Future {
|
10184
|
+
constructor() {
|
10185
|
+
this.promise = new Promise((resolve, reject) => {
|
10186
|
+
this.resolve = resolve;
|
10187
|
+
this.reject = reject;
|
10188
|
+
});
|
10189
|
+
}
|
10190
|
+
|
10191
|
+
}
|
10183
10192
|
|
10184
10193
|
const defaultId = 'default';
|
10185
10194
|
class DeviceManager {
|
@@ -11060,6 +11069,7 @@ function detachTrack(track, element) {
|
|
11060
11069
|
|
11061
11070
|
class LocalTrack extends Track {
|
11062
11071
|
constructor(mediaTrack, kind, constraints) {
|
11072
|
+
let userProvidedTrack = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
|
11063
11073
|
super(mediaTrack, kind);
|
11064
11074
|
this._isUpstreamPaused = false;
|
11065
11075
|
|
@@ -11076,6 +11086,7 @@ class LocalTrack extends Track {
|
|
11076
11086
|
this.constraints = constraints !== null && constraints !== void 0 ? constraints : mediaTrack.getConstraints();
|
11077
11087
|
this.reacquireTrack = false;
|
11078
11088
|
this.wasMuted = false;
|
11089
|
+
this.providedByUser = userProvidedTrack;
|
11079
11090
|
}
|
11080
11091
|
|
11081
11092
|
get id() {
|
@@ -11105,6 +11116,10 @@ class LocalTrack extends Track {
|
|
11105
11116
|
get isUpstreamPaused() {
|
11106
11117
|
return this._isUpstreamPaused;
|
11107
11118
|
}
|
11119
|
+
|
11120
|
+
get isUserProvided() {
|
11121
|
+
return this.providedByUser;
|
11122
|
+
}
|
11108
11123
|
/**
|
11109
11124
|
* @returns DeviceID of the device that is currently being used for this track
|
11110
11125
|
*/
|
@@ -11136,6 +11151,8 @@ class LocalTrack extends Track {
|
|
11136
11151
|
}
|
11137
11152
|
|
11138
11153
|
async replaceTrack(track) {
|
11154
|
+
let userProvidedTrack = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
11155
|
+
|
11139
11156
|
if (!this.sender) {
|
11140
11157
|
throw new TrackInvalidError('unable to replace an unpublished track');
|
11141
11158
|
} // detach
|
@@ -11164,6 +11181,7 @@ class LocalTrack extends Track {
|
|
11164
11181
|
attachToElement(track, el);
|
11165
11182
|
});
|
11166
11183
|
this.mediaStream = new MediaStream([track]);
|
11184
|
+
this.providedByUser = userProvidedTrack;
|
11167
11185
|
return this;
|
11168
11186
|
}
|
11169
11187
|
|
@@ -11235,7 +11253,7 @@ class LocalTrack extends Track {
|
|
11235
11253
|
if (!isMobile()) return;
|
11236
11254
|
livekitLogger.debug("visibility changed, is in Background: ".concat(this.isInBackground));
|
11237
11255
|
|
11238
|
-
if (!this.isInBackground && this.needsReAcquisition) {
|
11256
|
+
if (!this.isInBackground && this.needsReAcquisition && !this.isUserProvided) {
|
11239
11257
|
livekitLogger.debug("track needs to be reaquired, restarting ".concat(this.source));
|
11240
11258
|
await this.restart();
|
11241
11259
|
this.reacquireTrack = false; // Restore muted state if had to be restarted
|
@@ -11386,7 +11404,8 @@ function getNewAudioContext() {
|
|
11386
11404
|
|
11387
11405
|
class LocalAudioTrack extends LocalTrack {
|
11388
11406
|
constructor(mediaTrack, constraints) {
|
11389
|
-
|
11407
|
+
let userProvidedTrack = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
|
11408
|
+
super(mediaTrack, Track.Kind.Audio, constraints, userProvidedTrack);
|
11390
11409
|
/** @internal */
|
11391
11410
|
|
11392
11411
|
this.stopOnMute = false;
|
@@ -11446,7 +11465,7 @@ class LocalAudioTrack extends LocalTrack {
|
|
11446
11465
|
}
|
11447
11466
|
|
11448
11467
|
async unmute() {
|
11449
|
-
if (this.source === Track.Source.Microphone && this.stopOnMute) {
|
11468
|
+
if (this.source === Track.Source.Microphone && this.stopOnMute && !this.isUserProvided) {
|
11450
11469
|
livekitLogger.debug('reacquiring mic track');
|
11451
11470
|
await this.restartTrack();
|
11452
11471
|
}
|
@@ -11530,7 +11549,8 @@ class LocalAudioTrack extends LocalTrack {
|
|
11530
11549
|
const refreshSubscribedCodecAfterNewCodec = 5000;
|
11531
11550
|
class LocalVideoTrack extends LocalTrack {
|
11532
11551
|
constructor(mediaTrack, constraints) {
|
11533
|
-
|
11552
|
+
let userProvidedTrack = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
|
11553
|
+
super(mediaTrack, Track.Kind.Video, constraints, userProvidedTrack);
|
11534
11554
|
this.simulcastCodecs = new Map();
|
11535
11555
|
|
11536
11556
|
this.monitorSender = async () => {
|
@@ -11627,7 +11647,7 @@ class LocalVideoTrack extends LocalTrack {
|
|
11627
11647
|
}
|
11628
11648
|
|
11629
11649
|
async unmute() {
|
11630
|
-
if (this.source === Track.Source.Camera) {
|
11650
|
+
if (this.source === Track.Source.Camera && !this.isUserProvided) {
|
11631
11651
|
livekitLogger.debug('reacquiring camera track');
|
11632
11652
|
await this.restartTrack();
|
11633
11653
|
}
|
@@ -12225,6 +12245,8 @@ class RemoteVideoTrack extends RemoteTrack {
|
|
12225
12245
|
|
12226
12246
|
this.debouncedHandleResize();
|
12227
12247
|
this.updateVisibility();
|
12248
|
+
} else {
|
12249
|
+
livekitLogger.warn('visibility resize observer not triggered');
|
12228
12250
|
}
|
12229
12251
|
}
|
12230
12252
|
/**
|
@@ -12373,9 +12395,7 @@ class RemoteVideoTrack extends RemoteTrack {
|
|
12373
12395
|
}
|
12374
12396
|
|
12375
12397
|
class HTMLElementInfo {
|
12376
|
-
constructor(element) {
|
12377
|
-
let visible = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
12378
|
-
|
12398
|
+
constructor(element, visible) {
|
12379
12399
|
this.onVisibilityChanged = entry => {
|
12380
12400
|
var _a;
|
12381
12401
|
|
@@ -12392,7 +12412,7 @@ class HTMLElementInfo {
|
|
12392
12412
|
};
|
12393
12413
|
|
12394
12414
|
this.element = element;
|
12395
|
-
this.visible = visible;
|
12415
|
+
this.visible = visible !== null && visible !== void 0 ? visible : isElementInViewport(element);
|
12396
12416
|
this.visibilityChangedAt = 0;
|
12397
12417
|
}
|
12398
12418
|
|
@@ -12423,6 +12443,29 @@ class HTMLElementInfo {
|
|
12423
12443
|
(_b = getResizeObserver()) === null || _b === void 0 ? void 0 : _b.unobserve(this.element);
|
12424
12444
|
}
|
12425
12445
|
|
12446
|
+
} // does not account for occlusion by other elements
|
12447
|
+
|
12448
|
+
|
12449
|
+
function isElementInViewport(el) {
|
12450
|
+
let top = el.offsetTop;
|
12451
|
+
let left = el.offsetLeft;
|
12452
|
+
const width = el.offsetWidth;
|
12453
|
+
const height = el.offsetHeight;
|
12454
|
+
const {
|
12455
|
+
hidden
|
12456
|
+
} = el;
|
12457
|
+
const {
|
12458
|
+
opacity,
|
12459
|
+
display
|
12460
|
+
} = getComputedStyle(el);
|
12461
|
+
|
12462
|
+
while (el.offsetParent) {
|
12463
|
+
el = el.offsetParent;
|
12464
|
+
top += el.offsetTop;
|
12465
|
+
left += el.offsetLeft;
|
12466
|
+
}
|
12467
|
+
|
12468
|
+
return top < window.pageYOffset + window.innerHeight && left < window.pageXOffset + window.innerWidth && top + height > window.pageYOffset && left + width > window.pageXOffset && !hidden && (opacity !== '' ? parseFloat(opacity) > 0 : true) && display !== 'none';
|
12426
12469
|
}
|
12427
12470
|
|
12428
12471
|
class TrackPublication extends events.exports.EventEmitter {
|
@@ -12932,10 +12975,10 @@ function trackPermissionToProto(perms) {
|
|
12932
12975
|
function mediaTrackToLocalTrack(mediaStreamTrack, constraints) {
|
12933
12976
|
switch (mediaStreamTrack.kind) {
|
12934
12977
|
case 'audio':
|
12935
|
-
return new LocalAudioTrack(mediaStreamTrack, constraints);
|
12978
|
+
return new LocalAudioTrack(mediaStreamTrack, constraints, false);
|
12936
12979
|
|
12937
12980
|
case 'video':
|
12938
|
-
return new LocalVideoTrack(mediaStreamTrack, constraints);
|
12981
|
+
return new LocalVideoTrack(mediaStreamTrack, constraints, false);
|
12939
12982
|
|
12940
12983
|
default:
|
12941
12984
|
throw new TrackInvalidError("unsupported track type: ".concat(mediaStreamTrack.kind));
|
@@ -13395,9 +13438,7 @@ class RemoteParticipant extends Participant {
|
|
13395
13438
|
|
13396
13439
|
|
13397
13440
|
static fromParticipantInfo(signalClient, pi) {
|
13398
|
-
|
13399
|
-
rp.updateInfo(pi);
|
13400
|
-
return rp;
|
13441
|
+
return new RemoteParticipant(signalClient, pi.sid, pi.identity);
|
13401
13442
|
}
|
13402
13443
|
|
13403
13444
|
addTrackPublication(publication) {
|
@@ -13538,7 +13579,6 @@ class RemoteParticipant extends Participant {
|
|
13538
13579
|
|
13539
13580
|
|
13540
13581
|
updateInfo(info) {
|
13541
|
-
const alreadyHasMetadata = this.hasMetadata;
|
13542
13582
|
super.updateInfo(info); // we are getting a list of all available tracks, reconcile in here
|
13543
13583
|
// and send out events for changes
|
13544
13584
|
// reconcile track publications, publish events only if metadata is already there
|
@@ -13566,14 +13606,11 @@ class RemoteParticipant extends Participant {
|
|
13566
13606
|
}
|
13567
13607
|
|
13568
13608
|
validTracks.set(ti.sid, publication);
|
13569
|
-
}); //
|
13570
|
-
|
13571
|
-
if (alreadyHasMetadata) {
|
13572
|
-
newTracks.forEach(publication => {
|
13573
|
-
this.emit(ParticipantEvent.TrackPublished, publication);
|
13574
|
-
});
|
13575
|
-
} // detect removed tracks
|
13609
|
+
}); // always emit events for new publications, Room will not forward them unless it's ready
|
13576
13610
|
|
13611
|
+
newTracks.forEach(publication => {
|
13612
|
+
this.emit(ParticipantEvent.TrackPublished, publication);
|
13613
|
+
}); // detect removed tracks
|
13577
13614
|
|
13578
13615
|
this.tracks.forEach(publication => {
|
13579
13616
|
if (!validTracks.has(publication.trackSid)) {
|
@@ -14048,12 +14085,12 @@ class LocalParticipant extends Participant {
|
|
14048
14085
|
throw new TrackInvalidError('no video track found');
|
14049
14086
|
}
|
14050
14087
|
|
14051
|
-
const screenVideo = new LocalVideoTrack(tracks[0]);
|
14088
|
+
const screenVideo = new LocalVideoTrack(tracks[0], undefined, false);
|
14052
14089
|
screenVideo.source = Track.Source.ScreenShare;
|
14053
14090
|
const localTracks = [screenVideo];
|
14054
14091
|
|
14055
14092
|
if (stream.getAudioTracks().length > 0) {
|
14056
|
-
const screenAudio = new LocalAudioTrack(stream.getAudioTracks()[0]);
|
14093
|
+
const screenAudio = new LocalAudioTrack(stream.getAudioTracks()[0], undefined, false);
|
14057
14094
|
screenAudio.source = Track.Source.ScreenShareAudio;
|
14058
14095
|
localTracks.push(screenAudio);
|
14059
14096
|
}
|
@@ -14076,11 +14113,11 @@ class LocalParticipant extends Participant {
|
|
14076
14113
|
if (track instanceof MediaStreamTrack) {
|
14077
14114
|
switch (track.kind) {
|
14078
14115
|
case 'audio':
|
14079
|
-
track = new LocalAudioTrack(track);
|
14116
|
+
track = new LocalAudioTrack(track, undefined, true);
|
14080
14117
|
break;
|
14081
14118
|
|
14082
14119
|
case 'video':
|
14083
|
-
track = new LocalVideoTrack(track);
|
14120
|
+
track = new LocalVideoTrack(track, undefined, true);
|
14084
14121
|
break;
|
14085
14122
|
|
14086
14123
|
default:
|
@@ -19399,14 +19436,18 @@ class Room extends events.exports.EventEmitter {
|
|
19399
19436
|
this.audioEnabled = true;
|
19400
19437
|
|
19401
19438
|
this.connect = async (url, token, opts) => {
|
19402
|
-
var _a, _b
|
19403
|
-
|
19439
|
+
var _a, _b, _c, _d;
|
19404
19440
|
|
19405
|
-
if (this.state
|
19441
|
+
if (this.state === ConnectionState.Connected) {
|
19442
|
+
// when the state is reconnecting or connected, this function returns immediately
|
19406
19443
|
livekitLogger.warn("already connected to room ".concat(this.name));
|
19407
19444
|
return;
|
19408
19445
|
}
|
19409
19446
|
|
19447
|
+
if (this.connectFuture) {
|
19448
|
+
return this.connectFuture.promise;
|
19449
|
+
}
|
19450
|
+
|
19410
19451
|
this.setAndEmitConnectionState(ConnectionState.Connecting);
|
19411
19452
|
|
19412
19453
|
if (!this.abortController || this.abortController.signal.aborted) {
|
@@ -19472,50 +19513,48 @@ class Room extends events.exports.EventEmitter {
|
|
19472
19513
|
this.metadata = joinResponse.room.metadata;
|
19473
19514
|
this.emit(RoomEvent.SignalConnected);
|
19474
19515
|
} catch (err) {
|
19475
|
-
this.
|
19476
|
-
this.setAndEmitConnectionState(ConnectionState.Disconnected);
|
19516
|
+
this.recreateEngine();
|
19517
|
+
this.setAndEmitConnectionState(ConnectionState.Disconnected, new ConnectionError('could not establish signal connection'));
|
19477
19518
|
throw err;
|
19478
19519
|
} // don't return until ICE connected
|
19479
19520
|
|
19480
19521
|
|
19481
|
-
|
19482
|
-
|
19522
|
+
const connectTimeout = setTimeout(() => {
|
19523
|
+
// timeout
|
19524
|
+
this.recreateEngine();
|
19525
|
+
this.setAndEmitConnectionState(ConnectionState.Disconnected, new ConnectionError('could not connect PeerConnection after timeout'));
|
19526
|
+
}, maxICEConnectTimeout);
|
19483
19527
|
|
19484
|
-
|
19485
|
-
|
19486
|
-
|
19487
|
-
|
19488
|
-
|
19489
|
-
|
19490
|
-
|
19491
|
-
const abortHandler = () => {
|
19492
|
-
livekitLogger.warn('closing engine');
|
19493
|
-
clearTimeout(connectTimeout);
|
19494
|
-
this.engine.close();
|
19495
|
-
this.setAndEmitConnectionState(ConnectionState.Disconnected);
|
19496
|
-
reject(new ConnectionError('room connection has been cancelled'));
|
19497
|
-
};
|
19528
|
+
const abortHandler = () => {
|
19529
|
+
livekitLogger.warn('closing engine');
|
19530
|
+
clearTimeout(connectTimeout);
|
19531
|
+
this.recreateEngine();
|
19532
|
+
this.setAndEmitConnectionState(ConnectionState.Disconnected, new ConnectionError('room connection has been cancelled'));
|
19533
|
+
};
|
19498
19534
|
|
19499
|
-
|
19500
|
-
|
19501
|
-
|
19535
|
+
if ((_c = this.abortController) === null || _c === void 0 ? void 0 : _c.signal.aborted) {
|
19536
|
+
abortHandler();
|
19537
|
+
}
|
19502
19538
|
|
19503
|
-
|
19504
|
-
|
19505
|
-
|
19539
|
+
(_d = this.abortController) === null || _d === void 0 ? void 0 : _d.signal.addEventListener('abort', abortHandler);
|
19540
|
+
this.engine.once(EngineEvent.Connected, () => {
|
19541
|
+
var _a, _b;
|
19506
19542
|
|
19507
|
-
|
19508
|
-
|
19543
|
+
clearTimeout(connectTimeout);
|
19544
|
+
(_a = this.abortController) === null || _a === void 0 ? void 0 : _a.signal.removeEventListener('abort', abortHandler); // also hook unload event
|
19509
19545
|
|
19510
|
-
|
19511
|
-
|
19512
|
-
|
19513
|
-
|
19546
|
+
if (isWeb()) {
|
19547
|
+
window.addEventListener('beforeunload', this.onBeforeUnload);
|
19548
|
+
(_b = navigator.mediaDevices) === null || _b === void 0 ? void 0 : _b.addEventListener('devicechange', this.handleDeviceChange);
|
19549
|
+
}
|
19514
19550
|
|
19515
|
-
|
19516
|
-
resolve(this);
|
19517
|
-
});
|
19551
|
+
this.setAndEmitConnectionState(ConnectionState.Connected);
|
19518
19552
|
});
|
19553
|
+
|
19554
|
+
if (this.connectFuture) {
|
19555
|
+
/** @ts-ignore */
|
19556
|
+
return this.connectFuture.promise;
|
19557
|
+
}
|
19519
19558
|
};
|
19520
19559
|
/**
|
19521
19560
|
* disconnects the room, emits [[RoomEvent.Disconnected]]
|
@@ -19556,14 +19595,14 @@ class Room extends events.exports.EventEmitter {
|
|
19556
19595
|
};
|
19557
19596
|
|
19558
19597
|
this.handleRestarting = () => {
|
19559
|
-
|
19560
|
-
this.emit(RoomEvent.Reconnecting);
|
19561
|
-
} // also unwind existing participants & existing subscriptions
|
19562
|
-
|
19563
|
-
|
19598
|
+
// also unwind existing participants & existing subscriptions
|
19564
19599
|
for (const p of this.participants.values()) {
|
19565
19600
|
this.handleParticipantDisconnected(p.sid, p);
|
19566
19601
|
}
|
19602
|
+
|
19603
|
+
if (this.setAndEmitConnectionState(ConnectionState.Reconnecting)) {
|
19604
|
+
this.emit(RoomEvent.Reconnecting);
|
19605
|
+
}
|
19567
19606
|
};
|
19568
19607
|
|
19569
19608
|
this.handleRestarted = async joinResponse => {
|
@@ -19592,7 +19631,7 @@ class Room extends events.exports.EventEmitter {
|
|
19592
19631
|
this.localParticipant.unpublishTrack(track, false);
|
19593
19632
|
|
19594
19633
|
if (!track.isMuted) {
|
19595
|
-
if (track instanceof LocalAudioTrack || track instanceof LocalVideoTrack) {
|
19634
|
+
if ((track instanceof LocalAudioTrack || track instanceof LocalVideoTrack) && !track.isUserProvided) {
|
19596
19635
|
// we need to restart the track before publishing, often a full reconnect
|
19597
19636
|
// is necessary because computer had gone to sleep.
|
19598
19637
|
livekitLogger.debug('restarting existing track', {
|
@@ -19631,7 +19670,7 @@ class Room extends events.exports.EventEmitter {
|
|
19631
19670
|
this.handleParticipantDisconnected(info.sid, remoteParticipant);
|
19632
19671
|
} else if (isNewParticipant) {
|
19633
19672
|
// fire connected event
|
19634
|
-
this.
|
19673
|
+
this.emitWhenConnected(RoomEvent.ParticipantConnected, remoteParticipant);
|
19635
19674
|
} else {
|
19636
19675
|
// just update, no events
|
19637
19676
|
remoteParticipant.updateInfo(info);
|
@@ -19673,7 +19712,7 @@ class Room extends events.exports.EventEmitter {
|
|
19673
19712
|
}
|
19674
19713
|
});
|
19675
19714
|
this.activeSpeakers = activeSpeakers;
|
19676
|
-
this.
|
19715
|
+
this.emitWhenConnected(RoomEvent.ActiveSpeakersChanged, activeSpeakers);
|
19677
19716
|
}; // process list of changed speakers
|
19678
19717
|
|
19679
19718
|
|
@@ -19705,7 +19744,7 @@ class Room extends events.exports.EventEmitter {
|
|
19705
19744
|
const activeSpeakers = Array.from(lastSpeakers.values());
|
19706
19745
|
activeSpeakers.sort((a, b) => b.audioLevel - a.audioLevel);
|
19707
19746
|
this.activeSpeakers = activeSpeakers;
|
19708
|
-
this.
|
19747
|
+
this.emitWhenConnected(RoomEvent.ActiveSpeakersChanged, activeSpeakers);
|
19709
19748
|
};
|
19710
19749
|
|
19711
19750
|
this.handleStreamStateUpdate = streamStateUpdate => {
|
@@ -19724,7 +19763,7 @@ class Room extends events.exports.EventEmitter {
|
|
19724
19763
|
|
19725
19764
|
pub.track.streamState = Track.streamStateFromProto(streamState.state);
|
19726
19765
|
participant.emit(ParticipantEvent.TrackStreamStateChanged, pub, pub.track.streamState);
|
19727
|
-
this.
|
19766
|
+
this.emitWhenConnected(ParticipantEvent.TrackStreamStateChanged, pub, pub.track.streamState, participant);
|
19728
19767
|
});
|
19729
19768
|
};
|
19730
19769
|
|
@@ -19743,7 +19782,7 @@ class Room extends events.exports.EventEmitter {
|
|
19743
19782
|
|
19744
19783
|
pub._allowed = update.allowed;
|
19745
19784
|
participant.emit(ParticipantEvent.TrackSubscriptionPermissionChanged, pub, pub.subscriptionStatus);
|
19746
|
-
this.
|
19785
|
+
this.emitWhenConnected(ParticipantEvent.TrackSubscriptionPermissionChanged, pub, pub.subscriptionStatus, participant);
|
19747
19786
|
};
|
19748
19787
|
|
19749
19788
|
this.handleDataPacket = (userPacket, kind) => {
|
@@ -19780,7 +19819,7 @@ class Room extends events.exports.EventEmitter {
|
|
19780
19819
|
|
19781
19820
|
this.handleRoomUpdate = r => {
|
19782
19821
|
this.metadata = r.metadata;
|
19783
|
-
this.
|
19822
|
+
this.emitWhenConnected(RoomEvent.RoomMetadataChanged, r.metadata);
|
19784
19823
|
};
|
19785
19824
|
|
19786
19825
|
this.handleConnectionQualityUpdate = update => {
|
@@ -19838,6 +19877,10 @@ class Room extends events.exports.EventEmitter {
|
|
19838
19877
|
this.sendSyncState();
|
19839
19878
|
}
|
19840
19879
|
}).on(EngineEvent.Restarting, this.handleRestarting).on(EngineEvent.Restarted, this.handleRestarted);
|
19880
|
+
|
19881
|
+
if (this.localParticipant) {
|
19882
|
+
this.localParticipant.engine = this.engine;
|
19883
|
+
}
|
19841
19884
|
}
|
19842
19885
|
/**
|
19843
19886
|
* getLocalDevices abstracts navigator.mediaDevices.enumerateDevices.
|
@@ -20014,7 +20057,34 @@ class Room extends events.exports.EventEmitter {
|
|
20014
20057
|
}
|
20015
20058
|
}
|
20016
20059
|
|
20060
|
+
recreateEngine() {
|
20061
|
+
this.engine.close();
|
20062
|
+
/* @ts-ignore */
|
20063
|
+
|
20064
|
+
this.engine = undefined; // clear out existing remote participants, since they may have attached
|
20065
|
+
// the old engine
|
20066
|
+
|
20067
|
+
this.participants.clear();
|
20068
|
+
this.createEngine();
|
20069
|
+
}
|
20070
|
+
|
20017
20071
|
onTrackAdded(mediaTrack, stream, receiver) {
|
20072
|
+
// don't fire onSubscribed when connecting
|
20073
|
+
// WebRTC fires onTrack as soon as setRemoteDescription is called on the offer
|
20074
|
+
// at that time, ICE connectivity has not been established so the track is not
|
20075
|
+
// technically subscribed.
|
20076
|
+
// We'll defer these events until when the room is connected or eventually disconnected.
|
20077
|
+
if (this.state === ConnectionState.Connecting || this.state === ConnectionState.Reconnecting) {
|
20078
|
+
setTimeout(() => {
|
20079
|
+
this.onTrackAdded(mediaTrack, stream, receiver);
|
20080
|
+
}, 50);
|
20081
|
+
return;
|
20082
|
+
}
|
20083
|
+
|
20084
|
+
if (this.state === ConnectionState.Disconnected) {
|
20085
|
+
livekitLogger.warn('skipping incoming track after Room disconnected');
|
20086
|
+
}
|
20087
|
+
|
20018
20088
|
const parts = unpackStreamId(stream.id);
|
20019
20089
|
const participantId = parts[0];
|
20020
20090
|
let trackId = parts[1];
|
@@ -20084,7 +20154,7 @@ class Room extends events.exports.EventEmitter {
|
|
20084
20154
|
participant.tracks.forEach(publication => {
|
20085
20155
|
participant.unpublishTrack(publication.trackSid, true);
|
20086
20156
|
});
|
20087
|
-
this.
|
20157
|
+
this.emitWhenConnected(RoomEvent.ParticipantDisconnected, participant);
|
20088
20158
|
}
|
20089
20159
|
|
20090
20160
|
acquireAudioContext() {
|
@@ -20131,7 +20201,7 @@ class Room extends events.exports.EventEmitter {
|
|
20131
20201
|
|
20132
20202
|
|
20133
20203
|
participant.on(ParticipantEvent.TrackPublished, trackPublication => {
|
20134
|
-
this.
|
20204
|
+
this.emitWhenConnected(RoomEvent.TrackPublished, trackPublication, participant);
|
20135
20205
|
}).on(ParticipantEvent.TrackSubscribed, (track, publication) => {
|
20136
20206
|
// monitor playback status
|
20137
20207
|
if (track.kind === Track.Kind.Audio) {
|
@@ -20141,22 +20211,27 @@ class Room extends events.exports.EventEmitter {
|
|
20141
20211
|
|
20142
20212
|
this.emit(RoomEvent.TrackSubscribed, track, publication, participant);
|
20143
20213
|
}).on(ParticipantEvent.TrackUnpublished, publication => {
|
20144
|
-
this.
|
20214
|
+
this.emitWhenConnected(RoomEvent.TrackUnpublished, publication, participant);
|
20145
20215
|
}).on(ParticipantEvent.TrackUnsubscribed, (track, publication) => {
|
20146
20216
|
this.emit(RoomEvent.TrackUnsubscribed, track, publication, participant);
|
20147
20217
|
}).on(ParticipantEvent.TrackSubscriptionFailed, sid => {
|
20148
20218
|
this.emit(RoomEvent.TrackSubscriptionFailed, sid, participant);
|
20149
20219
|
}).on(ParticipantEvent.TrackMuted, pub => {
|
20150
|
-
this.
|
20220
|
+
this.emitWhenConnected(RoomEvent.TrackMuted, pub, participant);
|
20151
20221
|
}).on(ParticipantEvent.TrackUnmuted, pub => {
|
20152
|
-
this.
|
20222
|
+
this.emitWhenConnected(RoomEvent.TrackUnmuted, pub, participant);
|
20153
20223
|
}).on(ParticipantEvent.ParticipantMetadataChanged, metadata => {
|
20154
|
-
this.
|
20224
|
+
this.emitWhenConnected(RoomEvent.ParticipantMetadataChanged, metadata, participant);
|
20155
20225
|
}).on(ParticipantEvent.ConnectionQualityChanged, quality => {
|
20156
|
-
this.
|
20226
|
+
this.emitWhenConnected(RoomEvent.ConnectionQualityChanged, quality, participant);
|
20157
20227
|
}).on(ParticipantEvent.ParticipantPermissionsChanged, prevPermissions => {
|
20158
|
-
this.
|
20159
|
-
});
|
20228
|
+
this.emitWhenConnected(RoomEvent.ParticipantPermissionsChanged, prevPermissions, participant);
|
20229
|
+
}); // update info at the end after callbacks have been set up
|
20230
|
+
|
20231
|
+
if (info) {
|
20232
|
+
participant.updateInfo(info);
|
20233
|
+
}
|
20234
|
+
|
20160
20235
|
return participant;
|
20161
20236
|
}
|
20162
20237
|
|
@@ -20213,21 +20288,62 @@ class Room extends events.exports.EventEmitter {
|
|
20213
20288
|
}
|
20214
20289
|
}
|
20215
20290
|
|
20216
|
-
setAndEmitConnectionState(state) {
|
20291
|
+
setAndEmitConnectionState(state, error) {
|
20217
20292
|
if (state === this.state) {
|
20218
20293
|
// unchanged
|
20219
20294
|
return false;
|
20220
20295
|
}
|
20221
20296
|
|
20297
|
+
switch (state) {
|
20298
|
+
case ConnectionState.Connecting:
|
20299
|
+
case ConnectionState.Reconnecting:
|
20300
|
+
if (!this.connectFuture) {
|
20301
|
+
// reuse existing connect future if possible
|
20302
|
+
this.connectFuture = new Future();
|
20303
|
+
}
|
20304
|
+
|
20305
|
+
break;
|
20306
|
+
|
20307
|
+
case ConnectionState.Connected:
|
20308
|
+
if (this.connectFuture) {
|
20309
|
+
this.connectFuture.resolve();
|
20310
|
+
this.connectFuture = undefined;
|
20311
|
+
}
|
20312
|
+
|
20313
|
+
break;
|
20314
|
+
|
20315
|
+
case ConnectionState.Disconnected:
|
20316
|
+
if (this.connectFuture) {
|
20317
|
+
error !== null && error !== void 0 ? error : error = new Error('disconnected from Room');
|
20318
|
+
this.connectFuture.reject(error);
|
20319
|
+
this.connectFuture = undefined;
|
20320
|
+
}
|
20321
|
+
|
20322
|
+
break;
|
20323
|
+
|
20324
|
+
}
|
20325
|
+
|
20222
20326
|
this.state = state;
|
20223
20327
|
this.emit(RoomEvent.ConnectionStateChanged, this.state);
|
20224
20328
|
return true;
|
20329
|
+
}
|
20330
|
+
|
20331
|
+
emitWhenConnected(event) {
|
20332
|
+
if (this.state === ConnectionState.Connected) {
|
20333
|
+
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
20334
|
+
args[_key - 1] = arguments[_key];
|
20335
|
+
}
|
20336
|
+
|
20337
|
+
return this.emit(event, ...args);
|
20338
|
+
}
|
20339
|
+
|
20340
|
+
return false;
|
20225
20341
|
} // /** @internal */
|
20226
20342
|
|
20227
20343
|
|
20228
20344
|
emit(event) {
|
20229
|
-
for (var
|
20230
|
-
args[
|
20345
|
+
for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
|
20346
|
+
args[_key2 - 1] = arguments[_key2];
|
20231
20347
|
}
|
20232
20348
|
|
20233
20349
|
livekitLogger.debug('room event', {
|
@@ -20336,12 +20452,12 @@ async function createLocalScreenTracks(options) {
|
|
20336
20452
|
throw new TrackInvalidError('no video track found');
|
20337
20453
|
}
|
20338
20454
|
|
20339
|
-
const screenVideo = new LocalVideoTrack(tracks[0]);
|
20455
|
+
const screenVideo = new LocalVideoTrack(tracks[0], undefined, false);
|
20340
20456
|
screenVideo.source = Track.Source.ScreenShare;
|
20341
20457
|
const localTracks = [screenVideo];
|
20342
20458
|
|
20343
20459
|
if (stream.getAudioTracks().length > 0) {
|
20344
|
-
const screenAudio = new LocalAudioTrack(stream.getAudioTracks()[0]);
|
20460
|
+
const screenAudio = new LocalAudioTrack(stream.getAudioTracks()[0], undefined, false);
|
20345
20461
|
screenAudio.source = Track.Source.ScreenShareAudio;
|
20346
20462
|
localTracks.push(screenAudio);
|
20347
20463
|
}
|