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