[pulseaudio-discuss] [PATCH 2/2] chnages in pulseaudio alsa module to support UCM

jankovac503 at gmail.com jankovac503 at gmail.com
Wed Nov 2 16:55:24 PDT 2011


From: Janos Kovacs <jankovac503 at gmail.com>

---
 src/Makefile.am                     |    1 +
 src/modules/alsa/alsa-mixer.c       |   80 ++++++++++++---------
 src/modules/alsa/alsa-mixer.h       |   19 ++++-
 src/modules/alsa/alsa-sink.c        |   58 +++++++++++---
 src/modules/alsa/alsa-source.c      |   53 +++++++++++---
 src/modules/alsa/module-alsa-card.c |  138 +++++++++++++++++++++--------------
 6 files changed, 234 insertions(+), 115 deletions(-)

diff --git a/src/Makefile.am b/src/Makefile.am
index b5de764..0c97b7a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1563,6 +1563,7 @@ libalsa_util_la_SOURCES = \
 		modules/alsa/alsa-mixer.c modules/alsa/alsa-mixer.h \
 		modules/alsa/alsa-sink.c modules/alsa/alsa-sink.h \
 		modules/alsa/alsa-source.c modules/alsa/alsa-source.h \
+		modules/alsa/alsa-ucm.c modules/alsa/alsa-ucm.h \
 		modules/reserve-wrap.c modules/reserve-wrap.h
 libalsa_util_la_LDFLAGS = -avoid-version
 libalsa_util_la_LIBADD = $(MODULE_LIBADD) $(ASOUNDLIB_LIBS)
diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
index 9a5c066..c063fed 100644
--- a/src/modules/alsa/alsa-mixer.c
+++ b/src/modules/alsa/alsa-mixer.c
@@ -557,6 +557,11 @@ void pa_alsa_path_free(pa_alsa_path *p) {
 
     pa_xfree(p->name);
     pa_xfree(p->description);
+    pa_xfree(p->ucm_verb);
+    pa_xfree(p->ucm_device);
+
+    pa_xstrfreev(p->ucm_modifiers);
+
     pa_xfree(p);
 }
 
@@ -1232,14 +1237,14 @@ static int element_set_constant_volume(pa_alsa_element *e, snd_mixer_t *m) {
     return r;
 }
 
