@neurodevs/node-lsl 17.1.0 → 18.0.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 (178) hide show
  1. package/.claude/settings.local.json +10 -0
  2. package/.regressionproof.json +7 -0
  3. package/.vscode/launch.json +3 -2
  4. package/README.md +9 -35
  5. package/build/.spruce/settings.json +5 -1
  6. package/build/__tests__/AbstractPackageTest.d.ts +4 -4
  7. package/build/__tests__/AbstractPackageTest.js +9 -11
  8. package/build/__tests__/AbstractPackageTest.js.map +1 -1
  9. package/build/__tests__/impl/LslBackpressureMonitor.test.d.ts +7 -0
  10. package/build/__tests__/impl/LslBackpressureMonitor.test.js +26 -0
  11. package/build/__tests__/impl/LslBackpressureMonitor.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 +22 -8
  19. package/build/__tests__/impl/LslStreamInlet.test.js +240 -66
  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 +36 -46
  23. package/build/__tests__/impl/LslStreamOutlet.test.js.map +1 -1
  24. package/build/__tests__/impl/LslWebSocketBridge.test.js +16 -17
  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/LslBackpressureMonitor.d.ts +8 -0
  29. package/build/impl/LslBackpressureMonitor.js +8 -0
  30. package/build/impl/LslBackpressureMonitor.js.map +1 -0
  31. package/build/impl/LslEventMarkerEmitter.d.ts +35 -0
  32. package/build/impl/LslEventMarkerEmitter.js +86 -0
  33. package/build/impl/LslEventMarkerEmitter.js.map +1 -0
  34. package/build/impl/LslStreamInfo.d.ts +4 -8
  35. package/build/impl/LslStreamInfo.js +8 -21
  36. package/build/impl/LslStreamInfo.js.map +1 -1
  37. package/build/impl/LslStreamInlet.d.ts +31 -47
  38. package/build/impl/LslStreamInlet.js +82 -143
  39. package/build/impl/LslStreamInlet.js.map +1 -1
  40. package/build/impl/LslStreamOutlet.d.ts +15 -18
  41. package/build/impl/LslStreamOutlet.js +39 -47
  42. package/build/impl/LslStreamOutlet.js.map +1 -1
  43. package/build/impl/LslWebSocketBridge.d.ts +4 -5
  44. package/build/impl/LslWebSocketBridge.js +8 -8
  45. package/build/impl/LslWebSocketBridge.js.map +1 -1
  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 +12 -14
  56. package/build/index.js +14 -16
  57. package/build/index.js.map +1 -1
  58. package/build/scripts/finalizeHandles.d.ts +2 -0
  59. package/build/scripts/finalizeHandles.js +48 -0
  60. package/build/scripts/finalizeHandles.js.map +1 -0
  61. package/build/scripts/runLslEventMarkerEmitter.js +11 -0
  62. package/build/scripts/runLslEventMarkerEmitter.js.map +1 -0
  63. package/build/scripts/runOutletToInlet.js +7 -6
  64. package/build/scripts/runOutletToInlet.js.map +1 -1
  65. package/build/scripts/testDestroyOutlet.d.ts +1 -0
  66. package/build/scripts/testDestroyOutlet.js +4 -0
  67. package/build/scripts/testDestroyOutlet.js.map +1 -0
  68. package/build/testDoubles/BackpressureMonitor/FakeBackpressureMonitor.d.ts +6 -0
  69. package/build/testDoubles/BackpressureMonitor/FakeBackpressureMonitor.js +10 -0
  70. package/build/testDoubles/BackpressureMonitor/FakeBackpressureMonitor.js.map +1 -0
  71. package/build/testDoubles/EventMarkerEmitter/FakeEventMarkerEmitter.d.ts +17 -0
  72. package/build/testDoubles/EventMarkerEmitter/FakeEventMarkerEmitter.js +30 -0
  73. package/build/testDoubles/EventMarkerEmitter/FakeEventMarkerEmitter.js.map +1 -0
  74. package/build/testDoubles/EventMarkerEmitter/SpyEventMarkerEmitter.d.ts +10 -0
  75. package/build/testDoubles/EventMarkerEmitter/SpyEventMarkerEmitter.js +23 -0
  76. package/build/testDoubles/EventMarkerEmitter/SpyEventMarkerEmitter.js.map +1 -0
  77. package/build/testDoubles/EventMarkerEmitter/ThrowingEventMarkerEmitter.d.ts +9 -0
  78. package/build/testDoubles/EventMarkerEmitter/ThrowingEventMarkerEmitter.js +19 -0
  79. package/build/testDoubles/EventMarkerEmitter/ThrowingEventMarkerEmitter.js.map +1 -0
  80. package/build/testDoubles/StreamInfo/FakeStreamInfo.d.ts +3 -3
  81. package/build/testDoubles/StreamInfo/FakeStreamInfo.js +3 -3
  82. package/build/testDoubles/StreamInfo/FakeStreamInfo.js.map +1 -1
  83. package/build/testDoubles/StreamInlet/FakeStreamInlet.d.ts +8 -10
  84. package/build/testDoubles/StreamInlet/FakeStreamInlet.js +6 -7
  85. package/build/testDoubles/StreamInlet/FakeStreamInlet.js.map +1 -1
  86. package/build/testDoubles/StreamInlet/SpyStreamInlet.d.ts +2 -5
  87. package/build/testDoubles/StreamInlet/SpyStreamInlet.js +2 -8
  88. package/build/testDoubles/StreamInlet/SpyStreamInlet.js.map +1 -1
  89. package/build/testDoubles/StreamOutlet/FakeStreamOutlet.d.ts +7 -9
  90. package/build/testDoubles/StreamOutlet/FakeStreamOutlet.js +5 -8
  91. package/build/testDoubles/StreamOutlet/FakeStreamOutlet.js.map +1 -1
  92. package/build/testDoubles/WebSocketBridge/FakeWebSocketBridge.d.ts +1 -1
  93. package/build/testDoubles/WebSocketBridge/FakeWebSocketBridge.js +1 -1
  94. package/build/testDoubles/WebSocketBridge/FakeWebSocketBridge.js.map +1 -1
  95. package/build/testDoubles/WorkerThreads/FakeWorker.d.ts +27 -0
  96. package/build/testDoubles/WorkerThreads/FakeWorker.js +67 -0
  97. package/build/testDoubles/WorkerThreads/FakeWorker.js.map +1 -0
  98. package/build/validations.js +0 -2
  99. package/build/validations.js.map +1 -1
  100. package/package.json +24 -8
  101. package/src/.spruce/settings.json +5 -1
  102. package/src/__tests__/AbstractPackageTest.ts +13 -15
  103. package/src/__tests__/impl/LslBackpressureMonitor.test.ts +25 -0
  104. package/src/__tests__/impl/LslEventMarkerEmitter.test.ts +322 -0
  105. package/src/__tests__/impl/LslStreamInfo.test.ts +3 -40
  106. package/src/__tests__/impl/LslStreamInlet.test.ts +366 -95
  107. package/src/__tests__/impl/LslStreamOutlet.test.ts +61 -69
  108. package/src/__tests__/impl/LslWebSocketBridge.test.ts +18 -18
  109. package/src/assertions.ts +2 -1
  110. package/src/impl/LslBackpressureMonitor.ts +13 -0
  111. package/src/impl/LslEventMarkerEmitter.ts +133 -0
  112. package/src/impl/LslStreamInfo.ts +17 -29
  113. package/src/impl/LslStreamInlet.ts +105 -208
  114. package/src/impl/LslStreamOutlet.ts +54 -78
  115. package/src/impl/LslWebSocketBridge.ts +12 -12
  116. package/src/impl/workers/inlet/LslStreamInlet.worker.ts +74 -0
  117. package/src/impl/workers/inlet/StreamInletWorker.ts +348 -0
  118. package/src/impl/workers/outlet/LslStreamOutlet.worker.ts +144 -0
  119. package/src/index.ts +14 -17
  120. package/src/scripts/finalizeHandles.ts +63 -0
  121. package/src/scripts/runLslEventMarkerEmitter.ts +15 -0
  122. package/src/scripts/runOutletToInlet.ts +10 -8
  123. package/src/scripts/testDestroyOutlet.ts +5 -0
  124. package/src/testDoubles/BackpressureMonitor/FakeBackpressureMonitor.ts +13 -0
  125. package/src/testDoubles/EventMarkerEmitter/FakeEventMarkerEmitter.ts +46 -0
  126. package/src/testDoubles/EventMarkerEmitter/SpyEventMarkerEmitter.ts +31 -0
  127. package/src/testDoubles/EventMarkerEmitter/ThrowingEventMarkerEmitter.ts +29 -0
  128. package/src/testDoubles/StreamInfo/FakeStreamInfo.ts +4 -4
  129. package/src/testDoubles/StreamInlet/FakeStreamInlet.ts +11 -17
  130. package/src/testDoubles/StreamInlet/SpyStreamInlet.ts +3 -16
  131. package/src/testDoubles/StreamOutlet/FakeStreamOutlet.ts +12 -15
  132. package/src/testDoubles/WebSocketBridge/FakeWebSocketBridge.ts +1 -1
  133. package/src/testDoubles/WorkerThreads/FakeWorker.ts +99 -0
  134. package/src/validations.ts +0 -2
  135. package/build/__tests__/impl/LiblslAdapter.test.d.ts +0 -79
  136. package/build/__tests__/impl/LiblslAdapter.test.js +0 -688
  137. package/build/__tests__/impl/LiblslAdapter.test.js.map +0 -1
  138. package/build/__tests__/impl/LslEventMarkerOutlet.test.d.ts +0 -21
  139. package/build/__tests__/impl/LslEventMarkerOutlet.test.js +0 -160
  140. package/build/__tests__/impl/LslEventMarkerOutlet.test.js.map +0 -1
  141. package/build/handleError.d.ts +0 -8
  142. package/build/handleError.js +0 -25
  143. package/build/handleError.js.map +0 -1
  144. package/build/impl/LiblslAdapter.d.ts +0 -159
  145. package/build/impl/LiblslAdapter.js +0 -317
  146. package/build/impl/LiblslAdapter.js.map +0 -1
  147. package/build/impl/LslEventMarkerOutlet.d.ts +0 -28
  148. package/build/impl/LslEventMarkerOutlet.js +0 -63
  149. package/build/impl/LslEventMarkerOutlet.js.map +0 -1
  150. package/build/scripts/runLslEventMarkerOutlet.js +0 -18
  151. package/build/scripts/runLslEventMarkerOutlet.js.map +0 -1
  152. package/build/testDoubles/EventMarkerOutlet/FakeEventMarkerOutlet.d.ts +0 -13
  153. package/build/testDoubles/EventMarkerOutlet/FakeEventMarkerOutlet.js +0 -26
  154. package/build/testDoubles/EventMarkerOutlet/FakeEventMarkerOutlet.js.map +0 -1
  155. package/build/testDoubles/EventMarkerOutlet/MockEventMarkerOutlet.d.ts +0 -17
  156. package/build/testDoubles/EventMarkerOutlet/MockEventMarkerOutlet.js +0 -46
  157. package/build/testDoubles/EventMarkerOutlet/MockEventMarkerOutlet.js.map +0 -1
  158. package/build/testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.d.ts +0 -9
  159. package/build/testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.js +0 -19
  160. package/build/testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.js.map +0 -1
  161. package/build/testDoubles/EventMarkerOutlet/ThrowingEventMarkerOutlet.d.ts +0 -9
  162. package/build/testDoubles/EventMarkerOutlet/ThrowingEventMarkerOutlet.js +0 -19
  163. package/build/testDoubles/EventMarkerOutlet/ThrowingEventMarkerOutlet.js.map +0 -1
  164. package/build/testDoubles/Liblsl/FakeLiblsl.d.ts +0 -50
  165. package/build/testDoubles/Liblsl/FakeLiblsl.js +0 -126
  166. package/build/testDoubles/Liblsl/FakeLiblsl.js.map +0 -1
  167. package/src/__tests__/impl/LiblslAdapter.test.ts +0 -817
  168. package/src/__tests__/impl/LslEventMarkerOutlet.test.ts +0 -195
  169. package/src/handleError.ts +0 -24
  170. package/src/impl/LiblslAdapter.ts +0 -548
  171. package/src/impl/LslEventMarkerOutlet.ts +0 -97
  172. package/src/scripts/runLslEventMarkerOutlet.ts +0 -23
  173. package/src/testDoubles/EventMarkerOutlet/FakeEventMarkerOutlet.ts +0 -36
  174. package/src/testDoubles/EventMarkerOutlet/MockEventMarkerOutlet.ts +0 -75
  175. package/src/testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.ts +0 -24
  176. package/src/testDoubles/EventMarkerOutlet/ThrowingEventMarkerOutlet.ts +0 -28
  177. package/src/testDoubles/Liblsl/FakeLiblsl.ts +0 -182
  178. /package/build/scripts/{runLslEventMarkerOutlet.d.ts → runLslEventMarkerEmitter.d.ts} +0 -0
