@neurodevs/node-lsl 17.1.1 → 18.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/.claude/settings.local.json +10 -0
- package/.vscode/launch.json +54 -57
- package/.vscode/settings.json +61 -66
- package/.vscode/tasks.json +98 -129
- package/README.md +20 -44
- package/build/__tests__/AbstractPackageTest.d.ts +7 -5
- package/build/__tests__/AbstractPackageTest.js +22 -15
- package/build/__tests__/AbstractPackageTest.js.map +1 -1
- package/build/__tests__/impl/BleDeviceController.test.d.ts +54 -0
- package/build/__tests__/impl/BleDeviceController.test.js +333 -0
- package/build/__tests__/impl/BleDeviceController.test.js.map +1 -0
- package/build/__tests__/impl/LslEventMarkerEmitter.test.d.ts +34 -0
- package/build/__tests__/impl/LslEventMarkerEmitter.test.js +243 -0
- package/build/__tests__/impl/LslEventMarkerEmitter.test.js.map +1 -0
- package/build/__tests__/impl/LslStreamInfo.test.d.ts +0 -3
- package/build/__tests__/impl/LslStreamInfo.test.js +2 -27
- package/build/__tests__/impl/LslStreamInfo.test.js.map +1 -1
- package/build/__tests__/impl/LslStreamInlet.test.d.ts +20 -8
- package/build/__tests__/impl/LslStreamInlet.test.js +224 -69
- package/build/__tests__/impl/LslStreamInlet.test.js.map +1 -1
- package/build/__tests__/impl/LslStreamOutlet.test.d.ts +3 -7
- package/build/__tests__/impl/LslStreamOutlet.test.js +40 -50
- package/build/__tests__/impl/LslStreamOutlet.test.js.map +1 -1
- package/build/__tests__/impl/LslWebSocketBridge.test.js +19 -20
- package/build/__tests__/impl/LslWebSocketBridge.test.js.map +1 -1
- package/build/assertions.d.ts +1 -1
- package/build/assertions.js.map +1 -1
- package/build/impl/LslEventMarkerEmitter.d.ts +35 -0
- package/build/impl/LslEventMarkerEmitter.js +86 -0
- package/build/impl/LslEventMarkerEmitter.js.map +1 -0
- package/build/impl/LslStreamInfo.d.ts +4 -8
- package/build/impl/LslStreamInfo.js +8 -21
- package/build/impl/LslStreamInfo.js.map +1 -1
- package/build/impl/LslStreamInlet.d.ts +31 -50
- package/build/impl/LslStreamInlet.js +79 -149
- package/build/impl/LslStreamInlet.js.map +1 -1
- package/build/impl/LslStreamOutlet.d.ts +15 -18
- package/build/impl/LslStreamOutlet.js +39 -47
- package/build/impl/LslStreamOutlet.js.map +1 -1
- package/build/impl/LslWebSocketBridge.d.ts +4 -5
- package/build/impl/LslWebSocketBridge.js +10 -10
- package/build/impl/LslWebSocketBridge.js.map +1 -1
- package/build/impl/controllers/BleDeviceController.d.ts +58 -0
- package/build/impl/controllers/BleDeviceController.js +145 -0
- package/build/impl/controllers/BleDeviceController.js.map +1 -0
- package/build/impl/workers/inlet/LslStreamInlet.worker.d.ts +22 -0
- package/build/impl/workers/inlet/LslStreamInlet.worker.js +42 -0
- package/build/impl/workers/inlet/LslStreamInlet.worker.js.map +1 -0
- package/build/impl/workers/inlet/StreamInletWorker.d.ts +73 -0
- package/build/impl/workers/inlet/StreamInletWorker.js +253 -0
- package/build/impl/workers/inlet/StreamInletWorker.js.map +1 -0
- package/build/impl/workers/outlet/LslStreamOutlet.worker.d.ts +32 -0
- package/build/impl/workers/outlet/LslStreamOutlet.worker.js +82 -0
- package/build/impl/workers/outlet/LslStreamOutlet.worker.js.map +1 -0
- package/build/index.d.ts +14 -14
- package/build/index.js +16 -16
- package/build/index.js.map +1 -1
- package/build/scripts/discoverMuse.js +40 -0
- package/build/scripts/discoverMuse.js.map +1 -0
- package/build/scripts/finalizeHandles.d.ts +2 -0
- package/build/scripts/finalizeHandles.js +48 -0
- package/build/scripts/finalizeHandles.js.map +1 -0
- package/build/scripts/runLslEventMarkerEmitter.d.ts +1 -0
- package/build/scripts/runLslEventMarkerEmitter.js +11 -0
- package/build/scripts/runLslEventMarkerEmitter.js.map +1 -0
- package/build/scripts/runMuse.d.ts +1 -0
- package/build/scripts/runMuse.js +40 -0
- package/build/scripts/runMuse.js.map +1 -0
- package/build/scripts/runOutletToInlet.js +7 -6
- package/build/scripts/runOutletToInlet.js.map +1 -1
- package/build/scripts/testDestroyOutlet.d.ts +1 -0
- package/build/scripts/testDestroyOutlet.js +4 -0
- package/build/scripts/testDestroyOutlet.js.map +1 -0
- package/build/testDoubles/BleController/FakeBleController.d.ts +24 -0
- package/build/testDoubles/BleController/FakeBleController.js +42 -0
- package/build/testDoubles/BleController/FakeBleController.js.map +1 -0
- package/build/testDoubles/BleController/SpyBleController.d.ts +14 -0
- package/build/testDoubles/BleController/SpyBleController.js +48 -0
- package/build/testDoubles/BleController/SpyBleController.js.map +1 -0
- package/build/testDoubles/EventMarkerEmitter/FakeEventMarkerEmitter.d.ts +17 -0
- package/build/testDoubles/EventMarkerEmitter/FakeEventMarkerEmitter.js +30 -0
- package/build/testDoubles/EventMarkerEmitter/FakeEventMarkerEmitter.js.map +1 -0
- package/build/testDoubles/EventMarkerEmitter/SpyEventMarkerEmitter.d.ts +10 -0
- package/build/testDoubles/EventMarkerEmitter/SpyEventMarkerEmitter.js +23 -0
- package/build/testDoubles/EventMarkerEmitter/SpyEventMarkerEmitter.js.map +1 -0
- package/build/testDoubles/EventMarkerEmitter/ThrowingEventMarkerEmitter.d.ts +9 -0
- package/build/testDoubles/EventMarkerEmitter/ThrowingEventMarkerEmitter.js +19 -0
- package/build/testDoubles/EventMarkerEmitter/ThrowingEventMarkerEmitter.js.map +1 -0
- package/build/testDoubles/StreamInfo/FakeStreamInfo.d.ts +3 -3
- package/build/testDoubles/StreamInfo/FakeStreamInfo.js +3 -3
- package/build/testDoubles/StreamInfo/FakeStreamInfo.js.map +1 -1
- package/build/testDoubles/StreamInlet/FakeStreamInlet.d.ts +8 -10
- package/build/testDoubles/StreamInlet/FakeStreamInlet.js +6 -7
- package/build/testDoubles/StreamInlet/FakeStreamInlet.js.map +1 -1
- package/build/testDoubles/StreamInlet/SpyStreamInlet.d.ts +2 -5
- package/build/testDoubles/StreamInlet/SpyStreamInlet.js +2 -8
- package/build/testDoubles/StreamInlet/SpyStreamInlet.js.map +1 -1
- package/build/testDoubles/StreamOutlet/FakeStreamOutlet.d.ts +7 -9
- package/build/testDoubles/StreamOutlet/FakeStreamOutlet.js +8 -8
- package/build/testDoubles/StreamOutlet/FakeStreamOutlet.js.map +1 -1
- package/build/testDoubles/WebSocketBridge/FakeWebSocketBridge.d.ts +1 -1
- package/build/testDoubles/WebSocketBridge/FakeWebSocketBridge.js +1 -1
- package/build/testDoubles/WebSocketBridge/FakeWebSocketBridge.js.map +1 -1
- package/build/testDoubles/WorkerThreads/FakeWorker.d.ts +27 -0
- package/build/testDoubles/WorkerThreads/FakeWorker.js +67 -0
- package/build/testDoubles/WorkerThreads/FakeWorker.js.map +1 -0
- package/build/testDoubles/generateRandomOutletOptions.js +1 -1
- package/build/testDoubles/generateRandomOutletOptions.js.map +1 -1
- package/build/validations.js +0 -2
- package/build/validations.js.map +1 -1
- package/eslint.config.js +3 -0
- package/package.json +27 -49
- package/prettier.config.js +3 -0
- package/src/__tests__/AbstractPackageTest.ts +38 -21
- package/src/__tests__/impl/BleDeviceController.test.ts +492 -0
- package/src/__tests__/impl/LslEventMarkerEmitter.test.ts +323 -0
- package/src/__tests__/impl/LslStreamInfo.test.ts +3 -40
- package/src/__tests__/impl/LslStreamInlet.test.ts +344 -97
- package/src/__tests__/impl/LslStreamOutlet.test.ts +65 -73
- package/src/__tests__/impl/LslWebSocketBridge.test.ts +22 -21
- package/src/assertions.ts +2 -1
- package/src/impl/LslEventMarkerEmitter.ts +133 -0
- package/src/impl/LslStreamInfo.ts +17 -29
- package/src/impl/LslStreamInlet.ts +102 -215
- package/src/impl/LslStreamOutlet.ts +54 -78
- package/src/impl/LslWebSocketBridge.ts +14 -14
- package/src/impl/controllers/BleDeviceController.ts +223 -0
- package/src/impl/workers/inlet/LslStreamInlet.worker.ts +74 -0
- package/src/impl/workers/inlet/StreamInletWorker.ts +348 -0
- package/src/impl/workers/outlet/LslStreamOutlet.worker.ts +144 -0
- package/src/index.ts +16 -16
- package/src/scripts/discoverMuse.ts +50 -0
- package/src/scripts/finalizeHandles.ts +63 -0
- package/src/scripts/runLslEventMarkerEmitter.ts +15 -0
- package/src/scripts/runMuse.ts +50 -0
- package/src/scripts/runOutletToInlet.ts +10 -8
- package/src/scripts/testDestroyOutlet.ts +5 -0
- package/src/testDoubles/BleController/FakeBleController.ts +70 -0
- package/src/testDoubles/BleController/SpyBleController.ts +61 -0
- package/src/testDoubles/EventMarkerEmitter/FakeEventMarkerEmitter.ts +46 -0
- package/src/testDoubles/EventMarkerEmitter/SpyEventMarkerEmitter.ts +31 -0
- package/src/testDoubles/EventMarkerEmitter/ThrowingEventMarkerEmitter.ts +29 -0
- package/src/testDoubles/StreamInfo/FakeStreamInfo.ts +4 -4
- package/src/testDoubles/StreamInlet/FakeStreamInlet.ts +11 -17
- package/src/testDoubles/StreamInlet/SpyStreamInlet.ts +3 -16
- package/src/testDoubles/StreamOutlet/FakeStreamOutlet.ts +15 -15
- package/src/testDoubles/WebSocketBridge/FakeWebSocketBridge.ts +1 -1
- package/src/testDoubles/WorkerThreads/FakeWorker.ts +99 -0
- package/src/testDoubles/generateRandomOutletOptions.ts +2 -1
- package/src/validations.ts +0 -2
- package/tsconfig.json +23 -27
- package/build/.spruce/settings.json +0 -11
- package/build/__tests__/impl/LiblslAdapter.test.d.ts +0 -79
- package/build/__tests__/impl/LiblslAdapter.test.js +0 -688
- package/build/__tests__/impl/LiblslAdapter.test.js.map +0 -1
- package/build/__tests__/impl/LslEventMarkerOutlet.test.d.ts +0 -21
- package/build/__tests__/impl/LslEventMarkerOutlet.test.js +0 -160
- package/build/__tests__/impl/LslEventMarkerOutlet.test.js.map +0 -1
- package/build/handleError.d.ts +0 -8
- package/build/handleError.js +0 -25
- package/build/handleError.js.map +0 -1
- package/build/impl/LiblslAdapter.d.ts +0 -154
- package/build/impl/LiblslAdapter.js +0 -317
- package/build/impl/LiblslAdapter.js.map +0 -1
- package/build/impl/LslEventMarkerOutlet.d.ts +0 -28
- package/build/impl/LslEventMarkerOutlet.js +0 -63
- package/build/impl/LslEventMarkerOutlet.js.map +0 -1
- package/build/scripts/runLslEventMarkerOutlet.js +0 -18
- package/build/scripts/runLslEventMarkerOutlet.js.map +0 -1
- package/build/testDoubles/EventMarkerOutlet/FakeEventMarkerOutlet.d.ts +0 -13
- package/build/testDoubles/EventMarkerOutlet/FakeEventMarkerOutlet.js +0 -26
- package/build/testDoubles/EventMarkerOutlet/FakeEventMarkerOutlet.js.map +0 -1
- package/build/testDoubles/EventMarkerOutlet/MockEventMarkerOutlet.d.ts +0 -17
- package/build/testDoubles/EventMarkerOutlet/MockEventMarkerOutlet.js +0 -46
- package/build/testDoubles/EventMarkerOutlet/MockEventMarkerOutlet.js.map +0 -1
- package/build/testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.d.ts +0 -9
- package/build/testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.js +0 -19
- package/build/testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.js.map +0 -1
- package/build/testDoubles/EventMarkerOutlet/ThrowingEventMarkerOutlet.d.ts +0 -9
- package/build/testDoubles/EventMarkerOutlet/ThrowingEventMarkerOutlet.js +0 -19
- package/build/testDoubles/EventMarkerOutlet/ThrowingEventMarkerOutlet.js.map +0 -1
- package/build/testDoubles/Liblsl/FakeLiblsl.d.ts +0 -50
- package/build/testDoubles/Liblsl/FakeLiblsl.js +0 -126
- package/build/testDoubles/Liblsl/FakeLiblsl.js.map +0 -1
- package/eslint.config.mjs +0 -3
- package/src/.spruce/settings.json +0 -11
- package/src/__tests__/impl/LiblslAdapter.test.ts +0 -817
- package/src/__tests__/impl/LslEventMarkerOutlet.test.ts +0 -195
- package/src/handleError.ts +0 -24
- package/src/impl/LiblslAdapter.ts +0 -543
- package/src/impl/LslEventMarkerOutlet.ts +0 -97
- package/src/scripts/runLslEventMarkerOutlet.ts +0 -23
- package/src/testDoubles/EventMarkerOutlet/FakeEventMarkerOutlet.ts +0 -36
- package/src/testDoubles/EventMarkerOutlet/MockEventMarkerOutlet.ts +0 -75
- package/src/testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.ts +0 -24
- package/src/testDoubles/EventMarkerOutlet/ThrowingEventMarkerOutlet.ts +0 -28
- package/src/testDoubles/Liblsl/FakeLiblsl.ts +0 -182
- /package/build/scripts/{runLslEventMarkerOutlet.d.ts → discoverMuse.d.ts} +0 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { parentPort } from 'node:worker_threads'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
LiblslAdapter,
|
|
5
|
+
Liblsl,
|
|
6
|
+
OutletHandle,
|
|
7
|
+
handleLslError,
|
|
8
|
+
LslErrorCode,
|
|
9
|
+
} from '@neurodevs/ndx-native'
|
|
10
|
+
|
|
11
|
+
import LslStreamInfo, {
|
|
12
|
+
StreamInfo,
|
|
13
|
+
StreamInfoOptions,
|
|
14
|
+
} from '../../LslStreamInfo.js'
|
|
15
|
+
|
|
16
|
+
let lsl = LiblslAdapter.getInstance()
|
|
17
|
+
|
|
18
|
+
export function setOutletLiblslAdapter(adapter: Liblsl) {
|
|
19
|
+
LiblslAdapter.setInstance(adapter)
|
|
20
|
+
lsl = LiblslAdapter.getInstance()
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let handleLslErrorFn = handleLslError
|
|
24
|
+
|
|
25
|
+
export function setOutletHandleLslError(fn: typeof handleLslError) {
|
|
26
|
+
handleLslErrorFn = fn
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
let info: StreamInfo
|
|
30
|
+
let handle: OutletHandle
|
|
31
|
+
let pushMethod: (opts: unknown) => LslErrorCode
|
|
32
|
+
|
|
33
|
+
parentPort?.on('message', (msg: OutletMessage) => {
|
|
34
|
+
const { type } = msg
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
switch (type) {
|
|
38
|
+
case 'createOutlet': {
|
|
39
|
+
createOutlet(msg)
|
|
40
|
+
break
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
case 'pushSample': {
|
|
44
|
+
pushSample(msg)
|
|
45
|
+
break
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
case 'destroyOutlet': {
|
|
49
|
+
destroyOutlet()
|
|
50
|
+
break
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
} catch (err) {
|
|
54
|
+
parentPort?.postMessage({
|
|
55
|
+
type: 'error',
|
|
56
|
+
error: err instanceof Error ? err.message : String(err),
|
|
57
|
+
})
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
export function createOutlet(msg: {
|
|
62
|
+
type: 'createOutlet'
|
|
63
|
+
payload: CreateOutletPayload
|
|
64
|
+
}) {
|
|
65
|
+
const { payload } = msg
|
|
66
|
+
|
|
67
|
+
info = LslStreamInfo.Create(payload.infoOptions)
|
|
68
|
+
|
|
69
|
+
handle = lsl.createOutlet({
|
|
70
|
+
infoHandle: info.infoHandle,
|
|
71
|
+
chunkSize: payload.chunkSize,
|
|
72
|
+
maxBufferedMs: payload.maxBufferedMs,
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
pushMethod = (
|
|
76
|
+
lsl[payload.pushMethod] as (opts: unknown) => LslErrorCode
|
|
77
|
+
).bind(lsl)
|
|
78
|
+
|
|
79
|
+
parentPort?.postMessage({ type: 'ready' })
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function pushSample(msg: {
|
|
83
|
+
type: 'pushSample'
|
|
84
|
+
payload: PushSamplePayload
|
|
85
|
+
}) {
|
|
86
|
+
const { payload } = msg
|
|
87
|
+
const { sample, timestampSec = lsl.localClock() } = payload
|
|
88
|
+
|
|
89
|
+
if (!handle || !pushMethod) {
|
|
90
|
+
throw new Error('Outlet not initialized')
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const errorCode = pushMethod({
|
|
94
|
+
outletHandle: handle,
|
|
95
|
+
sample,
|
|
96
|
+
timestampSec,
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
try {
|
|
100
|
+
handleLslErrorFn(errorCode)
|
|
101
|
+
} catch {
|
|
102
|
+
parentPort?.postMessage({
|
|
103
|
+
type: 'error',
|
|
104
|
+
error: `Error pushing sample: ${LslErrorCode[errorCode]}`,
|
|
105
|
+
})
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function destroyOutlet() {
|
|
110
|
+
if (handle) {
|
|
111
|
+
lsl.destroyOutlet({ outletHandle: handle })
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (info) {
|
|
115
|
+
lsl.destroyStreamInfo({ infoHandle: info.infoHandle })
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
parentPort?.close()
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export type OutletMessage =
|
|
122
|
+
| {
|
|
123
|
+
type: 'createOutlet'
|
|
124
|
+
payload: CreateOutletPayload
|
|
125
|
+
}
|
|
126
|
+
| {
|
|
127
|
+
type: 'pushSample'
|
|
128
|
+
payload: PushSamplePayload
|
|
129
|
+
}
|
|
130
|
+
| {
|
|
131
|
+
type: 'destroyOutlet'
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export interface CreateOutletPayload {
|
|
135
|
+
infoOptions: StreamInfoOptions
|
|
136
|
+
chunkSize: number
|
|
137
|
+
maxBufferedMs: number
|
|
138
|
+
pushMethod: 'pushSampleFloatTimestamp' | 'pushSampleStringTimestamp'
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export interface PushSamplePayload {
|
|
142
|
+
sample: unknown
|
|
143
|
+
timestampSec?: number
|
|
144
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
//
|
|
1
|
+
// DeviceController
|
|
2
2
|
|
|
3
|
-
export { default as
|
|
4
|
-
export * from './impl/
|
|
3
|
+
export { default as BleDeviceController } from './impl/controllers/BleDeviceController.js'
|
|
4
|
+
export * from './impl/controllers/BleDeviceController.js'
|
|
5
5
|
|
|
6
|
-
export { default as
|
|
7
|
-
export * from './testDoubles/
|
|
6
|
+
export { default as FakeBleController } from './testDoubles/BleController/FakeBleController.js'
|
|
7
|
+
export * from './testDoubles/BleController/FakeBleController.js'
|
|
8
8
|
|
|
9
|
-
export { default as
|
|
10
|
-
export * from './testDoubles/
|
|
9
|
+
export { default as SpyBleController } from './testDoubles/BleController/SpyBleController.js'
|
|
10
|
+
export * from './testDoubles/BleController/SpyBleController.js'
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
export * from './testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.js'
|
|
12
|
+
// EventMarkerEmitter
|
|
14
13
|
|
|
15
|
-
export { default as
|
|
16
|
-
export * from './
|
|
14
|
+
export { default as LslEventMarkerEmitter } from './impl/LslEventMarkerEmitter.js'
|
|
15
|
+
export * from './impl/LslEventMarkerEmitter.js'
|
|
17
16
|
|
|
18
|
-
|
|
17
|
+
export { default as FakeEventMarkerEmitter } from './testDoubles/EventMarkerEmitter/FakeEventMarkerEmitter.js'
|
|
18
|
+
export * from './testDoubles/EventMarkerEmitter/FakeEventMarkerEmitter.js'
|
|
19
19
|
|
|
20
|
-
export { default as
|
|
21
|
-
export * from './
|
|
20
|
+
export { default as SpyEventMarkerEmitter } from './testDoubles/EventMarkerEmitter/SpyEventMarkerEmitter.js'
|
|
21
|
+
export * from './testDoubles/EventMarkerEmitter/SpyEventMarkerEmitter.js'
|
|
22
22
|
|
|
23
|
-
export { default as
|
|
24
|
-
export * from './testDoubles/
|
|
23
|
+
export { default as ThrowingEventMarkerEmitter } from './testDoubles/EventMarkerEmitter/ThrowingEventMarkerEmitter.js'
|
|
24
|
+
export * from './testDoubles/EventMarkerEmitter/ThrowingEventMarkerEmitter.js'
|
|
25
25
|
|
|
26
26
|
// StreamInfo
|
|
27
27
|
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import koffi from 'koffi'
|
|
2
|
+
|
|
3
|
+
import BleDeviceController from '../impl/controllers/BleDeviceController.js'
|
|
4
|
+
|
|
5
|
+
const MUSE_CHARACTERISTIC_UUIDS: Record<string, string> = {
|
|
6
|
+
CONTROL: '273E0001-4C4D-454D-96BE-F03BAC821358',
|
|
7
|
+
TELEMETRY: '273E000B-4C4D-454D-96BE-F03BAC821358',
|
|
8
|
+
GYROSCOPE: '273E0009-4C4D-454D-96BE-F03BAC821358',
|
|
9
|
+
ACCELEROMETER: '273E000A-4C4D-454D-96BE-F03BAC821358',
|
|
10
|
+
PPG_AMBIENT: '273E000F-4C4D-454D-96BE-F03BAC821358',
|
|
11
|
+
PPG_INFRARED: '273E0010-4C4D-454D-96BE-F03BAC821358',
|
|
12
|
+
PPG_RED: '273E0011-4C4D-454D-96BE-F03BAC821358',
|
|
13
|
+
EEG_TP9: '273E0003-4C4D-454D-96BE-F03BAC821358',
|
|
14
|
+
EEG_AF7: '273E0004-4C4D-454D-96BE-F03BAC821358',
|
|
15
|
+
EEG_AF8: '273E0005-4C4D-454D-96BE-F03BAC821358',
|
|
16
|
+
EEG_TP10: '273E0006-4C4D-454D-96BE-F03BAC821358',
|
|
17
|
+
EEG_AUX: '273E0007-4C4D-454D-96BE-F03BAC821358',
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const CONTROL_UUID = MUSE_CHARACTERISTIC_UUIDS['CONTROL']
|
|
21
|
+
|
|
22
|
+
const charCallbacks = Object.entries(MUSE_CHARACTERISTIC_UUIDS).map(
|
|
23
|
+
([name, uuid]) => {
|
|
24
|
+
return {
|
|
25
|
+
charUuid: uuid,
|
|
26
|
+
charName: name,
|
|
27
|
+
onData: (data: Buffer, length: number, timestampSec: number) => {
|
|
28
|
+
const bytes = koffi.decode(data, 'uint8', length) as number[]
|
|
29
|
+
console.info(`[${timestampSec}] length=${length}`, bytes)
|
|
30
|
+
},
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
const muse = await BleDeviceController.Create({
|
|
36
|
+
deviceNamePrefix: 'Muse',
|
|
37
|
+
charCallbacks,
|
|
38
|
+
rssiIntervalMs: 1000,
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
await muse.connect()
|
|
42
|
+
|
|
43
|
+
for (const cmd of ['h', 'p50', 's', 'd']) {
|
|
44
|
+
await muse.writeCharacteristic(CONTROL_UUID, cmd)
|
|
45
|
+
await new Promise((resolve) => setTimeout(resolve, 100))
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
await new Promise((resolve) => setTimeout(resolve, 5 * 1000))
|
|
49
|
+
|
|
50
|
+
await muse.disconnect()
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
export type DestroyHandle = () => void // Do not make this async
|
|
2
|
+
|
|
3
|
+
const destroyHandles = new Set<DestroyHandle>()
|
|
4
|
+
|
|
5
|
+
let isFinalizing = false
|
|
6
|
+
|
|
7
|
+
export function register(destroy: DestroyHandle) {
|
|
8
|
+
if (isFinalizing) {
|
|
9
|
+
destroy()
|
|
10
|
+
return
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
destroyHandles.add(destroy)
|
|
14
|
+
|
|
15
|
+
const unregister = () => {
|
|
16
|
+
destroyHandles.delete(destroy)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return unregister
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function finalizeHandles() {
|
|
23
|
+
if (isFinalizing) {
|
|
24
|
+
return
|
|
25
|
+
}
|
|
26
|
+
isFinalizing = true
|
|
27
|
+
|
|
28
|
+
for (const destroy of destroyHandles) {
|
|
29
|
+
try {
|
|
30
|
+
destroy()
|
|
31
|
+
} catch (err) {
|
|
32
|
+
console.error('Error during finalization:', err)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
destroyHandles.clear()
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
process.once('SIGINT', finalizeHandles)
|
|
40
|
+
|
|
41
|
+
process.once('SIGTERM', finalizeHandles)
|
|
42
|
+
|
|
43
|
+
process.once('uncaughtException', (err) => {
|
|
44
|
+
console.error('Uncaught exception:', err)
|
|
45
|
+
finalizeHandles()
|
|
46
|
+
process.exit(1)
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
process.once('unhandledRejection', (reason) => {
|
|
50
|
+
console.error('Unhandled rejection:', reason)
|
|
51
|
+
finalizeHandles()
|
|
52
|
+
process.exit(1)
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
process.once('beforeExit', () => {
|
|
56
|
+
if (destroyHandles.size > 0 && !isFinalizing) {
|
|
57
|
+
console.warn(
|
|
58
|
+
'Warning: process is exiting with active handles.\n' +
|
|
59
|
+
'Did you forget to call destroy()? Finalizing automatically.'
|
|
60
|
+
)
|
|
61
|
+
finalizeHandles()
|
|
62
|
+
}
|
|
63
|
+
})
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import LslEventMarkerEmitter from '../impl/LslEventMarkerEmitter.js'
|
|
2
|
+
|
|
3
|
+
const outlet = await LslEventMarkerEmitter.Create()
|
|
4
|
+
|
|
5
|
+
const markers = [
|
|
6
|
+
{ name: 'phase-1-begin', waitAfterMs: 100 },
|
|
7
|
+
{ name: 'phase-1-end', waitAfterMs: 100 },
|
|
8
|
+
{ name: 'never-reached-marker', waitAfterMs: 100 },
|
|
9
|
+
]
|
|
10
|
+
|
|
11
|
+
void outlet.emitMany(markers)
|
|
12
|
+
|
|
13
|
+
await new Promise((resolve) => setTimeout(resolve, 250))
|
|
14
|
+
|
|
15
|
+
outlet.interrupt()
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import koffi from 'koffi'
|
|
2
|
+
|
|
3
|
+
import BleDeviceController from '../impl/controllers/BleDeviceController.js'
|
|
4
|
+
|
|
5
|
+
const MUSE_CHARACTERISTIC_UUIDS: Record<string, string> = {
|
|
6
|
+
CONTROL: '273E0001-4C4D-454D-96BE-F03BAC821358',
|
|
7
|
+
TELEMETRY: '273E000B-4C4D-454D-96BE-F03BAC821358',
|
|
8
|
+
GYROSCOPE: '273E0009-4C4D-454D-96BE-F03BAC821358',
|
|
9
|
+
ACCELEROMETER: '273E000A-4C4D-454D-96BE-F03BAC821358',
|
|
10
|
+
PPG_AMBIENT: '273E000F-4C4D-454D-96BE-F03BAC821358',
|
|
11
|
+
PPG_INFRARED: '273E0010-4C4D-454D-96BE-F03BAC821358',
|
|
12
|
+
PPG_RED: '273E0011-4C4D-454D-96BE-F03BAC821358',
|
|
13
|
+
EEG_TP9: '273E0003-4C4D-454D-96BE-F03BAC821358',
|
|
14
|
+
EEG_AF7: '273E0004-4C4D-454D-96BE-F03BAC821358',
|
|
15
|
+
EEG_AF8: '273E0005-4C4D-454D-96BE-F03BAC821358',
|
|
16
|
+
EEG_TP10: '273E0006-4C4D-454D-96BE-F03BAC821358',
|
|
17
|
+
EEG_AUX: '273E0007-4C4D-454D-96BE-F03BAC821358',
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const CONTROL_UUID = MUSE_CHARACTERISTIC_UUIDS['CONTROL']
|
|
21
|
+
|
|
22
|
+
const charCallbacks = Object.entries(MUSE_CHARACTERISTIC_UUIDS).map(
|
|
23
|
+
([name, uuid]) => {
|
|
24
|
+
return {
|
|
25
|
+
charUuid: uuid,
|
|
26
|
+
charName: name,
|
|
27
|
+
onData: (data: Buffer, length: number, timestampSec: number) => {
|
|
28
|
+
const bytes = koffi.decode(data, 'uint8', length) as number[]
|
|
29
|
+
console.info(`[${timestampSec}] length=${length}`, bytes)
|
|
30
|
+
},
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
const muse = await BleDeviceController.Create({
|
|
36
|
+
deviceUuid: 'CA6A61B7-B7A8-AF24-3C9E-04A6A5012554',
|
|
37
|
+
charCallbacks,
|
|
38
|
+
rssiIntervalMs: 1000,
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
await muse.connect()
|
|
42
|
+
|
|
43
|
+
for (const cmd of ['h', 'p50', 's', 'd']) {
|
|
44
|
+
await muse.writeCharacteristic(CONTROL_UUID, cmd)
|
|
45
|
+
await new Promise((resolve) => setTimeout(resolve, 100))
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
await new Promise((resolve) => setTimeout(resolve, 5 * 1000))
|
|
49
|
+
|
|
50
|
+
await muse.disconnect()
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import LslStreamInlet from '../impl/LslStreamInlet.js'
|
|
2
2
|
import LslStreamOutlet from '../impl/LslStreamOutlet.js'
|
|
3
3
|
|
|
4
|
+
const sourceId = 'TestOutletID'
|
|
5
|
+
|
|
4
6
|
console.log('Creating outlet...')
|
|
5
7
|
const outlet = await LslStreamOutlet.Create({
|
|
6
8
|
name: 'TestOutlet',
|
|
7
9
|
type: 'TEST',
|
|
8
|
-
sourceId
|
|
10
|
+
sourceId,
|
|
9
11
|
sampleRateHz: 100,
|
|
10
12
|
channelNames: ['Ch1', 'Ch2', 'Ch3'],
|
|
11
13
|
channelFormat: 'float32',
|
|
@@ -16,20 +18,18 @@ const outlet = await LslStreamOutlet.Create({
|
|
|
16
18
|
|
|
17
19
|
console.log('Creating inlet...')
|
|
18
20
|
|
|
19
|
-
const inletOptions = {
|
|
20
|
-
info: outlet.info,
|
|
21
|
-
chunkSize: 1,
|
|
22
|
-
}
|
|
23
|
-
|
|
24
21
|
const inlet = await LslStreamInlet.Create(
|
|
25
|
-
|
|
22
|
+
{
|
|
23
|
+
sourceId,
|
|
24
|
+
chunkSize: 1,
|
|
25
|
+
},
|
|
26
26
|
(samples, timestamps) => {
|
|
27
27
|
console.log('Received samples:', samples, 'at timestamps:', timestamps)
|
|
28
28
|
}
|
|
29
29
|
)
|
|
30
30
|
|
|
31
31
|
console.log('Start pulling...')
|
|
32
|
-
inlet.startPulling()
|
|
32
|
+
await inlet.startPulling()
|
|
33
33
|
|
|
34
34
|
console.log('Waiting for 100 ms...')
|
|
35
35
|
await new Promise((resolve) => setTimeout(resolve, 100))
|
|
@@ -49,3 +49,5 @@ for (let i = 0; i < 30; i++) {
|
|
|
49
49
|
outlet.pushSample(sample)
|
|
50
50
|
await new Promise((resolve) => setTimeout(resolve, 100))
|
|
51
51
|
}
|
|
52
|
+
|
|
53
|
+
process.exit(0)
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import generateId from '@neurodevs/generate-id'
|
|
2
|
+
import {
|
|
3
|
+
BleController,
|
|
4
|
+
BleControllerOptions,
|
|
5
|
+
} from '../../impl/controllers/BleDeviceController.js'
|
|
6
|
+
|
|
7
|
+
export default class FakeBleController implements BleController {
|
|
8
|
+
public static callsToConstructor: (BleControllerOptions | undefined)[] = []
|
|
9
|
+
|
|
10
|
+
public static numCallsToConnect = 0
|
|
11
|
+
|
|
12
|
+
public static callsToWriteCharacteristic: {
|
|
13
|
+
characteristicUuid: string
|
|
14
|
+
value: string
|
|
15
|
+
}[] = []
|
|
16
|
+
|
|
17
|
+
public static numCallsToDisconnect = 0
|
|
18
|
+
|
|
19
|
+
public static fakeCharacteristics: Record<string, unknown> = {}
|
|
20
|
+
public static fakeName = `fake-${generateId()}`
|
|
21
|
+
|
|
22
|
+
private _uuid: string
|
|
23
|
+
private _name: string
|
|
24
|
+
|
|
25
|
+
public constructor(options?: BleControllerOptions) {
|
|
26
|
+
const { deviceUuid } = options ?? {}
|
|
27
|
+
|
|
28
|
+
this._uuid = deviceUuid ?? generateId()
|
|
29
|
+
this._name = FakeBleController.fakeName
|
|
30
|
+
|
|
31
|
+
FakeBleController.callsToConstructor.push(options)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public async connect() {
|
|
35
|
+
FakeBleController.numCallsToConnect++
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
public async writeCharacteristic(
|
|
39
|
+
characteristicUuid: string,
|
|
40
|
+
value: string
|
|
41
|
+
) {
|
|
42
|
+
FakeBleController.callsToWriteCharacteristic.push({
|
|
43
|
+
characteristicUuid,
|
|
44
|
+
value,
|
|
45
|
+
})
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
public async disconnect() {
|
|
49
|
+
FakeBleController.numCallsToDisconnect++
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
public get uuid() {
|
|
53
|
+
return this._uuid
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
public get name() {
|
|
57
|
+
return this._name
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
public static resetTestDouble() {
|
|
61
|
+
this.callsToConstructor = []
|
|
62
|
+
this.numCallsToConnect = 0
|
|
63
|
+
this.callsToWriteCharacteristic = []
|
|
64
|
+
this.numCallsToDisconnect = 0
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface CallToBleControllerConstructor {
|
|
69
|
+
options: BleControllerOptions
|
|
70
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import BleDeviceController, {
|
|
2
|
+
BleControllerOptions,
|
|
3
|
+
} from '../../impl/controllers/BleDeviceController.js'
|
|
4
|
+
|
|
5
|
+
export default class SpyBleController extends BleDeviceController {
|
|
6
|
+
public infoLogs: string[] = []
|
|
7
|
+
public warnLogs: string[] = []
|
|
8
|
+
public errorLogs: string[] = []
|
|
9
|
+
|
|
10
|
+
public constructor(options: BleControllerOptions) {
|
|
11
|
+
super(options)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
public getCharacteristicCallbacks() {
|
|
15
|
+
return this.charCallbacks
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
public getRssiIntervalMs() {
|
|
19
|
+
return this.rssiIntervalMs
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public getConnected() {
|
|
23
|
+
return this.connected
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public setLogInfoSpy() {
|
|
27
|
+
this.infoLogs = []
|
|
28
|
+
|
|
29
|
+
this.log.info = (...args: unknown[]) => {
|
|
30
|
+
const message = args.join(' ')
|
|
31
|
+
this.infoLogs.push(message)
|
|
32
|
+
return message
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
public setLogWarnSpy() {
|
|
37
|
+
this.warnLogs = []
|
|
38
|
+
|
|
39
|
+
this.log.warn = (...args: unknown[]) => {
|
|
40
|
+
const message = args.join(' ')
|
|
41
|
+
this.warnLogs.push(message)
|
|
42
|
+
return message
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public setLogErrorSpy() {
|
|
47
|
+
this.errorLogs = []
|
|
48
|
+
|
|
49
|
+
this.log.error = (...args: unknown[]) => {
|
|
50
|
+
const message = args.join(' ')
|
|
51
|
+
this.errorLogs.push(message)
|
|
52
|
+
return message
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
public resetTestDouble() {
|
|
57
|
+
this.infoLogs = []
|
|
58
|
+
this.warnLogs = []
|
|
59
|
+
this.errorLogs = []
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import {
|
|
2
|
+
EventMarkerEmitter,
|
|
3
|
+
EventMarkerOptions,
|
|
4
|
+
TimedEventMarker,
|
|
5
|
+
} from '../../impl/LslEventMarkerEmitter.js'
|
|
6
|
+
|
|
7
|
+
export default class FakeEventMarkerEmitter implements EventMarkerEmitter {
|
|
8
|
+
public static numCallsToConstructor = 0
|
|
9
|
+
|
|
10
|
+
public static callsToEmit: {
|
|
11
|
+
markerName: string
|
|
12
|
+
options?: EventMarkerOptions
|
|
13
|
+
}[] = []
|
|
14
|
+
|
|
15
|
+
public static callsToEmitMany: TimedEventMarker[][] = []
|
|
16
|
+
public static numCallsToInterrupt = 0
|
|
17
|
+
public static numCallsToDestroy = 0
|
|
18
|
+
|
|
19
|
+
public constructor() {
|
|
20
|
+
FakeEventMarkerEmitter.numCallsToConstructor++
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
public async emit(markerName: string, options?: EventMarkerOptions) {
|
|
24
|
+
FakeEventMarkerEmitter.callsToEmit.push({ markerName, options })
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
public async emitMany(markers: TimedEventMarker[]) {
|
|
28
|
+
FakeEventMarkerEmitter.callsToEmitMany.push(markers)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public interrupt() {
|
|
32
|
+
FakeEventMarkerEmitter.numCallsToInterrupt++
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public destroy() {
|
|
36
|
+
FakeEventMarkerEmitter.numCallsToDestroy++
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
public static resetTestDouble() {
|
|
40
|
+
this.numCallsToConstructor = 0
|
|
41
|
+
this.callsToEmit = []
|
|
42
|
+
this.callsToEmitMany = []
|
|
43
|
+
this.numCallsToInterrupt = 0
|
|
44
|
+
this.numCallsToDestroy = 0
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import LslEventMarkerEmitter from '../../impl/LslEventMarkerEmitter.js'
|
|
2
|
+
import { StreamOutlet } from '../../impl/LslStreamOutlet.js'
|
|
3
|
+
|
|
4
|
+
export default class SpyEventMarkerEmitter extends LslEventMarkerEmitter {
|
|
5
|
+
public static shouldCallWaitOnSuper = false
|
|
6
|
+
|
|
7
|
+
public totalwaitAfterMs: number
|
|
8
|
+
|
|
9
|
+
public constructor(outlet: StreamOutlet) {
|
|
10
|
+
super(outlet)
|
|
11
|
+
|
|
12
|
+
this.totalwaitAfterMs = 0
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
public async wait(waitAfterMs: number) {
|
|
16
|
+
this.totalwaitAfterMs += waitAfterMs
|
|
17
|
+
|
|
18
|
+
if (SpyEventMarkerEmitter.shouldCallWaitOnSuper) {
|
|
19
|
+
return super.wait(waitAfterMs)
|
|
20
|
+
}
|
|
21
|
+
return Promise.resolve()
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public getStreamOutlet() {
|
|
25
|
+
return this.outlet
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public resetTestDouble() {
|
|
29
|
+
this.totalwaitAfterMs = 0
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import {
|
|
2
|
+
EventMarkerEmitter,
|
|
3
|
+
EventMarkerOptions,
|
|
4
|
+
TimedEventMarker,
|
|
5
|
+
} from '../../impl/LslEventMarkerEmitter.js'
|
|
6
|
+
|
|
7
|
+
export default class ThrowingEventMarkerEmitter implements EventMarkerEmitter {
|
|
8
|
+
private errorMsg = 'Intentional throwing: '
|
|
9
|
+
|
|
10
|
+
public constructor() {
|
|
11
|
+
throw new Error(this.errorMsg + 'constructor')
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
public async emit(_markerName: string, _options?: EventMarkerOptions) {
|
|
15
|
+
throw new Error(this.errorMsg + 'emit')
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
public async emitMany(_markers: TimedEventMarker[]) {
|
|
19
|
+
throw new Error(this.errorMsg + 'emitMany')
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public interrupt() {
|
|
23
|
+
throw new Error(this.errorMsg + 'interrupt')
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public destroy() {
|
|
27
|
+
throw new Error(this.errorMsg + 'destroy')
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import generateId from '@neurodevs/generate-id'
|
|
2
|
+
import { InfoHandle } from '@neurodevs/ndx-native'
|
|
2
3
|
|
|
3
|
-
import { BoundStreamInfo } from 'impl/LiblslAdapter.js'
|
|
4
4
|
import { StreamInfo, StreamInfoOptions } from '../../impl/LslStreamInfo.js'
|
|
5
5
|
|
|
6
6
|
export default class FakeStreamInfo implements StreamInfo {
|
|
7
7
|
public static callsToConstructor: (StreamInfoOptions | undefined)[] = []
|
|
8
8
|
public static numCallsToDestroy = 0
|
|
9
9
|
|
|
10
|
-
public static
|
|
10
|
+
public static infoHandle = {} as InfoHandle
|
|
11
11
|
|
|
12
12
|
public name = generateId()
|
|
13
13
|
public type = generateId()
|
|
@@ -29,8 +29,8 @@ export default class FakeStreamInfo implements StreamInfo {
|
|
|
29
29
|
return this.channelNames.length
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
public get
|
|
33
|
-
return FakeStreamInfo.
|
|
32
|
+
public get infoHandle() {
|
|
33
|
+
return FakeStreamInfo.infoHandle
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
public static resetTestDouble() {
|