diff options
author | wm4 <wm4@nowhere> | 2013-01-06 19:28:08 +0100 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2013-01-06 19:28:08 +0100 |
commit | 9b3bf76d27c9cd87685aee4cb6652ef7071237b3 (patch) | |
tree | d4855cf4d61ba86b1f4ebab3f746c66f70b9c299 | |
parent | 67ee79283b5e3f1fb9e0bdad96922b0bd431b365 (diff) | |
download | mpv-9b3bf76d27c9cd87685aee4cb6652ef7071237b3.tar.bz2 mpv-9b3bf76d27c9cd87685aee4cb6652ef7071237b3.tar.xz |
ao_alsa: do not call snd_pcm_delay() when paused
This causes trouble when a hw device is used:
pcm_hw.c:514:(snd_pcm_hw_delay) SNDRV_PCM_IOCTL_DELAY failed (-77): File descriptor in bad state
when running mpv test.mkv --ao=alsa:device=iec958,alsa and pausing
during playback.
Historically, mplayer usually did not call snd_pcm_delay() (which is
called by get_delay()) while paused, so this problem never showed up.
But at least mpv has changes that cause get_delay() to be called when
updating the status line (see commit 3f949cf).
It's possible that calling snd_pcm_delay() is not always legal when the
audio is paused, and at least fails with the error message mentioned
above is the device is a hardware device. Change get_delay() to return
the last delay before the audio was paused. The intention is to get a
continuous playback status display, even when pausing or frame stepping,
otherwise we could just return the audio buffer fill status in
get_delay() or even just 0 when paused.
-rw-r--r-- | audio/out/ao_alsa.c | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/audio/out/ao_alsa.c b/audio/out/ao_alsa.c index 8e23ddefd2..366b912b76 100644 --- a/audio/out/ao_alsa.c +++ b/audio/out/ao_alsa.c @@ -69,6 +69,7 @@ static size_t bytes_per_sample; static int alsa_can_pause; static snd_pcm_sframes_t prepause_frames; +static float delay_before_pause; #define ALSA_DEVICE_SIZE 256 @@ -354,6 +355,7 @@ static int init(int rate_hz, int channels, int format, int flags) mp_msg(MSGT_AO,MSGL_V,"alsa-init: using ALSA %s\n", snd_asoundlib_version()); prepause_frames = 0; + delay_before_pause = 0; snd_lib_error_set_handler(alsa_error_handler); @@ -703,6 +705,7 @@ static void audio_pause(void) int err; if (alsa_can_pause) { + delay_before_pause = get_delay(); if ((err = snd_pcm_pause(alsa_handler, 1)) < 0) { mp_tmsg(MSGT_AO,MSGL_ERR,"[AO_ALSA] pcm pause error: %s\n", snd_strerror(err)); @@ -713,6 +716,7 @@ static void audio_pause(void) if (snd_pcm_delay(alsa_handler, &prepause_frames) < 0 || prepause_frames < 0) prepause_frames = 0; + delay_before_pause = prepause_frames / (float)ao_data.samplerate; if ((err = snd_pcm_drop(alsa_handler)) < 0) { @@ -757,6 +761,7 @@ static void reset(void) int err; prepause_frames = 0; + delay_before_pause = 0; if ((err = snd_pcm_drop(alsa_handler)) < 0) { mp_tmsg(MSGT_AO,MSGL_ERR,"[AO_ALSA] pcm prepare error: %s\n", snd_strerror(err)); @@ -847,6 +852,9 @@ static float get_delay(void) if (alsa_handler) { snd_pcm_sframes_t delay; + if (snd_pcm_state(alsa_handler) == SND_PCM_STATE_PAUSED) + return delay_before_pause; + if (snd_pcm_delay(alsa_handler, &delay) < 0) return 0; |