mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-23 00:34:03 +02:00
WASAPI: Try fixing a deadlock in exclusive mode.
Public issue https://github.com/mackron/miniaudio/issues/265
This commit is contained in:
+22
-19
@@ -15165,6 +15165,10 @@ static ma_result ma_device_stop__wasapi(ma_device* pDevice)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef MA_WASAPI_WAIT_TIMEOUT_MILLISECONDS
|
||||||
|
#define MA_WASAPI_WAIT_TIMEOUT_MILLISECONDS 5000
|
||||||
|
#endif
|
||||||
|
|
||||||
static ma_result ma_device_audio_thread__wasapi(ma_device* pDevice)
|
static ma_result ma_device_audio_thread__wasapi(ma_device* pDevice)
|
||||||
{
|
{
|
||||||
ma_result result;
|
ma_result result;
|
||||||
@@ -15231,7 +15235,7 @@ static ma_result ma_device_audio_thread__wasapi(ma_device* pDevice)
|
|||||||
if (pMappedDeviceBufferPlayback == NULL) {
|
if (pMappedDeviceBufferPlayback == NULL) {
|
||||||
/* WASAPI is weird with exclusive mode. You need to wait on the event _before_ querying the available frames. */
|
/* WASAPI is weird with exclusive mode. You need to wait on the event _before_ querying the available frames. */
|
||||||
if (pDevice->playback.shareMode == ma_share_mode_exclusive) {
|
if (pDevice->playback.shareMode == ma_share_mode_exclusive) {
|
||||||
if (WaitForSingleObject(pDevice->wasapi.hEventPlayback, INFINITE) != WAIT_OBJECT_0) {
|
if (WaitForSingleObject(pDevice->wasapi.hEventPlayback, MA_WASAPI_WAIT_TIMEOUT_MILLISECONDS) != WAIT_OBJECT_0) {
|
||||||
return MA_ERROR; /* Wait failed. */
|
return MA_ERROR; /* Wait failed. */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -15255,7 +15259,7 @@ static ma_result ma_device_audio_thread__wasapi(ma_device* pDevice)
|
|||||||
if (framesAvailablePlayback == 0) {
|
if (framesAvailablePlayback == 0) {
|
||||||
/* In exclusive mode we waited at the top. */
|
/* In exclusive mode we waited at the top. */
|
||||||
if (pDevice->playback.shareMode != ma_share_mode_exclusive) {
|
if (pDevice->playback.shareMode != ma_share_mode_exclusive) {
|
||||||
if (WaitForSingleObject(pDevice->wasapi.hEventPlayback, INFINITE) != WAIT_OBJECT_0) {
|
if (WaitForSingleObject(pDevice->wasapi.hEventPlayback, MA_WASAPI_WAIT_TIMEOUT_MILLISECONDS) != WAIT_OBJECT_0) {
|
||||||
return MA_ERROR; /* Wait failed. */
|
return MA_ERROR; /* Wait failed. */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -15280,7 +15284,7 @@ static ma_result ma_device_audio_thread__wasapi(ma_device* pDevice)
|
|||||||
/* Try grabbing some captured data if we haven't already got a mapped buffer. */
|
/* Try grabbing some captured data if we haven't already got a mapped buffer. */
|
||||||
if (pMappedDeviceBufferCapture == NULL) {
|
if (pMappedDeviceBufferCapture == NULL) {
|
||||||
if (pDevice->capture.shareMode == ma_share_mode_shared) {
|
if (pDevice->capture.shareMode == ma_share_mode_shared) {
|
||||||
if (WaitForSingleObject(pDevice->wasapi.hEventCapture, INFINITE) != WAIT_OBJECT_0) {
|
if (WaitForSingleObject(pDevice->wasapi.hEventCapture, MA_WASAPI_WAIT_TIMEOUT_MILLISECONDS) != WAIT_OBJECT_0) {
|
||||||
return MA_ERROR; /* Wait failed. */
|
return MA_ERROR; /* Wait failed. */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -15297,7 +15301,7 @@ static ma_result ma_device_audio_thread__wasapi(ma_device* pDevice)
|
|||||||
if (framesAvailableCapture == 0) {
|
if (framesAvailableCapture == 0) {
|
||||||
/* In exclusive mode we waited at the top. */
|
/* In exclusive mode we waited at the top. */
|
||||||
if (pDevice->capture.shareMode != ma_share_mode_shared) {
|
if (pDevice->capture.shareMode != ma_share_mode_shared) {
|
||||||
if (WaitForSingleObject(pDevice->wasapi.hEventCapture, INFINITE) != WAIT_OBJECT_0) {
|
if (WaitForSingleObject(pDevice->wasapi.hEventCapture, MA_WASAPI_WAIT_TIMEOUT_MILLISECONDS) != WAIT_OBJECT_0) {
|
||||||
return MA_ERROR; /* Wait failed. */
|
return MA_ERROR; /* Wait failed. */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -15540,7 +15544,7 @@ static ma_result ma_device_audio_thread__wasapi(ma_device* pDevice)
|
|||||||
DWORD flagsCapture; /* Passed to IAudioCaptureClient_GetBuffer(). */
|
DWORD flagsCapture; /* Passed to IAudioCaptureClient_GetBuffer(). */
|
||||||
|
|
||||||
/* Wait for data to become available first. */
|
/* Wait for data to become available first. */
|
||||||
if (WaitForSingleObject(pDevice->wasapi.hEventCapture, INFINITE) != WAIT_OBJECT_0) {
|
if (WaitForSingleObject(pDevice->wasapi.hEventCapture, MA_WASAPI_WAIT_TIMEOUT_MILLISECONDS) != WAIT_OBJECT_0) {
|
||||||
exitLoop = MA_TRUE;
|
exitLoop = MA_TRUE;
|
||||||
break; /* Wait failed. */
|
break; /* Wait failed. */
|
||||||
}
|
}
|
||||||
@@ -15637,12 +15641,6 @@ static ma_result ma_device_audio_thread__wasapi(ma_device* pDevice)
|
|||||||
{
|
{
|
||||||
ma_uint32 framesAvailablePlayback;
|
ma_uint32 framesAvailablePlayback;
|
||||||
|
|
||||||
/* Wait for space to become available first. */
|
|
||||||
if (WaitForSingleObject(pDevice->wasapi.hEventPlayback, INFINITE) != WAIT_OBJECT_0) {
|
|
||||||
exitLoop = MA_TRUE;
|
|
||||||
break; /* Wait failed. */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check how much space is available. If this returns 0 we just keep waiting. */
|
/* Check how much space is available. If this returns 0 we just keep waiting. */
|
||||||
result = ma_device__get_available_frames__wasapi(pDevice, (ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback, &framesAvailablePlayback);
|
result = ma_device__get_available_frames__wasapi(pDevice, (ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback, &framesAvailablePlayback);
|
||||||
if (result != MA_SUCCESS) {
|
if (result != MA_SUCCESS) {
|
||||||
@@ -15677,16 +15675,21 @@ static ma_result ma_device_audio_thread__wasapi(ma_device* pDevice)
|
|||||||
}
|
}
|
||||||
|
|
||||||
framesWrittenToPlaybackDevice += framesAvailablePlayback;
|
framesWrittenToPlaybackDevice += framesAvailablePlayback;
|
||||||
|
|
||||||
if (!c89atomic_load_8(&pDevice->wasapi.isStartedPlayback)) {
|
if (!c89atomic_load_8(&pDevice->wasapi.isStartedPlayback)) {
|
||||||
if (pDevice->playback.shareMode == ma_share_mode_exclusive || framesWrittenToPlaybackDevice >= pDevice->playback.internalPeriodSizeInFrames*1) {
|
hr = ma_IAudioClient_Start((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback);
|
||||||
hr = ma_IAudioClient_Start((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback);
|
if (FAILED(hr)) {
|
||||||
if (FAILED(hr)) {
|
ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to start internal playback device.", ma_result_from_HRESULT(hr));
|
||||||
ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to start internal playback device.", ma_result_from_HRESULT(hr));
|
exitLoop = MA_TRUE;
|
||||||
exitLoop = MA_TRUE;
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
c89atomic_exchange_8(&pDevice->wasapi.isStartedPlayback, MA_TRUE);
|
|
||||||
}
|
}
|
||||||
|
c89atomic_exchange_8(&pDevice->wasapi.isStartedPlayback, MA_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure we don't wait on the event before we've started the device or we may end up deadlocking. */
|
||||||
|
if (WaitForSingleObject(pDevice->wasapi.hEventPlayback, MA_WASAPI_WAIT_TIMEOUT_MILLISECONDS) != WAIT_OBJECT_0) {
|
||||||
|
exitLoop = MA_TRUE;
|
||||||
|
break; /* Wait failed. Probably timed out. */
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user