@neurodevs/node-lsl 17.1.1 → 18.1.0

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 (198) hide show
  1. package/.claude/settings.local.json +10 -0
  2. package/.vscode/launch.json +54 -57
  3. package/.vscode/settings.json +61 -66
  4. package/.vscode/tasks.json +98 -129
  5. package/README.md +20 -44
  6. package/build/__tests__/AbstractPackageTest.d.ts +7 -5
  7. package/build/__tests__/AbstractPackageTest.js +22 -15
  8. package/build/__tests__/AbstractPackageTest.js.map +1 -1
  9. package/build/__tests__/impl/BleDeviceController.test.d.ts +54 -0
  10. package/build/__tests__/impl/BleDeviceController.test.js +333 -0
  11. package/build/__tests__/impl/BleDeviceController.test.js.map +1 -0
  12. package/build/__tests__/impl/LslEventMarkerEmitter.test.d.ts +34 -0
  13. package/build/__tests__/impl/LslEventMarkerEmitter.test.js +243 -0
  14. package/build/__tests__/impl/LslEventMarkerEmitter.test.js.map +1 -0
  15. package/build/__tests__/impl/LslStreamInfo.test.d.ts +0 -3
  16. package/build/__tests__/impl/LslStreamInfo.test.js +2 -27
  17. package/build/__tests__/impl/LslStreamInfo.test.js.map +1 -1
  18. package/build/__tests__/impl/LslStreamInlet.test.d.ts +20 -8
  19. package/build/__tests__/impl/LslStreamInlet.test.js +224 -69
  20. package/build/__tests__/impl/LslStreamInlet.test.js.map +1 -1
  21. package/build/__tests__/impl/LslStreamOutlet.test.d.ts +3 -7
  22. package/build/__tests__/impl/LslStreamOutlet.test.js +40 -50
  23. package/build/__tests__/impl/LslStreamOutlet.test.js.map +1 -1
  24. package/build/__tests__/impl/LslWebSocketBridge.test.js +19 -20
  25. package/build/__tests__/impl/LslWebSocketBridge.test.js.map +1 -1
  26. package/build/assertions.d.ts +1 -1
  27. package/build/assertions.js.map +1 -1
  28. package/build/impl/LslEventMarkerEmitter.d.ts +35 -0
  29. package/build/impl/LslEventMarkerEmitter.js +86 -0
  30. package/build/impl/LslEventMarkerEmitter.js.map +1 -0
  31. package/build/impl/LslStreamInfo.d.ts +4 -8
  32. package/build/impl/LslStreamInfo.js +8 -21
  33. package/build/impl/LslStreamInfo.js.map +1 -1
  34. package/build/impl/LslStreamInlet.d.ts +31 -50
  35. package/build/impl/LslStreamInlet.js +79 -149
  36. package/build/impl/LslStreamInlet.js.map +1 -1
  37. package/build/impl/LslStreamOutlet.d.ts +15 -18
  38. package/build/impl/LslStreamOutlet.js +39 -47
  39. package/build/impl/LslStreamOutlet.js.map +1 -1
  40. package/build/impl/LslWebSocketBridge.d.ts +4 -5
  41. package/build/impl/LslWebSocketBridge.js +10 -10
  42. package/build/impl/LslWebSocketBridge.js.map +1 -1
  43. package/build/impl/controllers/BleDeviceController.d.ts +58 -0
  44. package/build/impl/controllers/BleDeviceController.js +145 -0
  45. package/build/impl/controllers/BleDeviceController.js.map +1 -0
  46. package/build/impl/workers/inlet/LslStreamInlet.worker.d.ts +22 -0
  47. package/build/impl/workers/inlet/LslStreamInlet.worker.js +42 -0
  48. package/build/impl/workers/inlet/LslStreamInlet.worker.js.map +1 -0
  49. package/build/impl/workers/inlet/StreamInletWorker.d.ts +73 -0
  50. package/build/impl/workers/inlet/StreamInletWorker.js +253 -0
  51. package/build/impl/workers/inlet/StreamInletWorker.js.map +1 -0
  52. package/build/impl/workers/outlet/LslStreamOutlet.worker.d.ts +32 -0
  53. package/build/impl/workers/outlet/LslStreamOutlet.worker.js +82 -0
  54. package/build/impl/workers/outlet/LslStreamOutlet.worker.js.map +1 -0
  55. package/build/index.d.ts +14 -14
  56. package/build/index.js +16 -16
  57. package/build/index.js.map +1 -1
  58. package/build/scripts/discoverMuse.js +40 -0
  59. package/build/scripts/discoverMuse.js.map +1 -0
  60. package/build/scripts/finalizeHandles.d.ts +2 -0
  61. package/build/scripts/finalizeHandles.js +48 -0
  62. package/build/scripts/finalizeHandles.js.map +1 -0
  63. package/build/scripts/runLslEventMarkerEmitter.d.ts +1 -0
  64. package/build/scripts/runLslEventMarkerEmitter.js +11 -0
  65. package/build/scripts/runLslEventMarkerEmitter.js.map +1 -0
  66. package/build/scripts/runMuse.d.ts +1 -0
  67. package/build/scripts/runMuse.js +40 -0
  68. package/build/scripts/runMuse.js.map +1 -0
  69. package/build/scripts/runOutletToInlet.js +7 -6
  70. package/build/scripts/runOutletToInlet.js.map +1 -1
  71. package/build/scripts/testDestroyOutlet.d.ts +1 -0
  72. package/build/scripts/testDestroyOutlet.js +4 -0
  73. package/build/scripts/testDestroyOutlet.js.map +1 -0
  74. package/build/testDoubles/BleController/FakeBleController.d.ts +24 -0
  75. package/build/testDoubles/BleController/FakeBleController.js +42 -0
  76. package/build/testDoubles/BleController/FakeBleController.js.map +1 -0
  77. package/build/testDoubles/BleController/SpyBleController.d.ts +14 -0
  78. package/build/testDoubles/BleController/SpyBleController.js +48 -0
  79. package/build/testDoubles/BleController/SpyBleController.js.map +1 -0
  80. package/build/testDoubles/EventMarkerEmitter/FakeEventMarkerEmitter.d.ts +17 -0
  81. package/build/testDoubles/EventMarkerEmitter/FakeEventMarkerEmitter.js +30 -0
  82. package/build/testDoubles/EventMarkerEmitter/FakeEventMarkerEmitter.js.map +1 -0
  83. package/build/testDoubles/EventMarkerEmitter/SpyEventMarkerEmitter.d.ts +10 -0
  84. package/build/testDoubles/EventMarkerEmitter/SpyEventMarkerEmitter.js +23 -0
  85. package/build/testDoubles/EventMarkerEmitter/SpyEventMarkerEmitter.js.map +1 -0
  86. package/build/testDoubles/EventMarkerEmitter/ThrowingEventMarkerEmitter.d.ts +9 -0
  87. package/build/testDoubles/EventMarkerEmitter/ThrowingEventMarkerEmitter.js +19 -0
  88. package/build/testDoubles/EventMarkerEmitter/ThrowingEventMarkerEmitter.js.map +1 -0
  89. package/build/testDoubles/StreamInfo/FakeStreamInfo.d.ts +3 -3
  90. package/build/testDoubles/StreamInfo/FakeStreamInfo.js +3 -3
  91. package/build/testDoubles/StreamInfo/FakeStreamInfo.js.map +1 -1
  92. package/build/testDoubles/StreamInlet/FakeStreamInlet.d.ts +8 -10
  93. package/build/testDoubles/StreamInlet/FakeStreamInlet.js +6 -7
  94. package/build/testDoubles/StreamInlet/FakeStreamInlet.js.map +1 -1
  95. package/build/testDoubles/StreamInlet/SpyStreamInlet.d.ts +2 -5
  96. package/build/testDoubles/StreamInlet/SpyStreamInlet.js +2 -8
  97. package/build/testDoubles/StreamInlet/SpyStreamInlet.js.map +1 -1
  98. package/build/testDoubles/StreamOutlet/FakeStreamOutlet.d.ts +7 -9
  99. package/build/testDoubles/StreamOutlet/FakeStreamOutlet.js +8 -8
  100. package/build/testDoubles/StreamOutlet/FakeStreamOutlet.js.map +1 -1
  101. package/build/testDoubles/WebSocketBridge/FakeWebSocketBridge.d.ts +1 -1
  102. package/build/testDoubles/WebSocketBridge/FakeWebSocketBridge.js +1 -1
  103. package/build/testDoubles/WebSocketBridge/FakeWebSocketBridge.js.map +1 -1
  104. package/build/testDoubles/WorkerThreads/FakeWorker.d.ts +27 -0
  105. package/build/testDoubles/WorkerThreads/FakeWorker.js +67 -0
  106. package/build/testDoubles/WorkerThreads/FakeWorker.js.map +1 -0
  107. package/build/testDoubles/generateRandomOutletOptions.js +1 -1
  108. package/build/testDoubles/generateRandomOutletOptions.js.map +1 -1
  109. package/build/validations.js +0 -2
  110. package/build/validations.js.map +1 -1
  111. package/eslint.config.js +3 -0
  112. package/package.json +27 -49
  113. package/prettier.config.js +3 -0
  114. package/src/__tests__/AbstractPackageTest.ts +38 -21
  115. package/src/__tests__/impl/BleDeviceController.test.ts +492 -0
  116. package/src/__tests__/impl/LslEventMarkerEmitter.test.ts +323 -0
  117. package/src/__tests__/impl/LslStreamInfo.test.ts +3 -40
  118. package/src/__tests__/impl/LslStreamInlet.test.ts +344 -97
  119. package/src/__tests__/impl/LslStreamOutlet.test.ts +65 -73
  120. package/src/__tests__/impl/LslWebSocketBridge.test.ts +22 -21
  121. package/src/assertions.ts +2 -1
  122. package/src/impl/LslEventMarkerEmitter.ts +133 -0
  123. package/src/impl/LslStreamInfo.ts +17 -29
  124. package/src/impl/LslStreamInlet.ts +102 -215
  125. package/src/impl/LslStreamOutlet.ts +54 -78
  126. package/src/impl/LslWebSocketBridge.ts +14 -14
  127. package/src/impl/controllers/BleDeviceController.ts +223 -0
  128. package/src/impl/workers/inlet/LslStreamInlet.worker.ts +74 -0
  129. package/src/impl/workers/inlet/StreamInletWorker.ts +348 -0
  130. package/src/impl/workers/outlet/LslStreamOutlet.worker.ts +144 -0
  131. package/src/index.ts +16 -16
  132. package/src/scripts/discoverMuse.ts +50 -0
  133. package/src/scripts/finalizeHandles.ts +63 -0
  134. package/src/scripts/runLslEventMarkerEmitter.ts +15 -0
  135. package/src/scripts/runMuse.ts +50 -0
  136. package/src/scripts/runOutletToInlet.ts +10 -8
  137. package/src/scripts/testDestroyOutlet.ts +5 -0
  138. package/src/testDoubles/BleController/FakeBleController.ts +70 -0
  139. package/src/testDoubles/BleController/SpyBleController.ts +61 -0
  140. package/src/testDoubles/EventMarkerEmitter/FakeEventMarkerEmitter.ts +46 -0
  141. package/src/testDoubles/EventMarkerEmitter/SpyEventMarkerEmitter.ts +31 -0
  142. package/src/testDoubles/EventMarkerEmitter/ThrowingEventMarkerEmitter.ts +29 -0
  143. package/src/testDoubles/StreamInfo/FakeStreamInfo.ts +4 -4
  144. package/src/testDoubles/StreamInlet/FakeStreamInlet.ts +11 -17
  145. package/src/testDoubles/StreamInlet/SpyStreamInlet.ts +3 -16
  146. package/src/testDoubles/StreamOutlet/FakeStreamOutlet.ts +15 -15
  147. package/src/testDoubles/WebSocketBridge/FakeWebSocketBridge.ts +1 -1
  148. package/src/testDoubles/WorkerThreads/FakeWorker.ts +99 -0
  149. package/src/testDoubles/generateRandomOutletOptions.ts +2 -1
  150. package/src/validations.ts +0 -2
  151. package/tsconfig.json +23 -27
  152. package/build/.spruce/settings.json +0 -11
  153. package/build/__tests__/impl/LiblslAdapter.test.d.ts +0 -79
  154. package/build/__tests__/impl/LiblslAdapter.test.js +0 -688
  155. package/build/__tests__/impl/LiblslAdapter.test.js.map +0 -1
  156. package/build/__tests__/impl/LslEventMarkerOutlet.test.d.ts +0 -21
  157. package/build/__tests__/impl/LslEventMarkerOutlet.test.js +0 -160
  158. package/build/__tests__/impl/LslEventMarkerOutlet.test.js.map +0 -1
  159. package/build/handleError.d.ts +0 -8
  160. package/build/handleError.js +0 -25
  161. package/build/handleError.js.map +0 -1
  162. package/build/impl/LiblslAdapter.d.ts +0 -154
  163. package/build/impl/LiblslAdapter.js +0 -317
  164. package/build/impl/LiblslAdapter.js.map +0 -1
  165. package/build/impl/LslEventMarkerOutlet.d.ts +0 -28
  166. package/build/impl/LslEventMarkerOutlet.js +0 -63
  167. package/build/impl/LslEventMarkerOutlet.js.map +0 -1
  168. package/build/scripts/runLslEventMarkerOutlet.js +0 -18
  169. package/build/scripts/runLslEventMarkerOutlet.js.map +0 -1
  170. package/build/testDoubles/EventMarkerOutlet/FakeEventMarkerOutlet.d.ts +0 -13
  171. package/build/testDoubles/EventMarkerOutlet/FakeEventMarkerOutlet.js +0 -26
  172. package/build/testDoubles/EventMarkerOutlet/FakeEventMarkerOutlet.js.map +0 -1
  173. package/build/testDoubles/EventMarkerOutlet/MockEventMarkerOutlet.d.ts +0 -17
  174. package/build/testDoubles/EventMarkerOutlet/MockEventMarkerOutlet.js +0 -46
  175. package/build/testDoubles/EventMarkerOutlet/MockEventMarkerOutlet.js.map +0 -1
  176. package/build/testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.d.ts +0 -9
  177. package/build/testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.js +0 -19
  178. package/build/testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.js.map +0 -1
  179. package/build/testDoubles/EventMarkerOutlet/ThrowingEventMarkerOutlet.d.ts +0 -9
  180. package/build/testDoubles/EventMarkerOutlet/ThrowingEventMarkerOutlet.js +0 -19
  181. package/build/testDoubles/EventMarkerOutlet/ThrowingEventMarkerOutlet.js.map +0 -1
  182. package/build/testDoubles/Liblsl/FakeLiblsl.d.ts +0 -50
  183. package/build/testDoubles/Liblsl/FakeLiblsl.js +0 -126
  184. package/build/testDoubles/Liblsl/FakeLiblsl.js.map +0 -1
  185. package/eslint.config.mjs +0 -3
  186. package/src/.spruce/settings.json +0 -11
  187. package/src/__tests__/impl/LiblslAdapter.test.ts +0 -817
  188. package/src/__tests__/impl/LslEventMarkerOutlet.test.ts +0 -195
  189. package/src/handleError.ts +0 -24
  190. package/src/impl/LiblslAdapter.ts +0 -543
  191. package/src/impl/LslEventMarkerOutlet.ts +0 -97
  192. package/src/scripts/runLslEventMarkerOutlet.ts +0 -23
  193. package/src/testDoubles/EventMarkerOutlet/FakeEventMarkerOutlet.ts +0 -36
  194. package/src/testDoubles/EventMarkerOutlet/MockEventMarkerOutlet.ts +0 -75
  195. package/src/testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.ts +0 -24
  196. package/src/testDoubles/EventMarkerOutlet/ThrowingEventMarkerOutlet.ts +0 -28
  197. package/src/testDoubles/Liblsl/FakeLiblsl.ts +0 -182
  198. /package/build/scripts/{runLslEventMarkerOutlet.d.ts → discoverMuse.d.ts} +0 -0
