ao_alsa: assume device lost if we couldn't recover after 10 attempts

ALSA API reports -EPIPE even when the the device is lost, which we
currently always assume to be an XRUN. If we assumed XRUN 10 times and
didn't manage to recover, just consider the device lost and try to
reconnect. Allows ao_alsa to recover from alsa server being killed then
reinitialized. And even in the worst case, this should be better than
the status quo of mpv attempting to prepare a PCM device indefinitely
until the user restarts mpv.

This is admittedly not ideal, and I don't think the -EPIPE hack is
necessary anymore, but I can only test on my setup and removing the
'assume -EPIPE is an XRUN' hack might break some setups for whatever
mysterious reasons.
This commit is contained in:
llyyr 2024-09-10 19:04:49 +05:30 committed by sfan5
parent 44da754018
commit a44a726301
1 changed files with 4 additions and 1 deletions

View File

@ -929,7 +929,7 @@ static bool recover_and_get_state(struct ao *ao, struct mp_pcm_state *state)
// Give it a number of chances to recover. This tries to deal with the fact // Give it a number of chances to recover. This tries to deal with the fact
// that the API is asynchronous, and to account for some past cargo-cult // that the API is asynchronous, and to account for some past cargo-cult
// (where things were retried in a loop). // (where things were retried in a loop).
for (int n = 0; n < 10; n++) { for (int n = 0; n <= 10; n++) {
err = snd_pcm_status(p->alsa, st); err = snd_pcm_status(p->alsa, st);
if (err == -EPIPE) { if (err == -EPIPE) {
// ALSA APIs can return -EPIPE when an XRUN happens, // ALSA APIs can return -EPIPE when an XRUN happens,
@ -943,6 +943,9 @@ static bool recover_and_get_state(struct ao *ao, struct mp_pcm_state *state)
pcmst = snd_pcm_status_get_state(st); pcmst = snd_pcm_status_get_state(st);
} }
if (n == 10)
pcmst = SND_PCM_STATE_DISCONNECTED;
if (pcmst == SND_PCM_STATE_PREPARED || if (pcmst == SND_PCM_STATE_PREPARED ||
pcmst == SND_PCM_STATE_RUNNING || pcmst == SND_PCM_STATE_RUNNING ||
pcmst == SND_PCM_STATE_PAUSED) pcmst == SND_PCM_STATE_PAUSED)