@neurodevs/node-lsl 2.0.2 → 3.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/README.md +1 -1
- package/build/Liblsl.d.ts +33 -25
- package/build/Liblsl.js +29 -30
- package/build/Liblsl.js.map +1 -1
- package/build/LslOutlet.d.ts +6 -5
- package/build/LslOutlet.js +21 -14
- package/build/LslOutlet.js.map +1 -1
- package/build/__tests__/behavioral/LslOutlet.test.d.ts +9 -10
- package/build/__tests__/behavioral/LslOutlet.test.js +49 -58
- package/build/__tests__/behavioral/LslOutlet.test.js.map +1 -1
- package/build/__tests__/implementation/Liblsl.test.d.ts +9 -9
- package/build/__tests__/implementation/Liblsl.test.js +76 -66
- package/build/__tests__/implementation/Liblsl.test.js.map +1 -1
- package/package.json +1 -1
- package/src/Liblsl.ts +76 -73
- package/src/LslOutlet.ts +31 -28
- package/src/__tests__/behavioral/LslOutlet.test.ts +62 -71
- package/src/__tests__/implementation/Liblsl.test.ts +96 -84
package/src/LslOutlet.ts
CHANGED
|
@@ -1,21 +1,17 @@
|
|
|
1
1
|
import { SchemaError, assertOptions } from '@sprucelabs/schema'
|
|
2
|
-
import LiblslImpl, {
|
|
3
|
-
LslBindingsOutlet,
|
|
4
|
-
LslBindingsStreamInfo,
|
|
5
|
-
LslSample,
|
|
6
|
-
} from './Liblsl'
|
|
2
|
+
import LiblslImpl, { BoundOutlet, BoundStreamInfo, LslSample } from './Liblsl'
|
|
7
3
|
|
|
8
4
|
export default class LslOutletImpl implements LslOutlet {
|
|
9
5
|
private outletOptions: LslOutletOptions
|
|
10
6
|
public static Class?: new (options: LslOutletOptions) => LslOutlet
|
|
11
|
-
private streamInfo:
|
|
12
|
-
private outlet:
|
|
7
|
+
private streamInfo: BoundStreamInfo
|
|
8
|
+
private outlet: BoundOutlet
|
|
13
9
|
|
|
14
10
|
protected constructor(options: LslOutletOptions) {
|
|
15
11
|
const { sampleRate, channelFormat } = assertOptions(options, [
|
|
16
12
|
'name',
|
|
17
13
|
'type',
|
|
18
|
-
'
|
|
14
|
+
'channelNames',
|
|
19
15
|
'sampleRate',
|
|
20
16
|
'channelFormat',
|
|
21
17
|
'sourceId',
|
|
@@ -27,10 +23,12 @@ export default class LslOutletImpl implements LslOutlet {
|
|
|
27
23
|
|
|
28
24
|
this.outletOptions = options
|
|
29
25
|
|
|
30
|
-
const { chunkSize, maxBuffered,
|
|
26
|
+
const { chunkSize, maxBuffered, channelNames, ...streamInfoOptions } = this
|
|
31
27
|
.outletOptions as any
|
|
32
28
|
|
|
33
|
-
|
|
29
|
+
const channelCount = channelNames.length
|
|
30
|
+
|
|
31
|
+
this.assertValidChannelCount(channelCount)
|
|
34
32
|
this.assertValidSampleRate(sampleRate)
|
|
35
33
|
this.assertValidChannelFormat(channelFormat)
|
|
36
34
|
this.assertValidChunkSize(chunkSize)
|
|
@@ -41,18 +39,18 @@ export default class LslOutletImpl implements LslOutlet {
|
|
|
41
39
|
|
|
42
40
|
this.streamInfo = this.lsl.createStreamInfo({
|
|
43
41
|
...streamInfoOptions,
|
|
44
|
-
channelCount
|
|
45
|
-
channelFormat:
|
|
42
|
+
channelCount,
|
|
43
|
+
channelFormat: this.lookupChannelFormat(channelFormat),
|
|
46
44
|
})
|
|
47
45
|
|
|
48
|
-
this.lsl.appendChannelsToStreamInfo(
|
|
49
|
-
this.streamInfo,
|
|
50
|
-
|
|
46
|
+
this.lsl.appendChannelsToStreamInfo({
|
|
47
|
+
info: this.streamInfo,
|
|
48
|
+
channels: channelNames.map((label: string) => ({
|
|
51
49
|
label,
|
|
52
50
|
unit: this.outletOptions.unit,
|
|
53
51
|
type: this.outletOptions.type,
|
|
54
|
-
}))
|
|
55
|
-
)
|
|
52
|
+
})),
|
|
53
|
+
})
|
|
56
54
|
|
|
57
55
|
this.outlet = this.lsl.createOutlet({
|
|
58
56
|
info: this.streamInfo,
|
|
@@ -65,6 +63,14 @@ export default class LslOutletImpl implements LslOutlet {
|
|
|
65
63
|
return new (this.Class ?? this)(options)
|
|
66
64
|
}
|
|
67
65
|
|
|
66
|
+
public pushSample(sample: LslSample) {
|
|
67
|
+
this.lsl.pushSample({ outlet: this.outlet, sample })
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
private lookupChannelFormat(channelFormat: ChannelFormat): number {
|
|
71
|
+
return CHANNEL_FORMATS.indexOf(channelFormat)
|
|
72
|
+
}
|
|
73
|
+
|
|
68
74
|
private assertValidMaxBufferred(maxBuffered: number) {
|
|
69
75
|
if (!this.isPositiveIntegerOrZero(maxBuffered)) {
|
|
70
76
|
throw new SchemaError({
|
|
@@ -111,8 +117,8 @@ export default class LslOutletImpl implements LslOutlet {
|
|
|
111
117
|
if (!this.isPositiveInteger(channelCount)) {
|
|
112
118
|
throw new SchemaError({
|
|
113
119
|
code: 'INVALID_PARAMETERS',
|
|
114
|
-
parameters: ['
|
|
115
|
-
friendlyMessage: '
|
|
120
|
+
parameters: ['channelNames'],
|
|
121
|
+
friendlyMessage: 'channelNames must have 1 or more labels.',
|
|
116
122
|
})
|
|
117
123
|
}
|
|
118
124
|
}
|
|
@@ -132,10 +138,6 @@ export default class LslOutletImpl implements LslOutlet {
|
|
|
132
138
|
private get lsl() {
|
|
133
139
|
return LiblslImpl.getInstance()
|
|
134
140
|
}
|
|
135
|
-
|
|
136
|
-
public pushSample(sample: LslSample) {
|
|
137
|
-
this.lsl.pushSample(this.outlet, sample)
|
|
138
|
-
}
|
|
139
141
|
}
|
|
140
142
|
|
|
141
143
|
const CHANNEL_FORMATS = [
|
|
@@ -150,10 +152,15 @@ const CHANNEL_FORMATS = [
|
|
|
150
152
|
] as const
|
|
151
153
|
|
|
152
154
|
export type ChannelFormat = (typeof CHANNEL_FORMATS)[number]
|
|
155
|
+
|
|
156
|
+
export interface LslOutlet {
|
|
157
|
+
pushSample(sample: LslSample): void
|
|
158
|
+
}
|
|
159
|
+
|
|
153
160
|
export interface LslOutletOptions {
|
|
154
161
|
name: string
|
|
155
162
|
type: string
|
|
156
|
-
|
|
163
|
+
channelNames: string[]
|
|
157
164
|
sampleRate: number
|
|
158
165
|
channelFormat: ChannelFormat
|
|
159
166
|
sourceId: string
|
|
@@ -162,7 +169,3 @@ export interface LslOutletOptions {
|
|
|
162
169
|
chunkSize: number
|
|
163
170
|
maxBuffered: number
|
|
164
171
|
}
|
|
165
|
-
|
|
166
|
-
export interface LslOutlet {
|
|
167
|
-
pushSample(sample: LslSample): void
|
|
168
|
-
}
|
|
@@ -9,10 +9,11 @@ import LiblslImpl, {
|
|
|
9
9
|
CreateOutletOptions,
|
|
10
10
|
CreateStreamInfoOptions,
|
|
11
11
|
Liblsl,
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
LslChannel,
|
|
12
|
+
BoundOutlet,
|
|
13
|
+
BoundStreamInfo,
|
|
15
14
|
LslSample,
|
|
15
|
+
AppendChannelsToStreamInfoOptions,
|
|
16
|
+
PushSampleOptions,
|
|
16
17
|
} from '../../Liblsl'
|
|
17
18
|
import LslOutlet, { ChannelFormat, LslOutletOptions } from '../../LslOutlet'
|
|
18
19
|
|
|
@@ -28,7 +29,7 @@ export const CHANNEL_FORMATS = [
|
|
|
28
29
|
] as const
|
|
29
30
|
|
|
30
31
|
export default class LslOutletTest extends AbstractSpruceTest {
|
|
31
|
-
private static
|
|
32
|
+
private static spyLiblsl: SpyLiblsl
|
|
32
33
|
private static randomOutletOptions: LslOutletOptions
|
|
33
34
|
private static channelIdx: number
|
|
34
35
|
|
|
@@ -39,7 +40,7 @@ export default class LslOutletTest extends AbstractSpruceTest {
|
|
|
39
40
|
this.randomOutletOptions = {
|
|
40
41
|
name: generateId(),
|
|
41
42
|
type: generateId(),
|
|
42
|
-
|
|
43
|
+
channelNames: new Array(randomInt(1, 10)).fill(generateId()),
|
|
43
44
|
sampleRate: Math.random() * 10,
|
|
44
45
|
channelFormat: CHANNEL_FORMATS[this.channelIdx],
|
|
45
46
|
sourceId: generateId(),
|
|
@@ -49,19 +50,19 @@ export default class LslOutletTest extends AbstractSpruceTest {
|
|
|
49
50
|
maxBuffered: randomInt(0, 10),
|
|
50
51
|
}
|
|
51
52
|
|
|
52
|
-
this.
|
|
53
|
-
LiblslImpl.setInstance(this.
|
|
53
|
+
this.spyLiblsl = new SpyLiblsl()
|
|
54
|
+
LiblslImpl.setInstance(this.spyLiblsl)
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
@test()
|
|
57
|
-
protected static async
|
|
58
|
+
protected static async throwsWhenMissingRequiredParams() {
|
|
58
59
|
//@ts-ignore
|
|
59
60
|
const err = assert.doesThrow(() => new LslOutlet())
|
|
60
61
|
errorAssert.assertError(err, 'MISSING_PARAMETERS', {
|
|
61
62
|
parameters: [
|
|
62
63
|
'name',
|
|
63
64
|
'type',
|
|
64
|
-
'
|
|
65
|
+
'channelNames',
|
|
65
66
|
'sampleRate',
|
|
66
67
|
'channelFormat',
|
|
67
68
|
'sourceId',
|
|
@@ -74,13 +75,8 @@ export default class LslOutletTest extends AbstractSpruceTest {
|
|
|
74
75
|
}
|
|
75
76
|
|
|
76
77
|
@test()
|
|
77
|
-
protected static async
|
|
78
|
-
this.
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
@test()
|
|
82
|
-
protected static async throwsWithInvalidChannelCount() {
|
|
83
|
-
this.assertThrowsInvalidChannelLabels(0)
|
|
78
|
+
protected static async throwsWithInvalidChannelNames() {
|
|
79
|
+
this.assertThrowsInvalidChannelNames(0)
|
|
84
80
|
}
|
|
85
81
|
|
|
86
82
|
@test()
|
|
@@ -99,15 +95,7 @@ export default class LslOutletTest extends AbstractSpruceTest {
|
|
|
99
95
|
}
|
|
100
96
|
|
|
101
97
|
@test()
|
|
102
|
-
protected static async
|
|
103
|
-
const valid = CHANNEL_FORMATS
|
|
104
|
-
for (const format of valid) {
|
|
105
|
-
this.Outlet({ channelFormat: format as ChannelFormat })
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
@test()
|
|
110
|
-
protected static async throwWithInvalidChunkSize() {
|
|
98
|
+
protected static async throwsWithInvalidChunkSize() {
|
|
111
99
|
this.Outlet({ chunkSize: 0 })
|
|
112
100
|
this.assertThrowsInvalidChunkSize(-1)
|
|
113
101
|
this.assertThrowsInvalidChunkSize(-1.5)
|
|
@@ -122,56 +110,67 @@ export default class LslOutletTest extends AbstractSpruceTest {
|
|
|
122
110
|
this.assertThrowsInvalidMaxBuffered(1.5)
|
|
123
111
|
}
|
|
124
112
|
|
|
125
|
-
@test(
|
|
126
|
-
|
|
127
|
-
|
|
113
|
+
@test()
|
|
114
|
+
protected static async supportsAllKnownChannelFormats() {
|
|
115
|
+
const valid = CHANNEL_FORMATS
|
|
116
|
+
for (const format of valid) {
|
|
117
|
+
this.Outlet({ channelFormat: format as ChannelFormat })
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
@test('pushing [1, 2] sample sends to LSL', [1, 2])
|
|
122
|
+
@test('pushing [1] sample sends to LSL', [1])
|
|
123
|
+
protected static async canPushSampleToLsl(sample: LslSample) {
|
|
128
124
|
this.pushSample(sample)
|
|
129
|
-
assert.isEqual(
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
125
|
+
assert.isEqual(
|
|
126
|
+
this.spyLiblsl.lastPushSampleOptions?.outlet,
|
|
127
|
+
this.spyLiblsl.outlet
|
|
128
|
+
)
|
|
129
|
+
assert.isEqualDeep(this.spyLiblsl.lastPushSampleOptions?.sample, sample)
|
|
130
|
+
assert.isEqualDeep(this.spyLiblsl.lastCreateOutletOptions, {
|
|
131
|
+
info: this.spyLiblsl.streamInfo,
|
|
133
132
|
chunkSize: this.randomOutletOptions.chunkSize,
|
|
134
133
|
maxBuffered: this.randomOutletOptions.maxBuffered,
|
|
135
134
|
})
|
|
136
135
|
}
|
|
137
136
|
|
|
138
137
|
@test()
|
|
139
|
-
protected static async
|
|
138
|
+
protected static async constructionCreatesStreamInfo() {
|
|
140
139
|
this.Outlet()
|
|
141
140
|
|
|
142
141
|
const { ...options } = this.randomOutletOptions as any
|
|
143
142
|
|
|
144
|
-
options.channelCount = options.
|
|
143
|
+
options.channelCount = options.channelNames.length
|
|
145
144
|
|
|
146
145
|
delete options.manufacturer
|
|
147
146
|
delete options.unit
|
|
148
147
|
delete options.chunkSize
|
|
149
148
|
delete options.maxBuffered
|
|
150
|
-
delete options.
|
|
149
|
+
delete options.channelNames
|
|
151
150
|
|
|
152
|
-
assert.isEqualDeep(this.
|
|
151
|
+
assert.isEqualDeep(this.spyLiblsl.lastCreateStreamInfoOptions, {
|
|
153
152
|
...options,
|
|
154
153
|
channelFormat: this.channelIdx,
|
|
155
154
|
})
|
|
156
155
|
}
|
|
157
156
|
|
|
158
157
|
@test()
|
|
159
|
-
protected static async
|
|
158
|
+
protected static async canOverrideClassInstantiatedInFactory() {
|
|
160
159
|
LslOutlet.Class = CheckingOutlet
|
|
161
160
|
const instance = this.Outlet()
|
|
162
161
|
assert.isInstanceOf(instance, CheckingOutlet)
|
|
163
162
|
}
|
|
164
163
|
|
|
165
|
-
@test('can add one label', [generateId()])
|
|
166
|
-
@test('can add two labels', [generateId(), generateId()])
|
|
164
|
+
@test('can add one label to channels', [generateId()])
|
|
165
|
+
@test('can add two labels to channels', [generateId(), generateId()])
|
|
167
166
|
protected static async appendsChannelsBasedOnCount(labels: string[]) {
|
|
168
167
|
const type = generateId()
|
|
169
168
|
const unit = generateId()
|
|
170
169
|
|
|
171
|
-
this.Outlet({
|
|
170
|
+
this.Outlet({ channelNames: labels, type, unit })
|
|
172
171
|
|
|
173
|
-
assert.isEqualDeep(this.
|
|
174
|
-
info: this.
|
|
172
|
+
assert.isEqualDeep(this.spyLiblsl.lastAppendChannelsToStreamInfoOptions, {
|
|
173
|
+
info: this.spyLiblsl.streamInfo,
|
|
175
174
|
channels: labels.map((label) => ({
|
|
176
175
|
label,
|
|
177
176
|
type,
|
|
@@ -187,7 +186,7 @@ export default class LslOutletTest extends AbstractSpruceTest {
|
|
|
187
186
|
outlet.pushSample([2])
|
|
188
187
|
outlet.pushSample([3])
|
|
189
188
|
|
|
190
|
-
assert.isEqual(this.
|
|
189
|
+
assert.isEqual(this.spyLiblsl.createStreamInfoHitCount, 1)
|
|
191
190
|
}
|
|
192
191
|
|
|
193
192
|
private static pushSample(sample: LslSample) {
|
|
@@ -207,10 +206,10 @@ export default class LslOutletTest extends AbstractSpruceTest {
|
|
|
207
206
|
this.assertDoesThrowInvalidParameters({ sampleRate }, ['sampleRate'])
|
|
208
207
|
}
|
|
209
208
|
|
|
210
|
-
private static
|
|
209
|
+
private static assertThrowsInvalidChannelNames(count: number) {
|
|
211
210
|
this.assertDoesThrowInvalidParameters(
|
|
212
|
-
{
|
|
213
|
-
['
|
|
211
|
+
{ channelNames: new Array(count).fill(generateId()) },
|
|
212
|
+
['channelNames']
|
|
214
213
|
)
|
|
215
214
|
}
|
|
216
215
|
|
|
@@ -233,42 +232,34 @@ export default class LslOutletTest extends AbstractSpruceTest {
|
|
|
233
232
|
}
|
|
234
233
|
|
|
235
234
|
class SpyLiblsl implements Liblsl {
|
|
236
|
-
public
|
|
237
|
-
public
|
|
238
|
-
public
|
|
239
|
-
public
|
|
240
|
-
|
|
241
|
-
public
|
|
242
|
-
public
|
|
243
|
-
info: LslBindingsStreamInfo
|
|
244
|
-
channels: LslChannel[]
|
|
245
|
-
}
|
|
235
|
+
public lastCreateStreamInfoOptions?: CreateStreamInfoOptions
|
|
236
|
+
public lastAppendChannelsToStreamInfoOptions?: AppendChannelsToStreamInfoOptions
|
|
237
|
+
public lastCreateOutletOptions?: CreateOutletOptions
|
|
238
|
+
public lastPushSampleOptions?: PushSampleOptions
|
|
239
|
+
|
|
240
|
+
public outlet: BoundOutlet = {} as BoundOutlet
|
|
241
|
+
public streamInfo: BoundStreamInfo = {} as BoundStreamInfo
|
|
246
242
|
public createStreamInfoHitCount = 0
|
|
247
243
|
|
|
248
|
-
public createStreamInfo(
|
|
249
|
-
options: CreateStreamInfoOptions
|
|
250
|
-
): LslBindingsStreamInfo {
|
|
244
|
+
public createStreamInfo(options: CreateStreamInfoOptions): BoundStreamInfo {
|
|
251
245
|
this.createStreamInfoHitCount++
|
|
252
|
-
this.
|
|
246
|
+
this.lastCreateStreamInfoOptions = options
|
|
253
247
|
return this.streamInfo
|
|
254
248
|
}
|
|
249
|
+
|
|
255
250
|
public appendChannelsToStreamInfo(
|
|
256
|
-
|
|
257
|
-
channels: LslChannel[]
|
|
251
|
+
options: AppendChannelsToStreamInfoOptions
|
|
258
252
|
): void {
|
|
259
|
-
this.
|
|
260
|
-
info,
|
|
261
|
-
channels,
|
|
262
|
-
}
|
|
253
|
+
this.lastAppendChannelsToStreamInfoOptions = options
|
|
263
254
|
}
|
|
264
255
|
|
|
265
|
-
public createOutlet(options: CreateOutletOptions):
|
|
266
|
-
this.
|
|
256
|
+
public createOutlet(options: CreateOutletOptions): BoundOutlet {
|
|
257
|
+
this.lastCreateOutletOptions = options
|
|
267
258
|
return this.outlet
|
|
268
259
|
}
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
this.
|
|
260
|
+
|
|
261
|
+
public pushSample(options: PushSampleOptions): void {
|
|
262
|
+
this.lastPushSampleOptions = options
|
|
272
263
|
}
|
|
273
264
|
}
|
|
274
265
|
|
|
@@ -8,16 +8,17 @@ import AbstractSpruceTest, {
|
|
|
8
8
|
import ArrayType from 'ref-array-napi'
|
|
9
9
|
import ref from 'ref-napi'
|
|
10
10
|
import LiblslImpl, {
|
|
11
|
-
CreateStreamInfoOptions,
|
|
12
|
-
LiblslBindings,
|
|
13
11
|
Liblsl,
|
|
14
|
-
|
|
12
|
+
LiblslBindings,
|
|
13
|
+
CreateStreamInfoOptions,
|
|
14
|
+
AppendChannelsToStreamInfoOptions,
|
|
15
15
|
CreateOutletOptions,
|
|
16
|
-
|
|
17
|
-
LslBindingsStreamInfo,
|
|
16
|
+
PushSampleOptions,
|
|
18
17
|
LslChannel,
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
BoundOutlet,
|
|
19
|
+
BoundStreamInfo,
|
|
20
|
+
BoundDesc,
|
|
21
|
+
BoundChild,
|
|
21
22
|
} from '../../Liblsl'
|
|
22
23
|
|
|
23
24
|
export default class LiblslTest extends AbstractSpruceTest {
|
|
@@ -25,10 +26,10 @@ export default class LiblslTest extends AbstractSpruceTest {
|
|
|
25
26
|
private static libraryPath?: string
|
|
26
27
|
private static libraryOptions?: Record<string, any>
|
|
27
28
|
private static fakeBindings: LiblslBindings
|
|
28
|
-
private static fakeStreamInfo:
|
|
29
|
-
private static fakeOutlet:
|
|
30
|
-
private static fakeDesc:
|
|
31
|
-
private static fakeChildNamedChannels:
|
|
29
|
+
private static fakeStreamInfo: BoundStreamInfo
|
|
30
|
+
private static fakeOutlet: BoundOutlet
|
|
31
|
+
private static fakeDesc: BoundDesc
|
|
32
|
+
private static fakeChildNamedChannels: BoundChild
|
|
32
33
|
private static createStreamInfoParams?: any[]
|
|
33
34
|
private static appendChildParams: any[] = []
|
|
34
35
|
private static createOutletParams?: any[]
|
|
@@ -36,8 +37,8 @@ export default class LiblslTest extends AbstractSpruceTest {
|
|
|
36
37
|
private static appendChildValueParams: any[]
|
|
37
38
|
private static localClock: number
|
|
38
39
|
private static shouldThrowWhenCreatingBindings: boolean
|
|
39
|
-
private static getDescriptionParams?: [
|
|
40
|
-
private static fakeChildNamedChannel:
|
|
40
|
+
private static getDescriptionParams?: [BoundStreamInfo]
|
|
41
|
+
private static fakeChildNamedChannel: BoundChild
|
|
41
42
|
private static appendChildHitCount: number
|
|
42
43
|
|
|
43
44
|
protected static async beforeEach(): Promise<void> {
|
|
@@ -79,7 +80,7 @@ export default class LiblslTest extends AbstractSpruceTest {
|
|
|
79
80
|
return 0
|
|
80
81
|
},
|
|
81
82
|
lsl_local_clock: () => this.localClock,
|
|
82
|
-
lsl_get_desc: (info:
|
|
83
|
+
lsl_get_desc: (info: BoundStreamInfo) => {
|
|
83
84
|
this.getDescriptionParams = [info]
|
|
84
85
|
return this.fakeDesc
|
|
85
86
|
},
|
|
@@ -108,12 +109,12 @@ export default class LiblslTest extends AbstractSpruceTest {
|
|
|
108
109
|
},
|
|
109
110
|
}
|
|
110
111
|
|
|
111
|
-
LiblslImpl.
|
|
112
|
+
LiblslImpl.resetInstance()
|
|
112
113
|
this.lsl = LiblslImpl.getInstance()
|
|
113
114
|
}
|
|
114
115
|
|
|
115
116
|
@test()
|
|
116
|
-
protected static async
|
|
117
|
+
protected static async throwsWithMissingEnv() {
|
|
117
118
|
delete process.env.LIBLSL_PATH
|
|
118
119
|
const err = assert.doesThrow(() => new LiblslImpl())
|
|
119
120
|
errorAssert.assertError(err, 'MISSING_PARAMETERS', {
|
|
@@ -122,7 +123,7 @@ export default class LiblslTest extends AbstractSpruceTest {
|
|
|
122
123
|
}
|
|
123
124
|
|
|
124
125
|
@test()
|
|
125
|
-
protected static async
|
|
126
|
+
protected static async throwsWhenBindingsFailToLoad() {
|
|
126
127
|
this.shouldThrowWhenCreatingBindings = true
|
|
127
128
|
const err = assert.doesThrow(() => new LiblslImpl())
|
|
128
129
|
errorAssert.assertError(err, 'FAILED_TO_LOAD_LIBLSL', {
|
|
@@ -130,6 +131,49 @@ export default class LiblslTest extends AbstractSpruceTest {
|
|
|
130
131
|
})
|
|
131
132
|
}
|
|
132
133
|
|
|
134
|
+
@test()
|
|
135
|
+
protected static throwsWhenCreateStreamInfoIsMissingRequiredParams() {
|
|
136
|
+
//@ts-ignore
|
|
137
|
+
const err = assert.doesThrow(() => this.lsl.createStreamInfo())
|
|
138
|
+
errorAssert.assertError(err, 'MISSING_PARAMETERS', {
|
|
139
|
+
parameters: [
|
|
140
|
+
'name',
|
|
141
|
+
'type',
|
|
142
|
+
'channelCount',
|
|
143
|
+
'sampleRate',
|
|
144
|
+
'channelFormat',
|
|
145
|
+
'sourceId',
|
|
146
|
+
],
|
|
147
|
+
})
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
@test()
|
|
151
|
+
protected static async throwsWhenAppendChannelsIsMissingRequiredParams() {
|
|
152
|
+
//@ts-ignore
|
|
153
|
+
const err = assert.doesThrow(() => this.lsl.appendChannelsToStreamInfo({}))
|
|
154
|
+
errorAssert.assertError(err, 'MISSING_PARAMETERS', {
|
|
155
|
+
parameters: ['info', 'channels'],
|
|
156
|
+
})
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
@test()
|
|
160
|
+
protected static async throwsWhenCreateOutletIsMissingRequiredParams() {
|
|
161
|
+
//@ts-ignore
|
|
162
|
+
const err = assert.doesThrow(() => this.lsl.createOutlet({}))
|
|
163
|
+
errorAssert.assertError(err, 'MISSING_PARAMETERS', {
|
|
164
|
+
parameters: ['info', 'chunkSize', 'maxBuffered'],
|
|
165
|
+
})
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
@test()
|
|
169
|
+
protected static async throwsWhenPushSampleIsMissingRequiredParams() {
|
|
170
|
+
//@ts-ignore
|
|
171
|
+
const err = assert.doesThrow(() => this.lsl.pushSample())
|
|
172
|
+
errorAssert.assertError(err, 'MISSING_PARAMETERS', {
|
|
173
|
+
parameters: ['outlet', 'sample'],
|
|
174
|
+
})
|
|
175
|
+
}
|
|
176
|
+
|
|
133
177
|
@test()
|
|
134
178
|
protected static async worksAsASingleton() {
|
|
135
179
|
const liblsl = LiblslImpl.getInstance()
|
|
@@ -172,23 +216,7 @@ export default class LiblslTest extends AbstractSpruceTest {
|
|
|
172
216
|
}
|
|
173
217
|
|
|
174
218
|
@test()
|
|
175
|
-
protected static
|
|
176
|
-
//@ts-ignore
|
|
177
|
-
const err = assert.doesThrow(() => this.lsl.createStreamInfo())
|
|
178
|
-
errorAssert.assertError(err, 'MISSING_PARAMETERS', {
|
|
179
|
-
parameters: [
|
|
180
|
-
'name',
|
|
181
|
-
'type',
|
|
182
|
-
'channelCount',
|
|
183
|
-
'sampleRate',
|
|
184
|
-
'channelFormat',
|
|
185
|
-
'sourceId',
|
|
186
|
-
],
|
|
187
|
-
})
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
@test()
|
|
191
|
-
protected static async canGetStreamInfoWithRequiredParams() {
|
|
219
|
+
protected static async canCreateStreamInfoWithRequiredParams() {
|
|
192
220
|
const options = this.generateRandomCreateStreamInfoOptions()
|
|
193
221
|
const actual = this.lsl.createStreamInfo(options)
|
|
194
222
|
|
|
@@ -196,15 +224,6 @@ export default class LiblslTest extends AbstractSpruceTest {
|
|
|
196
224
|
assert.isEqualDeep(this.createStreamInfoParams, Object.values(options))
|
|
197
225
|
}
|
|
198
226
|
|
|
199
|
-
@test()
|
|
200
|
-
protected static async createOutletThrowsWhenMissingRequiredParams() {
|
|
201
|
-
//@ts-ignore
|
|
202
|
-
const err = assert.doesThrow(() => this.lsl.createOutlet({}))
|
|
203
|
-
errorAssert.assertError(err, 'MISSING_PARAMETERS', {
|
|
204
|
-
parameters: ['info', 'chunkSize', 'maxBuffered'],
|
|
205
|
-
})
|
|
206
|
-
}
|
|
207
|
-
|
|
208
227
|
@test()
|
|
209
228
|
protected static async canCreateOutletWithRequiredParams() {
|
|
210
229
|
const info = this.createRandomStreamInfo()
|
|
@@ -219,37 +238,27 @@ export default class LiblslTest extends AbstractSpruceTest {
|
|
|
219
238
|
}
|
|
220
239
|
|
|
221
240
|
@test()
|
|
222
|
-
protected static async
|
|
223
|
-
//@ts-ignore
|
|
224
|
-
const err = assert.doesThrow(() => this.lsl.pushSample())
|
|
225
|
-
errorAssert.assertError(err, 'MISSING_PARAMETERS', {
|
|
226
|
-
parameters: ['outlet', 'sample'],
|
|
227
|
-
})
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
@test()
|
|
231
|
-
protected static async pushSampleCallsBindings() {
|
|
241
|
+
protected static async canPushSampleWithRequiredParams() {
|
|
232
242
|
const expected = [1, 2, 3]
|
|
233
|
-
|
|
243
|
+
const options = {
|
|
244
|
+
outlet: this.fakeOutlet,
|
|
245
|
+
sample: expected,
|
|
246
|
+
}
|
|
247
|
+
this.lsl.pushSample(options)
|
|
234
248
|
assert.isEqual(this.pushSampleParams?.[0], this.fakeOutlet)
|
|
235
249
|
assert.isEqual(this.pushSampleParams?.[1], expected)
|
|
236
250
|
assert.isEqual(this.pushSampleParams?.[2], this.localClock)
|
|
237
251
|
}
|
|
238
252
|
|
|
239
|
-
@test()
|
|
240
|
-
protected static async appendChannelsThrowsWithMissingParams() {
|
|
241
|
-
//@ts-ignore
|
|
242
|
-
const err = assert.doesThrow(() => this.lsl.appendChannelsToStreamInfo())
|
|
243
|
-
errorAssert.assertError(err, 'MISSING_PARAMETERS', {
|
|
244
|
-
parameters: ['info', 'channels'],
|
|
245
|
-
})
|
|
246
|
-
}
|
|
247
|
-
|
|
248
253
|
@test()
|
|
249
254
|
protected static async addingSingleChannelGetsDescription() {
|
|
250
255
|
const info = this.createRandomStreamInfo()
|
|
251
256
|
const channel: LslChannel = this.generateRandomChannelValues()
|
|
252
|
-
|
|
257
|
+
|
|
258
|
+
this.lsl.appendChannelsToStreamInfo({
|
|
259
|
+
info,
|
|
260
|
+
channels: [channel],
|
|
261
|
+
})
|
|
253
262
|
assert.isEqual(this.getDescriptionParams?.[0], info)
|
|
254
263
|
|
|
255
264
|
assert.isEqual(this.appendChildParams?.[0][0], this.fakeDesc)
|
|
@@ -280,7 +289,10 @@ export default class LiblslTest extends AbstractSpruceTest {
|
|
|
280
289
|
const channel1 = this.generateRandomChannelValues()
|
|
281
290
|
const channel2 = this.generateRandomChannelValues()
|
|
282
291
|
|
|
283
|
-
this.lsl.appendChannelsToStreamInfo(
|
|
292
|
+
this.lsl.appendChannelsToStreamInfo({
|
|
293
|
+
info,
|
|
294
|
+
channels: [channel1, channel2],
|
|
295
|
+
})
|
|
284
296
|
|
|
285
297
|
assert.isEqual(this.appendChildParams?.[2][0], this.fakeChildNamedChannels)
|
|
286
298
|
assert.isEqual(this.appendChildParams?.[2][1], 'channel')
|
|
@@ -290,6 +302,12 @@ export default class LiblslTest extends AbstractSpruceTest {
|
|
|
290
302
|
assert.isEqual(this.appendChildValueParams[5][2], channel2.type)
|
|
291
303
|
}
|
|
292
304
|
|
|
305
|
+
private static createRandomStreamInfo() {
|
|
306
|
+
return this.lsl.createStreamInfo(
|
|
307
|
+
this.generateRandomCreateStreamInfoOptions()
|
|
308
|
+
)
|
|
309
|
+
}
|
|
310
|
+
|
|
293
311
|
private static generateRandomChannelValues(): LslChannel {
|
|
294
312
|
return {
|
|
295
313
|
label: generateId(),
|
|
@@ -298,38 +316,32 @@ export default class LiblslTest extends AbstractSpruceTest {
|
|
|
298
316
|
}
|
|
299
317
|
}
|
|
300
318
|
|
|
301
|
-
private static createRandomStreamInfo() {
|
|
302
|
-
return this.lsl.createStreamInfo(
|
|
303
|
-
this.generateRandomCreateStreamInfoOptions()
|
|
304
|
-
)
|
|
305
|
-
}
|
|
306
|
-
|
|
307
319
|
private static generateRandomCreateStreamInfoOptions() {
|
|
308
320
|
return {
|
|
309
321
|
name: generateId(),
|
|
310
322
|
type: generateId(),
|
|
311
|
-
channelCount: randomInt(10),
|
|
312
|
-
sampleRate: randomInt(
|
|
313
|
-
channelFormat: randomInt(
|
|
323
|
+
channelCount: randomInt(1, 10),
|
|
324
|
+
sampleRate: randomInt(100),
|
|
325
|
+
channelFormat: randomInt(7),
|
|
314
326
|
sourceId: generateId(),
|
|
315
327
|
}
|
|
316
328
|
}
|
|
317
329
|
}
|
|
318
330
|
|
|
319
331
|
class FakeLiblsl implements Liblsl {
|
|
332
|
+
public createStreamInfo(_options: CreateStreamInfoOptions): BoundStreamInfo {
|
|
333
|
+
return {} as BoundStreamInfo
|
|
334
|
+
}
|
|
335
|
+
|
|
320
336
|
public appendChannelsToStreamInfo(
|
|
321
|
-
|
|
322
|
-
_channels: LslChannel[]
|
|
337
|
+
_options: AppendChannelsToStreamInfoOptions
|
|
323
338
|
): void {}
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
public createStreamInfo(
|
|
328
|
-
_options: CreateStreamInfoOptions
|
|
329
|
-
): LslBindingsStreamInfo {
|
|
330
|
-
return {} as LslBindingsStreamInfo
|
|
339
|
+
|
|
340
|
+
public createOutlet(_options: CreateOutletOptions): BoundOutlet {
|
|
341
|
+
return {} as BoundOutlet
|
|
331
342
|
}
|
|
332
|
-
|
|
343
|
+
|
|
344
|
+
public pushSample(_options: PushSampleOptions): void {}
|
|
333
345
|
}
|
|
334
346
|
|
|
335
347
|
const streamInfo = ref.refType(ref.types.void)
|