mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-05 13:30:02 -05:00
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:
parent
368dd51d04
commit
3a18da7cc3
1 changed files with 92 additions and 0 deletions
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue