node: add port and node params

Add a new struct spa_param_info that lists the available params on
a node/port and if they are readable/writable/updated. We can use
this to replace and improve the PARAM_List and also to notify
property change and updates.

Update elements and code to deal with this new param stuff. Add
port and node info to most elements and signal changes.

Use async enum_params in -inspect and use the param info to know
which ones to enumerate.

Use the port info to know what parameters to update in the
remote-node.
This commit is contained in:
Wim Taymans 2019-02-27 16:43:01 +01:00
parent 3d25adc598
commit 499dd3ff22
52 changed files with 1979 additions and 1461 deletions

View file

@ -379,7 +379,7 @@ static int impl_node_enum_params(struct spa_node *node, int seq,
result.index = result.next++;
if (result.index >= this->n_params)
return 0;
break;
param = this->params[result.index];
@ -390,10 +390,11 @@ static int impl_node_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) != 0)
continue;
pw_log_debug("client-node %p: %d param %u", this, seq, result.index);
if ((res = this->callbacks->result(this->callbacks_data, seq, 0, &result)) != 0)
return res;
if (++count != num)
if (++count == num)
break;
}
return 0;
@ -668,7 +669,7 @@ impl_node_port_enum_params(struct spa_node *node, int seq,
result.index = result.next++;
if (result.index >= port->n_params)
return 0;
break;
param = port->params[result.index];
@ -683,7 +684,7 @@ impl_node_port_enum_params(struct spa_node *node, int seq,
if ((res = this->callbacks->result(this->callbacks_data, seq, 0, &result)) != 0)
return res;
if (++count != num)
if (++count == num)
break;
}
return 0;

View file

@ -137,20 +137,6 @@ static int impl_node_enum_params(struct spa_node *node, int seq,
spa_pod_builder_init(&b, buffer, sizeof(buffer));
switch (id) {
case SPA_PARAM_List:
{
uint32_t list[] = { SPA_PARAM_Props,
SPA_PARAM_EnumFormat,
SPA_PARAM_Format };
if (result.index < SPA_N_ELEMENTS(list))
param = spa_pod_builder_add_object(&b,
SPA_TYPE_OBJECT_ParamList, id,
SPA_PARAM_LIST_id, SPA_POD_Id(list[result.index]));
else
return 0;
break;
}
case SPA_PARAM_Props:
if (impl->adapter == impl->cnode)
return 0;
@ -326,6 +312,26 @@ static const struct spa_node_callbacks adapter_node_callbacks = {
.result = adapter_result,
};
static void emit_node_info(struct node *this)
{
if (this->callbacks && this->callbacks->info) {
struct spa_node_info info;
struct spa_param_info params[4];
info = SPA_NODE_INFO_INIT();
info.max_input_ports = 0;
info.max_output_ports = 0;
info.change_mask |= SPA_NODE_CHANGE_MASK_PARAMS;
params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
params[1] = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_READWRITE);
params[2] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_READ);
params[3] = SPA_PARAM_INFO(SPA_PARAM_Profile, SPA_PARAM_INFO_WRITE);
info.params = params;
info.n_params = 4;
this->callbacks->info(this->callbacks_data, &info);
}
}
static int
impl_node_set_callbacks(struct spa_node *node,
const struct spa_node_callbacks *callbacks,
@ -342,6 +348,8 @@ impl_node_set_callbacks(struct spa_node *node,
this->callbacks = callbacks;
this->callbacks_data = data;
emit_node_info(this);
if (this->callbacks && impl->adapter && impl->adapter != impl->cnode)
spa_node_set_callbacks(impl->adapter, &adapter_node_callbacks, impl);

View file

@ -107,10 +107,18 @@ client_node_marshal_port_update(void *object,
SPA_POD_Pod(params[i]), NULL);
if (info) {
uint64_t change_mask = info->change_mask;
n_items = info->props ? info->props->n_items : 0;
change_mask &= SPA_PORT_CHANGE_MASK_FLAGS |
SPA_PORT_CHANGE_MASK_RATE |
SPA_PORT_CHANGE_MASK_PROPS |
SPA_PORT_CHANGE_MASK_PARAMS;
spa_pod_builder_push_struct(b, &f[1]);
spa_pod_builder_add(b,
SPA_POD_Long(change_mask),
SPA_POD_Int(info->flags),
SPA_POD_Int(info->rate),
SPA_POD_Int(n_items), NULL);
@ -119,7 +127,15 @@ client_node_marshal_port_update(void *object,
SPA_POD_String(info->props->items[i].key),
SPA_POD_String(info->props->items[i].value), NULL);
}
spa_pod_builder_add(b,
SPA_POD_Int(info->n_params), NULL);
for (i = 0; i < info->n_params; i++) {
spa_pod_builder_add(b,
SPA_POD_Id(info->params[i].id),
SPA_POD_Int(info->params[i].flags), NULL);
}
spa_pod_builder_pop(b, &f[1]);
} else {
spa_pod_builder_add(b,
SPA_POD_Pod(NULL), NULL);
@ -812,11 +828,17 @@ static int client_node_demarshal_port_update(void *object, void *data, size_t si
spa_pod_parser_pod(&p2, ipod);
if (spa_pod_parser_push_struct(&p2, &f2) < 0 ||
spa_pod_parser_get(&p2,
SPA_POD_Long(&info.change_mask),
SPA_POD_Int(&info.flags),
SPA_POD_Int(&info.rate),
SPA_POD_Int(&props.n_items), NULL) < 0)
return -EINVAL;
info.change_mask &= SPA_PORT_CHANGE_MASK_FLAGS |
SPA_PORT_CHANGE_MASK_RATE |
SPA_PORT_CHANGE_MASK_PROPS |
SPA_PORT_CHANGE_MASK_PARAMS;
if (props.n_items > 0) {
info.props = &props;
@ -828,6 +850,19 @@ static int client_node_demarshal_port_update(void *object, void *data, size_t si
return -EINVAL;
}
}
if (spa_pod_parser_get(&p2,
SPA_POD_Int(&info.n_params), NULL) < 0)
return -EINVAL;
if (info.n_params > 0) {
info.params = alloca(info.n_params * sizeof(struct spa_param_info));
for (i = 0; i < info.n_params; i++) {
if (spa_pod_parser_get(&p2,
SPA_POD_Id(&info.params[i].id),
SPA_POD_Int(&info.params[i].flags), NULL) < 0)
return -EINVAL;
}
}
}
pw_resource_do(resource, struct pw_client_node_proxy_methods, port_update, 0, direction,

View file

@ -406,27 +406,14 @@ static int add_port_update(struct pw_proxy *proxy, struct pw_port *port, uint32_
int res;
if (change_mask & PW_CLIENT_NODE_PORT_UPDATE_PARAMS) {
uint32_t idx1, idx2, id;
uint32_t i, idx2, id;
uint8_t buf[2048];
struct spa_pod_builder b = { 0 };
for (idx1 = 0;;) {
for (i = 0; i < port->info.n_params; i++) {
struct spa_pod *param;
spa_pod_builder_init(&b, buf, sizeof(buf));
if (spa_node_port_enum_params_sync(port->node->node,
port->direction, port->port_id,
SPA_PARAM_List, &idx1,
NULL, &param, &b,
port->node->pending) != 1)
break;
spa_pod_parse_object(param,
SPA_TYPE_OBJECT_ParamList, NULL,
SPA_PARAM_LIST_id, SPA_POD_Id(&id));
params = realloc(params, sizeof(struct spa_pod *) * (n_params + 1));
params[n_params++] = spa_pod_copy(param);
id = port->info.params[i].id;
for (idx2 = 0;;) {
spa_pod_builder_init(&b, buf, sizeof(buf));