@neurodevs/ndx-native 0.2.0 → 0.3.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/.regressionproof.json +7 -0
- package/.vscode/launch.json +52 -57
- package/.vscode/settings.json +62 -66
- package/.vscode/tasks.json +123 -129
- package/README.md +1 -0
- package/build/.spruce/settings.json +7 -7
- package/build/__tests__/AbstractPackageTest.d.ts +1 -0
- package/build/__tests__/AbstractPackageTest.js +1 -0
- package/build/__tests__/AbstractPackageTest.js.map +1 -1
- package/build/__tests__/impl/LabrecorderAdapter.test.d.ts +1 -1
- package/build/__tests__/impl/LabrecorderAdapter.test.js +9 -9
- package/build/__tests__/impl/LabrecorderAdapter.test.js.map +1 -1
- package/build/__tests__/impl/LiblslAdapter.test.d.ts +3 -4
- package/build/__tests__/impl/LiblslAdapter.test.js +18 -26
- package/build/__tests__/impl/LiblslAdapter.test.js.map +1 -1
- package/build/__tests__/impl/LibndxAdapter.test.d.ts +35 -0
- package/build/__tests__/impl/LibndxAdapter.test.js +258 -0
- package/build/__tests__/impl/LibndxAdapter.test.js.map +1 -0
- package/build/__tests__/impl/LibxdfAdapter.test.d.ts +1 -2
- package/build/__tests__/impl/LibxdfAdapter.test.js +5 -6
- package/build/__tests__/impl/LibxdfAdapter.test.js.map +1 -1
- package/build/impl/LiblslAdapter.d.ts +7 -9
- package/build/impl/LiblslAdapter.js +111 -117
- package/build/impl/LiblslAdapter.js.map +1 -1
- package/build/impl/LibndxAdapter.d.ts +57 -0
- package/build/impl/LibndxAdapter.js +145 -0
- package/build/impl/LibndxAdapter.js.map +1 -0
- package/build/impl/LibxdfAdapter.d.ts +3 -3
- package/build/impl/LibxdfAdapter.js +10 -7
- package/build/impl/LibxdfAdapter.js.map +1 -1
- package/build/index.d.ts +6 -2
- package/build/index.js +8 -3
- package/build/index.js.map +1 -1
- package/build/lib/{handleError.d.ts → handleLslError.d.ts} +1 -1
- package/build/lib/{handleError.js → handleLslError.js} +2 -2
- package/build/lib/handleLslError.js.map +1 -0
- package/build/testDoubles/Libndx/FakeLibndx.d.ts +22 -0
- package/build/testDoubles/Libndx/FakeLibndx.js +58 -0
- package/build/testDoubles/Libndx/FakeLibndx.js.map +1 -0
- package/build/types.d.ts +2 -0
- package/build/types.js +2 -0
- package/build/types.js.map +1 -0
- package/eslint.config.js +3 -0
- package/package.json +15 -31
- package/prettier.config.js +3 -0
- package/src/.spruce/settings.json +7 -7
- package/src/__tests__/AbstractPackageTest.ts +2 -0
- package/src/__tests__/impl/LabrecorderAdapter.test.ts +27 -11
- package/src/__tests__/impl/LiblslAdapter.test.ts +19 -26
- package/src/__tests__/impl/LibndxAdapter.test.ts +279 -0
- package/src/__tests__/impl/LibxdfAdapter.test.ts +5 -6
- package/src/impl/LiblslAdapter.ts +119 -127
- package/src/impl/LibndxAdapter.ts +204 -0
- package/src/impl/LibxdfAdapter.ts +13 -15
- package/src/index.ts +11 -3
- package/src/lib/{handleError.ts → handleLslError.ts} +1 -1
- package/src/testDoubles/Libndx/FakeLibndx.ts +74 -0
- package/src/types.ts +7 -0
- package/tsconfig.json +24 -27
- package/build/lib/handleError.js.map +0 -1
- package/eslint.config.mjs +0 -3
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import { test, assert } from '@neurodevs/node-tdd'
|
|
2
|
+
|
|
3
|
+
import LibndxAdapter, {
|
|
4
|
+
Libndx,
|
|
5
|
+
LibndxBindings,
|
|
6
|
+
} from '../../impl/LibndxAdapter.js'
|
|
7
|
+
import AbstractPackageTest from '../AbstractPackageTest.js'
|
|
8
|
+
import { DataType, define, OpenParams } from 'ffi-rs'
|
|
9
|
+
import { FfiRsDefineOptions } from '../../types.js'
|
|
10
|
+
import FakeLibndx from '../../testDoubles/Libndx/FakeLibndx.js'
|
|
11
|
+
|
|
12
|
+
export default class LibndxAdapterTest extends AbstractPackageTest {
|
|
13
|
+
public static ffiRsDefine = define
|
|
14
|
+
|
|
15
|
+
private static instance: Libndx
|
|
16
|
+
private static libndxPath = this.generateId()
|
|
17
|
+
private static shouldThrowWhenLoadingBindings: boolean
|
|
18
|
+
private static fakeBindings: LibndxBindings
|
|
19
|
+
|
|
20
|
+
private static ffiRsOpenOptions?: OpenParams
|
|
21
|
+
private static ffiRsDefineOptions?: FfiRsDefineOptions
|
|
22
|
+
|
|
23
|
+
private static readonly bleDeviceUuid = this.generateId()
|
|
24
|
+
private static readonly ftdiSerialNumber = this.generateId()
|
|
25
|
+
|
|
26
|
+
protected static async beforeEach() {
|
|
27
|
+
await super.beforeEach()
|
|
28
|
+
|
|
29
|
+
this.shouldThrowWhenLoadingBindings = false
|
|
30
|
+
this.fakeBindings = this.FakeBindings()
|
|
31
|
+
this.clearAndFakeFfi()
|
|
32
|
+
|
|
33
|
+
this.resetInstance()
|
|
34
|
+
this.instance = this.LibndxAdapter()
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@test()
|
|
38
|
+
protected static async createsInstance() {
|
|
39
|
+
assert.isTruthy(this.instance, 'Failed to create instance!')
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@test()
|
|
43
|
+
protected static async throwsWhenBindingsFailToLoad() {
|
|
44
|
+
this.resetInstance()
|
|
45
|
+
this.shouldThrowWhenLoadingBindings = true
|
|
46
|
+
|
|
47
|
+
const err = assert.doesThrow(() => this.LibndxAdapter())
|
|
48
|
+
const actual = (err.message ?? err.stack).replace(/\s+/g, '')
|
|
49
|
+
|
|
50
|
+
assert.isEqual(
|
|
51
|
+
actual,
|
|
52
|
+
this.failedToLoadError,
|
|
53
|
+
'Did not receive the expected error!'
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@test()
|
|
58
|
+
protected static async callsFfiRsOpenWithRequiredOptions() {
|
|
59
|
+
assert.isEqualDeep(this.ffiRsOpenOptions, {
|
|
60
|
+
library: 'ndx',
|
|
61
|
+
path: this.libndxPath,
|
|
62
|
+
})
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@test()
|
|
66
|
+
protected static async callsFfiRsDefineWithRequiredOptions() {
|
|
67
|
+
assert.isEqualDeep(
|
|
68
|
+
this.ffiRsDefineOptions,
|
|
69
|
+
{
|
|
70
|
+
create_ble_backend: {
|
|
71
|
+
library: 'ndx',
|
|
72
|
+
retType: DataType.String,
|
|
73
|
+
paramsType: [DataType.String],
|
|
74
|
+
},
|
|
75
|
+
start_ble_backend: {
|
|
76
|
+
library: 'ndx',
|
|
77
|
+
retType: DataType.String,
|
|
78
|
+
paramsType: [DataType.String],
|
|
79
|
+
},
|
|
80
|
+
stop_ble_backend: {
|
|
81
|
+
library: 'ndx',
|
|
82
|
+
retType: DataType.String,
|
|
83
|
+
paramsType: [DataType.String],
|
|
84
|
+
},
|
|
85
|
+
destroy_ble_backend: {
|
|
86
|
+
library: 'ndx',
|
|
87
|
+
retType: DataType.String,
|
|
88
|
+
paramsType: [DataType.String],
|
|
89
|
+
},
|
|
90
|
+
create_ftdi_backend: {
|
|
91
|
+
library: 'ndx',
|
|
92
|
+
retType: DataType.String,
|
|
93
|
+
paramsType: [DataType.String],
|
|
94
|
+
},
|
|
95
|
+
start_ftdi_backend: {
|
|
96
|
+
library: 'ndx',
|
|
97
|
+
retType: DataType.String,
|
|
98
|
+
paramsType: [DataType.String],
|
|
99
|
+
},
|
|
100
|
+
stop_ftdi_backend: {
|
|
101
|
+
library: 'ndx',
|
|
102
|
+
retType: DataType.String,
|
|
103
|
+
paramsType: [DataType.String],
|
|
104
|
+
},
|
|
105
|
+
destroy_ftdi_backend: {
|
|
106
|
+
library: 'ndx',
|
|
107
|
+
retType: DataType.String,
|
|
108
|
+
paramsType: [DataType.String],
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
'Did not pass valid options to ffiRsDefine!'
|
|
112
|
+
)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
@test()
|
|
116
|
+
protected static async getInstanceReturnsASingleton() {
|
|
117
|
+
assert.isEqual(LibndxAdapter.getInstance(), LibndxAdapter.getInstance())
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
@test()
|
|
121
|
+
protected static canSetInstance() {
|
|
122
|
+
const fake = new FakeLibndx()
|
|
123
|
+
LibndxAdapter.setInstance(fake)
|
|
124
|
+
assert.isEqual(LibndxAdapter.getInstance(), fake)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
@test()
|
|
128
|
+
protected static async createBleBackendCallsBindingAndReturnsJsonString() {
|
|
129
|
+
const raw = this.instance.createBleBackend({
|
|
130
|
+
deviceUuid: this.bleDeviceUuid,
|
|
131
|
+
})
|
|
132
|
+
const json = JSON.parse(raw)
|
|
133
|
+
|
|
134
|
+
assert.isTruthy(json, 'createBleBackend did not return a JSON string!')
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
@test()
|
|
138
|
+
protected static async startBleBackendCallsBindingAndReturnsJsonString() {
|
|
139
|
+
const raw = this.instance.startBleBackend({
|
|
140
|
+
deviceUuid: this.bleDeviceUuid,
|
|
141
|
+
})
|
|
142
|
+
const json = JSON.parse(raw)
|
|
143
|
+
|
|
144
|
+
assert.isTruthy(json, 'startBleBackend did not return a JSON string!')
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
@test()
|
|
148
|
+
protected static async stopBleBackendCallsBindingAndReturnsJsonString() {
|
|
149
|
+
const raw = this.instance.stopBleBackend({
|
|
150
|
+
deviceUuid: this.bleDeviceUuid,
|
|
151
|
+
})
|
|
152
|
+
const json = JSON.parse(raw)
|
|
153
|
+
|
|
154
|
+
assert.isTruthy(json, 'stopBleBackend did not return a JSON string!')
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
@test()
|
|
158
|
+
protected static async destroyBleBackendCallsBindingAndReturnsJsonString() {
|
|
159
|
+
const raw = this.instance.destroyBleBackend({
|
|
160
|
+
deviceUuid: this.bleDeviceUuid,
|
|
161
|
+
})
|
|
162
|
+
const json = JSON.parse(raw)
|
|
163
|
+
|
|
164
|
+
assert.isTruthy(json, 'destroyBleBackend did not return a JSON string!')
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
@test()
|
|
168
|
+
protected static async createFtdiBackendCallsBindingAndReturnsJsonString() {
|
|
169
|
+
const raw = this.instance.createFtdiBackend({
|
|
170
|
+
serialNumber: this.ftdiSerialNumber,
|
|
171
|
+
})
|
|
172
|
+
const json = JSON.parse(raw)
|
|
173
|
+
|
|
174
|
+
assert.isTruthy(json, 'createFtdiBackend did not return a JSON string!')
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
@test()
|
|
178
|
+
protected static async startFtdiBackendCallsBindingAndReturnsJsonString() {
|
|
179
|
+
const raw = this.instance.startFtdiBackend({
|
|
180
|
+
serialNumber: this.ftdiSerialNumber,
|
|
181
|
+
})
|
|
182
|
+
const json = JSON.parse(raw)
|
|
183
|
+
|
|
184
|
+
assert.isTruthy(json, 'startFtdiBackend did not return a JSON string!')
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
@test()
|
|
188
|
+
protected static async stopFtdiBackendCallsBindingAndReturnsJsonString() {
|
|
189
|
+
const raw = this.instance.stopFtdiBackend({
|
|
190
|
+
serialNumber: this.ftdiSerialNumber,
|
|
191
|
+
})
|
|
192
|
+
const json = JSON.parse(raw)
|
|
193
|
+
|
|
194
|
+
assert.isTruthy(json, 'stopFtdiBackend did not return a JSON string!')
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
@test()
|
|
198
|
+
protected static async destroyFtdiBackendCallsBindingAndReturnsJsonString() {
|
|
199
|
+
const raw = this.instance.destroyFtdiBackend({
|
|
200
|
+
serialNumber: this.ftdiSerialNumber,
|
|
201
|
+
})
|
|
202
|
+
const json = JSON.parse(raw)
|
|
203
|
+
|
|
204
|
+
assert.isTruthy(
|
|
205
|
+
json,
|
|
206
|
+
'destroyFtdiBackend did not return a JSON string!'
|
|
207
|
+
)
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
private static clearAndFakeFfi() {
|
|
211
|
+
delete this.ffiRsOpenOptions
|
|
212
|
+
delete this.ffiRsDefineOptions
|
|
213
|
+
this.fakeFfiRsOpen()
|
|
214
|
+
this.fakeFfiRsDefine()
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
private static fakeFfiRsOpen() {
|
|
218
|
+
LibndxAdapter.ffiRsOpen = (options) => {
|
|
219
|
+
this.ffiRsOpenOptions = options
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
private static fakeFfiRsDefine() {
|
|
224
|
+
LibndxAdapter.ffiRsDefine = ((options) => {
|
|
225
|
+
this.ffiRsDefineOptions = options
|
|
226
|
+
|
|
227
|
+
if (this.shouldThrowWhenLoadingBindings) {
|
|
228
|
+
throw new Error(this.fakeErrorMessage)
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return this.fakeBindings as any
|
|
232
|
+
}) as typeof define
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
private static get failedToLoadError() {
|
|
236
|
+
return `
|
|
237
|
+
\n -----------------------------------
|
|
238
|
+
\n Failed to load libndx! Tried to load from:
|
|
239
|
+
\n ${this.libndxPath}
|
|
240
|
+
\n Instructions to save your day (on MacOS):
|
|
241
|
+
\n 1. git clone https://github.com/neurodevs/libndx.git
|
|
242
|
+
\n 2. cd libndx && cmake -S . -B build && cmake --build build
|
|
243
|
+
\n 3. sudo cp build/libndx.dylib /opt/local/lib/
|
|
244
|
+
\n 4. Try whatever you were doing again!
|
|
245
|
+
\n Modify step 3 for your OS if you are not on MacOS.
|
|
246
|
+
\n If you're still unsure, ask an LLM with this error and your OS.
|
|
247
|
+
\n You could also post an issue on the repo:
|
|
248
|
+
\n https://github.com/neurodevs/ndx-native/issues
|
|
249
|
+
\n Good luck!
|
|
250
|
+
\n @ericthecurious
|
|
251
|
+
\n -----------------------------------
|
|
252
|
+
\n Original error: ${this.fakeErrorMessage}
|
|
253
|
+
\n
|
|
254
|
+
`.replace(/\s+/g, '')
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
private static FakeBindings(): LibndxBindings {
|
|
258
|
+
return {
|
|
259
|
+
create_ble_backend: () => JSON.stringify({}),
|
|
260
|
+
start_ble_backend: () => JSON.stringify({}),
|
|
261
|
+
stop_ble_backend: () => JSON.stringify({}),
|
|
262
|
+
destroy_ble_backend: () => JSON.stringify({}),
|
|
263
|
+
create_ftdi_backend: () => JSON.stringify({}),
|
|
264
|
+
start_ftdi_backend: () => JSON.stringify({}),
|
|
265
|
+
stop_ftdi_backend: () => JSON.stringify({}),
|
|
266
|
+
destroy_ftdi_backend: () => JSON.stringify({}),
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
private static resetInstance() {
|
|
271
|
+
LibndxAdapter.resetInstance()
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
private static LibndxAdapter() {
|
|
275
|
+
return LibndxAdapter.getInstance({
|
|
276
|
+
libndxPath: this.libndxPath,
|
|
277
|
+
})
|
|
278
|
+
}
|
|
279
|
+
}
|
|
@@ -7,10 +7,10 @@ import { test, assert } from '@neurodevs/node-tdd'
|
|
|
7
7
|
import { DataType, OpenParams } from 'ffi-rs'
|
|
8
8
|
|
|
9
9
|
import LibxdfAdapter, {
|
|
10
|
-
FfiRsDefineOptions,
|
|
11
10
|
LibxdfBindings,
|
|
12
11
|
XdfFile,
|
|
13
12
|
} from '../../impl/LibxdfAdapter.js'
|
|
13
|
+
import { FfiRsDefineOptions } from 'types.js'
|
|
14
14
|
import SpyLibxdf from '../../testDoubles/Libxdf/SpyLibxdf.js'
|
|
15
15
|
import AbstractPackageTest from '../AbstractPackageTest.js'
|
|
16
16
|
|
|
@@ -44,8 +44,8 @@ export default class LibxdfTest extends AbstractPackageTest {
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
@test()
|
|
47
|
-
protected static
|
|
48
|
-
assert.isTruthy(this.instance, '
|
|
47
|
+
protected static createsInstance() {
|
|
48
|
+
assert.isTruthy(this.instance, 'Failed to create instance!')
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
@test()
|
|
@@ -90,7 +90,7 @@ export default class LibxdfTest extends AbstractPackageTest {
|
|
|
90
90
|
paramsType: [DataType.String],
|
|
91
91
|
},
|
|
92
92
|
},
|
|
93
|
-
'
|
|
93
|
+
'Did not pass valid options to ffiRsDefine!'
|
|
94
94
|
)
|
|
95
95
|
}
|
|
96
96
|
|
|
@@ -101,7 +101,7 @@ export default class LibxdfTest extends AbstractPackageTest {
|
|
|
101
101
|
assert.isEqualDeep(
|
|
102
102
|
this.loadXdfCalls[0],
|
|
103
103
|
[this.path],
|
|
104
|
-
'
|
|
104
|
+
'Did not call load_xdf_to_json(path)!'
|
|
105
105
|
)
|
|
106
106
|
}
|
|
107
107
|
|
|
@@ -241,7 +241,6 @@ export default class LibxdfTest extends AbstractPackageTest {
|
|
|
241
241
|
private static readonly fakeNominalSampleRate = 0
|
|
242
242
|
private static readonly fakeEventName = generateId()
|
|
243
243
|
private static readonly fakeEventTimestamp = 0
|
|
244
|
-
private static readonly fakeErrorMessage = 'Fake error message!'
|
|
245
244
|
|
|
246
245
|
private static fakeSerializedXdf = `{"streams": [{"stream_id": ${this.fakeStreamId}, "time_series": [], "time_stamps": [], "stream_info": {"channel_count": ${this.fakeChannelCount}, "channel_format": "${this.fakeChannelFormat}", "nominal_srate": ${this.fakeNominalSampleRate}, "stream_name": "${this.fakeStreamName}", "stream_type": "${this.fakeStreamType}"}}], "events": [{"stream_id": ${this.fakeStreamId}, "event_name": "${this.fakeEventName}", "event_timestamp": ${this.fakeEventTimestamp}}]}`
|
|
247
246
|
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
} from 'ffi-rs'
|
|
10
10
|
|
|
11
11
|
import { CHANNEL_FORMATS } from '../consts.js'
|
|
12
|
-
import { LslErrorCode } from '../lib/
|
|
12
|
+
import { LslErrorCode } from '../lib/handleLslError.js'
|
|
13
13
|
|
|
14
14
|
export default class LiblslAdapter implements Liblsl {
|
|
15
15
|
public static open = open
|
|
@@ -29,20 +29,6 @@ export default class LiblslAdapter implements Liblsl {
|
|
|
29
29
|
this.tryToLoadBindings()
|
|
30
30
|
}
|
|
31
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
32
|
public static getInstance() {
|
|
47
33
|
if (!this.instance) {
|
|
48
34
|
this.setInstance(new this())
|
|
@@ -58,9 +44,13 @@ export default class LiblslAdapter implements Liblsl {
|
|
|
58
44
|
delete this.instance
|
|
59
45
|
}
|
|
60
46
|
|
|
61
|
-
private
|
|
62
|
-
|
|
63
|
-
|
|
47
|
+
private tryToLoadBindings() {
|
|
48
|
+
try {
|
|
49
|
+
this.openLiblsl()
|
|
50
|
+
this.defineBindings()
|
|
51
|
+
} catch (error) {
|
|
52
|
+
this.throwFailedToLoadLiblsl(error as Error)
|
|
53
|
+
}
|
|
64
54
|
}
|
|
65
55
|
|
|
66
56
|
private openLiblsl() {
|
|
@@ -70,8 +60,113 @@ export default class LiblslAdapter implements Liblsl {
|
|
|
70
60
|
})
|
|
71
61
|
}
|
|
72
62
|
|
|
73
|
-
private
|
|
74
|
-
|
|
63
|
+
private defineBindings() {
|
|
64
|
+
this.bindings = this.define({
|
|
65
|
+
lsl_local_clock: {
|
|
66
|
+
library: 'lsl',
|
|
67
|
+
retType: DataType.Double,
|
|
68
|
+
paramsType: [],
|
|
69
|
+
},
|
|
70
|
+
lsl_create_streaminfo: {
|
|
71
|
+
library: 'lsl',
|
|
72
|
+
retType: DataType.External,
|
|
73
|
+
paramsType: [
|
|
74
|
+
DataType.String,
|
|
75
|
+
DataType.String,
|
|
76
|
+
DataType.I32,
|
|
77
|
+
DataType.Double,
|
|
78
|
+
DataType.I32,
|
|
79
|
+
DataType.String,
|
|
80
|
+
],
|
|
81
|
+
},
|
|
82
|
+
lsl_destroy_streaminfo: {
|
|
83
|
+
library: 'lsl',
|
|
84
|
+
retType: DataType.Void,
|
|
85
|
+
paramsType: [DataType.External],
|
|
86
|
+
},
|
|
87
|
+
lsl_create_outlet: {
|
|
88
|
+
library: 'lsl',
|
|
89
|
+
retType: DataType.External,
|
|
90
|
+
paramsType: [DataType.External, DataType.I32, DataType.I32],
|
|
91
|
+
},
|
|
92
|
+
lsl_push_sample_ft: {
|
|
93
|
+
library: 'lsl',
|
|
94
|
+
retType: DataType.I32,
|
|
95
|
+
paramsType: [
|
|
96
|
+
DataType.External,
|
|
97
|
+
DataType.FloatArray,
|
|
98
|
+
DataType.Double,
|
|
99
|
+
],
|
|
100
|
+
},
|
|
101
|
+
lsl_push_sample_strt: {
|
|
102
|
+
library: 'lsl',
|
|
103
|
+
retType: DataType.I32,
|
|
104
|
+
paramsType: [
|
|
105
|
+
DataType.External,
|
|
106
|
+
DataType.StringArray,
|
|
107
|
+
DataType.Double,
|
|
108
|
+
],
|
|
109
|
+
},
|
|
110
|
+
lsl_destroy_outlet: {
|
|
111
|
+
library: 'lsl',
|
|
112
|
+
retType: DataType.Void,
|
|
113
|
+
paramsType: [DataType.External],
|
|
114
|
+
},
|
|
115
|
+
lsl_create_inlet: {
|
|
116
|
+
library: 'lsl',
|
|
117
|
+
retType: DataType.External,
|
|
118
|
+
paramsType: [
|
|
119
|
+
DataType.External,
|
|
120
|
+
DataType.I32,
|
|
121
|
+
DataType.I32,
|
|
122
|
+
DataType.I32,
|
|
123
|
+
],
|
|
124
|
+
},
|
|
125
|
+
lsl_inlet_flush: {
|
|
126
|
+
library: 'lsl',
|
|
127
|
+
retType: DataType.I32,
|
|
128
|
+
paramsType: [DataType.External],
|
|
129
|
+
},
|
|
130
|
+
lsl_destroy_inlet: {
|
|
131
|
+
library: 'lsl',
|
|
132
|
+
retType: DataType.Void,
|
|
133
|
+
paramsType: [DataType.External],
|
|
134
|
+
},
|
|
135
|
+
lsl_get_desc: {
|
|
136
|
+
library: 'lsl',
|
|
137
|
+
retType: DataType.External,
|
|
138
|
+
paramsType: [DataType.External],
|
|
139
|
+
},
|
|
140
|
+
lsl_get_channel_count: {
|
|
141
|
+
library: 'lsl',
|
|
142
|
+
retType: DataType.I32,
|
|
143
|
+
paramsType: [DataType.External],
|
|
144
|
+
},
|
|
145
|
+
lsl_append_child: {
|
|
146
|
+
library: 'lsl',
|
|
147
|
+
retType: DataType.External,
|
|
148
|
+
paramsType: [DataType.External, DataType.String],
|
|
149
|
+
},
|
|
150
|
+
lsl_append_child_value: {
|
|
151
|
+
library: 'lsl',
|
|
152
|
+
retType: DataType.External,
|
|
153
|
+
paramsType: [
|
|
154
|
+
DataType.External,
|
|
155
|
+
DataType.String,
|
|
156
|
+
DataType.String,
|
|
157
|
+
],
|
|
158
|
+
},
|
|
159
|
+
}) as LiblslBindings
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
private throwFailedToLoadLiblsl(error: Error) {
|
|
163
|
+
throw new Error(
|
|
164
|
+
`Loading the liblsl dylib failed! I tried to load it from ${this.liblslPath}.\n\n${error.message}\n\n`
|
|
165
|
+
)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
public localClock() {
|
|
169
|
+
return this.bindings.lsl_local_clock([])
|
|
75
170
|
}
|
|
76
171
|
|
|
77
172
|
public createStreamInfo(options: CreateStreamInfoOptions) {
|
|
@@ -332,10 +427,6 @@ export default class LiblslAdapter implements Liblsl {
|
|
|
332
427
|
this.bindings.lsl_destroy_inlet([inletHandle])
|
|
333
428
|
}
|
|
334
429
|
|
|
335
|
-
public localClock() {
|
|
336
|
-
return this.bindings.lsl_local_clock([])
|
|
337
|
-
}
|
|
338
|
-
|
|
339
430
|
private get open() {
|
|
340
431
|
return LiblslAdapter.open
|
|
341
432
|
}
|
|
@@ -351,110 +442,13 @@ export default class LiblslAdapter implements Liblsl {
|
|
|
351
442
|
private get alloc() {
|
|
352
443
|
return LiblslAdapter.alloc
|
|
353
444
|
}
|
|
354
|
-
|
|
355
|
-
private get liblslFuncs() {
|
|
356
|
-
return {
|
|
357
|
-
lsl_create_streaminfo: {
|
|
358
|
-
library: 'lsl',
|
|
359
|
-
retType: DataType.External,
|
|
360
|
-
paramsType: [
|
|
361
|
-
DataType.String,
|
|
362
|
-
DataType.String,
|
|
363
|
-
DataType.I32,
|
|
364
|
-
DataType.Double,
|
|
365
|
-
DataType.I32,
|
|
366
|
-
DataType.String,
|
|
367
|
-
],
|
|
368
|
-
},
|
|
369
|
-
lsl_destroy_streaminfo: {
|
|
370
|
-
library: 'lsl',
|
|
371
|
-
retType: DataType.Void,
|
|
372
|
-
paramsType: [DataType.External],
|
|
373
|
-
},
|
|
374
|
-
lsl_create_outlet: {
|
|
375
|
-
library: 'lsl',
|
|
376
|
-
retType: DataType.External,
|
|
377
|
-
paramsType: [DataType.External, DataType.I32, DataType.I32],
|
|
378
|
-
},
|
|
379
|
-
lsl_push_sample_ft: {
|
|
380
|
-
library: 'lsl',
|
|
381
|
-
retType: DataType.I32,
|
|
382
|
-
paramsType: [
|
|
383
|
-
DataType.External,
|
|
384
|
-
DataType.FloatArray,
|
|
385
|
-
DataType.Double,
|
|
386
|
-
],
|
|
387
|
-
},
|
|
388
|
-
lsl_push_sample_strt: {
|
|
389
|
-
library: 'lsl',
|
|
390
|
-
retType: DataType.I32,
|
|
391
|
-
paramsType: [
|
|
392
|
-
DataType.External,
|
|
393
|
-
DataType.StringArray,
|
|
394
|
-
DataType.Double,
|
|
395
|
-
],
|
|
396
|
-
},
|
|
397
|
-
lsl_destroy_outlet: {
|
|
398
|
-
library: 'lsl',
|
|
399
|
-
retType: DataType.Void,
|
|
400
|
-
paramsType: [DataType.External],
|
|
401
|
-
},
|
|
402
|
-
lsl_create_inlet: {
|
|
403
|
-
library: 'lsl',
|
|
404
|
-
retType: DataType.External,
|
|
405
|
-
paramsType: [
|
|
406
|
-
DataType.External,
|
|
407
|
-
DataType.I32,
|
|
408
|
-
DataType.I32,
|
|
409
|
-
DataType.I32,
|
|
410
|
-
],
|
|
411
|
-
},
|
|
412
|
-
lsl_inlet_flush: {
|
|
413
|
-
library: 'lsl',
|
|
414
|
-
retType: DataType.I32,
|
|
415
|
-
paramsType: [DataType.External],
|
|
416
|
-
},
|
|
417
|
-
lsl_destroy_inlet: {
|
|
418
|
-
library: 'lsl',
|
|
419
|
-
retType: DataType.Void,
|
|
420
|
-
paramsType: [DataType.External],
|
|
421
|
-
},
|
|
422
|
-
lsl_get_desc: {
|
|
423
|
-
library: 'lsl',
|
|
424
|
-
retType: DataType.External,
|
|
425
|
-
paramsType: [DataType.External],
|
|
426
|
-
},
|
|
427
|
-
lsl_get_channel_count: {
|
|
428
|
-
library: 'lsl',
|
|
429
|
-
retType: DataType.I32,
|
|
430
|
-
paramsType: [DataType.External],
|
|
431
|
-
},
|
|
432
|
-
lsl_append_child: {
|
|
433
|
-
library: 'lsl',
|
|
434
|
-
retType: DataType.External,
|
|
435
|
-
paramsType: [DataType.External, DataType.String],
|
|
436
|
-
},
|
|
437
|
-
lsl_append_child_value: {
|
|
438
|
-
library: 'lsl',
|
|
439
|
-
retType: DataType.External,
|
|
440
|
-
paramsType: [
|
|
441
|
-
DataType.External,
|
|
442
|
-
DataType.String,
|
|
443
|
-
DataType.String,
|
|
444
|
-
],
|
|
445
|
-
},
|
|
446
|
-
lsl_local_clock: {
|
|
447
|
-
library: 'lsl',
|
|
448
|
-
retType: DataType.Double,
|
|
449
|
-
paramsType: [],
|
|
450
|
-
},
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
445
|
}
|
|
454
446
|
|
|
455
447
|
export interface Liblsl {
|
|
456
448
|
liblslPath: string
|
|
457
449
|
|
|
450
|
+
localClock(): number
|
|
451
|
+
|
|
458
452
|
createStreamInfo(options: CreateStreamInfoOptions): InfoHandle
|
|
459
453
|
destroyStreamInfo(options: DestroyStreamInfoOptions): void
|
|
460
454
|
appendChannelsToStreamInfo(options: AppendChannelsToStreamInfoOptions): void
|
|
@@ -481,8 +475,6 @@ export interface Liblsl {
|
|
|
481
475
|
pullChunk(options: PullChunkOptions): number
|
|
482
476
|
flushInlet(options: FlushInletOptions): void
|
|
483
477
|
destroyInlet(options: DestroyInletOptions): void
|
|
484
|
-
|
|
485
|
-
localClock(): number
|
|
486
478
|
}
|
|
487
479
|
|
|
488
480
|
export interface CreateStreamInfoOptions {
|
|
@@ -575,6 +567,8 @@ export interface DestroyInletOptions {
|
|
|
575
567
|
}
|
|
576
568
|
|
|
577
569
|
export interface LiblslBindings {
|
|
570
|
+
lsl_local_clock(args: []): number
|
|
571
|
+
|
|
578
572
|
lsl_create_streaminfo(
|
|
579
573
|
args: [string, string, number, number, number, string]
|
|
580
574
|
): InfoHandle
|
|
@@ -593,8 +587,6 @@ export interface LiblslBindings {
|
|
|
593
587
|
lsl_create_inlet(args: any): InletHandle
|
|
594
588
|
lsl_inlet_flush(args: [InletHandle]): void
|
|
595
589
|
lsl_destroy_inlet(args: any): void
|
|
596
|
-
|
|
597
|
-
lsl_local_clock(args: []): number
|
|
598
590
|
}
|
|
599
591
|
|
|
600
592
|
export type ChannelFormat = (typeof CHANNEL_FORMATS)[number]
|