From 3733a5e21990d09c3f479d12d6776f0c69dc86f0 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Wed, 14 Oct 2020 12:35:27 +0200 Subject: [PATCH] media-session: save last target_node Keep a per node entry of the saved target node and use this when there is no other target node. When explicitly moving a stream, save the new target node. --- src/examples/media-session/media-session.c | 2 + src/examples/media-session/media-session.h | 3 + src/examples/media-session/policy-node.c | 79 ++++++++++++++------- src/examples/media-session/restore-stream.c | 27 +++---- 4 files changed, 66 insertions(+), 45 deletions(-) diff --git a/src/examples/media-session/media-session.c b/src/examples/media-session/media-session.c index e91302de0..4b5386e7a 100644 --- a/src/examples/media-session/media-session.c +++ b/src/examples/media-session/media-session.c @@ -624,6 +624,8 @@ static void node_destroy(void *object) pw_node_info_free(node->info); node->info = NULL; } + free(node->target_node); + node->target_node = NULL; } static const struct object_info node_info = { diff --git a/src/examples/media-session/media-session.h b/src/examples/media-session/media-session.h index 8d47672af..5994238b4 100644 --- a/src/examples/media-session/media-session.h +++ b/src/examples/media-session/media-session.h @@ -144,6 +144,9 @@ struct sm_node { struct spa_list param_list; /**< list of sm_param */ struct pw_node_info *info; struct spa_list port_list; + + char *target_node; /** desired target node from stored + * preferences */ }; struct sm_port { diff --git a/src/examples/media-session/policy-node.c b/src/examples/media-session/policy-node.c index 80c5cd167..32a31f5a1 100644 --- a/src/examples/media-session/policy-node.c +++ b/src/examples/media-session/policy-node.c @@ -329,6 +329,38 @@ static void destroy_node(struct impl *impl, struct node *node) sm_object_remove_data((struct sm_object*)node->obj, SESSION_KEY); } +static struct node *find_node_by_id(struct impl *impl, uint32_t id) +{ + struct node *node; + spa_list_for_each(node, &impl->node_list, link) { + if (node->id == id) + return node; + } + return NULL; +} + +static const char *get_device_name(struct node *node) +{ + if (node->type != NODE_TYPE_DEVICE || + node->obj->obj.props == NULL) + return NULL; + return pw_properties_get(node->obj->obj.props, PW_KEY_NODE_NAME); +} + +static uint32_t find_device_for_name(struct impl *impl, const char *name) +{ + struct node *node; + const char *str; + + spa_list_for_each(node, &impl->node_list, link) { + if ((str = get_device_name(node)) == NULL) + continue; + if (strcmp(str, name) == 0) + return node->obj->obj.id; + } + return SPA_ID_INVALID; +} + static void session_create(void *data, struct sm_object *object) { struct impl *impl = data; @@ -519,6 +551,7 @@ static int rescan_node(struct impl *impl, struct node *n) struct pw_node_info *info; struct node *peer; struct sm_object *obj; + uint32_t path_id = SPA_ID_INVALID; if (!n->active) { pw_log_debug(NAME " %p: node %d is not active", impl, n->id); @@ -561,28 +594,29 @@ static int rescan_node(struct impl *impl, struct node *n) return 0; } + str = spa_dict_lookup(props, PW_KEY_NODE_EXCLUSIVE); + exclusive = str ? pw_properties_parse_bool(str) : false; + + pw_log_debug(NAME " %p: exclusive:%d", impl, exclusive); + spa_zero(find); - - if ((str = spa_dict_lookup(props, PW_KEY_NODE_EXCLUSIVE)) != NULL) - exclusive = pw_properties_parse_bool(str); - else - exclusive = false; - find.impl = impl; find.target = n; find.exclusive = exclusive; - pw_log_debug(NAME " %p: exclusive:%d", impl, exclusive); - str = spa_dict_lookup(props, PW_KEY_NODE_DONT_RECONNECT); reconnect = str ? !pw_properties_parse_bool(str) : true; - str = spa_dict_lookup(props, PW_KEY_NODE_TARGET); - pw_log_info("trying to link node %d exclusive:%d reconnect:%d target:%s", n->id, - exclusive, reconnect, str); + /* we always honour the target node asked for by the client */ + if ((str = spa_dict_lookup(props, PW_KEY_NODE_TARGET)) != NULL) + path_id = atoi(str); + if (path_id == SPA_ID_INVALID && n->obj->target_node != NULL) + path_id = find_device_for_name(impl, n->obj->target_node); - if (str != NULL) { - uint32_t path_id = atoi(str); + pw_log_info("trying to link node %d exclusive:%d reconnect:%d target:%d", n->id, + exclusive, reconnect, path_id); + + if (path_id != SPA_ID_INVALID) { pw_log_debug(NAME " %p: target:%d", impl, path_id); if ((obj = sm_media_session_find_object(impl->session, path_id)) != NULL) { @@ -598,8 +632,7 @@ static int rescan_node(struct impl *impl, struct node *n) pw_log_warn("node %d target:%d not found, find fallback:%d", n->id, path_id, reconnect); } - - if (str == NULL || reconnect) { + if (path_id == SPA_ID_INVALID || reconnect) { spa_list_for_each(peer, &impl->node_list, link) find_node(&find, peer); } @@ -680,16 +713,6 @@ static const struct sm_media_session_events session_events = { .destroy = session_destroy, }; -static struct node *find_node_by_id(struct impl *impl, uint32_t id) -{ - struct node *node; - spa_list_for_each(node, &impl->node_list, link) { - if (node->id == id) - return node; - } - return NULL; -} - static int move_node(struct impl *impl, uint32_t source, uint32_t target) { struct node *n, *src_node, *dst_node; @@ -734,8 +757,6 @@ static int handle_move(struct impl *impl, struct node *src_node, struct node *ds const char *str; struct pw_node_info *info; - - if (src_node->peer == dst_node) return 0; @@ -753,6 +774,10 @@ static int handle_move(struct impl *impl, struct node *src_node, struct node *ds src_node->peer ? src_node->peer->id : SPA_ID_INVALID, dst_node->id); + free(src_node->obj->target_node); + str = get_device_name(dst_node); + src_node->obj->target_node = str ? strdup(str) : NULL; + if (src_node->peer) unlink_nodes(src_node, src_node->peer); link_nodes(src_node, dst_node); diff --git a/src/examples/media-session/restore-stream.c b/src/examples/media-session/restore-stream.c index 237683a34..7e797d6ad 100644 --- a/src/examples/media-session/restore-stream.c +++ b/src/examples/media-session/restore-stream.c @@ -74,12 +74,6 @@ struct stream { struct spa_hook listener; }; -struct find_data { - struct impl *impl; - const char *name; - uint32_t id; -}; - static void remove_idle_timeout(struct impl *impl) { struct pw_loop *main_loop = pw_context_get_main_loop(impl->context); @@ -129,7 +123,6 @@ static char *serialize_props(struct stream *str, const struct spa_pod *param) float val = 0.0f; bool b = false; char *ptr; - const char *v; size_t size; FILE *f; @@ -156,15 +149,16 @@ static char *serialize_props(struct stream *str, const struct spa_pod *param) fprintf(f, "volumes:%d", n_vals); for (i = 0; i < n_vals; i++) fprintf(f, ",%f", vals[i]); + fprintf(f, " "); break; } default: break; } } - if ((v = pw_properties_get(str->obj->obj.props, PW_KEY_NODE_TARGET)) != NULL) { - fprintf(f, "target-node:%s", v); - } + if (str->obj->target_node != NULL) + fprintf(f, "target-node:%s", str->obj->target_node); + fclose(f); return ptr; } @@ -192,7 +186,7 @@ static int restore_stream(struct stream *str, const char *val) { const char *p; char *end; - char buf[1024], target[256]; + char buf[1024]; struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buf, sizeof(buf)); struct spa_pod_frame f[2]; struct spa_pod *param; @@ -243,13 +237,10 @@ static int restore_stream(struct stream *str, const char *val) } else if (strstr(p, "target-node:") == p) { p += 12; - end = strstr(p, " "); - if (end == NULL) - continue; - - i = end - p; - strncpy(target, p, i); - target[i-1] = 0; + i = strlen(p); + pw_log_info("stream %d: target '%s'", str->obj->obj.id, p); + free(str->obj->target_node); + str->obj->target_node = i > 0 ? strndup(p, i) : NULL; } else { p++; }