damon: Proper room lifecycle

* Room creation/destruction is now separeted from starting/stopping
   (creating/destroying jmcore links)
 * Rooms can now be created and destryed when studio is stopped
 * Rooms are started/stopped when studio is started/stopped

Apart from better interraction of studio start/stop and room
lifecycles, it is now possible to implement load of studio with rooms
because during studio load rooms have to be created in stopped state
and eventually started only at later stage, during studio start.
This commit is contained in:
Nedko Arnaudov 2010-07-20 01:31:37 +03:00
parent ed2f5eb687
commit 5bb96d51e7
10 changed files with 484 additions and 322 deletions

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -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)

View File

@ -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 */

View File

@ -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

View File

@ -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 */