handle port renames. closes #32
[ladish.git] / daemon / graph.c
blobbcd8b42077e2cbaa3a1fbefeaec22adbe905a041
1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*
3 * LADI Session Handler (ladish)
5 * Copyright (C) 2008, 2009 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;
46 struct ladish_graph_client
48 struct list_head siblings;
49 char * name;
50 uint64_t id;
51 ladish_client_handle client;
52 struct list_head ports;
53 bool hidden;
56 struct ladish_graph_connection
58 struct list_head siblings;
59 uint64_t id;
60 bool hidden;
61 struct ladish_graph_port * port1_ptr;
62 struct ladish_graph_port * port2_ptr;
63 ladish_dict_handle dict;
64 bool changing;
67 struct ladish_graph
69 char * opath;
70 ladish_dict_handle dict;
71 struct list_head clients;
72 struct list_head ports;
73 struct list_head connections;
74 uint64_t graph_version;
75 uint64_t next_client_id;
76 uint64_t next_port_id;
77 uint64_t next_connection_id;
79 void * context;
80 ladish_graph_connect_request_handler connect_handler;
81 ladish_graph_disconnect_request_handler disconnect_handler;
84 struct ladish_graph_port * ladish_graph_find_port_by_id_internal(struct ladish_graph * graph_ptr, uint64_t port_id)
86 struct list_head * node_ptr;
87 struct ladish_graph_port * port_ptr;
89 list_for_each(node_ptr, &graph_ptr->ports)
91 port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph);
92 if (port_ptr->id == port_id)
94 return port_ptr;
98 return NULL;
101 struct ladish_graph_connection * ladish_graph_find_connection_by_id(struct ladish_graph * graph_ptr, uint64_t connection_id)
103 struct list_head * node_ptr;
104 struct ladish_graph_connection * connection_ptr;
106 list_for_each(node_ptr, &graph_ptr->connections)
108 connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
109 if (connection_ptr->id == connection_id)
111 return connection_ptr;
115 return NULL;
118 struct ladish_graph_connection *
119 ladish_graph_find_connection_by_ports(
120 struct ladish_graph * graph_ptr,
121 struct ladish_graph_port * port1_ptr,
122 struct ladish_graph_port * port2_ptr)
124 struct list_head * node_ptr;
125 struct ladish_graph_connection * connection_ptr;
127 list_for_each(node_ptr, &graph_ptr->connections)
129 connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
130 if ((connection_ptr->port1_ptr == port1_ptr && connection_ptr->port2_ptr == port2_ptr) ||
131 (connection_ptr->port1_ptr == port2_ptr && connection_ptr->port2_ptr == port1_ptr))
133 return connection_ptr;
137 return NULL;
140 #define graph_ptr ((struct ladish_graph *)call_ptr->iface_context)
142 static void get_all_ports(struct dbus_method_call * call_ptr)
144 DBusMessageIter iter, sub_iter;
146 call_ptr->reply = dbus_message_new_method_return(call_ptr->message);
147 if (call_ptr->reply == NULL)
149 goto fail;
152 dbus_message_iter_init_append(call_ptr->reply, &iter);
154 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub_iter))
156 goto fail_unref;
159 if (!dbus_message_iter_close_container(&iter, &sub_iter))
161 goto fail_unref;
164 return;
166 fail_unref:
167 dbus_message_unref(call_ptr->reply);
168 call_ptr->reply = NULL;
170 fail:
171 log_error("Ran out of memory trying to construct method return");
174 static void get_graph(struct dbus_method_call * call_ptr)
176 dbus_uint64_t known_version;
177 dbus_uint64_t current_version;
178 DBusMessageIter iter;
179 DBusMessageIter clients_array_iter;
180 DBusMessageIter connections_array_iter;
181 DBusMessageIter client_struct_iter;
182 struct list_head * client_node_ptr;
183 struct ladish_graph_client * client_ptr;
184 DBusMessageIter ports_array_iter;
185 struct list_head * port_node_ptr;
186 struct ladish_graph_port * port_ptr;
187 DBusMessageIter port_struct_iter;
188 struct list_head * connection_node_ptr;
189 struct ladish_graph_connection * connection_ptr;
190 DBusMessageIter connection_struct_iter;
192 //log_info("get_graph() called");
194 if (!dbus_message_get_args(call_ptr->message, &g_dbus_error, DBUS_TYPE_UINT64, &known_version, DBUS_TYPE_INVALID))
196 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, g_dbus_error.message);
197 dbus_error_free(&g_dbus_error);
198 return;
201 //log_info("Getting graph, known version is %" PRIu64, known_version);
203 call_ptr->reply = dbus_message_new_method_return(call_ptr->message);
204 if (call_ptr->reply == NULL)
206 log_error("Ran out of memory trying to construct method return");
207 goto exit;
210 dbus_message_iter_init_append(call_ptr->reply, &iter);
212 current_version = graph_ptr->graph_version;
213 if (known_version > current_version)
215 lash_dbus_error(
216 call_ptr,
217 LASH_DBUS_ERROR_INVALID_ARGS,
218 "known graph version %" PRIu64 " is newer than actual version %" PRIu64,
219 known_version,
220 current_version);
221 goto exit;
224 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT64, &current_version))
226 goto nomem;
229 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(tsa(tsuu))", &clients_array_iter))
231 goto nomem;
234 if (known_version < current_version)
236 list_for_each(client_node_ptr, &graph_ptr->clients)
238 client_ptr = list_entry(client_node_ptr, struct ladish_graph_client, siblings);
240 if (client_ptr->hidden)
242 continue;
245 if (!dbus_message_iter_open_container (&clients_array_iter, DBUS_TYPE_STRUCT, NULL, &client_struct_iter))
247 goto nomem_close_clients_array;
250 if (!dbus_message_iter_append_basic(&client_struct_iter, DBUS_TYPE_UINT64, &client_ptr->id))
252 goto nomem_close_client_struct;
255 log_info("client '%s' (%llu)", client_ptr->name, (unsigned long long)client_ptr->id);
256 if (!dbus_message_iter_append_basic(&client_struct_iter, DBUS_TYPE_STRING, &client_ptr->name))
258 goto nomem_close_client_struct;
261 if (!dbus_message_iter_open_container(&client_struct_iter, DBUS_TYPE_ARRAY, "(tsuu)", &ports_array_iter))
263 goto nomem_close_client_struct;
266 list_for_each(port_node_ptr, &client_ptr->ports)
268 port_ptr = list_entry(port_node_ptr, struct ladish_graph_port, siblings_client);
270 if (port_ptr->hidden)
272 continue;
275 if (!dbus_message_iter_open_container(&ports_array_iter, DBUS_TYPE_STRUCT, NULL, &port_struct_iter))
277 goto nomem_close_ports_array;
280 if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT64, &port_ptr->id))
282 goto nomem_close_port_struct;
285 if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_STRING, &port_ptr->name))
287 goto nomem_close_port_struct;
290 if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT32, &port_ptr->flags))
292 goto nomem_close_port_struct;
295 if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT32, &port_ptr->type))
297 goto nomem_close_port_struct;
300 if (!dbus_message_iter_close_container(&ports_array_iter, &port_struct_iter))
302 goto nomem_close_ports_array;
306 if (!dbus_message_iter_close_container(&client_struct_iter, &ports_array_iter))
308 goto nomem_close_client_struct;
311 if (!dbus_message_iter_close_container(&clients_array_iter, &client_struct_iter))
313 goto nomem_close_clients_array;
318 if (!dbus_message_iter_close_container(&iter, &clients_array_iter))
320 goto nomem;
323 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(tstststst)", &connections_array_iter))
325 goto nomem;
328 if (known_version < current_version)
330 list_for_each(connection_node_ptr, &graph_ptr->connections)
332 connection_ptr = list_entry(connection_node_ptr, struct ladish_graph_connection, siblings);
334 if (connection_ptr->hidden)
336 continue;
339 if (!dbus_message_iter_open_container(&connections_array_iter, DBUS_TYPE_STRUCT, NULL, &connection_struct_iter))
341 goto nomem_close_connections_array;
344 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port1_ptr->client_ptr->id))
346 goto nomem_close_connection_struct;
349 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port1_ptr->client_ptr->name))
351 goto nomem_close_connection_struct;
354 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port1_ptr->id))
356 goto nomem_close_connection_struct;
359 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port1_ptr->name))
361 goto nomem_close_connection_struct;
364 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port2_ptr->client_ptr->id))
366 goto nomem_close_connection_struct;
369 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port2_ptr->client_ptr->name))
371 goto nomem_close_connection_struct;
374 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port2_ptr->id))
376 goto nomem_close_connection_struct;
379 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port2_ptr->name))
381 goto nomem_close_connection_struct;
384 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->id))
386 goto nomem_close_connection_struct;
389 if (!dbus_message_iter_close_container(&connections_array_iter, &connection_struct_iter))
391 goto nomem_close_connections_array;
396 if (!dbus_message_iter_close_container(&iter, &connections_array_iter))
398 goto nomem;
401 return;
403 nomem_close_connection_struct:
404 dbus_message_iter_close_container(&connections_array_iter, &connection_struct_iter);
406 nomem_close_connections_array:
407 dbus_message_iter_close_container(&iter, &connections_array_iter);
408 goto nomem;
410 nomem_close_port_struct:
411 dbus_message_iter_close_container(&ports_array_iter, &port_struct_iter);
413 nomem_close_ports_array:
414 dbus_message_iter_close_container(&client_struct_iter, &ports_array_iter);
416 nomem_close_client_struct:
417 dbus_message_iter_close_container(&clients_array_iter, &client_struct_iter);
419 nomem_close_clients_array:
420 dbus_message_iter_close_container(&iter, &clients_array_iter);
422 nomem:
423 dbus_message_unref(call_ptr->reply);
424 call_ptr->reply = NULL;
425 log_error("Ran out of memory trying to construct method return");
427 exit:
428 return;
431 static void connect_ports_by_name(struct dbus_method_call * call_ptr)
433 log_info("connect_ports_by_name() called.");
434 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "connect by name is not implemented yet");
437 static void connect_ports_by_id(struct dbus_method_call * call_ptr)
439 dbus_uint64_t port1_id;
440 dbus_uint64_t port2_id;
441 struct ladish_graph_port * port1_ptr;
442 struct ladish_graph_port * port2_ptr;
444 if (!dbus_message_get_args(call_ptr->message, &g_dbus_error, DBUS_TYPE_UINT64, &port1_id, DBUS_TYPE_UINT64, &port2_id, DBUS_TYPE_INVALID))
446 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, g_dbus_error.message);
447 dbus_error_free(&g_dbus_error);
448 return;
451 log_info("connect_ports_by_id(%"PRIu64",%"PRIu64") called.", port1_id, port2_id);
453 if (graph_ptr->connect_handler == NULL)
455 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "connect requests on this graph cannot be handlined");
456 return;
459 port1_ptr = ladish_graph_find_port_by_id_internal(graph_ptr, port1_id);
460 if (port1_ptr == NULL)
462 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot connect unknown port with id %"PRIu64, port1_id);
463 return;
466 port2_ptr = ladish_graph_find_port_by_id_internal(graph_ptr, port2_id);
467 if (port2_ptr == NULL)
469 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot connect unknown port with id %"PRIu64, port2_id);
470 return;
473 log_info("connecting '%s':'%s' to '%s':'%s'", port1_ptr->client_ptr->name, port1_ptr->name, port2_ptr->client_ptr->name, port2_ptr->name);
475 if (graph_ptr->connect_handler(graph_ptr->context, (ladish_graph_handle)graph_ptr, port1_ptr->port, port2_ptr->port))
477 method_return_new_void(call_ptr);
479 else
481 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "connect failed");
485 static void disconnect_ports(struct dbus_method_call * call_ptr, struct ladish_graph_connection * connection_ptr)
487 log_info(
488 "disconnecting '%s':'%s' from '%s':'%s'",
489 connection_ptr->port1_ptr->client_ptr->name,
490 connection_ptr->port1_ptr->name,
491 connection_ptr->port2_ptr->client_ptr->name,
492 connection_ptr->port2_ptr->name);
494 connection_ptr->changing = true;
495 if (graph_ptr->disconnect_handler(graph_ptr->context, (ladish_graph_handle)graph_ptr, connection_ptr->id))
497 method_return_new_void(call_ptr);
499 else
501 connection_ptr->changing = false;
502 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "disconnect failed");
506 static void disconnect_ports_by_name(struct dbus_method_call * call_ptr)
508 log_info("disconnect_ports_by_name() called.");
509 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "disconnect by name is not implemented yet");
512 static void disconnect_ports_by_id(struct dbus_method_call * call_ptr)
514 dbus_uint64_t port1_id;
515 dbus_uint64_t port2_id;
516 struct ladish_graph_port * port1_ptr;
517 struct ladish_graph_port * port2_ptr;
518 struct ladish_graph_connection * connection_ptr;
520 if (!dbus_message_get_args(call_ptr->message, &g_dbus_error, DBUS_TYPE_UINT64, &port1_id, DBUS_TYPE_UINT64, &port2_id, DBUS_TYPE_INVALID))
522 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, g_dbus_error.message);
523 dbus_error_free(&g_dbus_error);
524 return;
527 log_info("disconnect_ports_by_id(%"PRIu64",%"PRIu64") called.", port1_id, port2_id);
529 if (graph_ptr->disconnect_handler == NULL)
531 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "disconnect requests on this graph cannot be handlined");
532 return;
535 port1_ptr = ladish_graph_find_port_by_id_internal(graph_ptr, port1_id);
536 if (port1_ptr == NULL)
538 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot disconnect unknown port with id %"PRIu64, port1_id);
539 return;
542 port2_ptr = ladish_graph_find_port_by_id_internal(graph_ptr, port2_id);
543 if (port2_ptr == NULL)
545 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot disconnect unknown port with id %"PRIu64, port2_id);
546 return;
549 connection_ptr = ladish_graph_find_connection_by_ports(graph_ptr, port1_ptr, port2_ptr);
550 if (connection_ptr == NULL)
552 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot disconnect not connected ports %"PRIu64" and %"PRIu64, port1_id, port2_id);
553 return;
556 disconnect_ports(call_ptr, connection_ptr);
559 static void disconnect_ports_by_connection_id(struct dbus_method_call * call_ptr)
561 dbus_uint64_t connection_id;
562 struct ladish_graph_connection * connection_ptr;
564 if (!dbus_message_get_args(call_ptr->message, &g_dbus_error, DBUS_TYPE_UINT64, &connection_id, DBUS_TYPE_INVALID))
566 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, g_dbus_error.message);
567 dbus_error_free(&g_dbus_error);
568 return;
571 log_info("disconnect_ports_by_connection_id(%"PRIu64") called.", connection_id);
573 connection_ptr = ladish_graph_find_connection_by_id(graph_ptr, connection_id);
574 if (connection_ptr == NULL)
576 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot find connection with id %"PRIu64, connection_id);
577 return;
580 disconnect_ports(call_ptr, connection_ptr);
583 static void get_client_pid(struct dbus_method_call * call_ptr)
585 int64_t pid = 0;
586 method_return_new_single(call_ptr, DBUS_TYPE_INT64, &pid);
589 #undef graph_ptr
591 bool ladish_graph_create(ladish_graph_handle * graph_handle_ptr, const char * opath)
593 struct ladish_graph * graph_ptr;
595 graph_ptr = malloc(sizeof(struct ladish_graph));
596 if (graph_ptr == NULL)
598 log_error("malloc() failed to allocate struct graph_implementator");
599 return false;
602 if (opath != NULL)
604 graph_ptr->opath = strdup(opath);
605 if (graph_ptr->opath == NULL)
607 log_error("strdup() failed for graph opath");
608 free(graph_ptr);
609 return false;
612 else
614 graph_ptr->opath = NULL;
617 if (!ladish_dict_create(&graph_ptr->dict))
619 log_error("ladish_dict_create() failed for graph");
620 if (graph_ptr->opath != NULL)
622 free(graph_ptr->opath);
624 free(graph_ptr);
625 return false;
628 INIT_LIST_HEAD(&graph_ptr->clients);
629 INIT_LIST_HEAD(&graph_ptr->ports);
630 INIT_LIST_HEAD(&graph_ptr->connections);
632 graph_ptr->graph_version = 1;
633 graph_ptr->next_client_id = 1;
634 graph_ptr->next_port_id = 1;
635 graph_ptr->next_connection_id = 1;
637 graph_ptr->context = NULL;
638 graph_ptr->connect_handler = NULL;
639 graph_ptr->disconnect_handler = NULL;
641 *graph_handle_ptr = (ladish_graph_handle)graph_ptr;
642 return true;
645 static
646 struct ladish_graph_client *
647 ladish_graph_find_client(
648 struct ladish_graph * graph_ptr,
649 ladish_client_handle client)
651 struct list_head * node_ptr;
652 struct ladish_graph_client * client_ptr;
654 list_for_each(node_ptr, &graph_ptr->clients)
656 client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
657 if (client_ptr->client == client)
659 return client_ptr;
663 return NULL;
666 static
667 struct ladish_graph_port *
668 ladish_graph_find_port(
669 struct ladish_graph * graph_ptr,
670 ladish_port_handle port)
672 struct list_head * node_ptr;
673 struct ladish_graph_port * port_ptr;
675 list_for_each(node_ptr, &graph_ptr->ports)
677 port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph);
678 if (port_ptr->port == port)
680 return port_ptr;
684 return NULL;
687 #if 0
688 static
689 struct ladish_graph_port *
690 ladish_graph_find_client_port(
691 struct ladish_graph * graph_ptr,
692 struct ladish_graph_client * client_ptr,
693 ladish_port_handle port)
695 struct list_head * node_ptr;
696 struct ladish_graph_port * port_ptr;
698 list_for_each(node_ptr, &client_ptr->ports)
700 port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_client);
701 if (port_ptr->port == port)
703 return port_ptr;
707 return NULL;
709 #endif
711 static void ladish_graph_hide_connection_internal(struct ladish_graph * graph_ptr, struct ladish_graph_connection * connection_ptr)
713 ASSERT(!connection_ptr->hidden);
714 connection_ptr->hidden = true;
715 graph_ptr->graph_version++;
717 if (graph_ptr->opath != NULL)
719 dbus_signal_emit(
720 g_dbus_connection,
721 graph_ptr->opath,
722 JACKDBUS_IFACE_PATCHBAY,
723 "PortsDisconnected",
724 "ttstststst",
725 &graph_ptr->graph_version,
726 &connection_ptr->port1_ptr->client_ptr->id,
727 &connection_ptr->port1_ptr->client_ptr->name,
728 &connection_ptr->port1_ptr->id,
729 &connection_ptr->port1_ptr->name,
730 &connection_ptr->port2_ptr->client_ptr->id,
731 &connection_ptr->port2_ptr->client_ptr->name,
732 &connection_ptr->port2_ptr->id,
733 &connection_ptr->port2_ptr->name,
734 &connection_ptr->id);
738 void ladish_graph_show_port_internal(struct ladish_graph * graph_ptr, struct ladish_graph_port * port_ptr)
740 if (port_ptr->client_ptr->hidden)
742 port_ptr->client_ptr->hidden = false;
743 graph_ptr->graph_version++;
744 if (graph_ptr->opath != NULL)
746 dbus_signal_emit(
747 g_dbus_connection,
748 graph_ptr->opath,
749 JACKDBUS_IFACE_PATCHBAY,
750 "ClientAppeared",
751 "tts",
752 &graph_ptr->graph_version,
753 &port_ptr->client_ptr->id,
754 &port_ptr->client_ptr->name);
758 ASSERT(port_ptr->hidden);
759 port_ptr->hidden = false;
760 graph_ptr->graph_version++;
761 if (graph_ptr->opath != NULL)
763 dbus_signal_emit(
764 g_dbus_connection,
765 graph_ptr->opath,
766 JACKDBUS_IFACE_PATCHBAY,
767 "PortAppeared",
768 "ttstsuu",
769 &graph_ptr->graph_version,
770 &port_ptr->client_ptr->id,
771 &port_ptr->client_ptr->name,
772 &port_ptr->id,
773 &port_ptr->name,
774 &port_ptr->flags,
775 &port_ptr->type);
777 ladish_try_connect_hidden_connections((ladish_graph_handle)graph_ptr);
781 void ladish_graph_hide_port_internal(struct ladish_graph * graph_ptr, struct ladish_graph_port * port_ptr)
783 ASSERT(!port_ptr->hidden);
784 port_ptr->hidden = true;
785 graph_ptr->graph_version++;
787 if (graph_ptr->opath != NULL)
789 dbus_signal_emit(
790 g_dbus_connection,
791 graph_ptr->opath,
792 JACKDBUS_IFACE_PATCHBAY,
793 "PortDisappeared",
794 "ttsts",
795 &graph_ptr->graph_version,
796 &port_ptr->client_ptr->id,
797 &port_ptr->client_ptr->name,
798 &port_ptr->id,
799 &port_ptr->name);
803 void ladish_graph_hide_client_internal(struct ladish_graph * graph_ptr, struct ladish_graph_client * client_ptr)
805 ASSERT(!client_ptr->hidden);
806 client_ptr->hidden = true;
807 graph_ptr->graph_version++;
809 if (graph_ptr->opath != NULL)
811 dbus_signal_emit(
812 g_dbus_connection,
813 graph_ptr->opath,
814 JACKDBUS_IFACE_PATCHBAY,
815 "ClientDisappeared",
816 "tts",
817 &graph_ptr->graph_version,
818 &client_ptr->id,
819 &client_ptr->name);
823 void ladish_hide_connections(struct ladish_graph * graph_ptr, struct ladish_graph_port * port_ptr)
825 struct list_head * node_ptr;
826 struct ladish_graph_connection * connection_ptr;
828 log_info("hidding connections of port %"PRIu64, port_ptr->id);
830 ASSERT(graph_ptr->opath != NULL);
832 list_for_each(node_ptr, &graph_ptr->connections)
834 connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
835 if (!connection_ptr->hidden && (connection_ptr->port1_ptr == port_ptr || connection_ptr->port2_ptr == port_ptr))
837 log_info("hidding connection between ports %"PRIu64" and %"PRIu64, connection_ptr->port1_ptr->id, connection_ptr->port2_ptr->id);
838 ladish_graph_hide_connection_internal(graph_ptr, connection_ptr);
843 static void ladish_graph_remove_connection_internal(struct ladish_graph * graph_ptr, struct ladish_graph_connection * connection_ptr)
845 list_del(&connection_ptr->siblings);
846 graph_ptr->graph_version++;
848 if (!connection_ptr->hidden && graph_ptr->opath != NULL)
850 dbus_signal_emit(
851 g_dbus_connection,
852 graph_ptr->opath,
853 JACKDBUS_IFACE_PATCHBAY,
854 "PortsDisconnected",
855 "ttstststst",
856 &graph_ptr->graph_version,
857 &connection_ptr->port1_ptr->client_ptr->id,
858 &connection_ptr->port1_ptr->client_ptr->name,
859 &connection_ptr->port1_ptr->id,
860 &connection_ptr->port1_ptr->name,
861 &connection_ptr->port2_ptr->client_ptr->id,
862 &connection_ptr->port2_ptr->client_ptr->name,
863 &connection_ptr->port2_ptr->id,
864 &connection_ptr->port2_ptr->name,
865 &connection_ptr->id);
868 ladish_dict_destroy(connection_ptr->dict);
869 free(connection_ptr);
872 void
873 ladish_graph_remove_port_internal(
874 struct ladish_graph * graph_ptr,
875 struct ladish_graph_client * client_ptr,
876 struct ladish_graph_port * port_ptr,
877 bool destroy)
879 if (destroy)
881 ladish_port_destroy(port_ptr->port);
884 list_del(&port_ptr->siblings_client);
885 list_del(&port_ptr->siblings_graph);
887 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");
888 if (graph_ptr->opath != NULL && !port_ptr->hidden)
890 dbus_signal_emit(
891 g_dbus_connection,
892 graph_ptr->opath,
893 JACKDBUS_IFACE_PATCHBAY,
894 "PortDisappeared",
895 "ttsts",
896 &graph_ptr->graph_version,
897 &client_ptr->id,
898 &client_ptr->name,
899 &port_ptr->id,
900 &port_ptr->name);
903 free(port_ptr->name);
904 free(port_ptr);
907 static
908 void
909 ladish_graph_remove_client_internal(
910 struct ladish_graph * graph_ptr,
911 struct ladish_graph_client * client_ptr,
912 bool destroy_client,
913 bool destroy_ports)
915 struct ladish_graph_port * port_ptr;
917 while (!list_empty(&client_ptr->ports))
919 port_ptr = list_entry(client_ptr->ports.next, struct ladish_graph_port, siblings_client);
920 ladish_graph_remove_port_internal(graph_ptr, client_ptr, port_ptr, destroy_ports);
923 graph_ptr->graph_version++;
924 list_del(&client_ptr->siblings);
925 log_info("removing client '%s' (%"PRIu64") from graph %s", client_ptr->name, client_ptr->id, graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
926 if (graph_ptr->opath != NULL && !client_ptr->hidden)
928 dbus_signal_emit(
929 g_dbus_connection,
930 graph_ptr->opath,
931 JACKDBUS_IFACE_PATCHBAY,
932 "ClientDisappeared",
933 "tts",
934 &graph_ptr->graph_version,
935 &client_ptr->id,
936 &client_ptr->name);
939 free(client_ptr->name);
941 if (destroy_client)
943 ladish_client_destroy(client_ptr->client);
946 free(client_ptr);
949 #define graph_ptr ((struct ladish_graph *)graph_handle)
951 void ladish_graph_destroy(ladish_graph_handle graph_handle, bool destroy_ports)
953 ladish_graph_clear(graph_handle, destroy_ports);
954 ladish_dict_destroy(graph_ptr->dict);
955 if (graph_ptr->opath != NULL)
957 free(graph_ptr->opath);
959 free(graph_ptr);
962 void
963 ladish_graph_set_connection_handlers(
964 ladish_graph_handle graph_handle,
965 void * graph_context,
966 ladish_graph_connect_request_handler connect_handler,
967 ladish_graph_disconnect_request_handler disconnect_handler)
969 graph_ptr->context = graph_context;
970 graph_ptr->connect_handler = connect_handler;
971 graph_ptr->disconnect_handler = disconnect_handler;
974 void ladish_graph_clear(ladish_graph_handle graph_handle, bool destroy_ports)
976 struct ladish_graph_client * client_ptr;
977 struct ladish_graph_connection * connection_ptr;
979 log_info("ladish_graph_clear() called for graph '%s'", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
981 while (!list_empty(&graph_ptr->connections))
983 connection_ptr = list_entry(graph_ptr->connections.next, struct ladish_graph_connection, siblings);
984 ladish_graph_remove_connection_internal(graph_ptr, connection_ptr);
987 while (!list_empty(&graph_ptr->clients))
989 client_ptr = list_entry(graph_ptr->clients.next, struct ladish_graph_client, siblings);
990 ladish_graph_remove_client_internal(graph_ptr, client_ptr, true, destroy_ports);
994 void * ladish_graph_get_dbus_context(ladish_graph_handle graph_handle)
996 return graph_handle;
999 ladish_dict_handle ladish_graph_get_dict(ladish_graph_handle graph_handle)
1001 return graph_ptr->dict;
1004 void ladish_graph_show_connection(ladish_graph_handle graph_handle, uint64_t connection_id)
1006 struct ladish_graph_connection * connection_ptr;
1008 log_info("ladish_graph_show_connection() called.");
1010 connection_ptr = ladish_graph_find_connection_by_id(graph_ptr, connection_id);
1011 if (connection_ptr == NULL)
1013 ASSERT_NO_PASS;
1014 return;
1017 ASSERT(graph_ptr->opath != NULL);
1018 ASSERT(connection_ptr->hidden);
1019 connection_ptr->hidden = false;
1020 connection_ptr->changing = false;
1021 graph_ptr->graph_version++;
1023 dbus_signal_emit(
1024 g_dbus_connection,
1025 graph_ptr->opath,
1026 JACKDBUS_IFACE_PATCHBAY,
1027 "PortsConnected",
1028 "ttstststst",
1029 &graph_ptr->graph_version,
1030 &connection_ptr->port1_ptr->client_ptr->id,
1031 &connection_ptr->port1_ptr->client_ptr->name,
1032 &connection_ptr->port1_ptr->id,
1033 &connection_ptr->port1_ptr->name,
1034 &connection_ptr->port2_ptr->client_ptr->id,
1035 &connection_ptr->port2_ptr->client_ptr->name,
1036 &connection_ptr->port2_ptr->id,
1037 &connection_ptr->port2_ptr->name,
1038 &connection_ptr->id);
1041 void ladish_graph_show_port(ladish_graph_handle graph_handle, ladish_port_handle port_handle)
1043 struct ladish_graph_port * port_ptr;
1045 //log_info("ladish_graph_show_port() called.");
1047 port_ptr = ladish_graph_find_port(graph_ptr, port_handle);
1048 if (port_ptr == NULL)
1050 ASSERT_NO_PASS;
1051 return;
1054 //log_info("port '%s' is %s", port_ptr->name, port_ptr->hidden ? "invisible" : "visible");
1056 ladish_graph_show_port_internal(graph_ptr, port_ptr);
1059 void ladish_graph_hide_port(ladish_graph_handle graph_handle, ladish_port_handle port_handle)
1061 struct ladish_graph_port * port_ptr;
1063 log_info("ladish_graph_hide_port() called.");
1065 port_ptr = ladish_graph_find_port(graph_ptr, port_handle);
1066 if (port_ptr == NULL)
1068 ASSERT_NO_PASS;
1069 return;
1072 log_info("Hidding port %"PRIu64, port_ptr->id);
1074 ASSERT(!port_ptr->hidden);
1076 if (graph_ptr->opath != NULL)
1078 ladish_hide_connections(graph_ptr, port_ptr);
1081 ladish_graph_hide_port_internal(graph_ptr, port_ptr);
1084 void ladish_graph_hide_client(ladish_graph_handle graph_handle, ladish_client_handle client_handle)
1086 struct ladish_graph_client * client_ptr;
1088 log_info("ladish_graph_hide_client() called.");
1090 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1091 if (client_ptr == NULL)
1093 ASSERT_NO_PASS;
1094 return;
1097 ladish_graph_hide_client_internal(graph_ptr, client_ptr);
1100 void ladish_graph_show_client(ladish_graph_handle graph_handle, ladish_client_handle client_handle)
1102 struct ladish_graph_client * client_ptr;
1104 log_info("ladish_graph_show_client() called.");
1106 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1107 if (client_ptr == NULL)
1109 ASSERT_NO_PASS;
1110 return;
1113 ASSERT(client_ptr->hidden);
1114 client_ptr->hidden = false;
1115 graph_ptr->graph_version++;
1117 if (graph_ptr->opath != NULL)
1119 dbus_signal_emit(
1120 g_dbus_connection,
1121 graph_ptr->opath,
1122 JACKDBUS_IFACE_PATCHBAY,
1123 "ClientAppeared",
1124 "tts",
1125 &graph_ptr->graph_version,
1126 &client_ptr->id,
1127 &client_ptr->name);
1131 void ladish_graph_adjust_port(ladish_graph_handle graph_handle, ladish_port_handle port_handle, uint32_t type, uint32_t flags)
1133 struct ladish_graph_port * port_ptr;
1135 //log_info("ladish_graph_adjust_port() called.");
1137 port_ptr = ladish_graph_find_port(graph_ptr, port_handle);
1138 if (port_ptr == NULL)
1140 ASSERT_NO_PASS;
1141 return;
1144 port_ptr->type = type;
1145 port_ptr->flags = flags;
1148 bool ladish_graph_add_client(ladish_graph_handle graph_handle, ladish_client_handle client_handle, const char * name, bool hidden)
1150 struct ladish_graph_client * client_ptr;
1152 log_info("adding client '%s' (%p) to graph %s", name, client_handle, graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
1154 client_ptr = malloc(sizeof(struct ladish_graph_client));
1155 if (client_ptr == NULL)
1157 log_error("malloc() failed for struct ladish_graph_client");
1158 return false;
1161 client_ptr->name = strdup(name);
1162 if (client_ptr->name == NULL)
1164 log_error("strdup() failed for graph client name");
1165 free(client_ptr);
1166 return false;
1169 client_ptr->id = graph_ptr->next_client_id++;
1170 client_ptr->client = client_handle;
1171 client_ptr->hidden = hidden;
1172 graph_ptr->graph_version++;
1174 INIT_LIST_HEAD(&client_ptr->ports);
1176 list_add_tail(&client_ptr->siblings, &graph_ptr->clients);
1178 if (!hidden && graph_ptr->opath != NULL)
1180 dbus_signal_emit(
1181 g_dbus_connection,
1182 graph_ptr->opath,
1183 JACKDBUS_IFACE_PATCHBAY,
1184 "ClientAppeared",
1185 "tts",
1186 &graph_ptr->graph_version,
1187 &client_ptr->id,
1188 &client_ptr->name);
1191 return true;
1194 void
1195 ladish_graph_remove_client(
1196 ladish_graph_handle graph_handle,
1197 ladish_client_handle client_handle,
1198 bool destroy_ports)
1200 struct ladish_graph_client * client_ptr;
1202 log_info("ladish_graph_remove_client() called.");
1204 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1205 if (client_ptr != NULL)
1207 ladish_graph_remove_client_internal(graph_ptr, client_ptr, false, destroy_ports);
1209 else
1211 ASSERT_NO_PASS;
1215 bool
1216 ladish_graph_add_port(
1217 ladish_graph_handle graph_handle,
1218 ladish_client_handle client_handle,
1219 ladish_port_handle port_handle,
1220 const char * name,
1221 uint32_t type,
1222 uint32_t flags,
1223 bool hidden)
1225 struct ladish_graph_client * client_ptr;
1226 struct ladish_graph_port * port_ptr;
1228 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1229 if (client_ptr == NULL)
1231 log_error("cannot find client to add port to. graph is %s", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
1232 ASSERT_NO_PASS;
1233 return false;
1236 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");
1238 port_ptr = malloc(sizeof(struct ladish_graph_port));
1239 if (port_ptr == NULL)
1241 log_error("malloc() failed for struct ladish_graph_port");
1242 return false;
1245 port_ptr->name = strdup(name);
1246 if (port_ptr->name == NULL)
1248 log_error("strdup() failed for graph port name");
1249 free(port_ptr);
1250 return false;
1253 port_ptr->type = type;
1254 port_ptr->flags = flags;
1256 port_ptr->id = graph_ptr->next_port_id++;
1257 port_ptr->port = port_handle;
1258 port_ptr->hidden = true;
1260 port_ptr->client_ptr = client_ptr;
1261 list_add_tail(&port_ptr->siblings_client, &client_ptr->ports);
1262 list_add_tail(&port_ptr->siblings_graph, &graph_ptr->ports);
1264 if (!hidden)
1266 ladish_graph_show_port_internal(graph_ptr, port_ptr);
1269 return true;
1272 uint64_t
1273 ladish_graph_add_connection(
1274 ladish_graph_handle graph_handle,
1275 ladish_port_handle port1_handle,
1276 ladish_port_handle port2_handle,
1277 bool hidden)
1279 struct ladish_graph_port * port1_ptr;
1280 struct ladish_graph_port * port2_ptr;
1281 struct ladish_graph_connection * connection_ptr;
1283 port1_ptr = ladish_graph_find_port(graph_ptr, port1_handle);
1284 ASSERT(port1_ptr != NULL);
1285 port2_ptr = ladish_graph_find_port(graph_ptr, port2_handle);
1286 ASSERT(port2_ptr != NULL);
1288 connection_ptr = malloc(sizeof(struct ladish_graph_connection));
1289 if (connection_ptr == NULL)
1291 log_error("malloc() failed for struct ladish_graph_connection");
1292 return 0;
1295 if (!ladish_dict_create(&connection_ptr->dict))
1297 log_error("ladish_dict_create() failed for connection");
1298 free(connection_ptr);
1299 return 0;
1302 connection_ptr->id = graph_ptr->next_connection_id++;
1303 connection_ptr->port1_ptr = port1_ptr;
1304 connection_ptr->port2_ptr = port2_ptr;
1305 connection_ptr->hidden = hidden;
1306 connection_ptr->changing = false;
1307 graph_ptr->graph_version++;
1309 list_add_tail(&connection_ptr->siblings, &graph_ptr->connections);
1311 /* log_info( */
1312 /* "new connection %"PRIu64" between '%s':'%s' and '%s':'%s'", */
1313 /* connection_ptr->id, */
1314 /* port1_ptr->client_ptr->name, */
1315 /* port1_ptr->name, */
1316 /* port2_ptr->client_ptr->name, */
1317 /* port2_ptr->name); */
1319 if (!hidden && graph_ptr->opath != NULL)
1321 dbus_signal_emit(
1322 g_dbus_connection,
1323 graph_ptr->opath,
1324 JACKDBUS_IFACE_PATCHBAY,
1325 "PortsConnected",
1326 "ttstststst",
1327 &graph_ptr->graph_version,
1328 &port1_ptr->client_ptr->id,
1329 &port1_ptr->client_ptr->name,
1330 &port1_ptr->id,
1331 &port1_ptr->name,
1332 &port2_ptr->client_ptr->id,
1333 &port2_ptr->client_ptr->name,
1334 &port2_ptr->id,
1335 &port2_ptr->name,
1336 &connection_ptr->id);
1339 return connection_ptr->id;
1342 void
1343 ladish_graph_remove_connection(
1344 ladish_graph_handle graph_handle,
1345 uint64_t connection_id,
1346 bool force)
1348 struct ladish_graph_connection * connection_ptr;
1350 connection_ptr = ladish_graph_find_connection_by_id(graph_ptr, connection_id);
1351 if (connection_ptr == NULL)
1353 ASSERT_NO_PASS;
1354 return;
1357 if (force || connection_ptr->changing)
1359 /* log_info( */
1360 /* "removing connection '%s':'%s' - '%s':'%s'", */
1361 /* connection_ptr->port1_ptr->client_ptr->name, */
1362 /* connection_ptr->port1_ptr->name, */
1363 /* connection_ptr->port2_ptr->client_ptr->name, */
1364 /* connection_ptr->port2_ptr->name); */
1366 ladish_graph_remove_connection_internal(graph_ptr, connection_ptr);
1368 else
1370 /* log_info( */
1371 /* "hiding connection '%s':'%s' - '%s':'%s'", */
1372 /* connection_ptr->port1_ptr->client_ptr->name, */
1373 /* connection_ptr->port1_ptr->name, */
1374 /* connection_ptr->port2_ptr->client_ptr->name, */
1375 /* connection_ptr->port2_ptr->name); */
1377 ladish_graph_hide_connection_internal(graph_ptr, connection_ptr);
1381 bool
1382 ladish_graph_get_connection_ports(
1383 ladish_graph_handle graph_handle,
1384 uint64_t connection_id,
1385 ladish_port_handle * port1_handle_ptr,
1386 ladish_port_handle * port2_handle_ptr)
1388 struct ladish_graph_connection * connection_ptr;
1390 connection_ptr = ladish_graph_find_connection_by_id(graph_ptr, connection_id);
1391 if (connection_ptr == NULL)
1393 return false;
1396 *port1_handle_ptr = connection_ptr->port1_ptr->port;
1397 *port2_handle_ptr = connection_ptr->port2_ptr->port;
1399 return true;
1402 ladish_dict_handle ladish_graph_get_connection_dict(ladish_graph_handle graph_handle, uint64_t connection_id)
1404 struct ladish_graph_connection * connection_ptr;
1406 connection_ptr = ladish_graph_find_connection_by_id(graph_ptr, connection_id);
1407 if (connection_ptr == NULL)
1409 return NULL;
1412 return connection_ptr->dict;
1415 bool
1416 ladish_graph_find_connection(
1417 ladish_graph_handle graph_handle,
1418 ladish_port_handle port1_handle,
1419 ladish_port_handle port2_handle,
1420 uint64_t * connection_id_ptr)
1422 struct ladish_graph_port * port1_ptr;
1423 struct ladish_graph_port * port2_ptr;
1424 struct ladish_graph_connection * connection_ptr;
1426 port1_ptr = ladish_graph_find_port(graph_ptr, port1_handle);
1427 if (port1_ptr == NULL)
1429 return false;
1432 port2_ptr = ladish_graph_find_port(graph_ptr, port2_handle);
1433 if (port1_ptr == NULL)
1435 return false;
1438 connection_ptr = ladish_graph_find_connection_by_ports(graph_ptr, port1_ptr, port2_ptr);
1439 if (connection_ptr == NULL)
1441 return false;
1444 *connection_id_ptr = connection_ptr->id;
1446 return true;
1449 ladish_client_handle ladish_graph_find_client_by_name(ladish_graph_handle graph_handle, const char * name)
1451 struct list_head * node_ptr;
1452 struct ladish_graph_client * client_ptr;
1454 list_for_each(node_ptr, &graph_ptr->clients)
1456 client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
1457 if (strcmp(client_ptr->name, name) == 0)
1459 return client_ptr->client;
1463 return NULL;
1466 ladish_port_handle ladish_graph_find_port_by_name(ladish_graph_handle graph_handle, ladish_client_handle client_handle, const char * name)
1468 struct ladish_graph_client * client_ptr;
1469 struct list_head * node_ptr;
1470 struct ladish_graph_port * port_ptr;
1472 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1473 if (client_ptr != NULL)
1475 list_for_each(node_ptr, &client_ptr->ports)
1477 port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_client);
1478 if (strcmp(port_ptr->name, name) == 0)
1480 return port_ptr->port;
1484 else
1486 ASSERT_NO_PASS;
1489 return NULL;
1492 ladish_client_handle ladish_graph_find_client_by_uuid(ladish_graph_handle graph_handle, const uuid_t uuid)
1494 struct list_head * node_ptr;
1495 struct ladish_graph_client * client_ptr;
1496 uuid_t current_uuid;
1498 list_for_each(node_ptr, &graph_ptr->clients)
1500 client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
1501 ladish_client_get_uuid(client_ptr->client, current_uuid);
1502 if (uuid_compare(current_uuid, uuid) == 0)
1504 return client_ptr->client;
1508 return NULL;
1511 ladish_port_handle ladish_graph_find_port_by_uuid(ladish_graph_handle graph_handle, const uuid_t uuid)
1513 struct list_head * node_ptr;
1514 struct ladish_graph_port * port_ptr;
1515 uuid_t current_uuid;
1517 list_for_each(node_ptr, &graph_ptr->ports)
1519 port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph);
1520 ladish_port_get_uuid(port_ptr->port, current_uuid);
1521 if (uuid_compare(current_uuid, uuid) == 0)
1523 return port_ptr->port;
1527 return NULL;
1530 ladish_client_handle ladish_graph_get_port_client(ladish_graph_handle graph_handle, ladish_port_handle port_handle)
1532 struct ladish_graph_port * port_ptr;
1534 port_ptr = ladish_graph_find_port(graph_ptr, port_handle);
1535 if (port_ptr == NULL)
1537 return NULL;
1540 return port_ptr->client_ptr->client;
1543 bool ladish_graph_is_port_present(ladish_graph_handle graph_handle, ladish_port_handle port_handle)
1545 return ladish_graph_find_port(graph_ptr, port_handle) != NULL;
1548 ladish_client_handle ladish_graph_find_client_by_id(ladish_graph_handle graph_handle, uint64_t client_id)
1550 struct list_head * node_ptr;
1551 struct ladish_graph_client * client_ptr;
1553 list_for_each(node_ptr, &graph_ptr->clients)
1555 client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
1556 if (client_ptr->id == client_id)
1558 return client_ptr->client;
1562 return NULL;
1565 ladish_port_handle ladish_graph_find_port_by_id(ladish_graph_handle graph_handle, uint64_t port_id)
1567 struct ladish_graph_port * port_ptr;
1569 port_ptr = ladish_graph_find_port_by_id_internal(graph_ptr, port_id);
1570 if (port_ptr == NULL)
1572 return NULL;
1575 return port_ptr->port;
1578 ladish_client_handle ladish_graph_find_client_by_jack_id(ladish_graph_handle graph_handle, uint64_t client_id)
1580 struct list_head * node_ptr;
1581 struct ladish_graph_client * client_ptr;
1583 list_for_each(node_ptr, &graph_ptr->clients)
1585 client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
1586 if (ladish_client_get_jack_id(client_ptr->client) == client_id)
1588 return client_ptr->client;
1592 return NULL;
1595 ladish_port_handle ladish_graph_find_port_by_jack_id(ladish_graph_handle graph_handle, uint64_t port_id)
1597 struct list_head * node_ptr;
1598 struct ladish_graph_port * port_ptr;
1600 list_for_each(node_ptr, &graph_ptr->ports)
1602 port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph);
1603 if (ladish_port_get_jack_id(port_ptr->port) == port_id)
1605 return port_ptr->port;
1609 return NULL;
1612 ladish_client_handle
1613 ladish_graph_remove_port(
1614 ladish_graph_handle graph_handle,
1615 ladish_port_handle port)
1617 struct ladish_graph_port * port_ptr;
1619 port_ptr = ladish_graph_find_port(graph_ptr, port);
1620 if (port_ptr == NULL)
1622 return NULL;
1625 ladish_graph_remove_port_internal(graph_ptr, port_ptr->client_ptr, port_ptr, false);
1626 return port_ptr->client_ptr->client;
1629 bool
1630 ladish_graph_rename_port(
1631 ladish_graph_handle graph_handle,
1632 ladish_port_handle port_handle,
1633 const char * new_port_name)
1635 char * name;
1636 struct ladish_graph_port * port_ptr;
1637 char * old_name;
1639 name = strdup(new_port_name);
1640 if (name == NULL)
1642 log_error("strdup('%s') failed.", new_port_name);
1643 return false;
1646 port_ptr = ladish_graph_find_port(graph_ptr, port_handle);
1647 if (port_ptr == NULL)
1649 ASSERT_NO_PASS;
1650 free(name);
1651 return false;
1654 old_name = port_ptr->name;
1655 port_ptr->name = name;
1657 graph_ptr->graph_version++;
1659 if (!port_ptr->hidden && graph_ptr->opath != NULL)
1661 dbus_signal_emit(
1662 g_dbus_connection,
1663 graph_ptr->opath,
1664 JACKDBUS_IFACE_PATCHBAY,
1665 "PortRenamed",
1666 "ttstss",
1667 &graph_ptr->graph_version,
1668 &port_ptr->client_ptr->id,
1669 &port_ptr->client_ptr->name,
1670 &port_ptr->id,
1671 &old_name,
1672 &port_ptr->name);
1675 free(old_name);
1677 return true;
1680 const char * ladish_graph_get_client_name(ladish_graph_handle graph_handle, ladish_client_handle client_handle)
1682 struct ladish_graph_client * client_ptr;
1684 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1685 if (client_ptr != NULL)
1687 return client_ptr->name;
1690 ASSERT_NO_PASS;
1691 return NULL;
1694 bool ladish_graph_is_client_empty(ladish_graph_handle graph_handle, ladish_client_handle client_handle)
1696 struct ladish_graph_client * client_ptr;
1698 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1699 if (client_ptr != NULL)
1701 return list_empty(&client_ptr->ports);
1704 ASSERT_NO_PASS;
1705 return true;
1708 bool ladish_graph_is_client_looks_empty(ladish_graph_handle graph_handle, ladish_client_handle client_handle)
1710 struct ladish_graph_client * client_ptr;
1711 struct list_head * node_ptr;
1712 struct ladish_graph_port * port_ptr;
1714 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1715 if (client_ptr != NULL)
1717 list_for_each(node_ptr, &client_ptr->ports)
1719 port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_client);
1720 if (!port_ptr->hidden)
1722 //log_info("port '%s' is visible, client '%s' does not look empty", port_ptr->name, client_ptr->name);
1723 return false;
1725 else
1727 //log_info("port '%s' is invisible", port_ptr->name);
1731 log_info("client '%s' looks empty in graph %s", client_ptr->name, graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
1732 return true;
1735 ASSERT_NO_PASS;
1736 return true;
1739 void ladish_try_connect_hidden_connections(ladish_graph_handle graph_handle)
1741 struct list_head * node_ptr;
1742 struct ladish_graph_connection * connection_ptr;
1744 if (graph_ptr->connect_handler == NULL)
1746 ASSERT_NO_PASS;
1747 return;
1750 ASSERT(graph_ptr->opath != NULL);
1752 list_for_each(node_ptr, &graph_ptr->connections)
1754 connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
1755 if (connection_ptr->hidden &&
1756 !connection_ptr->changing &&
1757 !connection_ptr->port1_ptr->hidden &&
1758 !connection_ptr->port2_ptr->hidden)
1760 log_info(
1761 "auto connecting '%s':'%s' to '%s':'%s'",
1762 connection_ptr->port1_ptr->client_ptr->name,
1763 connection_ptr->port1_ptr->name,
1764 connection_ptr->port2_ptr->client_ptr->name,
1765 connection_ptr->port2_ptr->name);
1767 connection_ptr->changing = true;
1768 if (!graph_ptr->connect_handler(graph_ptr->context, graph_handle, connection_ptr->port1_ptr->port, connection_ptr->port2_ptr->port))
1770 connection_ptr->changing = false;
1771 log_error("auto connect failed.");
1777 void ladish_graph_hide_all(ladish_graph_handle graph_handle)
1779 struct list_head * node_ptr;
1780 struct ladish_graph_connection * connection_ptr;
1781 struct ladish_graph_port * port_ptr;
1782 struct ladish_graph_client * client_ptr;
1784 log_info("hiding everything in graph %s", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
1786 list_for_each(node_ptr, &graph_ptr->connections)
1788 connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
1789 if (!connection_ptr->hidden)
1791 log_debug("hidding connection between ports %"PRIu64" and %"PRIu64, connection_ptr->port1_ptr->id, connection_ptr->port2_ptr->id);
1792 ladish_graph_hide_connection_internal(graph_ptr, connection_ptr);
1796 list_for_each(node_ptr, &graph_ptr->ports)
1798 port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph);
1799 if (!port_ptr->hidden)
1801 ladish_port_set_jack_id(port_ptr->port, 0);
1802 ladish_graph_hide_port_internal(graph_ptr, port_ptr);
1806 list_for_each(node_ptr, &graph_ptr->clients)
1808 client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
1809 if (!client_ptr->hidden)
1811 ladish_client_set_jack_id(client_ptr->client, 0);
1812 ladish_graph_hide_client_internal(graph_ptr, client_ptr);
1817 bool
1818 ladish_graph_iterate_nodes(
1819 ladish_graph_handle graph_handle,
1820 void * callback_context,
1821 bool
1822 (* client_begin_callback)(
1823 void * context,
1824 ladish_client_handle client_handle,
1825 const char * client_name,
1826 void ** client_iteration_context_ptr_ptr),
1827 bool
1828 (* port_callback)(
1829 void * context,
1830 void * client_iteration_context_ptr,
1831 ladish_client_handle client_handle,
1832 const char * client_name,
1833 ladish_port_handle port_handle,
1834 const char * port_name,
1835 uint32_t port_type,
1836 uint32_t port_flags),
1837 bool
1838 (* client_end_callback)(
1839 void * context,
1840 ladish_client_handle client_handle,
1841 const char * client_name,
1842 void * client_iteration_context_ptr))
1844 struct list_head * client_node_ptr;
1845 struct ladish_graph_client * client_ptr;
1846 void * client_context;
1847 struct list_head * port_node_ptr;
1848 struct ladish_graph_port * port_ptr;
1850 list_for_each(client_node_ptr, &graph_ptr->clients)
1852 client_ptr = list_entry(client_node_ptr, struct ladish_graph_client, siblings);
1854 if (client_ptr->hidden)
1856 continue;
1859 if (!client_begin_callback(callback_context, client_ptr->client, client_ptr->name, &client_context))
1861 return false;
1864 list_for_each(port_node_ptr, &client_ptr->ports)
1866 port_ptr = list_entry(port_node_ptr, struct ladish_graph_port, siblings_client);
1868 if (port_ptr->hidden)
1870 continue;
1873 if (!port_callback(
1874 callback_context,
1875 client_context,
1876 client_ptr->client,
1877 client_ptr->name,
1878 port_ptr->port,
1879 port_ptr->name,
1880 port_ptr->type,
1881 port_ptr->flags))
1883 return false;
1887 if (!client_end_callback(callback_context, client_ptr->client, client_ptr->name, &client_context))
1889 return false;
1893 return true;
1896 bool
1897 ladish_graph_iterate_connections(
1898 ladish_graph_handle graph_handle,
1899 void * callback_context,
1900 bool (* callback)(void * context, ladish_port_handle port1_handle, ladish_port_handle port2_handle, ladish_dict_handle dict))
1902 struct list_head * node_ptr;
1903 struct ladish_graph_connection * connection_ptr;
1905 list_for_each(node_ptr, &graph_ptr->connections)
1907 connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
1909 if (connection_ptr->hidden)
1911 continue;
1914 if (!callback(callback_context, connection_ptr->port1_ptr->port, connection_ptr->port2_ptr->port, connection_ptr->dict))
1916 return false;
1920 return true;
1923 static
1924 bool
1925 dump_dict_entry(
1926 void * context,
1927 const char * key,
1928 const char * value)
1930 log_info("%s key '%s' with value '%s'", (const char *)context, key, value);
1931 return true;
1934 static
1935 void
1936 dump_dict(
1937 const char * indent,
1938 ladish_dict_handle dict)
1940 if (ladish_dict_is_empty(dict))
1942 return;
1945 log_info("%sdict:", indent);
1946 ladish_dict_iterate(dict, (void *)indent, dump_dict_entry);
1949 void ladish_graph_dump(ladish_graph_handle graph_handle)
1951 struct list_head * client_node_ptr;
1952 struct ladish_graph_client * client_ptr;
1953 struct list_head * port_node_ptr;
1954 struct ladish_graph_port * port_ptr;
1955 struct list_head * connection_node_ptr;
1956 struct ladish_graph_connection * connection_ptr;
1958 log_info("graph %s", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
1959 log_info(" version %"PRIu64, graph_ptr->graph_version);
1960 dump_dict(" ", graph_ptr->dict);
1961 log_info(" clients:");
1962 list_for_each(client_node_ptr, &graph_ptr->clients)
1964 client_ptr = list_entry(client_node_ptr, struct ladish_graph_client, siblings);
1965 log_info(" %s client '%s', id=%"PRIu64", ptr=%p", client_ptr->hidden ? "invisible" : "visible", client_ptr->name, client_ptr->id, client_ptr->client);
1966 dump_dict(" ", ladish_client_get_dict(client_ptr->client));
1967 log_info(" ports:");
1968 list_for_each(port_node_ptr, &client_ptr->ports)
1970 port_ptr = list_entry(port_node_ptr, struct ladish_graph_port, siblings_client);
1972 log_info(" %s port '%s', id=%"PRIu64", type=0x%"PRIX32", flags=0x%"PRIX32", ptr=%p", port_ptr->hidden ? "invisible" : "visible", port_ptr->name, port_ptr->id, port_ptr->type, port_ptr->flags, port_ptr->port);
1973 dump_dict(" ", ladish_port_get_dict(port_ptr->port));
1976 log_info(" connections:");
1977 list_for_each(connection_node_ptr, &graph_ptr->connections)
1979 connection_ptr = list_entry(connection_node_ptr, struct ladish_graph_connection, siblings);
1981 log_info(
1982 " %s connection '%s':'%s' - '%s':'%s'%s",
1983 connection_ptr->hidden ? "invisible" : "visible",
1984 connection_ptr->port1_ptr->client_ptr->name,
1985 connection_ptr->port1_ptr->name,
1986 connection_ptr->port2_ptr->client_ptr->name,
1987 connection_ptr->port2_ptr->name,
1988 connection_ptr->changing ? " [changing]" : "");
1989 dump_dict(" ", connection_ptr->dict);
1993 #undef graph_ptr
1995 METHOD_ARGS_BEGIN(GetAllPorts, "Get all ports")
1996 METHOD_ARG_DESCRIBE_IN("ports_list", "as", "List of all ports")
1997 METHOD_ARGS_END
1999 METHOD_ARGS_BEGIN(GetGraph, "Get whole graph")
2000 METHOD_ARG_DESCRIBE_IN("known_graph_version", DBUS_TYPE_UINT64_AS_STRING, "Known graph version")
2001 METHOD_ARG_DESCRIBE_OUT("current_graph_version", DBUS_TYPE_UINT64_AS_STRING, "Current graph version")
2002 METHOD_ARG_DESCRIBE_OUT("clients_and_ports", "a(tsa(tsuu))", "Clients and their ports")
2003 METHOD_ARG_DESCRIBE_OUT("connections", "a(tstststst)", "Connections array")
2004 METHOD_ARGS_END
2006 METHOD_ARGS_BEGIN(ConnectPortsByName, "Connect ports")
2007 METHOD_ARG_DESCRIBE_IN("client1_name", DBUS_TYPE_STRING_AS_STRING, "name first port client")
2008 METHOD_ARG_DESCRIBE_IN("port1_name", DBUS_TYPE_STRING_AS_STRING, "name of first port")
2009 METHOD_ARG_DESCRIBE_IN("client2_name", DBUS_TYPE_STRING_AS_STRING, "name second port client")
2010 METHOD_ARG_DESCRIBE_IN("port2_name", DBUS_TYPE_STRING_AS_STRING, "name of second port")
2011 METHOD_ARGS_END
2013 METHOD_ARGS_BEGIN(ConnectPortsByID, "Connect ports")
2014 METHOD_ARG_DESCRIBE_IN("port1_id", DBUS_TYPE_UINT64_AS_STRING, "id of first port")
2015 METHOD_ARG_DESCRIBE_IN("port2_id", DBUS_TYPE_UINT64_AS_STRING, "if of second port")
2016 METHOD_ARGS_END
2018 METHOD_ARGS_BEGIN(DisconnectPortsByName, "Disconnect ports")
2019 METHOD_ARG_DESCRIBE_IN("client1_name", DBUS_TYPE_STRING_AS_STRING, "name first port client")
2020 METHOD_ARG_DESCRIBE_IN("port1_name", DBUS_TYPE_STRING_AS_STRING, "name of first port")
2021 METHOD_ARG_DESCRIBE_IN("client2_name", DBUS_TYPE_STRING_AS_STRING, "name second port client")
2022 METHOD_ARG_DESCRIBE_IN("port2_name", DBUS_TYPE_STRING_AS_STRING, "name of second port")
2023 METHOD_ARGS_END
2025 METHOD_ARGS_BEGIN(DisconnectPortsByID, "Disconnect ports")
2026 METHOD_ARG_DESCRIBE_IN("port1_id", DBUS_TYPE_UINT64_AS_STRING, "id of first port")
2027 METHOD_ARG_DESCRIBE_IN("port2_id", DBUS_TYPE_UINT64_AS_STRING, "if of second port")
2028 METHOD_ARGS_END
2030 METHOD_ARGS_BEGIN(DisconnectPortsByConnectionID, "Disconnect ports")
2031 METHOD_ARG_DESCRIBE_IN("connection_id", DBUS_TYPE_UINT64_AS_STRING, "id of connection to disconnect")
2032 METHOD_ARGS_END
2034 METHOD_ARGS_BEGIN(GetClientPID, "get process id of client")
2035 METHOD_ARG_DESCRIBE_IN("client_id", DBUS_TYPE_UINT64_AS_STRING, "id of client")
2036 METHOD_ARG_DESCRIBE_OUT("process_id", DBUS_TYPE_INT64_AS_STRING, "pid of client")
2037 METHOD_ARGS_END
2039 METHODS_BEGIN
2040 METHOD_DESCRIBE(GetAllPorts, get_all_ports)
2041 METHOD_DESCRIBE(GetGraph, get_graph)
2042 METHOD_DESCRIBE(ConnectPortsByName, connect_ports_by_name)
2043 METHOD_DESCRIBE(ConnectPortsByID, connect_ports_by_id)
2044 METHOD_DESCRIBE(DisconnectPortsByName, disconnect_ports_by_name)
2045 METHOD_DESCRIBE(DisconnectPortsByID, disconnect_ports_by_id)
2046 METHOD_DESCRIBE(DisconnectPortsByConnectionID, disconnect_ports_by_connection_id)
2047 METHOD_DESCRIBE(GetClientPID, get_client_pid)
2048 METHODS_END
2050 SIGNAL_ARGS_BEGIN(GraphChanged, "")
2051 SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
2052 SIGNAL_ARGS_END
2054 SIGNAL_ARGS_BEGIN(ClientAppeared, "")
2055 SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
2056 SIGNAL_ARG_DESCRIBE("client_id", DBUS_TYPE_UINT64_AS_STRING, "")
2057 SIGNAL_ARG_DESCRIBE("client_name", DBUS_TYPE_STRING_AS_STRING, "")
2058 SIGNAL_ARGS_END
2060 SIGNAL_ARGS_BEGIN(ClientDisappeared, "")
2061 SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
2062 SIGNAL_ARG_DESCRIBE("client_id", DBUS_TYPE_UINT64_AS_STRING, "")
2063 SIGNAL_ARG_DESCRIBE("client_name", DBUS_TYPE_STRING_AS_STRING, "")
2064 SIGNAL_ARGS_END
2066 SIGNAL_ARGS_BEGIN(PortAppeared, "")
2067 SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
2068 SIGNAL_ARG_DESCRIBE("client_id", DBUS_TYPE_UINT64_AS_STRING, "")
2069 SIGNAL_ARG_DESCRIBE("client_name", DBUS_TYPE_STRING_AS_STRING, "")
2070 SIGNAL_ARG_DESCRIBE("port_id", DBUS_TYPE_UINT64_AS_STRING, "")
2071 SIGNAL_ARG_DESCRIBE("port_name", DBUS_TYPE_STRING_AS_STRING, "")
2072 SIGNAL_ARG_DESCRIBE("port_flags", DBUS_TYPE_UINT32_AS_STRING, "")
2073 SIGNAL_ARG_DESCRIBE("port_type", DBUS_TYPE_UINT32_AS_STRING, "")
2074 SIGNAL_ARGS_END
2076 SIGNAL_ARGS_BEGIN(PortDisappeared, "")
2077 SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
2078 SIGNAL_ARG_DESCRIBE("client_id", DBUS_TYPE_UINT64_AS_STRING, "")
2079 SIGNAL_ARG_DESCRIBE("client_name", DBUS_TYPE_STRING_AS_STRING, "")
2080 SIGNAL_ARG_DESCRIBE("port_id", DBUS_TYPE_UINT64_AS_STRING, "")
2081 SIGNAL_ARG_DESCRIBE("port_name", DBUS_TYPE_STRING_AS_STRING, "")
2082 SIGNAL_ARGS_END
2084 SIGNAL_ARGS_BEGIN(PortsConnected, "")
2085 SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
2086 SIGNAL_ARG_DESCRIBE("client1_id", DBUS_TYPE_UINT64_AS_STRING, "")
2087 SIGNAL_ARG_DESCRIBE("client1_name", DBUS_TYPE_STRING_AS_STRING, "")
2088 SIGNAL_ARG_DESCRIBE("port1_id", DBUS_TYPE_UINT64_AS_STRING, "")
2089 SIGNAL_ARG_DESCRIBE("port1_name", DBUS_TYPE_STRING_AS_STRING, "")
2090 SIGNAL_ARG_DESCRIBE("client2_id", DBUS_TYPE_UINT64_AS_STRING, "")
2091 SIGNAL_ARG_DESCRIBE("client2_name", DBUS_TYPE_STRING_AS_STRING, "")
2092 SIGNAL_ARG_DESCRIBE("port2_id", DBUS_TYPE_UINT64_AS_STRING, "")
2093 SIGNAL_ARG_DESCRIBE("port2_name", DBUS_TYPE_STRING_AS_STRING, "")
2094 SIGNAL_ARG_DESCRIBE("connection_id", DBUS_TYPE_UINT64_AS_STRING, "")
2095 SIGNAL_ARGS_END
2097 SIGNAL_ARGS_BEGIN(PortsDisconnected, "")
2098 SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
2099 SIGNAL_ARG_DESCRIBE("client1_id", DBUS_TYPE_UINT64_AS_STRING, "")
2100 SIGNAL_ARG_DESCRIBE("client1_name", DBUS_TYPE_STRING_AS_STRING, "")
2101 SIGNAL_ARG_DESCRIBE("port1_id", DBUS_TYPE_UINT64_AS_STRING, "")
2102 SIGNAL_ARG_DESCRIBE("port1_name", DBUS_TYPE_STRING_AS_STRING, "")
2103 SIGNAL_ARG_DESCRIBE("client2_id", DBUS_TYPE_UINT64_AS_STRING, "")
2104 SIGNAL_ARG_DESCRIBE("client2_name", DBUS_TYPE_STRING_AS_STRING, "")
2105 SIGNAL_ARG_DESCRIBE("port2_id", DBUS_TYPE_UINT64_AS_STRING, "")
2106 SIGNAL_ARG_DESCRIBE("port2_name", DBUS_TYPE_STRING_AS_STRING, "")
2107 SIGNAL_ARG_DESCRIBE("connection_id", DBUS_TYPE_UINT64_AS_STRING, "")
2108 SIGNAL_ARGS_END
2110 SIGNALS_BEGIN
2111 SIGNAL_DESCRIBE(GraphChanged)
2112 SIGNAL_DESCRIBE(ClientAppeared)
2113 SIGNAL_DESCRIBE(ClientDisappeared)
2114 SIGNAL_DESCRIBE(PortAppeared)
2115 SIGNAL_DESCRIBE(PortDisappeared)
2116 SIGNAL_DESCRIBE(PortsConnected)
2117 SIGNAL_DESCRIBE(PortsDisconnected)
2118 SIGNALS_END
2120 INTERFACE_BEGIN(g_interface_patchbay, JACKDBUS_IFACE_PATCHBAY)
2121 INTERFACE_DEFAULT_HANDLER
2122 INTERFACE_EXPOSE_METHODS
2123 INTERFACE_EXPOSE_SIGNALS
2124 INTERFACE_END