client-node: pass spa_node_info along

Pass the complete spa_node_info to update node information. Remove
the redundant max/min port info.
Update the remote node based on port and node update events.
This commit is contained in:
Wim Taymans 2019-03-04 12:30:45 +01:00
parent a9b58618b2
commit ed988788fd
9 changed files with 205 additions and 90 deletions

@ -1 +1 @@
Subproject commit 6ca80e4ec7abb48ef19423b405c0add9f98f93a0
Subproject commit 53693d1e328c2dde8fc167579f077e2e876c78d4

View file

@ -70,16 +70,12 @@ struct pw_client_node_proxy_methods {
* \param params new params
*/
int (*update) (void *object,
#define PW_CLIENT_NODE_UPDATE_MAX_INPUTS (1 << 0)
#define PW_CLIENT_NODE_UPDATE_MAX_OUTPUTS (1 << 1)
#define PW_CLIENT_NODE_UPDATE_PARAMS (1 << 2)
#define PW_CLIENT_NODE_UPDATE_PROPS (1 << 3)
#define PW_CLIENT_NODE_UPDATE_PARAMS (1 << 0)
#define PW_CLIENT_NODE_UPDATE_INFO (1 << 1)
uint32_t change_mask,
uint32_t max_input_ports,
uint32_t max_output_ports,
uint32_t n_params,
const struct spa_pod **params,
const struct spa_dict *props);
const struct spa_node_info *info);
/**
* Update a node port
@ -115,16 +111,13 @@ struct pw_client_node_proxy_methods {
static inline int
pw_client_node_proxy_update(struct pw_client_node_proxy *p,
uint32_t change_mask,
uint32_t max_input_ports,
uint32_t max_output_ports,
uint32_t n_params,
const struct spa_pod **params,
const struct spa_dict *props)
const struct spa_node_info *info)
{
return pw_proxy_do((struct pw_proxy*)p, struct pw_client_node_proxy_methods, update, change_mask,
max_input_ports,
max_output_ports,
n_params, params, props);
return pw_proxy_do((struct pw_proxy*)p, struct pw_client_node_proxy_methods,
update,
change_mask, n_params, params, info);
}
static inline int
@ -136,12 +129,9 @@ pw_client_node_proxy_port_update(struct pw_client_node_proxy *p,
const struct spa_pod **params,
const struct spa_port_info *info)
{
return pw_proxy_do((struct pw_proxy*)p, struct pw_client_node_proxy_methods, port_update, direction,
port_id,
change_mask,
n_params,
params,
info);
return pw_proxy_do((struct pw_proxy*)p, struct pw_client_node_proxy_methods,
port_update, direction, port_id, change_mask,
n_params, params, info);
}
static inline int

View file

@ -136,9 +136,7 @@ struct node {
struct spa_source data_source;
int writefd;
uint32_t max_inputs;
uint32_t n_inputs;
uint32_t max_outputs;
uint32_t n_outputs;
struct port *in_ports[MAX_INPUTS];
struct port *out_ports[MAX_OUTPUTS];
@ -583,6 +581,7 @@ do_update_port(struct node *this,
port->properties = pw_properties_new_dict(info->props);
port->info.props = &port->properties->dict;
}
spa_node_emit_port_info(&this->hooks, port->direction, port->id, info);
}
}
}
@ -995,19 +994,13 @@ static int impl_node_process(struct spa_node *node)
static int
client_node_update(void *data,
uint32_t change_mask,
uint32_t max_input_ports,
uint32_t max_output_ports,
uint32_t n_params,
const struct spa_pod **params,
const struct spa_dict *props)
const struct spa_node_info *info)
{
struct impl *impl = data;
struct node *this = &impl->node;
if (change_mask & PW_CLIENT_NODE_UPDATE_MAX_INPUTS)
this->max_inputs = max_input_ports;
if (change_mask & PW_CLIENT_NODE_UPDATE_MAX_OUTPUTS)
this->max_outputs = max_output_ports;
if (change_mask & PW_CLIENT_NODE_UPDATE_PARAMS) {
uint32_t i;
spa_log_debug(this->log, "node %p: update %d params", this, n_params);
@ -1020,11 +1013,10 @@ client_node_update(void *data,
for (i = 0; i < this->n_params; i++)
this->params[i] = params[i] ? spa_pod_copy(params[i]) : NULL;
}
if (change_mask & PW_CLIENT_NODE_UPDATE_PROPS) {
pw_node_update_properties(impl->this.node, props);
if (change_mask & PW_CLIENT_NODE_UPDATE_INFO) {
spa_node_emit_info(&this->hooks, info);
}
spa_log_debug(this->log, "node %p: got node update max_in %u, max_out %u", this,
this->max_inputs, this->max_outputs);
spa_log_debug(this->log, "node %p: got node update", this);
return 0;
}
@ -1058,6 +1050,8 @@ client_node_port_update(void *data,
if (port == NULL) {
target = &this->dummy;
spa_zero(this->dummy);
target->direction = direction;
target->id = port_id;
} else
target = port;
@ -1066,9 +1060,6 @@ client_node_port_update(void *data,
change_mask,
n_params, params,
info);
if (info && (change_mask & PW_CLIENT_NODE_PORT_UPDATE_INFO))
spa_node_emit_port_info(&this->hooks, direction, port_id, info);
}
return 0;
}

View file

@ -50,31 +50,60 @@ static void push_dict(struct spa_pod_builder *b, const struct spa_dict *dict)
static int
client_node_marshal_update(void *object,
uint32_t change_mask,
uint32_t max_input_ports,
uint32_t max_output_ports,
uint32_t n_params,
const struct spa_pod **params,
const struct spa_dict *props)
const struct spa_node_info *info)
{
struct pw_proxy *proxy = object;
struct spa_pod_builder *b;
struct spa_pod_frame f;
uint32_t i;
struct spa_pod_frame f[2];
uint32_t i, n_items;
b = pw_protocol_native_begin_proxy(proxy, PW_CLIENT_NODE_PROXY_METHOD_UPDATE, NULL);
spa_pod_builder_push_struct(b, &f);
spa_pod_builder_push_struct(b, &f[0]);
spa_pod_builder_add(b,
SPA_POD_Int(change_mask),
SPA_POD_Int(max_input_ports),
SPA_POD_Int(max_output_ports),
SPA_POD_Int(n_params), NULL);
for (i = 0; i < n_params; i++)
spa_pod_builder_add(b, SPA_POD_Pod(params[i]), NULL);
push_dict(b, props);
spa_pod_builder_pop(b, &f);
if (info) {
uint64_t change_mask = info->change_mask;
n_items = info->props ? info->props->n_items : 0;
change_mask &= SPA_NODE_CHANGE_MASK_FLAGS |
SPA_NODE_CHANGE_MASK_PROPS |
SPA_NODE_CHANGE_MASK_PARAMS;
spa_pod_builder_push_struct(b, &f[1]);
spa_pod_builder_add(b,
SPA_POD_Int(info->max_input_ports),
SPA_POD_Int(info->max_output_ports),
SPA_POD_Long(change_mask),
SPA_POD_Long(info->flags),
SPA_POD_Int(n_items), NULL);
for (i = 0; i < n_items; i++) {
spa_pod_builder_add(b,
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);
}
spa_pod_builder_pop(b, &f[0]);
return pw_protocol_native_end_proxy(proxy, b);
}
@ -119,8 +148,9 @@ client_node_marshal_port_update(void *object,
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_Long(info->flags),
SPA_POD_Int(info->rate.num),
SPA_POD_Int(info->rate.denom),
SPA_POD_Int(n_items), NULL);
for (i = 0; i < n_items; i++) {
spa_pod_builder_add(b,
@ -745,8 +775,10 @@ static int client_node_demarshal_update(void *object, void *data, size_t size)
struct pw_resource *resource = object;
struct spa_pod_parser prs;
struct spa_pod_frame f[2];
uint32_t change_mask, max_input_ports, max_output_ports, n_params;
uint32_t change_mask, n_params;
const struct spa_pod **params;
struct spa_node_info info = SPA_NODE_INFO_INIT(), *infop = NULL;
struct spa_pod *ipod;
struct spa_dict props;
uint32_t i;
@ -754,8 +786,6 @@ static int client_node_demarshal_update(void *object, void *data, size_t size)
if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
spa_pod_parser_get(&prs,
SPA_POD_Int(&change_mask),
SPA_POD_Int(&max_input_ports),
SPA_POD_Int(&max_output_ports),
SPA_POD_Int(&n_params), NULL) < 0)
return -EINVAL;
@ -765,28 +795,58 @@ static int client_node_demarshal_update(void *object, void *data, size_t size)
SPA_POD_PodObject(&params[i]), NULL) < 0)
return -EINVAL;
if (spa_pod_parser_push_struct(&prs, &f[1]) < 0)
return -EINVAL;
if (spa_pod_parser_get(&prs,
SPA_POD_Int(&props.n_items), NULL) < 0)
SPA_POD_PodStruct(&ipod), NULL) < 0)
return -EINVAL;
props.items = alloca(props.n_items * sizeof(struct spa_dict_item));
for (i = 0; i < props.n_items; i++) {
if (spa_pod_parser_get(&prs,
SPA_POD_String(&props.items[i].key),
SPA_POD_String(&props.items[i].value),
NULL) < 0)
if (ipod) {
struct spa_pod_parser p2;
struct spa_pod_frame f2;
infop = &info;
spa_pod_parser_pod(&p2, ipod);
if (spa_pod_parser_push_struct(&p2, &f2) < 0 ||
spa_pod_parser_get(&p2,
SPA_POD_Int(&info.max_input_ports),
SPA_POD_Int(&info.max_output_ports),
SPA_POD_Long(&info.change_mask),
SPA_POD_Long(&info.flags),
SPA_POD_Int(&props.n_items), NULL) < 0)
return -EINVAL;
info.change_mask &= SPA_NODE_CHANGE_MASK_FLAGS |
SPA_NODE_CHANGE_MASK_PROPS |
SPA_NODE_CHANGE_MASK_PARAMS;
if (props.n_items > 0) {
info.props = &props;
props.items = alloca(props.n_items * sizeof(struct spa_dict_item));
for (i = 0; i < props.n_items; i++) {
if (spa_pod_parser_get(&p2,
SPA_POD_String(&props.items[i].key),
SPA_POD_String(&props.items[i].value), NULL) < 0)
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, update, 0, change_mask,
max_input_ports,
max_output_ports,
n_params,
params,
props.n_items > 0 ?
&props : NULL);
params, infop);
return 0;
}
@ -829,8 +889,9 @@ static int client_node_demarshal_port_update(void *object, void *data, size_t si
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_Long(&info.flags),
SPA_POD_Int(&info.rate.num),
SPA_POD_Int(&info.rate.denom),
SPA_POD_Int(&props.n_items), NULL) < 0)
return -EINVAL;

View file

@ -397,6 +397,64 @@ static int client_node_transport(void *object, uint32_t node_id,
return 0;
}
static int add_node_update(struct pw_proxy *proxy, uint32_t change_mask)
{
struct node_data *data = proxy->user_data;
struct pw_node *node = data->node;
struct spa_node_info ni = SPA_NODE_INFO_INIT();
uint32_t n_params = 0;
struct spa_pod **params = NULL;
int res;
if (change_mask & PW_CLIENT_NODE_UPDATE_PARAMS) {
uint32_t i, idx, id;
uint8_t buf[2048];
struct spa_pod_builder b = { 0 };
for (i = 0; i < node->info.n_params; i++) {
struct spa_pod *param;
id = node->info.params[i].id;
for (idx = 0;;) {
spa_pod_builder_init(&b, buf, sizeof(buf));
if (spa_node_enum_params_sync(node->node,
id, &idx,
NULL, &param, &b) != 1)
break;
params = realloc(params, sizeof(struct spa_pod *) * (n_params + 1));
params[n_params++] = spa_pod_copy(param);
}
}
}
if (change_mask & PW_CLIENT_NODE_UPDATE_INFO) {
ni.max_input_ports = node->info.max_input_ports;
ni.max_output_ports = node->info.max_output_ports;
ni.change_mask = SPA_NODE_CHANGE_MASK_FLAGS |
SPA_NODE_CHANGE_MASK_PROPS |
SPA_NODE_CHANGE_MASK_PARAMS;
ni.flags = 0;
ni.props = node->info.props;
ni.params = node->info.params;
ni.n_params = node->info.n_params;
}
res = pw_client_node_proxy_update(data->node_proxy,
change_mask,
n_params,
(const struct spa_pod **)params,
&ni);
if (params) {
while (n_params > 0)
free(params[--n_params]);
free(params);
}
return res;
}
static int add_port_update(struct pw_proxy *proxy, struct pw_port *port, uint32_t change_mask)
{
struct node_data *data = proxy->user_data;
@ -406,7 +464,7 @@ 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 i, idx2, id;
uint32_t i, idx, id;
uint8_t buf[2048];
struct spa_pod_builder b = { 0 };
@ -415,11 +473,11 @@ static int add_port_update(struct pw_proxy *proxy, struct pw_port *port, uint32_
id = port->info.params[i].id;
for (idx2 = 0;;) {
for (idx = 0;;) {
spa_pod_builder_init(&b, buf, sizeof(buf));
if (spa_node_port_enum_params_sync(port->node->node,
port->direction, port->port_id,
id, &idx2,
id, &idx,
NULL, &param, &b) != 1)
break;
@ -649,11 +707,6 @@ client_node_port_set_param(void *object,
goto done;
}
if ((res = add_port_update(proxy, port,
PW_CLIENT_NODE_PORT_UPDATE_PARAMS |
PW_CLIENT_NODE_PORT_UPDATE_INFO)) < 0)
pw_proxy_error(proxy, res, "can't add port update");
done:
return res;
}
@ -967,13 +1020,8 @@ static void do_node_init(struct pw_proxy *proxy)
struct pw_port *port;
pw_log_debug("%p: init", data);
pw_client_node_proxy_update(data->node_proxy,
PW_CLIENT_NODE_UPDATE_MAX_INPUTS |
PW_CLIENT_NODE_UPDATE_MAX_OUTPUTS |
PW_CLIENT_NODE_UPDATE_PARAMS,
data->node->info.max_input_ports,
data->node->info.max_output_ports,
0, NULL, NULL);
add_node_update(proxy, PW_CLIENT_NODE_UPDATE_PARAMS |
PW_CLIENT_NODE_UPDATE_INFO);
spa_list_for_each(port, &data->node->input_ports, link) {
add_port_update(proxy, port,
@ -1034,14 +1082,30 @@ static void node_info_changed(void *data, const struct pw_node_info *info)
pw_log_debug("info changed %p", d);
if (info->change_mask & PW_NODE_CHANGE_MASK_PROPS) {
change_mask |= PW_CLIENT_NODE_UPDATE_PROPS;
if (info->change_mask & PW_NODE_CHANGE_MASK_PROPS)
change_mask |= PW_CLIENT_NODE_UPDATE_INFO;
if (info->change_mask & PW_NODE_CHANGE_MASK_PARAMS) {
change_mask |= PW_CLIENT_NODE_UPDATE_PARAMS;
change_mask |= PW_CLIENT_NODE_UPDATE_INFO;
}
pw_client_node_proxy_update(d->node_proxy,
change_mask,
0, 0,
0, NULL,
info->props);
add_node_update((struct pw_proxy*)d->node_proxy, change_mask);
}
static void node_port_info_changed(void *data, struct pw_port *port,
const struct pw_port_info *info)
{
struct node_data *d = data;
uint32_t change_mask = 0;
pw_log_debug("info changed %p", d);
if (info->change_mask & PW_PORT_CHANGE_MASK_PROPS)
change_mask |= PW_CLIENT_NODE_PORT_UPDATE_INFO;
if (info->change_mask & PW_PORT_CHANGE_MASK_PARAMS) {
change_mask |= PW_CLIENT_NODE_PORT_UPDATE_PARAMS;
change_mask |= PW_CLIENT_NODE_PORT_UPDATE_INFO;
}
add_port_update((struct pw_proxy*)d->node_proxy, port, change_mask);
}
static void node_active_changed(void *data, bool active)
@ -1056,6 +1120,7 @@ static const struct pw_node_events node_events = {
PW_VERSION_NODE_EVENTS,
.destroy = node_destroy,
.info_changed = node_info_changed,
.port_info_changed = node_port_info_changed,
.active_changed = node_active_changed,
};

View file

@ -72,6 +72,9 @@ struct pw_node_events {
/** the node info changed */
void (*info_changed) (void *data, const struct pw_node_info *info);
/** a port on the node changed info */
void (*port_info_changed) (void *data, struct pw_port *port,
const struct pw_port_info *info);
/** the node active state changed */
void (*active_changed) (void *data, bool active);
/** the node enabled state changed */

