[pulseaudio-discuss] [PATCH 13/17] Create device prototypes before profiles

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


This simplifies profile creation, and the ownership of device
prototypes is clearer.
---
 src/modules/alsa/alsa-mixer.c                   | 18 +++++++++++++++
 src/modules/alsa/alsa-mixer.h                   |  1 +
 src/modules/alsa/module-alsa-card.c             | 29 ++++++++++++++++++++-----
 src/modules/bluetooth/module-bluetooth-device.c | 18 +++++++--------
 src/pulsecore/card.c                            | 25 ++++++---------------
 src/pulsecore/card.h                            | 13 ++++++-----
 6 files changed, 64 insertions(+), 40 deletions(-)

diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
index 14bfd88..1e08ec3 100644
--- a/src/modules/alsa/alsa-mixer.c
+++ b/src/modules/alsa/alsa-mixer.c
@@ -3382,6 +3382,24 @@ pa_alsa_mapping *pa_alsa_mapping_get(pa_alsa_profile_set *ps, const char *name)
     return m;
 }
 
+pa_device_prototype *pa_alsa_mapping_create_device_prototype(pa_alsa_mapping *mapping, pa_direction_t direction) {
+    pa_device_prototype *prototype;
+
+    pa_assert(mapping);
+
+    prototype = pa_device_prototype_new(direction);
+
+    if (direction == PA_DIRECTION_OUTPUT) {
+        pa_assert(!mapping->sink_prototype);
+        mapping->sink_prototype = prototype;
+    } else {
+        pa_assert(!mapping->source_prototype);
+        mapping->source_prototype = prototype;
+    }
+
+    return prototype;
+}
+
 static pa_alsa_profile *profile_get(pa_alsa_profile_set *ps, const char *name) {
     pa_alsa_profile *p;
 
diff --git a/src/modules/alsa/alsa-mixer.h b/src/modules/alsa/alsa-mixer.h
index 6869261..0a2a4e5 100644
--- a/src/modules/alsa/alsa-mixer.h
+++ b/src/modules/alsa/alsa-mixer.h
@@ -328,6 +328,7 @@ 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_mapping *pa_alsa_mapping_get(pa_alsa_profile_set *ps, const char *name);
+pa_device_prototype *pa_alsa_mapping_create_device_prototype(pa_alsa_mapping *mapping, pa_direction_t direction);
 
 pa_alsa_profile_set* pa_alsa_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);
diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c
index 4b09c95..c427386 100644
--- a/src/modules/alsa/module-alsa-card.c
+++ b/src/modules/alsa/module-alsa-card.c
@@ -137,6 +137,28 @@ struct profile_data {
     pa_alsa_profile *profile;
 };
 
