[pulseaudio-discuss] [PATCH 4/4] Profiles can have sink and source ports, and announce that through the API.

David Henningsson david.henningsson at canonical.com
Thu Jul 7 04:23:29 PDT 2011


Signed-off-by: David Henningsson <david.henningsson at canonical.com>
---
 src/pulse/introspect.c          |  139 +++++++++++++++++++++++----------------
 src/pulse/introspect.h          |    4 +
 src/pulsecore/card.c            |    2 +
 src/pulsecore/card.h            |    4 +
 src/pulsecore/device-port.c     |   11 +++
 src/pulsecore/device-port.h     |    4 +-
 src/pulsecore/protocol-native.c |   25 +++++++
 src/pulsecore/sink.c            |   20 +-----
 src/pulsecore/source.c          |   20 +-----
 9 files changed, 136 insertions(+), 93 deletions(-)

diff --git a/src/pulse/introspect.c b/src/pulse/introspect.c
index d1a0ed1..399d092 100644
--- a/src/pulse/introspect.c
+++ b/src/pulse/introspect.c
@@ -134,6 +134,42 @@ pa_operation* pa_context_get_server_info(pa_context *c, pa_server_info_cb_t cb,
 
 /*** Sink Info ***/
 
+static int read_sink_ports(pa_tagstruct *t, pa_operation *o, uint32_t* n_sink_ports, pa_sink_port_info*** sink_ports) {
+    int err = 0;
+    uint32_t n_ports, j;
+    pa_sink_port_info** ports;
+
+    if (o->context->version < 16 || (err = pa_tagstruct_getu32(t, &n_ports)) < 0 || n_ports == 0) {
+        *n_sink_ports = 0;
+        *sink_ports = NULL;
+        return err;
+    }
+
+    ports = pa_xnew(pa_sink_port_info*, n_ports+1);
+    ports[0] = pa_xnew0(pa_sink_port_info, n_ports);
+
+    for (j = 0; j < n_ports; j++) {
+        if (pa_tagstruct_gets(t, &ports[0][j].name) < 0 ||
+            pa_tagstruct_gets(t, &ports[0][j].description) < 0 ||
+            pa_tagstruct_getu32(t, &ports[0][j].priority) < 0) {
+
+            return -1;
+        }
+        if (o->context->version >= JACK_DETECTION_PROTOCOL_VERSION) {
+            uint32_t av;
+            if (pa_tagstruct_getu32(t, &av) < 0 || av > PA_PORT_AVAILABLE_YES)
+                return -1;
+            ports[0][j].available = av;
+        }
+        ports[j] = &ports[0][j];
+    }
+
+    ports[j] = NULL;
+    *n_sink_ports = n_ports;
+    *sink_ports = ports;
+    return 0;
+}
+
 static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
     pa_operation *o = userdata;
     int eol = 1;
@@ -191,39 +227,14 @@ static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, u
                  (pa_tagstruct_get_volume(t, &i.base_volume) < 0 ||
                   pa_tagstruct_getu32(t, &state) < 0 ||
                   pa_tagstruct_getu32(t, &i.n_volume_steps) < 0 ||
-                  pa_tagstruct_getu32(t, &i.card) < 0)) ||
-                (o->context->version >= 16 &&
-                 (pa_tagstruct_getu32(t, &i.n_ports)))) {
+                  pa_tagstruct_getu32(t, &i.card) < 0))) {
 
                 goto fail;
             }
 
             if (o->context->version >= 16) {
-                if (i.n_ports > 0) {
-                    i.ports = pa_xnew(pa_sink_port_info*, i.n_ports+1);
-                    i.ports[0] = pa_xnew(pa_sink_port_info, i.n_ports);
-
-                    for (j = 0; j < i.n_ports; j++) {
-                        if (pa_tagstruct_gets(t, &i.ports[0][j].name) < 0 ||
-                            pa_tagstruct_gets(t, &i.ports[0][j].description) < 0 ||
-                            pa_tagstruct_getu32(t, &i.ports[0][j].priority) < 0) {
-
-                            goto fail;
-                        }
-
-                        i.ports[0][j].available = PA_PORT_AVAILABLE_UNKNOWN;
-                        if (o->context->version >= JACK_DETECTION_PROTOCOL_VERSION) {
-                            uint32_t av;
-                            if (pa_tagstruct_getu32(t, &av) < 0 || av > PA_PORT_AVAILABLE_YES)
-                                goto fail;
-                            i.ports[0][j].available = av;
-                        }
-
-                        i.ports[j] = &i.ports[0][j];
-                    }
-
-                    i.ports[j] = NULL;
-                }
+                if (read_sink_ports(t, o, &i.n_ports, &i.ports) < 0)
+                    goto fail;
 
                 if (pa_tagstruct_gets(t, &ap) < 0)
                     goto fail;
@@ -407,6 +418,43 @@ pa_operation* pa_context_set_sink_port_by_name(pa_context *c, const char *name,
 
 /*** Source info ***/
 
+static int read_source_ports(pa_tagstruct *t, pa_operation *o, uint32_t* n_source_ports, pa_source_port_info*** source_ports) {
+    int err = 0;
+    uint32_t n_ports, j;
+    pa_source_port_info** ports;
+
+    pa_log_debug("read_source_ports");
+    if (o->context->version < 16 || (err = pa_tagstruct_getu32(t, &n_ports)) < 0 || n_ports == 0) {
+        *n_source_ports = 0;
+        *source_ports = NULL;
+        return err;
+    }
+
+    ports = pa_xnew(pa_source_port_info*, n_ports+1);
+    ports[0] = pa_xnew0(pa_source_port_info, n_ports);
+
+    for (j = 0; j < n_ports; j++) {
+        if (pa_tagstruct_gets(t, &ports[0][j].name) < 0 ||
+            pa_tagstruct_gets(t, &ports[0][j].description) < 0 ||
+            pa_tagstruct_getu32(t, &ports[0][j].priority) < 0) {
+
+            return -1;
+        }
+        if (o->context->version >= JACK_DETECTION_PROTOCOL_VERSION) {
+            uint32_t av;
+            if (pa_tagstruct_getu32(t, &av) < 0 || av > PA_PORT_AVAILABLE_YES)
+                return -1;
+            ports[0][j].available = av;
+        }
+        ports[j] = &ports[0][j];
+    }
+
+    ports[j] = NULL;
+    *n_source_ports = n_ports;
+    *source_ports = ports;
+    return 0;
+}
+
 static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
     pa_operation *o = userdata;
     int eol = 1;
@@ -464,39 +512,14 @@ static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command,
                  (pa_tagstruct_get_volume(t, &i.base_volume) < 0 ||
                   pa_tagstruct_getu32(t, &state) < 0 ||
                   pa_tagstruct_getu32(t, &i.n_volume_steps) < 0 ||
-                  pa_tagstruct_getu32(t, &i.card) < 0)) ||
-                (o->context->version >= 16 &&
-                 (pa_tagstruct_getu32(t, &i.n_ports)))) {
+                  pa_tagstruct_getu32(t, &i.card) < 0))) {
 
                 goto fail;
             }
 
             if (o->context->version >= 16) {
-                if (i.n_ports > 0) {
-                    i.ports = pa_xnew(pa_source_port_info*, i.n_ports+1);
-                    i.ports[0] = pa_xnew(pa_source_port_info, i.n_ports);
-
-                    for (j = 0; j < i.n_ports; j++) {
-                        if (pa_tagstruct_gets(t, &i.ports[0][j].name) < 0 ||
-                            pa_tagstruct_gets(t, &i.ports[0][j].description) < 0 ||
-                            pa_tagstruct_getu32(t, &i.ports[0][j].priority) < 0) {
-
-                            goto fail;
-                        }
-
-                        i.ports[0][j].available = PA_PORT_AVAILABLE_UNKNOWN;
-                        if (o->context->version >= JACK_DETECTION_PROTOCOL_VERSION) {
-                            uint32_t av;
-                            if (pa_tagstruct_getu32(t, &av) < 0 || av > PA_PORT_AVAILABLE_YES)
-                                goto fail;
-                            i.ports[0][j].available = av;
-                        }
-
-                        i.ports[j] = &i.ports[0][j];
-                    }
-
-                    i.ports[j] = NULL;
-                }
+                if (read_source_ports(t, o, &i.n_ports, &i.ports) < 0)
+                    goto fail;
 
                 if (pa_tagstruct_gets(t, &ap) < 0)
                     goto fail;
@@ -813,6 +836,10 @@ static void context_get_card_info_callback(pa_pdispatch *pd, uint32_t command, u
                         pa_xfree(i.profiles);
                         goto finish;
                     }
+                    if (o->context->version >= JACK_DETECTION_PROTOCOL_VERSION) {
+                        read_sink_ports(t, o, &i.profiles[j].n_sink_ports, &i.profiles[j].sink_ports);
+                        read_source_ports(t, o, &i.profiles[j].n_source_ports, &i.profiles[j].source_ports);
+                    }
                 }
 
                 /* Terminate with an extra NULL entry, just to make sure */
