diff --git a/extras/backends/sdl/backend_sdl.c b/extras/backends/sdl/backend_sdl.c index 1fcfdb41..9471e27d 100644 --- a/extras/backends/sdl/backend_sdl.c +++ b/extras/backends/sdl/backend_sdl.c @@ -169,7 +169,7 @@ static ma_device_state_sdl* ma_device_get_backend_state__sdl(ma_device* pDevice) } -static ma_result ma_device_step__sdl(ma_device* pDevice); +static ma_result ma_device_step__sdl(ma_device* pDevice, ma_blocking_mode blockingMode); static void ma_backend_info__sdl(ma_device_backend_info* pBackendInfo) @@ -562,7 +562,7 @@ static ma_result ma_device_start__sdl(ma_device* pDevice) ma_device_type deviceType = ma_device_get_type(pDevice); /* Step the device once to ensure buffers are pre-filled before starting. */ - ma_device_step__sdl(pDevice); + ma_device_step__sdl(pDevice, MA_BLOCKING_MODE_NON_BLOCKING); if (deviceType == ma_device_type_capture || deviceType == ma_device_type_duplex) { pContextStateSDL->SDL_PauseAudioDevice(pDeviceStateSDL->capture.deviceID, 0); @@ -593,18 +593,39 @@ static ma_result ma_device_stop__sdl(ma_device* pDevice) } -static ma_result ma_device_wait__sdl(ma_device* pDevice) +static ma_result ma_device_step__sdl(ma_device* pDevice, ma_blocking_mode blockingMode) { ma_device_state_sdl* pDeviceStateSDL = ma_device_get_backend_state__sdl(pDevice); - ma_device_state_async_wait(&pDeviceStateSDL->async); - return MA_SUCCESS; -} + for (;;) { + ma_result result; + + if (blockingMode == MA_BLOCKING_MODE_BLOCKING) { + ma_device_state_async_wait(&pDeviceStateSDL->async); + } + + if (!ma_device_is_started(pDevice)) { + return MA_DEVICE_NOT_STARTED; + } + + result = ma_device_state_async_step(&pDeviceStateSDL->async, pDevice); + if (result == MA_SUCCESS) { + break; + } + + if (result != MA_NO_DATA_AVAILABLE) { + return result; + } + + /* Getting here means no data was processed. In non-blocking mode we don't care, just get out of the loop. */ + if (blockingMode == MA_BLOCKING_MODE_NON_BLOCKING) { + break; + } + + /* Getting here means we're in blocking mode and no data was processed. In this case we'd rather keep waiting for data to be available. */ + continue; + } -static ma_result ma_device_step__sdl(ma_device* pDevice) -{ - ma_device_state_sdl* pDeviceStateSDL = ma_device_get_backend_state__sdl(pDevice); - ma_device_state_async_step(&pDeviceStateSDL->async, pDevice); return MA_SUCCESS; } @@ -612,23 +633,19 @@ static ma_result ma_device_step__sdl(ma_device* pDevice) static void ma_device_loop__sdl(ma_device* pDevice) { for (;;) { - ma_result result = ma_device_wait__sdl(pDevice); - if (result != MA_SUCCESS) { - break; - } - - /* If the wait terminated due to the device being stopped, abort now. */ - if (!ma_device_is_started(pDevice)) { - break; - } - - result = ma_device_step__sdl(pDevice); + ma_result result = ma_device_step__sdl(pDevice, MA_BLOCKING_MODE_BLOCKING); if (result != MA_SUCCESS) { break; } } } +static void ma_device_wake__sdl(ma_device* pDevice) +{ + ma_device_state_sdl* pDeviceStateSDL = ma_device_get_backend_state__sdl(pDevice); + ma_device_state_async_release(&pDeviceStateSDL->async); +} + static ma_device_backend_vtable ma_gDeviceBackendVTable_SDL = { @@ -643,7 +660,7 @@ static ma_device_backend_vtable ma_gDeviceBackendVTable_SDL = NULL, /* onDeviceRead */ NULL, /* onDeviceWrite */ ma_device_loop__sdl, - NULL /* onDeviceWakeup */ + ma_device_wake__sdl }; ma_device_backend_vtable* ma_device_backend_sdl = &ma_gDeviceBackendVTable_SDL; diff --git a/miniaudio.h b/miniaudio.h index 92d9204a..79537d46 100644 --- a/miniaudio.h +++ b/miniaudio.h @@ -9522,8 +9522,9 @@ typedef struct ma_device_state_async MA_API ma_result ma_device_state_async_init(ma_device_type deviceType, const ma_device_descriptor* pDescriptorPlayback, const ma_device_descriptor* pDescriptorCapture, const ma_allocation_callbacks* pAllocationCallbacks, ma_device_state_async* pAsyncDeviceState); MA_API void ma_device_state_async_uninit(ma_device_state_async* pAsyncDeviceState, const ma_allocation_callbacks* pAllocationCallbacks); MA_API ma_result ma_device_state_async_resize(ma_device_state_async* pAsyncDeviceState, ma_uint32 sizeInFramesPlayback, ma_uint32 sizeInFramesCapture, const ma_allocation_callbacks* pAllocationCallbacks); +MA_API void ma_device_state_async_release(ma_device_state_async* pAsyncDeviceState); MA_API void ma_device_state_async_wait(ma_device_state_async* pAsyncDeviceState); -MA_API void ma_device_state_async_step(ma_device_state_async* pAsyncDeviceState, ma_device* pDevice); +MA_API ma_result ma_device_state_async_step(ma_device_state_async* pAsyncDeviceState, ma_device* pDevice); /* Returns MA_SUCCESS if some data was processed, MA_NO_DATA_AVAILABLE if no data was processed. */ MA_API void ma_device_state_async_process(ma_device_state_async* pAsyncDeviceState, ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount); /* END ma_device_state_async.h */ @@ -46235,6 +46236,21 @@ MA_API ma_result ma_device_state_async_resize(ma_device_state_async* pAsyncDevic return MA_SUCCESS; } +MA_API void ma_device_state_async_release(ma_device_state_async* pAsyncDeviceState) +{ + if (pAsyncDeviceState == NULL) { + return; + } + + if (pAsyncDeviceState->deviceType == ma_device_type_capture || pAsyncDeviceState->deviceType == ma_device_type_duplex) { + ma_semaphore_release(&pAsyncDeviceState->capture.semaphore); + } + + if (pAsyncDeviceState->deviceType == ma_device_type_playback || pAsyncDeviceState->deviceType == ma_device_type_duplex) { + ma_semaphore_release(&pAsyncDeviceState->playback.semaphore); + } +} + MA_API void ma_device_state_async_wait(ma_device_state_async* pAsyncDeviceState) { if (pAsyncDeviceState == NULL) { @@ -46250,10 +46266,12 @@ MA_API void ma_device_state_async_wait(ma_device_state_async* pAsyncDeviceState) } } -MA_API void ma_device_state_async_step(ma_device_state_async* pAsyncDeviceState, ma_device* pDevice) +MA_API ma_result ma_device_state_async_step(ma_device_state_async* pAsyncDeviceState, ma_device* pDevice) { + ma_result result = MA_NO_DATA_AVAILABLE; + if (pAsyncDeviceState == NULL || pDevice == NULL) { - return; + return MA_INVALID_ARGS; } if (pAsyncDeviceState->deviceType == ma_device_type_capture || pAsyncDeviceState->deviceType == ma_device_type_duplex) { @@ -46262,6 +46280,7 @@ MA_API void ma_device_state_async_step(ma_device_state_async* pAsyncDeviceState, if (pAsyncDeviceState->capture.frameCount > 0) { ma_device_handle_backend_data_callback(pDevice, NULL, pAsyncDeviceState->capture.pBuffer, pAsyncDeviceState->capture.frameCount); pAsyncDeviceState->capture.frameCount = 0; + result = MA_SUCCESS; } } ma_spinlock_unlock(&pAsyncDeviceState->capture.lock); @@ -46275,10 +46294,13 @@ MA_API void ma_device_state_async_step(ma_device_state_async* pAsyncDeviceState, if (pAsyncDeviceState->playback.frameCount < pAsyncDeviceState->playback.frameCap) { ma_device_handle_backend_data_callback(pDevice, ma_offset_ptr(pAsyncDeviceState->playback.pBuffer, bytesPerFrame * pAsyncDeviceState->playback.frameCount), NULL, (pAsyncDeviceState->playback.frameCap - pAsyncDeviceState->playback.frameCount)); pAsyncDeviceState->playback.frameCount = pAsyncDeviceState->playback.frameCap; + result = MA_SUCCESS; } } ma_spinlock_unlock(&pAsyncDeviceState->playback.lock); } + + return result; } MA_API void ma_device_state_async_process(ma_device_state_async* pAsyncDeviceState, ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)