@neurodevs/node-lsl 14.0.1 → 14.1.1

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.
Files changed (57) hide show
  1. package/build/__tests__/impl/LiblslAdapter.test.d.ts +7 -5
  2. package/build/__tests__/impl/LiblslAdapter.test.js +27 -10
  3. package/build/__tests__/impl/LiblslAdapter.test.js.map +1 -1
  4. package/build/__tests__/impl/LslEventMarkerOutlet.test.d.ts +1 -0
  5. package/build/__tests__/impl/LslEventMarkerOutlet.test.js +7 -0
  6. package/build/__tests__/impl/LslEventMarkerOutlet.test.js.map +1 -1
  7. package/build/__tests__/impl/LslStreamInfo.test.d.ts +1 -0
  8. package/build/__tests__/impl/LslStreamInfo.test.js +8 -1
  9. package/build/__tests__/impl/LslStreamInfo.test.js.map +1 -1
  10. package/build/__tests__/impl/LslStreamInlet.test.d.ts +1 -0
  11. package/build/__tests__/impl/LslStreamInlet.test.js +8 -1
  12. package/build/__tests__/impl/LslStreamInlet.test.js.map +1 -1
  13. package/build/__tests__/impl/LslStreamOutlet.test.d.ts +1 -0
  14. package/build/__tests__/impl/LslStreamOutlet.test.js +8 -0
  15. package/build/__tests__/impl/LslStreamOutlet.test.js.map +1 -1
  16. package/build/impl/LiblslAdapter.d.ts +8 -2
  17. package/build/impl/LiblslAdapter.js +10 -1
  18. package/build/impl/LiblslAdapter.js.map +1 -1
  19. package/build/impl/LslEventMarkerOutlet.d.ts +2 -0
  20. package/build/impl/LslEventMarkerOutlet.js +3 -0
  21. package/build/impl/LslEventMarkerOutlet.js.map +1 -1
  22. package/build/impl/LslStreamInfo.d.ts +12 -10
  23. package/build/impl/LslStreamInfo.js +18 -17
  24. package/build/impl/LslStreamInfo.js.map +1 -1
  25. package/build/impl/LslStreamInlet.d.ts +3 -1
  26. package/build/impl/LslStreamInlet.js +12 -6
  27. package/build/impl/LslStreamInlet.js.map +1 -1
  28. package/build/impl/LslStreamOutlet.d.ts +3 -1
  29. package/build/impl/LslStreamOutlet.js +8 -3
  30. package/build/impl/LslStreamOutlet.js.map +1 -1
  31. package/build/impl/LslWebSocketBridge.d.ts +1 -1
  32. package/build/impl/LslWebSocketBridge.js +2 -2
  33. package/build/impl/LslWebSocketBridge.js.map +1 -1
  34. package/build/testDoubles/Liblsl/FakeLiblsl.d.ts +3 -1
  35. package/build/testDoubles/Liblsl/FakeLiblsl.js +4 -0
  36. package/build/testDoubles/Liblsl/FakeLiblsl.js.map +1 -1
  37. package/build/testDoubles/StreamInfo/FakeStreamInfo.d.ts +2 -0
  38. package/build/testDoubles/StreamInfo/FakeStreamInfo.js +5 -0
  39. package/build/testDoubles/StreamInfo/FakeStreamInfo.js.map +1 -1
  40. package/build/testDoubles/StreamInfo/SpyStreamInfo.d.ts +1 -1
  41. package/build/testDoubles/StreamInfo/SpyStreamInfo.js +2 -2
  42. package/build/testDoubles/StreamInfo/SpyStreamInfo.js.map +1 -1
  43. package/package.json +1 -1
  44. package/src/__tests__/impl/LiblslAdapter.test.ts +27 -5
  45. package/src/__tests__/impl/LslEventMarkerOutlet.test.ts +11 -0
  46. package/src/__tests__/impl/LslStreamInfo.test.ts +12 -1
  47. package/src/__tests__/impl/LslStreamInlet.test.ts +12 -1
  48. package/src/__tests__/impl/LslStreamOutlet.test.ts +12 -0
  49. package/src/impl/LiblslAdapter.ts +20 -4
  50. package/src/impl/LslEventMarkerOutlet.ts +5 -0
  51. package/src/impl/LslStreamInfo.ts +24 -21
  52. package/src/impl/LslStreamInlet.ts +15 -8
  53. package/src/impl/LslStreamOutlet.ts +10 -3
  54. package/src/impl/LslWebSocketBridge.ts +2 -2
  55. package/src/testDoubles/Liblsl/FakeLiblsl.ts +6 -0
  56. package/src/testDoubles/StreamInfo/FakeStreamInfo.ts +7 -0
  57. package/src/testDoubles/StreamInfo/SpyStreamInfo.ts +2 -2
