@neurodevs/node-lsl 11.4.1 → 12.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.
- package/.vscode/tasks.json +19 -1
- package/README.md +44 -34
- package/build/.spruce/settings.json +1 -3
- package/build/__tests__/{AbstractLslTest.d.ts → AbstractPackageTest.d.ts} +6 -4
- package/build/__tests__/AbstractPackageTest.js +58 -0
- package/build/__tests__/AbstractPackageTest.js.map +1 -0
- package/build/__tests__/{modules → impl}/LiblslAdapter.test.d.ts +5 -8
- package/build/__tests__/{modules → impl}/LiblslAdapter.test.js +37 -86
- package/build/__tests__/impl/LiblslAdapter.test.js.map +1 -0
- package/build/__tests__/{modules/EventMarkerOutlet.test.d.ts → impl/LslEventMarkerOutlet.test.d.ts} +5 -4
- package/build/__tests__/{modules/EventMarkerOutlet.test.js → impl/LslEventMarkerOutlet.test.js} +32 -25
- package/build/__tests__/impl/LslEventMarkerOutlet.test.js.map +1 -0
- package/build/__tests__/{modules → impl}/LslStreamInfo.test.d.ts +3 -4
- package/build/__tests__/{modules → impl}/LslStreamInfo.test.js +17 -27
- package/build/__tests__/impl/LslStreamInfo.test.js.map +1 -0
- package/build/__tests__/impl/LslStreamInlet.test.d.ts +10 -0
- package/build/__tests__/{modules → impl}/LslStreamInlet.test.js +9 -26
- package/build/__tests__/impl/LslStreamInlet.test.js.map +1 -0
- package/build/__tests__/{modules → impl}/LslStreamOutlet.test.d.ts +9 -7
- package/build/__tests__/{modules → impl}/LslStreamOutlet.test.js +40 -57
- package/build/__tests__/impl/LslStreamOutlet.test.js.map +1 -0
- package/build/__tests__/impl/LslWebSocketBridge.test.d.ts +7 -0
- package/build/__tests__/impl/LslWebSocketBridge.test.js +63 -0
- package/build/__tests__/impl/LslWebSocketBridge.test.js.map +1 -0
- package/build/assertions.d.ts +1 -1
- package/build/assertions.js +10 -31
- package/build/assertions.js.map +1 -1
- package/build/{modules → impl}/LiblslAdapter.d.ts +3 -1
- package/build/{modules → impl}/LiblslAdapter.js +15 -44
- package/build/impl/LiblslAdapter.js.map +1 -0
- package/build/impl/LslEventMarkerOutlet.d.ts +23 -0
- package/build/{modules/EventMarkerOutlet.js → impl/LslEventMarkerOutlet.js} +6 -6
- package/build/impl/LslEventMarkerOutlet.js.map +1 -0
- package/build/{modules → impl}/LslStreamInfo.js +4 -6
- package/build/impl/LslStreamInfo.js.map +1 -0
- package/build/{modules → impl}/LslStreamInlet.d.ts +8 -8
- package/build/{modules → impl}/LslStreamInlet.js +6 -14
- package/build/impl/LslStreamInlet.js.map +1 -0
- package/build/{modules → impl}/LslStreamOutlet.d.ts +8 -8
- package/build/{modules → impl}/LslStreamOutlet.js +2 -15
- package/build/impl/LslStreamOutlet.js.map +1 -0
- package/build/impl/LslWebSocketBridge.d.ts +8 -0
- package/build/impl/LslWebSocketBridge.js +10 -0
- package/build/impl/LslWebSocketBridge.js.map +1 -0
- package/build/index.d.ts +26 -22
- package/build/index.js +41 -34
- package/build/index.js.map +1 -1
- package/build/scripts/runLslEventMarkerOutlet.d.ts +1 -0
- package/build/scripts/runLslEventMarkerOutlet.js +23 -0
- package/build/scripts/runLslEventMarkerOutlet.js.map +1 -0
- package/build/scripts/runLslStreamOutlet.d.ts +1 -0
- package/build/scripts/runLslStreamOutlet.js +25 -0
- package/build/scripts/runLslStreamOutlet.js.map +1 -0
- package/build/testDoubles/{MarkerOutlet/FakeMarkerOutlet.d.ts → EventMarkerOutlet/FakeEventMarkerOutlet.d.ts} +2 -2
- package/build/testDoubles/EventMarkerOutlet/FakeEventMarkerOutlet.js +29 -0
- package/build/testDoubles/EventMarkerOutlet/FakeEventMarkerOutlet.js.map +1 -0
- package/build/testDoubles/{MarkerOutlet/MockMarkerOutlet.d.ts → EventMarkerOutlet/MockEventMarkerOutlet.d.ts} +2 -2
- package/build/testDoubles/{MarkerOutlet/MockMarkerOutlet.js → EventMarkerOutlet/MockEventMarkerOutlet.js} +3 -3
- package/build/testDoubles/EventMarkerOutlet/MockEventMarkerOutlet.js.map +1 -0
- package/build/testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.d.ts +9 -0
- package/build/testDoubles/{MarkerOutlet/SpyMarkerOutlet.js → EventMarkerOutlet/SpyEventMarkerOutlet.js} +8 -8
- package/build/testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.js.map +1 -0
- package/build/testDoubles/{MarkerOutlet/ThrowingMarkerOutlet.d.ts → EventMarkerOutlet/ThrowingEventMarkerOutlet.d.ts} +2 -2
- package/build/testDoubles/{MarkerOutlet/ThrowingMarkerOutlet.js → EventMarkerOutlet/ThrowingEventMarkerOutlet.js} +3 -3
- package/build/testDoubles/EventMarkerOutlet/ThrowingEventMarkerOutlet.js.map +1 -0
- package/build/testDoubles/StreamInfo/FakeStreamInfo.d.ts +1 -1
- package/build/testDoubles/StreamInfo/SpyStreamInfo.d.ts +1 -1
- package/build/testDoubles/StreamInfo/SpyStreamInfo.js +1 -1
- package/build/testDoubles/StreamInfo/SpyStreamInfo.js.map +1 -1
- package/build/testDoubles/StreamInlet/FakeStreamInlet.d.ts +10 -0
- package/build/testDoubles/StreamInlet/FakeStreamInlet.js +16 -0
- package/build/testDoubles/StreamInlet/FakeStreamInlet.js.map +1 -0
- package/build/testDoubles/StreamInlet/SpyStreamInlet.d.ts +7 -0
- package/build/testDoubles/{LslInlet/SpyLslInlet.js → StreamInlet/SpyStreamInlet.js} +5 -5
- package/build/testDoubles/StreamInlet/SpyStreamInlet.js.map +1 -0
- package/build/testDoubles/{LslOutlet/FakeLslOutlet.d.ts → StreamOutlet/FakeStreamOutlet.d.ts} +9 -10
- package/build/testDoubles/StreamOutlet/FakeStreamOutlet.js +62 -0
- package/build/testDoubles/StreamOutlet/FakeStreamOutlet.js.map +1 -0
- package/build/testDoubles/StreamTransportBridge/FakeStreamTransportBridge.d.ts +6 -0
- package/build/testDoubles/StreamTransportBridge/FakeStreamTransportBridge.js +13 -0
- package/build/testDoubles/StreamTransportBridge/FakeStreamTransportBridge.js.map +1 -0
- package/build/testDoubles/generateRandomOutletOptions.d.ts +2 -2
- package/build/testDoubles/generateRandomOutletOptions.js +10 -7
- package/build/testDoubles/generateRandomOutletOptions.js.map +1 -1
- package/build/types.d.ts +3 -3
- package/package.json +26 -18
- package/src/.spruce/settings.json +1 -3
- package/src/__tests__/{AbstractLslTest.ts → AbstractPackageTest.ts} +23 -17
- package/src/__tests__/{modules → impl}/LiblslAdapter.test.ts +36 -76
- package/src/__tests__/{modules/EventMarkerOutlet.test.ts → impl/LslEventMarkerOutlet.test.ts} +38 -27
- package/src/__tests__/{modules → impl}/LslStreamInfo.test.ts +7 -17
- package/src/__tests__/{modules → impl}/LslStreamInlet.test.ts +13 -30
- package/src/__tests__/{modules → impl}/LslStreamOutlet.test.ts +71 -63
- package/src/__tests__/impl/LslWebSocketBridge.test.ts +23 -0
- package/src/assertions.ts +19 -30
- package/src/{modules → impl}/LiblslAdapter.ts +18 -44
- package/src/{modules/EventMarkerOutlet.ts → impl/LslEventMarkerOutlet.ts} +16 -11
- package/src/{modules → impl}/LslStreamInfo.ts +1 -3
- package/src/{modules → impl}/LslStreamInlet.ts +14 -22
- package/src/{modules → impl}/LslStreamOutlet.ts +12 -26
- package/src/impl/LslWebSocketBridge.ts +13 -0
- package/src/index.ts +37 -29
- package/src/scripts/runLslEventMarkerOutlet.ts +23 -0
- package/src/scripts/runLslStreamOutlet.ts +22 -0
- package/src/testDoubles/{MarkerOutlet/FakeMarkerOutlet.ts → EventMarkerOutlet/FakeEventMarkerOutlet.ts} +6 -6
- package/src/testDoubles/{MarkerOutlet/MockMarkerOutlet.ts → EventMarkerOutlet/MockEventMarkerOutlet.ts} +2 -2
- package/src/testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.ts +24 -0
- package/src/testDoubles/{MarkerOutlet/ThrowingMarkerOutlet.ts → EventMarkerOutlet/ThrowingEventMarkerOutlet.ts} +2 -2
- package/src/testDoubles/StreamInfo/FakeStreamInfo.ts +1 -1
- package/src/testDoubles/StreamInfo/SpyStreamInfo.ts +1 -1
- package/src/testDoubles/StreamInlet/FakeStreamInlet.ts +20 -0
- package/src/testDoubles/StreamInlet/SpyStreamInlet.ts +16 -0
- package/src/testDoubles/{LslOutlet/FakeLslOutlet.ts → StreamOutlet/FakeStreamOutlet.ts} +17 -18
- package/src/testDoubles/StreamTransportBridge/FakeStreamTransportBridge.ts +15 -0
- package/src/testDoubles/generateRandomOutletOptions.ts +3 -3
- package/src/types.ts +3 -3
- 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/__tests__/AbstractLslTest.js +0 -86
- package/build/__tests__/AbstractLslTest.js.map +0 -1
- package/build/__tests__/modules/EventMarkerOutlet.test.js.map +0 -1
- package/build/__tests__/modules/LiblslAdapter.test.js.map +0 -1
- package/build/__tests__/modules/LslStreamInfo.test.js.map +0 -1
- package/build/__tests__/modules/LslStreamInlet.test.d.ts +0 -11
- package/build/__tests__/modules/LslStreamInlet.test.js.map +0 -1
- package/build/__tests__/modules/LslStreamOutlet.test.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/build/modules/EventMarkerOutlet.d.ts +0 -23
- package/build/modules/EventMarkerOutlet.js.map +0 -1
- package/build/modules/LiblslAdapter.js.map +0 -1
- package/build/modules/LslStreamInfo.js.map +0 -1
- package/build/modules/LslStreamInlet.js.map +0 -1
- package/build/modules/LslStreamOutlet.js.map +0 -1
- package/build/testDoubles/LslInlet/FakeLslInlet.d.ts +0 -11
- package/build/testDoubles/LslInlet/FakeLslInlet.js +0 -16
- package/build/testDoubles/LslInlet/FakeLslInlet.js.map +0 -1
- package/build/testDoubles/LslInlet/SpyLslInlet.d.ts +0 -7
- package/build/testDoubles/LslInlet/SpyLslInlet.js.map +0 -1
- package/build/testDoubles/LslOutlet/FakeLslOutlet.js +0 -59
- package/build/testDoubles/LslOutlet/FakeLslOutlet.js.map +0 -1
- package/build/testDoubles/MarkerOutlet/FakeMarkerOutlet.js +0 -29
- package/build/testDoubles/MarkerOutlet/FakeMarkerOutlet.js.map +0 -1
- package/build/testDoubles/MarkerOutlet/MockMarkerOutlet.js.map +0 -1
- package/build/testDoubles/MarkerOutlet/SpyMarkerOutlet.d.ts +0 -9
- package/build/testDoubles/MarkerOutlet/SpyMarkerOutlet.js.map +0 -1
- package/build/testDoubles/MarkerOutlet/ThrowingMarkerOutlet.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
- package/src/testDoubles/LslInlet/FakeLslInlet.ts +0 -22
- package/src/testDoubles/LslInlet/SpyLslInlet.ts +0 -16
- package/src/testDoubles/MarkerOutlet/SpyMarkerOutlet.ts +0 -24
- /package/build/{modules → impl}/LslStreamInfo.d.ts +0 -0
|
@@ -1,41 +1,24 @@
|
|
|
1
|
-
import { test, assert
|
|
2
|
-
import LslStreamInlet, {
|
|
3
|
-
import { SpyLslInlet } from '../../testDoubles/LslInlet/SpyLslInlet'
|
|
1
|
+
import { test, assert } from '@sprucelabs/test-utils'
|
|
2
|
+
import LslStreamInlet, { StreamInletOptions } from '../../impl/LslStreamInlet'
|
|
4
3
|
import FakeStreamInfo from '../../testDoubles/StreamInfo/FakeStreamInfo'
|
|
5
|
-
import
|
|
4
|
+
import { SpyStreamInlet } from '../../testDoubles/StreamInlet/SpyStreamInlet'
|
|
5
|
+
import AbstractPackageTest from '../AbstractPackageTest'
|
|
6
6
|
|
|
7
|
-
export default class LslStreamInletTest extends
|
|
8
|
-
private static instance:
|
|
7
|
+
export default class LslStreamInletTest extends AbstractPackageTest {
|
|
8
|
+
private static instance: SpyStreamInlet
|
|
9
9
|
|
|
10
10
|
protected static async beforeEach() {
|
|
11
11
|
await super.beforeEach()
|
|
12
12
|
|
|
13
|
-
this.
|
|
13
|
+
this.setSpyStreamInlet()
|
|
14
14
|
this.setFakeStreamInfo()
|
|
15
15
|
|
|
16
16
|
this.instance = this.LslStreamInlet()
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
@test()
|
|
20
|
-
protected static async
|
|
21
|
-
assert.isTruthy(this.instance, '
|
|
22
|
-
}
|
|
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
|
-
})
|
|
20
|
+
protected static async createsInstance() {
|
|
21
|
+
assert.isTruthy(this.instance, 'Failed to create instance!')
|
|
39
22
|
}
|
|
40
23
|
|
|
41
24
|
@test()
|
|
@@ -66,7 +49,7 @@ export default class LslStreamInletTest extends AbstractLslTest {
|
|
|
66
49
|
}
|
|
67
50
|
|
|
68
51
|
@test()
|
|
69
|
-
protected static async
|
|
52
|
+
protected static async callsBindingsToCreateStreamInlet() {
|
|
70
53
|
const fakeInfo = this.instance.getStreamInfo()
|
|
71
54
|
|
|
72
55
|
assert.isTruthy(fakeInfo, 'Should have created stream info!')
|
|
@@ -82,7 +65,7 @@ export default class LslStreamInletTest extends AbstractLslTest {
|
|
|
82
65
|
)
|
|
83
66
|
}
|
|
84
67
|
|
|
85
|
-
private static LslStreamInlet(options?: Partial<
|
|
68
|
+
private static LslStreamInlet(options?: Partial<StreamInletOptions>) {
|
|
86
69
|
const defaultOptions = {
|
|
87
70
|
channelNames: this.channelNames,
|
|
88
71
|
channelFormat: 'float32',
|
|
@@ -93,7 +76,7 @@ export default class LslStreamInletTest extends AbstractLslTest {
|
|
|
93
76
|
chunkSize: this.chunkSize,
|
|
94
77
|
maxBuffered: this.maxBuffered,
|
|
95
78
|
...options,
|
|
96
|
-
} as
|
|
97
|
-
return LslStreamInlet.Create(defaultOptions) as
|
|
79
|
+
} as StreamInletOptions
|
|
80
|
+
return LslStreamInlet.Create(defaultOptions) as SpyStreamInlet
|
|
98
81
|
}
|
|
99
82
|
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { test, assert
|
|
2
|
-
import
|
|
1
|
+
import { test, assert } from '@sprucelabs/test-utils'
|
|
2
|
+
import generateId from '@neurodevs/generate-id'
|
|
3
|
+
import { CHANNEL_FORMATS } from '../../consts'
|
|
4
|
+
import { StreamInfo } from '../../impl/LslStreamInfo'
|
|
3
5
|
import LslStreamOutlet, {
|
|
4
|
-
|
|
5
|
-
} from '../../
|
|
6
|
+
StreamOutletOptions,
|
|
7
|
+
} from '../../impl/LslStreamOutlet'
|
|
6
8
|
import {
|
|
7
9
|
TEST_SUPPORTED_CHANNEL_FORMATS,
|
|
8
10
|
TEST_UNSUPPORTED_CHANNEL_FORMATS,
|
|
@@ -11,11 +13,11 @@ import {
|
|
|
11
13
|
|
|
12
14
|
import generateRandomOutletOptions from '../../testDoubles/generateRandomOutletOptions'
|
|
13
15
|
import FakeStreamInfo from '../../testDoubles/StreamInfo/FakeStreamInfo'
|
|
14
|
-
import { LslSample } from '../../types'
|
|
15
|
-
import
|
|
16
|
+
import { ChannelFormat, LslSample } from '../../types'
|
|
17
|
+
import AbstractPackageTest from '../AbstractPackageTest'
|
|
16
18
|
|
|
17
|
-
export default class LslStreamOutletTest extends
|
|
18
|
-
private static randomOutletOptions:
|
|
19
|
+
export default class LslStreamOutletTest extends AbstractPackageTest {
|
|
20
|
+
private static randomOutletOptions: StreamOutletOptions
|
|
19
21
|
|
|
20
22
|
protected static async beforeEach() {
|
|
21
23
|
await super.beforeEach()
|
|
@@ -29,30 +31,8 @@ export default class LslStreamOutletTest extends AbstractLslTest {
|
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
@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)
|
|
34
|
+
protected static async throwsWithEmptyChannelNames() {
|
|
35
|
+
await this.assertThrowsWithEmptyChannelNames()
|
|
56
36
|
}
|
|
57
37
|
|
|
58
38
|
@test()
|
|
@@ -68,24 +48,30 @@ export default class LslStreamOutletTest extends AbstractLslTest {
|
|
|
68
48
|
|
|
69
49
|
@test()
|
|
70
50
|
protected static async throwsWithInvalidChannelFormat() {
|
|
71
|
-
await this.
|
|
72
|
-
|
|
73
|
-
{ channelFormat: generateId() },
|
|
74
|
-
['channelFormat']
|
|
51
|
+
await this.assertThrowsInvalidChannelFormat(
|
|
52
|
+
'invalid-format' as ChannelFormat
|
|
75
53
|
)
|
|
76
54
|
}
|
|
77
55
|
|
|
78
56
|
@test()
|
|
79
|
-
protected static async
|
|
57
|
+
protected static async allowsZeroChunkSize() {
|
|
80
58
|
await this.LslStreamOutlet({ chunkSize: 0 })
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
@test()
|
|
62
|
+
protected static async throwsWithInvalidChunkSize() {
|
|
81
63
|
await this.assertThrowsInvalidChunkSize(-1)
|
|
82
64
|
await this.assertThrowsInvalidChunkSize(-1.5)
|
|
83
65
|
await this.assertThrowsInvalidChunkSize(1.5)
|
|
84
66
|
}
|
|
85
67
|
|
|
86
68
|
@test()
|
|
87
|
-
protected static async
|
|
69
|
+
protected static async allowsZeroMaxBuffered() {
|
|
88
70
|
await this.LslStreamOutlet({ maxBuffered: 0 })
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
@test()
|
|
74
|
+
protected static async throwsWithInvalidMaxBuffered() {
|
|
89
75
|
await this.assertThrowsInvalidMaxBuffered(-1)
|
|
90
76
|
await this.assertThrowsInvalidMaxBuffered(-1.5)
|
|
91
77
|
await this.assertThrowsInvalidMaxBuffered(1.5)
|
|
@@ -226,41 +212,61 @@ export default class LslStreamOutletTest extends AbstractLslTest {
|
|
|
226
212
|
assert.isAbove(endMs - startMs, 10)
|
|
227
213
|
}
|
|
228
214
|
|
|
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
|
-
])
|
|
215
|
+
private static async assertThrowsWithEmptyChannelNames() {
|
|
216
|
+
await this.createAndAssertThrows(
|
|
217
|
+
'channelNames',
|
|
218
|
+
[],
|
|
219
|
+
`Invalid channel count! Must be a positive integer, not: 0.`
|
|
220
|
+
)
|
|
239
221
|
}
|
|
240
222
|
|
|
241
223
|
private static async assertThrowsInvalidSampleRate(sampleRate: number) {
|
|
242
|
-
await this.
|
|
224
|
+
await this.createAndAssertThrows(
|
|
243
225
|
'sampleRate',
|
|
244
|
-
|
|
226
|
+
sampleRate,
|
|
227
|
+
`Invalid sample rate! Must be a positive number or zero, not: ${sampleRate}`
|
|
228
|
+
)
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
private static async assertThrowsInvalidChannelFormat(
|
|
232
|
+
channelFormat: ChannelFormat
|
|
233
|
+
) {
|
|
234
|
+
await this.createAndAssertThrows(
|
|
235
|
+
'channelFormat',
|
|
236
|
+
channelFormat,
|
|
237
|
+
`Invalid channel format! Must be one of: ${CHANNEL_FORMATS.join(', ')}, not ${channelFormat}.`
|
|
238
|
+
)
|
|
245
239
|
}
|
|
246
240
|
|
|
247
|
-
private static async
|
|
248
|
-
await this.
|
|
249
|
-
|
|
250
|
-
|
|
241
|
+
private static async assertThrowsInvalidMaxBuffered(maxBuffered: number) {
|
|
242
|
+
await this.createAndAssertThrows(
|
|
243
|
+
'maxBuffered',
|
|
244
|
+
maxBuffered,
|
|
245
|
+
`Invalid max buffered! Must be a positive integer or zero, not: ${maxBuffered}`
|
|
251
246
|
)
|
|
252
247
|
}
|
|
253
248
|
|
|
254
|
-
private static async
|
|
255
|
-
|
|
256
|
-
|
|
249
|
+
private static async assertThrowsInvalidChunkSize(chunkSize: number) {
|
|
250
|
+
await this.createAndAssertThrows(
|
|
251
|
+
'chunkSize',
|
|
252
|
+
chunkSize,
|
|
253
|
+
`Invalid chunk size! Must be a positive integer or zero, not: ${chunkSize}`
|
|
254
|
+
)
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
private static async createAndAssertThrows(
|
|
258
|
+
option: keyof StreamOutletOptions,
|
|
259
|
+
value: number | string[] | ChannelFormat,
|
|
260
|
+
expectedMessage: string
|
|
257
261
|
) {
|
|
258
262
|
const err = await assert.doesThrowAsync(
|
|
259
|
-
async () => await this.LslStreamOutlet(
|
|
263
|
+
async () => await this.LslStreamOutlet({ [option]: value })
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
assert.isTrue(
|
|
267
|
+
err.message.includes(expectedMessage),
|
|
268
|
+
'Did not receive the expected error!'
|
|
260
269
|
)
|
|
261
|
-
errorAssert.assertError(err, 'INVALID_PARAMETERS', {
|
|
262
|
-
parameters,
|
|
263
|
-
})
|
|
264
270
|
}
|
|
265
271
|
|
|
266
272
|
private static async StringOutlet() {
|
|
@@ -271,7 +277,9 @@ export default class LslStreamOutletTest extends AbstractLslTest {
|
|
|
271
277
|
return await this.LslStreamOutlet({ channelFormat: 'float32' })
|
|
272
278
|
}
|
|
273
279
|
|
|
274
|
-
private static async LslStreamOutlet(
|
|
280
|
+
private static async LslStreamOutlet(
|
|
281
|
+
options?: Partial<StreamOutletOptions>
|
|
282
|
+
) {
|
|
275
283
|
return await LslStreamOutlet.Create({
|
|
276
284
|
...this.randomOutletOptions,
|
|
277
285
|
...options,
|
|
@@ -280,7 +288,7 @@ export default class LslStreamOutletTest extends AbstractLslTest {
|
|
|
280
288
|
}
|
|
281
289
|
|
|
282
290
|
class CheckingOutlet extends LslStreamOutlet {
|
|
283
|
-
public constructor(info: StreamInfo, options:
|
|
291
|
+
public constructor(info: StreamInfo, options: StreamOutletOptions) {
|
|
284
292
|
super(info, options)
|
|
285
293
|
}
|
|
286
294
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import AbstractSpruceTest, { test, assert } from '@sprucelabs/test-utils'
|
|
2
|
+
import LslWebSocketBridge, {
|
|
3
|
+
StreamTransportBridge,
|
|
4
|
+
} from '../../impl/LslWebSocketBridge'
|
|
5
|
+
|
|
6
|
+
export default class LslWebSocketBridgeTest extends AbstractSpruceTest {
|
|
7
|
+
private static instance: StreamTransportBridge
|
|
8
|
+
|
|
9
|
+
protected static async beforeEach() {
|
|
10
|
+
await super.beforeEach()
|
|
11
|
+
|
|
12
|
+
this.instance = this.LslWebSocketBridge()
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@test()
|
|
16
|
+
protected static async createsInstance() {
|
|
17
|
+
assert.isTruthy(this.instance, 'Failed to create instance!')
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
private static LslWebSocketBridge() {
|
|
21
|
+
return LslWebSocketBridge.Create()
|
|
22
|
+
}
|
|
23
|
+
}
|
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,19 +1,22 @@
|
|
|
1
1
|
import { DurationMarker } from '../types'
|
|
2
|
-
import LslStreamOutlet, {
|
|
2
|
+
import LslStreamOutlet, {
|
|
3
|
+
StreamOutletOptions,
|
|
4
|
+
StreamOutlet,
|
|
5
|
+
} from './LslStreamOutlet'
|
|
3
6
|
|
|
4
|
-
export default class
|
|
5
|
-
public static Class?:
|
|
7
|
+
export default class LslEventMarkerOutlet implements EventMarkerOutlet {
|
|
8
|
+
public static Class?: EventMarkerOutletConstructor
|
|
6
9
|
|
|
7
|
-
protected
|
|
10
|
+
protected streamOutlet: StreamOutlet
|
|
8
11
|
private isPlaying = false
|
|
9
12
|
private waitResolve?: () => void
|
|
10
13
|
private timeout?: any
|
|
11
14
|
|
|
12
|
-
protected constructor(
|
|
13
|
-
this.
|
|
15
|
+
protected constructor(outlet: StreamOutlet) {
|
|
16
|
+
this.streamOutlet = outlet
|
|
14
17
|
}
|
|
15
18
|
|
|
16
|
-
public static async Create(options?: Partial<
|
|
19
|
+
public static async Create(options?: Partial<StreamOutletOptions>) {
|
|
17
20
|
const defaultOptions = {
|
|
18
21
|
name: 'Event markers',
|
|
19
22
|
type: 'Markers',
|
|
@@ -25,7 +28,7 @@ export default class EventMarkerOutlet implements MarkerOutlet {
|
|
|
25
28
|
unit: 'N/A',
|
|
26
29
|
chunkSize: 0,
|
|
27
30
|
maxBuffered: 0,
|
|
28
|
-
} as
|
|
31
|
+
} as StreamOutletOptions
|
|
29
32
|
|
|
30
33
|
const outlet = await LslStreamOutlet.Create({
|
|
31
34
|
...defaultOptions,
|
|
@@ -55,7 +58,7 @@ export default class EventMarkerOutlet implements MarkerOutlet {
|
|
|
55
58
|
}
|
|
56
59
|
|
|
57
60
|
private pushMarkerToOutlet(markerName: string) {
|
|
58
|
-
this.
|
|
61
|
+
this.streamOutlet.pushSample([markerName])
|
|
59
62
|
}
|
|
60
63
|
|
|
61
64
|
protected async wait(durationMs: number) {
|
|
@@ -74,10 +77,12 @@ export default class EventMarkerOutlet implements MarkerOutlet {
|
|
|
74
77
|
}
|
|
75
78
|
}
|
|
76
79
|
|
|
77
|
-
export interface
|
|
80
|
+
export interface EventMarkerOutlet {
|
|
78
81
|
pushMarker(markerName: string): void
|
|
79
82
|
pushMarkers(markers: DurationMarker[]): Promise<void>
|
|
80
83
|
stop(): void
|
|
81
84
|
}
|
|
82
85
|
|
|
83
|
-
export type
|
|
86
|
+
export type EventMarkerOutletConstructor = new (
|
|
87
|
+
outlet: StreamOutlet
|
|
88
|
+
) => EventMarkerOutlet
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { generateId } from '@sprucelabs/test-utils'
|
|
1
|
+
import generateId from '@neurodevs/generate-id'
|
|
3
2
|
import { CHANNEL_FORMATS_MAP } from '../consts'
|
|
4
3
|
import { BoundStreamInfo, ChannelFormat } from '../types'
|
|
5
4
|
import LiblslAdapter from './LiblslAdapter'
|
|
@@ -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,18 +1,17 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { generateId } from '@sprucelabs/test-utils'
|
|
1
|
+
import generateId from '@neurodevs/generate-id'
|
|
3
2
|
import { ChannelFormat } from '../types'
|
|
4
3
|
import LiblslAdapter from './LiblslAdapter'
|
|
5
4
|
import LslStreamInfo, { StreamInfo, StreamInfoOptions } from './LslStreamInfo'
|
|
6
5
|
|
|
7
|
-
export default class LslStreamInlet implements
|
|
8
|
-
public static Class?:
|
|
6
|
+
export default class LslStreamInlet implements StreamInlet {
|
|
7
|
+
public static Class?: StreamInletConstructor
|
|
9
8
|
|
|
10
9
|
protected name: string
|
|
11
10
|
protected info: StreamInfo
|
|
12
11
|
private chunkSize: number
|
|
13
12
|
private maxBuffered: number
|
|
14
13
|
|
|
15
|
-
protected constructor(info: StreamInfo, options:
|
|
14
|
+
protected constructor(info: StreamInfo, options: StreamInletOptions) {
|
|
16
15
|
const {
|
|
17
16
|
name = this.defaultName,
|
|
18
17
|
chunkSize,
|
|
@@ -24,24 +23,17 @@ export default class LslStreamInlet implements LslInlet {
|
|
|
24
23
|
this.maxBuffered = maxBuffered
|
|
25
24
|
this.name = name
|
|
26
25
|
|
|
27
|
-
this.
|
|
26
|
+
this.createStreamInlet()
|
|
28
27
|
}
|
|
29
28
|
|
|
30
|
-
public static Create(options:
|
|
31
|
-
assertOptions(options, [
|
|
32
|
-
'channelNames',
|
|
33
|
-
'channelFormat',
|
|
34
|
-
'sampleRate',
|
|
35
|
-
'chunkSize',
|
|
36
|
-
'maxBuffered',
|
|
37
|
-
])
|
|
29
|
+
public static Create(options: StreamInletOptions) {
|
|
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
|
|
|
44
|
-
private
|
|
36
|
+
private createStreamInlet() {
|
|
45
37
|
this.lsl.createInlet({
|
|
46
38
|
info: this.boundStreamInfo,
|
|
47
39
|
chunkSize: this.chunkSize,
|
|
@@ -64,14 +56,14 @@ export default class LslStreamInlet implements LslInlet {
|
|
|
64
56
|
}
|
|
65
57
|
}
|
|
66
58
|
|
|
67
|
-
export interface
|
|
59
|
+
export interface StreamInlet {}
|
|
68
60
|
|
|
69
|
-
export type
|
|
61
|
+
export type StreamInletConstructor = new (
|
|
70
62
|
info: StreamInfo,
|
|
71
|
-
options:
|
|
72
|
-
) =>
|
|
63
|
+
options: StreamInletOptions
|
|
64
|
+
) => StreamInlet
|
|
73
65
|
|
|
74
|
-
export interface
|
|
66
|
+
export interface StreamInletOptions {
|
|
75
67
|
sampleRate: number
|
|
76
68
|
channelNames: string[]
|
|
77
69
|
channelFormat: ChannelFormat
|