diff --git a/src/pipewire/context.c b/src/pipewire/context.c index 7afec125d..bc9ea023b 100644 --- a/src/pipewire/context.c +++ b/src/pipewire/context.c @@ -834,12 +834,12 @@ static inline int run_nodes(struct pw_context *context, struct pw_impl_node *nod * don't get included here. They were added to the same driver but * need to otherwise stay idle unless some non-passive link activates * them. */ - if (node->link_group != NULL) { + if (node->link_groups != NULL) { spa_list_for_each(t, nodes, sort_link) { if (t->exported || !t->active || SPA_FLAG_IS_SET(t->checked, 1u<link_group, node->link_group)) + if (pw_strv_find_common(t->link_groups, node->link_groups) < 0) continue; pw_log_debug(" group %p: '%s'", t, t->name); @@ -931,15 +931,15 @@ static int collect_nodes(struct pw_context *context, struct pw_impl_node *node, } /* now go through all the nodes that have the same group and * that are not yet visited */ - if (n->group != NULL || n->link_group != NULL) { + if (n->groups != NULL || n->link_groups != NULL) { spa_list_for_each(t, &context->node_list, link) { if (t->exported || !t->active || t->visited) continue; - if ((t->group == NULL || !spa_streq(t->group, n->group)) && - (t->link_group == NULL || !spa_streq(t->link_group, n->link_group))) + if (pw_strv_find_common(t->groups, n->groups) < 0 && + pw_strv_find_common(t->link_groups, n->link_groups) < 0) continue; - pw_log_debug("%p: %s join group:%s link-group:%s", - t, t->name, n->group, n->link_group); + pw_log_debug("%p: %s join group of %s", + t, t->name, n->name); t->visited = true; spa_list_append(&queue, &t->sort_link); } diff --git a/src/pipewire/impl-node.c b/src/pipewire/impl-node.c index 7061646ad..a49005497 100644 --- a/src/pipewire/impl-node.c +++ b/src/pipewire/impl-node.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -42,6 +43,9 @@ struct impl { unsigned int cache_params:1; unsigned int pending_play:1; + + char *group; + char *link_group; }; #define pw_node_resource(r,m,v,...) pw_resource_call(r,struct pw_node_events,m,v,__VA_ARGS__) @@ -473,8 +477,8 @@ static int suspend_node(struct pw_impl_node *this) static void clear_info(struct pw_impl_node *this) { - free(this->group); - free(this->link_group); + pw_free_strv(this->groups); + pw_free_strv(this->link_groups); free(this->name); free((char*)this->info.error); } @@ -964,20 +968,26 @@ static void check_properties(struct pw_impl_node *node) /* group defines what nodes are scheduled together */ str = pw_properties_get(node->properties, PW_KEY_NODE_GROUP); - if (!spa_streq(str, node->group)) { - pw_log_info("%p: group '%s'->'%s'", node, node->group, str); - free(node->group); - node->group = str ? strdup(str) : NULL; - node->freewheel = spa_streq(node->group, "pipewire.freewheel"); + if (!spa_streq(str, impl->group)) { + pw_log_info("%p: group '%s'->'%s'", node, impl->group, str); + free(impl->group); + impl->group = str ? strdup(str) : NULL; + pw_free_strv(node->groups); + node->groups = impl->group ? + pw_strv_parse(impl->group, strlen(impl->group), INT_MAX, NULL) : NULL; + node->freewheel = pw_strv_find(node->groups, "pipewire.freewheel") >= 0; recalc_reason = "group changed"; } /* link group defines what nodes are logically linked together */ str = pw_properties_get(node->properties, PW_KEY_NODE_LINK_GROUP); - if (!spa_streq(str, node->link_group)) { - pw_log_info("%p: link group '%s'->'%s'", node, node->link_group, str); - free(node->link_group); - node->link_group = str ? strdup(str) : NULL; + if (!spa_streq(str, impl->link_group)) { + pw_log_info("%p: link group '%s'->'%s'", node, impl->link_group, str); + free(impl->link_group); + impl->link_group = str ? strdup(str) : NULL; + pw_free_strv(node->link_groups); + node->link_groups = impl->link_group ? + pw_strv_parse(impl->link_group, strlen(impl->link_group), INT_MAX, NULL) : NULL; recalc_reason = "link group changed"; } @@ -2098,6 +2108,8 @@ void pw_impl_node_destroy(struct pw_impl_node *node) clear_info(node); spa_system_close(node->data_system, node->source.fd); + free(impl->group); + free(impl->link_group); free(impl); #ifdef HAVE_MALLOC_TRIM diff --git a/src/pipewire/keys.h b/src/pipewire/keys.h index 0b8a7737d..fe96f10f3 100644 --- a/src/pipewire/keys.h +++ b/src/pipewire/keys.h @@ -137,7 +137,8 @@ extern "C" { #define PW_KEY_NODE_SESSION "node.session" /**< the session id this node is part of */ #define PW_KEY_NODE_GROUP "node.group" /**< the group id this node is part of. Nodes * in the same group are always scheduled - * with the same driver. */ + * with the same driver. Can be an array of + * group names. */ #define PW_KEY_NODE_EXCLUSIVE "node.exclusive" /**< node wants exclusive access to resources */ #define PW_KEY_NODE_AUTOCONNECT "node.autoconnect" /**< node wants to be automatically connected * to a compatible node */ @@ -177,7 +178,8 @@ extern "C" { * on output/input/all ports when the value is * "out"/"in"/"true" respectively */ #define PW_KEY_NODE_LINK_GROUP "node.link-group" /**< the node is internally linked to - * nodes with the same link-group */ + * nodes with the same link-group. Can be an + * array of group names. */ #define PW_KEY_NODE_NETWORK "node.network" /**< the node is on a network */ #define PW_KEY_NODE_TRIGGER "node.trigger" /**< the node is not scheduled automatically * based on the dependencies in the graph diff --git a/src/pipewire/private.h b/src/pipewire/private.h index 56a528225..58b2b6085 100644 --- a/src/pipewire/private.h +++ b/src/pipewire/private.h @@ -643,8 +643,8 @@ struct pw_impl_node { char *name; /** for debug */ uint32_t priority_driver; /** priority for being driver */ - char *group; /** group to schedule this node in */ - char *link_group; /** group this node is linked to */ + char **groups; /** groups to schedule this node in */ + char **link_groups; /** groups this node is linked to */ uint64_t spa_flags; unsigned int registered:1;