diff --git a/src/pulse/introspect.h b/src/pulse/introspect.h
index 8e4cc97..259c57b 100644
--- a/src/pulse/introspect.h
+++ b/src/pulse/introspect.h
@@ -452,6 +452,10 @@ typedef struct pa_card_profile_info {
     uint32_t n_sinks;                   /**< Number of sinks this profile would create */
     uint32_t n_sources;                 /**< Number of sources this profile would create */
     uint32_t priority;                  /**< The higher this value is the more useful this profile is as a default */
+    uint32_t n_sink_ports;              /**< Number of entries in sink_ports array \since MERGE_OF_JACK_DETECTION */
+    pa_sink_port_info** sink_ports;     /**< Array of available output ports, or NULL. Array is terminated by an entry set to NULL. The number of entries is stored in n_sink_ports. \since MERGE_OF_JACK_DETECTION */
+    uint32_t n_source_ports;            /**< Number of entries in source_ports array \since MERGE_OF_JACK_DETECTION */
+    pa_source_port_info** source_ports; /**< Array of available input ports, or NULL. Array is terminated by an entry set to NULL. The number of entries is stored in n_source_ports. \since MERGE_OF_JACK_DETECTION */
 } pa_card_profile_info;
 
 /** Stores information about cards. Please note that this structure
diff --git a/src/pulsecore/card.c b/src/pulsecore/card.c
index feaa444..f1c5be5 100644
--- a/src/pulsecore/card.c
+++ b/src/pulsecore/card.c
@@ -56,6 +56,8 @@ pa_card_profile *pa_card_profile_new(const char *name, const char *description,
 void pa_card_profile_free(pa_card_profile *c) {
     pa_assert(c);
 
+    pa_device_port_hashmap_free(c->sink_ports);
+    pa_device_port_hashmap_free(c->source_ports);
     pa_xfree(c->name);
     pa_xfree(c->description);
     pa_xfree(c);
diff --git a/src/pulsecore/card.h b/src/pulsecore/card.h
index 2d691b6..a50a6c1 100644
--- a/src/pulsecore/card.h
+++ b/src/pulsecore/card.h
@@ -28,6 +28,7 @@ typedef struct pa_card pa_card;
 #include <pulsecore/core.h>
 #include <pulsecore/module.h>
 #include <pulsecore/idxset.h>
+#include <pulsecore/device-port.h>
 
 typedef struct pa_card_profile {
     char *name;
@@ -42,6 +43,9 @@ typedef struct pa_card_profile {
     unsigned max_sink_channels;
     unsigned max_source_channels;
 
+    pa_hashmap *sink_ports;
+    pa_hashmap *source_ports;
+
     /* .. followed by some implementation specific data */
 } pa_card_profile;
 
