mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-03 09:01:54 -05:00
Support creating links for all ports from a node to another
This commit allows to specify the port-ids as "*" in create-link in order to connect all output ports from the first node to all input ports from the second node (in port-id order). For example, executing something like: `create-link my-virtual-device * alsa_output.usb-headset *`
This commit is contained in:
parent
da6ab064d2
commit
36060e375d
1 changed files with 108 additions and 20 deletions
|
|
@ -133,6 +133,11 @@ struct command {
|
|||
bool (*func) (struct data *data, const char *cmd, char *args, char **error);
|
||||
};
|
||||
|
||||
static struct spa_dict * global_props(struct global *global);
|
||||
static struct global * obj_global(struct remote_data *rd, uint32_t id);
|
||||
static int children_of(struct remote_data *rd, uint32_t parent_id,
|
||||
const char *child_type, uint32_t **children);
|
||||
|
||||
static int pw_split_ip(char *str, const char *delimiter, int max_tokens, char *tokens[])
|
||||
{
|
||||
const char *state = NULL;
|
||||
|
|
@ -1498,15 +1503,68 @@ static bool do_destroy(struct data *data, const char *cmd, char *args, char **er
|
|||
return true;
|
||||
}
|
||||
|
||||
static struct global *
|
||||
obj_global_port(struct remote_data *rd, struct global *global, const char *port_direction, const char *port_id)
|
||||
{
|
||||
struct global *global_port_found = NULL;
|
||||
uint32_t *ports = NULL;
|
||||
int port_count;
|
||||
|
||||
port_count = children_of(rd, global->id, PW_TYPE_INTERFACE_Port, &ports);
|
||||
|
||||
if (port_count <= 0)
|
||||
return NULL;
|
||||
|
||||
for (int i = 0; i < port_count; i++) {
|
||||
struct global *global_port = obj_global(rd, ports[i]);
|
||||
|
||||
if (!global_port)
|
||||
continue;
|
||||
|
||||
struct spa_dict *props_port = global_props(global_port);
|
||||
|
||||
if (spa_streq(spa_dict_lookup(props_port, "port.direction"), port_direction)
|
||||
&& spa_streq(spa_dict_lookup(props_port, "port.id"), port_id)) {
|
||||
global_port_found = global_port;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(ports);
|
||||
return global_port_found;
|
||||
}
|
||||
|
||||
static void create_link_with_properties(struct data *data, struct pw_properties *props)
|
||||
{
|
||||
struct remote_data *rd = data->current;
|
||||
uint32_t id;
|
||||
struct pw_proxy *proxy;
|
||||
struct proxy_data *pd;
|
||||
|
||||
proxy = (struct pw_proxy*)pw_core_create_object(rd->core,
|
||||
"link-factory",
|
||||
PW_TYPE_INTERFACE_Link,
|
||||
PW_VERSION_LINK,
|
||||
props ? &props->dict : NULL,
|
||||
sizeof(struct proxy_data));
|
||||
|
||||
pd = pw_proxy_get_user_data(proxy);
|
||||
pd->rd = rd;
|
||||
pd->proxy = proxy;
|
||||
pd->class = &link_class;
|
||||
pw_proxy_add_object_listener(proxy, &pd->object_listener, &link_events, pd);
|
||||
pw_proxy_add_listener(proxy, &pd->proxy_listener, &proxy_events, pd);
|
||||
|
||||
id = pw_map_insert_new(&data->vars, proxy);
|
||||
printf("%d = @proxy:%d\n", id, pw_proxy_get_id((struct pw_proxy*)proxy));
|
||||
}
|
||||
|
||||
static bool do_create_link(struct data *data, const char *cmd, char *args, char **error)
|
||||
{
|
||||
struct remote_data *rd = data->current;
|
||||
char *a[5];
|
||||
int n;
|
||||
uint32_t id;
|
||||
struct pw_proxy *proxy;
|
||||
struct pw_properties *props = NULL;
|
||||
struct proxy_data *pd;
|
||||
|
||||
n = pw_split_ip(args, WHITESPACE, 5, a);
|
||||
if (n < 4) {
|
||||
|
|
@ -1527,25 +1585,55 @@ static bool do_create_link(struct data *data, const char *cmd, char *args, char
|
|||
if (!spa_streq(a[3], "-"))
|
||||
pw_properties_set(props, PW_KEY_LINK_INPUT_PORT, a[3]);
|
||||
|
||||
proxy = (struct pw_proxy*)pw_core_create_object(rd->core,
|
||||
"link-factory",
|
||||
PW_TYPE_INTERFACE_Link,
|
||||
PW_VERSION_LINK,
|
||||
props ? &props->dict : NULL,
|
||||
sizeof(struct proxy_data));
|
||||
if (spa_streq(a[1], "*") && spa_streq(a[3], "*")) {
|
||||
struct global *global_out, *global_in;
|
||||
struct proxy_data *pd_out, *pd_in;
|
||||
uint32_t n_output_ports, n_input_ports;
|
||||
|
||||
global_out = find_global(rd, a[0]);
|
||||
if (global_out == NULL) {
|
||||
*error = spa_aprintf("%s: unknown global '%s'", cmd, a[0]);
|
||||
return false;
|
||||
}
|
||||
global_in = find_global(rd, a[2]);
|
||||
if (global_in == NULL) {
|
||||
*error = spa_aprintf("%s: unknown global '%s'", cmd, a[2]);
|
||||
return false;
|
||||
}
|
||||
|
||||
pd_out = pw_proxy_get_user_data(global_out->proxy);
|
||||
pd_in = pw_proxy_get_user_data(global_in->proxy);
|
||||
|
||||
n_output_ports = ((struct pw_node_info *)pd_out->info)->n_output_ports;
|
||||
n_input_ports = ((struct pw_node_info *)pd_in->info)->n_input_ports;
|
||||
|
||||
if (n_output_ports != n_input_ports) {
|
||||
*error = spa_aprintf("%s: Number of ports don't match (%u != %u)", cmd, n_output_ports, n_input_ports);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < n_output_ports; i++) {
|
||||
char port_id[4];
|
||||
struct global *global_port_out, *global_port_in;
|
||||
|
||||
snprintf(port_id, 4, "%d", i);
|
||||
|
||||
global_port_out = obj_global_port(rd, global_out, "out", port_id);
|
||||
global_port_in = obj_global_port(rd, global_in, "in", port_id);
|
||||
|
||||
if (!global_port_out || !global_port_in)
|
||||
continue;
|
||||
|
||||
pw_properties_setf(props, PW_KEY_LINK_OUTPUT_PORT, "%d", global_port_out->id);
|
||||
pw_properties_setf(props, PW_KEY_LINK_INPUT_PORT, "%d", global_port_in->id);
|
||||
|
||||
create_link_with_properties(data, props);
|
||||
}
|
||||
} else
|
||||
create_link_with_properties(data, props);
|
||||
|
||||
pw_properties_free(props);
|
||||
|
||||
pd = pw_proxy_get_user_data(proxy);
|
||||
pd->rd = rd;
|
||||
pd->proxy = proxy;
|
||||
pd->class = &link_class;
|
||||
pw_proxy_add_object_listener(proxy, &pd->object_listener, &link_events, pd);
|
||||
pw_proxy_add_listener(proxy, &pd->proxy_listener, &proxy_events, pd);
|
||||
|
||||
id = pw_map_insert_new(&data->vars, proxy);
|
||||
printf("%d = @proxy:%d\n", id, pw_proxy_get_id((struct pw_proxy*)proxy));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue