handle port renames. closes #32
[ladish.git] / gui / graph_canvas.c
blob586c9fa3aeaaec38522fd82f5791d633e5675d71
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 - 100 + rand() % 400;
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 - 100 + rand() % 400;
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
342 void
343 port_appeared(
344 void * graph_canvas,
345 uint64_t client_id,
346 uint64_t port_id,
347 const char * port_name,
348 bool is_input,
349 bool is_terminal,
350 bool is_midi)
352 int color;
353 struct client * client_ptr;
354 struct port * port_ptr;
356 log_info("canvas::port_appeared(%"PRIu64", %"PRIu64", \"%s\")", client_id, port_id, port_name);
358 client_ptr = find_client(graph_canvas_ptr, client_id);
359 if (client_ptr == NULL)
361 log_error("cannot find client %"PRIu64" of appearing port %"PRIu64" \"%s\"", client_id, port_id, port_name);
362 return;
365 port_ptr = malloc(sizeof(struct port));
366 if (port_ptr == NULL)
368 log_error("allocation of memory for struct port failed");
369 return;
372 port_ptr->id = port_id;
373 port_ptr->graph_canvas = graph_canvas_ptr;
375 // Darkest tango palette colour, with S -= 6, V -= 6, w/ transparency
376 if (is_midi)
378 color = 0x960909C0;
380 else
382 color = 0x244678C0;
385 if (!canvas_create_port(graph_canvas_ptr->canvas, client_ptr->canvas_module, port_name, is_input, color, port_ptr, &port_ptr->canvas_port))
387 log_error("canvas_create_port(\"%s\") failed", port_name);
388 free(client_ptr);
389 return;
392 list_add_tail(&port_ptr->siblings, &client_ptr->ports);
395 static
396 void
397 port_disappeared(
398 void * graph_canvas,
399 uint64_t client_id,
400 uint64_t port_id)
402 struct client * client_ptr;
403 struct port * port_ptr;
405 log_info("canvas::port_disappeared(%"PRIu64", %"PRIu64")", client_id, port_id);
407 client_ptr = find_client(graph_canvas_ptr, client_id);
408 if (client_ptr == NULL)
410 log_error("cannot find client %"PRIu64" of disappearing port %"PRIu64"", client_id, port_id);
411 return;
414 port_ptr = find_port(client_ptr, port_id);
415 if (client_ptr == NULL)
417 log_error("cannot find disappearing port %"PRIu64" of client %"PRIu64"", port_id, client_id);
418 return;
421 list_del(&port_ptr->siblings);
422 canvas_destroy_port(graph_canvas_ptr->canvas, port_ptr->canvas_port);
423 free(port_ptr);
426 static
427 void
428 port_renamed(
429 void * graph_canvas,
430 uint64_t client_id,
431 uint64_t port_id,
432 const char * old_port_name,
433 const char * new_port_name)
435 struct client * client_ptr;
436 struct port * port_ptr;
438 log_info("canvas::port_renamed(%"PRIu64", %"PRIu64", '%s', '%s')", client_id, port_id, old_port_name, new_port_name);
440 client_ptr = find_client(graph_canvas_ptr, client_id);
441 if (client_ptr == NULL)
443 log_error("cannot find client %"PRIu64" of renamed port %"PRIu64"", client_id, port_id);
444 return;
447 port_ptr = find_port(client_ptr, port_id);
448 if (client_ptr == NULL)
450 log_error("cannot find renamed port %"PRIu64" of client %"PRIu64"", port_id, client_id);
451 return;
454 canvas_set_port_name(port_ptr->canvas_port, new_port_name);
457 static
458 void
459 ports_connected(
460 void * graph_canvas,
461 uint64_t client1_id,
462 uint64_t port1_id,
463 uint64_t client2_id,
464 uint64_t port2_id)
466 struct client * client1_ptr;
467 struct port * port1_ptr;
468 struct client * client2_ptr;
469 struct port * port2_ptr;
471 log_info("canvas::ports_connected(%"PRIu64", %"PRIu64", %"PRIu64", %"PRIu64")", client1_id, port1_id, client2_id, port2_id);
473 client1_ptr = find_client(graph_canvas_ptr, client1_id);
474 if (client1_ptr == NULL)
476 log_error("cannot find client %"PRIu64" of connected port %"PRIu64"", client1_id, port1_id);
477 return;
480 port1_ptr = find_port(client1_ptr, port1_id);
481 if (client1_ptr == NULL)
483 log_error("cannot find connected port %"PRIu64" of client %"PRIu64"", port1_id, client1_id);
484 return;
487 client2_ptr = find_client(graph_canvas_ptr, client2_id);
488 if (client2_ptr == NULL)
490 log_error("cannot find client %"PRIu64" of connected port %"PRIu64"", client2_id, port2_id);
491 return;
494 port2_ptr = find_port(client2_ptr, port2_id);
495 if (client2_ptr == NULL)
497 log_error("cannot find connected port %"PRIu64" of client %"PRIu64"", port2_id, client2_id);
498 return;
501 canvas_add_connection(
502 graph_canvas_ptr->canvas,
503 port1_ptr->canvas_port,
504 port2_ptr->canvas_port,
505 canvas_get_port_color(port1_ptr->canvas_port) + 0x22222200);
508 static
509 void
510 ports_disconnected(
511 void * graph_canvas,
512 uint64_t client1_id,
513 uint64_t port1_id,
514 uint64_t client2_id,
515 uint64_t port2_id)
517 struct client * client1_ptr;
518 struct port * port1_ptr;
519 struct client * client2_ptr;
520 struct port * port2_ptr;
522 log_info("canvas::ports_disconnected(%"PRIu64", %"PRIu64", %"PRIu64", %"PRIu64")", client1_id, port1_id, client2_id, port2_id);
524 client1_ptr = find_client(graph_canvas_ptr, client1_id);
525 if (client1_ptr == NULL)
527 log_error("cannot find client %"PRIu64" of disconnected port %"PRIu64"", client1_id, port1_id);
528 return;
531 port1_ptr = find_port(client1_ptr, port1_id);
532 if (client1_ptr == NULL)
534 log_error("cannot find disconnected port %"PRIu64" of client %"PRIu64"", port1_id, client1_id);
535 return;
538 client2_ptr = find_client(graph_canvas_ptr, client2_id);
539 if (client2_ptr == NULL)
541 log_error("cannot find client %"PRIu64" of disconnected port %"PRIu64"", client2_id, port2_id);
542 return;
545 port2_ptr = find_port(client2_ptr, port2_id);
546 if (client2_ptr == NULL)
548 log_error("cannot find disconnected port %"PRIu64" of client %"PRIu64"", port2_id, client2_id);
549 return;
552 canvas_remove_connection(
553 graph_canvas_ptr->canvas,
554 port1_ptr->canvas_port,
555 port2_ptr->canvas_port);
558 void
559 graph_canvas_destroy(
560 graph_canvas_handle graph_canvas)
562 if (graph_canvas_ptr->graph != NULL)
564 graph_canvas_detach(graph_canvas);
567 free(graph_canvas_ptr);
570 bool
571 graph_canvas_attach(
572 graph_canvas_handle graph_canvas,
573 graph_proxy_handle graph)
575 ASSERT(graph_canvas_ptr->graph == NULL);
577 if (!graph_proxy_attach(
578 graph,
579 graph_canvas,
580 clear,
581 client_appeared,
582 client_disappeared,
583 port_appeared,
584 port_renamed,
585 port_disappeared,
586 ports_connected,
587 ports_disconnected))
589 return false;
592 graph_canvas_ptr->graph = graph;
594 return true;
597 void
598 graph_canvas_detach(
599 graph_canvas_handle graph_canvas)
601 ASSERT(graph_canvas_ptr->graph != NULL);
602 graph_proxy_detach(graph_canvas_ptr->graph, graph_canvas);
603 graph_canvas_ptr->graph = NULL;
606 canvas_handle
607 graph_canvas_get_canvas(
608 graph_canvas_handle graph_canvas)
610 return graph_canvas_ptr->canvas;