ladishd: clear project even if room project state is 'unloaded'. Fix for #117
[ladish.git] / gui / graph_canvas.c
blob7c2a95144d76b9a62887595650aac985ecf970b2
1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*
3 * LADI Session Handler (ladish)
5 * Copyright (C) 2009, 2010 Nedko Arnaudov <nedko@arnaudov.name>
7 **************************************************************************
8 * This file contains implementation of graph canvas 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.
27 #include <locale.h>
29 #include "graph_canvas.h"
30 #include "../dbus_constants.h"
32 struct graph_canvas
34 graph_proxy_handle graph;
35 canvas_handle canvas;
36 struct list_head clients;
39 struct client
41 struct list_head siblings;
42 uint64_t id;
43 canvas_module_handle canvas_module;
44 struct list_head ports;
45 struct graph_canvas * owner_ptr;
48 struct port
50 struct list_head siblings;
51 uint64_t id;
52 canvas_port_handle canvas_port;
53 struct graph_canvas * graph_canvas;
56 static
57 struct client *
58 find_client(
59 struct graph_canvas * graph_canvas_ptr,
60 uint64_t id)
62 struct list_head * node_ptr;
63 struct client * client_ptr;
65 list_for_each(node_ptr, &graph_canvas_ptr->clients)
67 client_ptr = list_entry(node_ptr, struct client, siblings);
68 if (client_ptr->id == id)
70 return client_ptr;
74 return NULL;
77 static
78 struct port *
79 find_port(
80 struct client * client_ptr,
81 uint64_t id)
83 struct list_head * node_ptr;
84 struct port * port_ptr;
86 list_for_each(node_ptr, &client_ptr->ports)
88 port_ptr = list_entry(node_ptr, struct port, siblings);
89 if (port_ptr->id == id)
91 return port_ptr;
95 return NULL;
98 #define port1_ptr ((struct port *)port1_context)
99 #define port2_ptr ((struct port *)port2_context)
101 static
102 void
103 connect_request(
104 void * port1_context,
105 void * port2_context)
107 log_info("connect request(%"PRIu64", %"PRIu64")", port1_ptr->id, port2_ptr->id);
109 ASSERT(port1_ptr->graph_canvas == port2_ptr->graph_canvas);
111 graph_proxy_connect_ports(port1_ptr->graph_canvas->graph, port1_ptr->id, port2_ptr->id);
114 void
115 disconnect_request(
116 void * port1_context,
117 void * port2_context)
119 log_info("disconnect request(%"PRIu64", %"PRIu64")", port1_ptr->id, port2_ptr->id);
121 ASSERT(port1_ptr->graph_canvas == port2_ptr->graph_canvas);
123 graph_proxy_disconnect_ports(port1_ptr->graph_canvas->graph, port1_ptr->id, port2_ptr->id);
126 #undef port1_ptr
127 #undef port2_ptr
129 #define client_ptr ((struct client *)module_context)
131 void
132 module_location_changed(
133 void * module_context,
134 double x,
135 double y)
137 char x_str[100];
138 char y_str[100];
139 char * locale;
141 log_info("module_location_changed(id = %3llu, x = %6.1f, y = %6.1f)", (unsigned long long)client_ptr->id, x, y);
143 locale = strdup(setlocale(LC_NUMERIC, NULL));
144 if (locale == NULL)
146 log_error("strdup() failed for locale string");
147 return;
150 setlocale(LC_NUMERIC, "POSIX");
151 sprintf(x_str, "%f", x);
152 sprintf(y_str, "%f", y);
153 setlocale(LC_NUMERIC, locale);
154 free(locale);
156 graph_proxy_dict_entry_set(
157 client_ptr->owner_ptr->graph,
158 GRAPH_DICT_OBJECT_TYPE_CLIENT,
159 client_ptr->id,
160 URI_CANVAS_X,
161 x_str);
163 graph_proxy_dict_entry_set(
164 client_ptr->owner_ptr->graph,
165 GRAPH_DICT_OBJECT_TYPE_CLIENT,
166 client_ptr->id,
167 URI_CANVAS_Y,
168 y_str);
171 #undef client_ptr
173 bool
174 graph_canvas_create(
175 int width,
176 int height,
177 void (* fill_canvas_menu)(GtkMenu * menu),
178 graph_canvas_handle * graph_canvas_handle_ptr)
180 struct graph_canvas * graph_canvas_ptr;
182 graph_canvas_ptr = malloc(sizeof(struct graph_canvas));
183 if (graph_canvas_ptr == NULL)
185 return false;
188 if (!canvas_create(
189 width,
190 height,
191 connect_request,
192 disconnect_request,
193 module_location_changed,
194 fill_canvas_menu,
195 NULL,
196 NULL,
197 &graph_canvas_ptr->canvas))
199 free(graph_canvas_ptr);
200 return false;
203 graph_canvas_ptr->graph = NULL;
204 INIT_LIST_HEAD(&graph_canvas_ptr->clients);
206 *graph_canvas_handle_ptr = (graph_canvas_handle)graph_canvas_ptr;
208 return true;
211 #define graph_canvas_ptr ((struct graph_canvas *)graph_canvas)
213 static
214 void
215 clear(
216 void * graph_canvas)
218 log_info("canvas::clear()");
219 canvas_clear(graph_canvas_ptr->canvas);
222 static
223 void
224 client_appeared(
225 void * graph_canvas,
226 uint64_t id,
227 const char * name)
229 struct client * client_ptr;
230 char * x_str;
231 char * y_str;
232 double x;
233 double y;
234 char * locale;
235 double width;
236 double height;
238 log_info("canvas::client_appeared(%"PRIu64", \"%s\")", id, name);
240 canvas_get_size(graph_canvas_ptr->canvas, &width, &height);
241 //log_debug("width %f, height %f", width, height);
243 client_ptr = malloc(sizeof(struct client));
244 if (client_ptr == NULL)
246 log_error("allocation of memory for struct client failed");
247 return;
250 client_ptr->id = id;
251 INIT_LIST_HEAD(&client_ptr->ports);
252 client_ptr->owner_ptr = graph_canvas_ptr;
254 x = 0;
255 y = 0;
257 if (!graph_proxy_dict_entry_get(
258 client_ptr->owner_ptr->graph,
259 GRAPH_DICT_OBJECT_TYPE_CLIENT,
261 URI_CANVAS_X,
262 &x_str))
264 x_str = NULL;
265 x = width / 2 - 200 + rand() % 300;
268 if (!graph_proxy_dict_entry_get(
269 client_ptr->owner_ptr->graph,
270 GRAPH_DICT_OBJECT_TYPE_CLIENT,
272 URI_CANVAS_Y,
273 &y_str))
275 y_str = NULL;
276 y = height / 2 - 200 + rand() % 300;
279 if (x_str != NULL || y_str != NULL)
281 locale = strdup(setlocale(LC_NUMERIC, NULL));
282 if (locale == NULL)
284 log_error("strdup() failed for locale string");
286 else
288 setlocale(LC_NUMERIC, "POSIX");
289 if (x_str != NULL)
291 //log_info("converting %s", x_str);
292 sscanf(x_str, "%lf", &x);
294 if (y_str != NULL)
296 //log_info("converting %s", y_str);
297 sscanf(y_str, "%lf", &y);
299 setlocale(LC_NUMERIC, locale);
300 free(locale);
303 if (x_str != NULL)
305 free(x_str);
308 if (y_str != NULL)
310 free(y_str);
314 if (!canvas_create_module(graph_canvas_ptr->canvas, name, x, y, true, true, client_ptr, &client_ptr->canvas_module))
316 log_error("canvas_create_module(\"%s\") failed", name);
317 free(client_ptr);
318 return;
321 if (x_str == NULL || y_str == NULL)
322 { /* we have generated random value, store it */
323 module_location_changed(client_ptr, x, y);
326 list_add_tail(&client_ptr->siblings, &graph_canvas_ptr->clients);
329 static
330 void
331 client_disappeared(
332 void * graph_canvas,
333 uint64_t id)
335 struct client * client_ptr;
337 log_info("canvas::client_disappeared(%"PRIu64")", id);
339 client_ptr = find_client(graph_canvas_ptr, id);
340 if (client_ptr == NULL)
342 log_error("cannot find disappearing client %"PRIu64"", id);
343 return;
346 list_del(&client_ptr->siblings);
347 canvas_destroy_module(graph_canvas_ptr->canvas, client_ptr->canvas_module);
348 free(client_ptr);
351 static void client_renamed(void * graph_canvas, uint64_t id, const char * old_name, const char * new_name)
353 struct client * client_ptr;
355 log_info("canvas::client_renamed(%"PRIu64", '%s', '%s')", id, old_name, new_name);
357 client_ptr = find_client(graph_canvas_ptr, id);
358 if (client_ptr == NULL)
360 log_error("cannot find renamed client %"PRIu64, id);
361 return;
364 canvas_set_module_name(client_ptr->canvas_module, new_name);
367 static
368 void
369 port_appeared(
370 void * graph_canvas,
371 uint64_t client_id,
372 uint64_t port_id,
373 const char * port_name,
374 bool is_input,
375 bool is_terminal,
376 bool is_midi)
378 int color;
379 struct client * client_ptr;
380 struct port * port_ptr;
382 log_info("canvas::port_appeared(%"PRIu64", %"PRIu64", \"%s\")", client_id, port_id, port_name);
384 client_ptr = find_client(graph_canvas_ptr, client_id);
385 if (client_ptr == NULL)
387 log_error("cannot find client %"PRIu64" of appearing port %"PRIu64" \"%s\"", client_id, port_id, port_name);
388 return;
391 port_ptr = malloc(sizeof(struct port));
392 if (port_ptr == NULL)
394 log_error("allocation of memory for struct port failed");
395 return;
398 port_ptr->id = port_id;
399 port_ptr->graph_canvas = graph_canvas_ptr;
401 // Darkest tango palette colour, with S -= 6, V -= 6, w/ transparency
402 if (is_midi)
404 color = 0x960909C0;
406 else
408 color = 0x244678C0;
411 if (!canvas_create_port(graph_canvas_ptr->canvas, client_ptr->canvas_module, port_name, is_input, color, port_ptr, &port_ptr->canvas_port))
413 log_error("canvas_create_port(\"%s\") failed", port_name);
414 free(client_ptr);
415 return;
418 list_add_tail(&port_ptr->siblings, &client_ptr->ports);
421 static
422 void
423 port_disappeared(
424 void * graph_canvas,
425 uint64_t client_id,
426 uint64_t port_id)
428 struct client * client_ptr;
429 struct port * port_ptr;
431 log_info("canvas::port_disappeared(%"PRIu64", %"PRIu64")", client_id, port_id);
433 client_ptr = find_client(graph_canvas_ptr, client_id);
434 if (client_ptr == NULL)
436 log_error("cannot find client %"PRIu64" of disappearing port %"PRIu64"", client_id, port_id);
437 return;
440 port_ptr = find_port(client_ptr, port_id);
441 if (client_ptr == NULL)
443 log_error("cannot find disappearing port %"PRIu64" of client %"PRIu64"", port_id, client_id);
444 return;
447 list_del(&port_ptr->siblings);
448 canvas_destroy_port(graph_canvas_ptr->canvas, port_ptr->canvas_port);
449 free(port_ptr);
452 static
453 void
454 port_renamed(
455 void * graph_canvas,
456 uint64_t client_id,
457 uint64_t port_id,
458 const char * old_port_name,
459 const char * new_port_name)
461 struct client * client_ptr;
462 struct port * port_ptr;
464 log_info("canvas::port_renamed(%"PRIu64", %"PRIu64", '%s', '%s')", client_id, port_id, old_port_name, new_port_name);
466 client_ptr = find_client(graph_canvas_ptr, client_id);
467 if (client_ptr == NULL)
469 log_error("cannot find client %"PRIu64" of renamed port %"PRIu64"", client_id, port_id);
470 return;
473 port_ptr = find_port(client_ptr, port_id);
474 if (client_ptr == NULL)
476 log_error("cannot find renamed port %"PRIu64" of client %"PRIu64"", port_id, client_id);
477 return;
480 canvas_set_port_name(port_ptr->canvas_port, new_port_name);
483 static
484 void
485 ports_connected(
486 void * graph_canvas,
487 uint64_t client1_id,
488 uint64_t port1_id,
489 uint64_t client2_id,
490 uint64_t port2_id)
492 struct client * client1_ptr;
493 struct port * port1_ptr;
494 struct client * client2_ptr;
495 struct port * port2_ptr;
497 log_info("canvas::ports_connected(%"PRIu64", %"PRIu64", %"PRIu64", %"PRIu64")", client1_id, port1_id, client2_id, port2_id);
499 client1_ptr = find_client(graph_canvas_ptr, client1_id);
500 if (client1_ptr == NULL)
502 log_error("cannot find client %"PRIu64" of connected port %"PRIu64"", client1_id, port1_id);
503 return;
506 port1_ptr = find_port(client1_ptr, port1_id);
507 if (client1_ptr == NULL)
509 log_error("cannot find connected port %"PRIu64" of client %"PRIu64"", port1_id, client1_id);
510 return;
513 client2_ptr = find_client(graph_canvas_ptr, client2_id);
514 if (client2_ptr == NULL)
516 log_error("cannot find client %"PRIu64" of connected port %"PRIu64"", client2_id, port2_id);
517 return;
520 port2_ptr = find_port(client2_ptr, port2_id);
521 if (client2_ptr == NULL)
523 log_error("cannot find connected port %"PRIu64" of client %"PRIu64"", port2_id, client2_id);
524 return;
527 canvas_add_connection(
528 graph_canvas_ptr->canvas,
529 port1_ptr->canvas_port,
530 port2_ptr->canvas_port,
531 canvas_get_port_color(port1_ptr->canvas_port) + 0x22222200);
534 static
535 void
536 ports_disconnected(
537 void * graph_canvas,
538 uint64_t client1_id,
539 uint64_t port1_id,
540 uint64_t client2_id,
541 uint64_t port2_id)
543 struct client * client1_ptr;
544 struct port * port1_ptr;
545 struct client * client2_ptr;
546 struct port * port2_ptr;
548 log_info("canvas::ports_disconnected(%"PRIu64", %"PRIu64", %"PRIu64", %"PRIu64")", client1_id, port1_id, client2_id, port2_id);
550 client1_ptr = find_client(graph_canvas_ptr, client1_id);
551 if (client1_ptr == NULL)
553 log_error("cannot find client %"PRIu64" of disconnected port %"PRIu64"", client1_id, port1_id);
554 return;
557 port1_ptr = find_port(client1_ptr, port1_id);
558 if (client1_ptr == NULL)
560 log_error("cannot find disconnected port %"PRIu64" of client %"PRIu64"", port1_id, client1_id);
561 return;
564 client2_ptr = find_client(graph_canvas_ptr, client2_id);
565 if (client2_ptr == NULL)
567 log_error("cannot find client %"PRIu64" of disconnected port %"PRIu64"", client2_id, port2_id);
568 return;
571 port2_ptr = find_port(client2_ptr, port2_id);
572 if (client2_ptr == NULL)
574 log_error("cannot find disconnected port %"PRIu64" of client %"PRIu64"", port2_id, client2_id);
575 return;
578 canvas_remove_connection(
579 graph_canvas_ptr->canvas,
580 port1_ptr->canvas_port,
581 port2_ptr->canvas_port);
584 void
585 graph_canvas_destroy(
586 graph_canvas_handle graph_canvas)
588 if (graph_canvas_ptr->graph != NULL)
590 graph_canvas_detach(graph_canvas);
593 free(graph_canvas_ptr);
596 bool
597 graph_canvas_attach(
598 graph_canvas_handle graph_canvas,
599 graph_proxy_handle graph)
601 ASSERT(graph_canvas_ptr->graph == NULL);
603 if (!graph_proxy_attach(
604 graph,
605 graph_canvas,
606 clear,
607 client_appeared,
608 client_renamed,
609 client_disappeared,
610 port_appeared,
611 port_renamed,
612 port_disappeared,
613 ports_connected,
614 ports_disconnected))
616 return false;
619 graph_canvas_ptr->graph = graph;
621 return true;
624 void
625 graph_canvas_detach(
626 graph_canvas_handle graph_canvas)
628 ASSERT(graph_canvas_ptr->graph != NULL);
629 graph_proxy_detach(graph_canvas_ptr->graph, graph_canvas);
630 graph_canvas_ptr->graph = NULL;
633 canvas_handle
634 graph_canvas_get_canvas(
635 graph_canvas_handle graph_canvas)
637 return graph_canvas_ptr->canvas;