Improve async handling

Don't use special callback in node to receive the results. Instead,
use a generic result callback to receive the result. This makes things
a bit more symetric and generic again because then you can choose how
to match the result to the request and you have a generic way to handle
both the sync and async case. We can then also remove the wait method.
This also makes the remote interface and spa interface to objects very
similar.

Make a helper object to receive and dispatch results. Use this in the
helper for enum_params.

Make device use the same result callbacks.
This commit is contained in:
Wim Taymans 2019-02-25 12:29:57 +01:00
parent 98463b689b
commit d2c18c7b1a
64 changed files with 1298 additions and 1141 deletions

View file

@ -121,10 +121,9 @@ struct impl {
#define GET_OUT_PORT(this,p) (&this->out_ports[p])
#define GET_PORT(this,d,p) (d == SPA_DIRECTION_INPUT ? GET_IN_PORT(this,p) : GET_OUT_PORT(this,p))
static int impl_node_enum_params(struct spa_node *node,
static int impl_node_enum_params(struct spa_node *node, int seq,
uint32_t id, uint32_t start, uint32_t num,
const struct spa_pod *filter,
spa_result_func_t func, void *data)
const struct spa_pod *filter)
{
return -ENOTSUP;
}
@ -301,34 +300,35 @@ static int port_enum_formats(struct spa_node *node,
}
static int
impl_node_port_enum_params(struct spa_node *node,
impl_node_port_enum_params(struct spa_node *node, int seq,
enum spa_direction direction, uint32_t port_id,
uint32_t id, uint32_t start, uint32_t num,
const struct spa_pod *filter,
spa_result_func_t func, void *data)
const struct spa_pod *filter)
{
struct impl *this;
struct port *port;
struct spa_pod *param;
struct spa_pod_builder b = { 0 };
uint8_t buffer[1024];
struct spa_result_node_enum_params result;
struct spa_result_node_params result;
uint32_t count = 0;
int res;
spa_return_val_if_fail(node != NULL, -EINVAL);
spa_return_val_if_fail(num != 0, -EINVAL);
spa_return_val_if_fail(func != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), -EINVAL);
port = GET_PORT(this, direction, port_id);
result.id = id;
result.next = start;
next:
result.index = result.next++;
spa_pod_builder_init(&b, buffer, sizeof(buffer));
switch (id) {
@ -340,23 +340,23 @@ impl_node_port_enum_params(struct spa_node *node,
SPA_PARAM_Meta,
SPA_PARAM_IO };
if (result.next < SPA_N_ELEMENTS(list))
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.next]));
SPA_PARAM_LIST_id, SPA_POD_Id(list[result.index]));
else
return 0;
break;
}
case SPA_PARAM_EnumFormat:
if ((res = port_enum_formats(node, direction, port_id, result.next, &param, &b)) <= 0)
if ((res = port_enum_formats(node, direction, port_id, result.index, &param, &b)) <= 0)
return res;
break;
case SPA_PARAM_Format:
if (!port->have_format)
return -EIO;
if (result.next > 0)
if (result.index > 0)
return 0;
param = spa_format_audio_raw_build(&b, id, &this->format.info.raw);
@ -365,7 +365,7 @@ impl_node_port_enum_params(struct spa_node *node,
case SPA_PARAM_Buffers:
if (!port->have_format)
return -EIO;
if (result.next > 0)
if (result.index > 0)
return 0;
param = spa_pod_builder_add_object(&b,
@ -384,7 +384,7 @@ impl_node_port_enum_params(struct spa_node *node,
if (!port->have_format)
return -EIO;
switch (result.next) {
switch (result.index) {
case 0:
param = spa_pod_builder_add_object(&b,
SPA_TYPE_OBJECT_ParamMeta, id,
@ -397,7 +397,7 @@ impl_node_port_enum_params(struct spa_node *node,
break;
case SPA_PARAM_IO:
switch (result.next) {
switch (result.index) {
case 0:
param = spa_pod_builder_add_object(&b,
SPA_TYPE_OBJECT_ParamIO, id,
@ -424,12 +424,10 @@ impl_node_port_enum_params(struct spa_node *node,
return -ENOENT;
}
result.next++;
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = func(data, count, &result)) != 0)
if ((res = this->callbacks->result(this->user_data, seq, 0, &result)) != 0)
return res;
if (++count != num)

View file

@ -354,33 +354,34 @@ static void mix_clear(struct node *this, struct mix *mix)
mix->valid = false;
}
static int impl_node_enum_params(struct spa_node *node,
static int impl_node_enum_params(struct spa_node *node, int seq,
uint32_t id, uint32_t start, uint32_t num,
const struct spa_pod *filter,
spa_result_func_t func, void *data)
const struct spa_pod *filter)
{
struct node *this;
uint8_t buffer[1024];
struct spa_pod_builder b = { 0 };
struct spa_result_node_enum_params result;
struct spa_result_node_params result;
uint32_t count = 0;
int res;
spa_return_val_if_fail(node != NULL, -EINVAL);
spa_return_val_if_fail(num != 0, -EINVAL);
spa_return_val_if_fail(func != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct node, node);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
result.id = id;
result.next = start;
while (true) {
struct spa_pod *param;
if (result.next >= this->n_params)
result.index = result.next++;
if (result.index >= this->n_params)
return 0;
param = this->params[result.next++];
param = this->params[result.index];
if (param == NULL || !spa_pod_is_object_id(param, id))
continue;
@ -389,7 +390,7 @@ static int impl_node_enum_params(struct spa_node *node,
if (spa_pod_filter(&b, &result.param, param, filter) != 0)
continue;
if ((res = func(data, count, &result)) != 0)
if ((res = this->callbacks->result(this->callbacks_data, seq, 0, &result)) != 0)
return res;
if (++count != num)
@ -490,8 +491,8 @@ impl_node_set_callbacks(struct spa_node *node,
void *data)
{
struct node *this;
int res = 0;
uint32_t i;
int res = 0;
spa_return_val_if_fail(node != NULL, -EINVAL);
@ -510,13 +511,13 @@ impl_node_set_callbacks(struct spa_node *node,
emit_port_info(this, this->out_ports[i]);
}
if (callbacks && this->resource)
res = pw_resource_sync(this->resource);
res = pw_resource_sync(this->resource, 0);
return res;
}
static int
impl_node_sync(struct spa_node *node)
impl_node_sync(struct spa_node *node, int seq)
{
struct node *this;
spa_return_val_if_fail(node != NULL, -EINVAL);
@ -524,35 +525,7 @@ impl_node_sync(struct spa_node *node)
pw_log_debug("client-node %p: sync", node);
if (this->resource == NULL)
return -EIO;
return pw_resource_sync(this->resource);
}
static int
impl_node_wait(struct spa_node *node, int res, struct spa_pending *pending,
spa_pending_func_t func, void *data)
{
struct node *this;
int seq;
spa_return_val_if_fail(node != NULL, -EINVAL);
spa_return_val_if_fail(func != NULL, -EINVAL);
spa_return_val_if_fail(pending != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct node, node);
pw_log_debug("client-node %p: wait %d %d", node, res, SPA_RESULT_ASYNC_SEQ(res));
if (this->resource == NULL)
return -EIO;
seq = pw_resource_sync(this->resource);
pending->seq = seq;
pending->res = res;
pending->func = func;
pending->data = data;
spa_list_append(&this->pending_list, &pending->link);
return seq;
return pw_resource_sync(this->resource, seq);
}
static void
@ -661,42 +634,43 @@ impl_node_remove_port(struct spa_node *node, enum spa_direction direction, uint3
}
static int
impl_node_port_enum_params(struct spa_node *node,
impl_node_port_enum_params(struct spa_node *node, int seq,
enum spa_direction direction, uint32_t port_id,
uint32_t id, uint32_t start, uint32_t num,
const struct spa_pod *filter,
spa_result_func_t func, void *data)
const struct spa_pod *filter)
{
struct node *this;
struct port *port;
uint8_t buffer[1024];
struct spa_pod_builder b = { 0 };
struct spa_result_node_enum_params result;
struct spa_result_node_params result;
uint32_t count = 0;
int res;
spa_return_val_if_fail(node != NULL, -EINVAL);
spa_return_val_if_fail(num != 0, -EINVAL);
spa_return_val_if_fail(func != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct node, node);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), -EINVAL);
port = GET_PORT(this, direction, port_id);
pw_log_debug("client-node %p: port %d.%d", this,
direction, port_id);
pw_log_debug("client-node %p: %d port %d.%d %u %u %u", this, seq,
direction, port_id, id, start, num);
result.id = id;
result.next = start;
while (true) {
struct spa_pod *param;
if (result.next >= port->n_params)
result.index = result.next++;
if (result.index >= port->n_params)
return 0;
param = port->params[result.next++];
param = port->params[result.index];
if (param == NULL || !spa_pod_is_object_id(param, id))
continue;
@ -705,7 +679,8 @@ impl_node_port_enum_params(struct spa_node *node,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
continue;
if ((res = func(data, count, &result)) != 0)
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)
@ -1136,7 +1111,6 @@ static const struct spa_node impl_node = {
NULL,
.set_callbacks = impl_node_set_callbacks,
.sync = impl_node_sync,
.wait = impl_node_wait,
.enum_params = impl_node_enum_params,
.set_param = impl_node_set_param,
.set_io = impl_node_set_io,
@ -1250,21 +1224,9 @@ static void client_node_resource_done(void *data, uint32_t seq)
{
struct impl *impl = data;
struct node *this = &impl->node;
struct spa_pending *p, *t;
uint32_t count = 0;
spa_list_for_each_safe(p, t, &this->pending_list, link) {
if (p->seq == (int) seq) {
pw_log_debug("client-node %p: do callback %d", this, p->res);
spa_list_remove(&p->link);
p->seq = p->res;
p->res = 0;
p->func(p, NULL);
count++;
}
}
if (count == 0)
pw_log_warn("client-node %p: unhandled done %d", this, seq);
pw_log_debug("client-node %p: emit result %d", this, seq);
this->callbacks->result(this->callbacks_data, seq, 0, NULL);
}
void pw_client_node_registered(struct pw_client_node *this, uint32_t node_id)
@ -1395,15 +1357,14 @@ static const struct pw_port_implementation port_impl = {
};
static int
impl_mix_port_enum_params(struct spa_node *node,
impl_mix_port_enum_params(struct spa_node *node, int seq,
enum spa_direction direction, uint32_t port_id,
uint32_t id, uint32_t start, uint32_t num,
const struct spa_pod *filter,
spa_result_func_t func, void *data)
const struct spa_pod *filter)
{
struct port *port = SPA_CONTAINER_OF(node, struct port, mix_node);
return impl_node_port_enum_params(&port->node->node, direction, port->id,
id, start, num, filter, func, data);
return impl_node_port_enum_params(&port->node->node, seq, direction, port->id,
id, start, num, filter);
}
static int

View file

@ -103,34 +103,37 @@ struct impl {
struct spa_buffer **buffers;
uint32_t n_buffers;
struct pw_memblock *mem;
struct spa_pending client_node_pending;
};
/** \endcond */
static int impl_node_enum_params(struct spa_node *node,
static int impl_node_enum_params(struct spa_node *node, int seq,
uint32_t id, uint32_t start, uint32_t num,
const struct spa_pod *filter,
spa_result_func_t func, void *data)
const struct spa_pod *filter)
{
struct node *this;
struct impl *impl;
struct spa_pod *param;
struct spa_pod_builder b = { 0 };
uint8_t buffer[1024];
struct spa_result_node_enum_params result;
struct spa_result_node_params result;
uint32_t count = 0;
int res;
spa_return_val_if_fail(node != NULL, -EINVAL);
spa_return_val_if_fail(num != 0, -EINVAL);
spa_return_val_if_fail(func != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct node, node);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
impl = this->impl;
result.id = id;
result.next = start;
next:
result.index = result.next++;
spa_pod_builder_init(&b, buffer, sizeof(buffer));
switch (id) {
@ -140,37 +143,41 @@ static int impl_node_enum_params(struct spa_node *node,
SPA_PARAM_EnumFormat,
SPA_PARAM_Format };
if (result.next < SPA_N_ELEMENTS(list))
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.next]));
SPA_PARAM_LIST_id, SPA_POD_Id(list[result.index]));
else
return 0;
break;
}
case SPA_PARAM_Props:
if (impl->adapter != impl->cnode) {
return spa_node_enum_params(impl->adapter,
id, start, num, filter, func, data);
}
return 0;
if (impl->adapter == impl->cnode)
return 0;
if ((res = spa_node_enum_params_sync(impl->adapter,
id, &start, filter, &param, &b,
impl->this.node->pending)) != 1)
return res;
break;
case SPA_PARAM_EnumFormat:
case SPA_PARAM_Format:
return spa_node_port_enum_params(impl->cnode,
if ((res = spa_node_port_enum_params_sync(impl->cnode,
impl->direction, 0,
id, start, num,
filter, func, data);
id, &start, filter, &param, &b,
impl->client_node->node->pending)) != 1)
return res;
break;
default:
return -ENOENT;
}
result.next++;
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = func(data, count, &result)) != 0)
if ((res = this->callbacks->result(this->callbacks_data, seq, 0, &result)) != 0)
return res;
if (++count != num)
@ -306,10 +313,17 @@ static int adapter_port_info(void *data,
}
return 0;
}
static int adapter_result(void *data, int seq, int res, const void *result)
{
struct impl *impl = data;
struct node *this = &impl->node;
return this->callbacks->result(this->callbacks_data, seq, res, result);
}
static const struct spa_node_callbacks adapter_node_callbacks = {
SPA_VERSION_NODE_CALLBACKS,
.port_info = adapter_port_info,
.result = adapter_result,
};
static int
@ -331,11 +345,11 @@ impl_node_set_callbacks(struct spa_node *node,
if (this->callbacks && impl->adapter && impl->adapter != impl->cnode)
spa_node_set_callbacks(impl->adapter, &adapter_node_callbacks, impl);
return spa_node_sync(impl->cnode);
return spa_node_sync(impl->cnode, 0);
}
static int
impl_node_sync(struct spa_node *node)
impl_node_sync(struct spa_node *node, int seq)
{
struct node *this;
struct impl *impl;
@ -345,22 +359,7 @@ impl_node_sync(struct spa_node *node)
this = SPA_CONTAINER_OF(node, struct node, node);
impl = this->impl;
return spa_node_sync(impl->cnode);
}
static int
impl_node_wait(struct spa_node *node, int seq, struct spa_pending *pending,
spa_pending_func_t func, void *data)
{
struct node *this;
struct impl *impl;
spa_return_val_if_fail(node != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct node, node);
impl = this->impl;
return spa_node_wait(impl->cnode, seq, pending, func, data);
return spa_node_sync(impl->cnode, seq);
}
static int
@ -410,27 +409,28 @@ impl_node_remove_port(struct spa_node *node, enum spa_direction direction, uint3
}
static int
impl_node_port_enum_params(struct spa_node *node,
impl_node_port_enum_params(struct spa_node *node, int seq,
enum spa_direction direction, uint32_t port_id,
uint32_t id, uint32_t start, uint32_t num,
const struct spa_pod *filter,
spa_result_func_t func, void *data)
const struct spa_pod *filter)
{
struct node *this;
struct impl *impl;
spa_return_val_if_fail(node != NULL, -EINVAL);
spa_return_val_if_fail(num != 0, -EINVAL);
spa_return_val_if_fail(func != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct node, node);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
impl = this->impl;
if (direction != impl->direction)
return -EINVAL;
return spa_node_port_enum_params(impl->adapter, direction, port_id, id,
start, num, filter, func, data);
pw_log_debug("%p: %d %u", this, seq, id);
return spa_node_port_enum_params(impl->adapter, seq, direction, port_id, id,
start, num, filter);
}
static int debug_params(struct impl *impl, struct spa_node *node,
@ -451,7 +451,8 @@ static int debug_params(struct impl *impl, struct spa_node *node,
res = spa_node_port_enum_params_sync(node,
direction, port_id,
id, &state,
NULL, &param, &b);
NULL, &param, &b,
impl->this.node->pending);
if (res != 1) {
if (res < 0)
spa_log_error(this->log, " error: %s", spa_strerror(res));
@ -486,7 +487,8 @@ static int negotiate_format(struct impl *impl)
SPA_DIRECTION_REVERSE(impl->direction),
impl->adapter_mix_port,
SPA_PARAM_EnumFormat, &state,
NULL, &format, &b)) != 1) {
NULL, &format, &b,
impl->this.node->pending)) != 1) {
debug_params(impl, impl->adapter_mix,
SPA_DIRECTION_REVERSE(impl->direction),
impl->adapter_mix_port,
@ -496,9 +498,10 @@ static int negotiate_format(struct impl *impl)
state = 0;
if ((res = spa_node_port_enum_params_sync(impl->cnode,
impl->direction, 0,
SPA_PARAM_EnumFormat, &state,
format, &format, &b)) != 1) {
impl->direction, 0,
SPA_PARAM_EnumFormat, &state,
format, &format, &b,
impl->client_node->node->pending)) != 1) {
debug_params(impl, impl->cnode, impl->direction, 0,
SPA_PARAM_EnumFormat, format);
return -ENOTSUP;
@ -547,10 +550,11 @@ static int negotiate_buffers(struct impl *impl)
state = 0;
if ((res = spa_node_port_enum_params_sync(impl->adapter_mix,
SPA_DIRECTION_REVERSE(impl->direction),
impl->adapter_mix_port,
SPA_PARAM_Buffers, &state,
param, &param, &b)) < 0) {
SPA_DIRECTION_REVERSE(impl->direction),
impl->adapter_mix_port,
SPA_PARAM_Buffers, &state,
param, &param, &b,
impl->this.node->pending)) != 1) {
debug_params(impl, impl->adapter_mix,
SPA_DIRECTION_REVERSE(impl->direction),
impl->adapter_mix_port,
@ -562,9 +566,10 @@ static int negotiate_buffers(struct impl *impl)
state = 0;
if ((res = spa_node_port_enum_params_sync(impl->cnode,
impl->direction, 0,
SPA_PARAM_Buffers, &state,
param, &param, &b)) < 0) {
impl->direction, 0,
SPA_PARAM_Buffers, &state,
param, &param, &b,
impl->client_node->node->pending)) < 0) {
debug_params(impl, impl->cnode, impl->direction, 0,
SPA_PARAM_Buffers, param);
return res;
@ -855,7 +860,6 @@ static const struct spa_node impl_node = {
SPA_VERSION_NODE,
.set_callbacks = impl_node_set_callbacks,
.sync = impl_node_sync,
.wait = impl_node_wait,
.enum_params = impl_node_enum_params,
.set_param = impl_node_set_param,
.set_io = impl_node_set_io,
@ -980,7 +984,8 @@ static void client_node_initialized(void *data)
if ((res = spa_node_port_enum_params_sync(impl->cnode,
impl->direction, 0,
SPA_PARAM_EnumFormat, &state,
NULL, &format, &b)) != 1) {
NULL, &format, &b,
impl->client_node->node->pending)) != 1) {
pw_log_warn("client-stream %p: no format given", &impl->this);
impl->adapter = impl->cnode;
impl->adapter_mix = impl->client_port->mix;
@ -1098,6 +1103,14 @@ static void client_node_destroy(void *data)
cleanup(impl);
}
static void client_node_result(void *data, int seq, int res, const void *result)
{
struct impl *impl = data;
struct node *node = &impl->node;
pw_log_debug("client-stream %p: result %d %d", &impl->this, seq, res);
node->callbacks->result(node->callbacks_data, seq, res, result);
}
static void client_node_active_changed(void *data, bool active)
{
struct impl *impl = data;
@ -1106,7 +1119,7 @@ static void client_node_active_changed(void *data, bool active)
impl->active = active;
}
static void client_node_info_changed (void *data, const struct pw_node_info *info)
static void client_node_info_changed(void *data, const struct pw_node_info *info)
{
struct impl *impl = data;
struct pw_client_stream *this = &impl->this;
@ -1120,6 +1133,7 @@ static const struct pw_node_events client_node_events = {
PW_VERSION_NODE_EVENTS,
.destroy = client_node_destroy,
.initialized = client_node_initialized,
.result = client_node_result,
.active_changed = client_node_active_changed,
.info_changed = client_node_info_changed,
};
@ -1145,13 +1159,13 @@ static void node_initialized(void *data)
static void node_peer_added(void *data, struct pw_node *peer)
{
struct impl *impl = data;
pw_node_events_peer_added(impl->client_node->node, peer);
pw_node_emit_peer_added(impl->client_node->node, peer);
}
static void node_peer_removed(void *data, struct pw_node *peer)
{
struct impl *impl = data;
pw_node_events_peer_removed(impl->client_node->node, peer);
pw_node_emit_peer_removed(impl->client_node->node, peer);
}
static void node_driver_changed(void *data, struct pw_node *old, struct pw_node *driver)
@ -1159,7 +1173,7 @@ static void node_driver_changed(void *data, struct pw_node *old, struct pw_node
struct impl *impl = data;
pw_log_debug("client-stream %p: driver changed %p->%p", &impl->this, old, driver);
impl->client_node->node->driver_node = driver;
pw_node_events_driver_changed(impl->client_node->node, old, driver);
pw_node_emit_driver_changed(impl->client_node->node, old, driver);
}
static const struct pw_node_events node_events = {

View file

@ -415,9 +415,10 @@ static int add_port_update(struct pw_proxy *proxy, struct pw_port *port, uint32_
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) != 1)
port->direction, port->port_id,
SPA_PARAM_List, &idx1,
NULL, &param, &b,
port->node->pending) != 1)
break;
spa_pod_parse_object(param,
@ -430,9 +431,10 @@ static int add_port_update(struct pw_proxy *proxy, struct pw_port *port, uint32_
for (idx2 = 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,
NULL, &param, &b) != 1)
port->direction, port->port_id,
id, &idx2,
NULL, &param, &b,
port->node->pending) != 1)
break;
params = realloc(params, sizeof(struct spa_pod *) * (n_params + 1));

