mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-22 00:06:59 +02:00
Disable automatic device switching in exclusive mode.
This was causing issues for me on WASAPI where it would return an error indicating that the device was already in use: AUDCLNT_E_DEVICE_IN_USE. If this is a bug in mini_al I'm happy to re-enable this once it's fixed, but I've been unable to figure out what's wrong so far. For consistency I have also disabled the generic automatic device switching feature.
This commit is contained in:
@@ -122,6 +122,9 @@
|
|||||||
// integer samples, interleaved. Let me know if you need non-interleaved and I'll look into it.
|
// integer samples, interleaved. Let me know if you need non-interleaved and I'll look into it.
|
||||||
// - The sndio backend is currently only enabled on OpenBSD builds.
|
// - The sndio backend is currently only enabled on OpenBSD builds.
|
||||||
// - The audio(4) backend is supported on OpenBSD, but you may need to disable sndiod before you can use it.
|
// - The audio(4) backend is supported on OpenBSD, but you may need to disable sndiod before you can use it.
|
||||||
|
// - If you are using the platform's default device, mini_al will try automatically switching the internal
|
||||||
|
// device when the device is unplugged. This feature is disabled when the device is opened in exclusive
|
||||||
|
// mode.
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
@@ -5384,6 +5387,7 @@ typedef mal_int64 MAL_REFERENCE_TIME;
|
|||||||
#define MAL_AUDCLNT_E_INVALID_DEVICE_PERIOD (-2004287456)
|
#define MAL_AUDCLNT_E_INVALID_DEVICE_PERIOD (-2004287456)
|
||||||
#define MAL_AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED (-2004287463)
|
#define MAL_AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED (-2004287463)
|
||||||
#define MAL_AUDCLNT_S_BUFFER_EMPTY (143196161)
|
#define MAL_AUDCLNT_S_BUFFER_EMPTY (143196161)
|
||||||
|
#define MAL_AUDCLNT_E_DEVICE_IN_USE (2290679818)
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
@@ -5957,6 +5961,13 @@ HRESULT mal_IMMNotificationClient_OnDefaultDeviceChanged(mal_IMMNotificationClie
|
|||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Not currently supporting automatic stream routing in exclusive mode. This is not working correctly on my machine due to
|
||||||
|
// AUDCLNT_E_DEVICE_IN_USE errors when reinitializing the device. If this is a bug in mini_al, we can try re-enabling this once
|
||||||
|
// it's fixed.
|
||||||
|
if (pThis->pDevice->exclusiveMode) {
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
// We don't change the device here - we change it in the worker thread to keep synchronization simple. To this I'm just setting a flag to
|
// We don't change the device here - we change it in the worker thread to keep synchronization simple. To this I'm just setting a flag to
|
||||||
// indicate that the default device has changed.
|
// indicate that the default device has changed.
|
||||||
mal_atomic_exchange_32(&pThis->pDevice->wasapi.hasDefaultDeviceChanged, MAL_TRUE);
|
mal_atomic_exchange_32(&pThis->pDevice->wasapi.hasDefaultDeviceChanged, MAL_TRUE);
|
||||||
@@ -6706,6 +6717,8 @@ mal_result mal_device_init_internal__wasapi(mal_context* pContext, mal_device_ty
|
|||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
if (hr == E_ACCESSDENIED) {
|
if (hr == E_ACCESSDENIED) {
|
||||||
errorMsg = "[WASAPI] Failed to initialize device. Access denied.", result = MAL_ACCESS_DENIED;
|
errorMsg = "[WASAPI] Failed to initialize device. Access denied.", result = MAL_ACCESS_DENIED;
|
||||||
|
} else if (hr == MAL_AUDCLNT_E_DEVICE_IN_USE) {
|
||||||
|
errorMsg = "[WASAPI] Failed to initialize device. Device in use.", result = MAL_DEVICE_BUSY;
|
||||||
} else {
|
} else {
|
||||||
errorMsg = "[WASAPI] Failed to initialize device.", result = MAL_FAILED_TO_OPEN_BACKEND_DEVICE;
|
errorMsg = "[WASAPI] Failed to initialize device.", result = MAL_FAILED_TO_OPEN_BACKEND_DEVICE;
|
||||||
}
|
}
|
||||||
@@ -6814,12 +6827,15 @@ mal_result mal_device_reinit__wasapi(mal_device* pDevice)
|
|||||||
// At this point we have some new objects ready to go. We need to uninitialize the previous ones and then set the new ones.
|
// At this point we have some new objects ready to go. We need to uninitialize the previous ones and then set the new ones.
|
||||||
if (pDevice->wasapi.pRenderClient) {
|
if (pDevice->wasapi.pRenderClient) {
|
||||||
mal_IAudioRenderClient_Release((mal_IAudioRenderClient*)pDevice->wasapi.pRenderClient);
|
mal_IAudioRenderClient_Release((mal_IAudioRenderClient*)pDevice->wasapi.pRenderClient);
|
||||||
|
pDevice->wasapi.pRenderClient = NULL;
|
||||||
}
|
}
|
||||||
if (pDevice->wasapi.pCaptureClient) {
|
if (pDevice->wasapi.pCaptureClient) {
|
||||||
mal_IAudioCaptureClient_Release((mal_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient);
|
mal_IAudioCaptureClient_Release((mal_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient);
|
||||||
|
pDevice->wasapi.pCaptureClient = NULL;
|
||||||
}
|
}
|
||||||
if (pDevice->wasapi.pAudioClient) {
|
if (pDevice->wasapi.pAudioClient) {
|
||||||
mal_IAudioClient_Release((mal_IAudioClient*)pDevice->wasapi.pAudioClient);
|
mal_IAudioClient_Release((mal_IAudioClient*)pDevice->wasapi.pAudioClient);
|
||||||
|
pDevice->wasapi.pAudioClient = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
pDevice->wasapi.pAudioClient = data.pAudioClient;
|
pDevice->wasapi.pAudioClient = data.pAudioClient;
|
||||||
@@ -6971,6 +6987,10 @@ mal_result mal_device__stop_backend__wasapi(mal_device* pDevice)
|
|||||||
{
|
{
|
||||||
mal_assert(pDevice != NULL);
|
mal_assert(pDevice != NULL);
|
||||||
|
|
||||||
|
if (pDevice->wasapi.pAudioClient == NULL) {
|
||||||
|
return MAL_DEVICE_NOT_INITIALIZED;
|
||||||
|
}
|
||||||
|
|
||||||
HRESULT hr = mal_IAudioClient_Stop((mal_IAudioClient*)pDevice->wasapi.pAudioClient);
|
HRESULT hr = mal_IAudioClient_Stop((mal_IAudioClient*)pDevice->wasapi.pAudioClient);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
return mal_post_error(pDevice, MAL_LOG_LEVEL_ERROR, "[WASAPI] Failed to stop internal device.", MAL_FAILED_TO_STOP_BACKEND_DEVICE);
|
return mal_post_error(pDevice, MAL_LOG_LEVEL_ERROR, "[WASAPI] Failed to stop internal device.", MAL_FAILED_TO_STOP_BACKEND_DEVICE);
|
||||||
@@ -7060,7 +7080,11 @@ mal_result mal_device__wait_for_frames__wasapi(mal_device* pDevice, mal_uint32*
|
|||||||
if (!needDeviceReinit) {
|
if (!needDeviceReinit) {
|
||||||
result = mal_device__get_available_frames__wasapi(pDevice, pFrameCount);
|
result = mal_device__get_available_frames__wasapi(pDevice, pFrameCount);
|
||||||
if (result != MAL_SUCCESS) {
|
if (result != MAL_SUCCESS) {
|
||||||
needDeviceReinit = MAL_TRUE;
|
if (!pDevice->exclusiveMode) {
|
||||||
|
needDeviceReinit = MAL_TRUE;
|
||||||
|
} else {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19945,7 +19969,7 @@ mal_thread_result MAL_THREADCALL mal_worker_thread(void* pData)
|
|||||||
// Now we just enter the main loop. When the main loop is terminated the device needs to be marked as stopped. This can
|
// Now we just enter the main loop. When the main loop is terminated the device needs to be marked as stopped. This can
|
||||||
// be broken with mal_device__break_main_loop().
|
// be broken with mal_device__break_main_loop().
|
||||||
mal_result mainLoopResult = pDevice->pContext->onDeviceMainLoop(pDevice);
|
mal_result mainLoopResult = pDevice->pContext->onDeviceMainLoop(pDevice);
|
||||||
if (mainLoopResult != MAL_SUCCESS && pDevice->isDefaultDevice && mal_device__get_state(pDevice) == MAL_STATE_STARTED) {
|
if (mainLoopResult != MAL_SUCCESS && pDevice->isDefaultDevice && mal_device__get_state(pDevice) == MAL_STATE_STARTED && !pDevice->exclusiveMode) {
|
||||||
// Something has failed during the main loop. It could be that the device has been lost. If it's the default device,
|
// Something has failed during the main loop. It could be that the device has been lost. If it's the default device,
|
||||||
// we can try switching over to the new default device by uninitializing and reinitializing.
|
// we can try switching over to the new default device by uninitializing and reinitializing.
|
||||||
mal_result reinitResult = MAL_ERROR;
|
mal_result reinitResult = MAL_ERROR;
|
||||||
@@ -28220,10 +28244,10 @@ mal_uint64 mal_sine_wave_read_ex(mal_sine_wave* pSineWave, mal_uint64 frameCount
|
|||||||
// - Automatically switch the internal device when the default device is unplugged. Note that this is still in the
|
// - Automatically switch the internal device when the default device is unplugged. Note that this is still in the
|
||||||
// early stages and not all backends handle this the same way. As of this version, this will not detect a default
|
// early stages and not all backends handle this the same way. As of this version, this will not detect a default
|
||||||
// device switch when changed from the operating system's audio preferences (unless the backend itself handles
|
// device switch when changed from the operating system's audio preferences (unless the backend itself handles
|
||||||
// this automatically).
|
// this automatically). This is not supported in exclusive mode.
|
||||||
// - WASAPI and Core Audio: Add support for stream routing. When the application is using a default device and the
|
// - WASAPI and Core Audio: Add support for stream routing. When the application is using a default device and the
|
||||||
// user switches the default device via the operating system's audio preferences, mini_al will automatically switch
|
// user switches the default device via the operating system's audio preferences, mini_al will automatically switch
|
||||||
// the internal device to the new default.
|
// the internal device to the new default. This is not supported in exclusive mode.
|
||||||
// - WASAPI: Add support for hardware offloading via IAudioClient2. Only supported on Windows 8 and newer.
|
// - WASAPI: Add support for hardware offloading via IAudioClient2. Only supported on Windows 8 and newer.
|
||||||
// - WASAPI: Add support for low-latency shared mode via IAudioClient3. Only supported on Windows 10 and newer.
|
// - WASAPI: Add support for low-latency shared mode via IAudioClient3. Only supported on Windows 10 and newer.
|
||||||
// - Add support for compiling the UWP build as C.
|
// - Add support for compiling the UWP build as C.
|
||||||
|
|||||||
Reference in New Issue
Block a user