mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-04 13:30:12 -05:00
impl-link: handle mixer failures better
It is possible that the mixer input can't be created because of hitting the max limits of dsp mixer or client-node. Make sure we handle those errors, destroy the link and clean up properly.
This commit is contained in:
parent
a67f38f790
commit
7e387d842b
3 changed files with 38 additions and 25 deletions
|
|
@ -219,6 +219,8 @@ static struct mix *find_mix(struct port *p, uint32_t mix_id)
|
|||
if (mix_id >= len) {
|
||||
size_t need = sizeof(struct mix) * (mix_id + 1 - len);
|
||||
void *ptr = pw_array_add(&p->mix, need);
|
||||
if (ptr == NULL)
|
||||
return NULL;
|
||||
memset(ptr, 0, need);
|
||||
}
|
||||
mix = pw_array_get_unchecked(&p->mix, mix_id, struct mix);
|
||||
|
|
|
|||
|
|
@ -451,7 +451,7 @@ static int port_set_io(struct pw_impl_link *this, struct pw_impl_port *port, uin
|
|||
return res;
|
||||
}
|
||||
|
||||
static int select_io(struct pw_impl_link *this)
|
||||
static void select_io(struct pw_impl_link *this)
|
||||
{
|
||||
struct impl *impl = SPA_CONTAINER_OF(this, struct impl, this);
|
||||
struct spa_io_buffers *io;
|
||||
|
|
@ -461,13 +461,9 @@ static int select_io(struct pw_impl_link *this)
|
|||
io = this->rt.out_mix.io;
|
||||
if (io == NULL)
|
||||
io = &impl->io;
|
||||
if (io == NULL)
|
||||
return -EIO;
|
||||
|
||||
this->io = io;
|
||||
*this->io = SPA_IO_BUFFERS_INIT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_allocation(struct pw_impl_link *this)
|
||||
|
|
@ -1229,6 +1225,16 @@ struct pw_impl_link *pw_context_create_link(struct pw_context *context,
|
|||
spa_hook_list_init(&this->listener_list);
|
||||
|
||||
impl->format_filter = format_filter;
|
||||
this->info.format = NULL;
|
||||
this->info.props = &this->properties->dict;
|
||||
|
||||
this->rt.out_mix.peer_id = input->global->id;
|
||||
this->rt.in_mix.peer_id = output->global->id;
|
||||
|
||||
if ((res = pw_impl_port_init_mix(output, &this->rt.out_mix)) < 0)
|
||||
goto error_output_mix;
|
||||
if ((res = pw_impl_port_init_mix(input, &this->rt.in_mix)) < 0)
|
||||
goto error_input_mix;
|
||||
|
||||
pw_impl_port_add_listener(input, &impl->input_port_listener, &input_port_events, impl);
|
||||
pw_impl_node_add_listener(input_node, &impl->input_node_listener, &input_node_events, impl);
|
||||
|
|
@ -1245,19 +1251,9 @@ struct pw_impl_link *pw_context_create_link(struct pw_context *context,
|
|||
spa_list_append(&output->links, &this->output_link);
|
||||
spa_list_append(&input->links, &this->input_link);
|
||||
|
||||
this->info.format = NULL;
|
||||
this->info.props = &this->properties->dict;
|
||||
|
||||
impl->io = SPA_IO_BUFFERS_INIT;
|
||||
|
||||
this->rt.out_mix.peer_id = input->global->id;
|
||||
this->rt.in_mix.peer_id = output->global->id;
|
||||
|
||||
pw_impl_port_init_mix(output, &this->rt.out_mix);
|
||||
pw_impl_port_init_mix(input, &this->rt.in_mix);
|
||||
|
||||
if ((res = select_io(this)) < 0)
|
||||
goto error_no_io;
|
||||
select_io(this);
|
||||
|
||||
if (this->feedback) {
|
||||
impl->inode = output_node;
|
||||
|
|
@ -1317,8 +1313,12 @@ error_work_queue:
|
|||
res = -errno;
|
||||
pw_log_debug("work queue failed: %m");
|
||||
goto error_free;
|
||||
error_no_io:
|
||||
pw_log_debug("%p: can't set io %d (%s)", this, res, spa_strerror(res));
|
||||
error_output_mix:
|
||||
pw_log_error("%p: can't get output mix %d (%s)", this, res, spa_strerror(res));
|
||||
goto error_free;
|
||||
error_input_mix:
|
||||
pw_log_error("%p: can't get input mix %d (%s)", this, res, spa_strerror(res));
|
||||
pw_impl_port_release_mix(output, &this->rt.out_mix);
|
||||
goto error_free;
|
||||
error_free:
|
||||
free(impl);
|
||||
|
|
|
|||
|
|
@ -214,16 +214,16 @@ int pw_impl_port_init_mix(struct pw_impl_port *port, struct pw_impl_port_mix *mi
|
|||
if (port_id == SPA_ID_INVALID)
|
||||
return -errno;
|
||||
|
||||
if ((res = spa_node_add_port(port->mix, port->direction, port_id, NULL)) < 0 &&
|
||||
res != -ENOTSUP)
|
||||
goto error_remove_map;
|
||||
|
||||
mix->port.direction = port->direction;
|
||||
mix->port.port_id = port_id;
|
||||
|
||||
spa_list_append(&port->mix_list, &mix->link);
|
||||
port->n_mix++;
|
||||
mix->p = port;
|
||||
|
||||
spa_node_add_port(port->mix, port->direction, port_id, NULL);
|
||||
|
||||
res = pw_impl_port_call_init_mix(port, mix);
|
||||
if ((res = pw_impl_port_call_init_mix(port, mix)) < 0)
|
||||
goto error_remove_port;
|
||||
|
||||
/* set the same format on the mixer as on the port if any */
|
||||
{
|
||||
|
|
@ -242,11 +242,20 @@ int pw_impl_port_init_mix(struct pw_impl_port *port, struct pw_impl_port_mix *mi
|
|||
}
|
||||
}
|
||||
|
||||
spa_list_append(&port->mix_list, &mix->link);
|
||||
port->n_mix++;
|
||||
|
||||
pw_log_debug("%p: init mix n_mix:%d %d.%d io:%p: (%s)", port,
|
||||
port->n_mix, port->port_id, mix->port.port_id,
|
||||
mix->io, spa_strerror(res));
|
||||
|
||||
return res;
|
||||
|
||||
error_remove_port:
|
||||
spa_node_remove_port(port->mix, port->direction, port_id);
|
||||
error_remove_map:
|
||||
pw_map_remove(&port->mix_port_map, port_id);
|
||||
return res;
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
|
|
@ -261,7 +270,9 @@ int pw_impl_port_release_mix(struct pw_impl_port *port, struct pw_impl_port_mix
|
|||
|
||||
res = pw_impl_port_call_release_mix(port, mix);
|
||||
|
||||
spa_node_remove_port(port->mix, port->direction, port_id);
|
||||
if ((res = spa_node_remove_port(port->mix, port->direction, port_id)) < 0 &&
|
||||
res != -ENOTSUP)
|
||||
pw_log_warn("can't remove mix port %d: %s", port_id, spa_strerror(res));
|
||||
|
||||
pw_log_debug("%p: release mix %d %d.%d", port,
|
||||
port->n_mix, port->port_id, mix->port.port_id);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue