diff --git a/binding/nodejs/src/errors.ts b/binding/nodejs/src/errors.ts index 4282c34..31fb9d8 100644 --- a/binding/nodejs/src/errors.ts +++ b/binding/nodejs/src/errors.ts @@ -15,7 +15,6 @@ import PvSpeakerStatus from "./pv_speaker_status_t"; class PvSpeakerStatusOutOfMemoryError extends Error {} class PvSpeakerStatusInvalidArgumentError extends Error {} class PvSpeakerStatusInvalidStateError extends Error {} -class PvSpeakerStatusOverflowBufferError extends Error {} class PvSpeakerStatusBackendError extends Error {} class PvSpeakerStatusDeviceAlreadyInitializedError extends Error {} class PvSpeakerStatusDeviceNotInitializedError extends Error {} @@ -30,8 +29,6 @@ function pvSpeakerStatusToException(status: PvSpeakerStatus, errorMessage: strin return new PvSpeakerStatusInvalidArgumentError(errorMessage); case PvSpeakerStatus.INVALID_STATE: return new PvSpeakerStatusInvalidStateError(errorMessage); - case PvSpeakerStatus.OVERFLOW_BUFFER: - return new PvSpeakerStatusOverflowBufferError(errorMessage); case PvSpeakerStatus.BACKEND_ERROR: return new PvSpeakerStatusBackendError(errorMessage); case PvSpeakerStatus.DEVICE_ALREADY_INITIALIZED: diff --git a/binding/nodejs/src/pv_speaker.ts b/binding/nodejs/src/pv_speaker.ts index 587ae90..88bc837 100644 --- a/binding/nodejs/src/pv_speaker.ts +++ b/binding/nodejs/src/pv_speaker.ts @@ -27,7 +27,7 @@ class PvSpeaker { private readonly _handle: number; private readonly _sampleRate: number; private readonly _bitsPerSample: number; - private readonly _frameLength: number; + private readonly _bufferSizeSecs: number; private readonly _version: string; /** @@ -35,25 +35,25 @@ class PvSpeaker { * * @param sampleRate The sample rate of the audio to be played. * @param bitsPerSample The number of bits per sample. - * @param deviceIndex The audio device index to use to play audio. A value of (-1) will use machine's default audio device. - * @param frameLength Length of the audio frames to send per write call. - * @param bufferedFramesCount The number of audio frames buffered internally for writing - i.e. internal circular buffer - * will be of size `frameLength` * `bufferedFramesCount`. If this value is too low, buffer overflows could occur - * and audio frames could be dropped. A higher value will increase memory usage. + * @param options Optional configuration arguments. + * @param options.bufferSizeSecs The size in seconds of the internal buffer used to buffer PCM data + * - i.e. internal circular buffer will be of size `sampleRate` * `bufferSizeSecs`. + * @param options.deviceIndex The index of the audio device to use. A value of (-1) will resort to default device. */ constructor( sampleRate: number, bitsPerSample: number, - deviceIndex: number = -1, - frameLength: number = 512, - bufferedFramesCount = 50, + options: { + bufferSizeSecs?: number; + deviceIndex?: number; + } = {} ) { let pvSpeakerHandleAndStatus; + const { bufferSizeSecs = 20, deviceIndex = -1 } = options; try { - pvSpeakerHandleAndStatus = PvSpeaker._pvSpeaker.init( - sampleRate, bitsPerSample, deviceIndex, frameLength, bufferedFramesCount); + pvSpeakerHandleAndStatus = PvSpeaker._pvSpeaker.init(sampleRate, bitsPerSample, bufferSizeSecs, deviceIndex); } catch (err: any) { - pvSpeakerStatusToException(err.code, err); + throw pvSpeakerStatusToException(err.code, err); } const status = pvSpeakerHandleAndStatus.status; if (status !== PvSpeakerStatus.SUCCESS) { @@ -62,7 +62,7 @@ class PvSpeaker { this._handle = pvSpeakerHandleAndStatus.handle; this._sampleRate = sampleRate; this._bitsPerSample = bitsPerSample; - this._frameLength = frameLength; + this._bufferSizeSecs = bufferSizeSecs; this._version = PvSpeaker._pvSpeaker.version(); } @@ -81,10 +81,10 @@ class PvSpeaker { } /** - * @returns Length of the audio frames to send per write call. + * @returns The size in seconds of the internal buffer used to buffer PCM data. */ - get frameLength(): number { - return this._frameLength; + get bufferSizeSecs(): number { + return this._bufferSizeSecs; } /** @@ -95,14 +95,14 @@ class PvSpeaker { } /** - * @returns Whether PvSpeaker has started and is available to receive pcm frames or not. + * @returns Whether PvSpeaker has started and is available to receive PCM frames or not. */ get isStarted(): boolean { return PvSpeaker._pvSpeaker.get_is_started(this._handle); } /** - * Starts the audio output device. After starting, pcm frames can be sent to the audio output device via `write`. + * Starts the audio output device. After starting, PCM frames can be sent to the audio output device via `write`. */ public start(): void { const status = PvSpeaker._pvSpeaker.start(this._handle); @@ -122,34 +122,34 @@ class PvSpeaker { } /** - * Synchronous call to write a frame of audio data. + * Synchronous call to write PCM data to the internal circular buffer for audio playback. + * Only writes as much PCM data as the internal circular buffer can currently fit, and + * returns the length of the PCM data that was successfully written. * - * @returns {Boolean} + * @returns {number} */ - public write(pcm: ArrayBuffer): void { - let i = 0; - const frameLength = this._frameLength * this._bitsPerSample / 8; - while (i < pcm.byteLength) { - const isLastFrame = i + frameLength >= pcm.byteLength; - const writeFrameLength = isLastFrame ? pcm.byteLength - i : frameLength; - const frame = pcm.slice(i, i + writeFrameLength); - const status = PvSpeaker._pvSpeaker.write(this._handle, this._bitsPerSample, frame); - if (status !== PvSpeakerStatus.SUCCESS) { - throw pvSpeakerStatusToException(status, "PvSpeaker failed to write audio data frame."); - } - - i += frameLength; + public write(pcm: ArrayBuffer): number { + const result = PvSpeaker._pvSpeaker.write(this._handle, this._bitsPerSample, pcm); + if (result.status !== PvSpeakerStatus.SUCCESS) { + throw pvSpeakerStatusToException(result.status, "PvSpeaker failed to write audio data frame."); } + + return result.written_length; } /** - * Enable or disable debug logging for PvSpeaker. Debug logs will indicate when there are overflows in the internal - * frame buffer and when an audio source is generating frames of silence. + * Synchronous call to write PCM data to the internal circular buffer for audio playback. + * This call blocks the thread until all PCM data has been successfully written and played. * - * @param isDebugLoggingEnabled Boolean indicating whether the debug logging is enabled or disabled. + * @returns {number} */ - public setDebugLogging(isDebugLoggingEnabled: boolean): void { - PvSpeaker._pvSpeaker.set_debug_logging(this._handle, isDebugLoggingEnabled); + public flush(pcm: ArrayBuffer = new ArrayBuffer(0)): number { + const result = PvSpeaker._pvSpeaker.flush(this._handle, this._bitsPerSample, pcm); + if (result.status !== PvSpeakerStatus.SUCCESS) { + throw pvSpeakerStatusToException(result.status, "PvSpeaker failed to flush audio data frame."); + } + + return result.written_length; } /** diff --git a/binding/nodejs/src/pv_speaker_status_t.ts b/binding/nodejs/src/pv_speaker_status_t.ts index 4822525..dd89e1c 100644 --- a/binding/nodejs/src/pv_speaker_status_t.ts +++ b/binding/nodejs/src/pv_speaker_status_t.ts @@ -15,7 +15,6 @@ enum PvSpeakerStatus { OUT_OF_MEMORY, INVALID_ARGUMENT, INVALID_STATE, - OVERFLOW_BUFFER, BACKEND_ERROR, DEVICE_ALREADY_INITIALIZED, DEVICE_NOT_INITIALIZED, diff --git a/binding/nodejs/test/pv_speaker.test.ts b/binding/nodejs/test/pv_speaker.test.ts index ab8e9a7..f3c2011 100644 --- a/binding/nodejs/test/pv_speaker.test.ts +++ b/binding/nodejs/test/pv_speaker.test.ts @@ -2,50 +2,63 @@ import { PvSpeaker } from "../src"; const SAMPLE_RATE = 22050; const BITS_PER_SAMPLE = 16; -const FRAME_LENGTH = 512; +const BUFFER_SIZE_SECS = 10; describe("Test PvSpeaker", () => { - test("invalid device index", () => { - const f = () => { - new PvSpeaker(SAMPLE_RATE, BITS_PER_SAMPLE, -2); - }; - - expect(f).toThrow(Error); + test("invalid sample rate", () => { + expect(() => { + new PvSpeaker(0, BITS_PER_SAMPLE); + }).toThrow(Error); }); - test("invalid frame length", () => { - const f = () => { - new PvSpeaker(SAMPLE_RATE, BITS_PER_SAMPLE, 0, 0); - }; - - expect(f).toThrow(Error); + test("invalid bits per sample", () => { + expect(() => { + new PvSpeaker(SAMPLE_RATE, 0); + }).toThrow(Error); }); - test("invalid buffered frames count", () => { - const f = () => { - new PvSpeaker(SAMPLE_RATE, BITS_PER_SAMPLE, 0, FRAME_LENGTH, 0); - }; + test("invalid buffer size secs", () => { + expect(() => { + new PvSpeaker(SAMPLE_RATE, BITS_PER_SAMPLE, { bufferSizeSecs: 0 }); + }).toThrow(Error); + }); - expect(f).toThrow(Error); + test("invalid device index", () => { + expect(() => { + new PvSpeaker(SAMPLE_RATE, BITS_PER_SAMPLE, { deviceIndex: -2 }); + }).toThrow(Error); }); test("start stop", async () => { - const speaker = new PvSpeaker(SAMPLE_RATE, BITS_PER_SAMPLE); - speaker.start(); - - const f = async () => { - const frames = new Int16Array(FRAME_LENGTH * 2).buffer; - speaker.write(frames); + expect(() => { + const speaker = new PvSpeaker(SAMPLE_RATE, BITS_PER_SAMPLE); + speaker.start(); + const pcm = new ArrayBuffer(SAMPLE_RATE); + speaker.write(pcm); + speaker.flush(pcm); + speaker.flush(); + speaker.stop(); speaker.release(); - } - - expect(f).not.toThrow(Error); + }).not.toThrow(Error); }); - test("set debug logging", () => { - const speaker = new PvSpeaker(SAMPLE_RATE, BITS_PER_SAMPLE); - speaker.setDebugLogging(true); - speaker.setDebugLogging(false); + test("write flow", async () => { + const bufferSizeSecs = 1; + const circularBufferSize = SAMPLE_RATE * bufferSizeSecs; + const bytesPerSample = (BITS_PER_SAMPLE / 8) + const pcm = new ArrayBuffer(circularBufferSize * bytesPerSample + bytesPerSample); + const pcmLength = pcm.byteLength / bytesPerSample; + + const speaker = new PvSpeaker(SAMPLE_RATE, BITS_PER_SAMPLE, { bufferSizeSecs }); + speaker.start(); + + let writeCount = speaker.write(pcm); + expect(writeCount).toBe(circularBufferSize); + writeCount = speaker.flush(pcm); + expect(writeCount).toBe(pcmLength); + writeCount = speaker.flush(); + expect(writeCount).toBe(0); + speaker.release(); }); @@ -90,32 +103,32 @@ describe("Test PvSpeaker", () => { speaker.release(); }); - test("bits per sample", () => { + test("sample rate", () => { const speaker = new PvSpeaker(SAMPLE_RATE, BITS_PER_SAMPLE); - expect(speaker.bitsPerSample).toBeDefined(); - expect(typeof speaker.bitsPerSample).toBe("number"); - expect(speaker.bitsPerSample).toBeGreaterThan(0); + expect(speaker.sampleRate).toBeDefined(); + expect(typeof speaker.sampleRate).toBe("number"); + expect(speaker.sampleRate).toBe(SAMPLE_RATE); speaker.release(); }); - test("sample rate", () => { + test("bits per sample", () => { const speaker = new PvSpeaker(SAMPLE_RATE, BITS_PER_SAMPLE); - expect(speaker.sampleRate).toBeDefined(); - expect(typeof speaker.sampleRate).toBe("number"); - expect(speaker.sampleRate).toBeGreaterThan(0); + expect(speaker.bitsPerSample).toBeDefined(); + expect(typeof speaker.bitsPerSample).toBe("number"); + expect(speaker.bitsPerSample).toBe(BITS_PER_SAMPLE); speaker.release(); }); - test("frame length", () => { - const speaker = new PvSpeaker(SAMPLE_RATE, BITS_PER_SAMPLE); + test("buffer size secs", () => { + const speaker = new PvSpeaker(SAMPLE_RATE, BITS_PER_SAMPLE, { bufferSizeSecs: BUFFER_SIZE_SECS }); - expect(speaker.frameLength).toBeDefined(); - expect(typeof speaker.frameLength).toBe("number"); - expect(speaker.frameLength).toBeGreaterThan(0); + expect(speaker.bufferSizeSecs).toBeDefined(); + expect(typeof speaker.bufferSizeSecs).toBe("number"); + expect(speaker.bufferSizeSecs).toBe(BUFFER_SIZE_SECS); speaker.release(); }); diff --git a/demo/nodejs/demo.js b/demo/nodejs/demo.js index aad094a..b8370f8 100644 --- a/demo/nodejs/demo.js +++ b/demo/nodejs/demo.js @@ -17,28 +17,46 @@ const { program } = require("commander"); const { PvSpeaker } = require("@picovoice/pvspeaker-node"); program -.option( - "-i, --audio_device_index ", - "index of audio device to use to play audio", - Number, - -1 -).option( - "-d, --show_audio_devices", - "show the list of available devices" -).option( - "-p, --input_wav_path ", - "path to PCM WAV file to be played" -); + .option( + "-s, --show_audio_devices", + "show the list of available devices" + ).option( + "-d, --audio_device_index ", + "index of audio device to use to play audio", + Number, + -1 + ).option( + "-i, --input_wav_path ", + "path to PCM WAV file to be played" + ).option( + "-b, --buffer_size_secs ", + "size of internal PCM buffer in seconds", + Number, + 20 + ); if (process.argv.length < 2) { program.help(); } program.parse(process.argv); +function splitList(inputArrayBuffer, maxSublistLength) { + const inputArray = new Uint8Array(inputArrayBuffer); + const result = []; + for (let i = 0; i < inputArray.length; i += maxSublistLength) { + let endIndex = Math.min(i + maxSublistLength, inputArray.length); + const chunk = new Uint8Array(inputArray.slice(i, endIndex)); + result.push(chunk.buffer); + } + + return result; +} + async function runDemo() { - let audioDeviceIndex = program["audio_device_index"]; let showAudioDevices = program["show_audio_devices"]; + let deviceIndex = program["audio_device_index"]; let inputWavPath = program["input_wav_path"]; + let bufferSizeSecs = program["buffer_size_secs"]; if (showAudioDevices) { const devices = PvSpeaker.getAvailableDevices(); @@ -73,22 +91,38 @@ async function runDemo() { const headerSize = 44; const pcmBuffer = wavBuffer.buffer.slice(headerSize); - const speaker = new PvSpeaker(sampleRate, bitsPerSample, audioDeviceIndex); - console.log(`Using PvSpeaker version: ${speaker.version}`); + let speaker = null; + try { + speaker = new PvSpeaker(sampleRate, bitsPerSample, { bufferSizeSecs, deviceIndex }); + console.log(`Using PvSpeaker version: ${speaker.version}`); + console.log(`Using device: ${speaker.getSelectedDevice()}`); - speaker.start(); - console.log(`Using device: ${speaker.getSelectedDevice()}`); + speaker.start(); + + console.log("Playing audio..."); + const bytesPerSample = bitsPerSample / 8; + const pcmList = splitList(pcmBuffer, sampleRate * bytesPerSample); + + pcmList.forEach(pcmSublist => { + let sublistLength = pcmSublist.byteLength / bytesPerSample; + let totalWrittenLength = 0; + while (totalWrittenLength < sublistLength) { + let remainingBuffer = pcmSublist.slice(totalWrittenLength); + let writtenLength = speaker.write(remainingBuffer); + totalWrittenLength += writtenLength; + } + }); + + console.log("Waiting for audio to finish..."); + speaker.flush(); - console.log("Playing audio..."); - try { - speaker.write(pcmBuffer); - speaker.stop(); console.log("Finished playing audio..."); + speaker.stop(); } catch (e) { console.log(e.message); + } finally { + speaker?.release(); } - - speaker.release(); } } diff --git a/project/node/pv_speaker_napi.c b/project/node/pv_speaker_napi.c index f94e531..a51e6d7 100644 --- a/project/node/pv_speaker_napi.c +++ b/project/node/pv_speaker_napi.c @@ -5,8 +5,8 @@ #include "pv_speaker.h" napi_value napi_pv_speaker_init(napi_env env, napi_callback_info info) { - size_t argc = 5; - napi_value args[5]; + size_t argc = 4; + napi_value args[4]; napi_status status = napi_get_cb_info(env, info, &argc, args, NULL, NULL); if (status != napi_ok) { napi_throw_error( @@ -36,43 +36,32 @@ napi_value napi_pv_speaker_init(napi_env env, napi_callback_info info) { return NULL; } - int32_t device_index; - status = napi_get_value_int32(env, args[2], &device_index); - if (status != napi_ok) { - napi_throw_error( - env, - pv_speaker_status_to_string(PV_SPEAKER_STATUS_INVALID_ARGUMENT), - "Unable to get the device index"); - return NULL; - } - - int32_t frame_length; - status = napi_get_value_int32(env, args[3], &frame_length); + int32_t buffer_size_secs; + status = napi_get_value_int32(env, args[2], &buffer_size_secs); if (status != napi_ok) { napi_throw_error( env, pv_speaker_status_to_string(PV_SPEAKER_STATUS_INVALID_ARGUMENT), - "Unable to get the frame length"); + "Unable to get the buffer size secs"); return NULL; } - int32_t buffered_frames_count; - status = napi_get_value_int32(env, args[4], &buffered_frames_count); + int32_t device_index; + status = napi_get_value_int32(env, args[3], &device_index); if (status != napi_ok) { napi_throw_error( env, pv_speaker_status_to_string(PV_SPEAKER_STATUS_INVALID_ARGUMENT), - "Unable to get the buffered frames count"); + "Unable to get the device index"); return NULL; } pv_speaker_t *handle = NULL; pv_speaker_status_t pv_speaker_status = pv_speaker_init( sample_rate, - frame_length, (int16_t) bits_per_sample, + buffer_size_secs, device_index, - buffered_frames_count, &handle); if (pv_speaker_status != PV_SPEAKER_STATUS_SUCCESS) { handle = NULL; @@ -275,34 +264,68 @@ napi_value napi_pv_speaker_write(napi_env env, napi_callback_info info) { return NULL; } - int32_t bytes_per_sample = 1; - if (bits_per_sample == 16) { - bytes_per_sample = 2; - } else if (bits_per_sample == 24) { - bytes_per_sample = 3; - } else if (bits_per_sample == 32) { - bytes_per_sample = 4; + int32_t bytes_per_sample = bits_per_sample / 8; + int32_t written_length = 0; + pv_speaker_status_t pv_speaker_status = pv_speaker_write( + (pv_speaker_t *)(uintptr_t) object_id, + (int8_t *) data, + (int32_t) (byte_length / bytes_per_sample), + &written_length); + + napi_value object_js = NULL; + napi_value status_js = NULL; + napi_value written_length_js = NULL; + const char *ERROR_MSG = "Unable to allocate memory for the write result"; + + status = napi_create_object(env, &object_js); + if (status != napi_ok) { + napi_throw_error( + env, + pv_speaker_status_to_string(PV_SPEAKER_STATUS_RUNTIME_ERROR), + ERROR_MSG); + return NULL; } - pv_speaker_status_t pv_speaker_status = pv_speaker_write( - (pv_speaker_t *)(uintptr_t) object_id, (int32_t) (byte_length / bytes_per_sample), (int8_t *) data); + status = napi_create_int32(env, pv_speaker_status, &status_js); + if (status != napi_ok) { + napi_throw_error( + env, + pv_speaker_status_to_string(PV_SPEAKER_STATUS_RUNTIME_ERROR), + ERROR_MSG); + return NULL; + } + status = napi_set_named_property(env, object_js, "status", status_js); + if (status != napi_ok) { + napi_throw_error( + env, + pv_speaker_status_to_string(PV_SPEAKER_STATUS_RUNTIME_ERROR), + ERROR_MSG); + return NULL; + } - napi_value result; - status = napi_create_int32(env, pv_speaker_status, &result); + status = napi_create_int32(env, written_length, &written_length_js); if (status != napi_ok) { napi_throw_error( env, pv_speaker_status_to_string(PV_SPEAKER_STATUS_RUNTIME_ERROR), - "Unable to allocate memory for the write result"); + ERROR_MSG); + return NULL; + } + status = napi_set_named_property(env, object_js, "written_length", written_length_js); + if (status != napi_ok) { + napi_throw_error( + env, + pv_speaker_status_to_string(PV_SPEAKER_STATUS_RUNTIME_ERROR), + ERROR_MSG); return NULL; } - return result; + return object_js; } -napi_value napi_pv_speaker_get_is_started(napi_env env, napi_callback_info info) { - size_t argc = 1; - napi_value args[1]; +napi_value napi_pv_speaker_flush(napi_env env, napi_callback_info info) { + size_t argc = 3; + napi_value args[3]; napi_status status = napi_get_cb_info(env, info, &argc, args, NULL, NULL); if (status != napi_ok) { napi_throw_error( @@ -323,24 +346,93 @@ napi_value napi_pv_speaker_get_is_started(napi_env env, napi_callback_info info) return NULL; } - bool is_started = pv_speaker_get_is_started((pv_speaker_t *)(uintptr_t) object_id); - - napi_value result; - status = napi_get_boolean(env, is_started, &result); + int32_t bits_per_sample; + status = napi_get_value_int32(env, args[1], &bits_per_sample); if (status != napi_ok) { napi_throw_error( env, pv_speaker_status_to_string(PV_SPEAKER_STATUS_INVALID_ARGUMENT), - "Unable to get is started flag."); + "Unable to get the bits per sample"); return NULL; } - return result; + void* data = NULL; + size_t byte_length = 0; + status = napi_get_arraybuffer_info(env, args[2], &data, &byte_length); + if (status != napi_ok) { + napi_throw_error( + env, + pv_speaker_status_to_string(PV_SPEAKER_STATUS_RUNTIME_ERROR), + "Unable to get buffer"); + return NULL; + } + + if (byte_length == 0) { + int8_t val = 0; + data = &val; + } + int32_t bytes_per_sample = bits_per_sample / 8; + int32_t written_length = 0; + pv_speaker_status_t pv_speaker_status = pv_speaker_flush( + (pv_speaker_t *)(uintptr_t) object_id, + (int8_t *) data, + (int32_t) byte_length / bytes_per_sample, + &written_length); + + napi_value object_js = NULL; + napi_value status_js = NULL; + napi_value written_length_js = NULL; + const char *ERROR_MSG = "Unable to allocate memory for the flush result"; + + status = napi_create_object(env, &object_js); + if (status != napi_ok) { + napi_throw_error( + env, + pv_speaker_status_to_string(PV_SPEAKER_STATUS_RUNTIME_ERROR), + ERROR_MSG); + return NULL; + } + + status = napi_create_int32(env, pv_speaker_status, &status_js); + if (status != napi_ok) { + napi_throw_error( + env, + pv_speaker_status_to_string(PV_SPEAKER_STATUS_RUNTIME_ERROR), + ERROR_MSG); + return NULL; + } + status = napi_set_named_property(env, object_js, "status", status_js); + if (status != napi_ok) { + napi_throw_error( + env, + pv_speaker_status_to_string(PV_SPEAKER_STATUS_RUNTIME_ERROR), + ERROR_MSG); + return NULL; + } + + status = napi_create_int32(env, written_length, &written_length_js); + if (status != napi_ok) { + napi_throw_error( + env, + pv_speaker_status_to_string(PV_SPEAKER_STATUS_RUNTIME_ERROR), + ERROR_MSG); + return NULL; + } + status = napi_set_named_property(env, object_js, "written_length", written_length_js); + if (status != napi_ok) { + napi_throw_error( + env, + pv_speaker_status_to_string(PV_SPEAKER_STATUS_RUNTIME_ERROR), + ERROR_MSG); + return NULL; + } + + return object_js; } -napi_value napi_pv_speaker_set_debug_logging(napi_env env, napi_callback_info info) { - size_t argc = 2; - napi_value args[2]; +napi_value napi_pv_speaker_get_is_started(napi_env env, napi_callback_info info) { + size_t argc = 1; + napi_value args[1]; napi_status status = napi_get_cb_info(env, info, &argc, args, NULL, NULL); if (status != napi_ok) { napi_throw_error( @@ -361,21 +453,21 @@ napi_value napi_pv_speaker_set_debug_logging(napi_env env, napi_callback_info in return NULL; } - bool is_debug_logging_enabled; - status = napi_get_value_bool(env, args[1], &is_debug_logging_enabled); + bool is_started = pv_speaker_get_is_started((pv_speaker_t *)(uintptr_t) object_id); + + napi_value result; + status = napi_get_boolean(env, is_started, &result); if (status != napi_ok) { napi_throw_error( env, pv_speaker_status_to_string(PV_SPEAKER_STATUS_INVALID_ARGUMENT), - "Unable to get debug logging flag"); + "Unable to get is started flag."); return NULL; } - pv_speaker_set_debug_logging((pv_speaker_t *)(uintptr_t) object_id, is_debug_logging_enabled); - return NULL; + return result; } - napi_value napi_pv_speaker_get_selected_device(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1]; @@ -505,11 +597,11 @@ napi_value Init(napi_env env, napi_value exports) { status = napi_define_properties(env, exports, 1, &desc); assert(status == napi_ok); - desc = DECLARE_NAPI_METHOD("get_is_started", napi_pv_speaker_get_is_started); + desc = DECLARE_NAPI_METHOD("flush", napi_pv_speaker_flush); status = napi_define_properties(env, exports, 1, &desc); assert(status == napi_ok); - desc = DECLARE_NAPI_METHOD("set_debug_logging", napi_pv_speaker_set_debug_logging); + desc = DECLARE_NAPI_METHOD("get_is_started", napi_pv_speaker_get_is_started); status = napi_define_properties(env, exports, 1, &desc); assert(status == napi_ok);