From 79c75fd07bec3ba6e33dcb5fce11aba37a20e601 Mon Sep 17 00:00:00 2001 From: Nedko Arnaudov Date: Sun, 7 Nov 2010 19:42:12 +0200 Subject: [PATCH] ladishd: properly handle stopping and removal of apps with a2j ports --- daemon/graph.c | 31 ++++++++++++ daemon/graph.h | 1 + daemon/port.c | 34 +++++++++++++ daemon/port.h | 5 ++ daemon/virtualizer.c | 110 +++++++++++++++++++++++++++++++++++++++---- 5 files changed, 171 insertions(+), 10 deletions(-) diff --git a/daemon/graph.c b/daemon/graph.c index fd71d3ee..a823160a 100644 --- a/daemon/graph.c +++ b/daemon/graph.c @@ -1786,6 +1786,37 @@ ladish_port_handle ladish_graph_find_port_by_jack_id(ladish_graph_handle graph_h return port_ptr->port; } +bool ladish_graph_client_has_visible_app_port(ladish_graph_handle graph_handle, ladish_client_handle client_handle, const uuid_t app_uuid) +{ + struct ladish_graph_client * client_ptr; + struct list_head * node_ptr; + struct ladish_graph_port * port_ptr; + + client_ptr = ladish_graph_find_client(graph_ptr, client_handle); + if (client_ptr == NULL) + { + ASSERT_NO_PASS; + return false; + } + + list_for_each(node_ptr, &client_ptr->ports) + { + port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_client); + if (port_ptr->hidden) + { + continue; + } + + if (ladish_port_belongs_to_app(port_ptr->port, app_uuid)) + { + ASSERT(!client_ptr->hidden); + return true; + } + } + + return false; +} + ladish_client_handle ladish_graph_remove_port( ladish_graph_handle graph_handle, diff --git a/daemon/graph.h b/daemon/graph.h index 6fd19fb1..c5092398 100644 --- a/daemon/graph.h +++ b/daemon/graph.h @@ -174,6 +174,7 @@ void ladish_graph_show_connection(ladish_graph_handle graph_handle, uint64_t con void ladish_try_connect_hidden_connections(ladish_graph_handle graph_handle); void ladish_graph_hide_non_virtual(ladish_graph_handle graph_handle); void ladish_graph_get_port_uuid(ladish_graph_handle graph, ladish_port_handle port, uuid_t uuid_ptr); +bool ladish_graph_client_has_visible_app_port(ladish_graph_handle graph, ladish_client_handle client, const uuid_t app_uuid); void ladish_graph_dump(ladish_graph_handle graph_handle); diff --git a/daemon/port.c b/daemon/port.c index 19cc5539..4590d8ce 100644 --- a/daemon/port.c +++ b/daemon/port.c @@ -31,6 +31,7 @@ struct ladish_port { int refcount; uuid_t uuid; /* The UUID of the port */ + uuid_t app_uuid; /* The UUID of the app that owns this client */ bool link; /* Whether the port is studio-room link port */ uint64_t jack_id; /* JACK port ID. */ uint64_t jack_id_room; /* JACK port ID in room. valid only for link ports */ @@ -71,6 +72,8 @@ ladish_port_create( uuid_copy(port_ptr->uuid, uuid_ptr); } + uuid_clear(port_ptr->app_uuid); + port_ptr->jack_id = 0; port_ptr->jack_id_room = 0; port_ptr->link = link; @@ -169,4 +172,35 @@ void * ladish_port_get_vgraph(ladish_port_handle port_handle) return port_ptr->vgraph; } +void ladish_port_set_app(ladish_port_handle port_handle, const uuid_t app_uuid) +{ + uuid_copy(port_ptr->app_uuid, app_uuid); +} + +bool ladish_port_get_app(ladish_port_handle port_handle, uuid_t app_uuid) +{ + if (uuid_is_null(port_ptr->app_uuid)) + { + return false; + } + + uuid_copy(app_uuid, port_ptr->app_uuid); + return true; +} + +bool ladish_port_has_app(ladish_port_handle port_handle) +{ + return !uuid_is_null(port_ptr->app_uuid); +} + +bool ladish_port_belongs_to_app(ladish_port_handle port_handle, const uuid_t app_uuid) +{ + if (uuid_is_null(port_ptr->app_uuid)) + { + return false; + } + + return uuid_compare(port_ptr->app_uuid, app_uuid) == 0; +} + #undef port_ptr diff --git a/daemon/port.h b/daemon/port.h index 336a7d52..264835cf 100644 --- a/daemon/port.h +++ b/daemon/port.h @@ -50,4 +50,9 @@ bool ladish_port_is_link(ladish_port_handle port_handle); void ladish_port_set_vgraph(ladish_port_handle port_handle, void * vgraph); void * ladish_port_get_vgraph(ladish_port_handle port_handle); +void ladish_port_set_app(ladish_port_handle port, const uuid_t app_uuid); +bool ladish_port_get_app(ladish_port_handle port, uuid_t app_uuid); +bool ladish_port_has_app(ladish_port_handle port); +bool ladish_port_belongs_to_app(ladish_port_handle port, const uuid_t app_uuid); + #endif /* #ifndef PORT_H__62F81E7C_91FA_44AB_94A9_E0E2D226ED58__INCLUDED */ diff --git a/daemon/virtualizer.c b/daemon/virtualizer.c index 4803fe8f..4f451602 100644 --- a/daemon/virtualizer.c +++ b/daemon/virtualizer.c @@ -216,7 +216,6 @@ lookup_port( ladish_graph_handle * vgraph_ptr) { ladish_port_handle port; - ladish_client_handle jclient; ladish_graph_handle vgraph; port = ladish_graph_find_port_by_jack_id(virtualizer_ptr->jack_graph, port_id, true, true); @@ -226,14 +225,7 @@ lookup_port( return false; } - jclient = ladish_graph_get_port_client(virtualizer_ptr->jack_graph, port); - if (jclient == NULL) - { - log_error("Port %"PRIu64" without jack client was (dis)connected", port_id); - return false; - } - - vgraph = ladish_client_get_vgraph(jclient); + vgraph = ladish_port_get_vgraph(port); if (vgraph == NULL) { vgraph = find_link_port_vgraph_by_jack_id(virtualizer_ptr, port_id, NULL); @@ -627,6 +619,13 @@ port_appeared( goto free_alsa_names; } + /* for normal ports, one can find the app_uuid through the jack client, + but for a2j ports the jack client is shared between graphs */ + if (has_app) + { + ladish_port_set_app(port, app_uuid); + } + ladish_client_set_jack_id(vclient, client_id); ladish_graph_adjust_port(vgraph, port, type, flags); ladish_graph_show_port(vgraph, port); @@ -642,9 +641,13 @@ port_appeared( /* set port jack id so invisible connections to/from it can be restored */ ladish_port_set_jack_id(port, port_id); - /* for normal ports, one can find the vgraph through the jack client, + /* for normal ports, one can find the vgraph and app_uuid through the jack client, but for a2j ports the jack client is shared between graphs */ ladish_port_set_vgraph(port, vgraph); + if (has_app) + { + ladish_port_set_app(port, app_uuid); + } if (!ladish_graph_add_port(virtualizer_ptr->jack_graph, jack_client, port, jack_port_name, type, flags, false)) { @@ -1099,6 +1102,19 @@ ladish_virtualizer_get_our_clients_count( return virtualizer_ptr->our_clients_count; } +static bool app_has_a2j_ports(ladish_graph_handle jack_graph, const uuid_t app_uuid) +{ + ladish_client_handle a2jclient; + + a2jclient = ladish_graph_find_client_by_uuid(jack_graph, g_a2j_uuid); + if (a2jclient == NULL) + { + return false; + } + + return ladish_graph_client_has_visible_app_port(jack_graph, a2jclient, app_uuid); +} + bool ladish_virtualizer_is_hidden_app( ladish_graph_handle jack_graph, @@ -1115,6 +1131,12 @@ ladish_virtualizer_is_hidden_app( //ladish_graph_dump(g_studio.jack_graph); + if (app_has_a2j_ports(jack_graph, app_uuid)) + { + log_info("app '%s' still has a2j ports", app_name); + return false; + } + jclient = ladish_graph_find_client_by_app(jack_graph, app_uuid); if (jclient == NULL) { @@ -1177,6 +1199,68 @@ ladish_virtualizer_is_hidden_app( return true; } +struct app_remove_context +{ + uuid_t app_uuid; + const char * app_name; +}; + +#define app_info_ptr ((struct app_remove_context *)context) + +static +bool +remove_app_port( + void * context, + ladish_graph_handle graph_handle, + void * client_iteration_context_ptr, + ladish_client_handle client_handle, + const char * client_name, + ladish_port_handle port_handle, + const char * port_name, + uint32_t port_type, + uint32_t port_flags) +{ + ladish_graph_handle vgraph; + ladish_client_handle vclient; + + if (!ladish_port_belongs_to_app(port_handle, app_info_ptr->app_uuid)) + { + return true; + } + + //log_info("removing port '%s':'%s' (JACK) of app '%s'", client_name, port_name, app_info_ptr->app_name); + + vgraph = ladish_port_get_vgraph(port_handle); + if (vgraph == NULL) + { + log_error("port '%s':'%s' of app '5s' has no vgraph", client_name, port_name, app_info_ptr->app_name); + ASSERT_NO_PASS; + return true; + } + + vclient = ladish_graph_get_port_client(vgraph, port_handle); + if (vgraph == NULL) + { + log_error("app port '%s':'%s' not found in vgraph '%s'", client_name, port_name, ladish_graph_get_description(vgraph)); + ASSERT_NO_PASS; + return true; + } + + log_info( + "removing %s %s port %p of app '%s' ('%s':'%s' in %s)", + port_type == JACKDBUS_PORT_TYPE_AUDIO ? "audio" : "midi", + JACKDBUS_PORT_IS_INPUT(port_flags) ? "input" : "output", + port_handle, + app_info_ptr->app_name, + ladish_graph_get_client_name(vgraph, vclient), + ladish_graph_get_port_name(vgraph, port_handle), + ladish_graph_get_description(vgraph)); + + return true; +} + +#undef app_info_ptr + void ladish_virtualizer_remove_app( ladish_graph_handle jack_graph, @@ -1190,9 +1274,15 @@ ladish_virtualizer_remove_app( bool is_empty; uuid_t jclient_uuid; bool is_a2j; + struct app_remove_context ctx; //ladish_graph_dump(g_studio.jack_graph); + uuid_copy(ctx.app_uuid, app_uuid); + ctx.app_name = app_name; + + ladish_graph_iterate_nodes(jack_graph, false, NULL, &ctx, NULL, remove_app_port, NULL); + jclient = ladish_graph_find_client_by_app(jack_graph, app_uuid); if (jclient == NULL) {