-int pa_alsa_path_select(pa_alsa_path *p, snd_mixer_t *m) {
+int pa_alsa_mixer_path_select(pa_alsa_path *p, snd_mixer_t *m) {
     pa_alsa_element *e;
     int r = 0;
 
     pa_assert(m);
     pa_assert(p);
 
-    pa_log_debug("Activating path %s", p->name);
+    pa_log_debug("Activating mixer path %s", p->name);
     pa_alsa_path_dump(p);
 
     PA_LLIST_FOREACH(e, p->elements) {
@@ -3070,32 +3075,36 @@ static void path_set_condense(pa_alsa_path_set *ps, snd_mixer_t *m) {
         pa_alsa_path *p2;
         void *state2;
 
+	if (p->use_ucm)
+	    continue;
+
         PA_HASHMAP_FOREACH(p2, ps->paths, state2) {
             pa_alsa_element *ea, *eb;
             pa_bool_t is_subset = TRUE;
 
-            if (p == p2)
+            if (p == p2 || p2->use_ucm)
                 continue;
 
             /* Compare the elements of each set... */
-            pa_assert_se(ea = p->elements);
-            pa_assert_se(eb = p2->elements);
-
-            while (is_subset) {
-                if (pa_streq(ea->alsa_name, eb->alsa_name)) {
-                    if (element_is_subset(ea, eb, m)) {
-                        ea = ea->next;
-                        eb = eb->next;
-                        if ((ea && !eb) || (!ea && eb))
-                            is_subset = FALSE;
-                        else if (!ea && !eb)
-                            break;
-                    } else
-                        is_subset = FALSE;
-
-                } else
-                    is_subset = FALSE;
-            }
+            if (!(ea = p->elements) || !(eb = p2->elements))
+	        is_subset= FALSE;
+	    else {
+                while (is_subset) {
+                    if (pa_streq(ea->alsa_name, eb->alsa_name)) {
+                        if (element_is_subset(ea, eb, m)) {
+                            ea = ea->next;
+			    eb = eb->next;
+                            if ((ea && !eb) || (!ea && eb))
+                                is_subset = FALSE;
+			    else if (!ea && !eb)
+			        break;
+			} else
+			    is_subset = FALSE;
+
+		    } else
+		        is_subset = FALSE;
+		}
+	    }
 
             if (is_subset) {
                 pa_log_debug("Removing path '%s' as it is a subset of '%s'.", p->name, p2->name);
@@ -3188,6 +3197,9 @@ static void profile_free(pa_alsa_profile *p) {
     if (p->output_mappings)
         pa_idxset_free(p->output_mappings, NULL, NULL);
 
+    pa_xfree(p->ucm_verb);
+    pa_xstrfreev(p->ucm_modifiers);
+
     pa_xfree(p);
 }
 
@@ -3242,7 +3254,7 @@ void pa_alsa_profile_set_free(pa_alsa_profile_set *ps) {
     pa_xfree(ps);
 }
 
-static pa_alsa_mapping *mapping_get(pa_alsa_profile_set *ps, const char *name) {
+pa_alsa_mapping *pa_alsa_mapping_get(pa_alsa_profile_set *ps, const char *name) {
     pa_alsa_mapping *m;
 
     if (!pa_startswith(name, "Mapping "))
@@ -3317,7 +3329,7 @@ static int mapping_parse_device_strings(
 
     pa_assert(ps);
 
-    if (!(m = mapping_get(ps, section))) {
+    if (!(m = pa_alsa_mapping_get(ps, section))) {
         pa_log("[%s:%u] %s invalid in section %s", filename, line, lvalue, section);
         return -1;
     }
@@ -3345,7 +3357,7 @@ static int mapping_parse_channel_map(
 
     pa_assert(ps);
 
-    if (!(m = mapping_get(ps, section))) {
+    if (!(m = pa_alsa_mapping_get(ps, section))) {
         pa_log("[%s:%u] %s invalid in section %s", filename, line, lvalue, section);
         return -1;
     }
@@ -3372,7 +3384,7 @@ static int mapping_parse_paths(
 
     pa_assert(ps);
 
-    if (!(m = mapping_get(ps, section))) {
+    if (!(m = pa_alsa_mapping_get(ps, section))) {
         pa_log("[%s:%u] %s invalid in section %s", filename, line, lvalue, section);
         return -1;
     }
@@ -3402,7 +3414,7 @@ static int mapping_parse_element(
 
     pa_assert(ps);
 
-    if (!(m = mapping_get(ps, section))) {
+    if (!(m = pa_alsa_mapping_get(ps, section))) {
         pa_log("[%s:%u] %s invalid in section %s", filename, line, lvalue, section);
         return -1;
     }
@@ -3432,7 +3444,7 @@ static int mapping_parse_direction(
 
     pa_assert(ps);
 
-    if (!(m = mapping_get(ps, section))) {
+    if (!(m = pa_alsa_mapping_get(ps, section))) {
         pa_log("[%s:%u] Section name %s invalid.", filename, line, section);
         return -1;
     }
@@ -3466,7 +3478,7 @@ static int mapping_parse_description(
 
     pa_assert(ps);
 
-    if ((m = mapping_get(ps, section))) {
+    if ((m = pa_alsa_mapping_get(ps, section))) {
         pa_xfree(m->description);
         m->description = pa_xstrdup(rvalue);
     } else if ((p = profile_get(ps, section))) {
@@ -3501,7 +3513,7 @@ static int mapping_parse_priority(
         return -1;
     }
 
-    if ((m = mapping_get(ps, section)))
+    if ((m = pa_alsa_mapping_get(ps, section)))
         m->priority = prio;
     else if ((p = profile_get(ps, section)))
         p->priority = prio;
@@ -3744,7 +3756,7 @@ static void mapping_paths_probe(pa_alsa_mapping *m, pa_alsa_profile *profile,
     pa_alsa_path_set_dump(ps);
 }
 
-static int mapping_verify(pa_alsa_mapping *m, const pa_channel_map *bonus) {
+int pa_alsa_mapping_verify(pa_alsa_mapping *m, const pa_channel_map *bonus) {
 
     static const struct description_map well_known_descriptions[] = {
         { "analog-mono",            N_("Analog Mono") },
@@ -3882,7 +3894,7 @@ static void profile_set_add_auto(pa_alsa_profile_set *ps) {
         profile_set_add_auto_pair(ps, NULL, n);
 }
 
-static int profile_verify(pa_alsa_profile *p) {
+int pa_alsa_profile_verify(pa_alsa_profile *p) {
 
     static const struct description_map well_known_descriptions[] = {
         { "output:analog-mono+input:analog-mono",     N_("Analog Mono Duplex") },
@@ -4067,7 +4079,7 @@ void pa_alsa_decibel_fix_dump(pa_alsa_decibel_fix *db_fix) {
     pa_xfree(db_values);
 }
 
-pa_alsa_profile_set* pa_alsa_profile_set_new(const char *fname, const pa_channel_map *bonus) {
+pa_alsa_profile_set* pa_alsa_mixer_profile_set_new(const char *fname, const pa_channel_map *bonus) {
     pa_alsa_profile_set *ps;
     pa_alsa_profile *p;
     pa_alsa_mapping *m;
@@ -4126,14 +4138,14 @@ pa_alsa_profile_set* pa_alsa_profile_set_new(const char *fname, const pa_channel
         goto fail;
 
     PA_HASHMAP_FOREACH(m, ps->mappings, state)
-        if (mapping_verify(m, bonus) < 0)
+        if (pa_alsa_mapping_verify(m, bonus) < 0)
             goto fail;
 
     if (ps->auto_profiles)
         profile_set_add_auto(ps);
 
     PA_HASHMAP_FOREACH(p, ps->profiles, state)
-        if (profile_verify(p) < 0)
+        if (pa_alsa_profile_verify(p) < 0)
             goto fail;
 
     PA_HASHMAP_FOREACH(db_fix, ps->decibel_fixes, state)
diff --git a/src/modules/alsa/alsa-mixer.h b/src/modules/alsa/alsa-mixer.h
index 74d12d6..55d3e0c 100644
--- a/src/modules/alsa/alsa-mixer.h
+++ b/src/modules/alsa/alsa-mixer.h
@@ -169,6 +169,7 @@ struct pa_alsa_path {
     pa_bool_t has_mute:1;
     pa_bool_t has_volume:1;
     pa_bool_t has_dB:1;
+    pa_bool_t use_ucm:1;
     /* These two are used during probing only */
     pa_bool_t has_req_any:1;
     pa_bool_t req_any_present:1;
@@ -184,6 +185,11 @@ struct pa_alsa_path {
 
     PA_LLIST_HEAD(pa_alsa_element, elements);
     PA_LLIST_HEAD(pa_alsa_setting, settings);
+
+    /* UCM stuff used only if use_ucm were TRUE */
+    char *ucm_verb;
+    char *ucm_device;
+    char **ucm_modifiers;
 };
 
 /* A path set is simply a set of paths that are applicable to a
@@ -209,7 +215,7 @@ int pa_alsa_path_get_volume(pa_alsa_path *p, snd_mixer_t *m, const pa_channel_ma
 int pa_alsa_path_get_mute(pa_alsa_path *path, snd_mixer_t *m, pa_bool_t *muted);
 int pa_alsa_path_set_volume(pa_alsa_path *path, snd_mixer_t *m, const pa_channel_map *cm, pa_cvolume *v, pa_bool_t deferred_volume, pa_bool_t write_to_hw);
 int pa_alsa_path_set_mute(pa_alsa_path *path, snd_mixer_t *m, pa_bool_t muted);
-int pa_alsa_path_select(pa_alsa_path *p, snd_mixer_t *m);
+int pa_alsa_mixer_path_select(pa_alsa_path *p, snd_mixer_t *m);
 void pa_alsa_path_set_callback(pa_alsa_path *p, snd_mixer_t *m, snd_mixer_elem_callback_t cb, void *userdata);
 void pa_alsa_path_free(pa_alsa_path *p);
 
@@ -262,6 +268,9 @@ struct pa_alsa_profile {
 
     pa_idxset *input_mappings;
     pa_idxset *output_mappings;
+
+    char  *ucm_verb;
+    char **ucm_modifiers;
 };
 
 struct pa_alsa_decibel_fix {
@@ -290,16 +299,22 @@ struct pa_alsa_profile_set {
     pa_bool_t auto_profiles;
     pa_bool_t ignore_dB:1;
     pa_bool_t probed:1;
+    pa_bool_t use_ucm;
 };
 
 void pa_alsa_mapping_dump(pa_alsa_mapping *m);
 void pa_alsa_profile_dump(pa_alsa_profile *p);
 void pa_alsa_decibel_fix_dump(pa_alsa_decibel_fix *db_fix);
 
-pa_alsa_profile_set* pa_alsa_profile_set_new(const char *fname, const pa_channel_map *bonus);
+pa_alsa_profile_set* pa_alsa_mixer_profile_set_new(const char *fname, const pa_channel_map *bonus);
 void pa_alsa_profile_set_probe(pa_alsa_profile_set *ps, const char *dev_id, const pa_sample_spec *ss, unsigned default_n_fragments, unsigned default_fragment_size_msec);
 void pa_alsa_profile_set_free(pa_alsa_profile_set *s);
 void pa_alsa_profile_set_dump(pa_alsa_profile_set *s);
+int pa_alsa_profile_verify(pa_alsa_profile *p);
+
+pa_alsa_mapping *pa_alsa_mapping_get(pa_alsa_profile_set *ps, const char *name);
+int pa_alsa_mapping_verify(pa_alsa_mapping *m, const pa_channel_map *bonus);
+
 
 snd_mixer_t *pa_alsa_open_mixer_for_pcm(snd_pcm_t *pcm, char **ctl_device);
 
diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index 647b0cd..fc2455d 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -58,6 +58,7 @@
 
 #include "alsa-util.h"
 #include "alsa-sink.h"
+#include "alsa-ucm.h"
 
 /* #define DEBUG_TIMING */
 
@@ -1445,15 +1446,24 @@ static void mixer_volume_init(struct userdata *u) {
 static int sink_set_port_cb(pa_sink *s, pa_device_port *p) {
     struct userdata *u = s->userdata;
     pa_alsa_port_data *data;
+    struct pa_alsa_ucm_config *ucm;
+    pa_alsa_path *newpath, *oldpath;
+
 
     pa_assert(u);
     pa_assert(p);
     pa_assert(u->mixer_handle);
 
     data = PA_DEVICE_PORT_DATA(p);
+    ucm = pa_alsa_card_get_ucm_config(s->card);
+    oldpath = u->mixer_path;
+
+    pa_assert_se(u->mixer_path = newpath = data->path);
 
-    pa_assert_se(u->mixer_path = data->path);
-    pa_alsa_path_select(u->mixer_path, u->mixer_handle);
+    if (newpath->use_ucm)
+        pa_alsa_ucm_path_select(newpath, oldpath, ucm);
+    else
+        pa_alsa_mixer_path_select(newpath, u->mixer_handle);
 
     mixer_volume_init(u);
 
@@ -1872,8 +1882,13 @@ fail:
 
 static int setup_mixer(struct userdata *u, pa_bool_t ignore_dB) {
     pa_bool_t need_mixer_callback = FALSE;
+    struct pa_alsa_ucm_config *ucm;
+    pa_alsa_path *path;
 
     pa_assert(u);
+    pa_assert(u->sink);
+
+    ucm = pa_alsa_card_get_ucm_config(u->sink->card);
 
     if (!u->mixer_handle)
         return 0;
@@ -1885,9 +1900,12 @@ static int setup_mixer(struct userdata *u, pa_bool_t ignore_dB) {
          * one that has been chosen as active */
 
         data = PA_DEVICE_PORT_DATA(u->sink->active_port);
-        u->mixer_path = data->path;
+        path = u->mixer_path = data->path;
 
-        pa_alsa_path_select(data->path, u->mixer_handle);
+	if (path->use_ucm)
+	    pa_alsa_ucm_path_select(path, NULL, ucm);
+	else
+	    pa_alsa_mixer_path_select(path, u->mixer_handle);
 
         if (data->setting)
             pa_alsa_setting_select(data->setting, u->mixer_handle);
@@ -1897,13 +1915,16 @@ static int setup_mixer(struct userdata *u, pa_bool_t ignore_dB) {
         if (!u->mixer_path && u->mixer_path_set)
             u->mixer_path = pa_hashmap_first(u->mixer_path_set->paths);
 
-        if (u->mixer_path) {
+        if ((path = u->mixer_path)) {
             /* Hmm, we have only a single path, then let's activate it */
 
-            pa_alsa_path_select(u->mixer_path, u->mixer_handle);
+            if (path->use_ucm)
+                pa_alsa_ucm_path_select(path, NULL, ucm);
+            else
+                pa_alsa_mixer_path_select(path, u->mixer_handle);
 
-            if (u->mixer_path->settings)
-                pa_alsa_setting_select(u->mixer_path->settings, u->mixer_handle);
+            if (path->settings)
+                pa_alsa_setting_select(path->settings, u->mixer_handle);
         } else
             return 0;
     }
@@ -2088,7 +2109,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
 
     } else if ((dev_id = pa_modargs_get_value(ma, "device_id", NULL))) {
 
-        if (!(profile_set = pa_alsa_profile_set_new(NULL, &map)))
+        if (!(profile_set = pa_alsa_mixer_profile_set_new(NULL, &map)))
             goto fail;
 
         if (!(u->pcm_handle = pa_alsa_open_by_device_id_auto(
@@ -2328,7 +2349,13 @@ fail:
 }
 
 static void userdata_free(struct userdata *u) {
+    struct pa_alsa_ucm_config *ucm;
+    struct pa_alsa_path *path;
+
     pa_assert(u);
+    pa_assert(u->sink);
+    ucm = pa_alsa_card_get_ucm_config(u->sink->card);
+    pa_assert(ucm);
 
     if (u->sink)
         pa_sink_unlink(u->sink);
@@ -2363,10 +2390,15 @@ static void userdata_free(struct userdata *u) {
     if (u->mixer_fdl)
         pa_alsa_fdlist_free(u->mixer_fdl);
 
-/*    if (u->mixer_path_set)
-        pa_alsa_path_set_free(u->mixer_path_set); Owned by the profile set */
-    if (u->mixer_path && !u->mixer_path_set)
-        pa_alsa_path_free(u->mixer_path);
+    if ((path = u->mixer_path)) {
+        if (path->use_ucm)
+            pa_alsa_ucm_path_select(NULL, path, ucm);
+
+        /*    if (u->mixer_path_set)
+	      pa_alsa_path_set_free(u->mixer_path_set); Owned by the profile set */
+        if (!u->mixer_path_set)
+            pa_alsa_path_free(path);
+    }
 
     if (u->mixer_handle)
         snd_mixer_close(u->mixer_handle);
diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
index cff8ce1..4a0a64f 100644
--- a/src/modules/alsa/alsa-source.c
+++ b/src/modules/alsa/alsa-source.c
@@ -53,6 +53,7 @@
 
 #include "alsa-util.h"
 #include "alsa-source.h"
+#include "alsa-ucm.h"
 
 /* #define DEBUG_TIMING */
 
@@ -1348,15 +1349,23 @@ static void mixer_volume_init(struct userdata *u) {
 static int source_set_port_cb(pa_source *s, pa_device_port *p) {
     struct userdata *u = s->userdata;
     pa_alsa_port_data *data;
+    struct pa_alsa_ucm_config *ucm;
+    pa_alsa_path *newpath, *oldpath;
 
     pa_assert(u);
     pa_assert(p);
     pa_assert(u->mixer_handle);
 
     data = PA_DEVICE_PORT_DATA(p);
+    ucm = pa_alsa_card_get_ucm_config(s->card);
+    oldpath = u->mixer_path;
 
-    pa_assert_se(u->mixer_path = data->path);
-    pa_alsa_path_select(u->mixer_path, u->mixer_handle);
+    pa_assert_se(u->mixer_path = newpath = data->path);
+
+    if (newpath->use_ucm)
+        pa_alsa_ucm_path_select(newpath, oldpath, ucm);
+    else
+        pa_alsa_mixer_path_select(newpath, u->mixer_handle);
 
     mixer_volume_init(u);
 
@@ -1613,8 +1622,13 @@ fail:
 
 static int setup_mixer(struct userdata *u, pa_bool_t ignore_dB) {
     pa_bool_t need_mixer_callback = FALSE;
+    struct pa_alsa_ucm_config *ucm;
+    pa_alsa_path *path;
 
     pa_assert(u);
+    pa_assert(u->source);
+
+    ucm = pa_alsa_card_get_ucm_config(u->source->card);
 
     if (!u->mixer_handle)
         return 0;
@@ -1626,9 +1640,12 @@ static int setup_mixer(struct userdata *u, pa_bool_t ignore_dB) {
          * one that has been chosen as active */
 
         data = PA_DEVICE_PORT_DATA(u->source->active_port);
-        u->mixer_path = data->path;
+        path = u->mixer_path = data->path;
 
-        pa_alsa_path_select(data->path, u->mixer_handle);
+        if (path->use_ucm)
+            pa_alsa_ucm_path_select(path, NULL, ucm);
+        else
+            pa_alsa_mixer_path_select(path, u->mixer_handle);
 
         if (data->setting)
             pa_alsa_setting_select(data->setting, u->mixer_handle);
@@ -1638,13 +1655,16 @@ static int setup_mixer(struct userdata *u, pa_bool_t ignore_dB) {
         if (!u->mixer_path && u->mixer_path_set)
             u->mixer_path = pa_hashmap_first(u->mixer_path_set->paths);
 
-        if (u->mixer_path) {
+        if ((path = u->mixer_path)) {
             /* Hmm, we have only a single path, then let's activate it */
 
-            pa_alsa_path_select(u->mixer_path, u->mixer_handle);
+            if (path->use_ucm)
+                pa_alsa_ucm_path_select(path, NULL, ucm);
+            else
+                pa_alsa_mixer_path_select(path, u->mixer_handle);
 
-            if (u->mixer_path->settings)
-                pa_alsa_setting_select(u->mixer_path->settings, u->mixer_handle);
+            if (path->settings)
+                pa_alsa_setting_select(path->settings, u->mixer_handle);
         } else
             return 0;
     }
@@ -1822,7 +1842,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
 
     } else if ((dev_id = pa_modargs_get_value(ma, "device_id", NULL))) {
 
-        if (!(profile_set = pa_alsa_profile_set_new(NULL, &map)))
+        if (!(profile_set = pa_alsa_mixer_profile_set_new(NULL, &map)))
             goto fail;
 
         if (!(u->pcm_handle = pa_alsa_open_by_device_id_auto(
@@ -2036,7 +2056,13 @@ fail:
 }
 
 static void userdata_free(struct userdata *u) {
+    struct pa_alsa_ucm_config *ucm;
+    struct pa_alsa_path *path;
+
     pa_assert(u);
+    pa_assert(u->source);
+    ucm = pa_alsa_card_get_ucm_config(u->source->card);
+    pa_assert(ucm);
 
     if (u->source)
         pa_source_unlink(u->source);
@@ -2068,8 +2094,13 @@ static void userdata_free(struct userdata *u) {
     if (u->mixer_fdl)
         pa_alsa_fdlist_free(u->mixer_fdl);
 
-    if (u->mixer_path && !u->mixer_path_set)
-        pa_alsa_path_free(u->mixer_path);
+    if ((path = u->mixer_path)) {
+        if (path->use_ucm)
+            pa_alsa_ucm_path_select(NULL, path, ucm);
+
+        if (!u->mixer_path_set)
+            pa_alsa_path_free(path);
+    }
 
     if (u->mixer_handle)
         snd_mixer_close(u->mixer_handle);
diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c
index 6bcf48b..1bed403 100644
--- a/src/modules/alsa/module-alsa-card.c
+++ b/src/modules/alsa/module-alsa-card.c
@@ -39,6 +39,7 @@
 #include "alsa-util.h"
 #include "alsa-sink.h"
 #include "alsa-source.h"
+#include "alsa-ucm.h"
 #include "module-alsa-card-symdef.h"
 
 PA_MODULE_AUTHOR("Lennart Poettering");
@@ -109,12 +110,23 @@ struct userdata {
     pa_modargs *modargs;
 
     pa_alsa_profile_set *profile_set;
-};
 
-struct profile_data {
-    pa_alsa_profile *profile;
+    pa_alsa_ucm_config ucm;
 };
 
+
+pa_alsa_ucm_config *pa_alsa_card_get_ucm_config(pa_card *card)
+{
+    struct userdata *u;
+    pa_alsa_ucm_config *ucm = NULL;
+
+
+    if (card && (u = card->userdata))
+        ucm = &u->ucm;
+
+    return ucm;
+}
+
 static void add_profiles(struct userdata *u, pa_hashmap *h, pa_hashmap *ports) {
     pa_alsa_profile *ap;
     void *state;
@@ -184,59 +196,69 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) {
     nd = PA_CARD_PROFILE_DATA(new_profile);
     od = PA_CARD_PROFILE_DATA(c->active_profile);
 
-    if (od->profile && od->profile->output_mappings)
-        PA_IDXSET_FOREACH(am, od->profile->output_mappings, idx) {
-            if (!am->sink)
-                continue;
-
-            if (nd->profile &&
-                nd->profile->output_mappings &&
-                pa_idxset_get_by_data(nd->profile->output_mappings, am, NULL))
-                continue;
-
-            sink_inputs = pa_sink_move_all_start(am->sink, sink_inputs);
-            pa_alsa_sink_free(am->sink);
-            am->sink = NULL;
-        }
-
-    if (od->profile && od->profile->input_mappings)
-        PA_IDXSET_FOREACH(am, od->profile->input_mappings, idx) {
-            if (!am->source)
-                continue;
-
-            if (nd->profile &&
-                nd->profile->input_mappings &&
-                pa_idxset_get_by_data(nd->profile->input_mappings, am, NULL))
-                continue;
+    pa_assert(nd);
+    pa_assert(od);
+
+    if (od->profile) {
+        if (od->profile->output_mappings)
+            PA_IDXSET_FOREACH(am, od->profile->output_mappings, idx) {
+                if (!am->sink)
+                    continue;
+
+                if (nd->profile &&
+                    nd->profile->output_mappings &&
+                    pa_idxset_get_by_data(nd->profile->output_mappings, am, NULL))
+                    continue;
+
+                sink_inputs = pa_sink_move_all_start(am->sink, sink_inputs);
+                pa_alsa_sink_free(am->sink);
+                am->sink = NULL;
+            }
+
+        if (od->profile->input_mappings)
+            PA_IDXSET_FOREACH(am, od->profile->input_mappings, idx) {
+                if (!am->source)
+                    continue;
+
+                if (nd->profile &&
+                    nd->profile->input_mappings &&
+                    pa_idxset_get_by_data(nd->profile->input_mappings, am, NULL))
+                    continue;
+
+                source_outputs = pa_source_move_all_start(am->source, source_outputs);
+                pa_alsa_source_free(am->source);
+                am->source = NULL;
+            }
+    }
 
-            source_outputs = pa_source_move_all_start(am->source, source_outputs);
-            pa_alsa_source_free(am->source);
-            am->source = NULL;
-        }
+    if (u->ucm.enabled)
+        pa_alsa_ucm_profile_select(nd->profile, od->profile, &u->ucm);
 
-    if (nd->profile && nd->profile->output_mappings)
-        PA_IDXSET_FOREACH(am, nd->profile->output_mappings, idx) {
+    if (nd->profile) {
+        if (nd->profile->output_mappings)
+            PA_IDXSET_FOREACH(am, nd->profile->output_mappings, idx) {
 
-            if (!am->sink)
-                am->sink = pa_alsa_sink_new(c->module, u->modargs, __FILE__, c, am);
+                if (!am->sink)
+                    am->sink = pa_alsa_sink_new(c->module, u->modargs, __FILE__, c, am);
 
-            if (sink_inputs && am->sink) {
-                pa_sink_move_all_finish(am->sink, sink_inputs, FALSE);
-                sink_inputs = NULL;
-            }
-        }
+                if (sink_inputs && am->sink) {
+                    pa_sink_move_all_finish(am->sink, sink_inputs, FALSE);
+                    sink_inputs = NULL;
+                }
+            }
 
-    if (nd->profile && nd->profile->input_mappings)
-        PA_IDXSET_FOREACH(am, nd->profile->input_mappings, idx) {
+        if (nd->profile && nd->profile->input_mappings)
+            PA_IDXSET_FOREACH(am, nd->profile->input_mappings, idx) {
 
-            if (!am->source)
-                am->source = pa_alsa_source_new(c->module, u->modargs, __FILE__, c, am);
+                if (!am->source)
+                    am->source = pa_alsa_source_new(c->module, u->modargs, __FILE__, c, am);
 
-            if (source_outputs && am->source) {
-                pa_source_move_all_finish(am->source, source_outputs, FALSE);
-                source_outputs = NULL;
-            }
-        }
+                if (source_outputs && am->source) {
+                    pa_source_move_all_finish(am->source, source_outputs, FALSE);
+                    source_outputs = NULL;
+                }
+            }
+    }
 
     if (sink_inputs)
         pa_sink_move_all_fail(sink_inputs);
@@ -302,6 +324,7 @@ int pa__init(pa_module *m) {
     const char *profile = NULL;
     char *fn = NULL;
     pa_bool_t namereg_fail = FALSE;
+    pa_channel_map *def_chmap;
 
     pa_alsa_refcnt_inc();
 
@@ -340,18 +363,23 @@ int pa__init(pa_module *m) {
         }
     }
 
+    def_chmap = &u->core->default_channel_map;
+
+    if (!(u->profile_set = pa_alsa_ucm_profile_set_new(alsa_card_index, &u->ucm, def_chmap))) {
+
 #ifdef HAVE_UDEV
-    fn = pa_udev_get_property(alsa_card_index, "PULSE_PROFILE_SET");
+        fn = pa_udev_get_property(alsa_card_index, "PULSE_PROFILE_SET");
 #endif
 
-    if (pa_modargs_get_value(ma, "profile_set", NULL)) {
+        if (pa_modargs_get_value(ma, "profile_set", NULL)) {
+            pa_xfree(fn);
+            fn = pa_xstrdup(pa_modargs_get_value(ma, "profile_set", NULL));
+        }
+
+        u->profile_set = pa_alsa_mixer_profile_set_new(fn, &u->core->default_channel_map);
         pa_xfree(fn);
-        fn = pa_xstrdup(pa_modargs_get_value(ma, "profile_set", NULL));
     }
 
-    u->profile_set = pa_alsa_profile_set_new(fn, &u->core->default_channel_map);
-    pa_xfree(fn);
-
     u->profile_set->ignore_dB = ignore_dB;
 
     if (!u->profile_set)
-- 
1.7.5.2



More information about the pulseaudio-discuss mailing list