mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-03 09:01:54 -05:00
pw-link: refactor do_link_ports() to not run the event-loop
Make do_link_ports() only create proxies. Previously it ran the event loop once per attempted link to detect link creation errors. Rename it to create_link_proxies() to make things clear. Created proxies are stored into a list (data->link_targets). create_link_proxies() returns the number of link proxies created. This can be zero when the two matching nodes have zero ports. Refactor main() to use create_link_proxies(), ask for a sync then run the event loop. It will stop on sync done, and we will have received all potential link proxy errors. Cleanup all proxies and listeners at the end of main().
This commit is contained in:
parent
e8d104f7bc
commit
54662ad209
1 changed files with 75 additions and 54 deletions
|
|
@ -29,6 +29,13 @@ struct object {
|
||||||
uint32_t extra[2];
|
uint32_t extra[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct target_link {
|
||||||
|
struct spa_list link;
|
||||||
|
struct pw_proxy *proxy;
|
||||||
|
struct spa_hook listener;
|
||||||
|
int result;
|
||||||
|
};
|
||||||
|
|
||||||
struct data {
|
struct data {
|
||||||
struct pw_main_loop *loop;
|
struct pw_main_loop *loop;
|
||||||
|
|
||||||
|
|
@ -56,6 +63,7 @@ struct data {
|
||||||
struct spa_hook registry_listener;
|
struct spa_hook registry_listener;
|
||||||
|
|
||||||
struct spa_list objects;
|
struct spa_list objects;
|
||||||
|
struct spa_list target_links;
|
||||||
|
|
||||||
int sync;
|
int sync;
|
||||||
int link_res;
|
int link_res;
|
||||||
|
|
@ -70,8 +78,8 @@ struct data {
|
||||||
|
|
||||||
static void link_proxy_error(void *data, int seq, int res, const char *message)
|
static void link_proxy_error(void *data, int seq, int res, const char *message)
|
||||||
{
|
{
|
||||||
struct data *d = data;
|
struct target_link *tl = data;
|
||||||
d->link_res = res;
|
tl->result = res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct pw_proxy_events link_proxy_events = {
|
static const struct pw_proxy_events link_proxy_events = {
|
||||||
|
|
@ -84,34 +92,6 @@ static void core_sync(struct data *data)
|
||||||
data->sync = pw_core_sync(data->core, PW_ID_CORE, data->sync);
|
data->sync = pw_core_sync(data->core, PW_ID_CORE, data->sync);
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|
||||||
PW_VERSION_LINK,
|
|
||||||
&data->props->dict, 0);
|
|
||||||
if (proxy == NULL)
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
spa_zero(listener);
|
|
||||||
pw_proxy_add_listener(proxy, &listener, &link_proxy_events, data);
|
|
||||||
|
|
||||||
core_sync(data);
|
|
||||||
pw_main_loop_run(data->loop);
|
|
||||||
|
|
||||||
spa_hook_remove(&listener);
|
|
||||||
|
|
||||||
pw_proxy_destroy(proxy);
|
|
||||||
|
|
||||||
return data->link_res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct object *find_object(struct data *data, uint32_t type, uint32_t id)
|
static struct object *find_object(struct data *data, uint32_t type, uint32_t id)
|
||||||
{
|
{
|
||||||
struct object *o;
|
struct object *o;
|
||||||
|
|
@ -338,7 +318,34 @@ static void do_list(struct data *data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_link_ports(struct data *data)
|
static int create_link_target(struct data *data)
|
||||||
|
{
|
||||||
|
struct target_link *tl = calloc(1, sizeof(*tl));
|
||||||
|
if (!tl)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
tl->proxy = pw_core_create_object(data->core,
|
||||||
|
"link-factory", PW_TYPE_INTERFACE_Link,
|
||||||
|
PW_VERSION_LINK, &data->props->dict, 0);
|
||||||
|
if (tl->proxy == NULL)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
pw_proxy_add_listener(tl->proxy, &tl->listener, &link_proxy_events, tl);
|
||||||
|
spa_list_append(&data->target_links, &tl->link);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* create_link_proxies() looks at the current objects and tries to find the
|
||||||
|
* matching output and input nodes (multiple links) or the matching output and
|
||||||
|
* input ports.
|
||||||
|
*
|
||||||
|
* If successful, it fills data->target_links with proxies for all links and
|
||||||
|
* returns the number of links. This can be zero (two nodes with no ports). It
|
||||||
|
* might return (negative) errors. -ENOENT means no matching nodes or ports
|
||||||
|
* were found.
|
||||||
|
*/
|
||||||
|
static int create_link_proxies(struct data *data)
|
||||||
{
|
{
|
||||||
uint32_t in_port = 0, out_port = 0;
|
uint32_t in_port = 0, out_port = 0;
|
||||||
struct object *n, *p;
|
struct object *n, *p;
|
||||||
|
|
@ -372,9 +379,8 @@ static int do_link_ports(struct data *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_node && out_node) {
|
if (in_node && out_node) {
|
||||||
int i, ret;
|
int i;
|
||||||
char port_id[32];
|
char port_id[32];
|
||||||
bool all_links_exist = true;
|
|
||||||
|
|
||||||
for (i=0;; i++) {
|
for (i=0;; i++) {
|
||||||
snprintf(port_id, sizeof(port_id), "%d", i);
|
snprintf(port_id, sizeof(port_id), "%d", i);
|
||||||
|
|
@ -382,27 +388,17 @@ static int do_link_ports(struct data *data)
|
||||||
struct object *port_out = find_node_port(data, out_node, PW_DIRECTION_OUTPUT, port_id);
|
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);
|
struct object *port_in = find_node_port(data, in_node, PW_DIRECTION_INPUT, port_id);
|
||||||
|
|
||||||
if (!port_out && !port_in) {
|
if (!port_out || !port_in)
|
||||||
fprintf(stderr, "Input & output port do not exist\n");
|
return i;
|
||||||
goto no_port;
|
|
||||||
} else if (!port_in) {
|
|
||||||
fprintf(stderr, "Input port does not exist\n");
|
|
||||||
goto no_port;
|
|
||||||
} else if (!port_out) {
|
|
||||||
fprintf(stderr, "Output port does not exist\n");
|
|
||||||
goto no_port;
|
|
||||||
}
|
|
||||||
|
|
||||||
pw_properties_setf(data->props, PW_KEY_LINK_OUTPUT_PORT, "%u", port_out->id);
|
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);
|
pw_properties_setf(data->props, PW_KEY_LINK_INPUT_PORT, "%u", port_in->id);
|
||||||
|
|
||||||
if ((ret = create_link(data)) < 0 && ret != -EEXIST)
|
int ret = create_link_target(data);
|
||||||
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (ret >= 0)
|
|
||||||
all_links_exist = false;
|
|
||||||
}
|
}
|
||||||
return (all_links_exist ? -EEXIST : 0);
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_port == 0 || out_port == 0)
|
if (in_port == 0 || out_port == 0)
|
||||||
|
|
@ -411,10 +407,12 @@ static int do_link_ports(struct data *data)
|
||||||
pw_properties_setf(data->props, PW_KEY_LINK_OUTPUT_PORT, "%u", out_port);
|
pw_properties_setf(data->props, PW_KEY_LINK_OUTPUT_PORT, "%u", out_port);
|
||||||
pw_properties_setf(data->props, PW_KEY_LINK_INPUT_PORT, "%u", in_port);
|
pw_properties_setf(data->props, PW_KEY_LINK_INPUT_PORT, "%u", in_port);
|
||||||
|
|
||||||
return create_link(data);
|
/*
|
||||||
|
* create_link_target() returns zero on success. We return the number of
|
||||||
no_port:
|
* links on success, meaning 1.
|
||||||
return -ENOENT;
|
*/
|
||||||
|
int ret = create_link_target(data);
|
||||||
|
return !ret ? 1 : ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_unlink_ports(struct data *data)
|
static int do_unlink_ports(struct data *data)
|
||||||
|
|
@ -718,6 +716,7 @@ int main(int argc, char *argv[])
|
||||||
setlocale(LC_ALL, "");
|
setlocale(LC_ALL, "");
|
||||||
pw_init(&argc, &argv);
|
pw_init(&argc, &argv);
|
||||||
spa_list_init(&data.objects);
|
spa_list_init(&data.objects);
|
||||||
|
spa_list_init(&data.target_links);
|
||||||
|
|
||||||
setlinebuf(stdout);
|
setlinebuf(stdout);
|
||||||
|
|
||||||
|
|
@ -867,10 +866,26 @@ int main(int argc, char *argv[])
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ((res = do_link_ports(&data)) < 0) {
|
int nb_links = create_link_proxies(&data);
|
||||||
fprintf(stderr, "failed to link ports: %s\n", spa_strerror(res));
|
if (nb_links < 0) {
|
||||||
|
fprintf(stderr, "failed to link ports: %s\n", spa_strerror(nb_links));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nb_links > 0) {
|
||||||
|
core_sync(&data);
|
||||||
|
pw_main_loop_run(data.loop);
|
||||||
|
|
||||||
|
struct target_link *tl;
|
||||||
|
spa_list_for_each(tl, &data.target_links, link) {
|
||||||
|
if (tl->result) {
|
||||||
|
fprintf(stderr, "failed to link ports: %s\n",
|
||||||
|
spa_strerror(tl->result));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.opt_mode & MODE_MONITOR) {
|
if (data.opt_mode & MODE_MONITOR) {
|
||||||
|
|
@ -879,6 +894,12 @@ int main(int argc, char *argv[])
|
||||||
data.monitoring = false;
|
data.monitoring = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct target_link *tl;
|
||||||
|
spa_list_for_each(tl, &data.target_links, link) {
|
||||||
|
spa_hook_remove(&tl->listener);
|
||||||
|
pw_proxy_destroy(tl->proxy);
|
||||||
|
}
|
||||||
|
|
||||||
if (data.out_regex)
|
if (data.out_regex)
|
||||||
regfree(data.out_regex);
|
regfree(data.out_regex);
|
||||||
if (data.in_regex)
|
if (data.in_regex)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue