daemon: when destroying room, remove its hidden app ports. Fixes #87
[ladish.git] / daemon / graph.c
blob7f8458c663d08b409d09301a9760e1ccea45bcf7
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_connection * ladish_graph_find_connection_by_id(struct ladish_graph * graph_ptr, uint64_t connection_id)
106 struct list_head * node_ptr;
107 struct ladish_graph_connection * connection_ptr;
109 list_for_each(node_ptr, &graph_ptr->connections)
111 connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
112 if (connection_ptr->id == connection_id)
114 return connection_ptr;
118 return NULL;
121 static
122 struct ladish_graph_connection *
123 ladish_graph_find_connection_by_ports(
124 struct ladish_graph * graph_ptr,
125 struct ladish_graph_port * port1_ptr,
126 struct ladish_graph_port * port2_ptr)
128 struct list_head * node_ptr;
129 struct ladish_graph_connection * connection_ptr;
131 list_for_each(node_ptr, &graph_ptr->connections)
133 connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
134 if ((connection_ptr->port1_ptr == port1_ptr && connection_ptr->port2_ptr == port2_ptr) ||
135 (connection_ptr->port1_ptr == port2_ptr && connection_ptr->port2_ptr == port1_ptr))
137 return connection_ptr;
141 return NULL;
144 #define graph_ptr ((struct ladish_graph *)call_ptr->iface_context)
146 static void get_all_ports(struct dbus_method_call * call_ptr)
148 DBusMessageIter iter, sub_iter;
150 call_ptr->reply = dbus_message_new_method_return(call_ptr->message);
151 if (call_ptr->reply == NULL)
153 goto fail;
156 dbus_message_iter_init_append(call_ptr->reply, &iter);
158 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub_iter))
160 goto fail_unref;
163 if (!dbus_message_iter_close_container(&iter, &sub_iter))
165 goto fail_unref;
168 return;
170 fail_unref:
171 dbus_message_unref(call_ptr->reply);
172 call_ptr->reply = NULL;
174 fail:
175 log_error("Ran out of memory trying to construct method return");
178 static void get_graph(struct dbus_method_call * call_ptr)
180 dbus_uint64_t known_version;
181 dbus_uint64_t current_version;
182 DBusMessageIter iter;
183 DBusMessageIter clients_array_iter;
184 DBusMessageIter connections_array_iter;
185 DBusMessageIter client_struct_iter;
186 struct list_head * client_node_ptr;
187 struct ladish_graph_client * client_ptr;
188 DBusMessageIter ports_array_iter;
189 struct list_head * port_node_ptr;
190 struct ladish_graph_port * port_ptr;
191 DBusMessageIter port_struct_iter;
192 struct list_head * connection_node_ptr;
193 struct ladish_graph_connection * connection_ptr;
194 DBusMessageIter connection_struct_iter;
196 //log_info("get_graph() called");
198 if (!dbus_message_get_args(call_ptr->message, &g_dbus_error, DBUS_TYPE_UINT64, &known_version, DBUS_TYPE_INVALID))
200 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, g_dbus_error.message);
201 dbus_error_free(&g_dbus_error);
202 return;
205 //log_info("Getting graph, known version is %" PRIu64, known_version);
207 call_ptr->reply = dbus_message_new_method_return(call_ptr->message);
208 if (call_ptr->reply == NULL)
210 log_error("Ran out of memory trying to construct method return");
211 goto exit;
214 dbus_message_iter_init_append(call_ptr->reply, &iter);
216 current_version = graph_ptr->graph_version;
217 if (known_version > current_version)
219 lash_dbus_error(
220 call_ptr,
221 LASH_DBUS_ERROR_INVALID_ARGS,
222 "known graph version %" PRIu64 " is newer than actual version %" PRIu64,
223 known_version,
224 current_version);
225 goto exit;
228 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT64, &current_version))
230 goto nomem;
233 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(tsa(tsuu))", &clients_array_iter))
235 goto nomem;
238 if (known_version < current_version)
240 list_for_each(client_node_ptr, &graph_ptr->clients)
242 client_ptr = list_entry(client_node_ptr, struct ladish_graph_client, siblings);
244 if (client_ptr->hidden)
246 continue;
249 if (!dbus_message_iter_open_container (&clients_array_iter, DBUS_TYPE_STRUCT, NULL, &client_struct_iter))
251 goto nomem_close_clients_array;
254 if (!dbus_message_iter_append_basic(&client_struct_iter, DBUS_TYPE_UINT64, &client_ptr->id))
256 goto nomem_close_client_struct;
259 log_info("client '%s' (%llu)", client_ptr->name, (unsigned long long)client_ptr->id);
260 if (!dbus_message_iter_append_basic(&client_struct_iter, DBUS_TYPE_STRING, &client_ptr->name))
262 goto nomem_close_client_struct;
265 if (!dbus_message_iter_open_container(&client_struct_iter, DBUS_TYPE_ARRAY, "(tsuu)", &ports_array_iter))
267 goto nomem_close_client_struct;
270 list_for_each(port_node_ptr, &client_ptr->ports)
272 port_ptr = list_entry(port_node_ptr, struct ladish_graph_port, siblings_client);
274 if (port_ptr->hidden)
276 continue;
279 if (!dbus_message_iter_open_container(&ports_array_iter, DBUS_TYPE_STRUCT, NULL, &port_struct_iter))
281 goto nomem_close_ports_array;
284 if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT64, &port_ptr->id))
286 goto nomem_close_port_struct;
289 if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_STRING, &port_ptr->name))
291 goto nomem_close_port_struct;
294 if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT32, &port_ptr->flags))
296 goto nomem_close_port_struct;
299 if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT32, &port_ptr->type))
301 goto nomem_close_port_struct;
304 if (!dbus_message_iter_close_container(&ports_array_iter, &port_struct_iter))
306 goto nomem_close_ports_array;
310 if (!dbus_message_iter_close_container(&client_struct_iter, &ports_array_iter))
312 goto nomem_close_client_struct;
315 if (!dbus_message_iter_close_container(&clients_array_iter, &client_struct_iter))
317 goto nomem_close_clients_array;
322 if (!dbus_message_iter_close_container(&iter, &clients_array_iter))
324 goto nomem;
327 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(tstststst)", &connections_array_iter))
329 goto nomem;
332 if (known_version < current_version)
334 list_for_each(connection_node_ptr, &graph_ptr->connections)
336 connection_ptr = list_entry(connection_node_ptr, struct ladish_graph_connection, siblings);
338 if (connection_ptr->hidden)
340 continue;
343 if (!dbus_message_iter_open_container(&connections_array_iter, DBUS_TYPE_STRUCT, NULL, &connection_struct_iter))
345 goto nomem_close_connections_array;
348 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port1_ptr->client_ptr->id))
350 goto nomem_close_connection_struct;
353 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port1_ptr->client_ptr->name))
355 goto nomem_close_connection_struct;
358 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port1_ptr->id))
360 goto nomem_close_connection_struct;
363 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port1_ptr->name))
365 goto nomem_close_connection_struct;
368 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port2_ptr->client_ptr->id))
370 goto nomem_close_connection_struct;
373 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port2_ptr->client_ptr->name))
375 goto nomem_close_connection_struct;
378 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port2_ptr->id))
380 goto nomem_close_connection_struct;
383 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port2_ptr->name))
385 goto nomem_close_connection_struct;
388 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->id))
390 goto nomem_close_connection_struct;
393 if (!dbus_message_iter_close_container(&connections_array_iter, &connection_struct_iter))
395 goto nomem_close_connections_array;
400 if (!dbus_message_iter_close_container(&iter, &connections_array_iter))
402 goto nomem;
405 return;
407 nomem_close_connection_struct:
408 dbus_message_iter_close_container(&connections_array_iter, &connection_struct_iter);
410 nomem_close_connections_array:
411 dbus_message_iter_close_container(&iter, &connections_array_iter);
412 goto nomem;
414 nomem_close_port_struct:
415 dbus_message_iter_close_container(&ports_array_iter, &port_struct_iter);
417 nomem_close_ports_array:
418 dbus_message_iter_close_container(&client_struct_iter, &ports_array_iter);
420 nomem_close_client_struct:
421 dbus_message_iter_close_container(&clients_array_iter, &client_struct_iter);
423 nomem_close_clients_array:
424 dbus_message_iter_close_container(&iter, &clients_array_iter);
426 nomem:
427 dbus_message_unref(call_ptr->reply);
428 call_ptr->reply = NULL;
429 log_error("Ran out of memory trying to construct method return");
431 exit:
432 return;
435 static void connect_ports_by_name(struct dbus_method_call * call_ptr)
437 log_info("connect_ports_by_name() called.");
438 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "connect by name is not implemented yet");
441 static void connect_ports_by_id(struct dbus_method_call * call_ptr)
443 dbus_uint64_t port1_id;
444 dbus_uint64_t port2_id;
445 struct ladish_graph_port * port1_ptr;
446 struct ladish_graph_port * port2_ptr;
448 if (!dbus_message_get_args(call_ptr->message, &g_dbus_error, DBUS_TYPE_UINT64, &port1_id, DBUS_TYPE_UINT64, &port2_id, DBUS_TYPE_INVALID))
450 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, g_dbus_error.message);
451 dbus_error_free(&g_dbus_error);
452 return;
455 log_info("connect_ports_by_id(%"PRIu64",%"PRIu64") called.", port1_id, port2_id);
457 if (graph_ptr->connect_handler == NULL)
459 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");
460 return;
463 port1_ptr = ladish_graph_find_port_by_id_internal(graph_ptr, port1_id);
464 if (port1_ptr == NULL)
466 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot connect unknown port with id %"PRIu64, port1_id);
467 return;
470 port2_ptr = ladish_graph_find_port_by_id_internal(graph_ptr, port2_id);
471 if (port2_ptr == NULL)
473 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot connect unknown port with id %"PRIu64, port2_id);
474 return;
477 log_info("connecting '%s':'%s' to '%s':'%s'", port1_ptr->client_ptr->name, port1_ptr->name, port2_ptr->client_ptr->name, port2_ptr->name);
479 if (graph_ptr->connect_handler(graph_ptr->context, (ladish_graph_handle)graph_ptr, port1_ptr->port, port2_ptr->port))
481 method_return_new_void(call_ptr);
483 else
485 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "connect failed");
489 static void disconnect_ports(struct dbus_method_call * call_ptr, struct ladish_graph_connection * connection_ptr)
491 log_info(
492 "disconnecting '%s':'%s' from '%s':'%s'",
493 connection_ptr->port1_ptr->client_ptr->name,
494 connection_ptr->port1_ptr->name,
495 connection_ptr->port2_ptr->client_ptr->name,
496 connection_ptr->port2_ptr->name);
498 connection_ptr->changing = true;
499 if (graph_ptr->disconnect_handler(graph_ptr->context, (ladish_graph_handle)graph_ptr, connection_ptr->id))
501 method_return_new_void(call_ptr);
503 else
505 connection_ptr->changing = false;
506 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "disconnect failed");
510 static void disconnect_ports_by_name(struct dbus_method_call * call_ptr)
512 log_info("disconnect_ports_by_name() called.");
513 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "disconnect by name is not implemented yet");
516 static void disconnect_ports_by_id(struct dbus_method_call * call_ptr)
518 dbus_uint64_t port1_id;
519 dbus_uint64_t port2_id;
520 struct ladish_graph_port * port1_ptr;
521 struct ladish_graph_port * port2_ptr;
522 struct ladish_graph_connection * connection_ptr;
524 if (!dbus_message_get_args(call_ptr->message, &g_dbus_error, DBUS_TYPE_UINT64, &port1_id, DBUS_TYPE_UINT64, &port2_id, DBUS_TYPE_INVALID))
526 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, g_dbus_error.message);
527 dbus_error_free(&g_dbus_error);
528 return;
531 log_info("disconnect_ports_by_id(%"PRIu64",%"PRIu64") called.", port1_id, port2_id);
533 if (graph_ptr->disconnect_handler == NULL)
535 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");
536 return;
539 port1_ptr = ladish_graph_find_port_by_id_internal(graph_ptr, port1_id);
540 if (port1_ptr == NULL)
542 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot disconnect unknown port with id %"PRIu64, port1_id);
543 return;
546 port2_ptr = ladish_graph_find_port_by_id_internal(graph_ptr, port2_id);
547 if (port2_ptr == NULL)
549 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot disconnect unknown port with id %"PRIu64, port2_id);
550 return;
553 connection_ptr = ladish_graph_find_connection_by_ports(graph_ptr, port1_ptr, port2_ptr);
554 if (connection_ptr == NULL)
556 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot disconnect not connected ports %"PRIu64" and %"PRIu64, port1_id, port2_id);
557 return;
560 disconnect_ports(call_ptr, connection_ptr);
563 static void disconnect_ports_by_connection_id(struct dbus_method_call * call_ptr)
565 dbus_uint64_t connection_id;
566 struct ladish_graph_connection * connection_ptr;
568 if (!dbus_message_get_args(call_ptr->message, &g_dbus_error, DBUS_TYPE_UINT64, &connection_id, DBUS_TYPE_INVALID))
570 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, g_dbus_error.message);
571 dbus_error_free(&g_dbus_error);
572 return;
575 log_info("disconnect_ports_by_connection_id(%"PRIu64") called.", connection_id);
577 connection_ptr = ladish_graph_find_connection_by_id(graph_ptr, connection_id);
578 if (connection_ptr == NULL)
580 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot find connection with id %"PRIu64, connection_id);
581 return;
584 disconnect_ports(call_ptr, connection_ptr);
587 static void get_client_pid(struct dbus_method_call * call_ptr)
589 int64_t pid = 0;
590 method_return_new_single(call_ptr, DBUS_TYPE_INT64, &pid);
593 #undef graph_ptr
595 bool ladish_graph_create(ladish_graph_handle * graph_handle_ptr, const char * opath)
597 struct ladish_graph * graph_ptr;
599 graph_ptr = malloc(sizeof(struct ladish_graph));
600 if (graph_ptr == NULL)
602 log_error("malloc() failed to allocate struct graph_implementator");
603 return false;
606 if (opath != NULL)
608 graph_ptr->opath = strdup(opath);
609 if (graph_ptr->opath == NULL)
611 log_error("strdup() failed for graph opath");
612 free(graph_ptr);
613 return false;
616 else
618 graph_ptr->opath = NULL;
621 if (!ladish_dict_create(&graph_ptr->dict))
623 log_error("ladish_dict_create() failed for graph");
624 if (graph_ptr->opath != NULL)
626 free(graph_ptr->opath);
628 free(graph_ptr);
629 return false;
632 INIT_LIST_HEAD(&graph_ptr->clients);
633 INIT_LIST_HEAD(&graph_ptr->ports);
634 INIT_LIST_HEAD(&graph_ptr->connections);
636 graph_ptr->graph_version = 1;
637 graph_ptr->next_client_id = 1;
638 graph_ptr->next_port_id = 1;
639 graph_ptr->next_connection_id = 1;
641 graph_ptr->context = NULL;
642 graph_ptr->connect_handler = NULL;
643 graph_ptr->disconnect_handler = NULL;
645 graph_ptr->persist = true;
647 *graph_handle_ptr = (ladish_graph_handle)graph_ptr;
648 return true;
651 static
652 struct ladish_graph_client *
653 ladish_graph_find_client(
654 struct ladish_graph * graph_ptr,
655 ladish_client_handle client)
657 struct list_head * node_ptr;
658 struct ladish_graph_client * client_ptr;
660 list_for_each(node_ptr, &graph_ptr->clients)
662 client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
663 if (client_ptr->client == client)
665 return client_ptr;
669 return NULL;
672 static
673 struct ladish_graph_port *
674 ladish_graph_find_port(
675 struct ladish_graph * graph_ptr,
676 ladish_port_handle port)
678 struct list_head * node_ptr;
679 struct ladish_graph_port * port_ptr;
681 //log_info("searching port %p", port);
683 list_for_each(node_ptr, &graph_ptr->ports)
685 port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph);
686 //log_info("checking port %s:%s, %p", port_ptr->client_ptr->name, port_ptr->name, port_ptr->port);
687 if (port_ptr->port == port)
689 return port_ptr;
693 return NULL;
696 static
697 struct ladish_graph_port *
698 ladish_graph_find_port_by_jack_id_internal(
699 struct ladish_graph * graph_ptr,
700 uint64_t port_id,
701 bool room,
702 bool studio)
704 struct list_head * node_ptr;
705 struct ladish_graph_port * port_ptr;
707 ASSERT(room || studio);
709 list_for_each(node_ptr, &graph_ptr->ports)
711 port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph);
712 //log_info("checking jack port id of port %s:%s, %p", port_ptr->client_ptr->name, port_ptr->name, port_ptr->port);
713 if ((studio && ladish_port_get_jack_id(port_ptr->port) == port_id) ||
714 (room && port_ptr->link && ladish_port_get_jack_id_room(port_ptr->port) == port_id))
716 //log_info("found");
717 return port_ptr;
721 return NULL;
724 #if 0
725 static
726 struct ladish_graph_port *
727 ladish_graph_find_client_port(
728 struct ladish_graph * graph_ptr,
729 struct ladish_graph_client * client_ptr,
730 ladish_port_handle port)
732 struct list_head * node_ptr;
733 struct ladish_graph_port * port_ptr;
735 list_for_each(node_ptr, &client_ptr->ports)
737 port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_client);
738 if (port_ptr->port == port)
740 return port_ptr;
744 return NULL;
746 #endif
748 static void ladish_graph_hide_connection_internal(struct ladish_graph * graph_ptr, struct ladish_graph_connection * connection_ptr)
750 ASSERT(!connection_ptr->hidden);
751 connection_ptr->hidden = true;
752 graph_ptr->graph_version++;
754 if (graph_ptr->opath != NULL)
756 dbus_signal_emit(
757 g_dbus_connection,
758 graph_ptr->opath,
759 JACKDBUS_IFACE_PATCHBAY,
760 "PortsDisconnected",
761 "ttstststst",
762 &graph_ptr->graph_version,
763 &connection_ptr->port1_ptr->client_ptr->id,
764 &connection_ptr->port1_ptr->client_ptr->name,
765 &connection_ptr->port1_ptr->id,
766 &connection_ptr->port1_ptr->name,
767 &connection_ptr->port2_ptr->client_ptr->id,
768 &connection_ptr->port2_ptr->client_ptr->name,
769 &connection_ptr->port2_ptr->id,
770 &connection_ptr->port2_ptr->name,
771 &connection_ptr->id);
775 static void ladish_graph_show_port_internal(struct ladish_graph * graph_ptr, struct ladish_graph_port * port_ptr)
777 if (port_ptr->client_ptr->hidden)
779 port_ptr->client_ptr->hidden = false;
780 graph_ptr->graph_version++;
781 if (graph_ptr->opath != NULL)
783 dbus_signal_emit(
784 g_dbus_connection,
785 graph_ptr->opath,
786 JACKDBUS_IFACE_PATCHBAY,
787 "ClientAppeared",
788 "tts",
789 &graph_ptr->graph_version,
790 &port_ptr->client_ptr->id,
791 &port_ptr->client_ptr->name);
795 ASSERT(port_ptr->hidden);
796 port_ptr->hidden = false;
797 graph_ptr->graph_version++;
798 if (graph_ptr->opath != NULL)
800 dbus_signal_emit(
801 g_dbus_connection,
802 graph_ptr->opath,
803 JACKDBUS_IFACE_PATCHBAY,
804 "PortAppeared",
805 "ttstsuu",
806 &graph_ptr->graph_version,
807 &port_ptr->client_ptr->id,
808 &port_ptr->client_ptr->name,
809 &port_ptr->id,
810 &port_ptr->name,
811 &port_ptr->flags,
812 &port_ptr->type);
814 ladish_try_connect_hidden_connections((ladish_graph_handle)graph_ptr);
818 static void ladish_graph_hide_port_internal(struct ladish_graph * graph_ptr, struct ladish_graph_port * port_ptr)
820 ASSERT(!port_ptr->hidden);
821 port_ptr->hidden = true;
822 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 "PortDisappeared",
831 "ttsts",
832 &graph_ptr->graph_version,
833 &port_ptr->client_ptr->id,
834 &port_ptr->client_ptr->name,
835 &port_ptr->id,
836 &port_ptr->name);
840 static void ladish_graph_hide_client_internal(struct ladish_graph * graph_ptr, struct ladish_graph_client * client_ptr)
842 ASSERT(!client_ptr->hidden);
843 client_ptr->hidden = true;
844 graph_ptr->graph_version++;
846 if (graph_ptr->opath != NULL)
848 dbus_signal_emit(
849 g_dbus_connection,
850 graph_ptr->opath,
851 JACKDBUS_IFACE_PATCHBAY,
852 "ClientDisappeared",
853 "tts",
854 &graph_ptr->graph_version,
855 &client_ptr->id,
856 &client_ptr->name);
860 static void ladish_hide_connections(struct ladish_graph * graph_ptr, struct ladish_graph_port * port_ptr)
862 struct list_head * node_ptr;
863 struct ladish_graph_connection * connection_ptr;
865 log_info("hidding connections of port %"PRIu64, port_ptr->id);
867 ASSERT(graph_ptr->opath != NULL);
869 list_for_each(node_ptr, &graph_ptr->connections)
871 connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
872 if (!connection_ptr->hidden && (connection_ptr->port1_ptr == port_ptr || connection_ptr->port2_ptr == port_ptr))
874 log_info("hidding connection between ports %"PRIu64" and %"PRIu64, connection_ptr->port1_ptr->id, connection_ptr->port2_ptr->id);
875 ladish_graph_hide_connection_internal(graph_ptr, connection_ptr);
880 static void ladish_graph_remove_connection_internal(struct ladish_graph * graph_ptr, struct ladish_graph_connection * connection_ptr)
882 list_del(&connection_ptr->siblings);
883 graph_ptr->graph_version++;
885 if (!connection_ptr->hidden && graph_ptr->opath != NULL)
887 dbus_signal_emit(
888 g_dbus_connection,
889 graph_ptr->opath,
890 JACKDBUS_IFACE_PATCHBAY,
891 "PortsDisconnected",
892 "ttstststst",
893 &graph_ptr->graph_version,
894 &connection_ptr->port1_ptr->client_ptr->id,
895 &connection_ptr->port1_ptr->client_ptr->name,
896 &connection_ptr->port1_ptr->id,
897 &connection_ptr->port1_ptr->name,
898 &connection_ptr->port2_ptr->client_ptr->id,
899 &connection_ptr->port2_ptr->client_ptr->name,
900 &connection_ptr->port2_ptr->id,
901 &connection_ptr->port2_ptr->name,
902 &connection_ptr->id);
905 ladish_dict_destroy(connection_ptr->dict);
906 free(connection_ptr);
909 static void ladish_graph_remove_port_connections(struct ladish_graph * graph_ptr, struct ladish_graph_port * port_ptr)
911 struct list_head * node_ptr;
912 struct list_head * temp_node_ptr;
913 struct ladish_graph_connection * connection_ptr;
915 list_for_each_safe(node_ptr, temp_node_ptr, &graph_ptr->connections)
917 connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
918 if (connection_ptr->port1_ptr == port_ptr || connection_ptr->port2_ptr == port_ptr)
920 log_info("removing connection between ports %"PRIu64" and %"PRIu64, connection_ptr->port1_ptr->id, connection_ptr->port2_ptr->id);
921 ladish_graph_remove_connection_internal(graph_ptr, connection_ptr);
926 static
927 void
928 ladish_graph_remove_port_internal(
929 struct ladish_graph * graph_ptr,
930 struct ladish_graph_client * client_ptr,
931 struct ladish_graph_port * port_ptr)
933 ladish_graph_remove_port_connections(graph_ptr, port_ptr);
935 ladish_port_del_ref(port_ptr->port);
937 list_del(&port_ptr->siblings_client);
938 list_del(&port_ptr->siblings_graph);
940 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");
941 if (graph_ptr->opath != NULL && !port_ptr->hidden)
943 dbus_signal_emit(
944 g_dbus_connection,
945 graph_ptr->opath,
946 JACKDBUS_IFACE_PATCHBAY,
947 "PortDisappeared",
948 "ttsts",
949 &graph_ptr->graph_version,
950 &client_ptr->id,
951 &client_ptr->name,
952 &port_ptr->id,
953 &port_ptr->name);
956 free(port_ptr->name);
957 free(port_ptr);
960 static
961 void
962 ladish_graph_remove_client_internal(
963 struct ladish_graph * graph_ptr,
964 struct ladish_graph_client * client_ptr,
965 bool destroy_client,
966 ladish_graph_simple_port_callback port_callback)
968 struct ladish_graph_port * port_ptr;
970 while (!list_empty(&client_ptr->ports))
972 port_ptr = list_entry(client_ptr->ports.next, struct ladish_graph_port, siblings_client);
973 if (port_callback != NULL)
975 port_callback(port_ptr->port);
977 ladish_graph_remove_port_internal(graph_ptr, client_ptr, port_ptr);
980 graph_ptr->graph_version++;
981 list_del(&client_ptr->siblings);
982 log_info("removing client '%s' (%"PRIu64") from graph %s", client_ptr->name, client_ptr->id, graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
983 if (graph_ptr->opath != NULL && !client_ptr->hidden)
985 dbus_signal_emit(
986 g_dbus_connection,
987 graph_ptr->opath,
988 JACKDBUS_IFACE_PATCHBAY,
989 "ClientDisappeared",
990 "tts",
991 &graph_ptr->graph_version,
992 &client_ptr->id,
993 &client_ptr->name);
996 free(client_ptr->name);
998 if (destroy_client)
1000 ladish_client_destroy(client_ptr->client);
1003 free(client_ptr);
1006 bool ladish_graph_client_looks_empty_internal(struct ladish_graph * graph_ptr, struct ladish_graph_client * client_ptr)
1008 struct list_head * node_ptr;
1009 struct ladish_graph_port * port_ptr;
1011 list_for_each(node_ptr, &client_ptr->ports)
1013 port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_client);
1014 if (!port_ptr->hidden)
1016 //log_info("port '%s' is visible, client '%s' does not look empty", port_ptr->name, client_ptr->name);
1017 return false;
1019 else
1021 //log_info("port '%s' is invisible", port_ptr->name);
1025 //log_info("client '%s' looks empty in graph %s", client_ptr->name, graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
1026 return true;
1029 #define graph_ptr ((struct ladish_graph *)graph_handle)
1031 void ladish_graph_destroy(ladish_graph_handle graph_handle)
1033 ladish_graph_clear(graph_handle, NULL);
1034 ladish_dict_destroy(graph_ptr->dict);
1035 if (graph_ptr->opath != NULL)
1037 free(graph_ptr->opath);
1039 free(graph_ptr);
1042 const char * ladish_graph_get_opath(ladish_graph_handle graph_handle)
1044 return graph_ptr->opath;
1047 const char * ladish_graph_get_description(ladish_graph_handle graph_handle)
1049 return graph_ptr->opath != NULL ? graph_ptr->opath : "JACK";
1052 void
1053 ladish_graph_set_connection_handlers(
1054 ladish_graph_handle graph_handle,
1055 void * graph_context,
1056 ladish_graph_connect_request_handler connect_handler,
1057 ladish_graph_disconnect_request_handler disconnect_handler)
1059 log_info("setting connection handlers for graph '%s'", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
1060 graph_ptr->context = graph_context;
1061 graph_ptr->connect_handler = connect_handler;
1062 graph_ptr->disconnect_handler = disconnect_handler;
1065 void ladish_graph_clear(ladish_graph_handle graph_handle, ladish_graph_simple_port_callback port_callback)
1067 struct ladish_graph_client * client_ptr;
1068 struct ladish_graph_connection * connection_ptr;
1070 log_info("ladish_graph_clear() called for graph '%s'", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
1072 while (!list_empty(&graph_ptr->connections))
1074 connection_ptr = list_entry(graph_ptr->connections.next, struct ladish_graph_connection, siblings);
1075 ladish_graph_remove_connection_internal(graph_ptr, connection_ptr);
1078 while (!list_empty(&graph_ptr->clients))
1080 client_ptr = list_entry(graph_ptr->clients.next, struct ladish_graph_client, siblings);
1081 ladish_graph_remove_client_internal(graph_ptr, client_ptr, true, port_callback);
1085 void * ladish_graph_get_dbus_context(ladish_graph_handle graph_handle)
1087 return graph_handle;
1090 ladish_dict_handle ladish_graph_get_dict(ladish_graph_handle graph_handle)
1092 return graph_ptr->dict;
1095 void ladish_graph_show_connection(ladish_graph_handle graph_handle, uint64_t connection_id)
1097 struct ladish_graph_connection * connection_ptr;
1099 log_info("ladish_graph_show_connection() called.");
1101 connection_ptr = ladish_graph_find_connection_by_id(graph_ptr, connection_id);
1102 if (connection_ptr == NULL)
1104 ASSERT_NO_PASS;
1105 return;
1108 ASSERT(graph_ptr->opath != NULL);
1109 ASSERT(connection_ptr->hidden);
1110 connection_ptr->hidden = false;
1111 connection_ptr->changing = false;
1112 graph_ptr->graph_version++;
1114 dbus_signal_emit(
1115 g_dbus_connection,
1116 graph_ptr->opath,
1117 JACKDBUS_IFACE_PATCHBAY,
1118 "PortsConnected",
1119 "ttstststst",
1120 &graph_ptr->graph_version,
1121 &connection_ptr->port1_ptr->client_ptr->id,
1122 &connection_ptr->port1_ptr->client_ptr->name,
1123 &connection_ptr->port1_ptr->id,
1124 &connection_ptr->port1_ptr->name,
1125 &connection_ptr->port2_ptr->client_ptr->id,
1126 &connection_ptr->port2_ptr->client_ptr->name,
1127 &connection_ptr->port2_ptr->id,
1128 &connection_ptr->port2_ptr->name,
1129 &connection_ptr->id);
1132 void ladish_graph_show_port(ladish_graph_handle graph_handle, ladish_port_handle port_handle)
1134 struct ladish_graph_port * port_ptr;
1136 //log_info("ladish_graph_show_port() called.");
1138 port_ptr = ladish_graph_find_port(graph_ptr, port_handle);
1139 if (port_ptr == NULL)
1141 ASSERT_NO_PASS;
1142 return;
1145 //log_info("port '%s' is %s", port_ptr->name, port_ptr->hidden ? "invisible" : "visible");
1147 ladish_graph_show_port_internal(graph_ptr, port_ptr);
1150 void ladish_graph_hide_port(ladish_graph_handle graph_handle, ladish_port_handle port_handle)
1152 struct ladish_graph_port * port_ptr;
1154 log_info("ladish_graph_hide_port() called.");
1156 port_ptr = ladish_graph_find_port(graph_ptr, port_handle);
1157 if (port_ptr == NULL)
1159 ASSERT_NO_PASS;
1160 return;
1163 log_info("Hidding port %"PRIu64, port_ptr->id);
1165 ASSERT(!port_ptr->hidden);
1167 if (graph_ptr->opath != NULL)
1169 ladish_hide_connections(graph_ptr, port_ptr);
1172 ladish_graph_hide_port_internal(graph_ptr, port_ptr);
1175 void ladish_graph_hide_client(ladish_graph_handle graph_handle, ladish_client_handle client_handle)
1177 struct ladish_graph_client * client_ptr;
1179 log_info("ladish_graph_hide_client() called.");
1181 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1182 if (client_ptr == NULL)
1184 ASSERT_NO_PASS;
1185 return;
1188 ladish_graph_hide_client_internal(graph_ptr, client_ptr);
1191 void ladish_graph_show_client(ladish_graph_handle graph_handle, ladish_client_handle client_handle)
1193 struct ladish_graph_client * client_ptr;
1195 log_info("ladish_graph_show_client() called.");
1197 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1198 if (client_ptr == NULL)
1200 ASSERT_NO_PASS;
1201 return;
1204 ASSERT(client_ptr->hidden);
1205 client_ptr->hidden = false;
1206 graph_ptr->graph_version++;
1208 if (graph_ptr->opath != NULL)
1210 dbus_signal_emit(
1211 g_dbus_connection,
1212 graph_ptr->opath,
1213 JACKDBUS_IFACE_PATCHBAY,
1214 "ClientAppeared",
1215 "tts",
1216 &graph_ptr->graph_version,
1217 &client_ptr->id,
1218 &client_ptr->name);
1222 void ladish_graph_adjust_port(ladish_graph_handle graph_handle, ladish_port_handle port_handle, uint32_t type, uint32_t flags)
1224 struct ladish_graph_port * port_ptr;
1226 //log_info("ladish_graph_adjust_port() called.");
1228 port_ptr = ladish_graph_find_port(graph_ptr, port_handle);
1229 if (port_ptr == NULL)
1231 ASSERT_NO_PASS;
1232 return;
1235 port_ptr->type = type;
1236 port_ptr->flags = flags;
1239 bool ladish_graph_add_client(ladish_graph_handle graph_handle, ladish_client_handle client_handle, const char * name, bool hidden)
1241 struct ladish_graph_client * client_ptr;
1243 log_info("adding client '%s' (%p) to graph %s", name, client_handle, graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
1245 client_ptr = malloc(sizeof(struct ladish_graph_client));
1246 if (client_ptr == NULL)
1248 log_error("malloc() failed for struct ladish_graph_client");
1249 return false;
1252 client_ptr->name = strdup(name);
1253 if (client_ptr->name == NULL)
1255 log_error("strdup() failed for graph client name");
1256 free(client_ptr);
1257 return false;
1260 client_ptr->id = graph_ptr->next_client_id++;
1261 client_ptr->client = client_handle;
1262 client_ptr->hidden = hidden;
1263 graph_ptr->graph_version++;
1265 INIT_LIST_HEAD(&client_ptr->ports);
1267 list_add_tail(&client_ptr->siblings, &graph_ptr->clients);
1269 if (!hidden && graph_ptr->opath != NULL)
1271 dbus_signal_emit(
1272 g_dbus_connection,
1273 graph_ptr->opath,
1274 JACKDBUS_IFACE_PATCHBAY,
1275 "ClientAppeared",
1276 "tts",
1277 &graph_ptr->graph_version,
1278 &client_ptr->id,
1279 &client_ptr->name);
1282 return true;
1285 void
1286 ladish_graph_remove_client(
1287 ladish_graph_handle graph_handle,
1288 ladish_client_handle client_handle)
1290 struct ladish_graph_client * client_ptr;
1292 log_info("ladish_graph_remove_client() called.");
1294 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1295 if (client_ptr != NULL)
1297 ladish_graph_remove_client_internal(graph_ptr, client_ptr, false, NULL);
1299 else
1301 ASSERT_NO_PASS;
1305 bool
1306 ladish_graph_add_port(
1307 ladish_graph_handle graph_handle,
1308 ladish_client_handle client_handle,
1309 ladish_port_handle port_handle,
1310 const char * name,
1311 uint32_t type,
1312 uint32_t flags,
1313 bool hidden)
1315 struct ladish_graph_client * client_ptr;
1316 struct ladish_graph_port * port_ptr;
1318 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1319 if (client_ptr == NULL)
1321 log_error("cannot find client to add port to. graph is %s", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
1322 ASSERT_NO_PASS;
1323 return false;
1326 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");
1328 port_ptr = malloc(sizeof(struct ladish_graph_port));
1329 if (port_ptr == NULL)
1331 log_error("malloc() failed for struct ladish_graph_port");
1332 return false;
1335 port_ptr->name = strdup(name);
1336 if (port_ptr->name == NULL)
1338 log_error("strdup() failed for graph port name");
1339 free(port_ptr);
1340 return false;
1343 port_ptr->type = type;
1344 port_ptr->flags = flags;
1346 port_ptr->id = graph_ptr->next_port_id++;
1347 port_ptr->port = port_handle;
1348 ladish_port_add_ref(port_ptr->port);
1349 port_ptr->hidden = true;
1351 port_ptr->link = ladish_port_is_link(port_handle);
1352 if (port_ptr->link)
1354 uuid_generate(port_ptr->link_uuid_override);
1357 port_ptr->client_ptr = client_ptr;
1358 list_add_tail(&port_ptr->siblings_client, &client_ptr->ports);
1359 list_add_tail(&port_ptr->siblings_graph, &graph_ptr->ports);
1361 if (!hidden)
1363 ladish_graph_show_port_internal(graph_ptr, port_ptr);
1366 return true;
1369 uint64_t
1370 ladish_graph_add_connection(
1371 ladish_graph_handle graph_handle,
1372 ladish_port_handle port1_handle,
1373 ladish_port_handle port2_handle,
1374 bool hidden)
1376 struct ladish_graph_port * port1_ptr;
1377 struct ladish_graph_port * port2_ptr;
1378 struct ladish_graph_connection * connection_ptr;
1380 port1_ptr = ladish_graph_find_port(graph_ptr, port1_handle);
1381 ASSERT(port1_ptr != NULL);
1382 port2_ptr = ladish_graph_find_port(graph_ptr, port2_handle);
1383 ASSERT(port2_ptr != NULL);
1385 connection_ptr = malloc(sizeof(struct ladish_graph_connection));
1386 if (connection_ptr == NULL)
1388 log_error("malloc() failed for struct ladish_graph_connection");
1389 return 0;
1392 if (!ladish_dict_create(&connection_ptr->dict))
1394 log_error("ladish_dict_create() failed for connection");
1395 free(connection_ptr);
1396 return 0;
1399 connection_ptr->id = graph_ptr->next_connection_id++;
1400 connection_ptr->port1_ptr = port1_ptr;
1401 connection_ptr->port2_ptr = port2_ptr;
1402 connection_ptr->hidden = hidden;
1403 connection_ptr->changing = false;
1404 graph_ptr->graph_version++;
1406 list_add_tail(&connection_ptr->siblings, &graph_ptr->connections);
1408 /* log_info( */
1409 /* "new connection %"PRIu64" between '%s':'%s' and '%s':'%s'", */
1410 /* connection_ptr->id, */
1411 /* port1_ptr->client_ptr->name, */
1412 /* port1_ptr->name, */
1413 /* port2_ptr->client_ptr->name, */
1414 /* port2_ptr->name); */
1416 if (!hidden && graph_ptr->opath != NULL)
1418 dbus_signal_emit(
1419 g_dbus_connection,
1420 graph_ptr->opath,
1421 JACKDBUS_IFACE_PATCHBAY,
1422 "PortsConnected",
1423 "ttstststst",
1424 &graph_ptr->graph_version,
1425 &port1_ptr->client_ptr->id,
1426 &port1_ptr->client_ptr->name,
1427 &port1_ptr->id,
1428 &port1_ptr->name,
1429 &port2_ptr->client_ptr->id,
1430 &port2_ptr->client_ptr->name,
1431 &port2_ptr->id,
1432 &port2_ptr->name,
1433 &connection_ptr->id);
1436 return connection_ptr->id;
1439 void
1440 ladish_graph_remove_connection(
1441 ladish_graph_handle graph_handle,
1442 uint64_t connection_id,
1443 bool force)
1445 struct ladish_graph_connection * connection_ptr;
1447 connection_ptr = ladish_graph_find_connection_by_id(graph_ptr, connection_id);
1448 if (connection_ptr == NULL)
1450 ASSERT_NO_PASS;
1451 return;
1454 if (force || connection_ptr->changing || !graph_ptr->persist)
1456 /* log_info( */
1457 /* "removing connection '%s':'%s' - '%s':'%s'", */
1458 /* connection_ptr->port1_ptr->client_ptr->name, */
1459 /* connection_ptr->port1_ptr->name, */
1460 /* connection_ptr->port2_ptr->client_ptr->name, */
1461 /* connection_ptr->port2_ptr->name); */
1463 ladish_graph_remove_connection_internal(graph_ptr, connection_ptr);
1465 else
1467 /* log_info( */
1468 /* "hiding connection '%s':'%s' - '%s':'%s'", */
1469 /* connection_ptr->port1_ptr->client_ptr->name, */
1470 /* connection_ptr->port1_ptr->name, */
1471 /* connection_ptr->port2_ptr->client_ptr->name, */
1472 /* connection_ptr->port2_ptr->name); */
1474 ladish_graph_hide_connection_internal(graph_ptr, connection_ptr);
1478 bool
1479 ladish_graph_get_connection_ports(
1480 ladish_graph_handle graph_handle,
1481 uint64_t connection_id,
1482 ladish_port_handle * port1_handle_ptr,
1483 ladish_port_handle * port2_handle_ptr)
1485 struct ladish_graph_connection * connection_ptr;
1487 connection_ptr = ladish_graph_find_connection_by_id(graph_ptr, connection_id);
1488 if (connection_ptr == NULL)
1490 return false;
1493 *port1_handle_ptr = connection_ptr->port1_ptr->port;
1494 *port2_handle_ptr = connection_ptr->port2_ptr->port;
1496 return true;
1499 ladish_dict_handle ladish_graph_get_connection_dict(ladish_graph_handle graph_handle, uint64_t connection_id)
1501 struct ladish_graph_connection * connection_ptr;
1503 connection_ptr = ladish_graph_find_connection_by_id(graph_ptr, connection_id);
1504 if (connection_ptr == NULL)
1506 return NULL;
1509 return connection_ptr->dict;
1512 bool
1513 ladish_graph_find_connection(
1514 ladish_graph_handle graph_handle,
1515 ladish_port_handle port1_handle,
1516 ladish_port_handle port2_handle,
1517 uint64_t * connection_id_ptr)
1519 struct ladish_graph_port * port1_ptr;
1520 struct ladish_graph_port * port2_ptr;
1521 struct ladish_graph_connection * connection_ptr;
1523 port1_ptr = ladish_graph_find_port(graph_ptr, port1_handle);
1524 if (port1_ptr == NULL)
1526 return false;
1529 port2_ptr = ladish_graph_find_port(graph_ptr, port2_handle);
1530 if (port1_ptr == NULL)
1532 return false;
1535 connection_ptr = ladish_graph_find_connection_by_ports(graph_ptr, port1_ptr, port2_ptr);
1536 if (connection_ptr == NULL)
1538 return false;
1541 *connection_id_ptr = connection_ptr->id;
1543 return true;
1546 ladish_client_handle ladish_graph_find_client_by_name(ladish_graph_handle graph_handle, const char * name)
1548 struct list_head * node_ptr;
1549 struct ladish_graph_client * client_ptr;
1551 list_for_each(node_ptr, &graph_ptr->clients)
1553 client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
1554 if (strcmp(client_ptr->name, name) == 0)
1556 return client_ptr->client;
1560 return NULL;
1563 ladish_port_handle ladish_graph_find_port_by_name(ladish_graph_handle graph_handle, ladish_client_handle client_handle, const char * name)
1565 struct ladish_graph_client * client_ptr;
1566 struct list_head * node_ptr;
1567 struct ladish_graph_port * port_ptr;
1569 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1570 if (client_ptr != NULL)
1572 list_for_each(node_ptr, &client_ptr->ports)
1574 port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_client);
1575 if (strcmp(port_ptr->name, name) == 0)
1577 return port_ptr->port;
1581 else
1583 ASSERT_NO_PASS;
1586 return NULL;
1589 ladish_client_handle ladish_graph_find_client_by_uuid(ladish_graph_handle graph_handle, const uuid_t uuid)
1591 struct list_head * node_ptr;
1592 struct ladish_graph_client * client_ptr;
1593 uuid_t current_uuid;
1595 list_for_each(node_ptr, &graph_ptr->clients)
1597 client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
1598 ladish_client_get_uuid(client_ptr->client, current_uuid);
1599 if (uuid_compare(current_uuid, uuid) == 0)
1601 return client_ptr->client;
1605 return NULL;
1608 ladish_port_handle ladish_graph_find_port_by_uuid(ladish_graph_handle graph_handle, const uuid_t uuid, bool use_link_override_uuids)
1610 struct list_head * node_ptr;
1611 struct ladish_graph_port * port_ptr;
1612 uuid_t current_uuid;
1613 /* char uuid1_str[37]; */
1614 /* char uuid2_str[37]; */
1616 /* log_info("searching by uuid for port in graph %s", ladish_graph_get_description(graph_handle)); */
1617 /* uuid_unparse(uuid, uuid1_str); */
1619 list_for_each(node_ptr, &graph_ptr->ports)
1621 port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph);
1623 /* if (port_ptr->link) */
1624 /* { */
1625 /* uuid_unparse(port_ptr->link_uuid_override, uuid2_str); */
1626 /* log_info("comparing link uuid %s with %s", uuid2_str, uuid1_str); */
1627 /* } */
1629 if (port_ptr->link && uuid_compare(port_ptr->link_uuid_override, uuid) == 0)
1631 /* log_info("found port %p of client '%s'", port_ptr->port, port_ptr->client_ptr->name); */
1632 return port_ptr->port;
1635 ladish_port_get_uuid(port_ptr->port, current_uuid);
1636 /* uuid_unparse(current_uuid, uuid2_str); */
1637 /* log_info("comparing port uuid %s with %s", uuid2_str, uuid1_str); */
1638 if (uuid_compare(current_uuid, uuid) == 0)
1640 return port_ptr->port;
1644 return NULL;
1647 ladish_client_handle ladish_graph_get_port_client(ladish_graph_handle graph_handle, ladish_port_handle port_handle)
1649 struct ladish_graph_port * port_ptr;
1651 port_ptr = ladish_graph_find_port(graph_ptr, port_handle);
1652 if (port_ptr == NULL)
1654 return NULL;
1657 return port_ptr->client_ptr->client;
1660 bool ladish_graph_is_port_present(ladish_graph_handle graph_handle, ladish_port_handle port_handle)
1662 return ladish_graph_find_port(graph_ptr, port_handle) != NULL;
1665 ladish_client_handle ladish_graph_find_client_by_id(ladish_graph_handle graph_handle, uint64_t client_id)
1667 struct list_head * node_ptr;
1668 struct ladish_graph_client * client_ptr;
1670 list_for_each(node_ptr, &graph_ptr->clients)
1672 client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
1673 if (client_ptr->id == client_id)
1675 return client_ptr->client;
1679 return NULL;
1682 ladish_port_handle ladish_graph_find_port_by_id(ladish_graph_handle graph_handle, uint64_t port_id)
1684 struct ladish_graph_port * port_ptr;
1686 port_ptr = ladish_graph_find_port_by_id_internal(graph_ptr, port_id);
1687 if (port_ptr == NULL)
1689 return NULL;
1692 return port_ptr->port;
1695 ladish_client_handle ladish_graph_find_client_by_jack_id(ladish_graph_handle graph_handle, uint64_t client_id)
1697 struct list_head * node_ptr;
1698 struct ladish_graph_client * client_ptr;
1700 list_for_each(node_ptr, &graph_ptr->clients)
1702 client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
1703 if (ladish_client_get_jack_id(client_ptr->client) == client_id)
1705 return client_ptr->client;
1709 return NULL;
1712 ladish_port_handle ladish_graph_find_port_by_jack_id(ladish_graph_handle graph_handle, uint64_t port_id, bool room, bool studio)
1714 struct ladish_graph_port * port_ptr;
1716 port_ptr = ladish_graph_find_port_by_jack_id_internal(graph_ptr, port_id, room, studio);
1717 if (port_ptr == NULL)
1719 return NULL;
1722 return port_ptr->port;
1725 ladish_client_handle
1726 ladish_graph_remove_port(
1727 ladish_graph_handle graph_handle,
1728 ladish_port_handle port)
1730 struct ladish_graph_port * port_ptr;
1732 port_ptr = ladish_graph_find_port(graph_ptr, port);
1733 if (port_ptr == NULL)
1735 return NULL;
1738 ladish_graph_remove_port_internal(graph_ptr, port_ptr->client_ptr, port_ptr);
1739 return port_ptr->client_ptr->client;
1742 ladish_client_handle
1743 ladish_graph_remove_port_by_jack_id(
1744 ladish_graph_handle graph_handle,
1745 uint64_t jack_port_id,
1746 bool room,
1747 bool studio)
1749 struct ladish_graph_port * port_ptr;
1751 port_ptr = ladish_graph_find_port_by_jack_id_internal(graph_ptr, jack_port_id, room, studio);
1752 if (port_ptr == NULL)
1754 return NULL;
1757 ladish_graph_remove_port_internal(graph_ptr, port_ptr->client_ptr, port_ptr);
1758 return port_ptr->client_ptr->client;
1761 bool
1762 ladish_graph_rename_client(
1763 ladish_graph_handle graph_handle,
1764 ladish_client_handle client_handle,
1765 const char * new_client_name)
1767 char * name;
1768 struct ladish_graph_client * client_ptr;
1769 char * old_name;
1771 name = strdup(new_client_name);
1772 if (name == NULL)
1774 log_error("strdup('%s') failed.", new_client_name);
1775 return false;
1778 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1779 if (client_ptr == NULL)
1781 free(name);
1782 ASSERT_NO_PASS;
1783 return false;
1786 old_name = client_ptr->name;
1787 client_ptr->name = name;
1789 graph_ptr->graph_version++;
1791 if (!client_ptr->hidden && graph_ptr->opath != NULL)
1793 dbus_signal_emit(
1794 g_dbus_connection,
1795 graph_ptr->opath,
1796 JACKDBUS_IFACE_PATCHBAY,
1797 "ClientRenamed",
1798 "ttss",
1799 &graph_ptr->graph_version,
1800 &client_ptr->id,
1801 &old_name,
1802 &client_ptr->name);
1805 free(old_name);
1807 return true;
1810 bool
1811 ladish_graph_rename_port(
1812 ladish_graph_handle graph_handle,
1813 ladish_port_handle port_handle,
1814 const char * new_port_name)
1816 char * name;
1817 struct ladish_graph_port * port_ptr;
1818 char * old_name;
1820 name = strdup(new_port_name);
1821 if (name == NULL)
1823 log_error("strdup('%s') failed.", new_port_name);
1824 return false;
1827 port_ptr = ladish_graph_find_port(graph_ptr, port_handle);
1828 if (port_ptr == NULL)
1830 ASSERT_NO_PASS;
1831 free(name);
1832 return false;
1835 old_name = port_ptr->name;
1836 port_ptr->name = name;
1838 graph_ptr->graph_version++;
1840 if (!port_ptr->hidden && graph_ptr->opath != NULL)
1842 dbus_signal_emit(
1843 g_dbus_connection,
1844 graph_ptr->opath,
1845 JACKDBUS_IFACE_PATCHBAY,
1846 "PortRenamed",
1847 "ttstss",
1848 &graph_ptr->graph_version,
1849 &port_ptr->client_ptr->id,
1850 &port_ptr->client_ptr->name,
1851 &port_ptr->id,
1852 &old_name,
1853 &port_ptr->name);
1856 free(old_name);
1858 return true;
1861 const char * ladish_graph_get_client_name(ladish_graph_handle graph_handle, ladish_client_handle client_handle)
1863 struct ladish_graph_client * client_ptr;
1865 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1866 if (client_ptr != NULL)
1868 return client_ptr->name;
1871 ASSERT_NO_PASS;
1872 return NULL;
1875 bool ladish_graph_client_is_empty(ladish_graph_handle graph_handle, ladish_client_handle client_handle)
1877 struct ladish_graph_client * client_ptr;
1879 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1880 if (client_ptr != NULL)
1882 return list_empty(&client_ptr->ports);
1885 ASSERT_NO_PASS;
1886 return true;
1889 bool ladish_graph_client_looks_empty(ladish_graph_handle graph_handle, ladish_client_handle client_handle)
1891 struct ladish_graph_client * client_ptr;
1893 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1894 if (client_ptr == NULL)
1896 ASSERT_NO_PASS;
1897 return true;
1900 if (ladish_graph_client_looks_empty_internal(graph_ptr, client_ptr))
1902 //log_info("client '%s' looks empty in graph %s", client_ptr->name, graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
1903 return true;
1906 return false;
1909 void ladish_try_connect_hidden_connections(ladish_graph_handle graph_handle)
1911 struct list_head * node_ptr;
1912 struct ladish_graph_connection * connection_ptr;
1914 if (!list_empty(&graph_ptr->connections) && graph_ptr->connect_handler == NULL)
1916 ASSERT_NO_PASS;
1917 return;
1920 ASSERT(graph_ptr->opath != NULL);
1922 list_for_each(node_ptr, &graph_ptr->connections)
1924 connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
1925 if (connection_ptr->hidden &&
1926 !connection_ptr->changing &&
1927 !connection_ptr->port1_ptr->hidden &&
1928 !connection_ptr->port2_ptr->hidden)
1930 log_info(
1931 "auto connecting '%s':'%s' to '%s':'%s'",
1932 connection_ptr->port1_ptr->client_ptr->name,
1933 connection_ptr->port1_ptr->name,
1934 connection_ptr->port2_ptr->client_ptr->name,
1935 connection_ptr->port2_ptr->name);
1937 connection_ptr->changing = true;
1938 if (!graph_ptr->connect_handler(graph_ptr->context, graph_handle, connection_ptr->port1_ptr->port, connection_ptr->port2_ptr->port))
1940 connection_ptr->changing = false;
1941 log_error("auto connect failed.");
1947 void ladish_graph_hide_non_virtual(ladish_graph_handle graph_handle)
1949 struct list_head * node_ptr;
1950 struct ladish_graph_connection * connection_ptr;
1951 struct ladish_graph_port * port_ptr;
1952 struct ladish_graph_client * client_ptr;
1954 log_info("hiding everything in graph %s", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
1956 list_for_each(node_ptr, &graph_ptr->connections)
1958 connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
1959 if (!connection_ptr->hidden &&
1960 (ladish_client_get_jack_id(connection_ptr->port1_ptr->client_ptr->client) != 0 ||
1961 ladish_client_get_jack_id(connection_ptr->port2_ptr->client_ptr->client) != 0))
1963 log_debug("hidding connection between ports %"PRIu64" and %"PRIu64, connection_ptr->port1_ptr->id, connection_ptr->port2_ptr->id);
1964 ladish_graph_hide_connection_internal(graph_ptr, connection_ptr);
1968 list_for_each(node_ptr, &graph_ptr->ports)
1970 port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph);
1971 if (!port_ptr->hidden && ladish_client_get_jack_id(port_ptr->client_ptr->client) != 0)
1973 ladish_port_set_jack_id(port_ptr->port, 0);
1974 ladish_graph_hide_port_internal(graph_ptr, port_ptr);
1978 list_for_each(node_ptr, &graph_ptr->clients)
1980 client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
1981 if (!client_ptr->hidden && ladish_client_get_jack_id(client_ptr->client) != 0)
1983 ladish_client_set_jack_id(client_ptr->client, 0);
1984 ladish_graph_hide_client_internal(graph_ptr, client_ptr);
1989 void ladish_graph_get_port_uuid(ladish_graph_handle graph_handle, ladish_port_handle port, uuid_t uuid_ptr)
1991 struct ladish_graph_port * port_ptr;
1993 port_ptr = ladish_graph_find_port(graph_ptr, port);
1994 ASSERT(port_ptr != NULL);
1995 ASSERT(port_ptr->link);
1997 uuid_copy(uuid_ptr, port_ptr->link_uuid_override);
2000 const char * ladish_graph_get_port_name(ladish_graph_handle graph_handle, ladish_port_handle port)
2002 struct ladish_graph_port * port_ptr;
2004 port_ptr = ladish_graph_find_port(graph_ptr, port);
2005 ASSERT(port_ptr != NULL);
2007 return port_ptr->name;
2010 bool
2011 ladish_graph_iterate_nodes(
2012 ladish_graph_handle graph_handle,
2013 bool skip_hidden,
2014 void * callback_context,
2015 bool
2016 (* client_begin_callback)(
2017 void * context,
2018 ladish_client_handle client_handle,
2019 const char * client_name,
2020 void ** client_iteration_context_ptr_ptr),
2021 bool
2022 (* port_callback)(
2023 void * context,
2024 void * client_iteration_context_ptr,
2025 ladish_client_handle client_handle,
2026 const char * client_name,
2027 ladish_port_handle port_handle,
2028 const char * port_name,
2029 uint32_t port_type,
2030 uint32_t port_flags),
2031 bool
2032 (* client_end_callback)(
2033 void * context,
2034 ladish_client_handle client_handle,
2035 const char * client_name,
2036 void * client_iteration_context_ptr))
2038 struct list_head * client_node_ptr;
2039 struct ladish_graph_client * client_ptr;
2040 void * client_context;
2041 struct list_head * port_node_ptr;
2042 struct ladish_graph_port * port_ptr;
2044 list_for_each(client_node_ptr, &graph_ptr->clients)
2046 client_ptr = list_entry(client_node_ptr, struct ladish_graph_client, siblings);
2048 if (skip_hidden && client_ptr->hidden)
2050 continue;
2053 if (client_begin_callback != NULL)
2055 if (!client_begin_callback(callback_context, client_ptr->client, client_ptr->name, &client_context))
2057 return false;
2060 else
2062 client_context = NULL;
2065 if (port_callback == NULL)
2067 continue;
2070 list_for_each(port_node_ptr, &client_ptr->ports)
2072 port_ptr = list_entry(port_node_ptr, struct ladish_graph_port, siblings_client);
2074 if (skip_hidden && port_ptr->hidden)
2076 continue;
2079 if (!port_callback(
2080 callback_context,
2081 client_context,
2082 client_ptr->client,
2083 client_ptr->name,
2084 port_ptr->port,
2085 port_ptr->name,
2086 port_ptr->type,
2087 port_ptr->flags))
2089 return false;
2093 if (client_end_callback != NULL)
2095 if (!client_end_callback(callback_context, client_ptr->client, client_ptr->name, &client_context))
2097 return false;
2102 return true;
2105 bool
2106 ladish_graph_iterate_connections(
2107 ladish_graph_handle graph_handle,
2108 bool skip_hidden,
2109 void * callback_context,
2110 bool (* callback)(void * context, ladish_port_handle port1_handle, ladish_port_handle port2_handle, ladish_dict_handle dict))
2112 struct list_head * node_ptr;
2113 struct ladish_graph_connection * connection_ptr;
2115 list_for_each(node_ptr, &graph_ptr->connections)
2117 connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
2119 if (skip_hidden && connection_ptr->hidden)
2121 continue;
2124 if (!callback(callback_context, connection_ptr->port1_ptr->port, connection_ptr->port2_ptr->port, connection_ptr->dict))
2126 return false;
2130 return true;
2133 static
2134 bool
2135 dump_dict_entry(
2136 void * context,
2137 const char * key,
2138 const char * value)
2140 log_info("%s key '%s' with value '%s'", (const char *)context, key, value);
2141 return true;
2144 static
2145 void
2146 dump_dict(
2147 const char * indent,
2148 ladish_dict_handle dict)
2150 if (ladish_dict_is_empty(dict))
2152 return;
2155 log_info("%sdict:", indent);
2156 ladish_dict_iterate(dict, (void *)indent, dump_dict_entry);
2159 void ladish_graph_dump(ladish_graph_handle graph_handle)
2161 struct list_head * client_node_ptr;
2162 struct ladish_graph_client * client_ptr;
2163 struct list_head * port_node_ptr;
2164 struct ladish_graph_port * port_ptr;
2165 struct list_head * connection_node_ptr;
2166 struct ladish_graph_connection * connection_ptr;
2168 log_info("graph %s", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
2169 log_info(" version %"PRIu64, graph_ptr->graph_version);
2170 dump_dict(" ", graph_ptr->dict);
2171 log_info(" clients:");
2172 list_for_each(client_node_ptr, &graph_ptr->clients)
2174 client_ptr = list_entry(client_node_ptr, struct ladish_graph_client, siblings);
2175 log_info(" %s client '%s', id=%"PRIu64", ptr=%p", client_ptr->hidden ? "invisible" : "visible", client_ptr->name, client_ptr->id, client_ptr->client);
2176 dump_dict(" ", ladish_client_get_dict(client_ptr->client));
2177 log_info(" ports:");
2178 list_for_each(port_node_ptr, &client_ptr->ports)
2180 port_ptr = list_entry(port_node_ptr, struct ladish_graph_port, siblings_client);
2182 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);
2183 dump_dict(" ", ladish_port_get_dict(port_ptr->port));
2186 log_info(" connections:");
2187 list_for_each(connection_node_ptr, &graph_ptr->connections)
2189 connection_ptr = list_entry(connection_node_ptr, struct ladish_graph_connection, siblings);
2191 log_info(
2192 " %s connection '%s':'%s' - '%s':'%s'%s",
2193 connection_ptr->hidden ? "invisible" : "visible",
2194 connection_ptr->port1_ptr->client_ptr->name,
2195 connection_ptr->port1_ptr->name,
2196 connection_ptr->port2_ptr->client_ptr->name,
2197 connection_ptr->port2_ptr->name,
2198 connection_ptr->changing ? " [changing]" : "");
2199 dump_dict(" ", connection_ptr->dict);
2203 void ladish_graph_clear_persist(ladish_graph_handle graph_handle)
2205 graph_ptr->persist = false;
2208 bool ladish_graph_is_persist(ladish_graph_handle graph_handle)
2210 return graph_ptr->persist;
2213 bool ladish_graph_looks_empty(ladish_graph_handle graph_handle)
2215 struct list_head * node_ptr;
2216 struct ladish_graph_connection * connection_ptr;
2217 struct ladish_graph_client * client_ptr;
2219 list_for_each(node_ptr, &graph_ptr->connections)
2221 connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
2223 if (!connection_ptr->hidden)
2225 return false;
2229 list_for_each(node_ptr, &graph_ptr->clients)
2231 client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
2232 if (!ladish_graph_client_looks_empty_internal(graph_ptr, client_ptr))
2234 return false;
2238 return true;
2241 #undef graph_ptr
2242 #define graph_ptr ((struct ladish_graph *)context)
2244 static
2245 bool
2246 ladish_graph_copy_client_begin_callback(
2247 void * context,
2248 ladish_client_handle client_handle,
2249 const char * client_name,
2250 void ** client_iteration_context_ptr_ptr)
2252 ladish_client_handle copy;
2254 if (!ladish_client_create_copy(client_handle, &copy))
2256 return false;
2259 if (!ladish_graph_add_client(context, copy, client_name, false))
2261 ladish_client_destroy(copy);
2262 return false;
2265 *client_iteration_context_ptr_ptr = copy;
2267 return true;
2270 static
2271 bool
2272 ladish_graph_copy_port_callback(
2273 void * context,
2274 void * client_iteration_context_ptr,
2275 ladish_client_handle client_handle,
2276 const char * client_name,
2277 ladish_port_handle port_handle,
2278 const char * port_name,
2279 uint32_t port_type,
2280 uint32_t port_flags)
2282 ladish_port_handle copy;
2284 if (!ladish_port_create_copy(port_handle, &copy))
2286 return false;
2289 if (!ladish_graph_add_port(context, client_iteration_context_ptr, copy, port_name, port_type, port_flags, true))
2291 ladish_port_destroy(copy);
2292 return false;
2295 return true;
2298 #undef graph_ptr
2300 bool ladish_graph_copy(ladish_graph_handle src, ladish_graph_handle dest, bool skip_hidden)
2302 return ladish_graph_iterate_nodes(
2303 src,
2304 skip_hidden,
2305 dest,
2306 ladish_graph_copy_client_begin_callback,
2307 ladish_graph_copy_port_callback,
2308 NULL);
2311 METHOD_ARGS_BEGIN(GetAllPorts, "Get all ports")
2312 METHOD_ARG_DESCRIBE_IN("ports_list", "as", "List of all ports")
2313 METHOD_ARGS_END
2315 METHOD_ARGS_BEGIN(GetGraph, "Get whole graph")
2316 METHOD_ARG_DESCRIBE_IN("known_graph_version", DBUS_TYPE_UINT64_AS_STRING, "Known graph version")
2317 METHOD_ARG_DESCRIBE_OUT("current_graph_version", DBUS_TYPE_UINT64_AS_STRING, "Current graph version")
2318 METHOD_ARG_DESCRIBE_OUT("clients_and_ports", "a(tsa(tsuu))", "Clients and their ports")
2319 METHOD_ARG_DESCRIBE_OUT("connections", "a(tstststst)", "Connections array")
2320 METHOD_ARGS_END
2322 METHOD_ARGS_BEGIN(ConnectPortsByName, "Connect ports")
2323 METHOD_ARG_DESCRIBE_IN("client1_name", DBUS_TYPE_STRING_AS_STRING, "name first port client")
2324 METHOD_ARG_DESCRIBE_IN("port1_name", DBUS_TYPE_STRING_AS_STRING, "name of first port")
2325 METHOD_ARG_DESCRIBE_IN("client2_name", DBUS_TYPE_STRING_AS_STRING, "name second port client")
2326 METHOD_ARG_DESCRIBE_IN("port2_name", DBUS_TYPE_STRING_AS_STRING, "name of second port")
2327 METHOD_ARGS_END
2329 METHOD_ARGS_BEGIN(ConnectPortsByID, "Connect ports")
2330 METHOD_ARG_DESCRIBE_IN("port1_id", DBUS_TYPE_UINT64_AS_STRING, "id of first port")
2331 METHOD_ARG_DESCRIBE_IN("port2_id", DBUS_TYPE_UINT64_AS_STRING, "if of second port")
2332 METHOD_ARGS_END
2334 METHOD_ARGS_BEGIN(DisconnectPortsByName, "Disconnect ports")
2335 METHOD_ARG_DESCRIBE_IN("client1_name", DBUS_TYPE_STRING_AS_STRING, "name first port client")
2336 METHOD_ARG_DESCRIBE_IN("port1_name", DBUS_TYPE_STRING_AS_STRING, "name of first port")
2337 METHOD_ARG_DESCRIBE_IN("client2_name", DBUS_TYPE_STRING_AS_STRING, "name second port client")
2338 METHOD_ARG_DESCRIBE_IN("port2_name", DBUS_TYPE_STRING_AS_STRING, "name of second port")
2339 METHOD_ARGS_END
2341 METHOD_ARGS_BEGIN(DisconnectPortsByID, "Disconnect ports")
2342 METHOD_ARG_DESCRIBE_IN("port1_id", DBUS_TYPE_UINT64_AS_STRING, "id of first port")
2343 METHOD_ARG_DESCRIBE_IN("port2_id", DBUS_TYPE_UINT64_AS_STRING, "if of second port")
2344 METHOD_ARGS_END
2346 METHOD_ARGS_BEGIN(DisconnectPortsByConnectionID, "Disconnect ports")
2347 METHOD_ARG_DESCRIBE_IN("connection_id", DBUS_TYPE_UINT64_AS_STRING, "id of connection to disconnect")
2348 METHOD_ARGS_END
2350 METHOD_ARGS_BEGIN(GetClientPID, "get process id of client")
2351 METHOD_ARG_DESCRIBE_IN("client_id", DBUS_TYPE_UINT64_AS_STRING, "id of client")
2352 METHOD_ARG_DESCRIBE_OUT("process_id", DBUS_TYPE_INT64_AS_STRING, "pid of client")
2353 METHOD_ARGS_END
2355 METHODS_BEGIN
2356 METHOD_DESCRIBE(GetAllPorts, get_all_ports)
2357 METHOD_DESCRIBE(GetGraph, get_graph)
2358 METHOD_DESCRIBE(ConnectPortsByName, connect_ports_by_name)
2359 METHOD_DESCRIBE(ConnectPortsByID, connect_ports_by_id)
2360 METHOD_DESCRIBE(DisconnectPortsByName, disconnect_ports_by_name)
2361 METHOD_DESCRIBE(DisconnectPortsByID, disconnect_ports_by_id)
2362 METHOD_DESCRIBE(DisconnectPortsByConnectionID, disconnect_ports_by_connection_id)
2363 METHOD_DESCRIBE(GetClientPID, get_client_pid)
2364 METHODS_END
2366 SIGNAL_ARGS_BEGIN(GraphChanged, "")
2367 SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
2368 SIGNAL_ARGS_END
2370 SIGNAL_ARGS_BEGIN(ClientAppeared, "")
2371 SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
2372 SIGNAL_ARG_DESCRIBE("client_id", DBUS_TYPE_UINT64_AS_STRING, "")
2373 SIGNAL_ARG_DESCRIBE("client_name", DBUS_TYPE_STRING_AS_STRING, "")
2374 SIGNAL_ARGS_END
2376 SIGNAL_ARGS_BEGIN(ClientDisappeared, "")
2377 SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
2378 SIGNAL_ARG_DESCRIBE("client_id", DBUS_TYPE_UINT64_AS_STRING, "")
2379 SIGNAL_ARG_DESCRIBE("client_name", DBUS_TYPE_STRING_AS_STRING, "")
2380 SIGNAL_ARGS_END
2382 SIGNAL_ARGS_BEGIN(PortAppeared, "")
2383 SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
2384 SIGNAL_ARG_DESCRIBE("client_id", DBUS_TYPE_UINT64_AS_STRING, "")
2385 SIGNAL_ARG_DESCRIBE("client_name", DBUS_TYPE_STRING_AS_STRING, "")
2386 SIGNAL_ARG_DESCRIBE("port_id", DBUS_TYPE_UINT64_AS_STRING, "")
2387 SIGNAL_ARG_DESCRIBE("port_name", DBUS_TYPE_STRING_AS_STRING, "")
2388 SIGNAL_ARG_DESCRIBE("port_flags", DBUS_TYPE_UINT32_AS_STRING, "")
2389 SIGNAL_ARG_DESCRIBE("port_type", DBUS_TYPE_UINT32_AS_STRING, "")
2390 SIGNAL_ARGS_END
2392 SIGNAL_ARGS_BEGIN(PortDisappeared, "")
2393 SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
2394 SIGNAL_ARG_DESCRIBE("client_id", DBUS_TYPE_UINT64_AS_STRING, "")
2395 SIGNAL_ARG_DESCRIBE("client_name", DBUS_TYPE_STRING_AS_STRING, "")
2396 SIGNAL_ARG_DESCRIBE("port_id", DBUS_TYPE_UINT64_AS_STRING, "")
2397 SIGNAL_ARG_DESCRIBE("port_name", DBUS_TYPE_STRING_AS_STRING, "")
2398 SIGNAL_ARGS_END
2400 SIGNAL_ARGS_BEGIN(PortsConnected, "")
2401 SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
2402 SIGNAL_ARG_DESCRIBE("client1_id", DBUS_TYPE_UINT64_AS_STRING, "")
2403 SIGNAL_ARG_DESCRIBE("client1_name", DBUS_TYPE_STRING_AS_STRING, "")
2404 SIGNAL_ARG_DESCRIBE("port1_id", DBUS_TYPE_UINT64_AS_STRING, "")
2405 SIGNAL_ARG_DESCRIBE("port1_name", DBUS_TYPE_STRING_AS_STRING, "")
2406 SIGNAL_ARG_DESCRIBE("client2_id", DBUS_TYPE_UINT64_AS_STRING, "")
2407 SIGNAL_ARG_DESCRIBE("client2_name", DBUS_TYPE_STRING_AS_STRING, "")
2408 SIGNAL_ARG_DESCRIBE("port2_id", DBUS_TYPE_UINT64_AS_STRING, "")
2409 SIGNAL_ARG_DESCRIBE("port2_name", DBUS_TYPE_STRING_AS_STRING, "")
2410 SIGNAL_ARG_DESCRIBE("connection_id", DBUS_TYPE_UINT64_AS_STRING, "")
2411 SIGNAL_ARGS_END
2413 SIGNAL_ARGS_BEGIN(PortsDisconnected, "")
2414 SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
2415 SIGNAL_ARG_DESCRIBE("client1_id", DBUS_TYPE_UINT64_AS_STRING, "")
2416 SIGNAL_ARG_DESCRIBE("client1_name", DBUS_TYPE_STRING_AS_STRING, "")
2417 SIGNAL_ARG_DESCRIBE("port1_id", DBUS_TYPE_UINT64_AS_STRING, "")
2418 SIGNAL_ARG_DESCRIBE("port1_name", DBUS_TYPE_STRING_AS_STRING, "")
2419 SIGNAL_ARG_DESCRIBE("client2_id", DBUS_TYPE_UINT64_AS_STRING, "")
2420 SIGNAL_ARG_DESCRIBE("client2_name", DBUS_TYPE_STRING_AS_STRING, "")
2421 SIGNAL_ARG_DESCRIBE("port2_id", DBUS_TYPE_UINT64_AS_STRING, "")
2422 SIGNAL_ARG_DESCRIBE("port2_name", DBUS_TYPE_STRING_AS_STRING, "")
2423 SIGNAL_ARG_DESCRIBE("connection_id", DBUS_TYPE_UINT64_AS_STRING, "")
2424 SIGNAL_ARGS_END
2426 SIGNALS_BEGIN
2427 SIGNAL_DESCRIBE(GraphChanged)
2428 SIGNAL_DESCRIBE(ClientAppeared)
2429 SIGNAL_DESCRIBE(ClientDisappeared)
2430 SIGNAL_DESCRIBE(PortAppeared)
2431 SIGNAL_DESCRIBE(PortDisappeared)
2432 SIGNAL_DESCRIBE(PortsConnected)
2433 SIGNAL_DESCRIBE(PortsDisconnected)
2434 SIGNALS_END
2436 INTERFACE_BEGIN(g_interface_patchbay, JACKDBUS_IFACE_PATCHBAY)
2437 INTERFACE_DEFAULT_HANDLER
2438 INTERFACE_EXPOSE_METHODS
2439 INTERFACE_EXPOSE_SIGNALS
2440 INTERFACE_END