livekit-client 2.5.2 → 2.5.4

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.
@@ -3397,6 +3397,218 @@ target => {
3397
3397
  }
3398
3398
  });
3399
3399
 
3400
+ // Copyright 2021-2024 Buf Technologies, Inc.
3401
+ //
3402
+ // Licensed under the Apache License, Version 2.0 (the "License");
3403
+ // you may not use this file except in compliance with the License.
3404
+ // You may obtain a copy of the License at
3405
+ //
3406
+ // http://www.apache.org/licenses/LICENSE-2.0
3407
+ //
3408
+ // Unless required by applicable law or agreed to in writing, software
3409
+ // distributed under the License is distributed on an "AS IS" BASIS,
3410
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3411
+ // See the License for the specific language governing permissions and
3412
+ // limitations under the License.
3413
+ /**
3414
+ * A Timestamp represents a point in time independent of any time zone or local
3415
+ * calendar, encoded as a count of seconds and fractions of seconds at
3416
+ * nanosecond resolution. The count is relative to an epoch at UTC midnight on
3417
+ * January 1, 1970, in the proleptic Gregorian calendar which extends the
3418
+ * Gregorian calendar backwards to year one.
3419
+ *
3420
+ * All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap
3421
+ * second table is needed for interpretation, using a [24-hour linear
3422
+ * smear](https://developers.google.com/time/smear).
3423
+ *
3424
+ * The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By
3425
+ * restricting to that range, we ensure that we can convert to and from [RFC
3426
+ * 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings.
3427
+ *
3428
+ * # Examples
3429
+ *
3430
+ * Example 1: Compute Timestamp from POSIX `time()`.
3431
+ *
3432
+ * Timestamp timestamp;
3433
+ * timestamp.set_seconds(time(NULL));
3434
+ * timestamp.set_nanos(0);
3435
+ *
3436
+ * Example 2: Compute Timestamp from POSIX `gettimeofday()`.
3437
+ *
3438
+ * struct timeval tv;
3439
+ * gettimeofday(&tv, NULL);
3440
+ *
3441
+ * Timestamp timestamp;
3442
+ * timestamp.set_seconds(tv.tv_sec);
3443
+ * timestamp.set_nanos(tv.tv_usec * 1000);
3444
+ *
3445
+ * Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.
3446
+ *
3447
+ * FILETIME ft;
3448
+ * GetSystemTimeAsFileTime(&ft);
3449
+ * UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
3450
+ *
3451
+ * // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z
3452
+ * // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.
3453
+ * Timestamp timestamp;
3454
+ * timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
3455
+ * timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
3456
+ *
3457
+ * Example 4: Compute Timestamp from Java `System.currentTimeMillis()`.
3458
+ *
3459
+ * long millis = System.currentTimeMillis();
3460
+ *
3461
+ * Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
3462
+ * .setNanos((int) ((millis % 1000) * 1000000)).build();
3463
+ *
3464
+ * Example 5: Compute Timestamp from Java `Instant.now()`.
3465
+ *
3466
+ * Instant now = Instant.now();
3467
+ *
3468
+ * Timestamp timestamp =
3469
+ * Timestamp.newBuilder().setSeconds(now.getEpochSecond())
3470
+ * .setNanos(now.getNano()).build();
3471
+ *
3472
+ * Example 6: Compute Timestamp from current time in Python.
3473
+ *
3474
+ * timestamp = Timestamp()
3475
+ * timestamp.GetCurrentTime()
3476
+ *
3477
+ * # JSON Mapping
3478
+ *
3479
+ * In JSON format, the Timestamp type is encoded as a string in the
3480
+ * [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the
3481
+ * format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z"
3482
+ * where {year} is always expressed using four digits while {month}, {day},
3483
+ * {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional
3484
+ * seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution),
3485
+ * are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone
3486
+ * is required. A proto3 JSON serializer should always use UTC (as indicated by
3487
+ * "Z") when printing the Timestamp type and a proto3 JSON parser should be
3488
+ * able to accept both UTC and other timezones (as indicated by an offset).
3489
+ *
3490
+ * For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past
3491
+ * 01:30 UTC on January 15, 2017.
3492
+ *
3493
+ * In JavaScript, one can convert a Date object to this format using the
3494
+ * standard
3495
+ * [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString)
3496
+ * method. In Python, a standard `datetime.datetime` object can be converted
3497
+ * to this format using
3498
+ * [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with
3499
+ * the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use
3500
+ * the Joda Time's [`ISODateTimeFormat.dateTime()`](
3501
+ * http://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime()
3502
+ * ) to obtain a formatter capable of generating timestamps in this format.
3503
+ *
3504
+ *
3505
+ * @generated from message google.protobuf.Timestamp
3506
+ */
3507
+ class Timestamp extends Message {
3508
+ constructor(data) {
3509
+ super();
3510
+ /**
3511
+ * Represents seconds of UTC time since Unix epoch
3512
+ * 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
3513
+ * 9999-12-31T23:59:59Z inclusive.
3514
+ *
3515
+ * @generated from field: int64 seconds = 1;
3516
+ */
3517
+ this.seconds = protoInt64.zero;
3518
+ /**
3519
+ * Non-negative fractions of a second at nanosecond resolution. Negative
3520
+ * second values with fractions must still have non-negative nanos values
3521
+ * that count forward in time. Must be from 0 to 999,999,999
3522
+ * inclusive.
3523
+ *
3524
+ * @generated from field: int32 nanos = 2;
3525
+ */
3526
+ this.nanos = 0;
3527
+ proto3.util.initPartial(data, this);
3528
+ }
3529
+ fromJson(json, options) {
3530
+ if (typeof json !== "string") {
3531
+ throw new Error("cannot decode google.protobuf.Timestamp from JSON: ".concat(proto3.json.debug(json)));
3532
+ }
3533
+ const matches = json.match(/^([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})(?:Z|\.([0-9]{3,9})Z|([+-][0-9][0-9]:[0-9][0-9]))$/);
3534
+ if (!matches) {
3535
+ throw new Error("cannot decode google.protobuf.Timestamp from JSON: invalid RFC 3339 string");
3536
+ }
3537
+ const ms = Date.parse(matches[1] + "-" + matches[2] + "-" + matches[3] + "T" + matches[4] + ":" + matches[5] + ":" + matches[6] + (matches[8] ? matches[8] : "Z"));
3538
+ if (Number.isNaN(ms)) {
3539
+ throw new Error("cannot decode google.protobuf.Timestamp from JSON: invalid RFC 3339 string");
3540
+ }
3541
+ if (ms < Date.parse("0001-01-01T00:00:00Z") || ms > Date.parse("9999-12-31T23:59:59Z")) {
3542
+ throw new Error("cannot decode message google.protobuf.Timestamp from JSON: must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive");
3543
+ }
3544
+ this.seconds = protoInt64.parse(ms / 1000);
3545
+ this.nanos = 0;
3546
+ if (matches[7]) {
3547
+ this.nanos = parseInt("1" + matches[7] + "0".repeat(9 - matches[7].length)) - 1000000000;
3548
+ }
3549
+ return this;
3550
+ }
3551
+ toJson(options) {
3552
+ const ms = Number(this.seconds) * 1000;
3553
+ if (ms < Date.parse("0001-01-01T00:00:00Z") || ms > Date.parse("9999-12-31T23:59:59Z")) {
3554
+ throw new Error("cannot encode google.protobuf.Timestamp to JSON: must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive");
3555
+ }
3556
+ if (this.nanos < 0) {
3557
+ throw new Error("cannot encode google.protobuf.Timestamp to JSON: nanos must not be negative");
3558
+ }
3559
+ let z = "Z";
3560
+ if (this.nanos > 0) {
3561
+ const nanosStr = (this.nanos + 1000000000).toString().substring(1);
3562
+ if (nanosStr.substring(3) === "000000") {
3563
+ z = "." + nanosStr.substring(0, 3) + "Z";
3564
+ } else if (nanosStr.substring(6) === "000") {
3565
+ z = "." + nanosStr.substring(0, 6) + "Z";
3566
+ } else {
3567
+ z = "." + nanosStr + "Z";
3568
+ }
3569
+ }
3570
+ return new Date(ms).toISOString().replace(".000Z", z);
3571
+ }
3572
+ toDate() {
3573
+ return new Date(Number(this.seconds) * 1000 + Math.ceil(this.nanos / 1000000));
3574
+ }
3575
+ static now() {
3576
+ return Timestamp.fromDate(new Date());
3577
+ }
3578
+ static fromDate(date) {
3579
+ const ms = date.getTime();
3580
+ return new Timestamp({
3581
+ seconds: protoInt64.parse(Math.floor(ms / 1000)),
3582
+ nanos: ms % 1000 * 1000000
3583
+ });
3584
+ }
3585
+ static fromBinary(bytes, options) {
3586
+ return new Timestamp().fromBinary(bytes, options);
3587
+ }
3588
+ static fromJson(jsonValue, options) {
3589
+ return new Timestamp().fromJson(jsonValue, options);
3590
+ }
3591
+ static fromJsonString(jsonString, options) {
3592
+ return new Timestamp().fromJsonString(jsonString, options);
3593
+ }
3594
+ static equals(a, b) {
3595
+ return proto3.util.equals(Timestamp, a, b);
3596
+ }
3597
+ }
3598
+ Timestamp.runtime = proto3;
3599
+ Timestamp.typeName = "google.protobuf.Timestamp";
3600
+ Timestamp.fields = proto3.util.newFieldList(() => [{
3601
+ no: 1,
3602
+ name: "seconds",
3603
+ kind: "scalar",
3604
+ T: 3 /* ScalarType.INT64 */
3605
+ }, {
3606
+ no: 2,
3607
+ name: "nanos",
3608
+ kind: "scalar",
3609
+ T: 5 /* ScalarType.INT32 */
3610
+ }]);
3611
+
3400
3612
  // @generated by protoc-gen-es v1.10.0 with parameter "target=js+dts"
