daemon: Router templates
[ladish.git] / daemon / room.c
blobfb6b9c21b9d66208eefbdef823bfbcc348eab759
1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*
3 * LADI Session Handler (ladish)
5 * Copyright (C) 2010 Nedko Arnaudov <nedko@arnaudov.name>
7 **************************************************************************
8 * This file contains the core parts of room object implementation
9 **************************************************************************
11 * LADI Session Handler is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * LADI Session Handler is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with LADI Session Handler. If not, see <http://www.gnu.org/licenses/>
23 * or write to the Free Software Foundation, Inc.,
24 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include "room_internal.h"
28 #include "../dbus_constants.h"
29 #include "graph_dict.h"
30 #include "../lib/wkports.h"
31 #include "studio.h"
32 #include "../proxies/jmcore_proxy.h"
33 #include "cmd.h"
34 #include "../dbus/error.h"
36 extern const struct dbus_interface_descriptor g_interface_room;
38 static bool port_is_input(uint32_t flags)
40 bool playback;
42 playback = JACKDBUS_PORT_IS_INPUT(flags);
43 ASSERT(playback || JACKDBUS_PORT_IS_OUTPUT(flags)); /* playback or capture */
44 ASSERT(!(playback && JACKDBUS_PORT_IS_OUTPUT(flags))); /* but not both */
46 return playback;
49 struct ladish_room * ladish_room_create_internal(const uuid_t uuid_ptr, const char * name, const char * object_path)
51 struct ladish_room * room_ptr;
53 room_ptr = malloc(sizeof(struct ladish_room));
54 if (room_ptr == NULL)
56 log_error("malloc() failed to allocate struct ladish_room");
57 goto fail;
60 if (uuid_ptr != NULL)
62 uuid_copy(room_ptr->uuid, uuid_ptr);
64 else
66 uuid_generate(room_ptr->uuid);
69 room_ptr->name = strdup(name);
70 if (room_ptr->name == NULL)
72 log_error("strdup() failed for room name");
73 goto free_room;
76 if (object_path != NULL)
78 room_ptr->object_path = strdup(object_path);
79 if (room_ptr->object_path == NULL)
81 log_error("strdup() failed for room name");
82 goto free_name;
86 if (!ladish_graph_create(&room_ptr->graph, object_path))
88 goto free_opath;
91 return room_ptr;
93 free_opath:
94 if (object_path != NULL)
96 free(room_ptr->object_path);
98 free_name:
99 free(room_ptr->name);
100 free_room:
101 free(room_ptr);
102 fail:
103 return NULL;
106 bool
107 ladish_room_create_template(
108 const uuid_t uuid_ptr,
109 const char * name,
110 ladish_room_handle * room_handle_ptr)
112 struct ladish_room * room_ptr;
114 room_ptr = ladish_room_create_internal(uuid_ptr, name, NULL);
115 if (room_ptr == NULL)
117 return false;
120 room_ptr->template = true;
122 *room_handle_ptr = (ladish_room_handle)room_ptr;
123 return true;
126 #define room_ptr ((struct ladish_room *)context)
128 static
129 bool
130 create_shadow_port(
131 void * context,
132 ladish_port_handle port_handle,
133 const char * port_name,
134 uint32_t port_type,
135 uint32_t port_flags)
137 //log_info("Studio room port \"%s\"", port_name);
139 if (port_is_input(port_flags))
141 JACKDBUS_PORT_CLEAR_INPUT(port_flags);
142 JACKDBUS_PORT_SET_OUTPUT(port_flags);
144 else
146 JACKDBUS_PORT_CLEAR_OUTPUT(port_flags);
147 JACKDBUS_PORT_SET_INPUT(port_flags);
150 if (!ladish_graph_add_port(room_ptr->owner, room_ptr->client, port_handle, port_name, port_type, port_flags, true))
152 log_error("ladish_graph_add_port() failed to add link port to room owner graph");
153 return false;
156 return true;
159 static
160 bool
161 create_port_link(
162 void * context,
163 ladish_port_handle port_handle,
164 const char * port_name,
165 uint32_t port_type,
166 uint32_t port_flags)
168 uuid_t uuid_in_owner;
169 uuid_t uuid_in_room;
170 char uuid_in_owner_str[37];
171 char uuid_in_room_str[37];
172 const char * input_port;
173 const char * output_port;
175 //log_info("Room port \"%s\"", port_name);
177 ladish_graph_get_port_uuid(room_ptr->graph, port_handle, uuid_in_room);
178 ladish_graph_get_port_uuid(room_ptr->owner, port_handle, uuid_in_owner);
180 uuid_unparse(uuid_in_room, uuid_in_room_str);
181 uuid_unparse(uuid_in_owner, uuid_in_owner_str);
183 if (port_is_input(port_flags))
185 input_port = uuid_in_room_str;
186 output_port = uuid_in_owner_str;
187 log_info("room input port %s is linked to owner graph output port %s", input_port, output_port);
189 else
191 input_port = uuid_in_owner_str;
192 output_port = uuid_in_room_str;
193 log_info("owner graph input port %s is linked to room output port %s", input_port, output_port);
196 if (!jmcore_proxy_create_link(port_type == JACKDBUS_PORT_TYPE_MIDI, input_port, output_port))
198 log_error("jmcore_proxy_create_link() failed.");
199 return false;
202 return true;
205 static
206 bool
207 destroy_port_link(
208 void * context,
209 ladish_graph_handle graph_handle,
210 void * client_iteration_context_ptr,
211 ladish_client_handle client_handle,
212 const char * client_name,
213 ladish_port_handle port_handle,
214 const char * port_name,
215 uint32_t port_type,
216 uint32_t port_flags)
218 uuid_t uuid_in_room;
219 char uuid_in_room_str[37];
221 if (ladish_port_is_link(port_handle))
223 log_info("link port %s", port_name);
225 ladish_graph_get_port_uuid(ladish_room_get_graph(context), port_handle, uuid_in_room);
226 uuid_unparse(uuid_in_room, uuid_in_room_str);
227 jmcore_proxy_destroy_link(uuid_in_room_str);
229 else
231 log_info("jack port %s", port_name);
234 return true;
237 #undef room_ptr
239 static void remove_port_callback(ladish_port_handle port)
241 ladish_graph_handle jack_graph;
242 ladish_client_handle jack_client;
244 jack_graph = ladish_studio_get_jack_graph();
246 jack_client = ladish_graph_remove_port(jack_graph, port);
247 if (jack_client == NULL)
248 { /* room app port not found in jack graph */
249 /* this can happen if the port is hidden in the vgraph */
250 return;
253 if (ladish_graph_client_is_empty(jack_graph, jack_client))
255 ladish_graph_remove_client(jack_graph, jack_client);
259 bool
260 ladish_room_create(
261 const uuid_t uuid_ptr,
262 const char * name,
263 ladish_room_handle template,
264 ladish_graph_handle owner,
265 ladish_room_handle * room_handle_ptr)
267 struct ladish_room * room_ptr;
268 char object_path[1024];
269 unsigned int index;
271 index = ladish_studio_get_room_index();
272 sprintf(object_path, DBUS_BASE_PATH "/Room%u", index);
274 room_ptr = ladish_room_create_internal(uuid_ptr, name, object_path);
275 if (room_ptr == NULL)
277 goto release_index;
280 room_ptr->template = false;
281 room_ptr->index = index;
282 room_ptr->owner = owner;
283 room_ptr->started = false;
284 room_ptr->version = 1;
286 room_ptr->project_name = NULL;
287 room_ptr->project_dir = NULL;
288 room_ptr->project_unloading = false;
290 if (template != NULL)
292 ladish_room_get_uuid(template, room_ptr->template_uuid);
293 if (!ladish_graph_copy(ladish_room_get_graph(template), room_ptr->graph, false))
295 goto destroy;
298 else
300 uuid_clear(room_ptr->template_uuid);
303 if (!ladish_app_supervisor_create(&room_ptr->app_supervisor, object_path, room_ptr->name, room_ptr->graph, ladish_virtualizer_rename_app))
305 log_error("ladish_app_supervisor_create() failed.");
306 goto destroy;
309 room_ptr->dbus_object = dbus_object_path_new(
310 object_path,
311 &g_interface_room, room_ptr,
312 &g_interface_patchbay, ladish_graph_get_dbus_context(room_ptr->graph),
313 &g_iface_graph_dict, room_ptr->graph,
314 &g_iface_app_supervisor, room_ptr->app_supervisor,
315 NULL);
316 if (room_ptr->dbus_object == NULL)
318 log_error("dbus_object_path_new() failed");
319 goto destroy_app_supervisor;
322 if (!dbus_object_path_register(g_dbus_connection, room_ptr->dbus_object))
324 log_error("object_path_register() failed");
325 goto destroy_dbus_object;
328 log_info("D-Bus object \"%s\" created for room \"%s\".", object_path, room_ptr->name);
330 if (!ladish_client_create(room_ptr->uuid, &room_ptr->client))
332 log_error("ladish_client_create() failed.");
333 goto unregister_dbus_object;
336 if (!ladish_graph_add_client(owner, room_ptr->client, room_ptr->name, true))
338 log_error("ladish_graph_add_client() failed to add room client to owner graph.");
339 goto destroy_client;
342 if (!ladish_room_iterate_link_ports((ladish_room_handle)room_ptr, room_ptr, create_shadow_port))
344 log_error("Creation of studio room link ports failed.");
345 goto remove_client;
348 ladish_studio_room_appeared((ladish_room_handle)room_ptr);
350 *room_handle_ptr = (ladish_room_handle)room_ptr;
351 return true;
353 remove_client:
354 ladish_graph_remove_client(owner, room_ptr->client);
355 destroy_client:
356 ladish_client_destroy(room_ptr->client);
357 unregister_dbus_object:
358 dbus_object_path_unregister(g_dbus_connection, room_ptr->dbus_object);
359 destroy_dbus_object:
360 dbus_object_path_destroy(g_dbus_connection, room_ptr->dbus_object);
361 destroy_app_supervisor:
362 ladish_app_supervisor_destroy(room_ptr->app_supervisor);
363 destroy:
364 ladish_graph_destroy(room_ptr->graph);
365 free(room_ptr->name);
366 free(room_ptr);
367 release_index:
368 ladish_studio_release_room_index(index);
369 return false;
372 #define room_ptr ((struct ladish_room *)room_handle)
374 void ladish_room_destroy(ladish_room_handle room_handle)
376 /* project has either both name and dir no none of them */
377 ASSERT((room_ptr->project_dir == NULL && room_ptr->project_name == NULL) || (room_ptr->project_dir != NULL && room_ptr->project_name != NULL));
378 if (room_ptr->project_dir == NULL)
380 free(room_ptr->project_dir);
382 if (room_ptr->project_name == NULL)
384 free(room_ptr->project_name);
387 if (!room_ptr->template)
389 ASSERT(!room_ptr->started); /* attempt to destroy not stopped room */
391 /* ladish_graph_dump(graph); */
393 if (ladish_studio_is_started())
395 ladish_graph_clear(room_ptr->graph, remove_port_callback);
398 dbus_object_path_destroy(g_dbus_connection, room_ptr->dbus_object);
399 ladish_app_supervisor_destroy(room_ptr->app_supervisor);
401 ladish_graph_remove_client(room_ptr->owner, room_ptr->client);
402 ladish_client_destroy(room_ptr->client);
404 ladish_studio_room_disappeared((ladish_room_handle)room_ptr);
405 ladish_studio_release_room_index(room_ptr->index);
408 ladish_graph_destroy(room_ptr->graph);
409 free(room_ptr->name);
410 free(room_ptr);
413 struct list_head * ladish_room_get_list_node(ladish_room_handle room_handle)
415 return &room_ptr->siblings;
418 const char * ladish_room_get_name(ladish_room_handle room_handle)
420 return room_ptr->name;
423 const char * ladish_room_get_opath(ladish_room_handle room_handle)
425 return ladish_graph_get_opath(room_ptr->graph);
428 bool ladish_room_get_template_uuid(ladish_room_handle room_handle, uuid_t uuid_ptr)
430 if (uuid_is_null(room_ptr->template_uuid))
432 return false;
435 uuid_copy(uuid_ptr, room_ptr->template_uuid);
436 return true;
439 void ladish_room_get_uuid(ladish_room_handle room_handle, uuid_t uuid_ptr)
441 uuid_copy(uuid_ptr, room_ptr->uuid);
444 ladish_graph_handle ladish_room_get_graph(ladish_room_handle room_handle)
446 return room_ptr->graph;
449 ladish_app_supervisor_handle ladish_room_get_app_supervisor(ladish_room_handle room_handle)
451 return room_ptr->app_supervisor;
454 struct ladish_room_iterate_link_ports_context
456 void * context;
457 bool
458 (* callback)(
459 void * context,
460 ladish_port_handle port_handle,
461 const char * port_name,
462 uint32_t port_type,
463 uint32_t port_flags);
466 #define context_ptr ((struct ladish_room_iterate_link_ports_context *)context)
468 static
469 bool
470 ladish_room_iterate_link_ports_client_callback(
471 void * context,
472 ladish_graph_handle graph_handle,
473 ladish_client_handle client_handle,
474 const char * client_name,
475 void ** client_iteration_context_ptr_ptr)
477 uuid_t uuid;
479 ladish_client_get_uuid(client_handle, uuid);
481 if (uuid_compare(uuid, ladish_wkclient_capture) == 0 ||
482 uuid_compare(uuid, ladish_wkclient_playback) == 0)
484 *client_iteration_context_ptr_ptr = (void *)1;
486 else
488 *client_iteration_context_ptr_ptr = (void *)0;
491 return true;
494 static
495 bool
496 ladish_room_iterate_link_ports_port_callback(
497 void * context,
498 ladish_graph_handle graph_handle,
499 void * client_iteration_context_ptr,
500 ladish_client_handle client_handle,
501 const char * client_name,
502 ladish_port_handle port_handle,
503 const char * port_name,
504 uint32_t port_type,
505 uint32_t port_flags)
507 if (client_iteration_context_ptr == (void *)0)
509 /* port of non-link client */
510 return true;
513 return context_ptr->callback(context_ptr->context, port_handle, port_name, port_type, port_flags);
516 #undef context_ptr
518 bool
519 ladish_room_iterate_link_ports(
520 ladish_room_handle room_handle,
521 void * callback_context,
522 bool
523 (* callback)(
524 void * context,
525 ladish_port_handle port_handle,
526 const char * port_name,
527 uint32_t port_type,
528 uint32_t port_flags))
530 struct ladish_room_iterate_link_ports_context context;
532 context.context = callback_context;
533 context.callback = callback;
535 return ladish_graph_iterate_nodes(
536 room_ptr->graph,
537 false,
538 NULL,
539 &context,
540 ladish_room_iterate_link_ports_client_callback,
541 ladish_room_iterate_link_ports_port_callback,
542 NULL);
545 bool ladish_room_start(ladish_room_handle room_handle, ladish_virtualizer_handle virtualizer)
547 if (!ladish_room_iterate_link_ports(room_handle, room_ptr, create_port_link))
549 log_error("Creation of room port links failed.");
550 return false;
553 ladish_virtualizer_set_graph_connection_handlers(virtualizer, room_ptr->graph);
554 room_ptr->started = true;
556 return true;
559 void ladish_room_initiate_stop(ladish_room_handle room_handle, bool clear_persist)
561 if (!room_ptr->started)
563 return;
566 ladish_graph_set_connection_handlers(room_ptr->graph, NULL, NULL, NULL);
568 if (clear_persist)
570 ladish_graph_clear_persist(room_ptr->graph);
573 ladish_graph_iterate_nodes(room_ptr->graph, false, NULL, room_ptr, NULL, destroy_port_link, NULL);
574 ladish_app_supervisor_stop(room_ptr->app_supervisor);
577 bool ladish_room_stopped(ladish_room_handle room_handle)
579 unsigned int running_app_count;
581 if (!room_ptr->started)
583 return true;
586 running_app_count = ladish_app_supervisor_get_running_app_count(room_ptr->app_supervisor);
587 if (running_app_count != 0)
589 log_info("there are %u running app(s) in room \"%s\"", running_app_count, room_ptr->name);
590 return false;
593 if (!ladish_graph_looks_empty(room_ptr->graph))
595 log_info("the room \"%s\" graph is still not empty", room_ptr->name);
596 return false;
599 if (!ladish_graph_client_looks_empty(room_ptr->owner, room_ptr->client))
601 log_info("the room \"%s\" client in owner still does not look empty", room_ptr->name);
602 return false;
605 room_ptr->started = false;
606 return true;
609 static
610 bool
611 ladish_room_app_is_stopped(
612 void * context,
613 const char * name,
614 bool running,
615 const char * command,
616 bool terminal,
617 uint8_t level,
618 pid_t pid,
619 const uuid_t uuid)
621 if (pid != 0)
623 log_info("App '%s' is still running pid=%u", name, (unsigned int)pid);
624 return false;
627 if (!ladish_virtualizer_is_hidden_app(ladish_studio_get_jack_graph(), uuid, name))
629 log_info("App '%s' is still visible in the jack graph", name);
630 return false;
633 return true;
636 bool ladish_room_unload_project(ladish_room_handle room_handle)
638 if (!room_ptr->project_unloading)
640 if (!ladish_app_supervisor_has_apps(room_ptr->app_supervisor))
642 goto done;
645 log_info("Stopping room apps...");
646 ladish_graph_dump(room_ptr->graph);
647 room_ptr->project_unloading = true;
648 ladish_graph_clear_persist(room_ptr->graph);
649 ladish_app_supervisor_stop(room_ptr->app_supervisor);
650 return false;
653 if (!ladish_app_supervisor_enum(room_ptr->app_supervisor, room_ptr, ladish_room_app_is_stopped))
655 return false;
658 ladish_app_supervisor_clear(room_ptr->app_supervisor);
659 ASSERT(!ladish_app_supervisor_has_apps(room_ptr->app_supervisor));
661 ladish_graph_set_persist(room_ptr->graph);
663 log_info("Room apps stopped.");
664 ladish_graph_dump(room_ptr->graph);
665 room_ptr->project_unloading = false;
667 done:
668 if (room_ptr->project_name != NULL)
670 free(room_ptr->project_name);
671 room_ptr->project_name = NULL;
673 if (room_ptr->project_dir != NULL)
675 free(room_ptr->project_dir);
676 room_ptr->project_dir = NULL;
679 ladish_room_emit_project_properties_changed(room_ptr);
681 return true;
684 ladish_port_handle
685 ladish_room_add_port(
686 ladish_room_handle room_handle,
687 const uuid_t uuid_ptr,
688 const char * name,
689 uint32_t type,
690 uint32_t flags)
692 ladish_port_handle port;
693 bool playback;
694 ladish_client_handle client;
695 const char * client_name;
696 uuid_t client_uuid;
697 bool new_client;
699 playback = port_is_input(flags);
701 ASSERT(!uuid_is_null(uuid_ptr));
702 if (!ladish_port_create(uuid_ptr, true, &port))
704 log_error("Creation of room port \"%s\" failed.", name);
705 goto fail;
708 client_name = playback ? "Playback" : "Capture";
709 uuid_copy(client_uuid, playback ? ladish_wkclient_playback : ladish_wkclient_capture);
711 /* if client is not found, create it and add it to graph */
712 client = ladish_graph_find_client_by_uuid(room_ptr->graph, client_uuid);
713 new_client = client == NULL;
714 if (new_client)
716 if (!ladish_client_create(client_uuid, &client))
718 log_error("ladish_client_create() failed to create %s room client.", playback ? "playback" : "capture");
719 goto fail_destroy_port;
722 if (!ladish_graph_add_client(room_ptr->graph, client, client_name, true))
724 log_error("ladish_graph_add_client() failed to add %s room client to room graph.", playback ? "playback" : "capture");
725 goto fail_destroy_client;
729 if (!ladish_graph_add_port(room_ptr->graph, client, port, name, type, flags, true))
731 log_error("ladish_graph_add_port() failed to add %s room port \"%s\" to room graph.", playback ? "playback" : "capture", name);
732 goto fail_destroy_client;
735 if (!create_shadow_port(room_ptr, port, name, type, flags))
737 log_error("ladish_graph_add_port() failed to add port \"%s\" to room owner graph.", name);
738 goto fail_remove_port;
741 return port;
743 fail_remove_port:
744 ASSERT(client != NULL);
745 if (ladish_graph_remove_port(room_ptr->graph, port) != client)
747 ASSERT_NO_PASS;
749 fail_destroy_client:
750 if (new_client)
752 ladish_client_destroy(client);
754 fail_destroy_port:
755 ladish_port_destroy(port);
756 fail:
757 return NULL;
760 #undef room_ptr
762 ladish_room_handle ladish_room_from_list_node(struct list_head * node_ptr)
764 return (ladish_room_handle)list_entry(node_ptr, struct ladish_room, siblings);
767 static bool ladish_room_fill_project_properties(DBusMessageIter * iter_ptr, struct ladish_room * room_ptr)
769 DBusMessageIter dict_iter;
771 if (!dbus_message_iter_append_basic(iter_ptr, DBUS_TYPE_UINT64, &room_ptr->version))
773 log_error("dbus_message_iter_append_basic() failed.");
774 return false;
777 if (!dbus_message_iter_open_container(iter_ptr, DBUS_TYPE_ARRAY, "{sv}", &dict_iter))
779 log_error("dbus_message_iter_open_container() failed.");
780 return false;
783 if (!dbus_maybe_add_dict_entry_string(&dict_iter, "name", room_ptr->project_name))
785 log_error("dbus_maybe_add_dict_entry_string() failed.");
786 return false;
789 if (!dbus_maybe_add_dict_entry_string(&dict_iter, "dir", room_ptr->project_dir))
791 log_error("dbus_maybe_add_dict_entry_string() failed.");
792 return false;
795 if (!dbus_message_iter_close_container(iter_ptr, &dict_iter))
797 log_error("dbus_message_iter_close_container() failed.");
798 return false;
801 return true;
804 void ladish_room_emit_project_properties_changed(struct ladish_room * room_ptr)
806 DBusMessage * message_ptr;
807 DBusMessageIter iter;
809 room_ptr->version++;
811 message_ptr = dbus_message_new_signal(room_ptr->object_path, IFACE_ROOM, "ProjectPropertiesChanged");
812 if (message_ptr == NULL)
814 log_error("dbus_message_new_signal() failed.");
815 return;
818 dbus_message_iter_init_append(message_ptr, &iter);
820 if (ladish_room_fill_project_properties(&iter, room_ptr))
822 dbus_signal_send(g_dbus_connection, message_ptr);
825 dbus_message_unref(message_ptr);
828 /**********************************************************************************/
829 /* D-Bus methods */
830 /**********************************************************************************/
832 #define room_ptr ((struct ladish_room *)call_ptr->iface_context)
834 static void ladish_room_dbus_get_name(struct dbus_method_call * call_ptr)
836 method_return_new_single(call_ptr, DBUS_TYPE_STRING, &room_ptr->name);
839 static void ladish_room_dbus_save_project(struct dbus_method_call * call_ptr)
841 const char * dir;
842 const char * name;
844 log_info("Save project request");
846 if (!dbus_message_get_args(call_ptr->message, &g_dbus_error, DBUS_TYPE_STRING, &dir, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID))
848 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, g_dbus_error.message);
849 dbus_error_free(&g_dbus_error);
850 return;
853 if (ladish_command_save_project(call_ptr, ladish_studio_get_cmd_queue(), room_ptr->uuid, dir, name))
855 method_return_new_void(call_ptr);
859 static void ladish_room_dbus_unload_project(struct dbus_method_call * call_ptr)
861 log_info("Unload project request");
863 if (ladish_command_unload_project(call_ptr, ladish_studio_get_cmd_queue(), room_ptr->uuid))
865 method_return_new_void(call_ptr);
869 static void ladish_room_dbus_load_project(struct dbus_method_call * call_ptr)
871 const char * dir;
873 log_info("Load project request");
875 if (!dbus_message_get_args(call_ptr->message, &g_dbus_error, DBUS_TYPE_STRING, &dir, DBUS_TYPE_INVALID))
877 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, g_dbus_error.message);
878 dbus_error_free(&g_dbus_error);
879 return;
882 if (ladish_command_load_project(call_ptr, ladish_studio_get_cmd_queue(), room_ptr->uuid, dir))
884 method_return_new_void(call_ptr);
888 static void ladish_room_dbus_get_project_properties(struct dbus_method_call * call_ptr)
890 DBusMessageIter iter;
892 call_ptr->reply = dbus_message_new_method_return(call_ptr->message);
893 if (call_ptr->reply == NULL)
895 goto fail;
898 dbus_message_iter_init_append(call_ptr->reply, &iter);
900 if (!ladish_room_fill_project_properties(&iter, room_ptr))
902 goto fail_unref;
905 return;
907 fail_unref:
908 dbus_message_unref(call_ptr->reply);
909 call_ptr->reply = NULL;
911 fail:
912 log_error("Ran out of memory trying to construct method return");
915 #undef room_ptr
917 METHOD_ARGS_BEGIN(GetName, "Get room name")
918 METHOD_ARG_DESCRIBE_OUT("room_name", "s", "Name of room")
919 METHOD_ARGS_END
921 METHOD_ARGS_BEGIN(SaveProject, "Save the current project")
922 METHOD_ARG_DESCRIBE_IN("project_dir", "s", "Project directory. Can be an empty string if project has a path associated already")
923 METHOD_ARG_DESCRIBE_IN("project_name", "s", "Name of the project. Can be an empty string if project has a name associated already")
924 METHOD_ARGS_END
926 METHOD_ARGS_BEGIN(UnloadProject, "Unload project, if any")
927 METHOD_ARGS_END
929 METHOD_ARGS_BEGIN(LoadProject, "Load project")
930 METHOD_ARG_DESCRIBE_IN("project_dir", "s", "Project directory")
931 METHOD_ARGS_END
933 METHOD_ARGS_BEGIN(GetProjectProperties, "Get project properties")
934 METHOD_ARG_DESCRIBE_OUT("new_version", DBUS_TYPE_UINT64_AS_STRING, "New version of the project properties")
935 METHOD_ARG_DESCRIBE_OUT("properties", "a{sv}", "project properties")
936 METHOD_ARGS_END
938 METHODS_BEGIN
939 METHOD_DESCRIBE(GetName, ladish_room_dbus_get_name) /* sync */
940 METHOD_DESCRIBE(SaveProject, ladish_room_dbus_save_project) /* async */
941 METHOD_DESCRIBE(UnloadProject, ladish_room_dbus_unload_project) /* async */
942 METHOD_DESCRIBE(LoadProject, ladish_room_dbus_load_project) /* async */
943 METHOD_DESCRIBE(GetProjectProperties, ladish_room_dbus_get_project_properties) /* sync */
944 METHODS_END
946 SIGNAL_ARGS_BEGIN(ProjectPropertiesChanged, "Project properties changed")
947 SIGNAL_ARG_DESCRIBE("new_version", DBUS_TYPE_UINT64_AS_STRING, "New version of the project properties")
948 SIGNAL_ARG_DESCRIBE("properties", "a{sv}", "project properties")
949 SIGNAL_ARGS_END
951 SIGNALS_BEGIN
952 SIGNAL_DESCRIBE(ProjectPropertiesChanged)
953 SIGNALS_END
955 INTERFACE_BEGIN(g_interface_room, IFACE_ROOM)
956 INTERFACE_DEFAULT_HANDLER
957 INTERFACE_EXPOSE_METHODS
958 INTERFACE_EXPOSE_SIGNALS
959 INTERFACE_END