diff --git a/src/modules/module-client-node/client-node.c b/src/modules/module-client-node/client-node.c index 27a6bcde1..688d8814a 100644 --- a/src/modules/module-client-node/client-node.c +++ b/src/modules/module-client-node/client-node.c @@ -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); diff --git a/src/pipewire/impl-link.c b/src/pipewire/impl-link.c index e38447c9d..9dadd6977 100644 --- a/src/pipewire/impl-link.c +++ b/src/pipewire/impl-link.c @@ -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); diff --git a/src/pipewire/impl-port.c b/src/pipewire/impl-port.c index 3666dc154..e33359aac 100644 --- a/src/pipewire/impl-port.c +++ b/src/pipewire/impl-port.c @@ -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);