@neurodevs/node-lsl 14.0.0 → 14.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/build/__tests__/impl/LiblslAdapter.test.d.ts +7 -5
- package/build/__tests__/impl/LiblslAdapter.test.js +27 -10
- package/build/__tests__/impl/LiblslAdapter.test.js.map +1 -1
- package/build/__tests__/impl/LslEventMarkerOutlet.test.d.ts +1 -0
- package/build/__tests__/impl/LslEventMarkerOutlet.test.js +7 -0
- package/build/__tests__/impl/LslEventMarkerOutlet.test.js.map +1 -1
- package/build/__tests__/impl/LslStreamInfo.test.d.ts +1 -0
- package/build/__tests__/impl/LslStreamInfo.test.js +8 -1
- package/build/__tests__/impl/LslStreamInfo.test.js.map +1 -1
- package/build/__tests__/impl/LslStreamInlet.test.d.ts +1 -0
- package/build/__tests__/impl/LslStreamInlet.test.js +8 -1
- package/build/__tests__/impl/LslStreamInlet.test.js.map +1 -1
- package/build/__tests__/impl/LslStreamOutlet.test.d.ts +1 -0
- package/build/__tests__/impl/LslStreamOutlet.test.js +8 -0
- package/build/__tests__/impl/LslStreamOutlet.test.js.map +1 -1
- package/build/impl/LiblslAdapter.d.ts +8 -2
- package/build/impl/LiblslAdapter.js +10 -1
- package/build/impl/LiblslAdapter.js.map +1 -1
- package/build/impl/LslEventMarkerOutlet.d.ts +2 -0
- package/build/impl/LslEventMarkerOutlet.js +3 -0
- package/build/impl/LslEventMarkerOutlet.js.map +1 -1
- package/build/impl/LslStreamInfo.d.ts +11 -9
- package/build/impl/LslStreamInfo.js +17 -14
- package/build/impl/LslStreamInfo.js.map +1 -1
- package/build/impl/LslStreamInlet.d.ts +3 -0
- package/build/impl/LslStreamInlet.js +11 -1
- package/build/impl/LslStreamInlet.js.map +1 -1
- package/build/impl/LslStreamOutlet.d.ts +18 -17
- package/build/impl/LslStreamOutlet.js +61 -65
- package/build/impl/LslStreamOutlet.js.map +1 -1
- package/build/impl/LslWebSocketBridge.d.ts +1 -1
- package/build/impl/LslWebSocketBridge.js +2 -2
- package/build/impl/LslWebSocketBridge.js.map +1 -1
- package/build/testDoubles/Liblsl/FakeLiblsl.d.ts +3 -1
- package/build/testDoubles/Liblsl/FakeLiblsl.js +4 -0
- package/build/testDoubles/Liblsl/FakeLiblsl.js.map +1 -1
- package/build/testDoubles/StreamInfo/FakeStreamInfo.d.ts +2 -0
- package/build/testDoubles/StreamInfo/FakeStreamInfo.js +5 -0
- package/build/testDoubles/StreamInfo/FakeStreamInfo.js.map +1 -1
- package/build/testDoubles/StreamInfo/SpyStreamInfo.d.ts +1 -1
- package/build/testDoubles/StreamInfo/SpyStreamInfo.js +2 -2
- package/build/testDoubles/StreamInfo/SpyStreamInfo.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/impl/LiblslAdapter.test.ts +27 -5
- package/src/__tests__/impl/LslEventMarkerOutlet.test.ts +11 -0
- package/src/__tests__/impl/LslStreamInfo.test.ts +12 -1
- package/src/__tests__/impl/LslStreamInlet.test.ts +12 -1
- package/src/__tests__/impl/LslStreamOutlet.test.ts +12 -0
- package/src/impl/LiblslAdapter.ts +20 -4
- package/src/impl/LslEventMarkerOutlet.ts +5 -0
- package/src/impl/LslStreamInfo.ts +22 -17
- package/src/impl/LslStreamInlet.ts +14 -1
- package/src/impl/LslStreamOutlet.ts +94 -85
- package/src/impl/LslWebSocketBridge.ts +2 -2
- package/src/testDoubles/Liblsl/FakeLiblsl.ts +6 -0
- package/src/testDoubles/StreamInfo/FakeStreamInfo.ts +7 -0
- package/src/testDoubles/StreamInfo/SpyStreamInfo.ts +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SpyStreamInfo.js","sourceRoot":"","sources":["../../../src/testDoubles/StreamInfo/SpyStreamInfo.ts"],"names":[],"mappings":"AAAA,OAAO,aAAoC,MAAM,6BAA6B,CAAA;AAE9E,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,aAAa;IACpD,YAAmB,OAA0B;QACzC,KAAK,CAAC,OAAO,CAAC,CAAA;IAClB,CAAC;IAEM,
|
|
1
|
+
{"version":3,"file":"SpyStreamInfo.js","sourceRoot":"","sources":["../../../src/testDoubles/StreamInfo/SpyStreamInfo.ts"],"names":[],"mappings":"AAAA,OAAO,aAAoC,MAAM,6BAA6B,CAAA;AAE9E,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,aAAa;IACpD,YAAmB,OAA0B;QACzC,KAAK,CAAC,OAAO,CAAC,CAAA;IAClB,CAAC;IAEM,YAAY;QACf,OAAO,IAAI,CAAC,SAAS,CAAA;IACzB,CAAC;IAEM,OAAO;QACV,OAAO,IAAI,CAAC,IAAI,CAAA;IACpB,CAAC;IAEM,OAAO;QACV,OAAO,IAAI,CAAC,IAAI,CAAA;IACpB,CAAC;IAEM,WAAW;QACd,OAAO,IAAI,CAAC,QAAQ,CAAA;IACxB,CAAC;IAEM,QAAQ;QACX,OAAO,IAAI,CAAC,KAAK,CAAA;IACrB,CAAC;CACJ"}
|
package/package.json
CHANGED
|
@@ -33,7 +33,9 @@ export default class LiblslAdapterTest extends AbstractPackageTest {
|
|
|
33
33
|
private static fakeInlet: BoundInlet = {}
|
|
34
34
|
private static fakeDesc: BoundDescription
|
|
35
35
|
private static fakeChildNamedChannels: BoundChild
|
|
36
|
+
|
|
36
37
|
private static createStreamInfoParams?: any[]
|
|
38
|
+
private static destroyStreamInfoParams?: any[]
|
|
37
39
|
private static appendChildParams: any[] = []
|
|
38
40
|
private static createOutletParams?: any[]
|
|
39
41
|
private static destroyOutletParams?: any[]
|
|
@@ -162,6 +164,11 @@ export default class LiblslAdapterTest extends AbstractPackageTest {
|
|
|
162
164
|
DataType.String,
|
|
163
165
|
],
|
|
164
166
|
},
|
|
167
|
+
lsl_destroy_streaminfo: {
|
|
168
|
+
library: 'lsl',
|
|
169
|
+
retType: DataType.Void,
|
|
170
|
+
paramsType: [DataType.External],
|
|
171
|
+
},
|
|
165
172
|
lsl_create_outlet: {
|
|
166
173
|
library: 'lsl',
|
|
167
174
|
retType: DataType.External,
|
|
@@ -233,7 +240,7 @@ export default class LiblslAdapterTest extends AbstractPackageTest {
|
|
|
233
240
|
}
|
|
234
241
|
|
|
235
242
|
@test()
|
|
236
|
-
protected static async
|
|
243
|
+
protected static async createsStreamInfoWithRequiredParams() {
|
|
237
244
|
const options = this.generateRandomCreateStreamInfoOptions()
|
|
238
245
|
const actual = this.instance.createStreamInfo(options)
|
|
239
246
|
|
|
@@ -242,7 +249,19 @@ export default class LiblslAdapterTest extends AbstractPackageTest {
|
|
|
242
249
|
}
|
|
243
250
|
|
|
244
251
|
@test()
|
|
245
|
-
protected static async
|
|
252
|
+
protected static async destroysStreamInfoWithBoundInfo() {
|
|
253
|
+
const info = this.createRandomStreamInfo()
|
|
254
|
+
this.instance.destroyStreamInfo({ info })
|
|
255
|
+
|
|
256
|
+
assert.isEqualDeep(
|
|
257
|
+
this.destroyStreamInfoParams,
|
|
258
|
+
[info],
|
|
259
|
+
'Did not call destroyStreamInfo with expected params!'
|
|
260
|
+
)
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
@test()
|
|
264
|
+
protected static async createsOutletWithRequiredParams() {
|
|
246
265
|
const { options, outlet } = this.createRandomOutlet()
|
|
247
266
|
|
|
248
267
|
const expected = {
|
|
@@ -255,7 +274,7 @@ export default class LiblslAdapterTest extends AbstractPackageTest {
|
|
|
255
274
|
}
|
|
256
275
|
|
|
257
276
|
@test()
|
|
258
|
-
protected static async
|
|
277
|
+
protected static async pushesFloatSample() {
|
|
259
278
|
const expected = [1.0, 2.0, 3.0]
|
|
260
279
|
const timestamp = randomInt(100)
|
|
261
280
|
const options = {
|
|
@@ -273,7 +292,7 @@ export default class LiblslAdapterTest extends AbstractPackageTest {
|
|
|
273
292
|
}
|
|
274
293
|
|
|
275
294
|
@test()
|
|
276
|
-
protected static async
|
|
295
|
+
protected static async pushesStringSample() {
|
|
277
296
|
const expected = [this.generateId()]
|
|
278
297
|
const timestamp = randomInt(100)
|
|
279
298
|
const options = {
|
|
@@ -386,7 +405,7 @@ export default class LiblslAdapterTest extends AbstractPackageTest {
|
|
|
386
405
|
}
|
|
387
406
|
|
|
388
407
|
@test()
|
|
389
|
-
protected static async
|
|
408
|
+
protected static async createInletWithRequiredParams() {
|
|
390
409
|
const { options, inlet } = this.createRandomInlet()
|
|
391
410
|
|
|
392
411
|
const expected = {
|
|
@@ -604,6 +623,9 @@ export default class LiblslAdapterTest extends AbstractPackageTest {
|
|
|
604
623
|
this.createStreamInfoParams = params
|
|
605
624
|
return this.fakeStreamInfo
|
|
606
625
|
},
|
|
626
|
+
lsl_destroy_streaminfo: (params: any[]) => {
|
|
627
|
+
this.destroyStreamInfoParams = params
|
|
628
|
+
},
|
|
607
629
|
lsl_create_outlet: (params: any[]) => {
|
|
608
630
|
this.createOutletParams = params
|
|
609
631
|
return this.fakeOutlet
|
|
@@ -148,6 +148,17 @@ export default class EventMarkerOutletTest extends AbstractPackageTest {
|
|
|
148
148
|
assert.isEqual(FakeStreamOutlet.callsToPushSample[0][0], markerName)
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
+
@test()
|
|
152
|
+
protected static async destroyCallsDestroyOnInternalStreamOutlet() {
|
|
153
|
+
this.instance.destroy()
|
|
154
|
+
|
|
155
|
+
assert.isEqual(
|
|
156
|
+
FakeStreamOutlet.numCallsToDestroy,
|
|
157
|
+
1,
|
|
158
|
+
'Did not call destroy on outlet!'
|
|
159
|
+
)
|
|
160
|
+
}
|
|
161
|
+
|
|
151
162
|
private static get streamOutlet() {
|
|
152
163
|
return this.instance.getStreamOutlet()
|
|
153
164
|
}
|
|
@@ -170,7 +170,7 @@ export default class LslStreamInfoTest extends AbstractPackageTest {
|
|
|
170
170
|
assert.isEqualDeep(
|
|
171
171
|
this.fakeLiblsl.lastAppendChannelsToStreamInfoOptions,
|
|
172
172
|
{
|
|
173
|
-
info: this.instance.
|
|
173
|
+
info: this.instance.getBoundInfo(),
|
|
174
174
|
channels: this.channelNames.map((label: string) => ({
|
|
175
175
|
label,
|
|
176
176
|
units: this.units,
|
|
@@ -181,6 +181,17 @@ export default class LslStreamInfoTest extends AbstractPackageTest {
|
|
|
181
181
|
)
|
|
182
182
|
}
|
|
183
183
|
|
|
184
|
+
@test()
|
|
185
|
+
protected static async callsBindingsToDestroyStreamInfo() {
|
|
186
|
+
this.instance.destroy()
|
|
187
|
+
|
|
188
|
+
assert.isEqualDeep(
|
|
189
|
+
this.fakeLiblsl.lastDestroyStreamInfoOptions?.info,
|
|
190
|
+
this.instance.getBoundInfo(),
|
|
191
|
+
'Should have called destroyStreamInfo!'
|
|
192
|
+
)
|
|
193
|
+
}
|
|
194
|
+
|
|
184
195
|
private static readonly defaultOptions = {
|
|
185
196
|
name: this.generateId(),
|
|
186
197
|
type: this.generateId(),
|
|
@@ -90,7 +90,18 @@ export default class LslStreamInletTest extends AbstractPackageTest {
|
|
|
90
90
|
assert.isEqualDeep(
|
|
91
91
|
this.fakeLiblsl.lastDestroyInletOptions,
|
|
92
92
|
{ inlet: this.boundInlet },
|
|
93
|
-
'
|
|
93
|
+
'Did not destroy inlet!'
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
@test()
|
|
98
|
+
protected static async destroyAlsoCallsDestroyStreamInfo() {
|
|
99
|
+
this.instance.destroy()
|
|
100
|
+
|
|
101
|
+
assert.isEqualDeep(
|
|
102
|
+
this.fakeLiblsl.lastDestroyStreamInfoOptions,
|
|
103
|
+
{ info: this.instance.getStreamInfo().boundStreamInfo },
|
|
104
|
+
'Did not destroy stream info!'
|
|
94
105
|
)
|
|
95
106
|
}
|
|
96
107
|
|
|
@@ -193,6 +193,18 @@ export default class LslStreamOutletTest extends AbstractPackageTest {
|
|
|
193
193
|
assert.isEqual(this.fakeLiblsl.destroyOutletHitCount, 1)
|
|
194
194
|
}
|
|
195
195
|
|
|
196
|
+
@test()
|
|
197
|
+
protected static async destroyAlsoCallsDestroyStreamInfo() {
|
|
198
|
+
const outlet = await this.LslStreamOutlet()
|
|
199
|
+
outlet.destroy()
|
|
200
|
+
|
|
201
|
+
assert.isEqualDeep(
|
|
202
|
+
this.fakeLiblsl.lastDestroyStreamInfoOptions,
|
|
203
|
+
{ info: this.fakeLiblsl.streamInfo },
|
|
204
|
+
'Did not call destroyStreamInfo on destroy!'
|
|
205
|
+
)
|
|
206
|
+
}
|
|
207
|
+
|
|
196
208
|
@test()
|
|
197
209
|
protected static async pushSampleShouldNotCreateMultipleOutlets() {
|
|
198
210
|
const outlet = await this.FloatOutlet()
|
|
@@ -69,10 +69,10 @@ export default class LiblslAdapter implements Liblsl {
|
|
|
69
69
|
const {
|
|
70
70
|
name,
|
|
71
71
|
type,
|
|
72
|
+
sourceId,
|
|
72
73
|
channelCount,
|
|
73
|
-
sampleRateHz,
|
|
74
74
|
channelFormat,
|
|
75
|
-
|
|
75
|
+
sampleRateHz,
|
|
76
76
|
} = options
|
|
77
77
|
|
|
78
78
|
return this.bindings.lsl_create_streaminfo([
|
|
@@ -85,6 +85,11 @@ export default class LiblslAdapter implements Liblsl {
|
|
|
85
85
|
])
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
+
public destroyStreamInfo(options: DestroyStreamInfoOptions) {
|
|
89
|
+
const { info } = options
|
|
90
|
+
this.bindings.lsl_destroy_streaminfo([info])
|
|
91
|
+
}
|
|
92
|
+
|
|
88
93
|
public appendChannelsToStreamInfo(
|
|
89
94
|
options: AppendChannelsToStreamInfoOptions
|
|
90
95
|
) {
|
|
@@ -248,6 +253,11 @@ export default class LiblslAdapter implements Liblsl {
|
|
|
248
253
|
DataType.String,
|
|
249
254
|
],
|
|
250
255
|
},
|
|
256
|
+
lsl_destroy_streaminfo: {
|
|
257
|
+
library: 'lsl',
|
|
258
|
+
retType: DataType.Void,
|
|
259
|
+
paramsType: [DataType.External],
|
|
260
|
+
},
|
|
251
261
|
lsl_create_outlet: {
|
|
252
262
|
library: 'lsl',
|
|
253
263
|
retType: DataType.External,
|
|
@@ -323,6 +333,7 @@ export interface Liblsl {
|
|
|
323
333
|
liblslPath: string
|
|
324
334
|
|
|
325
335
|
createStreamInfo(options: CreateStreamInfoOptions): BoundStreamInfo
|
|
336
|
+
destroyStreamInfo(options: DestroyStreamInfoOptions): void
|
|
326
337
|
appendChannelsToStreamInfo(options: AppendChannelsToStreamInfoOptions): void
|
|
327
338
|
|
|
328
339
|
createOutlet(options: CreateOutletOptions): BoundOutlet
|
|
@@ -349,10 +360,10 @@ export interface Liblsl {
|
|
|
349
360
|
export interface CreateStreamInfoOptions {
|
|
350
361
|
name: string
|
|
351
362
|
type: string
|
|
363
|
+
sourceId: string
|
|
352
364
|
channelCount: number
|
|
353
|
-
sampleRateHz: number
|
|
354
365
|
channelFormat: number
|
|
355
|
-
|
|
366
|
+
sampleRateHz: number
|
|
356
367
|
manufacturer?: string
|
|
357
368
|
units?: string
|
|
358
369
|
}
|
|
@@ -368,6 +379,10 @@ export interface CreateOutletOptions {
|
|
|
368
379
|
maxBufferedMs: number
|
|
369
380
|
}
|
|
370
381
|
|
|
382
|
+
export interface DestroyStreamInfoOptions {
|
|
383
|
+
info: BoundStreamInfo
|
|
384
|
+
}
|
|
385
|
+
|
|
371
386
|
export interface PushSampleFloatTimestampOptions {
|
|
372
387
|
outlet: BoundOutlet
|
|
373
388
|
sample: number[]
|
|
@@ -421,6 +436,7 @@ export interface LiblslBindings {
|
|
|
421
436
|
args: [string, string, number, number, number, string]
|
|
422
437
|
): BoundStreamInfo
|
|
423
438
|
|
|
439
|
+
lsl_destroy_streaminfo(args: [BoundStreamInfo]): void
|
|
424
440
|
lsl_create_outlet(args: [BoundStreamInfo, number, number]): BoundOutlet
|
|
425
441
|
lsl_push_sample_ft(args: [BoundOutlet, LslSample, number]): LslErrorCode
|
|
426
442
|
lsl_push_sample_strt(args: [BoundOutlet, LslSample, number]): LslErrorCode
|
|
@@ -74,12 +74,17 @@ export default class LslEventMarkerOutlet implements EventMarkerOutlet {
|
|
|
74
74
|
clearTimeout(this.timeout)
|
|
75
75
|
this.isPlaying = false
|
|
76
76
|
}
|
|
77
|
+
|
|
78
|
+
public destroy() {
|
|
79
|
+
this.outlet.destroy()
|
|
80
|
+
}
|
|
77
81
|
}
|
|
78
82
|
|
|
79
83
|
export interface EventMarkerOutlet {
|
|
80
84
|
pushMarker(markerName: string): void
|
|
81
85
|
pushMarkers(markers: DurationMarker[]): Promise<void>
|
|
82
86
|
stop(): void
|
|
87
|
+
destroy(): void
|
|
83
88
|
}
|
|
84
89
|
|
|
85
90
|
export type EventMarkerOutletConstructor = new (
|
|
@@ -11,11 +11,16 @@ export default class LslStreamInfo implements StreamInfo {
|
|
|
11
11
|
protected type: string
|
|
12
12
|
protected sourceId: string
|
|
13
13
|
protected units: string
|
|
14
|
-
protected
|
|
14
|
+
protected boundInfo!: BoundStreamInfo
|
|
15
15
|
private channelNames: string[]
|
|
16
16
|
private channelFormat: ChannelFormat
|
|
17
17
|
private sampleRateHz: number
|
|
18
18
|
|
|
19
|
+
private readonly defaultName = `lsl-stream-info-${generateId()}`
|
|
20
|
+
private readonly defaultType = generateId()
|
|
21
|
+
private readonly defaultSourceId = generateId()
|
|
22
|
+
private readonly defaultUnits = 'N/A'
|
|
23
|
+
|
|
19
24
|
protected constructor(options: StreamInfoOptions) {
|
|
20
25
|
const {
|
|
21
26
|
name = this.defaultName,
|
|
@@ -44,7 +49,7 @@ export default class LslStreamInfo implements StreamInfo {
|
|
|
44
49
|
}
|
|
45
50
|
|
|
46
51
|
private createStreamInfo() {
|
|
47
|
-
this.
|
|
52
|
+
this.boundInfo = this.lsl.createStreamInfo({
|
|
48
53
|
name: this.name,
|
|
49
54
|
type: this.type,
|
|
50
55
|
sourceId: this.sourceId,
|
|
@@ -54,9 +59,17 @@ export default class LslStreamInfo implements StreamInfo {
|
|
|
54
59
|
})
|
|
55
60
|
}
|
|
56
61
|
|
|
62
|
+
private get channelCount() {
|
|
63
|
+
return this.channelNames.length
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
private get lslChannelFormat() {
|
|
67
|
+
return CHANNEL_FORMATS_MAP[this.channelFormat]
|
|
68
|
+
}
|
|
69
|
+
|
|
57
70
|
private appendChannelsToStreamInfo() {
|
|
58
71
|
this.lsl.appendChannelsToStreamInfo({
|
|
59
|
-
info: this.
|
|
72
|
+
info: this.boundInfo,
|
|
60
73
|
channels: this.channelNames.map((label: string) => ({
|
|
61
74
|
label,
|
|
62
75
|
units: this.units,
|
|
@@ -65,30 +78,22 @@ export default class LslStreamInfo implements StreamInfo {
|
|
|
65
78
|
})
|
|
66
79
|
}
|
|
67
80
|
|
|
68
|
-
public
|
|
69
|
-
|
|
81
|
+
public destroy() {
|
|
82
|
+
this.lsl.destroyStreamInfo({ info: this.boundInfo })
|
|
70
83
|
}
|
|
71
84
|
|
|
72
|
-
|
|
73
|
-
return this.
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
private get lslChannelFormat() {
|
|
77
|
-
return CHANNEL_FORMATS_MAP[this.channelFormat]
|
|
85
|
+
public get boundStreamInfo() {
|
|
86
|
+
return this.boundInfo
|
|
78
87
|
}
|
|
79
88
|
|
|
80
89
|
private get lsl() {
|
|
81
90
|
return LiblslAdapter.getInstance()
|
|
82
91
|
}
|
|
83
|
-
|
|
84
|
-
private readonly defaultName = `lsl-stream-info-${generateId()}`
|
|
85
|
-
private readonly defaultType = generateId()
|
|
86
|
-
private readonly defaultSourceId = generateId()
|
|
87
|
-
private readonly defaultUnits = 'N/A'
|
|
88
92
|
}
|
|
89
93
|
|
|
90
94
|
export interface StreamInfo {
|
|
91
|
-
|
|
95
|
+
destroy(): void
|
|
96
|
+
readonly boundStreamInfo: BoundStreamInfo
|
|
92
97
|
}
|
|
93
98
|
|
|
94
99
|
type StreamInfoConstructor = new (options: StreamInfoOptions) => StreamInfo
|
|
@@ -88,12 +88,16 @@ export default class LslStreamInlet implements StreamInlet {
|
|
|
88
88
|
|
|
89
89
|
private createBoundInlet() {
|
|
90
90
|
this.inlet = this.lsl.createInlet({
|
|
91
|
-
info: this.
|
|
91
|
+
info: this.boundStreamInfo,
|
|
92
92
|
chunkSize: this.chunkSize,
|
|
93
93
|
maxBufferedMs: this.maxBufferedMs / 1000,
|
|
94
94
|
})
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
+
private get boundStreamInfo() {
|
|
98
|
+
return this.info.boundStreamInfo
|
|
99
|
+
}
|
|
100
|
+
|
|
97
101
|
public startPulling() {
|
|
98
102
|
this.isRunning = true
|
|
99
103
|
|
|
@@ -250,6 +254,15 @@ export default class LslStreamInlet implements StreamInlet {
|
|
|
250
254
|
}
|
|
251
255
|
|
|
252
256
|
public destroy() {
|
|
257
|
+
this.destroyBoundStreamInfo()
|
|
258
|
+
this.destroyBoundInlet()
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
private destroyBoundStreamInfo() {
|
|
262
|
+
this.lsl.destroyStreamInfo({ info: this.boundStreamInfo })
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
private destroyBoundInlet() {
|
|
253
266
|
this.lsl.destroyInlet({ inlet: this.inlet })
|
|
254
267
|
}
|
|
255
268
|
|
|
@@ -21,14 +21,48 @@ import LslStreamInfo, {
|
|
|
21
21
|
export default class LslStreamOutlet implements StreamOutlet {
|
|
22
22
|
public static Class?: StreamOutletConstructor
|
|
23
23
|
|
|
24
|
+
public readonly name: string
|
|
25
|
+
public readonly type: string
|
|
26
|
+
public readonly sourceId: string
|
|
27
|
+
public readonly channelNames: string[]
|
|
28
|
+
public readonly channelFormat: ChannelFormat
|
|
29
|
+
public readonly channelCount: number
|
|
30
|
+
public readonly sampleRateHz: number
|
|
31
|
+
public readonly chunkSize: number
|
|
32
|
+
public readonly maxBufferedMs = 360 * 1000
|
|
33
|
+
public readonly manufacturer: string = 'N/A'
|
|
34
|
+
public readonly units: string = 'N/A'
|
|
35
|
+
|
|
24
36
|
private info: StreamInfo
|
|
25
|
-
private options: StreamOutletOptions
|
|
26
37
|
private outlet!: BoundOutlet
|
|
27
38
|
private pushSampleMethod!: (options: unknown) => LslErrorCode
|
|
28
39
|
|
|
29
40
|
protected constructor(info: StreamInfo, options: StreamOutletOptions) {
|
|
41
|
+
const {
|
|
42
|
+
name,
|
|
43
|
+
type,
|
|
44
|
+
sourceId,
|
|
45
|
+
channelNames,
|
|
46
|
+
channelFormat,
|
|
47
|
+
sampleRateHz,
|
|
48
|
+
chunkSize,
|
|
49
|
+
maxBufferedMs,
|
|
50
|
+
manufacturer,
|
|
51
|
+
units,
|
|
52
|
+
} = options
|
|
53
|
+
|
|
30
54
|
this.info = info
|
|
31
|
-
this.
|
|
55
|
+
this.name = name
|
|
56
|
+
this.type = type
|
|
57
|
+
this.sourceId = sourceId
|
|
58
|
+
this.channelNames = channelNames
|
|
59
|
+
this.channelFormat = channelFormat
|
|
60
|
+
this.channelCount = channelNames.length
|
|
61
|
+
this.sampleRateHz = sampleRateHz
|
|
62
|
+
this.chunkSize = chunkSize
|
|
63
|
+
this.maxBufferedMs = maxBufferedMs ?? this.maxBufferedMs
|
|
64
|
+
this.manufacturer = manufacturer ?? this.manufacturer
|
|
65
|
+
this.units = units ?? this.units
|
|
32
66
|
|
|
33
67
|
this.validateOptions()
|
|
34
68
|
this.createStreamOutlet()
|
|
@@ -38,20 +72,10 @@ export default class LslStreamOutlet implements StreamOutlet {
|
|
|
38
72
|
public static async Create(options: StreamOutletOptions) {
|
|
39
73
|
const { waitAfterConstructionMs = 10 } = options ?? {}
|
|
40
74
|
|
|
41
|
-
const
|
|
42
|
-
channelNames: options.channelNames,
|
|
43
|
-
channelFormat: options.channelFormat,
|
|
44
|
-
sampleRateHz: options.sampleRateHz,
|
|
45
|
-
name: options.name,
|
|
46
|
-
type: options.type,
|
|
47
|
-
sourceId: options.sourceId,
|
|
48
|
-
units: options.units,
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const info = this.LslStreamInfo(infoOptions)
|
|
75
|
+
const info = this.LslStreamInfo(options)
|
|
52
76
|
const instance = new (this.Class ?? this)(info, options)
|
|
53
77
|
|
|
54
|
-
await this.
|
|
78
|
+
await this.waitToAllowSetup(waitAfterConstructionMs)
|
|
55
79
|
|
|
56
80
|
return instance
|
|
57
81
|
}
|
|
@@ -62,6 +86,23 @@ export default class LslStreamOutlet implements StreamOutlet {
|
|
|
62
86
|
assertValidChannelFormat(this.channelFormat)
|
|
63
87
|
assertValidChunkSize(this.chunkSize)
|
|
64
88
|
assertValidMaxBufferedMs(this.maxBufferedMs)
|
|
89
|
+
this.validateChannelFormat()
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
private validateChannelFormat() {
|
|
93
|
+
if (!this.isChannelFormatSupported) {
|
|
94
|
+
this.throwUnsupportedChannelFormat()
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
private get isChannelFormatSupported() {
|
|
99
|
+
return this.channelFormat in this.methodMap
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
private throwUnsupportedChannelFormat() {
|
|
103
|
+
throw new Error(
|
|
104
|
+
`This method currently does not support the ${this.channelFormat} type! Please implement it.`
|
|
105
|
+
)
|
|
65
106
|
}
|
|
66
107
|
|
|
67
108
|
private createStreamOutlet() {
|
|
@@ -72,28 +113,16 @@ export default class LslStreamOutlet implements StreamOutlet {
|
|
|
72
113
|
})
|
|
73
114
|
}
|
|
74
115
|
|
|
75
|
-
private
|
|
76
|
-
this.
|
|
116
|
+
private get boundStreamInfo() {
|
|
117
|
+
return this.info.boundStreamInfo
|
|
118
|
+
}
|
|
77
119
|
|
|
120
|
+
private setPushSampleMethod() {
|
|
78
121
|
this.pushSampleMethod = (
|
|
79
122
|
this.lsl[this.pushMethod] as (options: unknown) => LslErrorCode
|
|
80
123
|
).bind(this.lsl)
|
|
81
124
|
}
|
|
82
125
|
|
|
83
|
-
private validateChannelFormat() {
|
|
84
|
-
if (!(this.channelFormat in this.methodMap)) {
|
|
85
|
-
this.throwUnsupportedChannelFormat()
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
private throwUnsupportedChannelFormat() {
|
|
90
|
-
throw new Error(this.unsupportedChannelMessage)
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
private get unsupportedChannelMessage() {
|
|
94
|
-
return `This method currently does not support the ${this.channelFormat} type! Please implement it.`
|
|
95
|
-
}
|
|
96
|
-
|
|
97
126
|
private get pushMethod() {
|
|
98
127
|
return this.methodMap[this.channelFormat]
|
|
99
128
|
}
|
|
@@ -106,77 +135,57 @@ export default class LslStreamOutlet implements StreamOutlet {
|
|
|
106
135
|
public pushSample(sample: LslSample) {
|
|
107
136
|
const timestamp = this.lsl.localClock()
|
|
108
137
|
|
|
109
|
-
|
|
110
|
-
this.
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
)
|
|
138
|
+
const err = this.pushSampleMethod({
|
|
139
|
+
outlet: this.outlet,
|
|
140
|
+
sample,
|
|
141
|
+
timestamp,
|
|
142
|
+
})
|
|
143
|
+
handleError(err)
|
|
116
144
|
}
|
|
117
145
|
|
|
118
146
|
public destroy() {
|
|
119
|
-
this.
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
public get name() {
|
|
123
|
-
return this.options.name
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
public get type() {
|
|
127
|
-
return this.options.type
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
public get sourceId() {
|
|
131
|
-
return this.options.sourceId
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
public get channelNames() {
|
|
135
|
-
return this.options.channelNames
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
public get channelCount() {
|
|
139
|
-
return this.channelNames.length
|
|
147
|
+
this.destroyBoundStreamInfo()
|
|
148
|
+
this.destroyBoundOutlet()
|
|
140
149
|
}
|
|
141
150
|
|
|
142
|
-
|
|
143
|
-
|
|
151
|
+
private destroyBoundStreamInfo() {
|
|
152
|
+
this.lsl.destroyStreamInfo({ info: this.boundStreamInfo })
|
|
144
153
|
}
|
|
145
154
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
public get chunkSize() {
|
|
151
|
-
return this.options.chunkSize
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
public get maxBufferedMs() {
|
|
155
|
-
return this.options.maxBufferedMs ?? 360 * 1000
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
public get manufacturer() {
|
|
159
|
-
return this.options.manufacturer ?? 'N/A'
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
public get units() {
|
|
163
|
-
return this.options.units ?? 'N/A'
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
private get boundStreamInfo() {
|
|
167
|
-
return this.info.boundStreamInfo
|
|
155
|
+
private destroyBoundOutlet() {
|
|
156
|
+
this.lsl.destroyOutlet({ outlet: this.outlet })
|
|
168
157
|
}
|
|
169
158
|
|
|
170
159
|
private get lsl() {
|
|
171
160
|
return LiblslAdapter.getInstance()
|
|
172
161
|
}
|
|
173
162
|
|
|
174
|
-
private static async
|
|
175
|
-
|
|
163
|
+
private static async waitToAllowSetup(waitAfterConstructionMs: number) {
|
|
164
|
+
await new Promise((resolve) =>
|
|
165
|
+
setTimeout(resolve, waitAfterConstructionMs)
|
|
166
|
+
)
|
|
176
167
|
}
|
|
177
168
|
|
|
178
169
|
private static LslStreamInfo(options: StreamInfoOptions) {
|
|
179
|
-
|
|
170
|
+
const {
|
|
171
|
+
channelNames,
|
|
172
|
+
channelFormat,
|
|
173
|
+
sampleRateHz,
|
|
174
|
+
name,
|
|
175
|
+
type,
|
|
176
|
+
sourceId,
|
|
177
|
+
units,
|
|
178
|
+
} = options
|
|
179
|
+
|
|
180
|
+
return LslStreamInfo.Create({
|
|
181
|
+
name,
|
|
182
|
+
type,
|
|
183
|
+
sourceId,
|
|
184
|
+
channelNames,
|
|
185
|
+
channelFormat,
|
|
186
|
+
sampleRateHz,
|
|
187
|
+
units,
|
|
188
|
+
})
|
|
180
189
|
}
|
|
181
190
|
}
|
|
182
191
|
|
|
@@ -51,12 +51,12 @@ export default class LslWebSocketBridge implements WebSocketBridge {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
public destroy() {
|
|
54
|
-
this.
|
|
54
|
+
this.destroyBoundInlet()
|
|
55
55
|
this.closeWebSocketServer()
|
|
56
56
|
this.isDestroyed = true
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
private
|
|
59
|
+
private destroyBoundInlet() {
|
|
60
60
|
this.inlet.destroy()
|
|
61
61
|
}
|
|
62
62
|
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
FlushInletOptions,
|
|
16
16
|
PullChunkOptions,
|
|
17
17
|
PullSampleOptions,
|
|
18
|
+
DestroyStreamInfoOptions,
|
|
18
19
|
} from 'impl/LiblslAdapter.js'
|
|
19
20
|
|
|
20
21
|
export default class FakeLiblsl implements Liblsl {
|
|
@@ -45,6 +46,7 @@ export default class FakeLiblsl implements Liblsl {
|
|
|
45
46
|
public streamInfo: BoundStreamInfo = {} as BoundStreamInfo
|
|
46
47
|
|
|
47
48
|
public lastCreateStreamInfoOptions?: CreateStreamInfoOptions
|
|
49
|
+
public lastDestroyStreamInfoOptions?: DestroyStreamInfoOptions
|
|
48
50
|
public lastAppendChannelsToStreamInfoOptions?: AppendChannelsToStreamInfoOptions
|
|
49
51
|
public lastCreateOutletOptions?: CreateOutletOptions
|
|
50
52
|
public lastPushSampleFloatTimestampOptions?: PushSampleFloatTimestampOptions
|
|
@@ -70,6 +72,10 @@ export default class FakeLiblsl implements Liblsl {
|
|
|
70
72
|
return this.streamInfo
|
|
71
73
|
}
|
|
72
74
|
|
|
75
|
+
public destroyStreamInfo(options: DestroyStreamInfoOptions) {
|
|
76
|
+
this.lastDestroyStreamInfoOptions = options
|
|
77
|
+
}
|
|
78
|
+
|
|
73
79
|
public appendChannelsToStreamInfo(
|
|
74
80
|
options: AppendChannelsToStreamInfoOptions
|
|
75
81
|
) {
|