2009-07-26 23:26:29 +03:00
|
|
|
/* -*- Mode: C ; c-basic-offset: 2 -*- */
|
2009-07-29 20:45:43 +03:00
|
|
|
/*
|
|
|
|
* LADI Session Handler (ladish)
|
2009-07-26 23:26:29 +03:00
|
|
|
*
|
2009-07-29 20:45:43 +03:00
|
|
|
* Copyright (C) 2009 Nedko Arnaudov <nedko@arnaudov.name>
|
2009-07-26 23:26:29 +03:00
|
|
|
*
|
2009-07-29 20:45:43 +03:00
|
|
|
**************************************************************************
|
2009-09-12 14:50:35 +03:00
|
|
|
* This file contains part of the studio singleton object implementation
|
|
|
|
* Other parts are in the other studio*.c files in same directory.
|
2009-07-29 20:45:43 +03:00
|
|
|
**************************************************************************
|
|
|
|
*
|
|
|
|
* LADI Session Handler is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* LADI Session Handler is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with LADI Session Handler. If not, see <http://www.gnu.org/licenses/>
|
|
|
|
* or write to the Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
*/
|
2009-07-26 23:26:29 +03:00
|
|
|
|
|
|
|
#include "common.h"
|
2009-08-24 01:04:07 +03:00
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <unistd.h>
|
2009-08-24 01:58:14 +03:00
|
|
|
#include <dirent.h>
|
2009-08-24 01:04:07 +03:00
|
|
|
|
2009-09-12 14:50:35 +03:00
|
|
|
#include "studio_internal.h"
|
2009-08-22 03:07:19 +03:00
|
|
|
#include "../dbus_constants.h"
|
2009-08-23 01:21:23 +03:00
|
|
|
#include "control.h"
|
2009-08-23 11:09:15 +03:00
|
|
|
#include "../catdup.h"
|
2009-08-24 00:25:43 +03:00
|
|
|
#include "dirhelpers.h"
|
2009-09-07 20:53:56 +03:00
|
|
|
#include "graph_dict.h"
|
2009-09-12 11:11:52 +03:00
|
|
|
#include "escape.h"
|
2009-08-24 00:25:43 +03:00
|
|
|
|
2009-08-24 01:58:14 +03:00
|
|
|
#define STUDIOS_DIR "/studios/"
|
2009-08-24 00:25:43 +03:00
|
|
|
char * g_studios_dir;
|
2009-08-07 23:28:34 +03:00
|
|
|
|
2009-09-12 14:50:35 +03:00
|
|
|
struct studio g_studio;
|
2009-08-23 01:21:23 +03:00
|
|
|
|
|
|
|
#define EVENT_JACK_START 0
|
|
|
|
#define EVENT_JACK_STOP 1
|
|
|
|
|
|
|
|
struct event
|
|
|
|
{
|
|
|
|
struct list_head siblings;
|
|
|
|
unsigned int type;
|
2009-08-07 23:28:34 +03:00
|
|
|
};
|
|
|
|
|
2009-08-23 11:09:15 +03:00
|
|
|
bool studio_name_generate(char ** name_ptr)
|
|
|
|
{
|
|
|
|
time_t now;
|
|
|
|
char timestamp_str[26];
|
|
|
|
char * name;
|
|
|
|
|
|
|
|
time(&now);
|
|
|
|
//ctime_r(&now, timestamp_str);
|
|
|
|
//timestamp_str[24] = 0;
|
|
|
|
snprintf(timestamp_str, sizeof(timestamp_str), "%llu", (unsigned long long)now);
|
|
|
|
|
|
|
|
name = catdup("Studio ", timestamp_str);
|
|
|
|
if (name == NULL)
|
|
|
|
{
|
2009-09-20 18:23:42 +03:00
|
|
|
log_error("catdup failed to create studio name");
|
2009-08-23 11:09:15 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
*name_ptr = name;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2009-07-26 23:26:29 +03:00
|
|
|
bool
|
2009-08-30 18:38:17 +03:00
|
|
|
studio_publish(void)
|
2009-07-26 23:26:29 +03:00
|
|
|
{
|
2009-09-05 17:27:56 +03:00
|
|
|
dbus_object_path object;
|
2009-07-26 23:26:29 +03:00
|
|
|
|
2009-09-20 18:48:42 +03:00
|
|
|
ASSERT(g_studio.name != NULL);
|
2009-08-23 11:09:15 +03:00
|
|
|
|
2009-09-06 00:13:05 +03:00
|
|
|
object = dbus_object_path_new(
|
|
|
|
STUDIO_OBJECT_PATH,
|
|
|
|
&g_interface_studio, &g_studio,
|
2009-09-12 22:30:33 +03:00
|
|
|
&g_interface_patchbay, ladish_graph_get_dbus_context(g_studio.studio_graph),
|
|
|
|
&g_iface_graph_dict, g_studio.studio_graph,
|
2009-09-06 00:13:05 +03:00
|
|
|
NULL);
|
2009-08-23 01:21:23 +03:00
|
|
|
if (object == NULL)
|
|
|
|
{
|
2009-09-20 18:23:42 +03:00
|
|
|
log_error("dbus_object_path_new() failed");
|
2009-08-23 01:21:23 +03:00
|
|
|
return false;
|
|
|
|
}
|
2009-07-26 23:26:29 +03:00
|
|
|
|
2009-09-04 02:27:05 +03:00
|
|
|
if (!dbus_object_path_register(g_dbus_connection, object))
|
2009-07-26 23:26:29 +03:00
|
|
|
{
|
2009-09-20 18:23:42 +03:00
|
|
|
log_error("object_path_register() failed");
|
2009-09-04 02:27:05 +03:00
|
|
|
dbus_object_path_destroy(g_dbus_connection, object);
|
2009-07-26 23:26:29 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-09-20 18:23:42 +03:00
|
|
|
log_info("Studio D-Bus object created. \"%s\"", g_studio.name);
|
2009-08-23 01:21:23 +03:00
|
|
|
|
|
|
|
g_studio.dbus_object = object;
|
2009-08-21 23:13:19 +03:00
|
|
|
|
2009-08-23 01:21:23 +03:00
|
|
|
emit_studio_appeared();
|
2009-07-26 23:26:29 +03:00
|
|
|
|
2009-08-23 01:21:23 +03:00
|
|
|
return true;
|
|
|
|
}
|
2009-07-26 23:26:29 +03:00
|
|
|
|
2009-08-30 22:40:28 +03:00
|
|
|
static void emit_studio_started()
|
2009-08-23 01:21:23 +03:00
|
|
|
{
|
2009-09-05 19:12:53 +03:00
|
|
|
dbus_signal_emit(g_dbus_connection, STUDIO_OBJECT_PATH, IFACE_STUDIO, "StudioStarted", "");
|
2009-08-30 22:40:28 +03:00
|
|
|
}
|
2009-07-26 23:26:29 +03:00
|
|
|
|
2009-08-30 22:40:28 +03:00
|
|
|
static void emit_studio_stopped()
|
|
|
|
{
|
2009-09-05 19:12:53 +03:00
|
|
|
dbus_signal_emit(g_dbus_connection, STUDIO_OBJECT_PATH, IFACE_STUDIO, "StudioStopped", "");
|
2009-08-30 22:40:28 +03:00
|
|
|
}
|
2009-08-01 19:07:16 +03:00
|
|
|
|
2009-09-12 14:50:35 +03:00
|
|
|
bool studio_start(void)
|
2009-08-30 22:40:28 +03:00
|
|
|
{
|
2009-10-08 23:45:03 +03:00
|
|
|
if (g_studio.jack_pending)
|
|
|
|
{
|
|
|
|
log_error("JACK is not in stable state");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-08-30 22:40:28 +03:00
|
|
|
if (!g_studio.jack_running)
|
2009-08-23 01:21:23 +03:00
|
|
|
{
|
2009-09-20 18:23:42 +03:00
|
|
|
log_info("Starting JACK server.");
|
2009-08-30 22:40:28 +03:00
|
|
|
|
2009-10-08 23:45:03 +03:00
|
|
|
g_studio.jack_pending = true;
|
2009-08-30 22:40:28 +03:00
|
|
|
if (!jack_proxy_start_server())
|
|
|
|
{
|
2009-09-20 18:23:42 +03:00
|
|
|
log_error("jack_proxy_start_server() failed.");
|
2009-08-30 22:40:28 +03:00
|
|
|
return false;
|
|
|
|
}
|
2009-08-23 01:21:23 +03:00
|
|
|
}
|
2009-07-26 23:26:29 +03:00
|
|
|
|
2009-08-30 22:40:28 +03:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2009-10-08 23:45:03 +03:00
|
|
|
static bool studio_stop(bool clear, bool * clear_defered_ptr)
|
2009-08-30 22:40:28 +03:00
|
|
|
{
|
2009-10-08 23:45:03 +03:00
|
|
|
if (g_studio.jack_pending)
|
|
|
|
{
|
|
|
|
log_error("JACK is not in stable state");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-08-24 03:33:47 +03:00
|
|
|
if (g_studio.jack_running)
|
|
|
|
{
|
2009-09-20 18:23:42 +03:00
|
|
|
log_info("Stopping JACK server...");
|
2009-08-24 03:33:47 +03:00
|
|
|
|
2009-08-31 02:06:55 +03:00
|
|
|
g_studio.automatic = false; /* even if it was automatic, it is not anymore because user knows about it */
|
|
|
|
|
2009-10-08 23:45:03 +03:00
|
|
|
g_studio.jack_pending = true;
|
|
|
|
|
|
|
|
if (clear)
|
2009-08-24 03:33:47 +03:00
|
|
|
{
|
2009-10-08 23:45:03 +03:00
|
|
|
log_info("defer studio clear until jack stops");
|
|
|
|
g_studio.clear_on_jack_stop = true;
|
|
|
|
*clear_defered_ptr = true;
|
2009-08-24 03:33:47 +03:00
|
|
|
}
|
2009-10-08 23:45:03 +03:00
|
|
|
|
|
|
|
if (!jack_proxy_stop_server())
|
2009-08-24 03:33:47 +03:00
|
|
|
{
|
2009-09-20 18:23:42 +03:00
|
|
|
log_error("Stopping JACK server failed.");
|
2009-10-08 23:45:03 +03:00
|
|
|
g_studio.jack_pending = false;
|
2009-08-30 22:40:28 +03:00
|
|
|
return false;
|
2009-08-24 03:33:47 +03:00
|
|
|
}
|
|
|
|
}
|
2009-10-08 23:45:03 +03:00
|
|
|
else if (clear)
|
|
|
|
{
|
|
|
|
*clear_defered_ptr = false;
|
|
|
|
}
|
2009-08-24 03:33:47 +03:00
|
|
|
|
2009-08-30 22:40:28 +03:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2009-10-08 23:45:03 +03:00
|
|
|
bool studio_clear(bool defer_if_started)
|
2009-08-30 22:40:28 +03:00
|
|
|
{
|
2009-10-08 23:45:03 +03:00
|
|
|
bool clear_defered;
|
|
|
|
|
|
|
|
log_info("studio_clear() called.");
|
|
|
|
|
|
|
|
if (!studio_stop(defer_if_started, &clear_defered))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (defer_if_started && clear_defered)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
ladish_graph_dump(g_studio.studio_graph);
|
|
|
|
ladish_graph_dump(g_studio.jack_graph);
|
|
|
|
ladish_graph_clear(g_studio.studio_graph, false);
|
|
|
|
ladish_graph_clear(g_studio.jack_graph, true);
|
|
|
|
|
2009-09-06 16:40:03 +03:00
|
|
|
jack_conf_clear();
|
2009-09-06 00:13:05 +03:00
|
|
|
|
2009-08-30 22:40:28 +03:00
|
|
|
g_studio.modified = false;
|
|
|
|
g_studio.persisted = false;
|
2009-08-31 02:06:55 +03:00
|
|
|
g_studio.automatic = false;
|
2009-08-30 22:40:28 +03:00
|
|
|
|
2009-08-23 01:21:23 +03:00
|
|
|
if (g_studio.dbus_object != NULL)
|
|
|
|
{
|
2009-09-04 02:27:05 +03:00
|
|
|
dbus_object_path_destroy(g_dbus_connection, g_studio.dbus_object);
|
2009-08-23 01:21:23 +03:00
|
|
|
g_studio.dbus_object = NULL;
|
|
|
|
emit_studio_disappeared();
|
|
|
|
}
|
2009-08-23 11:09:15 +03:00
|
|
|
|
|
|
|
if (g_studio.name != NULL)
|
|
|
|
{
|
|
|
|
free(g_studio.name);
|
|
|
|
g_studio.name = NULL;
|
|
|
|
}
|
2009-08-24 00:25:43 +03:00
|
|
|
|
|
|
|
if (g_studio.filename != NULL)
|
|
|
|
{
|
|
|
|
free(g_studio.filename);
|
|
|
|
g_studio.filename = NULL;
|
|
|
|
}
|
2009-10-08 23:45:03 +03:00
|
|
|
|
|
|
|
return true;
|
2009-08-23 01:21:23 +03:00
|
|
|
}
|
2009-08-07 23:28:34 +03:00
|
|
|
|
2009-07-26 23:26:29 +03:00
|
|
|
void
|
2009-08-31 02:06:55 +03:00
|
|
|
studio_clear_if_automatic(void)
|
2009-07-26 23:26:29 +03:00
|
|
|
{
|
2009-08-31 02:06:55 +03:00
|
|
|
if (g_studio.automatic)
|
2009-08-23 01:21:23 +03:00
|
|
|
{
|
2009-09-20 18:23:42 +03:00
|
|
|
log_info("Unloading automatic studio.");
|
2009-10-08 23:45:03 +03:00
|
|
|
studio_clear(true);
|
2009-08-23 01:21:23 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2009-07-26 23:26:29 +03:00
|
|
|
|
2009-08-23 01:21:23 +03:00
|
|
|
void on_event_jack_started(void)
|
|
|
|
{
|
2009-10-08 23:45:03 +03:00
|
|
|
g_studio.jack_pending = false;
|
|
|
|
g_studio.jack_running = true;
|
|
|
|
|
2009-08-23 01:21:23 +03:00
|
|
|
if (g_studio.dbus_object == NULL)
|
2009-08-01 19:07:16 +03:00
|
|
|
{
|
2009-09-20 18:48:42 +03:00
|
|
|
ASSERT(g_studio.name == NULL);
|
2009-08-23 11:09:15 +03:00
|
|
|
if (!studio_name_generate(&g_studio.name))
|
|
|
|
{
|
2009-09-20 18:23:42 +03:00
|
|
|
log_error("studio_name_generate() failed.");
|
2009-08-23 11:09:15 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-08-31 02:06:55 +03:00
|
|
|
g_studio.automatic = true;
|
|
|
|
|
2009-08-30 18:38:17 +03:00
|
|
|
studio_publish();
|
2009-08-01 19:07:16 +03:00
|
|
|
}
|
|
|
|
|
2009-09-12 14:50:35 +03:00
|
|
|
if (!studio_fetch_jack_settings())
|
2009-07-26 23:26:29 +03:00
|
|
|
{
|
2009-09-20 18:23:42 +03:00
|
|
|
log_error("studio_fetch_jack_settings() failed.");
|
2009-08-23 01:21:23 +03:00
|
|
|
|
2009-08-31 02:06:55 +03:00
|
|
|
studio_clear_if_automatic();
|
2009-08-23 01:21:23 +03:00
|
|
|
return;
|
2009-07-26 23:26:29 +03:00
|
|
|
}
|
|
|
|
|
2009-09-20 18:23:42 +03:00
|
|
|
log_info("jack conf successfully retrieved");
|
2009-08-23 01:21:23 +03:00
|
|
|
g_studio.jack_conf_valid = true;
|
2009-09-03 05:45:39 +03:00
|
|
|
|
2009-09-12 09:58:37 +03:00
|
|
|
if (!graph_proxy_create(JACKDBUS_SERVICE_NAME, JACKDBUS_OBJECT_PATH, false, &g_studio.jack_graph_proxy))
|
2009-09-03 05:45:39 +03:00
|
|
|
{
|
2009-09-20 18:23:42 +03:00
|
|
|
log_error("graph_proxy_create() failed for jackdbus");
|
2009-09-06 00:13:05 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-09-12 22:30:33 +03:00
|
|
|
if (!ladish_jack_dispatcher_create(g_studio.jack_graph_proxy, g_studio.jack_graph, g_studio.studio_graph, &g_studio.jack_dispatcher))
|
2009-09-06 01:15:25 +03:00
|
|
|
{
|
2009-09-20 18:23:42 +03:00
|
|
|
log_error("ladish_jack_dispatcher_create() failed.");
|
2009-09-06 01:15:25 +03:00
|
|
|
}
|
2009-09-06 00:13:05 +03:00
|
|
|
|
2009-09-06 01:15:25 +03:00
|
|
|
if (!graph_proxy_activate(g_studio.jack_graph_proxy))
|
|
|
|
{
|
2009-09-20 18:23:42 +03:00
|
|
|
log_error("graph_proxy_activate() failed.");
|
2009-09-06 01:15:25 +03:00
|
|
|
}
|
2009-09-03 05:45:39 +03:00
|
|
|
}
|
2009-10-08 23:45:03 +03:00
|
|
|
|
|
|
|
emit_studio_started();
|
2009-07-26 23:26:29 +03:00
|
|
|
}
|
2009-08-01 19:07:16 +03:00
|
|
|
|
2009-08-23 01:21:23 +03:00
|
|
|
void on_event_jack_stopped(void)
|
2009-08-01 19:07:16 +03:00
|
|
|
{
|
2009-10-08 23:45:03 +03:00
|
|
|
emit_studio_stopped();
|
|
|
|
g_studio.jack_pending = false;
|
2009-08-24 03:33:47 +03:00
|
|
|
g_studio.jack_running = false;
|
|
|
|
|
2009-10-08 23:45:03 +03:00
|
|
|
if (g_studio.clear_on_jack_stop)
|
|
|
|
{
|
|
|
|
g_studio.clear_on_jack_stop = false;
|
|
|
|
studio_clear(false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
studio_clear_if_automatic();
|
|
|
|
}
|
|
|
|
|
2009-09-06 01:15:25 +03:00
|
|
|
if (g_studio.jack_dispatcher)
|
|
|
|
{
|
|
|
|
ladish_jack_dispatcher_destroy(g_studio.jack_dispatcher);
|
2009-09-06 16:40:03 +03:00
|
|
|
g_studio.jack_dispatcher = NULL;
|
2009-09-06 01:15:25 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (g_studio.jack_graph_proxy)
|
|
|
|
{
|
|
|
|
graph_proxy_destroy(g_studio.jack_graph_proxy);
|
|
|
|
g_studio.jack_graph_proxy = NULL;
|
|
|
|
}
|
2009-09-03 05:45:39 +03:00
|
|
|
|
2009-08-23 01:21:23 +03:00
|
|
|
/* TODO: if user wants, restart jack server and reconnect all jack apps to it */
|
|
|
|
}
|
|
|
|
|
|
|
|
void studio_run(void)
|
|
|
|
{
|
|
|
|
struct event * event_ptr;
|
|
|
|
|
|
|
|
while (!list_empty(&g_studio.event_queue))
|
2009-08-01 19:07:16 +03:00
|
|
|
{
|
2009-08-23 01:21:23 +03:00
|
|
|
event_ptr = list_entry(g_studio.event_queue.next, struct event, siblings);
|
|
|
|
list_del(g_studio.event_queue.next);
|
|
|
|
|
|
|
|
switch (event_ptr->type)
|
|
|
|
{
|
|
|
|
case EVENT_JACK_START:
|
|
|
|
on_event_jack_started();
|
|
|
|
break;
|
|
|
|
case EVENT_JACK_STOP:
|
|
|
|
on_event_jack_stopped();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
free(event_ptr);
|
2009-08-01 19:07:16 +03:00
|
|
|
}
|
2009-08-23 01:21:23 +03:00
|
|
|
}
|
2009-08-01 19:07:16 +03:00
|
|
|
|
2009-08-23 01:21:23 +03:00
|
|
|
static void on_jack_server_started(void)
|
|
|
|
{
|
|
|
|
struct event * event_ptr;
|
|
|
|
|
2009-09-20 18:23:42 +03:00
|
|
|
log_info("JACK server start detected.");
|
2009-08-23 01:21:23 +03:00
|
|
|
|
|
|
|
event_ptr = malloc(sizeof(struct event));
|
|
|
|
if (event_ptr == NULL)
|
2009-08-01 19:07:16 +03:00
|
|
|
{
|
2009-09-20 18:23:42 +03:00
|
|
|
log_error("malloc() failed to allocate struct event. Ignoring JACK start.");
|
2009-08-23 01:21:23 +03:00
|
|
|
return;
|
2009-08-01 19:07:16 +03:00
|
|
|
}
|
|
|
|
|
2009-08-23 01:21:23 +03:00
|
|
|
event_ptr->type = EVENT_JACK_START;
|
|
|
|
list_add_tail(&event_ptr->siblings, &g_studio.event_queue);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void on_jack_server_stopped(void)
|
|
|
|
{
|
|
|
|
struct event * event_ptr;
|
|
|
|
|
2009-09-20 18:23:42 +03:00
|
|
|
log_info("JACK server stop detected.");
|
2009-08-23 01:21:23 +03:00
|
|
|
|
|
|
|
event_ptr = malloc(sizeof(struct event));
|
|
|
|
if (event_ptr == NULL)
|
|
|
|
{
|
2009-09-20 18:23:42 +03:00
|
|
|
log_error("malloc() failed to allocate struct event. Ignoring JACK stop.");
|
2009-08-23 01:21:23 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
event_ptr->type = EVENT_JACK_STOP;
|
|
|
|
list_add_tail(&event_ptr->siblings, &g_studio.event_queue);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void on_jack_server_appeared(void)
|
|
|
|
{
|
2009-09-20 18:23:42 +03:00
|
|
|
log_info("JACK controller appeared.");
|
2009-08-23 01:21:23 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void on_jack_server_disappeared(void)
|
|
|
|
{
|
2009-09-20 18:23:42 +03:00
|
|
|
log_info("JACK controller disappeared.");
|
2009-08-23 01:21:23 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bool studio_init(void)
|
|
|
|
{
|
2009-09-20 18:23:42 +03:00
|
|
|
log_info("studio object construct");
|
2009-08-23 01:21:23 +03:00
|
|
|
|
2009-08-24 00:25:43 +03:00
|
|
|
g_studios_dir = catdup(g_base_dir, STUDIOS_DIR);
|
|
|
|
if (g_studios_dir == NULL)
|
|
|
|
{
|
2009-09-20 18:23:42 +03:00
|
|
|
log_error("catdup failed for '%s' and '%s'", g_base_dir, STUDIOS_DIR);
|
2009-09-06 00:13:05 +03:00
|
|
|
goto fail;
|
2009-08-24 00:25:43 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!ensure_dir_exist(g_studios_dir, 0700))
|
|
|
|
{
|
2009-09-06 00:13:05 +03:00
|
|
|
goto free_studios_dir;
|
2009-08-24 00:25:43 +03:00
|
|
|
}
|
|
|
|
|
2009-08-23 01:21:23 +03:00
|
|
|
INIT_LIST_HEAD(&g_studio.all_connections);
|
|
|
|
INIT_LIST_HEAD(&g_studio.all_ports);
|
|
|
|
INIT_LIST_HEAD(&g_studio.all_clients);
|
|
|
|
INIT_LIST_HEAD(&g_studio.jack_connections);
|
|
|
|
INIT_LIST_HEAD(&g_studio.jack_ports);
|
|
|
|
INIT_LIST_HEAD(&g_studio.jack_clients);
|
|
|
|
INIT_LIST_HEAD(&g_studio.rooms);
|
|
|
|
INIT_LIST_HEAD(&g_studio.clients);
|
|
|
|
INIT_LIST_HEAD(&g_studio.ports);
|
|
|
|
|
|
|
|
INIT_LIST_HEAD(&g_studio.jack_conf);
|
|
|
|
INIT_LIST_HEAD(&g_studio.jack_params);
|
|
|
|
|
|
|
|
INIT_LIST_HEAD(&g_studio.event_queue);
|
|
|
|
|
|
|
|
g_studio.dbus_object = NULL;
|
2009-08-23 11:09:15 +03:00
|
|
|
g_studio.name = NULL;
|
2009-08-24 00:25:43 +03:00
|
|
|
g_studio.filename = NULL;
|
2009-08-24 03:33:47 +03:00
|
|
|
g_studio.jack_running = false;
|
2009-10-08 23:45:03 +03:00
|
|
|
g_studio.jack_pending = false;
|
2009-08-23 01:21:23 +03:00
|
|
|
|
2009-09-20 17:30:48 +03:00
|
|
|
if (!ladish_graph_create(&g_studio.jack_graph, NULL))
|
2009-09-06 00:13:05 +03:00
|
|
|
{
|
2009-09-20 18:23:42 +03:00
|
|
|
log_error("ladish_graph_create() failed to create jack graph object.");
|
2009-09-06 00:13:05 +03:00
|
|
|
goto free_studios_dir;
|
|
|
|
}
|
|
|
|
|
2009-09-20 17:30:48 +03:00
|
|
|
if (!ladish_graph_create(&g_studio.studio_graph, STUDIO_OBJECT_PATH))
|
2009-09-12 22:30:33 +03:00
|
|
|
{
|
2009-09-20 18:23:42 +03:00
|
|
|
log_error("ladish_graph_create() failed to create studio graph object.");
|
2009-09-12 22:30:33 +03:00
|
|
|
goto jack_graph_destroy;
|
|
|
|
}
|
|
|
|
|
2009-10-19 01:16:59 +03:00
|
|
|
ladish_cqueue_init(&g_studio.cmd_queue);
|
|
|
|
|
2009-08-23 01:21:23 +03:00
|
|
|
if (!jack_proxy_init(
|
|
|
|
on_jack_server_started,
|
|
|
|
on_jack_server_stopped,
|
|
|
|
on_jack_server_appeared,
|
|
|
|
on_jack_server_disappeared))
|
|
|
|
{
|
2009-09-20 18:23:42 +03:00
|
|
|
log_error("jack_proxy_init() failed.");
|
2009-09-12 22:30:33 +03:00
|
|
|
goto studio_graph_destroy;
|
2009-08-23 01:21:23 +03:00
|
|
|
}
|
2009-08-01 19:07:16 +03:00
|
|
|
|
|
|
|
return true;
|
2009-09-06 00:13:05 +03:00
|
|
|
|
2009-09-12 22:30:33 +03:00
|
|
|
studio_graph_destroy:
|
2009-10-08 23:45:03 +03:00
|
|
|
ladish_graph_destroy(g_studio.studio_graph, false);
|
2009-09-12 22:30:33 +03:00
|
|
|
jack_graph_destroy:
|
2009-10-08 23:45:03 +03:00
|
|
|
ladish_graph_destroy(g_studio.jack_graph, false);
|
2009-09-06 00:13:05 +03:00
|
|
|
free_studios_dir:
|
2009-10-08 23:45:03 +03:00
|
|
|
studio_clear(false);
|
2009-09-06 00:13:05 +03:00
|
|
|
free(g_studios_dir);
|
|
|
|
fail:
|
|
|
|
return false;
|
2009-08-01 19:07:16 +03:00
|
|
|
}
|
2009-08-07 23:28:34 +03:00
|
|
|
|
2009-08-23 01:21:23 +03:00
|
|
|
void studio_uninit(void)
|
2009-08-07 23:28:34 +03:00
|
|
|
{
|
2009-10-08 23:45:03 +03:00
|
|
|
log_info("studio_uninit()");
|
2009-08-23 01:21:23 +03:00
|
|
|
|
2009-10-08 23:45:03 +03:00
|
|
|
jack_proxy_uninit();
|
2009-09-12 22:30:33 +03:00
|
|
|
|
2009-10-08 23:45:03 +03:00
|
|
|
studio_clear(false);
|
2009-08-23 01:21:23 +03:00
|
|
|
|
2009-10-19 01:16:59 +03:00
|
|
|
ladish_cqueue_uninit(&g_studio.cmd_queue);
|
|
|
|
|
2009-09-03 05:42:35 +03:00
|
|
|
free(g_studios_dir);
|
|
|
|
|
2009-09-20 18:23:42 +03:00
|
|
|
log_info("studio object destroy");
|
2009-08-07 23:28:34 +03:00
|
|
|
}
|
|
|
|
|
2009-08-23 01:21:23 +03:00
|
|
|
bool studio_is_loaded(void)
|
|
|
|
{
|
|
|
|
return g_studio.dbus_object != NULL;
|
|
|
|
}
|
|
|
|
|
2009-09-12 14:50:35 +03:00
|
|
|
bool studio_compose_filename(const char * name, char ** filename_ptr_ptr, char ** backup_filename_ptr_ptr)
|
2009-08-24 00:25:43 +03:00
|
|
|
{
|
|
|
|
size_t len_dir;
|
|
|
|
char * p;
|
|
|
|
const char * src;
|
2009-08-30 13:23:36 +03:00
|
|
|
char * filename_ptr;
|
2009-11-20 01:39:37 +02:00
|
|
|
char * backup_filename_ptr = NULL;
|
2009-08-24 00:25:43 +03:00
|
|
|
|
|
|
|
len_dir = strlen(g_studios_dir);
|
|
|
|
|
2009-08-30 13:23:36 +03:00
|
|
|
filename_ptr = malloc(len_dir + 1 + strlen(name) * 3 + 4 + 1);
|
|
|
|
if (filename_ptr == NULL)
|
2009-08-24 00:25:43 +03:00
|
|
|
{
|
2009-09-20 18:23:42 +03:00
|
|
|
log_error("malloc failed to allocate memory for studio file path");
|
2009-08-24 00:25:43 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-08-31 04:19:50 +03:00
|
|
|
if (backup_filename_ptr_ptr != NULL)
|
2009-08-30 13:23:36 +03:00
|
|
|
{
|
2009-08-31 04:19:50 +03:00
|
|
|
backup_filename_ptr = malloc(len_dir + 1 + strlen(name) * 3 + 4 + 4 + 1);
|
|
|
|
if (backup_filename_ptr == NULL)
|
|
|
|
{
|
2009-09-20 18:23:42 +03:00
|
|
|
log_error("malloc failed to allocate memory for studio backup file path");
|
2009-08-31 04:19:50 +03:00
|
|
|
free(filename_ptr);
|
|
|
|
return false;
|
|
|
|
}
|
2009-08-30 13:23:36 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
p = filename_ptr;
|
2009-08-24 00:25:43 +03:00
|
|
|
memcpy(p, g_studios_dir, len_dir);
|
|
|
|
p += len_dir;
|
|
|
|
|
|
|
|
*p++ = '/';
|
|
|
|
|
2009-08-30 13:23:36 +03:00
|
|
|
src = name;
|
2009-08-24 00:25:43 +03:00
|
|
|
escape(&src, &p);
|
|
|
|
strcpy(p, ".xml");
|
|
|
|
|
2009-08-30 13:23:36 +03:00
|
|
|
*filename_ptr_ptr = filename_ptr;
|
2009-08-31 04:19:50 +03:00
|
|
|
|
|
|
|
if (backup_filename_ptr_ptr != NULL)
|
|
|
|
{
|
|
|
|
strcpy(backup_filename_ptr, filename_ptr);
|
|
|
|
strcat(backup_filename_ptr, ".bak");
|
|
|
|
*backup_filename_ptr_ptr = backup_filename_ptr;
|
|
|
|
}
|
2009-08-30 13:23:36 +03:00
|
|
|
|
2009-08-24 00:25:43 +03:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2009-08-24 01:58:14 +03:00
|
|
|
bool studios_iterate(void * call_ptr, void * context, bool (* callback)(void * call_ptr, void * context, const char * studio, uint32_t modtime))
|
|
|
|
{
|
|
|
|
DIR * dir;
|
|
|
|
struct dirent * dentry;
|
|
|
|
size_t len;
|
|
|
|
struct stat st;
|
|
|
|
char * path;
|
2009-08-31 04:19:50 +03:00
|
|
|
char * name;
|
2009-08-24 01:58:14 +03:00
|
|
|
|
|
|
|
dir = opendir(g_studios_dir);
|
|
|
|
if (dir == NULL)
|
|
|
|
{
|
|
|
|
lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "Cannot open directory '%s': %d (%s)", g_studios_dir, errno, strerror(errno));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
while ((dentry = readdir(dir)) != NULL)
|
|
|
|
{
|
|
|
|
if (dentry->d_type != DT_REG)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
len = strlen(dentry->d_name);
|
2009-08-31 04:19:50 +03:00
|
|
|
if (len <= 4 || strcmp(dentry->d_name + (len - 4), ".xml") != 0)
|
2009-08-24 01:58:14 +03:00
|
|
|
continue;
|
|
|
|
|
|
|
|
path = catdup(g_studios_dir, dentry->d_name);
|
|
|
|
if (path == NULL)
|
|
|
|
{
|
|
|
|
lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "catdup() failed");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (stat(path, &st) != 0)
|
|
|
|
{
|
|
|
|
lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "failed to stat '%s': %d (%s)", path, errno, strerror(errno));
|
|
|
|
free(path);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
free(path);
|
|
|
|
|
2009-08-31 04:19:50 +03:00
|
|
|
name = malloc(len - 4 + 1);
|
|
|
|
name[unescape(dentry->d_name, len - 4, name)] = 0;
|
2009-09-20 18:23:42 +03:00
|
|
|
//log_info("name = '%s'", name);
|
2009-08-31 04:19:50 +03:00
|
|
|
|
|
|
|
if (!callback(call_ptr, context, name, st.st_mtime))
|
2009-08-24 01:58:14 +03:00
|
|
|
{
|
2009-08-31 04:19:50 +03:00
|
|
|
free(name);
|
2009-08-24 01:58:14 +03:00
|
|
|
closedir(dir);
|
|
|
|
return false;
|
|
|
|
}
|
2009-08-31 04:19:50 +03:00
|
|
|
|
|
|
|
free(name);
|
2009-08-24 01:58:14 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
closedir(dir);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2009-08-30 14:36:27 +03:00
|
|
|
bool studio_delete(void * call_ptr, const char * studio_name)
|
|
|
|
{
|
|
|
|
char * filename;
|
|
|
|
char * bak_filename;
|
|
|
|
struct stat st;
|
|
|
|
bool ret;
|
|
|
|
|
|
|
|
ret = false;
|
|
|
|
|
2009-09-12 14:50:35 +03:00
|
|
|
if (!studio_compose_filename(studio_name, &filename, &bak_filename))
|
2009-08-30 14:36:27 +03:00
|
|
|
{
|
|
|
|
lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "failed to compose studio filename");
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
2009-09-20 18:23:42 +03:00
|
|
|
log_info("Deleting studio ('%s')", filename);
|
2009-08-30 14:36:27 +03:00
|
|
|
|
|
|
|
if (unlink(filename) != 0)
|
|
|
|
{
|
|
|
|
lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "unlink(%s) failed: %d (%s)", filename, errno, strerror(errno));
|
|
|
|
goto free;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* try to delete the backup file */
|
|
|
|
if (stat(bak_filename, &st) == 0)
|
|
|
|
{
|
|
|
|
if (unlink(bak_filename) != 0)
|
|
|
|
{
|
|
|
|
/* failing to delete backup file will not case delete command failure */
|
2009-09-20 18:23:42 +03:00
|
|
|
log_error("unlink(%s) failed: %d (%s)", bak_filename, errno, strerror(errno));
|
2009-08-30 14:36:27 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = true;
|
|
|
|
|
|
|
|
free:
|
|
|
|
free(filename);
|
|
|
|
free(bak_filename);
|
|
|
|
exit:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2009-08-23 12:58:01 +03:00
|
|
|
void emit_studio_renamed()
|
|
|
|
{
|
2009-09-05 19:12:53 +03:00
|
|
|
dbus_signal_emit(g_dbus_connection, STUDIO_OBJECT_PATH, IFACE_STUDIO, "StudioRenamed", "s", &g_studio.name);
|
2009-08-23 12:58:01 +03:00
|
|
|
}
|
|
|
|
|
2009-09-05 18:18:07 +03:00
|
|
|
static void ladish_get_studio_name(struct dbus_method_call * call_ptr)
|
2009-08-23 11:09:15 +03:00
|
|
|
{
|
|
|
|
method_return_new_single(call_ptr, DBUS_TYPE_STRING, &g_studio.name);
|
|
|
|
}
|
|
|
|
|
2009-09-05 18:18:07 +03:00
|
|
|
static void ladish_rename_studio(struct dbus_method_call * call_ptr)
|
2009-08-23 11:09:15 +03:00
|
|
|
{
|
|
|
|
const char * new_name;
|
|
|
|
char * new_name_dup;
|
|
|
|
|
|
|
|
if (!dbus_message_get_args(call_ptr->message, &g_dbus_error, DBUS_TYPE_STRING, &new_name, DBUS_TYPE_INVALID))
|
|
|
|
{
|
|
|
|
lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, g_dbus_error.message);
|
|
|
|
dbus_error_free(&g_dbus_error);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-09-20 18:23:42 +03:00
|
|
|
log_info("Rename studio request (%s)", new_name);
|
2009-08-31 01:50:24 +03:00
|
|
|
|
2009-08-23 11:09:15 +03:00
|
|
|
new_name_dup = strdup(new_name);
|
|
|
|
if (new_name_dup == NULL)
|
|
|
|
{
|
|
|
|
lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "strdup() failed to allocate new name.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
free(g_studio.name);
|
|
|
|
g_studio.name = new_name_dup;
|
|
|
|
|
|
|
|
method_return_new_void(call_ptr);
|
2009-08-23 12:58:01 +03:00
|
|
|
emit_studio_renamed();
|
2009-08-23 11:09:15 +03:00
|
|
|
}
|
|
|
|
|
2009-09-05 18:18:07 +03:00
|
|
|
static void ladish_save_studio(struct dbus_method_call * call_ptr)
|
2009-08-07 23:28:34 +03:00
|
|
|
{
|
2009-08-24 01:04:07 +03:00
|
|
|
if (studio_save(call_ptr))
|
|
|
|
{
|
|
|
|
method_return_new_void(call_ptr);
|
|
|
|
}
|
2009-08-07 23:28:34 +03:00
|
|
|
}
|
2009-08-20 22:43:11 +03:00
|
|
|
|
2009-09-05 18:18:07 +03:00
|
|
|
static void ladish_unload_studio(struct dbus_method_call * call_ptr)
|
2009-08-30 16:23:19 +03:00
|
|
|
{
|
2009-09-20 18:23:42 +03:00
|
|
|
log_info("Unload studio request");
|
2009-10-08 23:45:03 +03:00
|
|
|
studio_clear(true);
|
2009-08-30 16:23:19 +03:00
|
|
|
method_return_new_void(call_ptr);
|
|
|
|
}
|
|
|
|
|
2009-08-30 16:13:38 +03:00
|
|
|
bool studio_new(void * call_ptr, const char * studio_name)
|
|
|
|
{
|
2009-09-20 18:23:42 +03:00
|
|
|
log_info("New studio request (%s)", studio_name);
|
2009-10-08 23:45:03 +03:00
|
|
|
if (!studio_clear(false))
|
|
|
|
{
|
|
|
|
lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "Cannot create new studio when other studio is running.");
|
|
|
|
return false;
|
|
|
|
}
|
2009-08-30 16:13:38 +03:00
|
|
|
|
2009-09-20 18:48:42 +03:00
|
|
|
ASSERT(g_studio.name == NULL);
|
2009-08-30 16:13:38 +03:00
|
|
|
if (*studio_name != 0)
|
|
|
|
{
|
|
|
|
g_studio.name = strdup(studio_name);
|
|
|
|
if (g_studio.name == NULL)
|
|
|
|
{
|
|
|
|
lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "strdup() failed to allocate studio name.");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (!studio_name_generate(&g_studio.name))
|
|
|
|
{
|
|
|
|
lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "studio_name_generate() failed.");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-08-30 18:38:17 +03:00
|
|
|
if (!studio_publish())
|
2009-08-30 16:13:38 +03:00
|
|
|
{
|
2009-08-30 18:38:17 +03:00
|
|
|
lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "studio_publish() failed.");
|
2009-10-08 23:45:03 +03:00
|
|
|
studio_clear(false);
|
2009-08-30 16:13:38 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2009-09-05 18:18:07 +03:00
|
|
|
static void ladish_stop_studio(struct dbus_method_call * call_ptr)
|
2009-08-30 22:40:28 +03:00
|
|
|
{
|
2009-09-20 18:23:42 +03:00
|
|
|
log_info("Studio stop requested");
|
2009-08-30 22:40:28 +03:00
|
|
|
|
2009-10-08 23:45:03 +03:00
|
|
|
if (!studio_stop(false, NULL))
|
2009-08-30 22:40:28 +03:00
|
|
|
{
|
|
|
|
lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "Failed to stop studio.");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
method_return_new_void(call_ptr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-05 18:18:07 +03:00
|
|
|
static void ladish_start_studio(struct dbus_method_call * call_ptr)
|
2009-08-30 22:40:28 +03:00
|
|
|
{
|
2009-09-20 18:23:42 +03:00
|
|
|
log_info("Studio start requested");
|
2009-08-30 22:40:28 +03:00
|
|
|
|
|
|
|
if (!studio_start())
|
|
|
|
{
|
|
|
|
lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "Failed to start studio.");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
method_return_new_void(call_ptr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-23 11:09:15 +03:00
|
|
|
METHOD_ARGS_BEGIN(GetName, "Get studio name")
|
|
|
|
METHOD_ARG_DESCRIBE_OUT("studio_name", "s", "Name of studio")
|
|
|
|
METHOD_ARGS_END
|
|
|
|
|
|
|
|
METHOD_ARGS_BEGIN(Rename, "Rename studio")
|
|
|
|
METHOD_ARG_DESCRIBE_IN("studio_name", "s", "New name")
|
|
|
|
METHOD_ARGS_END
|
|
|
|
|
2009-08-23 01:21:23 +03:00
|
|
|
METHOD_ARGS_BEGIN(Save, "Save studio")
|
|
|
|
METHOD_ARGS_END
|
|
|
|
|
2009-08-30 16:23:19 +03:00
|
|
|
METHOD_ARGS_BEGIN(Unload, "Unload studio")
|
|
|
|
METHOD_ARGS_END
|
|
|
|
|
2009-08-30 22:40:28 +03:00
|
|
|
METHOD_ARGS_BEGIN(Start, "Start studio")
|
|
|
|
METHOD_ARGS_END
|
|
|
|
|
|
|
|
METHOD_ARGS_BEGIN(Stop, "Stop studio")
|
|
|
|
METHOD_ARGS_END
|
|
|
|
|
2009-08-20 22:43:11 +03:00
|
|
|
METHODS_BEGIN
|
2009-08-23 11:09:15 +03:00
|
|
|
METHOD_DESCRIBE(GetName, ladish_get_studio_name)
|
|
|
|
METHOD_DESCRIBE(Rename, ladish_rename_studio)
|
2009-08-23 01:21:23 +03:00
|
|
|
METHOD_DESCRIBE(Save, ladish_save_studio)
|
2009-08-30 16:23:19 +03:00
|
|
|
METHOD_DESCRIBE(Unload, ladish_unload_studio)
|
2009-08-30 22:40:28 +03:00
|
|
|
METHOD_DESCRIBE(Start, ladish_start_studio)
|
|
|
|
METHOD_DESCRIBE(Stop, ladish_stop_studio)
|
2009-08-20 22:43:11 +03:00
|
|
|
METHODS_END
|
|
|
|
|
2009-08-23 12:58:01 +03:00
|
|
|
SIGNAL_ARGS_BEGIN(StudioRenamed, "Studio name changed")
|
|
|
|
SIGNAL_ARG_DESCRIBE("studio_name", "s", "New studio name")
|
|
|
|
SIGNAL_ARGS_END
|
|
|
|
|
2009-08-30 22:40:28 +03:00
|
|
|
SIGNAL_ARGS_BEGIN(StudioStarted, "Studio started")
|
|
|
|
SIGNAL_ARGS_END
|
|
|
|
|
|
|
|
SIGNAL_ARGS_BEGIN(StudioStopped, "Studio stopped")
|
|
|
|
SIGNAL_ARGS_END
|
|
|
|
|
2009-08-20 22:43:11 +03:00
|
|
|
SIGNAL_ARGS_BEGIN(RoomAppeared, "Room D-Bus object appeared")
|
|
|
|
SIGNAL_ARG_DESCRIBE("room_path", "s", "room object path")
|
|
|
|
SIGNAL_ARGS_END
|
|
|
|
|
|
|
|
SIGNAL_ARGS_BEGIN(RoomDisappeared, "Room D-Bus object disappeared")
|
|
|
|
SIGNAL_ARG_DESCRIBE("room_path", "s", "room object path")
|
|
|
|
SIGNAL_ARGS_END
|
|
|
|
|
|
|
|
SIGNALS_BEGIN
|
2009-08-23 12:58:01 +03:00
|
|
|
SIGNAL_DESCRIBE(StudioRenamed)
|
2009-08-30 22:40:28 +03:00
|
|
|
SIGNAL_DESCRIBE(StudioStarted)
|
|
|
|
SIGNAL_DESCRIBE(StudioStopped)
|
2009-08-20 22:43:11 +03:00
|
|
|
SIGNAL_DESCRIBE(RoomAppeared)
|
|
|
|
SIGNAL_DESCRIBE(RoomDisappeared)
|
|
|
|
SIGNALS_END
|
|
|
|
|
2009-08-22 03:07:19 +03:00
|
|
|
INTERFACE_BEGIN(g_interface_studio, IFACE_STUDIO)
|
2009-08-20 22:43:11 +03:00
|
|
|
INTERFACE_DEFAULT_HANDLER
|
|
|
|
INTERFACE_EXPOSE_METHODS
|
|
|
|
INTERFACE_EXPOSE_SIGNALS
|
|
|
|
INTERFACE_END
|