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,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)
|
|||||||
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,
|
|||||||
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
|
|||||||
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
|
|||||||
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
|
|||||||
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)
|
|||||||
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;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// 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 @@
|
|||||||
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)
|
|||||||
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()
|
|||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user