impl-node: support multiple link-group and group

Support an array for the node.group and node.link-group properties.
This makes it possible to make a node member of multiple groups and
link-groups.

See #3612
This commit is contained in:
Wim Taymans 2023-10-31 10:58:49 +01:00
parent 72fa74ff57
commit 98d44d9757
4 changed files with 36 additions and 22 deletions

View file

@ -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<<direction))
continue;
if (!spa_streq(t->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);
}

View file

@ -9,6 +9,7 @@
#include <errno.h>
#include <time.h>
#include <malloc.h>
#include <limits.h>
#include <spa/support/system.h>
#include <spa/pod/parser.h>
@ -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

View file

@ -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

View file

@ -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;