pw-link: Support creating links for all ports from a node to another

This allows to call pw-link with output and input nodes instead of
ports and pw-link will connect all output ports from the first node
to all input ports in the second node by port-id.

Note that the number of ports in each node isn't checked before
starting, so the ports will be connected until there's no matching
port to connect (i.e. if the output node has 2 output ports and
the input node has 5 ports, then only the first two ports will be
connected).
This commit is contained in:
Antonio Larrosa 2022-04-22 12:51:28 +02:00 committed by Wim Taymans
parent 368dd51d04
commit 3a18da7cc3

View file

@ -109,6 +109,8 @@ static int create_link(struct data *data)
struct pw_proxy *proxy;
struct spa_hook listener;
data->link_res = 0;
proxy = pw_core_create_object(data->core,
"link-factory",
PW_TYPE_INTERFACE_Link,
@ -139,6 +141,47 @@ static struct object *find_object(struct data *data, uint32_t type, uint32_t id)
return NULL;
}
static struct object *find_node_port(struct data *data, struct object *node, enum pw_direction direction, const char *port_id)
{
struct object *o;
spa_list_for_each(o, &data->objects, link) {
const char *o_port_id;
if (o->type != OBJECT_PORT)
continue;
if (o->extra[1] != node->id)
continue;
if (o->extra[0] != direction)
continue;
if ((o_port_id = pw_properties_get(o->props, PW_KEY_PORT_ID)) == NULL)
continue;
if (spa_streq(o_port_id, port_id))
return o;
}
return NULL;
}
static char *node_name(char *buffer, int size, struct object *n)
{
const char *name;
buffer[0] = '\0';
if ((name = pw_properties_get(n->props, PW_KEY_NODE_NAME)) == NULL)
return buffer;
snprintf(buffer, size, "%s", name);
return buffer;
}
static char *node_path(char *buffer, int size, struct object *n)
{
const char *name;
buffer[0] = '\0';
if ((name = pw_properties_get(n->props, PW_KEY_OBJECT_PATH)) == NULL)
return buffer;
snprintf(buffer, size, "%s", name);
return buffer;
}
static char *port_name(char *buffer, int size, struct object *n, struct object *p)
{
const char *name1, *name2;
@ -241,6 +284,19 @@ static void do_list_port_links(struct data *data, struct object *node, struct ob
}
}
static int node_matches(struct data *data, struct object *n, const char *name)
{
char buffer[1024];
uint32_t id = atoi(name);
if (n->id == id)
return 1;
if (spa_streq(node_name(buffer, sizeof(buffer), n), name))
return 1;
if (spa_streq(node_path(buffer, sizeof(buffer), n), name))
return 1;
return 0;
}
static int port_matches(struct data *data, struct object *n, struct object *p, const char *name)
{
char buffer[1024];
@ -304,11 +360,20 @@ static int do_link_ports(struct data *data)
{
uint32_t in_port = 0, out_port = 0;
struct object *n, *p;
struct object *in_node = NULL, *out_node = NULL;
spa_list_for_each(n, &data->objects, link) {
if (n->type != OBJECT_NODE)
continue;
if (out_node == NULL && node_matches(data, n, data->opt_output)) {
out_node = n;
continue;
} else if (in_node == NULL && node_matches(data, n, data->opt_input)) {
in_node = n;
continue;
}
spa_list_for_each(p, &data->objects, link) {
if (p->type != OBJECT_PORT)
continue;
@ -323,6 +388,33 @@ static int do_link_ports(struct data *data)
in_port = p->id;
}
}
if (in_node && out_node) {
int i, ret;
char port_id[5];
bool all_links_exist = true;
for (i=0;; i++) {
snprintf(port_id, sizeof(port_id), "%d", i);
struct object *port_out = find_node_port(data, out_node, PW_DIRECTION_OUTPUT, port_id);
struct object *port_in = find_node_port(data, in_node, PW_DIRECTION_INPUT, port_id);
if (!port_out || !port_in)
break;
pw_properties_setf(data->props, PW_KEY_LINK_OUTPUT_PORT, "%u", port_out->id);
pw_properties_setf(data->props, PW_KEY_LINK_INPUT_PORT, "%u", port_in->id);
if ((ret = create_link(data)) < 0 && ret != -EEXIST)
return ret;
if (ret >= 0)
all_links_exist = false;
}
return (all_links_exist ? -EEXIST : 0);
}
if (in_port == 0 || out_port == 0)
return -ENOENT;