daemon: handle apps with same name in different vgraphs
[ladish.git] / daemon / graph.c
blob52f8c23ab8153c0a8639cdc1e556b34bc8fef54c
1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*
3 * LADI Session Handler (ladish)
5 * Copyright (C) 2008, 2009, 2010 Nedko Arnaudov <nedko@arnaudov.name>
6 * Copyright (C) 2008 Juuso Alasuutari
8 **************************************************************************
9 * This file contains implementation of the D-Bus patchbay interface helpers
10 **************************************************************************
12 * LADI Session Handler is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * LADI Session Handler is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with LADI Session Handler. If not, see <http://www.gnu.org/licenses/>
24 * or write to the Free Software Foundation, Inc.,
25 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
28 #include "common.h"
29 #include "graph.h"
30 #include "../dbus/error.h"
31 #include "../dbus_constants.h"
33 struct ladish_graph_port
35 struct list_head siblings_client;
36 struct list_head siblings_graph;
37 struct ladish_graph_client * client_ptr;
38 char * name;
39 uint32_t type;
40 uint32_t flags;
41 uint64_t id;
42 ladish_port_handle port;
43 bool hidden;
44 bool link;
45 uuid_t link_uuid_override;
48 struct ladish_graph_client
50 struct list_head siblings;
51 char * name;
52 uint64_t id;
53 ladish_client_handle client;
54 struct list_head ports;
55 bool hidden;
58 struct ladish_graph_connection
60 struct list_head siblings;
61 uint64_t id;
62 bool hidden;
63 struct ladish_graph_port * port1_ptr;
64 struct ladish_graph_port * port2_ptr;
65 ladish_dict_handle dict;
66 bool changing;
69 struct ladish_graph
71 char * opath;
72 ladish_dict_handle dict;
73 struct list_head clients;
74 struct list_head ports;
75 struct list_head connections;
76 uint64_t graph_version;
77 uint64_t next_client_id;
78 uint64_t next_port_id;
79 uint64_t next_connection_id;
80 bool persist;
82 void * context;
83 ladish_graph_connect_request_handler connect_handler;
84 ladish_graph_disconnect_request_handler disconnect_handler;
87 static struct ladish_graph_port * ladish_graph_find_port_by_id_internal(struct ladish_graph * graph_ptr, uint64_t port_id)
89 struct list_head * node_ptr;
90 struct ladish_graph_port * port_ptr;
92 list_for_each(node_ptr, &graph_ptr->ports)
94 port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph);
95 if (port_ptr->id == port_id)
97 return port_ptr;
101 return NULL;
104 static struct ladish_graph_port *
105 ladish_graph_find_port_by_uuid_internal(
106 struct ladish_graph * graph_ptr,
107 const uuid_t uuid,
108 bool use_link_override_uuids)
110 struct list_head * node_ptr;
111 struct ladish_graph_port * port_ptr;
112 uuid_t current_uuid;
113 /* char uuid1_str[37]; */
114 /* char uuid2_str[37]; */
116 /* log_info("searching by uuid for port in graph %s", ladish_graph_get_description((ladish_graph_handle)graph_ptr)); */
117 /* uuid_unparse(uuid, uuid1_str); */
119 list_for_each(node_ptr, &graph_ptr->ports)
121 port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph);
123 /* if (port_ptr->link) */
124 /* { */
125 /* uuid_unparse(port_ptr->link_uuid_override, uuid2_str); */
126 /* log_info("comparing link uuid %s with %s", uuid2_str, uuid1_str); */
127 /* } */
129 if (use_link_override_uuids && port_ptr->link && uuid_compare(port_ptr->link_uuid_override, uuid) == 0)
131 /* log_info("found port %p of client '%s'", port_ptr->port, port_ptr->client_ptr->name); */
132 return port_ptr;
135 ladish_port_get_uuid(port_ptr->port, current_uuid);
136 /* uuid_unparse(current_uuid, uuid2_str); */
137 /* log_info("comparing port uuid %s with %s", uuid2_str, uuid1_str); */
138 if (uuid_compare(current_uuid, uuid) == 0)
140 return port_ptr;
144 return NULL;
147 static struct ladish_graph_connection * ladish_graph_find_connection_by_id(struct ladish_graph * graph_ptr, uint64_t connection_id)
149 struct list_head * node_ptr;
150 struct ladish_graph_connection * connection_ptr;
152 list_for_each(node_ptr, &graph_ptr->connections)
154 connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
155 if (connection_ptr->id == connection_id)
157 return connection_ptr;
161 return NULL;
164 static
165 struct ladish_graph_connection *
166 ladish_graph_find_connection_by_ports(
167 struct ladish_graph * graph_ptr,
168 struct ladish_graph_port * port1_ptr,
169 struct ladish_graph_port * port2_ptr)
171 struct list_head * node_ptr;
172 struct ladish_graph_connection * connection_ptr;
174 list_for_each(node_ptr, &graph_ptr->connections)
176 connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
177 if ((connection_ptr->port1_ptr == port1_ptr && connection_ptr->port2_ptr == port2_ptr) ||
178 (connection_ptr->port1_ptr == port2_ptr && connection_ptr->port2_ptr == port1_ptr))
180 return connection_ptr;
184 return NULL;
187 #define graph_ptr ((struct ladish_graph *)call_ptr->iface_context)
189 static void get_all_ports(struct dbus_method_call * call_ptr)
191 DBusMessageIter iter, sub_iter;
193 call_ptr->reply = dbus_message_new_method_return(call_ptr->message);
194 if (call_ptr->reply == NULL)
196 goto fail;
199 dbus_message_iter_init_append(call_ptr->reply, &iter);
201 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub_iter))
203 goto fail_unref;
206 if (!dbus_message_iter_close_container(&iter, &sub_iter))
208 goto fail_unref;
211 return;
213 fail_unref:
214 dbus_message_unref(call_ptr->reply);
215 call_ptr->reply = NULL;
217 fail:
218 log_error("Ran out of memory trying to construct method return");
221 static void get_graph(struct dbus_method_call * call_ptr)
223 dbus_uint64_t known_version;
224 dbus_uint64_t current_version;
225 DBusMessageIter iter;
226 DBusMessageIter clients_array_iter;
227 DBusMessageIter connections_array_iter;
228 DBusMessageIter client_struct_iter;
229 struct list_head * client_node_ptr;
230 struct ladish_graph_client * client_ptr;
231 DBusMessageIter ports_array_iter;
232 struct list_head * port_node_ptr;
233 struct ladish_graph_port * port_ptr;
234 DBusMessageIter port_struct_iter;
235 struct list_head * connection_node_ptr;
236 struct ladish_graph_connection * connection_ptr;
237 DBusMessageIter connection_struct_iter;
239 //log_info("get_graph() called");
241 if (!dbus_message_get_args(call_ptr->message, &g_dbus_error, DBUS_TYPE_UINT64, &known_version, DBUS_TYPE_INVALID))
243 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, g_dbus_error.message);
244 dbus_error_free(&g_dbus_error);
245 return;
248 //log_info("Getting graph, known version is %" PRIu64, known_version);
250 call_ptr->reply = dbus_message_new_method_return(call_ptr->message);
251 if (call_ptr->reply == NULL)
253 log_error("Ran out of memory trying to construct method return");
254 goto exit;
257 dbus_message_iter_init_append(call_ptr->reply, &iter);
259 current_version = graph_ptr->graph_version;
260 if (known_version > current_version)
262 lash_dbus_error(
263 call_ptr,
264 LASH_DBUS_ERROR_INVALID_ARGS,
265 "known graph version %" PRIu64 " is newer than actual version %" PRIu64,
266 known_version,
267 current_version);
268 goto exit;
271 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT64, &current_version))
273 goto nomem;
276 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(tsa(tsuu))", &clients_array_iter))
278 goto nomem;
281 if (known_version < current_version)
283 list_for_each(client_node_ptr, &graph_ptr->clients)
285 client_ptr = list_entry(client_node_ptr, struct ladish_graph_client, siblings);
287 if (client_ptr->hidden)
289 continue;
292 if (!dbus_message_iter_open_container (&clients_array_iter, DBUS_TYPE_STRUCT, NULL, &client_struct_iter))
294 goto nomem_close_clients_array;
297 if (!dbus_message_iter_append_basic(&client_struct_iter, DBUS_TYPE_UINT64, &client_ptr->id))
299 goto nomem_close_client_struct;
302 log_info("client '%s' (%llu)", client_ptr->name, (unsigned long long)client_ptr->id);
303 if (!dbus_message_iter_append_basic(&client_struct_iter, DBUS_TYPE_STRING, &client_ptr->name))
305 goto nomem_close_client_struct;
308 if (!dbus_message_iter_open_container(&client_struct_iter, DBUS_TYPE_ARRAY, "(tsuu)", &ports_array_iter))
310 goto nomem_close_client_struct;
313 list_for_each(port_node_ptr, &client_ptr->ports)
315 port_ptr = list_entry(port_node_ptr, struct ladish_graph_port, siblings_client);
317 if (port_ptr->hidden)
319 continue;
322 if (!dbus_message_iter_open_container(&ports_array_iter, DBUS_TYPE_STRUCT, NULL, &port_struct_iter))
324 goto nomem_close_ports_array;
327 if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT64, &port_ptr->id))
329 goto nomem_close_port_struct;
332 if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_STRING, &port_ptr->name))
334 goto nomem_close_port_struct;
337 if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT32, &port_ptr->flags))
339 goto nomem_close_port_struct;
342 if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT32, &port_ptr->type))
344 goto nomem_close_port_struct;
347 if (!dbus_message_iter_close_container(&ports_array_iter, &port_struct_iter))
349 goto nomem_close_ports_array;
353 if (!dbus_message_iter_close_container(&client_struct_iter, &ports_array_iter))
355 goto nomem_close_client_struct;
358 if (!dbus_message_iter_close_container(&clients_array_iter, &client_struct_iter))
360 goto nomem_close_clients_array;
365 if (!dbus_message_iter_close_container(&iter, &clients_array_iter))
367 goto nomem;
370 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(tstststst)", &connections_array_iter))
372 goto nomem;
375 if (known_version < current_version)
377 list_for_each(connection_node_ptr, &graph_ptr->connections)
379 connection_ptr = list_entry(connection_node_ptr, struct ladish_graph_connection, siblings);
381 if (connection_ptr->hidden)
383 continue;
386 if (!dbus_message_iter_open_container(&connections_array_iter, DBUS_TYPE_STRUCT, NULL, &connection_struct_iter))
388 goto nomem_close_connections_array;
391 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port1_ptr->client_ptr->id))
393 goto nomem_close_connection_struct;
396 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port1_ptr->client_ptr->name))
398 goto nomem_close_connection_struct;
401 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port1_ptr->id))
403 goto nomem_close_connection_struct;
406 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port1_ptr->name))
408 goto nomem_close_connection_struct;
411 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port2_ptr->client_ptr->id))
413 goto nomem_close_connection_struct;
416 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port2_ptr->client_ptr->name))
418 goto nomem_close_connection_struct;
421 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port2_ptr->id))
423 goto nomem_close_connection_struct;
426 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port2_ptr->name))
428 goto nomem_close_connection_struct;
431 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->id))
433 goto nomem_close_connection_struct;
436 if (!dbus_message_iter_close_container(&connections_array_iter, &connection_struct_iter))
438 goto nomem_close_connections_array;
443 if (!dbus_message_iter_close_container(&iter, &connections_array_iter))
445 goto nomem;
448 return;
450 nomem_close_connection_struct:
451 dbus_message_iter_close_container(&connections_array_iter, &connection_struct_iter);
453 nomem_close_connections_array:
454 dbus_message_iter_close_container(&iter, &connections_array_iter);
455 goto nomem;
457 nomem_close_port_struct:
458 dbus_message_iter_close_container(&ports_array_iter, &port_struct_iter);
460 nomem_close_ports_array:
461 dbus_message_iter_close_container(&client_struct_iter, &ports_array_iter);
463 nomem_close_client_struct:
464 dbus_message_iter_close_container(&clients_array_iter, &client_struct_iter);
466 nomem_close_clients_array:
467 dbus_message_iter_close_container(&iter, &clients_array_iter);
469 nomem:
470 dbus_message_unref(call_ptr->reply);
471 call_ptr->reply = NULL;
472 log_error("Ran out of memory trying to construct method return");
474 exit:
475 return;
478 static void connect_ports_by_name(struct dbus_method_call * call_ptr)
480 log_info("connect_ports_by_name() called.");
481 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "connect by name is not implemented yet");
484 static void connect_ports_by_id(struct dbus_method_call * call_ptr)
486 dbus_uint64_t port1_id;
487 dbus_uint64_t port2_id;
488 struct ladish_graph_port * port1_ptr;
489 struct ladish_graph_port * port2_ptr;
491 if (!dbus_message_get_args(call_ptr->message, &g_dbus_error, DBUS_TYPE_UINT64, &port1_id, DBUS_TYPE_UINT64, &port2_id, DBUS_TYPE_INVALID))
493 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, g_dbus_error.message);
494 dbus_error_free(&g_dbus_error);
495 return;
498 log_info("connect_ports_by_id(%"PRIu64",%"PRIu64") called.", port1_id, port2_id);
500 if (graph_ptr->connect_handler == NULL)
502 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "connect requests on graph %s cannot be handlined", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
503 return;
506 port1_ptr = ladish_graph_find_port_by_id_internal(graph_ptr, port1_id);
507 if (port1_ptr == NULL)
509 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot connect unknown port with id %"PRIu64, port1_id);
510 return;
513 port2_ptr = ladish_graph_find_port_by_id_internal(graph_ptr, port2_id);
514 if (port2_ptr == NULL)
516 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot connect unknown port with id %"PRIu64, port2_id);
517 return;
520 log_info("connecting '%s':'%s' to '%s':'%s'", port1_ptr->client_ptr->name, port1_ptr->name, port2_ptr->client_ptr->name, port2_ptr->name);
522 if (graph_ptr->connect_handler(graph_ptr->context, (ladish_graph_handle)graph_ptr, port1_ptr->port, port2_ptr->port))
524 method_return_new_void(call_ptr);
526 else
528 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "connect failed");
532 static void disconnect_ports(struct dbus_method_call * call_ptr, struct ladish_graph_connection * connection_ptr)
534 log_info(
535 "disconnecting '%s':'%s' from '%s':'%s'",
536 connection_ptr->port1_ptr->client_ptr->name,
537 connection_ptr->port1_ptr->name,
538 connection_ptr->port2_ptr->client_ptr->name,
539 connection_ptr->port2_ptr->name);
541 connection_ptr->changing = true;
542 if (graph_ptr->disconnect_handler(graph_ptr->context, (ladish_graph_handle)graph_ptr, connection_ptr->id))
544 method_return_new_void(call_ptr);
546 else
548 connection_ptr->changing = false;
549 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "disconnect failed");
553 static void disconnect_ports_by_name(struct dbus_method_call * call_ptr)
555 log_info("disconnect_ports_by_name() called.");
556 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "disconnect by name is not implemented yet");
559 static void disconnect_ports_by_id(struct dbus_method_call * call_ptr)
561 dbus_uint64_t port1_id;
562 dbus_uint64_t port2_id;
563 struct ladish_graph_port * port1_ptr;
564 struct ladish_graph_port * port2_ptr;
565 struct ladish_graph_connection * connection_ptr;
567 if (!dbus_message_get_args(call_ptr->message, &g_dbus_error, DBUS_TYPE_UINT64, &port1_id, DBUS_TYPE_UINT64, &port2_id, DBUS_TYPE_INVALID))
569 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, g_dbus_error.message);
570 dbus_error_free(&g_dbus_error);
571 return;
574 log_info("disconnect_ports_by_id(%"PRIu64",%"PRIu64") called.", port1_id, port2_id);
576 if (graph_ptr->disconnect_handler == NULL)
578 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "disconnect requests on graph %s cannot be handlined", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
579 return;
582 port1_ptr = ladish_graph_find_port_by_id_internal(graph_ptr, port1_id);
583 if (port1_ptr == NULL)
585 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot disconnect unknown port with id %"PRIu64, port1_id);
586 return;
589 port2_ptr = ladish_graph_find_port_by_id_internal(graph_ptr, port2_id);
590 if (port2_ptr == NULL)
592 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot disconnect unknown port with id %"PRIu64, port2_id);
593 return;
596 connection_ptr = ladish_graph_find_connection_by_ports(graph_ptr, port1_ptr, port2_ptr);
597 if (connection_ptr == NULL)
599 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot disconnect not connected ports %"PRIu64" and %"PRIu64, port1_id, port2_id);
600 return;
603 disconnect_ports(call_ptr, connection_ptr);
606 static void disconnect_ports_by_connection_id(struct dbus_method_call * call_ptr)
608 dbus_uint64_t connection_id;
609 struct ladish_graph_connection * connection_ptr;
611 if (!dbus_message_get_args(call_ptr->message, &g_dbus_error, DBUS_TYPE_UINT64, &connection_id, DBUS_TYPE_INVALID))
613 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, g_dbus_error.message);
614 dbus_error_free(&g_dbus_error);
615 return;
618 log_info("disconnect_ports_by_connection_id(%"PRIu64") called.", connection_id);
620 connection_ptr = ladish_graph_find_connection_by_id(graph_ptr, connection_id);
621 if (connection_ptr == NULL)
623 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot find connection with id %"PRIu64, connection_id);
624 return;
627 disconnect_ports(call_ptr, connection_ptr);
630 static void get_client_pid(struct dbus_method_call * call_ptr)
632 int64_t pid = 0;
633 method_return_new_single(call_ptr, DBUS_TYPE_INT64, &pid);
636 #undef graph_ptr
638 bool ladish_graph_create(ladish_graph_handle * graph_handle_ptr, const char * opath)
640 struct ladish_graph * graph_ptr;
642 graph_ptr = malloc(sizeof(struct ladish_graph));
643 if (graph_ptr == NULL)
645 log_error("malloc() failed to allocate struct graph_implementator");
646 return false;
649 if (opath != NULL)
651 graph_ptr->opath = strdup(opath);
652 if (graph_ptr->opath == NULL)
654 log_error("strdup() failed for graph opath");
655 free(graph_ptr);
656 return false;
659 else
661 graph_ptr->opath = NULL;
664 if (!ladish_dict_create(&graph_ptr->dict))
666 log_error("ladish_dict_create() failed for graph");
667 if (graph_ptr->opath != NULL)
669 free(graph_ptr->opath);
671 free(graph_ptr);
672 return false;
675 INIT_LIST_HEAD(&graph_ptr->clients);
676 INIT_LIST_HEAD(&graph_ptr->ports);
677 INIT_LIST_HEAD(&graph_ptr->connections);
679 graph_ptr->graph_version = 1;
680 graph_ptr->next_client_id = 1;
681 graph_ptr->next_port_id = 1;
682 graph_ptr->next_connection_id = 1;
684 graph_ptr->context = NULL;
685 graph_ptr->connect_handler = NULL;
686 graph_ptr->disconnect_handler = NULL;
688 graph_ptr->persist = true;
690 *graph_handle_ptr = (ladish_graph_handle)graph_ptr;
691 return true;
694 static
695 struct ladish_graph_client *
696 ladish_graph_find_client(
697 struct ladish_graph * graph_ptr,
698 ladish_client_handle client)
700 struct list_head * node_ptr;
701 struct ladish_graph_client * client_ptr;
703 list_for_each(node_ptr, &graph_ptr->clients)
705 client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
706 if (client_ptr->client == client)
708 return client_ptr;
712 return NULL;
715 static
716 struct ladish_graph_port *
717 ladish_graph_find_port(
718 struct ladish_graph * graph_ptr,
719 ladish_port_handle port)
721 struct list_head * node_ptr;
722 struct ladish_graph_port * port_ptr;
724 //log_info("searching port %p", port);
726 list_for_each(node_ptr, &graph_ptr->ports)
728 port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph);
729 //log_info("checking port %s:%s, %p", port_ptr->client_ptr->name, port_ptr->name, port_ptr->port);
730 if (port_ptr->port == port)
732 return port_ptr;
736 return NULL;
739 static
740 struct ladish_graph_port *
741 ladish_graph_find_port_by_jack_id_internal(
742 struct ladish_graph * graph_ptr,
743 uint64_t port_id,
744 bool room,
745 bool studio)
747 struct list_head * node_ptr;
748 struct ladish_graph_port * port_ptr;
750 ASSERT(room || studio);
752 list_for_each(node_ptr, &graph_ptr->ports)
754 port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph);
755 //log_info("checking jack port id of port %s:%s, %p", port_ptr->client_ptr->name, port_ptr->name, port_ptr->port);
756 if ((studio && ladish_port_get_jack_id(port_ptr->port) == port_id) ||
757 (room && port_ptr->link && ladish_port_get_jack_id_room(port_ptr->port) == port_id))
759 //log_info("found");
760 return port_ptr;
764 return NULL;
767 #if 0
768 static
769 struct ladish_graph_port *
770 ladish_graph_find_client_port(
771 struct ladish_graph * graph_ptr,
772 struct ladish_graph_client * client_ptr,
773 ladish_port_handle port)
775 struct list_head * node_ptr;
776 struct ladish_graph_port * port_ptr;
778 list_for_each(node_ptr, &client_ptr->ports)
780 port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_client);
781 if (port_ptr->port == port)
783 return port_ptr;
787 return NULL;
789 #endif
791 static void ladish_graph_hide_connection_internal(struct ladish_graph * graph_ptr, struct ladish_graph_connection * connection_ptr)
793 ASSERT(!connection_ptr->hidden);
794 connection_ptr->hidden = true;
795 graph_ptr->graph_version++;
797 if (graph_ptr->opath != NULL)
799 dbus_signal_emit(
800 g_dbus_connection,
801 graph_ptr->opath,
802 JACKDBUS_IFACE_PATCHBAY,
803 "PortsDisconnected",
804 "ttstststst",
805 &graph_ptr->graph_version,
806 &connection_ptr->port1_ptr->client_ptr->id,
807 &connection_ptr->port1_ptr->client_ptr->name,
808 &connection_ptr->port1_ptr->id,
809 &connection_ptr->port1_ptr->name,
810 &connection_ptr->port2_ptr->client_ptr->id,
811 &connection_ptr->port2_ptr->client_ptr->name,
812 &connection_ptr->port2_ptr->id,
813 &connection_ptr->port2_ptr->name,
814 &connection_ptr->id);
818 static void ladish_graph_show_port_internal(struct ladish_graph * graph_ptr, struct ladish_graph_port * port_ptr)
820 if (port_ptr->client_ptr->hidden)
822 port_ptr->client_ptr->hidden = false;
823 graph_ptr->graph_version++;
824 if (graph_ptr->opath != NULL)
826 dbus_signal_emit(
827 g_dbus_connection,
828 graph_ptr->opath,
829 JACKDBUS_IFACE_PATCHBAY,
830 "ClientAppeared",
831 "tts",
832 &graph_ptr->graph_version,
833 &port_ptr->client_ptr->id,
834 &port_ptr->client_ptr->name);
838 ASSERT(port_ptr->hidden);
839 port_ptr->hidden = false;
840 graph_ptr->graph_version++;
841 if (graph_ptr->opath != NULL)
843 dbus_signal_emit(
844 g_dbus_connection,
845 graph_ptr->opath,
846 JACKDBUS_IFACE_PATCHBAY,
847 "PortAppeared",
848 "ttstsuu",
849 &graph_ptr->graph_version,
850 &port_ptr->client_ptr->id,
851 &port_ptr->client_ptr->name,
852 &port_ptr->id,
853 &port_ptr->name,
854 &port_ptr->flags,
855 &port_ptr->type);
857 ladish_try_connect_hidden_connections((ladish_graph_handle)graph_ptr);
861 static void ladish_graph_hide_port_internal(struct ladish_graph * graph_ptr, struct ladish_graph_port * port_ptr)
863 ASSERT(!port_ptr->hidden);
864 port_ptr->hidden = true;
865 graph_ptr->graph_version++;
867 if (graph_ptr->opath != NULL)
869 dbus_signal_emit(
870 g_dbus_connection,
871 graph_ptr->opath,
872 JACKDBUS_IFACE_PATCHBAY,
873 "PortDisappeared",
874 "ttsts",
875 &graph_ptr->graph_version,
876 &port_ptr->client_ptr->id,
877 &port_ptr->client_ptr->name,
878 &port_ptr->id,
879 &port_ptr->name);
883 static void ladish_graph_hide_client_internal(struct ladish_graph * graph_ptr, struct ladish_graph_client * client_ptr)
885 ASSERT(!client_ptr->hidden);
886 client_ptr->hidden = true;
887 graph_ptr->graph_version++;
889 if (graph_ptr->opath != NULL)
891 dbus_signal_emit(
892 g_dbus_connection,
893 graph_ptr->opath,
894 JACKDBUS_IFACE_PATCHBAY,
895 "ClientDisappeared",
896 "tts",
897 &graph_ptr->graph_version,
898 &client_ptr->id,
899 &client_ptr->name);
903 static void ladish_hide_connections(struct ladish_graph * graph_ptr, struct ladish_graph_port * port_ptr)
905 struct list_head * node_ptr;
906 struct ladish_graph_connection * connection_ptr;
908 log_info("hidding connections of port %"PRIu64, port_ptr->id);
910 ASSERT(graph_ptr->opath != NULL);
912 list_for_each(node_ptr, &graph_ptr->connections)
914 connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
915 if (!connection_ptr->hidden && (connection_ptr->port1_ptr == port_ptr || connection_ptr->port2_ptr == port_ptr))
917 log_info("hidding connection between ports %"PRIu64" and %"PRIu64, connection_ptr->port1_ptr->id, connection_ptr->port2_ptr->id);
918 ladish_graph_hide_connection_internal(graph_ptr, connection_ptr);
923 static void ladish_graph_remove_connection_internal(struct ladish_graph * graph_ptr, struct ladish_graph_connection * connection_ptr)
925 list_del(&connection_ptr->siblings);
926 graph_ptr->graph_version++;
928 if (!connection_ptr->hidden && graph_ptr->opath != NULL)
930 dbus_signal_emit(
931 g_dbus_connection,
932 graph_ptr->opath,
933 JACKDBUS_IFACE_PATCHBAY,
934 "PortsDisconnected",
935 "ttstststst",
936 &graph_ptr->graph_version,
937 &connection_ptr->port1_ptr->client_ptr->id,
938 &connection_ptr->port1_ptr->client_ptr->name,
939 &connection_ptr->port1_ptr->id,
940 &connection_ptr->port1_ptr->name,
941 &connection_ptr->port2_ptr->client_ptr->id,
942 &connection_ptr->port2_ptr->client_ptr->name,
943 &connection_ptr->port2_ptr->id,
944 &connection_ptr->port2_ptr->name,
945 &connection_ptr->id);
948 ladish_dict_destroy(connection_ptr->dict);
949 free(connection_ptr);
952 static void ladish_graph_remove_port_connections(struct ladish_graph * graph_ptr, struct ladish_graph_port * port_ptr)
954 struct list_head * node_ptr;
955 struct list_head * temp_node_ptr;
956 struct ladish_graph_connection * connection_ptr;
958 list_for_each_safe(node_ptr, temp_node_ptr, &graph_ptr->connections)
960 connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
961 if (connection_ptr->port1_ptr == port_ptr || connection_ptr->port2_ptr == port_ptr)
963 log_info("removing connection between ports %"PRIu64" and %"PRIu64, connection_ptr->port1_ptr->id, connection_ptr->port2_ptr->id);
964 ladish_graph_remove_connection_internal(graph_ptr, connection_ptr);
969 static
970 void
971 ladish_graph_remove_port_internal(
972 struct ladish_graph * graph_ptr,
973 struct ladish_graph_client * client_ptr,
974 struct ladish_graph_port * port_ptr)
976 ladish_graph_remove_port_connections(graph_ptr, port_ptr);
978 ladish_port_del_ref(port_ptr->port);
980 list_del(&port_ptr->siblings_client);
981 list_del(&port_ptr->siblings_graph);
983 log_info("removing port '%s':'%s' (%"PRIu64":%"PRIu64") from graph %s", client_ptr->name, port_ptr->name, client_ptr->id, port_ptr->id, graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
984 if (graph_ptr->opath != NULL && !port_ptr->hidden)
986 dbus_signal_emit(
987 g_dbus_connection,
988 graph_ptr->opath,
989 JACKDBUS_IFACE_PATCHBAY,
990 "PortDisappeared",
991 "ttsts",
992 &graph_ptr->graph_version,
993 &client_ptr->id,
994 &client_ptr->name,
995 &port_ptr->id,
996 &port_ptr->name);
999 free(port_ptr->name);
1000 free(port_ptr);
1003 static
1004 void
1005 ladish_graph_remove_client_internal(
1006 struct ladish_graph * graph_ptr,
1007 struct ladish_graph_client * client_ptr,
1008 bool destroy_client,
1009 ladish_graph_simple_port_callback port_callback)
1011 struct ladish_graph_port * port_ptr;
1013 while (!list_empty(&client_ptr->ports))
1015 port_ptr = list_entry(client_ptr->ports.next, struct ladish_graph_port, siblings_client);
1016 if (port_callback != NULL)
1018 port_callback(port_ptr->port);
1020 ladish_graph_remove_port_internal(graph_ptr, client_ptr, port_ptr);
1023 graph_ptr->graph_version++;
1024 list_del(&client_ptr->siblings);
1025 log_info("removing client '%s' (%"PRIu64") from graph %s", client_ptr->name, client_ptr->id, graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
1026 if (graph_ptr->opath != NULL && !client_ptr->hidden)
1028 dbus_signal_emit(
1029 g_dbus_connection,
1030 graph_ptr->opath,
1031 JACKDBUS_IFACE_PATCHBAY,
1032 "ClientDisappeared",
1033 "tts",
1034 &graph_ptr->graph_version,
1035 &client_ptr->id,
1036 &client_ptr->name);
1039 free(client_ptr->name);
1041 if (destroy_client)
1043 ladish_client_destroy(client_ptr->client);
1046 free(client_ptr);
1049 bool ladish_graph_client_looks_empty_internal(struct ladish_graph * graph_ptr, struct ladish_graph_client * client_ptr)
1051 struct list_head * node_ptr;
1052 struct ladish_graph_port * port_ptr;
1054 list_for_each(node_ptr, &client_ptr->ports)
1056 port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_client);
1057 if (!port_ptr->hidden)
1059 //log_info("port '%s' is visible, client '%s' does not look empty", port_ptr->name, client_ptr->name);
1060 return false;
1062 else
1064 //log_info("port '%s' is invisible", port_ptr->name);
1068 //log_info("client '%s' looks empty in graph %s", client_ptr->name, graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
1069 return true;
1072 #define graph_ptr ((struct ladish_graph *)graph_handle)
1074 void ladish_graph_destroy(ladish_graph_handle graph_handle)
1076 ladish_graph_clear(graph_handle, NULL);
1077 ladish_dict_destroy(graph_ptr->dict);
1078 if (graph_ptr->opath != NULL)
1080 free(graph_ptr->opath);
1082 free(graph_ptr);
1085 const char * ladish_graph_get_opath(ladish_graph_handle graph_handle)
1087 return graph_ptr->opath;
1090 const char * ladish_graph_get_description(ladish_graph_handle graph_handle)
1092 return graph_ptr->opath != NULL ? graph_ptr->opath : "JACK";
1095 void
1096 ladish_graph_set_connection_handlers(
1097 ladish_graph_handle graph_handle,
1098 void * graph_context,
1099 ladish_graph_connect_request_handler connect_handler,
1100 ladish_graph_disconnect_request_handler disconnect_handler)
1102 log_info("setting connection handlers for graph '%s'", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
1103 graph_ptr->context = graph_context;
1104 graph_ptr->connect_handler = connect_handler;
1105 graph_ptr->disconnect_handler = disconnect_handler;
1108 void ladish_graph_clear(ladish_graph_handle graph_handle, ladish_graph_simple_port_callback port_callback)
1110 struct ladish_graph_client * client_ptr;
1111 struct ladish_graph_connection * connection_ptr;
1113 log_info("ladish_graph_clear() called for graph '%s'", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
1115 while (!list_empty(&graph_ptr->connections))
1117 connection_ptr = list_entry(graph_ptr->connections.next, struct ladish_graph_connection, siblings);
1118 ladish_graph_remove_connection_internal(graph_ptr, connection_ptr);
1121 while (!list_empty(&graph_ptr->clients))
1123 client_ptr = list_entry(graph_ptr->clients.next, struct ladish_graph_client, siblings);
1124 ladish_graph_remove_client_internal(graph_ptr, client_ptr, true, port_callback);
1128 void * ladish_graph_get_dbus_context(ladish_graph_handle graph_handle)
1130 return graph_handle;
1133 ladish_dict_handle ladish_graph_get_dict(ladish_graph_handle graph_handle)
1135 return graph_ptr->dict;
1138 void ladish_graph_show_connection(ladish_graph_handle graph_handle, uint64_t connection_id)
1140 struct ladish_graph_connection * connection_ptr;
1142 log_info("ladish_graph_show_connection() called.");
1144 connection_ptr = ladish_graph_find_connection_by_id(graph_ptr, connection_id);
1145 if (connection_ptr == NULL)
1147 ASSERT_NO_PASS;
1148 return;
1151 ASSERT(graph_ptr->opath != NULL);
1152 ASSERT(connection_ptr->hidden);
1153 connection_ptr->hidden = false;
1154 connection_ptr->changing = false;
1155 graph_ptr->graph_version++;
1157 dbus_signal_emit(
1158 g_dbus_connection,
1159 graph_ptr->opath,
1160 JACKDBUS_IFACE_PATCHBAY,
1161 "PortsConnected",
1162 "ttstststst",
1163 &graph_ptr->graph_version,
1164 &connection_ptr->port1_ptr->client_ptr->id,
1165 &connection_ptr->port1_ptr->client_ptr->name,
1166 &connection_ptr->port1_ptr->id,
1167 &connection_ptr->port1_ptr->name,
1168 &connection_ptr->port2_ptr->client_ptr->id,
1169 &connection_ptr->port2_ptr->client_ptr->name,
1170 &connection_ptr->port2_ptr->id,
1171 &connection_ptr->port2_ptr->name,
1172 &connection_ptr->id);
1175 void ladish_graph_show_port(ladish_graph_handle graph_handle, ladish_port_handle port_handle)
1177 struct ladish_graph_port * port_ptr;
1179 //log_info("ladish_graph_show_port() called.");
1181 port_ptr = ladish_graph_find_port(graph_ptr, port_handle);
1182 if (port_ptr == NULL)
1184 ASSERT_NO_PASS;
1185 return;
1188 //log_info("port '%s' is %s", port_ptr->name, port_ptr->hidden ? "invisible" : "visible");
1190 ladish_graph_show_port_internal(graph_ptr, port_ptr);
1193 void ladish_graph_hide_port(ladish_graph_handle graph_handle, ladish_port_handle port_handle)
1195 struct ladish_graph_port * port_ptr;
1197 log_info("ladish_graph_hide_port() called.");
1199 port_ptr = ladish_graph_find_port(graph_ptr, port_handle);
1200 if (port_ptr == NULL)
1202 ASSERT_NO_PASS;
1203 return;
1206 log_info("Hidding port %"PRIu64, port_ptr->id);
1208 ASSERT(!port_ptr->hidden);
1210 if (graph_ptr->opath != NULL)
1212 ladish_hide_connections(graph_ptr, port_ptr);
1215 ladish_graph_hide_port_internal(graph_ptr, port_ptr);
1218 void ladish_graph_hide_client(ladish_graph_handle graph_handle, ladish_client_handle client_handle)
1220 struct ladish_graph_client * client_ptr;
1222 log_info("ladish_graph_hide_client() called.");
1224 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1225 if (client_ptr == NULL)
1227 ASSERT_NO_PASS;
1228 return;
1231 ladish_graph_hide_client_internal(graph_ptr, client_ptr);
1234 void ladish_graph_show_client(ladish_graph_handle graph_handle, ladish_client_handle client_handle)
1236 struct ladish_graph_client * client_ptr;
1238 log_info("ladish_graph_show_client() called.");
1240 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1241 if (client_ptr == NULL)
1243 ASSERT_NO_PASS;
1244 return;
1247 ASSERT(client_ptr->hidden);
1248 client_ptr->hidden = false;
1249 graph_ptr->graph_version++;
1251 if (graph_ptr->opath != NULL)
1253 dbus_signal_emit(
1254 g_dbus_connection,
1255 graph_ptr->opath,
1256 JACKDBUS_IFACE_PATCHBAY,
1257 "ClientAppeared",
1258 "tts",
1259 &graph_ptr->graph_version,
1260 &client_ptr->id,
1261 &client_ptr->name);
1265 void ladish_graph_adjust_port(ladish_graph_handle graph_handle, ladish_port_handle port_handle, uint32_t type, uint32_t flags)
1267 struct ladish_graph_port * port_ptr;
1269 //log_info("ladish_graph_adjust_port() called.");
1271 port_ptr = ladish_graph_find_port(graph_ptr, port_handle);
1272 if (port_ptr == NULL)
1274 ASSERT_NO_PASS;
1275 return;
1278 port_ptr->type = type;
1279 port_ptr->flags = flags;
1282 bool ladish_graph_add_client(ladish_graph_handle graph_handle, ladish_client_handle client_handle, const char * name, bool hidden)
1284 struct ladish_graph_client * client_ptr;
1286 log_info("adding client '%s' (%p) to graph %s", name, client_handle, graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
1288 client_ptr = malloc(sizeof(struct ladish_graph_client));
1289 if (client_ptr == NULL)
1291 log_error("malloc() failed for struct ladish_graph_client");
1292 return false;
1295 client_ptr->name = strdup(name);
1296 if (client_ptr->name == NULL)
1298 log_error("strdup() failed for graph client name");
1299 free(client_ptr);
1300 return false;
1303 client_ptr->id = graph_ptr->next_client_id++;
1304 client_ptr->client = client_handle;
1305 client_ptr->hidden = hidden;
1306 graph_ptr->graph_version++;
1308 INIT_LIST_HEAD(&client_ptr->ports);
1310 list_add_tail(&client_ptr->siblings, &graph_ptr->clients);
1312 if (!hidden && graph_ptr->opath != NULL)
1314 dbus_signal_emit(
1315 g_dbus_connection,
1316 graph_ptr->opath,
1317 JACKDBUS_IFACE_PATCHBAY,
1318 "ClientAppeared",
1319 "tts",
1320 &graph_ptr->graph_version,
1321 &client_ptr->id,
1322 &client_ptr->name);
1325 return true;
1328 void
1329 ladish_graph_remove_client(
1330 ladish_graph_handle graph_handle,
1331 ladish_client_handle client_handle)
1333 struct ladish_graph_client * client_ptr;
1335 log_info("ladish_graph_remove_client() called.");
1337 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1338 if (client_ptr != NULL)
1340 ladish_graph_remove_client_internal(graph_ptr, client_ptr, false, NULL);
1342 else
1344 ASSERT_NO_PASS;
1348 bool
1349 ladish_graph_add_port(
1350 ladish_graph_handle graph_handle,
1351 ladish_client_handle client_handle,
1352 ladish_port_handle port_handle,
1353 const char * name,
1354 uint32_t type,
1355 uint32_t flags,
1356 bool hidden)
1358 struct ladish_graph_client * client_ptr;
1359 struct ladish_graph_port * port_ptr;
1361 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1362 if (client_ptr == NULL)
1364 log_error("cannot find client to add port to. graph is %s", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
1365 ASSERT_NO_PASS;
1366 return false;
1369 log_info("adding port '%s' (%p) to client '%s' in graph %s", name, port_handle, client_ptr->name, graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
1371 port_ptr = malloc(sizeof(struct ladish_graph_port));
1372 if (port_ptr == NULL)
1374 log_error("malloc() failed for struct ladish_graph_port");
1375 return false;
1378 port_ptr->name = strdup(name);
1379 if (port_ptr->name == NULL)
1381 log_error("strdup() failed for graph port name");
1382 free(port_ptr);
1383 return false;
1386 port_ptr->type = type;
1387 port_ptr->flags = flags;
1389 port_ptr->id = graph_ptr->next_port_id++;
1390 port_ptr->port = port_handle;
1391 ladish_port_add_ref(port_ptr->port);
1392 port_ptr->hidden = true;
1394 port_ptr->link = ladish_port_is_link(port_handle);
1395 if (port_ptr->link)
1397 uuid_generate(port_ptr->link_uuid_override);
1400 port_ptr->client_ptr = client_ptr;
1401 list_add_tail(&port_ptr->siblings_client, &client_ptr->ports);
1402 list_add_tail(&port_ptr->siblings_graph, &graph_ptr->ports);
1404 if (!hidden)
1406 ladish_graph_show_port_internal(graph_ptr, port_ptr);
1409 return true;
1412 uint64_t
1413 ladish_graph_add_connection(
1414 ladish_graph_handle graph_handle,
1415 ladish_port_handle port1_handle,
1416 ladish_port_handle port2_handle,
1417 bool hidden)
1419 struct ladish_graph_port * port1_ptr;
1420 struct ladish_graph_port * port2_ptr;
1421 struct ladish_graph_connection * connection_ptr;
1423 port1_ptr = ladish_graph_find_port(graph_ptr, port1_handle);
1424 ASSERT(port1_ptr != NULL);
1425 port2_ptr = ladish_graph_find_port(graph_ptr, port2_handle);
1426 ASSERT(port2_ptr != NULL);
1428 connection_ptr = malloc(sizeof(struct ladish_graph_connection));
1429 if (connection_ptr == NULL)
1431 log_error("malloc() failed for struct ladish_graph_connection");
1432 return 0;
1435 if (!ladish_dict_create(&connection_ptr->dict))
1437 log_error("ladish_dict_create() failed for connection");
1438 free(connection_ptr);
1439 return 0;
1442 connection_ptr->id = graph_ptr->next_connection_id++;
1443 connection_ptr->port1_ptr = port1_ptr;
1444 connection_ptr->port2_ptr = port2_ptr;
1445 connection_ptr->hidden = hidden;
1446 connection_ptr->changing = false;
1447 graph_ptr->graph_version++;
1449 list_add_tail(&connection_ptr->siblings, &graph_ptr->connections);
1451 /* log_info( */
1452 /* "new connection %"PRIu64" between '%s':'%s' and '%s':'%s'", */
1453 /* connection_ptr->id, */
1454 /* port1_ptr->client_ptr->name, */
1455 /* port1_ptr->name, */
1456 /* port2_ptr->client_ptr->name, */
1457 /* port2_ptr->name); */
1459 if (!hidden && graph_ptr->opath != NULL)
1461 dbus_signal_emit(
1462 g_dbus_connection,
1463 graph_ptr->opath,
1464 JACKDBUS_IFACE_PATCHBAY,
1465 "PortsConnected",
1466 "ttstststst",
1467 &graph_ptr->graph_version,
1468 &port1_ptr->client_ptr->id,
1469 &port1_ptr->client_ptr->name,
1470 &port1_ptr->id,
1471 &port1_ptr->name,
1472 &port2_ptr->client_ptr->id,
1473 &port2_ptr->client_ptr->name,
1474 &port2_ptr->id,
1475 &port2_ptr->name,
1476 &connection_ptr->id);
1479 return connection_ptr->id;
1482 void
1483 ladish_graph_remove_connection(
1484 ladish_graph_handle graph_handle,
1485 uint64_t connection_id,
1486 bool force)
1488 struct ladish_graph_connection * connection_ptr;
1490 connection_ptr = ladish_graph_find_connection_by_id(graph_ptr, connection_id);
1491 if (connection_ptr == NULL)
1493 ASSERT_NO_PASS;
1494 return;
1497 if (force || connection_ptr->changing || !graph_ptr->persist)
1499 /* log_info( */
1500 /* "removing connection '%s':'%s' - '%s':'%s'", */
1501 /* connection_ptr->port1_ptr->client_ptr->name, */
1502 /* connection_ptr->port1_ptr->name, */
1503 /* connection_ptr->port2_ptr->client_ptr->name, */
1504 /* connection_ptr->port2_ptr->name); */
1506 ladish_graph_remove_connection_internal(graph_ptr, connection_ptr);
1508 else
1510 /* log_info( */
1511 /* "hiding connection '%s':'%s' - '%s':'%s'", */
1512 /* connection_ptr->port1_ptr->client_ptr->name, */
1513 /* connection_ptr->port1_ptr->name, */
1514 /* connection_ptr->port2_ptr->client_ptr->name, */
1515 /* connection_ptr->port2_ptr->name); */
1517 ladish_graph_hide_connection_internal(graph_ptr, connection_ptr);
1521 bool
1522 ladish_graph_get_connection_ports(
1523 ladish_graph_handle graph_handle,
1524 uint64_t connection_id,
1525 ladish_port_handle * port1_handle_ptr,
1526 ladish_port_handle * port2_handle_ptr)
1528 struct ladish_graph_connection * connection_ptr;
1530 connection_ptr = ladish_graph_find_connection_by_id(graph_ptr, connection_id);
1531 if (connection_ptr == NULL)
1533 return false;
1536 *port1_handle_ptr = connection_ptr->port1_ptr->port;
1537 *port2_handle_ptr = connection_ptr->port2_ptr->port;
1539 return true;
1542 ladish_dict_handle ladish_graph_get_connection_dict(ladish_graph_handle graph_handle, uint64_t connection_id)
1544 struct ladish_graph_connection * connection_ptr;
1546 connection_ptr = ladish_graph_find_connection_by_id(graph_ptr, connection_id);
1547 if (connection_ptr == NULL)
1549 return NULL;
1552 return connection_ptr->dict;
1555 bool
1556 ladish_graph_find_connection(
1557 ladish_graph_handle graph_handle,
1558 ladish_port_handle port1_handle,
1559 ladish_port_handle port2_handle,
1560 uint64_t * connection_id_ptr)
1562 struct ladish_graph_port * port1_ptr;
1563 struct ladish_graph_port * port2_ptr;
1564 struct ladish_graph_connection * connection_ptr;
1566 port1_ptr = ladish_graph_find_port(graph_ptr, port1_handle);
1567 if (port1_ptr == NULL)
1569 return false;
1572 port2_ptr = ladish_graph_find_port(graph_ptr, port2_handle);
1573 if (port1_ptr == NULL)
1575 return false;
1578 connection_ptr = ladish_graph_find_connection_by_ports(graph_ptr, port1_ptr, port2_ptr);
1579 if (connection_ptr == NULL)
1581 return false;
1584 *connection_id_ptr = connection_ptr->id;
1586 return true;
1589 ladish_client_handle ladish_graph_find_client_by_name(ladish_graph_handle graph_handle, const char * name, bool appless)
1591 struct list_head * node_ptr;
1592 struct ladish_graph_client * client_ptr;
1594 list_for_each(node_ptr, &graph_ptr->clients)
1596 client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
1597 if (strcmp(client_ptr->name, name) == 0 &&
1598 (!appless || !ladish_client_has_app(client_ptr->client))) /* if appless is true, then an appless client is being searched */
1600 return client_ptr->client;
1604 return NULL;
1607 ladish_client_handle ladish_graph_find_client_by_app(ladish_graph_handle graph_handle, const uuid_t app_uuid)
1609 struct list_head * node_ptr;
1610 struct ladish_graph_client * client_ptr;
1611 uuid_t current_uuid;
1613 list_for_each(node_ptr, &graph_ptr->clients)
1615 client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
1616 ladish_client_get_app(client_ptr->client, current_uuid);
1617 if (uuid_compare(current_uuid, app_uuid) == 0)
1619 return client_ptr->client;
1623 return NULL;
1626 ladish_port_handle ladish_graph_find_port_by_name(ladish_graph_handle graph_handle, ladish_client_handle client_handle, const char * name)
1628 struct ladish_graph_client * client_ptr;
1629 struct list_head * node_ptr;
1630 struct ladish_graph_port * port_ptr;
1632 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1633 if (client_ptr != NULL)
1635 list_for_each(node_ptr, &client_ptr->ports)
1637 port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_client);
1638 if (strcmp(port_ptr->name, name) == 0)
1640 return port_ptr->port;
1644 else
1646 ASSERT_NO_PASS;
1649 return NULL;
1652 ladish_client_handle ladish_graph_find_client_by_uuid(ladish_graph_handle graph_handle, const uuid_t uuid)
1654 struct list_head * node_ptr;
1655 struct ladish_graph_client * client_ptr;
1656 uuid_t current_uuid;
1658 list_for_each(node_ptr, &graph_ptr->clients)
1660 client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
1661 ladish_client_get_uuid(client_ptr->client, current_uuid);
1662 if (uuid_compare(current_uuid, uuid) == 0)
1664 return client_ptr->client;
1668 return NULL;
1671 ladish_port_handle ladish_graph_find_port_by_uuid(ladish_graph_handle graph_handle, const uuid_t uuid, bool use_link_override_uuids)
1673 struct ladish_graph_port * port_ptr;
1675 port_ptr = ladish_graph_find_port_by_uuid_internal(graph_ptr, uuid, use_link_override_uuids);
1676 if (port_ptr != NULL)
1678 return port_ptr->port;
1681 return NULL;
1684 ladish_client_handle ladish_graph_get_port_client(ladish_graph_handle graph_handle, ladish_port_handle port_handle)
1686 struct ladish_graph_port * port_ptr;
1688 port_ptr = ladish_graph_find_port(graph_ptr, port_handle);
1689 if (port_ptr == NULL)
1691 return NULL;
1694 return port_ptr->client_ptr->client;
1697 bool ladish_graph_is_port_present(ladish_graph_handle graph_handle, ladish_port_handle port_handle)
1699 return ladish_graph_find_port(graph_ptr, port_handle) != NULL;
1702 ladish_client_handle ladish_graph_find_client_by_id(ladish_graph_handle graph_handle, uint64_t client_id)
1704 struct list_head * node_ptr;
1705 struct ladish_graph_client * client_ptr;
1707 list_for_each(node_ptr, &graph_ptr->clients)
1709 client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
1710 if (client_ptr->id == client_id)
1712 return client_ptr->client;
1716 return NULL;
1719 ladish_port_handle ladish_graph_find_port_by_id(ladish_graph_handle graph_handle, uint64_t port_id)
1721 struct ladish_graph_port * port_ptr;
1723 port_ptr = ladish_graph_find_port_by_id_internal(graph_ptr, port_id);
1724 if (port_ptr == NULL)
1726 return NULL;
1729 return port_ptr->port;
1732 ladish_client_handle ladish_graph_find_client_by_jack_id(ladish_graph_handle graph_handle, uint64_t client_id)
1734 struct list_head * node_ptr;
1735 struct ladish_graph_client * client_ptr;
1737 list_for_each(node_ptr, &graph_ptr->clients)
1739 client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
1740 if (ladish_client_get_jack_id(client_ptr->client) == client_id)
1742 return client_ptr->client;
1746 return NULL;
1749 ladish_port_handle ladish_graph_find_port_by_jack_id(ladish_graph_handle graph_handle, uint64_t port_id, bool room, bool studio)
1751 struct ladish_graph_port * port_ptr;
1753 port_ptr = ladish_graph_find_port_by_jack_id_internal(graph_ptr, port_id, room, studio);
1754 if (port_ptr == NULL)
1756 return NULL;
1759 return port_ptr->port;
1762 ladish_client_handle
1763 ladish_graph_remove_port(
1764 ladish_graph_handle graph_handle,
1765 ladish_port_handle port)
1767 struct ladish_graph_port * port_ptr;
1768 ladish_client_handle client;
1770 port_ptr = ladish_graph_find_port(graph_ptr, port);
1771 if (port_ptr == NULL)
1773 return NULL;
1776 client = port_ptr->client_ptr->client;
1777 ladish_graph_remove_port_internal(graph_ptr, port_ptr->client_ptr, port_ptr);
1778 return client;
1781 ladish_client_handle
1782 ladish_graph_remove_port_by_jack_id(
1783 ladish_graph_handle graph_handle,
1784 uint64_t jack_port_id,
1785 bool room,
1786 bool studio)
1788 struct ladish_graph_port * port_ptr;
1789 ladish_client_handle client;
1791 port_ptr = ladish_graph_find_port_by_jack_id_internal(graph_ptr, jack_port_id, room, studio);
1792 if (port_ptr == NULL)
1794 return NULL;
1797 client = port_ptr->client_ptr->client;
1798 ladish_graph_remove_port_internal(graph_ptr, port_ptr->client_ptr, port_ptr);
1799 return client;
1802 bool
1803 ladish_graph_rename_client(
1804 ladish_graph_handle graph_handle,
1805 ladish_client_handle client_handle,
1806 const char * new_client_name)
1808 char * name;
1809 struct ladish_graph_client * client_ptr;
1810 char * old_name;
1812 name = strdup(new_client_name);
1813 if (name == NULL)
1815 log_error("strdup('%s') failed.", new_client_name);
1816 return false;
1819 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1820 if (client_ptr == NULL)
1822 free(name);
1823 ASSERT_NO_PASS;
1824 return false;
1827 old_name = client_ptr->name;
1828 client_ptr->name = name;
1830 graph_ptr->graph_version++;
1832 if (!client_ptr->hidden && graph_ptr->opath != NULL)
1834 dbus_signal_emit(
1835 g_dbus_connection,
1836 graph_ptr->opath,
1837 JACKDBUS_IFACE_PATCHBAY,
1838 "ClientRenamed",
1839 "ttss",
1840 &graph_ptr->graph_version,
1841 &client_ptr->id,
1842 &old_name,
1843 &client_ptr->name);
1846 free(old_name);
1848 return true;
1851 bool
1852 ladish_graph_rename_port(
1853 ladish_graph_handle graph_handle,
1854 ladish_port_handle port_handle,
1855 const char * new_port_name)
1857 char * name;
1858 struct ladish_graph_port * port_ptr;
1859 char * old_name;
1861 name = strdup(new_port_name);
1862 if (name == NULL)
1864 log_error("strdup('%s') failed.", new_port_name);
1865 return false;
1868 port_ptr = ladish_graph_find_port(graph_ptr, port_handle);
1869 if (port_ptr == NULL)
1871 ASSERT_NO_PASS;
1872 free(name);
1873 return false;
1876 old_name = port_ptr->name;
1877 port_ptr->name = name;
1879 graph_ptr->graph_version++;
1881 if (!port_ptr->hidden && graph_ptr->opath != NULL)
1883 dbus_signal_emit(
1884 g_dbus_connection,
1885 graph_ptr->opath,
1886 JACKDBUS_IFACE_PATCHBAY,
1887 "PortRenamed",
1888 "ttstss",
1889 &graph_ptr->graph_version,
1890 &port_ptr->client_ptr->id,
1891 &port_ptr->client_ptr->name,
1892 &port_ptr->id,
1893 &old_name,
1894 &port_ptr->name);
1897 free(old_name);
1899 return true;
1902 const char * ladish_graph_get_client_name(ladish_graph_handle graph_handle, ladish_client_handle client_handle)
1904 struct ladish_graph_client * client_ptr;
1906 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1907 if (client_ptr != NULL)
1909 return client_ptr->name;
1912 ASSERT_NO_PASS;
1913 return NULL;
1916 bool ladish_graph_client_is_empty(ladish_graph_handle graph_handle, ladish_client_handle client_handle)
1918 struct ladish_graph_client * client_ptr;
1920 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1921 if (client_ptr != NULL)
1923 return list_empty(&client_ptr->ports);
1926 ASSERT_NO_PASS;
1927 return true;
1930 bool ladish_graph_client_looks_empty(ladish_graph_handle graph_handle, ladish_client_handle client_handle)
1932 struct ladish_graph_client * client_ptr;
1934 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1935 if (client_ptr == NULL)
1937 ASSERT_NO_PASS;
1938 return true;
1941 if (ladish_graph_client_looks_empty_internal(graph_ptr, client_ptr))
1943 //log_info("client '%s' looks empty in graph %s", client_ptr->name, graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
1944 return true;
1947 return false;
1950 bool ladish_graph_client_is_hidden(ladish_graph_handle graph_handle, ladish_client_handle client_handle)
1952 struct ladish_graph_client * client_ptr;
1954 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1955 if (client_ptr != NULL)
1957 return client_ptr->hidden;
1960 ASSERT_NO_PASS;
1961 return true;
1964 void ladish_try_connect_hidden_connections(ladish_graph_handle graph_handle)
1966 struct list_head * node_ptr;
1967 struct ladish_graph_connection * connection_ptr;
1969 if (!list_empty(&graph_ptr->connections) && graph_ptr->connect_handler == NULL)
1971 ASSERT_NO_PASS;
1972 return;
1975 ASSERT(graph_ptr->opath != NULL);
1977 list_for_each(node_ptr, &graph_ptr->connections)
1979 connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
1980 log_debug(
1981 "checking connection (%s, %s) '%s':'%s' (%s) to '%s':'%s' (%s)",
1982 connection_ptr->hidden ? "hidden" : "visible",
1983 connection_ptr->changing ? "changing" : "not changing",
1984 connection_ptr->port1_ptr->client_ptr->name,
1985 connection_ptr->port1_ptr->name,
1986 connection_ptr->port1_ptr->hidden ? "hidden" : "visible",
1987 connection_ptr->port2_ptr->client_ptr->name,
1988 connection_ptr->port2_ptr->name,
1989 connection_ptr->port2_ptr->hidden ? "hidden" : "visible");
1990 if (connection_ptr->hidden &&
1991 !connection_ptr->changing &&
1992 !connection_ptr->port1_ptr->hidden &&
1993 !connection_ptr->port2_ptr->hidden)
1995 log_info(
1996 "auto connecting '%s':'%s' to '%s':'%s'",
1997 connection_ptr->port1_ptr->client_ptr->name,
1998 connection_ptr->port1_ptr->name,
1999 connection_ptr->port2_ptr->client_ptr->name,
2000 connection_ptr->port2_ptr->name);
2002 connection_ptr->changing = true;
2003 if (!graph_ptr->connect_handler(graph_ptr->context, graph_handle, connection_ptr->port1_ptr->port, connection_ptr->port2_ptr->port))
2005 connection_ptr->changing = false;
2006 log_error("auto connect failed.");
2012 void ladish_graph_hide_non_virtual(ladish_graph_handle graph_handle)
2014 struct list_head * node_ptr;
2015 struct ladish_graph_connection * connection_ptr;
2016 struct ladish_graph_port * port_ptr;
2017 struct ladish_graph_client * client_ptr;
2019 log_info("hiding everything in graph %s", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
2021 list_for_each(node_ptr, &graph_ptr->connections)
2023 connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
2024 if (!connection_ptr->hidden &&
2025 (ladish_client_get_jack_id(connection_ptr->port1_ptr->client_ptr->client) != 0 ||
2026 ladish_client_get_jack_id(connection_ptr->port2_ptr->client_ptr->client) != 0))
2028 log_debug("hidding connection between ports %"PRIu64" and %"PRIu64, connection_ptr->port1_ptr->id, connection_ptr->port2_ptr->id);
2029 ladish_graph_hide_connection_internal(graph_ptr, connection_ptr);
2033 list_for_each(node_ptr, &graph_ptr->ports)
2035 port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph);
2036 if (!port_ptr->hidden && ladish_client_get_jack_id(port_ptr->client_ptr->client) != 0)
2038 ladish_port_set_jack_id(port_ptr->port, 0);
2039 ladish_graph_hide_port_internal(graph_ptr, port_ptr);
2043 list_for_each(node_ptr, &graph_ptr->clients)
2045 client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
2046 if (!client_ptr->hidden && ladish_client_get_jack_id(client_ptr->client) != 0)
2048 ladish_client_set_jack_id(client_ptr->client, 0);
2049 ladish_graph_hide_client_internal(graph_ptr, client_ptr);
2054 void ladish_graph_get_port_uuid(ladish_graph_handle graph_handle, ladish_port_handle port, uuid_t uuid_ptr)
2056 struct ladish_graph_port * port_ptr;
2058 port_ptr = ladish_graph_find_port(graph_ptr, port);
2059 ASSERT(port_ptr != NULL);
2060 ASSERT(port_ptr->link);
2062 uuid_copy(uuid_ptr, port_ptr->link_uuid_override);
2065 const char * ladish_graph_get_port_name(ladish_graph_handle graph_handle, ladish_port_handle port)
2067 struct ladish_graph_port * port_ptr;
2069 port_ptr = ladish_graph_find_port(graph_ptr, port);
2070 ASSERT(port_ptr != NULL);
2072 return port_ptr->name;
2075 void ladish_graph_set_link_port_override_uuid(ladish_graph_handle graph_handle, const uuid_t uuid, const uuid_t override_uuid)
2077 struct ladish_graph_port * port_ptr;
2079 port_ptr = ladish_graph_find_port_by_uuid_internal(graph_ptr, uuid, false);
2080 ASSERT(ladish_port_is_link(port_ptr->port));
2081 uuid_copy(port_ptr->link_uuid_override, override_uuid);
2084 bool
2085 ladish_graph_iterate_nodes(
2086 ladish_graph_handle graph_handle,
2087 bool skip_hidden,
2088 void * vgraph_filter,
2089 void * callback_context,
2090 bool
2091 (* client_begin_callback)(
2092 void * context,
2093 ladish_graph_handle graph_handle,
2094 ladish_client_handle client_handle,
2095 const char * client_name,
2096 void ** client_iteration_context_ptr_ptr),
2097 bool
2098 (* port_callback)(
2099 void * context,
2100 ladish_graph_handle graph_handle,
2101 void * client_iteration_context_ptr,
2102 ladish_client_handle client_handle,
2103 const char * client_name,
2104 ladish_port_handle port_handle,
2105 const char * port_name,
2106 uint32_t port_type,
2107 uint32_t port_flags),
2108 bool
2109 (* client_end_callback)(
2110 void * context,
2111 ladish_graph_handle graph_handle,
2112 ladish_client_handle client_handle,
2113 const char * client_name,
2114 void * client_iteration_context_ptr))
2116 struct list_head * client_node_ptr;
2117 struct ladish_graph_client * client_ptr;
2118 void * client_context;
2119 struct list_head * port_node_ptr;
2120 struct ladish_graph_port * port_ptr;
2121 void * vgraph;
2123 list_for_each(client_node_ptr, &graph_ptr->clients)
2125 client_ptr = list_entry(client_node_ptr, struct ladish_graph_client, siblings);
2127 if (skip_hidden && client_ptr->hidden)
2129 continue;
2132 if (vgraph_filter != NULL)
2134 vgraph = ladish_client_get_vgraph(client_ptr->client);
2135 if (vgraph != vgraph_filter)
2137 continue;
2141 if (client_begin_callback != NULL)
2143 if (!client_begin_callback(callback_context, graph_handle, client_ptr->client, client_ptr->name, &client_context))
2145 return false;
2148 else
2150 client_context = NULL;
2153 if (port_callback == NULL)
2155 continue;
2158 list_for_each(port_node_ptr, &client_ptr->ports)
2160 port_ptr = list_entry(port_node_ptr, struct ladish_graph_port, siblings_client);
2162 if (skip_hidden && port_ptr->hidden)
2164 continue;
2167 if (!port_callback(
2168 callback_context,
2169 graph_handle,
2170 client_context,
2171 client_ptr->client,
2172 client_ptr->name,
2173 port_ptr->port,
2174 port_ptr->name,
2175 port_ptr->type,
2176 port_ptr->flags))
2178 return false;
2182 if (client_end_callback != NULL)
2184 if (!client_end_callback(callback_context, graph_handle, client_ptr->client, client_ptr->name, &client_context))
2186 return false;
2191 return true;
2194 bool
2195 ladish_graph_iterate_connections(
2196 ladish_graph_handle graph_handle,
2197 bool skip_hidden,
2198 void * callback_context,
2199 bool (* callback)(
2200 void * context,
2201 ladish_graph_handle graph_handle,
2202 ladish_port_handle port1_handle,
2203 ladish_port_handle port2_handle,
2204 ladish_dict_handle dict))
2206 struct list_head * node_ptr;
2207 struct ladish_graph_connection * connection_ptr;
2209 list_for_each(node_ptr, &graph_ptr->connections)
2211 connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
2213 if (skip_hidden && connection_ptr->hidden)
2215 continue;
2218 if (!callback(callback_context, graph_handle, connection_ptr->port1_ptr->port, connection_ptr->port2_ptr->port, connection_ptr->dict))
2220 return false;
2224 return true;
2227 static
2228 bool
2229 dump_dict_entry(
2230 void * context,
2231 const char * key,
2232 const char * value)
2234 log_info("%s key '%s' with value '%s'", (const char *)context, key, value);
2235 return true;
2238 static
2239 void
2240 dump_dict(
2241 const char * indent,
2242 ladish_dict_handle dict)
2244 if (ladish_dict_is_empty(dict))
2246 return;
2249 log_info("%sdict:", indent);
2250 ladish_dict_iterate(dict, (void *)indent, dump_dict_entry);
2253 void ladish_graph_dump(ladish_graph_handle graph_handle)
2255 struct list_head * client_node_ptr;
2256 struct ladish_graph_client * client_ptr;
2257 struct list_head * port_node_ptr;
2258 struct ladish_graph_port * port_ptr;
2259 struct list_head * connection_node_ptr;
2260 struct ladish_graph_connection * connection_ptr;
2261 uuid_t uuid;
2262 char uuid_str[37];
2264 log_info("graph %s", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
2265 log_info(" version %"PRIu64, graph_ptr->graph_version);
2266 log_info(" persist: %s", graph_ptr->persist ? "yes" : "no");
2267 dump_dict(" ", graph_ptr->dict);
2268 log_info(" clients:");
2269 list_for_each(client_node_ptr, &graph_ptr->clients)
2271 client_ptr = list_entry(client_node_ptr, struct ladish_graph_client, siblings);
2272 log_info(" %s client '%s', id=%"PRIu64", ptr=%p%", client_ptr->hidden ? "invisible" : "visible", client_ptr->name, client_ptr->id, client_ptr->client);
2273 ladish_client_get_uuid(client_ptr->client, uuid);
2274 uuid_unparse(uuid, uuid_str);
2275 log_info(" uuid=%s", uuid_str);
2276 if (ladish_client_get_interlink(client_ptr->client, uuid))
2278 uuid_unparse(uuid, uuid_str);
2279 log_info(" interlink=%s", uuid_str);
2281 else
2283 log_info(" no interlink");
2285 dump_dict(" ", ladish_client_get_dict(client_ptr->client));
2286 log_info(" ports:");
2287 list_for_each(port_node_ptr, &client_ptr->ports)
2289 port_ptr = list_entry(port_node_ptr, struct ladish_graph_port, siblings_client);
2291 ladish_port_get_uuid(port_ptr->port, uuid);
2292 uuid_unparse(uuid, uuid_str);
2294 log_info(" %s port '%s', uuid=%s, id=%"PRIu64", type=0x%"PRIX32", flags=0x%"PRIX32", ptr=%p", port_ptr->hidden ? "invisible" : "visible", port_ptr->name, uuid_str, port_ptr->id, port_ptr->type, port_ptr->flags, port_ptr->port);
2295 dump_dict(" ", ladish_port_get_dict(port_ptr->port));
2298 log_info(" connections:");
2299 list_for_each(connection_node_ptr, &graph_ptr->connections)
2301 connection_ptr = list_entry(connection_node_ptr, struct ladish_graph_connection, siblings);
2303 log_info(
2304 " %s connection '%s':'%s' - '%s':'%s'%s",
2305 connection_ptr->hidden ? "invisible" : "visible",
2306 connection_ptr->port1_ptr->client_ptr->name,
2307 connection_ptr->port1_ptr->name,
2308 connection_ptr->port2_ptr->client_ptr->name,
2309 connection_ptr->port2_ptr->name,
2310 connection_ptr->changing ? " [changing]" : "");
2311 dump_dict(" ", connection_ptr->dict);
2315 void ladish_graph_clear_persist(ladish_graph_handle graph_handle)
2317 log_info("Clearing persist flag for graph", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
2318 graph_ptr->persist = false;
2321 void ladish_graph_set_persist(ladish_graph_handle graph_handle)
2323 log_info("Setting persist flag for graph", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
2324 graph_ptr->persist = true;
2327 bool ladish_graph_is_persist(ladish_graph_handle graph_handle)
2329 return graph_ptr->persist;
2332 bool ladish_graph_looks_empty(ladish_graph_handle graph_handle)
2334 struct list_head * node_ptr;
2335 struct ladish_graph_connection * connection_ptr;
2336 struct ladish_graph_client * client_ptr;
2338 list_for_each(node_ptr, &graph_ptr->connections)
2340 connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
2342 if (!connection_ptr->hidden)
2344 return false;
2348 list_for_each(node_ptr, &graph_ptr->clients)
2350 client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
2351 if (!ladish_graph_client_looks_empty_internal(graph_ptr, client_ptr))
2353 return false;
2357 return true;
2360 #undef graph_ptr
2361 #define graph_ptr ((struct ladish_graph *)context)
2363 static
2364 bool
2365 ladish_graph_copy_client_begin_callback(
2366 void * context,
2367 ladish_graph_handle graph_handle,
2368 ladish_client_handle client_handle,
2369 const char * client_name,
2370 void ** client_iteration_context_ptr_ptr)
2372 ladish_client_handle copy;
2374 if (!ladish_client_create_copy(client_handle, &copy))
2376 return false;
2379 if (!ladish_graph_add_client(context, copy, client_name, false))
2381 ladish_client_destroy(copy);
2382 return false;
2385 *client_iteration_context_ptr_ptr = copy;
2387 return true;
2390 static
2391 bool
2392 ladish_graph_copy_port_callback(
2393 void * context,
2394 ladish_graph_handle graph_handle,
2395 void * client_iteration_context_ptr,
2396 ladish_client_handle client_handle,
2397 const char * client_name,
2398 ladish_port_handle port_handle,
2399 const char * port_name,
2400 uint32_t port_type,
2401 uint32_t port_flags)
2403 ladish_port_handle copy;
2405 if (!ladish_port_create_copy(port_handle, &copy))
2407 return false;
2410 if (!ladish_graph_add_port(context, client_iteration_context_ptr, copy, port_name, port_type, port_flags, true))
2412 ladish_port_destroy(copy);
2413 return false;
2416 return true;
2419 #undef graph_ptr
2421 bool ladish_graph_copy(ladish_graph_handle src, ladish_graph_handle dest, bool skip_hidden)
2423 return ladish_graph_iterate_nodes(
2424 src,
2425 skip_hidden,
2426 NULL,
2427 dest,
2428 ladish_graph_copy_client_begin_callback,
2429 ladish_graph_copy_port_callback,
2430 NULL);
2433 METHOD_ARGS_BEGIN(GetAllPorts, "Get all ports")
2434 METHOD_ARG_DESCRIBE_IN("ports_list", "as", "List of all ports")
2435 METHOD_ARGS_END
2437 METHOD_ARGS_BEGIN(GetGraph, "Get whole graph")
2438 METHOD_ARG_DESCRIBE_IN("known_graph_version", DBUS_TYPE_UINT64_AS_STRING, "Known graph version")
2439 METHOD_ARG_DESCRIBE_OUT("current_graph_version", DBUS_TYPE_UINT64_AS_STRING, "Current graph version")
2440 METHOD_ARG_DESCRIBE_OUT("clients_and_ports", "a(tsa(tsuu))", "Clients and their ports")
2441 METHOD_ARG_DESCRIBE_OUT("connections", "a(tstststst)", "Connections array")
2442 METHOD_ARGS_END
2444 METHOD_ARGS_BEGIN(ConnectPortsByName, "Connect ports")
2445 METHOD_ARG_DESCRIBE_IN("client1_name", DBUS_TYPE_STRING_AS_STRING, "name first port client")
2446 METHOD_ARG_DESCRIBE_IN("port1_name", DBUS_TYPE_STRING_AS_STRING, "name of first port")
2447 METHOD_ARG_DESCRIBE_IN("client2_name", DBUS_TYPE_STRING_AS_STRING, "name second port client")
2448 METHOD_ARG_DESCRIBE_IN("port2_name", DBUS_TYPE_STRING_AS_STRING, "name of second port")
2449 METHOD_ARGS_END
2451 METHOD_ARGS_BEGIN(ConnectPortsByID, "Connect ports")
2452 METHOD_ARG_DESCRIBE_IN("port1_id", DBUS_TYPE_UINT64_AS_STRING, "id of first port")
2453 METHOD_ARG_DESCRIBE_IN("port2_id", DBUS_TYPE_UINT64_AS_STRING, "if of second port")
2454 METHOD_ARGS_END
2456 METHOD_ARGS_BEGIN(DisconnectPortsByName, "Disconnect ports")
2457 METHOD_ARG_DESCRIBE_IN("client1_name", DBUS_TYPE_STRING_AS_STRING, "name first port client")
2458 METHOD_ARG_DESCRIBE_IN("port1_name", DBUS_TYPE_STRING_AS_STRING, "name of first port")
2459 METHOD_ARG_DESCRIBE_IN("client2_name", DBUS_TYPE_STRING_AS_STRING, "name second port client")
2460 METHOD_ARG_DESCRIBE_IN("port2_name", DBUS_TYPE_STRING_AS_STRING, "name of second port")
2461 METHOD_ARGS_END
2463 METHOD_ARGS_BEGIN(DisconnectPortsByID, "Disconnect ports")
2464 METHOD_ARG_DESCRIBE_IN("port1_id", DBUS_TYPE_UINT64_AS_STRING, "id of first port")
2465 METHOD_ARG_DESCRIBE_IN("port2_id", DBUS_TYPE_UINT64_AS_STRING, "if of second port")
2466 METHOD_ARGS_END
2468 METHOD_ARGS_BEGIN(DisconnectPortsByConnectionID, "Disconnect ports")
2469 METHOD_ARG_DESCRIBE_IN("connection_id", DBUS_TYPE_UINT64_AS_STRING, "id of connection to disconnect")
2470 METHOD_ARGS_END
2472 METHOD_ARGS_BEGIN(GetClientPID, "get process id of client")
2473 METHOD_ARG_DESCRIBE_IN("client_id", DBUS_TYPE_UINT64_AS_STRING, "id of client")
2474 METHOD_ARG_DESCRIBE_OUT("process_id", DBUS_TYPE_INT64_AS_STRING, "pid of client")
2475 METHOD_ARGS_END
2477 METHODS_BEGIN
2478 METHOD_DESCRIBE(GetAllPorts, get_all_ports)
2479 METHOD_DESCRIBE(GetGraph, get_graph)
2480 METHOD_DESCRIBE(ConnectPortsByName, connect_ports_by_name)
2481 METHOD_DESCRIBE(ConnectPortsByID, connect_ports_by_id)
2482 METHOD_DESCRIBE(DisconnectPortsByName, disconnect_ports_by_name)
2483 METHOD_DESCRIBE(DisconnectPortsByID, disconnect_ports_by_id)
2484 METHOD_DESCRIBE(DisconnectPortsByConnectionID, disconnect_ports_by_connection_id)
2485 METHOD_DESCRIBE(GetClientPID, get_client_pid)
2486 METHODS_END
2488 SIGNAL_ARGS_BEGIN(GraphChanged, "")
2489 SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
2490 SIGNAL_ARGS_END
2492 SIGNAL_ARGS_BEGIN(ClientAppeared, "")
2493 SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
2494 SIGNAL_ARG_DESCRIBE("client_id", DBUS_TYPE_UINT64_AS_STRING, "")
2495 SIGNAL_ARG_DESCRIBE("client_name", DBUS_TYPE_STRING_AS_STRING, "")
2496 SIGNAL_ARGS_END
2498 SIGNAL_ARGS_BEGIN(ClientDisappeared, "")
2499 SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
2500 SIGNAL_ARG_DESCRIBE("client_id", DBUS_TYPE_UINT64_AS_STRING, "")
2501 SIGNAL_ARG_DESCRIBE("client_name", DBUS_TYPE_STRING_AS_STRING, "")
2502 SIGNAL_ARGS_END
2504 SIGNAL_ARGS_BEGIN(PortAppeared, "")
2505 SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
2506 SIGNAL_ARG_DESCRIBE("client_id", DBUS_TYPE_UINT64_AS_STRING, "")
2507 SIGNAL_ARG_DESCRIBE("client_name", DBUS_TYPE_STRING_AS_STRING, "")
2508 SIGNAL_ARG_DESCRIBE("port_id", DBUS_TYPE_UINT64_AS_STRING, "")
2509 SIGNAL_ARG_DESCRIBE("port_name", DBUS_TYPE_STRING_AS_STRING, "")
2510 SIGNAL_ARG_DESCRIBE("port_flags", DBUS_TYPE_UINT32_AS_STRING, "")
2511 SIGNAL_ARG_DESCRIBE("port_type", DBUS_TYPE_UINT32_AS_STRING, "")
2512 SIGNAL_ARGS_END
2514 SIGNAL_ARGS_BEGIN(PortDisappeared, "")
2515 SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
2516 SIGNAL_ARG_DESCRIBE("client_id", DBUS_TYPE_UINT64_AS_STRING, "")
2517 SIGNAL_ARG_DESCRIBE("client_name", DBUS_TYPE_STRING_AS_STRING, "")
2518 SIGNAL_ARG_DESCRIBE("port_id", DBUS_TYPE_UINT64_AS_STRING, "")
2519 SIGNAL_ARG_DESCRIBE("port_name", DBUS_TYPE_STRING_AS_STRING, "")
2520 SIGNAL_ARGS_END
2522 SIGNAL_ARGS_BEGIN(PortsConnected, "")
2523 SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
2524 SIGNAL_ARG_DESCRIBE("client1_id", DBUS_TYPE_UINT64_AS_STRING, "")
2525 SIGNAL_ARG_DESCRIBE("client1_name", DBUS_TYPE_STRING_AS_STRING, "")
2526 SIGNAL_ARG_DESCRIBE("port1_id", DBUS_TYPE_UINT64_AS_STRING, "")
2527 SIGNAL_ARG_DESCRIBE("port1_name", DBUS_TYPE_STRING_AS_STRING, "")
2528 SIGNAL_ARG_DESCRIBE("client2_id", DBUS_TYPE_UINT64_AS_STRING, "")
2529 SIGNAL_ARG_DESCRIBE("client2_name", DBUS_TYPE_STRING_AS_STRING, "")
2530 SIGNAL_ARG_DESCRIBE("port2_id", DBUS_TYPE_UINT64_AS_STRING, "")
2531 SIGNAL_ARG_DESCRIBE("port2_name", DBUS_TYPE_STRING_AS_STRING, "")
2532 SIGNAL_ARG_DESCRIBE("connection_id", DBUS_TYPE_UINT64_AS_STRING, "")
2533 SIGNAL_ARGS_END
2535 SIGNAL_ARGS_BEGIN(PortsDisconnected, "")
2536 SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
2537 SIGNAL_ARG_DESCRIBE("client1_id", DBUS_TYPE_UINT64_AS_STRING, "")
2538 SIGNAL_ARG_DESCRIBE("client1_name", DBUS_TYPE_STRING_AS_STRING, "")
2539 SIGNAL_ARG_DESCRIBE("port1_id", DBUS_TYPE_UINT64_AS_STRING, "")
2540 SIGNAL_ARG_DESCRIBE("port1_name", DBUS_TYPE_STRING_AS_STRING, "")
2541 SIGNAL_ARG_DESCRIBE("client2_id", DBUS_TYPE_UINT64_AS_STRING, "")
2542 SIGNAL_ARG_DESCRIBE("client2_name", DBUS_TYPE_STRING_AS_STRING, "")
2543 SIGNAL_ARG_DESCRIBE("port2_id", DBUS_TYPE_UINT64_AS_STRING, "")
2544 SIGNAL_ARG_DESCRIBE("port2_name", DBUS_TYPE_STRING_AS_STRING, "")
2545 SIGNAL_ARG_DESCRIBE("connection_id", DBUS_TYPE_UINT64_AS_STRING, "")
2546 SIGNAL_ARGS_END
2548 SIGNALS_BEGIN
2549 SIGNAL_DESCRIBE(GraphChanged)
2550 SIGNAL_DESCRIBE(ClientAppeared)
2551 SIGNAL_DESCRIBE(ClientDisappeared)
2552 SIGNAL_DESCRIBE(PortAppeared)
2553 SIGNAL_DESCRIBE(PortDisappeared)
2554 SIGNAL_DESCRIBE(PortsConnected)
2555 SIGNAL_DESCRIBE(PortsDisconnected)
2556 SIGNALS_END
2558 INTERFACE_BEGIN(g_interface_patchbay, JACKDBUS_IFACE_PATCHBAY)
2559 INTERFACE_DEFAULT_HANDLER
2560 INTERFACE_EXPOSE_METHODS
2561 INTERFACE_EXPOSE_SIGNALS
2562 INTERFACE_END