View file

@ -127,8 +127,9 @@ process_messages(struct client_data *data)
const struct pw_protocol_native_demarshal *demarshal;
const struct pw_protocol_marshal *marshal;
uint32_t permissions, required;
int seq;
if (!pw_protocol_native_connection_get_next(conn, &opcode, &id, &message, &size))
if (!pw_protocol_native_connection_get_next(conn, &opcode, &id, &message, &size, &seq))
break;
pw_log_trace("protocol-native %p: got message %d from %u", client->protocol,
@ -147,6 +148,7 @@ process_messages(struct client_data *data)
-EINVAL, "unknown resource %u", id);
continue;
}
resource->seq = seq;
marshal = pw_resource_get_marshal(resource);
if (marshal == NULL || opcode >= marshal->n_methods)
@ -478,17 +480,20 @@ on_remote_data(void *data, int fd, enum spa_io mask)
uint8_t opcode;
uint32_t id, size;
void *message;
int seq;
while (!impl->disconnecting
&& pw_protocol_native_connection_get_next(conn, &opcode, &id, &message, &size)) {
&& pw_protocol_native_connection_get_next(conn,
&opcode, &id, &message, &size, &seq)) {
struct pw_proxy *proxy;
const struct pw_protocol_native_demarshal *demarshal;
const struct pw_protocol_marshal *marshal;
pw_log_trace("protocol-native %p: got message %d from %u", this, opcode, id);
pw_log_trace("protocol-native %p: got message %d from %u seq:%d",
this, opcode, id, seq);
if (debug_messages) {
fprintf(stderr, "<<<<<<<<< in: %d %d %d\n", id, opcode, size);
fprintf(stderr, "<<<<<<<<< in: %d %d %d %d\n", id, opcode, size, seq);
spa_debug_pod(0, NULL, (struct spa_pod *)message);
}
@ -498,6 +503,7 @@ on_remote_data(void *data, int fd, enum spa_io mask)
pw_log_error("protocol-native %p: could not find proxy %u", this, id);
continue;
}
proxy->seq = seq;
marshal = pw_proxy_get_marshal(proxy);
if (marshal == NULL || opcode >= marshal->n_events) {

View file

@ -41,6 +41,8 @@
#define MAX_FDS 1024
#define MAX_FDS_MSG 28
#define HDR_SIZE 16
static bool debug_messages = 0;
struct buffer {
@ -277,7 +279,8 @@ pw_protocol_native_connection_get_next(struct pw_protocol_native_connection *con
uint8_t *opcode,
uint32_t *dest_id,
void **dt,
uint32_t *sz)
uint32_t *sz,
int *seq)
{
struct impl *impl = SPA_CONTAINER_OF(conn, struct impl, this);
size_t len, size;
@ -310,19 +313,20 @@ pw_protocol_native_connection_get_next(struct pw_protocol_native_connection *con
data += buf->offset;
size -= buf->offset;
if (size < 8) {
if (connection_ensure_size(conn, buf, 8) == NULL)
if (size < HDR_SIZE) {
if (connection_ensure_size(conn, buf, HDR_SIZE) == NULL)
return false;
buf->update = true;
goto again;
}
p = (uint32_t *) data;
data += 8;
size -= 8;
data += HDR_SIZE;
size -= HDR_SIZE;
*dest_id = p[0];
*opcode = p[1] >> 24;
len = p[1] & 0xffffff;
*seq = p[2];
if (len > size) {
if (connection_ensure_size(conn, buf, len) == NULL)
@ -332,7 +336,7 @@ pw_protocol_native_connection_get_next(struct pw_protocol_native_connection *con
}
buf->size = len;
buf->data = data;
buf->offset += 8;
buf->offset += HDR_SIZE;
*dt = buf->data;
*sz = buf->size;
@ -345,11 +349,11 @@ static inline void *begin_write(struct pw_protocol_native_connection *conn, uint
struct impl *impl = SPA_CONTAINER_OF(conn, struct impl, this);
uint32_t *p;
struct buffer *buf = &impl->out;
/* 4 for dest_id, 1 for opcode, 3 for size and size for payload */
if ((p = connection_ensure_size(conn, buf, 8 + size)) == NULL)
/* header and size for payload */
if ((p = connection_ensure_size(conn, buf, HDR_SIZE + size)) == NULL)
return NULL;
return p + 2;
return SPA_MEMBER(p, HDR_SIZE, void);
}
static int builder_overflow(void *callbacks_data, uint32_t size)
@ -392,20 +396,21 @@ pw_protocol_native_connection_end(struct pw_protocol_native_connection *conn,
struct buffer *buf = &impl->out;
uint32_t seq;
if ((p = connection_ensure_size(conn, buf, 8 + size)) == NULL)
if ((p = connection_ensure_size(conn, buf, HDR_SIZE + size)) == NULL)
return -ENOMEM;
seq = impl->seq;
impl->seq = (impl->seq + 1) & SPA_ASYNC_SEQ_MASK;
*p++ = impl->dest_id;
*p++ = (impl->opcode << 24) | (size & 0xffffff);
p[0] = impl->dest_id;
p[1] = (impl->opcode << 24) | (size & 0xffffff);
p[2] = seq;
buf->buffer_size += 8 + size;
buf->buffer_size += HDR_SIZE + size;
if (debug_messages) {
fprintf(stderr, ">>>>>>>>> out: %d %d %d\n", impl->dest_id, impl->opcode, size);
spa_debug_pod(0, NULL, (struct spa_pod *)p);
spa_debug_pod(0, NULL, SPA_MEMBER(p, HDR_SIZE, struct spa_pod));
}
spa_hook_list_call(&conn->listener_list,

View file

@ -75,7 +75,7 @@ bool
pw_protocol_native_connection_get_next(struct pw_protocol_native_connection *conn,
uint8_t *opcode,
uint32_t *dest_id,
void **data, uint32_t *size);
void **data, uint32_t *size, int *seq);
uint32_t pw_protocol_native_connection_add_fd(struct pw_protocol_native_connection *conn, int fd);

View file

@ -646,7 +646,7 @@ static int device_demarshal_info(void *object, void *data, size_t size)
return pw_proxy_notify(proxy, struct pw_device_proxy_events, info, 0, &info);
}
static int device_marshal_param(void *object, uint32_t id, uint32_t index, uint32_t next,
static int device_marshal_param(void *object, uint32_t seq, uint32_t id, uint32_t index, uint32_t next,
const struct spa_pod *param)
{
struct pw_resource *resource = object;
@ -655,6 +655,7 @@ static int device_marshal_param(void *object, uint32_t id, uint32_t index, uint3
b = pw_protocol_native_begin_resource(resource, PW_DEVICE_PROXY_EVENT_PARAM, NULL);
spa_pod_builder_add_struct(b,
SPA_POD_Int(seq),
SPA_POD_Id(id),
SPA_POD_Int(index),
SPA_POD_Int(next),
@ -667,29 +668,33 @@ static int device_demarshal_param(void *object, void *data, size_t size)
{
struct pw_proxy *proxy = object;
struct spa_pod_parser prs;
uint32_t id, index, next;
uint32_t seq, id, index, next;
struct spa_pod *param;
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&seq),
SPA_POD_Id(&id),
SPA_POD_Int(&index),
SPA_POD_Int(&next),
SPA_POD_Pod(&param)) < 0)
return -EINVAL;
return pw_proxy_notify(proxy, struct pw_device_proxy_events, param, 0, id, index, next, param);
return pw_proxy_notify(proxy, struct pw_device_proxy_events, param, 0,
seq, id, index, next, param);
}
static int device_marshal_enum_params(void *object, uint32_t id, uint32_t index, uint32_t num,
const struct spa_pod *filter)
static int device_marshal_enum_params(void *object, uint32_t seq,
uint32_t id, uint32_t index, uint32_t num, const struct spa_pod *filter)
{
struct pw_proxy *proxy = object;
struct spa_pod_builder *b;
int res;
b = pw_protocol_native_begin_proxy(proxy, PW_DEVICE_PROXY_METHOD_ENUM_PARAMS, NULL);
b = pw_protocol_native_begin_proxy(proxy, PW_DEVICE_PROXY_METHOD_ENUM_PARAMS, &res);
spa_pod_builder_add_struct(b,
SPA_POD_Int(res),
SPA_POD_Id(id),
SPA_POD_Int(index),
SPA_POD_Int(num),
@ -702,18 +707,20 @@ static int device_demarshal_enum_params(void *object, void *data, size_t size)
{
struct pw_resource *resource = object;
struct spa_pod_parser prs;
uint32_t id, index, num;
uint32_t id, index, num, seq;
struct spa_pod *filter;
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&seq),
SPA_POD_Id(&id),
SPA_POD_Int(&index),
SPA_POD_Int(&num),
SPA_POD_Pod(&filter)) < 0)
return -EINVAL;
return pw_resource_do(resource, struct pw_device_proxy_methods, enum_params, 0, id, index, num, filter);
return pw_resource_do(resource, struct pw_device_proxy_methods, enum_params, 0,
seq, id, index, num, filter);
}
static int device_marshal_set_param(void *object, uint32_t id, uint32_t flags,
@ -870,8 +877,8 @@ static int node_demarshal_info(void *object, void *data, size_t size)
return pw_proxy_notify(proxy, struct pw_node_proxy_events, info, 0, &info);
}
static int node_marshal_param(void *object, uint32_t id, uint32_t index, uint32_t next,
const struct spa_pod *param)
static int node_marshal_param(void *object, uint32_t seq, uint32_t id,
uint32_t index, uint32_t next, const struct spa_pod *param)
{
struct pw_resource *resource = object;
struct spa_pod_builder *b;
@ -879,6 +886,7 @@ static int node_marshal_param(void *object, uint32_t id, uint32_t index, uint32_
b = pw_protocol_native_begin_resource(resource, PW_NODE_PROXY_EVENT_PARAM, NULL);
spa_pod_builder_add_struct(b,
SPA_POD_Int(seq),
SPA_POD_Id(id),
SPA_POD_Int(index),
SPA_POD_Int(next),
@ -891,29 +899,33 @@ static int node_demarshal_param(void *object, void *data, size_t size)
{
struct pw_proxy *proxy = object;
struct spa_pod_parser prs;
uint32_t id, index, next;
uint32_t seq, id, index, next;
struct spa_pod *param;
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&seq),
SPA_POD_Id(&id),
SPA_POD_Int(&index),
SPA_POD_Int(&next),
SPA_POD_Pod(&param)) < 0)
return -EINVAL;
return pw_proxy_notify(proxy, struct pw_node_proxy_events, param, 0, id, index, next, param);
return pw_proxy_notify(proxy, struct pw_node_proxy_events, param, 0,
seq, id, index, next, param);
}
static int node_marshal_enum_params(void *object, uint32_t id, uint32_t index, uint32_t num,
const struct spa_pod *filter)
static int node_marshal_enum_params(void *object, uint32_t seq, uint32_t id,
uint32_t index, uint32_t num, const struct spa_pod *filter)
{
struct pw_proxy *proxy = object;
struct spa_pod_builder *b;
int res;
b = pw_protocol_native_begin_proxy(proxy, PW_NODE_PROXY_METHOD_ENUM_PARAMS, NULL);
b = pw_protocol_native_begin_proxy(proxy, PW_NODE_PROXY_METHOD_ENUM_PARAMS, &res);
spa_pod_builder_add_struct(b,
SPA_POD_Int(res),
SPA_POD_Id(id),
SPA_POD_Int(index),
SPA_POD_Int(num),
@ -926,18 +938,20 @@ static int node_demarshal_enum_params(void *object, void *data, size_t size)
{
struct pw_resource *resource = object;
struct spa_pod_parser prs;
uint32_t id, index, num;
uint32_t seq, id, index, num;
struct spa_pod *filter;
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&seq),
SPA_POD_Id(&id),
SPA_POD_Int(&index),
SPA_POD_Int(&num),
SPA_POD_Pod(&filter)) < 0)
return -EINVAL;
return pw_resource_do(resource, struct pw_node_proxy_methods, enum_params, 0, id, index, num, filter);
return pw_resource_do(resource, struct pw_node_proxy_methods, enum_params, 0,
seq, id, index, num, filter);
}
static int node_marshal_set_param(void *object, uint32_t id, uint32_t flags,
@ -1050,8 +1064,8 @@ static int port_demarshal_info(void *object, void *data, size_t size)
return pw_proxy_notify(proxy, struct pw_port_proxy_events, info, 0, &info);
}
static int port_marshal_param(void *object, uint32_t id, uint32_t index, uint32_t next,
const struct spa_pod *param)
static int port_marshal_param(void *object, uint32_t seq, uint32_t id,
uint32_t index, uint32_t next, const struct spa_pod *param)
{
struct pw_resource *resource = object;
struct spa_pod_builder *b;
@ -1059,6 +1073,7 @@ static int port_marshal_param(void *object, uint32_t id, uint32_t index, uint32_
b = pw_protocol_native_begin_resource(resource, PW_PORT_PROXY_EVENT_PARAM, NULL);
spa_pod_builder_add_struct(b,
SPA_POD_Int(seq),
SPA_POD_Id(id),
SPA_POD_Int(index),
SPA_POD_Int(next),
@ -1071,29 +1086,33 @@ static int port_demarshal_param(void *object, void *data, size_t size)
{
struct pw_proxy *proxy = object;
struct spa_pod_parser prs;
uint32_t id, index, next;
uint32_t seq, id, index, next;
struct spa_pod *param;
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&seq),
SPA_POD_Id(&id),
SPA_POD_Int(&index),
SPA_POD_Int(&next),
SPA_POD_Pod(&param)) < 0)
return -EINVAL;
return pw_proxy_notify(proxy, struct pw_port_proxy_events, param, 0, id, index, next, param);
return pw_proxy_notify(proxy, struct pw_port_proxy_events, param, 0,
seq, id, index, next, param);
}
static int port_marshal_enum_params(void *object, uint32_t id, uint32_t index, uint32_t num,
const struct spa_pod *filter)
static int port_marshal_enum_params(void *object, uint32_t seq, uint32_t id,
uint32_t index, uint32_t num, const struct spa_pod *filter)
{
struct pw_proxy *proxy = object;
struct spa_pod_builder *b;
int res;
b = pw_protocol_native_begin_proxy(proxy, PW_PORT_PROXY_METHOD_ENUM_PARAMS, NULL);
b = pw_protocol_native_begin_proxy(proxy, PW_PORT_PROXY_METHOD_ENUM_PARAMS, &res);
spa_pod_builder_add_struct(b,
SPA_POD_Int(res),
SPA_POD_Id(id),
SPA_POD_Int(index),
SPA_POD_Int(num),
@ -1106,18 +1125,20 @@ static int port_demarshal_enum_params(void *object, void *data, size_t size)
{
struct pw_resource *resource = object;
struct spa_pod_parser prs;
uint32_t id, index, num;
uint32_t seq, id, index, num;
struct spa_pod *filter;
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&seq),
SPA_POD_Id(&id),
SPA_POD_Int(&index),
SPA_POD_Int(&num),
SPA_POD_Pod(&filter)) < 0)
return -EINVAL;
return pw_resource_do(resource, struct pw_port_proxy_methods, enum_params, 0, id, index, num, filter);
return pw_resource_do(resource, struct pw_port_proxy_methods, enum_params, 0,
seq, id, index, num, filter);
}
static int client_marshal_info(void *object, const struct pw_client_info *info)

View file

@ -57,14 +57,14 @@ struct impl {
char *factory_name;
struct spa_hook node_listener;
struct spa_pending init_pending;
int init_pending;
void *user_data;
int async_init:1;
};
static void pw_spa_node_free(void *data)
static void spa_node_free(void *data)
{
struct impl *impl = data;
struct pw_node *node = impl->this;
@ -82,10 +82,11 @@ static void pw_spa_node_free(void *data)
dlclose(impl->hnd);
}
static int complete_init(struct impl *impl)
static void complete_init(struct impl *impl)
{
struct pw_node *this = impl->this;
impl->init_pending = SPA_ID_INVALID;
if (SPA_FLAG_CHECK(impl->flags, PW_SPA_NODE_FLAG_DISABLE))
pw_node_set_enabled(this, false);
@ -96,20 +97,23 @@ static int complete_init(struct impl *impl)
pw_node_register(this, impl->owner, impl->parent, NULL);
else
pw_node_initialized(this);
return 0;
}
static int on_init_done(struct spa_pending *pending, const void *result)
static void spa_node_result(void *data, int seq, int res, const void *result)
{
struct impl *impl = pending->data;
struct pw_node *this = impl->this;
pw_log_debug("spa-node %p: init complete event %d %d", this, pending->seq, pending->res);
return complete_init(impl);
struct impl *impl = data;
struct pw_node *node = impl->this;
if (seq == impl->init_pending) {
pw_log_debug("spa-node %p: init complete event %d %d", node, seq, res);
complete_init(impl);
}
}
static const struct pw_node_events node_events = {
PW_VERSION_NODE_EVENTS,
.free = pw_spa_node_free,
.free = spa_node_free,
.result = spa_node_result,
};
struct pw_node *
@ -148,7 +152,7 @@ pw_spa_node_new(struct pw_core *core,
goto clean_node;
if (SPA_RESULT_IS_ASYNC(res)) {
spa_node_wait(impl->node, res, &impl->init_pending, on_init_done, impl);
impl->init_pending = spa_node_sync(impl->node, res);
} else {
complete_init(impl);
}
@ -166,6 +170,17 @@ void *pw_spa_node_get_user_data(struct pw_node *node)
return impl->user_data;
}
static int on_node_result(void *data, int seq, int res, const void *result)
{
struct spa_pending_queue *pending = data;
return spa_pending_queue_complete(pending, seq, res, result);
}
static const struct spa_node_callbacks node_callbacks = {
SPA_VERSION_NODE_CALLBACKS,
.result = on_node_result,
};
static int
setup_props(struct pw_core *core, struct spa_node *spa_node, struct pw_properties *pw_props)
{
@ -177,10 +192,17 @@ setup_props(struct pw_core *core, struct spa_node *spa_node, struct pw_propertie
uint8_t buf[2048];
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buf, sizeof(buf));
const struct spa_pod_prop *prop = NULL;
struct spa_pending_queue pending;
spa_pending_queue_init(&pending);
spa_node_set_callbacks(spa_node, &node_callbacks, &pending);
if ((res = spa_node_enum_params_sync(spa_node,
SPA_PARAM_Props, &index, NULL, &props, &b)) != 1) {
pw_log_debug("spa_node_get_props failed: %d", res);
SPA_PARAM_Props, &index, NULL, &props,
&b, &pending)) != 1) {
if (res < 0)
pw_log_debug("spa_node_get_props failed: %d", res);
return res;
}