[pulseaudio-commits] 3 commits - src/modules

David Henningsson diwic at kemper.freedesktop.org
Tue Sep 16 00:34:45 PDT 2014


 src/modules/alsa/alsa-mixer.c       |   14 +---
 src/modules/alsa/alsa-mixer.h       |    6 -
 src/modules/alsa/alsa-sink.c        |    6 -
 src/modules/alsa/alsa-source.c      |    6 -
 src/modules/alsa/alsa-ucm.c         |    7 --
 src/modules/alsa/alsa-util.c        |  111 ++++++++++++++++++++++++------------
 src/modules/alsa/alsa-util.h        |    7 --
 src/modules/alsa/module-alsa-card.c |   50 ++++++++--------
 8 files changed, 120 insertions(+), 87 deletions(-)

New commits:
commit 300a5e3ed70064c296e09bc4e40531f3257154c5
Author: David Henningsson <david.henningsson at canonical.com>
Date:   Mon Sep 1 15:58:22 2014 +0200

    alsa: Remove unnecessary hctl handles being passed around
    
    Now that we have switched to using the mixer handle only,
    there is no use for sending hctl handles around.
    
    Signed-off-by: David Henningsson <david.henningsson at canonical.com>

diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
index 6be56fe..8b23d90 100644
--- a/src/modules/alsa/alsa-mixer.c
+++ b/src/modules/alsa/alsa-mixer.c
@@ -2657,7 +2657,7 @@ static void path_create_settings(pa_alsa_path *p) {
     element_create_settings(p->elements, NULL);
 }
 