@@ -1,548 +0,0 @@
1
- import {
2
- createPointer,
3
- DataType,
4
- define,
5
- JsExternal,
6
- load,
7
- open,
8
- unwrapPointer,
9
- } from 'ffi-rs'
10
-
11
- import { CHANNEL_FORMATS } from '../consts.js'
12
- import { LslErrorCode } from '../handleError.js'
13
-
14
- export default class LiblslAdapter implements Liblsl {
15
- public static open = open
16
- public static define = define
17
- public static load = load
18
- public static alloc = Buffer.alloc
19
-
20
- private static instance?: Liblsl
21
-
22
- public liblslPath: string
23
- private bindings!: LiblslBindings
24
-
25
- private readonly defaultMacOsPath = `/opt/homebrew/Cellar/lsl/1.16.2/lib/liblsl.1.16.2.dylib`
26
-
27
- protected constructor() {
28
- this.liblslPath = process.env.LIBLSL_PATH ?? this.defaultMacOsPath
29
- this.tryToLoadBindings()
30
- }
31
-
32
- private tryToLoadBindings() {
33
- try {
34
- this.loadBindings()
35
- } catch (error) {
36
- this.throwFailedToLoadLiblsl(error as Error)
37
- }
38
- }
39
-
40
- private throwFailedToLoadLiblsl(error: Error) {
41
- throw new Error(
42
- `Loading the liblsl dylib failed! I tried to load it from ${this.liblslPath}.\n\n${error.message}\n\n`
43
- )
44
- }
45
-
46
- public static getInstance() {
47
- if (!this.instance) {
48
- this.setInstance(new this())
49
- }
50
- return this.instance!
51
- }
52
-
53
- public static setInstance(instance: Liblsl) {
54
- this.instance = instance
55
- }
56
-
57
- public static resetInstance() {
58
- delete this.instance
59
- }
60
-
61
- private loadBindings() {
62
- this.openLiblsl()
63
- this.bindings = this.defineLiblslBindings()
64
- }
65
-
66
- private openLiblsl() {
67
- this.open({
68
- library: 'lsl',
69
- path: this.liblslPath,
70
- })
71
- }
72
-
73
- private defineLiblslBindings() {
74
- return this.define(this.liblslFuncs) as LiblslBindings
75
- }
76
-
77
- public createStreamInfo(options: CreateStreamInfoOptions) {
78
- const {
79
- name,
80
- type,
81
- sourceId,
82
- channelCount,
83
- channelFormat,
84
- sampleRateHz,
85
- } = options
86
-
87
- return this.bindings.lsl_create_streaminfo([
88
- name,
89
- type,
90
- channelCount,
91
- sampleRateHz,
92
- channelFormat,
93
- sourceId,
94
- ])
95
- }
96
-
97
- public appendChannelsToStreamInfo(
98
- options: AppendChannelsToStreamInfoOptions
99
- ) {
100
- const { info, channels } = options
101
-
102
- const description = this.bindings.lsl_get_desc([info])
103
- const parent = this.bindings.lsl_append_child([description, 'channels'])
104
-
105
- for (const channel of channels) {
106
- const child = this.bindings.lsl_append_child([parent, 'channel'])
107
- this.bindings.lsl_append_child_value([
108
- child,
109
- 'label',
110
- channel.label,
111
- ])
112
- this.bindings.lsl_append_child_value([child, 'unit', channel.units])
113
- this.bindings.lsl_append_child_value([child, 'type', channel.type])
114
- }
115
- }
116
-
117
- public destroyStreamInfo(options: DestroyStreamInfoOptions) {
118
- const { info } = options
119
- this.bindings.lsl_destroy_streaminfo([info])
120
- }
121
-
122
- public async resolveByProp(options: ResolveByPropOptions) {
123
- const { prop, value, minResults = 1, timeoutMs = 1000 } = options
124
-
125
- const maxResults = 1024
126
- const bytesPerPointer = 8
127
-
128
- const resultsBuffer = this.alloc(maxResults * bytesPerPointer)
129
-
130
- const resultsBufferPtr = unwrapPointer(
131
- createPointer({
132
- paramsType: [DataType.U8Array],
133
- paramsValue: [resultsBuffer],
134
- })
135
- )[0]
136
-
137
- const numResults = await this.load({
138
- library: 'lsl',
139
- funcName: 'lsl_resolve_byprop',
140
- retType: DataType.I32,
141
- paramsType: [
142
- DataType.External,
143
- DataType.I32,
144
- DataType.String,
145
- DataType.String,
146
- DataType.I32,
147
- DataType.Double,
148
- ],
149
- paramsValue: [
150
- resultsBufferPtr,
151
- maxResults,
152
- prop,
153
- value,
154
- minResults,
155
- timeoutMs / 1000,
156
- ],
157
- runInNewThread: true,
158
- })
159
-
160
- const handles: bigint[] = []
161
-
162
- for (let i = 0; i < numResults; i++) {
163
- const handle = resultsBuffer.readBigUInt64LE(i * bytesPerPointer)
164
-
165
- if (handle !== 0n) {
166
- handles.push(handle)
167
- }
168
- }
169
-
170
- return handles
171
- }
172
-
173
- public createOutlet(options: CreateOutletOptions) {
174
- const { info, chunkSize, maxBufferedMs } = options
175
-
176
- return this.bindings.lsl_create_outlet([
177
- info,
178
- chunkSize,
179
- maxBufferedMs / 1000,
180
- ])
181
- }
182
-
183
- public pushSampleFloatTimestamp(options: PushSampleFloatTimestampOptions) {
184
- const { outlet, sample, timestamp } = options
185
- return this.bindings.lsl_push_sample_ft([outlet, sample, timestamp])
186
- }
187
-
188
- public pushSampleStringTimestamp(
189
- options: PushSampleStringTimestampOptions
190
- ) {
191
- const { outlet, sample, timestamp } = options
192
- return this.bindings.lsl_push_sample_strt([outlet, sample, timestamp])
193
- }
194
-
195
- public destroyOutlet(options: DestroyOutletOptions) {
196
- const { outlet } = options
197
- this.bindings.lsl_destroy_outlet([outlet])
198
- }
199
-
200
- public createInlet(options: CreateInletOptions) {
201
- const { info, maxBufferedMs } = options
202
-
203
- return this.bindings.lsl_create_inlet([
204
- info,
205
- maxBufferedMs / 1000,
206
- this.maxChunkSize,
207
- this.shouldRecover,
208
- ])
209
- }
210
-
211
- private readonly maxChunkSize = 0
212
- private readonly shouldRecover = 1
213
-
214
- public pullSample(options: PullSampleOptions) {
215
- const {
216
- inlet,
217
- dataBufferPtr,
218
- dataBufferElements,
219
- timeout,
220
- errcodePtr,
221
- } = options
222
-
223
- return this.load({
224
- library: 'lsl',
225
- funcName: 'lsl_pull_sample_f',
226
- retType: DataType.Double,
227
- paramsType: [
228
- DataType.External,
229
- DataType.External,
230
- DataType.I32,
231
- DataType.Double,
232
- DataType.External,
233
- ],
234
- paramsValue: [
235
- inlet,
236
- dataBufferPtr,
237
- dataBufferElements,
238
- timeout,
239
- errcodePtr,
240
- ],
241
- })
242
- }
243
-
244
- public pullChunk(options: PullChunkOptions) {
245
- const {
246
- inlet,
247
- dataBufferPtr,
248
- timestampBufferPtr,
249
- dataBufferElements,
250
- timestampBufferElements,
251
- timeout,
252
- errcodePtr,
253
- } = options
254
-
255
- return this.load({
256
- library: 'lsl',
257
- funcName: 'lsl_pull_chunk_f',
258
- retType: DataType.Double,
259
- paramsType: [
260
- DataType.External,
261
- DataType.External,
262
- DataType.External,
263
- DataType.I32,
264
- DataType.I32,
265
- DataType.Double,
266
- DataType.External,
267
- ],
268
- paramsValue: [
269
- inlet,
270
- unwrapPointer([dataBufferPtr])[0],
271
- unwrapPointer([timestampBufferPtr])[0],
272
- dataBufferElements,
273
- timestampBufferElements,
274
- timeout,
275
- unwrapPointer([errcodePtr])[0],
276
- ],
277
- })
278
- }
279
-
280
- public flushInlet(options: FlushInletOptions) {
281
- const { inlet } = options
282
- this.bindings.lsl_flush_inlet([inlet])
283
- }
284
-
285
- public destroyInlet(options: DestroyInletOptions) {
286
- const { inlet } = options
287
- this.bindings.lsl_destroy_inlet([inlet])
288
- }
289
-
290
- public localClock() {
291
- return this.bindings.lsl_local_clock([])
292
- }
293
-
294
- private get open() {
295
- return LiblslAdapter.open
296
- }
297
-
298
- private get define() {
299
- return LiblslAdapter.define
300
- }
301
-
302
- private get load() {
303
- return LiblslAdapter.load
304
- }
305
-
306
- private get alloc() {
307
- return LiblslAdapter.alloc
308
- }
309
-
310
- private get liblslFuncs() {
311
- return {
312
- lsl_create_streaminfo: {
313
- library: 'lsl',
314
- retType: DataType.External,
315
- paramsType: [
316
- DataType.String,
317
- DataType.String,
318
- DataType.I32,
319
- DataType.Double,
320
- DataType.I32,
321
- DataType.String,
322
- ],
323
- },
324
- lsl_destroy_streaminfo: {
325
- library: 'lsl',
326
- retType: DataType.Void,
327
- paramsType: [DataType.External],
328
- },
329
- lsl_create_outlet: {
330
- library: 'lsl',
331
- retType: DataType.External,
332
- paramsType: [DataType.External, DataType.I32, DataType.I32],
333
- },
334
- lsl_push_sample_ft: {
335
- library: 'lsl',
336
- retType: DataType.I32,
337
- paramsType: [
338
- DataType.External,
339
- DataType.FloatArray,
340
- DataType.Double,
341
- ],
342
- },
343
- lsl_push_sample_strt: {
344
- library: 'lsl',
345
- retType: DataType.I32,
346
- paramsType: [
347
- DataType.External,
348
- DataType.StringArray,
349
- DataType.Double,
350
- ],
351
- },
352
- lsl_destroy_outlet: {
353
- library: 'lsl',
354
- retType: DataType.Void,
355
- paramsType: [DataType.External],
356
- },
357
- lsl_create_inlet: {
358
- library: 'lsl',
359
- retType: DataType.External,
360
- paramsType: [
361
- DataType.External,
362
- DataType.I32,
363
- DataType.I32,
364
- DataType.I32,
365
- ],
366
- },
367
- lsl_flush_inlet: {
368
- library: 'lsl',
369
- retType: DataType.I32,
370
- paramsType: [DataType.External],
371
- },
372
- lsl_destroy_inlet: {
373
- library: 'lsl',
374
- retType: DataType.Void,
375
- paramsType: [DataType.External],
376
- },
377
- lsl_get_desc: {
378
- library: 'lsl',
379
- retType: DataType.External,
380
- paramsType: [DataType.External],
381
- },
382
- lsl_append_child: {
383
- library: 'lsl',
384
- retType: DataType.External,
385
- paramsType: [DataType.External, DataType.String],
386
- },
387
- lsl_append_child_value: {
388
- library: 'lsl',
389
- retType: DataType.External,
390
- paramsType: [
391
- DataType.External,
392
- DataType.String,
393
- DataType.String,
394
- ],
395
- },
396
- lsl_local_clock: {
397
- library: 'lsl',
398
- retType: DataType.Double,
399
- paramsType: [],
400
- },
401
- }
402
- }
403
- }
404
-
405
- export interface Liblsl {
406
- liblslPath: string
407
-
408
- createStreamInfo(options: CreateStreamInfoOptions): BoundStreamInfo
409
- destroyStreamInfo(options: DestroyStreamInfoOptions): void
410
- appendChannelsToStreamInfo(options: AppendChannelsToStreamInfoOptions): void
411
-
412
- resolveByProp(options: ResolveByPropOptions): Promise<bigint[]>
413
-
414
- createOutlet(options: CreateOutletOptions): BoundOutlet
415
-
416
- pushSampleFloatTimestamp(
417
- options: PushSampleFloatTimestampOptions
418
- ): LslErrorCode
419
-
420
- pushSampleStringTimestamp(
421
- options: PushSampleStringTimestampOptions
422
- ): LslErrorCode
423
-
424
- destroyOutlet(options: DestroyOutletOptions): void
425
-
426
- createInlet(options: CreateInletOptions): BoundInlet
427
- pullSample(options: PullSampleOptions): number
428
- pullChunk(options: PullChunkOptions): number
429
- flushInlet(options: FlushInletOptions): void
430
- destroyInlet(options: DestroyInletOptions): void
431
-
432
- localClock(): number
433
- }
434
-
435
- export interface CreateStreamInfoOptions {
436
- name: string
437
- type: string
438
- sourceId: string
439
- channelCount: number
440
- channelFormat: number
441
- sampleRateHz: number
442
- manufacturer?: string
443
- units?: string
444
- }
445
-
446
- export interface AppendChannelsToStreamInfoOptions {
447
- info: BoundStreamInfo
448
- channels: LslChannel[]
449
- }
450
-
451
- export interface DestroyStreamInfoOptions {
452
- info: BoundStreamInfo
453
- }
454
-
455
- export interface ResolveByPropOptions {
456
- prop: string
457
- value: string
458
- minResults?: number
459
- timeoutMs?: number
460
- }
461
-
462
- export interface CreateOutletOptions {
463
- info: BoundStreamInfo
464
- chunkSize: number
465
- maxBufferedMs: number
466
- }
467
-
468
- export interface PushSampleFloatTimestampOptions {
469
- outlet: BoundOutlet
470
- sample: number[]
471
- timestamp: number
472
- }
473
-
474
- export interface PushSampleStringTimestampOptions {
475
- outlet: BoundOutlet
476
- sample: string[]
477
- timestamp: number
478
- }
479
-
480
- export interface DestroyOutletOptions {
481
- outlet: BoundOutlet
482
- }
483
-
484
- export interface CreateInletOptions {
485
- info: BoundStreamInfo
486
- maxBufferedMs: number
487
- }
488
-
489
- export interface PullSampleOptions {
490
- inlet: BoundInlet
491
- dataBufferPtr: JsExternal
492
- dataBufferElements: number
493
- timeout: number
494
- errcodePtr: JsExternal
495
- }
496
-
497
- export interface PullChunkOptions {
498
- inlet: BoundInlet
499
- dataBufferPtr: JsExternal
500
- timestampBufferPtr: JsExternal
501
- dataBufferElements: number
502
- timestampBufferElements: number
503
- timeout: number
504
- errcodePtr: JsExternal
505
- }
506
-
507
- export interface FlushInletOptions {
508
- inlet: BoundInlet
509
- }
510
-
511
- export interface DestroyInletOptions {
512
- inlet: BoundInlet
513
- }
514
-
515
- export interface LiblslBindings {
516
- lsl_create_streaminfo(
517
- args: [string, string, number, number, number, string]
518
- ): BoundStreamInfo
519
-
520
- lsl_destroy_streaminfo(args: [BoundStreamInfo]): void
521
- lsl_create_outlet(args: [BoundStreamInfo, number, number]): BoundOutlet
522
- lsl_push_sample_ft(args: [BoundOutlet, LslSample, number]): LslErrorCode
523
- lsl_push_sample_strt(args: [BoundOutlet, LslSample, number]): LslErrorCode
524
- lsl_destroy_outlet(args: [BoundOutlet]): void
525
- lsl_create_inlet(args: any): BoundInlet
526
- lsl_flush_inlet(args: [BoundInlet]): void
527
- lsl_destroy_inlet(args: any): void
528
- lsl_local_clock(args: []): number
529
- lsl_get_desc(args: [BoundStreamInfo]): BoundDescription
530
- lsl_append_child(args: [BoundDescription, string]): BoundChild
531
- lsl_append_child_value(args: [BoundChild, string, string]): void
532
- }
533
-
534
- export type ChannelFormat = (typeof CHANNEL_FORMATS)[number]
535
-
536
- export interface LslChannel {
537
- label: string
538
- units: string
539
- type: string
540
- }
541
-
542
- export type LslSample = (number | string | undefined)[]
543
-
544
- export interface BoundStreamInfo {}
545
- export interface BoundOutlet {}
546
- export interface BoundInlet {}
547
- export interface BoundDescription {}
548
- export interface BoundChild {}
@@ -1,97 +0,0 @@
1
- import LslStreamOutlet, {
2
- StreamOutletOptions,
3
- StreamOutlet,
4
- } from './LslStreamOutlet.js'
5
-
6
- export default class LslEventMarkerOutlet implements EventMarkerOutlet {
7
- public static Class?: EventMarkerOutletConstructor
8
-
9
- protected outlet: StreamOutlet
10
- private isPlaying = false
11
- private waitResolve?: () => void
12
- private timeout?: any
13
-
14
- protected constructor(outlet: StreamOutlet) {
15
- this.outlet = outlet
16
- }
17
-
18
- public static async Create(options?: Partial<StreamOutletOptions>) {
19
- const defaultOptions = {
20
- name: 'Event markers',
21
- type: 'Markers',
22
- channelNames: ['Markers'],
23
- sampleRateHz: 0,
24
- channelFormat: 'string',
25
- sourceId: 'event-markers',
26
- manufacturer: 'N/A',
27
- units: 'N/A',
28
- chunkSize: 0,
29
- maxBufferedMs: 0,
30
- } as StreamOutletOptions
31
-
32
- const outlet = await LslStreamOutlet.Create({
33
- ...defaultOptions,
34
- ...options,
35
- })
36
-
37
- return new (this.Class ?? this)(outlet)
38
- }
39
-
40
- public pushMarker(markerName: string) {
41
- this.pushMarkerToOutlet(markerName)
42
- }
43
-
44
- public async pushMarkers(markers: DurationMarker[]) {
45
- this.isPlaying = true
46
-
47
- for (let marker of markers) {
48
- const { name, durationMs } = marker
49
- this.pushMarkerToOutlet(name)
50
-
51
- await this.wait(durationMs)
52
-
53
- if (!this.isPlaying) {
54
- return
55
- }
56
- }
57
- }
58
-
59
- private pushMarkerToOutlet(markerName: string) {
60
- this.outlet.pushSample([markerName])
61
- }
62
-
63
- protected async wait(durationMs: number) {
64
- return new Promise((resolve) => this.setTimeout(resolve, durationMs))
65
- }
66
-
67
- private setTimeout(resolve: (value: unknown) => void, durationMs: number) {
68
- this.waitResolve = resolve as any
69
- this.timeout = setTimeout(resolve, durationMs)
70
- }
71
-
72
- public stop() {
73
- this.waitResolve?.()
74
- clearTimeout(this.timeout)
75
- this.isPlaying = false
76
- }
77
-
78
- public destroy() {
79
- this.outlet.destroy()
80
- }
81
- }
82
-
83
- export interface EventMarkerOutlet {
84
- pushMarker(markerName: string): void
85
- pushMarkers(markers: DurationMarker[]): Promise<void>
86
- stop(): void
87
- destroy(): void
88
- }
89
-
90
- export type EventMarkerOutletConstructor = new (
91
- outlet: StreamOutlet
92
- ) => EventMarkerOutlet
93
-
94
- export interface DurationMarker {
95
- name: string
96
- durationMs: number
97
- }
@@ -1,23 +0,0 @@
1
- import LslEventMarkerOutlet from '../impl/LslEventMarkerOutlet.js'
2
-
3
- async function main() {
4
- const outlet = await LslEventMarkerOutlet.Create()
5
-
6
- const markers = [
7
- { name: 'phase-1-begin', durationMs: 100 },
8
- { name: 'phase-1-end', durationMs: 10 },
9
- ]
10
-
11
- // Hangs until complete
12
- await outlet.pushMarkers(markers)
13
-
14
- // Void promise, does not hang
15
- void outlet.pushMarkers(markers)
16
-
17
- // Interrupts the above pushMarkers process
18
- outlet.stop()
19
- }
20
-
21
- main().catch((error) => {
22
- console.error('Error in main:', error)
23
- })
@@ -1,36 +0,0 @@
1
- import {
2
- DurationMarker,
3
- EventMarkerOutlet,
4
- } from '../../impl/LslEventMarkerOutlet.js'
5
-
6
- export default class FakeEventMarkerOutlet implements EventMarkerOutlet {
7
- public static callsToPushMarker: string[] = []
8
- public static callsToPushMarkers: DurationMarker[][] = []
9
- public static numCallsToStop = 0
10
- public static numCallsToDestroy = 0
11
-
12
- public constructor() {}
13
-
14
- public pushMarker(markerName: string) {
15
- FakeEventMarkerOutlet.callsToPushMarker.push(markerName)
16
- }
17
-
18
- public async pushMarkers(markers: DurationMarker[]) {
19
- FakeEventMarkerOutlet.callsToPushMarkers.push(markers)
20
- }
21
-
22
- public stop() {
23
- FakeEventMarkerOutlet.numCallsToStop++
24
- }
25
-
26
- public destroy() {
27
- FakeEventMarkerOutlet.numCallsToDestroy++
28
- }
29
-
30
- public static resetTestDouble() {
31
- this.callsToPushMarker = []
32
- this.callsToPushMarkers = []
33
- this.numCallsToStop = 0
34
- this.numCallsToDestroy = 0
35
- }
36
- }