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.
This commit is contained in:
Wim Taymans 2017-11-29 16:58:17 +01:00
parent 425073afd8
commit 91a3670610
6 changed files with 81 additions and 47 deletions

View file

@ -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)

View file

@ -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;
}

View file

@ -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, &params);
}
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, &params);
}
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 *

View file

@ -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 */

View file

@ -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, &param, &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)
{

View file

@ -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);