diff --git a/pipewire-jack/src/pipewire-jack.c b/pipewire-jack/src/pipewire-jack.c index e0b8e4452..1ec1d4a61 100644 --- a/pipewire-jack/src/pipewire-jack.c +++ b/pipewire-jack/src/pipewire-jack.c @@ -142,7 +142,6 @@ struct object { uint32_t dst_serial; bool src_ours; bool dst_ours; - bool is_complete; struct port *our_input; struct port *our_output; } port_link; @@ -541,6 +540,17 @@ static struct mix *find_mix_peer(struct client *c, uint32_t peer_id) return NULL; } +static struct mix *find_port_peer(struct port *port, uint32_t peer_id) +{ + struct mix *mix; + spa_list_for_each(mix, &port->mix, port_link) { + pw_log_info("%p %d %d", port, mix->peer_id, peer_id); + if (mix->peer_id == peer_id) + return mix; + } + return NULL; +} + static struct mix *find_mix(struct client *c, struct port *port, uint32_t mix_id) { struct mix *mix; @@ -2766,8 +2776,6 @@ static int client_node_port_set_mix_info(void *data, struct client *c = (struct client *) data; struct port *p = GET_PORT(c, direction, port_id); struct mix *mix; - struct object *l; - uint32_t src, dst; int res = 0; if (p == NULL || !p->valid) { @@ -2775,40 +2783,21 @@ static int client_node_port_set_mix_info(void *data, goto exit; } - if ((mix = ensure_mix(c, p, mix_id)) == NULL) { - res = -ENOMEM; - goto exit; - } - mix->peer_id = peer_id; + mix = find_mix(c, p, mix_id); - if (direction == SPA_DIRECTION_INPUT) { - src = peer_id; - dst = p->object->id; - } else { - src = p->object->id; - dst = peer_id; - } - - if ((l = find_link(c, src, dst)) != NULL) { - if (direction == SPA_DIRECTION_INPUT) - mix->peer_port = l->port_link.our_output; - else - mix->peer_port = l->port_link.our_input; - - pw_log_debug("peer port %p %p %p", mix->peer_port, - l->port_link.our_output, l->port_link.our_input); - - if (!l->port_link.is_complete) { - l->port_link.is_complete = true; - pw_log_info("%p: our link %u/%u -> %u/%u completed", c, - l->port_link.src, l->port_link.src_serial, - l->port_link.dst, l->port_link.dst_serial); - queue_notify(c, NOTIFY_TYPE_CONNECT, l, 1, NULL); - queue_notify(c, NOTIFY_TYPE_GRAPH, NULL, 0, NULL); - emit_callbacks(c); + if (peer_id == SPA_ID_INVALID) { + if (mix == NULL) { + res = -ENOENT; + goto exit; } + free_mix(c, mix); + } else { + if (mix != NULL) { + res = -EEXIST; + goto exit; + } + mix = create_mix(c, p, mix_id, peer_id); } - exit: if (res < 0) pw_proxy_error((struct pw_proxy*)c->node, res, spa_strerror(res)); @@ -3366,7 +3355,16 @@ static void registry_event_global(void *data, uint32_t id, if (o->port_link.dst_ours) o->port_link.our_input = p->port.port; - o->port_link.is_complete = !o->port_link.src_ours && !o->port_link.dst_ours; + if (o->port_link.our_input != NULL && + o->port_link.our_output != NULL) { + struct mix *mix; + mix = find_port_peer(o->port_link.our_output, o->port_link.dst); + if (mix != NULL) + mix->peer_port = o->port_link.our_input; + mix = find_port_peer(o->port_link.our_input, o->port_link.src); + if (mix != NULL) + mix->peer_port = o->port_link.our_output; + } pw_log_debug("%p: add link %d %u/%u->%u/%u", c, id, o->port_link.src, o->port_link.src_serial, o->port_link.dst, o->port_link.dst_serial); @@ -3427,14 +3425,11 @@ static void registry_event_global(void *data, uint32_t id, break; case INTERFACE_Link: - pw_log_info("%p: link %u %u/%u -> %u/%u added complete:%d", c, + pw_log_info("%p: link %u %u/%u -> %u/%u added", c, o->id, o->port_link.src, o->port_link.src_serial, - o->port_link.dst, o->port_link.dst_serial, - o->port_link.is_complete); - if (o->port_link.is_complete) { - queue_notify(c, NOTIFY_TYPE_CONNECT, o, 1, NULL); - queue_notify(c, NOTIFY_TYPE_GRAPH, NULL, 0, NULL); - } + o->port_link.dst, o->port_link.dst_serial); + queue_notify(c, NOTIFY_TYPE_CONNECT, o, 1, NULL); + queue_notify(c, NOTIFY_TYPE_GRAPH, NULL, 0, NULL); break; } emit_callbacks(c); @@ -3482,13 +3477,11 @@ static void registry_event_global_remove(void *data, uint32_t id) queue_notify(c, NOTIFY_TYPE_PORTREGISTRATION, o, 0, NULL); break; case INTERFACE_Link: - if (o->port_link.is_complete && - find_type(c, o->port_link.src, INTERFACE_Port, true) != NULL && + if (find_type(c, o->port_link.src, INTERFACE_Port, true) != NULL && find_type(c, o->port_link.dst, INTERFACE_Port, true) != NULL) { pw_log_info("%p: link %u %u/%u -> %u/%u removed", c, o->id, o->port_link.src, o->port_link.src_serial, o->port_link.dst, o->port_link.dst_serial); - o->port_link.is_complete = false; queue_notify(c, NOTIFY_TYPE_CONNECT, o, 0, NULL); queue_notify(c, NOTIFY_TYPE_GRAPH, NULL, 0, NULL); } else { diff --git a/src/modules/module-client-node/client-node.c b/src/modules/module-client-node/client-node.c index cb6a993ea..64c82fe3c 100644 --- a/src/modules/module-client-node/client-node.c +++ b/src/modules/module-client-node/client-node.c @@ -1408,6 +1408,11 @@ static int port_init_mix(void *data, struct pw_impl_port_mix *mix) m->peer_id = mix->peer_id; + if (impl->resource && impl->resource->version >= 4) + pw_client_node_resource_port_set_mix_info(impl->resource, + mix->port.direction, mix->p->port_id, + mix->port.port_id, mix->peer_id, NULL); + pw_log_debug("%p: init mix id:%d io:%p base:%p", impl, mix->id, mix->io, area->map->ptr); @@ -1430,6 +1435,11 @@ static int port_release_mix(void *data, struct pw_impl_port_mix *mix) if ((m = find_mix(port, mix->port.port_id)) == NULL || !m->valid) return -EINVAL; + if (impl->resource && impl->resource->version >= 4) + pw_client_node_resource_port_set_mix_info(impl->resource, + mix->port.direction, mix->p->port_id, + mix->port.port_id, SPA_ID_INVALID, NULL); + pw_map_remove(&impl->io_map, mix->id); m->valid = false; @@ -1515,13 +1525,7 @@ static int impl_mix_port_set_io(void *object, mix->io = data; else mix->io = NULL; - - if (mix->io != NULL && impl->resource && impl->resource->version >= 4) - pw_client_node_resource_port_set_mix_info(impl->resource, - direction, port->port_id, - mix->port.port_id, mix->peer_id, NULL); } - return do_port_set_io(impl, direction, port->port_id, mix->port.port_id, id, data, size); diff --git a/src/modules/module-client-node/remote-node.c b/src/modules/module-client-node/remote-node.c index b3a13d2d0..51e8707eb 100644 --- a/src/modules/module-client-node/remote-node.c +++ b/src/modules/module-client-node/remote-node.c @@ -896,6 +896,47 @@ error_exit: return res; } +static void clear_mix(struct node_data *data, struct mix *mix) +{ + pw_log_debug("port %p: mix clear %d.%d", mix->port, mix->port->port_id, mix->mix_id); + + spa_node_port_set_io(mix->port->mix, mix->mix.port.direction, + mix->mix.port.port_id, SPA_IO_Buffers, NULL, 0); + + spa_list_remove(&mix->link); + + clear_buffers(data, mix); + pw_array_clear(&mix->buffers); + + spa_list_append(&data->free_mix, &mix->link); + pw_impl_port_release_mix(mix->port, &mix->mix); +} + +static int client_node_port_set_mix_info(void *_data, + enum spa_direction direction, uint32_t port_id, + uint32_t mix_id, uint32_t peer_id, const struct spa_dict *props) +{ + struct node_data *data = _data; + struct mix *mix; + + pw_log_debug("%p: %d:%d:%d peer:%d", data, direction, port_id, mix_id, peer_id); + + mix = find_mix(data, direction, port_id, mix_id); + + if (peer_id == SPA_ID_INVALID) { + if (mix == NULL) + return -EINVAL; + clear_mix(data, mix); + } else { + if (mix != NULL) + return -EEXIST; + mix = create_mix(data, direction, port_id, mix_id, peer_id); + if (mix == NULL) + return -errno; + } + return 0; +} + static const struct pw_client_node_events client_node_events = { PW_VERSION_CLIENT_NODE_EVENTS, .transport = client_node_transport, @@ -909,6 +950,7 @@ static const struct pw_client_node_events client_node_events = { .port_use_buffers = client_node_port_use_buffers, .port_set_io = client_node_port_set_io, .set_activation = client_node_set_activation, + .port_set_mix_info = client_node_port_set_mix_info, }; static void do_node_init(struct node_data *data) @@ -934,22 +976,6 @@ static void do_node_init(struct node_data *data) } } -static void clear_mix(struct node_data *data, struct mix *mix) -{ - pw_log_debug("port %p: mix clear %d.%d", mix->port, mix->port->port_id, mix->mix_id); - - spa_node_port_set_io(mix->port->mix, mix->mix.port.direction, - mix->mix.port.port_id, SPA_IO_Buffers, NULL, 0); - - spa_list_remove(&mix->link); - - clear_buffers(data, mix); - pw_array_clear(&mix->buffers); - - spa_list_append(&data->free_mix, &mix->link); - pw_impl_port_release_mix(mix->port, &mix->mix); -} - static void clean_node(struct node_data *d) { struct mix *mix;