mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-22 00:06:59 +02:00
Fix re-routing on the WASAPI backend.
This commit is contained in:
@@ -6808,6 +6808,7 @@ mal_result mal_device_reinit__wasapi(mal_device* pDevice)
|
||||
pDevice->wasapi.pAudioClient = data.pAudioClient;
|
||||
pDevice->wasapi.pRenderClient = data.pRenderClient;
|
||||
pDevice->wasapi.pCaptureClient = data.pCaptureClient;
|
||||
pDevice->wasapi.isStarted = MAL_FALSE;
|
||||
|
||||
pDevice->internalFormat = data.formatOut;
|
||||
pDevice->internalChannels = data.channelsOut;
|
||||
@@ -6817,6 +6818,13 @@ mal_result mal_device_reinit__wasapi(mal_device* pDevice)
|
||||
pDevice->periods = data.periodsOut;
|
||||
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
|
||||
mal_IAudioClient_SetEventHandle((mal_IAudioClient*)pDevice->wasapi.pAudioClient, pDevice->wasapi.hEvent);
|
||||
#endif
|
||||
@@ -6855,6 +6863,7 @@ mal_result mal_device_init__wasapi(mal_context* pContext, mal_device_type type,
|
||||
pDevice->wasapi.pAudioClient = data.pAudioClient;
|
||||
pDevice->wasapi.pRenderClient = data.pRenderClient;
|
||||
pDevice->wasapi.pCaptureClient = data.pCaptureClient;
|
||||
pDevice->wasapi.isStarted = MAL_FALSE;
|
||||
|
||||
pDevice->internalFormat = data.formatOut;
|
||||
pDevice->internalChannels = data.channelsOut;
|
||||
@@ -7012,6 +7021,29 @@ mal_result mal_device__get_available_frames__wasapi(mal_device* pDevice, mal_uin
|
||||
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)
|
||||
{
|
||||
@@ -7093,6 +7125,14 @@ mal_result mal_device_write__wasapi(mal_device* pDevice, mal_uint32 pcmFrameCoun
|
||||
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. */
|
||||
result = mal_device__get_available_frames__wasapi(pDevice, &pDevice->wasapi.deviceBufferFramesCapacityPlayback);
|
||||
if (result != MAL_SUCCESS) {
|
||||
@@ -7184,6 +7224,14 @@ mal_result mal_device_read__wasapi(mal_device* pDevice, mal_uint32 pcmFrameCount
|
||||
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. */
|
||||
result = mal_device__get_available_frames__wasapi(pDevice, &pDevice->wasapi.deviceBufferFramesCapacityCapture);
|
||||
if (result != MAL_SUCCESS) {
|
||||
@@ -19961,35 +20009,6 @@ mal_thread_result MAL_THREADCALL mal_worker_thread(void* pData)
|
||||
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. */
|
||||
if (result != MAL_SUCCESS) {
|
||||
break;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// This test just plays a constant sine wave tone. Mainly intended to check how physically
|
||||
// unplugging a device while it's playing works.
|
||||
//#define MAL_DEBUG_OUTPUT
|
||||
#define MAL_DEBUG_OUTPUT
|
||||
#define MINI_AL_IMPLEMENTATION
|
||||
#include "../mini_al.h"
|
||||
#include <stdio.h>
|
||||
@@ -8,10 +8,11 @@
|
||||
mal_sine_wave g_sineWave;
|
||||
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)pDevice;
|
||||
(void)logLevel;
|
||||
printf("%s\n", message);
|
||||
}
|
||||
|
||||
@@ -27,7 +28,7 @@ mal_uint32 on_send(mal_device* pDevice, mal_uint32 frameCount, void* pFramesOut)
|
||||
mal_assert(pDevice != NULL);
|
||||
|
||||
//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()
|
||||
@@ -41,12 +42,12 @@ int main()
|
||||
}
|
||||
|
||||
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.shareMode = mal_share_mode_exclusive;
|
||||
|
||||
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) {
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user