From 24c1f46353213e3392b542a6c3655bcd215e7c63 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Mon, 24 Jul 2006 01:38:51 +0000 Subject: audioOutput_alsa: better period_size auto-configuration We'll try setting an initial value of 50ms, and halve it each time snd_pcm_hw_params fails with -EPIPE. This way we'll can use a larger (50ms) period_size whenever a device supports it, and automatically pick smaller ones if we can't set larger ones. This removes the calculation borrowed from libao (svn) as well. Other minor things: "Alsa" => "ALSA" in error messages _US appended to *_TIME constants so we won't get confused (shank's request) git-svn-id: https://svn.musicpd.org/mpd/trunk@4438 09075e82-0dd4-0310-85a5-a0d7c8717e4f --- src/audioOutputs/audioOutput_alsa.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/audioOutputs/audioOutput_alsa.c b/src/audioOutputs/audioOutput_alsa.c index 603abcee4..c129e2d6e 100644 --- a/src/audioOutputs/audioOutput_alsa.c +++ b/src/audioOutputs/audioOutput_alsa.c @@ -25,12 +25,12 @@ #define ALSA_PCM_NEW_HW_PARAMS_API #define ALSA_PCM_NEW_SW_PARAMS_API -#define MPD_ALSA_BUFFER_TIME 500000 +#define MPD_ALSA_BUFFER_TIME_US 500000 /* the default period time of xmms is 50 ms, so let's use that as well. * a user can tweak this parameter via the "period_time" config parameter. */ -#define MPD_ALSA_PERIOD_TIME 50000 -#define MPD_ALSA_SAMPLE_XFER 256 +#define MPD_ALSA_PERIOD_TIME_US 50000 +#define MPD_ALSA_RETRY_NR 5 #include "../conf.h" #include "../log.h" @@ -65,8 +65,8 @@ static AlsaData *newAlsaData(void) ret->pcmHandle = NULL; ret->writei = snd_pcm_writei; ret->useMmap = 0; - ret->buffer_time = MPD_ALSA_BUFFER_TIME; - ret->period_time = MPD_ALSA_PERIOD_TIME; + ret->buffer_time = MPD_ALSA_BUFFER_TIME_US; + ret->period_time = MPD_ALSA_PERIOD_TIME_US; return ret; } @@ -139,7 +139,9 @@ static int alsa_openDevice(AudioOutput * audioOutput) snd_pcm_uframes_t alsa_buffer_size; snd_pcm_uframes_t alsa_period_size; int err; - char *cmd = NULL; + const char *cmd = NULL; + unsigned int period_time; + int retry = MPD_ALSA_RETRY_NR; switch (audioFormat->bits) { case 8: @@ -155,7 +157,7 @@ static int alsa_openDevice(AudioOutput * audioOutput) bitformat = SND_PCM_FORMAT_S32; break; default: - ERROR("Alsa device \"%s\" doesn't support %i bit audio\n", + ERROR("ALSA device \"%s\" doesn't support %i bit audio\n", ad->device, audioFormat->bits); return -1; } @@ -173,6 +175,7 @@ static int alsa_openDevice(AudioOutput * audioOutput) if (err < 0) goto error; +configure_hw: /* configure HW params */ snd_pcm_hw_params_alloca(&hwparams); @@ -204,7 +207,7 @@ static int alsa_openDevice(AudioOutput * audioOutput) err = snd_pcm_hw_params_set_format(ad->pcmHandle, hwparams, bitformat); if (err < 0) { - ERROR("Alsa device \"%s\" does not support %i bit audio: " + ERROR("ALSA device \"%s\" does not support %i bit audio: " "%s\n", ad->device, (int)bitformat, snd_strerror(-err)); goto fail; } @@ -212,7 +215,7 @@ static int alsa_openDevice(AudioOutput * audioOutput) err = snd_pcm_hw_params_set_channels_near(ad->pcmHandle, hwparams, &channels); if (err < 0) { - ERROR("Alsa device \"%s\" does not support %i channels: " + ERROR("ALSA device \"%s\" does not support %i channels: " "%s\n", ad->device, (int)audioFormat->channels, snd_strerror(-err)); goto fail; @@ -222,7 +225,7 @@ static int alsa_openDevice(AudioOutput * audioOutput) err = snd_pcm_hw_params_set_rate_near(ad->pcmHandle, hwparams, &sampleRate, NULL); if (err < 0 || sampleRate == 0) { - ERROR("Alsa device \"%s\" does not support %i Hz audio\n", + ERROR("ALSA device \"%s\" does not support %i Hz audio\n", ad->device, (int)audioFormat->sampleRate); goto fail; } @@ -234,8 +237,7 @@ static int alsa_openDevice(AudioOutput * audioOutput) if (err < 0) goto error; - if (!ad->period_time && sampleRate > 0) - ad->period_time = 1000000 * MPD_ALSA_SAMPLE_XFER / sampleRate; + period_time = ad->period_time; cmd = "snd_pcm_hw_params_set_period_time_near"; err = snd_pcm_hw_params_set_period_time_near(ad->pcmHandle, hwparams, &ad->period_time, NULL); @@ -244,8 +246,13 @@ static int alsa_openDevice(AudioOutput * audioOutput) cmd = "snd_pcm_hw_params"; err = snd_pcm_hw_params(ad->pcmHandle, hwparams); - if (err < 0) + if (err == -EPIPE && --retry > 0) { + ad->period_time = period_time >> 1; + goto configure_hw; + } else if (err < 0) goto error; + if (retry != MPD_ALSA_RETRY_NR) + DEBUG("ALSA period_time set to %d\n", ad->period_time); cmd = "snd_pcm_hw_params_get_buffer_size"; err = snd_pcm_hw_params_get_buffer_size(hwparams, &alsa_buffer_size); -- cgit v1.2.3