rename graph clients when app is renamed
[ladish.git] / gui / graph_canvas.c
blobd41dd4ae39651ff405cd2593f6f2afcaf3fdc521
1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*
3 * LADI Session Handler (ladish)
5 * Copyright (C) 2009 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 graph_canvas_handle * graph_canvas_handle_ptr)
179 struct graph_canvas * graph_canvas_ptr;
181 graph_canvas_ptr = malloc(sizeof(struct graph_canvas));
182 if (graph_canvas_ptr == NULL)
184 return false;
187 if (!canvas_create(width, height, connect_request, disconnect_request, module_location_changed, &graph_canvas_ptr->canvas))
189 free(graph_canvas_ptr);
190 return false;
193 graph_canvas_ptr->graph = NULL;
194 INIT_LIST_HEAD(&graph_canvas_ptr->clients);
196 *graph_canvas_handle_ptr = (graph_canvas_handle)graph_canvas_ptr;
198 return true;
201 #define graph_canvas_ptr ((struct graph_canvas *)graph_canvas)
203 static
204 void
205 clear(
206 void * graph_canvas)
208 log_info("canvas::clear()");
209 canvas_clear(graph_canvas_ptr->canvas);
212 static
213 void
214 client_appeared(
215 void * graph_canvas,
216 uint64_t id,
217 const char * name)
219 struct client * client_ptr;
220 char * x_str;
221 char * y_str;
222 double x;
223 double y;
224 char * locale;
225 double width;
226 double height;
228 log_info("canvas::client_appeared(%"PRIu64", \"%s\")", id, name);
230 canvas_get_size(graph_canvas_ptr->canvas, &width, &height);
231 //log_debug("width %f, height %f", width, height);
233 client_ptr = malloc(sizeof(struct client));
234 if (client_ptr == NULL)
236 log_error("allocation of memory for struct client failed");
237 return;
240 client_ptr->id = id;
241 INIT_LIST_HEAD(&client_ptr->ports);
242 client_ptr->owner_ptr = graph_canvas_ptr;
244 x = 0;
245 y = 0;
247 if (!graph_proxy_dict_entry_get(
248 client_ptr->owner_ptr->graph,
249 GRAPH_DICT_OBJECT_TYPE_CLIENT,
251 URI_CANVAS_X,
252 &x_str))
254 x_str = NULL;
255 x = width / 2 - 200 + rand() % 300;
258 if (!graph_proxy_dict_entry_get(
259 client_ptr->owner_ptr->graph,
260 GRAPH_DICT_OBJECT_TYPE_CLIENT,
262 URI_CANVAS_Y,
263 &y_str))
265 y_str = NULL;
266 y = height / 2 - 200 + rand() % 300;
269 if (x_str != NULL || y_str != NULL)
271 locale = strdup(setlocale(LC_NUMERIC, NULL));
272 if (locale == NULL)
274 log_error("strdup() failed for locale string");
276 else
278 setlocale(LC_NUMERIC, "POSIX");
279 if (x_str != NULL)
281 //log_info("converting %s", x_str);
282 sscanf(x_str, "%lf", &x);
284 if (y_str != NULL)
286 //log_info("converting %s", y_str);
287 sscanf(y_str, "%lf", &y);
289 setlocale(LC_NUMERIC, locale);
290 free(locale);
293 if (x_str != NULL)
295 free(x_str);
298 if (y_str != NULL)
300 free(y_str);
304 if (!canvas_create_module(graph_canvas_ptr->canvas, name, x, y, true, true, client_ptr, &client_ptr->canvas_module))
306 log_error("canvas_create_module(\"%s\") failed", name);
307 free(client_ptr);
308 return;
311 if (x_str == NULL || y_str == NULL)
312 { /* we have generated random value, store it */
313 module_location_changed(client_ptr, x, y);
316 list_add_tail(&client_ptr->siblings, &graph_canvas_ptr->clients);
319 static
320 void
321 client_disappeared(
322 void * graph_canvas,
323 uint64_t id)
325 struct client * client_ptr;
327 log_info("canvas::client_disappeared(%"PRIu64")", id);
329 client_ptr = find_client(graph_canvas_ptr, id);
330 if (client_ptr == NULL)
332 log_error("cannot find disappearing client %"PRIu64"", id);
333 return;
336 list_del(&client_ptr->siblings);
337 canvas_destroy_module(graph_canvas_ptr->canvas, client_ptr->canvas_module);
338 free(client_ptr);
341 static void client_renamed(void * graph_canvas, uint64_t id, const char * old_name, const char * new_name)
343 struct client * client_ptr;
345 log_info("canvas::client_renamed(%"PRIu64", '%s', '%s')", id, old_name, new_name);
347 client_ptr = find_client(graph_canvas_ptr, id);
348 if (client_ptr == NULL)
350 log_error("cannot find renamed client %"PRIu64, id);
351 return;
354 canvas_set_module_name(client_ptr->canvas_module, new_name);
357 static
358 void
359 port_appeared(
360 void * graph_canvas,
361 uint64_t client_id,
362 uint64_t port_id,
363 const char * port_name,
364 bool is_input,
365 bool is_terminal,
366 bool is_midi)
368 int color;
369 struct client * client_ptr;
370 struct port * port_ptr;
372 log_info("canvas::port_appeared(%"PRIu64", %"PRIu64", \"%s\")", client_id, port_id, port_name);
374 client_ptr = find_client(graph_canvas_ptr, client_id);
375 if (client_ptr == NULL)
377 log_error("cannot find client %"PRIu64" of appearing port %"PRIu64" \"%s\"", client_id, port_id, port_name);
378 return;
381 port_ptr = malloc(sizeof(struct port));
382 if (port_ptr == NULL)
384 log_error("allocation of memory for struct port failed");
385 return;
388 port_ptr->id = port_id;
389 port_ptr->graph_canvas = graph_canvas_ptr;
391 // Darkest tango palette colour, with S -= 6, V -= 6, w/ transparency
392 if (is_midi)
394 color = 0x960909C0;
396 else
398 color = 0x244678C0;
401 if (!canvas_create_port(graph_canvas_ptr->canvas, client_ptr->canvas_module, port_name, is_input, color, port_ptr, &port_ptr->canvas_port))
403 log_error("canvas_create_port(\"%s\") failed", port_name);
404 free(client_ptr);
405 return;
408 list_add_tail(&port_ptr->siblings, &client_ptr->ports);
411 static
412 void
413 port_disappeared(
414 void * graph_canvas,
415 uint64_t client_id,
416 uint64_t port_id)
418 struct client * client_ptr;
419 struct port * port_ptr;
421 log_info("canvas::port_disappeared(%"PRIu64", %"PRIu64")", client_id, port_id);
423 client_ptr = find_client(graph_canvas_ptr, client_id);
424 if (client_ptr == NULL)
426 log_error("cannot find client %"PRIu64" of disappearing port %"PRIu64"", client_id, port_id);
427 return;
430 port_ptr = find_port(client_ptr, port_id);
431 if (client_ptr == NULL)
433 log_error("cannot find disappearing port %"PRIu64" of client %"PRIu64"", port_id, client_id);
434 return;
437 list_del(&port_ptr->siblings);
438 canvas_destroy_port(graph_canvas_ptr->canvas, port_ptr->canvas_port);
439 free(port_ptr);
442 static
443 void
444 port_renamed(
445 void * graph_canvas,
446 uint64_t client_id,
447 uint64_t port_id,
448 const char * old_port_name,
449 const char * new_port_name)
451 struct client * client_ptr;
452 struct port * port_ptr;
454 log_info("canvas::port_renamed(%"PRIu64", %"PRIu64", '%s', '%s')", client_id, port_id, old_port_name, new_port_name);
456 client_ptr = find_client(graph_canvas_ptr, client_id);
457 if (client_ptr == NULL)
459 log_error("cannot find client %"PRIu64" of renamed port %"PRIu64"", client_id, port_id);
460 return;
463 port_ptr = find_port(client_ptr, port_id);
464 if (client_ptr == NULL)
466 log_error("cannot find renamed port %"PRIu64" of client %"PRIu64"", port_id, client_id);
467 return;
470 canvas_set_port_name(port_ptr->canvas_port, new_port_name);
473 static
474 void
475 ports_connected(
476 void * graph_canvas,
477 uint64_t client1_id,
478 uint64_t port1_id,
479 uint64_t client2_id,
480 uint64_t port2_id)
482 struct client * client1_ptr;
483 struct port * port1_ptr;
484 struct client * client2_ptr;
485 struct port * port2_ptr;
487 log_info("canvas::ports_connected(%"PRIu64", %"PRIu64", %"PRIu64", %"PRIu64")", client1_id, port1_id, client2_id, port2_id);
489 client1_ptr = find_client(graph_canvas_ptr, client1_id);
490 if (client1_ptr == NULL)
492 log_error("cannot find client %"PRIu64" of connected port %"PRIu64"", client1_id, port1_id);
493 return;
496 port1_ptr = find_port(client1_ptr, port1_id);
497 if (client1_ptr == NULL)
499 log_error("cannot find connected port %"PRIu64" of client %"PRIu64"", port1_id, client1_id);
500 return;
503 client2_ptr = find_client(graph_canvas_ptr, client2_id);
504 if (client2_ptr == NULL)
506 log_error("cannot find client %"PRIu64" of connected port %"PRIu64"", client2_id, port2_id);
507 return;
510 port2_ptr = find_port(client2_ptr, port2_id);
511 if (client2_ptr == NULL)
513 log_error("cannot find connected port %"PRIu64" of client %"PRIu64"", port2_id, client2_id);
514 return;
517 canvas_add_connection(
518 graph_canvas_ptr->canvas,
519 port1_ptr->canvas_port,
520 port2_ptr->canvas_port,
521 canvas_get_port_color(port1_ptr->canvas_port) + 0x22222200);
524 static
525 void
526 ports_disconnected(
527 void * graph_canvas,
528 uint64_t client1_id,
529 uint64_t port1_id,
530 uint64_t client2_id,
531 uint64_t port2_id)
533 struct client * client1_ptr;
534 struct port * port1_ptr;
535 struct client * client2_ptr;
536 struct port * port2_ptr;
538 log_info("canvas::ports_disconnected(%"PRIu64", %"PRIu64", %"PRIu64", %"PRIu64")", client1_id, port1_id, client2_id, port2_id);
540 client1_ptr = find_client(graph_canvas_ptr, client1_id);
541 if (client1_ptr == NULL)
543 log_error("cannot find client %"PRIu64" of disconnected port %"PRIu64"", client1_id, port1_id);
544 return;
547 port1_ptr = find_port(client1_ptr, port1_id);
548 if (client1_ptr == NULL)
550 log_error("cannot find disconnected port %"PRIu64" of client %"PRIu64"", port1_id, client1_id);
551 return;
554 client2_ptr = find_client(graph_canvas_ptr, client2_id);
555 if (client2_ptr == NULL)
557 log_error("cannot find client %"PRIu64" of disconnected port %"PRIu64"", client2_id, port2_id);
558 return;
561 port2_ptr = find_port(client2_ptr, port2_id);
562 if (client2_ptr == NULL)
564 log_error("cannot find disconnected port %"PRIu64" of client %"PRIu64"", port2_id, client2_id);
565 return;
568 canvas_remove_connection(
569 graph_canvas_ptr->canvas,
570 port1_ptr->canvas_port,
571 port2_ptr->canvas_port);
574 void
575 graph_canvas_destroy(
576 graph_canvas_handle graph_canvas)
578 if (graph_canvas_ptr->graph != NULL)
580 graph_canvas_detach(graph_canvas);
583 free(graph_canvas_ptr);
586 bool
587 graph_canvas_attach(
588 graph_canvas_handle graph_canvas,
589 graph_proxy_handle graph)
591 ASSERT(graph_canvas_ptr->graph == NULL);
593 if (!graph_proxy_attach(
594 graph,
595 graph_canvas,
596 clear,
597 client_appeared,
598 client_renamed,
599 client_disappeared,
600 port_appeared,
601 port_renamed,
602 port_disappeared,
603 ports_connected,
604 ports_disconnected))
606 return false;
609 graph_canvas_ptr->graph = graph;
611 return true;
614 void
615 graph_canvas_detach(
616 graph_canvas_handle graph_canvas)
618 ASSERT(graph_canvas_ptr->graph != NULL);
619 graph_proxy_detach(graph_canvas_ptr->graph, graph_canvas);
620 graph_canvas_ptr->graph = NULL;
623 canvas_handle
624 graph_canvas_get_canvas(
625 graph_canvas_handle graph_canvas)
627 return graph_canvas_ptr->canvas;