@livekit/rtc-node 0.13.32 → 0.13.34
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/async_queue.d.ts +2 -3
- package/dist/audio_filter.d.ts +2 -3
- package/dist/audio_frame.d.ts +5 -6
- package/dist/audio_mixer.d.ts +3 -6
- package/dist/audio_resampler.d.ts +3 -6
- package/dist/audio_source.d.ts +5 -6
- package/dist/{audio_stream-4M8XlO4-.d.cts → audio_stream-BNVaONuH.d.cts} +36 -10
- package/dist/audio_stream.d.cts +2 -2
- package/dist/audio_stream.d.ts +61 -18
- package/dist/data_streams/index.d.cts +1 -1
- package/dist/data_streams/index.d.ts +4 -3
- package/dist/data_streams/stream_reader.cjs +97 -58
- package/dist/data_streams/stream_reader.cjs.map +1 -1
- package/dist/data_streams/stream_reader.d.cts +1 -1
- package/dist/data_streams/stream_reader.d.ts +65 -2
- package/dist/data_streams/stream_reader.d.ts.map +1 -1
- package/dist/data_streams/stream_writer.d.cts +1 -1
- package/dist/data_streams/stream_writer.d.ts +5 -7
- package/dist/data_streams/types.cjs.map +1 -1
- package/dist/data_streams/types.d.cts +1 -1
- package/dist/data_streams/types.d.ts +47 -2
- package/dist/data_streams/types.d.ts.map +1 -1
- package/dist/e2ee.cjs +5 -1
- package/dist/e2ee.cjs.map +1 -1
- package/dist/e2ee.d.cts +3 -1
- package/dist/e2ee.d.ts +11 -11
- package/dist/e2ee.d.ts.map +1 -1
- package/dist/ffi_client.d.ts +8 -10
- package/dist/frame_processor.d.ts +8 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +22 -17
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -107
- package/dist/log.d.ts +5 -7
- package/dist/participant.cjs +179 -192
- package/dist/participant.cjs.map +1 -1
- package/dist/participant.d.cts +2 -2
- package/dist/participant.d.ts +169 -18
- package/dist/participant.d.ts.map +1 -1
- package/dist/room.cjs +166 -120
- package/dist/room.cjs.map +1 -1
- package/dist/room.d.cts +2 -2
- package/dist/room.d.ts +228 -18
- package/dist/room.d.ts.map +1 -1
- package/dist/rpc.d.ts +7 -9
- package/dist/tests/e2e_common.cjs +157 -0
- package/dist/tests/e2e_common.cjs.map +1 -0
- package/dist/tests/e2e_common.d.cts +56 -0
- package/dist/tests/e2e_common.d.ts +37 -0
- package/dist/tests/e2e_common.d.ts.map +1 -0
- package/dist/track.d.cts +2 -2
- package/dist/track.d.ts +67 -18
- package/dist/track_publication.d.cts +2 -2
- package/dist/track_publication.d.ts +45 -18
- package/dist/transcription.d.ts +3 -4
- package/dist/{types-_PdPVish.d.ts → types-f7wTlFjs.d.cts} +34 -11
- package/dist/types.d.ts +2 -3
- package/dist/utils.cjs +27 -2
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.d.cts +8 -1
- package/dist/utils.d.ts +10 -5
- package/dist/utils.d.ts.map +1 -1
- package/dist/version.cjs +1 -1
- package/dist/version.cjs.map +1 -1
- package/dist/version.d.cts +1 -1
- package/dist/version.d.ts +2 -3
- package/dist/video_frame.d.ts +4 -5
- package/dist/video_source.d.ts +6 -8
- package/dist/video_stream.d.cts +2 -2
- package/dist/video_stream.d.ts +5 -22
- package/package.json +6 -7
- package/src/audio_stream_room_lifecycle.test.ts +4 -1
- package/src/data_streams/stream_reader.ts +132 -82
- package/src/data_streams/types.ts +6 -0
- package/src/e2ee.ts +7 -0
- package/src/index.ts +8 -1
- package/src/participant.ts +252 -223
- package/src/room.ts +233 -134
- package/src/tests/e2e.test.ts +50 -139
- package/src/tests/e2e_common.ts +163 -0
- package/src/tests/e2e_data_streams.test.ts +639 -0
- package/src/utils.ts +30 -0
- package/src/version.ts +1 -1
- package/dist/async_queue.js +0 -56
- package/dist/async_queue.js.map +0 -1
- package/dist/audio_filter.js +0 -24
- package/dist/audio_filter.js.map +0 -1
- package/dist/audio_frame.js +0 -78
- package/dist/audio_frame.js.map +0 -1
- package/dist/audio_mixer.js +0 -269
- package/dist/audio_mixer.js.map +0 -1
- package/dist/audio_resampler.js +0 -154
- package/dist/audio_resampler.js.map +0 -1
- package/dist/audio_source.js +0 -134
- package/dist/audio_source.js.map +0 -1
- package/dist/audio_stream-CTyN1Ldy.d.ts +0 -523
- package/dist/audio_stream.js +0 -122
- package/dist/audio_stream.js.map +0 -1
- package/dist/data_streams/index.js +0 -3
- package/dist/data_streams/index.js.map +0 -1
- package/dist/data_streams/stream_reader.js +0 -124
- package/dist/data_streams/stream_reader.js.map +0 -1
- package/dist/data_streams/stream_writer.js +0 -26
- package/dist/data_streams/stream_writer.js.map +0 -1
- package/dist/data_streams/types.js +0 -1
- package/dist/data_streams/types.js.map +0 -1
- package/dist/e2ee.js +0 -251
- package/dist/e2ee.js.map +0 -1
- package/dist/ffi_client.js +0 -89
- package/dist/ffi_client.js.map +0 -1
- package/dist/frame_processor.js +0 -29
- package/dist/frame_processor.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/log.js +0 -9
- package/dist/log.js.map +0 -1
- package/dist/participant.js +0 -715
- package/dist/participant.js.map +0 -1
- package/dist/room.js +0 -900
- package/dist/room.js.map +0 -1
- package/dist/rpc.js +0 -65
- package/dist/rpc.js.map +0 -1
- package/dist/track.js +0 -234
- package/dist/track.js.map +0 -1
- package/dist/track_publication.js +0 -100
- package/dist/track_publication.js.map +0 -1
- package/dist/transcription.js +0 -1
- package/dist/transcription.js.map +0 -1
- package/dist/types-_PdPVish.d.cts +0 -87
- package/dist/types.js +0 -1
- package/dist/types.js.map +0 -1
- package/dist/utils.js +0 -35
- package/dist/utils.js.map +0 -1
- package/dist/version.js +0 -5
- package/dist/version.js.map +0 -1
- package/dist/video_frame.js +0 -207
- package/dist/video_frame.js.map +0 -1
- package/dist/video_source.js +0 -53
- package/dist/video_source.js.map +0 -1
- package/dist/video_stream.js +0 -70
- package/dist/video_stream.js.map +0 -1
package/dist/room.cjs
CHANGED
|
@@ -40,8 +40,10 @@ var import_rtc_ffi_bindings = require("@livekit/rtc-ffi-bindings");
|
|
|
40
40
|
var import_rtc_ffi_bindings2 = require("@livekit/rtc-ffi-bindings");
|
|
41
41
|
var import_rtc_ffi_bindings3 = require("@livekit/rtc-ffi-bindings");
|
|
42
42
|
var import_rtc_ffi_bindings4 = require("@livekit/rtc-ffi-bindings");
|
|
43
|
+
var import_rtc_ffi_bindings5 = require("@livekit/rtc-ffi-bindings");
|
|
43
44
|
var import_events = __toESM(require("events"), 1);
|
|
44
45
|
var import_stream_reader = require("./data_streams/stream_reader.cjs");
|
|
46
|
+
var import_types = require("./data_streams/types.cjs");
|
|
45
47
|
var import_e2ee = require("./e2ee.cjs");
|
|
46
48
|
var import_ffi_client = require("./ffi_client.cjs");
|
|
47
49
|
var import_log = require("./log.cjs");
|
|
@@ -50,11 +52,11 @@ var import_track = require("./track.cjs");
|
|
|
50
52
|
var import_track_publication = require("./track_publication.cjs");
|
|
51
53
|
var import_utils = require("./utils.cjs");
|
|
52
54
|
const defaultRtcConfiguration = {
|
|
53
|
-
iceTransportType:
|
|
54
|
-
continualGatheringPolicy:
|
|
55
|
+
iceTransportType: import_rtc_ffi_bindings4.IceTransportType.TRANSPORT_ALL,
|
|
56
|
+
continualGatheringPolicy: import_rtc_ffi_bindings4.ContinualGatheringPolicy.GATHER_CONTINUALLY,
|
|
55
57
|
iceServers: []
|
|
56
58
|
};
|
|
57
|
-
const defaultRoomOptions = new
|
|
59
|
+
const defaultRoomOptions = new import_rtc_ffi_bindings4.RoomOptions({
|
|
58
60
|
autoSubscribe: true,
|
|
59
61
|
dynacast: false,
|
|
60
62
|
e2ee: void 0,
|
|
@@ -72,8 +74,9 @@ class Room extends import_events.default {
|
|
|
72
74
|
* before processing the next events
|
|
73
75
|
*/
|
|
74
76
|
this.ffiEventLock = new import_mutex.Mutex();
|
|
75
|
-
|
|
76
|
-
|
|
77
|
+
// Active incoming stream readers keyed by their FFI reader handle id. Each entry
|
|
78
|
+
// owns the FfiClient listener feeding reader events into the ReadableStream.
|
|
79
|
+
this.streamReaders = /* @__PURE__ */ new Map();
|
|
77
80
|
this.byteStreamHandlers = /* @__PURE__ */ new Map();
|
|
78
81
|
this.textStreamHandlers = /* @__PURE__ */ new Map();
|
|
79
82
|
this.preConnectEvents = [];
|
|
@@ -84,7 +87,7 @@ class Room extends import_events.default {
|
|
|
84
87
|
// events fire exactly once, no matter which path (explicit disconnect()
|
|
85
88
|
// vs. FFI 'disconnected' event) wins the race.
|
|
86
89
|
this.hasCleanedUp = false;
|
|
87
|
-
this._connectionState =
|
|
90
|
+
this._connectionState = import_rtc_ffi_bindings4.ConnectionState.CONN_DISCONNECTED;
|
|
88
91
|
this.remoteParticipants = /* @__PURE__ */ new Map();
|
|
89
92
|
this.onFfiEvent = async (ffiEvent) => {
|
|
90
93
|
const unlock = await this.ffiEventLock.lock();
|
|
@@ -211,9 +214,9 @@ class Room extends import_events.default {
|
|
|
211
214
|
trackInfo.sid
|
|
212
215
|
);
|
|
213
216
|
publication.subscribed = true;
|
|
214
|
-
if (trackInfo.kind ==
|
|
217
|
+
if (trackInfo.kind == import_rtc_ffi_bindings5.TrackKind.KIND_VIDEO) {
|
|
215
218
|
publication.track = new import_track.RemoteVideoTrack(ownedTrack);
|
|
216
|
-
} else if (trackInfo.kind ==
|
|
219
|
+
} else if (trackInfo.kind == import_rtc_ffi_bindings5.TrackKind.KIND_AUDIO) {
|
|
217
220
|
publication.track = new import_track.RemoteAudioTrack(ownedTrack);
|
|
218
221
|
}
|
|
219
222
|
(_b = publication.track) == null ? void 0 : _b.setRoom(this);
|
|
@@ -384,12 +387,10 @@ class Room extends import_events.default {
|
|
|
384
387
|
this.emit("reconnected" /* Reconnected */);
|
|
385
388
|
} else if (ev.case == "roomSidChanged") {
|
|
386
389
|
this.emit("roomSidChanged" /* RoomSidChanged */, ev.value.sid);
|
|
387
|
-
} else if (ev.case === "
|
|
388
|
-
this.
|
|
389
|
-
} else if (ev.case === "
|
|
390
|
-
this.
|
|
391
|
-
} else if (ev.case === "streamTrailerReceived" && ev.value.trailer) {
|
|
392
|
-
this.handleStreamTrailer(ev.value.trailer);
|
|
390
|
+
} else if (ev.case === "byteStreamOpened" && ev.value.reader) {
|
|
391
|
+
this.handleByteStreamOpened(ev.value.reader, ev.value.participantIdentity);
|
|
392
|
+
} else if (ev.case === "textStreamOpened" && ev.value.reader) {
|
|
393
|
+
this.handleTextStreamOpened(ev.value.reader, ev.value.participantIdentity);
|
|
393
394
|
} else if (ev.case === "roomUpdated") {
|
|
394
395
|
this.info = ev.value;
|
|
395
396
|
this.emit("roomUpdated" /* RoomUpdated */);
|
|
@@ -432,7 +433,7 @@ class Room extends import_events.default {
|
|
|
432
433
|
return (_a = this.info) == null ? void 0 : _a.metadata;
|
|
433
434
|
}
|
|
434
435
|
get isConnected() {
|
|
435
|
-
return this.ffiHandle != void 0 && this.connectionState !=
|
|
436
|
+
return this.ffiHandle != void 0 && this.connectionState != import_rtc_ffi_bindings4.ConnectionState.CONN_DISCONNECTED;
|
|
436
437
|
}
|
|
437
438
|
/** @internal */
|
|
438
439
|
get token() {
|
|
@@ -547,13 +548,33 @@ class Room extends import_events.default {
|
|
|
547
548
|
* @throws ConnectError - if connection fails
|
|
548
549
|
*/
|
|
549
550
|
async connect(url, token, opts) {
|
|
550
|
-
const
|
|
551
|
+
const { dataStream, ...restOpts } = opts ?? {};
|
|
552
|
+
const options = { ...defaultRoomOptions, ...restOpts };
|
|
551
553
|
const e2eeEnabled = options.encryption || options.e2ee;
|
|
552
|
-
const
|
|
553
|
-
const
|
|
554
|
+
const userE2EEOptions = options.encryption ?? options.e2ee;
|
|
555
|
+
const e2eeOptions = {
|
|
556
|
+
...import_e2ee.defaultE2EEOptions,
|
|
557
|
+
...userE2EEOptions,
|
|
558
|
+
keyProviderOptions: {
|
|
559
|
+
...import_e2ee.defaultE2EEOptions.keyProviderOptions,
|
|
560
|
+
...userE2EEOptions == null ? void 0 : userE2EEOptions.keyProviderOptions
|
|
561
|
+
}
|
|
562
|
+
};
|
|
563
|
+
const mergedOptions = { ...options };
|
|
564
|
+
if (options.encryption) {
|
|
565
|
+
mergedOptions.encryption = e2eeOptions;
|
|
566
|
+
} else if (options.e2ee) {
|
|
567
|
+
mergedOptions.e2ee = e2eeOptions;
|
|
568
|
+
}
|
|
569
|
+
if (dataStream) {
|
|
570
|
+
mergedOptions.dataStream = new import_rtc_ffi_bindings4.RoomDataStreamOptions({
|
|
571
|
+
maxPayloadByteLength: (0, import_utils.numberToBigInt)(dataStream.maxPayloadByteLength)
|
|
572
|
+
});
|
|
573
|
+
}
|
|
574
|
+
const req = new import_rtc_ffi_bindings4.ConnectRequest({
|
|
554
575
|
url,
|
|
555
576
|
token,
|
|
556
|
-
options
|
|
577
|
+
options: mergedOptions
|
|
557
578
|
});
|
|
558
579
|
import_ffi_client.FfiClient.instance.on(import_ffi_client.FfiClientEvent.FfiEvent, this.onFfiEvent);
|
|
559
580
|
try {
|
|
@@ -588,7 +609,7 @@ class Room extends import_events.default {
|
|
|
588
609
|
rp.trackPublications.set(publication.sid, publication);
|
|
589
610
|
}
|
|
590
611
|
}
|
|
591
|
-
this.updateConnectionState(
|
|
612
|
+
this.updateConnectionState(import_rtc_ffi_bindings4.ConnectionState.CONN_CONNECTED);
|
|
592
613
|
import_ffi_client.FfiClient.instance.request({
|
|
593
614
|
message: {
|
|
594
615
|
case: "readyForRoomEvent",
|
|
@@ -674,21 +695,16 @@ class Room extends import_events.default {
|
|
|
674
695
|
var _a, _b;
|
|
675
696
|
if (this.hasCleanedUp) return;
|
|
676
697
|
this.hasCleanedUp = true;
|
|
677
|
-
for (const [,
|
|
678
|
-
|
|
679
|
-
streamController.controller.error(new Error("Disconnected while receiving"));
|
|
680
|
-
} catch {
|
|
681
|
-
}
|
|
682
|
-
}
|
|
683
|
-
this.byteStreamControllers.clear();
|
|
684
|
-
for (const [, streamController] of this.textStreamControllers) {
|
|
698
|
+
for (const [, { controller, listener }] of this.streamReaders) {
|
|
699
|
+
import_ffi_client.FfiClient.instance.off(import_ffi_client.FfiClientEvent.FfiEvent, listener);
|
|
685
700
|
try {
|
|
686
|
-
|
|
701
|
+
controller.error(new Error("Disconnected while receiving"));
|
|
687
702
|
} catch {
|
|
688
703
|
}
|
|
689
704
|
}
|
|
690
|
-
this.
|
|
705
|
+
this.streamReaders.clear();
|
|
691
706
|
if (this.localParticipant) {
|
|
707
|
+
this.localParticipant.disposeOpenStreamWriters();
|
|
692
708
|
for (const pub of this.localParticipant.trackPublications.values()) {
|
|
693
709
|
(_a = pub.track) == null ? void 0 : _a.setRoom(null);
|
|
694
710
|
}
|
|
@@ -700,7 +716,7 @@ class Room extends import_events.default {
|
|
|
700
716
|
}
|
|
701
717
|
this.sidPromise = void 0;
|
|
702
718
|
this.disconnectController.abort();
|
|
703
|
-
this.updateConnectionState(
|
|
719
|
+
this.updateConnectionState(import_rtc_ffi_bindings4.ConnectionState.CONN_DISCONNECTED);
|
|
704
720
|
this.emit("disconnected" /* Disconnected */, reason);
|
|
705
721
|
}
|
|
706
722
|
/**
|
|
@@ -784,100 +800,130 @@ class Room extends import_events.default {
|
|
|
784
800
|
this.remoteParticipants.set(ownedInfo.info.identity, participant);
|
|
785
801
|
return participant;
|
|
786
802
|
}
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
start: (controller) => {
|
|
800
|
-
streamController = controller;
|
|
801
|
-
this.byteStreamControllers.set(streamHeader.streamId, {
|
|
802
|
-
header: streamHeader,
|
|
803
|
-
controller: streamController,
|
|
804
|
-
startTime: Date.now()
|
|
805
|
-
});
|
|
806
|
-
}
|
|
807
|
-
});
|
|
808
|
-
const info = {
|
|
809
|
-
streamId: streamHeader.streamId,
|
|
810
|
-
name: streamHeader.contentHeader.value.name ?? "unknown",
|
|
811
|
-
mimeType: streamHeader.mimeType,
|
|
812
|
-
totalSize: streamHeader.totalLength ? Number(streamHeader.totalLength) : void 0,
|
|
813
|
-
topic: streamHeader.topic,
|
|
814
|
-
timestamp: (0, import_utils.bigIntToNumber)(streamHeader.timestamp),
|
|
815
|
-
attributes: streamHeader.attributes
|
|
816
|
-
};
|
|
817
|
-
streamHandlerCallback(
|
|
818
|
-
new import_stream_reader.ByteStreamReader(info, stream, (0, import_utils.bigIntToNumber)(streamHeader.totalLength)),
|
|
819
|
-
{ identity: participantIdentity }
|
|
820
|
-
);
|
|
821
|
-
} else if (streamHeader.contentHeader.case === "textHeader") {
|
|
822
|
-
const streamHandlerCallback = this.textStreamHandlers.get(streamHeader.topic ?? "");
|
|
823
|
-
if (!streamHandlerCallback) {
|
|
824
|
-
import_log.log.debug(
|
|
825
|
-
"ignoring incoming text stream due to no handler for topic: %s",
|
|
826
|
-
streamHeader.topic ?? "undefined"
|
|
827
|
-
);
|
|
803
|
+
handleByteStreamOpened(ownedReader, participantIdentity) {
|
|
804
|
+
const info = (0, import_utils.byteStreamInfoFromProto)(ownedReader.info);
|
|
805
|
+
const readerHandle = ownedReader.handle.id;
|
|
806
|
+
const streamHandlerCallback = this.byteStreamHandlers.get(info.topic);
|
|
807
|
+
if (!streamHandlerCallback) {
|
|
808
|
+
import_log.log.debug("ignoring incoming byte stream due to no handler for topic: %s", info.topic);
|
|
809
|
+
new import_ffi_client.FfiHandle(readerHandle).dispose();
|
|
810
|
+
return;
|
|
811
|
+
}
|
|
812
|
+
let listener = null;
|
|
813
|
+
const unsubscribe = () => {
|
|
814
|
+
if (!listener) {
|
|
828
815
|
return;
|
|
829
816
|
}
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
817
|
+
import_ffi_client.FfiClient.instance.off(import_ffi_client.FfiClientEvent.FfiEvent, listener);
|
|
818
|
+
listener = null;
|
|
819
|
+
this.streamReaders.delete(readerHandle);
|
|
820
|
+
};
|
|
821
|
+
const stream = new ReadableStream({
|
|
822
|
+
start: (controller) => {
|
|
823
|
+
listener = (ev) => {
|
|
824
|
+
if (ev.message.case !== "byteStreamReaderEvent" || ev.message.value.readerHandle !== readerHandle) {
|
|
825
|
+
return;
|
|
826
|
+
}
|
|
827
|
+
const detail = ev.message.value.detail;
|
|
828
|
+
if (detail.case === "chunkReceived") {
|
|
829
|
+
const content = detail.value.content;
|
|
830
|
+
if (content.length > 0) {
|
|
831
|
+
controller.enqueue(new import_rtc_ffi_bindings4.DataStream_Chunk({ content }));
|
|
832
|
+
}
|
|
833
|
+
} else if (detail.case === "eos") {
|
|
834
|
+
unsubscribe();
|
|
835
|
+
const error = detail.value.error;
|
|
836
|
+
if (error) {
|
|
837
|
+
controller.error(new Error(error.description ?? "stream terminated"));
|
|
838
|
+
} else {
|
|
839
|
+
controller.close();
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
};
|
|
843
|
+
import_ffi_client.FfiClient.instance.on(import_ffi_client.FfiClientEvent.FfiEvent, listener);
|
|
844
|
+
this.streamReaders.set(readerHandle, { controller, listener });
|
|
845
|
+
import_ffi_client.FfiClient.instance.request({
|
|
846
|
+
message: {
|
|
847
|
+
case: "byteReadIncremental",
|
|
848
|
+
value: new import_rtc_ffi_bindings4.ByteStreamReaderReadIncrementalRequest({ readerHandle })
|
|
849
|
+
}
|
|
850
|
+
});
|
|
851
|
+
},
|
|
852
|
+
// The consumer stopped reading before end-of-stream — ByteStreamReader
|
|
853
|
+
// .close(), or breaking out of a for-await. The eos event that would have
|
|
854
|
+
// unsubscribed is never consumed, so the listener would otherwise be run
|
|
855
|
+
// against every FFI event for the rest of the process. Only the
|
|
856
|
+
// subscription is released: the reader handle was consumed by the
|
|
857
|
+
// readIncremental request above, so there is nothing left to dispose.
|
|
858
|
+
cancel: () => unsubscribe()
|
|
859
|
+
});
|
|
860
|
+
streamHandlerCallback(
|
|
861
|
+
new import_stream_reader.ByteStreamReader(info, stream, (0, import_utils.bigIntToNumber)(ownedReader.info.totalLength)),
|
|
862
|
+
{ identity: participantIdentity }
|
|
863
|
+
);
|
|
854
864
|
}
|
|
855
|
-
|
|
856
|
-
const
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
865
|
+
handleTextStreamOpened(ownedReader, participantIdentity) {
|
|
866
|
+
const info = (0, import_utils.textStreamInfoFromProto)(ownedReader.info);
|
|
867
|
+
const readerHandle = ownedReader.handle.id;
|
|
868
|
+
const streamHandlerCallback = this.textStreamHandlers.get(info.topic);
|
|
869
|
+
if (!streamHandlerCallback) {
|
|
870
|
+
import_log.log.debug("ignoring incoming text stream due to no handler for topic: %s", info.topic);
|
|
871
|
+
new import_ffi_client.FfiHandle(readerHandle).dispose();
|
|
872
|
+
return;
|
|
861
873
|
}
|
|
862
|
-
const
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
874
|
+
const textEncoder = new TextEncoder();
|
|
875
|
+
let listener = null;
|
|
876
|
+
const unsubscribe = () => {
|
|
877
|
+
if (!listener) {
|
|
878
|
+
return;
|
|
866
879
|
}
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
const
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
880
|
+
import_ffi_client.FfiClient.instance.off(import_ffi_client.FfiClientEvent.FfiEvent, listener);
|
|
881
|
+
listener = null;
|
|
882
|
+
this.streamReaders.delete(readerHandle);
|
|
883
|
+
};
|
|
884
|
+
const stream = new ReadableStream({
|
|
885
|
+
start: (controller) => {
|
|
886
|
+
listener = (ev) => {
|
|
887
|
+
if (ev.message.case !== "textStreamReaderEvent" || ev.message.value.readerHandle !== readerHandle) {
|
|
888
|
+
return;
|
|
889
|
+
}
|
|
890
|
+
const detail = ev.message.value.detail;
|
|
891
|
+
if (detail.case === "chunkReceived") {
|
|
892
|
+
const content = textEncoder.encode(detail.value.content);
|
|
893
|
+
if (content.length > 0) {
|
|
894
|
+
controller.enqueue(new import_rtc_ffi_bindings4.DataStream_Chunk({ content }));
|
|
895
|
+
}
|
|
896
|
+
} else if (detail.case === "eos") {
|
|
897
|
+
unsubscribe();
|
|
898
|
+
const error = detail.value.error;
|
|
899
|
+
if (error) {
|
|
900
|
+
controller.error(new Error(error.description ?? "stream terminated"));
|
|
901
|
+
} else {
|
|
902
|
+
controller.close();
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
};
|
|
906
|
+
import_ffi_client.FfiClient.instance.on(import_ffi_client.FfiClientEvent.FfiEvent, listener);
|
|
907
|
+
this.streamReaders.set(readerHandle, { controller, listener });
|
|
908
|
+
import_ffi_client.FfiClient.instance.request({
|
|
909
|
+
message: {
|
|
910
|
+
case: "textReadIncremental",
|
|
911
|
+
value: new import_rtc_ffi_bindings4.TextStreamReaderReadIncrementalRequest({ readerHandle })
|
|
912
|
+
}
|
|
913
|
+
});
|
|
914
|
+
},
|
|
915
|
+
// The consumer stopped reading before end-of-stream — TextStreamReader
|
|
916
|
+
// .close(), or breaking out of a for-await. The eos event that would have
|
|
917
|
+
// unsubscribed is never consumed, so the listener would otherwise be run
|
|
918
|
+
// against every FFI event for the rest of the process. Only the
|
|
919
|
+
// subscription is released: the reader handle was consumed by the
|
|
920
|
+
// readIncremental request above, so there is nothing left to dispose.
|
|
921
|
+
cancel: () => unsubscribe()
|
|
922
|
+
});
|
|
923
|
+
streamHandlerCallback(
|
|
924
|
+
new import_stream_reader.TextStreamReader(info, stream, (0, import_utils.bigIntToNumber)(ownedReader.info.totalLength)),
|
|
925
|
+
{ identity: participantIdentity }
|
|
926
|
+
);
|
|
881
927
|
}
|
|
882
928
|
}
|
|
883
929
|
class ConnectError extends Error {
|