@@ -0,0 +1,58 @@
1
+ import { Libndx, NativePeripheral } from '@neurodevs/ndx-native';
2
+ export default class BleDeviceController implements BleController {
3
+ static Class?: BleControllerConstructor;
4
+ static setTimeout: typeof setTimeout;
5
+ static waitAfterMs: number;
6
+ private static _ndx?;
7
+ static get ndx(): Libndx;
8
+ static set ndx(value: Libndx);
9
+ protected charCallbacks: CharacteristicCallbacks;
10
+ protected rssiIntervalMs?: number;
11
+ protected connected: boolean;
12
+ protected log: Console;
13
+ private deviceUuid?;
14
+ private deviceNamePrefix?;
15
+ private deviceName?;
16
+ private onConnected?;
17
+ protected constructor(options: BleControllerOptions);
18
+ static Create(options: BleControllerOptions): Promise<BleDeviceController | BleController>;
19
+ connect(): Promise<void>;
20
+ private discoverUuid;
21
+ private waitForDiscoveredUuid;
22
+ private createBleBackend;
23
+ private throwIfError;
24
+ private setBleRssiInterval;
25
+ private startBleBackend;
26
+ private waitForOnConnected;
27
+ private waitToDiscoverServices;
28
+ writeCharacteristic(charUuid: CharacteristicUuid, value: string): Promise<void>;
29
+ disconnect(): Promise<void>;
30
+ get uuid(): string;
31
+ get name(): string;
32
+ private get ndx();
33
+ }
34
+ export interface BleController {
35
+ uuid: string;
36
+ name: string;
37
+ connect(): Promise<void>;
38
+ writeCharacteristic(charUuid: CharacteristicUuid, value: string): Promise<void>;
39
+ disconnect(): Promise<void>;
40
+ }
41
+ export type BleControllerOptions = {
42
+ charCallbacks: CharacteristicCallbacks;
43
+ onConnected?: (peripheral: NativePeripheral) => void;
44
+ rssiIntervalMs?: number;
45
+ } & ({
46
+ deviceUuid: string;
47
+ deviceNamePrefix?: string;
48
+ } | {
49
+ deviceUuid?: string;
50
+ deviceNamePrefix: string;
51
+ });
52
+ export type BleControllerConstructor = new (options: BleControllerOptions) => BleController;
53
+ export type CharacteristicCallbacks = {
54
+ charUuid: string;
55
+ charName?: string;
56
+ onData: (data: Buffer, length: number, timestampSec: number) => void;
57
+ }[];
58
+ export type CharacteristicUuid = string;
@@ -0,0 +1,145 @@
1
+ import { LibndxAdapter } from '@neurodevs/ndx-native';
2
+ export default class BleDeviceController {
3
+ static Class;
4
+ static setTimeout = setTimeout;
5
+ static waitAfterMs = 1000;
6
+ static _ndx;
7
+ static get ndx() {
8
+ if (!this._ndx) {
9
+ this._ndx = LibndxAdapter.getInstance();
10
+ }
11
+ return this._ndx;
12
+ }
13
+ static set ndx(value) {
14
+ this._ndx = value;
15
+ }
16
+ charCallbacks;
17
+ rssiIntervalMs;
18
+ connected = false;
19
+ log = console;
20
+ deviceUuid;
21
+ deviceNamePrefix;
22
+ deviceName;
23
+ onConnected;
24
+ constructor(options) {
25
+ const { deviceUuid, deviceNamePrefix, charCallbacks, onConnected, rssiIntervalMs, } = options;
26
+ this.deviceUuid = deviceUuid;
27
+ this.deviceNamePrefix = deviceNamePrefix;
28
+ this.charCallbacks = charCallbacks;
29
+ this.onConnected = onConnected;
30
+ this.rssiIntervalMs = rssiIntervalMs;
31
+ }
32
+ static async Create(options) {
33
+ return new (this.Class ?? this)(options);
34
+ }
35
+ async connect() {
36
+ if (!this.deviceUuid) {
37
+ await this.discoverUuid();
38
+ }
39
+ this.createBleBackend();
40
+ this.startBleBackend();
41
+ await this.waitForOnConnected();
42
+ await this.waitToDiscoverServices();
43
+ this.setBleRssiInterval();
44
+ }
45
+ async discoverUuid() {
46
+ const { status, error } = this.ndx.discoverBleUuid({
47
+ namePrefix: this.deviceNamePrefix,
48
+ onDiscovered: (uuid) => {
49
+ this.deviceUuid = uuid;
50
+ },
51
+ });
52
+ this.throwIfError(status, error);
53
+ await this.waitForDiscoveredUuid();
54
+ }
55
+ async waitForDiscoveredUuid() {
56
+ await new Promise((resolve) => {
57
+ const checkDiscovered = () => {
58
+ if (this.deviceUuid) {
59
+ resolve();
60
+ }
61
+ else {
62
+ BleDeviceController.setTimeout(checkDiscovered, 100);
63
+ }
64
+ };
65
+ checkDiscovered();
66
+ });
67
+ }
68
+ createBleBackend() {
69
+ const { status, error } = this.ndx.createBleBackend({
70
+ deviceUuid: this.uuid,
71
+ });
72
+ this.throwIfError(status, error);
73
+ }
74
+ throwIfError(status, error) {
75
+ if (status !== 200) {
76
+ throw new Error(`${status} error: ${error ?? 'Unknown error'}`);
77
+ }
78
+ }
79
+ setBleRssiInterval() {
80
+ if (this.rssiIntervalMs) {
81
+ this.ndx.setBleRssiInterval({
82
+ deviceUuid: this.uuid,
83
+ intervalMs: this.rssiIntervalMs,
84
+ onRssi: (rssi) => {
85
+ this.log.info(`[RSSI=${rssi}]`);
86
+ },
87
+ });
88
+ }
89
+ }
90
+ startBleBackend() {
91
+ const { status, error } = this.ndx.startBleBackend({
92
+ deviceUuid: this.uuid,
93
+ onConnected: (peripheral) => {
94
+ const { name } = peripheral;
95
+ this.deviceName = name;
96
+ this.connected = true;
97
+ this.log.info(`Connected to device ${this.uuid}!`);
98
+ this.onConnected?.(peripheral);
99
+ },
100
+ charCallbacks: this.charCallbacks,
101
+ });
102
+ this.throwIfError(status, error);
103
+ }
104
+ async waitForOnConnected() {
105
+ await new Promise((resolve) => {
106
+ const checkConnected = () => {
107
+ if (this.connected) {
108
+ resolve();
109
+ }
110
+ else {
111
+ BleDeviceController.setTimeout(checkConnected, 100);
112
+ }
113
+ };
114
+ checkConnected();
115
+ });
116
+ }
117
+ async waitToDiscoverServices() {
118
+ await new Promise((resolve) => BleDeviceController.setTimeout(resolve, BleDeviceController.waitAfterMs));
119
+ }
120
+ async writeCharacteristic(charUuid, value) {
121
+ const { status, error } = this.ndx.writeBleCharacteristic({
122
+ deviceUuid: this.uuid,
123
+ charUuid,
124
+ value,
125
+ });
126
+ this.throwIfError(status, error);
127
+ }
128
+ async disconnect() {
129
+ const { status, error } = this.ndx.stopBleBackend({
130
+ deviceUuid: this.uuid,
131
+ });
132
+ this.throwIfError(status, error);
133
+ this.connected = false;
134
+ }
135
+ get uuid() {
136
+ return this.deviceUuid ?? '';
137
+ }
138
+ get name() {
139
+ return this.deviceName ?? 'N/A';
140
+ }
141
+ get ndx() {
142
+ return BleDeviceController.ndx;
143
+ }
144
+ }
145
+ //# sourceMappingURL=BleDeviceController.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BleDeviceController.js","sourceRoot":"","sources":["../../../src/impl/controllers/BleDeviceController.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ export type InletMessage = {
2
+ type: 'createInlet';
3
+ payload: CreateInletPayload;
4
+ } | {
5
+ type: 'startPulling';
6
+ } | {
7
+ type: 'flushInlet';
8
+ } | {
9
+ type: 'stopPulling';
10
+ } | {
11
+ type: 'destroyInlet';
12
+ };
13
+ export interface CreateInletPayload {
14
+ sourceId: string;
15
+ chunkSize: number;
16
+ maxBufferedMs: number;
17
+ openStreamTimeoutMs: number;
18
+ waitAfterOpenStreamMs: number;
19
+ pullTimeoutMs: number;
20
+ waitBetweenPullsMs: number;
21
+ flushInletOnStop: boolean;
22
+ }
@@ -0,0 +1,42 @@
1
+ import { parentPort } from 'node:worker_threads';
2
+ import StreamInletWorker from './StreamInletWorker.js';
3
+ const worker = new StreamInletWorker();
4
+ parentPort?.on('message', async (msg) => {
5
+ try {
6
+ switch (msg.type) {
7
+ case 'createInlet':
8
+ const { payload } = msg;
9
+ await worker.createInlet(payload);
10
+ parentPort?.postMessage({ type: 'ready' });
11
+ break;
12
+ case 'startPulling':
13
+ worker.startPulling((samples, timestamps) => {
14
+ parentPort?.postMessage({
15
+ type: 'data',
16
+ payload: {
17
+ samples,
18
+ timestamps,
19
+ },
20
+ });
21
+ });
22
+ break;
23
+ case 'stopPulling':
24
+ worker.stopPulling();
25
+ break;
26
+ case 'flushInlet':
27
+ worker.flushInlet();
28
+ break;
29
+ case 'destroyInlet':
30
+ worker.destroyInlet();
31
+ parentPort?.close();
32
+ break;
33
+ }
34
+ }
35
+ catch (err) {
36
+ parentPort?.postMessage({
37
+ type: 'error',
38
+ error: err instanceof Error ? err.message : String(err),
39
+ });
40
+ }
41
+ });
42
+ //# sourceMappingURL=LslStreamInlet.worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LslStreamInlet.worker.js","sourceRoot":"","sources":["../../../../src/impl/workers/inlet/LslStreamInlet.worker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAChD,OAAO,iBAAiB,MAAM,wBAAwB,CAAA;AAEtD,MAAM,MAAM,GAAG,IAAI,iBAAiB,EAAE,CAAA;AAEtC,UAAU,EAAE,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,GAAiB,EAAE,EAAE;IAClD,IAAI,CAAC;QACD,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;YACf,KAAK,aAAa;gBACd,MAAM,EAAE,OAAO,EAAE,GAAG,GAAG,CAAA;gBACvB,MAAM,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAA;gBACjC,UAAU,EAAE,WAAW,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAA;gBAC1C,MAAK;YAET,KAAK,cAAc;gBACf,MAAM,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,UAAU,EAAE,EAAE;oBACxC,UAAU,EAAE,WAAW,CAAC;wBACpB,IAAI,EAAE,MAAM;wBACZ,OAAO,EAAE;4BACL,OAAO;4BACP,UAAU;yBACb;qBACJ,CAAC,CAAA;gBACN,CAAC,CAAC,CAAA;gBACF,MAAK;YAET,KAAK,aAAa;gBACd,MAAM,CAAC,WAAW,EAAE,CAAA;gBACpB,MAAK;YACT,KAAK,YAAY;gBACb,MAAM,CAAC,UAAU,EAAE,CAAA;gBACnB,MAAK;YAET,KAAK,cAAc;gBACf,MAAM,CAAC,YAAY,EAAE,CAAA;gBACrB,UAAU,EAAE,KAAK,EAAE,CAAA;gBACnB,MAAK;QACb,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACX,UAAU,EAAE,WAAW,CAAC;YACpB,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;SAC1D,CAAC,CAAA;IACN,CAAC;AACL,CAAC,CAAC,CAAA"}
@@ -0,0 +1,73 @@
1
+ import { handleLslError, InfoHandle, InletHandle } from '@neurodevs/ndx-native';
2
+ import { freePointer } from 'ffi-rs';
3
+ import { OnDataCallback } from '../../LslStreamInlet.js';
4
+ import { CreateInletPayload } from './LslStreamInlet.worker.js';
5
+ export default class StreamInletWorker {
6
+ static lsl: import("@neurodevs/ndx-native").Liblsl;
7
+ static handleLslError: typeof handleLslError;
8
+ static freePointer: typeof freePointer;
9
+ private sourceId;
10
+ private chunkSize;
11
+ private maxBufferedMs;
12
+ private openStreamTimeoutMs;
13
+ private waitAfterOpenStreamMs;
14
+ private waitBetweenPullsMs;
15
+ private pullTimeoutMs;
16
+ private flushInletOnStop;
17
+ private pullMethod;
18
+ protected infoHandle: InfoHandle;
19
+ protected inletHandle: InletHandle;
20
+ private channelCount;
21
+ private sampleBuffer;
22
+ private sampleBufferRef;
23
+ private sampleBufferPtr;
24
+ private timestampBuffer;
25
+ private timestampBufferRef;
26
+ private timestampBufferPtr;
27
+ private pullErrorBuffer;
28
+ private pullErrorBufferRef;
29
+ private pullErrorBufferPtr;
30
+ private openStreamErrorBuffer;
31
+ private openStreamErrorBufferRef;
32
+ private openStreamErrorBufferPtr;
33
+ private onData;
34
+ private readonly bytesPerFloat;
35
+ private readonly bytesPerDouble;
36
+ private readonly bytesPerI32;
37
+ private isRunning;
38
+ createInlet(payload: CreateInletPayload): Promise<void>;
39
+ private resolveInfoHandle;
40
+ private resolveByProp;
41
+ private throwNoStreamFound;
42
+ private warnMultipleStreamsFound;
43
+ private doCreateInlet;
44
+ private getChannelCount;
45
+ private allocateWritableBuffers;
46
+ private allocateDataBuffer;
47
+ private allocateTimestampBuffer;
48
+ private allocatePullErrorBuffer;
49
+ private allocateOpenStreamErrorBuffer;
50
+ private setPullMethod;
51
+ private pullSample;
52
+ private doPullsample;
53
+ private readSamplesFromBuffer;
54
+ private pullChunk;
55
+ private doPullChunk;
56
+ private readTimestampsFromBuffer;
57
+ private openStream;
58
+ private waitForSetup;
59
+ startPulling(onData: OnDataCallback): void;
60
+ private pullLoop;
61
+ private pullDataOnce;
62
+ private handleLslErrorIfPresent;
63
+ private waitBetweenPulls;
64
+ flushInlet(): void;
65
+ stopPulling(): void;
66
+ private closeStream;
67
+ destroyInlet(): void;
68
+ private doDestroyInlet;
69
+ private freeNativePointers;
70
+ private get lsl();
71
+ private get handleLslError();
72
+ private get freePointer();
73
+ }
@@ -0,0 +1,253 @@
1
+ import { handleLslError, LiblslAdapter, } from '@neurodevs/ndx-native';
2
+ import { unwrapPointer, createPointer, DataType, freePointer, PointerType, } from 'ffi-rs';
3
+ export default class StreamInletWorker {
4
+ static lsl = LiblslAdapter.getInstance();
5
+ static handleLslError = handleLslError;
6
+ static freePointer = freePointer;
7
+ sourceId;
8
+ chunkSize;
9
+ maxBufferedMs;
10
+ openStreamTimeoutMs;
11
+ waitAfterOpenStreamMs;
12
+ waitBetweenPullsMs;
13
+ pullTimeoutMs;
14
+ flushInletOnStop;
15
+ pullMethod;
16
+ infoHandle;
17
+ inletHandle;
18
+ channelCount;
19
+ sampleBuffer;
20
+ sampleBufferRef;
21
+ sampleBufferPtr;
22
+ timestampBuffer;
23
+ timestampBufferRef;
24
+ timestampBufferPtr;
25
+ pullErrorBuffer;
26
+ pullErrorBufferRef;
27
+ pullErrorBufferPtr;
28
+ openStreamErrorBuffer;
29
+ openStreamErrorBufferRef;
30
+ openStreamErrorBufferPtr;
31
+ onData;
32
+ bytesPerFloat = 4;
33
+ bytesPerDouble = 8;
34
+ bytesPerI32 = 4;
35
+ isRunning = false;
36
+ async createInlet(payload) {
37
+ Object.assign(this, payload);
38
+ this.infoHandle = this.resolveInfoHandle();
39
+ this.inletHandle = this.doCreateInlet();
40
+ this.channelCount = this.getChannelCount();
41
+ this.allocateWritableBuffers();
42
+ this.setPullMethod();
43
+ this.openStream();
44
+ await this.waitForSetup();
45
+ }
46
+ resolveInfoHandle() {
47
+ const handles = this.resolveByProp();
48
+ if (handles.length === 0) {
49
+ this.throwNoStreamFound();
50
+ }
51
+ else if (handles.length > 1) {
52
+ this.warnMultipleStreamsFound();
53
+ }
54
+ return handles[0];
55
+ }
56
+ resolveByProp() {
57
+ return this.lsl.resolveByProp({
58
+ prop: 'source_id',
59
+ value: this.sourceId,
60
+ });
61
+ }
62
+ throwNoStreamFound() {
63
+ throw new Error(`No stream info for sourceId "${this.sourceId}"`);
64
+ }
65
+ warnMultipleStreamsFound() {
66
+ console.warn(`Multiple stream infos for sourceId "${this.sourceId}", using the first one.`);
67
+ }
68
+ doCreateInlet() {
69
+ return this.lsl.createInlet({
70
+ infoHandle: this.infoHandle,
71
+ maxBufferedMs: this.maxBufferedMs,
72
+ });
73
+ }
74
+ getChannelCount() {
75
+ return this.lsl.getChannelCount({ infoHandle: this.infoHandle });
76
+ }
77
+ allocateWritableBuffers() {
78
+ this.allocateDataBuffer();
79
+ this.allocateTimestampBuffer();
80
+ this.allocatePullErrorBuffer();
81
+ this.allocateOpenStreamErrorBuffer();
82
+ }
83
+ allocateDataBuffer() {
84
+ this.sampleBuffer = Buffer.alloc(this.channelCount * this.chunkSize * this.bytesPerFloat);
85
+ this.sampleBufferRef = createPointer({
86
+ paramsType: [DataType.U8Array],
87
+ paramsValue: [this.sampleBuffer],
88
+ });
89
+ this.sampleBufferPtr = unwrapPointer(this.sampleBufferRef)[0];
90
+ }
91
+ allocateTimestampBuffer() {
92
+ this.timestampBuffer = Buffer.alloc(this.chunkSize * this.bytesPerDouble);
93
+ this.timestampBufferRef = createPointer({
94
+ paramsType: [DataType.U8Array],
95
+ paramsValue: [this.timestampBuffer],
96
+ });
97
+ this.timestampBufferPtr = unwrapPointer(this.timestampBufferRef)[0];
98
+ }
99
+ allocatePullErrorBuffer() {
100
+ this.pullErrorBuffer = Buffer.alloc(this.bytesPerI32);
101
+ this.pullErrorBufferRef = createPointer({
102
+ paramsType: [DataType.U8Array],
103
+ paramsValue: [this.pullErrorBuffer],
104
+ });
105
+ this.pullErrorBufferPtr = unwrapPointer(this.pullErrorBufferRef)[0];
106
+ }
107
+ allocateOpenStreamErrorBuffer() {
108
+ this.openStreamErrorBuffer = Buffer.alloc(this.bytesPerI32);
109
+ this.openStreamErrorBufferRef = createPointer({
110
+ paramsType: [DataType.U8Array],
111
+ paramsValue: [this.openStreamErrorBuffer],
112
+ });
113
+ this.openStreamErrorBufferPtr = unwrapPointer(this.openStreamErrorBufferRef)[0];
114
+ }
115
+ setPullMethod() {
116
+ this.pullMethod =
117
+ this.chunkSize === 1 ? this.pullSample : this.pullChunk;
118
+ }
119
+ pullSample = () => {
120
+ const timestampSec = this.doPullsample();
121
+ if (timestampSec > 0) {
122
+ return {
123
+ samples: this.readSamplesFromBuffer(),
124
+ timestamps: [timestampSec],
125
+ };
126
+ }
127
+ return { samples: undefined, timestamps: undefined };
128
+ };
129
+ doPullsample() {
130
+ return this.lsl.pullSample({
131
+ inletHandle: this.inletHandle,
132
+ sampleBufferPtr: this.sampleBufferPtr,
133
+ sampleBufferElements: this.channelCount,
134
+ timeoutMs: this.pullTimeoutMs,
135
+ errorCodePtr: this.pullErrorBufferPtr,
136
+ });
137
+ }
138
+ readSamplesFromBuffer() {
139
+ const floats = new Float32Array(this.sampleBuffer.buffer, this.sampleBuffer.byteOffset, this.chunkSize * this.channelCount);
140
+ return Array.from(floats);
141
+ }
142
+ pullChunk = () => {
143
+ const firstTimestampSec = this.doPullChunk();
144
+ if (firstTimestampSec > 0) {
145
+ return {
146
+ samples: this.readSamplesFromBuffer(),
147
+ timestamps: this.readTimestampsFromBuffer(),
148
+ };
149
+ }
150
+ return { samples: undefined, timestamps: undefined };
151
+ };
152
+ doPullChunk() {
153
+ return this.lsl.pullChunk({
154
+ inletHandle: this.inletHandle,
155
+ sampleBufferPtr: this.sampleBufferPtr,
156
+ sampleBufferElements: this.chunkSize * this.channelCount,
157
+ timestampBufferPtr: this.timestampBufferPtr,
158
+ timestampBufferElements: this.chunkSize,
159
+ timeoutMs: this.pullTimeoutMs,
160
+ errorCodePtr: this.pullErrorBufferPtr,
161
+ });
162
+ }
163
+ readTimestampsFromBuffer() {
164
+ const doubles = new Float64Array(this.timestampBuffer.buffer, this.timestampBuffer.byteOffset, this.chunkSize);
165
+ return Array.from(doubles);
166
+ }
167
+ openStream() {
168
+ this.lsl.openStream({
169
+ inletHandle: this.inletHandle,
170
+ timeoutMs: this.openStreamTimeoutMs,
171
+ errorCodePtr: this.openStreamErrorBufferPtr,
172
+ });
173
+ }
174
+ async waitForSetup() {
175
+ return new Promise((r) => setTimeout(r, this.waitAfterOpenStreamMs));
176
+ }
177
+ startPulling(onData) {
178
+ if (this.isRunning) {
179
+ console.warn('StreamInletWorker is already running.');
180
+ return;
181
+ }
182
+ this.isRunning = true;
183
+ this.onData = onData;
184
+ void this.pullLoop();
185
+ }
186
+ async pullLoop() {
187
+ while (this.isRunning) {
188
+ await this.pullDataOnce();
189
+ await this.waitBetweenPulls();
190
+ }
191
+ }
192
+ async pullDataOnce() {
193
+ const { samples, timestamps } = this.pullMethod();
194
+ this.handleLslErrorIfPresent();
195
+ if (samples && timestamps) {
196
+ this.onData(samples, timestamps);
197
+ }
198
+ }
199
+ handleLslErrorIfPresent() {
200
+ const errorCode = this.pullErrorBuffer.readInt32LE();
201
+ this.handleLslError(errorCode);
202
+ }
203
+ async waitBetweenPulls() {
204
+ await new Promise((r) => setTimeout(r, this.waitBetweenPullsMs));
205
+ }
206
+ flushInlet() {
207
+ this.lsl.flushInlet({ inletHandle: this.inletHandle });
208
+ }
209
+ stopPulling() {
210
+ this.isRunning = false;
211
+ this.closeStream();
212
+ if (this.flushInletOnStop) {
213
+ this.flushInlet();
214
+ }
215
+ }
216
+ closeStream() {
217
+ this.lsl.closeStream({ inletHandle: this.inletHandle });
218
+ }
219
+ destroyInlet() {
220
+ this.doDestroyInlet();
221
+ this.freeNativePointers();
222
+ }
223
+ doDestroyInlet() {
224
+ this.lsl.destroyInlet({ inletHandle: this.inletHandle });
225
+ }
226
+ freeNativePointers() {
227
+ this.freePointer({
228
+ paramsType: [
229
+ DataType.U8Array,
230
+ DataType.U8Array,
231
+ DataType.U8Array,
232
+ DataType.U8Array,
233
+ ],
234
+ paramsValue: [
235
+ this.openStreamErrorBufferPtr,
236
+ this.sampleBufferPtr,
237
+ this.timestampBufferPtr,
238
+ this.pullErrorBufferPtr,
239
+ ],
240
+ pointerType: PointerType.CPointer,
241
+ });
242
+ }
243
+ get lsl() {
244
+ return StreamInletWorker.lsl;
245
+ }
246
+ get handleLslError() {
247
+ return StreamInletWorker.handleLslError;
248
+ }
249
+ get freePointer() {
250
+ return StreamInletWorker.freePointer;
251
+ }
252
+ }
253
+ //# sourceMappingURL=StreamInletWorker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StreamInletWorker.js","sourceRoot":"","sources":["../../../../src/impl/workers/inlet/StreamInletWorker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import { Liblsl, handleLslError } from '@neurodevs/ndx-native';
2
+ import { StreamInfoOptions } from '../../LslStreamInfo.js';
3
+ export declare function setOutletLiblslAdapter(adapter: Liblsl): void;
4
+ export declare function setOutletHandleLslError(fn: typeof handleLslError): void;
5
+ export declare function createOutlet(msg: {
6
+ type: 'createOutlet';
7
+ payload: CreateOutletPayload;
8
+ }): void;
9
+ export declare function pushSample(msg: {
10
+ type: 'pushSample';
11
+ payload: PushSamplePayload;
12
+ }): void;
13
+ export declare function destroyOutlet(): void;
14
+ export type OutletMessage = {
15
+ type: 'createOutlet';
16
+ payload: CreateOutletPayload;
17
+ } | {
18
+ type: 'pushSample';
19
+ payload: PushSamplePayload;
20
+ } | {
21
+ type: 'destroyOutlet';
22
+ };
23
+ export interface CreateOutletPayload {
24
+ infoOptions: StreamInfoOptions;
25
+ chunkSize: number;
26
+ maxBufferedMs: number;
27
+ pushMethod: 'pushSampleFloatTimestamp' | 'pushSampleStringTimestamp';
28
+ }
29
+ export interface PushSamplePayload {
30
+ sample: unknown;
31
+ timestampSec?: number;
32
+ }