0
0
mirror of https://github.com/mpv-player/mpv.git synced 2024-09-20 03:52:22 +02:00

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.
This commit is contained in:
wm4 2013-01-06 19:28:08 +01:00
parent 67ee79283b
commit 9b3bf76d27

View File

@ -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;