livekit-client 1.1.6 → 1.1.9

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.
Files changed (48) hide show
  1. package/README.md +1 -0
  2. package/dist/livekit-client.esm.mjs +535 -120
  3. package/dist/livekit-client.esm.mjs.map +1 -1
  4. package/dist/livekit-client.umd.js +1 -1
  5. package/dist/livekit-client.umd.js.map +1 -1
  6. package/dist/src/api/SignalClient.d.ts +2 -1
  7. package/dist/src/api/SignalClient.d.ts.map +1 -1
  8. package/dist/src/index.d.ts +4 -3
  9. package/dist/src/index.d.ts.map +1 -1
  10. package/dist/src/proto/livekit_models.d.ts +234 -0
  11. package/dist/src/proto/livekit_models.d.ts.map +1 -1
  12. package/dist/src/proto/livekit_rtc.d.ts +944 -6
  13. package/dist/src/proto/livekit_rtc.d.ts.map +1 -1
  14. package/dist/src/room/RTCEngine.d.ts +2 -2
  15. package/dist/src/room/RTCEngine.d.ts.map +1 -1
  16. package/dist/src/room/Room.d.ts +2 -2
  17. package/dist/src/room/Room.d.ts.map +1 -1
  18. package/dist/src/room/participant/LocalParticipant.d.ts +3 -1
  19. package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
  20. package/dist/src/room/participant/Participant.d.ts.map +1 -1
  21. package/dist/src/room/participant/RemoteParticipant.d.ts.map +1 -1
  22. package/dist/src/room/track/LocalAudioTrack.d.ts.map +1 -1
  23. package/dist/src/room/track/LocalTrack.d.ts +2 -0
  24. package/dist/src/room/track/LocalTrack.d.ts.map +1 -1
  25. package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -1
  26. package/dist/src/room/track/RemoteTrack.d.ts.map +1 -1
  27. package/dist/src/room/track/Track.d.ts +7 -0
  28. package/dist/src/room/track/Track.d.ts.map +1 -1
  29. package/dist/src/room/track/TrackPublication.d.ts.map +1 -1
  30. package/package.json +3 -1
  31. package/src/api/SignalClient.ts +19 -6
  32. package/src/index.ts +6 -2
  33. package/src/proto/livekit_models.ts +179 -4
  34. package/src/proto/livekit_rtc.ts +14 -1
  35. package/src/room/RTCEngine.ts +4 -2
  36. package/src/room/Room.ts +32 -9
  37. package/src/room/participant/LocalParticipant.ts +30 -2
  38. package/src/room/participant/Participant.ts +2 -0
  39. package/src/room/participant/RemoteParticipant.ts +4 -0
  40. package/src/room/track/LocalAudioTrack.ts +16 -12
  41. package/src/room/track/LocalTrack.ts +37 -25
  42. package/src/room/track/LocalVideoTrack.ts +15 -11
  43. package/src/room/track/RemoteTrack.ts +1 -0
  44. package/src/room/track/Track.ts +12 -0
  45. package/src/room/track/TrackPublication.ts +2 -0
  46. package/dist/src/api/RequestQueue.d.ts +0 -13
  47. package/dist/src/api/RequestQueue.d.ts.map +0 -1
  48. package/src/api/RequestQueue.ts +0 -53
@@ -4484,6 +4484,82 @@ function clientConfigSettingToJSON(object) {
4484
4484
  return 'UNKNOWN';
4485
4485
  }
4486
4486
  }
4487
+ var DisconnectReason;
4488
+
4489
+ (function (DisconnectReason) {
4490
+ DisconnectReason[DisconnectReason["UNKNOWN_REASON"] = 0] = "UNKNOWN_REASON";
4491
+ DisconnectReason[DisconnectReason["CLIENT_INITIATED"] = 1] = "CLIENT_INITIATED";
4492
+ DisconnectReason[DisconnectReason["DUPLICATE_IDENTITY"] = 2] = "DUPLICATE_IDENTITY";
4493
+ DisconnectReason[DisconnectReason["SERVER_SHUTDOWN"] = 3] = "SERVER_SHUTDOWN";
4494
+ DisconnectReason[DisconnectReason["PARTICIPANT_REMOVED"] = 4] = "PARTICIPANT_REMOVED";
4495
+ DisconnectReason[DisconnectReason["ROOM_DELETED"] = 5] = "ROOM_DELETED";
4496
+ DisconnectReason[DisconnectReason["STATE_MISMATCH"] = 6] = "STATE_MISMATCH";
4497
+ DisconnectReason[DisconnectReason["UNRECOGNIZED"] = -1] = "UNRECOGNIZED";
4498
+ })(DisconnectReason || (DisconnectReason = {}));
4499
+
4500
+ function disconnectReasonFromJSON(object) {
4501
+ switch (object) {
4502
+ case 0:
4503
+ case 'UNKNOWN_REASON':
4504
+ return DisconnectReason.UNKNOWN_REASON;
4505
+
4506
+ case 1:
4507
+ case 'CLIENT_INITIATED':
4508
+ return DisconnectReason.CLIENT_INITIATED;
4509
+
4510
+ case 2:
4511
+ case 'DUPLICATE_IDENTITY':
4512
+ return DisconnectReason.DUPLICATE_IDENTITY;
4513
+
4514
+ case 3:
4515
+ case 'SERVER_SHUTDOWN':
4516
+ return DisconnectReason.SERVER_SHUTDOWN;
4517
+
4518
+ case 4:
4519
+ case 'PARTICIPANT_REMOVED':
4520
+ return DisconnectReason.PARTICIPANT_REMOVED;
4521
+
4522
+ case 5:
4523
+ case 'ROOM_DELETED':
4524
+ return DisconnectReason.ROOM_DELETED;
4525
+
4526
+ case 6:
4527
+ case 'STATE_MISMATCH':
4528
+ return DisconnectReason.STATE_MISMATCH;
4529
+
4530
+ case -1:
4531
+ case 'UNRECOGNIZED':
4532
+ default:
4533
+ return DisconnectReason.UNRECOGNIZED;
4534
+ }
4535
+ }
4536
+ function disconnectReasonToJSON(object) {
4537
+ switch (object) {
4538
+ case DisconnectReason.UNKNOWN_REASON:
4539
+ return 'UNKNOWN_REASON';
4540
+
4541
+ case DisconnectReason.CLIENT_INITIATED:
4542
+ return 'CLIENT_INITIATED';
4543
+
4544
+ case DisconnectReason.DUPLICATE_IDENTITY:
4545
+ return 'DUPLICATE_IDENTITY';
4546
+
4547
+ case DisconnectReason.SERVER_SHUTDOWN:
4548
+ return 'SERVER_SHUTDOWN';
4549
+
4550
+ case DisconnectReason.PARTICIPANT_REMOVED:
4551
+ return 'PARTICIPANT_REMOVED';
4552
+
4553
+ case DisconnectReason.ROOM_DELETED:
4554
+ return 'ROOM_DELETED';
4555
+
4556
+ case DisconnectReason.STATE_MISMATCH:
4557
+ return 'STATE_MISMATCH';
4558
+
4559
+ default:
4560
+ return 'UNKNOWN';
4561
+ }
4562
+ }
4487
4563
  var ParticipantInfo_State;