@@ -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
- sourceId,
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
- sourceId: string
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,18 @@ export default class LslStreamInfo implements StreamInfo {
11
11
  protected type: string
12
12
  protected sourceId: string
13
13
  protected units: string
14
- protected streamInfo!: BoundStreamInfo
14
+ protected boundInfo!: BoundStreamInfo
15
15
  private channelNames: string[]
16
16
  private channelFormat: ChannelFormat
17
17
  private sampleRateHz: number
18
18
 
19
+ private lsl = LiblslAdapter.getInstance()
20
+
21
+ private readonly defaultName = `lsl-stream-info-${generateId()}`
22
+ private readonly defaultType = generateId()
23
+ private readonly defaultSourceId = generateId()
24
+ private readonly defaultUnits = 'N/A'
25
+
19
26
  protected constructor(options: StreamInfoOptions) {
20
27
  const {
21
28
  name = this.defaultName,
@@ -44,7 +51,7 @@ export default class LslStreamInfo implements StreamInfo {
44
51
  }
45
52
 
46
53
  private createStreamInfo() {
47
- this.streamInfo = this.lsl.createStreamInfo({
54
+ this.boundInfo = this.lsl.createStreamInfo({
48
55
  name: this.name,
49
56
  type: this.type,
50
57
  sourceId: this.sourceId,
@@ -54,9 +61,17 @@ export default class LslStreamInfo implements StreamInfo {
54
61
  })
55
62
  }
56
63
 
64
+ private get channelCount() {
65
+ return this.channelNames.length
66
+ }
67
+
68
+ private get lslChannelFormat() {
69
+ return CHANNEL_FORMATS_MAP[this.channelFormat]
70
+ }
71
+
57
72
  private appendChannelsToStreamInfo() {
58
73
  this.lsl.appendChannelsToStreamInfo({
59
- info: this.streamInfo,
74
+ info: this.boundInfo,
60
75
  channels: this.channelNames.map((label: string) => ({
61
76
  label,
62
77
  units: this.units,
@@ -65,30 +80,18 @@ export default class LslStreamInfo implements StreamInfo {
65
80
  })
66
81
  }
67
82
 
68
- public get boundStreamInfo() {
69
- return this.streamInfo
83
+ public destroy() {
84
+ this.lsl.destroyStreamInfo({ info: this.boundInfo })
70
85
  }
71
86
 
72
- private get channelCount() {
73
- return this.channelNames.length
74
- }
75
-
76
- private get lslChannelFormat() {
77
- return CHANNEL_FORMATS_MAP[this.channelFormat]
78
- }
79
-
80
- private get lsl() {
81
- return LiblslAdapter.getInstance()
87
+ public get boundStreamInfo() {
88
+ return this.boundInfo
82
89
  }
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
90
  }
89
91
 
90
92
  export interface StreamInfo {
91
- boundStreamInfo: BoundStreamInfo
93
+ destroy(): void
94
+ readonly boundStreamInfo: BoundStreamInfo
92
95
  }
93
96
 
94
97
  type StreamInfoConstructor = new (options: StreamInfoOptions) => StreamInfo
@@ -2,7 +2,7 @@ import generateId from '@neurodevs/generate-id'
2
2
  import { createPointer, DataType, JsExternal, unwrapPointer } from 'ffi-rs'
3
3
 
4
4
  import handleError from '../handleError.js'
5
- import { BoundInlet, ChannelFormat, Liblsl } from './LiblslAdapter.js'
5
+ import { BoundInlet, ChannelFormat } from './LiblslAdapter.js'
6
6
  import LiblslAdapter from './LiblslAdapter.js'
7
7
  import LslStreamInfo, {
8
8
  StreamInfo,
@@ -29,7 +29,7 @@ export default class LslStreamInlet implements StreamInlet {
29
29
  timestamps: Float64Array | undefined
30
30
  }
31
31
 
32
- private lsl: Liblsl
32
+ private lsl = LiblslAdapter.getInstance()
33
33
 
34
34
  protected inlet!: BoundInlet
35
35
 
@@ -74,8 +74,6 @@ export default class LslStreamInlet implements StreamInlet {
74
74
  this.pullDataMethod = this.pullChunk
75
75
  }
76
76
 
77
- this.lsl = this.getLiblslSingleton()
78
-
79
77
  this.createBoundInlet()
80
78
  }
81
79
 
@@ -88,12 +86,16 @@ export default class LslStreamInlet implements StreamInlet {
88
86
 
89
87
  private createBoundInlet() {
90
88
  this.inlet = this.lsl.createInlet({
91
- info: this.info.boundStreamInfo,
89
+ info: this.boundStreamInfo,
92
90
  chunkSize: this.chunkSize,
93
91
  maxBufferedMs: this.maxBufferedMs / 1000,
94
92
  })
95
93
  }
96
94
 
95
+ private get boundStreamInfo() {
96
+ return this.info.boundStreamInfo
97
+ }
98
+
97
99
  public startPulling() {
98
100
  this.isRunning = true
99
101
 
@@ -250,11 +252,16 @@ export default class LslStreamInlet implements StreamInlet {
250
252
  }
251
253
 
252
254
  public destroy() {
253
- this.lsl.destroyInlet({ inlet: this.inlet })
255
+ this.destroyBoundStreamInfo()
256
+ this.destroyBoundInlet()
254
257
  }
255
258
 
256
- private getLiblslSingleton() {
257
- return LiblslAdapter.getInstance()
259
+ private destroyBoundStreamInfo() {
260
+ this.lsl.destroyStreamInfo({ info: this.boundStreamInfo })
261
+ }
262
+
263
+ private destroyBoundInlet() {
264
+ this.lsl.destroyInlet({ inlet: this.inlet })
258
265
  }
259
266
 
260
267
  private static LslStreamInfo(options: StreamInfoOptions) {
@@ -37,6 +37,8 @@ export default class LslStreamOutlet implements StreamOutlet {
37
37
  private outlet!: BoundOutlet
38
38
  private pushSampleMethod!: (options: unknown) => LslErrorCode
39
39
 
40
+ private lsl = LiblslAdapter.getInstance()
41
+
40
42
  protected constructor(info: StreamInfo, options: StreamOutletOptions) {
41
43
  const {
42
44
  name,
@@ -144,11 +146,16 @@ export default class LslStreamOutlet implements StreamOutlet {
144
146
  }
145
147
 
146
148
  public destroy() {
147
- this.lsl.destroyOutlet({ outlet: this.outlet })
149
+ this.destroyBoundStreamInfo()
150
+ this.destroyBoundOutlet()
148
151
  }
149
152
 
150
- private get lsl() {
151
- return LiblslAdapter.getInstance()
153
+ private destroyBoundStreamInfo() {
154
+ this.lsl.destroyStreamInfo({ info: this.boundStreamInfo })
155
+ }
156
+
157
+ private destroyBoundOutlet() {
158
+ this.lsl.destroyOutlet({ outlet: this.outlet })
152
159
  }
153
160
 
154
161
  private static async waitToAllowSetup(waitAfterConstructionMs: number) {
@@ -51,12 +51,12 @@ export default class LslWebSocketBridge implements WebSocketBridge {
51
51
  }
52
52
 
53
53
  public destroy() {
54
- this.destroyCppBoundInlet()
54
+ this.destroyBoundInlet()
55
55
  this.closeWebSocketServer()
56
56
  this.isDestroyed = true
57
57
  }
58
58
 
59
- private destroyCppBoundInlet() {
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
  ) {
@@ -3,17 +3,24 @@ import { StreamInfo, StreamInfoOptions } from '../../impl/LslStreamInfo.js'
3
3
 
4
4
  export default class FakeStreamInfo implements StreamInfo {
5
5
  public static callsToConstructor: StreamInfoOptions[] = []
6
+ public static numCallsToDestroy = 0
7
+
6
8
  public static boundStreamInfo = {} as BoundStreamInfo
7
9
 
8
10
  public constructor(options: StreamInfoOptions) {
9
11
  FakeStreamInfo.callsToConstructor.push(options)
10
12
  }
11
13
 
14
+ public destroy() {
15
+ FakeStreamInfo.numCallsToDestroy++
16
+ }
17
+
12
18
  public get boundStreamInfo() {
13
19
  return FakeStreamInfo.boundStreamInfo
14
20
  }
15
21
 
16
22
  public static resetTestDouble() {
17
23
  FakeStreamInfo.callsToConstructor = []
24
+ FakeStreamInfo.numCallsToDestroy = 0
18
25
  }
19
26
  }
@@ -5,8 +5,8 @@ export default class SpyStreamInfo extends LslStreamInfo {
5
5
  super(options)
6
6
  }
7
7
 
8
- public getStreamInfo() {
9
- return this.streamInfo
8
+ public getBoundInfo() {
9
+ return this.boundInfo
10
10
  }
11
11
 
12
12
  public getName() {