summaryrefslogtreecommitdiffstats
path: root/src/modules
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2009-01-08 01:03:42 +0100
committerLennart Poettering <lennart@poettering.net>2009-01-08 01:03:42 +0100
commitc2450501af82d1c9d1994e4f4ce80d506d3c90ae (patch)
treedc443a4862811e03663aa92b2f0ffb45b26b2f58 /src/modules
parente67bc1d752f768efb556b57aff8be4e1d82b173b (diff)
Prefer mixer controls with volumes over switches
When we look for a mixer control prefer controls that have both volume and a mute switch over those that have only a volume switch over those that only have a mute switch. Originally pointed out by Adel Gadllah.
Diffstat (limited to 'src/modules')
-rw-r--r--src/modules/alsa-util.c80
-rw-r--r--src/modules/alsa-util.h2
-rw-r--r--src/modules/module-alsa-sink.c2
-rw-r--r--src/modules/module-alsa-source.c2
4 files changed, 75 insertions, 11 deletions
diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c
index 75b84c40..ff3af19d 100644
--- a/src/modules/alsa-util.c
+++ b/src/modules/alsa-util.c
@@ -760,8 +760,32 @@ int pa_alsa_prepare_mixer(snd_mixer_t *mixer, const char *dev) {
return 0;
}
-snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name, const char *fallback) {
- snd_mixer_elem_t *elem;
+static pa_bool_t elem_has_volume(snd_mixer_elem_t *elem, pa_bool_t playback) {
+ pa_assert(elem);
+
+ if (playback && snd_mixer_selem_has_playback_volume(elem))
+ return TRUE;
+
+ if (!playback && snd_mixer_selem_has_capture_volume(elem))
+ return TRUE;
+
+ return FALSE;
+}
+
+static pa_bool_t elem_has_switch(snd_mixer_elem_t *elem, pa_bool_t playback) {
+ pa_assert(elem);
+
+ if (playback && snd_mixer_selem_has_playback_switch(elem))
+ return TRUE;
+
+ if (!playback && snd_mixer_selem_has_capture_switch(elem))
+ return TRUE;
+
+ return FALSE;
+}
+
+snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name, const char *fallback, pa_bool_t playback) {
+ snd_mixer_elem_t *elem = NULL, *fallback_elem = NULL;
snd_mixer_selem_id_t *sid = NULL;
snd_mixer_selem_id_alloca(&sid);
@@ -771,17 +795,57 @@ snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name, const
snd_mixer_selem_id_set_name(sid, name);
- if (!(elem = snd_mixer_find_selem(mixer, sid))) {
- pa_log_info("Cannot find mixer control \"%s\".", snd_mixer_selem_id_get_name(sid));
+ if ((elem = snd_mixer_find_selem(mixer, sid))) {
+
+ if (elem_has_volume(elem, playback) &&
+ elem_has_switch(elem, playback))
+ goto success;
+
+ if (!elem_has_volume(elem, playback) &&
+ !elem_has_switch(elem, playback))
+ elem = NULL;
+ }
+
+ pa_log_info("Cannot find mixer control \"%s\" or mixer control is no combination of switch/volume.", snd_mixer_selem_id_get_name(sid));
+
+ if (fallback) {
+ snd_mixer_selem_id_set_name(sid, fallback);
+
+ if ((fallback_elem = snd_mixer_find_selem(mixer, sid))) {
+
+ if (elem_has_volume(fallback_elem, playback) &&
+ elem_has_switch(fallback_elem, playback)) {
+ elem = fallback_elem;
+ goto success;
+ }
+
+ if (!elem_has_volume(fallback_elem, playback) &&
+ !elem_has_switch(fallback_elem, playback))
+ fallback_elem = NULL;
+ }
+
+ pa_log_warn("Cannot find fallback mixer control \"%s\" or mixer control is no combination of switch/volume.", snd_mixer_selem_id_get_name(sid));
+ }
+
+ if (elem && fallback_elem) {
- if (fallback) {
- snd_mixer_selem_id_set_name(sid, fallback);
+ /* Hmm, so we have both elements, but neither has both mute
+ * and volume. Let's prefer the one with the volume */
- if (!(elem = snd_mixer_find_selem(mixer, sid)))
- pa_log_warn("Cannot find fallback mixer control \"%s\".", snd_mixer_selem_id_get_name(sid));
+ if (elem_has_volume(elem, playback))
+ goto success;
+
+ if (elem_has_volume(fallback_elem, playback)) {
+ elem = fallback_elem;
+ goto success;
}
}
+ if (!elem && fallback_elem)
+ elem = fallback_elem;
+
+success:
+
if (elem)
pa_log_info("Using mixer control \"%s\".", snd_mixer_selem_id_get_name(sid));
diff --git a/src/modules/alsa-util.h b/src/modules/alsa-util.h
index aaa01c78..95bb983a 100644
--- a/src/modules/alsa-util.h
+++ b/src/modules/alsa-util.h
@@ -52,7 +52,7 @@ int pa_alsa_set_hw_params(
int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min);
int pa_alsa_prepare_mixer(snd_mixer_t *mixer, const char *dev);
-snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name, const char *fallback);
+snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name, const char *fallback, pa_bool_t playback);
snd_pcm_t *pa_alsa_open_by_device_id(
const char *dev_id,
diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 6dea172f..95a8c972 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -1409,7 +1409,7 @@ int pa__init(pa_module*m) {
}
if (found)
- if (!(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "Master", "PCM")))
+ if (!(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "Master", "PCM", TRUE)))
found = FALSE;
if (!found) {
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index f796ef14..b6c6ed1a 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -1236,7 +1236,7 @@ int pa__init(pa_module*m) {
}
if (found)
- if (!(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "Capture", "Mic")))
+ if (!(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "Capture", "Mic", FALSE)))
found = FALSE;
if (!found) {