4488
4564
 
4489
4565
  (function (ParticipantInfo_State) {
@@ -5204,7 +5280,8 @@ function createBaseSimulcastCodecInfo() {
5204
5280
  return {
5205
5281
  mimeType: '',
5206
5282
  mid: '',
5207
- cid: ''
5283
+ cid: '',
5284
+ layers: []
5208
5285
  };
5209
5286
  }
5210
5287
 
@@ -5224,6 +5301,10 @@ const SimulcastCodecInfo = {
5224
5301
  writer.uint32(26).string(message.cid);
5225
5302
  }
5226
5303
 
5304
+ for (const v of message.layers) {
5305
+ VideoLayer.encode(v, writer.uint32(34).fork()).ldelim();
5306
+ }
5307
+
5227
5308
  return writer;
5228
5309
  },
5229
5310
 
@@ -5248,6 +5329,10 @@ const SimulcastCodecInfo = {
5248
5329
  message.cid = reader.string();
5249
5330
  break;
5250
5331
 
5332
+ case 4:
5333
+ message.layers.push(VideoLayer.decode(reader, reader.uint32()));
5334
+ break;
5335
+
5251
5336
  default:
5252
5337
  reader.skipType(tag & 7);
5253
5338
  break;
@@ -5261,7 +5346,8 @@ const SimulcastCodecInfo = {
5261
5346
  return {
5262
5347
  mimeType: isSet$1(object.mimeType) ? String(object.mimeType) : '',
5263
5348
  mid: isSet$1(object.mid) ? String(object.mid) : '',
5264
- cid: isSet$1(object.cid) ? String(object.cid) : ''
5349
+ cid: isSet$1(object.cid) ? String(object.cid) : '',
5350
+ layers: Array.isArray(object === null || object === void 0 ? void 0 : object.layers) ? object.layers.map(e => VideoLayer.fromJSON(e)) : []
5265
5351
  };
5266
5352
  },
5267
5353
 
@@ -5270,16 +5356,24 @@ const SimulcastCodecInfo = {
5270
5356
  message.mimeType !== undefined && (obj.mimeType = message.mimeType);
5271
5357
  message.mid !== undefined && (obj.mid = message.mid);
5272
5358
  message.cid !== undefined && (obj.cid = message.cid);
5359
+
5360
+ if (message.layers) {
5361
+ obj.layers = message.layers.map(e => e ? VideoLayer.toJSON(e) : undefined);
5362
+ } else {
5363
+ obj.layers = [];
5364
+ }
5365
+
5273
5366
  return obj;
5274
5367
  },
5275
5368
 
5276
5369
  fromPartial(object) {
5277
- var _a, _b, _c;
5370
+ var _a, _b, _c, _d;
5278
5371
 
5279
5372
  const message = createBaseSimulcastCodecInfo();
5280
5373
  message.mimeType = (_a = object.mimeType) !== null && _a !== void 0 ? _a : '';
5281
5374
  message.mid = (_b = object.mid) !== null && _b !== void 0 ? _b : '';
5282
5375
  message.cid = (_c = object.cid) !== null && _c !== void 0 ? _c : '';
5376
+ message.layers = ((_d = object.layers) === null || _d === void 0 ? void 0 : _d.map(e => VideoLayer.fromPartial(e))) || [];
5283
5377
  return message;
5284
5378
  }
5285
5379
 
@@ -6179,7 +6273,8 @@ function createBaseClientConfiguration() {
6179
6273
  return {
6180
6274
  video: undefined,
6181
6275
  screen: undefined,
6182
- resumeConnection: 0
6276
+ resumeConnection: 0,
6277
+ disabledCodecs: undefined
6183
6278
  };
6184
6279
  }
6185
6280
 
@@ -6199,6 +6294,10 @@ const ClientConfiguration = {
6199
6294
  writer.uint32(24).int32(message.resumeConnection);
6200
6295
  }
6201
6296
 
6297
+ if (message.disabledCodecs !== undefined) {
6298
+ DisabledCodecs.encode(message.disabledCodecs, writer.uint32(34).fork()).ldelim();
6299
+ }
6300
+
6202
6301
  return writer;
6203
6302
  },
6204
6303
 
@@ -6223,6 +6322,10 @@ const ClientConfiguration = {
6223
6322
  message.resumeConnection = reader.int32();
6224
6323
  break;
6225
6324
 
6325
+ case 4:
6326
+ message.disabledCodecs = DisabledCodecs.decode(reader, reader.uint32());
6327
+ break;
6328
+
6226
6329
  default:
6227
6330
  reader.skipType(tag & 7);
6228
6331
  break;
@@ -6236,7 +6339,8 @@ const ClientConfiguration = {
6236
6339
  return {
6237
6340
  video: isSet$1(object.video) ? VideoConfiguration.fromJSON(object.video) : undefined,
6238
6341
  screen: isSet$1(object.screen) ? VideoConfiguration.fromJSON(object.screen) : undefined,
6239
- resumeConnection: isSet$1(object.resumeConnection) ? clientConfigSettingFromJSON(object.resumeConnection) : 0
6342
+ resumeConnection: isSet$1(object.resumeConnection) ? clientConfigSettingFromJSON(object.resumeConnection) : 0,
6343
+ disabledCodecs: isSet$1(object.disabledCodecs) ? DisabledCodecs.fromJSON(object.disabledCodecs) : undefined
6240
6344
  };
6241
6345
  },
6242
6346
 
@@ -6245,6 +6349,7 @@ const ClientConfiguration = {
6245
6349
  message.video !== undefined && (obj.video = message.video ? VideoConfiguration.toJSON(message.video) : undefined);
6246
6350
  message.screen !== undefined && (obj.screen = message.screen ? VideoConfiguration.toJSON(message.screen) : undefined);
6247
6351
  message.resumeConnection !== undefined && (obj.resumeConnection = clientConfigSettingToJSON(message.resumeConnection));
6352
+ message.disabledCodecs !== undefined && (obj.disabledCodecs = message.disabledCodecs ? DisabledCodecs.toJSON(message.disabledCodecs) : undefined);
6248
6353
  return obj;
6249
6354
  },
6250
6355
 
@@ -6255,6 +6360,7 @@ const ClientConfiguration = {
6255
6360
  message.video = object.video !== undefined && object.video !== null ? VideoConfiguration.fromPartial(object.video) : undefined;
6256
6361
  message.screen = object.screen !== undefined && object.screen !== null ? VideoConfiguration.fromPartial(object.screen) : undefined;
6257
6362
  message.resumeConnection = (_a = object.resumeConnection) !== null && _a !== void 0 ? _a : 0;
6363
+ message.disabledCodecs = object.disabledCodecs !== undefined && object.disabledCodecs !== null ? DisabledCodecs.fromPartial(object.disabledCodecs) : undefined;
6258
6364
  return message;
6259
6365
  }
6260
6366
 
@@ -6321,6 +6427,73 @@ const VideoConfiguration = {
6321
6427
 
6322
6428
  };
6323
6429
 
6430
+ function createBaseDisabledCodecs() {
6431
+ return {
6432
+ codecs: []
6433
+ };
6434
+ }
6435
+
6436
+ const DisabledCodecs = {
6437
+ encode(message) {
6438
+ let writer = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : minimal.Writer.create();
6439
+
6440
+ for (const v of message.codecs) {
6441
+ Codec.encode(v, writer.uint32(10).fork()).ldelim();
6442
+ }
6443
+
6444
+ return writer;
6445
+ },
6446
+
6447
+ decode(input, length) {
6448
+ const reader = input instanceof minimal.Reader ? input : new minimal.Reader(input);
6449
+ let end = length === undefined ? reader.len : reader.pos + length;
6450
+ const message = createBaseDisabledCodecs();
6451
+
6452
+ while (reader.pos < end) {
6453
+ const tag = reader.uint32();
6454
+
6455
+ switch (tag >>> 3) {
6456
+ case 1:
6457
+ message.codecs.push(Codec.decode(reader, reader.uint32()));
6458
+ break;
6459
+
6460
+ default:
6461
+ reader.skipType(tag & 7);
6462
+ break;
6463
+ }
6464
+ }
6465
+
6466
+ return message;
6467
+ },
6468
+
6469
+ fromJSON(object) {
6470
+ return {
6471
+ codecs: Array.isArray(object === null || object === void 0 ? void 0 : object.codecs) ? object.codecs.map(e => Codec.fromJSON(e)) : []
6472
+ };
6473
+ },
6474
+
6475
+ toJSON(message) {
6476
+ const obj = {};
6477
+
6478
+ if (message.codecs) {
6479
+ obj.codecs = message.codecs.map(e => e ? Codec.toJSON(e) : undefined);
6480
+ } else {
6481
+ obj.codecs = [];
6482
+ }
6483
+
6484
+ return obj;
6485
+ },
6486
+
6487
+ fromPartial(object) {
6488
+ var _a;
6489
+
6490
+ const message = createBaseDisabledCodecs();
6491
+ message.codecs = ((_a = object.codecs) === null || _a === void 0 ? void 0 : _a.map(e => Codec.fromPartial(e))) || [];
6492
+ return message;
6493
+ }
6494
+
6495
+ };
6496
+
6324
6497
  var globalThis$1 = (() => {
6325
6498
  if (typeof globalThis$1 !== 'undefined') return globalThis$1;
6326
6499
  if (typeof self !== 'undefined') return self;
@@ -6346,9 +6519,11 @@ const btoa = globalThis$1.btoa || (bin => globalThis$1.Buffer.from(bin, 'binary'
6346
6519
 
6347
6520
  function base64FromBytes(arr) {
6348
6521
  const bin = [];
6349
- arr.forEach(byte => {
6522
+
6523
+ for (const byte of arr) {
6350
6524
  bin.push(String.fromCharCode(byte));
6351
- });
6525
+ }
6526
+
6352
6527
  return btoa(bin.join(''));
6353
6528
  }
6354
6529
 
@@ -8033,7 +8208,8 @@ const UpdateTrackSettings = {
8033
8208
 
8034
8209
  function createBaseLeaveRequest() {
8035
8210
  return {
8036
- canReconnect: false
8211
+ canReconnect: false,
8212
+ reason: 0
8037
8213
  };
8038
8214
  }
8039
8215
 
@@ -8045,6 +8221,10 @@ const LeaveRequest = {
8045
8221
  writer.uint32(8).bool(message.canReconnect);
8046
8222
  }
8047
8223
 
8224
+ if (message.reason !== 0) {
8225
+ writer.uint32(16).int32(message.reason);
8226
+ }
8227
+
8048
8228
  return writer;
8049
8229
  },
8050
8230
 
@@ -8061,6 +8241,10 @@ const LeaveRequest = {
8061
8241
  message.canReconnect = reader.bool();
8062
8242
  break;
8063
8243
 
8244
+ case 2:
8245
+ message.reason = reader.int32();
8246
+ break;
8247
+
8064
8248
  default:
8065
8249
  reader.skipType(tag & 7);
8066
8250
  break;
@@ -8072,21 +8256,24 @@ const LeaveRequest = {
8072
8256
 
8073
8257
  fromJSON(object) {
8074
8258
  return {
8075
- canReconnect: isSet(object.canReconnect) ? Boolean(object.canReconnect) : false
8259
+ canReconnect: isSet(object.canReconnect) ? Boolean(object.canReconnect) : false,
8260
+ reason: isSet(object.reason) ? disconnectReasonFromJSON(object.reason) : 0
8076
8261
  };
8077
8262
  },
8078
8263
 
8079
8264
  toJSON(message) {
8080
8265
  const obj = {};
8081
8266
  message.canReconnect !== undefined && (obj.canReconnect = message.canReconnect);
8267
+ message.reason !== undefined && (obj.reason = disconnectReasonToJSON(message.reason));
8082
8268
  return obj;
8083
8269
  },
8084
8270
 
8085
8271
  fromPartial(object) {
8086
- var _a;
8272
+ var _a, _b;
8087
8273
 
8088
8274
  const message = createBaseLeaveRequest();
8089
8275
  message.canReconnect = (_a = object.canReconnect) !== null && _a !== void 0 ? _a : false;
8276
+ message.reason = (_b = object.reason) !== null && _b !== void 0 ? _b : 0;
8090
8277
  return message;
8091
8278
  }
8092
8279
 
@@ -10070,7 +10257,7 @@ function computeBitrate(currentStats, prevStats) {
10070
10257
  return (bytesNow - bytesPrev) * 8 * 1000 / (currentStats.timestamp - prevStats.timestamp);
10071
10258
  }
10072
10259
 
10073
- var version$1 = "1.1.6";
10260
+ var version$1 = "1.1.9";
10074
10261
 
10075
10262
  const version = version$1;
10076
10263
  const protocolVersion = 8;
@@ -10190,6 +10377,178 @@ class Future {
10190
10377
 
10191
10378
  }
10192
10379
 
10380
+ class Queue {
10381
+ /**
10382
+ * @class Queue
10383
+ *
10384
+ * Priority queue with rate limiting<br>
10385
+ * See the medium article:<br>
10386
+ * https://mmomtchev.medium.com/parallelizing-download-loops-in-js-with-async-await-queue-670420880cd6
10387
+ *
10388
+ * @param {number} [_maxConcurrent=1] Number of tasks allowed to run simultaneously
10389
+ * @param {number} [_minCycle=0] Minimum number of milliseconds between two consecutive tasks
10390
+ */
10391
+ constructor(_maxConcurrent, _minCycle) {
10392
+ this.maxConcurrent = _maxConcurrent || 1;
10393
+ this.minCycle = _minCycle || 0;
10394
+ this.queueRunning = [];
10395
+ this.queueWaiting = {};
10396
+ this.lastRun = 0;
10397
+ }
10398
+ /** @private */
10399
+
10400
+
10401
+ dequeue(hash) {
10402
+ const q = this.queueRunning;
10403
+ const idx = q.findIndex(x => x.hash === hash);
10404
+ if (idx == -1) throw 'queue desync';
10405
+ const o = q[idx];
10406
+ q.splice(idx, 1);
10407
+ return o;
10408
+ }
10409
+ /** @private */
10410
+
10411
+
10412
+ getFirstWaiting() {
10413
+ for (let p of Object.keys(this.queueWaiting).sort((a, b) => a - b)) if (this.queueWaiting[p] !== undefined && this.queueWaiting[p].length > 0) return this.queueWaiting[p];
10414
+
10415
+ return undefined;
10416
+ }
10417
+ /**
10418
+ * Signal that the task `hash` has finished.<br>
10419
+ * Frees its slot in the queue
10420
+ *
10421
+ * @method end
10422
+ * @param {any} hash Unique hash identifying the task, Symbol() works very well
10423
+ */
10424
+
10425
+
10426
+ end(hash) {
10427
+ const me = this.dequeue(hash);
10428
+ me.resolve();
10429
+ /* Choose the next task to run and unblock its promise */
10430
+
10431
+ const q = this.getFirstWaiting();
10432
+
10433
+ if (q !== undefined) {
10434
+ const next = q.shift();
10435
+ next.resolve();
10436
+ }
10437
+ }
10438
+ /**
10439
+ * Wait for a slot in the queue
10440
+ *
10441
+ * @method wait
10442
+ * @param {any} hash Unique hash identifying the task
10443
+ * @param {number} [priority=0] Optional priority, -1 is higher priority than 1
10444
+ * @return {Promise<void>} Resolved when the task is ready to run
10445
+ */
10446
+
10447
+
10448
+ async wait(hash, _priority) {
10449
+ const priority = _priority === undefined ? 0 : _priority;
10450
+ /* Us on the queue */
10451
+
10452
+ let me = {
10453
+ hash,
10454
+ priority
10455
+ };
10456
+ /* Create priorities on the fly */
10457
+
10458
+ if (this.queueWaiting[priority] == undefined) this.queueWaiting[priority] = [];
10459
+ /* Are we allowed to run? */
10460
+
10461
+ if (this.queueRunning.length >= this.maxConcurrent) {
10462
+ /* This promise will be unlocked from the outside */
10463
+
10464
+ /* and it cannot reject */
10465
+ me.promise = new Promise(resolve => {
10466
+ me.resolve = resolve;
10467
+ });
10468
+ /* Get in the line */
10469
+
10470
+ this.queueWaiting[priority].push(me);
10471
+ await me.promise;
10472
+ }
10473
+
10474
+ this.queueRunning.push(me);
10475
+ me.promise = new Promise(resolve => {
10476
+ me.resolve = resolve;
10477
+ });
10478
+ /* Wait if it is too soon */
10479
+
10480
+ while (Date.now() - this.lastRun < this.minCycle) {
10481
+ await new Promise(resolve => setTimeout(resolve, this.minCycle - Date.now() + this.lastRun));
10482
+ }
10483
+
10484
+ this.lastRun = Date.now();
10485
+ }
10486
+ /**
10487
+ * Run a job (equivalent to calling Queue.wait(), fn() and then Queue.end())<br>
10488
+ * fn can be both synchronous or asynchronous function
10489
+ *
10490
+ * @method run
10491
+ * @param {Function} fn The job
10492
+ * @param {number} [priority=0] Optional priority, -1 is higher priority than 1
10493
+ * @return {Promise<any>} Resolved when the task has finished with the return value of fn
10494
+ */
10495
+
10496
+
10497
+ run(job, _priority) {
10498
+ const priority = _priority === undefined ? 0 : _priority;
10499
+ const id = Symbol();
10500
+ return this.wait(id, priority).then(() => job()).finally(() => {
10501
+ this.end(id);
10502
+ });
10503
+ }
10504
+ /**
10505
+ * @interface QueueStats {running: number, waiting: number, last: number}
10506
+ */
10507
+
10508
+ /**
10509
+ * Return the number of running and waiting jobs
10510
+ *
10511
+ * @method stat
10512
+ * @return {QueueStats} running, waiting, last
10513
+ */
10514
+
10515
+
10516
+ stat() {
10517
+ return {
10518
+ running: this.queueRunning.length,
10519
+ waiting: Object.keys(this.queueWaiting).reduce((t, x) => t += this.queueWaiting[x].length, 0),
10520
+ last: this.lastRun
10521
+ };
10522
+ }
10523
+ /**
10524
+ * Returns a promise that resolves when the queue is empty
10525
+ *
10526
+ * @method flush
10527
+ * @return {Promise<void>}
10528
+ */
10529
+
10530
+
10531
+ async flush() {
10532
+ /* Aways wait on the lowest priority in the queue */
10533
+ while (this.stat().waiting > 0) {
10534
+ for (let p of Object.keys(this.queueWaiting).sort((a, b) => b - a)) {
10535
+ const qp = this.queueWaiting[p];
10536
+
10537
+ if (qp !== undefined && qp.length > 0) {
10538
+ await qp[qp.length - 1].promise;
10539
+ }
10540
+ }
10541
+ }
10542
+ /* And then finish on the running queue */
10543
+
10544
+
10545
+ while (this.queueRunning.length > 0) {
10546
+ await Promise.allSettled(this.queueRunning.map(x => x.promise));
10547
+ }
10548
+ }
10549
+
10550
+ }
10551
+
10193
10552
  const defaultId = 'default';
10194
10553
  class DeviceManager {
10195
10554
  static getInstance() {
@@ -10742,6 +11101,7 @@ class Track extends events.exports.EventEmitter {
10742
11101
 
10743
11102
  this.kind = kind;
10744
11103
  this._mediaStreamTrack = mediaTrack;
11104
+ this._mediaStreamID = mediaTrack.id;
10745
11105
  this.source = Track.Source.Unknown;
10746
11106
 
10747
11107
  if (isWeb()) {
@@ -10761,6 +11121,16 @@ class Track extends events.exports.EventEmitter {
10761
11121
  get mediaStreamTrack() {
10762
11122
  return this._mediaStreamTrack;
10763
11123
  }
11124
+ /**
11125
+ * @internal
11126
+ * used for keep mediaStream's first id, since it's id might change
11127
+ * if we disable/enable a track
11128
+ */
11129
+
11130
+
11131
+ get mediaStreamID() {
11132
+ return this._mediaStreamID;
11133
+ }
10764
11134
 
10765
11135
  attach(element) {
10766
11136
  let elementType = 'audio';
@@ -11087,6 +11457,7 @@ class LocalTrack extends Track {
11087
11457
  this.reacquireTrack = false;
11088
11458
  this.wasMuted = false;
11089
11459
  this.providedByUser = userProvidedTrack;
11460
+ this.muteQueue = new Queue();
11090
11461
  }
11091
11462
 
11092
11463
  get id() {
@@ -11167,7 +11538,9 @@ class LocalTrack extends Track {
11167
11538
  // 'A MediaStreamTrack ended due to a capture failure`
11168
11539
 
11169
11540
 
11170
- this._mediaStreamTrack.stop();
11541
+ if (!this.providedByUser) {
11542
+ this._mediaStreamTrack.stop();
11543
+ }
11171
11544
 
11172
11545
  track.addEventListener('ended', this.handleEnded);
11173
11546
  livekitLogger.debug('replace MediaStreamTrack');
@@ -11235,6 +11608,8 @@ class LocalTrack extends Track {
11235
11608
  }
11236
11609
 
11237
11610
  setTrackMuted(muted) {
11611
+ livekitLogger.debug("setting ".concat(this.kind, " track ").concat(muted ? 'muted' : 'unmuted'));
11612
+
11238
11613
  if (this.isMuted === muted) {
11239
11614
  return;
11240
11615
  }
@@ -11268,34 +11643,38 @@ class LocalTrack extends Track {
11268
11643
  }
11269
11644
 
11270
11645
  async pauseUpstream() {
11271
- if (this._isUpstreamPaused === true) {
11272
- return;
11273
- }
11646
+ this.muteQueue.run(async () => {
11647
+ if (this._isUpstreamPaused === true) {
11648
+ return;
11649
+ }
11274
11650
 
11275
- if (!this.sender) {
11276
- livekitLogger.warn('unable to pause upstream for an unpublished track');
11277
- return;
11278
- }
11651
+ if (!this.sender) {
11652
+ livekitLogger.warn('unable to pause upstream for an unpublished track');
11653
+ return;
11654
+ }
11279
11655
 
11280
- this._isUpstreamPaused = true;
11281
- this.emit(TrackEvent.UpstreamPaused, this);
11282
- const emptyTrack = this.kind === Track.Kind.Audio ? getEmptyAudioStreamTrack() : getEmptyVideoStreamTrack();
11283
- await this.sender.replaceTrack(emptyTrack);
11656
+ this._isUpstreamPaused = true;
11657
+ this.emit(TrackEvent.UpstreamPaused, this);
11658
+ const emptyTrack = this.kind === Track.Kind.Audio ? getEmptyAudioStreamTrack() : getEmptyVideoStreamTrack();
11659
+ await this.sender.replaceTrack(emptyTrack);
11660
+ });
11284
11661
  }
11285
11662
 
11286
11663
  async resumeUpstream() {
11287
- if (this._isUpstreamPaused === false) {
11288
- return;
11289
- }
11664
+ this.muteQueue.run(async () => {
11665
+ if (this._isUpstreamPaused === false) {
11666
+ return;
11667
+ }
11290
11668
 
11291
- if (!this.sender) {
11292
- livekitLogger.warn('unable to resume upstream for an unpublished track');
11293
- return;
11294
- }
11669
+ if (!this.sender) {
11670
+ livekitLogger.warn('unable to resume upstream for an unpublished track');
11671
+ return;
11672
+ }
11295
11673
 
11296
- this._isUpstreamPaused = false;
11297
- this.emit(TrackEvent.UpstreamResumed, this);
11298
- await this.sender.replaceTrack(this._mediaStreamTrack);
11674
+ this._isUpstreamPaused = false;
11675
+ this.emit(TrackEvent.UpstreamResumed, this);
11676
+ await this.sender.replaceTrack(this._mediaStreamTrack);
11677
+ });
11299
11678
  }
11300
11679
 
11301
11680
  }
@@ -11453,24 +11832,28 @@ class LocalAudioTrack extends LocalTrack {
11453
11832
  }
11454
11833
 
11455
11834
  async mute() {
11456
- // disabled special handling as it will cause BT headsets to switch communication modes
11457
- if (this.source === Track.Source.Microphone && this.stopOnMute) {
11458
- livekitLogger.debug('stopping mic track'); // also stop the track, so that microphone indicator is turned off
11835
+ await this.muteQueue.run(async () => {
11836
+ // disabled special handling as it will cause BT headsets to switch communication modes
11837
+ if (this.source === Track.Source.Microphone && this.stopOnMute && !this.isUserProvided) {
11838
+ livekitLogger.debug('stopping mic track'); // also stop the track, so that microphone indicator is turned off
11459
11839
 
11460
- this._mediaStreamTrack.stop();
11461
- }
11840
+ this._mediaStreamTrack.stop();
11841
+ }
11462
11842
 
11463
- await super.mute();
11843
+ await super.mute();
11844
+ });
11464
11845
  return this;
11465
11846
  }
11466
11847
 
11467
11848
  async unmute() {
11468
- if (this.source === Track.Source.Microphone && this.stopOnMute && !this.isUserProvided) {
11469
- livekitLogger.debug('reacquiring mic track');
11470
- await this.restartTrack();
11471
- }
11849
+ await this.muteQueue.run(async () => {
11850
+ if (this.source === Track.Source.Microphone && this.stopOnMute && !this.isUserProvided) {
11851
+ livekitLogger.debug('reacquiring mic track');
11852
+ await this.restartTrack();
11853
+ }
11472
11854
 
11473
- await super.unmute();
11855
+ await super.unmute();
11856
+ });
11474
11857
  return this;
11475
11858
  }
11476
11859
 
@@ -11636,23 +12019,27 @@ class LocalVideoTrack extends LocalTrack {
11636
12019
  }
11637
12020
 
11638
12021
  async mute() {
11639
- if (this.source === Track.Source.Camera) {
11640
- livekitLogger.debug('stopping camera track'); // also stop the track, so that camera indicator is turned off
12022
+ await this.muteQueue.run(async () => {
12023
+ if (this.source === Track.Source.Camera && !this.isUserProvided) {
12024
+ livekitLogger.debug('stopping camera track'); // also stop the track, so that camera indicator is turned off
11641
12025
 
11642
- this._mediaStreamTrack.stop();
11643
- }
12026
+ this._mediaStreamTrack.stop();
12027
+ }
11644
12028
 
11645
- await super.mute();
12029
+ await super.mute();
12030
+ });
11646
12031
  return this;
11647
12032
  }
11648
12033
 
11649
12034
  async unmute() {
11650
- if (this.source === Track.Source.Camera && !this.isUserProvided) {
11651
- livekitLogger.debug('reacquiring camera track');
11652
- await this.restartTrack();
11653
- }
12035
+ await this.muteQueue.run(async () => {
12036
+ if (this.source === Track.Source.Camera && !this.isUserProvided) {
12037
+ livekitLogger.debug('reacquiring camera track');
12038
+ await this.restartTrack();
12039
+ }
11654
12040
 
11655
- await super.unmute();
12041
+ await super.unmute();
12042
+ });
11656
12043
  return this;
11657
12044
  }
11658
12045
 
@@ -11969,6 +12356,7 @@ class RemoteTrack extends Track {
11969
12356
  setMuted(muted) {
11970
12357
  if (this.isMuted !== muted) {
11971
12358
  this.isMuted = muted;
12359
+ this._mediaStreamTrack.enabled = !muted;
11972
12360
  this.emit(muted ? TrackEvent.Muted : TrackEvent.Unmuted, this);
11973
12361
  }
11974
12362
  }
@@ -12553,6 +12941,9 @@ class TrackPublication extends events.exports.EventEmitter {
12553
12941
  }
12554
12942
 
12555
12943
  this.trackInfo = info;
12944
+ livekitLogger.trace('update publication info', {
12945
+ info
12946
+ });
12556
12947
  }
12557
12948
 
12558
12949
  }
@@ -12875,6 +13266,9 @@ class Participant extends events.exports.EventEmitter {
12875
13266
 
12876
13267
 
12877
13268
  this.participantInfo = info;
13269
+ livekitLogger.trace('update participant info', {
13270
+ info
13271
+ });
12878
13272
  }
12879
13273
  /** @internal */
12880
13274
 
@@ -13619,6 +14013,10 @@ class RemoteParticipant extends Participant {
13619
14013
 
13620
14014
  this.tracks.forEach(publication => {
13621
14015
  if (!validTracks.has(publication.trackSid)) {
14016
+ livekitLogger.trace('detected removed track on remote participant, unpublishing', {
14017
+ publication,
14018
+ participantSid: this.sid
14019
+ });
13622
14020
  this.unpublishTrack(publication.trackSid, true);
13623
14021
  }
13624
14022
  });
@@ -14500,6 +14898,32 @@ class LocalParticipant extends Participant {
14500
14898
  this.updateTrackSubscriptionPermissions();
14501
14899
  }
14502
14900
  }
14901
+ /** @internal */
14902
+
14903
+
14904
+ updateInfo(info) {
14905
+ super.updateInfo(info); // reconcile track mute status.
14906
+ // if server's track mute status doesn't match actual, we'll have to update
14907
+ // the server's copy
14908
+
14909
+ info.tracks.forEach(ti => {
14910
+ var _a, _b;
14911
+
14912
+ const pub = this.tracks.get(ti.sid);
14913
+
14914
+ if (pub) {
14915
+ const mutedOnServer = pub.isMuted || ((_b = (_a = pub.track) === null || _a === void 0 ? void 0 : _a.isUpstreamPaused) !== null && _b !== void 0 ? _b : false);
14916
+
14917
+ if (mutedOnServer !== ti.muted) {
14918
+ livekitLogger.debug('updating server mute state after reconcile', {
14919
+ sid: ti.sid,
14920
+ muted: mutedOnServer
14921
+ });
14922
+ this.engine.client.sendMuteTrack(ti.sid, mutedOnServer);
14923
+ }
14924
+ }
14925
+ });
14926
+ }
14503
14927
 
14504
14928
  getPublicationForTrack(track) {
14505
14929
  let publication;
@@ -14577,7 +15001,7 @@ class LocalParticipant extends Participant {
14577
15001
  this.tracks.forEach(track => {
14578
15002
  if (track.track !== undefined) {
14579
15003
  infos.push({
14580
- cid: track.track.mediaStreamTrack.id,
15004
+ cid: track.track.mediaStreamID,
14581
15005
  track: track.trackInfo
14582
15006
  });
14583
15007
  }
@@ -18094,57 +18518,6 @@ adapterFactory({
18094
18518
  window: typeof window === 'undefined' ? undefined : window
18095
18519
  });
18096
18520
 
18097
- class Queue {
18098
- constructor() {
18099
- this.queue = [];
18100
- this.running = false;
18101
- }
18102
-
18103
- enqueue(cb) {
18104
- livekitLogger.trace('enqueuing request to fire later');
18105
- this.queue.push(cb);
18106
- }
18107
-
18108
- dequeue() {
18109
- const evt = this.queue.shift();
18110
- if (evt) evt();
18111
- livekitLogger.trace('firing request from queue');
18112
- }
18113
-
18114
- async run() {
18115
- if (this.running) return;
18116
- livekitLogger.trace('start queue');
18117
- this.running = true;
18118
-
18119
- while (this.running && this.queue.length > 0) {
18120
- this.dequeue();
18121
- }
18122
-
18123
- this.running = false;
18124
- livekitLogger.trace('queue finished');
18125
- }
18126
-
18127
- pause() {
18128
- livekitLogger.trace('pausing queue');
18129
- this.running = false;
18130
- }
18131
-
18132
- reset() {
18133
- livekitLogger.trace('resetting queue');
18134
- this.running = false;
18135
- this.queue = [];
18136
- }
18137
-
18138
- isRunning() {
18139
- return this.running;
18140
- }
18141
-
18142
- isEmpty() {
18143
- return this.queue.length === 0;
18144
- }
18145
-
18146
- }
18147
-
18148
18521
  const passThroughQueueSignals = ['syncState', 'trickle', 'offer', 'answer', 'simulate', 'leave'];
18149
18522
 
18150
18523
  function canPassThroughQueue(req) {
@@ -18165,6 +18538,7 @@ class SignalClient {
18165
18538
  this.isReconnecting = false;
18166
18539
  this.useJSON = useJSON;
18167
18540
  this.requestQueue = new Queue();
18541
+ this.queuedRequests = [];
18168
18542
  }
18169
18543
 
18170
18544
  async join(url, token, opts, abortSignal) {
@@ -18392,14 +18766,20 @@ class SignalClient {
18392
18766
 
18393
18767
  async sendRequest(req) {
18394
18768
  let fromQueue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
18395
- // capture all requests while reconnecting and put them in a queue.
18396
- // keep order by queueing up new events as long as the queue is not empty
18769
+ // capture all requests while reconnecting and put them in a queue
18397
18770
  // unless the request originates from the queue, then don't enqueue again
18398
18771
  const canQueue = !fromQueue && !canPassThroughQueue(req);
18399
18772
 
18400
- if (canQueue && (this.isReconnecting || !this.requestQueue.isEmpty())) {
18401
- this.requestQueue.enqueue(() => this.sendRequest(req, true));
18773
+ if (canQueue && this.isReconnecting) {
18774
+ this.queuedRequests.push(async () => {
18775
+ await this.sendRequest(req, true);
18776
+ });
18402
18777
  return;
18778
+ } // make sure previously queued requests are being sent first
18779
+
18780
+
18781
+ if (!fromQueue) {
18782
+ await this.requestQueue.flush();
18403
18783
  }
18404
18784
 
18405
18785
  if (this.signalLatency) {
@@ -18497,8 +18877,15 @@ class SignalClient {
18497
18877
  }
18498
18878
 
18499
18879
  setReconnected() {
18880
+ while (this.queuedRequests.length > 0) {
18881
+ const req = this.queuedRequests.shift();
18882
+
18883
+ if (req) {
18884
+ this.requestQueue.run(req);
18885
+ }
18886
+ }
18887
+
18500
18888
  this.isReconnecting = false;
18501
- this.requestQueue.run();
18502
18889
  }
18503
18890
 
18504
18891
  handleWSError(ev) {
@@ -19126,9 +19513,13 @@ class RTCEngine extends events.exports.EventEmitter {
19126
19513
  this.fullReconnectOnNext = true;
19127
19514
  this.primaryPC = undefined;
19128
19515
  } else {
19129
- this.emit(EngineEvent.Disconnected);
19516
+ this.emit(EngineEvent.Disconnected, leave === null || leave === void 0 ? void 0 : leave.reason);
19130
19517
  this.close();
19131
19518
  }
19519
+
19520
+ livekitLogger.trace('leave request', {
19521
+ leave
19522
+ });
19132
19523
  };
19133
19524
  }
19134
19525
 
@@ -19511,7 +19902,14 @@ class Room extends events.exports.EventEmitter {
19511
19902
  }); // populate remote participants, these should not trigger new events
19512
19903
 
19513
19904
  joinResponse.otherParticipants.forEach(info => {
19514
- this.getOrCreateParticipant(info.sid, info);
19905
+ if (info.sid !== this.localParticipant.sid && info.identity !== this.localParticipant.identity) {
19906
+ this.getOrCreateParticipant(info.sid, info);
19907
+ } else {
19908
+ livekitLogger.warn('received info to create local participant as remote participant', {
19909
+ info,
19910
+ localParticipant: this.localParticipant
19911
+ });
19912
+ }
19515
19913
  });
19516
19914
  this.name = joinResponse.room.name;
19517
19915
  this.sid = joinResponse.room.sid;
@@ -19867,8 +20265,8 @@ class Room extends events.exports.EventEmitter {
19867
20265
  this.engine.client.onConnectionQuality = this.handleConnectionQualityUpdate;
19868
20266
  this.engine.on(EngineEvent.MediaTrackAdded, (mediaTrack, stream, receiver) => {
19869
20267
  this.onTrackAdded(mediaTrack, stream, receiver);
19870
- }).on(EngineEvent.Disconnected, () => {
19871
- this.handleDisconnect();
20268
+ }).on(EngineEvent.Disconnected, reason => {
20269
+ this.handleDisconnect(this.options.stopLocalTrackOnUnpublish, reason);
19872
20270
  }).on(EngineEvent.ActiveSpeakersUpdate, this.handleActiveSpeakersUpdate).on(EngineEvent.DataPacketReceived, this.handleDataPacket).on(EngineEvent.Resuming, () => {
19873
20271
  if (this.setAndEmitConnectionState(ConnectionState.Reconnecting)) {
19874
20272
  this.emit(RoomEvent.Reconnecting);
@@ -19930,6 +20328,15 @@ class Room extends events.exports.EventEmitter {
19930
20328
  let req;
19931
20329
 
19932
20330
  switch (scenario) {
20331
+ case 'signal-reconnect':
20332
+ this.engine.client.close();
20333
+
20334
+ if (this.engine.client.onClose) {
20335
+ this.engine.client.onClose('simulate disconnect');
20336
+ }
20337
+
20338
+ break;
20339
+
19933
20340
  case 'speaker':
19934
20341
  req = SimulateScenario.fromPartial({
19935
20342
  speakerUpdate: 3
@@ -20079,21 +20486,28 @@ class Room extends events.exports.EventEmitter {
20079
20486
  // at that time, ICE connectivity has not been established so the track is not
20080
20487
  // technically subscribed.
20081
20488
  // We'll defer these events until when the room is connected or eventually disconnected.
20082
- if (this.state === ConnectionState.Connecting || this.state === ConnectionState.Reconnecting) {
20083
- setTimeout(() => {
20489
+ if (this.connectFuture) {
20490
+ this.connectFuture.promise.then(() => {
20084
20491
  this.onTrackAdded(mediaTrack, stream, receiver);
20085
- }, 50);
20492
+ });
20086
20493
  return;
20087
20494
  }
20088
20495
 
20089
20496
  if (this.state === ConnectionState.Disconnected) {
20090
20497
  livekitLogger.warn('skipping incoming track after Room disconnected');
20498
+ return;
20091
20499
  }
20092
20500
 
20093
20501
  const parts = unpackStreamId(stream.id);
20094
20502
  const participantId = parts[0];
20095
20503
  let trackId = parts[1];
20096
20504
  if (!trackId || trackId === '') trackId = mediaTrack.id;
20505
+
20506
+ if (participantId === this.localParticipant.sid) {
20507
+ livekitLogger.warn('tried to create RemoteParticipant for local participant');
20508
+ return;
20509
+ }
20510
+
20097
20511
  const participant = this.getOrCreateParticipant(participantId);
20098
20512
  let adaptiveStreamSettings;
20099
20513
 
@@ -20110,6 +20524,7 @@ class Room extends events.exports.EventEmitter {
20110
20524
 
20111
20525
  handleDisconnect() {
20112
20526
  let shouldStopTracks = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
20527
+ let reason = arguments.length > 1 ? arguments[1] : undefined;
20113
20528
 
20114
20529
  var _a;
20115
20530
 
@@ -20144,7 +20559,7 @@ class Room extends events.exports.EventEmitter {
20144
20559
  }
20145
20560
 
20146
20561
  this.setAndEmitConnectionState(ConnectionState.Disconnected);
20147
- this.emit(RoomEvent.Disconnected);
20562
+ this.emit(RoomEvent.Disconnected, reason);
20148
20563
  }
20149
20564
 
20150
20565
  handleParticipantDisconnected(sid, participant) {
@@ -20470,5 +20885,5 @@ async function createLocalScreenTracks(options) {
20470
20885
  return localTracks;
20471
20886
  }
20472
20887
 
20473
- export { AudioPresets, ConnectionError, ConnectionQuality, ConnectionState, DataPacket_Kind, EngineEvent, LivekitError, LocalAudioTrack, LocalParticipant, LocalTrack, LocalTrackPublication, LocalVideoTrack, LogLevel, MediaDeviceFailure, Participant, ParticipantEvent, PublishDataError, RemoteAudioTrack, RemoteParticipant, RemoteTrack, RemoteTrackPublication, RemoteVideoTrack, Room, RoomEvent, RoomState, ScreenSharePresets, Track, TrackEvent, TrackInvalidError, TrackPublication, UnexpectedConnectionState, UnsupportedServer, VideoPreset, VideoPresets, VideoPresets43, VideoQuality, attachToElement, createLocalAudioTrack, createLocalScreenTracks, createLocalTracks, createLocalVideoTrack, detachTrack, protocolVersion, setLogExtension, setLogLevel, version };
20888
+ export { AudioPresets, ConnectionError, ConnectionQuality, ConnectionState, DataPacket_Kind, DisconnectReason, EngineEvent, LivekitError, LocalAudioTrack, LocalParticipant, LocalTrack, LocalTrackPublication, LocalVideoTrack, LogLevel, MediaDeviceFailure, Participant, ParticipantEvent, PublishDataError, RemoteAudioTrack, RemoteParticipant, RemoteTrack, RemoteTrackPublication, RemoteVideoTrack, Room, RoomEvent, RoomState, ScreenSharePresets, Track, TrackEvent, TrackInvalidError, TrackPublication, UnexpectedConnectionState, UnsupportedServer, VideoPreset, VideoPresets, VideoPresets43, VideoQuality, attachToElement, createLocalAudioTrack, createLocalScreenTracks, createLocalTracks, createLocalVideoTrack, detachTrack, getEmptyAudioStreamTrack, getEmptyVideoStreamTrack, protocolVersion, setLogExtension, setLogLevel, version };
20474
20889
  //# sourceMappingURL=livekit-client.esm.mjs.map