[pulseaudio-commits] [Git][pulseaudio/pulseaudio][master] 5 commits: alsa-mixer: Handle the index for ALSA mixer jack identifiers

PulseAudio Marge Bot gitlab at gitlab.freedesktop.org
Wed Dec 30 15:54:44 UTC 2020



PulseAudio Marge Bot pushed to branch master at PulseAudio / pulseaudio


Commits:
aad2fca0 by Kai-Heng Feng at 2020-12-30T15:49:09+00:00
alsa-mixer: Handle the index for ALSA mixer jack identifiers

Some systems have two jacks with same name but different index, we need
to take index into consideration to use both jacks.

Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/272>

- - - - -
2a0fa78d by Kai-Heng Feng at 2020-12-30T15:49:09+00:00
alsa-mixer: Support dual Front Headphone Jack

There are dual Front Headphone Jacks with different indices or with
different names, they can be found on HP EliteDesk 800 SFF and HP
EliteDesk 800 DM, respectively.

Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/272>

- - - - -
d51870d4 by Tanu Kaskinen at 2020-12-30T15:49:09+00:00
alsa-mixer: Use unambiguous descriptions with dual headphone outputs

Previously both paths had description "Headphones", which I assume can
cause confusion with users who see two ports with identical names. I
don't have this kind of hardware myself nor have I heard complaints from
users, this is just something I noticed while reading the configuration
files.

Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/272>

- - - - -
0c14f89b by Tanu Kaskinen at 2020-12-30T15:49:09+00:00
alsa-mixer: Move HP EliteDesk 800 SFF/DM second headphone output to path analog-output-headphones-2

The two headphone outputs should be handled in separate paths so that
volume control can be implemented properly for both outputs.

Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/272>

- - - - -
21a53104 by Tanu Kaskinen at 2020-12-30T15:49:09+00:00
alsa-mixer: Add support for the Headphone,1 element

This is seen at least on HP EliteDesk 800 DM and HP EliteDesk 800 SFF.

