1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
3 * LADI Session Handler (ladish)
5 * Copyright (C) 2009,2010,2011,2012 Nedko Arnaudov <nedko@arnaudov.name>
7 **************************************************************************
8 * This file contains implementation of the graph view object
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.
28 #include "graph_view.h"
29 #include "gtk_builder.h"
30 #include "world_tree.h"
32 #include "../proxies/room_proxy.h"
33 #include "../common/catdup.h"
37 struct list_head siblings
;
41 graph_canvas_handle graph_canvas
;
42 graph_proxy_handle graph
;
43 GtkWidget
* canvas_widget
;
44 ladish_app_supervisor_proxy_handle app_supervisor
;
45 ladish_room_proxy_handle room
;
48 struct list_head g_views
;
50 GtkScrolledWindow
* g_main_scrolledwin
;
51 static struct graph_view
* g_current_view
;
52 GtkWidget
* g_view_label
;
54 const char * g_view_label_text
= "";
58 g_view_label_text
= _(
59 "If you've started ladish for the first time, you should:\n\n"
60 " 1. Create a new studio (in the menu, Studio -> New Studio)\n"
61 " 2. Configure JACK (in the menu, Tools -> Configure JACK)\n"
62 " 3. Start the studio (in the menu, Studio -> Start Studio)\n"
63 " 4. Start apps (in the menu, Application -> Run)\n"
64 " 5. Connect their ports by click & drag on canvas\n"
65 " 6. Save the studio (in the menu, Studio -> Save Studio)\n");
67 g_main_scrolledwin
= GTK_SCROLLED_WINDOW(get_gtk_builder_widget("main_scrolledwin"));
68 INIT_LIST_HEAD(&g_views
);
70 g_view_label
= gtk_label_new(g_view_label_text
);
71 g_object_ref(g_view_label
);
72 gtk_widget_show(g_view_label
);
74 g_current_view
= NULL
;
75 gtk_scrolled_window_add_with_viewport(g_main_scrolledwin
, g_view_label
);
78 void announce_view_name_change(struct graph_view
* view_ptr
)
80 world_tree_name_changed((graph_view_handle
)view_ptr
);
82 if (g_current_view
== view_ptr
)
84 set_main_window_title((graph_view_handle
)view_ptr
);
90 static void detach_canvas(struct graph_view
* view_ptr
)
94 child
= gtk_bin_get_child(GTK_BIN(g_main_scrolledwin
));
95 if (child
== view_ptr
->canvas_widget
)
97 gtk_container_remove(GTK_CONTAINER(g_main_scrolledwin
), view_ptr
->canvas_widget
);
98 g_current_view
= NULL
;
99 gtk_widget_show(g_view_label
);
100 gtk_scrolled_window_add_with_viewport(g_main_scrolledwin
, g_view_label
);
104 #define view_ptr ((struct graph_view *)context)
106 static void app_added(void * context
, uint64_t id
, const char * name
, bool running
, bool terminal
, const char * level
)
108 //log_info("app added. id=%"PRIu64", name='%s', %srunning, %s, level '%s'", id, name, running ? "" : "not ", terminal ? "terminal" : "shell", level);
109 world_tree_add_app(context
, id
, name
, running
, terminal
, level
);
112 static void app_state_changed(void * context
, uint64_t id
, const char * name
, bool running
, bool terminal
, const char * level
)
114 //log_info("app state changed. id=%"PRIu64", name='%s', %srunning, %s, level '%s'", id, name, running ? "" : "not ", terminal ? "terminal" : "shell", level);
115 world_tree_app_state_changed(context
, id
, name
, running
, terminal
, level
);
118 static void app_removed(void * context
, uint64_t id
)
120 //log_info("app removed. id=%"PRIu64, id);
121 world_tree_remove_app(context
, id
);
126 project_properties_changed(
128 const char * project_dir
,
129 const char * project_name
,
130 const char * UNUSED(project_description
),
131 const char * UNUSED(project_notes
))
134 char * project_name_buffer
;
135 char * full_name_buffer
;
137 log_info("Room '%s' project properties changed. name='%s', dir='%s'", view_ptr
->view_name
, project_name
, project_dir
);
139 empty
= strlen(project_name
) == 0;
143 project_name_buffer
= strdup(project_name
);
144 if (project_name_buffer
== NULL
)
149 full_name_buffer
= catdup4(view_ptr
->view_name
, " (", project_name
, ")");
150 if (full_name_buffer
== NULL
)
152 free(project_name_buffer
);
156 if (view_ptr
->full_name
!= NULL
&& view_ptr
->full_name
!= view_ptr
->view_name
)
158 free(view_ptr
->full_name
);
161 if (view_ptr
->project_name
!= NULL
)
163 free(view_ptr
->project_name
);
166 view_ptr
->full_name
= full_name_buffer
;
167 view_ptr
->project_name
= project_name_buffer
;
171 if (view_ptr
->full_name
!= NULL
&& view_ptr
->full_name
!= view_ptr
->view_name
)
173 free(view_ptr
->full_name
);
176 if (view_ptr
->project_name
!= NULL
)
178 free(view_ptr
->project_name
);
181 view_ptr
->full_name
= view_ptr
->view_name
;
182 view_ptr
->project_name
= NULL
;
185 announce_view_name_change(view_ptr
);
190 static void fill_canvas_menu(GtkMenu
* menu
)
192 fill_view_popup_menu(menu
, (graph_view_handle
)g_current_view
);
198 const char * service
,
200 bool graph_dict_supported
,
201 bool graph_manager_supported
,
202 bool app_supervisor_supported
,
204 graph_view_handle
* handle_ptr
)
206 struct graph_view
* view_ptr
;
208 view_ptr
= malloc(sizeof(struct graph_view
));
209 if (view_ptr
== NULL
)
211 log_error("malloc() failed for struct graph_view");
215 view_ptr
->view_name
= strdup(name
);
216 if (view_ptr
->view_name
== NULL
)
218 log_error("strdup() failed for \"%s\"", name
);
222 view_ptr
->app_supervisor
= NULL
;
223 view_ptr
->room
= NULL
;
224 view_ptr
->full_name
= view_ptr
->view_name
;
225 view_ptr
->project_name
= NULL
;
227 if (!graph_proxy_create(service
, object
, graph_dict_supported
, graph_manager_supported
, &view_ptr
->graph
))
232 if (!graph_canvas_create(1600 * 2, 1200 * 2, fill_canvas_menu
, &view_ptr
->graph_canvas
))
237 if (!graph_canvas_attach(view_ptr
->graph_canvas
, view_ptr
->graph
))
239 goto destroy_graph_canvas
;
242 view_ptr
->canvas_widget
= canvas_get_widget(graph_canvas_get_canvas(view_ptr
->graph_canvas
));
244 list_add_tail(&view_ptr
->siblings
, &g_views
);
246 gtk_widget_show(view_ptr
->canvas_widget
);
248 world_tree_add((graph_view_handle
)view_ptr
, force_activate
);
250 if (app_supervisor_supported
)
252 if (!ladish_app_supervisor_proxy_create(service
, object
, view_ptr
, app_added
, app_state_changed
, app_removed
, &view_ptr
->app_supervisor
))
254 goto remove_from_world_tree
;
258 if (strcmp(object
, STUDIO_OBJECT_PATH
) != 0 && strcmp(object
, JACKDBUS_OBJECT_PATH
) != 0) /* TODO: this is a quite lame way to detect room views */
260 if (!ladish_room_proxy_create(service
, object
, view_ptr
, project_properties_changed
, &view_ptr
->room
))
262 goto free_app_supervisor
;
266 if (!graph_proxy_activate(view_ptr
->graph
))
268 goto free_room_proxy
;
273 *handle_ptr
= (graph_view_handle
)view_ptr
;
278 if (view_ptr
->room
!= NULL
)
280 ladish_room_proxy_destroy(view_ptr
->room
);
283 if (view_ptr
->app_supervisor
!= NULL
)
285 ladish_app_supervisor_proxy_destroy(view_ptr
->app_supervisor
);
287 remove_from_world_tree
:
288 list_del(&view_ptr
->siblings
);
289 if (!list_empty(&g_views
))
291 world_tree_activate((graph_view_handle
)list_entry(g_views
.next
, struct graph_view
, siblings
));
295 set_main_window_title(NULL
);
298 detach_canvas(view_ptr
);
300 world_tree_remove((graph_view_handle
)view_ptr
);
301 destroy_graph_canvas
:
302 graph_canvas_destroy(view_ptr
->graph_canvas
);
304 graph_proxy_destroy(view_ptr
->graph
);
306 if (view_ptr
->full_name
!= NULL
&& view_ptr
->full_name
!= view_ptr
->view_name
)
308 free(view_ptr
->full_name
);
310 if (view_ptr
->project_name
!= NULL
)
312 free(view_ptr
->project_name
);
314 free(view_ptr
->view_name
);
321 static void attach_canvas(struct graph_view
* view_ptr
)
325 child
= gtk_bin_get_child(GTK_BIN(g_main_scrolledwin
));
327 if (child
== view_ptr
->canvas_widget
)
334 gtk_container_remove(GTK_CONTAINER(g_main_scrolledwin
), child
);
337 g_current_view
= view_ptr
;
338 gtk_container_add(GTK_CONTAINER(g_main_scrolledwin
), view_ptr
->canvas_widget
);
340 //_main_scrolledwin->property_hadjustment().get_value()->set_step_increment(10);
341 //_main_scrolledwin->property_vadjustment().get_value()->set_step_increment(10);
344 #define view_ptr ((struct graph_view *)view)
346 void destroy_view(graph_view_handle view
)
348 list_del(&view_ptr
->siblings
);
349 if (!list_empty(&g_views
))
351 world_tree_activate((graph_view_handle
)list_entry(g_views
.next
, struct graph_view
, siblings
));
355 set_main_window_title(NULL
);
358 detach_canvas(view_ptr
);
360 world_tree_remove(view
);
362 graph_canvas_detach(view_ptr
->graph_canvas
);
363 graph_canvas_destroy(view_ptr
->graph_canvas
);
364 graph_proxy_destroy(view_ptr
->graph
);
366 if (view_ptr
->app_supervisor
!= NULL
)
368 ladish_app_supervisor_proxy_destroy(view_ptr
->app_supervisor
);
371 if (view_ptr
->room
!= NULL
)
373 ladish_room_proxy_destroy(view_ptr
->room
);
376 if (view_ptr
->full_name
!= NULL
&& view_ptr
->full_name
!= view_ptr
->view_name
)
378 free(view_ptr
->full_name
);
380 if (view_ptr
->project_name
!= NULL
)
382 free(view_ptr
->project_name
);
384 free(view_ptr
->view_name
);
389 void activate_view(graph_view_handle view
)
391 attach_canvas(view_ptr
);
392 set_main_window_title(view
);
396 const char * get_view_name(graph_view_handle view
)
398 return view_ptr
->full_name
;
401 const char * get_view_opath(graph_view_handle view
)
403 return graph_proxy_get_object(view_ptr
->graph
);
406 bool set_view_name(graph_view_handle view
, const char * name
)
408 char * view_name_buffer
;
409 char * full_name_buffer
;
411 view_name_buffer
= strdup(name
);
412 if (view_name_buffer
== NULL
)
414 log_error("strdup() failed for \"%s\"", name
);
418 if (view_ptr
->project_name
!= NULL
)
420 full_name_buffer
= catdup4(view_name_buffer
, " (", view_ptr
->project_name
, ")");
421 if (full_name_buffer
== NULL
)
423 free(view_name_buffer
);
429 full_name_buffer
= view_name_buffer
;
432 if (view_ptr
->full_name
!= NULL
&& view_ptr
->full_name
!= view_ptr
->view_name
)
434 free(view_ptr
->full_name
);
437 free(view_ptr
->view_name
);
439 view_ptr
->view_name
= view_name_buffer
;
440 view_ptr
->full_name
= full_name_buffer
;
442 announce_view_name_change(view_ptr
);
447 canvas_handle
get_current_canvas(void)
449 if (g_current_view
== NULL
)
454 return graph_canvas_get_canvas(g_current_view
->graph_canvas
);
457 const char * get_current_view_room_name(void)
459 if (g_current_view
== NULL
|| !is_room_view((graph_view_handle
)g_current_view
))
464 return g_current_view
->view_name
;
467 graph_view_handle
get_current_view(void)
469 return (graph_view_handle
)g_current_view
;
472 bool is_room_view(graph_view_handle view
)
474 return view_ptr
->room
!= NULL
;
477 bool app_run_custom(graph_view_handle view
, const char * command
, const char * name
, bool run_in_terminal
, const char * level
)
479 return ladish_app_supervisor_proxy_run_custom(view_ptr
->app_supervisor
, command
, name
, run_in_terminal
, level
);
482 ladish_app_supervisor_proxy_handle
graph_view_get_app_supervisor(graph_view_handle view
)
484 return view_ptr
->app_supervisor
;
487 ladish_room_proxy_handle
graph_view_get_room(graph_view_handle view
)
489 return view_ptr
->room
;
492 bool room_has_project(graph_view_handle view
)
494 return view_ptr
->project_name
!= NULL
;