From 84a7bf671ce5864158d0531f6ffb7070587a2969 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 4 Dec 2018 11:48:15 +0100 Subject: [PATCH] stream: connect to source and sink Stream: also connect to the right source, try to convert the name to index when lookup fails, just like what pulseaudio does. Implement more proplist functions, add some more info to the stream. stream: handle NULL format Improve introspection of the sink_input and source_output name, this should be the media.name when possible. --- src/context.c | 19 +++++++++++++++++++ src/introspect.c | 40 ++++++++++++++++++++-------------------- src/proplist.c | 33 +++++++++++++++++++++++++++++---- src/stream.c | 24 +++++++++++++++++++++--- 4 files changed, 89 insertions(+), 27 deletions(-) diff --git a/src/context.c b/src/context.c index 7e87f3f91..0f3193794 100644 --- a/src/context.c +++ b/src/context.c @@ -97,6 +97,25 @@ struct global *pa_context_find_global(pa_context *c, uint32_t id) return NULL; } +struct global *pa_context_find_global_by_name(pa_context *c, uint32_t mask, const char *name) +{ + struct global *g; + const char *str; + uint32_t id = atoi(name); + + spa_list_for_each(g, &c->globals, link) { + if (!(g->mask & mask)) + continue; + if (g->props != NULL && + (str = pw_properties_get(g->props, "node.name")) != NULL && + strcmp(str, name) == 0) + return g; + if (g->id == id) + return g; + } + return NULL; +} + struct global *pa_context_find_linked(pa_context *c, uint32_t idx) { struct global *g, *f; diff --git a/src/introspect.c b/src/introspect.c index 426a52eda..7ccf44b35 100644 --- a/src/introspect.c +++ b/src/introspect.c @@ -363,24 +363,6 @@ static void sink_info(pa_operation *o, void *userdata) pa_operation_done(o); } -struct global *pa_context_find_global_by_name(pa_context *c, uint32_t mask, const char *name) -{ - struct global *g; - const char *str; - - spa_list_for_each(g, &c->globals, link) { - if (!(g->mask & mask)) - continue; - if (g->props == NULL) - continue; - if ((str = pw_properties_get(g->props, "node.name")) == NULL) - continue; - if (strcmp(str, name) == 0) - return g; - } - return NULL; -} - pa_operation* pa_context_get_sink_info_by_name(pa_context *c, const char *name, pa_sink_info_cb_t cb, void *userdata) { pa_operation *o; @@ -1269,6 +1251,7 @@ static void sink_input_callback(struct sink_input_data *d) { struct global *g = d->global, *l; struct pw_node_info *info = g->info; + const char *name; pa_sink_input_info i; pa_format_info ii[1]; pa_stream *s; @@ -1279,9 +1262,17 @@ static void sink_input_callback(struct sink_input_data *d) s = find_stream(d->context, g->id); + if (info->props) { + if ((name = spa_dict_lookup(info->props, "media.name")) == NULL && + (name = spa_dict_lookup(info->props, "application.name")) == NULL) + name = info->name; + } + else + name = info->name; + spa_zero(i); i.index = g->id; - i.name = info->name; + i.name = name ? name : "Unknown"; i.owner_module = PA_INVALID_INDEX; i.client = g->parent_id; if (s) { @@ -1525,6 +1516,7 @@ static void source_output_callback(struct source_output_data *d) { struct global *g = d->global, *l; struct pw_node_info *info = g->info; + const char *name; pa_source_output_info i; pa_format_info ii[1]; pa_stream *s; @@ -1535,9 +1527,17 @@ static void source_output_callback(struct source_output_data *d) s = find_stream(d->context, g->id); + if (info->props) { + if ((name = spa_dict_lookup(info->props, "media.name")) == NULL && + (name = spa_dict_lookup(info->props, "application.name")) == NULL) + name = info->name; + } + else + name = info->name; + spa_zero(i); i.index = g->id; - i.name = info->name; + i.name = name ? name : "Unknown"; i.owner_module = PA_INVALID_INDEX; i.client = g->parent_id; if (s) { diff --git a/src/proplist.c b/src/proplist.c index 281898f1e..fad5c1a5f 100644 --- a/src/proplist.c +++ b/src/proplist.c @@ -159,7 +159,13 @@ int pa_proplist_get(pa_proplist *p, const char *key, const void **data, size_t * void pa_proplist_update(pa_proplist *p, pa_update_mode_t mode, const pa_proplist *other) { spa_assert(p); - pw_log_warn("Not Implemented"); + spa_assert(mode == PA_UPDATE_SET || mode == PA_UPDATE_MERGE || mode == PA_UPDATE_REPLACE); + spa_assert(other); + + if (mode == PA_UPDATE_SET) + pa_proplist_clear(p); + + pa_proplist_update_dict(p, &other->props->dict); } int pa_proplist_unset(pa_proplist *p, const char *key) @@ -274,7 +280,7 @@ int pa_proplist_contains(pa_proplist *p, const char *key) void pa_proplist_clear(pa_proplist *p) { spa_assert(p); - pw_log_warn("Not Implemented"); + pw_properties_clear(p->props); } pa_proplist* pa_proplist_copy(const pa_proplist *p) @@ -305,8 +311,27 @@ int pa_proplist_isempty(pa_proplist *p) int pa_proplist_equal(pa_proplist *a, pa_proplist *b) { + int i; + spa_assert(a); spa_assert(b); - pw_log_warn("Not Implemented"); - return 0; + + if (a == b) + return 1; + + if (pa_proplist_size(a) != pa_proplist_size(b)) + return 0; + + for (i = 0; i < a->props->dict.n_items; i++) { + const struct spa_dict_item *ai, *bi; + + ai = &a->props->dict.items[i]; + bi = spa_dict_lookup_item(&b->props->dict, ai->key); + + if (bi == NULL || bi->value == NULL || ai->value == NULL) + return 0; + if (strcmp(ai->value, bi->value) != 0) + return 0; + } + return 1; } diff --git a/src/stream.c b/src/stream.c index 1ed347c88..ed5144af7 100644 --- a/src/stream.c +++ b/src/stream.c @@ -337,6 +337,11 @@ static void stream_format_changed(void *data, const struct spa_pod *format) struct spa_audio_info info = { 0 }; int i, res; + if (format == NULL) { + res = 0; + goto done; + } + spa_format_parse(format, &info.media_type, &info.media_subtype); if (info.media_type != SPA_MEDIA_TYPE_audio || @@ -497,10 +502,11 @@ pa_stream* stream_new(pa_context *c, const char *name, if (name) pa_proplist_sets(s->proplist, PA_PROP_MEDIA_NAME, name); else - name = pa_proplist_gets(p, PA_PROP_MEDIA_NAME); + name = pa_proplist_gets(s->proplist, PA_PROP_MEDIA_NAME); props = pw_properties_new("client.api", "pulseaudio", NULL); + pw_properties_update(props, &s->proplist->props->dict); s->stream = pw_stream_new(c->remote, name, props); s->refcount = 1; @@ -762,6 +768,8 @@ static int create_stream(pa_stream_direction_t direction, spa_assert(s); spa_assert(s->refcount >= 1); + pw_log_debug("stream %p: connect %s %08x", s, dev, flags); + s->direction = direction; s->timing_info_valid = false; s->disconnecting = false; @@ -824,8 +832,18 @@ static int create_stream(pa_stream_direction_t direction, if ((str = getenv("PIPEWIRE_NODE")) != NULL) devid = atoi(str); } - else if ((g = pa_context_find_global_by_name(s->context, PA_SUBSCRIPTION_MASK_SINK, dev)) != NULL) { - devid = g->id; + else { + uint32_t mask; + + if (direction == PA_STREAM_PLAYBACK) + mask = PA_SUBSCRIPTION_MASK_SINK; + else if (direction == PA_STREAM_RECORD) + mask = PA_SUBSCRIPTION_MASK_SOURCE; + else + mask = 0; + + if ((g = pa_context_find_global_by_name(s->context, mask, dev)) != NULL) + devid = g->id; } if ((str = pa_proplist_gets(s->proplist, PA_PROP_MEDIA_ROLE)) == NULL)