diff --git a/daemon/cmd_create_room.c b/daemon/cmd_create_room.c index 88e3fb60..99d2753a 100644 --- a/daemon/cmd_create_room.c +++ b/daemon/cmd_create_room.c @@ -27,7 +27,6 @@ #include "cmd.h" #include "studio_internal.h" #include "../dbus/error.h" -#include "../proxies/jmcore_proxy.h" #include "control.h" struct ladish_command_create_room @@ -37,96 +36,11 @@ struct ladish_command_create_room char * template_name; }; -struct add_room_ports_context -{ - ladish_client_handle room_client; - ladish_graph_handle room_graph; -}; - -#define add_room_ports_context_ptr ((struct add_room_ports_context *)context) - -static -bool -ladish_studio_add_room_ports( - void * context, - ladish_port_handle port_handle, - const char * port_name, - uint32_t port_type, - uint32_t port_flags) -{ - uuid_t uuid_in_studio; - uuid_t uuid_in_room; - char uuid_in_studio_str[37]; - char uuid_in_room_str[37]; - bool room_input; - const char * input_port; - const char * output_port; - - //log_info("Studio room port \"%s\"", port_name); - - if (JACKDBUS_PORT_IS_INPUT(port_flags)) - { - JACKDBUS_PORT_CLEAR_INPUT(port_flags); - JACKDBUS_PORT_SET_OUTPUT(port_flags); - room_input = true; - } - else if (JACKDBUS_PORT_IS_OUTPUT(port_flags)) - { - JACKDBUS_PORT_CLEAR_OUTPUT(port_flags); - JACKDBUS_PORT_SET_INPUT(port_flags); - room_input = false; - } - else - { - log_error("room link port with bad flags %"PRIu32, port_flags); - return false; - } - - if (!ladish_graph_add_port(g_studio.studio_graph, add_room_ports_context_ptr->room_client, port_handle, port_name, port_type, port_flags, true)) - { - log_error("ladish_graph_add_port() failed to add link port to studio graph"); - return false; - } - - ladish_graph_get_port_uuid(add_room_ports_context_ptr->room_graph, port_handle, uuid_in_room); - ladish_graph_get_port_uuid(g_studio.studio_graph, port_handle, uuid_in_studio); - - uuid_unparse(uuid_in_room, uuid_in_room_str); - uuid_unparse(uuid_in_studio, uuid_in_studio_str); - - if (room_input) - { - input_port = uuid_in_room_str; - output_port = uuid_in_studio_str; - log_info("room input port %s is linked to studio output port %s", input_port, output_port); - } - else - { - input_port = uuid_in_studio_str; - output_port = uuid_in_room_str; - log_info("studio input port %s is linked to room output port %s", input_port, output_port); - } - - if (!jmcore_proxy_create_link(port_type == JACKDBUS_PORT_TYPE_MIDI, input_port, output_port)) - { - log_error("jmcore_proxy_create_link() failed."); - return false; - } - - return true; -} - -#undef add_room_ports_context_ptr #define cmd_ptr ((struct ladish_command_create_room *)cmd_context) static bool run(void * cmd_context) { ladish_room_handle room; - char room_dbus_name[1024]; - ladish_client_handle room_client; - uuid_t room_uuid; - ladish_graph_handle room_graph; - struct add_room_ports_context context; ASSERT(cmd_ptr->command.state == LADISH_COMMAND_STATE_PENDING); @@ -139,60 +53,26 @@ static bool run(void * cmd_context) goto fail; } - g_studio.room_count++; - - sprintf(room_dbus_name, DBUS_BASE_PATH "/Room%u", g_studio.room_count); - - if (!ladish_room_create(NULL, cmd_ptr->room_name, room, room_dbus_name, &room)) + if (!ladish_room_create(NULL, cmd_ptr->room_name, room, g_studio.studio_graph, &room)) { log_error("ladish_room_create() failed."); - goto fail_decrement_room_count; + goto fail; } - room_graph = ladish_room_get_graph(room); - if (g_studio.virtualizer != NULL) + if (ladish_studio_is_started()) { - ladish_virtualizer_set_graph_connection_handlers(g_studio.virtualizer, room_graph); + if (!ladish_room_start(room, ladish_studio_get_virtualizer())) + { + log_error("ladish_room_start() failed"); + goto fail_destroy_room; + } } - ladish_room_get_uuid(room, room_uuid); - - if (!ladish_client_create(room_uuid, &room_client)) - { - log_error("ladish_client_create() failed."); - goto fail_destroy_room; - } - - if (!ladish_graph_add_client(g_studio.studio_graph, room_client, cmd_ptr->room_name, false)) - { - log_error("ladish_graph_add_client() failed to add room client to studio graph."); - goto fail_destroy_room_client; - } - - context.room_client = room_client; - context.room_graph = room_graph; - - if (!ladish_room_iterate_link_ports(room, &context, ladish_studio_add_room_ports)) - { - log_error("Creation of studio room link ports failed."); - goto fail_remove_room_client; - } - - list_add_tail(ladish_room_get_list_node(room), &g_studio.rooms); - - ladish_studio_emit_room_appeared(room); - cmd_ptr->command.state = LADISH_COMMAND_STATE_DONE; return true; -fail_remove_room_client: - ladish_graph_remove_client(g_studio.studio_graph, room_client); -fail_destroy_room_client: - ladish_client_destroy(room_client); fail_destroy_room: ladish_room_destroy(room); -fail_decrement_room_count: - g_studio.room_count--; fail: return false; } diff --git a/daemon/cmd_delete_room.c b/daemon/cmd_delete_room.c index 19ab4dea..212676b7 100644 --- a/daemon/cmd_delete_room.c +++ b/daemon/cmd_delete_room.c @@ -27,7 +27,6 @@ #include "cmd.h" #include "studio_internal.h" #include "../dbus/error.h" -#include "../proxies/jmcore_proxy.h" struct ladish_command_delete_room { @@ -35,60 +34,12 @@ struct ladish_command_delete_room char * name; }; -static -bool -uninit_room_ports( - void * context, - 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) -{ - uuid_t uuid_in_room; - char uuid_in_room_str[37]; - - if (ladish_port_is_link(port_handle)) - { - log_info("link port %s", port_name); - - ladish_graph_get_port_uuid(ladish_room_get_graph(context), port_handle, uuid_in_room); - uuid_unparse(uuid_in_room, uuid_in_room_str); - jmcore_proxy_destroy_link(uuid_in_room_str); - } - else - { - log_info("jack port %s", port_name); - } - - return true; -} - -static void remove_port_callback(ladish_port_handle port) -{ - ladish_client_handle jack_client; - - jack_client = ladish_graph_remove_port(g_studio.jack_graph, port); - ASSERT(jack_client != NULL); /* room app port not found in jack graph */ - if (ladish_graph_client_is_empty(g_studio.jack_graph, jack_client)) - { - ladish_graph_remove_client(g_studio.jack_graph, jack_client); - } -} - #define cmd_ptr ((struct ladish_command_delete_room *)context) static bool run(void * context) { struct list_head * node_ptr; ladish_room_handle room; - uuid_t room_uuid; - ladish_client_handle room_client; - unsigned int running_app_count; - ladish_app_supervisor_handle supervisor; - ladish_graph_handle graph; if (cmd_ptr->command.state == LADISH_COMMAND_STATE_PENDING) { @@ -108,55 +59,23 @@ static bool run(void * context) return false; found: - supervisor = ladish_room_get_app_supervisor(room); - graph = ladish_room_get_graph(room); - ladish_room_get_uuid(room, room_uuid); - room_client = ladish_graph_find_client_by_uuid(g_studio.studio_graph, room_uuid); - ASSERT(room_client != NULL); - if (cmd_ptr->command.state == LADISH_COMMAND_STATE_PENDING) { - ladish_graph_clear_persist(graph); - ladish_graph_iterate_nodes(ladish_room_get_graph(room), false, NULL, room, NULL, uninit_room_ports, NULL); - ladish_app_supervisor_stop(supervisor); - + ladish_room_initiate_stop(room, true); cmd_ptr->command.state = LADISH_COMMAND_STATE_WAITING; return true; } ASSERT(cmd_ptr->command.state == LADISH_COMMAND_STATE_WAITING); - running_app_count = ladish_app_supervisor_get_running_app_count(supervisor); - if (running_app_count != 0) + if (!ladish_room_stopped(room)) { - log_info("there are %u running app(s) in room \"%s\"", running_app_count, cmd_ptr->name); return true; } - if (!ladish_graph_looks_empty(graph)) - { - log_info("the room \"%s\" graph is still not empty", cmd_ptr->name); - return true; - } - - if (!ladish_graph_client_looks_empty(g_studio.studio_graph, room_client)) - { - log_info("the room \"%s\" studio client still does not look empty", cmd_ptr->name); - return true; - } - - /* ladish_graph_dump(graph); */ /* ladish_graph_dump(g_studio.studio_graph); */ /* ladish_graph_dump(g_studio.jack_graph); */ - ladish_graph_clear(graph, remove_port_callback); - - list_del(node_ptr); - ladish_studio_emit_room_disappeared(room); - - ladish_graph_remove_client(g_studio.studio_graph, room_client); - ladish_client_destroy(room_client); - ladish_room_destroy(room); ladish_graph_dump(g_studio.studio_graph); diff --git a/daemon/cmd_start_studio.c b/daemon/cmd_start_studio.c index 62769f41..585164e8 100644 --- a/daemon/cmd_start_studio.c +++ b/daemon/cmd_start_studio.c @@ -38,6 +38,11 @@ struct ladish_command_start_studio uint64_t deadline; }; +static bool start_room(void * context, ladish_room_handle room) +{ + return ladish_room_start(room, context); +} + #define cmd_ptr ((struct ladish_command_start_studio *)context) static bool run(void * context) @@ -113,6 +118,8 @@ static bool run(void * context) ladish_studio_on_event_jack_started(); /* fetch configuration and announce start */ + ladish_studio_iterate_rooms(ladish_studio_get_virtualizer(), start_room); + cmd_ptr->command.state = LADISH_COMMAND_STATE_DONE; return true; } diff --git a/daemon/cmd_stop_studio.c b/daemon/cmd_stop_studio.c index a5cbc79c..34060a12 100644 --- a/daemon/cmd_stop_studio.c +++ b/daemon/cmd_stop_studio.c @@ -32,9 +32,10 @@ #include "../common/time.h" #include "studio.h" -#define STOP_STATE_WAITING_FOR_JACK_CLIENTS_DISAPPEAR 1 -#define STOP_STATE_WAITING_FOR_CHILDS_TERMINATION 2 -#define STOP_STATE_WAITING_FOR_JACK_SERVER_STOP 3 +#define STOP_STATE_WAITING_FOR_ROOM_STOP 1 +#define STOP_STATE_WAITING_FOR_JACK_CLIENTS_DISAPPEAR 2 +#define STOP_STATE_WAITING_FOR_CHILDS_TERMINATION 3 +#define STOP_STATE_WAITING_FOR_JACK_SERVER_STOP 4 struct ladish_command_stop_studio { @@ -43,6 +44,17 @@ struct ladish_command_stop_studio unsigned int stop_state; }; +static bool stop_room(void * context, ladish_room_handle room) +{ + ladish_room_initiate_stop(room, false); + return true; +} + +static bool room_stopped(void * context, ladish_room_handle room) +{ + return ladish_room_stopped(room); +} + #define cmd_ptr ((struct ladish_command_stop_studio *)context) static bool run(void * context) @@ -67,9 +79,26 @@ static bool run(void * context) ladish_studio_stop_app_supervisors(); cmd_ptr->command.state = LADISH_COMMAND_STATE_WAITING; - cmd_ptr->stop_state = STOP_STATE_WAITING_FOR_JACK_CLIENTS_DISAPPEAR; + cmd_ptr->stop_state = STOP_STATE_WAITING_FOR_ROOM_STOP; + + if (!ladish_studio_iterate_rooms(ladish_studio_get_virtualizer(), stop_room)) + { + log_error("room stop initiation failed"); + return false; + } + /* fall through */ case LADISH_COMMAND_STATE_WAITING: + if (cmd_ptr->stop_state == STOP_STATE_WAITING_FOR_ROOM_STOP) + { + if (!ladish_studio_iterate_rooms(ladish_studio_get_virtualizer(), room_stopped)) + { + return true; + } + + cmd_ptr->stop_state = STOP_STATE_WAITING_FOR_JACK_CLIENTS_DISAPPEAR; + } + if (cmd_ptr->stop_state == STOP_STATE_WAITING_FOR_JACK_CLIENTS_DISAPPEAR) { clients_count = ladish_virtualizer_get_our_clients_count(g_studio.virtualizer); diff --git a/daemon/cmd_unload_studio.c b/daemon/cmd_unload_studio.c index 57c3d4f9..8fdc4ec0 100644 --- a/daemon/cmd_unload_studio.c +++ b/daemon/cmd_unload_studio.c @@ -37,11 +37,13 @@ static bool run(void * context) ladish_graph_dump(g_studio.studio_graph); ladish_graph_dump(g_studio.jack_graph); + + /* remove rooms that own clients in studio graph before clearing it */ + ladish_studio_remove_all_rooms(); + ladish_graph_clear(g_studio.studio_graph, NULL); ladish_graph_clear(g_studio.jack_graph, NULL); - ladish_studio_remove_all_rooms(); - ladish_studio_jack_conf_clear(); g_studio.modified = false; diff --git a/daemon/control.c b/daemon/control.c index 7043998f..0c74c85a 100644 --- a/daemon/control.c +++ b/daemon/control.c @@ -46,9 +46,9 @@ static struct list_head g_room_templates; static bool create_empty_room_template(const uuid_t uuid_ptr, const char * name, ladish_room_handle * room_ptr) { - if (!ladish_room_create(uuid_ptr, name, NULL, NULL, room_ptr)) + if (!ladish_room_create_template(uuid_ptr, name, room_ptr)) { - log_error("ladish_room_create() failed for room template \"%s\".", name); + log_error("ladish_room_create_template() failed for room template \"%s\".", name); return false; } diff --git a/daemon/room.c b/daemon/room.c index c71bc157..182dee90 100644 --- a/daemon/room.c +++ b/daemon/room.c @@ -28,6 +28,8 @@ #include "../dbus_constants.h" #include "graph_dict.h" #include "../lib/wkports.h" +#include "studio.h" +#include "../proxies/jmcore_proxy.h" struct ladish_room { @@ -35,9 +37,16 @@ struct ladish_room uuid_t uuid; char * name; uuid_t template_uuid; + + /* these are not valid for templates */ + ladish_graph_handle owner; + unsigned int index; + char * object_path; dbus_object_path dbus_object; ladish_graph_handle graph; ladish_app_supervisor_handle app_supervisor; + ladish_client_handle client; + bool started; }; extern const struct dbus_interface_descriptor g_interface_room; @@ -45,13 +54,25 @@ extern const struct dbus_interface_descriptor g_interface_room; /* implemented in studio.c */ void ladish_on_app_renamed(void * context, const char * old_name, const char * new_app_name); -bool -ladish_room_create( - const uuid_t uuid_ptr, - const char * name, - ladish_room_handle template, - const char * object_path, - ladish_room_handle * room_handle_ptr) +static bool get_port_direction(uint32_t port_flags, bool * room_input_ptr) +{ + if (JACKDBUS_PORT_IS_INPUT(port_flags)) + { + *room_input_ptr = true; + return true; + } + + if (JACKDBUS_PORT_IS_OUTPUT(port_flags)) + { + *room_input_ptr = false; + return true; + } + + log_error("room link port with bad flags %"PRIu32, port_flags); + return false; +} + +struct ladish_room * ladish_room_create_internal(const uuid_t uuid_ptr, const char * name, const char * object_path) { struct ladish_room * room_ptr; @@ -62,29 +83,13 @@ ladish_room_create( goto fail; } - if (uuid_ptr == NULL) - { - if (template == NULL) - { - uuid_generate(room_ptr->uuid); - } - else - { - ladish_room_get_uuid(template, room_ptr->uuid); - } - } - else + if (uuid_ptr != NULL) { uuid_copy(room_ptr->uuid, uuid_ptr); } - - if (template != NULL) - { - ladish_room_get_uuid(template, room_ptr->template_uuid); - } else { - uuid_clear(room_ptr->template_uuid); + uuid_generate(room_ptr->uuid); } room_ptr->name = strdup(name); @@ -99,80 +104,304 @@ ladish_room_create( goto free_name; } - if (template != NULL) - { - if (!ladish_graph_copy(ladish_room_get_graph(template), room_ptr->graph, false)) - { - goto destroy_graph; - } - } + return room_ptr; - if (object_path) - { - if (!ladish_app_supervisor_create(&room_ptr->app_supervisor, object_path, room_ptr->name, room_ptr->graph, ladish_on_app_renamed)) - { - log_error("ladish_app_supervisor_create() failed."); - goto destroy_graph; - } - - room_ptr->dbus_object = dbus_object_path_new( - object_path, - &g_interface_room, room_ptr, - &g_interface_patchbay, ladish_graph_get_dbus_context(room_ptr->graph), - &g_iface_graph_dict, room_ptr->graph, - &g_iface_app_supervisor, room_ptr->app_supervisor, - NULL); - if (room_ptr->dbus_object == NULL) - { - log_error("dbus_object_path_new() failed"); - goto destroy_app_supervisor; - } - - if (!dbus_object_path_register(g_dbus_connection, room_ptr->dbus_object)) - { - log_error("object_path_register() failed"); - goto destroy_dbus_object; - } - - log_info("D-Bus object \"%s\" created for room \"%s\".", object_path, room_ptr->name); - } - else - { - room_ptr->dbus_object = NULL; - room_ptr->app_supervisor = NULL; - } - - *room_handle_ptr = (ladish_room_handle)room_ptr; - return true; - -destroy_dbus_object: - dbus_object_path_destroy(g_dbus_connection, room_ptr->dbus_object); -destroy_app_supervisor: - ladish_app_supervisor_destroy(room_ptr->app_supervisor); -destroy_graph: - ladish_graph_destroy(room_ptr->graph); free_name: free(room_ptr->name); free_room: free(room_ptr); fail: + return NULL; +} + +bool +ladish_room_create_template( + const uuid_t uuid_ptr, + const char * name, + ladish_room_handle * room_handle_ptr) +{ + struct ladish_room * room_ptr; + + room_ptr = ladish_room_create_internal(uuid_ptr, name, NULL); + if (room_ptr == NULL) + { + return false; + } + + uuid_clear(room_ptr->template_uuid); + + *room_handle_ptr = (ladish_room_handle)room_ptr; + return true; +} + +#define room_ptr ((struct ladish_room *)context) + +static +bool +create_shadow_port( + void * context, + ladish_port_handle port_handle, + const char * port_name, + uint32_t port_type, + uint32_t port_flags) +{ + bool room_input; + + //log_info("Studio room port \"%s\"", port_name); + + if (!get_port_direction(port_flags, &room_input)) + { + return false; + } + + if (room_input) + { + JACKDBUS_PORT_CLEAR_INPUT(port_flags); + JACKDBUS_PORT_SET_OUTPUT(port_flags); + } + else + { + JACKDBUS_PORT_CLEAR_OUTPUT(port_flags); + JACKDBUS_PORT_SET_INPUT(port_flags); + } + + if (!ladish_graph_add_port(room_ptr->owner, room_ptr->client, port_handle, port_name, port_type, port_flags, true)) + { + log_error("ladish_graph_add_port() failed to add link port to room owner graph"); + return false; + } + + return true; +} + +static +bool +create_port_link( + void * context, + ladish_port_handle port_handle, + const char * port_name, + uint32_t port_type, + uint32_t port_flags) +{ + uuid_t uuid_in_owner; + uuid_t uuid_in_room; + char uuid_in_owner_str[37]; + char uuid_in_room_str[37]; + bool room_input; + const char * input_port; + const char * output_port; + + //log_info("Room port \"%s\"", port_name); + + if (!get_port_direction(port_flags, &room_input)) + { + return false; + } + + ladish_graph_get_port_uuid(room_ptr->graph, port_handle, uuid_in_room); + ladish_graph_get_port_uuid(room_ptr->owner, port_handle, uuid_in_owner); + + uuid_unparse(uuid_in_room, uuid_in_room_str); + uuid_unparse(uuid_in_owner, uuid_in_owner_str); + + if (room_input) + { + input_port = uuid_in_room_str; + output_port = uuid_in_owner_str; + log_info("room input port %s is linked to owner graph output port %s", input_port, output_port); + } + else + { + input_port = uuid_in_owner_str; + output_port = uuid_in_room_str; + log_info("owner graph input port %s is linked to room output port %s", input_port, output_port); + } + + if (!jmcore_proxy_create_link(port_type == JACKDBUS_PORT_TYPE_MIDI, input_port, output_port)) + { + log_error("jmcore_proxy_create_link() failed."); + return false; + } + + return true; +} + +static +bool +destroy_port_link( + void * context, + 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) +{ + uuid_t uuid_in_room; + char uuid_in_room_str[37]; + + if (ladish_port_is_link(port_handle)) + { + log_info("link port %s", port_name); + + ladish_graph_get_port_uuid(ladish_room_get_graph(context), port_handle, uuid_in_room); + uuid_unparse(uuid_in_room, uuid_in_room_str); + jmcore_proxy_destroy_link(uuid_in_room_str); + } + else + { + log_info("jack port %s", port_name); + } + + return true; +} + +#undef room_ptr + +static void remove_port_callback(ladish_port_handle port) +{ + ladish_graph_handle jack_graph; + ladish_client_handle jack_client; + + jack_graph = ladish_studio_get_jack_graph(); + + jack_client = ladish_graph_remove_port(jack_graph, port); + if (jack_client == NULL) + { /* room app port not found in jack graph */ + /* this can happen if the port is hidden in the vgraph */ + return; + } + + if (ladish_graph_client_is_empty(jack_graph, jack_client)) + { + ladish_graph_remove_client(jack_graph, jack_client); + } +} + +bool +ladish_room_create( + const uuid_t uuid_ptr, + const char * name, + ladish_room_handle template, + ladish_graph_handle owner, + ladish_room_handle * room_handle_ptr) +{ + struct ladish_room * room_ptr; + char object_path[1024]; + unsigned int index; + + index = ladish_studio_get_room_index(); + sprintf(object_path, DBUS_BASE_PATH "/Room%u", index); + + room_ptr = ladish_room_create_internal(uuid_ptr, name, object_path); + if (room_ptr == NULL) + { + goto release_index; + } + + room_ptr->index = index; + ladish_room_get_uuid(template, room_ptr->template_uuid); + room_ptr->owner = owner; + room_ptr->started = false; + + if (!ladish_graph_copy(ladish_room_get_graph(template), room_ptr->graph, false)) + { + goto destroy; + } + + if (!ladish_app_supervisor_create(&room_ptr->app_supervisor, object_path, room_ptr->name, room_ptr->graph, ladish_on_app_renamed)) + { + log_error("ladish_app_supervisor_create() failed."); + goto destroy; + } + + room_ptr->dbus_object = dbus_object_path_new( + object_path, + &g_interface_room, room_ptr, + &g_interface_patchbay, ladish_graph_get_dbus_context(room_ptr->graph), + &g_iface_graph_dict, room_ptr->graph, + &g_iface_app_supervisor, room_ptr->app_supervisor, + NULL); + if (room_ptr->dbus_object == NULL) + { + log_error("dbus_object_path_new() failed"); + goto destroy_app_supervisor; + } + + if (!dbus_object_path_register(g_dbus_connection, room_ptr->dbus_object)) + { + log_error("object_path_register() failed"); + goto destroy_dbus_object; + } + + log_info("D-Bus object \"%s\" created for room \"%s\".", object_path, room_ptr->name); + + if (!ladish_client_create(room_ptr->uuid, &room_ptr->client)) + { + log_error("ladish_client_create() failed."); + goto unregister_dbus_object; + } + + if (!ladish_graph_add_client(owner, room_ptr->client, room_ptr->name, true)) + { + log_error("ladish_graph_add_client() failed to add room client to owner graph."); + goto destroy_client; + } + + if (!ladish_room_iterate_link_ports((ladish_room_handle)room_ptr, room_ptr, create_shadow_port)) + { + log_error("Creation of studio room link ports failed."); + goto remove_client; + } + + ladish_studio_room_appeared((ladish_room_handle)room_ptr); + + *room_handle_ptr = (ladish_room_handle)room_ptr; + return true; + +remove_client: + ladish_graph_remove_client(owner, room_ptr->client); +destroy_client: + ladish_client_destroy(room_ptr->client); +unregister_dbus_object: + dbus_object_path_unregister(g_dbus_connection, room_ptr->dbus_object); +destroy_dbus_object: + dbus_object_path_destroy(g_dbus_connection, room_ptr->dbus_object); +destroy_app_supervisor: + ladish_app_supervisor_destroy(room_ptr->app_supervisor); +destroy: + ladish_graph_destroy(room_ptr->graph); + free(room_ptr->name); + free(room_ptr); +release_index: + ladish_studio_release_room_index(index); return false; } #define room_ptr ((struct ladish_room *)room_handle) -void -ladish_room_destroy( - ladish_room_handle room_handle) +void ladish_room_destroy(ladish_room_handle room_handle) { - if (room_ptr->dbus_object != NULL) + if (!uuid_is_null(room_ptr->template_uuid)) { - dbus_object_path_destroy(g_dbus_connection, room_ptr->dbus_object); - } + ASSERT(!room_ptr->started); /* attempt to destroy not stopped room */ - if (room_ptr->app_supervisor != NULL) - { + /* ladish_graph_dump(graph); */ + + if (ladish_studio_is_started()) + { + ladish_graph_clear(room_ptr->graph, remove_port_callback); + } + + dbus_object_path_destroy(g_dbus_connection, room_ptr->dbus_object); ladish_app_supervisor_destroy(room_ptr->app_supervisor); + + ladish_graph_remove_client(room_ptr->owner, room_ptr->client); + ladish_client_destroy(room_ptr->client); + + ladish_studio_room_disappeared((ladish_room_handle)room_ptr); + ladish_studio_release_room_index(room_ptr->index); } ladish_graph_destroy(room_ptr->graph); @@ -310,6 +539,70 @@ ladish_room_iterate_link_ports( NULL); } +bool ladish_room_start(ladish_room_handle room_handle, ladish_virtualizer_handle virtualizer) +{ + if (!ladish_room_iterate_link_ports(room_handle, room_ptr, create_port_link)) + { + log_error("Creation of room port links failed."); + return false; + } + + ladish_virtualizer_set_graph_connection_handlers(virtualizer, room_ptr->graph); + room_ptr->started = true; + + return true; +} + +void ladish_room_initiate_stop(ladish_room_handle room_handle, bool clear_persist) +{ + if (!room_ptr->started) + { + return; + } + + ladish_graph_set_connection_handlers(room_ptr->graph, NULL, NULL, NULL); + + if (clear_persist) + { + ladish_graph_clear_persist(room_ptr->graph); + } + + ladish_graph_iterate_nodes(room_ptr->graph, false, NULL, room_ptr, NULL, destroy_port_link, NULL); + ladish_app_supervisor_stop(room_ptr->app_supervisor); +} + +bool ladish_room_stopped(ladish_room_handle room_handle) +{ + unsigned int running_app_count; + + if (!room_ptr->started) + { + return true; + } + + running_app_count = ladish_app_supervisor_get_running_app_count(room_ptr->app_supervisor); + if (running_app_count != 0) + { + log_info("there are %u running app(s) in room \"%s\"", running_app_count, room_ptr->name); + return false; + } + + if (!ladish_graph_looks_empty(room_ptr->graph)) + { + log_info("the room \"%s\" graph is still not empty", room_ptr->name); + return false; + } + + if (!ladish_graph_client_looks_empty(room_ptr->owner, room_ptr->client)) + { + log_info("the room \"%s\" client in owner still does not look empty", room_ptr->name); + return false; + } + + room_ptr->started = false; + return true; +} + #undef room_ptr ladish_room_handle ladish_room_from_list_node(struct list_head * node_ptr) diff --git a/daemon/room.h b/daemon/room.h index b6be9d9b..7616a219 100644 --- a/daemon/room.h +++ b/daemon/room.h @@ -30,15 +30,22 @@ #include "common.h" #include "graph.h" #include "app_supervisor.h" +#include "virtualizer.h" typedef struct ladish_room_tag { int unused; } * ladish_room_handle; +bool +ladish_room_create_template( + const uuid_t uuid_ptr, + const char * name, + ladish_room_handle * room_handle_ptr); + bool ladish_room_create( const uuid_t uuid_ptr, const char * name, ladish_room_handle template, - const char * object_path, + ladish_graph_handle owner, ladish_room_handle * room_handle_ptr); void @@ -67,4 +74,8 @@ ladish_room_iterate_link_ports( uint32_t port_type, uint32_t port_flags)); +bool ladish_room_start(ladish_room_handle room_handle, ladish_virtualizer_handle virtualizer); +void ladish_room_initiate_stop(ladish_room_handle room_handle, bool clear_persist); +bool ladish_room_stopped(ladish_room_handle room_handle); + #endif /* #ifndef ROOM_H__9A1CF253_0A17_402A_BDF8_9BD72B467118__INCLUDED */ diff --git a/daemon/studio.c b/daemon/studio.c index 32deac23..ac0604e6 100644 --- a/daemon/studio.c +++ b/daemon/studio.c @@ -183,7 +183,7 @@ static bool ladish_studio_fill_room_info(DBusMessageIter * iter_ptr, ladish_room return true; } -void ladish_studio_emit_room_appeared(ladish_room_handle room) +static void ladish_studio_emit_room_appeared(ladish_room_handle room) { DBusMessage * message_ptr; DBusMessageIter iter; @@ -227,6 +227,18 @@ void ladish_studio_emit_room_disappeared(ladish_room_handle room) dbus_message_unref(message_ptr); } +void ladish_studio_room_appeared(ladish_room_handle room) +{ + list_add_tail(ladish_room_get_list_node(room), &g_studio.rooms); + ladish_studio_emit_room_appeared(room); +} + +void ladish_studio_room_disappeared(ladish_room_handle room) +{ + list_del(ladish_room_get_list_node(room)); + ladish_studio_emit_room_disappeared(room); +} + bool ladish_studio_set_graph_connection_handlers( void * context, @@ -880,6 +892,27 @@ void ladish_studio_emit_renamed(void) dbus_signal_emit(g_dbus_connection, STUDIO_OBJECT_PATH, IFACE_STUDIO, "StudioRenamed", "s", &g_studio.name); } +unsigned int ladish_studio_get_room_index(void) +{ + return ++g_studio.room_count; +} + +void ladish_studio_release_room_index(unsigned int index) +{ + if (index == g_studio.room_count) + { + g_studio.room_count--; + } +} + +void ladish_studio_remove_all_rooms(void) +{ + while (!list_empty(&g_studio.rooms)) + { + ladish_room_destroy(ladish_room_from_list_node(g_studio.rooms.next)); + } +} + /**********************************************************************************/ /* D-Bus methods */ /**********************************************************************************/ @@ -1077,21 +1110,6 @@ static void ladish_studio_dbus_delete_room(struct dbus_method_call * call_ptr) } } -void ladish_studio_remove_all_rooms(void) -{ - struct list_head * node_ptr; - ladish_room_handle room; - - while (!list_empty(&g_studio.rooms)) - { - node_ptr = g_studio.rooms.next; - list_del(node_ptr); - room = ladish_room_from_list_node(node_ptr); - ladish_studio_emit_room_disappeared(room); - ladish_room_destroy(room); - } -} - METHOD_ARGS_BEGIN(GetName, "Get studio name") METHOD_ARG_DESCRIBE_OUT("studio_name", "s", "Name of studio") METHOD_ARGS_END diff --git a/daemon/studio.h b/daemon/studio.h index 972b1e45..0dbc09cd 100644 --- a/daemon/studio.h +++ b/daemon/studio.h @@ -65,7 +65,10 @@ ladish_virtualizer_handle ladish_studio_get_virtualizer(void); ladish_graph_handle ladish_studio_get_jack_graph(void); bool ladish_studio_has_rooms(void); -void ladish_studio_emit_room_appeared(ladish_room_handle room); -void ladish_studio_emit_room_disappeared(ladish_room_handle room); +unsigned int ladish_studio_get_room_index(void); +void ladish_studio_release_room_index(unsigned int index); + +void ladish_studio_room_appeared(ladish_room_handle room); +void ladish_studio_room_disappeared(ladish_room_handle room); #endif /* #ifndef STUDIO_H__0BEDE85E_4FB3_4D74_BC08_C373A22409C0__INCLUDED */