diff --git a/src/pulsecore/device-port.c b/src/pulsecore/device-port.c
index d80b144..9e6ad43 100644
--- a/src/pulsecore/device-port.c
+++ b/src/pulsecore/device-port.c
@@ -51,3 +51,14 @@ pa_device_port *pa_device_port_new(const char *name, const char *description, si
 
     return p;
 }
+
+void pa_device_port_hashmap_free(pa_hashmap *h) {
+    if (h) {
+        pa_device_port *p;
+
+        while ((p = pa_hashmap_steal_first(h)))
+            pa_device_port_unref(p);
+
+        pa_hashmap_free(h, NULL, NULL);
+    }
+}
diff --git a/src/pulsecore/device-port.h b/src/pulsecore/device-port.h
index fa866a1..d28fa2a 100644
--- a/src/pulsecore/device-port.h
+++ b/src/pulsecore/device-port.h
@@ -53,6 +53,8 @@ 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(const char *name, const char *description, size_t extra);
-/*void pa_device_port_free(pa_device_port *p); */
+
+
+void pa_device_port_hashmap_free(pa_hashmap *h);
 
 #endif
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 4dcc07c..6e7b190 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -3195,6 +3195,26 @@ static void client_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_c
         pa_tagstruct_put_proplist(t, client->proplist);
 }
 
