diff --git a/src/modules/module-jack.c b/src/modules/module-jack.c index 1330f4bd0..bec2b0213 100644 --- a/src/modules/module-jack.c +++ b/src/modules/module-jack.c @@ -237,20 +237,21 @@ notify_clients(struct impl *impl, int notify, } } -static void port_destroy(void *data) +static void port_free(void *data) { struct pw_jack_port *port = data; struct port *p = port->user_data; struct impl *impl = p->impl; + struct jack_client *jc = p->jc; + pw_log_debug("port %p: free", port); - pw_log_debug("port %p: destroy", port); - - notify_clients(impl, jack_notify_PortRegistrationOffCallback, false, "", port->port_id, 0); + if (jc->node->control->active) + notify_clients(impl, jack_notify_PortRegistrationOffCallback, false, "", port->port_id, 0); } static const struct pw_jack_port_events port_listener = { PW_VERSION_JACK_PORT_EVENTS, - .destroy = port_destroy, + .free = port_free, }; static int process_messages(struct client *client); @@ -336,14 +337,16 @@ handle_activate_client(struct client *client) jack_graph_manager_next_stop(mgr); + jc = server->client_table[ref_num]; + if (jc) + notify_client(jc, ref_num, NULL, jack_notify_ActivateClient, true, "", 0, 0); + for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (input_ports[i] != EMPTY); i++) notify_clients(impl, jack_notify_PortRegistrationOnCallback, false, "", input_ports[i], 0); for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (output_ports[i] != EMPTY); i++) notify_clients(impl, jack_notify_PortRegistrationOnCallback, false, "", output_ports[i], 0); - jc = server->client_table[ref_num]; - if (jc) - notify_client(jc, ref_num, NULL, jack_notify_ActivateClient, true, "", 0, 0); + jc->activated = true; CheckWrite(&result, sizeof(int)); return 0; @@ -352,29 +355,51 @@ handle_activate_client(struct client *client) static int client_deactivate(struct impl *impl, int ref_num) { struct jack_server *server = &impl->server; - int fw_ref = server->freewheel_ref_num, i; + int fw_ref = server->freewheel_ref_num, i, j; struct jack_graph_manager *mgr = server->graph_manager; struct jack_connection_manager *conn; - jack_int_t input_ports[PORT_NUM_FOR_CLIENT]; - jack_int_t output_ports[PORT_NUM_FOR_CLIENT]; + struct jack_client *jc; + const jack_int_t *inputs, *outputs; + jack_int_t conns[CONNECTION_NUM_FOR_PORT]; conn = jack_graph_manager_next_start(mgr); - memcpy (input_ports, jack_connection_manager_get_inputs(conn, ref_num), sizeof(input_ports)); - memcpy (output_ports, jack_connection_manager_get_outputs(conn, ref_num), sizeof(input_ports)); - if (jack_connection_manager_is_direct_connection(conn, fw_ref, ref_num)) jack_connection_manager_direct_disconnect(conn, fw_ref, ref_num); if (jack_connection_manager_is_direct_connection(conn, ref_num, fw_ref)) jack_connection_manager_direct_disconnect(conn, ref_num, fw_ref); + inputs = jack_connection_manager_get_inputs(conn, ref_num); + outputs = jack_connection_manager_get_outputs(conn, ref_num); + + for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (inputs[i] != EMPTY); i++) { + memcpy(conns, jack_connection_manager_get_connections(conn, inputs[i]), sizeof(conns)); + for (j = 0; (j < CONNECTION_NUM_FOR_PORT) && (conns[j] != EMPTY); j++) { + jack_connection_manager_disconnect_ports(conn, conns[j], inputs[i]); + notify_clients(impl, jack_notify_PortDisconnectCallback, + false, "", conns[j], inputs[i]); + } + } + for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (outputs[i] != EMPTY); i++) { + memcpy(conns, jack_connection_manager_get_connections(conn, outputs[i]), sizeof(conns)); + for (j = 0; (j < CONNECTION_NUM_FOR_PORT) && (conns[j] != EMPTY); j++) { + jack_connection_manager_disconnect_ports(conn, outputs[i], conns[j]); + notify_clients(impl, jack_notify_PortDisconnectCallback, + false, "", outputs[i], conns[j]); + } + } + + for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (inputs[i] != EMPTY); i++) + notify_clients(impl, jack_notify_PortRegistrationOffCallback, false, "", inputs[i], 0); + for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (outputs[i] != EMPTY); i++) + notify_clients(impl, jack_notify_PortRegistrationOffCallback, false, "", outputs[i], 0); + jack_graph_manager_next_stop(mgr); - for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (input_ports[i] != EMPTY); i++) - notify_clients(impl, jack_notify_PortRegistrationOffCallback, false, "", input_ports[i], 0); - for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (output_ports[i] != EMPTY); i++) - notify_clients(impl, jack_notify_PortRegistrationOffCallback, false, "", output_ports[i], 0); + jc = server->client_table[ref_num]; + if (jc) + jc->activated = false; return 0; } @@ -448,7 +473,8 @@ static void node_destroy(void *data) pw_log_debug("module-jack %p: jack_client %p destroy", impl, jc); - client_deactivate(impl, ref_num); + if (jc->activated) + client_deactivate(impl, ref_num); spa_list_remove(&jc->client_link); spa_list_remove(&jc->node->graph_link); @@ -584,12 +610,14 @@ static void link_destroy(void *data) pw_log_debug("module-jack %p: link %p destroy", impl, ld->link); conn = jack_graph_manager_next_start(mgr); - if (jack_connection_manager_disconnect_ports(conn, src_id, dst_id)) { - pw_log_warn("module-jack %p: ports can't disconnect", impl); + if (jack_connection_manager_is_connected(conn, src_id, dst_id)) { + if (jack_connection_manager_disconnect_ports(conn, src_id, dst_id)) { + pw_log_warn("module-jack %p: ports can't disconnect", impl); + } + notify_clients(impl, jack_notify_PortDisconnectCallback, false, "", src_id, dst_id); } jack_graph_manager_next_stop(mgr); - notify_clients(impl, jack_notify_PortDisconnectCallback, false, "", src_id, dst_id); } static const struct pw_link_events link_events = { diff --git a/src/modules/module-jack/defs.h b/src/modules/module-jack/defs.h index a362b48d6..ac3812513 100644 --- a/src/modules/module-jack/defs.h +++ b/src/modules/module-jack/defs.h @@ -135,7 +135,7 @@ enum jack_notification_type { #define kGetUUIDByClient_size (JACK_CLIENT_NAME_SIZE+1) #define CheckRead(var,size) if(read(client->fd,var,size)!=size) {pw_log_error("read error"); return -1; } -#define CheckWrite(var,size) if(write(client->fd,var,size)!=size) {pw_log_error("write error"); return -1; } +#define CheckWrite(var,size) if(send(client->fd,var,size,MSG_NOSIGNAL)!=size) {pw_log_error("write error"); return -1; } #define CheckSize(expected) { int __size; CheckRead(&__size, sizeof(int)); if (__size != expected) { pw_log_error("CheckSize error size %d != %d", __size, (int)expected); return -1; } } #define jack_error pw_log_error diff --git a/src/modules/module-jack/jack-node.c b/src/modules/module-jack/jack-node.c index 2194ff828..364056b6d 100644 --- a/src/modules/module-jack/jack-node.c +++ b/src/modules/module-jack/jack-node.c @@ -530,9 +530,16 @@ static void port_destroy(void *data) jack_graph_manager_release_port(mgr, port->port_id); } +static void port_free(void *data) +{ + struct port_data *pd = data; + spa_hook_list_call(&pd->listener_list, struct pw_jack_port_events, free); +} + static const struct pw_port_events port_events = { PW_VERSION_PORT_EVENTS, .destroy = port_destroy, + .free = port_free, }; struct pw_jack_port * diff --git a/src/modules/module-jack/jack-node.h b/src/modules/module-jack/jack-node.h index 1443004b2..dfae0e392 100644 --- a/src/modules/module-jack/jack-node.h +++ b/src/modules/module-jack/jack-node.h @@ -75,6 +75,8 @@ struct pw_jack_port_events { uint32_t version; void (*destroy) (void *data); + + void (*free) (void *data); }; struct pw_jack_node * diff --git a/src/modules/module-jack/server.h b/src/modules/module-jack/server.h index 598dc7602..a45132c1e 100644 --- a/src/modules/module-jack/server.h +++ b/src/modules/module-jack/server.h @@ -26,6 +26,7 @@ struct jack_client { int fd; /* notify fd */ struct spa_hook node_listener; struct spa_list client_link; + bool activated; }; struct jack_server { diff --git a/src/modules/module-jack/shared.h b/src/modules/module-jack/shared.h index 943525fe9..b0a5715b1 100644 --- a/src/modules/module-jack/shared.h +++ b/src/modules/module-jack/shared.h @@ -437,6 +437,12 @@ jack_connection_manager_get_outputs(struct jack_connection_manager *conn, int re return GET_ITEMS_FIXED_ARRAY(conn->output_port[ref_num]); } +static inline const jack_int_t * +jack_connection_manager_get_connections(struct jack_connection_manager *conn, int port_index) +{ + return GET_ITEMS_FIXED_ARRAY(conn->connection[port_index]); +} + static inline int jack_connection_manager_get_output_refnum(struct jack_connection_manager *conn, jack_port_id_t port_index) @@ -591,14 +597,10 @@ jack_connection_manager_disconnect_ports(struct jack_connection_manager *conn, pw_log_error("connection %p: ports are not connected", conn); return -1; } - if (jack_connection_manager_disconnect(conn, src_id, dst_id) < 0) { - pw_log_error("connection %p: connection table is full", conn); - return -1; - } - if (jack_connection_manager_disconnect(conn, dst_id, src_id) < 0) { - pw_log_error("connection %p: connection table is full", conn); - return -1; - } + + jack_connection_manager_disconnect(conn, src_id, dst_id); + jack_connection_manager_disconnect(conn, dst_id, src_id); + if (jack_connection_manager_is_loop_path(conn, src_id, dst_id) < 0) jack_connection_manager_dec_feedback_connection(conn, src_id, dst_id); else diff --git a/src/pipewire/port.c b/src/pipewire/port.c index e27363bed..0e3d43008 100644 --- a/src/pipewire/port.c +++ b/src/pipewire/port.c @@ -337,6 +337,9 @@ void pw_port_destroy(struct pw_port *port) spa_list_remove(&port->link); spa_hook_list_call(&node->listener_list, struct pw_node_events, port_removed, port); } + + pw_log_debug("port %p: free", port); + spa_hook_list_call(&port->listener_list, struct pw_port_events, free); free(port); } diff --git a/src/pipewire/port.h b/src/pipewire/port.h index 038f3c52c..88d8995ab 100644 --- a/src/pipewire/port.h +++ b/src/pipewire/port.h @@ -94,6 +94,8 @@ struct pw_port_events { void (*destroy) (void *data); + void (*free) (void *data); + void (*link_added) (void *data, struct pw_link *link); void (*link_removed) (void *data, struct pw_link *link);