-int pa_alsa_path_probe(pa_alsa_path *p, snd_mixer_t *m, snd_hctl_t *hctl, bool ignore_dB) {
+int pa_alsa_path_probe(pa_alsa_path *p, snd_mixer_t *m, bool ignore_dB) {
     pa_alsa_element *e;
     pa_alsa_jack *j;
     double min_dB[PA_CHANNEL_POSITION_MAX], max_dB[PA_CHANNEL_POSITION_MAX];
@@ -3851,7 +3851,6 @@ static void mapping_paths_probe(pa_alsa_mapping *m, pa_alsa_profile *profile,
     snd_pcm_t *pcm_handle;
     pa_alsa_path_set *ps;
     snd_mixer_t *mixer_handle;
-    snd_hctl_t *hctl_handle;
 
     if (direction == PA_ALSA_DIRECTION_OUTPUT) {
         if (m->output_path_set)
@@ -3870,7 +3869,7 @@ static void mapping_paths_probe(pa_alsa_mapping *m, pa_alsa_profile *profile,
 
     pa_assert(pcm_handle);
 
-    mixer_handle = pa_alsa_open_mixer_for_pcm(pcm_handle, NULL, &hctl_handle);
+    mixer_handle = pa_alsa_open_mixer_for_pcm(pcm_handle, NULL);
     if (!mixer_handle) {
         /* Cannot open mixer, remove all entries */
         pa_hashmap_remove_all(ps->paths);
@@ -3878,7 +3877,7 @@ static void mapping_paths_probe(pa_alsa_mapping *m, pa_alsa_profile *profile,
     }
 
     PA_HASHMAP_FOREACH(p, ps->paths, state) {
-        if (pa_alsa_path_probe(p, mixer_handle, hctl_handle, m->profile_set->ignore_dB) < 0) {
+        if (pa_alsa_path_probe(p, mixer_handle, m->profile_set->ignore_dB) < 0) {
             pa_hashmap_remove(ps->paths, p);
         }
     }
diff --git a/src/modules/alsa/alsa-mixer.h b/src/modules/alsa/alsa-mixer.h
index ff3cb2d..7e6300e 100644
--- a/src/modules/alsa/alsa-mixer.h
+++ b/src/modules/alsa/alsa-mixer.h
@@ -226,7 +226,7 @@ void pa_alsa_element_dump(pa_alsa_element *e);
 
 pa_alsa_path *pa_alsa_path_new(const char *paths_dir, const char *fname, pa_alsa_direction_t direction);
 pa_alsa_path *pa_alsa_path_synthesize(const char *element, pa_alsa_direction_t direction);
-int pa_alsa_path_probe(pa_alsa_path *p, snd_mixer_t *m, snd_hctl_t *hctl, bool ignore_dB);
+int pa_alsa_path_probe(pa_alsa_path *p, snd_mixer_t *m, bool ignore_dB);
 void pa_alsa_path_dump(pa_alsa_path *p);
 int pa_alsa_path_get_volume(pa_alsa_path *p, snd_mixer_t *m, const pa_channel_map *cm, pa_cvolume *v);
 int pa_alsa_path_get_mute(pa_alsa_path *path, snd_mixer_t *m, bool *muted);
@@ -335,7 +335,7 @@ void pa_alsa_profile_set_free(pa_alsa_profile_set *s);
 void pa_alsa_profile_set_dump(pa_alsa_profile_set *s);
 void pa_alsa_profile_set_drop_unsupported(pa_alsa_profile_set *s);
 
-snd_mixer_t *pa_alsa_open_mixer_for_pcm(snd_pcm_t *pcm, char **ctl_device, snd_hctl_t **hctl);
+snd_mixer_t *pa_alsa_open_mixer_for_pcm(snd_pcm_t *pcm, char **ctl_device);
 
 pa_alsa_fdlist *pa_alsa_fdlist_new(void);
 void pa_alsa_fdlist_free(pa_alsa_fdlist *fdl);
diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index daa9061..9e9b863 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -1886,12 +1886,10 @@ static void set_sink_name(pa_sink_new_data *data, pa_modargs *ma, const char *de
 }
 
 static void find_mixer(struct userdata *u, pa_alsa_mapping *mapping, const char *element, bool ignore_dB) {
-    snd_hctl_t *hctl;
-
     if (!mapping && !element)
         return;
 
-    if (!(u->mixer_handle = pa_alsa_open_mixer_for_pcm(u->pcm_handle, &u->control_device, &hctl))) {
+    if (!(u->mixer_handle = pa_alsa_open_mixer_for_pcm(u->pcm_handle, &u->control_device))) {
         pa_log_info("Failed to find a working mixer device.");
         return;
     }
@@ -1901,7 +1899,7 @@ static void find_mixer(struct userdata *u, pa_alsa_mapping *mapping, const char
         if (!(u->mixer_path = pa_alsa_path_synthesize(element, PA_ALSA_DIRECTION_OUTPUT)))
             goto fail;
 
-        if (pa_alsa_path_probe(u->mixer_path, u->mixer_handle, hctl, ignore_dB) < 0)
+        if (pa_alsa_path_probe(u->mixer_path, u->mixer_handle, ignore_dB) < 0)
             goto fail;
 
         pa_log_debug("Probed mixer path %s:", u->mixer_path->name);
diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
index c0759c6..2da0513 100644
--- a/src/modules/alsa/alsa-source.c
+++ b/src/modules/alsa/alsa-source.c
@@ -1604,12 +1604,10 @@ static void set_source_name(pa_source_new_data *data, pa_modargs *ma, const char
 }
 
 static void find_mixer(struct userdata *u, pa_alsa_mapping *mapping, const char *element, bool ignore_dB) {
-    snd_hctl_t *hctl;
-
     if (!mapping && !element)
         return;
 
-    if (!(u->mixer_handle = pa_alsa_open_mixer_for_pcm(u->pcm_handle, &u->control_device, &hctl))) {
+    if (!(u->mixer_handle = pa_alsa_open_mixer_for_pcm(u->pcm_handle, &u->control_device))) {
         pa_log_info("Failed to find a working mixer device.");
         return;
     }
@@ -1619,7 +1617,7 @@ static void find_mixer(struct userdata *u, pa_alsa_mapping *mapping, const char
         if (!(u->mixer_path = pa_alsa_path_synthesize(element, PA_ALSA_DIRECTION_INPUT)))
             goto fail;
 
-        if (pa_alsa_path_probe(u->mixer_path, u->mixer_handle, hctl, ignore_dB) < 0)
+        if (pa_alsa_path_probe(u->mixer_path, u->mixer_handle, ignore_dB) < 0)
             goto fail;
 
         pa_log_debug("Probed mixer path %s:", u->mixer_path->name);
diff --git a/src/modules/alsa/alsa-ucm.c b/src/modules/alsa/alsa-ucm.c
index 23522c7..6c848a9 100644
--- a/src/modules/alsa/alsa-ucm.c
+++ b/src/modules/alsa/alsa-ucm.c
@@ -1426,21 +1426,20 @@ static void profile_finalize_probing(pa_alsa_profile *p) {
 static void ucm_mapping_jack_probe(pa_alsa_mapping *m) {
     snd_pcm_t *pcm_handle;
     snd_mixer_t *mixer_handle;
-    snd_hctl_t *hctl_handle;
     pa_alsa_ucm_mapping_context *context = &m->ucm_context;
     pa_alsa_ucm_device *dev;
     uint32_t idx;
 
     pcm_handle = m->direction == PA_ALSA_DIRECTION_OUTPUT ? m->output_pcm : m->input_pcm;
-    mixer_handle = pa_alsa_open_mixer_for_pcm(pcm_handle, NULL, &hctl_handle);
-    if (!mixer_handle || !hctl_handle)
+    mixer_handle = pa_alsa_open_mixer_for_pcm(pcm_handle, NULL);
+    if (!mixer_handle)
         return;
 
     PA_IDXSET_FOREACH(dev, context->ucm_devices, idx) {
         pa_alsa_jack *jack;
         jack = m->direction == PA_ALSA_DIRECTION_OUTPUT ? dev->output_jack : dev->input_jack;
         pa_assert (jack);
-        jack->has_control = pa_alsa_find_jack(hctl_handle, jack->alsa_name) != NULL;
+        jack->has_control = pa_alsa_mixer_find(mixer_handle, jack->alsa_name, 0) != NULL;
         pa_log_info("UCM jack %s has_control=%d", jack->name, jack->has_control);
     }
 
diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c
index 97edb67..0563c00 100644
--- a/src/modules/alsa/alsa-util.c
+++ b/src/modules/alsa/alsa-util.c
@@ -1476,30 +1476,6 @@ snd_mixer_elem_t *pa_alsa_mixer_find(snd_mixer_t *mixer, const char *name, unsig
     return NULL;
 }
 
-snd_hctl_elem_t* pa_alsa_find_jack(snd_hctl_t *hctl, const char* jack_name) {
-    snd_ctl_elem_id_t *id;
-
-    snd_ctl_elem_id_alloca(&id);
-    snd_ctl_elem_id_clear(id);
-    snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_CARD);
-    snd_ctl_elem_id_set_name(id, jack_name);
-
-    return snd_hctl_find_elem(hctl, id);
-}
-
-snd_hctl_elem_t* pa_alsa_find_eld_ctl(snd_hctl_t *hctl, int device) {
-    snd_ctl_elem_id_t *id;
-
-    /* See if we can find the ELD control */
-    snd_ctl_elem_id_alloca(&id);
-    snd_ctl_elem_id_clear(id);
-    snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_PCM);
-    snd_ctl_elem_id_set_name(id, "ELD");
-    snd_ctl_elem_id_set_device(id, device);
-
-    return snd_hctl_find_elem(hctl, id);
-}
-
 static int mixer_class_compare(const snd_mixer_elem_t *c1, const snd_mixer_elem_t *c2)
 {
     /* Dummy compare function */
@@ -1544,7 +1520,7 @@ static int mixer_class_event(snd_mixer_class_t *class, unsigned int mask,
     return 0;
 }
 
-static int prepare_mixer(snd_mixer_t *mixer, const char *dev, snd_hctl_t **hctl) {
+static int prepare_mixer(snd_mixer_t *mixer, const char *dev) {
     int err;
     snd_mixer_class_t *class;
 
@@ -1556,13 +1532,6 @@ static int prepare_mixer(snd_mixer_t *mixer, const char *dev, snd_hctl_t **hctl)
         return -1;
     }
 
-    /* Note: The hctl handle returned should not be freed.
-       It is closed/freed by alsa-lib on snd_mixer_close/free */
-    if (hctl && (err = snd_mixer_get_hctl(mixer, dev, hctl)) < 0) {
-        pa_log_info("Unable to get hctl of mixer %s: %s", dev, pa_alsa_strerror(err));
-        return -1;
-    }
-
     if (snd_mixer_class_malloc(&class)) {
         pa_log_info("Failed to allocate mixer class for %s", dev);
         return -1;
@@ -1590,7 +1559,7 @@ static int prepare_mixer(snd_mixer_t *mixer, const char *dev, snd_hctl_t **hctl)
     return 0;
 }
 
-snd_mixer_t *pa_alsa_open_mixer(int alsa_card_index, char **ctl_device, snd_hctl_t **hctl) {
+snd_mixer_t *pa_alsa_open_mixer(int alsa_card_index, char **ctl_device) {
     int err;
     snd_mixer_t *m;
     char *md;
@@ -1604,7 +1573,7 @@ snd_mixer_t *pa_alsa_open_mixer(int alsa_card_index, char **ctl_device, snd_hctl
 
     /* Then, try by card index */
     md = pa_sprintf_malloc("hw:%i", alsa_card_index);
-    if (prepare_mixer(m, md, hctl) >= 0) {
+    if (prepare_mixer(m, md) >= 0) {
 
         if (ctl_device)
             *ctl_device = md;
@@ -1620,7 +1589,7 @@ snd_mixer_t *pa_alsa_open_mixer(int alsa_card_index, char **ctl_device, snd_hctl
     return NULL;
 }
 
-snd_mixer_t *pa_alsa_open_mixer_for_pcm(snd_pcm_t *pcm, char **ctl_device, snd_hctl_t **hctl) {
+snd_mixer_t *pa_alsa_open_mixer_for_pcm(snd_pcm_t *pcm, char **ctl_device) {
     int err;
     snd_mixer_t *m;
     const char *dev;
@@ -1636,7 +1605,7 @@ snd_mixer_t *pa_alsa_open_mixer_for_pcm(snd_pcm_t *pcm, char **ctl_device, snd_h
 
     /* First, try by name */
     if ((dev = snd_pcm_name(pcm)))
-        if (prepare_mixer(m, dev, hctl) >= 0) {
+        if (prepare_mixer(m, dev) >= 0) {
             if (ctl_device)
                 *ctl_device = pa_xstrdup(dev);
 
@@ -1653,7 +1622,7 @@ snd_mixer_t *pa_alsa_open_mixer_for_pcm(snd_pcm_t *pcm, char **ctl_device, snd_h
             md = pa_sprintf_malloc("hw:%i", card_idx);
 
             if (!dev || !pa_streq(dev, md))
-                if (prepare_mixer(m, md, hctl) >= 0) {
+                if (prepare_mixer(m, md) >= 0) {
 
                     if (ctl_device)
                         *ctl_device = md;
@@ -1671,25 +1640,19 @@ snd_mixer_t *pa_alsa_open_mixer_for_pcm(snd_pcm_t *pcm, char **ctl_device, snd_h
     return NULL;
 }
 
-int pa_alsa_get_hdmi_eld(snd_hctl_t *hctl, int device, pa_hdmi_eld *eld) {
+int pa_alsa_get_hdmi_eld(snd_hctl_elem_t *elem, pa_hdmi_eld *eld) {
 
     /* The ELD format is specific to HDA Intel sound cards and defined in the
        HDA specification: http://www.intel.com/content/www/us/en/standards/high-definition-audio-specification.html */
     int err;
-    snd_hctl_elem_t *elem;
     snd_ctl_elem_info_t *info;
     snd_ctl_elem_value_t *value;
     uint8_t *elddata;
     unsigned int eldsize, mnl;
+    unsigned int device;
 
     pa_assert(eld != NULL);
-
-    /* See if we can find the ELD control */
-    elem = pa_alsa_find_eld_ctl(hctl, device);
-    if (elem == NULL) {
-        pa_log_debug("No ELD info control found (for device=%d)", device);
-        return -1;
-    }
+    pa_assert(elem != NULL);
 
     /* Does it have any contents? */
     snd_ctl_elem_info_alloca(&info);
@@ -1700,6 +1663,7 @@ int pa_alsa_get_hdmi_eld(snd_hctl_t *hctl, int device, pa_hdmi_eld *eld) {
         return -1;
     }
 
+    device = snd_hctl_elem_get_device(elem);
     eldsize = snd_ctl_elem_info_get_count(info);
     elddata = (unsigned char *) snd_ctl_elem_value_get_bytes(value);
     if (elddata == NULL || eldsize == 0) {
diff --git a/src/modules/alsa/alsa-util.h b/src/modules/alsa/alsa-util.h
index 50b0aaf..fb47940 100644
--- a/src/modules/alsa/alsa-util.h
+++ b/src/modules/alsa/alsa-util.h
@@ -142,18 +142,15 @@ const char* pa_alsa_strerror(int errnum);
 
 bool pa_alsa_may_tsched(bool want);
 
-snd_hctl_elem_t* pa_alsa_find_jack(snd_hctl_t *hctl, const char* jack_name);
-snd_hctl_elem_t* pa_alsa_find_eld_ctl(snd_hctl_t *hctl, int device);
-
 snd_mixer_elem_t *pa_alsa_mixer_find(snd_mixer_t *mixer, const char *name, unsigned int device);
 
-snd_mixer_t *pa_alsa_open_mixer(int alsa_card_index, char **ctl_device, snd_hctl_t **hctl);
+snd_mixer_t *pa_alsa_open_mixer(int alsa_card_index, char **ctl_device);
 
 typedef struct pa_hdmi_eld pa_hdmi_eld;
 struct pa_hdmi_eld {
     char monitor_name[17];
 };
 
-int pa_alsa_get_hdmi_eld(snd_hctl_t *hctl, int device, pa_hdmi_eld *eld);
+int pa_alsa_get_hdmi_eld(snd_hctl_elem_t *elem, pa_hdmi_eld *eld);
 
 #endif
diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c
index d39d13e..ed332e0 100644
--- a/src/modules/alsa/module-alsa-card.c
+++ b/src/modules/alsa/module-alsa-card.c
@@ -111,7 +111,6 @@ struct userdata {
     int alsa_card_index;
 
     snd_mixer_t *mixer_handle;
-    snd_hctl_t *hctl_handle;
     pa_hashmap *jacks;
     pa_alsa_fdlist *mixer_fdl;
 
@@ -422,7 +421,7 @@ static int hdmi_eld_changed(snd_mixer_elem_t *melem, unsigned int mask) {
         return 0;
     }
 
-    if (pa_alsa_get_hdmi_eld(u->hctl_handle, device, &eld) < 0)
+    if (pa_alsa_get_hdmi_eld(elem, &eld) < 0)
         memset(&eld, 0, sizeof(eld));
 
     old_monitor_name = pa_proplist_gets(p->proplist, PA_PROP_DEVICE_PRODUCT_NAME);
@@ -444,7 +443,7 @@ static void init_eld_ctls(struct userdata *u) {
     void *state;
     pa_device_port *port;
 
-    if (!u->hctl_handle)
+    if (!u->mixer_handle)
         return;
 
     PA_HASHMAP_FOREACH(port, u->card->ports, state) {
@@ -501,7 +500,7 @@ static void init_jacks(struct userdata *u) {
 
     u->mixer_fdl = pa_alsa_fdlist_new();
 
-    u->mixer_handle = pa_alsa_open_mixer(u->alsa_card_index, NULL, &u->hctl_handle);
+    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);
@@ -516,7 +515,7 @@ static void init_jacks(struct userdata *u) {
         }
 
     } else
-        pa_log("Failed to open hctl/mixer for jack detection");
+        pa_log("Failed to open mixer for jack detection");
 
 }
 

commit f2120fc2b69579d51a2e1874649739a799815be9
Author: David Henningsson <david.henningsson at canonical.com>
Date:   Mon Sep 1 15:41:39 2014 +0200

    alsa-mixer/card: Move to use the new mixer interface
    
    Use the new mixer API to get callbacks, instead of using the hctl
    API. Using the hctl API caused a memory leak, because alsa-lib itself
    used the hctl callbacks, which we were previously overriding.
    
    Signed-off-by: David Henningsson <david.henningsson at canonical.com>

diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
index 201f835..6be56fe 100644
--- a/src/modules/alsa/alsa-mixer.c
+++ b/src/modules/alsa/alsa-mixer.c
@@ -1725,12 +1725,11 @@ static int element_probe(pa_alsa_element *e, snd_mixer_t *m) {
     return 0;
 }
 
-static int jack_probe(pa_alsa_jack *j, snd_hctl_t *h) {
-    pa_assert(h);
+static int jack_probe(pa_alsa_jack *j, snd_mixer_t *m) {
     pa_assert(j);
     pa_assert(j->path);
 
-    j->has_control = pa_alsa_find_jack(h, j->alsa_name) != NULL;
+    j->has_control = pa_alsa_mixer_find(m, j->alsa_name, 0) != NULL;
 
     if (j->has_control) {
         if (j->required_absent != PA_ALSA_REQUIRED_IGNORE)
@@ -2678,7 +2677,7 @@ int pa_alsa_path_probe(pa_alsa_path *p, snd_mixer_t *m, snd_hctl_t *hctl, bool i
     pa_log_debug("Probing path '%s'", p->name);
 
     PA_LLIST_FOREACH(j, p->jacks) {
-        if (jack_probe(j, hctl) < 0) {
+        if (jack_probe(j, m) < 0) {
             p->supported = false;
             pa_log_debug("Probe of jack '%s' failed.", j->alsa_name);
             return -1;
diff --git a/src/modules/alsa/alsa-mixer.h b/src/modules/alsa/alsa-mixer.h
index 4949560..ff3cb2d 100644
--- a/src/modules/alsa/alsa-mixer.h
+++ b/src/modules/alsa/alsa-mixer.h
@@ -164,7 +164,7 @@ struct pa_alsa_jack {
     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_hctl_elem_t *hctl_elem; /* Jack detection handle */
+    snd_mixer_elem_t *melem; /* Jack detection handle */
     pa_available_t state_unplugged, state_plugged;
 
     pa_alsa_required_t required;
diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c
index 63ff6e6..d39d13e 100644
--- a/src/modules/alsa/module-alsa-card.c
+++ b/src/modules/alsa/module-alsa-card.c
@@ -350,8 +350,9 @@ static void report_port_state(pa_device_port *p, struct userdata *u) {
     pa_device_port_set_available(p, pa);
 }
 
-static int report_jack_state(snd_hctl_elem_t *elem, unsigned int mask) {
-    struct userdata *u = snd_hctl_elem_get_callback_private(elem);
+static int report_jack_state(snd_mixer_elem_t *melem, unsigned int mask) {
+    struct userdata *u = snd_mixer_elem_get_callback_private(melem);
+    snd_hctl_elem_t *elem = snd_mixer_elem_get_private(melem);
     snd_ctl_elem_value_t *elem_value;
     bool plugged_in;
     void *state;
@@ -374,7 +375,7 @@ static int report_jack_state(snd_hctl_elem_t *elem, unsigned int mask) {
     pa_log_debug("Jack '%s' is now %s", pa_strnull(snd_hctl_elem_get_name(elem)), plugged_in ? "plugged in" : "unplugged");
 
     PA_HASHMAP_FOREACH(jack, u->jacks, state)
-        if (jack->hctl_elem == elem) {
+        if (jack->melem == melem) {
             jack->plugged_in = plugged_in;
             if (u->use_ucm) {
                 pa_assert(u->card->ports);
@@ -403,8 +404,9 @@ static pa_device_port* find_port_with_eld_device(pa_hashmap *ports, int device)
     return NULL;
 }
 
-static int hdmi_eld_changed(snd_hctl_elem_t *elem, unsigned int mask) {
-    struct userdata *u = snd_hctl_elem_get_callback_private(elem);
+static int hdmi_eld_changed(snd_mixer_elem_t *melem, unsigned int mask) {
+    struct userdata *u = snd_mixer_elem_get_callback_private(melem);
+    snd_hctl_elem_t *elem = snd_mixer_elem_get_private(melem);
     int device = snd_hctl_elem_get_device(elem);
     const char *old_monitor_name;
     pa_device_port *p;
@@ -447,7 +449,7 @@ static void init_eld_ctls(struct userdata *u) {
 
     PA_HASHMAP_FOREACH(port, u->card->ports, state) {
         pa_alsa_port_data *data = PA_DEVICE_PORT_DATA(port);
-        snd_hctl_elem_t* hctl_elem;
+        snd_mixer_elem_t* melem;
         int device;
 
         pa_assert(data->path);
@@ -455,15 +457,14 @@ static void init_eld_ctls(struct userdata *u) {
         if (device < 0)
             continue;
 
-        hctl_elem = pa_alsa_find_eld_ctl(u->hctl_handle, device);
-        if (!hctl_elem) {
-            pa_log_debug("No ELD device found for port %s.", port->name);
-            continue;
+        melem = pa_alsa_mixer_find(u->mixer_handle, "ELD", device);
+        if (melem) {
+            snd_mixer_elem_set_callback(melem, hdmi_eld_changed);
+            snd_mixer_elem_set_callback_private(melem, u);
+            hdmi_eld_changed(melem, 0);
         }
-
-        snd_hctl_elem_set_callback_private(hctl_elem, u);
-        snd_hctl_elem_set_callback(hctl_elem, hdmi_eld_changed);
-        hdmi_eld_changed(hctl_elem, 0);
+        else
+            pa_log_debug("No ELD device found for port %s.", port->name);
     }
 }
 
@@ -501,17 +502,17 @@ static void init_jacks(struct userdata *u) {
     u->mixer_fdl = pa_alsa_fdlist_new();
 
     u->mixer_handle = pa_alsa_open_mixer(u->alsa_card_index, NULL, &u->hctl_handle);
-    if (u->mixer_handle && pa_alsa_fdlist_set_handle(u->mixer_fdl, NULL, u->hctl_handle, u->core->mainloop) >= 0) {
+    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->hctl_elem = pa_alsa_find_jack(u->hctl_handle, jack->alsa_name);
-            if (!jack->hctl_elem) {
+            jack->melem = pa_alsa_mixer_find(u->mixer_handle, jack->alsa_name, 0);
+            if (!jack->melem) {
                 pa_log_warn("Jack '%s' seems to have disappeared.", jack->alsa_name);
                 jack->has_control = false;
                 continue;
             }
-            snd_hctl_elem_set_callback_private(jack->hctl_elem, u);
-            snd_hctl_elem_set_callback(jack->hctl_elem, report_jack_state);
-            report_jack_state(jack->hctl_elem, 0);
+            snd_mixer_elem_set_callback(jack->melem, report_jack_state);
+            snd_mixer_elem_set_callback_private(jack->melem, u);
+            report_jack_state(jack->melem, 0);
         }
 
     } else

commit 1fd8848e64cfb352d0ab12ee27c8c667d81a8f6d
Author: David Henningsson <david.henningsson at canonical.com>
Date:   Mon Sep 1 15:38:25 2014 +0200

    alsa-util: Add functions for accessing mixer elements through mixer class
    
    Instead of using the hctl interface, we can find controls belonging
    to other iface types than "mixer". We do this by introducing a new
    mixer class "SND_MIXER_ELEM_PULSEAUDIO" and create snd_mixer_elem's
    for all PCM and CARD iface types (as Jacks are of the CARD type and
    ELD controls are of the PCM type).
    
    Signed-off-by: David Henningsson <david.henningsson at canonical.com>

diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c
index 1ce2e16..97edb67 100644
--- a/src/modules/alsa/alsa-util.c
+++ b/src/modules/alsa/alsa-util.c
@@ -1457,6 +1457,25 @@ bool pa_alsa_may_tsched(bool want) {
     return true;
 }
 
+#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 *elem;
+
+    for (elem = snd_mixer_first_elem(mixer); elem; elem = snd_mixer_elem_next(elem)) {
+        snd_hctl_elem_t *helem;
+        if (snd_mixer_elem_get_type(elem) != SND_MIXER_ELEM_PULSEAUDIO)
+            continue;
+        helem = snd_mixer_elem_get_private(elem);
+        if (!pa_streq(snd_hctl_elem_get_name(helem), name))
+            continue;
+        if (snd_hctl_elem_get_device(helem) != device)
+            continue;
+        return elem;
+    }
+    return NULL;
+}
+
 snd_hctl_elem_t* pa_alsa_find_jack(snd_hctl_t *hctl, const char* jack_name) {
     snd_ctl_elem_id_t *id;
 
@@ -1481,8 +1500,53 @@ snd_hctl_elem_t* pa_alsa_find_eld_ctl(snd_hctl_t *hctl, int device) {
     return snd_hctl_find_elem(hctl, id);
 }
 
+static int mixer_class_compare(const snd_mixer_elem_t *c1, const snd_mixer_elem_t *c2)
+{
+    /* Dummy compare function */
+    return c1 == c2 ? 0 : (c1 > c2 ? 1 : -1);
+}
+
+static int mixer_class_event(snd_mixer_class_t *class, unsigned int mask,
+			snd_hctl_elem_t *helem, snd_mixer_elem_t *melem)
+{
+    int err;
+    const char *name = snd_hctl_elem_get_name(helem);
+    if (mask & SND_CTL_EVENT_MASK_ADD) {
+        snd_ctl_elem_iface_t iface = snd_hctl_elem_get_interface(helem);
+        if (iface == SND_CTL_ELEM_IFACE_CARD || iface == SND_CTL_ELEM_IFACE_PCM) {
+            snd_mixer_elem_t *new_melem;
+
+            /* Put the hctl pointer as our private data - it will be useful for callbacks */
+            if ((err = snd_mixer_elem_new(&new_melem, SND_MIXER_ELEM_PULSEAUDIO, 0, helem, NULL)) < 0) {
+                pa_log_warn("snd_mixer_elem_new failed: %s", pa_alsa_strerror(err));
+                return 0;
+            }
+
+            if ((err = snd_mixer_elem_attach(new_melem, helem)) < 0) {
+                pa_log_warn("snd_mixer_elem_attach failed: %s", pa_alsa_strerror(err));
+		snd_mixer_elem_free(melem);
+                return 0;
+            }
+
+            if ((err = snd_mixer_elem_add(new_melem, class)) < 0) {
+                pa_log_warn("snd_mixer_elem_add failed: %s", pa_alsa_strerror(err));
+                return 0;
+            }
+        }
+    }
+    else if (mask & SND_CTL_EVENT_MASK_VALUE) {
+        snd_mixer_elem_value(melem); /* Calls the element callback */
+        return 0;
+    }
+    else
+        pa_log_info("Got an unknown mixer class event for %s: mask 0x%x\n", name, mask);
+
+    return 0;
+}
+
 static int prepare_mixer(snd_mixer_t *mixer, const char *dev, snd_hctl_t **hctl) {
     int err;
+    snd_mixer_class_t *class;
 
     pa_assert(mixer);
     pa_assert(dev);
@@ -1499,6 +1563,19 @@ static int prepare_mixer(snd_mixer_t *mixer, const char *dev, snd_hctl_t **hctl)
         return -1;
     }
 
+    if (snd_mixer_class_malloc(&class)) {
+        pa_log_info("Failed to allocate mixer class for %s", dev);
+        return -1;
+    }
+    snd_mixer_class_set_event(class, mixer_class_event);
+    snd_mixer_class_set_compare(class, mixer_class_compare);
+    if ((err = snd_mixer_class_register(class, mixer)) < 0) {
+        pa_log_info("Unable register mixer class for %s: %s", dev, pa_alsa_strerror(err));
+        snd_mixer_class_free(class);
+        return -1;
+    }
+    /* From here on, the mixer class is deallocated by alsa on snd_mixer_close/free. */
+
     if ((err = snd_mixer_selem_register(mixer, NULL, NULL)) < 0) {
         pa_log_warn("Unable to register mixer: %s", pa_alsa_strerror(err));
         return -1;
diff --git a/src/modules/alsa/alsa-util.h b/src/modules/alsa/alsa-util.h
index bb2ad4e..50b0aaf 100644
--- a/src/modules/alsa/alsa-util.h
+++ b/src/modules/alsa/alsa-util.h
@@ -145,6 +145,8 @@ bool pa_alsa_may_tsched(bool want);
 snd_hctl_elem_t* pa_alsa_find_jack(snd_hctl_t *hctl, const char* jack_name);
 snd_hctl_elem_t* pa_alsa_find_eld_ctl(snd_hctl_t *hctl, int device);
 
+snd_mixer_elem_t *pa_alsa_mixer_find(snd_mixer_t *mixer, const char *name, unsigned int device);
+
 snd_mixer_t *pa_alsa_open_mixer(int alsa_card_index, char **ctl_device, snd_hctl_t **hctl);
 
 typedef struct pa_hdmi_eld pa_hdmi_eld;



More information about the pulseaudio-commits mailing list