mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-24 09:14:04 +02:00
WASAPI and WinMM: Stop the device an internal error occurs.
This commit is contained in:
@@ -512,6 +512,7 @@ typedef int mal_result;
|
|||||||
#define MAL_INVALID_DEVICE_CONFIG -31
|
#define MAL_INVALID_DEVICE_CONFIG -31
|
||||||
#define MAL_ACCESS_DENIED -32
|
#define MAL_ACCESS_DENIED -32
|
||||||
#define MAL_TOO_LARGE -33
|
#define MAL_TOO_LARGE -33
|
||||||
|
#define MAL_DEVICE_UNAVAILABLE -34
|
||||||
|
|
||||||
// Standard sample rates.
|
// Standard sample rates.
|
||||||
#define MAL_SAMPLE_RATE_8000 8000
|
#define MAL_SAMPLE_RATE_8000 8000
|
||||||
@@ -6467,56 +6468,66 @@ mal_result mal_device__break_main_loop__wasapi(mal_device* pDevice)
|
|||||||
return MAL_SUCCESS;
|
return MAL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
mal_uint32 mal_device__get_available_frames__wasapi(mal_device* pDevice)
|
mal_result mal_device__get_available_frames__wasapi(mal_device* pDevice, mal_uint32* pFrameCount)
|
||||||
{
|
{
|
||||||
mal_assert(pDevice != NULL);
|
mal_assert(pDevice != NULL);
|
||||||
|
mal_assert(pFrameCount != NULL);
|
||||||
|
|
||||||
|
*pFrameCount = 0;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
if (pDevice->type == mal_device_type_playback) {
|
if (pDevice->type == mal_device_type_playback) {
|
||||||
mal_uint32 paddingFramesCount;
|
mal_uint32 paddingFramesCount;
|
||||||
HRESULT hr = mal_IAudioClient_GetCurrentPadding((mal_IAudioClient*)pDevice->wasapi.pAudioClient, &paddingFramesCount);
|
HRESULT hr = mal_IAudioClient_GetCurrentPadding((mal_IAudioClient*)pDevice->wasapi.pAudioClient, &paddingFramesCount);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
return 0;
|
return MAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pDevice->exclusiveMode) {
|
if (pDevice->exclusiveMode) {
|
||||||
return paddingFramesCount;
|
*pFrameCount = paddingFramesCount;
|
||||||
|
return MAL_SUCCESS;
|
||||||
} else {
|
} else {
|
||||||
return pDevice->bufferSizeInFrames - paddingFramesCount;
|
*pFrameCount = pDevice->bufferSizeInFrames - paddingFramesCount;
|
||||||
|
return MAL_SUCCESS;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mal_uint32 framesAvailable;
|
mal_uint32 framesAvailable;
|
||||||
HRESULT hr = mal_IAudioCaptureClient_GetNextPacketSize((mal_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, &framesAvailable);
|
HRESULT hr = mal_IAudioCaptureClient_GetNextPacketSize((mal_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, &framesAvailable);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
return 0;
|
return MAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return framesAvailable;
|
*pFrameCount = framesAvailable;
|
||||||
|
return MAL_SUCCESS;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
mal_uint32 paddingFramesCount;
|
mal_uint32 paddingFramesCount;
|
||||||
HRESULT hr = mal_IAudioClient_GetCurrentPadding((mal_IAudioClient*)pDevice->wasapi.pAudioClient, &paddingFramesCount);
|
HRESULT hr = mal_IAudioClient_GetCurrentPadding((mal_IAudioClient*)pDevice->wasapi.pAudioClient, &paddingFramesCount);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
return 0;
|
return MAL_DEVICE_UNAVAILABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Slightly different rules for exclusive and shared modes.
|
// Slightly different rules for exclusive and shared modes.
|
||||||
if (pDevice->exclusiveMode) {
|
if (pDevice->exclusiveMode) {
|
||||||
return paddingFramesCount;
|
*pFrameCount = paddingFramesCount;
|
||||||
} else {
|
} else {
|
||||||
if (pDevice->type == mal_device_type_playback) {
|
if (pDevice->type == mal_device_type_playback) {
|
||||||
return pDevice->bufferSizeInFrames - paddingFramesCount;
|
*pFrameCount = pDevice->bufferSizeInFrames - paddingFramesCount;
|
||||||
} else {
|
} else {
|
||||||
return paddingFramesCount;
|
*pFrameCount = paddingFramesCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return MAL_SUCCESS;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
mal_uint32 mal_device__wait_for_frames__wasapi(mal_device* pDevice)
|
mal_result mal_device__wait_for_frames__wasapi(mal_device* pDevice, mal_uint32* pFrameCount)
|
||||||
{
|
{
|
||||||
mal_assert(pDevice != NULL);
|
mal_assert(pDevice != NULL);
|
||||||
|
|
||||||
|
mal_result result;
|
||||||
|
|
||||||
while (!pDevice->wasapi.breakFromMainLoop) {
|
while (!pDevice->wasapi.breakFromMainLoop) {
|
||||||
// Wait for a buffer to become available or for the stop event to be signalled.
|
// Wait for a buffer to become available or for the stop event to be signalled.
|
||||||
HANDLE hEvents[2];
|
HANDLE hEvents[2];
|
||||||
@@ -6532,14 +6543,18 @@ mal_uint32 mal_device__wait_for_frames__wasapi(mal_device* pDevice)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
mal_uint32 framesAvailable = mal_device__get_available_frames__wasapi(pDevice);
|
result = mal_device__get_available_frames__wasapi(pDevice, pFrameCount);
|
||||||
if (framesAvailable > 0) {
|
if (result != MAL_SUCCESS) {
|
||||||
return framesAvailable;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*pFrameCount > 0) {
|
||||||
|
return MAL_SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We'll get here if the loop was terminated. Just return whatever's available.
|
// We'll get here if the loop was terminated. Just return whatever's available.
|
||||||
return mal_device__get_available_frames__wasapi(pDevice);
|
return mal_device__get_available_frames__wasapi(pDevice, pFrameCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
mal_result mal_device__main_loop__wasapi(mal_device* pDevice)
|
mal_result mal_device__main_loop__wasapi(mal_device* pDevice)
|
||||||
@@ -6551,14 +6566,19 @@ mal_result mal_device__main_loop__wasapi(mal_device* pDevice)
|
|||||||
|
|
||||||
pDevice->wasapi.breakFromMainLoop = MAL_FALSE;
|
pDevice->wasapi.breakFromMainLoop = MAL_FALSE;
|
||||||
while (!pDevice->wasapi.breakFromMainLoop) {
|
while (!pDevice->wasapi.breakFromMainLoop) {
|
||||||
mal_uint32 framesAvailable = mal_device__wait_for_frames__wasapi(pDevice);
|
mal_uint32 framesAvailable;
|
||||||
|
mal_result result = mal_device__wait_for_frames__wasapi(pDevice, &framesAvailable);
|
||||||
|
if (result != MAL_SUCCESS) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
if (framesAvailable == 0) {
|
if (framesAvailable == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If it's a playback device, don't bother grabbing more data if the device is being stopped.
|
// If it's a playback device, don't bother grabbing more data if the device is being stopped.
|
||||||
if (pDevice->wasapi.breakFromMainLoop && pDevice->type == mal_device_type_playback) {
|
if (pDevice->wasapi.breakFromMainLoop && pDevice->type == mal_device_type_playback) {
|
||||||
return MAL_FALSE;
|
return MAL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pDevice->type == mal_device_type_playback) {
|
if (pDevice->type == mal_device_type_playback) {
|
||||||
@@ -8732,7 +8752,7 @@ mal_result mal_device__main_loop__winmm(mal_device* pDevice)
|
|||||||
MMRESULT resultMM = ((MAL_PFN_waveOutUnprepareHeader)pDevice->pContext->winmm.waveOutUnprepareHeader)((HWAVEOUT)pDevice->winmm.hDevice, &((LPWAVEHDR)pDevice->winmm.pWAVEHDR)[i], sizeof(WAVEHDR));
|
MMRESULT resultMM = ((MAL_PFN_waveOutUnprepareHeader)pDevice->pContext->winmm.waveOutUnprepareHeader)((HWAVEOUT)pDevice->winmm.hDevice, &((LPWAVEHDR)pDevice->winmm.pWAVEHDR)[i], sizeof(WAVEHDR));
|
||||||
if (resultMM != MMSYSERR_NOERROR) {
|
if (resultMM != MMSYSERR_NOERROR) {
|
||||||
mal_post_error(pDevice, MAL_LOG_LEVEL_ERROR, "[WinMM] Failed to unprepare header for playback device in preparation for sending a new block of data to the device for playback.", mal_result_from_MMRESULT(resultMM));
|
mal_post_error(pDevice, MAL_LOG_LEVEL_ERROR, "[WinMM] Failed to unprepare header for playback device in preparation for sending a new block of data to the device for playback.", mal_result_from_MMRESULT(resultMM));
|
||||||
break;
|
return MAL_DEVICE_UNAVAILABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
mal_zero_object(&((LPWAVEHDR)pDevice->winmm.pWAVEHDR)[i]);
|
mal_zero_object(&((LPWAVEHDR)pDevice->winmm.pWAVEHDR)[i]);
|
||||||
@@ -8746,7 +8766,7 @@ mal_result mal_device__main_loop__winmm(mal_device* pDevice)
|
|||||||
resultMM = ((MAL_PFN_waveOutPrepareHeader)pDevice->pContext->winmm.waveOutPrepareHeader)((HWAVEOUT)pDevice->winmm.hDevice, &((LPWAVEHDR)pDevice->winmm.pWAVEHDR)[i], sizeof(WAVEHDR));
|
resultMM = ((MAL_PFN_waveOutPrepareHeader)pDevice->pContext->winmm.waveOutPrepareHeader)((HWAVEOUT)pDevice->winmm.hDevice, &((LPWAVEHDR)pDevice->winmm.pWAVEHDR)[i], sizeof(WAVEHDR));
|
||||||
if (resultMM != MMSYSERR_NOERROR) {
|
if (resultMM != MMSYSERR_NOERROR) {
|
||||||
mal_post_error(pDevice, MAL_LOG_LEVEL_ERROR, "[WinMM] Failed to prepare header for playback device in preparation for sending a new block of data to the device for playback.", mal_result_from_MMRESULT(resultMM));
|
mal_post_error(pDevice, MAL_LOG_LEVEL_ERROR, "[WinMM] Failed to prepare header for playback device in preparation for sending a new block of data to the device for playback.", mal_result_from_MMRESULT(resultMM));
|
||||||
break;
|
return MAL_DEVICE_UNAVAILABLE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Capture.
|
// Capture.
|
||||||
@@ -8758,7 +8778,7 @@ mal_result mal_device__main_loop__winmm(mal_device* pDevice)
|
|||||||
MMRESULT resultMM = ((MAL_PFN_waveInUnprepareHeader)pDevice->pContext->winmm.waveInUnprepareHeader)((HWAVEIN)pDevice->winmm.hDevice, &((LPWAVEHDR)pDevice->winmm.pWAVEHDR)[i], sizeof(WAVEHDR));
|
MMRESULT resultMM = ((MAL_PFN_waveInUnprepareHeader)pDevice->pContext->winmm.waveInUnprepareHeader)((HWAVEIN)pDevice->winmm.hDevice, &((LPWAVEHDR)pDevice->winmm.pWAVEHDR)[i], sizeof(WAVEHDR));
|
||||||
if (resultMM != MMSYSERR_NOERROR) {
|
if (resultMM != MMSYSERR_NOERROR) {
|
||||||
mal_post_error(pDevice, MAL_LOG_LEVEL_ERROR, "[WinMM] Failed to unprepare header for capture device in preparation for adding a new capture buffer for the device.", mal_result_from_MMRESULT(resultMM));
|
mal_post_error(pDevice, MAL_LOG_LEVEL_ERROR, "[WinMM] Failed to unprepare header for capture device in preparation for adding a new capture buffer for the device.", mal_result_from_MMRESULT(resultMM));
|
||||||
break;
|
return MAL_DEVICE_UNAVAILABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
mal_zero_object(&((LPWAVEHDR)pDevice->winmm.pWAVEHDR)[i]);
|
mal_zero_object(&((LPWAVEHDR)pDevice->winmm.pWAVEHDR)[i]);
|
||||||
@@ -8771,7 +8791,7 @@ mal_result mal_device__main_loop__winmm(mal_device* pDevice)
|
|||||||
resultMM = ((MAL_PFN_waveInPrepareHeader)pDevice->pContext->winmm.waveInPrepareHeader)((HWAVEIN)pDevice->winmm.hDevice, &((LPWAVEHDR)pDevice->winmm.pWAVEHDR)[i], sizeof(WAVEHDR));
|
resultMM = ((MAL_PFN_waveInPrepareHeader)pDevice->pContext->winmm.waveInPrepareHeader)((HWAVEIN)pDevice->winmm.hDevice, &((LPWAVEHDR)pDevice->winmm.pWAVEHDR)[i], sizeof(WAVEHDR));
|
||||||
if (resultMM != MMSYSERR_NOERROR) {
|
if (resultMM != MMSYSERR_NOERROR) {
|
||||||
mal_post_error(pDevice, MAL_LOG_LEVEL_ERROR, "[WinMM] Failed to prepare header for capture device in preparation for adding a new capture buffer for the device.", mal_result_from_MMRESULT(resultMM));
|
mal_post_error(pDevice, MAL_LOG_LEVEL_ERROR, "[WinMM] Failed to prepare header for capture device in preparation for adding a new capture buffer for the device.", mal_result_from_MMRESULT(resultMM));
|
||||||
break;
|
return MAL_DEVICE_UNAVAILABLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8791,14 +8811,14 @@ mal_result mal_device__main_loop__winmm(mal_device* pDevice)
|
|||||||
MMRESULT resultMM = ((MAL_PFN_waveOutWrite)pDevice->pContext->winmm.waveOutWrite)((HWAVEOUT)pDevice->winmm.hDevice, &((LPWAVEHDR)pDevice->winmm.pWAVEHDR)[i], sizeof(WAVEHDR));
|
MMRESULT resultMM = ((MAL_PFN_waveOutWrite)pDevice->pContext->winmm.waveOutWrite)((HWAVEOUT)pDevice->winmm.hDevice, &((LPWAVEHDR)pDevice->winmm.pWAVEHDR)[i], sizeof(WAVEHDR));
|
||||||
if (resultMM != MMSYSERR_NOERROR) {
|
if (resultMM != MMSYSERR_NOERROR) {
|
||||||
mal_post_error(pDevice, MAL_LOG_LEVEL_ERROR, "[WinMM] Failed to write data to the internal playback device.", mal_result_from_MMRESULT(resultMM));
|
mal_post_error(pDevice, MAL_LOG_LEVEL_ERROR, "[WinMM] Failed to write data to the internal playback device.", mal_result_from_MMRESULT(resultMM));
|
||||||
break;
|
return MAL_DEVICE_UNAVAILABLE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Capture.
|
// Capture.
|
||||||
MMRESULT resultMM = ((MAL_PFN_waveInAddBuffer)pDevice->pContext->winmm.waveInAddBuffer)((HWAVEIN)pDevice->winmm.hDevice, &((LPWAVEHDR)pDevice->winmm.pWAVEHDR)[i], sizeof(WAVEHDR));
|
MMRESULT resultMM = ((MAL_PFN_waveInAddBuffer)pDevice->pContext->winmm.waveInAddBuffer)((HWAVEIN)pDevice->winmm.hDevice, &((LPWAVEHDR)pDevice->winmm.pWAVEHDR)[i], sizeof(WAVEHDR));
|
||||||
if (resultMM != MMSYSERR_NOERROR) {
|
if (resultMM != MMSYSERR_NOERROR) {
|
||||||
mal_post_error(pDevice, MAL_LOG_LEVEL_ERROR, "[WinMM] Failed to add new capture buffer to the internal capture device.", mal_result_from_MMRESULT(resultMM));
|
mal_post_error(pDevice, MAL_LOG_LEVEL_ERROR, "[WinMM] Failed to add new capture buffer to the internal capture device.", mal_result_from_MMRESULT(resultMM));
|
||||||
break;
|
return MAL_DEVICE_UNAVAILABLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user