mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-04 13:30:12 -05:00
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:
parent
425073afd8
commit
91a3670610
6 changed files with 81 additions and 47 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
int pw_node_for_each_port(struct pw_node *node,
|
||||
enum pw_direction direction,
|
||||
bool (*callback) (void *data, struct pw_port *port),
|
||||
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 *
|
||||
|
|
|
|||
|
|
@ -138,10 +138,13 @@ 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,
|
||||
/** 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,
|
||||
bool (*callback) (void *data, struct pw_port *port),
|
||||
int (*callback) (void *data, struct pw_port *port),
|
||||
void *data);
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue