[pulseaudio-discuss] [PATCH 11/17] alsa: Create UCM ports in pa_alsa_profile_set_create_ports()

Tanu Kaskinen tanu.kaskinen at linux.intel.com
Mon Dec 30 05:04:46 PST 2013


Now also UCM ports are created before any device prototypes or card
profiles are created.

There is some code duplication: alsa-ucm.c already had functions
ucm_add_ports_combination() and ucm_add_port_combination(), and now
this patch adds add_port_combination() that is very similar to
ucm_add_port_combination(), and pa_alsa_profile_set_create_ports()
is similar to ucm_add_ports_combination() (the recursion was replaced
with a loop, though, so it looks different, but it still does
essentially the same thing). The old ucm_* functions will be removed
later, so the duplication isn't permanenet. Port creation is now done
in the new functions, but the old ucm_* variants are still kept,
because they link profiles to ports and ports to sinks/sources, which
the new functions don't do (those things will be done later by the
core).
---
 src/modules/alsa/alsa-mixer.c |  18 ++--
 src/modules/alsa/alsa-mixer.h |   1 +
 src/modules/alsa/alsa-ucm.c   | 190 +++++++++++++++++++++++++++++-------------
 src/modules/alsa/alsa-ucm.h   |   2 +
 4 files changed, 146 insertions(+), 65 deletions(-)

diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
index bd243ba..14bfd88 100644
--- a/src/modules/alsa/alsa-mixer.c
+++ b/src/modules/alsa/alsa-mixer.c
@@ -4639,16 +4639,24 @@ static void path_create_ports(pa_core *core, pa_alsa_path *path, pa_hashmap *por
 }
 
 void pa_alsa_profile_set_create_ports(pa_core *core, pa_alsa_profile_set *profile_set, pa_hashmap *ports) {
-    pa_alsa_path *path;
     void *state;
 
     pa_assert(core);
     pa_assert(profile_set);
     pa_assert(ports);
 
-    PA_HASHMAP_FOREACH(path, profile_set->output_paths, state)
-        path_create_ports(core, path, ports);
+    if (profile_set->use_ucm) {
+        pa_alsa_mapping *mapping;
+
+        PA_HASHMAP_FOREACH(mapping, profile_set->mappings, state)
+            pa_alsa_ucm_mapping_create_ports(core, mapping, ports);
+    } else {
+        pa_alsa_path *path;
 
-    PA_HASHMAP_FOREACH(path, profile_set->input_paths, state)
-        path_create_ports(core, path, ports);
+        PA_HASHMAP_FOREACH(path, profile_set->output_paths, state)
+            path_create_ports(core, path, ports);
+
+        PA_HASHMAP_FOREACH(path, profile_set->input_paths, state)
+            path_create_ports(core, path, ports);
+    }
 }
diff --git a/src/modules/alsa/alsa-mixer.h b/src/modules/alsa/alsa-mixer.h
index a39befe..6869261 100644
--- a/src/modules/alsa/alsa-mixer.h
+++ b/src/modules/alsa/alsa-mixer.h
@@ -318,6 +318,7 @@ struct pa_alsa_profile_set {
     pa_hashmap *input_paths;
     pa_hashmap *output_paths;
 
+    bool use_ucm;
     bool auto_profiles;
     bool ignore_dB:1;
     bool probed:1;
diff --git a/src/modules/alsa/alsa-ucm.c b/src/modules/alsa/alsa-ucm.c
index 302c8fc..2924506 100644
--- a/src/modules/alsa/alsa-ucm.c
+++ b/src/modules/alsa/alsa-ucm.c
@@ -676,23 +676,14 @@ static void ucm_add_port_combination(
 
     pa_device_port *port;
     int i;
-    unsigned priority;
-    double prio2;
     char *name = NULL;
-    char *desc = NULL;
     const char *dev_name;
-    const char *direction;
     pa_alsa_ucm_device *dev;
 
     dev = pdevices[0];
     dev_name = pa_proplist_gets(dev->proplist, PA_ALSA_PROP_UCM_NAME);
 
     name = pa_sprintf_malloc("%s%s", is_sink ? PA_UCM_PRE_TAG_OUTPUT : PA_UCM_PRE_TAG_INPUT, dev_name);
-    desc = num == 1 ? pa_xstrdup(pa_proplist_gets(dev->proplist, PA_ALSA_PROP_UCM_DESCRIPTION))
-            : pa_sprintf_malloc("Combination port for %s", dev_name);
-
-    priority = is_sink ? dev->playback_priority : dev->capture_priority;
-    prio2 = (priority == 0 ? 0 : 1.0/priority);
 
     for (i = 1; i < num; i++) {
         char *tmp;
@@ -703,57 +694,11 @@ static void ucm_add_port_combination(
         tmp = pa_sprintf_malloc("%s+%s", name, dev_name);
         pa_xfree(name);
         name = tmp;
-
-        tmp = pa_sprintf_malloc("%s,%s", desc, dev_name);
-        pa_xfree(desc);
-        desc = tmp;
-
-        priority = is_sink ? dev->playback_priority : dev->capture_priority;
-        if (priority != 0 && prio2 > 0)
-            prio2 += 1.0/priority;
     }
 
-    /* Make combination ports always have lower priority, and use the formula
-       1/p = 1/p1 + 1/p2 + ... 1/pn.
-       This way, the result will always be less than the individual components,
-       yet higher components will lead to higher result. */
-
-    if (num > 1)
-        priority = prio2 > 0 ? 1.0/prio2 : 0;
-
     port = pa_hashmap_get(ports, name);
-    if (!port) {
-        pa_device_port_new_data port_data;
-
-        pa_device_port_new_data_init(&port_data);
-        pa_device_port_new_data_set_name(&port_data, name);
-        pa_device_port_new_data_set_description(&port_data, desc);
-        pa_device_port_new_data_set_direction(&port_data, is_sink ? PA_DIRECTION_OUTPUT : PA_DIRECTION_INPUT);
-        pa_node_new_data_set_fallback_name_prefix(&port_data.node_data, "alsa");
-
-        port = pa_device_port_new(core, &port_data, 0);
-        pa_device_port_new_data_done(&port_data);
-
-        if (!port) {
-            pa_log("Failed to create port %s.", name);
-            goto fail;
-        }
-
-        pa_hashmap_put(ports, port->name, port);
-        pa_dynarray_append(context->ports, port);
-        pa_log_debug("Add port %s: %s", port->name, port->description);
-        port->profiles = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
-    }
-
-    port->priority = priority;
-
+    pa_assert(port);
     pa_xfree(name);
-    name = NULL;
-    pa_xfree(desc);
-    desc = NULL;
-
-    direction = is_sink ? "output" : "input";
-    pa_log_debug("Port %s direction %s, priority %d", port->name, direction, priority);
 
     if (cp) {
         pa_log_debug("Adding profile %s to port %s.", cp->name, port->name);
@@ -766,10 +711,6 @@ static void ucm_add_port_combination(
     }
 
     return;
-
-fail:
-    pa_xfree(name);
-    pa_xfree(desc);
 }
 
 static int ucm_port_contains(const char *port_name, const char *dev_name, bool is_sink) {
@@ -1522,6 +1463,7 @@ pa_alsa_profile_set* pa_alsa_ucm_add_profile_set(pa_alsa_ucm_config *ucm, pa_cha
     pa_alsa_profile_set *ps;
 
     ps = pa_xnew0(pa_alsa_profile_set, 1);
+    ps->use_ucm = true;
     ps->mappings = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
     ps->profiles = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
     ps->decibel_fixes = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
@@ -1678,6 +1620,131 @@ void pa_alsa_ucm_roled_stream_end(pa_alsa_ucm_config *ucm, const char *role, pa_
     }
 }
 
+static void add_port_combination(
+        pa_alsa_ucm_mapping_context *context,
+        bool is_sink,
+        pa_alsa_ucm_device **pdevices,
+        int num,
+        pa_hashmap *ports,
+        pa_core *core) {
+
+    pa_device_port *port;
+    int i;
+    unsigned priority;
+    double prio2;
+    char *name = NULL;
+    char *desc = NULL;
+    const char *dev_name;
+    const char *direction;
+    pa_alsa_ucm_device *dev;
+
+    dev = pdevices[0];
+    dev_name = pa_proplist_gets(dev->proplist, PA_ALSA_PROP_UCM_NAME);
+
+    name = pa_sprintf_malloc("%s%s", is_sink ? PA_UCM_PRE_TAG_OUTPUT : PA_UCM_PRE_TAG_INPUT, dev_name);
+    desc = num == 1 ? pa_xstrdup(pa_proplist_gets(dev->proplist, PA_ALSA_PROP_UCM_DESCRIPTION))
+            : pa_sprintf_malloc("Combination port for %s", dev_name);
+
+    priority = is_sink ? dev->playback_priority : dev->capture_priority;
+    prio2 = (priority == 0 ? 0 : 1.0/priority);
+
+    for (i = 1; i < num; i++) {
+        char *tmp;
+
+        dev = pdevices[i];
+        dev_name = pa_proplist_gets(dev->proplist, PA_ALSA_PROP_UCM_NAME);
+
+        tmp = pa_sprintf_malloc("%s+%s", name, dev_name);
+        pa_xfree(name);
+        name = tmp;
+
+        tmp = pa_sprintf_malloc("%s,%s", desc, dev_name);
+        pa_xfree(desc);
+        desc = tmp;
+
+        priority = is_sink ? dev->playback_priority : dev->capture_priority;
+        if (priority != 0 && prio2 > 0)
+            prio2 += 1.0/priority;
+    }
+
+    /* Make combination ports always have lower priority, and use the formula
+       1/p = 1/p1 + 1/p2 + ... 1/pn.
+       This way, the result will always be less than the individual components,
+       yet higher components will lead to higher result. */
+
+    if (num > 1)
+        priority = prio2 > 0 ? 1.0/prio2 : 0;
+
+    port = pa_hashmap_get(ports, name);
+    if (!port) {
+        pa_device_port_new_data port_data;
+
+        pa_device_port_new_data_init(&port_data);
+        pa_device_port_new_data_set_name(&port_data, name);
+        pa_device_port_new_data_set_description(&port_data, desc);
+        pa_device_port_new_data_set_direction(&port_data, is_sink ? PA_DIRECTION_OUTPUT : PA_DIRECTION_INPUT);
+        pa_node_new_data_set_fallback_name_prefix(&port_data.node_data, "alsa");
+
+        port = pa_device_port_new(core, &port_data, 0);
+        pa_device_port_new_data_done(&port_data);
+
+        if (!port) {
+            pa_log("Failed to create port %s.", name);
+            goto fail;
+        }
+
+        pa_hashmap_put(ports, port->name, port);
+        pa_dynarray_append(context->ports, port);
+        pa_log_debug("Add port %s: %s", port->name, port->description);
+    }
+
+    port->priority = priority;
+
+    pa_xfree(name);
+    name = NULL;
+    pa_xfree(desc);
+    desc = NULL;
+
+    direction = is_sink ? "output" : "input";
+    pa_log_debug("Port %s direction %s, priority %d", port->name, direction, priority);
+
+    return;
+
+fail:
+    pa_xfree(name);
+    pa_xfree(desc);
+}
+
+void pa_alsa_ucm_mapping_create_ports(pa_core *core, pa_alsa_mapping *mapping, pa_hashmap *ports) {
+    pa_alsa_ucm_mapping_context *context;
+    bool is_sink;
+    pa_alsa_ucm_device **combination_devices;
+    pa_alsa_ucm_device *device;
+    uint32_t idx;
+    unsigned dev_num = 0;
+
+    pa_assert(core);
+    pa_assert(mapping);
+    pa_assert(ports);
+
+    context = &mapping->ucm_context;
+    is_sink = context->direction == PA_DIRECTION_OUTPUT;
+
+    if (pa_idxset_isempty(context->ucm_devices))
+        return;
+
+    combination_devices = pa_xnew0(pa_alsa_ucm_device *, pa_idxset_size(context->ucm_devices));
+
+    PA_IDXSET_FOREACH(device, context->ucm_devices, idx) {
+        if (ucm_check_conformance(combination_devices, dev_num, device)) {
+            combination_devices[dev_num++] = device;
+            add_port_combination(context, is_sink, combination_devices, dev_num, ports, core);
+        }
+    }
+
+    pa_xfree(combination_devices);
+}
+
 #else /* HAVE_ALSA_UCM */
 
 /* Dummy functions for systems without UCM support */
@@ -1732,4 +1799,7 @@ void pa_alsa_ucm_roled_stream_begin(pa_alsa_ucm_config *ucm, const char *role, p
 void pa_alsa_ucm_roled_stream_end(pa_alsa_ucm_config *ucm, const char *role, pa_direction_t dir) {
 }
 
+void pa_alsa_ucm_mapping_create_ports(pa_core *core, pa_alsa_mapping *mapping, pa_hashmap *ports) {
+}
+
 #endif
diff --git a/src/modules/alsa/alsa-ucm.h b/src/modules/alsa/alsa-ucm.h
index 66b27a0..605b1a3 100644
--- a/src/modules/alsa/alsa-ucm.h
+++ b/src/modules/alsa/alsa-ucm.h
@@ -195,4 +195,6 @@ struct pa_alsa_ucm_mapping_context {
     pa_dynarray *ports;
 };
 
+void pa_alsa_ucm_mapping_create_ports(pa_core *core, pa_alsa_mapping *mapping, pa_hashmap *ports);
+
 #endif
-- 
1.8.3.1



More information about the pulseaudio-discuss mailing list