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.
@@ -0,0 +1,348 @@
1
+ #ifndef TRUEHEAR_AUDIO_H
2
+ #define TRUEHEAR_AUDIO_H
3
+
4
+ #include "audio_device_types.h"
5
+
6
+ /**
7
+ * @file truehear_audio.h
8
+ * @brief Public, platform-agnostic Truehear audio API.
9
+ *
10
+ * This header exposes a stable C interface for audio device discovery and
11
+ * default-device management across supported operating systems.
12
+ *
13
+ * Intended consumers:
14
+ * - Node/NPM native addon layer
15
+ * - integration tests
16
+ * - CLI / application code that must remain platform-neutral
17
+ *
18
+ * ---------------------------------------------------------------------------
19
+ * Why this API exists
20
+ * ---------------------------------------------------------------------------
21
+ * Platform audio APIs are different (Windows COM, CoreAudio, PipeWire, etc.).
22
+ * This file hides those differences behind one portable interface.
23
+ *
24
+ * Keep this API clean:
25
+ * - No COM/Windows-only types
26
+ * - No IMMDevice/IPolicyConfig in public signatures
27
+ * - No platform-specific structs in public contracts
28
+ *
29
+ * Layering:
30
+ * App / Node addon / tests
31
+ * ↓
32
+ * truehear_audio.h (this file)
33
+ * ↓
34
+ * platform implementation
35
+ * ↓
36
+ * Windows Core Audio | macOS CoreAudio | Linux PipeWire/Pulse/ALSA
37
+ *
38
+ * ---------------------------------------------------------------------------
39
+ * Error model
40
+ * ---------------------------------------------------------------------------
41
+ * Most functions return:
42
+ * - 0 on success
43
+ * - -1 on failure
44
+ *
45
+ * On failure, call truehear_audio_get_last_error() for a human-readable reason.
46
+ *
47
+ * ---------------------------------------------------------------------------
48
+ * Memory model
49
+ * ---------------------------------------------------------------------------
50
+ * truehear_audio_list_devices() allocates memory for the output list.
51
+ * Caller MUST free it using truehear_audio_free_device_list().
52
+ *
53
+ */
54
+
55
+ #ifdef __cplusplus
56
+ extern "C" {
57
+ #endif
58
+
59
+ /* ============================================================================================== */
60
+ /* Quick Start */
61
+ /* ============================================================================================== */
62
+ /**
63
+ * Basic flow:
64
+ *
65
+ * 1) Enumerate devices:
66
+ * truehear_audio_list_devices(type, &list)
67
+ * 2) Pick a device ID from list.items[i].id
68
+ * 3) Set default:
69
+ * truehear_audio_set_default_device(type, device_id)
70
+ * Optional (communication profile):
71
+ * truehear_audio_set_default_communication_device(type, device_id)
72
+ * 4) Cleanup:
73
+ * truehear_audio_free_device_list(&list)
74
+ *
75
+ * Typical type mapping:
76
+ * - TRUEHEAR_AUDIO_DEVICE_TYPE_PLAYBACK -> output devices (speakers/headphones)
77
+ * - TRUEHEAR_AUDIO_DEVICE_TYPE_RECORDING -> input devices (microphones)
78
+ */
79
+
80
+ /* ============================================================================================== */
81
+ /* Device Enumeration */
82
+ /* ============================================================================================== */
83
+
84
+ /**
85
+ * @brief Enumerate audio devices for a given device class.
86
+ *
87
+ * @param type
88
+ * Device class to enumerate:
89
+ * - TRUEHEAR_AUDIO_DEVICE_TYPE_PLAYBACK
90
+ * - TRUEHEAR_AUDIO_DEVICE_TYPE_RECORDING
91
+ *
92
+ * @param[out] out_list
93
+ * Receives an allocated device list on success.
94
+ *
95
+ * @return
96
+ * - 0 on success
97
+ * - -1 on failure (use truehear_audio_get_last_error())
98
+ *
99
+ * @pre
100
+ * - out_list != NULL
101
+ *
102
+ * @post (on success)
103
+ * - out_list is initialized and owns allocated memory
104
+ * - caller must call truehear_audio_free_device_list(out_list)
105
+ *
106
+ * @post (on failure)
107
+ * - out_list content is implementation-defined; caller should still treat
108
+ * cleanup as safe via truehear_audio_free_device_list(out_list)
109
+ *
110
+ * @Example:
111
+ * @code
112
+ * #include <stdio.h>
113
+ * #include "truehear_audio.h"
114
+ *
115
+ * static void print_devices(TruehearAudioDeviceType type) {
116
+ * TruehearAudioDeviceInfoList list;
117
+ *
118
+ * if (truehear_audio_list_devices(type, &list) != 0) {
119
+ * fprintf(stderr, "List failed: %s\n", truehear_audio_get_last_error());
120
+ * return;
121
+ * }
122
+ *
123
+ * for (int i = 0; i < list.count; ++i) {
124
+ * const TruehearAudioDeviceInfo *d = &list.items[i];
125
+ * printf("[%d] name='%s' id='%s' is_default=%d\n",
126
+ * i,
127
+ * d->name ? d->name : "(null)",
128
+ * d->id ? d->id : "(null)",
129
+ * d->is_default);
130
+ * }
131
+ *
132
+ * truehear_audio_free_device_list(&list);
133
+ * }
134
+ * @endcode
135
+ */
136
+ int truehear_audio_list_devices(
137
+ TruehearAudioDeviceType type,
138
+ TruehearAudioDeviceInfoList *out_list);
139
+
140
+ /* ============================================================================================== */
141
+ /* Default Device Management */
142
+ /* ============================================================================================== */
143
+
144
+ /**
145
+ * @brief Set the system default audio device.
146
+ *
147
+ * Typical meaning:
148
+ * - playback => system default output
149
+ * - recording => system default input
150
+ *
151
+ * @param type
152
+ * Playback or recording device class.
153
+ *
154
+ * @param device_id
155
+ * Non-NULL, non-empty device ID from truehear_audio_list_devices().
156
+ *
157
+ * @return
158
+ * - 0 on success
159
+ * - -1 on failure (use truehear_audio_get_last_error())
160
+ *
161
+ * @pre
162
+ * - device_id != NULL
163
+ * - device_id points to a valid, null-terminated string
164
+ *
165
+ * Example:
166
+ * @code
167
+ * // Set first playback device as system default (demo only).
168
+ * TruehearAudioDeviceInfoList list;
169
+ * if (truehear_audio_list_devices(TRUEHEAR_AUDIO_DEVICE_TYPE_PLAYBACK, &list) != 0) {
170
+ * fprintf(stderr, "List failed: %s\n", truehear_audio_get_last_error());
171
+ * return;
172
+ * }
173
+ *
174
+ * if (list.count > 0 && list.items[0].id) {
175
+ * if (truehear_audio_set_default_device(
176
+ * TRUEHEAR_AUDIO_DEVICE_TYPE_PLAYBACK,
177
+ * list.items[0].id) != 0) {
178
+ * fprintf(stderr, "Set default failed: %s\n", truehear_audio_get_last_error());
179
+ * }
180
+ * }
181
+ *
182
+ * truehear_audio_free_device_list(&list);
183
+ * @endcode
184
+ */
185
+ int truehear_audio_set_default_device(
186
+ TruehearAudioDeviceType type,
187
+ const char *device_id);
188
+
189
+ /**
190
+ * @brief Set the default communication audio device.
191
+ *
192
+ * Some platforms (notably Windows) distinguish:
193
+ * - regular multimedia default
194
+ * - communication default (calls/conferencing apps)
195
+ *
196
+ * On platforms without a communication role, this may return failure with an
197
+ * "unsupported" style error message.
198
+ *
199
+ * @param type
200
+ * Playback or recording device class.
201
+ *
202
+ * @param device_id
203
+ * Non-NULL, non-empty device ID from truehear_audio_list_devices().
204
+ *
205
+ * @return
206
+ * - 0 on success
207
+ * - -1 on failure (use truehear_audio_get_last_error())
208
+ *
209
+ * Example:
210
+ * @code
211
+ * // Try to set communication default for microphones.
212
+ * TruehearAudioDeviceInfoList list;
213
+ * if (truehear_audio_list_devices(TRUEHEAR_AUDIO_DEVICE_TYPE_RECORDING, &list) != 0) {
214
+ * fprintf(stderr, "List failed: %s\n", truehear_audio_get_last_error());
215
+ * return;
216
+ * }
217
+ *
218
+ * // Pick a candidate by your own policy (name match, index, etc.)
219
+ * for (int i = 0; i < list.count; ++i) {
220
+ * if (list.items[i].id) {
221
+ * if (truehear_audio_set_default_communication_device(
222
+ * TRUEHEAR_AUDIO_DEVICE_TYPE_RECORDING,
223
+ * list.items[i].id) != 0) {
224
+ * fprintf(stderr, "Set comm default failed: %s\n",
225
+ * truehear_audio_get_last_error());
226
+ * }
227
+ * break;
228
+ * }
229
+ * }
230
+ *
231
+ * truehear_audio_free_device_list(&list);
232
+ * @endcode
233
+ */
234
+ int truehear_audio_set_default_communication_device(
235
+ TruehearAudioDeviceType type,
236
+ const char *device_id);
237
+
238
+ /* ============================================================================================== */
239
+ /* Memory Management */
240
+ /* ============================================================================================== */
241
+
242
+ /**
243
+ * @brief Free resources in a device list returned by truehear_audio_list_devices().
244
+ *
245
+ * Releases:
246
+ * - list->items
247
+ * - item.name
248
+ * - item.id
249
+ * - item.device
250
+ *
251
+ * Safe to call with:
252
+ * - NULL
253
+ * - list with count == 0
254
+ * - list with items == NULL
255
+ *
256
+ * After return, callers should not read prior pointers from @p list.
257
+ *
258
+ * @param list
259
+ * Pointer to a list previously used with truehear_audio_list_devices().
260
+ */
261
+ void truehear_audio_free_device_list(
262
+ TruehearAudioDeviceInfoList *list);
263
+
264
+ /* ============================================================================================== */
265
+ /* Error Reporting */
266
+ /* ============================================================================================== */
267
+
268
+ /**
269
+ * @brief Return a human-readable message for the most recent API failure.
270
+ *
271
+ * Use immediately after a function returns -1.
272
+ *
273
+ * @return
274
+ * Library-owned const string pointer.
275
+ * - Do NOT free
276
+ * - Do NOT modify
277
+ * - May be overwritten by subsequent API calls
278
+ *
279
+ * Example:
280
+ * @code
281
+ * if (truehear_audio_set_default_device(type, id) != 0) {
282
+ * const char *err = truehear_audio_get_last_error();
283
+ * fprintf(stderr, "truehear error: %s\n", err ? err : "(unknown)");
284
+ * }
285
+ * @endcode
286
+ */
287
+ const char *truehear_audio_get_last_error(void);
288
+
289
+ /* ============================================================================================== */
290
+ /* End-to-End Example */
291
+ /* ============================================================================================== */
292
+ /**
293
+ * @code
294
+ * #include <stdio.h>
295
+ * #include <string.h>
296
+ * #include "truehear_audio.h"
297
+ *
298
+ * // Demo: set playback default by substring match on device name.
299
+ * int set_playback_default_by_name(const char *needle) {
300
+ * TruehearAudioDeviceInfoList list;
301
+ * int rc = truehear_audio_list_devices(TRUEHEAR_AUDIO_DEVICE_TYPE_PLAYBACK, &list);
302
+ * if (rc != 0) {
303
+ * fprintf(stderr, "List failed: %s\n", truehear_audio_get_last_error());
304
+ * return -1;
305
+ * }
306
+ *
307
+ * const char *selected_id = NULL;
308
+ * for (int i = 0; i < list.count; ++i) {
309
+ * const TruehearAudioDeviceInfo *d = &list.items[i];
310
+ * if (d->name && strstr(d->name, needle) && d->id) {
311
+ * selected_id = d->id;
312
+ * break;
313
+ * }
314
+ * }
315
+ *
316
+ * if (!selected_id) {
317
+ * fprintf(stderr, "No matching playback device for '%s'\n", needle);
318
+ * truehear_audio_free_device_list(&list);
319
+ * return -1;
320
+ * }
321
+ *
322
+ * rc = truehear_audio_set_default_device(
323
+ * TRUEHEAR_AUDIO_DEVICE_TYPE_PLAYBACK, selected_id);
324
+ * if (rc != 0) {
325
+ * fprintf(stderr, "Set default failed: %s\n", truehear_audio_get_last_error());
326
+ * truehear_audio_free_device_list(&list);
327
+ * return -1;
328
+ * }
329
+ *
330
+ * // Optional: also set communication default.
331
+ * if (truehear_audio_set_default_communication_device(
332
+ * TRUEHEAR_AUDIO_DEVICE_TYPE_PLAYBACK, selected_id) != 0) {
333
+ * // Not fatal on platforms where unsupported.
334
+ * fprintf(stderr, "Set communication default warning: %s\n",
335
+ * truehear_audio_get_last_error());
336
+ * }
337
+ *
338
+ * truehear_audio_free_device_list(&list);
339
+ * return 0;
340
+ * }
341
+ * @endcode
342
+ */
343
+
344
+ #ifdef __cplusplus
345
+ } /* extern "C" */
346
+ #endif
347
+
348
+ #endif /* TRUEHEAR_AUDIO_H */
package/package.json ADDED
@@ -0,0 +1,85 @@
1
+ {
2
+ "name": "truehear-audio-library-node",
3
+ "version": "1.0.0",
4
+ "description": "Native Node.js audio device listing and default-device switching library.",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "default": "./dist/index.js"
13
+ }
14
+ },
15
+ "os": [
16
+ "win32"
17
+ ],
18
+ "cpu": [
19
+ "x64"
20
+ ],
21
+ "files": [
22
+ "dist/**/*.js",
23
+ "dist/**/*.js.map",
24
+ "dist/**/*.d.ts",
25
+ "dist/**/*.d.ts.map",
26
+ "prebuilds",
27
+ "include",
28
+ "src",
29
+ "binding.gyp",
30
+ "README.md",
31
+ "LICENSE"
32
+ ],
33
+ "gypfile": true,
34
+ "scripts": {
35
+ "install": "node-gyp-build",
36
+ "clean:dist": "node -e \"require('fs').rmSync('dist', { recursive: true, force: true })\"",
37
+ "clean:prebuilds": "node -e \"require('fs').rmSync('prebuilds', { recursive: true, force: true })\"",
38
+ "clean:native": "node-gyp clean",
39
+ "build:native": "node-gyp rebuild",
40
+ "build:native:debug": "node-gyp rebuild --debug",
41
+ "build:ts": "npm run clean:dist && tsc -p tsconfig.lib.json",
42
+ "copy:prebuild": "node scripts/copy-prebuild.cjs",
43
+ "build:prebuild": "npm run clean:prebuilds && npm run build:native && npm run copy:prebuild",
44
+ "build": "npm run build:native && npm run build:ts",
45
+ "build:package": "npm run build:ts && npm run build:prebuild",
46
+ "prepack": "npm run build:package",
47
+ "typecheck": "tsc -b",
48
+ "test:native": "node node/tests/native.test.cjs",
49
+ "test:list": "tsx node/tests/list.devices.ts",
50
+ "test:set": "tsx node/tests/set.device.ts",
51
+ "test": "npm run test:native && npm run test:list",
52
+ "pack:check": "npm pack --dry-run",
53
+ "pack:local": "npm pack"
54
+ },
55
+ "keywords": [
56
+ "audio",
57
+ "device",
58
+ "windows",
59
+ "core-audio",
60
+ "wasapi",
61
+ "node-api",
62
+ "napi",
63
+ "native-addon",
64
+ "default-audio-device"
65
+ ],
66
+ "author": "@truehear team",
67
+ "license": "ISC",
68
+ "repository": {
69
+ "type": "git",
70
+ "url": "git+https://github.com/TrueHear/truehear-audio-library-node.git"
71
+ },
72
+ "bugs": {
73
+ "url": "https://github.com/TrueHear/truehear-audio-library-node/issues"
74
+ },
75
+ "homepage": "https://github.com/TrueHear/truehear-audio-library-node#readme",
76
+ "dependencies": {
77
+ "node-gyp-build": "^4.8.4"
78
+ },
79
+ "devDependencies": {
80
+ "@types/node": "^25.9.3",
81
+ "node-gyp": "^13.0.0",
82
+ "tsx": "^4.20.0",
83
+ "typescript": "^5.0.0"
84
+ }
85
+ }