diff --git a/README.md b/README.md index 0b218b7..26632d4 100644 --- a/README.md +++ b/README.md @@ -96,6 +96,47 @@ An example of the output is: ``` Note that the `defaultInput` and `defaultOutput` values can be used as to specify which device to use for playback or recording with optional parameter `deviceId`. +### Getting default Devices + +To get the default devices, call the `getDefaultDevices` function. + +```js +var portAudio = require('naudiodon'); + +console.log(portAudio.getDefaultDevices()); +``` + +An example of the output is: + +```js +{ + defaultInputDevice: { + id: 0, + name: 'Built-in Microphone', + maxInputChannels: 2, + maxOutputChannels: 0, + defaultSampleRate: 44100, + defaultLowInputLatency: 0, + defaultLowOutputLatency: 0, + defaultHighInputLatency: 0, + defaultHighOutputLatency: 0, + hostAPIName: 'Core Audio' + }, + defaultOutputDevice: { + id: 1, + name: 'Built-in Output', + maxInputChannels: 0, + maxOutputChannels: 2, + defaultSampleRate: 44100, + defaultLowInputLatency: 0, + defaultLowOutputLatency: 0, + defaultHighInputLatency: 0, + defaultHighOutputLatency: 0, + hostAPIName: 'Core Audio' + } +} +``` + ### Playing audio Playing audio involves streaming audio data to a new instance of `AudioIO` configured with `outOptions` - which returns a Node.js [Writable Stream](https://nodejs.org/dist/latest-v6.x/docs/api/stream.html#stream_writable_streams): diff --git a/binding.gyp b/binding.gyp index b5caf34..58a4859 100644 --- a/binding.gyp +++ b/binding.gyp @@ -7,6 +7,7 @@ "src/naudiodon.cc", "src/GetDevices.cc", "src/GetHostAPIs.cc", + "src/GetDefaultDevices.cc", "src/AudioIO.cc", "src/PaContext.cc" ], diff --git a/index.d.ts b/index.d.ts index 49989f1..c743fbf 100644 --- a/index.d.ts +++ b/index.d.ts @@ -32,6 +32,14 @@ export interface DeviceInfo { /** Get list of supported devices */ export function getDevices(): DeviceInfo[] +export interface DefaultDevices { + defaultInputDevice: DeviceInfo + defaultOutputDevice: DeviceInfo +} + +/** Get default input and output device */ +export function getDefaultDevices(): DefaultDevices + /** The details returned from getHostAPIs for a particular device */ export interface HostInfo { readonly id: number diff --git a/index.js b/index.js index de88bec..6d1642f 100644 --- a/index.js +++ b/index.js @@ -27,6 +27,7 @@ exports.SampleFormat32Bit = 32; exports.getDevices = portAudioBindings.getDevices; exports.getHostAPIs = portAudioBindings.getHostAPIs; +exports.getDefaultDevices = portAudioBindings.getDefaultDevices; function AudioIO(options) { const audioIOAdon = portAudioBindings.create(options); diff --git a/package-lock.json b/package-lock.json index 70e323d..f7b8536 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "naudiodon", - "version": "2.2.5", + "version": "2.3.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/src/GetDefaultDevices.cc b/src/GetDefaultDevices.cc new file mode 100644 index 0000000..72451f3 --- /dev/null +++ b/src/GetDefaultDevices.cc @@ -0,0 +1,87 @@ +/* Copyright 2019 Streampunk Media Ltd. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include "GetDefaultDevices.h" +#include "naudiodonUtil.h" +#include + +namespace streampunk { + +napi_value getDefaultDevices(napi_env env, napi_callback_info info) { + napi_status status; + napi_value result, defaultInputDevice, defaultOutputDevice; + + uint32_t defaultInputDevId; + uint32_t defaultOutputDevId; + + PaError errCode = Pa_Initialize(); + if (errCode != paNoError) + NAPI_THROW_ERROR((std::string("Could not initialize PortAudio: ") + Pa_GetErrorText(errCode)).c_str()); + + defaultInputDevId = (PaDeviceIndex)Pa_GetDefaultInputDevice(); + defaultOutputDevId = (PaDeviceIndex)Pa_GetDefaultOutputDevice(); + + status = napi_create_object(env, &result); + CHECK_STATUS; + + defaultInputDevice = getDeviceInfo(env, defaultInputDevId); + CHECK_STATUS; + status = napi_set_named_property(env, result, "defaultInputDevice", defaultInputDevice); + CHECK_STATUS; + defaultOutputDevice = getDeviceInfo(env, defaultOutputDevId); + CHECK_STATUS; + status = napi_set_named_property(env, result, "defaultOutputDevice", defaultOutputDevice); + CHECK_STATUS; + + Pa_Terminate(); + return result; +} + +napi_value getDeviceInfo(napi_env env, uint32_t id){ + napi_status status; + napi_value devInfo; + + PaError errCode = Pa_Initialize(); + if (errCode != paNoError) + NAPI_THROW_ERROR((std::string("Could not initialize PortAudio: ") + Pa_GetErrorText(errCode)).c_str()); + + const PaDeviceInfo* deviceInfo = Pa_GetDeviceInfo(id); + status = napi_create_object(env, &devInfo); + CHECK_STATUS; + status = naud_set_uint32(env, devInfo, "id", id); + CHECK_STATUS; + status = naud_set_string_utf8(env, devInfo, "name", deviceInfo->name); + CHECK_STATUS; + status = naud_set_uint32(env, devInfo, "maxInputChannels", deviceInfo->maxInputChannels); + CHECK_STATUS; + status = naud_set_uint32(env, devInfo, "maxOutputChannels", deviceInfo->maxOutputChannels); + CHECK_STATUS; + status = naud_set_uint32(env, devInfo, "defaultSampleRate", deviceInfo->defaultSampleRate); + CHECK_STATUS; + status = naud_set_uint32(env, devInfo, "defaultLowInputLatency", deviceInfo->defaultLowInputLatency); + CHECK_STATUS; + status = naud_set_uint32(env, devInfo, "defaultLowOutputLatency", deviceInfo->defaultLowOutputLatency); + CHECK_STATUS; + status = naud_set_uint32(env, devInfo, "defaultHighInputLatency", deviceInfo->defaultHighInputLatency); + CHECK_STATUS; + status = naud_set_uint32(env, devInfo, "defaultHighOutputLatency", deviceInfo->defaultHighOutputLatency); + CHECK_STATUS; + status = naud_set_string_utf8(env, devInfo, "hostAPIName", Pa_GetHostApiInfo(deviceInfo->hostApi)->name); + CHECK_STATUS; + Pa_Terminate(); + + return devInfo; +} +} // namespace streampunk diff --git a/src/GetDefaultDevices.h b/src/GetDefaultDevices.h new file mode 100644 index 0000000..82083fb --- /dev/null +++ b/src/GetDefaultDevices.h @@ -0,0 +1,29 @@ +/* Copyright 2019 Streampunk Media Ltd. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#ifndef GETDEFAULTDEVICES_H +#define GETDEFAULTDEVICES_H + +#include "node_api.h" + +namespace streampunk { + +napi_value getDefaultDevices(napi_env env, napi_callback_info info); +napi_value getDeviceInfo(napi_env env, uint32_t id); + + +} // namespace streampunk + +#endif diff --git a/src/naudiodon.cc b/src/naudiodon.cc index a55ea1a..2f9ee21 100644 --- a/src/naudiodon.cc +++ b/src/naudiodon.cc @@ -18,6 +18,7 @@ #include "GetDevices.h" #include "GetHostAPIs.h" #include "AudioIO.h" +#include "GetDefaultDevices.h" napi_value Create(napi_env env, napi_callback_info info) { napi_status status; @@ -43,9 +44,10 @@ napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor desc[] = { DECLARE_NAPI_METHOD("getDevices", streampunk::getDevices), DECLARE_NAPI_METHOD("getHostAPIs", streampunk::getHostAPIs), - DECLARE_NAPI_METHOD("create", Create) + DECLARE_NAPI_METHOD("create", Create), + DECLARE_NAPI_METHOD("getDefaultDevices", streampunk::getDefaultDevices) }; - status = napi_define_properties(env, exports, 3, desc); + status = napi_define_properties(env, exports, 4, desc); CHECK_STATUS; return exports;