[pulseaudio-discuss] [PATCH v2 5/5] device-port: Make it impossible to have a dual-direction port.

Tanu Kaskinen tanuk at iki.fi
Fri Jun 29 08:04:59 PDT 2012


From: Tanu Kaskinen <tanu.kaskinen at digia.com>

---
 src/modules/alsa/alsa-mixer.c                   |   81 ++++++++++++++++-------
 src/modules/bluetooth/module-bluetooth-device.c |   24 ++-----
 src/modules/module-switch-on-port-available.c   |   27 +++++---
 src/pulsecore/device-port.c                     |   45 ++++++++-----
 src/pulsecore/device-port.h                     |    5 +-
 src/pulsecore/protocol-native.c                 |    2 +-
 6 files changed, 111 insertions(+), 73 deletions(-)

diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
index b573e8d..90b55f5 100644
--- a/src/modules/alsa/alsa-mixer.c
+++ b/src/modules/alsa/alsa-mixer.c
@@ -2812,12 +2812,41 @@ void pa_alsa_path_set_set_callback(pa_alsa_path_set *ps, snd_mixer_t *m, snd_mix
         pa_alsa_path_set_callback(p, m, cb, userdata);
 }
 
+static pa_alsa_path *profile_set_get_path(pa_alsa_profile_set *ps, const char *path_name) {
+    pa_alsa_path *path;
+
+    pa_assert(ps);
+    pa_assert(path_name);
+
+    if ((path = pa_hashmap_get(ps->output_paths, path_name)))
+        return path;
+
+    return pa_hashmap_get(ps->input_paths, path_name);
+}
+
+static void profile_set_add_path(pa_alsa_profile_set *ps, pa_alsa_path *path) {
+    pa_assert(ps);
+    pa_assert(path);
+
+    switch (path->direction) {
+        case PA_ALSA_DIRECTION_OUTPUT:
+            pa_assert_se(pa_hashmap_put(ps->output_paths, path->name, path) >= 0);
+            break;
+
+        case PA_ALSA_DIRECTION_INPUT:
+            pa_assert_se(pa_hashmap_put(ps->input_paths, path->name, path) >= 0);
+            break;
+
+        default:
+            pa_assert_not_reached();
+    }
+}
+
 pa_alsa_path_set *pa_alsa_path_set_new(pa_alsa_mapping *m, pa_alsa_direction_t direction, const char *paths_dir) {
     pa_alsa_path_set *ps;
     char **pn = NULL, **en = NULL, **ie;
     pa_alsa_decibel_fix *db_fix;
     void *state, *state2;
-    pa_hashmap *cache;
 
     pa_assert(m);
     pa_assert(m->profile_set);
@@ -2831,14 +2860,10 @@ pa_alsa_path_set *pa_alsa_path_set_new(pa_alsa_mapping *m, pa_alsa_direction_t d
     ps->direction = direction;
     ps->paths = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
 
-    if (direction == PA_ALSA_DIRECTION_OUTPUT) {
+    if (direction == PA_ALSA_DIRECTION_OUTPUT)
         pn = m->output_path_names;
-        cache = m->profile_set->output_paths;
-    }
-    else if (direction == PA_ALSA_DIRECTION_INPUT) {
+    else
         pn = m->input_path_names;
-        cache = m->profile_set->input_paths;
-    }
 
     if (pn) {
         char **in;
@@ -2857,15 +2882,21 @@ pa_alsa_path_set *pa_alsa_path_set_new(pa_alsa_mapping *m, pa_alsa_direction_t d
             if (duplicate)
                 continue;
 
-            p = pa_hashmap_get(cache, *in);
+            p = profile_set_get_path(m->profile_set, *in);
+
+            if (p && p->direction != direction) {
+                pa_log("Configuration error: Path %s is used both as an input and as an output path.", p->name);
+                goto fail;
+            }
+
             if (!p) {
                 char *fn = pa_sprintf_malloc("%s.conf", *in);
                 p = pa_alsa_path_new(paths_dir, fn, direction);
                 pa_xfree(fn);
                 if (p)
-                    pa_hashmap_put(cache, *in, p);
+                    profile_set_add_path(m->profile_set, p);
             }
-            pa_assert(pa_hashmap_get(cache, *in) == p);
+
             if (p)
                 pa_hashmap_put(ps->paths, p, p);
 
@@ -2876,13 +2907,11 @@ pa_alsa_path_set *pa_alsa_path_set_new(pa_alsa_mapping *m, pa_alsa_direction_t d
 
     if (direction == PA_ALSA_DIRECTION_OUTPUT)
         en = m->output_element;
-    else if (direction == PA_ALSA_DIRECTION_INPUT)
+    else
         en = m->input_element;
 
-    if (!en) {
-        pa_alsa_path_set_free(ps);
-        return NULL;
-    }
+    if (!en)
+        goto fail;
 
     for (ie = en; *ie; ie++) {
         char **je;
@@ -2934,6 +2963,12 @@ finish:
     }
 
     return ps;
+
+fail:
+    if (ps)
+        pa_alsa_path_set_free(ps);
+
+    return NULL;
 }
 
 void pa_alsa_path_set_dump(pa_alsa_path_set *ps) {
@@ -4376,13 +4411,13 @@ void pa_alsa_profile_set_dump(pa_alsa_profile_set *ps) {
         pa_alsa_decibel_fix_dump(db_fix);
 }
 
-static pa_device_port* device_port_alsa_init(pa_hashmap *ports,
+static pa_device_port* device_port_alsa_init(pa_hashmap *ports, /* card ports */
     const char* name,
     const char* description,
     pa_alsa_path *path,
     pa_alsa_setting *setting,
     pa_card_profile *cp,
-    pa_hashmap *extra,
+    pa_hashmap *extra, /* sink/source ports */
     pa_core *core) {
 
     pa_device_port *p;
@@ -4393,8 +4428,11 @@ static pa_device_port* device_port_alsa_init(pa_hashmap *ports,
 
     if (!p) {
         pa_alsa_port_data *data;
+        pa_direction_t direction;
 
-        p = pa_device_port_new(core, name, description, sizeof(pa_alsa_port_data));
+        direction = path->direction == PA_ALSA_DIRECTION_OUTPUT ? PA_DIRECTION_OUTPUT : PA_DIRECTION_INPUT;
+
+        p = pa_device_port_new(core, name, description, direction, sizeof(pa_alsa_port_data));
         pa_assert(p);
         pa_hashmap_put(ports, p->name, p);
         pa_proplist_update(p->proplist, PA_UPDATE_REPLACE, path->proplist);
@@ -4405,9 +4443,6 @@ static pa_device_port* device_port_alsa_init(pa_hashmap *ports,
         path->port = p;
     }
 
-    p->is_input |= path->direction == PA_ALSA_DIRECTION_ANY || path->direction == PA_ALSA_DIRECTION_INPUT;
-    p->is_output |= path->direction == PA_ALSA_DIRECTION_ANY || path->direction == PA_ALSA_DIRECTION_OUTPUT;
-
     if (cp)
         pa_hashmap_put(p->profiles, cp->name, cp);
 
@@ -4422,8 +4457,8 @@ static pa_device_port* device_port_alsa_init(pa_hashmap *ports,
 void pa_alsa_path_set_add_ports(
         pa_alsa_path_set *ps,
         pa_card_profile *cp,
-        pa_hashmap *ports,
-        pa_hashmap *extra,
+        pa_hashmap *ports, /* card ports */
+        pa_hashmap *extra, /* sink/source ports */
         pa_core *core) {
 
     pa_alsa_path *path;
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index 06b4033..3b841ff 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -2759,51 +2759,39 @@ static void create_ports_for_profile(struct userdata *u, pa_card_new_data *card_
 
     switch (*d) {
         case PROFILE_A2DP:
-            pa_assert_se(port = pa_device_port_new(u->core, "a2dp-output", _("Bluetooth High Quality (A2DP)"), 0));
+            pa_assert_se(port = pa_device_port_new(u->core, "a2dp-output", _("Bluetooth High Quality (A2DP)"), PA_DIRECTION_OUTPUT, 0));
             pa_assert_se(pa_hashmap_put(card_new_data->ports, port->name, port) >= 0);
-            port->is_output = 1;
-            port->is_input = 0;
             port->priority = profile->priority * 100;
             pa_hashmap_put(port->profiles, profile->name, profile);
             break;
 
         case PROFILE_A2DP_SOURCE:
-            pa_assert_se(port = pa_device_port_new(u->core, "a2dp-input", _("Bluetooth High Quality (A2DP)"), 0));
+            pa_assert_se(port = pa_device_port_new(u->core, "a2dp-input", _("Bluetooth High Quality (A2DP)"), PA_DIRECTION_INPUT, 0));
             pa_assert_se(pa_hashmap_put(card_new_data->ports, port->name, port) >= 0);
-            port->is_output = 0;
-            port->is_input = 1;
             port->priority = profile->priority * 100;
             pa_hashmap_put(port->profiles, profile->name, profile);
             break;
 
         case PROFILE_HSP:
-            pa_assert_se(port = pa_device_port_new(u->core, "hsp-output", _("Bluetooth Telephony (HSP/HFP)"), 0));
+            pa_assert_se(port = pa_device_port_new(u->core, "hsp-output", _("Bluetooth Telephony (HSP/HFP)"), PA_DIRECTION_OUTPUT, 0));
             pa_assert_se(pa_hashmap_put(card_new_data->ports, port->name, port) >= 0);
-            port->is_output = 1;
-            port->is_input = 0;
             port->priority = profile->priority * 100;
             pa_hashmap_put(port->profiles, profile->name, profile);
 
-            pa_assert_se(port = pa_device_port_new(u->core, "hsp-input", _("Bluetooth Telephony (HSP/HFP)"), 0));
+            pa_assert_se(port = pa_device_port_new(u->core, "hsp-input", _("Bluetooth Telephony (HSP/HFP)"), PA_DIRECTION_INPUT, 0));
             pa_assert_se(pa_hashmap_put(card_new_data->ports, port->name, port) >= 0);
-            port->is_output = 0;
-            port->is_input = 1;
             port->priority = profile->priority * 100;
             pa_hashmap_put(port->profiles, profile->name, profile);
             break;
 
         case PROFILE_HFGW:
-            pa_assert_se(port = pa_device_port_new(u->core, "hfgw-output", _("Bluetooth Handsfree Gateway"), 0));
+            pa_assert_se(port = pa_device_port_new(u->core, "hfgw-output", _("Bluetooth Handsfree Gateway"), PA_DIRECTION_OUTPUT, 0));
             pa_assert_se(pa_hashmap_put(card_new_data->ports, port->name, port) >= 0);
-            port->is_output = 1;
-            port->is_input = 0;
             port->priority = profile->priority * 100;
             pa_hashmap_put(port->profiles, profile->name, profile);
 
-            pa_assert_se(port = pa_device_port_new(u->core, "hfgw-input", _("Bluetooth Handsfree Gateway"), 0));
+            pa_assert_se(port = pa_device_port_new(u->core, "hfgw-input", _("Bluetooth Handsfree Gateway"), PA_DIRECTION_INPUT, 0));
             pa_assert_se(pa_hashmap_put(card_new_data->ports, port->name, port) >= 0);
-            port->is_output = 0;
-            port->is_input = 1;
             port->priority = profile->priority * 100;
             pa_hashmap_put(port->profiles, profile->name, profile);
             break;
diff --git a/src/modules/module-switch-on-port-available.c b/src/modules/module-switch-on-port-available.c
index 05bf5fe..07586de 100644
--- a/src/modules/module-switch-on-port-available.c
+++ b/src/modules/module-switch-on-port-available.c
@@ -92,13 +92,11 @@ static pa_bool_t try_to_switch_profile(pa_card *card, pa_device_port *port) {
     pa_log_debug("Finding best profile");
 
     PA_HASHMAP_FOREACH(profile, port->profiles, state) {
-        pa_direction_t direction = port->is_output ? PA_DIRECTION_OUTPUT : PA_DIRECTION_INPUT;
-
         if (best_profile && best_profile->priority >= profile->priority)
             continue;
 
         /* We make a best effort to keep other direction unchanged */
-        switch (direction) {
+        switch (port->direction) {
             case PA_DIRECTION_OUTPUT:
                 if (!profile_good_for_output(profile))
                     continue;
@@ -135,15 +133,22 @@ static void find_sink_and_source(pa_card *card, pa_device_port *port, pa_sink **
     pa_source *source = NULL;
     uint32_t state;
 
-    if (port->is_output)
-        PA_IDXSET_FOREACH(sink, card->sinks, state)
-            if (port == pa_hashmap_get(sink->ports, port->name))
-                break;
+    switch (port->direction) {
+        case PA_DIRECTION_OUTPUT:
+            PA_IDXSET_FOREACH(sink, card->sinks, state)
+                if (port == pa_hashmap_get(sink->ports, port->name))
+                    break;
+            break;
 
-    if (port->is_input)
-        PA_IDXSET_FOREACH(source, card->sources, state)
-            if (port == pa_hashmap_get(source->ports, port->name))
-                break;
+        case PA_DIRECTION_INPUT:
+            PA_IDXSET_FOREACH(source, card->sources, state)
+                if (port == pa_hashmap_get(source->ports, port->name))
+                    break;
+            break;
+
+        default:
+            pa_assert_not_reached();
+    }
 
     *si = sink;
     *so = source;
diff --git a/src/pulsecore/device-port.c b/src/pulsecore/device-port.c
index 28879f7..ef178ab 100644
--- a/src/pulsecore/device-port.c
+++ b/src/pulsecore/device-port.c
@@ -81,7 +81,7 @@ static void device_port_free(pa_object *o) {
 }
 
 
-pa_device_port *pa_device_port_new(pa_core *c, const char *name, const char *description, size_t extra) {
+pa_device_port *pa_device_port_new(pa_core *c, const char *name, const char *description, pa_direction_t direction, size_t extra) {
     pa_device_port *p;
 
     pa_assert(name);
@@ -89,16 +89,15 @@ pa_device_port *pa_device_port_new(pa_core *c, const char *name, const char *des
     p = PA_DEVICE_PORT(pa_object_new_internal(PA_ALIGN(sizeof(pa_device_port)) + extra, pa_device_port_type_id, pa_device_port_check_type));
     p->parent.free = device_port_free;
 
+    p->core = c;
     p->name = pa_xstrdup(name);
     p->description = pa_xstrdup(description);
-    p->core = c;
     p->priority = 0;
     p->available = PA_PORT_AVAILABLE_UNKNOWN;
+    p->proplist = pa_proplist_new();
     p->profiles = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
-    p->is_input = FALSE;
-    p->is_output = FALSE;
+    p->direction = direction;
     p->latency_offset = 0;
-    p->proplist = pa_proplist_new();
 
     return p;
 }
@@ -121,22 +120,34 @@ void pa_device_port_set_latency_offset(pa_device_port *p, int64_t offset) {
 
     p->latency_offset = offset;
 
-    if (p->is_output) {
-        pa_sink *sink;
+    switch (p->direction) {
+        case PA_DIRECTION_OUTPUT: {
+            pa_sink *sink;
 
-        PA_IDXSET_FOREACH(sink, p->core->sinks, state)
-            if (sink->active_port == p) {
-                pa_sink_set_latency_offset(sink, p->latency_offset);
-                break;
+            PA_IDXSET_FOREACH(sink, p->core->sinks, state) {
+                if (sink->active_port == p) {
+                    pa_sink_set_latency_offset(sink, p->latency_offset);
+                    break;
+                }
             }
 
-    } else {
-        pa_source *source;
+            break;
+        }
 
-        PA_IDXSET_FOREACH(source, p->core->sources, state)
-            if (source->active_port == p) {
-                pa_source_set_latency_offset(source, p->latency_offset);
-                break;
+        case PA_DIRECTION_INPUT: {
+            pa_source *source;
+
+            PA_IDXSET_FOREACH(source, p->core->sources, state) {
+                if (source->active_port == p) {
+                    pa_source_set_latency_offset(source, p->latency_offset);
+                    break;
+                }
             }
+
+            break;
+        }
+
+        default:
+            pa_assert_not_reached();
     }
 }
diff --git a/src/pulsecore/device-port.h b/src/pulsecore/device-port.h
index a5c6420..45f5553 100644
--- a/src/pulsecore/device-port.h
+++ b/src/pulsecore/device-port.h
@@ -49,8 +49,7 @@ struct pa_device_port {
 
     pa_proplist *proplist;
     pa_hashmap *profiles; /* Does not own the profiles */
-    pa_bool_t is_input:1;
-    pa_bool_t is_output:1;
+    pa_direction_t direction;
     int64_t latency_offset;
 
     /* .. followed by some implementation specific data */
@@ -61,7 +60,7 @@ PA_DECLARE_PUBLIC_CLASS(pa_device_port);
 
 #define PA_DEVICE_PORT_DATA(d) ((void*) ((uint8_t*) d + PA_ALIGN(sizeof(pa_device_port))))
 
-pa_device_port *pa_device_port_new(pa_core *c, const char *name, const char *description, size_t extra);
+pa_device_port *pa_device_port_new(pa_core *c, const char *name, const char *description, pa_direction_t direction, size_t extra);
 
 void pa_device_port_hashmap_free(pa_hashmap *h);
 
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 3e9c911..f34264f 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -3265,7 +3265,7 @@ static void card_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_car
         pa_tagstruct_puts(t, port->description);
         pa_tagstruct_putu32(t, port->priority);
         pa_tagstruct_putu32(t, port->available);
-        pa_tagstruct_putu8(t, /* FIXME: port->direction */ (port->is_input ? PA_DIRECTION_INPUT : 0) | (port->is_output ? PA_DIRECTION_OUTPUT : 0));
+        pa_tagstruct_putu8(t, port->direction);
         pa_tagstruct_put_proplist(t, port->proplist);
 
         pa_tagstruct_putu32(t, pa_hashmap_size(port->profiles));
-- 
1.7.10



More information about the pulseaudio-discuss mailing list