From 16327bff8a5924c4475c20c61485ffc589efb2e5 Mon Sep 17 00:00:00 2001 From: Marcelo Fernandez Date: Tue, 31 Oct 2017 13:07:35 -0300 Subject: [PATCH] Improved WASAPI driver logic when devices are connected or disconnected --- drivers/wasapi/audio_driver_wasapi.cpp | 53 +++++++++++++++++++------- drivers/wasapi/audio_driver_wasapi.h | 2 +- servers/audio_server.cpp | 2 +- 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/drivers/wasapi/audio_driver_wasapi.cpp b/drivers/wasapi/audio_driver_wasapi.cpp index eb86491dece..0671ee408ec 100644 --- a/drivers/wasapi/audio_driver_wasapi.cpp +++ b/drivers/wasapi/audio_driver_wasapi.cpp @@ -39,7 +39,7 @@ const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator); const IID IID_IAudioClient = __uuidof(IAudioClient); const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient); -Error AudioDriverWASAPI::init_device() { +Error AudioDriverWASAPI::init_device(bool reinit) { WAVEFORMATEX *pwfex; IMMDeviceEnumerator *enumerator = NULL; @@ -51,10 +51,24 @@ Error AudioDriverWASAPI::init_device() { ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); hr = enumerator->GetDefaultAudioEndpoint(eRender, eConsole, &device); - ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); + if (reinit) { + // In case we're trying to re-initialize the device prevent throwing this error on the console, + // otherwise if there is currently no devie available this will spam the console. + if (hr != S_OK) { + return ERR_CANT_OPEN; + } + } else { + ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); + } hr = device->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void **)&audio_client); - ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); + if (reinit) { + if (hr != S_OK) { + return ERR_CANT_OPEN; + } + } else { + ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); + } hr = audio_client->GetMixFormat(&pwfex); ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); @@ -152,7 +166,9 @@ Error AudioDriverWASAPI::finish_device() { Error AudioDriverWASAPI::init() { Error err = init_device(); - ERR_FAIL_COND_V(err != OK, err); + if (err != OK) { + ERR_PRINT("WASAPI: init_device error"); + } active = false; exit_thread = false; @@ -209,7 +225,7 @@ void AudioDriverWASAPI::thread_func(void *p_udata) { unsigned int left_frames = ad->buffer_frames; unsigned int buffer_idx = 0; - while (left_frames > 0) { + while (left_frames > 0 && ad->audio_client) { WaitForSingleObject(ad->event, 1000); UINT32 cur_frames; @@ -271,9 +287,9 @@ void AudioDriverWASAPI::thread_func(void *p_udata) { } else if (hr == AUDCLNT_E_DEVICE_INVALIDATED) { // Device is not valid anymore, reopen it - Error err = ad->reopen(); + Error err = ad->finish_device(); if (err != OK) { - ad->exit_thread = true; + ERR_PRINT("WASAPI: finish_device error"); } else { // We reopened the device and samples_in may have resized, so invalidate the current left_frames left_frames = 0; @@ -285,9 +301,9 @@ void AudioDriverWASAPI::thread_func(void *p_udata) { } else if (hr == AUDCLNT_E_DEVICE_INVALIDATED) { // Device is not valid anymore, reopen it - Error err = ad->reopen(); + Error err = ad->finish_device(); if (err != OK) { - ad->exit_thread = true; + ERR_PRINT("WASAPI: finish_device error"); } else { // We reopened the device and samples_in may have resized, so invalidate the current left_frames left_frames = 0; @@ -296,6 +312,13 @@ void AudioDriverWASAPI::thread_func(void *p_udata) { ERR_PRINT("WASAPI: GetCurrentPadding error"); } } + + if (!ad->audio_client) { + Error err = ad->init_device(true); + if (err == OK) { + ad->start(); + } + } } ad->thread_exited = true; @@ -303,11 +326,13 @@ void AudioDriverWASAPI::thread_func(void *p_udata) { void AudioDriverWASAPI::start() { - HRESULT hr = audio_client->Start(); - if (hr != S_OK) { - ERR_PRINT("WASAPI: Start failed"); - } else { - active = true; + if (audio_client) { + HRESULT hr = audio_client->Start(); + if (hr != S_OK) { + ERR_PRINT("WASAPI: Start failed"); + } else { + active = true; + } } } diff --git a/drivers/wasapi/audio_driver_wasapi.h b/drivers/wasapi/audio_driver_wasapi.h index fab8ab32509..87a2db724c7 100644 --- a/drivers/wasapi/audio_driver_wasapi.h +++ b/drivers/wasapi/audio_driver_wasapi.h @@ -64,7 +64,7 @@ class AudioDriverWASAPI : public AudioDriver { static void thread_func(void *p_udata); - Error init_device(); + Error init_device(bool reinit = false); Error finish_device(); Error reopen(); diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index 18b70145952..697abead687 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -226,7 +226,7 @@ void AudioServer::_driver_process(int p_frames, int32_t *p_buffer) { static int total = 0; ticks = OS::get_singleton()->get_ticks_msec(); - if ((ticks - first_ticks) > 10 * 1000) { + if ((ticks - first_ticks) > 10 * 1000 && count > 0) { print_line("Audio Driver " + String(AudioDriver::get_singleton()->get_name()) + " average latency: " + itos(total / count) + "ms (frame=" + itos(p_frames) + ")"); first_ticks = ticks; total = 0;