Merge branch 'stable' into 'main'
[ladish.git] / daemon / graph.c
blob7c9cbc5677edb7719144c8fb55e14d433bd5246e
1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*
3 * LADI Session Handler (ladish)
5 * Copyright (C) 2008,2009,2010,2011,2012,2013 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_constants.h"
31 #include "virtualizer.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 void ladish_graph_emit_ports_disconnected(struct ladish_graph * graph_ptr, struct ladish_graph_connection * connection_ptr)
89 ASSERT(graph_ptr->opath != NULL);
91 cdbus_signal_emit(
92 cdbus_g_dbus_connection,
93 graph_ptr->opath,
94 JACKDBUS_IFACE_PATCHBAY,
95 "PortsDisconnected",
96 "ttstststst",
97 &graph_ptr->graph_version,
98 &connection_ptr->port1_ptr->client_ptr->id,
99 &connection_ptr->port1_ptr->client_ptr->name,
100 &connection_ptr->port1_ptr->id,
101 &connection_ptr->port1_ptr->name,
102 &connection_ptr->port2_ptr->client_ptr->id,
103 &connection_ptr->port2_ptr->client_ptr->name,
104 &connection_ptr->port2_ptr->id,
105 &connection_ptr->port2_ptr->name,
106 &connection_ptr->id);
109 static void ladish_graph_emit_ports_connected(struct ladish_graph * graph_ptr, struct ladish_graph_connection * connection_ptr)
111 ASSERT(graph_ptr->opath != NULL);
113 cdbus_signal_emit(
114 cdbus_g_dbus_connection,
115 graph_ptr->opath,
116 JACKDBUS_IFACE_PATCHBAY,
117 "PortsConnected",
118 "ttstststst",
119 &graph_ptr->graph_version,
120 &connection_ptr->port1_ptr->client_ptr->id,
121 &connection_ptr->port1_ptr->client_ptr->name,
122 &connection_ptr->port1_ptr->id,
123 &connection_ptr->port1_ptr->name,
124 &connection_ptr->port2_ptr->client_ptr->id,
125 &connection_ptr->port2_ptr->client_ptr->name,
126 &connection_ptr->port2_ptr->id,
127 &connection_ptr->port2_ptr->name,
128 &connection_ptr->id);
131 static void ladish_graph_emit_client_appeared(struct ladish_graph * graph_ptr, struct ladish_graph_client * client_ptr)
133 ASSERT(graph_ptr->opath != NULL);
135 cdbus_signal_emit(
136 cdbus_g_dbus_connection,
137 graph_ptr->opath,
138 JACKDBUS_IFACE_PATCHBAY,
139 "ClientAppeared",
140 "tts",
141 &graph_ptr->graph_version,
142 &client_ptr->id,
143 &client_ptr->name);
146 static void ladish_graph_emit_client_disappeared(struct ladish_graph * graph_ptr, struct ladish_graph_client * client_ptr)
148 ASSERT(graph_ptr->opath != NULL);
150 cdbus_signal_emit(
151 cdbus_g_dbus_connection,
152 graph_ptr->opath,
153 JACKDBUS_IFACE_PATCHBAY,
154 "ClientDisappeared",
155 "tts",
156 &graph_ptr->graph_version,
157 &client_ptr->id,
158 &client_ptr->name);
161 static void ladish_graph_emit_port_appeared(struct ladish_graph * graph_ptr, struct ladish_graph_port * port_ptr)
163 ASSERT(graph_ptr->opath != NULL);
165 cdbus_signal_emit(
166 cdbus_g_dbus_connection,
167 graph_ptr->opath,
168 JACKDBUS_IFACE_PATCHBAY,
169 "PortAppeared",
170 "ttstsuu",
171 &graph_ptr->graph_version,
172 &port_ptr->client_ptr->id,
173 &port_ptr->client_ptr->name,
174 &port_ptr->id,
175 &port_ptr->name,
176 &port_ptr->flags,
177 &port_ptr->type);
180 static void ladish_graph_emit_port_disappeared(struct ladish_graph * graph_ptr, struct ladish_graph_port * port_ptr)
182 ASSERT(graph_ptr->opath != NULL);
184 cdbus_signal_emit(
185 cdbus_g_dbus_connection,
186 graph_ptr->opath,
187 JACKDBUS_IFACE_PATCHBAY,
188 "PortDisappeared",
189 "ttsts",
190 &graph_ptr->graph_version,
191 &port_ptr->client_ptr->id,
192 &port_ptr->client_ptr->name,
193 &port_ptr->id,
194 &port_ptr->name);
197 static
198 bool
199 ladish_graph_find_connection_ports_by_name_internal(
200 struct ladish_graph * graph_ptr,
201 const char * client1_name,
202 const char * port1_name,
203 const char * client2_name,
204 const char * port2_name,
205 struct ladish_graph_port ** port1_ptr_ptr,
206 struct ladish_graph_port ** port2_ptr_ptr)
208 struct list_head * client1_node_ptr;
209 struct ladish_graph_client * client1_ptr;
210 struct list_head * port1_node_ptr;
211 struct ladish_graph_port * port1_ptr;
212 struct list_head * client2_node_ptr;
213 struct ladish_graph_client * client2_ptr;
214 struct list_head * port2_node_ptr;
215 struct ladish_graph_port * port2_ptr;
218 * Port names are not unique, so in order to find best match,
219 * ports are searched with these assumptions:
221 * 1. port1 and port2 are of same type (midi or audio)
222 * 2. port1 is a source (capture, output) port
223 * 3. port2 is a destination (playback, input) port
225 * all these conditions have to be met for a port pair to match
227 list_for_each(client1_node_ptr, &graph_ptr->clients)
229 client1_ptr = list_entry(client1_node_ptr, struct ladish_graph_client, siblings);
230 if (strcmp(client1_ptr->name, client1_name) == 0)
232 list_for_each(port1_node_ptr, &client1_ptr->ports)
234 port1_ptr = list_entry(port1_node_ptr, struct ladish_graph_port, siblings_client);
235 if (JACKDBUS_PORT_IS_OUTPUT(port1_ptr->flags) &&
236 strcmp(port1_ptr->name, port1_name) == 0)
238 list_for_each(client2_node_ptr, &graph_ptr->clients)
240 client2_ptr = list_entry(client2_node_ptr, struct ladish_graph_client, siblings);
241 if (strcmp(client2_ptr->name, client2_name) == 0)
243 list_for_each(port2_node_ptr, &client2_ptr->ports)
245 port2_ptr = list_entry(port2_node_ptr, struct ladish_graph_port, siblings_client);
246 if (port2_ptr->type == port1_ptr->type &&
247 JACKDBUS_PORT_IS_INPUT(port2_ptr->flags) &&
248 strcmp(port2_ptr->name, port2_name) == 0)
250 *port1_ptr_ptr = port1_ptr;
251 *port2_ptr_ptr = port2_ptr;
252 return true;
262 return false;
265 static
266 bool
267 ladish_graph_find_connection_ports_by_name(
268 struct ladish_graph * graph_ptr,
269 const char * client1_name,
270 const char * port1_name,
271 const char * client2_name,
272 const char * port2_name,
273 struct ladish_graph_port ** port1_ptr_ptr,
274 struct ladish_graph_port ** port2_ptr_ptr)
276 if (ladish_graph_find_connection_ports_by_name_internal(
277 graph_ptr,
278 client1_name,
279 port1_name,
280 client2_name,
281 port2_name,
282 port1_ptr_ptr,
283 port2_ptr_ptr))
285 return true;
288 if (ladish_graph_find_connection_ports_by_name_internal(
289 graph_ptr,
290 client2_name,
291 port2_name,
292 client1_name,
293 port1_name,
294 port1_ptr_ptr,
295 port2_ptr_ptr))
297 return true;
300 return false;
303 static struct ladish_graph_port * ladish_graph_find_port_by_id_internal(struct ladish_graph * graph_ptr, uint64_t port_id)
305 struct list_head * node_ptr;
306 struct ladish_graph_port * port_ptr;
308 list_for_each(node_ptr, &graph_ptr->ports)
310 port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph);
311 if (port_ptr->id == port_id)
313 return port_ptr;
317 return NULL;
320 //#define LOG_PORT_LOOKUP
322 static struct ladish_graph_port *
323 ladish_graph_find_port_by_uuid_internal(
324 struct ladish_graph * graph_ptr,
325 struct ladish_graph_client * client_ptr,
326 const uuid_t uuid,
327 bool use_link_override_uuids,
328 void * vgraph_filter)
330 struct list_head * node_ptr;
331 struct ladish_graph_port * port_ptr;
332 uuid_t current_uuid;
333 #if defined(LOG_PORT_LOOKUP)
334 char uuid1_str[37];
335 char uuid2_str[37];
337 log_info("searching by uuid for port in graph %s", ladish_graph_get_description((ladish_graph_handle)graph_ptr));
338 uuid_unparse(uuid, uuid1_str);
339 #endif
341 list_for_each(node_ptr, &graph_ptr->ports)
343 port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph);
345 if (client_ptr != NULL && port_ptr->client_ptr != client_ptr)
347 continue;
350 if (vgraph_filter != NULL && ladish_port_get_vgraph(port_ptr->port) != vgraph_filter)
352 continue;
355 #if defined(LOG_PORT_LOOKUP)
356 if (port_ptr->link)
358 uuid_unparse(port_ptr->link_uuid_override, uuid2_str);
359 log_info("comparing link uuid %s with %s", uuid2_str, uuid1_str);
361 #endif
363 if (use_link_override_uuids && port_ptr->link && uuid_compare(port_ptr->link_uuid_override, uuid) == 0)
365 #if defined(LOG_PORT_LOOKUP)
366 log_info("found link port %p of client '%s'", port_ptr->port, port_ptr->client_ptr->name);
367 #endif
368 return port_ptr;
371 ladish_port_get_uuid(port_ptr->port, current_uuid);
372 #if defined(LOG_PORT_LOOKUP)
373 uuid_unparse(current_uuid, uuid2_str);
374 log_info("comparing port uuid %s with %s", uuid2_str, uuid1_str);
375 #endif
376 if (uuid_compare(current_uuid, uuid) == 0)
378 #if defined(LOG_PORT_LOOKUP)
379 log_info("found port %p of client '%s'", port_ptr->port, port_ptr->client_ptr->name);
380 #endif
381 return port_ptr;
385 return NULL;
388 static struct ladish_graph_connection * ladish_graph_find_connection_by_id(struct ladish_graph * graph_ptr, uint64_t connection_id)
390 struct list_head * node_ptr;
391 struct ladish_graph_connection * connection_ptr;
393 list_for_each(node_ptr, &graph_ptr->connections)
395 connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
396 if (connection_ptr->id == connection_id)
398 return connection_ptr;
402 return NULL;
405 static
406 struct ladish_graph_connection *
407 ladish_graph_find_connection_by_ports(
408 struct ladish_graph * graph_ptr,
409 struct ladish_graph_port * port1_ptr,
410 struct ladish_graph_port * port2_ptr)
412 struct list_head * node_ptr;
413 struct ladish_graph_connection * connection_ptr;
415 list_for_each(node_ptr, &graph_ptr->connections)
417 connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
418 if ((connection_ptr->port1_ptr == port1_ptr && connection_ptr->port2_ptr == port2_ptr) ||
419 (connection_ptr->port1_ptr == port2_ptr && connection_ptr->port2_ptr == port1_ptr))
421 return connection_ptr;
425 return NULL;
428 #define graph_ptr ((struct ladish_graph *)call_ptr->iface_context)
430 static void get_all_ports(struct cdbus_method_call * call_ptr)
432 DBusMessageIter iter, sub_iter;
434 call_ptr->reply = dbus_message_new_method_return(call_ptr->message);
435 if (call_ptr->reply == NULL)
437 goto fail;
440 dbus_message_iter_init_append(call_ptr->reply, &iter);
442 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub_iter))
444 goto fail_unref;
447 if (!dbus_message_iter_close_container(&iter, &sub_iter))
449 goto fail_unref;
452 return;
454 fail_unref:
455 dbus_message_unref(call_ptr->reply);
456 call_ptr->reply = NULL;
458 fail:
459 log_error("Ran out of memory trying to construct method return");
462 static void get_graph(struct cdbus_method_call * call_ptr)
464 dbus_uint64_t known_version;
465 dbus_uint64_t current_version;
466 DBusMessageIter iter;
467 DBusMessageIter clients_array_iter;
468 DBusMessageIter connections_array_iter;
469 DBusMessageIter client_struct_iter;
470 struct list_head * client_node_ptr;
471 struct ladish_graph_client * client_ptr;
472 DBusMessageIter ports_array_iter;
473 struct list_head * port_node_ptr;
474 struct ladish_graph_port * port_ptr;
475 DBusMessageIter port_struct_iter;
476 struct list_head * connection_node_ptr;
477 struct ladish_graph_connection * connection_ptr;
478 DBusMessageIter connection_struct_iter;
480 //log_info("get_graph() called");
482 if (!dbus_message_get_args(call_ptr->message, &cdbus_g_dbus_error, DBUS_TYPE_UINT64, &known_version, DBUS_TYPE_INVALID))
484 cdbus_error(call_ptr, DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, cdbus_g_dbus_error.message);
485 dbus_error_free(&cdbus_g_dbus_error);
486 return;
489 //log_info("Getting graph, known version is %" PRIu64, known_version);
491 call_ptr->reply = dbus_message_new_method_return(call_ptr->message);
492 if (call_ptr->reply == NULL)
494 log_error("Ran out of memory trying to construct method return");
495 goto exit;
498 dbus_message_iter_init_append(call_ptr->reply, &iter);
500 current_version = graph_ptr->graph_version;
501 if (known_version > current_version)
503 cdbus_error(
504 call_ptr,
505 DBUS_ERROR_INVALID_ARGS,
506 "known graph version %" PRIu64 " is newer than actual version %" PRIu64,
507 known_version,
508 current_version);
509 goto exit;
512 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT64, &current_version))
514 goto nomem;
517 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(tsa(tsuu))", &clients_array_iter))
519 goto nomem;
522 if (known_version < current_version)
524 list_for_each(client_node_ptr, &graph_ptr->clients)
526 client_ptr = list_entry(client_node_ptr, struct ladish_graph_client, siblings);
528 if (client_ptr->hidden)
530 continue;
533 if (!dbus_message_iter_open_container (&clients_array_iter, DBUS_TYPE_STRUCT, NULL, &client_struct_iter))
535 goto nomem_close_clients_array;
538 if (!dbus_message_iter_append_basic(&client_struct_iter, DBUS_TYPE_UINT64, &client_ptr->id))
540 goto nomem_close_client_struct;
543 log_info("client '%s' (%llu)", client_ptr->name, (unsigned long long)client_ptr->id);
544 if (!dbus_message_iter_append_basic(&client_struct_iter, DBUS_TYPE_STRING, &client_ptr->name))
546 goto nomem_close_client_struct;
549 if (!dbus_message_iter_open_container(&client_struct_iter, DBUS_TYPE_ARRAY, "(tsuu)", &ports_array_iter))
551 goto nomem_close_client_struct;
554 list_for_each(port_node_ptr, &client_ptr->ports)
556 port_ptr = list_entry(port_node_ptr, struct ladish_graph_port, siblings_client);
558 if (port_ptr->hidden)
560 continue;
563 if (!dbus_message_iter_open_container(&ports_array_iter, DBUS_TYPE_STRUCT, NULL, &port_struct_iter))
565 goto nomem_close_ports_array;
568 if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT64, &port_ptr->id))
570 goto nomem_close_port_struct;
573 if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_STRING, &port_ptr->name))
575 goto nomem_close_port_struct;
578 if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT32, &port_ptr->flags))
580 goto nomem_close_port_struct;
583 if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT32, &port_ptr->type))
585 goto nomem_close_port_struct;
588 if (!dbus_message_iter_close_container(&ports_array_iter, &port_struct_iter))
590 goto nomem_close_ports_array;
594 if (!dbus_message_iter_close_container(&client_struct_iter, &ports_array_iter))
596 goto nomem_close_client_struct;
599 if (!dbus_message_iter_close_container(&clients_array_iter, &client_struct_iter))
601 goto nomem_close_clients_array;
606 if (!dbus_message_iter_close_container(&iter, &clients_array_iter))
608 goto nomem;
611 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(tstststst)", &connections_array_iter))
613 goto nomem;
616 if (known_version < current_version)
618 list_for_each(connection_node_ptr, &graph_ptr->connections)
620 connection_ptr = list_entry(connection_node_ptr, struct ladish_graph_connection, siblings);
622 if (connection_ptr->hidden)
624 continue;
627 if (!dbus_message_iter_open_container(&connections_array_iter, DBUS_TYPE_STRUCT, NULL, &connection_struct_iter))
629 goto nomem_close_connections_array;
632 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port1_ptr->client_ptr->id))
634 goto nomem_close_connection_struct;
637 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port1_ptr->client_ptr->name))
639 goto nomem_close_connection_struct;
642 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port1_ptr->id))
644 goto nomem_close_connection_struct;
647 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port1_ptr->name))
649 goto nomem_close_connection_struct;
652 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port2_ptr->client_ptr->id))
654 goto nomem_close_connection_struct;
657 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port2_ptr->client_ptr->name))
659 goto nomem_close_connection_struct;
662 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port2_ptr->id))
664 goto nomem_close_connection_struct;
667 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port2_ptr->name))
669 goto nomem_close_connection_struct;
672 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->id))
674 goto nomem_close_connection_struct;
677 if (!dbus_message_iter_close_container(&connections_array_iter, &connection_struct_iter))
679 goto nomem_close_connections_array;
684 if (!dbus_message_iter_close_container(&iter, &connections_array_iter))
686 goto nomem;
689 return;
691 nomem_close_connection_struct:
692 dbus_message_iter_close_container(&connections_array_iter, &connection_struct_iter);
694 nomem_close_connections_array:
695 dbus_message_iter_close_container(&iter, &connections_array_iter);
696 goto nomem;
698 nomem_close_port_struct:
699 dbus_message_iter_close_container(&ports_array_iter, &port_struct_iter);
701 nomem_close_ports_array:
702 dbus_message_iter_close_container(&client_struct_iter, &ports_array_iter);
704 nomem_close_client_struct:
705 dbus_message_iter_close_container(&clients_array_iter, &client_struct_iter);
707 nomem_close_clients_array:
708 dbus_message_iter_close_container(&iter, &clients_array_iter);
710 nomem:
711 dbus_message_unref(call_ptr->reply);
712 call_ptr->reply = NULL;
713 log_error("Ran out of memory trying to construct method return");
715 exit:
716 return;
719 static void connect_ports_by_name(struct cdbus_method_call * call_ptr)
721 const char * client1_name;
722 const char * port1_name;
723 const char * client2_name;
724 const char * port2_name;
725 struct ladish_graph_port * port1;
726 struct ladish_graph_port * port2;
728 if (!dbus_message_get_args(
729 call_ptr->message,
730 &cdbus_g_dbus_error,
731 DBUS_TYPE_STRING, &client1_name,
732 DBUS_TYPE_STRING, &port1_name,
733 DBUS_TYPE_STRING, &client2_name,
734 DBUS_TYPE_STRING, &port2_name,
735 DBUS_TYPE_INVALID))
737 cdbus_error(call_ptr, DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, cdbus_g_dbus_error.message);
738 dbus_error_free(&cdbus_g_dbus_error);
739 return;
742 log_info("connect_ports_by_name(\"%s\", \"%s\", \"%s\", \"%s\") called.", client1_name, port1_name, client2_name, port2_name);
744 if (!ladish_graph_find_connection_ports_by_name(graph_ptr, client1_name, port1_name, client2_name, port2_name, &port1, &port2))
746 cdbus_error(call_ptr, DBUS_ERROR_INVALID_ARGS, "Cannot connect unknown ports");
747 return;
750 if (graph_ptr->connect_handler(graph_ptr->context, (ladish_graph_handle)graph_ptr, port1->port, port2->port))
752 cdbus_method_return_new_void(call_ptr);
754 else
756 cdbus_error(call_ptr, DBUS_ERROR_FAILED, "connect failed");
760 static void connect_ports_by_id(struct cdbus_method_call * call_ptr)
762 dbus_uint64_t port1_id;
763 dbus_uint64_t port2_id;
764 struct ladish_graph_port * port1_ptr;
765 struct ladish_graph_port * port2_ptr;
767 if (!dbus_message_get_args(call_ptr->message, &cdbus_g_dbus_error, DBUS_TYPE_UINT64, &port1_id, DBUS_TYPE_UINT64, &port2_id, DBUS_TYPE_INVALID))
769 cdbus_error(call_ptr, DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, cdbus_g_dbus_error.message);
770 dbus_error_free(&cdbus_g_dbus_error);
771 return;
774 log_info("connect_ports_by_id(%"PRIu64",%"PRIu64") called.", port1_id, port2_id);
776 if (graph_ptr->connect_handler == NULL)
778 cdbus_error(call_ptr, DBUS_ERROR_FAILED, "connect requests on graph %s cannot be handlined", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
779 return;
782 port1_ptr = ladish_graph_find_port_by_id_internal(graph_ptr, port1_id);
783 if (port1_ptr == NULL)
785 cdbus_error(call_ptr, DBUS_ERROR_INVALID_ARGS, "Cannot connect unknown port with id %"PRIu64, port1_id);
786 return;
789 port2_ptr = ladish_graph_find_port_by_id_internal(graph_ptr, port2_id);
790 if (port2_ptr == NULL)
792 cdbus_error(call_ptr, DBUS_ERROR_INVALID_ARGS, "Cannot connect unknown port with id %"PRIu64, port2_id);
793 return;
796 log_info("connecting '%s':'%s' to '%s':'%s'", port1_ptr->client_ptr->name, port1_ptr->name, port2_ptr->client_ptr->name, port2_ptr->name);
798 if (graph_ptr->connect_handler(graph_ptr->context, (ladish_graph_handle)graph_ptr, port1_ptr->port, port2_ptr->port))
800 cdbus_method_return_new_void(call_ptr);
802 else
804 cdbus_error(call_ptr, DBUS_ERROR_FAILED, "connect failed");
808 static void disconnect_ports(struct cdbus_method_call * call_ptr, struct ladish_graph_connection * connection_ptr)
810 log_info(
811 "disconnecting '%s':'%s' from '%s':'%s'",
812 connection_ptr->port1_ptr->client_ptr->name,
813 connection_ptr->port1_ptr->name,
814 connection_ptr->port2_ptr->client_ptr->name,
815 connection_ptr->port2_ptr->name);
817 connection_ptr->changing = true;
818 if (graph_ptr->disconnect_handler(graph_ptr->context, (ladish_graph_handle)graph_ptr, connection_ptr->id))
820 cdbus_method_return_new_void(call_ptr);
822 else
824 connection_ptr->changing = false;
825 cdbus_error(call_ptr, DBUS_ERROR_FAILED, "disconnect failed");
829 static void disconnect_ports_by_name(struct cdbus_method_call * call_ptr)
831 const char * client1_name;
832 const char * port1_name;
833 const char * client2_name;
834 const char * port2_name;
835 struct ladish_graph_port * port1;
836 struct ladish_graph_port * port2;
837 struct ladish_graph_connection * connection_ptr;
839 if (!dbus_message_get_args(
840 call_ptr->message,
841 &cdbus_g_dbus_error,
842 DBUS_TYPE_STRING, &client1_name,
843 DBUS_TYPE_STRING, &port1_name,
844 DBUS_TYPE_STRING, &client2_name,
845 DBUS_TYPE_STRING, &port2_name,
846 DBUS_TYPE_INVALID))
848 cdbus_error(call_ptr, DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, cdbus_g_dbus_error.message);
849 dbus_error_free(&cdbus_g_dbus_error);
850 return;
853 log_info("disconnect_ports_by_name(\"%s\", \"%s\", \"%s\", \"%s\") called.", client1_name, port1_name, client2_name, port2_name);
855 if (!ladish_graph_find_connection_ports_by_name(graph_ptr, client1_name, port1_name, client2_name, port2_name, &port1, &port2))
857 cdbus_error(call_ptr, DBUS_ERROR_INVALID_ARGS, "Cannot disconnect unknown ports");
858 return;
861 connection_ptr = ladish_graph_find_connection_by_ports(graph_ptr, port1, port2);
862 if (connection_ptr == NULL)
864 cdbus_error(call_ptr, DBUS_ERROR_INVALID_ARGS, "Cannot disconnect not connected ports");
865 return;
868 disconnect_ports(call_ptr, connection_ptr);
871 static void disconnect_ports_by_id(struct cdbus_method_call * call_ptr)
873 dbus_uint64_t port1_id;
874 dbus_uint64_t port2_id;
875 struct ladish_graph_port * port1_ptr;
876 struct ladish_graph_port * port2_ptr;
877 struct ladish_graph_connection * connection_ptr;
879 if (!dbus_message_get_args(call_ptr->message, &cdbus_g_dbus_error, DBUS_TYPE_UINT64, &port1_id, DBUS_TYPE_UINT64, &port2_id, DBUS_TYPE_INVALID))
881 cdbus_error(call_ptr, DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, cdbus_g_dbus_error.message);
882 dbus_error_free(&cdbus_g_dbus_error);
883 return;
886 log_info("disconnect_ports_by_id(%"PRIu64",%"PRIu64") called.", port1_id, port2_id);
888 if (graph_ptr->disconnect_handler == NULL)
890 cdbus_error(call_ptr, DBUS_ERROR_FAILED, "disconnect requests on graph %s cannot be handlined", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
891 return;
894 port1_ptr = ladish_graph_find_port_by_id_internal(graph_ptr, port1_id);
895 if (port1_ptr == NULL)
897 cdbus_error(call_ptr, DBUS_ERROR_INVALID_ARGS, "Cannot disconnect unknown port with id %"PRIu64, port1_id);
898 return;
901 port2_ptr = ladish_graph_find_port_by_id_internal(graph_ptr, port2_id);
902 if (port2_ptr == NULL)
904 cdbus_error(call_ptr, DBUS_ERROR_INVALID_ARGS, "Cannot disconnect unknown port with id %"PRIu64, port2_id);
905 return;
908 connection_ptr = ladish_graph_find_connection_by_ports(graph_ptr, port1_ptr, port2_ptr);
909 if (connection_ptr == NULL)
911 cdbus_error(call_ptr, DBUS_ERROR_INVALID_ARGS, "Cannot disconnect not connected ports %"PRIu64" and %"PRIu64, port1_id, port2_id);
912 return;
915 disconnect_ports(call_ptr, connection_ptr);
918 static void disconnect_ports_by_connection_id(struct cdbus_method_call * call_ptr)
920 dbus_uint64_t connection_id;
921 struct ladish_graph_connection * connection_ptr;
923 if (!dbus_message_get_args(call_ptr->message, &cdbus_g_dbus_error, DBUS_TYPE_UINT64, &connection_id, DBUS_TYPE_INVALID))
925 cdbus_error(call_ptr, DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, cdbus_g_dbus_error.message);
926 dbus_error_free(&cdbus_g_dbus_error);
927 return;
930 log_info("disconnect_ports_by_connection_id(%"PRIu64") called.", connection_id);
932 connection_ptr = ladish_graph_find_connection_by_id(graph_ptr, connection_id);
933 if (connection_ptr == NULL)
935 cdbus_error(call_ptr, DBUS_ERROR_INVALID_ARGS, "Cannot find connection with id %"PRIu64, connection_id);
936 return;
939 disconnect_ports(call_ptr, connection_ptr);
942 static void get_client_pid(struct cdbus_method_call * call_ptr)
944 int64_t pid = 0;
945 cdbus_method_return_new_single(call_ptr, DBUS_TYPE_INT64, &pid);
948 #undef graph_ptr
950 bool ladish_graph_create(ladish_graph_handle * graph_handle_ptr, const char * opath)
952 struct ladish_graph * graph_ptr;
954 graph_ptr = malloc(sizeof(struct ladish_graph));
955 if (graph_ptr == NULL)
957 log_error("malloc() failed to allocate struct graph_implementator");
958 return false;
961 if (opath != NULL)
963 graph_ptr->opath = strdup(opath);
964 if (graph_ptr->opath == NULL)
966 log_error("strdup() failed for graph opath");
967 free(graph_ptr);
968 return false;
971 else
973 graph_ptr->opath = NULL;
976 if (!ladish_dict_create(&graph_ptr->dict))
978 log_error("ladish_dict_create() failed for graph");
979 if (graph_ptr->opath != NULL)
981 free(graph_ptr->opath);
983 free(graph_ptr);
984 return false;
987 INIT_LIST_HEAD(&graph_ptr->clients);
988 INIT_LIST_HEAD(&graph_ptr->ports);
989 INIT_LIST_HEAD(&graph_ptr->connections);
991 graph_ptr->graph_version = 1;
992 graph_ptr->next_client_id = 1;
993 graph_ptr->next_port_id = 1;
994 graph_ptr->next_connection_id = 1;
996 graph_ptr->context = NULL;
997 graph_ptr->connect_handler = NULL;
998 graph_ptr->disconnect_handler = NULL;
1000 graph_ptr->persist = true;
1002 *graph_handle_ptr = (ladish_graph_handle)graph_ptr;
1003 return true;
1006 static
1007 struct ladish_graph_client *
1008 ladish_graph_find_client(
1009 struct ladish_graph * graph_ptr,
1010 ladish_client_handle client)
1012 struct list_head * node_ptr;
1013 struct ladish_graph_client * client_ptr;
1015 list_for_each(node_ptr, &graph_ptr->clients)
1017 client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
1018 if (client_ptr->client == client)
1020 return client_ptr;
1024 return NULL;
1027 static
1028 struct ladish_graph_port *
1029 ladish_graph_find_port(
1030 struct ladish_graph * graph_ptr,
1031 ladish_port_handle port)
1033 struct list_head * node_ptr;
1034 struct ladish_graph_port * port_ptr;
1036 //log_info("searching port %p", port);
1038 list_for_each(node_ptr, &graph_ptr->ports)
1040 port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph);
1041 //log_info("checking port %s:%s, %p", port_ptr->client_ptr->name, port_ptr->name, port_ptr->port);
1042 if (port_ptr->port == port)
1044 return port_ptr;
1048 return NULL;
1051 #if defined(LOG_PORT_LOOKUP)
1052 #undef LOG_PORT_LOOKUP
1053 #endif
1054 //#define LOG_PORT_LOOKUP
1056 static
1057 struct ladish_graph_port *
1058 ladish_graph_find_port_by_jack_id_internal(
1059 struct ladish_graph * graph_ptr,
1060 uint64_t port_id,
1061 bool room,
1062 bool studio)
1064 struct list_head * node_ptr;
1065 struct ladish_graph_port * port_ptr;
1067 ASSERT(room || studio);
1069 #if defined(LOG_PORT_LOOKUP)
1070 log_info(
1071 "searching (in %s, %s) by jack id %"PRIu64" for port in graph %s",
1072 studio ? "studio" : "",
1073 room ? "room" : "",
1074 port_id,
1075 ladish_graph_get_description((ladish_graph_handle)graph_ptr));
1076 #endif
1078 list_for_each(node_ptr, &graph_ptr->ports)
1080 port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph);
1081 #if defined(LOG_PORT_LOOKUP)
1082 log_info(
1083 "checking jack port id of port %s:%s, %p; studio id %"PRIu64", room id %"PRIu64,
1084 port_ptr->client_ptr->name,
1085 port_ptr->name, port_ptr->port,
1086 ladish_port_get_jack_id(port_ptr->port),
1087 ladish_port_get_jack_id_room(port_ptr->port));
1088 #endif
1089 if ((studio && ladish_port_get_jack_id(port_ptr->port) == port_id) ||
1090 (room && port_ptr->link && ladish_port_get_jack_id_room(port_ptr->port) == port_id))
1092 //log_info("found");
1093 return port_ptr;
1097 return NULL;
1100 #if 0
1101 static
1102 struct ladish_graph_port *
1103 ladish_graph_find_client_port(
1104 struct ladish_graph * graph_ptr,
1105 struct ladish_graph_client * client_ptr,
1106 ladish_port_handle port)
1108 struct list_head * node_ptr;
1109 struct ladish_graph_port * port_ptr;
1111 list_for_each(node_ptr, &client_ptr->ports)
1113 port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_client);
1114 if (port_ptr->port == port)
1116 return port_ptr;
1120 return NULL;
1122 #endif
1124 static void ladish_graph_hide_connection_internal(struct ladish_graph * graph_ptr, struct ladish_graph_connection * connection_ptr)
1126 ASSERT(!connection_ptr->hidden);
1127 connection_ptr->hidden = true;
1128 graph_ptr->graph_version++;
1130 if (graph_ptr->opath != NULL)
1132 ladish_graph_emit_ports_disconnected(graph_ptr, connection_ptr);
1136 static void ladish_graph_show_port_internal(struct ladish_graph * graph_ptr, struct ladish_graph_port * port_ptr)
1138 if (port_ptr->client_ptr->hidden)
1140 port_ptr->client_ptr->hidden = false;
1141 graph_ptr->graph_version++;
1142 if (graph_ptr->opath != NULL)
1144 ladish_graph_emit_client_appeared(graph_ptr, port_ptr->client_ptr);
1148 ASSERT(port_ptr->hidden);
1149 port_ptr->hidden = false;
1150 graph_ptr->graph_version++;
1151 if (graph_ptr->opath != NULL)
1153 ladish_graph_emit_port_appeared(graph_ptr, port_ptr);
1154 ladish_try_connect_hidden_connections((ladish_graph_handle)graph_ptr);
1158 static void ladish_graph_hide_port_internal(struct ladish_graph * graph_ptr, struct ladish_graph_port * port_ptr)
1160 ASSERT(!port_ptr->hidden);
1161 port_ptr->hidden = true;
1162 graph_ptr->graph_version++;
1164 if (graph_ptr->opath != NULL)
1166 ladish_graph_emit_port_disappeared(graph_ptr, port_ptr);
1170 static void ladish_graph_hide_client_internal(struct ladish_graph * graph_ptr, struct ladish_graph_client * client_ptr)
1172 ASSERT(!client_ptr->hidden);
1173 client_ptr->hidden = true;
1174 graph_ptr->graph_version++;
1176 if (graph_ptr->opath != NULL)
1178 ladish_graph_emit_client_disappeared(graph_ptr, client_ptr);
1182 static void ladish_hide_connections(struct ladish_graph * graph_ptr, struct ladish_graph_port * port_ptr)
1184 struct list_head * node_ptr;
1185 struct ladish_graph_connection * connection_ptr;
1187 log_info("hidding connections of port %"PRIu64, port_ptr->id);
1189 ASSERT(graph_ptr->opath != NULL);
1191 list_for_each(node_ptr, &graph_ptr->connections)
1193 connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
1194 if (!connection_ptr->hidden && (connection_ptr->port1_ptr == port_ptr || connection_ptr->port2_ptr == port_ptr))
1196 log_info("hidding connection between ports %"PRIu64" and %"PRIu64, connection_ptr->port1_ptr->id, connection_ptr->port2_ptr->id);
1197 ladish_graph_hide_connection_internal(graph_ptr, connection_ptr);
1202 static void ladish_graph_remove_connection_internal(struct ladish_graph * graph_ptr, struct ladish_graph_connection * connection_ptr)
1204 list_del(&connection_ptr->siblings);
1205 graph_ptr->graph_version++;
1207 if (!connection_ptr->hidden && graph_ptr->opath != NULL)
1209 ladish_graph_emit_ports_disconnected(graph_ptr, connection_ptr);
1212 ladish_dict_destroy(connection_ptr->dict);
1213 free(connection_ptr);
1216 static void ladish_graph_remove_port_connections(struct ladish_graph * graph_ptr, struct ladish_graph_port * port_ptr)
1218 struct list_head * node_ptr;
1219 struct list_head * temp_node_ptr;
1220 struct ladish_graph_connection * connection_ptr;
1222 list_for_each_safe(node_ptr, temp_node_ptr, &graph_ptr->connections)
1224 connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
1225 if (connection_ptr->port1_ptr == port_ptr || connection_ptr->port2_ptr == port_ptr)
1227 log_info("removing connection between ports %"PRIu64" and %"PRIu64, connection_ptr->port1_ptr->id, connection_ptr->port2_ptr->id);
1228 ladish_graph_remove_connection_internal(graph_ptr, connection_ptr);
1233 static
1234 void
1235 ladish_graph_remove_port_internal(
1236 struct ladish_graph * graph_ptr,
1237 struct ladish_graph_client * client_ptr,
1238 struct ladish_graph_port * port_ptr)
1240 ladish_graph_remove_port_connections(graph_ptr, port_ptr);
1242 ladish_port_del_ref(port_ptr->port);
1244 list_del(&port_ptr->siblings_client);
1245 list_del(&port_ptr->siblings_graph);
1247 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");
1248 if (graph_ptr->opath != NULL && !port_ptr->hidden)
1250 ASSERT(port_ptr->client_ptr == client_ptr);
1251 ladish_graph_emit_port_disappeared(graph_ptr, port_ptr);
1254 free(port_ptr->name);
1255 free(port_ptr);
1258 static
1259 void
1260 ladish_graph_remove_client_internal(
1261 struct ladish_graph * graph_ptr,
1262 struct ladish_graph_client * client_ptr,
1263 bool destroy_client,
1264 ladish_graph_simple_port_callback port_callback)
1266 struct ladish_graph_port * port_ptr;
1268 while (!list_empty(&client_ptr->ports))
1270 port_ptr = list_entry(client_ptr->ports.next, struct ladish_graph_port, siblings_client);
1271 if (port_callback != NULL)
1273 port_callback(port_ptr->port);
1275 ladish_graph_remove_port_internal(graph_ptr, client_ptr, port_ptr);
1278 graph_ptr->graph_version++;
1279 list_del(&client_ptr->siblings);
1280 log_info("removing client '%s' (%"PRIu64") from graph %s", client_ptr->name, client_ptr->id, graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
1281 if (graph_ptr->opath != NULL && !client_ptr->hidden)
1283 ladish_graph_emit_client_disappeared(graph_ptr, client_ptr);
1286 free(client_ptr->name);
1288 if (destroy_client)
1290 ladish_client_destroy(client_ptr->client);
1293 free(client_ptr);
1296 bool ladish_graph_client_looks_empty_internal(struct ladish_graph * graph_ptr, struct ladish_graph_client * client_ptr)
1298 struct list_head * node_ptr;
1299 struct ladish_graph_port * port_ptr;
1301 list_for_each(node_ptr, &client_ptr->ports)
1303 port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_client);
1304 if (!port_ptr->hidden)
1306 log_debug("port '%s' is visible, client '%s' does not look empty", port_ptr->name, client_ptr->name);
1307 return false;
1309 else
1311 log_debug("port '%s' is invisible", port_ptr->name);
1315 log_debug("client '%s' looks empty in graph %s", client_ptr->name, graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
1316 return true;
1319 #define graph_ptr ((struct ladish_graph *)graph_handle)
1321 void ladish_graph_destroy(ladish_graph_handle graph_handle)
1323 ladish_graph_clear(graph_handle, NULL);
1324 ladish_dict_destroy(graph_ptr->dict);
1325 if (graph_ptr->opath != NULL)
1327 free(graph_ptr->opath);
1329 free(graph_ptr);
1332 const char * ladish_graph_get_opath(ladish_graph_handle graph_handle)
1334 return graph_ptr->opath;
1337 const char * ladish_graph_get_description(ladish_graph_handle graph_handle)
1339 return graph_ptr->opath != NULL ? graph_ptr->opath : "JACK";
1342 void
1343 ladish_graph_set_connection_handlers(
1344 ladish_graph_handle graph_handle,
1345 void * graph_context,
1346 ladish_graph_connect_request_handler connect_handler,
1347 ladish_graph_disconnect_request_handler disconnect_handler)
1349 log_info("setting connection handlers for graph '%s'", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
1350 graph_ptr->context = graph_context;
1351 graph_ptr->connect_handler = connect_handler;
1352 graph_ptr->disconnect_handler = disconnect_handler;
1355 void ladish_graph_clear(ladish_graph_handle graph_handle, ladish_graph_simple_port_callback port_callback)
1357 struct ladish_graph_client * client_ptr;
1358 struct ladish_graph_connection * connection_ptr;
1360 log_info("ladish_graph_clear() called for graph '%s'", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
1362 while (!list_empty(&graph_ptr->connections))
1364 connection_ptr = list_entry(graph_ptr->connections.next, struct ladish_graph_connection, siblings);
1365 ladish_graph_remove_connection_internal(graph_ptr, connection_ptr);
1368 while (!list_empty(&graph_ptr->clients))
1370 client_ptr = list_entry(graph_ptr->clients.next, struct ladish_graph_client, siblings);
1371 ladish_graph_remove_client_internal(graph_ptr, client_ptr, true, port_callback);
1375 void * ladish_graph_get_dbus_context(ladish_graph_handle graph_handle)
1377 return graph_handle;
1380 ladish_dict_handle ladish_graph_get_dict(ladish_graph_handle graph_handle)
1382 return graph_ptr->dict;
1385 void ladish_graph_show_connection(ladish_graph_handle graph_handle, uint64_t connection_id)
1387 struct ladish_graph_connection * connection_ptr;
1389 log_info("ladish_graph_show_connection() called.");
1391 connection_ptr = ladish_graph_find_connection_by_id(graph_ptr, connection_id);
1392 if (connection_ptr == NULL)
1394 ASSERT_NO_PASS;
1395 return;
1398 ASSERT(graph_ptr->opath != NULL);
1399 ASSERT(connection_ptr->hidden);
1400 connection_ptr->hidden = false;
1401 connection_ptr->changing = false;
1402 graph_ptr->graph_version++;
1404 ladish_graph_emit_ports_connected(graph_ptr, connection_ptr);
1407 void ladish_graph_show_port(ladish_graph_handle graph_handle, ladish_port_handle port_handle)
1409 struct ladish_graph_port * port_ptr;
1411 //log_info("ladish_graph_show_port() called.");
1413 port_ptr = ladish_graph_find_port(graph_ptr, port_handle);
1414 if (port_ptr == NULL)
1416 ASSERT_NO_PASS;
1417 return;
1420 //log_info("port '%s' is %s", port_ptr->name, port_ptr->hidden ? "invisible" : "visible");
1422 ladish_graph_show_port_internal(graph_ptr, port_ptr);
1425 void ladish_graph_hide_port(ladish_graph_handle graph_handle, ladish_port_handle port_handle)
1427 struct ladish_graph_port * port_ptr;
1429 log_info("ladish_graph_hide_port() called.");
1431 port_ptr = ladish_graph_find_port(graph_ptr, port_handle);
1432 if (port_ptr == NULL)
1434 ASSERT_NO_PASS;
1435 return;
1438 log_info("Hidding port %"PRIu64, port_ptr->id);
1440 ASSERT(!port_ptr->hidden);
1442 if (graph_ptr->opath != NULL)
1444 ladish_hide_connections(graph_ptr, port_ptr);
1447 ladish_graph_hide_port_internal(graph_ptr, port_ptr);
1450 void ladish_graph_hide_client(ladish_graph_handle graph_handle, ladish_client_handle client_handle)
1452 struct ladish_graph_client * client_ptr;
1454 log_info("ladish_graph_hide_client() called.");
1456 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1457 if (client_ptr == NULL)
1459 ASSERT_NO_PASS;
1460 return;
1463 ladish_graph_hide_client_internal(graph_ptr, client_ptr);
1466 void ladish_graph_show_client(ladish_graph_handle graph_handle, ladish_client_handle client_handle)
1468 struct ladish_graph_client * client_ptr;
1470 log_info("ladish_graph_show_client() called.");
1472 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1473 if (client_ptr == NULL)
1475 ASSERT_NO_PASS;
1476 return;
1479 ASSERT(client_ptr->hidden);
1480 client_ptr->hidden = false;
1481 graph_ptr->graph_version++;
1483 if (graph_ptr->opath != NULL)
1485 ladish_graph_emit_client_appeared(graph_ptr, client_ptr);
1489 void ladish_graph_adjust_port(ladish_graph_handle graph_handle, ladish_port_handle port_handle, uint32_t type, uint32_t flags)
1491 struct ladish_graph_port * port_ptr;
1493 //log_info("ladish_graph_adjust_port() called.");
1495 port_ptr = ladish_graph_find_port(graph_ptr, port_handle);
1496 if (port_ptr == NULL)
1498 ASSERT_NO_PASS;
1499 return;
1502 port_ptr->type = type;
1503 port_ptr->flags = flags;
1506 bool ladish_graph_add_client(ladish_graph_handle graph_handle, ladish_client_handle client_handle, const char * name, bool hidden)
1508 struct ladish_graph_client * client_ptr;
1510 log_info("adding client '%s' (%p) to graph %s", name, client_handle, graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
1512 client_ptr = malloc(sizeof(struct ladish_graph_client));
1513 if (client_ptr == NULL)
1515 log_error("malloc() failed for struct ladish_graph_client");
1516 return false;
1519 client_ptr->name = strdup(name);
1520 if (client_ptr->name == NULL)
1522 log_error("strdup() failed for graph client name");
1523 free(client_ptr);
1524 return false;
1527 client_ptr->id = graph_ptr->next_client_id++;
1528 client_ptr->client = client_handle;
1529 client_ptr->hidden = hidden;
1530 graph_ptr->graph_version++;
1532 INIT_LIST_HEAD(&client_ptr->ports);
1534 list_add_tail(&client_ptr->siblings, &graph_ptr->clients);
1536 if (!hidden && graph_ptr->opath != NULL)
1538 ladish_graph_emit_client_appeared(graph_ptr, client_ptr);
1541 return true;
1544 void
1545 ladish_graph_remove_client(
1546 ladish_graph_handle graph_handle,
1547 ladish_client_handle client_handle)
1549 struct ladish_graph_client * client_ptr;
1551 log_info("ladish_graph_remove_client() called.");
1553 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1554 if (client_ptr != NULL)
1556 ladish_graph_remove_client_internal(graph_ptr, client_ptr, false, NULL);
1558 else
1560 ASSERT_NO_PASS;
1564 uint64_t
1565 ladish_graph_get_client_id(
1566 ladish_graph_handle graph_handle,
1567 ladish_client_handle client_handle)
1569 struct ladish_graph_client * client_ptr;
1571 log_info("ladish_graph_get_client_id() called.");
1573 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1574 if (client_ptr != NULL)
1576 return client_ptr->id;
1578 else
1580 ASSERT_NO_PASS;
1581 return 0;
1585 bool
1586 ladish_graph_add_port(
1587 ladish_graph_handle graph_handle,
1588 ladish_client_handle client_handle,
1589 ladish_port_handle port_handle,
1590 const char * name,
1591 uint32_t type,
1592 uint32_t flags,
1593 bool hidden)
1595 struct ladish_graph_client * client_ptr;
1596 struct ladish_graph_port * port_ptr;
1598 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1599 if (client_ptr == NULL)
1601 log_error("cannot find client to add port to. graph is %s", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
1602 ASSERT_NO_PASS;
1603 return false;
1606 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");
1608 port_ptr = malloc(sizeof(struct ladish_graph_port));
1609 if (port_ptr == NULL)
1611 log_error("malloc() failed for struct ladish_graph_port");
1612 return false;
1615 port_ptr->name = strdup(name);
1616 if (port_ptr->name == NULL)
1618 log_error("strdup() failed for graph port name");
1619 free(port_ptr);
1620 return false;
1623 port_ptr->type = type;
1624 port_ptr->flags = flags;
1626 port_ptr->id = graph_ptr->next_port_id++;
1627 port_ptr->port = port_handle;
1628 ladish_port_add_ref(port_ptr->port);
1629 port_ptr->hidden = true;
1631 port_ptr->link = ladish_port_is_link(port_handle);
1632 if (port_ptr->link)
1634 uuid_generate(port_ptr->link_uuid_override);
1637 port_ptr->client_ptr = client_ptr;
1638 list_add_tail(&port_ptr->siblings_client, &client_ptr->ports);
1639 list_add_tail(&port_ptr->siblings_graph, &graph_ptr->ports);
1641 if (!hidden)
1643 ladish_graph_show_port_internal(graph_ptr, port_ptr);
1646 return true;
1649 uint64_t
1650 ladish_graph_add_connection(
1651 ladish_graph_handle graph_handle,
1652 ladish_port_handle port1_handle,
1653 ladish_port_handle port2_handle,
1654 bool hidden)
1656 struct ladish_graph_port * port1_ptr;
1657 struct ladish_graph_port * port2_ptr;
1658 struct ladish_graph_connection * connection_ptr;
1660 port1_ptr = ladish_graph_find_port(graph_ptr, port1_handle);
1661 ASSERT(port1_ptr != NULL);
1662 port2_ptr = ladish_graph_find_port(graph_ptr, port2_handle);
1663 ASSERT(port2_ptr != NULL);
1665 connection_ptr = malloc(sizeof(struct ladish_graph_connection));
1666 if (connection_ptr == NULL)
1668 log_error("malloc() failed for struct ladish_graph_connection");
1669 return 0;
1672 if (!ladish_dict_create(&connection_ptr->dict))
1674 log_error("ladish_dict_create() failed for connection");
1675 free(connection_ptr);
1676 return 0;
1679 connection_ptr->id = graph_ptr->next_connection_id++;
1680 connection_ptr->port1_ptr = port1_ptr;
1681 connection_ptr->port2_ptr = port2_ptr;
1682 connection_ptr->hidden = hidden;
1683 connection_ptr->changing = false;
1684 graph_ptr->graph_version++;
1686 list_add_tail(&connection_ptr->siblings, &graph_ptr->connections);
1688 /* log_info( */
1689 /* "new connection %"PRIu64" between '%s':'%s' and '%s':'%s'", */
1690 /* connection_ptr->id, */
1691 /* port1_ptr->client_ptr->name, */
1692 /* port1_ptr->name, */
1693 /* port2_ptr->client_ptr->name, */
1694 /* port2_ptr->name); */
1696 if (!hidden && graph_ptr->opath != NULL)
1698 ladish_graph_emit_ports_connected(graph_ptr, connection_ptr);
1701 return connection_ptr->id;
1704 void
1705 ladish_graph_remove_connection(
1706 ladish_graph_handle graph_handle,
1707 uint64_t connection_id,
1708 bool force)
1710 struct ladish_graph_connection * connection_ptr;
1712 connection_ptr = ladish_graph_find_connection_by_id(graph_ptr, connection_id);
1713 if (connection_ptr == NULL)
1715 ASSERT_NO_PASS;
1716 return;
1719 if (force || connection_ptr->changing || !graph_ptr->persist)
1721 /* log_info( */
1722 /* "removing connection '%s':'%s' - '%s':'%s'", */
1723 /* connection_ptr->port1_ptr->client_ptr->name, */
1724 /* connection_ptr->port1_ptr->name, */
1725 /* connection_ptr->port2_ptr->client_ptr->name, */
1726 /* connection_ptr->port2_ptr->name); */
1728 ladish_graph_remove_connection_internal(graph_ptr, connection_ptr);
1730 else
1732 /* log_info( */
1733 /* "hiding connection '%s':'%s' - '%s':'%s'", */
1734 /* connection_ptr->port1_ptr->client_ptr->name, */
1735 /* connection_ptr->port1_ptr->name, */
1736 /* connection_ptr->port2_ptr->client_ptr->name, */
1737 /* connection_ptr->port2_ptr->name); */
1739 ladish_graph_hide_connection_internal(graph_ptr, connection_ptr);
1743 bool
1744 ladish_graph_get_connection_ports(
1745 ladish_graph_handle graph_handle,
1746 uint64_t connection_id,
1747 ladish_port_handle * port1_handle_ptr,
1748 ladish_port_handle * port2_handle_ptr)
1750 struct ladish_graph_connection * connection_ptr;
1752 connection_ptr = ladish_graph_find_connection_by_id(graph_ptr, connection_id);
1753 if (connection_ptr == NULL)
1755 return false;
1758 *port1_handle_ptr = connection_ptr->port1_ptr->port;
1759 *port2_handle_ptr = connection_ptr->port2_ptr->port;
1761 return true;
1764 ladish_dict_handle ladish_graph_get_connection_dict(ladish_graph_handle graph_handle, uint64_t connection_id)
1766 struct ladish_graph_connection * connection_ptr;
1768 connection_ptr = ladish_graph_find_connection_by_id(graph_ptr, connection_id);
1769 if (connection_ptr == NULL)
1771 return NULL;
1774 return connection_ptr->dict;
1777 bool
1778 ladish_graph_find_connection(
1779 ladish_graph_handle graph_handle,
1780 ladish_port_handle port1_handle,
1781 ladish_port_handle port2_handle,
1782 uint64_t * connection_id_ptr)
1784 struct ladish_graph_port * port1_ptr;
1785 struct ladish_graph_port * port2_ptr;
1786 struct ladish_graph_connection * connection_ptr;
1788 port1_ptr = ladish_graph_find_port(graph_ptr, port1_handle);
1789 if (port1_ptr == NULL)
1791 return false;
1794 port2_ptr = ladish_graph_find_port(graph_ptr, port2_handle);
1795 if (port1_ptr == NULL)
1797 return false;
1800 connection_ptr = ladish_graph_find_connection_by_ports(graph_ptr, port1_ptr, port2_ptr);
1801 if (connection_ptr == NULL)
1803 return false;
1806 *connection_id_ptr = connection_ptr->id;
1808 return true;
1811 ladish_client_handle ladish_graph_find_client_by_name(ladish_graph_handle graph_handle, const char * name, bool appless)
1813 struct list_head * node_ptr;
1814 struct ladish_graph_client * client_ptr;
1816 list_for_each(node_ptr, &graph_ptr->clients)
1818 client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
1819 if (strcmp(client_ptr->name, name) == 0 &&
1820 (!appless || !ladish_client_has_app(client_ptr->client))) /* if appless is true, then an appless client is being searched */
1822 return client_ptr->client;
1826 return NULL;
1829 ladish_client_handle ladish_graph_find_client_by_app(ladish_graph_handle graph_handle, const uuid_t app_uuid)
1831 struct list_head * node_ptr;
1832 struct ladish_graph_client * client_ptr;
1833 uuid_t current_uuid;
1835 list_for_each(node_ptr, &graph_ptr->clients)
1837 client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
1838 if (!ladish_client_get_app(client_ptr->client, current_uuid))
1839 continue;
1841 if (uuid_compare(current_uuid, app_uuid) == 0)
1843 return client_ptr->client;
1847 return NULL;
1850 ladish_port_handle
1851 ladish_graph_find_port_by_name(
1852 ladish_graph_handle graph_handle,
1853 ladish_client_handle client_handle,
1854 const char * name,
1855 void * vgraph_filter)
1857 struct ladish_graph_client * client_ptr;
1858 struct list_head * node_ptr;
1859 struct ladish_graph_port * port_ptr;
1861 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1862 if (client_ptr != NULL)
1864 list_for_each(node_ptr, &client_ptr->ports)
1866 port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_client);
1868 if (vgraph_filter != NULL && ladish_port_get_vgraph(port_ptr->port) != vgraph_filter)
1870 continue;
1873 if (strcmp(port_ptr->name, name) == 0)
1875 return port_ptr->port;
1879 else
1881 ASSERT_NO_PASS;
1884 return NULL;
1887 ladish_client_handle ladish_graph_find_client_by_uuid(ladish_graph_handle graph_handle, const uuid_t uuid)
1889 struct list_head * node_ptr;
1890 struct ladish_graph_client * client_ptr;
1891 uuid_t current_uuid;
1893 list_for_each(node_ptr, &graph_ptr->clients)
1895 client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
1896 ladish_client_get_uuid(client_ptr->client, current_uuid);
1897 if (uuid_compare(current_uuid, uuid) == 0)
1899 return client_ptr->client;
1903 return NULL;
1906 ladish_port_handle ladish_graph_find_port_by_uuid(ladish_graph_handle graph_handle, const uuid_t uuid, bool use_link_override_uuids, void * vgraph_filter)
1908 struct ladish_graph_port * port_ptr;
1910 port_ptr = ladish_graph_find_port_by_uuid_internal(graph_ptr, NULL, uuid, use_link_override_uuids, vgraph_filter);
1911 if (port_ptr != NULL)
1913 return port_ptr->port;
1916 return NULL;
1919 ladish_client_handle ladish_graph_get_port_client(ladish_graph_handle graph_handle, ladish_port_handle port_handle)
1921 struct ladish_graph_port * port_ptr;
1923 port_ptr = ladish_graph_find_port(graph_ptr, port_handle);
1924 if (port_ptr == NULL)
1926 return NULL;
1929 return port_ptr->client_ptr->client;
1932 bool ladish_graph_is_port_present(ladish_graph_handle graph_handle, ladish_port_handle port_handle)
1934 return ladish_graph_find_port(graph_ptr, port_handle) != NULL;
1937 ladish_client_handle ladish_graph_find_client_by_id(ladish_graph_handle graph_handle, uint64_t client_id)
1939 struct list_head * node_ptr;
1940 struct ladish_graph_client * client_ptr;
1942 list_for_each(node_ptr, &graph_ptr->clients)
1944 client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
1945 if (client_ptr->id == client_id)
1947 return client_ptr->client;
1951 return NULL;
1954 ladish_port_handle ladish_graph_find_port_by_id(ladish_graph_handle graph_handle, uint64_t port_id)
1956 struct ladish_graph_port * port_ptr;
1958 port_ptr = ladish_graph_find_port_by_id_internal(graph_ptr, port_id);
1959 if (port_ptr == NULL)
1961 return NULL;
1964 return port_ptr->port;
1967 ladish_client_handle ladish_graph_find_client_by_jack_id(ladish_graph_handle graph_handle, uint64_t client_id)
1969 struct list_head * node_ptr;
1970 struct ladish_graph_client * client_ptr;
1972 list_for_each(node_ptr, &graph_ptr->clients)
1974 client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
1975 if (ladish_client_get_jack_id(client_ptr->client) == client_id)
1977 return client_ptr->client;
1981 return NULL;
1984 ladish_port_handle ladish_graph_find_port_by_jack_id(ladish_graph_handle graph_handle, uint64_t port_id, bool room, bool studio)
1986 struct ladish_graph_port * port_ptr;
1988 port_ptr = ladish_graph_find_port_by_jack_id_internal(graph_ptr, port_id, room, studio);
1989 if (port_ptr == NULL)
1991 return NULL;
1994 return port_ptr->port;
1997 bool ladish_graph_client_has_visible_app_port(ladish_graph_handle graph_handle, ladish_client_handle client_handle, const uuid_t app_uuid)
1999 struct ladish_graph_client * client_ptr;
2000 struct list_head * node_ptr;
2001 struct ladish_graph_port * port_ptr;
2003 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
2004 if (client_ptr == NULL)
2006 ASSERT_NO_PASS;
2007 return false;
2010 list_for_each(node_ptr, &client_ptr->ports)
2012 port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_client);
2013 if (port_ptr->hidden)
2015 continue;
2018 if (ladish_port_belongs_to_app(port_ptr->port, app_uuid))
2020 ASSERT(!client_ptr->hidden);
2021 return true;
2025 return false;
2028 bool ladish_graph_client_has_visible_ports(ladish_graph_handle graph_handle, ladish_client_handle client_handle)
2030 struct ladish_graph_client * client_ptr;
2031 struct list_head * node_ptr;
2032 struct ladish_graph_port * port_ptr;
2034 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
2035 if (client_ptr == NULL)
2037 ASSERT_NO_PASS;
2038 return false;
2041 list_for_each(node_ptr, &client_ptr->ports)
2043 port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_client);
2044 if (!port_ptr->hidden)
2046 return true;
2050 return false;
2053 ladish_client_handle
2054 ladish_graph_remove_port(
2055 ladish_graph_handle graph_handle,
2056 ladish_port_handle port)
2058 struct ladish_graph_port * port_ptr;
2059 ladish_client_handle client;
2061 port_ptr = ladish_graph_find_port(graph_ptr, port);
2062 if (port_ptr == NULL)
2064 return NULL;
2067 client = port_ptr->client_ptr->client;
2068 ladish_graph_remove_port_internal(graph_ptr, port_ptr->client_ptr, port_ptr);
2069 return client;
2072 ladish_client_handle
2073 ladish_graph_remove_port_by_jack_id(
2074 ladish_graph_handle graph_handle,
2075 uint64_t jack_port_id,
2076 bool room,
2077 bool studio)
2079 struct ladish_graph_port * port_ptr;
2080 ladish_client_handle client;
2082 port_ptr = ladish_graph_find_port_by_jack_id_internal(graph_ptr, jack_port_id, room, studio);
2083 if (port_ptr == NULL)
2085 return NULL;
2088 client = port_ptr->client_ptr->client;
2089 ladish_graph_remove_port_internal(graph_ptr, port_ptr->client_ptr, port_ptr);
2090 return client;
2093 void
2094 ladish_graph_move_port(
2095 ladish_graph_handle graph_handle,
2096 ladish_port_handle port_handle,
2097 ladish_client_handle client_handle)
2099 struct ladish_graph_port * port_ptr;
2100 struct ladish_graph_client * client_ptr;
2101 struct list_head * node_ptr;
2102 struct ladish_graph_connection * connection_ptr;
2104 port_ptr = ladish_graph_find_port(graph_ptr, port_handle);
2105 if (port_ptr == NULL)
2107 ASSERT_NO_PASS;
2108 return;
2111 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
2112 if (client_ptr == NULL)
2114 ASSERT_NO_PASS;
2115 return;
2118 list_del(&port_ptr->siblings_client);
2119 list_del(&port_ptr->siblings_graph);
2120 graph_ptr->graph_version++;
2122 if (graph_ptr->opath != NULL && !port_ptr->hidden)
2124 list_for_each(node_ptr, &graph_ptr->connections)
2126 connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
2127 if (!connection_ptr->hidden && (connection_ptr->port1_ptr == port_ptr || connection_ptr->port2_ptr == port_ptr))
2129 ladish_graph_emit_ports_disconnected(graph_ptr, connection_ptr);
2130 graph_ptr->graph_version++;
2134 ladish_graph_emit_port_disappeared(graph_ptr, port_ptr);
2137 port_ptr->id = graph_ptr->next_port_id++;
2138 port_ptr->client_ptr = client_ptr;
2139 list_add_tail(&port_ptr->siblings_client, &client_ptr->ports);
2140 list_add_tail(&port_ptr->siblings_graph, &graph_ptr->ports);
2141 graph_ptr->graph_version++;
2143 if (graph_ptr->opath != NULL && !port_ptr->hidden)
2145 ladish_graph_emit_port_appeared(graph_ptr, port_ptr);
2147 list_for_each(node_ptr, &graph_ptr->connections)
2149 connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
2150 if (!connection_ptr->hidden && (connection_ptr->port1_ptr == port_ptr || connection_ptr->port2_ptr == port_ptr))
2152 graph_ptr->next_connection_id++;
2153 graph_ptr->graph_version++;
2154 ladish_graph_emit_ports_connected(graph_ptr, connection_ptr);
2160 bool
2161 ladish_graph_rename_client(
2162 ladish_graph_handle graph_handle,
2163 ladish_client_handle client_handle,
2164 const char * new_client_name)
2166 char * name;
2167 struct ladish_graph_client * client_ptr;
2168 char * old_name;
2170 name = strdup(new_client_name);
2171 if (name == NULL)
2173 log_error("strdup('%s') failed.", new_client_name);
2174 return false;
2177 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
2178 if (client_ptr == NULL)
2180 free(name);
2181 ASSERT_NO_PASS;
2182 return false;
2185 old_name = client_ptr->name;
2186 client_ptr->name = name;
2188 graph_ptr->graph_version++;
2190 if (!client_ptr->hidden && graph_ptr->opath != NULL)
2192 cdbus_signal_emit(
2193 cdbus_g_dbus_connection,
2194 graph_ptr->opath,
2195 JACKDBUS_IFACE_PATCHBAY,
2196 "ClientRenamed",
2197 "ttss",
2198 &graph_ptr->graph_version,
2199 &client_ptr->id,
2200 &old_name,
2201 &client_ptr->name);
2204 free(old_name);
2206 return true;
2209 bool
2210 ladish_graph_rename_port(
2211 ladish_graph_handle graph_handle,
2212 ladish_port_handle port_handle,
2213 const char * new_port_name)
2215 char * name;
2216 struct ladish_graph_port * port_ptr;
2217 char * old_name;
2219 name = strdup(new_port_name);
2220 if (name == NULL)
2222 log_error("strdup('%s') failed.", new_port_name);
2223 return false;
2226 port_ptr = ladish_graph_find_port(graph_ptr, port_handle);
2227 if (port_ptr == NULL)
2229 ASSERT_NO_PASS;
2230 free(name);
2231 return false;
2234 old_name = port_ptr->name;
2235 port_ptr->name = name;
2237 graph_ptr->graph_version++;
2239 if (!port_ptr->hidden && graph_ptr->opath != NULL)
2241 cdbus_signal_emit(
2242 cdbus_g_dbus_connection,
2243 graph_ptr->opath,
2244 JACKDBUS_IFACE_PATCHBAY,
2245 "PortRenamed",
2246 "ttstss",
2247 &graph_ptr->graph_version,
2248 &port_ptr->client_ptr->id,
2249 &port_ptr->client_ptr->name,
2250 &port_ptr->id,
2251 &old_name,
2252 &port_ptr->name);
2255 free(old_name);
2257 return true;
2260 const char * ladish_graph_get_client_name(ladish_graph_handle graph_handle, ladish_client_handle client_handle)
2262 struct ladish_graph_client * client_ptr;
2264 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
2265 if (client_ptr != NULL)
2267 return client_ptr->name;
2270 ASSERT_NO_PASS;
2271 return NULL;
2274 bool ladish_graph_client_is_empty(ladish_graph_handle graph_handle, ladish_client_handle client_handle)
2276 struct ladish_graph_client * client_ptr;
2278 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
2279 if (client_ptr != NULL)
2281 return list_empty(&client_ptr->ports);
2284 ASSERT_NO_PASS;
2285 return true;
2288 bool ladish_graph_client_looks_empty(ladish_graph_handle graph_handle, ladish_client_handle client_handle)
2290 struct ladish_graph_client * client_ptr;
2292 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
2293 if (client_ptr == NULL)
2295 ASSERT_NO_PASS;
2296 return true;
2299 if (ladish_graph_client_looks_empty_internal(graph_ptr, client_ptr))
2301 //log_info("client '%s' looks empty in graph %s", client_ptr->name, graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
2302 return true;
2305 return false;
2308 bool ladish_graph_client_is_hidden(ladish_graph_handle graph_handle, ladish_client_handle client_handle)
2310 struct ladish_graph_client * client_ptr;
2312 client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
2313 if (client_ptr != NULL)
2315 return client_ptr->hidden;
2318 ASSERT_NO_PASS;
2319 return true;
2322 void ladish_try_connect_hidden_connections(ladish_graph_handle graph_handle)
2324 struct list_head * node_ptr;
2325 struct ladish_graph_connection * connection_ptr;
2327 if (!list_empty(&graph_ptr->connections) && graph_ptr->connect_handler == NULL)
2329 ASSERT_NO_PASS;
2330 return;
2333 ASSERT(graph_ptr->opath != NULL);
2335 list_for_each(node_ptr, &graph_ptr->connections)
2337 connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
2338 log_debug(
2339 "checking connection (%s, %s) '%s':'%s' (%s) to '%s':'%s' (%s)",
2340 connection_ptr->hidden ? "hidden" : "visible",
2341 connection_ptr->changing ? "changing" : "not changing",
2342 connection_ptr->port1_ptr->client_ptr->name,
2343 connection_ptr->port1_ptr->name,
2344 connection_ptr->port1_ptr->hidden ? "hidden" : "visible",
2345 connection_ptr->port2_ptr->client_ptr->name,
2346 connection_ptr->port2_ptr->name,
2347 connection_ptr->port2_ptr->hidden ? "hidden" : "visible");
2348 if (connection_ptr->hidden &&
2349 !connection_ptr->changing &&
2350 !connection_ptr->port1_ptr->hidden &&
2351 !connection_ptr->port2_ptr->hidden)
2353 log_info(
2354 "auto connecting '%s':'%s' to '%s':'%s'",
2355 connection_ptr->port1_ptr->client_ptr->name,
2356 connection_ptr->port1_ptr->name,
2357 connection_ptr->port2_ptr->client_ptr->name,
2358 connection_ptr->port2_ptr->name);
2360 connection_ptr->changing = true;
2361 if (!graph_ptr->connect_handler(graph_ptr->context, graph_handle, connection_ptr->port1_ptr->port, connection_ptr->port2_ptr->port))
2363 connection_ptr->changing = false;
2364 log_error("auto connect failed.");
2370 bool ladish_disconnect_visible_connections(ladish_graph_handle graph_handle)
2372 struct list_head * node_ptr;
2373 struct ladish_graph_connection * connection_ptr;
2375 if (graph_ptr->disconnect_handler == NULL)
2377 ASSERT_NO_PASS;
2378 return false;
2381 ASSERT(graph_ptr->opath != NULL);
2383 list_for_each(node_ptr, &graph_ptr->connections)
2385 connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
2386 log_debug(
2387 "checking connection (%s, %s) '%s':'%s' (%s) to '%s':'%s' (%s)",
2388 connection_ptr->hidden ? "hidden" : "visible",
2389 connection_ptr->changing ? "changing" : "not changing",
2390 connection_ptr->port1_ptr->client_ptr->name,
2391 connection_ptr->port1_ptr->name,
2392 connection_ptr->port1_ptr->hidden ? "hidden" : "visible",
2393 connection_ptr->port2_ptr->client_ptr->name,
2394 connection_ptr->port2_ptr->name,
2395 connection_ptr->port2_ptr->hidden ? "hidden" : "visible");
2396 if (!connection_ptr->hidden &&
2397 !connection_ptr->changing &&
2398 !connection_ptr->port1_ptr->hidden &&
2399 !connection_ptr->port2_ptr->hidden)
2401 log_info(
2402 "disconnecting '%s':'%s' from '%s':'%s'",
2403 connection_ptr->port1_ptr->client_ptr->name,
2404 connection_ptr->port1_ptr->name,
2405 connection_ptr->port2_ptr->client_ptr->name,
2406 connection_ptr->port2_ptr->name);
2408 connection_ptr->changing = true;
2409 if (!graph_ptr->disconnect_handler(graph_ptr->context, graph_handle, connection_ptr->id))
2411 connection_ptr->changing = false;
2412 log_error("disconnect failed.");
2413 return false;
2418 return true;
2421 void ladish_graph_hide_non_virtual(ladish_graph_handle graph_handle)
2423 struct list_head * node_ptr;
2424 struct ladish_graph_connection * connection_ptr;
2425 struct ladish_graph_port * port_ptr;
2426 struct ladish_graph_client * client_ptr;
2428 log_info("hiding everything in graph %s", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
2430 list_for_each(node_ptr, &graph_ptr->connections)
2432 connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
2433 if (!connection_ptr->hidden &&
2434 (ladish_client_get_jack_id(connection_ptr->port1_ptr->client_ptr->client) != 0 ||
2435 ladish_client_get_jack_id(connection_ptr->port2_ptr->client_ptr->client) != 0))
2437 log_debug("hidding connection between ports %"PRIu64" and %"PRIu64, connection_ptr->port1_ptr->id, connection_ptr->port2_ptr->id);
2438 ladish_graph_hide_connection_internal(graph_ptr, connection_ptr);
2442 list_for_each(node_ptr, &graph_ptr->ports)
2444 port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph);
2445 if (!port_ptr->hidden && ladish_client_get_jack_id(port_ptr->client_ptr->client) != 0)
2447 ladish_port_set_jack_id(port_ptr->port, 0);
2448 ladish_graph_hide_port_internal(graph_ptr, port_ptr);
2452 list_for_each(node_ptr, &graph_ptr->clients)
2454 client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
2455 if (!client_ptr->hidden && ladish_client_get_jack_id(client_ptr->client) != 0)
2457 ladish_client_set_jack_id(client_ptr->client, 0);
2458 ladish_graph_hide_client_internal(graph_ptr, client_ptr);
2463 void ladish_graph_get_port_uuid(ladish_graph_handle graph_handle, ladish_port_handle port, uuid_t uuid_ptr)
2465 struct ladish_graph_port * port_ptr;
2467 port_ptr = ladish_graph_find_port(graph_ptr, port);
2468 ASSERT(port_ptr != NULL);
2469 ASSERT(port_ptr->link);
2471 uuid_copy(uuid_ptr, port_ptr->link_uuid_override);
2474 const char * ladish_graph_get_port_name(ladish_graph_handle graph_handle, ladish_port_handle port)
2476 struct ladish_graph_port * port_ptr;
2478 port_ptr = ladish_graph_find_port(graph_ptr, port);
2479 ASSERT(port_ptr != NULL);
2481 return port_ptr->name;
2484 ladish_port_handle
2485 ladish_graph_find_client_port_by_uuid(
2486 ladish_graph_handle graph_handle,
2487 ladish_client_handle client,
2488 const uuid_t uuid,
2489 bool use_link_override_uuids)
2491 struct ladish_graph_client * client_ptr;
2492 struct ladish_graph_port * port_ptr;
2494 client_ptr = ladish_graph_find_client(graph_ptr, client);
2495 ASSERT(client_ptr != NULL);
2497 port_ptr = ladish_graph_find_port_by_uuid_internal(graph_ptr, client_ptr, uuid, use_link_override_uuids, NULL);
2498 if (port_ptr != NULL)
2500 return port_ptr->port;
2503 return NULL;
2506 void
2507 ladish_graph_set_link_port_override_uuid(
2508 ladish_graph_handle graph_handle,
2509 ladish_port_handle port,
2510 const uuid_t override_uuid)
2512 struct ladish_graph_port * port_ptr;
2514 port_ptr = ladish_graph_find_port(graph_ptr, port);
2515 ASSERT(port_ptr != NULL && ladish_port_is_link(port_ptr->port));
2517 uuid_copy(port_ptr->link_uuid_override, override_uuid);
2520 bool
2521 ladish_graph_iterate_nodes(
2522 ladish_graph_handle graph_handle,
2523 void * callback_context,
2524 bool
2525 (* client_begin_callback)(
2526 void * context,
2527 ladish_graph_handle graph_handle,
2528 bool hidden,
2529 ladish_client_handle client_handle,
2530 const char * client_name,
2531 void ** client_iteration_context_ptr_ptr),
2532 bool
2533 (* port_callback)(
2534 void * context,
2535 ladish_graph_handle graph_handle,
2536 bool hidden,
2537 void * client_iteration_context_ptr,
2538 ladish_client_handle client_handle,
2539 const char * client_name,
2540 ladish_port_handle port_handle,
2541 const char * port_name,
2542 uint32_t port_type,
2543 uint32_t port_flags),
2544 bool
2545 (* client_end_callback)(
2546 void * context,
2547 ladish_graph_handle graph_handle,
2548 bool hidden,
2549 ladish_client_handle client_handle,
2550 const char * client_name,
2551 void * client_iteration_context_ptr))
2553 struct list_head * client_node_ptr;
2554 struct ladish_graph_client * client_ptr;
2555 void * client_context;
2556 struct list_head * port_node_ptr;
2557 struct list_head * port_temp_node_ptr;
2558 struct ladish_graph_port * port_ptr;
2560 list_for_each(client_node_ptr, &graph_ptr->clients)
2562 client_ptr = list_entry(client_node_ptr, struct ladish_graph_client, siblings);
2564 if (client_begin_callback != NULL)
2566 if (!client_begin_callback(callback_context, graph_handle, client_ptr->hidden, client_ptr->client, client_ptr->name, &client_context))
2568 return false;
2571 else
2573 client_context = NULL;
2576 if (port_callback == NULL)
2578 continue;
2581 list_for_each_safe(port_node_ptr, port_temp_node_ptr, &client_ptr->ports)
2583 port_ptr = list_entry(port_node_ptr, struct ladish_graph_port, siblings_client);
2585 if (!port_callback(
2586 callback_context,
2587 graph_handle,
2588 port_ptr->hidden,
2589 client_context,
2590 client_ptr->client,
2591 client_ptr->name,
2592 port_ptr->port,
2593 port_ptr->name,
2594 port_ptr->type,
2595 port_ptr->flags))
2597 return false;
2601 if (client_end_callback != NULL)
2603 if (!client_end_callback(callback_context, graph_handle, client_ptr->hidden, client_ptr->client, client_ptr->name, &client_context))
2605 return false;
2610 return true;
2613 bool
2614 ladish_graph_iterate_connections(
2615 ladish_graph_handle graph_handle,
2616 void * callback_context,
2617 bool (* callback)(
2618 void * context,
2619 ladish_graph_handle graph_handle,
2620 bool connection_hidden,
2621 ladish_client_handle client1_handle,
2622 ladish_port_handle port1_handle,
2623 bool port1_hidden,
2624 ladish_client_handle client2_handle,
2625 ladish_port_handle port2_handle,
2626 bool port2_hidden,
2627 ladish_dict_handle dict))
2629 struct list_head * node_ptr;
2630 struct ladish_graph_connection * connection_ptr;
2632 list_for_each(node_ptr, &graph_ptr->connections)
2634 connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
2636 if (!callback(
2637 callback_context,
2638 graph_handle,
2639 connection_ptr->hidden,
2640 connection_ptr->port1_ptr->client_ptr->client,
2641 connection_ptr->port1_ptr->port,
2642 connection_ptr->port1_ptr->hidden,
2643 connection_ptr->port2_ptr->client_ptr->client,
2644 connection_ptr->port2_ptr->port,
2645 connection_ptr->port2_ptr->hidden,
2646 connection_ptr->dict))
2648 return false;
2652 return true;
2655 bool
2656 ladish_graph_interate_client_ports(
2657 ladish_graph_handle graph_handle,
2658 ladish_client_handle client,
2659 void * callback_context,
2660 bool
2661 (* port_callback)(
2662 void * context,
2663 ladish_graph_handle graph_handle,
2664 bool hidden,
2665 ladish_client_handle client_handle,
2666 const char * client_name,
2667 ladish_port_handle port_handle,
2668 const char * port_name,
2669 uint32_t port_type,
2670 uint32_t port_flags))
2672 struct ladish_graph_client * client_ptr;
2673 struct list_head * port_node_ptr;
2674 struct list_head * port_temp_node_ptr;
2675 struct ladish_graph_port * port_ptr;
2677 client_ptr = ladish_graph_find_client(graph_ptr, client);
2678 if (client_ptr == NULL)
2680 ASSERT_NO_PASS;
2681 return false;
2684 list_for_each_safe(port_node_ptr, port_temp_node_ptr, &client_ptr->ports)
2686 port_ptr = list_entry(port_node_ptr, struct ladish_graph_port, siblings_client);
2688 if (!port_callback(
2689 callback_context,
2690 graph_handle,
2691 port_ptr->hidden,
2692 client_ptr->client,
2693 client_ptr->name,
2694 port_ptr->port,
2695 port_ptr->name,
2696 port_ptr->type,
2697 port_ptr->flags))
2699 return false;
2703 return true;
2706 static
2707 bool
2708 dump_dict_entry(
2709 void * context,
2710 const char * key,
2711 const char * value)
2713 log_info("%s key '%s' with value '%s'", (const char *)context, key, value);
2714 return true;
2717 static
2718 void
2719 dump_dict(
2720 const char * indent,
2721 ladish_dict_handle dict)
2723 if (ladish_dict_is_empty(dict))
2725 return;
2728 log_info("%sdict:", indent);
2729 ladish_dict_iterate(dict, (void *)indent, dump_dict_entry);
2732 void ladish_graph_dump(ladish_graph_handle graph_handle)
2734 struct list_head * client_node_ptr;
2735 struct ladish_graph_client * client_ptr;
2736 struct list_head * port_node_ptr;
2737 struct ladish_graph_port * port_ptr;
2738 struct list_head * connection_node_ptr;
2739 struct ladish_graph_connection * connection_ptr;
2740 uuid_t uuid;
2741 char uuid_str[37];
2742 ladish_graph_handle vgraph;
2744 log_info("graph %s", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
2745 log_info(" version %"PRIu64, graph_ptr->graph_version);
2746 log_info(" persist: %s", graph_ptr->persist ? "yes" : "no");
2747 dump_dict(" ", graph_ptr->dict);
2748 log_info(" clients:");
2749 list_for_each(client_node_ptr, &graph_ptr->clients)
2751 client_ptr = list_entry(client_node_ptr, struct ladish_graph_client, siblings);
2752 log_info(" %s client '%s', id=%"PRIu64", ptr=%p", client_ptr->hidden ? "invisible" : "visible", client_ptr->name, client_ptr->id, client_ptr->client);
2754 ladish_client_get_uuid(client_ptr->client, uuid);
2755 uuid_unparse(uuid, uuid_str);
2756 log_info(" uuid=%s", uuid_str);
2758 if (ladish_client_get_interlink(client_ptr->client, uuid))
2760 uuid_unparse(uuid, uuid_str);
2761 log_info(" interlink=%s", uuid_str);
2763 else
2765 log_info(" no interlink");
2768 if (ladish_client_get_app(client_ptr->client, uuid))
2770 uuid_unparse(uuid, uuid_str);
2771 log_info(" app=%s", uuid_str);
2773 else
2775 log_info(" appless client");
2778 dump_dict(" ", ladish_client_get_dict(client_ptr->client));
2779 log_info(" ports:");
2780 list_for_each(port_node_ptr, &client_ptr->ports)
2782 port_ptr = list_entry(port_node_ptr, struct ladish_graph_port, siblings_client);
2784 ladish_port_get_uuid(port_ptr->port, uuid);
2785 uuid_unparse(uuid, uuid_str);
2787 vgraph = ladish_port_get_vgraph(port_ptr->port);
2789 log_info(" %s port '%s', uuid=%s, id=%"PRIu64"", port_ptr->hidden ? "invisible" : "visible", port_ptr->name, uuid_str, port_ptr->id);
2790 log_info(" type=0x%"PRIX32", flags=0x%"PRIX32", ptr=%p, vgraph=%s", port_ptr->type, port_ptr->flags, port_ptr->port, vgraph != NULL ? ladish_graph_get_description(vgraph) : "NULL");
2792 if (ladish_port_get_app(port_ptr->port, uuid))
2794 uuid_unparse(uuid, uuid_str);
2795 log_info(" app=%s", uuid_str);
2797 else
2799 log_info(" appless port");
2802 dump_dict(" ", ladish_port_get_dict(port_ptr->port));
2805 log_info(" connections:");
2806 list_for_each(connection_node_ptr, &graph_ptr->connections)
2808 connection_ptr = list_entry(connection_node_ptr, struct ladish_graph_connection, siblings);
2810 log_info(
2811 " %s connection '%s':'%s' - '%s':'%s'%s",
2812 connection_ptr->hidden ? "invisible" : "visible",
2813 connection_ptr->port1_ptr->client_ptr->name,
2814 connection_ptr->port1_ptr->name,
2815 connection_ptr->port2_ptr->client_ptr->name,
2816 connection_ptr->port2_ptr->name,
2817 connection_ptr->changing ? " [changing]" : "");
2818 dump_dict(" ", connection_ptr->dict);
2822 void ladish_graph_clear_persist(ladish_graph_handle graph_handle)
2824 log_info("Clearing persist flag for graph %s", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
2825 graph_ptr->persist = false;
2828 void ladish_graph_set_persist(ladish_graph_handle graph_handle)
2830 log_info("Setting persist flag for graph %s", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
2831 graph_ptr->persist = true;
2834 bool ladish_graph_is_persist(ladish_graph_handle graph_handle)
2836 return graph_ptr->persist;
2839 bool ladish_graph_has_visible_connections(ladish_graph_handle graph_handle)
2841 struct list_head * node_ptr;
2842 struct ladish_graph_connection * connection_ptr;
2844 list_for_each(node_ptr, &graph_ptr->connections)
2846 connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
2848 if (!connection_ptr->hidden)
2850 return true;
2854 return false;
2857 bool ladish_graph_looks_empty(ladish_graph_handle graph_handle)
2859 struct list_head * node_ptr;
2860 struct ladish_graph_client * client_ptr;
2862 if (ladish_graph_has_visible_connections(graph_handle))
2864 return false;
2867 list_for_each(node_ptr, &graph_ptr->clients)
2869 client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
2870 if (!ladish_graph_client_looks_empty_internal(graph_ptr, client_ptr))
2872 return false;
2876 return true;
2879 void ladish_graph_remove_hidden_objects(ladish_graph_handle graph_handle)
2881 struct list_head * node_ptr;
2882 struct list_head * temp_node_ptr;
2883 struct ladish_graph_client * client_ptr;
2884 struct ladish_graph_connection * connection_ptr;
2886 log_info("ladish_graph_remove_hidden_objects() called for graph '%s'", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
2888 list_for_each_safe(node_ptr, temp_node_ptr, &graph_ptr->connections)
2890 connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
2891 if (connection_ptr->hidden)
2893 ladish_graph_remove_connection_internal(graph_ptr, connection_ptr);
2897 list_for_each_safe(node_ptr, temp_node_ptr, &graph_ptr->clients)
2899 client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
2900 if (client_ptr->hidden)
2902 ladish_graph_remove_client_internal(graph_ptr, client_ptr, true, NULL);
2907 /* Trick the world that graph objects disappear and the reapper so the new dict values are fetched */
2908 /* This is a nasty hack and should be removed once dict object can emit signals */
2909 void ladish_graph_trick_dicts(ladish_graph_handle graph_handle)
2911 struct list_head * node_ptr;
2912 struct ladish_graph_connection * connection_ptr;
2913 struct ladish_graph_client * client_ptr;
2914 struct ladish_graph_port * port_ptr;
2916 list_for_each(node_ptr, &graph_ptr->connections)
2918 connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
2919 if (!connection_ptr->hidden)
2921 graph_ptr->graph_version++;
2922 ladish_graph_emit_ports_disconnected(graph_ptr, connection_ptr);
2926 list_for_each(node_ptr, &graph_ptr->ports)
2928 port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph);
2930 if (!port_ptr->hidden)
2932 graph_ptr->graph_version++;
2933 ladish_graph_emit_port_disappeared(graph_ptr, port_ptr);
2937 list_for_each(node_ptr, &graph_ptr->clients)
2939 client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
2941 if (!client_ptr->hidden)
2943 graph_ptr->graph_version++;
2944 ladish_graph_emit_client_disappeared(graph_ptr, client_ptr);
2945 graph_ptr->graph_version++;
2946 ladish_graph_emit_client_appeared(graph_ptr, client_ptr);
2950 list_for_each(node_ptr, &graph_ptr->ports)
2952 port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph);
2954 if (!port_ptr->hidden)
2956 graph_ptr->graph_version++;
2957 ladish_graph_emit_port_appeared(graph_ptr, port_ptr);
2961 list_for_each(node_ptr, &graph_ptr->connections)
2963 connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
2964 if (!connection_ptr->hidden)
2966 graph_ptr->graph_version++;
2967 ladish_graph_emit_ports_connected(graph_ptr, connection_ptr);
2972 #undef graph_ptr
2973 #define graph_ptr ((struct ladish_graph *)context)
2975 static
2976 bool
2977 ladish_graph_copy_client_begin_callback(
2978 void * context,
2979 ladish_graph_handle UNUSED(graph_handle),
2980 bool UNUSED(hidden),
2981 ladish_client_handle client_handle,
2982 const char * client_name,
2983 void ** client_iteration_context_ptr_ptr)
2985 ladish_client_handle copy;
2987 if (!ladish_client_create_copy(client_handle, &copy))
2989 return false;
2992 if (!ladish_graph_add_client(context, copy, client_name, false))
2994 ladish_client_destroy(copy);
2995 return false;
2998 *client_iteration_context_ptr_ptr = copy;
3000 return true;
3003 static
3004 bool
3005 ladish_graph_copy_port_callback(
3006 void * context,
3007 ladish_graph_handle UNUSED(graph_handle),
3008 bool UNUSED(hidden),
3009 void * client_iteration_context_ptr,
3010 ladish_client_handle UNUSED(client_handle),
3011 const char * UNUSED(client_name),
3012 ladish_port_handle port_handle,
3013 const char * port_name,
3014 uint32_t port_type,
3015 uint32_t port_flags)
3017 ladish_port_handle copy;
3019 if (!ladish_port_create_copy(port_handle, &copy))
3021 return false;
3024 if (!ladish_graph_add_port(context, client_iteration_context_ptr, copy, port_name, port_type, port_flags, true))
3026 ladish_port_destroy(copy);
3027 return false;
3030 return true;
3033 #undef graph_ptr
3035 bool ladish_graph_copy(ladish_graph_handle src, ladish_graph_handle dest)
3037 return ladish_graph_iterate_nodes(
3038 src,
3039 dest,
3040 ladish_graph_copy_client_begin_callback,
3041 ladish_graph_copy_port_callback,
3042 NULL);
3045 CDBUS_METHOD_ARGS_BEGIN(GetAllPorts, "Get all ports")
3046 CDBUS_METHOD_ARG_DESCRIBE_OUT("ports_list", "as", "List of all ports")
3047 CDBUS_METHOD_ARGS_END
3049 CDBUS_METHOD_ARGS_BEGIN(GetGraph, "Get whole graph")
3050 CDBUS_METHOD_ARG_DESCRIBE_IN("known_graph_version", DBUS_TYPE_UINT64_AS_STRING, "Known graph version")
3051 CDBUS_METHOD_ARG_DESCRIBE_OUT("current_graph_version", DBUS_TYPE_UINT64_AS_STRING, "Current graph version")
3052 CDBUS_METHOD_ARG_DESCRIBE_OUT("clients_and_ports", "a(tsa(tsuu))", "Clients and their ports")
3053 CDBUS_METHOD_ARG_DESCRIBE_OUT("connections", "a(tstststst)", "Connections array")
3054 CDBUS_METHOD_ARGS_END
3056 CDBUS_METHOD_ARGS_BEGIN(ConnectPortsByName, "Connect ports")
3057 CDBUS_METHOD_ARG_DESCRIBE_IN("client1_name", DBUS_TYPE_STRING_AS_STRING, "name first port client")
3058 CDBUS_METHOD_ARG_DESCRIBE_IN("port1_name", DBUS_TYPE_STRING_AS_STRING, "name of first port")
3059 CDBUS_METHOD_ARG_DESCRIBE_IN("client2_name", DBUS_TYPE_STRING_AS_STRING, "name second port client")
3060 CDBUS_METHOD_ARG_DESCRIBE_IN("port2_name", DBUS_TYPE_STRING_AS_STRING, "name of second port")
3061 CDBUS_METHOD_ARGS_END
3063 CDBUS_METHOD_ARGS_BEGIN(ConnectPortsByID, "Connect ports")
3064 CDBUS_METHOD_ARG_DESCRIBE_IN("port1_id", DBUS_TYPE_UINT64_AS_STRING, "id of first port")
3065 CDBUS_METHOD_ARG_DESCRIBE_IN("port2_id", DBUS_TYPE_UINT64_AS_STRING, "if of second port")
3066 CDBUS_METHOD_ARGS_END
3068 CDBUS_METHOD_ARGS_BEGIN(DisconnectPortsByName, "Disconnect ports")
3069 CDBUS_METHOD_ARG_DESCRIBE_IN("client1_name", DBUS_TYPE_STRING_AS_STRING, "name first port client")
3070 CDBUS_METHOD_ARG_DESCRIBE_IN("port1_name", DBUS_TYPE_STRING_AS_STRING, "name of first port")
3071 CDBUS_METHOD_ARG_DESCRIBE_IN("client2_name", DBUS_TYPE_STRING_AS_STRING, "name second port client")
3072 CDBUS_METHOD_ARG_DESCRIBE_IN("port2_name", DBUS_TYPE_STRING_AS_STRING, "name of second port")
3073 CDBUS_METHOD_ARGS_END
3075 CDBUS_METHOD_ARGS_BEGIN(DisconnectPortsByID, "Disconnect ports")
3076 CDBUS_METHOD_ARG_DESCRIBE_IN("port1_id", DBUS_TYPE_UINT64_AS_STRING, "id of first port")
3077 CDBUS_METHOD_ARG_DESCRIBE_IN("port2_id", DBUS_TYPE_UINT64_AS_STRING, "if of second port")
3078 CDBUS_METHOD_ARGS_END
3080 CDBUS_METHOD_ARGS_BEGIN(DisconnectPortsByConnectionID, "Disconnect ports")
3081 CDBUS_METHOD_ARG_DESCRIBE_IN("connection_id", DBUS_TYPE_UINT64_AS_STRING, "id of connection to disconnect")
3082 CDBUS_METHOD_ARGS_END
3084 CDBUS_METHOD_ARGS_BEGIN(GetClientPID, "get process id of client")
3085 CDBUS_METHOD_ARG_DESCRIBE_IN("client_id", DBUS_TYPE_UINT64_AS_STRING, "id of client")
3086 CDBUS_METHOD_ARG_DESCRIBE_OUT("process_id", DBUS_TYPE_INT64_AS_STRING, "pid of client")
3087 CDBUS_METHOD_ARGS_END
3089 CDBUS_METHODS_BEGIN
3090 CDBUS_METHOD_DESCRIBE(GetAllPorts, get_all_ports)
3091 CDBUS_METHOD_DESCRIBE(GetGraph, get_graph)
3092 CDBUS_METHOD_DESCRIBE(ConnectPortsByName, connect_ports_by_name)
3093 CDBUS_METHOD_DESCRIBE(ConnectPortsByID, connect_ports_by_id)
3094 CDBUS_METHOD_DESCRIBE(DisconnectPortsByName, disconnect_ports_by_name)
3095 CDBUS_METHOD_DESCRIBE(DisconnectPortsByID, disconnect_ports_by_id)
3096 CDBUS_METHOD_DESCRIBE(DisconnectPortsByConnectionID, disconnect_ports_by_connection_id)
3097 CDBUS_METHOD_DESCRIBE(GetClientPID, get_client_pid)
3098 CDBUS_METHODS_END
3100 CDBUS_SIGNAL_ARGS_BEGIN(GraphChanged, "")
3101 CDBUS_SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
3102 CDBUS_SIGNAL_ARGS_END
3104 CDBUS_SIGNAL_ARGS_BEGIN(ClientAppeared, "")
3105 CDBUS_SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
3106 CDBUS_SIGNAL_ARG_DESCRIBE("client_id", DBUS_TYPE_UINT64_AS_STRING, "")
3107 CDBUS_SIGNAL_ARG_DESCRIBE("client_name", DBUS_TYPE_STRING_AS_STRING, "")
3108 CDBUS_SIGNAL_ARGS_END
3110 CDBUS_SIGNAL_ARGS_BEGIN(ClientDisappeared, "")
3111 CDBUS_SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
3112 CDBUS_SIGNAL_ARG_DESCRIBE("client_id", DBUS_TYPE_UINT64_AS_STRING, "")
3113 CDBUS_SIGNAL_ARG_DESCRIBE("client_name", DBUS_TYPE_STRING_AS_STRING, "")
3114 CDBUS_SIGNAL_ARGS_END
3116 CDBUS_SIGNAL_ARGS_BEGIN(ClientRenamed, "")
3117 CDBUS_SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
3118 CDBUS_SIGNAL_ARG_DESCRIBE("client_id", DBUS_TYPE_UINT64_AS_STRING, "")
3119 CDBUS_SIGNAL_ARG_DESCRIBE("old_client_name", DBUS_TYPE_STRING_AS_STRING, "")
3120 CDBUS_SIGNAL_ARG_DESCRIBE("new_client_name", DBUS_TYPE_STRING_AS_STRING, "")
3121 CDBUS_SIGNAL_ARGS_END
3123 CDBUS_SIGNAL_ARGS_BEGIN(PortAppeared, "")
3124 CDBUS_SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
3125 CDBUS_SIGNAL_ARG_DESCRIBE("client_id", DBUS_TYPE_UINT64_AS_STRING, "")
3126 CDBUS_SIGNAL_ARG_DESCRIBE("client_name", DBUS_TYPE_STRING_AS_STRING, "")
3127 CDBUS_SIGNAL_ARG_DESCRIBE("port_id", DBUS_TYPE_UINT64_AS_STRING, "")
3128 CDBUS_SIGNAL_ARG_DESCRIBE("port_name", DBUS_TYPE_STRING_AS_STRING, "")
3129 CDBUS_SIGNAL_ARG_DESCRIBE("port_flags", DBUS_TYPE_UINT32_AS_STRING, "")
3130 CDBUS_SIGNAL_ARG_DESCRIBE("port_type", DBUS_TYPE_UINT32_AS_STRING, "")
3131 CDBUS_SIGNAL_ARGS_END
3133 CDBUS_SIGNAL_ARGS_BEGIN(PortDisappeared, "")
3134 CDBUS_SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
3135 CDBUS_SIGNAL_ARG_DESCRIBE("client_id", DBUS_TYPE_UINT64_AS_STRING, "")
3136 CDBUS_SIGNAL_ARG_DESCRIBE("client_name", DBUS_TYPE_STRING_AS_STRING, "")
3137 CDBUS_SIGNAL_ARG_DESCRIBE("port_id", DBUS_TYPE_UINT64_AS_STRING, "")
3138 CDBUS_SIGNAL_ARG_DESCRIBE("port_name", DBUS_TYPE_STRING_AS_STRING, "")
3139 CDBUS_SIGNAL_ARGS_END
3141 CDBUS_SIGNAL_ARGS_BEGIN(PortRenamed, "")
3142 CDBUS_SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
3143 CDBUS_SIGNAL_ARG_DESCRIBE("client_id", DBUS_TYPE_UINT64_AS_STRING, "")
3144 CDBUS_SIGNAL_ARG_DESCRIBE("client_name", DBUS_TYPE_STRING_AS_STRING, "")
3145 CDBUS_SIGNAL_ARG_DESCRIBE("port_id", DBUS_TYPE_UINT64_AS_STRING, "")
3146 CDBUS_SIGNAL_ARG_DESCRIBE("old_port_name", DBUS_TYPE_STRING_AS_STRING, "")
3147 CDBUS_SIGNAL_ARG_DESCRIBE("new_port_name", DBUS_TYPE_STRING_AS_STRING, "")
3148 CDBUS_SIGNAL_ARGS_END
3150 CDBUS_SIGNAL_ARGS_BEGIN(PortsConnected, "")
3151 CDBUS_SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
3152 CDBUS_SIGNAL_ARG_DESCRIBE("client1_id", DBUS_TYPE_UINT64_AS_STRING, "")
3153 CDBUS_SIGNAL_ARG_DESCRIBE("client1_name", DBUS_TYPE_STRING_AS_STRING, "")
3154 CDBUS_SIGNAL_ARG_DESCRIBE("port1_id", DBUS_TYPE_UINT64_AS_STRING, "")
3155 CDBUS_SIGNAL_ARG_DESCRIBE("port1_name", DBUS_TYPE_STRING_AS_STRING, "")
3156 CDBUS_SIGNAL_ARG_DESCRIBE("client2_id", DBUS_TYPE_UINT64_AS_STRING, "")
3157 CDBUS_SIGNAL_ARG_DESCRIBE("client2_name", DBUS_TYPE_STRING_AS_STRING, "")
3158 CDBUS_SIGNAL_ARG_DESCRIBE("port2_id", DBUS_TYPE_UINT64_AS_STRING, "")
3159 CDBUS_SIGNAL_ARG_DESCRIBE("port2_name", DBUS_TYPE_STRING_AS_STRING, "")
3160 CDBUS_SIGNAL_ARG_DESCRIBE("connection_id", DBUS_TYPE_UINT64_AS_STRING, "")
3161 CDBUS_SIGNAL_ARGS_END
3163 CDBUS_SIGNAL_ARGS_BEGIN(PortsDisconnected, "")
3164 CDBUS_SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
3165 CDBUS_SIGNAL_ARG_DESCRIBE("client1_id", DBUS_TYPE_UINT64_AS_STRING, "")
3166 CDBUS_SIGNAL_ARG_DESCRIBE("client1_name", DBUS_TYPE_STRING_AS_STRING, "")
3167 CDBUS_SIGNAL_ARG_DESCRIBE("port1_id", DBUS_TYPE_UINT64_AS_STRING, "")
3168 CDBUS_SIGNAL_ARG_DESCRIBE("port1_name", DBUS_TYPE_STRING_AS_STRING, "")
3169 CDBUS_SIGNAL_ARG_DESCRIBE("client2_id", DBUS_TYPE_UINT64_AS_STRING, "")
3170 CDBUS_SIGNAL_ARG_DESCRIBE("client2_name", DBUS_TYPE_STRING_AS_STRING, "")
3171 CDBUS_SIGNAL_ARG_DESCRIBE("port2_id", DBUS_TYPE_UINT64_AS_STRING, "")
3172 CDBUS_SIGNAL_ARG_DESCRIBE("port2_name", DBUS_TYPE_STRING_AS_STRING, "")
3173 CDBUS_SIGNAL_ARG_DESCRIBE("connection_id", DBUS_TYPE_UINT64_AS_STRING, "")
3174 CDBUS_SIGNAL_ARGS_END
3176 CDBUS_SIGNALS_BEGIN
3177 CDBUS_SIGNAL_DESCRIBE(GraphChanged)
3178 CDBUS_SIGNAL_DESCRIBE(ClientAppeared)
3179 CDBUS_SIGNAL_DESCRIBE(ClientDisappeared)
3180 CDBUS_SIGNAL_DESCRIBE(ClientRenamed)
3181 CDBUS_SIGNAL_DESCRIBE(PortAppeared)
3182 CDBUS_SIGNAL_DESCRIBE(PortDisappeared)
3183 CDBUS_SIGNAL_DESCRIBE(PortRenamed)
3184 CDBUS_SIGNAL_DESCRIBE(PortsConnected)
3185 CDBUS_SIGNAL_DESCRIBE(PortsDisconnected)
3186 CDBUS_SIGNALS_END
3188 CDBUS_INTERFACE_DEFAULT_HANDLER_METHODS_AND_SIGNALS(g_interface_patchbay, JACKDBUS_IFACE_PATCHBAY)