mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-22 00:06:59 +02:00
ALSA: Fix an error where restarting a device can fail.
This commit is contained in:
+30
-5
@@ -28024,6 +28024,12 @@ static ma_result ma_device_start__alsa(ma_device* pDevice)
|
|||||||
|
|
||||||
static ma_result ma_device_stop__alsa(ma_device* pDevice)
|
static ma_result ma_device_stop__alsa(ma_device* pDevice)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
The stop callback will get called on the worker thread after read/write__alsa() has returned. At this point there is
|
||||||
|
a small chance that our wakeupfd has not been cleared. We'll clear that out now if applicable.
|
||||||
|
*/
|
||||||
|
int resultPoll;
|
||||||
|
|
||||||
if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
|
if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
|
||||||
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[ALSA] Dropping capture device...\n");
|
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[ALSA] Dropping capture device...\n");
|
||||||
((ma_snd_pcm_drop_proc)pDevice->pContext->alsa.snd_pcm_drop)((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture);
|
((ma_snd_pcm_drop_proc)pDevice->pContext->alsa.snd_pcm_drop)((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture);
|
||||||
@@ -28036,6 +28042,13 @@ static ma_result ma_device_stop__alsa(ma_device* pDevice)
|
|||||||
} else {
|
} else {
|
||||||
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[ALSA] Preparing capture device successful.\n");
|
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[ALSA] Preparing capture device successful.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Clear the wakeupfd. */
|
||||||
|
resultPoll = poll((struct pollfd*)pDevice->alsa.pPollDescriptorsCapture, 1, 0);
|
||||||
|
if (resultPoll > 0) {
|
||||||
|
ma_uint64 t;
|
||||||
|
read(((struct pollfd*)pDevice->alsa.pPollDescriptorsCapture)[0].fd, &t, sizeof(t));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
|
if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
|
||||||
@@ -28050,6 +28063,14 @@ static ma_result ma_device_stop__alsa(ma_device* pDevice)
|
|||||||
} else {
|
} else {
|
||||||
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[ALSA] Preparing playback device successful.\n");
|
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[ALSA] Preparing playback device successful.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Clear the wakeupfd. */
|
||||||
|
resultPoll = poll((struct pollfd*)pDevice->alsa.pPollDescriptorsPlayback, 1, 0);
|
||||||
|
if (resultPoll > 0) {
|
||||||
|
ma_uint64 t;
|
||||||
|
read(((struct pollfd*)pDevice->alsa.pPollDescriptorsPlayback)[0].fd, &t, sizeof(t));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return MA_SUCCESS;
|
return MA_SUCCESS;
|
||||||
@@ -28062,7 +28083,7 @@ static ma_result ma_device_wait__alsa(ma_device* pDevice, ma_snd_pcm_t* pPCM, st
|
|||||||
int resultALSA;
|
int resultALSA;
|
||||||
int resultPoll = poll(pPollDescriptors, pollDescriptorCount, -1);
|
int resultPoll = poll(pPollDescriptors, pollDescriptorCount, -1);
|
||||||
if (resultPoll < 0) {
|
if (resultPoll < 0) {
|
||||||
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[ALSA] poll() failed.");
|
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[ALSA] poll() failed.\n");
|
||||||
return ma_result_from_errno(errno);
|
return ma_result_from_errno(errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28075,7 +28096,7 @@ static ma_result ma_device_wait__alsa(ma_device* pDevice, ma_snd_pcm_t* pPCM, st
|
|||||||
ma_uint64 t;
|
ma_uint64 t;
|
||||||
int resultRead = read(pPollDescriptors[0].fd, &t, sizeof(t)); /* <-- Important that we read here so that the next write() does not block. */
|
int resultRead = read(pPollDescriptors[0].fd, &t, sizeof(t)); /* <-- Important that we read here so that the next write() does not block. */
|
||||||
if (resultRead < 0) {
|
if (resultRead < 0) {
|
||||||
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[ALSA] read() failed.");
|
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[ALSA] read() failed.\n");
|
||||||
return ma_result_from_errno(errno);
|
return ma_result_from_errno(errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28089,13 +28110,17 @@ static ma_result ma_device_wait__alsa(ma_device* pDevice, ma_snd_pcm_t* pPCM, st
|
|||||||
*/
|
*/
|
||||||
resultALSA = ((ma_snd_pcm_poll_descriptors_revents_proc)pDevice->pContext->alsa.snd_pcm_poll_descriptors_revents)(pPCM, pPollDescriptors + 1, pollDescriptorCount - 1, &revents); /* +1, -1 to ignore the wakeup descriptor. */
|
resultALSA = ((ma_snd_pcm_poll_descriptors_revents_proc)pDevice->pContext->alsa.snd_pcm_poll_descriptors_revents)(pPCM, pPollDescriptors + 1, pollDescriptorCount - 1, &revents); /* +1, -1 to ignore the wakeup descriptor. */
|
||||||
if (resultALSA < 0) {
|
if (resultALSA < 0) {
|
||||||
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[ALSA] snd_pcm_poll_descriptors_revents() failed.");
|
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[ALSA] snd_pcm_poll_descriptors_revents() failed.\n");
|
||||||
return ma_result_from_errno(-resultALSA);
|
return ma_result_from_errno(-resultALSA);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((revents & POLLERR) != 0) {
|
if ((revents & POLLERR) != 0) {
|
||||||
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[ALSA] POLLERR detected.");
|
ma_snd_pcm_state_t state = ((ma_snd_pcm_state_proc)pDevice->pContext->alsa.snd_pcm_state)(pPCM);
|
||||||
return ma_result_from_errno(errno);
|
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 {
|
||||||
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((revents & requiredEvent) == requiredEvent) {
|
if ((revents & requiredEvent) == requiredEvent) {
|
||||||
|
|||||||
Reference in New Issue
Block a user