diff --git a/daemon/app_supervisor.c b/daemon/app_supervisor.c index 75089e99..02025e54 100644 --- a/daemon/app_supervisor.c +++ b/daemon/app_supervisor.c @@ -2,7 +2,7 @@ /* * LADI Session Handler (ladish) * - * Copyright (C) 2009, 2010, 2011, 2012 Nedko Arnaudov + * Copyright (C) 2009, 2010, 2011, 2012, 2013 Nedko Arnaudov * ************************************************************************** * This file contains implementation of app supervisor object @@ -61,6 +61,13 @@ struct ladish_app unsigned int state; char * dbus_name; struct ladish_app_supervisor * supervisor; + struct list_head clients; +}; + +struct ladish_app_client +{ + struct list_head siblings; + ladish_client_handle client; }; struct ladish_app_supervisor @@ -128,6 +135,27 @@ static int ladish_level_string_to_integer(const char * level) return 255; } +static +struct ladish_app_client * +ladish_app_find_client( + struct ladish_app * app_ptr, + ladish_client_handle client) +{ + struct list_head * node_ptr; + struct ladish_app_client * app_client_ptr; + + list_for_each(node_ptr, &app_ptr->siblings) + { + app_client_ptr = list_entry(node_ptr, struct ladish_app_client, siblings); + if (app_client_ptr->client == client) + { + return app_client_ptr; + } + } + + return NULL; +} + bool ladish_app_supervisor_create( ladish_app_supervisor_handle * supervisor_handle_ptr, @@ -223,6 +251,7 @@ void remove_app_internal(struct ladish_app_supervisor * supervisor_ptr, struct l free(app_ptr->name); free(app_ptr->commandline); free(app_ptr->js_commandline); + ASSERT(list_empty(&app_ptr->clients)); free(app_ptr); } @@ -477,6 +506,8 @@ ladish_app_supervisor_add( app_ptr->supervisor = supervisor_ptr; list_add_tail(&app_ptr->siblings, &supervisor_ptr->applist); + INIT_LIST_HEAD(&app_ptr->siblings); + supervisor_ptr->version++; running = false; @@ -1117,6 +1148,56 @@ void ladish_app_del_pid(ladish_app_handle app_handle, pid_t pid) } } +bool ladish_app_add_client(ladish_app_handle app_handle, ladish_client_handle client) +{ + struct ladish_app_client * app_client_ptr; + + app_client_ptr = malloc(sizeof(struct ladish_app_client)); + if (app_client_ptr == NULL) + { + return false; + } + + ladish_add_ref(client); + app_client_ptr->client = client; + + list_add_tail(&app_ptr->siblings, &app_client_ptr->siblings); + return true; +} + +void ladish_app_del_client(ladish_app_handle app_handle, ladish_client_handle client) +{ + struct ladish_app_client * app_client_ptr; + + app_client_ptr = ladish_app_find_client(app_ptr, client); + if (app_client_ptr == NULL) + { + log_error("Cannot find client '%s' to remove from app '%s'", ladish_client_get_jack_name(client), app_ptr->name); + return; + } + + list_del(&app_client_ptr->siblings); + free(app_client_ptr); + ladish_del_ref(client); +} + +bool ladish_app_enum_clients(ladish_app_handle app_handle, void * context, ladish_app_enum_clients_callback callback) +{ + struct list_head * node_ptr; + struct ladish_app_client * app_client_ptr; + + list_for_each(node_ptr, &app_ptr->siblings) + { + app_client_ptr = list_entry(node_ptr, struct ladish_app_client, siblings); + if (!callback(context, app_client_ptr->client)) + { + return false; + } + } + + return true; +} + bool ladish_app_set_dbus_name(ladish_app_handle app_handle, const char * name) { char * dup; diff --git a/daemon/app_supervisor.h b/daemon/app_supervisor.h index 1b98d7aa..c3be131a 100644 --- a/daemon/app_supervisor.h +++ b/daemon/app_supervisor.h @@ -29,6 +29,7 @@ #define APP_SUPERVISOR_H__712E6589_DCB1_4CE9_9812_4F250D55E8A2__INCLUDED #include "common.h" +#include "client.h" #define LADISH_APP_STATE_STOPPED 0 /**< @brief app is stopped (not running) */ #define LADISH_APP_STATE_STARTED 1 /**< @brief app is running and not stopping */ @@ -96,6 +97,17 @@ typedef bool (* ladish_app_supervisor_enum_callback)( */ typedef void (* ladish_save_complete_callback)(void * context, bool success); +/** + * Type of function that is called during app client enumeration + * + * @param[in] context User defined context that was supplied to ladish_app_supervisor_enum() + * @param[in] client Client handle + * + * @retval true Continue iteration + * @retval false Stop iteration + */ +typedef bool (* ladish_app_enum_clients_callback)(void * context, ladish_client_handle client); + /** * Check whether app level string is valid. * @@ -459,6 +471,36 @@ void ladish_app_add_pid(ladish_app_handle app_handle, pid_t pid); */ void ladish_app_del_pid(ladish_app_handle app_handle, pid_t pid); +/** + * Associate client with app. + * + * @param[in] app_handle Handle of app + * @param[in] client Client to associate with the app + * + * @return success status + */ +bool ladish_app_add_client(ladish_app_handle app_handle, ladish_client_handle client); + +/** + * Deassociate client with app. + * + * @param[in] app_handle Handle of app + * @param[in] client Client to deassociate with the app + */ +void ladish_app_del_client(ladish_app_handle app_handle, ladish_client_handle client); + +/** + * Iterate app clients. + * + * @param[in] app_handle Handle of app + * @param[in] context User defined context to be supplied when the callback suppiled through the @c callback parameter is called + * @param[in] callback Callback to be called for each client + * + * @retval true All clients iterated + * @retval false Iteration stopped because callback returned false + */ +bool ladish_app_enum_clients(ladish_app_handle app_handle, void * context, ladish_app_enum_clients_callback callback); + /** * Set the D-Bus unique name for the app. * diff --git a/daemon/graph.c b/daemon/graph.c index 1326b29b..388b8023 100644 --- a/daemon/graph.c +++ b/daemon/graph.c @@ -1824,7 +1824,7 @@ ladish_client_handle ladish_graph_find_client_by_name(ladish_graph_handle graph_ return NULL; } -ladish_client_handle ladish_graph_find_client_by_app(ladish_graph_handle graph_handle, const uuid_t app_uuid) +ladish_client_handle ladish_graph_find_app_client(ladish_graph_handle graph_handle, const uuid_t app_uuid, const char * name) { struct list_head * node_ptr; struct ladish_graph_client * client_ptr; @@ -1836,11 +1836,14 @@ ladish_client_handle ladish_graph_find_client_by_app(ladish_graph_handle graph_h if (!ladish_client_get_app(client_ptr->client, current_uuid)) continue; - if (uuid_compare(current_uuid, app_uuid) == 0) - { - ladish_add_ref(client_ptr->client); - return client_ptr->client; - } + if (uuid_compare(current_uuid, app_uuid) != 0) + continue; + + if (name != NULL && strcmp(client_ptr->name, name) != 0) + continue; + + ladish_add_ref(client_ptr->client); + return client_ptr->client; } return NULL; diff --git a/daemon/graph.h b/daemon/graph.h index a9ef368c..03fff9b0 100644 --- a/daemon/graph.h +++ b/daemon/graph.h @@ -2,7 +2,7 @@ /* * LADI Session Handler (ladish) * - * Copyright (C) 2009,2010,2011,2012 Nedko Arnaudov + * Copyright (C) 2009,2010,2011,2012,2013 Nedko Arnaudov * ************************************************************************** * This file contains interface to the D-Bus patchbay interface helpers @@ -147,7 +147,7 @@ ladish_port_handle ladish_graph_find_port_by_id(ladish_graph_handle graph_handle ladish_client_handle ladish_graph_find_client_by_jack_id(ladish_graph_handle graph_handle, uint64_t client_id); ladish_port_handle ladish_graph_find_port_by_jack_id(ladish_graph_handle graph_handle, uint64_t port_id, bool room, bool studio); ladish_client_handle ladish_graph_find_client_by_name(ladish_graph_handle graph_handle, const char * name, bool appless); -ladish_client_handle ladish_graph_find_client_by_app(ladish_graph_handle graph_handle, const uuid_t app_uuid); +ladish_client_handle ladish_graph_find_app_client(ladish_graph_handle graph_handle, const uuid_t app_uuid, const char * name); ladish_port_handle ladish_graph_find_port_by_name(ladish_graph_handle graph_handle, ladish_client_handle client_handle, const char * name, void * vgraph_filter); ladish_client_handle ladish_graph_find_client_by_uuid(ladish_graph_handle graph_handle, const uuid_t uuid); ladish_port_handle ladish_graph_find_port_by_uuid(ladish_graph_handle graph_handle, const uuid_t uuid, bool use_link_override_uuids, void * vgraph_filter); diff --git a/daemon/virtualizer.c b/daemon/virtualizer.c index a97e7f97..aaf7594f 100644 --- a/daemon/virtualizer.c +++ b/daemon/virtualizer.c @@ -2,7 +2,7 @@ /* * LADI Session Handler (ladish) * - * Copyright (C) 2009,2010,2011,2012 Nedko Arnaudov + * Copyright (C) 2009,2010,2011,2012,2013 Nedko Arnaudov * ************************************************************************** * This file contains implementation of the graph virtualizer object @@ -280,9 +280,9 @@ static void client_appeared(void * context, uint64_t id, const char * jack_name) bool is_a2j; ladish_app_handle app; uuid_t app_uuid; - const char * name; + char * client_name; pid_t pid; - ladish_graph_handle graph; + ladish_graph_handle vgraph; bool jmcore; log_info("client_appeared(%"PRIu64", %s)", id, jack_name); @@ -290,9 +290,9 @@ static void client_appeared(void * context, uint64_t id, const char * jack_name) a2j_name = a2j_proxy_get_jack_client_name_cached(); is_a2j = a2j_name != NULL && strcmp(a2j_name, jack_name) == 0; - name = jack_name; + client_name = NULL; app = NULL; - graph = NULL; + vgraph = NULL; jmcore = false; if (!graph_proxy_get_client_pid(virtualizer_ptr->jack_graph_proxy, id, &pid)) @@ -312,13 +312,11 @@ static void client_appeared(void * context, uint64_t id, const char * jack_name) } else { - app = ladish_find_app_by_pid(pid, &graph); + app = ladish_find_app_by_pid(pid, &vgraph); if (app != NULL) { ladish_app_get_uuid(app, app_uuid); ASSERT(!uuid_is_null(app_uuid)); - name = ladish_app_get_name(app); - log_info("app name is '%s'", name); } } } @@ -334,17 +332,29 @@ static void client_appeared(void * context, uint64_t id, const char * jack_name) { if (app != NULL) { - client = ladish_graph_find_client_by_app(virtualizer_ptr->jack_graph, app_uuid); + if (!graph_proxy_get_client_original_name( + virtualizer_ptr->jack_graph_proxy, + id, + &client_name)) + { + log_error("Cannot get original name of client %"PRIu64", falling back to \"%s\"", id, jack_name); + } + else + { + log_info("client name is '%s'", client_name); + } + + client = ladish_graph_find_app_client(virtualizer_ptr->jack_graph, app_uuid, client_name != NULL ? client_name : jack_name); if (client == NULL) { - log_info("Lookup by app uuid failed, attempting lookup by name '%s'", name); - goto find_by_name; + log_info("Lookup by app uuid failed, attempting lookup by app name '%s'", ladish_app_get_name(app)); + client = ladish_graph_find_client_by_name(virtualizer_ptr->jack_graph, ladish_app_get_name(app), false); } } else { - find_by_name: - client = ladish_graph_find_client_by_name(virtualizer_ptr->jack_graph, name, true); + /* external client */ + client = ladish_graph_find_client_by_name(virtualizer_ptr->jack_graph, jack_name, true); } } @@ -353,7 +363,7 @@ static void client_appeared(void * context, uint64_t id, const char * jack_name) log_info("found existing client"); if (ladish_client_get_jack_id(client) != 0) { - log_error("Ignoring client with duplicate name '%s' ('%s')", name, jack_name); + log_error("Ignoring client with duplicate name '%s'", jack_name); goto unref_client; } @@ -374,9 +384,9 @@ static void client_appeared(void * context, uint64_t id, const char * jack_name) ladish_client_set_jack_id(client, id); ladish_client_set_jack_name(client, jack_name); - if (!ladish_graph_add_client(virtualizer_ptr->jack_graph, client, name, false)) + if (!ladish_graph_add_client(virtualizer_ptr->jack_graph, client, client_name != NULL ? client_name : jack_name, false)) { - log_error("ladish_graph_add_client() failed to add client %"PRIu64" (%s) to JACK graph", id, name); + log_error("ladish_graph_add_client() failed to add client %"PRIu64" (%s) to JACK graph", id, jack_name); goto unref_client; } @@ -389,12 +399,15 @@ done: if (app != NULL) { /* interlink client and app */ + + ASSERT(pid != 0); ladish_app_add_pid(app, pid); + ladish_app_add_client(app, client); ladish_client_set_pid(client, pid); ladish_client_set_app(client, app_uuid); - ASSERT(graph); - ladish_client_set_vgraph(client, graph); + ASSERT(vgraph != NULL); + ladish_client_set_vgraph(client, vgraph); virtualizer_ptr->our_clients_count++; } else if (jmcore) @@ -477,6 +490,7 @@ static void client_disappeared(void * context, uint64_t id) if (app != NULL) { ladish_app_del_pid(app, pid); + ladish_app_del_client(app, client); } else { @@ -838,7 +852,7 @@ port_appeared( { if (has_app) { - vclient = ladish_graph_find_client_by_app(vgraph, app_uuid); + vclient = ladish_graph_find_app_client(vgraph, app_uuid, NULL); if (vclient == NULL) { log_info("Lookup by app uuid failed, attempting lookup by name '%s'", vclient_name); @@ -1294,7 +1308,7 @@ ladish_virtualizer_is_hidden_app( return false; } - client = ladish_graph_find_client_by_app(jack_graph, app_uuid); + client = ladish_graph_find_app_client(jack_graph, app_uuid, NULL); if (client == NULL) { log_info("App without JACK client is treated as hidden one"); @@ -1440,7 +1454,7 @@ ladish_virtualizer_remove_app( ladish_graph_iterate_nodes(jack_graph, &ctx, NULL, remove_app_port, NULL); - client = ladish_graph_find_client_by_app(jack_graph, app_uuid); + client = ladish_graph_find_app_client(jack_graph, app_uuid, NULL); if (client == NULL) { log_info("removing app without JACK client"); @@ -1518,14 +1532,14 @@ ladish_virtualizer_rename_app( { ladish_client_handle client; - client = ladish_graph_find_client_by_app(vgraph, uuid); + client = ladish_graph_find_app_client(vgraph, uuid, NULL); if (client != NULL) { ladish_graph_rename_client(vgraph, client, new_app_name); ladish_del_ref(client); } - client = ladish_graph_find_client_by_app(g_studio.jack_graph, uuid); + client = ladish_graph_find_app_client(g_studio.jack_graph, uuid, NULL); if (client != NULL) { ladish_graph_rename_client(g_studio.jack_graph, client, new_app_name);