spa: save the old change_mask and restore when emitting full

When we add a new listener to an object, it will emit the full state
of the object. For this it temporarily sets the change_mask to all
changes. Restore the previous state after this or else we might not
emit the right change_mask for the next listener.

Consider the case where one there are two listeners on an object.
The object emits a change and the first listener wants to enumerate the
changed params. For this is adds a new listener and then triggers the
enumeration. If we set the change_mask to 0 after adding the listener,
the second listener would get a 0 change_mask and fail to update
its state.
This commit is contained in:
Wim Taymans 2021-05-25 15:22:13 +02:00
parent c8c0a152b7
commit 46ef88e520
42 changed files with 151 additions and 77 deletions

View file

@ -141,13 +141,15 @@ static int impl_add_listener(void *object,
{
struct data *d = object;
struct spa_hook_list save;
uint64_t old;
spa_hook_list_isolate(&d->hooks, &save, listener, events, data);
old = d->info.change_mask;
d->info.change_mask = SPA_PORT_CHANGE_MASK_FLAGS |
SPA_PORT_CHANGE_MASK_PARAMS;
spa_node_emit_port_info(&d->hooks, SPA_DIRECTION_INPUT, 0, &d->info);
d->info.change_mask = 0;
d->info.change_mask = old;
spa_hook_list_join(&d->hooks, &save);
@ -526,7 +528,7 @@ int main(int argc, char *argv[])
data.info = SPA_PORT_INFO_INIT();
data.info.change_mask = SPA_PORT_CHANGE_MASK_FLAGS;
data.info.flags = 0;
data.info.change_mask = SPA_PORT_CHANGE_MASK_PARAMS;
data.info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
data.params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
data.params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
data.params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);

View file

@ -115,12 +115,14 @@ static int impl_add_listener(void *object,
{
struct data *d = object;
struct spa_hook_list save;
uint64_t old;
spa_hook_list_isolate(&d->hooks, &save, listener, events, data);
old = d->info.change_mask;
d->info.change_mask = d->info_all;
spa_node_emit_port_info(&d->hooks, SPA_DIRECTION_OUTPUT, 0, &d->info);
d->info.change_mask = 0;
d->info.change_mask = old;
spa_hook_list_join(&d->hooks, &save);
return 0;

View file

@ -434,20 +434,22 @@ static int impl_send_command(void *object, const struct spa_command *command)
static void emit_node_info(struct filter *d, bool full)
{
uint64_t old = full ? d->info.change_mask : 0;
if (full)
d->info.change_mask = d->change_mask_all;
if (d->info.change_mask != 0)
spa_node_emit_info(&d->hooks, &d->info);
d->info.change_mask = 0;
d->info.change_mask = old;
}
static void emit_port_info(struct filter *d, struct port *p, bool full)
{
uint64_t old = full ? p->info.change_mask : 0;
if (full)
p->info.change_mask = p->change_mask_all;
if (p->info.change_mask != 0)
spa_node_emit_port_info(&d->hooks, p->direction, p->id, &p->info);
p->info.change_mask = 0;
p->info.change_mask = old;
}
static int impl_add_listener(void *object,
@ -1465,7 +1467,6 @@ void *pw_filter_add_port(struct pw_filter *filter,
p->change_mask_all = SPA_PORT_CHANGE_MASK_FLAGS |
SPA_PORT_CHANGE_MASK_PROPS;
p->info = SPA_PORT_INFO_INIT();
p->info.change_mask = 0;
p->info.flags = 0;
if (SPA_FLAG_IS_SET(flags, PW_FILTER_PORT_FLAG_ALLOC_BUFFERS))
p->info.flags |= SPA_PORT_FLAG_CAN_ALLOC_BUFFERS;

View file

@ -546,20 +546,22 @@ static int impl_send_command(void *object, const struct spa_command *command)
static void emit_node_info(struct stream *d, bool full)
{
uint64_t old = full ? d->info.change_mask : 0;
if (full)
d->info.change_mask = d->change_mask_all;
if (d->info.change_mask != 0)
spa_node_emit_info(&d->hooks, &d->info);
d->info.change_mask = 0;
d->info.change_mask = old;
}
static void emit_port_info(struct stream *d, bool full)
{
uint64_t old = full ? d->port_info.change_mask : 0;
if (full)
d->port_info.change_mask = d->port_change_mask_all;
if (d->port_info.change_mask != 0)
spa_node_emit_port_info(&d->hooks, d->direction, 0, &d->port_info);
d->port_info.change_mask = 0;
d->port_info.change_mask = old;
}
static int impl_add_listener(void *object,