aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/audioOutputs/audioOutput_alsa.c33
1 files changed, 20 insertions, 13 deletions
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);