[pulseaudio-discuss] [PATCH v2 1/2] alsa-mixer: Add alsa index number support for Element and Jack
Hui Wang
hui.wang at canonical.com
Mon Jan 14 04:24:13 UTC 2019
We have met a couple of machines which have two Kcontrols with the
exact same names and with the different index numbers, for example:
(1 physical headphone jack + 1 physical headset jack on front panel)
- Simple mixer control 'Headphone',0 (volume and switch)
- Simple mixer control 'Headphone',1 (volume and switch)
(1 physical mic jack + 1 physical headset jack on front panel)
- iface=CARD,name='Mic Jack' index 0
- iface=CARD,name='Mic Jack' index 1
To let pulseaudio treat them as different Jacks or differnt Elements,
we introduce index to the pa_alsa_jack and pa_alsa_element.
When probing jacks or elements, we add index as a parameter.
Signed-off-by: Hui Wang <hui.wang at canonical.com>
---
src/modules/alsa/alsa-mixer.c | 59 ++++++++++++++-----
src/modules/alsa/alsa-mixer.h | 2 +
src/modules/alsa/alsa-ucm.c | 2 +-
src/modules/alsa/alsa-util.c | 4 +-
src/modules/alsa/alsa-util.h | 2 +-
.../mixer/paths/analog-output.conf.common | 5 ++
src/modules/alsa/module-alsa-card.c | 4 +-
7 files changed, 59 insertions(+), 19 deletions(-)
diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
index 91dfc66ee..e32ec5cd7 100644
--- a/src/modules/alsa/alsa-mixer.c
+++ b/src/modules/alsa/alsa-mixer.c
@@ -718,11 +718,11 @@ static pa_volume_t from_alsa_volume(long v, long min, long max) {
return (pa_volume_t) round(((double) (v - min) * PA_VOLUME_NORM) / (double) (max - min));
}
-#define SELEM_INIT(sid, name) \
+#define SELEM_INIT(sid, name, index) \
do { \
snd_mixer_selem_id_alloca(&(sid)); \
snd_mixer_selem_id_set_name((sid), (name)); \
- snd_mixer_selem_id_set_index((sid), 0); \
+ snd_mixer_selem_id_set_index((sid), index); \
} while(false)
static int element_get_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_channel_map *cm, pa_cvolume *v) {
@@ -737,7 +737,7 @@ static int element_get_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
pa_assert(cm);
pa_assert(v);
- SELEM_INIT(sid, e->alsa_name);
+ SELEM_INIT(sid, e->alsa_name, e->index);
if (!(me = snd_mixer_find_selem(m, sid))) {
pa_log_warn("Element %s seems to have disappeared.", e->alsa_name);
return -1;
@@ -902,7 +902,7 @@ static int element_get_switch(pa_alsa_element *e, snd_mixer_t *m, bool *b) {
pa_assert(e);
pa_assert(b);
- SELEM_INIT(sid, e->alsa_name);
+ SELEM_INIT(sid, e->alsa_name, e->index);
if (!(me = snd_mixer_find_selem(m, sid))) {
pa_log_warn("Element %s seems to have disappeared.", e->alsa_name);
return -1;
@@ -1066,7 +1066,7 @@ static int element_set_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
pa_assert(v);
pa_assert(pa_cvolume_compatible_with_channel_map(v, cm));
- SELEM_INIT(sid, e->alsa_name);
+ SELEM_INIT(sid, e->alsa_name, e->index);
if (!(me = snd_mixer_find_selem(m, sid))) {
pa_log_warn("Element %s seems to have disappeared.", e->alsa_name);
return -1;
@@ -1256,7 +1256,7 @@ static int element_set_switch(pa_alsa_element *e, snd_mixer_t *m, bool b) {
pa_assert(m);
pa_assert(e);
- SELEM_INIT(sid, e->alsa_name);
+ SELEM_INIT(sid, e->alsa_name, e->index);
if (!(me = snd_mixer_find_selem(m, sid))) {
pa_log_warn("Element %s seems to have disappeared.", e->alsa_name);
return -1;
@@ -1307,7 +1307,7 @@ static int element_set_constant_volume(pa_alsa_element *e, snd_mixer_t *m) {
pa_assert(m);
pa_assert(e);
- SELEM_INIT(sid, e->alsa_name);
+ SELEM_INIT(sid, e->alsa_name, e->index);
if (!(me = snd_mixer_find_selem(m, sid))) {
pa_log_warn("Element %s seems to have disappeared.", e->alsa_name);
return -1;
@@ -1734,7 +1734,7 @@ static int element_probe(pa_alsa_element *e, snd_mixer_t *m) {
pa_assert(e);
pa_assert(e->path);
- SELEM_INIT(sid, e->alsa_name);
+ SELEM_INIT(sid, e->alsa_name, e->index);
if (!(me = snd_mixer_find_selem(m, sid))) {
@@ -1837,7 +1837,7 @@ static int jack_probe(pa_alsa_jack *j, pa_alsa_mapping *mapping, snd_mixer_t *m)
j->append_pcm_to_name = false;
}
- has_control = pa_alsa_mixer_find(m, j->alsa_name, 0) != NULL;
+ has_control = pa_alsa_mixer_find(m, j->alsa_name, 0, j->index) != NULL;
pa_alsa_jack_set_has_control(j, has_control);
if (j->has_control) {
@@ -1959,6 +1959,36 @@ finish:
return o;
}
+static int element_parse_index(pa_config_parser_state *state) {
+ pa_alsa_path *p;
+ pa_alsa_element *e;
+ pa_alsa_jack *j;
+ uint32_t ind;
+
+ pa_assert(state);
+
+ p = state->userdata;
+
+ e = element_get(p, state->section, true);
+ j = jack_get(p, state->section);
+ if (!e && !j)
+ goto error;
+
+ if (pa_atou(state->rvalue, &ind) < 0)
+ goto error;
+
+ if (e)
+ e->index = ind;
+ else
+ j->index = ind;
+
+ return 0;
+
+error:
+ pa_log("[%s:%u] Required makes no sense in '%s'", state->filename, state->lineno, state->section);
+ return -1;
+}
+
static int element_parse_switch(pa_config_parser_state *state) {
pa_alsa_path *p;
pa_alsa_element *e;
@@ -2399,7 +2429,7 @@ static int element_set_option(pa_alsa_element *e, snd_mixer_t *m, int alsa_idx)
pa_assert(e);
pa_assert(m);
- SELEM_INIT(sid, e->alsa_name);
+ SELEM_INIT(sid, e->alsa_name, e->index);
if (!(me = snd_mixer_find_selem(m, sid))) {
pa_log_warn("Element %s seems to have disappeared.", e->alsa_name);
return -1;
@@ -2606,6 +2636,7 @@ pa_alsa_path* pa_alsa_path_new(const char *paths_dir, const char *fname, pa_alsa
{ "append-pcm-to-name", jack_parse_append_pcm_to_name, NULL, NULL },
/* [Element ...] */
+ { "index", element_parse_index, NULL, NULL },
{ "switch", element_parse_switch, NULL, NULL },
{ "volume", element_parse_volume, NULL, NULL },
{ "enumeration", element_parse_enumeration, NULL, NULL },
@@ -3014,7 +3045,7 @@ static void element_set_callback(pa_alsa_element *e, snd_mixer_t *m, snd_mixer_e
pa_assert(m);
pa_assert(cb);
- SELEM_INIT(sid, e->alsa_name);
+ SELEM_INIT(sid, e->alsa_name, e->index);
if (!(me = snd_mixer_find_selem(m, sid))) {
pa_log_warn("Element %s seems to have disappeared.", e->alsa_name);
return;
@@ -3294,7 +3325,7 @@ static bool element_is_subset(pa_alsa_element *a, pa_alsa_element *b, snd_mixer_
snd_mixer_selem_id_t *sid;
snd_mixer_elem_t *me;
- SELEM_INIT(sid, a->alsa_name);
+ SELEM_INIT(sid, a->alsa_name, a->index);
if (!(me = snd_mixer_find_selem(m, sid))) {
pa_log_warn("Element %s seems to have disappeared.", a->alsa_name);
return false;
@@ -3402,7 +3433,7 @@ static void path_set_condense(pa_alsa_path_set *ps, snd_mixer_t *m) {
continue;
PA_LLIST_FOREACH(jb, p2->jacks) {
- if (jb->has_control && pa_streq(jb->alsa_name, ja->alsa_name) &&
+ if (jb->has_control && pa_streq(jb->alsa_name, ja->alsa_name) && (jb->index == ja->index) &&
(ja->state_plugged == jb->state_plugged) &&
(ja->state_unplugged == jb->state_unplugged)) {
exists = true;
@@ -3424,7 +3455,7 @@ static void path_set_condense(pa_alsa_path_set *ps, snd_mixer_t *m) {
break;
PA_LLIST_FOREACH(eb, p2->elements) {
- if (pa_streq(ea->alsa_name, eb->alsa_name)) {
+ if (pa_streq(ea->alsa_name, eb->alsa_name) && (ea->index == eb->index)) {
found_matching_element = true;
is_subset = element_is_subset(ea, eb, m);
break;
diff --git a/src/modules/alsa/alsa-mixer.h b/src/modules/alsa/alsa-mixer.h
index 3ea4d7329..5a8ed03b6 100644
--- a/src/modules/alsa/alsa-mixer.h
+++ b/src/modules/alsa/alsa-mixer.h
@@ -124,6 +124,7 @@ struct pa_alsa_element {
PA_LLIST_FIELDS(pa_alsa_element);
char *alsa_name;
+ uint32_t index;
pa_alsa_direction_t direction;
pa_alsa_switch_use_t switch_use;
@@ -160,6 +161,7 @@ struct pa_alsa_jack {
char *name; /* E g "Headphone" */
char *alsa_name; /* E g "Headphone Jack" */
+ uint32_t index;
bool has_control; /* is the jack itself present? */
bool plugged_in; /* is this jack currently plugged in? */
snd_mixer_elem_t *melem; /* Jack detection handle */
diff --git a/src/modules/alsa/alsa-ucm.c b/src/modules/alsa/alsa-ucm.c
index d2d3ee1eb..bde6e4d0f 100644
--- a/src/modules/alsa/alsa-ucm.c
+++ b/src/modules/alsa/alsa-ucm.c
@@ -1515,7 +1515,7 @@ static void ucm_mapping_jack_probe(pa_alsa_mapping *m) {
PA_IDXSET_FOREACH(dev, context->ucm_devices, idx) {
bool has_control;
- has_control = pa_alsa_mixer_find(mixer_handle, dev->jack->alsa_name, 0) != NULL;
+ has_control = pa_alsa_mixer_find(mixer_handle, dev->jack->alsa_name, 0, dev->jack->index) != NULL;
pa_alsa_jack_set_has_control(dev->jack, has_control);
pa_log_info("UCM jack %s has_control=%d", dev->jack->name, dev->jack->has_control);
}
diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c
index c5f6188e6..242645c59 100644
--- a/src/modules/alsa/alsa-util.c
+++ b/src/modules/alsa/alsa-util.c
@@ -1595,7 +1595,7 @@ bool pa_alsa_may_tsched(bool want) {
#define SND_MIXER_ELEM_PULSEAUDIO (SND_MIXER_ELEM_LAST + 10)
-snd_mixer_elem_t *pa_alsa_mixer_find(snd_mixer_t *mixer, const char *name, unsigned int device) {
+snd_mixer_elem_t *pa_alsa_mixer_find(snd_mixer_t *mixer, const char *name, unsigned int device, unsigned int index) {
snd_mixer_elem_t *elem;
for (elem = snd_mixer_first_elem(mixer); elem; elem = snd_mixer_elem_next(elem)) {
@@ -1607,6 +1607,8 @@ snd_mixer_elem_t *pa_alsa_mixer_find(snd_mixer_t *mixer, const char *name, unsig
continue;
if (snd_hctl_elem_get_device(helem) != device)
continue;
+ if (snd_hctl_elem_get_index(helem) != index)
+ continue;
return elem;
}
return NULL;
diff --git a/src/modules/alsa/alsa-util.h b/src/modules/alsa/alsa-util.h
index 6b27339ec..58fc211c0 100644
--- a/src/modules/alsa/alsa-util.h
+++ b/src/modules/alsa/alsa-util.h
@@ -141,7 +141,7 @@ const char* pa_alsa_strerror(int errnum);
bool pa_alsa_may_tsched(bool want);
-snd_mixer_elem_t *pa_alsa_mixer_find(snd_mixer_t *mixer, const char *name, unsigned int device);
+snd_mixer_elem_t *pa_alsa_mixer_find(snd_mixer_t *mixer, const char *name, unsigned int device, unsigned int index);
snd_mixer_t *pa_alsa_open_mixer(int alsa_card_index, char **ctl_device);
diff --git a/src/modules/alsa/mixer/paths/analog-output.conf.common b/src/modules/alsa/mixer/paths/analog-output.conf.common
index e52830d99..8730ab5a4 100644
--- a/src/modules/alsa/mixer/paths/analog-output.conf.common
+++ b/src/modules/alsa/mixer/paths/analog-output.conf.common
@@ -86,6 +86,9 @@
; required-absent = ignore | enumeration | any # In this element, this option must not exist or the path will be invalid
;
; [Element ...] # For each element that we shall control
+; index = <the index number> # If the index number of this Element is not 0, we need to set the correct index number here,
+; # if it is 0, don't need to set it here
+;
; required = ignore | switch | volume | enumeration | any # If set, require this element to be of this kind and available,
; # otherwise don't consider this path valid for the card
; required-any = ignore | switch | volume | enumeration | any # If set, at least one of the elements or jacks with required-any in this
@@ -120,6 +123,8 @@
; # channels in a mask
; [Jack ...] # For each jack that we will use for jack detection
; # The name 'Jack Foo' must match ALSA's 'Foo Jack' control.
+; index = <the index number> # If the index number of this Jack is not 0, we need to set the correct index number here,
+; # if it is 0, don't need to set it here
; required = ignore | any # If not set to ignore, make the path invalid if this jack control is not present.
; required-absent = ignore | any # If not set to ignore, make the path invalid if this jack control is present.
; required-any = ignore | any # If not set to ignore, make the path invalid if no jack controls and no elements with
diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c
index 473248767..656b58278 100644
--- a/src/modules/alsa/module-alsa-card.c
+++ b/src/modules/alsa/module-alsa-card.c
@@ -583,7 +583,7 @@ static void init_eld_ctls(struct userdata *u) {
if (device < 0)
continue;
- melem = pa_alsa_mixer_find(u->mixer_handle, "ELD", device);
+ melem = pa_alsa_mixer_find(u->mixer_handle, "ELD", device, 0);
if (melem) {
snd_mixer_elem_set_callback(melem, hdmi_eld_changed);
snd_mixer_elem_set_callback_private(melem, u);
@@ -630,7 +630,7 @@ static void init_jacks(struct userdata *u) {
u->mixer_handle = pa_alsa_open_mixer(u->alsa_card_index, NULL);
if (u->mixer_handle && pa_alsa_fdlist_set_handle(u->mixer_fdl, u->mixer_handle, NULL, u->core->mainloop) >= 0) {
PA_HASHMAP_FOREACH(jack, u->jacks, state) {
- jack->melem = pa_alsa_mixer_find(u->mixer_handle, jack->alsa_name, 0);
+ jack->melem = pa_alsa_mixer_find(u->mixer_handle, jack->alsa_name, 0, jack->index);
if (!jack->melem) {
pa_log_warn("Jack '%s' seems to have disappeared.", jack->alsa_name);
pa_alsa_jack_set_has_control(jack, false);
--
2.17.1
More information about the pulseaudio-discuss
mailing list