+static void device_ports_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_hashmap *ports) {
+    void *state = NULL;
+    pa_device_port *p;
+
+    if (!ports) {
+        pa_tagstruct_putu32(t, 0);
+        return;
+    }
+
+    pa_tagstruct_putu32(t, pa_hashmap_size(ports));
+    PA_HASHMAP_FOREACH(p, ports, state) {
+        pa_tagstruct_puts(t, p->name);
+        pa_tagstruct_puts(t, p->description);
+        pa_tagstruct_putu32(t, p->priority);
+        if (c->version >= JACK_DETECTION_PROTOCOL_VERSION)
+            pa_tagstruct_putu32(t, p->available);
+    }
+
+}
+
 static void card_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_card *card) {
     void *state = NULL;
     pa_card_profile *p;
@@ -3216,6 +3236,11 @@ static void card_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_car
             pa_tagstruct_putu32(t, p->n_sinks);
             pa_tagstruct_putu32(t, p->n_sources);
             pa_tagstruct_putu32(t, p->priority);
+
+            if (c->version >= JACK_DETECTION_PROTOCOL_VERSION) {
+                device_ports_fill_tagstruct(c, t, p->sink_ports);
+                device_ports_fill_tagstruct(c, t, p->source_ports);
+            }
         }
     }
 
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 7dd0868..9a24301 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -131,15 +131,7 @@ void pa_sink_new_data_done(pa_sink_new_data *data) {
 
     pa_proplist_free(data->proplist);
 
-    if (data->ports) {
-        pa_device_port *p;
-
-        while ((p = pa_hashmap_steal_first(data->ports)))
-            pa_device_port_unref(p);
-
-        pa_hashmap_free(data->ports, NULL, NULL);
-    }
-
+    pa_device_port_hashmap_free(data->ports);
     pa_xfree(data->name);
     pa_xfree(data->active_port);
 }
@@ -587,15 +579,7 @@ static void sink_free(pa_object *o) {
     if (s->proplist)
         pa_proplist_free(s->proplist);
 
-    if (s->ports) {
-        pa_device_port *p;
-
-        while ((p = pa_hashmap_steal_first(s->ports)))
-           pa_device_port_unref(p);
-
-        pa_hashmap_free(s->ports, NULL, NULL);
-    }
-
+    pa_device_port_hashmap_free(s->ports);
     pa_xfree(s);
 }
 
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index eaedd4e..80df806 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -123,15 +123,7 @@ void pa_source_new_data_done(pa_source_new_data *data) {
 
     pa_proplist_free(data->proplist);
 
-    if (data->ports) {
-        pa_device_port *p;
-
-        while ((p = pa_hashmap_steal_first(data->ports)))
-            pa_device_port_unref(p);
-
-        pa_hashmap_free(data->ports, NULL, NULL);
-    }
-
+    pa_device_port_hashmap_free(data->ports);
     pa_xfree(data->name);
     pa_xfree(data->active_port);
 }
@@ -519,15 +511,7 @@ static void source_free(pa_object *o) {
     if (s->proplist)
         pa_proplist_free(s->proplist);
 
-    if (s->ports) {
-        pa_device_port *p;
-
-        while ((p = pa_hashmap_steal_first(s->ports)))
-            pa_device_port_unref(p);
-
-        pa_hashmap_free(s->ports, NULL, NULL);
-    }
-
+    pa_device_port_hashmap_free(s->ports);
     pa_xfree(s);
 }
 
-- 
1.7.4.1



More information about the pulseaudio-discuss mailing list