summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2016-08-09 16:52:33 +0200
committerwm4 <wm4@nowhere>2016-08-09 17:09:29 +0200
commit367e9fb7f1e2143607a6d1ae0c1db5765c5f003b (patch)
tree7b0bd4b531d934f8bb9a42e1bd75a40d353c0059
parent2ded41d2beff54de26ab1c4d16ab4d0bd14eeba0 (diff)
downloadmpv-367e9fb7f1e2143607a6d1ae0c1db5765c5f003b.tar.bz2
mpv-367e9fb7f1e2143607a6d1ae0c1db5765c5f003b.tar.xz
ao_alsa: make pause state more robust, reduce minor code duplication
With the previous commit, ao_alsa.c now has 3 possible ways to pause playback. Actually all 3 of them need get_delay() to fake its return value, so don't duplicate that code. Also much of the code looks a bit questionable when considering inconsistent pause/resume calls from outside, so ignore redundant calls.
-rw-r--r--audio/out/ao_alsa.c47
1 files changed, 25 insertions, 22 deletions
diff --git a/audio/out/ao_alsa.c b/audio/out/ao_alsa.c
index 28281482ee..bbe15b4b61 100644
--- a/audio/out/ao_alsa.c
+++ b/audio/out/ao_alsa.c
@@ -53,7 +53,7 @@ struct priv {
bool device_lost;
snd_pcm_format_t alsa_fmt;
bool can_pause;
- bool pretend_pause;
+ bool paused;
snd_pcm_sframes_t prepause_frames;
double delay_before_pause;
snd_pcm_uframes_t buffersize;
@@ -883,7 +883,7 @@ static double get_delay(struct ao *ao)
struct priv *p = ao->priv;
snd_pcm_sframes_t delay;
- if (snd_pcm_state(p->alsa) == SND_PCM_STATE_PAUSED || p->pretend_pause)
+ if (p->paused)
return p->delay_before_pause;
if (snd_pcm_delay(p->alsa, &delay) < 0)
@@ -917,29 +917,27 @@ static void audio_pause(struct ao *ao)
struct priv *p = ao->priv;
int err;
+ if (p->paused)
+ return;
+
+ p->delay_before_pause = get_delay(ao);
+ p->prepause_frames = p->delay_before_pause * ao->samplerate;
+
if (ao->stream_silence) {
- if (snd_pcm_state(p->alsa) == SND_PCM_STATE_RUNNING) {
- p->delay_before_pause = get_delay(ao);
- p->prepause_frames = p->delay_before_pause * ao->samplerate;
- soft_reset(ao);
- p->pretend_pause = true;
- }
+ soft_reset(ao);
} else if (p->can_pause) {
if (snd_pcm_state(p->alsa) == SND_PCM_STATE_RUNNING) {
- p->delay_before_pause = get_delay(ao);
err = snd_pcm_pause(p->alsa, 1);
CHECK_ALSA_ERROR("pcm pause error");
+ p->prepause_frames = 0;
}
} else {
- if (snd_pcm_delay(p->alsa, &p->prepause_frames) < 0
- || p->prepause_frames < 0)
- p->prepause_frames = 0;
- p->delay_before_pause = p->prepause_frames / (double)ao->samplerate;
-
err = snd_pcm_drop(p->alsa);
CHECK_ALSA_ERROR("pcm drop error");
}
+ p->paused = true;
+
alsa_error: ;
}
@@ -961,13 +959,14 @@ static void audio_resume(struct ao *ao)
struct priv *p = ao->priv;
int err;
+ if (!p->paused)
+ return;
+
resume_device(ao);
if (ao->stream_silence) {
- p->pretend_pause = false;
+ p->paused = false;
get_delay(ao); // recovers from underrun (as a side-effect)
- if (p->prepause_frames)
- ao_play_silence(ao, p->prepause_frames);
} else if (p->can_pause) {
if (snd_pcm_state(p->alsa) == SND_PCM_STATE_PAUSED) {
err = snd_pcm_pause(p->alsa, 0);
@@ -977,11 +976,13 @@ static void audio_resume(struct ao *ao)
MP_VERBOSE(ao, "resume not supported by hardware\n");
err = snd_pcm_prepare(p->alsa);
CHECK_ALSA_ERROR("pcm prepare error");
- if (p->prepause_frames)
- ao_play_silence(ao, p->prepause_frames);
}
+ if (p->prepause_frames)
+ ao_play_silence(ao, p->prepause_frames);
+
alsa_error: ;
+ p->paused = false;
}
static void reset(struct ao *ao)
@@ -989,13 +990,13 @@ static void reset(struct ao *ao)
struct priv *p = ao->priv;
int err;
- p->pretend_pause = false;
+ p->paused = false;
+ p->prepause_frames = 0;
+ p->delay_before_pause = 0;
if (ao->stream_silence) {
soft_reset(ao);
} else {
- p->prepause_frames = 0;
- p->delay_before_pause = 0;
err = snd_pcm_drop(p->alsa);
CHECK_ALSA_ERROR("pcm prepare error");
err = snd_pcm_prepare(p->alsa);
@@ -1039,6 +1040,8 @@ static int play(struct ao *ao, void **data, int samples, int flags)
}
} while (res == 0);
+ p->paused = false;
+
return res < 0 ? -1 : res;
alsa_error: