@neurodevs/node-lsl 11.4.1 → 11.4.2
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/README.md +40 -29
- package/build/.spruce/settings.json +1 -3
- package/build/__tests__/AbstractLslTest.d.ts +1 -0
- package/build/__tests__/AbstractLslTest.js +1 -0
- package/build/__tests__/AbstractLslTest.js.map +1 -1
- package/build/__tests__/modules/LiblslAdapter.test.d.ts +1 -5
- package/build/__tests__/modules/LiblslAdapter.test.js +5 -61
- package/build/__tests__/modules/LiblslAdapter.test.js.map +1 -1
- package/build/__tests__/modules/LslStreamInfo.test.d.ts +0 -1
- package/build/__tests__/modules/LslStreamInfo.test.js +0 -11
- package/build/__tests__/modules/LslStreamInfo.test.js.map +1 -1
- package/build/__tests__/modules/LslStreamInlet.test.d.ts +0 -1
- package/build/__tests__/modules/LslStreamInlet.test.js +0 -17
- package/build/__tests__/modules/LslStreamInlet.test.js.map +1 -1
- package/build/__tests__/modules/LslStreamOutlet.test.d.ts +7 -5
- package/build/__tests__/modules/LslStreamOutlet.test.js +34 -52
- package/build/__tests__/modules/LslStreamOutlet.test.js.map +1 -1
- package/build/assertions.d.ts +1 -1
- package/build/assertions.js +10 -31
- package/build/assertions.js.map +1 -1
- package/build/modules/LiblslAdapter.d.ts +3 -1
- package/build/modules/LiblslAdapter.js +15 -44
- package/build/modules/LiblslAdapter.js.map +1 -1
- package/build/modules/LslStreamInfo.js +0 -2
- package/build/modules/LslStreamInfo.js.map +1 -1
- package/build/modules/LslStreamInlet.js +2 -10
- package/build/modules/LslStreamInlet.js.map +1 -1
- package/build/modules/LslStreamOutlet.js +0 -13
- package/build/modules/LslStreamOutlet.js.map +1 -1
- package/build/scripts/demoMarkerOutlet.d.ts +1 -0
- package/build/scripts/demoMarkerOutlet.js +23 -0
- package/build/scripts/demoMarkerOutlet.js.map +1 -0
- package/build/scripts/demoStreamOutlet.d.ts +1 -0
- package/build/scripts/demoStreamOutlet.js +25 -0
- package/build/scripts/demoStreamOutlet.js.map +1 -0
- package/package.json +8 -12
- package/src/.spruce/settings.json +1 -3
- package/src/__tests__/AbstractLslTest.ts +1 -0
- package/src/__tests__/modules/LiblslAdapter.test.ts +12 -58
- package/src/__tests__/modules/LslStreamInfo.test.ts +1 -12
- package/src/__tests__/modules/LslStreamInlet.test.ts +1 -18
- package/src/__tests__/modules/LslStreamOutlet.test.ts +56 -55
- package/src/assertions.ts +19 -30
- package/src/modules/LiblslAdapter.ts +18 -44
- package/src/modules/LslStreamInfo.ts +0 -2
- package/src/modules/LslStreamInlet.ts +2 -10
- package/src/modules/LslStreamOutlet.ts +0 -14
- package/src/scripts/demoMarkerOutlet.ts +23 -0
- package/src/scripts/demoStreamOutlet.ts +22 -0
- package/build/.spruce/errors/errors.types.d.ts +0 -21
- package/build/.spruce/errors/errors.types.js +0 -3
- package/build/.spruce/errors/errors.types.js.map +0 -1
- package/build/.spruce/errors/nodeLsl/failedToLoadLiblsl.schema.d.ts +0 -3
- package/build/.spruce/errors/nodeLsl/failedToLoadLiblsl.schema.js +0 -19
- package/build/.spruce/errors/nodeLsl/failedToLoadLiblsl.schema.js.map +0 -1
- package/build/.spruce/errors/options.types.d.ts +0 -7
- package/build/.spruce/errors/options.types.js +0 -3
- package/build/.spruce/errors/options.types.js.map +0 -1
- package/build/.spruce/schemas/fields/fieldClassMap.d.ts +0 -2
- package/build/.spruce/schemas/fields/fieldClassMap.js +0 -5
- package/build/.spruce/schemas/fields/fieldClassMap.js.map +0 -1
- package/build/.spruce/schemas/fields/fields.types.d.ts +0 -1
- package/build/.spruce/schemas/fields/fields.types.js +0 -3
- package/build/.spruce/schemas/fields/fields.types.js.map +0 -1
- package/build/errors/SpruceError.d.ts +0 -6
- package/build/errors/SpruceError.js +0 -26
- package/build/errors/SpruceError.js.map +0 -1
- package/build/errors/failedToLoadLiblsl.builder.d.ts +0 -11
- package/build/errors/failedToLoadLiblsl.builder.js +0 -14
- package/build/errors/failedToLoadLiblsl.builder.js.map +0 -1
- package/src/.spruce/errors/errors.types.ts +0 -37
- package/src/.spruce/errors/nodeLsl/failedToLoadLiblsl.schema.ts +0 -22
- package/src/.spruce/errors/options.types.ts +0 -10
- package/src/.spruce/schemas/fields/fieldClassMap.ts +0 -6
- package/src/.spruce/schemas/fields/fields.types.ts +0 -1
- package/src/errors/SpruceError.ts +0 -23
- package/src/errors/failedToLoadLiblsl.builder.ts +0 -12
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { test, assert, generateId
|
|
1
|
+
import { test, assert, generateId } from '@sprucelabs/test-utils'
|
|
2
2
|
import { CHANNEL_FORMATS } from '../../consts'
|
|
3
3
|
import LslStreamInfo, { StreamInfoOptions } from '../../modules/LslStreamInfo'
|
|
4
4
|
import SpyStreamInfo from '../../testDoubles/StreamInfo/SpyStreamInfo'
|
|
@@ -20,17 +20,6 @@ export default class LslStreamInfoTest extends AbstractLslTest {
|
|
|
20
20
|
assert.isTruthy(this.instance, 'Instance should be created!')
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
@test()
|
|
24
|
-
protected static async throwsWithMissingRequiredOptions() {
|
|
25
|
-
const err = assert.doesThrow(
|
|
26
|
-
// @ts-ignore
|
|
27
|
-
() => LslStreamInfo.Create()
|
|
28
|
-
)
|
|
29
|
-
errorAssert.assertError(err, 'MISSING_PARAMETERS', {
|
|
30
|
-
parameters: ['channelNames', 'channelFormat', 'sampleRate'],
|
|
31
|
-
})
|
|
32
|
-
}
|
|
33
|
-
|
|
34
23
|
@test()
|
|
35
24
|
protected static async generatesUniqueNameIfNotProvided() {
|
|
36
25
|
const instance1 = this.LslStreamInfo({ name: undefined })
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { test, assert
|
|
1
|
+
import { test, assert } from '@sprucelabs/test-utils'
|
|
2
2
|
import LslStreamInlet, { LslInletOptions } from '../../modules/LslStreamInlet'
|
|
3
3
|
import { SpyLslInlet } from '../../testDoubles/LslInlet/SpyLslInlet'
|
|
4
4
|
import FakeStreamInfo from '../../testDoubles/StreamInfo/FakeStreamInfo'
|
|
@@ -21,23 +21,6 @@ export default class LslStreamInletTest extends AbstractLslTest {
|
|
|
21
21
|
assert.isTruthy(this.instance, 'Instance should be created!')
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
@test()
|
|
25
|
-
protected static async throwsWithMissingRequiredOptions() {
|
|
26
|
-
const err = assert.doesThrow(
|
|
27
|
-
// @ts-ignore
|
|
28
|
-
() => LslStreamInlet.Create()
|
|
29
|
-
)
|
|
30
|
-
errorAssert.assertError(err, 'MISSING_PARAMETERS', {
|
|
31
|
-
parameters: [
|
|
32
|
-
'channelNames',
|
|
33
|
-
'channelFormat',
|
|
34
|
-
'sampleRate',
|
|
35
|
-
'chunkSize',
|
|
36
|
-
'maxBuffered',
|
|
37
|
-
],
|
|
38
|
-
})
|
|
39
|
-
}
|
|
40
|
-
|
|
41
24
|
@test()
|
|
42
25
|
protected static async createsStreamInfoWithExpectedOptions() {
|
|
43
26
|
assert.isEqualDeep(
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { test, assert,
|
|
1
|
+
import { test, assert, generateId } from '@sprucelabs/test-utils'
|
|
2
|
+
import { CHANNEL_FORMATS } from '../../consts'
|
|
2
3
|
import { StreamInfo } from '../../modules/LslStreamInfo'
|
|
3
4
|
import LslStreamOutlet, {
|
|
4
5
|
LslOutletOptions,
|
|
@@ -11,7 +12,7 @@ import {
|
|
|
11
12
|
|
|
12
13
|
import generateRandomOutletOptions from '../../testDoubles/generateRandomOutletOptions'
|
|
13
14
|
import FakeStreamInfo from '../../testDoubles/StreamInfo/FakeStreamInfo'
|
|
14
|
-
import { LslSample } from '../../types'
|
|
15
|
+
import { ChannelFormat, LslSample } from '../../types'
|
|
15
16
|
import AbstractLslTest from '../AbstractLslTest'
|
|
16
17
|
|
|
17
18
|
export default class LslStreamOutletTest extends AbstractLslTest {
|
|
@@ -29,30 +30,8 @@ export default class LslStreamOutletTest extends AbstractLslTest {
|
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
@test()
|
|
32
|
-
protected static async
|
|
33
|
-
|
|
34
|
-
//@ts-ignore
|
|
35
|
-
async () => await LslStreamOutlet.Create()
|
|
36
|
-
)
|
|
37
|
-
errorAssert.assertError(err, 'MISSING_PARAMETERS', {
|
|
38
|
-
parameters: [
|
|
39
|
-
'name',
|
|
40
|
-
'type',
|
|
41
|
-
'sourceId',
|
|
42
|
-
'channelNames',
|
|
43
|
-
'channelFormat',
|
|
44
|
-
'sampleRate',
|
|
45
|
-
'chunkSize',
|
|
46
|
-
'maxBuffered',
|
|
47
|
-
'manufacturer',
|
|
48
|
-
'unit',
|
|
49
|
-
],
|
|
50
|
-
})
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
@test()
|
|
54
|
-
protected static async throwsWithInvalidChannelNames() {
|
|
55
|
-
await this.assertThrowsInvalidChannelNames(0)
|
|
33
|
+
protected static async throwsWithEmptyChannelNames() {
|
|
34
|
+
await this.assertThrowsWithEmptyChannelNames()
|
|
56
35
|
}
|
|
57
36
|
|
|
58
37
|
@test()
|
|
@@ -68,24 +47,30 @@ export default class LslStreamOutletTest extends AbstractLslTest {
|
|
|
68
47
|
|
|
69
48
|
@test()
|
|
70
49
|
protected static async throwsWithInvalidChannelFormat() {
|
|
71
|
-
await this.
|
|
72
|
-
|
|
73
|
-
{ channelFormat: generateId() },
|
|
74
|
-
['channelFormat']
|
|
50
|
+
await this.assertThrowsInvalidChannelFormat(
|
|
51
|
+
'invalid-format' as ChannelFormat
|
|
75
52
|
)
|
|
76
53
|
}
|
|
77
54
|
|
|
78
55
|
@test()
|
|
79
|
-
protected static async
|
|
56
|
+
protected static async allowsZeroChunkSize() {
|
|
80
57
|
await this.LslStreamOutlet({ chunkSize: 0 })
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@test()
|
|
61
|
+
protected static async throwsWithInvalidChunkSize() {
|
|
81
62
|
await this.assertThrowsInvalidChunkSize(-1)
|
|
82
63
|
await this.assertThrowsInvalidChunkSize(-1.5)
|
|
83
64
|
await this.assertThrowsInvalidChunkSize(1.5)
|
|
84
65
|
}
|
|
85
66
|
|
|
86
67
|
@test()
|
|
87
|
-
protected static async
|
|
68
|
+
protected static async allowsZeroMaxBuffered() {
|
|
88
69
|
await this.LslStreamOutlet({ maxBuffered: 0 })
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
@test()
|
|
73
|
+
protected static async throwsWithInvalidMaxBuffered() {
|
|
89
74
|
await this.assertThrowsInvalidMaxBuffered(-1)
|
|
90
75
|
await this.assertThrowsInvalidMaxBuffered(-1.5)
|
|
91
76
|
await this.assertThrowsInvalidMaxBuffered(1.5)
|
|
@@ -226,41 +211,57 @@ export default class LslStreamOutletTest extends AbstractLslTest {
|
|
|
226
211
|
assert.isAbove(endMs - startMs, 10)
|
|
227
212
|
}
|
|
228
213
|
|
|
229
|
-
private static async
|
|
230
|
-
await this.
|
|
231
|
-
'
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
private static async assertThrowsInvalidChunkSize(chunkSize: number) {
|
|
236
|
-
await this.assertDoesThrowInvalidParameters({ chunkSize }, [
|
|
237
|
-
'chunkSize',
|
|
238
|
-
])
|
|
214
|
+
private static async assertThrowsWithEmptyChannelNames() {
|
|
215
|
+
await this.createAndAssertThrows(
|
|
216
|
+
'channelNames',
|
|
217
|
+
[],
|
|
218
|
+
`Invalid channel count! Must be a positive integer, not: 0.`
|
|
219
|
+
)
|
|
239
220
|
}
|
|
240
221
|
|
|
241
222
|
private static async assertThrowsInvalidSampleRate(sampleRate: number) {
|
|
242
|
-
await this.
|
|
223
|
+
await this.createAndAssertThrows(
|
|
243
224
|
'sampleRate',
|
|
244
|
-
|
|
225
|
+
sampleRate,
|
|
226
|
+
`Invalid sample rate! Must be a positive number or zero, not: ${sampleRate}`
|
|
227
|
+
)
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
private static async assertThrowsInvalidChannelFormat(
|
|
231
|
+
channelFormat: ChannelFormat
|
|
232
|
+
) {
|
|
233
|
+
await this.createAndAssertThrows(
|
|
234
|
+
'channelFormat',
|
|
235
|
+
channelFormat,
|
|
236
|
+
`Invalid channel format! Must be one of: ${CHANNEL_FORMATS.join(', ')}, not ${channelFormat}.`
|
|
237
|
+
)
|
|
245
238
|
}
|
|
246
239
|
|
|
247
|
-
private static async
|
|
248
|
-
await this.
|
|
249
|
-
|
|
250
|
-
|
|
240
|
+
private static async assertThrowsInvalidMaxBuffered(maxBuffered: number) {
|
|
241
|
+
await this.createAndAssertThrows(
|
|
242
|
+
'maxBuffered',
|
|
243
|
+
maxBuffered,
|
|
244
|
+
`Invalid max buffered! Must be a positive integer or zero, not: ${maxBuffered}`
|
|
251
245
|
)
|
|
252
246
|
}
|
|
253
247
|
|
|
254
|
-
private static async
|
|
255
|
-
|
|
256
|
-
|
|
248
|
+
private static async assertThrowsInvalidChunkSize(chunkSize: number) {
|
|
249
|
+
await this.createAndAssertThrows(
|
|
250
|
+
'chunkSize',
|
|
251
|
+
chunkSize,
|
|
252
|
+
`Invalid chunk size! Must be a positive integer or zero, not: ${chunkSize}`
|
|
253
|
+
)
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
private static async createAndAssertThrows(
|
|
257
|
+
option: keyof LslOutletOptions,
|
|
258
|
+
value: number | string[] | ChannelFormat,
|
|
259
|
+
expectedMessage: string
|
|
257
260
|
) {
|
|
258
261
|
const err = await assert.doesThrowAsync(
|
|
259
|
-
async () => await this.LslStreamOutlet(
|
|
262
|
+
async () => await this.LslStreamOutlet({ [option]: value })
|
|
260
263
|
)
|
|
261
|
-
|
|
262
|
-
parameters,
|
|
263
|
-
})
|
|
264
|
+
assert.isTrue(err.message.includes(expectedMessage))
|
|
264
265
|
}
|
|
265
266
|
|
|
266
267
|
private static async StringOutlet() {
|
package/src/assertions.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { SchemaError } from '@sprucelabs/schema'
|
|
2
1
|
import { CHANNEL_FORMATS } from './consts'
|
|
3
2
|
import { ChannelFormat } from './types'
|
|
4
3
|
import {
|
|
@@ -8,52 +7,42 @@ import {
|
|
|
8
7
|
isStringInArray,
|
|
9
8
|
} from './validations'
|
|
10
9
|
|
|
11
|
-
export function
|
|
12
|
-
if (!isPositiveIntegerOrZero(
|
|
13
|
-
throw new
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
friendlyMessage: 'Max buffered must be a positive integer or zero.',
|
|
17
|
-
})
|
|
10
|
+
export function assertValidChunkSize(chunkSize: number) {
|
|
11
|
+
if (!isPositiveIntegerOrZero(chunkSize)) {
|
|
12
|
+
throw new Error(
|
|
13
|
+
`Invalid chunk size! Must be a positive integer or zero, not: ${chunkSize}.`
|
|
14
|
+
)
|
|
18
15
|
}
|
|
19
16
|
}
|
|
20
17
|
|
|
21
|
-
export function
|
|
22
|
-
if (!isPositiveIntegerOrZero(
|
|
23
|
-
throw new
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
friendlyMessage: 'Chunk size must be a positive integer or zero.',
|
|
27
|
-
})
|
|
18
|
+
export function assertValidMaxBuffered(maxBuffered: number) {
|
|
19
|
+
if (!isPositiveIntegerOrZero(maxBuffered)) {
|
|
20
|
+
throw new Error(
|
|
21
|
+
`Invalid max buffered! Must be a positive integer or zero, not: ${maxBuffered}.`
|
|
22
|
+
)
|
|
28
23
|
}
|
|
29
24
|
}
|
|
30
25
|
|
|
31
26
|
export function assertValidChannelFormat(channelFormat: ChannelFormat) {
|
|
32
27
|
if (!isStringInArray(channelFormat, CHANNEL_FORMATS)) {
|
|
33
|
-
throw new
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
friendlyMessage: `Invalid `,
|
|
37
|
-
})
|
|
28
|
+
throw new Error(
|
|
29
|
+
`Invalid channel format! Must be one of: ${CHANNEL_FORMATS.join(', ')}, not ${channelFormat}.`
|
|
30
|
+
)
|
|
38
31
|
}
|
|
39
32
|
}
|
|
40
33
|
|
|
41
34
|
export function assertValidSampleRate(sampleRate: number) {
|
|
42
35
|
if (!isGreaterThanOrEqualToZero(sampleRate)) {
|
|
43
|
-
throw new
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
friendlyMessage: 'Sample rate must be a positive number or zero.',
|
|
47
|
-
})
|
|
36
|
+
throw new Error(
|
|
37
|
+
`Invalid sample rate! Must be a positive number or zero, not: ${sampleRate}.`
|
|
38
|
+
)
|
|
48
39
|
}
|
|
49
40
|
}
|
|
50
41
|
|
|
51
42
|
export function assertValidChannelCount(channelCount: number) {
|
|
52
43
|
if (!isPositiveInteger(channelCount)) {
|
|
53
|
-
throw new
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
friendlyMessage: 'channelNames must have 1 or more labels.',
|
|
57
|
-
})
|
|
44
|
+
throw new Error(
|
|
45
|
+
`Invalid channel count! Must be a positive integer, not: ${channelCount}.`
|
|
46
|
+
)
|
|
58
47
|
}
|
|
59
48
|
}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import { assertOptions } from '@sprucelabs/schema'
|
|
2
1
|
import { DataType, define, open } from 'ffi-rs'
|
|
3
|
-
import SpruceError from '../errors/SpruceError'
|
|
4
2
|
import {
|
|
5
3
|
Liblsl,
|
|
6
4
|
LiblslBindings,
|
|
@@ -15,29 +13,30 @@ import {
|
|
|
15
13
|
} from '../types'
|
|
16
14
|
|
|
17
15
|
export default class LiblslAdapter implements Liblsl {
|
|
18
|
-
private static instance?: Liblsl
|
|
19
16
|
public static ffiRsOpen = open
|
|
20
17
|
public static ffiRsDefine = define
|
|
18
|
+
private static instance?: Liblsl
|
|
21
19
|
|
|
20
|
+
private path: string
|
|
22
21
|
private bindings!: LiblslBindings
|
|
23
22
|
|
|
24
23
|
protected constructor() {
|
|
25
|
-
|
|
26
|
-
this.tryToLoadBindings(
|
|
24
|
+
this.path = process.env.LIBLSL_PATH! ?? this.defaultMacOsPath
|
|
25
|
+
this.tryToLoadBindings()
|
|
27
26
|
}
|
|
28
27
|
|
|
29
|
-
private tryToLoadBindings(
|
|
28
|
+
private tryToLoadBindings() {
|
|
30
29
|
try {
|
|
31
|
-
this.bindings = this.loadBindings(path)
|
|
30
|
+
this.bindings = this.loadBindings(this.path)
|
|
32
31
|
} catch (error) {
|
|
33
|
-
throw new
|
|
34
|
-
code: 'FAILED_TO_LOAD_LIBLSL',
|
|
35
|
-
liblslPath: path,
|
|
36
|
-
originalError: error as any,
|
|
37
|
-
})
|
|
32
|
+
throw new Error(this.generateFailedMessage(error as Error))
|
|
38
33
|
}
|
|
39
34
|
}
|
|
40
35
|
|
|
36
|
+
private generateFailedMessage(error: Error) {
|
|
37
|
+
return `Loading the liblsl dylib failed! I tried to load it from ${this.path}.\n\n${error.message}\n\n`
|
|
38
|
+
}
|
|
39
|
+
|
|
41
40
|
public static getInstance() {
|
|
42
41
|
if (!this.instance) {
|
|
43
42
|
this.setInstance(new this())
|
|
@@ -145,14 +144,7 @@ export default class LiblslAdapter implements Liblsl {
|
|
|
145
144
|
sampleRate,
|
|
146
145
|
channelFormat,
|
|
147
146
|
sourceId,
|
|
148
|
-
} =
|
|
149
|
-
'name',
|
|
150
|
-
'type',
|
|
151
|
-
'channelCount',
|
|
152
|
-
'sampleRate',
|
|
153
|
-
'channelFormat',
|
|
154
|
-
'sourceId',
|
|
155
|
-
])
|
|
147
|
+
} = options
|
|
156
148
|
|
|
157
149
|
return this.bindings.lsl_create_streaminfo([
|
|
158
150
|
name,
|
|
@@ -167,7 +159,7 @@ export default class LiblslAdapter implements Liblsl {
|
|
|
167
159
|
public appendChannelsToStreamInfo(
|
|
168
160
|
options: AppendChannelsToStreamInfoOptions
|
|
169
161
|
) {
|
|
170
|
-
const { info, channels } =
|
|
162
|
+
const { info, channels } = options
|
|
171
163
|
|
|
172
164
|
const description = this.bindings.lsl_get_desc([info])
|
|
173
165
|
const parent = this.bindings.lsl_append_child([description, 'channels'])
|
|
@@ -185,47 +177,29 @@ export default class LiblslAdapter implements Liblsl {
|
|
|
185
177
|
}
|
|
186
178
|
|
|
187
179
|
public createOutlet(options: CreateOutletOptions) {
|
|
188
|
-
const { info, chunkSize, maxBuffered } =
|
|
189
|
-
'info',
|
|
190
|
-
'chunkSize',
|
|
191
|
-
'maxBuffered',
|
|
192
|
-
])
|
|
193
|
-
|
|
180
|
+
const { info, chunkSize, maxBuffered } = options
|
|
194
181
|
return this.bindings.lsl_create_outlet([info, chunkSize, maxBuffered])
|
|
195
182
|
}
|
|
196
183
|
|
|
197
184
|
public pushSampleFloatTimestamp(options: PushSampleFloatTimestampOptions) {
|
|
198
|
-
const { outlet, sample, timestamp } =
|
|
199
|
-
'outlet',
|
|
200
|
-
'sample',
|
|
201
|
-
'timestamp',
|
|
202
|
-
])
|
|
185
|
+
const { outlet, sample, timestamp } = options
|
|
203
186
|
this.bindings.lsl_push_sample_ft([outlet, sample, timestamp])
|
|
204
187
|
}
|
|
205
188
|
|
|
206
189
|
public pushSampleStringTimestamp(
|
|
207
190
|
options: PushSampleStringTimestampOptions
|
|
208
191
|
) {
|
|
209
|
-
const { outlet, sample, timestamp } =
|
|
210
|
-
'outlet',
|
|
211
|
-
'sample',
|
|
212
|
-
'timestamp',
|
|
213
|
-
])
|
|
192
|
+
const { outlet, sample, timestamp } = options
|
|
214
193
|
this.bindings.lsl_push_sample_strt([outlet, sample, timestamp])
|
|
215
194
|
}
|
|
216
195
|
|
|
217
196
|
public destroyOutlet(options: DestroyOutletOptions) {
|
|
218
|
-
const { outlet } =
|
|
197
|
+
const { outlet } = options
|
|
219
198
|
this.bindings.lsl_destroy_outlet([outlet])
|
|
220
199
|
}
|
|
221
200
|
|
|
222
201
|
public createInlet(options: CreateInletOptions) {
|
|
223
|
-
const { info, chunkSize, maxBuffered } =
|
|
224
|
-
'info',
|
|
225
|
-
'chunkSize',
|
|
226
|
-
'maxBuffered',
|
|
227
|
-
])
|
|
228
|
-
|
|
202
|
+
const { info, chunkSize, maxBuffered } = options
|
|
229
203
|
return this.bindings.lsl_create_inlet([info, chunkSize, maxBuffered])
|
|
230
204
|
}
|
|
231
205
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { assertOptions } from '@sprucelabs/schema'
|
|
2
1
|
import { generateId } from '@sprucelabs/test-utils'
|
|
3
2
|
import { CHANNEL_FORMATS_MAP } from '../consts'
|
|
4
3
|
import { BoundStreamInfo, ChannelFormat } from '../types'
|
|
@@ -40,7 +39,6 @@ export default class LslStreamInfo implements StreamInfo {
|
|
|
40
39
|
}
|
|
41
40
|
|
|
42
41
|
public static Create(options: StreamInfoOptions) {
|
|
43
|
-
assertOptions(options, ['channelNames', 'channelFormat', 'sampleRate'])
|
|
44
42
|
return new (this.Class ?? this)(options)
|
|
45
43
|
}
|
|
46
44
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { assertOptions } from '@sprucelabs/schema'
|
|
2
1
|
import { generateId } from '@sprucelabs/test-utils'
|
|
3
2
|
import { ChannelFormat } from '../types'
|
|
4
3
|
import LiblslAdapter from './LiblslAdapter'
|
|
@@ -28,16 +27,9 @@ export default class LslStreamInlet implements LslInlet {
|
|
|
28
27
|
}
|
|
29
28
|
|
|
30
29
|
public static Create(options: LslInletOptions) {
|
|
31
|
-
assertOptions(options, [
|
|
32
|
-
'channelNames',
|
|
33
|
-
'channelFormat',
|
|
34
|
-
'sampleRate',
|
|
35
|
-
'chunkSize',
|
|
36
|
-
'maxBuffered',
|
|
37
|
-
])
|
|
38
30
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
39
|
-
const { maxBuffered, chunkSize, ...
|
|
40
|
-
const info = this.LslStreamInfo(
|
|
31
|
+
const { maxBuffered, chunkSize, ...infoOptions } = options
|
|
32
|
+
const info = this.LslStreamInfo(infoOptions)
|
|
41
33
|
return new (this.Class ?? this)(info, options)
|
|
42
34
|
}
|
|
43
35
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { assertOptions } from '@sprucelabs/schema'
|
|
2
1
|
import {
|
|
3
2
|
assertValidChannelCount,
|
|
4
3
|
assertValidChannelFormat,
|
|
@@ -28,19 +27,6 @@ export default class LslStreamOutlet implements LslOutlet {
|
|
|
28
27
|
}
|
|
29
28
|
|
|
30
29
|
public static async Create(options: LslOutletOptions) {
|
|
31
|
-
assertOptions(options, [
|
|
32
|
-
'name',
|
|
33
|
-
'type',
|
|
34
|
-
'sourceId',
|
|
35
|
-
'channelNames',
|
|
36
|
-
'channelFormat',
|
|
37
|
-
'sampleRate',
|
|
38
|
-
'chunkSize',
|
|
39
|
-
'maxBuffered',
|
|
40
|
-
'manufacturer',
|
|
41
|
-
'unit',
|
|
42
|
-
])
|
|
43
|
-
|
|
44
30
|
const { waitAfterConstructionMs = 10 } = options ?? {}
|
|
45
31
|
|
|
46
32
|
const streamInfoOptions = {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import EventMarkerOutlet from '../modules/EventMarkerOutlet'
|
|
2
|
+
|
|
3
|
+
async function main() {
|
|
4
|
+
const outlet = await EventMarkerOutlet.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
|
+
})
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import LslStreamOutlet from '../modules/LslStreamOutlet'
|
|
2
|
+
|
|
3
|
+
async function main() {
|
|
4
|
+
const instance = await LslStreamOutlet.Create({
|
|
5
|
+
name: 'Muse S (2nd gen)',
|
|
6
|
+
type: 'EEG',
|
|
7
|
+
channelNames: ['TP9', 'AF7', 'AF8', 'TP10', 'AUX'],
|
|
8
|
+
sampleRate: 256,
|
|
9
|
+
channelFormat: 'float32',
|
|
10
|
+
sourceId: 'muse-s-eeg',
|
|
11
|
+
manufacturer: 'Interaxon Inc.',
|
|
12
|
+
unit: 'microvolt',
|
|
13
|
+
chunkSize: 12,
|
|
14
|
+
maxBuffered: 360,
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
instance.pushSample([1, 2, 3, 4, 5])
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
main().catch((error) => {
|
|
21
|
+
console.error('Error in main:', error)
|
|
22
|
+
})
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { default as SchemaEntity } from '@sprucelabs/schema';
|
|
2
|
-
import * as SpruceSchema from '@sprucelabs/schema';
|
|
3
|
-
export declare namespace SpruceErrors.NodeLsl {
|
|
4
|
-
interface FailedToLoadLiblsl {
|
|
5
|
-
'liblslPath': string;
|
|
6
|
-
}
|
|
7
|
-
interface FailedToLoadLiblslSchema extends SpruceSchema.Schema {
|
|
8
|
-
id: 'failedToLoadLiblsl';
|
|
9
|
-
namespace: 'NodeLsl';
|
|
10
|
-
name: 'FAILED_TO_LOAD_LIBLSL';
|
|
11
|
-
fields: {
|
|
12
|
-
/** . */
|
|
13
|
-
'liblslPath': {
|
|
14
|
-
type: 'text';
|
|
15
|
-
isRequired: true;
|
|
16
|
-
options: undefined;
|
|
17
|
-
};
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
type FailedToLoadLiblslEntity = SchemaEntity<SpruceErrors.NodeLsl.FailedToLoadLiblslSchema>;
|
|
21
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"errors.types.js","sourceRoot":"","sources":["../../../src/.spruce/errors/errors.types.ts"],"names":[],"mappings":""}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const schema_1 = require("@sprucelabs/schema");
|
|
4
|
-
const failedToLoadLiblslSchema = {
|
|
5
|
-
id: 'failedToLoadLiblsl',
|
|
6
|
-
namespace: 'NodeLsl',
|
|
7
|
-
name: 'FAILED_TO_LOAD_LIBLSL',
|
|
8
|
-
fields: {
|
|
9
|
-
/** . */
|
|
10
|
-
'liblslPath': {
|
|
11
|
-
type: 'text',
|
|
12
|
-
isRequired: true,
|
|
13
|
-
options: undefined
|
|
14
|
-
},
|
|
15
|
-
}
|
|
16
|
-
};
|
|
17
|
-
schema_1.SchemaRegistry.getInstance().trackSchema(failedToLoadLiblslSchema);
|
|
18
|
-
exports.default = failedToLoadLiblslSchema;
|
|
19
|
-
//# sourceMappingURL=failedToLoadLiblsl.schema.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"failedToLoadLiblsl.schema.js","sourceRoot":"","sources":["../../../../src/.spruce/errors/nodeLsl/failedToLoadLiblsl.schema.ts"],"names":[],"mappings":";;AAAA,+CAAmD;AAKnD,MAAM,wBAAwB,GAAmD;IAChF,EAAE,EAAE,oBAAoB;IACxB,SAAS,EAAE,SAAS;IACpB,IAAI,EAAE,uBAAuB;IACzB,MAAM,EAAE;QACA,QAAQ;QACR,YAAY,EAAE;YACV,IAAI,EAAE,MAAM;YACZ,UAAU,EAAE,IAAI;YAChB,OAAO,EAAE,SAAS;SACrB;KACR;CACL,CAAA;AAED,uBAAc,CAAC,WAAW,EAAE,CAAC,WAAW,CAAC,wBAAwB,CAAC,CAAA;AAElE,kBAAe,wBAAwB,CAAA"}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { SpruceErrors } from "./errors.types";
|
|
2
|
-
import { ErrorOptions as ISpruceErrorOptions } from "@sprucelabs/error";
|
|
3
|
-
export interface FailedToLoadLiblslErrorOptions extends SpruceErrors.NodeLsl.FailedToLoadLiblsl, ISpruceErrorOptions {
|
|
4
|
-
code: 'FAILED_TO_LOAD_LIBLSL';
|
|
5
|
-
}
|
|
6
|
-
type ErrorOptions = FailedToLoadLiblslErrorOptions;
|
|
7
|
-
export default ErrorOptions;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"options.types.js","sourceRoot":"","sources":["../../../src/.spruce/errors/options.types.ts"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fieldClassMap.js","sourceRoot":"","sources":["../../../../src/.spruce/schemas/fields/fieldClassMap.ts"],"names":[],"mappings":";;AAAA,+CAAkD;AAKlD,kBAAe,sBAAa,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { FieldDefinitions, FieldDefinitionMap, FieldValueTypeGeneratorMap, FieldMap } from '@sprucelabs/schema';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fields.types.js","sourceRoot":"","sources":["../../../../src/.spruce/schemas/fields/fields.types.ts"],"names":[],"mappings":""}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import BaseSpruceError from '@sprucelabs/error';
|
|
2
|
-
import ErrorOptions from './../.spruce/errors/options.types';
|
|
3
|
-
export default class SpruceError extends BaseSpruceError<ErrorOptions> {
|
|
4
|
-
/** an easy to understand version of the errors */
|
|
5
|
-
friendlyMessage(): string;
|
|
6
|
-
}
|