Skip to content

Commit

Permalink
PulseAudio: Experimental fix for a deadlock with PulseAudio.
Browse files Browse the repository at this point in the history
  • Loading branch information
mackron committed Apr 7, 2019
1 parent 83a879d commit dea8309
Showing 1 changed file with 19 additions and 1 deletion.
20 changes: 19 additions & 1 deletion miniaudio.h
Original file line number Diff line number Diff line change
Expand Up @@ -14776,6 +14776,10 @@ ma_result ma_device_read__pulse(ma_device* pDevice, void* pPCMFrames, ma_uint32

ma_uint32 totalFramesRead = 0;
while (totalFramesRead < frameCount) {
if (ma_device__get_state(pDevice) != MA_STATE_STARTED) {
break;
}

/* If a buffer is mapped we need to write to that first. Once it's consumed we reset the event and unmap it. */
if (pDevice->pulse.pMappedBufferCapture != NULL && pDevice->pulse.mappedBufferFramesRemainingCapture > 0) {
ma_uint32 bpf = ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
Expand Down Expand Up @@ -14825,6 +14829,10 @@ ma_result ma_device_read__pulse(ma_device* pDevice, void* pPCMFrames, ma_uint32
for (;;) {
//printf("TRACE: Inner loop.\n");

if (ma_device__get_state(pDevice) != MA_STATE_STARTED) {
break;
}

/* If the device has been corked, don't try to continue. */
if (((ma_pa_stream_is_corked_proc)pDevice->pContext->pulse.pa_stream_is_corked)((ma_pa_stream*)pDevice->pulse.pStreamCapture)) {
break;
Expand Down Expand Up @@ -14860,11 +14868,21 @@ ma_result ma_device_read__pulse(ma_device* pDevice, void* pPCMFrames, ma_uint32
printf("TRACE: Capture: pa_mainloop_iterate(). readableSizeInBytes=%ld\n", readableSizeInBytes);
#endif

int error = ((ma_pa_mainloop_iterate_proc)pDevice->pContext->pulse.pa_mainloop_iterate)((ma_pa_mainloop*)pDevice->pulse.pMainLoop, 1, NULL);
/*
I have had reports of a deadlock in this part of the code. I have reproduced this when using the "Built-in Audio Analogue Stereo" device without
an actual microphone connected. I'm experimenting here by not blocking in pa_mainloop_iterate() and instead sleep for a bit when there are not
dispatches.
*/
int error = ((ma_pa_mainloop_iterate_proc)pDevice->pContext->pulse.pa_mainloop_iterate)((ma_pa_mainloop*)pDevice->pulse.pMainLoop, 0, NULL);
if (error < 0) {
return ma_result_from_pulse(error);
}

/* Sleep for a bit if nothing was dispatched. */
if (error == 0) {
ma_sleep(1);
}

continue;
}
} else {
Expand Down

0 comments on commit dea8309

Please sign in to comment.