mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-21 15:56:58 +02:00
ALSA: Fix a bug where a playback device can fail to start.
This commit is contained in:
@@ -21,6 +21,7 @@ v0.11.22 - TBD
|
||||
* WASAPI: Fix an error when stopping the device where it was possible miniaudio would not wait for the device to be drained due to an error with the wait time calculation.
|
||||
* WASAPI: Fix a COM related crash with device rerouting.
|
||||
* DirectSound: Add support for specifying an explicit window handle for SetCooperativeLevel().
|
||||
* ALSA: Fix a bug where a playback device can fail to start.
|
||||
* ALSA: Fix some warnings relating to unhandled return value of `read()`.
|
||||
* Web: Fix ScriptProcessorNode path when compiling with `--closure=1`. Note that the Audio Worklets path is not currently working due to the callback specified in `emscripten_create_wasm_audio_worklet_processor_async` never getting fired.
|
||||
* Web: Fix an error with the unlocked notification when compiling as C++.
|
||||
|
||||
+17
-4
@@ -28227,7 +28227,21 @@ static ma_result ma_device_start__alsa(ma_device* pDevice)
|
||||
}
|
||||
|
||||
if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
|
||||
/* Don't need to do anything for playback because it'll be started automatically when enough data has been written. */
|
||||
/*
|
||||
When data is written to the device we wait for the device to get ready to receive data with poll(). In my testing
|
||||
I have observed that poll() can sometimes block forever unless the device is started explicitly with snd_pcm_start()
|
||||
or some data is written with snd_pcm_writei().
|
||||
|
||||
To resolve this I've decided to do an explicit start with snd_pcm_start(). The problem with this is that the device
|
||||
is started without any data in the internal buffer which will result in an immediate underrun. If instead we were
|
||||
to call into snd_pcm_writei() in an attempt to prevent the underrun, we would run the risk of a weird deadlock
|
||||
issue as documented inside ma_device_write__alsa().
|
||||
*/
|
||||
resultALSA = ((ma_snd_pcm_start_proc)pDevice->pContext->alsa.snd_pcm_start)((ma_snd_pcm_t*)pDevice->alsa.pPCMPlayback);
|
||||
if (resultALSA < 0) {
|
||||
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[ALSA] Failed to start playback device.");
|
||||
return ma_result_from_errno(-resultALSA);
|
||||
}
|
||||
}
|
||||
|
||||
return MA_SUCCESS;
|
||||
@@ -28288,7 +28302,6 @@ static ma_result ma_device_stop__alsa(ma_device* pDevice)
|
||||
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[ALSA] Failed to read from playback wakeupfd. read() = %d\n", resultRead);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return MA_SUCCESS;
|
||||
@@ -28314,7 +28327,7 @@ static ma_result ma_device_wait__alsa(ma_device* pDevice, ma_snd_pcm_t* pPCM, st
|
||||
|
||||
/*
|
||||
Before checking the ALSA poll descriptor flag we need to check if the wakeup descriptor
|
||||
has had it's POLLIN flag set. If so, we need to actually read the data and then exit
|
||||
has had it's POLLIN flag set. If so, we need to actually read the data and then exit the
|
||||
function. The wakeup descriptor will be the first item in the descriptors buffer.
|
||||
*/
|
||||
if ((pPollDescriptors[0].revents & POLLIN) != 0) {
|
||||
@@ -28343,7 +28356,7 @@ static ma_result ma_device_wait__alsa(ma_device* pDevice, ma_snd_pcm_t* pPCM, st
|
||||
ma_snd_pcm_state_t state = ((ma_snd_pcm_state_proc)pDevice->pContext->alsa.snd_pcm_state)(pPCM);
|
||||
if (state == MA_SND_PCM_STATE_XRUN) {
|
||||
/* The PCM is in a xrun state. This will be recovered from at a higher level. We can disregard this. */
|
||||
} else {
|
||||
} else {
|
||||
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_WARNING, "[ALSA] POLLERR detected. status = %d\n", ((ma_snd_pcm_state_proc)pDevice->pContext->alsa.snd_pcm_state)(pPCM));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user