Add app list version number to the AppStateChanged signal and check it
[ladish.git] / daemon / control.c
blob414d5f1d182514959d3e94b8ab6d850e6d0eba0d
1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*
3 * LADI Session Handler (ladish)
5 * Copyright (C) 2008, 2009, 2010 Nedko Arnaudov <nedko@arnaudov.name>
6 * Copyright (C) 2008 Juuso Alasuutari <juuso.alasuutari@gmail.com>
8 **************************************************************************
9 * This file contains code of the D-Bus control interface helpers
10 **************************************************************************
12 * LADI Session Handler is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * LADI Session Handler is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with LADI Session Handler. If not, see <http://www.gnu.org/licenses/>
24 * or write to the Free Software Foundation, Inc.,
25 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
28 #include "common.h"
29 #include "studio.h"
30 #include "../dbus/error.h"
31 #include "control.h"
32 #include "../dbus_constants.h"
33 #include "cmd.h"
34 #include "room.h"
35 #include "../lib/wkports.h"
37 #define INTERFACE_NAME IFACE_CONTROL
39 /* 805e485f-65e4-4c37-a959-2a3b60b3c270 */
40 UUID_DEFINE(empty_room,0x80,0x5E,0x48,0x5F,0x65,0xE4,0x4C,0x37,0xA9,0x59,0x2A,0x3B,0x60,0xB3,0xC2,0x70);
42 /* c603f2a0-d96a-493e-a8cf-55581d950aa9 */
43 UUID_DEFINE(basic_room,0xC6,0x03,0xF2,0xA0,0xD9,0x6A,0x49,0x3E,0xA8,0xCF,0x55,0x58,0x1D,0x95,0x0A,0xA9);
45 static struct list_head g_room_templates;
47 static bool create_empty_room_template(const uuid_t uuid_ptr, const char * name, ladish_room_handle * room_ptr)
49 if (!ladish_room_create_template(uuid_ptr, name, room_ptr))
51 log_error("ladish_room_create_template() failed for room template \"%s\".", name);
52 return false;
55 return true;
58 struct room_descriptor
60 const char * name;
61 ladish_room_handle room;
62 ladish_graph_handle graph;
63 ladish_client_handle capture;
64 ladish_client_handle playback;
67 static
68 bool
69 create_room_template(
70 const uuid_t uuid_ptr,
71 const char * name,
72 struct room_descriptor * room_descriptor_ptr)
74 ladish_room_handle room;
75 ladish_graph_handle graph;
76 ladish_client_handle capture;
77 ladish_client_handle playback;
79 if (!create_empty_room_template(uuid_ptr, name, &room))
81 log_error("ladish_room_create() failed for room template \"%s\".", name);
82 goto fail;
85 graph = ladish_room_get_graph(room);
87 if (!ladish_client_create(ladish_wkclient_capture, &capture))
89 log_error("ladish_client_create() failed to create capture client to room template \"%s\".", name);
90 goto fail_destroy;
93 if (!ladish_graph_add_client(graph, capture, "Capture", false))
95 log_error("ladish_graph_add_client() failed to add capture client to room template \"%s\".", name);
96 goto fail_destroy;
99 if (!ladish_client_create(ladish_wkclient_playback, &playback))
101 log_error("ladish_client_create() failed to create playback client to room template \"%s\".", name);
102 goto fail_destroy;
105 if (!ladish_graph_add_client(graph, playback, "Playback", false))
107 log_error("ladish_graph_add_client() failed to add playback client to room template \"%s\".", name);
108 goto fail_destroy;
111 room_descriptor_ptr->name = ladish_room_get_name(room);
112 room_descriptor_ptr->room = room;
113 room_descriptor_ptr->graph = graph;
114 room_descriptor_ptr->capture = capture;
115 room_descriptor_ptr->playback = playback;
117 return true;
119 fail_destroy:
120 ladish_room_destroy(room); /* this will destroy the graph clients as well */
121 fail:
122 return false;
125 static
126 bool
127 create_room_template_port(
128 struct room_descriptor * room_descriptor_ptr,
129 const uuid_t uuid_ptr,
130 const char * name,
131 uint32_t type,
132 uint32_t flags)
134 ladish_port_handle port;
135 bool playback;
136 ladish_client_handle client;
138 playback = JACKDBUS_PORT_IS_INPUT(flags);
139 ASSERT(playback || JACKDBUS_PORT_IS_OUTPUT(flags)); /* playback or capture */
140 ASSERT(!(playback && JACKDBUS_PORT_IS_OUTPUT(flags))); /* but not both */
141 client = playback ? room_descriptor_ptr->playback : room_descriptor_ptr->capture;
143 if (!ladish_port_create(uuid_ptr, true, &port))
145 log_error("Creation of room template \"%s\" %s port \"%s\" failed.", room_descriptor_ptr->name, playback ? "playback" : "capture", name);
146 return false;
149 if (!ladish_graph_add_port(room_descriptor_ptr->graph, client, port, name, type, flags, false))
151 log_error("Adding of room template \"%s\" %s port \"%s\" to graph failed.", room_descriptor_ptr->name, playback ? "playback" : "capture", name);
152 ladish_port_destroy(port);
153 return false;
156 return true;
159 void create_builtin_room_templates(void)
161 struct room_descriptor room_descriptor;
163 if (create_empty_room_template(empty_room, "Empty", &room_descriptor.room))
165 list_add_tail(ladish_room_get_list_node(room_descriptor.room), &g_room_templates);
168 if (create_room_template(basic_room, "Basic", &room_descriptor))
170 if (!create_room_template_port(&room_descriptor, ladish_wkport_capture_left, "Left", JACKDBUS_PORT_TYPE_AUDIO, JACKDBUS_PORT_FLAG_OUTPUT))
172 goto fail;
175 if (!create_room_template_port(&room_descriptor, ladish_wkport_capture_right, "Right", JACKDBUS_PORT_TYPE_AUDIO, JACKDBUS_PORT_FLAG_OUTPUT))
177 goto fail;
180 if (!create_room_template_port(&room_descriptor, ladish_wkport_midi_capture, "MIDI", JACKDBUS_PORT_TYPE_MIDI, JACKDBUS_PORT_FLAG_OUTPUT))
182 goto fail;
185 if (!create_room_template_port(&room_descriptor, ladish_wkport_playback_left, "Left", JACKDBUS_PORT_TYPE_AUDIO, JACKDBUS_PORT_FLAG_INPUT))
187 goto fail;
190 if (!create_room_template_port(&room_descriptor, ladish_wkport_playback_right, "Right", JACKDBUS_PORT_TYPE_AUDIO, JACKDBUS_PORT_FLAG_INPUT))
192 goto fail;
195 if (!create_room_template_port(&room_descriptor, ladish_wkport_monitor_left, "Monitor Left", JACKDBUS_PORT_TYPE_AUDIO, JACKDBUS_PORT_FLAG_INPUT))
197 goto fail;
200 if (!create_room_template_port(&room_descriptor, ladish_wkport_monitor_right, "Monitor Right", JACKDBUS_PORT_TYPE_AUDIO, JACKDBUS_PORT_FLAG_INPUT))
202 goto fail;
205 if (!create_room_template_port(&room_descriptor, ladish_wkport_midi_playback, "MIDI", JACKDBUS_PORT_TYPE_MIDI, JACKDBUS_PORT_FLAG_INPUT))
207 goto fail;
210 list_add_tail(ladish_room_get_list_node(room_descriptor.room), &g_room_templates);
213 return;
215 fail:
216 ladish_room_destroy(room_descriptor.room); /* this will destroy the graph clients and ports as well */
219 void create_room_templates(void)
221 create_builtin_room_templates();
224 void maybe_create_room_templates(void)
226 if (list_empty(&g_room_templates))
228 create_room_templates();
232 bool room_templates_init(void)
234 INIT_LIST_HEAD(&g_room_templates);
236 return true;
239 void room_templates_uninit(void)
241 struct list_head * node_ptr;
242 ladish_room_handle room;
244 while (!list_empty(&g_room_templates))
246 node_ptr = g_room_templates.next;
247 list_del(node_ptr);
248 room = ladish_room_from_list_node(node_ptr);
249 ladish_room_destroy(room);
253 bool room_templates_enum(void * context, bool (* callback)(void * context, ladish_room_handle room))
255 struct list_head * node_ptr;
257 maybe_create_room_templates();
259 list_for_each(node_ptr, &g_room_templates)
261 if (!callback(context, ladish_room_from_list_node(node_ptr)))
263 return false;
267 return true;
270 ladish_room_handle find_room_template_by_name(const char * name)
272 ladish_room_handle room;
273 struct list_head * node_ptr;
275 maybe_create_room_templates();
277 list_for_each(node_ptr, &g_room_templates)
279 room = ladish_room_from_list_node(node_ptr);
280 if (strcmp(ladish_room_get_name(room), name) == 0)
282 return room;
286 return NULL;
289 ladish_room_handle find_room_template_by_uuid(const uuid_t uuid_ptr)
291 ladish_room_handle room;
292 struct list_head * node_ptr;
293 uuid_t uuid;
295 maybe_create_room_templates();
297 list_for_each(node_ptr, &g_room_templates)
299 room = ladish_room_from_list_node(node_ptr);
300 ladish_room_get_uuid(room, uuid);
301 if (uuid_compare(uuid, uuid_ptr) == 0)
303 return room;
307 return NULL;
310 static void ladish_is_studio_loaded(struct dbus_method_call * call_ptr)
312 DBusMessageIter iter;
313 dbus_bool_t is_loaded;
315 is_loaded = ladish_studio_is_loaded();
317 call_ptr->reply = dbus_message_new_method_return(call_ptr->message);
318 if (call_ptr->reply == NULL)
320 goto fail;
323 dbus_message_iter_init_append(call_ptr->reply, &iter);
325 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &is_loaded))
327 goto fail_unref;
330 return;
332 fail_unref:
333 dbus_message_unref(call_ptr->reply);
334 call_ptr->reply = NULL;
336 fail:
337 log_error("Ran out of memory trying to construct method return");
340 #define array_iter_ptr ((DBusMessageIter *)context)
342 static bool get_studio_list_callback(void * call_ptr, void * context, const char * studio, uint32_t modtime)
344 DBusMessageIter struct_iter;
345 DBusMessageIter dict_iter;
346 bool ret;
348 ret = false;
350 if (!dbus_message_iter_open_container(array_iter_ptr, DBUS_TYPE_STRUCT, NULL, &struct_iter))
351 goto exit;
353 if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &studio))
354 goto close_struct;
356 if (!dbus_message_iter_open_container(&struct_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter))
357 goto close_struct;
359 /* if (!maybe_add_dict_entry_string(&dict_iter, "Description", xxx)) */
360 /* goto close_dict; */
362 if (!dbus_add_dict_entry_uint32(&dict_iter, "Modification Time", modtime))
363 goto close_dict;
365 ret = true;
367 close_dict:
368 if (!dbus_message_iter_close_container(&struct_iter, &dict_iter))
369 ret = false;
371 close_struct:
372 if (!dbus_message_iter_close_container(array_iter_ptr, &struct_iter))
373 ret = false;
375 exit:
376 return ret;
379 static void ladish_get_studio_list(struct dbus_method_call * call_ptr)
381 DBusMessageIter iter, array_iter;
383 call_ptr->reply = dbus_message_new_method_return(call_ptr->message);
384 if (call_ptr->reply == NULL)
386 goto fail;
389 dbus_message_iter_init_append(call_ptr->reply, &iter);
391 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sa{sv})", &array_iter))
393 goto fail_unref;
396 if (!ladish_studios_iterate(call_ptr, &array_iter, get_studio_list_callback))
398 dbus_message_iter_close_container(&iter, &array_iter);
399 if (call_ptr->reply == NULL)
400 goto fail_unref;
402 /* studios_iterate or get_studio_list_callback() composed error reply */
403 return;
406 if (!dbus_message_iter_close_container(&iter, &array_iter))
408 goto fail_unref;
411 return;
413 fail_unref:
414 dbus_message_unref(call_ptr->reply);
415 call_ptr->reply = NULL;
417 fail:
418 log_error("Ran out of memory trying to construct method return");
421 static void ladish_load_studio(struct dbus_method_call * call_ptr)
423 const char * name;
425 dbus_error_init(&g_dbus_error);
427 if (!dbus_message_get_args(call_ptr->message, &g_dbus_error, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID))
429 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, g_dbus_error.message);
430 dbus_error_free(&g_dbus_error);
431 return;
434 log_info("Load studio request (%s)", name);
436 if (ladish_command_load_studio(call_ptr, ladish_studio_get_cmd_queue(), name))
438 method_return_new_void(call_ptr);
442 static void ladish_delete_studio(struct dbus_method_call * call_ptr)
444 const char * name;
446 dbus_error_init(&g_dbus_error);
448 if (!dbus_message_get_args(call_ptr->message, &g_dbus_error, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID))
450 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, g_dbus_error.message);
451 dbus_error_free(&g_dbus_error);
452 return;
455 if (ladish_studio_delete(call_ptr, name))
457 method_return_new_void(call_ptr);
461 static void ladish_new_studio(struct dbus_method_call * call_ptr)
463 const char * name;
465 dbus_error_init(&g_dbus_error);
467 if (!dbus_message_get_args(call_ptr->message, &g_dbus_error, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID))
469 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, g_dbus_error.message);
470 dbus_error_free(&g_dbus_error);
471 return;
474 log_info("New studio request (%s)", name);
476 if (ladish_command_new_studio(call_ptr, ladish_studio_get_cmd_queue(), name))
478 method_return_new_void(call_ptr);
482 static void ladish_get_application_list(struct dbus_method_call * call_ptr)
484 DBusMessageIter iter;
485 DBusMessageIter array_iter;
486 #if 0
487 DBusMessageIter struct_iter;
488 DBusMessageIter dict_iter;
489 struct list_head * node_ptr;
490 struct lash_appdb_entry * entry_ptr;
491 #endif
493 log_info("Getting applications list");
495 call_ptr->reply = dbus_message_new_method_return(call_ptr->message);
496 if (call_ptr->reply == NULL)
498 goto fail;
501 dbus_message_iter_init_append(call_ptr->reply, &iter);
503 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sa{sv})", &array_iter))
505 goto fail_unref;
508 #if 0
509 list_for_each(node_ptr, &g_server->appdb)
511 entry_ptr = list_entry(node_ptr, struct lash_appdb_entry, siblings);
513 if (!dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, NULL, &struct_iter))
514 goto fail_unref;
516 if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, (const void *) &entry_ptr->name))
518 dbus_message_iter_close_container(&iter, &array_iter);
519 goto fail_unref;
522 if (!dbus_message_iter_open_container(&struct_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter))
523 goto fail_unref;
525 if (!maybe_add_dict_entry_string(&dict_iter, "GenericName", entry_ptr->generic_name))
526 goto fail_unref;
528 if (!maybe_add_dict_entry_string(&dict_iter, "Comment", entry_ptr->comment))
529 goto fail_unref;
531 if (!maybe_add_dict_entry_string(&dict_iter, "Icon", entry_ptr->icon))
532 goto fail_unref;
534 if (!dbus_message_iter_close_container(&struct_iter, &dict_iter))
535 goto fail_unref;
537 if (!dbus_message_iter_close_container(&array_iter, &struct_iter))
538 goto fail_unref;
540 #endif
542 if (!dbus_message_iter_close_container(&iter, &array_iter))
544 goto fail_unref;
547 return;
549 fail_unref:
550 dbus_message_unref(call_ptr->reply);
551 call_ptr->reply = NULL;
552 fail:
553 return;
556 #define array_iter_ptr ((DBusMessageIter *)context)
558 bool room_template_list_filler(void * context, ladish_room_handle room)
560 DBusMessageIter struct_iter;
561 DBusMessageIter dict_iter;
562 const char * name;
564 name = ladish_room_get_name(room);
566 if (!dbus_message_iter_open_container(array_iter_ptr, DBUS_TYPE_STRUCT, NULL, &struct_iter))
567 return false;
569 if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &name))
570 return false;
572 if (!dbus_message_iter_open_container(&struct_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter))
573 return false;
575 if (!dbus_message_iter_close_container(&struct_iter, &dict_iter))
576 return false;
578 if (!dbus_message_iter_close_container(array_iter_ptr, &struct_iter))
579 return false;
581 return true;
584 #undef array_iter_ptr
586 static void ladish_get_room_template_list(struct dbus_method_call * call_ptr)
588 DBusMessageIter iter, array_iter;
590 call_ptr->reply = dbus_message_new_method_return(call_ptr->message);
591 if (call_ptr->reply == NULL)
593 goto fail;
596 dbus_message_iter_init_append(call_ptr->reply, &iter);
598 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sa{sv})", &array_iter))
600 goto fail_unref;
603 if (!room_templates_enum(&array_iter, room_template_list_filler))
605 goto fail_unref;
608 if (!dbus_message_iter_close_container(&iter, &array_iter))
610 goto fail_unref;
613 return;
615 fail_unref:
616 dbus_message_unref(call_ptr->reply);
617 call_ptr->reply = NULL;
619 fail:
620 log_error("Ran out of memory trying to construct method return");
623 static void ladish_delete_room_template(struct dbus_method_call * call_ptr)
625 const char * name;
627 dbus_error_init(&g_dbus_error);
629 if (!dbus_message_get_args(call_ptr->message, &g_dbus_error, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID))
631 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, g_dbus_error.message);
632 dbus_error_free(&g_dbus_error);
633 return;
636 log_info("Delete room request (%s)", name);
639 method_return_new_void(call_ptr);
643 static void ladish_create_room_template(struct dbus_method_call * call_ptr)
645 const char * name;
647 dbus_error_init(&g_dbus_error);
649 if (!dbus_message_get_args(call_ptr->message, &g_dbus_error, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID))
651 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, g_dbus_error.message);
652 dbus_error_free(&g_dbus_error);
653 return;
656 log_info("New room request (%s)", name);
659 method_return_new_void(call_ptr);
663 static void ladish_exit(struct dbus_method_call * call_ptr)
665 log_info("Exit command received through D-Bus");
667 if (!ladish_command_exit(NULL, ladish_studio_get_cmd_queue()))
668 { /* if queuing of command failed, force exit anyway,
669 JACK server will be left started,
670 but refusing exit command is worse */
671 g_quit = true;
674 method_return_new_void(call_ptr);
677 void emit_studio_appeared(void)
679 dbus_signal_emit(g_dbus_connection, CONTROL_OBJECT_PATH, INTERFACE_NAME, "StudioAppeared", "");
682 void emit_studio_disappeared(void)
684 dbus_signal_emit(g_dbus_connection, CONTROL_OBJECT_PATH, INTERFACE_NAME, "StudioDisappeared", "");
687 void emit_queue_execution_halted(void)
689 dbus_signal_emit(g_dbus_connection, CONTROL_OBJECT_PATH, INTERFACE_NAME, "QueueExecutionHalted", "");
692 void emit_clean_exit(void)
694 dbus_signal_emit(g_dbus_connection, CONTROL_OBJECT_PATH, INTERFACE_NAME, "CleanExit", "");
697 METHOD_ARGS_BEGIN(IsStudioLoaded, "Check whether studio D-Bus object is present")
698 METHOD_ARG_DESCRIBE_OUT("present", "b", "Whether studio D-Bus object is present")
699 METHOD_ARGS_END
701 METHOD_ARGS_BEGIN(GetStudioList, "Get list of studios")
702 METHOD_ARG_DESCRIBE_OUT("studio_list", "a(sa{sv})", "List of studios, name and properties")
703 METHOD_ARGS_END
705 METHOD_ARGS_BEGIN(NewStudio, "New studio")
706 METHOD_ARG_DESCRIBE_IN("studio_name", "s", "Name of studio, if empty name will be generated")
707 METHOD_ARGS_END
709 METHOD_ARGS_BEGIN(LoadStudio, "Load studio")
710 METHOD_ARG_DESCRIBE_IN("studio_name", "s", "Name of studio to load")
711 METHOD_ARG_DESCRIBE_IN("options", "a{sv}", "Load options")
712 METHOD_ARGS_END
714 METHOD_ARGS_BEGIN(DeleteStudio, "Delete studio")
715 METHOD_ARG_DESCRIBE_IN("studio_name", "s", "Name of studio to delete")
716 METHOD_ARGS_END
718 METHOD_ARGS_BEGIN(GetApplicationList, "Get list of applications that can be launched")
719 METHOD_ARG_DESCRIBE_OUT("applications", "a(sa{sv})", "List of applications, name and properties")
720 METHOD_ARGS_END
722 METHOD_ARGS_BEGIN(GetRoomTemplateList, "Get list of room templates")
723 METHOD_ARG_DESCRIBE_OUT("room_template_list", "a(sa{sv})", "List of room templates (name and properties)")
724 METHOD_ARGS_END
726 METHOD_ARGS_BEGIN(CreateRoomTemplate, "New room template")
727 METHOD_ARG_DESCRIBE_IN("room_template name", "s", "Name of the room template")
728 METHOD_ARGS_END
730 METHOD_ARGS_BEGIN(DeleteRoomTemplate, "Delete room template")
731 METHOD_ARG_DESCRIBE_IN("room_template_name", "s", "Name of room template to delete")
732 METHOD_ARGS_END
734 METHOD_ARGS_BEGIN(Exit, "Tell ladish D-Bus service to exit")
735 METHOD_ARGS_END
737 METHODS_BEGIN
738 METHOD_DESCRIBE(IsStudioLoaded, ladish_is_studio_loaded)
739 METHOD_DESCRIBE(GetStudioList, ladish_get_studio_list)
740 METHOD_DESCRIBE(NewStudio, ladish_new_studio)
741 METHOD_DESCRIBE(LoadStudio, ladish_load_studio)
742 METHOD_DESCRIBE(DeleteStudio, ladish_delete_studio)
743 METHOD_DESCRIBE(GetApplicationList, ladish_get_application_list)
744 METHOD_DESCRIBE(GetRoomTemplateList, ladish_get_room_template_list)
745 METHOD_DESCRIBE(CreateRoomTemplate, ladish_create_room_template)
746 METHOD_DESCRIBE(DeleteRoomTemplate, ladish_delete_room_template)
747 METHOD_DESCRIBE(Exit, ladish_exit)
748 METHODS_END
750 SIGNAL_ARGS_BEGIN(StudioAppeared, "Studio D-Bus object appeared")
751 SIGNAL_ARGS_END
753 SIGNAL_ARGS_BEGIN(StudioDisappeared, "Studio D-Bus object disappeared")
754 SIGNAL_ARGS_END
756 SIGNAL_ARGS_BEGIN(QueueExecutionHalted, "Queue execution is halted because of error")
757 SIGNAL_ARGS_END
759 SIGNAL_ARGS_BEGIN(CleanExit, "Exit was requested")
760 SIGNAL_ARGS_END
762 SIGNALS_BEGIN
763 SIGNAL_DESCRIBE(StudioAppeared)
764 SIGNAL_DESCRIBE(StudioDisappeared)
765 SIGNAL_DESCRIBE(QueueExecutionHalted)
766 SIGNAL_DESCRIBE(CleanExit)
767 SIGNALS_END
770 * Interface description.
773 INTERFACE_BEGIN(g_lashd_interface_control, INTERFACE_NAME)
774 INTERFACE_DEFAULT_HANDLER
775 INTERFACE_EXPOSE_METHODS
776 INTERFACE_EXPOSE_SIGNALS
777 INTERFACE_END