@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.
- package/.claude/settings.local.json +10 -0
- package/.vscode/launch.json +54 -57
- package/.vscode/settings.json +61 -66
- package/.vscode/tasks.json +98 -129
- package/README.md +20 -44
- package/build/__tests__/AbstractPackageTest.d.ts +7 -5
- package/build/__tests__/AbstractPackageTest.js +22 -15
- package/build/__tests__/AbstractPackageTest.js.map +1 -1
- package/build/__tests__/impl/BleDeviceController.test.d.ts +54 -0
- package/build/__tests__/impl/BleDeviceController.test.js +333 -0
- package/build/__tests__/impl/BleDeviceController.test.js.map +1 -0
- package/build/__tests__/impl/LslEventMarkerEmitter.test.d.ts +34 -0
- package/build/__tests__/impl/LslEventMarkerEmitter.test.js +243 -0
- package/build/__tests__/impl/LslEventMarkerEmitter.test.js.map +1 -0
- package/build/__tests__/impl/LslStreamInfo.test.d.ts +0 -3
- package/build/__tests__/impl/LslStreamInfo.test.js +2 -27
- package/build/__tests__/impl/LslStreamInfo.test.js.map +1 -1
- package/build/__tests__/impl/LslStreamInlet.test.d.ts +20 -8
- package/build/__tests__/impl/LslStreamInlet.test.js +224 -69
- package/build/__tests__/impl/LslStreamInlet.test.js.map +1 -1
- package/build/__tests__/impl/LslStreamOutlet.test.d.ts +3 -7
- package/build/__tests__/impl/LslStreamOutlet.test.js +40 -50
- package/build/__tests__/impl/LslStreamOutlet.test.js.map +1 -1
- package/build/__tests__/impl/LslWebSocketBridge.test.js +19 -20
- package/build/__tests__/impl/LslWebSocketBridge.test.js.map +1 -1
- package/build/assertions.d.ts +1 -1
- package/build/assertions.js.map +1 -1
- package/build/impl/LslEventMarkerEmitter.d.ts +35 -0
- package/build/impl/LslEventMarkerEmitter.js +86 -0
- package/build/impl/LslEventMarkerEmitter.js.map +1 -0
- package/build/impl/LslStreamInfo.d.ts +4 -8
- package/build/impl/LslStreamInfo.js +8 -21
- package/build/impl/LslStreamInfo.js.map +1 -1
- package/build/impl/LslStreamInlet.d.ts +31 -50
- package/build/impl/LslStreamInlet.js +79 -149
- package/build/impl/LslStreamInlet.js.map +1 -1
- package/build/impl/LslStreamOutlet.d.ts +15 -18
- package/build/impl/LslStreamOutlet.js +39 -47
- package/build/impl/LslStreamOutlet.js.map +1 -1
- package/build/impl/LslWebSocketBridge.d.ts +4 -5
- package/build/impl/LslWebSocketBridge.js +10 -10
- package/build/impl/LslWebSocketBridge.js.map +1 -1
- package/build/impl/controllers/BleDeviceController.d.ts +58 -0
- package/build/impl/controllers/BleDeviceController.js +145 -0
- package/build/impl/controllers/BleDeviceController.js.map +1 -0
- package/build/impl/workers/inlet/LslStreamInlet.worker.d.ts +22 -0
- package/build/impl/workers/inlet/LslStreamInlet.worker.js +42 -0
- package/build/impl/workers/inlet/LslStreamInlet.worker.js.map +1 -0
- package/build/impl/workers/inlet/StreamInletWorker.d.ts +73 -0
- package/build/impl/workers/inlet/StreamInletWorker.js +253 -0
- package/build/impl/workers/inlet/StreamInletWorker.js.map +1 -0
- package/build/impl/workers/outlet/LslStreamOutlet.worker.d.ts +32 -0
- package/build/impl/workers/outlet/LslStreamOutlet.worker.js +82 -0
- package/build/impl/workers/outlet/LslStreamOutlet.worker.js.map +1 -0
- package/build/index.d.ts +14 -14
- package/build/index.js +16 -16
- package/build/index.js.map +1 -1
- package/build/scripts/discoverMuse.js +40 -0
- package/build/scripts/discoverMuse.js.map +1 -0
- package/build/scripts/finalizeHandles.d.ts +2 -0
- package/build/scripts/finalizeHandles.js +48 -0
- package/build/scripts/finalizeHandles.js.map +1 -0
- package/build/scripts/runLslEventMarkerEmitter.d.ts +1 -0
- package/build/scripts/runLslEventMarkerEmitter.js +11 -0
- package/build/scripts/runLslEventMarkerEmitter.js.map +1 -0
- package/build/scripts/runMuse.d.ts +1 -0
- package/build/scripts/runMuse.js +40 -0
- package/build/scripts/runMuse.js.map +1 -0
- package/build/scripts/runOutletToInlet.js +7 -6
- package/build/scripts/runOutletToInlet.js.map +1 -1
- package/build/scripts/testDestroyOutlet.d.ts +1 -0
- package/build/scripts/testDestroyOutlet.js +4 -0
- package/build/scripts/testDestroyOutlet.js.map +1 -0
- package/build/testDoubles/BleController/FakeBleController.d.ts +24 -0
- package/build/testDoubles/BleController/FakeBleController.js +42 -0
- package/build/testDoubles/BleController/FakeBleController.js.map +1 -0
- package/build/testDoubles/BleController/SpyBleController.d.ts +14 -0
- package/build/testDoubles/BleController/SpyBleController.js +48 -0
- package/build/testDoubles/BleController/SpyBleController.js.map +1 -0
- package/build/testDoubles/EventMarkerEmitter/FakeEventMarkerEmitter.d.ts +17 -0
- package/build/testDoubles/EventMarkerEmitter/FakeEventMarkerEmitter.js +30 -0
- package/build/testDoubles/EventMarkerEmitter/FakeEventMarkerEmitter.js.map +1 -0
- package/build/testDoubles/EventMarkerEmitter/SpyEventMarkerEmitter.d.ts +10 -0
- package/build/testDoubles/EventMarkerEmitter/SpyEventMarkerEmitter.js +23 -0
- package/build/testDoubles/EventMarkerEmitter/SpyEventMarkerEmitter.js.map +1 -0
- package/build/testDoubles/EventMarkerEmitter/ThrowingEventMarkerEmitter.d.ts +9 -0
- package/build/testDoubles/EventMarkerEmitter/ThrowingEventMarkerEmitter.js +19 -0
- package/build/testDoubles/EventMarkerEmitter/ThrowingEventMarkerEmitter.js.map +1 -0
- package/build/testDoubles/StreamInfo/FakeStreamInfo.d.ts +3 -3
- package/build/testDoubles/StreamInfo/FakeStreamInfo.js +3 -3
- package/build/testDoubles/StreamInfo/FakeStreamInfo.js.map +1 -1
- package/build/testDoubles/StreamInlet/FakeStreamInlet.d.ts +8 -10
- package/build/testDoubles/StreamInlet/FakeStreamInlet.js +6 -7
- package/build/testDoubles/StreamInlet/FakeStreamInlet.js.map +1 -1
- package/build/testDoubles/StreamInlet/SpyStreamInlet.d.ts +2 -5
- package/build/testDoubles/StreamInlet/SpyStreamInlet.js +2 -8
- package/build/testDoubles/StreamInlet/SpyStreamInlet.js.map +1 -1
- package/build/testDoubles/StreamOutlet/FakeStreamOutlet.d.ts +7 -9
- package/build/testDoubles/StreamOutlet/FakeStreamOutlet.js +8 -8
- package/build/testDoubles/StreamOutlet/FakeStreamOutlet.js.map +1 -1
- package/build/testDoubles/WebSocketBridge/FakeWebSocketBridge.d.ts +1 -1
- package/build/testDoubles/WebSocketBridge/FakeWebSocketBridge.js +1 -1
- package/build/testDoubles/WebSocketBridge/FakeWebSocketBridge.js.map +1 -1
- package/build/testDoubles/WorkerThreads/FakeWorker.d.ts +27 -0
- package/build/testDoubles/WorkerThreads/FakeWorker.js +67 -0
- package/build/testDoubles/WorkerThreads/FakeWorker.js.map +1 -0
- package/build/testDoubles/generateRandomOutletOptions.js +1 -1
- package/build/testDoubles/generateRandomOutletOptions.js.map +1 -1
- package/build/validations.js +0 -2
- package/build/validations.js.map +1 -1
- package/eslint.config.js +3 -0
- package/package.json +27 -49
- package/prettier.config.js +3 -0
- package/src/__tests__/AbstractPackageTest.ts +38 -21
- package/src/__tests__/impl/BleDeviceController.test.ts +492 -0
- package/src/__tests__/impl/LslEventMarkerEmitter.test.ts +323 -0
- package/src/__tests__/impl/LslStreamInfo.test.ts +3 -40
- package/src/__tests__/impl/LslStreamInlet.test.ts +344 -97
- package/src/__tests__/impl/LslStreamOutlet.test.ts +65 -73
- package/src/__tests__/impl/LslWebSocketBridge.test.ts +22 -21
- package/src/assertions.ts +2 -1
- package/src/impl/LslEventMarkerEmitter.ts +133 -0
- package/src/impl/LslStreamInfo.ts +17 -29
- package/src/impl/LslStreamInlet.ts +102 -215
- package/src/impl/LslStreamOutlet.ts +54 -78
- package/src/impl/LslWebSocketBridge.ts +14 -14
- package/src/impl/controllers/BleDeviceController.ts +223 -0
- package/src/impl/workers/inlet/LslStreamInlet.worker.ts +74 -0
- package/src/impl/workers/inlet/StreamInletWorker.ts +348 -0
- package/src/impl/workers/outlet/LslStreamOutlet.worker.ts +144 -0
- package/src/index.ts +16 -16
- package/src/scripts/discoverMuse.ts +50 -0
- package/src/scripts/finalizeHandles.ts +63 -0
- package/src/scripts/runLslEventMarkerEmitter.ts +15 -0
- package/src/scripts/runMuse.ts +50 -0
- package/src/scripts/runOutletToInlet.ts +10 -8
- package/src/scripts/testDestroyOutlet.ts +5 -0
- package/src/testDoubles/BleController/FakeBleController.ts +70 -0
- package/src/testDoubles/BleController/SpyBleController.ts +61 -0
- package/src/testDoubles/EventMarkerEmitter/FakeEventMarkerEmitter.ts +46 -0
- package/src/testDoubles/EventMarkerEmitter/SpyEventMarkerEmitter.ts +31 -0
- package/src/testDoubles/EventMarkerEmitter/ThrowingEventMarkerEmitter.ts +29 -0
- package/src/testDoubles/StreamInfo/FakeStreamInfo.ts +4 -4
- package/src/testDoubles/StreamInlet/FakeStreamInlet.ts +11 -17
- package/src/testDoubles/StreamInlet/SpyStreamInlet.ts +3 -16
- package/src/testDoubles/StreamOutlet/FakeStreamOutlet.ts +15 -15
- package/src/testDoubles/WebSocketBridge/FakeWebSocketBridge.ts +1 -1
- package/src/testDoubles/WorkerThreads/FakeWorker.ts +99 -0
- package/src/testDoubles/generateRandomOutletOptions.ts +2 -1
- package/src/validations.ts +0 -2
- package/tsconfig.json +23 -27
- package/build/.spruce/settings.json +0 -11
- package/build/__tests__/impl/LiblslAdapter.test.d.ts +0 -79
- package/build/__tests__/impl/LiblslAdapter.test.js +0 -688
- package/build/__tests__/impl/LiblslAdapter.test.js.map +0 -1
- package/build/__tests__/impl/LslEventMarkerOutlet.test.d.ts +0 -21
- package/build/__tests__/impl/LslEventMarkerOutlet.test.js +0 -160
- package/build/__tests__/impl/LslEventMarkerOutlet.test.js.map +0 -1
- package/build/handleError.d.ts +0 -8
- package/build/handleError.js +0 -25
- package/build/handleError.js.map +0 -1
- package/build/impl/LiblslAdapter.d.ts +0 -154
- package/build/impl/LiblslAdapter.js +0 -317
- package/build/impl/LiblslAdapter.js.map +0 -1
- package/build/impl/LslEventMarkerOutlet.d.ts +0 -28
- package/build/impl/LslEventMarkerOutlet.js +0 -63
- package/build/impl/LslEventMarkerOutlet.js.map +0 -1
- package/build/scripts/runLslEventMarkerOutlet.js +0 -18
- package/build/scripts/runLslEventMarkerOutlet.js.map +0 -1
- package/build/testDoubles/EventMarkerOutlet/FakeEventMarkerOutlet.d.ts +0 -13
- package/build/testDoubles/EventMarkerOutlet/FakeEventMarkerOutlet.js +0 -26
- package/build/testDoubles/EventMarkerOutlet/FakeEventMarkerOutlet.js.map +0 -1
- package/build/testDoubles/EventMarkerOutlet/MockEventMarkerOutlet.d.ts +0 -17
- package/build/testDoubles/EventMarkerOutlet/MockEventMarkerOutlet.js +0 -46
- package/build/testDoubles/EventMarkerOutlet/MockEventMarkerOutlet.js.map +0 -1
- package/build/testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.d.ts +0 -9
- package/build/testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.js +0 -19
- package/build/testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.js.map +0 -1
- package/build/testDoubles/EventMarkerOutlet/ThrowingEventMarkerOutlet.d.ts +0 -9
- package/build/testDoubles/EventMarkerOutlet/ThrowingEventMarkerOutlet.js +0 -19
- package/build/testDoubles/EventMarkerOutlet/ThrowingEventMarkerOutlet.js.map +0 -1
- package/build/testDoubles/Liblsl/FakeLiblsl.d.ts +0 -50
- package/build/testDoubles/Liblsl/FakeLiblsl.js +0 -126
- package/build/testDoubles/Liblsl/FakeLiblsl.js.map +0 -1
- package/eslint.config.mjs +0 -3
- package/src/.spruce/settings.json +0 -11
- package/src/__tests__/impl/LiblslAdapter.test.ts +0 -817
- package/src/__tests__/impl/LslEventMarkerOutlet.test.ts +0 -195
- package/src/handleError.ts +0 -24
- package/src/impl/LiblslAdapter.ts +0 -543
- package/src/impl/LslEventMarkerOutlet.ts +0 -97
- package/src/scripts/runLslEventMarkerOutlet.ts +0 -23
- package/src/testDoubles/EventMarkerOutlet/FakeEventMarkerOutlet.ts +0 -36
- package/src/testDoubles/EventMarkerOutlet/MockEventMarkerOutlet.ts +0 -75
- package/src/testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.ts +0 -24
- package/src/testDoubles/EventMarkerOutlet/ThrowingEventMarkerOutlet.ts +0 -28
- package/src/testDoubles/Liblsl/FakeLiblsl.ts +0 -182
- /package/build/scripts/{runLslEventMarkerOutlet.d.ts → discoverMuse.d.ts} +0 -0
|
@@ -1,543 +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
|
-
dataBufferPtr,
|
|
271
|
-
timestampBufferPtr,
|
|
272
|
-
dataBufferElements,
|
|
273
|
-
timestampBufferElements,
|
|
274
|
-
timeout,
|
|
275
|
-
errcodePtr,
|
|
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 extends PullSampleOptions {
|
|
498
|
-
timestampBufferPtr: JsExternal
|
|
499
|
-
timestampBufferElements: number
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
export interface FlushInletOptions {
|
|
503
|
-
inlet: BoundInlet
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
export interface DestroyInletOptions {
|
|
507
|
-
inlet: BoundInlet
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
export interface LiblslBindings {
|
|
511
|
-
lsl_create_streaminfo(
|
|
512
|
-
args: [string, string, number, number, number, string]
|
|
513
|
-
): BoundStreamInfo
|
|
514
|
-
|
|
515
|
-
lsl_destroy_streaminfo(args: [BoundStreamInfo]): void
|
|
516
|
-
lsl_create_outlet(args: [BoundStreamInfo, number, number]): BoundOutlet
|
|
517
|
-
lsl_push_sample_ft(args: [BoundOutlet, LslSample, number]): LslErrorCode
|
|
518
|
-
lsl_push_sample_strt(args: [BoundOutlet, LslSample, number]): LslErrorCode
|
|
519
|
-
lsl_destroy_outlet(args: [BoundOutlet]): void
|
|
520
|
-
lsl_create_inlet(args: any): BoundInlet
|
|
521
|
-
lsl_flush_inlet(args: [BoundInlet]): void
|
|
522
|
-
lsl_destroy_inlet(args: any): void
|
|
523
|
-
lsl_local_clock(args: []): number
|
|
524
|
-
lsl_get_desc(args: [BoundStreamInfo]): BoundDescription
|
|
525
|
-
lsl_append_child(args: [BoundDescription, string]): BoundChild
|
|
526
|
-
lsl_append_child_value(args: [BoundChild, string, string]): void
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
export type ChannelFormat = (typeof CHANNEL_FORMATS)[number]
|
|
530
|
-
|
|
531
|
-
export interface LslChannel {
|
|
532
|
-
label: string
|
|
533
|
-
units: string
|
|
534
|
-
type: string
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
export type LslSample = (number | string | undefined)[]
|
|
538
|
-
|
|
539
|
-
export interface BoundStreamInfo {}
|
|
540
|
-
export interface BoundOutlet {}
|
|
541
|
-
export interface BoundInlet {}
|
|
542
|
-
export interface BoundDescription {}
|
|
543
|
-
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
|
-
}
|