waf: fix the include path workaround
[ladish.git] / daemon / room.c
blob526b93f4cd49dd9eb399d3e94673ec4a02928627
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"
35 #include "recent_projects.h"
37 extern const struct dbus_interface_descriptor g_interface_room;
39 static bool port_is_input(uint32_t flags)
41 bool playback;
43 playback = JACKDBUS_PORT_IS_INPUT(flags);
44 ASSERT(playback || JACKDBUS_PORT_IS_OUTPUT(flags)); /* playback or capture */
45 ASSERT(!(playback && JACKDBUS_PORT_IS_OUTPUT(flags))); /* but not both */
47 return playback;
50 struct ladish_room * ladish_room_create_internal(const uuid_t uuid_ptr, const char * name, const char * object_path)
52 struct ladish_room * room_ptr;
54 room_ptr = malloc(sizeof(struct ladish_room));
55 if (room_ptr == NULL)
57 log_error("malloc() failed to allocate struct ladish_room");
58 goto fail;
61 if (uuid_ptr != NULL)
63 uuid_copy(room_ptr->uuid, uuid_ptr);
65 else
67 uuid_generate(room_ptr->uuid);
70 room_ptr->name = strdup(name);
71 if (room_ptr->name == NULL)
73 log_error("strdup() failed for room name");
74 goto free_room;
77 if (object_path != NULL)
79 room_ptr->object_path = strdup(object_path);
80 if (room_ptr->object_path == NULL)
82 log_error("strdup() failed for room name");
83 goto free_name;
87 if (!ladish_graph_create(&room_ptr->graph, object_path))
89 goto free_opath;
92 return room_ptr;
94 free_opath:
95 if (object_path != NULL)
97 free(room_ptr->object_path);
99 free_name:
100 free(room_ptr->name);
101 free_room:
102 free(room_ptr);
103 fail:
104 return NULL;
107 bool
108 ladish_room_create_template(
109 const uuid_t uuid_ptr,
110 const char * name,
111 ladish_room_handle * room_handle_ptr)
113 struct ladish_room * room_ptr;
115 room_ptr = ladish_room_create_internal(uuid_ptr, name, NULL);
116 if (room_ptr == NULL)
118 return false;
121 room_ptr->template = true;
123 *room_handle_ptr = (ladish_room_handle)room_ptr;
124 return true;
127 #define room_ptr ((struct ladish_room *)context)
129 static
130 bool
131 create_shadow_port(
132 void * context,
133 ladish_port_handle port_handle,
134 const char * port_name,
135 uint32_t port_type,
136 uint32_t port_flags)
138 //log_info("Studio room port \"%s\"", port_name);
140 if (port_is_input(port_flags))
142 JACKDBUS_PORT_CLEAR_INPUT(port_flags);
143 JACKDBUS_PORT_SET_OUTPUT(port_flags);
145 else
147 JACKDBUS_PORT_CLEAR_OUTPUT(port_flags);
148 JACKDBUS_PORT_SET_INPUT(port_flags);
151 if (!ladish_graph_add_port(room_ptr->owner, room_ptr->client, port_handle, port_name, port_type, port_flags, true))
153 log_error("ladish_graph_add_port() failed to add link port to room owner graph");
154 return false;
157 return true;
160 static
161 bool
162 create_port_link(
163 void * context,
164 ladish_port_handle port_handle,
165 const char * port_name,
166 uint32_t port_type,
167 uint32_t port_flags)
169 uuid_t uuid_in_owner;
170 uuid_t uuid_in_room;
171 char uuid_in_owner_str[37];
172 char uuid_in_room_str[37];
173 const char * input_port;
174 const char * output_port;
176 //log_info("Room port \"%s\"", port_name);
178 ladish_graph_get_port_uuid(room_ptr->graph, port_handle, uuid_in_room);
179 ladish_graph_get_port_uuid(room_ptr->owner, port_handle, uuid_in_owner);
181 uuid_unparse(uuid_in_room, uuid_in_room_str);
182 uuid_unparse(uuid_in_owner, uuid_in_owner_str);
184 if (port_is_input(port_flags))
186 input_port = uuid_in_room_str;
187 output_port = uuid_in_owner_str;
188 log_info("room input port %s is linked to owner graph output port %s", input_port, output_port);
190 else
192 input_port = uuid_in_owner_str;
193 output_port = uuid_in_room_str;
194 log_info("owner graph input port %s is linked to room output port %s", input_port, output_port);
197 if (!jmcore_proxy_create_link(port_type == JACKDBUS_PORT_TYPE_MIDI, input_port, output_port))
199 log_error("jmcore_proxy_create_link() failed.");
200 return false;
203 return true;
206 static
207 bool
208 destroy_port_link(
209 void * context,
210 ladish_graph_handle graph_handle,
211 void * client_iteration_context_ptr,
212 ladish_client_handle client_handle,
213 const char * client_name,
214 ladish_port_handle port_handle,
215 const char * port_name,
216 uint32_t port_type,
217 uint32_t port_flags)
219 uuid_t uuid_in_room;
220 char uuid_in_room_str[37];
222 if (ladish_port_is_link(port_handle))
224 log_info("link port %s", port_name);
226 ladish_graph_get_port_uuid(ladish_room_get_graph(context), port_handle, uuid_in_room);
227 uuid_unparse(uuid_in_room, uuid_in_room_str);
228 jmcore_proxy_destroy_link(uuid_in_room_str);
230 else
232 log_info("jack port %s", port_name);
235 return true;
238 #undef room_ptr
240 static void remove_port_callback(ladish_port_handle port)
242 ladish_graph_handle jack_graph;
243 ladish_client_handle jack_client;
245 jack_graph = ladish_studio_get_jack_graph();
247 jack_client = ladish_graph_remove_port(jack_graph, port);
248 if (jack_client == NULL)
249 { /* room app port not found in jack graph */
250 /* this can happen if the port is hidden in the vgraph */
251 return;
254 if (ladish_graph_client_is_empty(jack_graph, jack_client))
256 ladish_graph_remove_client(jack_graph, jack_client);
260 bool
261 ladish_room_create(
262 const uuid_t uuid_ptr,
263 const char * name,
264 ladish_room_handle template,
265 ladish_graph_handle owner,
266 ladish_room_handle * room_handle_ptr)
268 struct ladish_room * room_ptr;
269 char object_path[1024];
270 unsigned int index;
272 index = ladish_studio_get_room_index();
273 sprintf(object_path, DBUS_BASE_PATH "/Room%u", index);
275 room_ptr = ladish_room_create_internal(uuid_ptr, name, object_path);
276 if (room_ptr == NULL)
278 goto release_index;
281 room_ptr->template = false;
282 room_ptr->index = index;
283 room_ptr->owner = owner;
284 room_ptr->started = false;
285 room_ptr->version = 1;
287 room_ptr->project_name = NULL;
288 room_ptr->project_dir = NULL;
289 room_ptr->project_state = ROOM_PROJECT_STATE_UNLOADED;
291 if (template != NULL)
293 ladish_room_get_uuid(template, room_ptr->template_uuid);
294 if (!ladish_graph_copy(ladish_room_get_graph(template), room_ptr->graph, false))
296 goto destroy;
299 else
301 uuid_clear(room_ptr->template_uuid);
304 if (!ladish_app_supervisor_create(&room_ptr->app_supervisor, object_path, room_ptr->name, room_ptr->graph, ladish_virtualizer_rename_app))
306 log_error("ladish_app_supervisor_create() failed.");
307 goto destroy;
310 room_ptr->dbus_object = dbus_object_path_new(
311 object_path,
312 &g_interface_room, room_ptr,
313 &g_interface_patchbay, ladish_graph_get_dbus_context(room_ptr->graph),
314 &g_iface_graph_dict, room_ptr->graph,
315 &g_iface_app_supervisor, room_ptr->app_supervisor,
316 &g_iface_recent_items, NULL,
317 NULL);
318 if (room_ptr->dbus_object == NULL)
320 log_error("dbus_object_path_new() failed");
321 goto destroy_app_supervisor;
324 if (!dbus_object_path_register(g_dbus_connection, room_ptr->dbus_object))
326 log_error("object_path_register() failed");
327 goto destroy_dbus_object;
330 log_info("D-Bus object \"%s\" created for room \"%s\".", object_path, room_ptr->name);
332 if (!ladish_client_create(room_ptr->uuid, &room_ptr->client))
334 log_error("ladish_client_create() failed.");
335 goto unregister_dbus_object;
338 if (!ladish_graph_add_client(owner, room_ptr->client, room_ptr->name, true))
340 log_error("ladish_graph_add_client() failed to add room client to owner graph.");
341 goto destroy_client;
344 if (!ladish_room_iterate_link_ports((ladish_room_handle)room_ptr, room_ptr, create_shadow_port))
346 log_error("Creation of studio room link ports failed.");
347 goto remove_client;
350 ladish_studio_room_appeared((ladish_room_handle)room_ptr);
352 *room_handle_ptr = (ladish_room_handle)room_ptr;
353 return true;
355 remove_client:
356 ladish_graph_remove_client(owner, room_ptr->client);
357 destroy_client:
358 ladish_client_destroy(room_ptr->client);
359 unregister_dbus_object:
360 dbus_object_path_unregister(g_dbus_connection, room_ptr->dbus_object);
361 destroy_dbus_object:
362 dbus_object_path_destroy(g_dbus_connection, room_ptr->dbus_object);
363 destroy_app_supervisor:
364 ladish_app_supervisor_destroy(room_ptr->app_supervisor);
365 destroy:
366 ladish_graph_destroy(room_ptr->graph);
367 free(room_ptr->name);
368 free(room_ptr);
369 release_index:
370 ladish_studio_release_room_index(index);
371 return false;
374 #define room_ptr ((struct ladish_room *)room_handle)
376 void ladish_room_destroy(ladish_room_handle room_handle)
378 /* project has either both name and dir no none of them */
379 ASSERT((room_ptr->project_dir == NULL && room_ptr->project_name == NULL) || (room_ptr->project_dir != NULL && room_ptr->project_name != NULL));
380 if (room_ptr->project_dir == NULL)
382 free(room_ptr->project_dir);
384 if (room_ptr->project_name == NULL)
386 free(room_ptr->project_name);
389 if (!room_ptr->template)
391 ASSERT(!room_ptr->started); /* attempt to destroy not stopped room */
393 /* ladish_graph_dump(graph); */
395 if (ladish_studio_is_started())
397 ladish_graph_clear(room_ptr->graph, remove_port_callback);
400 dbus_object_path_destroy(g_dbus_connection, room_ptr->dbus_object);
401 ladish_app_supervisor_destroy(room_ptr->app_supervisor);
403 ladish_graph_remove_client(room_ptr->owner, room_ptr->client);
404 ladish_client_destroy(room_ptr->client);
406 ladish_studio_room_disappeared((ladish_room_handle)room_ptr);
407 ladish_studio_release_room_index(room_ptr->index);
410 ladish_graph_destroy(room_ptr->graph);
411 free(room_ptr->name);
412 free(room_ptr);
415 struct list_head * ladish_room_get_list_node(ladish_room_handle room_handle)
417 return &room_ptr->siblings;
420 const char * ladish_room_get_name(ladish_room_handle room_handle)
422 return room_ptr->name;
425 const char * ladish_room_get_opath(ladish_room_handle room_handle)
427 return ladish_graph_get_opath(room_ptr->graph);
430 bool ladish_room_get_template_uuid(ladish_room_handle room_handle, uuid_t uuid_ptr)
432 if (uuid_is_null(room_ptr->template_uuid))
434 return false;
437 uuid_copy(uuid_ptr, room_ptr->template_uuid);
438 return true;
441 void ladish_room_get_uuid(ladish_room_handle room_handle, uuid_t uuid_ptr)
443 uuid_copy(uuid_ptr, room_ptr->uuid);
446 ladish_graph_handle ladish_room_get_graph(ladish_room_handle room_handle)
448 return room_ptr->graph;
451 ladish_app_supervisor_handle ladish_room_get_app_supervisor(ladish_room_handle room_handle)
453 return room_ptr->app_supervisor;
456 struct ladish_room_iterate_link_ports_context
458 void * context;
459 bool
460 (* callback)(
461 void * context,
462 ladish_port_handle port_handle,
463 const char * port_name,
464 uint32_t port_type,
465 uint32_t port_flags);
468 #define context_ptr ((struct ladish_room_iterate_link_ports_context *)context)
470 static
471 bool
472 ladish_room_iterate_link_ports_client_callback(
473 void * context,
474 ladish_graph_handle graph_handle,
475 ladish_client_handle client_handle,
476 const char * client_name,
477 void ** client_iteration_context_ptr_ptr)
479 uuid_t uuid;
481 ladish_client_get_uuid(client_handle, uuid);
483 if (uuid_compare(uuid, ladish_wkclient_capture) == 0 ||
484 uuid_compare(uuid, ladish_wkclient_playback) == 0)
486 *client_iteration_context_ptr_ptr = (void *)1;
488 else
490 *client_iteration_context_ptr_ptr = (void *)0;
493 return true;
496 static
497 bool
498 ladish_room_iterate_link_ports_port_callback(
499 void * context,
500 ladish_graph_handle graph_handle,
501 void * client_iteration_context_ptr,
502 ladish_client_handle client_handle,
503 const char * client_name,
504 ladish_port_handle port_handle,
505 const char * port_name,
506 uint32_t port_type,
507 uint32_t port_flags)
509 if (client_iteration_context_ptr == (void *)0)
511 /* port of non-link client */
512 return true;
515 return context_ptr->callback(context_ptr->context, port_handle, port_name, port_type, port_flags);
518 #undef context_ptr
520 bool
521 ladish_room_iterate_link_ports(
522 ladish_room_handle room_handle,
523 void * callback_context,
524 bool
525 (* callback)(
526 void * context,
527 ladish_port_handle port_handle,
528 const char * port_name,
529 uint32_t port_type,
530 uint32_t port_flags))
532 struct ladish_room_iterate_link_ports_context context;
534 context.context = callback_context;
535 context.callback = callback;
537 return ladish_graph_iterate_nodes(
538 room_ptr->graph,
539 false,
540 &context,
541 ladish_room_iterate_link_ports_client_callback,
542 ladish_room_iterate_link_ports_port_callback,
543 NULL);
546 bool ladish_room_start(ladish_room_handle room_handle, ladish_virtualizer_handle virtualizer)
548 if (!ladish_room_iterate_link_ports(room_handle, room_ptr, create_port_link))
550 log_error("Creation of room port links failed.");
551 return false;
554 ladish_virtualizer_set_graph_connection_handlers(virtualizer, room_ptr->graph);
555 room_ptr->started = true;
557 ladish_app_supervisor_autorun(room_ptr->app_supervisor);
559 return true;
562 void ladish_room_initiate_stop(ladish_room_handle room_handle, bool clear_persist)
564 if (!room_ptr->started)
566 return;
569 ladish_graph_set_connection_handlers(room_ptr->graph, NULL, NULL, NULL);
571 if (clear_persist)
573 ladish_graph_clear_persist(room_ptr->graph);
576 ladish_graph_iterate_nodes(room_ptr->graph, false, room_ptr, NULL, destroy_port_link, NULL);
577 ladish_app_supervisor_stop(room_ptr->app_supervisor);
580 bool ladish_room_stopped(ladish_room_handle room_handle)
582 unsigned int running_app_count;
584 if (!room_ptr->started)
586 return true;
589 running_app_count = ladish_app_supervisor_get_running_app_count(room_ptr->app_supervisor);
590 if (running_app_count != 0)
592 log_info("there are %u running app(s) in room \"%s\"", running_app_count, room_ptr->name);
593 return false;
596 if (!ladish_graph_looks_empty(room_ptr->graph))
598 log_info("the room \"%s\" graph is still not empty", room_ptr->name);
599 return false;
602 if (!ladish_graph_client_looks_empty(room_ptr->owner, room_ptr->client))
604 log_info("the room \"%s\" client in owner still does not look empty", room_ptr->name);
605 return false;
608 room_ptr->started = false;
609 return true;
612 static
613 bool
614 ladish_room_app_is_stopped(
615 void * context,
616 const char * name,
617 bool running,
618 const char * command,
619 bool terminal,
620 uint8_t level,
621 pid_t pid,
622 const uuid_t uuid)
624 if (pid != 0)
626 log_info("App '%s' is still running pid=%u", name, (unsigned int)pid);
627 return false;
630 if (!ladish_virtualizer_is_hidden_app(ladish_studio_get_jack_graph(), uuid, name))
632 log_info("App '%s' is still visible in the jack graph", name);
633 return false;
636 return true;
639 static
640 bool
641 ladish_remove_room_app(
642 void * context,
643 const char * name,
644 bool running,
645 const char * command,
646 bool terminal,
647 uint8_t level,
648 pid_t pid,
649 const uuid_t uuid)
651 ladish_virtualizer_remove_app(ladish_studio_get_jack_graph(), uuid, name);
652 return true;
655 bool ladish_room_unload_project(ladish_room_handle room_handle)
657 unsigned int old_project_state;
659 switch (room_ptr->project_state)
661 case ROOM_PROJECT_STATE_UNLOADED:
662 case ROOM_PROJECT_STATE_LOADED:
663 if (!ladish_app_supervisor_has_apps(room_ptr->app_supervisor) &&
664 !ladish_graph_has_visible_connections(room_ptr->graph))
666 break;
669 log_info("Disconnecting ports within room...");
670 ladish_disconnect_visible_connections(room_ptr->graph);
672 room_ptr->project_state = ROOM_PROJECT_STATE_UNLOADING_CONNECTIONS;
673 return false;
675 case ROOM_PROJECT_STATE_UNLOADING_CONNECTIONS:
676 if (ladish_graph_has_visible_connections(room_ptr->graph))
678 return false;
681 log_info("Ports within room disconnected");
683 if (!ladish_app_supervisor_has_apps(room_ptr->app_supervisor))
685 break;
688 log_info("Stopping room apps...");
689 ladish_graph_dump(room_ptr->graph);
690 //ladish_graph_clear_persist(room_ptr->graph);
691 ladish_app_supervisor_stop(room_ptr->app_supervisor);
693 room_ptr->project_state = ROOM_PROJECT_STATE_UNLOADING_APPS;
694 return false;
696 case ROOM_PROJECT_STATE_UNLOADING_APPS:
697 if (!ladish_app_supervisor_enum(room_ptr->app_supervisor, room_ptr, ladish_room_app_is_stopped))
699 return false;
702 /* remove app clients, ports and connections */
703 ladish_app_supervisor_enum(room_ptr->app_supervisor, room_ptr, ladish_remove_room_app);
705 ladish_app_supervisor_clear(room_ptr->app_supervisor);
706 ASSERT(!ladish_app_supervisor_has_apps(room_ptr->app_supervisor));
708 //ladish_graph_set_persist(room_ptr->graph);
710 log_info("Room apps stopped.");
711 break;
713 default:
714 ASSERT_NO_PASS;
715 log_error("unknown project state");
716 return false;
719 old_project_state = room_ptr->project_state;
721 ladish_room_clear_project(room_ptr);
723 if (old_project_state != room_ptr->project_state)
725 ladish_room_emit_project_properties_changed(room_ptr);
728 return true;
731 ladish_port_handle
732 ladish_room_add_port(
733 ladish_room_handle room_handle,
734 const uuid_t uuid_ptr,
735 const char * name,
736 uint32_t type,
737 uint32_t flags)
739 ladish_port_handle port;
740 bool playback;
741 ladish_client_handle client;
742 const char * client_name;
743 uuid_t client_uuid;
744 bool new_client;
746 playback = port_is_input(flags);
748 ASSERT(!uuid_is_null(uuid_ptr));
749 if (!ladish_port_create(uuid_ptr, true, &port))
751 log_error("Creation of room port \"%s\" failed.", name);
752 goto fail;
755 client_name = playback ? "Playback" : "Capture";
756 uuid_copy(client_uuid, playback ? ladish_wkclient_playback : ladish_wkclient_capture);
758 /* if client is not found, create it and add it to graph */
759 client = ladish_graph_find_client_by_uuid(room_ptr->graph, client_uuid);
760 new_client = client == NULL;
761 if (new_client)
763 if (!ladish_client_create(client_uuid, &client))
765 log_error("ladish_client_create() failed to create %s room client.", playback ? "playback" : "capture");
766 goto fail_destroy_port;
769 if (!ladish_graph_add_client(room_ptr->graph, client, client_name, true))
771 log_error("ladish_graph_add_client() failed to add %s room client to room graph.", playback ? "playback" : "capture");
772 goto fail_destroy_client;
776 if (!ladish_graph_add_port(room_ptr->graph, client, port, name, type, flags, true))
778 log_error("ladish_graph_add_port() failed to add %s room port \"%s\" to room graph.", playback ? "playback" : "capture", name);
779 goto fail_destroy_client;
782 if (!create_shadow_port(room_ptr, port, name, type, flags))
784 log_error("ladish_graph_add_port() failed to add port \"%s\" to room owner graph.", name);
785 goto fail_remove_port;
788 return port;
790 fail_remove_port:
791 ASSERT(client != NULL);
792 if (ladish_graph_remove_port(room_ptr->graph, port) != client)
794 ASSERT_NO_PASS;
796 fail_destroy_client:
797 if (new_client)
799 ladish_client_destroy(client);
801 fail_destroy_port:
802 ladish_port_destroy(port);
803 fail:
804 return NULL;
807 #undef room_ptr
809 ladish_room_handle ladish_room_from_list_node(struct list_head * node_ptr)
811 return (ladish_room_handle)list_entry(node_ptr, struct ladish_room, siblings);
814 static bool ladish_room_fill_project_properties(DBusMessageIter * iter_ptr, struct ladish_room * room_ptr)
816 DBusMessageIter dict_iter;
818 if (!dbus_message_iter_append_basic(iter_ptr, DBUS_TYPE_UINT64, &room_ptr->version))
820 log_error("dbus_message_iter_append_basic() failed.");
821 return false;
824 if (!dbus_message_iter_open_container(iter_ptr, DBUS_TYPE_ARRAY, "{sv}", &dict_iter))
826 log_error("dbus_message_iter_open_container() failed.");
827 return false;
830 if (!dbus_maybe_add_dict_entry_string(&dict_iter, "name", room_ptr->project_name))
832 log_error("dbus_maybe_add_dict_entry_string() failed.");
833 return false;
836 if (!dbus_maybe_add_dict_entry_string(&dict_iter, "dir", room_ptr->project_dir))
838 log_error("dbus_maybe_add_dict_entry_string() failed.");
839 return false;
842 if (!dbus_message_iter_close_container(iter_ptr, &dict_iter))
844 log_error("dbus_message_iter_close_container() failed.");
845 return false;
848 return true;
851 void ladish_room_emit_project_properties_changed(struct ladish_room * room_ptr)
853 DBusMessage * message_ptr;
854 DBusMessageIter iter;
856 room_ptr->version++;
858 message_ptr = dbus_message_new_signal(room_ptr->object_path, IFACE_ROOM, "ProjectPropertiesChanged");
859 if (message_ptr == NULL)
861 log_error("dbus_message_new_signal() failed.");
862 return;
865 dbus_message_iter_init_append(message_ptr, &iter);
867 if (ladish_room_fill_project_properties(&iter, room_ptr))
869 dbus_signal_send(g_dbus_connection, message_ptr);
872 dbus_message_unref(message_ptr);
875 void ladish_room_clear_project(struct ladish_room * room_ptr)
877 if (!ladish_app_supervisor_clear(room_ptr->app_supervisor))
879 ASSERT_NO_PASS;
882 ASSERT(!ladish_app_supervisor_has_apps(room_ptr->app_supervisor));
884 ladish_graph_remove_hidden_objects(room_ptr->graph);
886 if (room_ptr->project_name != NULL)
888 free(room_ptr->project_name);
889 room_ptr->project_name = NULL;
891 if (room_ptr->project_dir != NULL)
893 free(room_ptr->project_dir);
894 room_ptr->project_dir = NULL;
897 room_ptr->project_state = ROOM_PROJECT_STATE_UNLOADED;
898 ladish_graph_dump(room_ptr->graph);
901 /**********************************************************************************/
902 /* D-Bus methods */
903 /**********************************************************************************/
905 #define room_ptr ((struct ladish_room *)call_ptr->iface_context)
907 static void ladish_room_dbus_get_name(struct dbus_method_call * call_ptr)
909 method_return_new_single(call_ptr, DBUS_TYPE_STRING, &room_ptr->name);
912 static void ladish_room_dbus_save_project(struct dbus_method_call * call_ptr)
914 const char * dir;
915 const char * name;
917 log_info("Save project request");
919 if (!dbus_message_get_args(call_ptr->message, &g_dbus_error, DBUS_TYPE_STRING, &dir, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID))
921 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, g_dbus_error.message);
922 dbus_error_free(&g_dbus_error);
923 return;
926 if (ladish_command_save_project(call_ptr, ladish_studio_get_cmd_queue(), room_ptr->uuid, dir, name))
928 method_return_new_void(call_ptr);
932 static void ladish_room_dbus_unload_project(struct dbus_method_call * call_ptr)
934 log_info("Unload project request");
936 if (ladish_command_unload_project(call_ptr, ladish_studio_get_cmd_queue(), room_ptr->uuid))
938 method_return_new_void(call_ptr);
942 static void ladish_room_dbus_load_project(struct dbus_method_call * call_ptr)
944 const char * dir;
946 log_info("Load project request");
948 if (!dbus_message_get_args(call_ptr->message, &g_dbus_error, DBUS_TYPE_STRING, &dir, DBUS_TYPE_INVALID))
950 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, g_dbus_error.message);
951 dbus_error_free(&g_dbus_error);
952 return;
955 if (ladish_command_load_project(call_ptr, ladish_studio_get_cmd_queue(), room_ptr->uuid, dir))
957 method_return_new_void(call_ptr);
961 static void ladish_room_dbus_get_project_properties(struct dbus_method_call * call_ptr)
963 DBusMessageIter iter;
965 call_ptr->reply = dbus_message_new_method_return(call_ptr->message);
966 if (call_ptr->reply == NULL)
968 goto fail;
971 dbus_message_iter_init_append(call_ptr->reply, &iter);
973 if (!ladish_room_fill_project_properties(&iter, room_ptr))
975 goto fail_unref;
978 return;
980 fail_unref:
981 dbus_message_unref(call_ptr->reply);
982 call_ptr->reply = NULL;
984 fail:
985 log_error("Ran out of memory trying to construct method return");
988 #undef room_ptr
990 METHOD_ARGS_BEGIN(GetName, "Get room name")
991 METHOD_ARG_DESCRIBE_OUT("room_name", "s", "Name of room")
992 METHOD_ARGS_END
994 METHOD_ARGS_BEGIN(SaveProject, "Save the current project")
995 METHOD_ARG_DESCRIBE_IN("project_dir", "s", "Project directory. Can be an empty string if project has a path associated already")
996 METHOD_ARG_DESCRIBE_IN("project_name", "s", "Name of the project. Can be an empty string if project has a name associated already")
997 METHOD_ARGS_END
999 METHOD_ARGS_BEGIN(UnloadProject, "Unload project, if any")
1000 METHOD_ARGS_END
1002 METHOD_ARGS_BEGIN(LoadProject, "Load project")
1003 METHOD_ARG_DESCRIBE_IN("project_dir", "s", "Project directory")
1004 METHOD_ARGS_END
1006 METHOD_ARGS_BEGIN(GetProjectProperties, "Get project properties")
1007 METHOD_ARG_DESCRIBE_OUT("new_version", DBUS_TYPE_UINT64_AS_STRING, "New version of the project properties")
1008 METHOD_ARG_DESCRIBE_OUT("properties", "a{sv}", "project properties")
1009 METHOD_ARGS_END
1011 METHODS_BEGIN
1012 METHOD_DESCRIBE(GetName, ladish_room_dbus_get_name) /* sync */
1013 METHOD_DESCRIBE(SaveProject, ladish_room_dbus_save_project) /* async */
1014 METHOD_DESCRIBE(UnloadProject, ladish_room_dbus_unload_project) /* async */
1015 METHOD_DESCRIBE(LoadProject, ladish_room_dbus_load_project) /* async */
1016 METHOD_DESCRIBE(GetProjectProperties, ladish_room_dbus_get_project_properties) /* sync */
1017 METHODS_END
1019 SIGNAL_ARGS_BEGIN(ProjectPropertiesChanged, "Project properties changed")
1020 SIGNAL_ARG_DESCRIBE("new_version", DBUS_TYPE_UINT64_AS_STRING, "New version of the project properties")
1021 SIGNAL_ARG_DESCRIBE("properties", "a{sv}", "project properties")
1022 SIGNAL_ARGS_END
1024 SIGNALS_BEGIN
1025 SIGNAL_DESCRIBE(ProjectPropertiesChanged)
1026 SIGNALS_END
1028 INTERFACE_BEGIN(g_interface_room, IFACE_ROOM)
1029 INTERFACE_DEFAULT_HANDLER
1030 INTERFACE_EXPOSE_METHODS
1031 INTERFACE_EXPOSE_SIGNALS
1032 INTERFACE_END