3401
3613
  // @generated from file livekit_metrics.proto (package livekit, syntax proto3)
3402
3614
  /* eslint-disable */
@@ -3408,18 +3620,28 @@ target => {
3408
3620
  */
3409
3621
  const MetricsBatch = /*@__PURE__*/proto3.makeMessageType("livekit.MetricsBatch", () => [{
3410
3622
  no: 1,
3623
+ name: "timestamp_ms",
3624
+ kind: "scalar",
3625
+ T: 3 /* ScalarType.INT64 */
3626
+ }, {
3627
+ no: 2,
3628
+ name: "normalized_timestamp",
3629
+ kind: "message",
3630
+ T: Timestamp
3631
+ }, {
3632
+ no: 3,
3411
3633
  name: "str_data",
3412
3634
  kind: "scalar",
3413
3635
  T: 9 /* ScalarType.STRING */,
3414
3636
  repeated: true
3415
3637
  }, {
3416
- no: 2,
3638
+ no: 4,
3417
3639
  name: "time_series",
3418
3640
  kind: "message",
3419
3641
  T: TimeSeriesMetric,
3420
3642
  repeated: true
3421
3643
  }, {
3422
- no: 3,
3644
+ no: 5,
3423
3645
  name: "events",
3424
3646
  kind: "message",
3425
3647
  T: EventMetric,
@@ -3446,16 +3668,6 @@ const TimeSeriesMetric = /*@__PURE__*/proto3.makeMessageType("livekit.TimeSeries
3446
3668
  T: 13 /* ScalarType.UINT32 */
3447
3669
  }, {
3448
3670
  no: 4,
3449
- name: "start_timestamp",
3450
- kind: "scalar",
3451
- T: 3 /* ScalarType.INT64 */
3452
- }, {
3453
- no: 5,
3454
- name: "end_timestamp",
3455
- kind: "scalar",
3456
- T: 3 /* ScalarType.INT64 */
3457
- }, {
3458
- no: 6,
3459
3671
  name: "samples",
3460
3672
  kind: "message",
3461
3673
  T: MetricSample,
@@ -3467,11 +3679,16 @@ const TimeSeriesMetric = /*@__PURE__*/proto3.makeMessageType("livekit.TimeSeries
3467
3679
  */
3468
3680
  const MetricSample = /*@__PURE__*/proto3.makeMessageType("livekit.MetricSample", () => [{
3469
3681
  no: 1,
3470
- name: "timestamp",
3682
+ name: "timestamp_ms",
3471
3683
  kind: "scalar",
3472
3684
  T: 3 /* ScalarType.INT64 */
3473
3685
  }, {
3474
3686
  no: 2,
3687
+ name: "normalized_timestamp",
3688
+ kind: "message",
3689
+ T: Timestamp
3690
+ }, {
3691
+ no: 3,
3475
3692
  name: "value",
3476
3693
  kind: "scalar",
3477
3694
  T: 2 /* ScalarType.FLOAT */
@@ -3497,17 +3714,28 @@ const EventMetric = /*@__PURE__*/proto3.makeMessageType("livekit.EventMetric", (
3497
3714
  T: 13 /* ScalarType.UINT32 */
3498
3715
  }, {
3499
3716
  no: 4,
3500
- name: "start_timestamp",
3717
+ name: "start_timestamp_ms",
3501
3718
  kind: "scalar",
3502
3719
  T: 3 /* ScalarType.INT64 */
3503
3720
  }, {
3504
3721
  no: 5,
3505
- name: "end_timestamp",
3722
+ name: "end_timestamp_ms",
3506
3723
  kind: "scalar",
3507
3724
  T: 3 /* ScalarType.INT64 */,
3508
3725
  opt: true
3509
3726
  }, {
3510
3727
  no: 6,
3728
+ name: "normalized_start_timestamp",
3729
+ kind: "message",
3730
+ T: Timestamp
3731
+ }, {
3732
+ no: 7,
3733
+ name: "normalized_end_timestamp",
3734
+ kind: "message",
3735
+ T: Timestamp,
3736
+ opt: true
3737
+ }, {
3738
+ no: 8,
3511
3739
  name: "metadata",
3512
3740
  kind: "scalar",
3513
3741
  T: 9 /* ScalarType.STRING */
@@ -4185,6 +4413,12 @@ const DataPacket = /*@__PURE__*/proto3.makeMessageType("livekit.DataPacket", ()
4185
4413
  kind: "message",
4186
4414
  T: MetricsBatch,
4187
4415
  oneof: "value"
4416
+ }, {
4417
+ no: 9,
4418
+ name: "chat_message",
4419
+ kind: "message",
4420
+ T: ChatMessage,
4421
+ oneof: "value"
4188
4422
  }]);
4189
4423
 
4190
4424
  /**
@@ -4356,6 +4590,42 @@ const TranscriptionSegment = /*@__PURE__*/proto3.makeMessageType("livekit.Transc
4356
4590
  T: 9 /* ScalarType.STRING */
4357
4591
  }]);
4358
4592
 
4593
+ /**
4594
+ * @generated from message livekit.ChatMessage
4595
+ */
4596
+ const ChatMessage = /*@__PURE__*/proto3.makeMessageType("livekit.ChatMessage", () => [{
4597
+ no: 1,
4598
+ name: "id",
4599
+ kind: "scalar",
4600
+ T: 9 /* ScalarType.STRING */
4601
+ }, {
4602
+ no: 2,
4603
+ name: "timestamp",
4604
+ kind: "scalar",
4605
+ T: 3 /* ScalarType.INT64 */
4606
+ }, {
4607
+ no: 3,
4608
+ name: "edit_timestamp",
4609
+ kind: "scalar",
4610
+ T: 3 /* ScalarType.INT64 */,
4611
+ opt: true
4612
+ }, {
4613
+ no: 4,
4614
+ name: "message",
4615
+ kind: "scalar",
4616
+ T: 9 /* ScalarType.STRING */
4617
+ }, {
4618
+ no: 5,
4619
+ name: "deleted",
4620
+ kind: "scalar",
4621
+ T: 8 /* ScalarType.BOOL */
4622
+ }, {
4623
+ no: 6,
4624
+ name: "generated",
4625
+ kind: "scalar",
4626
+ T: 8 /* ScalarType.BOOL */
4627
+ }]);
4628
+
4359
4629
  /**
4360
4630
  * @generated from message livekit.ParticipantTracks
4361
4631
  */
@@ -4518,6 +4788,12 @@ const ClientInfo_SDK = /*@__PURE__*/proto3.makeEnum("livekit.ClientInfo.SDK", [{
4518
4788
  }, {
4519
4789
  no: 10,
4520
4790
  name: "CPP"
4791
+ }, {
4792
+ no: 11,
4793
+ name: "UNITY_WEB"
4794
+ }, {
4795
+ no: 12,
4796
+ name: "NODE"
4521
4797
  }]);
4522
4798
 
4523
4799
  /**
@@ -10320,6 +10596,7 @@ var RoomEvent;
10320
10596
  * args: (kind: MediaDeviceKind, deviceId: string)
10321
10597
  */
10322
10598
  RoomEvent["ActiveDeviceChanged"] = "activeDeviceChanged";
10599
+ RoomEvent["ChatMessage"] = "chatMessage";
10323
10600
  /**
10324
10601
  * fired when the first remote participant has subscribed to the localParticipant's track
10325
10602
  */
@@ -10491,6 +10768,8 @@ var ParticipantEvent;
10491
10768
  * fired on local participant only, when the first remote participant has subscribed to the track specified in the payload
10492
10769
  */
10493
10770
  ParticipantEvent["LocalTrackSubscribed"] = "localTrackSubscribed";
10771
+ /** only emitted on local participant */
10772
+ ParticipantEvent["ChatMessage"] = "chatMessage";
10494
10773
  })(ParticipantEvent || (ParticipantEvent = {}));
10495
10774
  /** @internal */
10496
10775
  var EngineEvent;
@@ -10714,7 +10993,7 @@ function getOSVersion(ua) {
10714
10993
  return ua.includes('mac os') ? getMatch(/\(.+?(\d+_\d+(:?_\d+)?)/, ua, 1).replace(/_/g, '.') : undefined;
10715
10994
  }
10716
10995
 
10717
- var version$1 = "2.5.2";
10996
+ var version$1 = "2.5.4";
10718
10997
 
10719
10998
  const version = version$1;
10720
10999
  const protocolVersion = 15;
@@ -11872,6 +12151,20 @@ function extractTranscriptionSegments(transcription, firstReceivedTimesMap) {
11872
12151
  };
11873
12152
  });
11874
12153
  }
12154
+ function extractChatMessage(msg) {
12155
+ const {
12156
+ id,
12157
+ timestamp,
12158
+ message,
12159
+ editTimestamp
12160
+ } = msg;
12161
+ return {
12162
+ id,
12163
+ timestamp: Number.parseInt(timestamp.toString()),
12164
+ editTimestamp: editTimestamp ? Number.parseInt(editTimestamp.toString()) : undefined,
12165
+ message
12166
+ };
12167
+ }
11875
12168
 
11876
12169
  const defaultId = 'default';
11877
12170
  class DeviceManager {
@@ -18973,6 +19266,9 @@ class LocalParticipant extends Participant {
18973
19266
  source,
18974
19267
  enabled
18975
19268
  }));
19269
+ if (this.republishPromise) {
19270
+ yield this.republishPromise;
19271
+ }
18976
19272
  let track = this.getTrackPublication(source);
18977
19273
  if (enabled) {
18978
19274
  if (track) {
@@ -18980,11 +19276,14 @@ class LocalParticipant extends Participant {
18980
19276
  } else {
18981
19277
  let localTracks;
18982
19278
  if (this.pendingPublishing.has(source)) {
18983
- this.log.info('skipping duplicate published source', Object.assign(Object.assign({}, this.logContext), {
18984
- source
18985
- }));
18986
- // no-op it's already been requested
18987
- return;
19279
+ const pendingTrack = yield this.waitForPendingPublicationOfSource(source);
19280
+ if (!pendingTrack) {
19281
+ this.log.info('skipping duplicate published source', Object.assign(Object.assign({}, this.logContext), {
19282
+ source
19283
+ }));
19284
+ }
19285
+ yield pendingTrack === null || pendingTrack === void 0 ? void 0 : pendingTrack.unmute();
19286
+ return pendingTrack;
18988
19287
  }
18989
19288
  this.pendingPublishing.add(source);
18990
19289
  try {
@@ -19026,16 +19325,22 @@ class LocalParticipant extends Participant {
19026
19325
  this.pendingPublishing.delete(source);
19027
19326
  }
19028
19327
  }
19029
- } else if (track && track.track) {
19030
- // screenshare cannot be muted, unpublish instead
19031
- if (source === Track.Source.ScreenShare) {
19032
- track = yield this.unpublishTrack(track.track);
19033
- const screenAudioTrack = this.getTrackPublication(Track.Source.ScreenShareAudio);
19034
- if (screenAudioTrack && screenAudioTrack.track) {
19035
- this.unpublishTrack(screenAudioTrack.track);
19328
+ } else {
19329
+ if (!(track === null || track === void 0 ? void 0 : track.track)) {
19330
+ // if there's no track available yet first wait for pending publishing promises of that source to see if it becomes available
19331
+ track = yield this.waitForPendingPublicationOfSource(source);
19332
+ }
19333
+ if (track && track.track) {
19334
+ // screenshare cannot be muted, unpublish instead
19335
+ if (source === Track.Source.ScreenShare) {
19336
+ track = yield this.unpublishTrack(track.track);
19337
+ const screenAudioTrack = this.getTrackPublication(Track.Source.ScreenShareAudio);
19338
+ if (screenAudioTrack && screenAudioTrack.track) {
19339
+ this.unpublishTrack(screenAudioTrack.track);
19340
+ }
19341
+ } else {
19342
+ yield track.mute();
19036
19343
  }
19037
- } else {
19038
- yield track.mute();
19039
19344
  }
19040
19345
  }
19041
19346
  return track;
@@ -19182,109 +19487,121 @@ class LocalParticipant extends Participant {
19182
19487
  */
19183
19488
  publishTrack(track, options) {
19184
19489
  return __awaiter(this, void 0, void 0, function* () {
19185
- var _a, _b, _c, _d;
19186
- if (track instanceof LocalAudioTrack) {
19187
- track.setAudioContext(this.audioContext);
19188
- }
19189
- yield (_a = this.reconnectFuture) === null || _a === void 0 ? void 0 : _a.promise;
19190
- if (track instanceof LocalTrack && this.pendingPublishPromises.has(track)) {
19191
- yield this.pendingPublishPromises.get(track);
19192
- }
19193
- let defaultConstraints;
19194
- if (track instanceof MediaStreamTrack) {
19195
- defaultConstraints = track.getConstraints();
19196
- } else {
19197
- // we want to access constraints directly as `track.mediaStreamTrack`
19198
- // might be pointing to a non-device track (e.g. processed track) already
19199
- defaultConstraints = track.constraints;
19200
- let deviceKind = undefined;
19201
- switch (track.source) {
19202
- case Track.Source.Microphone:
19203
- deviceKind = 'audioinput';
19204
- break;
19205
- case Track.Source.Camera:
19206
- deviceKind = 'videoinput';
19490
+ return this.publishOrRepublishTrack(track, options);
19491
+ });
19492
+ }
19493
+ publishOrRepublishTrack(track_1, options_1) {
19494
+ return __awaiter(this, arguments, void 0, function (track, options) {
19495
+ var _this2 = this;
19496
+ let isRepublish = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
19497
+ return function* () {
19498
+ var _a, _b, _c, _d;
19499
+ if (track instanceof LocalAudioTrack) {
19500
+ track.setAudioContext(_this2.audioContext);
19207
19501
  }
19208
- if (deviceKind && this.activeDeviceMap.has(deviceKind)) {
19209
- defaultConstraints = Object.assign(Object.assign({}, defaultConstraints), {
19210
- deviceId: this.activeDeviceMap.get(deviceKind)
19211
- });
19502
+ yield (_a = _this2.reconnectFuture) === null || _a === void 0 ? void 0 : _a.promise;
19503
+ if (_this2.republishPromise && !isRepublish) {
19504
+ yield _this2.republishPromise;
19212
19505
  }
19213
- }
19214
- // convert raw media track into audio or video track
19215
- if (track instanceof MediaStreamTrack) {
19216
- switch (track.kind) {
19217
- case 'audio':
19218
- track = new LocalAudioTrack(track, defaultConstraints, true, this.audioContext, {
19219
- loggerName: this.roomOptions.loggerName,
19220
- loggerContextCb: () => this.logContext
19221
- });
19222
- break;
19223
- case 'video':
19224
- track = new LocalVideoTrack(track, defaultConstraints, true, {
19225
- loggerName: this.roomOptions.loggerName,
19226
- loggerContextCb: () => this.logContext
19506
+ if (track instanceof LocalTrack && _this2.pendingPublishPromises.has(track)) {
19507
+ yield _this2.pendingPublishPromises.get(track);
19508
+ }
19509
+ let defaultConstraints;
19510
+ if (track instanceof MediaStreamTrack) {
19511
+ defaultConstraints = track.getConstraints();
19512
+ } else {
19513
+ // we want to access constraints directly as `track.mediaStreamTrack`
19514
+ // might be pointing to a non-device track (e.g. processed track) already
19515
+ defaultConstraints = track.constraints;
19516
+ let deviceKind = undefined;
19517
+ switch (track.source) {
19518
+ case Track.Source.Microphone:
19519
+ deviceKind = 'audioinput';
19520
+ break;
19521
+ case Track.Source.Camera:
19522
+ deviceKind = 'videoinput';
19523
+ }
19524
+ if (deviceKind && _this2.activeDeviceMap.has(deviceKind)) {
19525
+ defaultConstraints = Object.assign(Object.assign({}, defaultConstraints), {
19526
+ deviceId: _this2.activeDeviceMap.get(deviceKind)
19227
19527
  });
19228
- break;
19229
- default:
19230
- throw new TrackInvalidError("unsupported MediaStreamTrack kind ".concat(track.kind));
19528
+ }
19231
19529
  }
19232
- } else {
19233
- track.updateLoggerOptions({
19234
- loggerName: this.roomOptions.loggerName,
19235
- loggerContextCb: () => this.logContext
19530
+ // convert raw media track into audio or video track
19531
+ if (track instanceof MediaStreamTrack) {
19532
+ switch (track.kind) {
19533
+ case 'audio':
19534
+ track = new LocalAudioTrack(track, defaultConstraints, true, _this2.audioContext, {
19535
+ loggerName: _this2.roomOptions.loggerName,
19536
+ loggerContextCb: () => _this2.logContext
19537
+ });
19538
+ break;
19539
+ case 'video':
19540
+ track = new LocalVideoTrack(track, defaultConstraints, true, {
19541
+ loggerName: _this2.roomOptions.loggerName,
19542
+ loggerContextCb: () => _this2.logContext
19543
+ });
19544
+ break;
19545
+ default:
19546
+ throw new TrackInvalidError("unsupported MediaStreamTrack kind ".concat(track.kind));
19547
+ }
19548
+ } else {
19549
+ track.updateLoggerOptions({
19550
+ loggerName: _this2.roomOptions.loggerName,
19551
+ loggerContextCb: () => _this2.logContext
19552
+ });
19553
+ }
19554
+ // is it already published? if so skip
19555
+ let existingPublication;
19556
+ _this2.trackPublications.forEach(publication => {
19557
+ if (!publication.track) {
19558
+ return;
19559
+ }
19560
+ if (publication.track === track) {
19561
+ existingPublication = publication;
19562
+ }
19236
19563
  });
19237
- }
19238
- // is it already published? if so skip
19239
- let existingPublication;
19240
- this.trackPublications.forEach(publication => {
19241
- if (!publication.track) {
19242
- return;
19564
+ if (existingPublication) {
19565
+ _this2.log.warn('track has already been published, skipping', Object.assign(Object.assign({}, _this2.logContext), getLogContextFromTrack(existingPublication)));
19566
+ return existingPublication;
19567
+ }
19568
+ const isStereoInput = 'channelCount' in track.mediaStreamTrack.getSettings() &&
19569
+ // @ts-ignore `channelCount` on getSettings() is currently only available for Safari, but is generally the best way to determine a stereo track https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackSettings/channelCount
19570
+ track.mediaStreamTrack.getSettings().channelCount === 2 || track.mediaStreamTrack.getConstraints().channelCount === 2;
19571
+ const isStereo = (_b = options === null || options === void 0 ? void 0 : options.forceStereo) !== null && _b !== void 0 ? _b : isStereoInput;
19572
+ // disable dtx for stereo track if not enabled explicitly
19573
+ if (isStereo) {
19574
+ if (!options) {
19575
+ options = {};
19576
+ }
19577
+ if (options.dtx === undefined) {
19578
+ _this2.log.info("Opus DTX will be disabled for stereo tracks by default. Enable them explicitly to make it work.", Object.assign(Object.assign({}, _this2.logContext), getLogContextFromTrack(track)));
19579
+ }
19580
+ if (options.red === undefined) {
19581
+ _this2.log.info("Opus RED will be disabled for stereo tracks by default. Enable them explicitly to make it work.");
19582
+ }
19583
+ (_c = options.dtx) !== null && _c !== void 0 ? _c : options.dtx = false;
19584
+ (_d = options.red) !== null && _d !== void 0 ? _d : options.red = false;
19243
19585
  }
19244
- if (publication.track === track) {
19245
- existingPublication = publication;
19586
+ const opts = Object.assign(Object.assign({}, _this2.roomOptions.publishDefaults), options);
19587
+ if (!isE2EESimulcastSupported() && _this2.roomOptions.e2ee) {
19588
+ _this2.log.info("End-to-end encryption is set up, simulcast publishing will be disabled on Safari versions and iOS browsers running iOS < v17.2", Object.assign({}, _this2.logContext));
19589
+ opts.simulcast = false;
19246
19590
  }
19247
- });
19248
- if (existingPublication) {
19249
- this.log.warn('track has already been published, skipping', Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(existingPublication)));
19250
- return existingPublication;
19251
- }
19252
- const isStereoInput = 'channelCount' in track.mediaStreamTrack.getSettings() &&
19253
- // @ts-ignore `channelCount` on getSettings() is currently only available for Safari, but is generally the best way to determine a stereo track https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackSettings/channelCount
19254
- track.mediaStreamTrack.getSettings().channelCount === 2 || track.mediaStreamTrack.getConstraints().channelCount === 2;
19255
- const isStereo = (_b = options === null || options === void 0 ? void 0 : options.forceStereo) !== null && _b !== void 0 ? _b : isStereoInput;
19256
- // disable dtx for stereo track if not enabled explicitly
19257
- if (isStereo) {
19258
- if (!options) {
19259
- options = {};
19260
- }
19261
- if (options.dtx === undefined) {
19262
- this.log.info("Opus DTX will be disabled for stereo tracks by default. Enable them explicitly to make it work.", Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)));
19263
- }
19264
- if (options.red === undefined) {
19265
- this.log.info("Opus RED will be disabled for stereo tracks by default. Enable them explicitly to make it work.");
19266
- }
19267
- (_c = options.dtx) !== null && _c !== void 0 ? _c : options.dtx = false;
19268
- (_d = options.red) !== null && _d !== void 0 ? _d : options.red = false;
19269
- }
19270
- const opts = Object.assign(Object.assign({}, this.roomOptions.publishDefaults), options);
19271
- if (!isE2EESimulcastSupported() && this.roomOptions.e2ee) {
19272
- this.log.info("End-to-end encryption is set up, simulcast publishing will be disabled on Safari versions and iOS browsers running iOS < v17.2", Object.assign({}, this.logContext));
19273
- opts.simulcast = false;
19274
- }
19275
- if (opts.source) {
19276
- track.source = opts.source;
19277
- }
19278
- const publishPromise = this.publish(track, opts, isStereo);
19279
- this.pendingPublishPromises.set(track, publishPromise);
19280
- try {
19281
- const publication = yield publishPromise;
19282
- return publication;
19283
- } catch (e) {
19284
- throw e;
19285
- } finally {
19286
- this.pendingPublishPromises.delete(track);
19287
- }
19591
+ if (opts.source) {
19592
+ track.source = opts.source;
19593
+ }
19594
+ const publishPromise = _this2.publish(track, opts, isStereo);
19595
+ _this2.pendingPublishPromises.set(track, publishPromise);
19596
+ try {
19597
+ const publication = yield publishPromise;
19598
+ return publication;
19599
+ } catch (e) {
19600
+ throw e;
19601
+ } finally {
19602
+ _this2.pendingPublishPromises.delete(track);
19603
+ }
19604
+ }();
19288
19605
  });
19289
19606
  }
19290
19607
  publish(track, opts, isStereo) {
@@ -19670,31 +19987,44 @@ class LocalParticipant extends Participant {
19670
19987
  }
19671
19988
  republishAllTracks(options_1) {
19672
19989
  return __awaiter(this, arguments, void 0, function (options) {
19673
- var _this2 = this;
19990
+ var _this3 = this;
19674
19991
  let restartTracks = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
19675
19992
  return function* () {
19676
- const localPubs = [];
19677
- _this2.trackPublications.forEach(pub => {
19678
- if (pub.track) {
19679
- if (options) {
19680
- pub.options = Object.assign(Object.assign({}, pub.options), options);
19681
- }
19682
- localPubs.push(pub);
19683
- }
19684
- });
19685
- yield Promise.all(localPubs.map(pub => __awaiter(_this2, void 0, void 0, function* () {
19686
- const track = pub.track;
19687
- yield this.unpublishTrack(track, false);
19688
- if (restartTracks && !track.isMuted && track.source !== Track.Source.ScreenShare && track.source !== Track.Source.ScreenShareAudio && (track instanceof LocalAudioTrack || track instanceof LocalVideoTrack) && !track.isUserProvided) {
19689
- // generally we need to restart the track before publishing, often a full reconnect
19690
- // is necessary because computer had gone to sleep.
19691
- this.log.debug('restarting existing track', Object.assign(Object.assign({}, this.logContext), {
19692
- track: pub.trackSid
19693
- }));
19694
- yield track.restartTrack();
19993
+ if (_this3.republishPromise) {
19994
+ yield _this3.republishPromise;
19995
+ }
19996
+ _this3.republishPromise = new Promise((resolve, reject) => __awaiter(_this3, void 0, void 0, function* () {
19997
+ try {
19998
+ const localPubs = [];
19999
+ this.trackPublications.forEach(pub => {
20000
+ if (pub.track) {
20001
+ if (options) {
20002
+ pub.options = Object.assign(Object.assign({}, pub.options), options);
20003
+ }
20004
+ localPubs.push(pub);
20005
+ }
20006
+ });
20007
+ yield Promise.all(localPubs.map(pub => __awaiter(this, void 0, void 0, function* () {
20008
+ const track = pub.track;
20009
+ yield this.unpublishTrack(track, false);
20010
+ if (restartTracks && !track.isMuted && track.source !== Track.Source.ScreenShare && track.source !== Track.Source.ScreenShareAudio && (track instanceof LocalAudioTrack || track instanceof LocalVideoTrack) && !track.isUserProvided) {
20011
+ // generally we need to restart the track before publishing, often a full reconnect
20012
+ // is necessary because computer had gone to sleep.
20013
+ this.log.debug('restarting existing track', Object.assign(Object.assign({}, this.logContext), {
20014
+ track: pub.trackSid
20015
+ }));
20016
+ yield track.restartTrack();
20017
+ }
20018
+ yield this.publishOrRepublishTrack(track, pub.options, true);
20019
+ })));
20020
+ resolve();
20021
+ } catch (error) {
20022
+ reject(error);
20023
+ } finally {
20024
+ this.republishPromise = undefined;
19695
20025
  }
19696
- yield this.publishTrack(track, pub.options);
19697
- })));
20026
+ }));
20027
+ yield _this3.republishPromise;
19698
20028
  }();
19699
20029
  });
19700
20030
  }
@@ -19707,7 +20037,7 @@ class LocalParticipant extends Participant {
19707
20037
  */
19708
20038
  publishData(data_1) {
19709
20039
  return __awaiter(this, arguments, void 0, function (data) {
19710
- var _this3 = this;
20040
+ var _this4 = this;
19711
20041
  let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
19712
20042
  return function* () {
19713
20043
  const kind = options.reliable ? DataPacket_Kind.RELIABLE : DataPacket_Kind.LOSSY;
@@ -19718,17 +20048,57 @@ class LocalParticipant extends Participant {
19718
20048
  value: {
19719
20049
  case: 'user',
19720
20050
  value: new UserPacket({
19721
- participantIdentity: _this3.identity,
20051
+ participantIdentity: _this4.identity,
19722
20052
  payload: data,
19723
20053
  destinationIdentities,
19724
20054
  topic
19725
20055
  })
19726
20056
  }
19727
20057
  });
19728
- yield _this3.engine.sendDataPacket(packet, kind);
20058
+ yield _this4.engine.sendDataPacket(packet, kind);
19729
20059
  }();
19730
20060
  });
19731
20061
  }
20062
+ sendChatMessage(text) {
20063
+ return __awaiter(this, void 0, void 0, function* () {
20064
+ const msg = {
20065
+ id: crypto.randomUUID(),
20066
+ message: text,
20067
+ timestamp: Date.now()
20068
+ };
20069
+ const packet = new DataPacket({
20070
+ value: {
20071
+ case: 'chatMessage',
20072
+ value: new ChatMessage(Object.assign(Object.assign({}, msg), {
20073
+ timestamp: protoInt64.parse(msg.timestamp)
20074
+ }))
20075
+ }
20076
+ });
20077
+ yield this.engine.sendDataPacket(packet, DataPacket_Kind.RELIABLE);
20078
+ this.emit(ParticipantEvent.ChatMessage, msg);
20079
+ return msg;
20080
+ });
20081
+ }
20082
+ editChatMessage(editText, originalMessage) {
20083
+ return __awaiter(this, void 0, void 0, function* () {
20084
+ const msg = Object.assign(Object.assign({}, originalMessage), {
20085
+ message: editText,
20086
+ editTimestamp: Date.now()
20087
+ });
20088
+ const packet = new DataPacket({
20089
+ value: {
20090
+ case: 'chatMessage',
20091
+ value: new ChatMessage(Object.assign(Object.assign({}, msg), {
20092
+ timestamp: protoInt64.parse(msg.timestamp),
20093
+ editTimestamp: protoInt64.parse(msg.editTimestamp)
20094
+ }))
20095
+ }
20096
+ });
20097
+ yield this.engine.sendDataPacket(packet, DataPacket_Kind.RELIABLE);
20098
+ this.emit(ParticipantEvent.ChatMessage, msg);
20099
+ return msg;
20100
+ });
20101
+ }
19732
20102
  /**
19733
20103
  * Control who can subscribe to LocalParticipant's published tracks.
19734
20104
  *
@@ -19806,6 +20176,17 @@ class LocalParticipant extends Participant {
19806
20176
  });
19807
20177
  return publication;
19808
20178
  }
20179
+ waitForPendingPublicationOfSource(source) {
20180
+ return __awaiter(this, void 0, void 0, function* () {
20181
+ const publishPromiseEntry = Array.from(this.pendingPublishPromises.entries()).find(_ref3 => {
20182
+ let [pendingTrack] = _ref3;
20183
+ return pendingTrack.source === source;
20184
+ });
20185
+ if (publishPromiseEntry) {
20186
+ return publishPromiseEntry[1];
20187
+ }
20188
+ });
20189
+ }
19809
20190
  }
19810
20191
 
19811
20192
  class RemoteTrackPublication extends TrackPublication {
@@ -20876,6 +21257,8 @@ class Room extends eventsExports.EventEmitter {
20876
21257
  this.handleTranscription(participant, packet.value.value);
20877
21258
  } else if (packet.value.case === 'sipDtmf') {
20878
21259
  this.handleSipDtmf(participant, packet.value.value);
21260
+ } else if (packet.value.case === 'chatMessage') {
21261
+ this.handleChatMessage(participant, packet.value.value);
20879
21262
  }
20880
21263
  };
20881
21264
  this.handleUserPacket = (participant, userPacket, kind) => {
@@ -20898,6 +21281,10 @@ class Room extends eventsExports.EventEmitter {
20898
21281
  participant === null || participant === void 0 ? void 0 : participant.emit(ParticipantEvent.TranscriptionReceived, segments, publication);
20899
21282
  this.emit(RoomEvent.TranscriptionReceived, segments, participant, publication);
20900
21283
  };
21284
+ this.handleChatMessage = (participant, chatMessage) => {
21285
+ const msg = extractChatMessage(chatMessage);
21286
+ this.emit(RoomEvent.ChatMessage, msg, participant);
21287
+ };
20901
21288
  this.handleAudioPlaybackStarted = () => {
20902
21289
  if (this.canPlaybackAudio) {
20903
21290
  return;
@@ -20928,7 +21315,8 @@ class Room extends eventsExports.EventEmitter {
20928
21315
  }
20929
21316
  };
20930
21317
  this.handleDeviceChange = () => __awaiter(this, void 0, void 0, function* () {
20931
- const availableDevices = yield DeviceManager.getInstance().getDevices();
21318
+ // check for available devices, but don't request permissions in order to avoid prompts for kinds that haven't been used before
21319
+ const availableDevices = yield DeviceManager.getInstance().getDevices(undefined, false);
20932
21320
  // inputs are automatically handled via TrackEvent.Ended causing a TrackEvent.Restarted. Here we only need to worry about audiooutputs changing
20933
21321
  const kinds = ['audiooutput'];
20934
21322
  for (let kind of kinds) {
@@ -21024,6 +21412,9 @@ class Room extends eventsExports.EventEmitter {
21024
21412
  this.onLocalParticipantPermissionsChanged = prevPermissions => {
21025
21413
  this.emit(RoomEvent.ParticipantPermissionsChanged, prevPermissions, this.localParticipant);
21026
21414
  };
21415
+ this.onLocalChatMessageSent = msg => {
21416
+ this.emit(RoomEvent.ChatMessage, msg, this.localParticipant);
21417
+ };
21027
21418
  this.setMaxListeners(100);
21028
21419
  this.remoteParticipants = new Map();
21029
21420
  this.sidToIdentity = new Map();
@@ -21483,7 +21874,7 @@ class Room extends eventsExports.EventEmitter {
21483
21874
  });
21484
21875
  }
21485
21876
  setupLocalParticipantEvents() {
21486
- this.localParticipant.on(ParticipantEvent.ParticipantMetadataChanged, this.onLocalParticipantMetadataChanged).on(ParticipantEvent.ParticipantNameChanged, this.onLocalParticipantNameChanged).on(ParticipantEvent.AttributesChanged, this.onLocalAttributesChanged).on(ParticipantEvent.TrackMuted, this.onLocalTrackMuted).on(ParticipantEvent.TrackUnmuted, this.onLocalTrackUnmuted).on(ParticipantEvent.LocalTrackPublished, this.onLocalTrackPublished).on(ParticipantEvent.LocalTrackUnpublished, this.onLocalTrackUnpublished).on(ParticipantEvent.ConnectionQualityChanged, this.onLocalConnectionQualityChanged).on(ParticipantEvent.MediaDevicesError, this.onMediaDevicesError).on(ParticipantEvent.AudioStreamAcquired, this.startAudio).on(ParticipantEvent.ParticipantPermissionsChanged, this.onLocalParticipantPermissionsChanged);
21877
+ this.localParticipant.on(ParticipantEvent.ParticipantMetadataChanged, this.onLocalParticipantMetadataChanged).on(ParticipantEvent.ParticipantNameChanged, this.onLocalParticipantNameChanged).on(ParticipantEvent.AttributesChanged, this.onLocalAttributesChanged).on(ParticipantEvent.TrackMuted, this.onLocalTrackMuted).on(ParticipantEvent.TrackUnmuted, this.onLocalTrackUnmuted).on(ParticipantEvent.LocalTrackPublished, this.onLocalTrackPublished).on(ParticipantEvent.LocalTrackUnpublished, this.onLocalTrackUnpublished).on(ParticipantEvent.ConnectionQualityChanged, this.onLocalConnectionQualityChanged).on(ParticipantEvent.MediaDevicesError, this.onMediaDevicesError).on(ParticipantEvent.AudioStreamAcquired, this.startAudio).on(ParticipantEvent.ChatMessage, this.onLocalChatMessageSent).on(ParticipantEvent.ParticipantPermissionsChanged, this.onLocalParticipantPermissionsChanged);
21487
21878
  }
21488
21879
  recreateEngine() {
21489
21880
  var _a;
@@ -21577,7 +21968,7 @@ class Room extends eventsExports.EventEmitter {
21577
21968
  (_b = pub.track) === null || _b === void 0 ? void 0 : _b.stop();
21578
21969
  }
21579
21970
  });
21580
- this.localParticipant.off(ParticipantEvent.ParticipantMetadataChanged, this.onLocalParticipantMetadataChanged).off(ParticipantEvent.ParticipantNameChanged, this.onLocalParticipantNameChanged).off(ParticipantEvent.AttributesChanged, this.onLocalAttributesChanged).off(ParticipantEvent.TrackMuted, this.onLocalTrackMuted).off(ParticipantEvent.TrackUnmuted, this.onLocalTrackUnmuted).off(ParticipantEvent.LocalTrackPublished, this.onLocalTrackPublished).off(ParticipantEvent.LocalTrackUnpublished, this.onLocalTrackUnpublished).off(ParticipantEvent.ConnectionQualityChanged, this.onLocalConnectionQualityChanged).off(ParticipantEvent.MediaDevicesError, this.onMediaDevicesError).off(ParticipantEvent.AudioStreamAcquired, this.startAudio).off(ParticipantEvent.ParticipantPermissionsChanged, this.onLocalParticipantPermissionsChanged);
21971
+ this.localParticipant.off(ParticipantEvent.ParticipantMetadataChanged, this.onLocalParticipantMetadataChanged).off(ParticipantEvent.ParticipantNameChanged, this.onLocalParticipantNameChanged).off(ParticipantEvent.AttributesChanged, this.onLocalAttributesChanged).off(ParticipantEvent.TrackMuted, this.onLocalTrackMuted).off(ParticipantEvent.TrackUnmuted, this.onLocalTrackUnmuted).off(ParticipantEvent.LocalTrackPublished, this.onLocalTrackPublished).off(ParticipantEvent.LocalTrackUnpublished, this.onLocalTrackUnpublished).off(ParticipantEvent.ConnectionQualityChanged, this.onLocalConnectionQualityChanged).off(ParticipantEvent.MediaDevicesError, this.onMediaDevicesError).off(ParticipantEvent.AudioStreamAcquired, this.startAudio).off(ParticipantEvent.ChatMessage, this.onLocalChatMessageSent).off(ParticipantEvent.ParticipantPermissionsChanged, this.onLocalParticipantPermissionsChanged);
21581
21972
  this.localParticipant.trackPublications.clear();
21582
21973
  this.localParticipant.videoTrackPublications.clear();
21583
21974
  this.localParticipant.audioTrackPublications.clear();