jack: set global_mix safely

Keep track of the active number of mixer ports and update the global mix
io in sync with the data thread because that is where we will check the
state of the global mix io.

This is mostly important for output ports. When removing all links from
an output port, we first will clear all the mixer io and then remove the
global mixer with client_node_port_set_mix_info(). If we don't clear the
io before that, the data thread will be using that buffers as they are
cleared.

See !1915
This commit is contained in:
Wim Taymans 2024-02-21 12:40:00 +01:00
parent c58e187590
commit bb887cd5c5

View file

@ -570,7 +570,15 @@ do_mix_set_io(struct spa_loop *loop, bool async, uint32_t seq,
const void *data, size_t size, void *user_data)
{
const struct io_info *info = data;
struct port *port = info->mix->port;
info->mix->io = info->data;
if (info->mix->io) {
if (port->n_mix++ == 0 && port->global_mix != NULL)
port->global_mix->io = &port->io;
} else {
if (--port->n_mix == 0 && port->global_mix != NULL)
port->global_mix->io = NULL;
}
return 0;
}
@ -591,10 +599,11 @@ static void init_mix(struct mix *mix, uint32_t mix_id, struct port *port, uint32
mix->io = NULL;
mix->n_buffers = 0;
spa_list_init(&mix->queue);
if (mix_id == SPA_ID_INVALID)
if (mix_id == SPA_ID_INVALID) {
port->global_mix = mix;
else if (port->n_mix++ == 0 && port->global_mix != NULL)
mix_set_io(port->global_mix, &port->io);
if (port->n_mix > 0)
mix_set_io(port->global_mix, &port->io);
}
}
static struct mix *find_mix_peer(struct client *c, uint32_t peer_id)
{
@ -681,8 +690,6 @@ static void free_mix(struct client *c, struct mix *mix)
spa_list_remove(&mix->port_link);
if (mix->id == SPA_ID_INVALID)
port->global_mix = NULL;
else if (--port->n_mix == 0 && port->global_mix != NULL)
mix_set_io(port->global_mix, NULL);
spa_list_remove(&mix->link);
spa_list_append(&c->free_mix, &mix->link);
}