Commit e30bcb13 authored by David Reid's avatar David Reid

Fix re-routing on the WASAPI backend.

parent 7a3b0085
...@@ -6808,7 +6808,8 @@ mal_result mal_device_reinit__wasapi(mal_device* pDevice) ...@@ -6808,7 +6808,8 @@ mal_result mal_device_reinit__wasapi(mal_device* pDevice)
pDevice->wasapi.pAudioClient = data.pAudioClient; pDevice->wasapi.pAudioClient = data.pAudioClient;
pDevice->wasapi.pRenderClient = data.pRenderClient; pDevice->wasapi.pRenderClient = data.pRenderClient;
pDevice->wasapi.pCaptureClient = data.pCaptureClient; pDevice->wasapi.pCaptureClient = data.pCaptureClient;
pDevice->wasapi.isStarted = MAL_FALSE;
pDevice->internalFormat = data.formatOut; pDevice->internalFormat = data.formatOut;
pDevice->internalChannels = data.channelsOut; pDevice->internalChannels = data.channelsOut;
pDevice->internalSampleRate = data.sampleRateOut; pDevice->internalSampleRate = data.sampleRateOut;
...@@ -6817,6 +6818,13 @@ mal_result mal_device_reinit__wasapi(mal_device* pDevice) ...@@ -6817,6 +6818,13 @@ mal_result mal_device_reinit__wasapi(mal_device* pDevice)
pDevice->periods = data.periodsOut; pDevice->periods = data.periodsOut;
mal_strcpy_s(pDevice->name, sizeof(pDevice->name), data.deviceName); mal_strcpy_s(pDevice->name, sizeof(pDevice->name), data.deviceName);
if (pDevice->type == mal_device_type_playback) {
mal_IAudioClient_SetEventHandle((mal_IAudioClient*)pDevice->wasapi.pAudioClient, pDevice->wasapi.hEventPlayback);
}
if (pDevice->type == mal_device_type_capture) {
mal_IAudioClient_SetEventHandle((mal_IAudioClient*)pDevice->wasapi.pAudioClient, pDevice->wasapi.hEventCapture);
}
#if 0 #if 0
mal_IAudioClient_SetEventHandle((mal_IAudioClient*)pDevice->wasapi.pAudioClient, pDevice->wasapi.hEvent); mal_IAudioClient_SetEventHandle((mal_IAudioClient*)pDevice->wasapi.pAudioClient, pDevice->wasapi.hEvent);
#endif #endif
...@@ -6855,6 +6863,7 @@ mal_result mal_device_init__wasapi(mal_context* pContext, mal_device_type type, ...@@ -6855,6 +6863,7 @@ mal_result mal_device_init__wasapi(mal_context* pContext, mal_device_type type,
pDevice->wasapi.pAudioClient = data.pAudioClient; pDevice->wasapi.pAudioClient = data.pAudioClient;
pDevice->wasapi.pRenderClient = data.pRenderClient; pDevice->wasapi.pRenderClient = data.pRenderClient;
pDevice->wasapi.pCaptureClient = data.pCaptureClient; pDevice->wasapi.pCaptureClient = data.pCaptureClient;
pDevice->wasapi.isStarted = MAL_FALSE;
pDevice->internalFormat = data.formatOut; pDevice->internalFormat = data.formatOut;
pDevice->internalChannels = data.channelsOut; pDevice->internalChannels = data.channelsOut;
...@@ -7012,6 +7021,29 @@ mal_result mal_device__get_available_frames__wasapi(mal_device* pDevice, mal_uin ...@@ -7012,6 +7021,29 @@ mal_result mal_device__get_available_frames__wasapi(mal_device* pDevice, mal_uin
return MAL_SUCCESS; return MAL_SUCCESS;
} }
mal_bool32 mal_device_is_reroute_required__wasapi(mal_device* pDevice)
{
mal_assert(pDevice != NULL);
return pDevice->wasapi.hasDefaultDeviceChanged && pDevice->isDefaultDevice;
}
mal_result mal_device_reroute__wasapi(mal_device* pDevice)
{
mal_atomic_exchange_32(&pDevice->wasapi.hasDefaultDeviceChanged, MAL_FALSE);
#ifdef MAL_DEBUG_OUTPUT
printf("=== CHANGING DEVICE ===\n");
#endif
mal_result result = pDevice->pContext->onDeviceReinit(pDevice);
if (result != MAL_SUCCESS) {
return result;
}
mal_device__post_init_setup(pDevice);
return MAL_SUCCESS;
}
mal_result mal_device_write__wasapi(mal_device* pDevice, mal_uint32 pcmFrameCount, const void* pPCMFrames, mal_uint32* pPCMFramesWritten) mal_result mal_device_write__wasapi(mal_device* pDevice, mal_uint32 pcmFrameCount, const void* pPCMFrames, mal_uint32* pPCMFramesWritten)
{ {
...@@ -7093,6 +7125,14 @@ mal_result mal_device_write__wasapi(mal_device* pDevice, mal_uint32 pcmFrameCoun ...@@ -7093,6 +7125,14 @@ mal_result mal_device_write__wasapi(mal_device* pDevice, mal_uint32 pcmFrameCoun
break; break;
} }
/* We may need to reroute the device. */
if (mal_device_is_reroute_required__wasapi(pDevice)) {
result = mal_device_reroute__wasapi(pDevice);
if (result != MAL_SUCCESS) {
break;
}
}
/* The device buffer has become available, so now we need to get a pointer to it. */ /* The device buffer has become available, so now we need to get a pointer to it. */
result = mal_device__get_available_frames__wasapi(pDevice, &pDevice->wasapi.deviceBufferFramesCapacityPlayback); result = mal_device__get_available_frames__wasapi(pDevice, &pDevice->wasapi.deviceBufferFramesCapacityPlayback);
if (result != MAL_SUCCESS) { if (result != MAL_SUCCESS) {
...@@ -7184,6 +7224,14 @@ mal_result mal_device_read__wasapi(mal_device* pDevice, mal_uint32 pcmFrameCount ...@@ -7184,6 +7224,14 @@ mal_result mal_device_read__wasapi(mal_device* pDevice, mal_uint32 pcmFrameCount
break; break;
} }
/* We may need to reroute the device. */
if (mal_device_is_reroute_required__wasapi(pDevice)) {
result = mal_device_reroute__wasapi(pDevice);
if (result != MAL_SUCCESS) {
break;
}
}
/* The device buffer has become available, so now we need to get a pointer to it. */ /* The device buffer has become available, so now we need to get a pointer to it. */
result = mal_device__get_available_frames__wasapi(pDevice, &pDevice->wasapi.deviceBufferFramesCapacityCapture); result = mal_device__get_available_frames__wasapi(pDevice, &pDevice->wasapi.deviceBufferFramesCapacityCapture);
if (result != MAL_SUCCESS) { if (result != MAL_SUCCESS) {
...@@ -19961,35 +20009,6 @@ mal_thread_result MAL_THREADCALL mal_worker_thread(void* pData) ...@@ -19961,35 +20009,6 @@ mal_thread_result MAL_THREADCALL mal_worker_thread(void* pData)
totalFramesProcessed += framesProcessed; totalFramesProcessed += framesProcessed;
} }
/* If something has gone wrong while writing or reading, we can try switching devices. */
if (result != MAL_SUCCESS && pDevice->isDefaultDevice && mal_device__get_state(pDevice) == MAL_STATE_STARTED && pDevice->initConfig.shareMode != mal_share_mode_exclusive) {
/* Here is where we try switching to the new default device. */
mal_result reinitResult = MAL_ERROR;
if (pDevice->pContext->onDeviceReinit) {
reinitResult = pDevice->pContext->onDeviceReinit(pDevice);
} else {
pDevice->pContext->onDeviceStop(pDevice);
mal_device__set_state(pDevice, MAL_STATE_STOPPED);
pDevice->pContext->onDeviceUninit(pDevice);
mal_device__set_state(pDevice, MAL_STATE_UNINITIALIZED);
reinitResult = pDevice->pContext->onDeviceInit(pDevice->pContext, pDevice->type, NULL, &pDevice->initConfig, pDevice);
}
/* Perform the post initialization setup just in case the data conversion pipeline needs to be reinitialized. */
if (reinitResult == MAL_SUCCESS) {
mal_device__post_init_setup(pDevice);
}
/* If reinitialization was successful, loop back to the start. */
if (reinitResult == MAL_SUCCESS) {
mal_device__set_state(pDevice, MAL_STATE_STARTING); /* <-- The device is restarting. */
mal_event_signal(&pDevice->wakeupEvent);
continue;
}
}
/* Get out of the loop if read()/write() returned an error. It probably means the device has been stopped. */ /* Get out of the loop if read()/write() returned an error. It probably means the device has been stopped. */
if (result != MAL_SUCCESS) { if (result != MAL_SUCCESS) {
break; break;
// This test just plays a constant sine wave tone. Mainly intended to check how physically // This test just plays a constant sine wave tone. Mainly intended to check how physically
// unplugging a device while it's playing works. // unplugging a device while it's playing works.
//#define MAL_DEBUG_OUTPUT #define MAL_DEBUG_OUTPUT
#define MINI_AL_IMPLEMENTATION #define MINI_AL_IMPLEMENTATION
#include "../mini_al.h" #include "../mini_al.h"
#include <stdio.h> #include <stdio.h>
...@@ -8,10 +8,11 @@ ...@@ -8,10 +8,11 @@
mal_sine_wave g_sineWave; mal_sine_wave g_sineWave;
mal_event g_stopEvent; mal_event g_stopEvent;
void on_log(mal_context* pContext, mal_device* pDevice, const char* message) void on_log(mal_context* pContext, mal_device* pDevice, mal_uint32 logLevel, const char* message)
{ {
(void)pContext; (void)pContext;
(void)pDevice; (void)pDevice;
(void)logLevel;
printf("%s\n", message); printf("%s\n", message);
} }
...@@ -27,7 +28,7 @@ mal_uint32 on_send(mal_device* pDevice, mal_uint32 frameCount, void* pFramesOut) ...@@ -27,7 +28,7 @@ mal_uint32 on_send(mal_device* pDevice, mal_uint32 frameCount, void* pFramesOut)
mal_assert(pDevice != NULL); mal_assert(pDevice != NULL);
//printf("TESTING: %d\n", frameCount); //printf("TESTING: %d\n", frameCount);
return (mal_uint32)mal_sine_wave_read_ex(&g_sineWave, frameCount, pDevice->channels, mal_stream_layout_interleaved, (float**)&pFramesOut); return (mal_uint32)mal_sine_wave_read_f32_ex(&g_sineWave, frameCount, pDevice->channels, mal_stream_layout_interleaved, (float**)&pFramesOut);
} }
int main() int main()
...@@ -41,12 +42,12 @@ int main() ...@@ -41,12 +42,12 @@ int main()
} }
mal_context_config contextConfig = mal_context_config_init(on_log); mal_context_config contextConfig = mal_context_config_init(on_log);
mal_device_config deviceConfig = mal_device_config_init_playback(mal_format_f32, 0, 48000, on_send); mal_device_config deviceConfig = mal_device_config_init_playback(mal_format_f32, 0, 48000, on_send, NULL);
deviceConfig.onStopCallback = on_stop; deviceConfig.onStopCallback = on_stop;
//deviceConfig.shareMode = mal_share_mode_exclusive; //deviceConfig.shareMode = mal_share_mode_exclusive;
mal_device device; mal_device device;
result = mal_device_init_ex(&backend, 1, &contextConfig, mal_device_type_playback, NULL, &deviceConfig, NULL, &device); result = mal_device_init_ex(&backend, 1, &contextConfig, mal_device_type_playback, NULL, &deviceConfig, &device);
if (result != MAL_SUCCESS) { if (result != MAL_SUCCESS) {
return result; return result;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment