From 91a3670610a8a7eab7436a7fec8539cedc9091c0 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Wed, 29 Nov 2017 16:58:17 +0100 Subject: [PATCH] node: make port for_each more powerful Make an int return from pw_node_for_each_port() so that we can return errors or early exit. Add pw_port_for_each_param() to iterate params. And use this to collect the formats. --- src/modules/module-autolink.c | 4 +- src/modules/module-jack/jack-node.c | 8 ++-- src/pipewire/node.c | 67 +++++++++++++---------------- src/pipewire/node.h | 13 +++--- src/pipewire/port.c | 27 ++++++++++++ src/pipewire/private.h | 9 ++++ 6 files changed, 81 insertions(+), 47 deletions(-) diff --git a/src/modules/module-autolink.c b/src/modules/module-autolink.c index 66be909de..38ba2959a 100644 --- a/src/modules/module-autolink.c +++ b/src/modules/module-autolink.c @@ -234,10 +234,10 @@ static void node_port_removed(void *data, struct pw_port *port) { } -static bool on_node_port_added(void *data, struct pw_port *port) +static int on_node_port_added(void *data, struct pw_port *port) { node_port_added(data, port); - return true; + return 0; } static void on_node_created(struct pw_node *node, struct node_info *info) diff --git a/src/modules/module-jack/jack-node.c b/src/modules/module-jack/jack-node.c index b565ff121..eba04e177 100644 --- a/src/modules/module-jack/jack-node.c +++ b/src/modules/module-jack/jack-node.c @@ -1067,16 +1067,16 @@ struct find_data { struct pw_jack_port *result; }; -static bool find_port(void *data, struct pw_port *port) +static int find_port(void *data, struct pw_port *port) { struct find_data *d = data; struct port_data *pd = pw_port_get_user_data(port); if (pd->port.port_id == d->port_id) { d->result = &pd->port; - return false; + return 1; } - return true; + return 0; } struct pw_jack_port * @@ -1085,7 +1085,7 @@ pw_jack_node_find_port(struct pw_jack_node *node, jack_port_id_t port_id) { struct find_data data = { port_id, }; - if (!pw_node_for_each_port(node->node, direction, find_port, &data)) + if (pw_node_for_each_port(node->node, direction, find_port, &data) == 1) return data.result; return NULL; } diff --git a/src/pipewire/node.c b/src/pipewire/node.c index db7f7fff2..99fa75f30 100644 --- a/src/pipewire/node.c +++ b/src/pipewire/node.c @@ -219,49 +219,43 @@ static int update_port_ids(struct pw_node *node) return 0; } -static int collect_params(struct pw_port *port, uint32_t param_id, struct spa_pod ***result) +struct param_array { + struct spa_pod **params; + uint32_t n_params; +}; + +static int add_param(void *data, struct spa_pod *param) { - int res; - uint8_t buffer[4096]; - struct spa_pod_builder b = { 0 }; - uint32_t state = 0; + struct param_array *arr = data; + uint32_t idx = arr->n_params++; - for (res = 0;; res++) { - struct spa_pod *fmt; - - spa_pod_builder_init(&b, buffer, sizeof(buffer)); - if (spa_node_port_enum_params(port->node->node, - port->direction, port->port_id, - param_id, &state, - NULL, &fmt, &b) <= 0) - break; - - *result = realloc(*result, sizeof(struct spa_pod *) * (res + 1)); - (*result)[res] = pw_spa_pod_copy(fmt); - } - return res; + arr->params = realloc(arr->params, sizeof(struct spa_pod *) * arr->n_params); + arr->params[idx] = pw_spa_pod_copy(param); + return 0; } static void update_info(struct pw_node *this) { struct pw_type *t = &this->core->type; + struct param_array params; + struct pw_port *port; - this->info.input_params = NULL; + params = (struct param_array) { NULL }; if (!spa_list_is_empty(&this->input_ports)) { - struct pw_port *port = spa_list_first(&this->input_ports, struct pw_port, link); - this->info.n_input_params = collect_params(port, - t->param.idEnumFormat, - &this->info.input_params); + port = spa_list_first(&this->input_ports, struct pw_port, link); + pw_port_for_each_param(port, t->param.idEnumFormat, NULL, add_param, ¶ms); } + this->info.input_params = params.params; + this->info.n_input_params = params.n_params; - this->info.output_params = NULL; + params = (struct param_array) { NULL }; if (!spa_list_is_empty(&this->output_ports)) { - struct pw_port *port = spa_list_first(&this->output_ports, struct pw_port, link); - this->info.n_output_params = collect_params(port, - t->param.idEnumFormat, - &this->info.output_params); + port = spa_list_first(&this->output_ports, struct pw_port, link); + pw_port_for_each_param(port, t->param.idEnumFormat, NULL, add_param, ¶ms); } + this->info.output_params = params.params; + this->info.n_output_params = params.n_params; } static void @@ -614,13 +608,14 @@ void pw_node_destroy(struct pw_node *node) free(impl); } -bool pw_node_for_each_port(struct pw_node *node, - enum pw_direction direction, - bool (*callback) (void *data, struct pw_port *port), - void *data) +int pw_node_for_each_port(struct pw_node *node, + enum pw_direction direction, + int (*callback) (void *data, struct pw_port *port), + void *data) { struct spa_list *ports; struct pw_port *p, *t; + int res; if (direction == PW_DIRECTION_INPUT) ports = &node->input_ports; @@ -628,9 +623,9 @@ bool pw_node_for_each_port(struct pw_node *node, ports = &node->output_ports; spa_list_for_each_safe(p, t, ports, link) - if (!callback(data, p)) - return false; - return true; + if ((res = callback(data, p)) != 0) + return res; + return 0; } struct pw_port * diff --git a/src/pipewire/node.h b/src/pipewire/node.h index 5523cc843..a9dd306d5 100644 --- a/src/pipewire/node.h +++ b/src/pipewire/node.h @@ -138,11 +138,14 @@ void pw_node_add_listener(struct pw_node *node, const struct pw_node_events *events, void *data); -/** iterate the ports in the given direction */ -bool pw_node_for_each_port(struct pw_node *node, - enum pw_direction direction, - bool (*callback) (void *data, struct pw_port *port), - void *data); +/** Iterate the ports in the given direction. The callback should return + * 0 to fetch the next item, any other value stops the iteration and returns + * the value. When all callbacks return 0, this function returns 0 when all + * items are iterated. */ +int pw_node_for_each_port(struct pw_node *node, + enum pw_direction direction, + int (*callback) (void *data, struct pw_port *port), + void *data); /** Find the port with direction and port_id or NULL when not found */ diff --git a/src/pipewire/port.c b/src/pipewire/port.c index 4d7ef490b..d7b9d1d8c 100644 --- a/src/pipewire/port.c +++ b/src/pipewire/port.c @@ -382,6 +382,33 @@ int pw_port_pause(struct pw_port *port) return 0; } +int pw_port_for_each_param(struct pw_port *port, + uint32_t param_id, + const struct spa_pod *filter, + int (*callback) (void *data, struct spa_pod *param), + void *data) +{ + int res; + uint8_t buffer[4096]; + struct spa_pod_builder b = { 0 }; + uint32_t state; + struct spa_pod *param; + + for (state = 0;;) { + spa_pod_builder_init(&b, buffer, sizeof(buffer)); + if ((res = spa_node_port_enum_params(port->node->node, + port->direction, + port->port_id, + param_id, &state, + filter, ¶m, &b)) <= 0) + break; + + if ((res = callback(data, param)) != 0) + break; + } + return res; +} + int pw_port_set_param(struct pw_port *port, uint32_t id, uint32_t flags, const struct spa_pod *param) { diff --git a/src/pipewire/private.h b/src/pipewire/private.h index 2f5fa74c8..6159491ba 100644 --- a/src/pipewire/private.h +++ b/src/pipewire/private.h @@ -429,6 +429,15 @@ bool pw_port_add(struct pw_port *port, struct pw_node *node); /** Destroy a port \memberof pw_port */ void pw_port_destroy(struct pw_port *port); +/** Iterate the params of the given port. The callback should return + * 1 to fetch the next item, 0 to stop iteration or <0 on error. + * The function returns 0 on success or the error returned by the callback. */ +int pw_port_for_each_param(struct pw_port *port, + uint32_t param_id, + const struct spa_pod *filter, + int (*callback) (void *data, struct spa_pod *param), + void *data); + /** Set a param on a port \memberof pw_port */ int pw_port_set_param(struct pw_port *port, uint32_t id, uint32_t flags, const struct spa_pod *param);