summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaroslav Kysela <perex@perex.cz>2010-08-11 19:45:40 +0200
committerJaroslav Kysela <perex@perex.cz>2010-08-11 19:55:15 +0200
commit09879a4bb58199f64abcb8df506f917c8efc2383 (patch)
treea33a7b3e27a4963ff78bab812fa00ac6ccbc7fcc
parente6d5dcf1f625984605d362338d71162de45a6c60 (diff)
downloadalsa-lib-09879a4bb58199f64abcb8df506f917c8efc2383.tar.gz
pcm: add defaults.pcm.minperiodtime parsing
Some broken applications like Audacious don't set any timing parameters. While the alsa-lib behaviour is to select the smallest period size and biggest buffer size, the result is the generation of thousands interrupts per second. The default value in alsa.conf is 5000usec. Signed-off-by: Jaroslav Kysela <perex@perex.cz>
-rw-r--r--src/conf/alsa.conf1
-rw-r--r--src/pcm/pcm.c8
-rw-r--r--src/pcm/pcm_local.h1
-rw-r--r--src/pcm/pcm_params.c13
4 files changed, 21 insertions, 2 deletions
diff --git a/src/conf/alsa.conf b/src/conf/alsa.conf
index db642597..51605290 100644
--- a/src/conf/alsa.conf
+++ b/src/conf/alsa.conf
@@ -63,6 +63,7 @@ defaults.pcm.card 0
defaults.pcm.device 0
defaults.pcm.subdevice -1
defaults.pcm.nonblock 1
+defaults.pcm.minperiodtime 5000 # in us
defaults.pcm.ipc_key 5678293
defaults.pcm.ipc_gid audio
defaults.pcm.ipc_perm 0660
diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
index f910189a..f3c2f743 100644
--- a/src/pcm/pcm.c
+++ b/src/pcm/pcm.c
@@ -2058,7 +2058,7 @@ static int snd_pcm_open_conf(snd_pcm_t **pcmp, const char *name,
const char *str;
char *buf = NULL, *buf1 = NULL;
int err;
- snd_config_t *conf, *type_conf = NULL;
+ snd_config_t *conf, *type_conf = NULL, *tmp;
snd_config_iterator_t i, next;
const char *id;
const char *lib = NULL, *open_name = NULL;
@@ -2191,6 +2191,12 @@ static int snd_pcm_open_conf(snd_pcm_t **pcmp, const char *name,
snd_dlclose(h);
}
}
+ if (err >= 0) {
+ err = snd_config_search(pcm_root, "defaults.pcm.minperiodtime", &tmp);
+ if (err >= 0)
+ snd_config_get_integer(tmp, &(*pcmp)->minperiodtime);
+ err = 0;
+ }
if (type_conf)
snd_config_delete(type_conf);
free(buf);
diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h
index 9aa81e14..dda970c1 100644
--- a/src/pcm/pcm_local.h
+++ b/src/pcm/pcm_local.h
@@ -179,6 +179,7 @@ struct _snd_pcm {
snd_pcm_type_t type;
snd_pcm_stream_t stream;
int mode;
+ long minperiodtime; /* in us */
int poll_fd_count;
int poll_fd;
unsigned short poll_events;
diff --git a/src/pcm/pcm_params.c b/src/pcm/pcm_params.c
index 0e1c3fc5..6120677a 100644
--- a/src/pcm/pcm_params.c
+++ b/src/pcm/pcm_params.c
@@ -1102,8 +1102,19 @@ static int snd_pcm_hw_params_choose(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
if (err < 0)
return err;
err = snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_RATE, NULL, 0);
- if (err < 0)
return err;
+ if (pcm->minperiodtime > 0) {
+ unsigned int min, max;
+ int dir = 1;
+ err = snd_pcm_hw_param_get_min(params, SND_PCM_HW_PARAM_PERIOD_TIME, &min, &dir);
+ if (err >= 0)
+ err = snd_pcm_hw_param_get_max(params, SND_PCM_HW_PARAM_PERIOD_TIME, &max, &dir);
+ if (err >= 0 && (long)min < pcm->minperiodtime &&
+ (long)max > pcm->minperiodtime) {
+ min = pcm->minperiodtime; dir = 1;
+ snd_pcm_hw_param_set_min(pcm, params, SND_CHANGE, SND_PCM_HW_PARAM_PERIOD_TIME, &min, &dir);
+ }
+ }
if (compat && *compat) {
/* old mode */
err = snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_PERIOD_TIME, NULL, 0);