View file

@ -87,6 +87,8 @@ static void emit_info_changed(struct pw_port *port)
return;
pw_port_emit_info_changed(port, &port->info);
if (port->node)
pw_node_emit_port_info_changed(port->node, port, &port->info);
if (port->global)
spa_list_for_each(resource, &port->global->resource_list, link)

View file

@ -316,6 +316,7 @@ struct pw_node_activation {
#define pw_node_emit_port_added(n,p) pw_node_emit(n, port_added, 0, p)
#define pw_node_emit_port_removed(n,p) pw_node_emit(n, port_removed, 0, p)
#define pw_node_emit_info_changed(n,i) pw_node_emit(n, info_changed, 0, i)
#define pw_node_emit_port_info_changed(n,p,i) pw_node_emit(n, port_info_changed, 0, p, i)
#define pw_node_emit_active_changed(n,a) pw_node_emit(n, active_changed, 0, a)
#define pw_node_emit_enabled_changed(n,e) pw_node_emit(n, enabled_changed, 0, e)
#define pw_node_emit_state_request(n,s) pw_node_emit(n, state_request, 0, s)

View file

@ -492,6 +492,8 @@ static int port_set_format(struct spa_node *node,
if (stream->state == PW_STREAM_STATE_ERROR)
return -EIO;
emit_port_info(impl);
stream_set_state(stream,
p ?
PW_STREAM_STATE_READY :