This is used by the analog-output-headphones-2 path, but all other paths
on the same sink need to handle the element too. The existing
configuration is inconsistent between files regarding whether headphone
outputs should be muted or not when not using them. I chose to be
consistent within files, which means that Headphone,1 handling is
inconsistent between files in the same way that the existing Headphone
and Headphone2 handling is. (My opinion is that unused paths should be
always muted, but I didn't want to do that policy change in this patch.)

Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/272>

- - - - -


12 changed files:

- src/modules/alsa/alsa-mixer.c
- src/modules/alsa/alsa-mixer.h
- src/modules/alsa/alsa-ucm.c
- src/modules/alsa/alsa-util.c
- src/modules/alsa/alsa-util.h
- src/modules/alsa/mixer/paths/analog-output-headphones-2.conf
- src/modules/alsa/mixer/paths/analog-output-headphones.conf
- src/modules/alsa/mixer/paths/analog-output-lineout.conf
- src/modules/alsa/mixer/paths/analog-output-mono.conf
- src/modules/alsa/mixer/paths/analog-output-speaker-always.conf
- src/modules/alsa/mixer/paths/analog-output-speaker.conf
- src/modules/alsa/module-alsa-card.c


Changes:

=====================================
src/modules/alsa/alsa-mixer.c
=====================================
@@ -113,7 +113,7 @@ struct description2_map {
     pa_device_port_type_t type;
 };
 
-static char *alsa_id_str(char *dst, size_t dst_len, pa_alsa_mixer_id *id) {
+char *pa_alsa_mixer_id_to_string(char *dst, size_t dst_len, pa_alsa_mixer_id *id) {
     if (id->index > 0) {
         snprintf(dst, dst_len, "'%s',%d", id->name, id->index);
     } else {
@@ -153,7 +153,7 @@ static int alsa_id_decode(const char *src, char *name, int *index) {
     return 0;
 }
 
-pa_alsa_jack *pa_alsa_jack_new(pa_alsa_path *path, const char *mixer_device_name, const char *name) {
+pa_alsa_jack *pa_alsa_jack_new(pa_alsa_path *path, const char *mixer_device_name, const char *name, int index) {
     pa_alsa_jack *jack;
 
     pa_assert(name);
@@ -162,7 +162,8 @@ pa_alsa_jack *pa_alsa_jack_new(pa_alsa_path *path, const char *mixer_device_name
     jack->path = path;
     jack->mixer_device_name = pa_xstrdup(mixer_device_name);
     jack->name = pa_xstrdup(name);
-    jack->alsa_name = pa_sprintf_malloc("%s Jack", name);
+    jack->alsa_id.name = pa_sprintf_malloc("%s Jack", name);
+    jack->alsa_id.index = index;
     jack->state_unplugged = PA_AVAILABLE_NO;
     jack->state_plugged = PA_AVAILABLE_YES;
     jack->ucm_devices = pa_dynarray_new(NULL);
@@ -177,7 +178,7 @@ void pa_alsa_jack_free(pa_alsa_jack *jack) {
     pa_dynarray_free(jack->ucm_hw_mute_devices);
     pa_dynarray_free(jack->ucm_devices);
 
-    pa_xfree(jack->alsa_name);
+    pa_xfree(jack->alsa_id.name);
     pa_xfree(jack->name);
     pa_xfree(jack->mixer_device_name);
     pa_xfree(jack);
@@ -835,7 +836,7 @@ static int element_get_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
 
     SELEM_INIT(sid, &e->alsa_id);
     if (!(me = snd_mixer_find_selem(m, sid))) {
-        alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+        pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
         pa_log_warn("Element %s seems to have disappeared.", buf);
         return -1;
     }
@@ -861,14 +862,14 @@ static int element_get_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
                             if (value < e->db_fix->min_step) {
                                 value = e->db_fix->min_step;
                                 snd_mixer_selem_set_playback_volume(me, c, value);
-                                alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+                                pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
                                 pa_log_debug("Playback volume for element %s channel %i was below the dB fix limit. "
                                              "Volume reset to %0.2f dB.", buf, c,
                                              e->db_fix->db_values[value - e->db_fix->min_step] / 100.0);
                             } else if (value > e->db_fix->max_step) {
                                 value = e->db_fix->max_step;
                                 snd_mixer_selem_set_playback_volume(me, c, value);
-                                alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+                                pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
                                 pa_log_debug("Playback volume for element %s channel %i was over the dB fix limit. "
                                              "Volume reset to %0.2f dB.", buf, c,
                                              e->db_fix->db_values[value - e->db_fix->min_step] / 100.0);
@@ -891,14 +892,14 @@ static int element_get_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
                             if (value < e->db_fix->min_step) {
                                 value = e->db_fix->min_step;
                                 snd_mixer_selem_set_capture_volume(me, c, value);
-                                alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+                                pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
                                 pa_log_debug("Capture volume for element %s channel %i was below the dB fix limit. "
                                              "Volume reset to %0.2f dB.", buf, c,
                                              e->db_fix->db_values[value - e->db_fix->min_step] / 100.0);
                             } else if (value > e->db_fix->max_step) {
                                 value = e->db_fix->max_step;
                                 snd_mixer_selem_set_capture_volume(me, c, value);
-                                alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+                                pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
                                 pa_log_debug("Capture volume for element %s channel %i was over the dB fix limit. "
                                              "Volume reset to %0.2f dB.", buf, c,
                                              e->db_fix->db_values[value - e->db_fix->min_step] / 100.0);
@@ -1006,7 +1007,7 @@ static int element_get_switch(pa_alsa_element *e, snd_mixer_t *m, bool *b) {
 
     SELEM_INIT(sid, &e->alsa_id);
     if (!(me = snd_mixer_find_selem(m, sid))) {
-        alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+        pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
         pa_log_warn("Element %s seems to have disappeared.", buf);
         return -1;
     }
@@ -1172,7 +1173,7 @@ static int element_set_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
 
     SELEM_INIT(sid, &e->alsa_id);
     if (!(me = snd_mixer_find_selem(m, sid))) {
-        alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+        pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
         pa_log_warn("Element %s seems to have disappeared.", buf);
         return -1;
     }
@@ -1364,7 +1365,7 @@ static int element_set_switch(pa_alsa_element *e, snd_mixer_t *m, bool b) {
 
     SELEM_INIT(sid, &e->alsa_id);
     if (!(me = snd_mixer_find_selem(m, sid))) {
-        alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+        pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
         pa_log_warn("Element %s seems to have disappeared.", buf);
         return -1;
     }
@@ -1375,7 +1376,7 @@ static int element_set_switch(pa_alsa_element *e, snd_mixer_t *m, bool b) {
         r = snd_mixer_selem_set_capture_switch_all(me, b);
 
     if (r < 0) {
-        alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+        pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
         pa_log_warn("Failed to set switch of %s: %s", buf, pa_alsa_strerror(errno));
     }
 
@@ -1419,7 +1420,7 @@ static int element_set_constant_volume(pa_alsa_element *e, snd_mixer_t *m) {
 
     SELEM_INIT(sid, &e->alsa_id);
     if (!(me = snd_mixer_find_selem(m, sid))) {
-        alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+        pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
         pa_log_warn("Element %s seems to have disappeared.", buf);
         return -1;
     }
@@ -1464,7 +1465,7 @@ static int element_set_constant_volume(pa_alsa_element *e, snd_mixer_t *m) {
     }
 
     if (r < 0) {
-        alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+        pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
         pa_log_warn("Failed to set volume of %s: %s", buf, pa_alsa_strerror(errno));
     }
 
@@ -1670,19 +1671,19 @@ static bool element_probe_volume(pa_alsa_element *e, snd_mixer_elem_t *me) {
         r = snd_mixer_selem_get_capture_volume_range(me, &e->min_volume, &e->max_volume);
 
     if (r < 0) {
-        alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+        pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
         pa_log_warn("Failed to get volume range of %s: %s", buf, pa_alsa_strerror(r));
         return false;
     }
 
     if (e->min_volume >= e->max_volume) {
-        alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+        pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
         pa_log_warn("Your kernel driver is broken for element %s: it reports a volume range from %li to %li which makes no sense.",
                     buf, e->min_volume, e->max_volume);
         return false;
     }
     if (e->volume_use == PA_ALSA_VOLUME_CONSTANT && (e->min_volume > e->constant_volume || e->max_volume < e->constant_volume)) {
-        alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+        pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
         pa_log_warn("Constant volume %li configured for element %s, but the available range is from %li to %li.",
                     e->constant_volume, buf, e->min_volume, e->max_volume);
         return false;
@@ -1690,7 +1691,7 @@ static bool element_probe_volume(pa_alsa_element *e, snd_mixer_elem_t *me) {
 
 
     if (e->db_fix && ((e->min_volume > e->db_fix->min_step) || (e->max_volume < e->db_fix->max_step))) {
-        alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+        pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
         pa_log_warn("The step range of the decibel fix for element %s (%li-%li) doesn't fit to the "
                     "real hardware range (%li-%li). Disabling the decibel fix.", buf,
                     e->db_fix->min_step, e->db_fix->max_step, e->min_volume, e->max_volume);
@@ -1717,19 +1718,19 @@ static bool element_probe_volume(pa_alsa_element *e, snd_mixer_elem_t *me) {
         long max_dB_checked = 0;
 
         if (element_ask_vol_dB(me, e->direction, e->min_volume, &min_dB_checked) < 0) {
-            alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+            pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
             pa_log_warn("Failed to query the dB value for %s at volume level %li", buf, e->min_volume);
             return false;
         }
 
         if (element_ask_vol_dB(me, e->direction, e->max_volume, &max_dB_checked) < 0) {
-            alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+            pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
             pa_log_warn("Failed to query the dB value for %s at volume level %li", buf, e->max_volume);
             return false;
         }
 
         if (min_dB != min_dB_checked || max_dB != max_dB_checked) {
-            alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+            pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
             pa_log_warn("Your kernel driver is broken: the reported dB range for %s (from %0.2f dB to %0.2f dB) "
                         "doesn't match the dB values at minimum and maximum volume levels: %0.2f dB at level %li, "
                         "%0.2f dB at level %li.", buf, min_dB / 100.0, max_dB / 100.0,
@@ -1752,7 +1753,7 @@ static bool element_probe_volume(pa_alsa_element *e, snd_mixer_elem_t *me) {
 
     if (e->volume_limit >= 0) {
         if (e->volume_limit <= e->min_volume || e->volume_limit > e->max_volume) {
-            alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+            pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
             pa_log_warn("Volume limit for element %s of path %s is invalid: %li isn't within the valid range "
                         "%li-%li. The volume limit is ignored.",
                         buf, e->path->name, e->volume_limit, e->min_volume + 1, e->max_volume);
@@ -1764,7 +1765,7 @@ static bool element_probe_volume(pa_alsa_element *e, snd_mixer_elem_t *me) {
                     e->db_fix->max_step = e->max_volume;
                     e->max_dB = ((double) e->db_fix->db_values[e->db_fix->max_step - e->db_fix->min_step]) / 100.0;
                 } else if (element_ask_vol_dB(me, e->direction, e->max_volume, &max_dB) < 0) {
-                    alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+                    pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
                     pa_log_warn("Failed to get dB value of %s: %s", buf, pa_alsa_strerror(r));
                     e->has_dB = false;
                 } else
@@ -1809,7 +1810,7 @@ static bool element_probe_volume(pa_alsa_element *e, snd_mixer_elem_t *me) {
     }
 
     if (e->n_channels <= 0) {
-        alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+        pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
         pa_log_warn("Volume element %s with no channels?", buf);
         return false;
     } else if (e->n_channels > POSITION_MASK_CHANNELS) {
@@ -1824,7 +1825,7 @@ static bool element_probe_volume(pa_alsa_element *e, snd_mixer_elem_t *me) {
          * Since the array size is fixed at POSITION_MASK_CHANNELS, we obviously
          * don't support elements with more than POSITION_MASK_CHANNELS
          * channels... */
-        alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+        pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
         pa_log_warn("Volume element %s has %u channels. That's too much! I can't handle that!", buf, e->n_channels);
         return false;
     }
@@ -1973,12 +1974,12 @@ static int jack_probe(pa_alsa_jack *j, pa_alsa_mapping *mapping, snd_mixer_t *m)
         }
 
         new_name = pa_sprintf_malloc("%s,pcm=%i Jack", j->name, mapping->hw_device_index);
-        pa_xfree(j->alsa_name);
-        j->alsa_name = new_name;
+        pa_xfree(j->alsa_id.name);
+        j->alsa_id.name = new_name;
         j->append_pcm_to_name = false;
     }
 
-    has_control = pa_alsa_mixer_find_card(m, j->alsa_name, 0) != NULL;
+    has_control = pa_alsa_mixer_find_card(m, &j->alsa_id, 0) != NULL;
     pa_alsa_jack_set_has_control(j, has_control);
 
     if (j->has_control) {
@@ -2041,19 +2042,26 @@ finish:
 
 static pa_alsa_jack* jack_get(pa_alsa_path *p, const char *section) {
     pa_alsa_jack *j;
+    char *name;
+    int index;
 
     if (!pa_startswith(section, "Jack "))
         return NULL;
     section += 5;
 
-    if (p->last_jack && pa_streq(p->last_jack->name, section))
+    name = alloca(strlen(section) + 1);
+    if (alsa_id_decode(section, name, &index))
+        return NULL;
+
+    if (p->last_jack && pa_streq(p->last_jack->name, name) &&
+        p->last_jack->alsa_id.index == index)
         return p->last_jack;
 
     PA_LLIST_FOREACH(j, p->jacks)
-        if (pa_streq(j->name, section))
+        if (pa_streq(j->name, name) && j->alsa_id.index == index)
             goto finish;
 
-    j = pa_alsa_jack_new(p, NULL, section);
+    j = pa_alsa_jack_new(p, NULL, name, index);
     PA_LLIST_INSERT_AFTER(pa_alsa_jack, p->jacks, p->last_jack, j);
 
 finish:
@@ -2645,7 +2653,7 @@ static int element_set_option(pa_alsa_element *e, snd_mixer_t *m, int alsa_idx)
 
     SELEM_INIT(sid, &e->alsa_id);
     if (!(me = snd_mixer_find_selem(m, sid))) {
-        alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+        pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
         pa_log_warn("Element %s seems to have disappeared.", buf);
         return -1;
     }
@@ -2658,7 +2666,7 @@ static int element_set_option(pa_alsa_element *e, snd_mixer_t *m, int alsa_idx)
             r = snd_mixer_selem_set_capture_switch_all(me, alsa_idx);
 
         if (r < 0) {
-            alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+            pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
             pa_log_warn("Failed to set switch of %s: %s", buf, pa_alsa_strerror(errno));
         }
 
@@ -2666,7 +2674,7 @@ static int element_set_option(pa_alsa_element *e, snd_mixer_t *m, int alsa_idx)
         pa_assert(e->enumeration_use == PA_ALSA_ENUMERATION_SELECT);
 
         if ((r = snd_mixer_selem_set_enum_item(me, 0, alsa_idx)) < 0) {
-            alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+            pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
             pa_log_warn("Failed to set enumeration of %s: %s", buf, pa_alsa_strerror(errno));
         }
     }
@@ -2723,7 +2731,7 @@ static int option_verify(pa_alsa_option *o) {
 
     if (o->element->enumeration_use != PA_ALSA_ENUMERATION_SELECT &&
         o->element->switch_use != PA_ALSA_SWITCH_SELECT) {
-        alsa_id_str(buf, sizeof(buf), &o->element->alsa_id);
+        pa_alsa_mixer_id_to_string(buf, sizeof(buf), &o->element->alsa_id);
         pa_log("Element %s of option %s not set for select.", buf, o->name);
         return -1;
     }
@@ -2731,7 +2739,7 @@ static int option_verify(pa_alsa_option *o) {
     if (o->element->switch_use == PA_ALSA_SWITCH_SELECT &&
         !pa_streq(o->alsa_name, "on") &&
         !pa_streq(o->alsa_name, "off")) {
-        alsa_id_str(buf, sizeof(buf), &o->element->alsa_id);
+        pa_alsa_mixer_id_to_string(buf, sizeof(buf), &o->element->alsa_id);
         pa_log("Switch %s options need be named off or on ", buf);
         return -1;
     }
@@ -2757,13 +2765,13 @@ static int element_verify(pa_alsa_element *e) {
         (e->required_any != PA_ALSA_REQUIRED_IGNORE && e->required_any == e->required_absent) ||
         (e->required_absent == PA_ALSA_REQUIRED_ANY && e->required_any != PA_ALSA_REQUIRED_IGNORE) ||
         (e->required_absent == PA_ALSA_REQUIRED_ANY && e->required != PA_ALSA_REQUIRED_IGNORE)) {
-        alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+        pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
         pa_log("Element %s cannot be required and absent at the same time.", buf);
         return -1;
     }
 
     if (e->switch_use == PA_ALSA_SWITCH_SELECT && e->enumeration_use == PA_ALSA_ENUMERATION_SELECT) {
-        alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+        pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
         pa_log("Element %s cannot set select for both switch and enumeration.", buf);
         return -1;
     }
@@ -2789,6 +2797,7 @@ static int path_verify(pa_alsa_path *p) {
         { "analog-input-video",               N_("Video"),                        PA_DEVICE_PORT_TYPE_VIDEO },
         { "analog-output",                    N_("Analog Output"),                PA_DEVICE_PORT_TYPE_ANALOG },
         { "analog-output-headphones",         N_("Headphones"),                   PA_DEVICE_PORT_TYPE_HEADPHONES },
+        { "analog-output-headphones-2",       N_("Headphones 2"),                 PA_DEVICE_PORT_TYPE_HEADPHONES },
         { "analog-output-headphones-mono",    N_("Headphones Mono Output"),       PA_DEVICE_PORT_TYPE_HEADPHONES },
         { "analog-output-lineout",            N_("Line Out"),                     PA_DEVICE_PORT_TYPE_LINE },
         { "analog-output-mono",               N_("Analog Mono Output"),           PA_DEVICE_PORT_TYPE_ANALOG },
@@ -3168,16 +3177,17 @@ int pa_alsa_path_probe(pa_alsa_path *p, pa_alsa_mapping *mapping, snd_mixer_t *m
     pa_log_debug("Probing path '%s'", p->name);
 
     PA_LLIST_FOREACH(j, p->jacks) {
+        pa_alsa_mixer_id_to_string(buf, sizeof(buf), &j->alsa_id);
         if (jack_probe(j, mapping, m) < 0) {
             p->supported = false;
-            pa_log_debug("Probe of jack '%s' failed.", j->alsa_name);
+            pa_log_debug("Probe of jack %s failed.", buf);
             return -1;
         }
-        pa_log_debug("Probe of jack '%s' succeeded (%s)", j->alsa_name, j->has_control ? "found!" : "not found");
+        pa_log_debug("Probe of jack %s succeeded (%s)", buf, j->has_control ? "found!" : "not found");
     }
 
     PA_LLIST_FOREACH(e, p->elements) {
-        alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+        pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
         if (element_probe(e, m) < 0) {
             p->supported = false;
             pa_log_debug("Probe of element %s failed.", buf);
@@ -3286,7 +3296,7 @@ void pa_alsa_setting_dump(pa_alsa_setting *s) {
 void pa_alsa_jack_dump(pa_alsa_jack *j) {
     pa_assert(j);
 
-    pa_log_debug("Jack %s, alsa_name='%s', detection %s", j->name, j->alsa_name, j->has_control ? "possible" : "unavailable");
+    pa_log_debug("Jack %s, alsa_name='%s', index='%d', detection %s", j->name, j->alsa_id.name, j->alsa_id.index, j->has_control ? "possible" : "unavailable");
 }
 
 void pa_alsa_option_dump(pa_alsa_option *o) {
@@ -3306,7 +3316,7 @@ void pa_alsa_element_dump(pa_alsa_element *e) {
     pa_alsa_option *o;
     pa_assert(e);
 
-    alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+    pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
     pa_log_debug("Element %s, direction=%i, switch=%i, volume=%i, volume_limit=%li, enumeration=%i, required=%i, required_any=%i, required_absent=%i, mask=0x%llx, n_channels=%u, override_map=%02x",
                  buf,
                  e->direction,
@@ -3366,7 +3376,7 @@ static void element_set_callback(pa_alsa_element *e, snd_mixer_t *m, snd_mixer_e
 
     SELEM_INIT(sid, &e->alsa_id);
     if (!(me = snd_mixer_find_selem(m, sid))) {
-        alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+        pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
         pa_log_warn("Element %s seems to have disappeared.", buf);
         return;
     }
@@ -3661,7 +3671,7 @@ static bool element_is_subset(pa_alsa_element *a, pa_alsa_element *b, snd_mixer_
 
                     SELEM_INIT(sid, &a->alsa_id);
                     if (!(me = snd_mixer_find_selem(m, sid))) {
-                        alsa_id_str(buf, sizeof(buf), &a->alsa_id);
+                        pa_alsa_mixer_id_to_string(buf, sizeof(buf), &a->alsa_id);
                         pa_log_warn("Element %s seems to have disappeared.", buf);
                         return false;
                     }
@@ -3692,7 +3702,7 @@ static bool element_is_subset(pa_alsa_element *a, pa_alsa_element *b, snd_mixer_
                 return false;
             for (s = 0; s <= SND_MIXER_SCHN_LAST; s++)
                 if (a->masks[s][a->n_channels-1] != b->masks[s][b->n_channels-1]) {
-                    alsa_id_str(buf, sizeof(buf), &a->alsa_id);
+                    pa_alsa_mixer_id_to_string(buf, sizeof(buf), &a->alsa_id);
                     pa_log_debug("Element %s is not a subset - mask a: 0x%" PRIx64 ", mask b: 0x%" PRIx64 ", at channel %d",
                                  buf, a->masks[s][a->n_channels-1], b->masks[s][b->n_channels-1], s);
                     return false;
@@ -3769,7 +3779,8 @@ 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(ja->alsa_id.name, jb->alsa_id.name) &&
+                       (ja->alsa_id.index == jb->alsa_id.index) &&
                        (ja->state_plugged == jb->state_plugged) &&
                        (ja->state_unplugged == jb->state_unplugged)) {
                         exists = true;
@@ -4459,7 +4470,8 @@ static void profile_set_set_availability_groups(pa_alsa_profile_set *ps) {
                 PA_LLIST_FOREACH(j2, p2->jacks) {
                     if (!j2->has_control || j2->state_plugged == PA_AVAILABLE_NO)
                         continue;
-                    if (pa_streq(j->alsa_name, j2->alsa_name)) {
+                    if (pa_streq(j->alsa_id.name, j2->alsa_id.name) &&
+                        j->alsa_id.index == j2->alsa_id.index) {
                         j->state_plugged = PA_AVAILABLE_UNKNOWN;
                         j2->state_plugged = PA_AVAILABLE_UNKNOWN;
                         found = p2->availability_group;


=====================================
src/modules/alsa/alsa-mixer.h
=====================================
@@ -115,6 +115,8 @@ struct pa_alsa_mixer_id {
     int index;
 };
 
+char *pa_alsa_mixer_id_to_string(char *dst, size_t dst_len, pa_alsa_mixer_id *id);
+
 /* An option belongs to an element and refers to one enumeration item
  * of the element is an enumeration item, or a switch status if the
  * element is a switch item. */
@@ -179,8 +181,8 @@ struct pa_alsa_jack {
     snd_mixer_t *mixer_handle;
     char *mixer_device_name;
 
+    struct pa_alsa_mixer_id alsa_id;
     char *name; /* E g "Headphone" */
-    char *alsa_name; /* E g "Headphone Jack" */
     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 */
@@ -196,7 +198,7 @@ struct pa_alsa_jack {
     bool append_pcm_to_name;
 };
 
-pa_alsa_jack *pa_alsa_jack_new(pa_alsa_path *path, const char *mixer_device_name, const char *name);
+pa_alsa_jack *pa_alsa_jack_new(pa_alsa_path *path, const char *mixer_device_name, const char *name, int index);
 void pa_alsa_jack_free(pa_alsa_jack *jack);
 void pa_alsa_jack_set_has_control(pa_alsa_jack *jack, bool has_control);
 void pa_alsa_jack_set_plugged_in(pa_alsa_jack *jack, bool plugged_in);


=====================================
src/modules/alsa/alsa-ucm.c
=====================================
@@ -1719,7 +1719,7 @@ static pa_alsa_jack* ucm_get_jack(pa_alsa_ucm_config *ucm, pa_alsa_ucm_device *d
         pa_log("[%s] No mixer device name for JackControl \"%s\"", device_name, jack_control);
         return NULL;
     }
-    j = pa_alsa_jack_new(NULL, mixer_device_name, name);
+    j = pa_alsa_jack_new(NULL, mixer_device_name, name, 0);
     PA_LLIST_PREPEND(pa_alsa_jack, ucm->jacks, j);
 
 finish:
@@ -1953,7 +1953,7 @@ static void ucm_mapping_jack_probe(pa_alsa_mapping *m, pa_hashmap *mixers) {
             continue;
         }
 
-        has_control = pa_alsa_mixer_find_card(mixer_handle, dev->jack->alsa_name, 0) != NULL;
+        has_control = pa_alsa_mixer_find_card(mixer_handle, &dev->jack->alsa_id, 0) != 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);
     }


=====================================
src/modules/alsa/alsa-util.c
=====================================
@@ -1635,8 +1635,8 @@ static snd_mixer_elem_t *pa_alsa_mixer_find(snd_mixer_t *mixer,
     return NULL;
 }
 
-snd_mixer_elem_t *pa_alsa_mixer_find_card(snd_mixer_t *mixer, const char *name, unsigned int device) {
-    return pa_alsa_mixer_find(mixer, SND_CTL_ELEM_IFACE_CARD, name, 0, device);
+snd_mixer_elem_t *pa_alsa_mixer_find_card(snd_mixer_t *mixer, struct pa_alsa_mixer_id *alsa_id, unsigned int device) {
+    return pa_alsa_mixer_find(mixer, SND_CTL_ELEM_IFACE_CARD, alsa_id->name, alsa_id->index, device);
 }
 
 snd_mixer_elem_t *pa_alsa_mixer_find_pcm(snd_mixer_t *mixer, const char *name, unsigned int device) {


=====================================
src/modules/alsa/alsa-util.h
=====================================
@@ -148,7 +148,7 @@ const char* pa_alsa_strerror(int errnum);
 
 bool pa_alsa_may_tsched(bool want);
 
-snd_mixer_elem_t *pa_alsa_mixer_find_card(snd_mixer_t *mixer, const char *name, unsigned int device);
+snd_mixer_elem_t *pa_alsa_mixer_find_card(snd_mixer_t *mixer, struct pa_alsa_mixer_id *alsa_id, unsigned int device);
 snd_mixer_elem_t *pa_alsa_mixer_find_pcm(snd_mixer_t *mixer, const char *name, unsigned int device);
 
 snd_mixer_t *pa_alsa_open_mixer(pa_hashmap *mixers, int alsa_card_index, bool probe);


=====================================
src/modules/alsa/mixer/paths/analog-output-headphones-2.conf
=====================================
@@ -13,17 +13,24 @@
 # You should have received a copy of the GNU Lesser General Public License
 # along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
 
-; Path for mixers that have a 'Headphone2' control
+; Path for the second headphone output on dual-headphone machines.
 ;
 ; See analog-output.conf.common for an explanation on the directives
 
 [General]
 priority = 98
-description-key = analog-output-headphones
 
 [Properties]
 device.icon_name = audio-headphones
 
+; HP EliteDesk 800 SFF Headphone
+[Jack Front Headphone,1]
+required-any = any
+
+; HP EliteDesk 800 DM Headphone
+[Jack Front Headphone Surround]
+required-any = any
+
 [Element Hardware Master]
 switch = mute
 volume = merge
@@ -47,6 +54,13 @@ volume = off
 switch = mute
 volume = zero
 
+[Element Headphone,1]
+required-any = any
+switch = mute
+volume = merge
+override-map.1 = all
+override-map.2 = all-left,all-right
+
 [Element Headphone+LO]
 switch = mute
 volume = zero
@@ -56,7 +70,7 @@ switch = off
 volume = off
 
 [Element Headphone2]
-required = any
+required-any = any
 switch = mute
 volume = merge
 override-map.1 = all


=====================================
src/modules/alsa/mixer/paths/analog-output-headphones.conf
=====================================
@@ -35,6 +35,10 @@ state.unplugged = unknown
 [Jack Front Headphone]
 required-any = any
 
+; HP EliteDesk 800 DM Headset
+[Jack Front Headphone Front]
+required-any = any
+
 [Jack Front Headphone Phantom]
 required-any = any
 state.plugged = unknown
@@ -89,6 +93,13 @@ volume = merge
 override-map.1 = all
 override-map.2 = all-left,all-right
 
+; This path is intended to control the first headphones, not
+; the second headphones. But it should not hurt if we leave the second
+; headphone jack enabled nonetheless.
+[Element Headphone,1]
+switch = mute
+volume = zero
+
 [Element Headset]
 required-any = any
 switch = mute


=====================================
src/modules/alsa/mixer/paths/analog-output-lineout.conf
=====================================
@@ -127,6 +127,10 @@ required-any = any
 switch = off
 volume = off
 
+[Element Headphone,1]
+switch = off
+volume = off
+
 [Element Headphone2]
 switch = off
 volume = off


=====================================
src/modules/alsa/mixer/paths/analog-output-mono.conf
=====================================
@@ -44,6 +44,10 @@ override-map.2 = all-left,all-right
 switch = mute
 volume = zero
 
+[Element Headphone,1]
+switch = mute
+volume = zero
+
 [Element Headphone+LO]
 switch = mute
 volume = zero


=====================================
src/modules/alsa/mixer/paths/analog-output-speaker-always.conf
=====================================
@@ -76,6 +76,10 @@ volume = off
 switch = mute
 volume = zero
 
+[Element Headphone,1]
+switch = mute
+volume = zero
+
 [Element Headphone2]
 switch = mute
 volume = zero


=====================================
src/modules/alsa/mixer/paths/analog-output-speaker.conf
=====================================
@@ -101,6 +101,10 @@ name = analog-output-speaker
 switch = off
 volume = off
 
+[Element Headphone,1]
+switch = off
+volume = off
+
 [Element Headphone2]
 switch = off
 volume = off


=====================================
src/modules/alsa/module-alsa-card.c
=====================================
@@ -623,6 +623,7 @@ static void init_jacks(struct userdata *u) {
     void *state;
     pa_alsa_path* path;
     pa_alsa_jack* jack;
+    char buf[64];
 
     u->jacks = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
 
@@ -665,9 +666,10 @@ static void init_jacks(struct userdata *u) {
             }
         }
         pa_alsa_mixer_set_fdlist(u->mixers, jack->mixer_handle, u->core->mainloop);
-        jack->melem = pa_alsa_mixer_find_card(jack->mixer_handle, jack->alsa_name, 0);
+        jack->melem = pa_alsa_mixer_find_card(jack->mixer_handle, &jack->alsa_id, 0);
         if (!jack->melem) {
-            pa_log_warn("Jack '%s' seems to have disappeared.", jack->alsa_name);
+            pa_alsa_mixer_id_to_string(buf, sizeof(buf), &jack->alsa_id);
+            pa_log_warn("Jack %s seems to have disappeared.", buf);
             pa_alsa_jack_set_has_control(jack, false);
             continue;
         }



View it on GitLab: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/compare/3ecea410d79d398126b54579b422e2f16baede5f...21a531041ab0b5e52dbde1e3ed4ab8fb49198fda

-- 
View it on GitLab: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/compare/3ecea410d79d398126b54579b422e2f16baede5f...21a531041ab0b5e52dbde1e3ed4ab8fb49198fda
You're receiving this email because of your account on gitlab.freedesktop.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/pulseaudio-commits/attachments/20201230/2baa99d0/attachment-0001.htm>


More information about the pulseaudio-commits mailing list