Somewhat sane default canvas positions for clients
[ladish.git] / gui / graph_canvas.c
blobec19d30cf2977217c978d1cd5e822ab1d4838bfc
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 list_add_tail(&client_ptr->siblings, &graph_canvas_ptr->clients);
314 static
315 void
316 client_disappeared(
317 void * graph_canvas,
318 uint64_t id)
320 struct client * client_ptr;
322 log_info("canvas::client_disappeared(%"PRIu64")", id);
324 client_ptr = find_client(graph_canvas_ptr, id);
325 if (client_ptr == NULL)
327 log_error("cannot find disappearing client %"PRIu64"", id);
328 return;
331 list_del(&client_ptr->siblings);
332 canvas_destroy_module(graph_canvas_ptr->canvas, client_ptr->canvas_module);
333 free(client_ptr);
336 static
337 void
338 port_appeared(
339 void * graph_canvas,
340 uint64_t client_id,
341 uint64_t port_id,
342 const char * port_name,
343 bool is_input,
344 bool is_terminal,
345 bool is_midi)
347 int color;
348 struct client * client_ptr;
349 struct port * port_ptr;
351 log_info("canvas::port_appeared(%"PRIu64", %"PRIu64", \"%s\")", client_id, port_id, port_name);
353 client_ptr = find_client(graph_canvas_ptr, client_id);
354 if (client_ptr == NULL)
356 log_error("cannot find client %"PRIu64" of appearing port %"PRIu64" \"%s\"", client_id, port_id, port_name);
357 return;
360 port_ptr = malloc(sizeof(struct port));
361 if (port_ptr == NULL)
363 log_error("allocation of memory for struct port failed");
364 return;
367 port_ptr->id = port_id;
368 port_ptr->graph_canvas = graph_canvas_ptr;
370 // Darkest tango palette colour, with S -= 6, V -= 6, w/ transparency
371 if (is_midi)
373 color = 0x960909C0;
375 else
377 color = 0x244678C0;
380 if (!canvas_create_port(graph_canvas_ptr->canvas, client_ptr->canvas_module, port_name, is_input, color, port_ptr, &port_ptr->canvas_port))
382 log_error("canvas_create_port(\"%s\") failed", port_name);
383 free(client_ptr);
384 return;
387 list_add_tail(&port_ptr->siblings, &client_ptr->ports);
390 static
391 void
392 port_disappeared(
393 void * graph_canvas,
394 uint64_t client_id,
395 uint64_t port_id)
397 struct client * client_ptr;
398 struct port * port_ptr;
400 log_info("canvas::port_disappeared(%"PRIu64", %"PRIu64")", client_id, port_id);
402 client_ptr = find_client(graph_canvas_ptr, client_id);
403 if (client_ptr == NULL)
405 log_error("cannot find client %"PRIu64" of disappearing port %"PRIu64"", client_id, port_id);
406 return;
409 port_ptr = find_port(client_ptr, port_id);
410 if (client_ptr == NULL)
412 log_error("cannot find disappearing port %"PRIu64" of client %"PRIu64"", port_id, client_id);
413 return;
416 list_del(&port_ptr->siblings);
417 canvas_destroy_port(graph_canvas_ptr->canvas, port_ptr->canvas_port);
418 free(port_ptr);
421 static
422 void
423 ports_connected(
424 void * graph_canvas,
425 uint64_t client1_id,
426 uint64_t port1_id,
427 uint64_t client2_id,
428 uint64_t port2_id)
430 struct client * client1_ptr;
431 struct port * port1_ptr;
432 struct client * client2_ptr;
433 struct port * port2_ptr;
435 log_info("canvas::ports_connected(%"PRIu64", %"PRIu64", %"PRIu64", %"PRIu64")", client1_id, port1_id, client2_id, port2_id);
437 client1_ptr = find_client(graph_canvas_ptr, client1_id);
438 if (client1_ptr == NULL)
440 log_error("cannot find client %"PRIu64" of connected port %"PRIu64"", client1_id, port1_id);
441 return;
444 port1_ptr = find_port(client1_ptr, port1_id);
445 if (client1_ptr == NULL)
447 log_error("cannot find connected port %"PRIu64" of client %"PRIu64"", port1_id, client1_id);
448 return;
451 client2_ptr = find_client(graph_canvas_ptr, client2_id);
452 if (client2_ptr == NULL)
454 log_error("cannot find client %"PRIu64" of connected port %"PRIu64"", client2_id, port2_id);
455 return;
458 port2_ptr = find_port(client2_ptr, port2_id);
459 if (client2_ptr == NULL)
461 log_error("cannot find connected port %"PRIu64" of client %"PRIu64"", port2_id, client2_id);
462 return;
465 canvas_add_connection(
466 graph_canvas_ptr->canvas,
467 port1_ptr->canvas_port,
468 port2_ptr->canvas_port,
469 canvas_get_port_color(port1_ptr->canvas_port) + 0x22222200);
472 static
473 void
474 ports_disconnected(
475 void * graph_canvas,
476 uint64_t client1_id,
477 uint64_t port1_id,
478 uint64_t client2_id,
479 uint64_t port2_id)
481 struct client * client1_ptr;
482 struct port * port1_ptr;
483 struct client * client2_ptr;
484 struct port * port2_ptr;
486 log_info("canvas::ports_disconnected(%"PRIu64", %"PRIu64", %"PRIu64", %"PRIu64")", client1_id, port1_id, client2_id, port2_id);
488 client1_ptr = find_client(graph_canvas_ptr, client1_id);
489 if (client1_ptr == NULL)
491 log_error("cannot find client %"PRIu64" of disconnected port %"PRIu64"", client1_id, port1_id);
492 return;
495 port1_ptr = find_port(client1_ptr, port1_id);
496 if (client1_ptr == NULL)
498 log_error("cannot find disconnected port %"PRIu64" of client %"PRIu64"", port1_id, client1_id);
499 return;
502 client2_ptr = find_client(graph_canvas_ptr, client2_id);
503 if (client2_ptr == NULL)
505 log_error("cannot find client %"PRIu64" of disconnected port %"PRIu64"", client2_id, port2_id);
506 return;
509 port2_ptr = find_port(client2_ptr, port2_id);
510 if (client2_ptr == NULL)
512 log_error("cannot find disconnected port %"PRIu64" of client %"PRIu64"", port2_id, client2_id);
513 return;
516 canvas_remove_connection(
517 graph_canvas_ptr->canvas,
518 port1_ptr->canvas_port,
519 port2_ptr->canvas_port);
522 void
523 graph_canvas_destroy(
524 graph_canvas_handle graph_canvas)
526 if (graph_canvas_ptr->graph != NULL)
528 graph_canvas_detach(graph_canvas);
531 free(graph_canvas_ptr);
534 bool
535 graph_canvas_attach(
536 graph_canvas_handle graph_canvas,
537 graph_proxy_handle graph)
539 ASSERT(graph_canvas_ptr->graph == NULL);
541 if (!graph_proxy_attach(
542 graph,
543 graph_canvas,
544 clear,
545 client_appeared,
546 client_disappeared,
547 port_appeared,
548 port_disappeared,
549 ports_connected,
550 ports_disconnected))
552 return false;
555 graph_canvas_ptr->graph = graph;
557 return true;
560 void
561 graph_canvas_detach(
562 graph_canvas_handle graph_canvas)
564 ASSERT(graph_canvas_ptr->graph != NULL);
565 graph_proxy_detach(graph_canvas_ptr->graph, graph_canvas);
566 graph_canvas_ptr->graph = NULL;
569 canvas_handle
570 graph_canvas_get_canvas(
571 graph_canvas_handle graph_canvas)
573 return graph_canvas_ptr->canvas;