Commit 248fa5c9 authored by David Reid's avatar David Reid

WASAPI: Fix a crash when starting a device while rerouting.

Public issue https://github.com/mackron/miniaudio/issues/582
parent 169a75e1
......@@ -7494,7 +7494,8 @@ struct ma_device
ma_bool8 isDetachedPlayback;
ma_bool8 isDetachedCapture;
ma_wasapi_usage usage;
void *hAvrtHandle;
void* hAvrtHandle;
ma_mutex rerouteLock;
} wasapi;
#endif
#ifdef MA_SUPPORT_DSOUND
......@@ -20434,7 +20435,7 @@ static HRESULT STDMETHODCALLTYPE ma_IMMNotificationClient_OnDefaultDeviceChanged
ma_uint32 previousState = ma_device_get_state(pThis->pDevice);
ma_bool8 restartDevice = MA_FALSE;
if (previousState == ma_device_state_starting) {
if (previousState == ma_device_state_uninitialized || previousState == ma_device_state_starting) {
ma_log_postf(ma_device_get_log(pThis->pDevice), MA_LOG_LEVEL_DEBUG, "[WASAPI] Stream rerouting abandoned because the device is in the process of starting.\n");
return S_OK;
}
......@@ -20445,6 +20446,8 @@ static HRESULT STDMETHODCALLTYPE ma_IMMNotificationClient_OnDefaultDeviceChanged
}
if (pDefaultDeviceID != NULL) { /* <-- The input device ID will be null if there's no other device available. */
ma_mutex_lock(&pThis->pDevice->wasapi.rerouteLock);
{
if (dataFlow == ma_eRender) {
ma_device_reroute__wasapi(pThis->pDevice, ma_device_type_playback);
......@@ -20453,11 +20456,13 @@ static HRESULT STDMETHODCALLTYPE ma_IMMNotificationClient_OnDefaultDeviceChanged
if (pThis->pDevice->type == ma_device_type_duplex && pThis->pDevice->wasapi.isDetachedCapture) {
restartDevice = MA_FALSE; /* It's a duplex device and the capture side is detached. We cannot be restarting the device just yet. */
} else {
}
else {
restartDevice = MA_TRUE; /* It's not a duplex device, or the capture side is also attached so we can go ahead and restart the device. */
}
}
} else {
}
else {
ma_device_reroute__wasapi(pThis->pDevice, (pThis->pDevice->type == ma_device_type_loopback) ? ma_device_type_loopback : ma_device_type_capture);
if (pThis->pDevice->wasapi.isDetachedCapture) {
......@@ -20465,11 +20470,14 @@ static HRESULT STDMETHODCALLTYPE ma_IMMNotificationClient_OnDefaultDeviceChanged
if (pThis->pDevice->type == ma_device_type_duplex && pThis->pDevice->wasapi.isDetachedPlayback) {
restartDevice = MA_FALSE; /* It's a duplex device and the playback side is detached. We cannot be restarting the device just yet. */
} else {
}
else {
restartDevice = MA_TRUE; /* It's not a duplex device, or the playback side is also attached so we can go ahead and restart the device. */
}
}
}
}
ma_mutex_unlock(&pThis->pDevice->wasapi.rerouteLock);
if (restartDevice) {
ma_device_start(pThis->pDevice);
......@@ -22251,6 +22259,8 @@ static ma_result ma_device_init__wasapi(ma_device* pDevice, const ma_device_conf
}
}
ma_mutex_init(&pDevice->wasapi.rerouteLock);
hr = ma_CoCreateInstance(pDevice->pContext, MA_CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, MA_IID_IMMDeviceEnumerator, (void**)&pDeviceEnumerator);
if (FAILED(hr)) {
ma_device_uninit__wasapi(pDevice);
......@@ -22350,9 +22360,10 @@ static ma_result ma_device_reroute__wasapi(ma_device* pDevice, ma_device_type de
}
ma_device__post_init_setup(pDevice, deviceType);
ma_device__on_notification_rerouted(pDevice);
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "=== DEVICE CHANGED ===\n");
return MA_SUCCESS;
}
......@@ -41171,6 +41182,9 @@ MA_API ma_result ma_device_start(ma_device* pDevice)
return MA_SUCCESS; /* Already started. */
}
/* Wait for any rerouting to finish before attempting to start the device. */
ma_mutex_lock(&pDevice->wasapi.rerouteLock);
{
ma_mutex_lock(&pDevice->startStopLock);
{
/* Starting and stopping are wrapped in a mutex which means we can assert that the device is in a stopped or paused state. */
......@@ -41211,6 +41225,8 @@ MA_API ma_result ma_device_start(ma_device* pDevice)
}
}
ma_mutex_unlock(&pDevice->startStopLock);
}
ma_mutex_unlock(&pDevice->wasapi.rerouteLock);
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