truehear-audio-library-node 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,220 @@
1
+ # truehear-audio-library-node
2
+
3
+ Native Node.js audio library for listing audio devices and setting default audio devices.
4
+
5
+ Author: @truehear team
6
+
7
+ ## Installation
8
+
9
+ Install the package with npm:
10
+
11
+ ```bash
12
+ npm install truehear-audio-library-node
13
+ ```
14
+
15
+ ## Platform support
16
+
17
+ Currently supported platform:
18
+
19
+ ```text
20
+ Windows
21
+ ```
22
+
23
+ This package uses a native Node.js addon to access system audio devices.
24
+
25
+ ## Basic usage
26
+
27
+ ```ts
28
+ import { listDevices } from 'truehear-audio-library-node';
29
+
30
+ const devices = listDevices('playback');
31
+
32
+ console.log(devices);
33
+ ```
34
+
35
+ ## List playback devices
36
+
37
+ Playback devices are output devices such as speakers, headphones, HDMI output, or monitor audio.
38
+
39
+ ```ts
40
+ import { listDevices } from 'truehear-audio-library-node';
41
+
42
+ const playbackDevices = listDevices('playback');
43
+
44
+ console.log(playbackDevices);
45
+ ```
46
+
47
+ Example output:
48
+
49
+ ```ts
50
+ [
51
+ {
52
+ default: true,
53
+ defaultCommunication: false,
54
+ type: 'playback',
55
+ name: 'Speakers (Realtek(R) Audio)',
56
+ id: '{0.0.0.00000000}.{37439da3-a6eb-4740-8405-6cfbae03dd57}'
57
+ }
58
+ ]
59
+ ```
60
+
61
+ ## List recording devices
62
+
63
+ Recording devices are input devices such as microphones, headset microphones, or USB audio input devices.
64
+
65
+ ```ts
66
+ import { listDevices } from 'truehear-audio-library-node';
67
+
68
+ const recordingDevices = listDevices('recording');
69
+
70
+ console.log(recordingDevices);
71
+ ```
72
+
73
+ ## Set the default playback device
74
+
75
+ Use the device `id` returned from `listDevices`.
76
+
77
+ ```ts
78
+ import {
79
+ listDevices,
80
+ setDefaultDevice,
81
+ } from 'truehear-audio-library-node';
82
+
83
+ const devices = listDevices('playback');
84
+
85
+ const targetDevice = devices[0];
86
+
87
+ setDefaultDevice('playback', targetDevice.id);
88
+ ```
89
+
90
+ ## Set the default recording device
91
+
92
+ ```ts
93
+ import {
94
+ listDevices,
95
+ setDefaultDevice,
96
+ } from 'truehear-audio-library-node';
97
+
98
+ const devices = listDevices('recording');
99
+
100
+ const targetDevice = devices[0];
101
+
102
+ setDefaultDevice('recording', targetDevice.id);
103
+ ```
104
+
105
+ ## Set the default communication device
106
+
107
+ Communication devices are used by calling and meeting applications.
108
+
109
+ ```ts
110
+ import {
111
+ listDevices,
112
+ setDefaultCommunicationDevice,
113
+ } from 'truehear-audio-library-node';
114
+
115
+ const devices = listDevices('playback');
116
+
117
+ const targetDevice = devices[0];
118
+
119
+ setDefaultCommunicationDevice('playback', targetDevice.id);
120
+ ```
121
+
122
+ ## API
123
+
124
+ ### `listDevices(type)`
125
+
126
+ Lists audio devices.
127
+
128
+ ```ts
129
+ listDevices(type: AudioDeviceType): AudioDeviceInfo[]
130
+ ```
131
+
132
+ Example:
133
+
134
+ ```ts
135
+ const playbackDevices = listDevices('playback');
136
+ const recordingDevices = listDevices('recording');
137
+ ```
138
+
139
+ ### `setDefaultDevice(type, deviceId)`
140
+
141
+ Sets the normal default audio device.
142
+
143
+ ```ts
144
+ setDefaultDevice(type: AudioDeviceType, deviceId: string): void
145
+ ```
146
+
147
+ Example:
148
+
149
+ ```ts
150
+ setDefaultDevice('playback', deviceId);
151
+ ```
152
+
153
+ ### `setDefaultCommunicationDevice(type, deviceId)`
154
+
155
+ Sets the default communication audio device.
156
+
157
+ ```ts
158
+ setDefaultCommunicationDevice(
159
+ type: AudioDeviceType,
160
+ deviceId: string
161
+ ): void
162
+ ```
163
+
164
+ Example:
165
+
166
+ ```ts
167
+ setDefaultCommunicationDevice('playback', deviceId);
168
+ ```
169
+
170
+ ## Types
171
+
172
+ ### `AudioDeviceType`
173
+
174
+ ```ts
175
+ type AudioDeviceType = 'playback' | 'recording';
176
+ ```
177
+
178
+ ### `AudioDeviceInfo`
179
+
180
+ ```ts
181
+ type AudioDeviceInfo = {
182
+ default: boolean;
183
+ defaultCommunication: boolean;
184
+ type: AudioDeviceType;
185
+ name: string;
186
+ id: string;
187
+ };
188
+ ```
189
+
190
+ ## Device ID
191
+
192
+ The `id` field is the native operating system device identifier.
193
+
194
+ Use this value when calling:
195
+
196
+ ```ts
197
+ setDefaultDevice(type, deviceId);
198
+ setDefaultCommunicationDevice(type, deviceId);
199
+ ```
200
+
201
+ ## Error handling
202
+
203
+ Invalid arguments throw `TypeError`.
204
+
205
+ Native audio failures throw `Error`.
206
+
207
+ ```ts
208
+ import { listDevices } from 'truehear-audio-library-node';
209
+
210
+ try {
211
+ const devices = listDevices('playback');
212
+ console.log(devices);
213
+ } catch (error) {
214
+ console.error(error);
215
+ }
216
+ ```
217
+
218
+ ## License
219
+
220
+ ISC
package/binding.gyp ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "targets": [
3
+ {
4
+ "target_name": "truehear_audio_native",
5
+ "sources": [
6
+ "src/addon.c",
7
+ "src/truehear_audio_win.c",
8
+ "src/policy_config_guids.c",
9
+ "src/mmdevice_guids.c"
10
+ ],
11
+ "include_dirs": [
12
+ "include"
13
+ ],
14
+ "defines": [
15
+ "NAPI_VERSION=8"
16
+ ],
17
+ "conditions": [
18
+ [
19
+ "OS==\"win\"",
20
+ {
21
+ "libraries": [
22
+ "ole32.lib",
23
+ "mmdevapi.lib",
24
+ "uuid.lib"
25
+ ],
26
+ "msvs_settings": {
27
+ "VCCLCompilerTool": {
28
+ "WarningLevel": 4,
29
+ "DebugInformationFormat": 3
30
+ }
31
+ }
32
+ }
33
+ ],
34
+ [
35
+ "OS!=\"win\"",
36
+ {
37
+ "sources!": [
38
+ "src/truehear_audio_win.c"
39
+ ]
40
+ }
41
+ ]
42
+ ]
43
+ }
44
+ ]
45
+ }
@@ -0,0 +1,240 @@
1
+ /**
2
+ * Public audio device type definitions.
3
+ *
4
+ * This file is intentionally TypeScript-only.
5
+ *
6
+ * Design goals:
7
+ * - Describe the public API shape exposed to TypeScript consumers.
8
+ * - Stay independent from the native implementation details.
9
+ * - Mirror the object shape returned from the native addon.
10
+ * - Provide high-quality JSDoc for IDEs, IntelliSense, and generated docs.
11
+ */
12
+ /**
13
+ * Represents the direction of an audio endpoint.
14
+ *
15
+ * Use this type to distinguish between:
16
+ * - `playback`: audio output devices such as speakers, headphones, or HDMI audio
17
+ * - `recording`: audio input devices such as microphones or headset mics
18
+ *
19
+ * @remarks
20
+ * This value is used by the native binding to query and update the correct
21
+ * class of device on the operating system.
22
+ *
23
+ * @example
24
+ * ```ts
25
+ * const deviceType: AudioDeviceType = "playback";
26
+ * ```
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * function isInputDevice(type: AudioDeviceType) {
31
+ * return type === "recording";
32
+ * }
33
+ * ```
34
+ */
35
+ export type AudioDeviceType = "playback" | "recording";
36
+ /**
37
+ * Describes a single audio device exposed by the operating system.
38
+ *
39
+ * This is the TypeScript representation of the native C structure returned
40
+ * by the addon.
41
+ *
42
+ * @remarks
43
+ * The native layer converts platform-specific endpoint metadata into this
44
+ * plain JavaScript object shape so that consumers can work with a stable,
45
+ * ergonomic API.
46
+ *
47
+ * @example
48
+ * ```ts
49
+ * const device: AudioDeviceInfo = {
50
+ * default: true,
51
+ * defaultCommunication: false,
52
+ * type: "playback",
53
+ * name: "Speakers (Realtek(R) Audio)",
54
+ * id: "{0.0.0.00000000}.{37439da3-a6eb-4740-8405-6cfbae03dd57}",
55
+ * };
56
+ * ```
57
+ */
58
+ export type AudioDeviceInfo = {
59
+ /**
60
+ * Indicates whether this device is the current system default for
61
+ * standard audio output or input.
62
+ *
63
+ * @remarks
64
+ * On Windows, this typically corresponds to the default multimedia endpoint
65
+ * used by normal desktop applications.
66
+ *
67
+ * - `true` — the device is the current default device
68
+ * - `false` — the device is available, but not selected as default
69
+ */
70
+ default: boolean;
71
+ /**
72
+ * Indicates whether this device is the current system default for
73
+ * communication audio.
74
+ *
75
+ * @remarks
76
+ * Communication devices are typically used by:
77
+ * - Teams
78
+ * - Zoom
79
+ * - Discord
80
+ * - voice and calling applications
81
+ *
82
+ * This is separate from the normal default audio device.
83
+ */
84
+ defaultCommunication: boolean;
85
+ /**
86
+ * The direction of the device.
87
+ *
88
+ * @remarks
89
+ * - `playback` means an output device
90
+ * - `recording` means an input device
91
+ */
92
+ type: AudioDeviceType;
93
+ /**
94
+ * A human-readable device name presented by the operating system.
95
+ *
96
+ * @example
97
+ * ```ts
98
+ * "Speakers (Realtek(R) Audio)"
99
+ * "Microphone (USB PnP Audio Device)"
100
+ * ```
101
+ */
102
+ name: string;
103
+ /**
104
+ * The native operating-system identifier for the device.
105
+ *
106
+ * @remarks
107
+ * On Windows, this is typically the Core Audio endpoint ID. It is stable
108
+ * enough to be passed back into device selection APIs.
109
+ *
110
+ * @example
111
+ * ```ts
112
+ * "{0.0.0.00000000}.{37439da3-a6eb-4740-8405-6cfbae03dd57}"
113
+ * ```
114
+ */
115
+ id: string;
116
+ };
117
+ /**
118
+ * Shape of the native binding loaded from the compiled `.node` file.
119
+ *
120
+ * @remarks
121
+ * This type is internal to the TypeScript wrapper layer. It describes the
122
+ * JavaScript object exported by the native addon and consumed by the public
123
+ * API wrapper.
124
+ *
125
+ * The actual implementation is in native C/C++ and is loaded at runtime.
126
+ */
127
+ export type NativeAudioBinding = {
128
+ /**
129
+ * Returns the list of available audio devices for the requested direction.
130
+ *
131
+ * @param type - The device direction to query.
132
+ * @returns An array of audio devices currently available on the system.
133
+ *
134
+ * @example
135
+ * ```ts
136
+ * const playbackDevices = binding.listDevices("playback");
137
+ * console.log(playbackDevices);
138
+ * ```
139
+ *
140
+ * @example
141
+ * ```ts
142
+ * const recordingDevices = binding.listDevices("recording");
143
+ * const defaultMic = recordingDevices.find((d) => d.default);
144
+ * console.log(defaultMic?.name);
145
+ * ```
146
+ *
147
+ * @example
148
+ * ```ts
149
+ * for (const device of binding.listDevices("playback")) {
150
+ * console.log(`${device.default ? "[default] " : ""}${device.name}`);
151
+ * }
152
+ * ```
153
+ */
154
+ listDevices(type: AudioDeviceType): AudioDeviceInfo[];
155
+ /**
156
+ * Sets the current default normal audio device for the given direction.
157
+ *
158
+ * @remarks
159
+ * This changes the device used by standard applications for either:
160
+ * - audio playback, when `type` is `"playback"`
161
+ * - audio recording, when `type` is `"recording"`
162
+ *
163
+ * Use the `id` value returned by {@link listDevices}.
164
+ *
165
+ * @param type - The device direction to update.
166
+ * @param deviceId - The native device identifier returned by {@link listDevices}.
167
+ *
168
+ * @example
169
+ * ```ts
170
+ * const devices = binding.listDevices("playback");
171
+ * const speakers = devices.find((d) => d.name.includes("Speakers"));
172
+ *
173
+ * if (speakers) {
174
+ * binding.setDefaultDevice("playback", speakers.id);
175
+ * }
176
+ * ```
177
+ *
178
+ * @example
179
+ * ```ts
180
+ * const mics = binding.listDevices("recording");
181
+ * const usbMic = mics.find((d) => d.name.includes("USB"));
182
+ *
183
+ * if (usbMic) {
184
+ * binding.setDefaultDevice("recording", usbMic.id);
185
+ * }
186
+ * ```
187
+ *
188
+ * @example
189
+ * ```ts
190
+ * // Swap to the first available output device.
191
+ * const devices = binding.listDevices("playback");
192
+ * if (devices.length > 0) {
193
+ * binding.setDefaultDevice("playback", devices[0].id);
194
+ * }
195
+ * ```
196
+ */
197
+ setDefaultDevice(type: AudioDeviceType, deviceId: string): void;
198
+ /**
199
+ * Sets the current default communication audio device for the given direction.
200
+ *
201
+ * @remarks
202
+ * Communication devices are typically used by apps that prioritize voice
203
+ * calling and conferencing.
204
+ *
205
+ * Use the `id` value returned by {@link listDevices}.
206
+ *
207
+ * @param type - The device direction to update.
208
+ * @param deviceId - The native device identifier returned by {@link listDevices}.
209
+ *
210
+ * @example
211
+ * ```ts
212
+ * const devices = binding.listDevices("recording");
213
+ * const headsetMic = devices.find((d) => d.name.includes("Headset"));
214
+ *
215
+ * if (headsetMic) {
216
+ * binding.setDefaultCommunicationDevice("recording", headsetMic.id);
217
+ * }
218
+ * ```
219
+ *
220
+ * @example
221
+ * ```ts
222
+ * const speakers = binding.listDevices("playback").find((d) => d.default);
223
+ *
224
+ * if (speakers) {
225
+ * binding.setDefaultCommunicationDevice("playback", speakers.id);
226
+ * }
227
+ * ```
228
+ *
229
+ * @example
230
+ * ```ts
231
+ * // Set the communication output device to the first available playback device.
232
+ * const playbackDevices = binding.listDevices("playback");
233
+ * if (playbackDevices[0]) {
234
+ * binding.setDefaultCommunicationDevice("playback", playbackDevices[0].id);
235
+ * }
236
+ * ```
237
+ */
238
+ setDefaultCommunicationDevice(type: AudioDeviceType, deviceId: string): void;
239
+ };
240
+ //# sourceMappingURL=audio-device.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio-device.types.d.ts","sourceRoot":"","sources":["../../node/domain/audio-device.types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,WAAW,CAAC;AAEvD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B;;;;;;;;;;OAUG;IACH,OAAO,EAAE,OAAO,CAAC;IAEjB;;;;;;;;;;;;OAYG;IACH,oBAAoB,EAAE,OAAO,CAAC;IAE9B;;;;;;OAMG;IACH,IAAI,EAAE,eAAe,CAAC;IAEtB;;;;;;;;OAQG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;;;;;;;;;;OAWG;IACH,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,WAAW,CAAC,IAAI,EAAE,eAAe,GAAG,eAAe,EAAE,CAAC;IAEtD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAyCG;IACH,gBAAgB,CAAC,IAAI,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAEhE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAuCG;IACH,6BAA6B,CAAC,IAAI,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9E,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Public audio device type definitions.
3
+ *
4
+ * This file is intentionally TypeScript-only.
5
+ *
6
+ * Design goals:
7
+ * - Describe the public API shape exposed to TypeScript consumers.
8
+ * - Stay independent from the native implementation details.
9
+ * - Mirror the object shape returned from the native addon.
10
+ * - Provide high-quality JSDoc for IDEs, IntelliSense, and generated docs.
11
+ */
12
+ export {};
13
+ //# sourceMappingURL=audio-device.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio-device.types.js","sourceRoot":"","sources":["../../node/domain/audio-device.types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}
@@ -0,0 +1,123 @@
1
+ import type { AudioDeviceInfo, AudioDeviceType } from "./domain/audio-device.types.js";
2
+ /**
3
+ * Public types re-exported from the package root.
4
+ *
5
+ * Consumers can import these directly from the package entrypoint:
6
+ *
7
+ * ```ts
8
+ * import type { AudioDeviceInfo, AudioDeviceType } from 'truehear-audio-library-node';
9
+ * ```
10
+ */
11
+ export type { AudioDeviceInfo, AudioDeviceType };
12
+ /**
13
+ * List available audio devices for a given direction.
14
+ *
15
+ * @param type - The device direction to query.
16
+ * @returns The list of devices exposed by the operating system.
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * import { listDevices } from 'truehear-audio-library-node';
21
+ *
22
+ * const playbackDevices = listDevices('playback');
23
+ * console.log(playbackDevices);
24
+ * ```
25
+ *
26
+ * @example
27
+ * ```ts
28
+ * const recordingDevices = listDevices('recording');
29
+ * const defaultMic = recordingDevices.find((device) => device.default);
30
+ *
31
+ * if (defaultMic) {
32
+ * console.log(`Default microphone: ${defaultMic.name}`);
33
+ * }
34
+ * ```
35
+ *
36
+ * @example
37
+ * ```ts
38
+ * for (const device of listDevices('playback')) {
39
+ * console.log(`${device.default ? '[default] ' : ''}${device.name}`);
40
+ * }
41
+ * ```
42
+ */
43
+ export declare const listDevices: (type: AudioDeviceType) => AudioDeviceInfo[];
44
+ /**
45
+ * Set the system's default normal audio device.
46
+ *
47
+ * @remarks
48
+ * Use this function to switch the primary device used by standard applications.
49
+ *
50
+ * @param type - The device direction to update.
51
+ * @param deviceId - The native device identifier returned by {@link listDevices}.
52
+ *
53
+ * @example
54
+ * ```ts
55
+ * const devices = listDevices('playback');
56
+ * const speakers = devices.find((device) => device.name.includes('Speakers'));
57
+ *
58
+ * if (speakers) {
59
+ * setDefaultDevice('playback', speakers.id);
60
+ * }
61
+ * ```
62
+ *
63
+ * @example
64
+ * ```ts
65
+ * const mics = listDevices('recording');
66
+ * const usbMic = mics.find((device) => device.name.includes('USB'));
67
+ *
68
+ * if (usbMic) {
69
+ * setDefaultDevice('recording', usbMic.id);
70
+ * }
71
+ * ```
72
+ */
73
+ export declare const setDefaultDevice: (type: AudioDeviceType, deviceId: string) => void;
74
+ /**
75
+ * Set the system's default communication audio device.
76
+ *
77
+ * @remarks
78
+ * Communication devices are typically used by calling and conferencing apps
79
+ * such as Teams, Zoom, Discord, and similar voice-capable software.
80
+ *
81
+ * @param type - The device direction to update.
82
+ * @param deviceId - The native device identifier returned by {@link listDevices}.
83
+ *
84
+ * @example
85
+ * ```ts
86
+ * const devices = listDevices('playback');
87
+ * const defaultPlayback = devices.find((device) => device.default);
88
+ *
89
+ * if (defaultPlayback) {
90
+ * setDefaultCommunicationDevice('playback', defaultPlayback.id);
91
+ * }
92
+ * ```
93
+ *
94
+ * @example
95
+ * ```ts
96
+ * const recordingDevices = listDevices('recording');
97
+ * const headsetMic = recordingDevices.find((device) =>
98
+ * device.name.toLowerCase().includes('headset'),
99
+ * );
100
+ *
101
+ * if (headsetMic) {
102
+ * setDefaultCommunicationDevice('recording', headsetMic.id);
103
+ * }
104
+ * ```
105
+ */
106
+ export declare const setDefaultCommunicationDevice: (type: AudioDeviceType, deviceId: string) => void;
107
+ /**
108
+ * Default package export for consumers who prefer object-style access.
109
+ *
110
+ * @example
111
+ * ```ts
112
+ * import truehearAudio from 'truehear-audio-library-node';
113
+ *
114
+ * const devices = truehearAudio.listDevices('playback');
115
+ * ```
116
+ */
117
+ declare const truehearAudio: {
118
+ listDevices: (type: AudioDeviceType) => AudioDeviceInfo[];
119
+ setDefaultDevice: (type: AudioDeviceType, deviceId: string) => void;
120
+ setDefaultCommunicationDevice: (type: AudioDeviceType, deviceId: string) => void;
121
+ };
122
+ export default truehearAudio;
123
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../node/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EAEhB,MAAM,gCAAgC,CAAC;AAExC;;;;;;;;GAQG;AACH,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,CAAC;AA+CjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,eAAO,MAAM,WAAW,8CAAqB,CAAC;AAE9C;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,gBAAgB,mDAA0B,CAAC;AAExD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,eAAO,MAAM,6BAA6B,mDACJ,CAAC;AAEvC;;;;;;;;;GASG;AACH,QAAA,MAAM,aAAa;;;;CAIlB,CAAC;AAEF,eAAe,aAAa,CAAC"}