+static void add_device_prototypes(struct userdata *u, pa_card_new_data *data) {
+    pa_alsa_mapping *mapping;
+    void *state;
+
+    pa_assert(u);
+    pa_assert(data);
+
+    PA_HASHMAP_FOREACH(mapping, u->profile_set->mappings, state) {
+        pa_device_prototype *prototype;
+
+        if (mapping->direction == PA_ALSA_DIRECTION_ANY || mapping->direction == PA_ALSA_DIRECTION_OUTPUT) {
+            prototype = pa_alsa_mapping_create_device_prototype(mapping, PA_DIRECTION_OUTPUT);
+            pa_card_new_data_add_device_prototype(data, prototype);
+        }
+
+        if (mapping->direction == PA_ALSA_DIRECTION_ANY || mapping->direction == PA_ALSA_DIRECTION_INPUT) {
+            prototype = pa_alsa_mapping_create_device_prototype(mapping, PA_DIRECTION_INPUT);
+            pa_card_new_data_add_device_prototype(data, prototype);
+        }
+    }
+}
+
 static void add_profiles(struct userdata *u, pa_card_new_data *data) {
     pa_alsa_profile *ap;
     void *state;
@@ -155,9 +177,6 @@ static void add_profiles(struct userdata *u, pa_card_new_data *data) {
 
         if (ap->output_mappings) {
             PA_IDXSET_FOREACH(m, ap->output_mappings, idx) {
-                if (!m->sink_prototype)
-                    m->sink_prototype = pa_device_prototype_new(PA_DIRECTION_OUTPUT);
-
                 pa_hashmap_put(cp->sink_prototypes, m->sink_prototype, m->sink_prototype);
 
                 if (u->use_ucm)
@@ -171,9 +190,6 @@ static void add_profiles(struct userdata *u, pa_card_new_data *data) {
 
         if (ap->input_mappings) {
             PA_IDXSET_FOREACH(m, ap->input_mappings, idx) {
-                if (!m->source_prototype)
-                    m->source_prototype = pa_device_prototype_new(PA_DIRECTION_INPUT);
-
                 pa_hashmap_put(cp->source_prototypes, m->source_prototype, m->source_prototype);
 
                 if (u->use_ucm)
@@ -712,6 +728,7 @@ int pa__init(pa_module *m) {
             pa_reserve_wrapper_set_application_device_name(reserve, description);
 
     pa_alsa_profile_set_create_ports(u->core, u->profile_set, data.ports);
+    add_device_prototypes(u, &data);
     add_profiles(u, &data);
 
     if (pa_hashmap_isempty(data.profiles)) {
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index 59acaf8..f44eb2f 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -2203,16 +2203,6 @@ static pa_card_profile *create_card_profile(struct userdata *u, const char *uuid
     else if (pa_streq(uuid, HFP_AG_UUID))
         profile = PROFILE_HFGW;
 
-    if (profile == PROFILE_A2DP || (!USE_SCO_OVER_PCM(u) && (profile == PROFILE_HSP || profile == PROFILE_HFGW))) {
-        if (!u->sink_prototype)
-            u->sink_prototype = pa_device_prototype_new(PA_DIRECTION_OUTPUT);
-    }
-
-    if (profile == PROFILE_A2DP_SOURCE || (!USE_SCO_OVER_PCM(u) && (profile == PROFILE_HSP || profile == PROFILE_HFGW))) {
-        if (!u->source_prototype)
-            u->source_prototype = pa_device_prototype_new(PA_DIRECTION_INPUT);
-    }
-
     if (profile == PROFILE_A2DP) {
         p = pa_card_profile_new("a2dp", _("High Fidelity Playback (A2DP)"), sizeof(enum profile));
         p->priority = 10;
@@ -2326,6 +2316,14 @@ static int add_card(struct userdata *u) {
         return -1;
     }
 
+    /* We create prototypes for both directions even if the device only
+     * supports one direction, because it makes the code simpler. Having an
+     * extra prototype does no harm. */
+    u->sink_prototype = pa_device_prototype_new(PA_DIRECTION_OUTPUT);
+    pa_card_new_data_add_device_prototype(&data, u->sink_prototype);
+    u->source_prototype = pa_device_prototype_new(PA_DIRECTION_INPUT);
+    pa_card_new_data_add_device_prototype(&data, u->source_prototype);
+
     PA_LLIST_FOREACH(uuid, device->uuids) {
         p = create_card_profile(u, uuid->uuid, data.ports);
 
diff --git a/src/pulsecore/card.c b/src/pulsecore/card.c
index 32e1652..7f57e02 100644
--- a/src/pulsecore/card.c
+++ b/src/pulsecore/card.c
@@ -131,20 +131,18 @@ void pa_card_new_data_set_name(pa_card_new_data *data, const char *name) {
     data->name = pa_xstrdup(name);
 }
 
-void pa_card_new_data_add_profile(pa_card_new_data *data, pa_card_profile *profile) {
-    pa_device_prototype *prototype;
-    void *state;
+void pa_card_new_data_add_device_prototype(pa_card_new_data *data, pa_device_prototype *prototype) {
+    pa_assert(data);
+    pa_assert(prototype);
+
+    pa_hashmap_put(data->device_prototypes, prototype, prototype);
+}
 
+void pa_card_new_data_add_profile(pa_card_new_data *data, pa_card_profile *profile) {
     pa_assert(data);
     pa_assert(profile);
 
     pa_assert_se(pa_hashmap_put(data->profiles, profile->name, profile) >= 0);
-
-    PA_HASHMAP_FOREACH(prototype, profile->sink_prototypes, state)
-        pa_hashmap_put(data->device_prototypes, prototype, prototype);
-
-    PA_HASHMAP_FOREACH(prototype, profile->source_prototypes, state)
-        pa_hashmap_put(data->device_prototypes, prototype, prototype);
 }
 
 void pa_card_new_data_set_profile(pa_card_new_data *data, const char *profile) {
@@ -299,9 +297,6 @@ void pa_card_free(pa_card *c) {
 }
 
 void pa_card_add_profile(pa_card *c, pa_card_profile *profile) {
-    pa_device_prototype *prototype;
-    void *state;
-
     pa_assert(c);
     pa_assert(profile);
 
@@ -309,12 +304,6 @@ void pa_card_add_profile(pa_card *c, pa_card_profile *profile) {
     pa_assert_se(pa_hashmap_put(c->profiles, profile->name, profile) >= 0);
     profile->card = c;
 
-    PA_HASHMAP_FOREACH(prototype, profile->sink_prototypes, state)
-        pa_hashmap_put(c->device_prototypes, prototype, prototype);
-
-    PA_HASHMAP_FOREACH(prototype, profile->source_prototypes, state)
-        pa_hashmap_put(c->device_prototypes, prototype, prototype);
-
     pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_CHANGE, c->index);
 
     pa_hook_fire(&c->core->hooks[PA_CORE_HOOK_CARD_PROFILE_ADDED], profile);
diff --git a/src/pulsecore/card.h b/src/pulsecore/card.h
index ce1cb22..850dfa1 100644
--- a/src/pulsecore/card.h
+++ b/src/pulsecore/card.h
@@ -64,10 +64,6 @@ typedef struct pa_card_profile {
     unsigned priority;
     pa_available_t available; /* PA_AVAILABLE_UNKNOWN, PA_AVAILABLE_NO or PA_AVAILABLE_YES */
 
-    /* When populating these hashmaps, note that you initially own the device
-     * prototype objects that you add, but once you call
-     * pa_card_new_data_add_profile(), the prototype ownership moves to
-     * pa_card_new_data (and later to pa_card). */
     pa_hashmap *sink_prototypes; /* pa_device_prototype -> pa_device_prototype (hashmap-as-a-set) */
     pa_hashmap *source_prototypes; /* pa_device_prototype -> pa_device_prototype (hashmap-as-a-set) */
 
@@ -119,8 +115,6 @@ typedef struct pa_card_new_data {
     const char *driver;
     pa_module *module;
 
-    /* Don't populate this manually. pa_card_new_data_add_profile() will
-     * automatically add the prototypes from the added profile. */
     pa_hashmap *device_prototypes; /* pa_device_prototype -> pa_device_prototype (hashmap-as-a-set) */
 
     pa_hashmap *profiles;
@@ -156,7 +150,13 @@ void pa_card_profile_set_available(pa_card_profile *c, pa_available_t available)
 
 pa_card_new_data *pa_card_new_data_init(pa_card_new_data *data);
 void pa_card_new_data_set_name(pa_card_new_data *data, const char *name);
+
+/* The ownership of the prototype moves to pa_card_new_data. */
+void pa_card_new_data_add_device_prototype(pa_card_new_data *data, pa_device_prototype *prototype);
+
+/* The ownership of the profile moves to pa_card_new_data. */
 void pa_card_new_data_add_profile(pa_card_new_data *data, pa_card_profile *profile);
+
 void pa_card_new_data_set_profile(pa_card_new_data *data, const char *profile);
 void pa_card_new_data_set_recreate_devices_on_profile_switch(pa_card_new_data *data, bool recreate);
 void pa_card_new_data_done(pa_card_new_data *data);
@@ -164,6 +164,7 @@ void pa_card_new_data_done(pa_card_new_data *data);
 pa_card *pa_card_new(pa_core *c, pa_card_new_data *data);
 void pa_card_free(pa_card *c);
 
+/* The ownership of the profile moves to pa_card. */
 void pa_card_add_profile(pa_card *c, pa_card_profile *profile);
 
 int pa_card_set_profile(pa_card *c, pa_card_profile *profile, bool save, bool bypass_router);
-- 
1.8.3.1



More information about the pulseaudio-discuss mailing list