root/daemon/graph.c @ 9f3f884c4d817f9bf22db8a4693c00e1789cae2b

Revision 9f3f884c4d817f9bf22db8a4693c00e1789cae2b, 61.9 KB (checked in by Nedko Arnaudov <nedko@…>, 3 years ago)

daemon: improve log messages and add TODO comments

  • Property mode set to 100644
Line 
1/* -*- Mode: C ; c-basic-offset: 2 -*- */
2/*
3 * LADI Session Handler (ladish)
4 *
5 * Copyright (C) 2008, 2009, 2010 Nedko Arnaudov <nedko@arnaudov.name>
6 * Copyright (C) 2008 Juuso Alasuutari
7 *
8 **************************************************************************
9 * This file contains implementation of the D-Bus patchbay interface helpers
10 **************************************************************************
11 *
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.
16 *
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.
21 *
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.
26 */
27
28#include "common.h"
29#include "graph.h"
30#include "../dbus/error.h"
31#include "../dbus_constants.h"
32
33struct ladish_graph_port
34{
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};
45
46struct ladish_graph_client
47{
48  struct list_head siblings;
49  char * name;
50  uint64_t id;
51  ladish_client_handle client;
52  struct list_head ports;
53  bool hidden;
54};
55
56struct ladish_graph_connection
57{
58  struct list_head siblings;
59  uint64_t id;
60  bool hidden;
61  struct ladish_graph_port * port1_ptr;
62  struct ladish_graph_port * port2_ptr;
63  ladish_dict_handle dict;
64  bool changing;
65};
66
67struct ladish_graph
68{
69  char * opath;
70  ladish_dict_handle dict;
71  struct list_head clients;
72  struct list_head ports;
73  struct list_head connections;
74  uint64_t graph_version;
75  uint64_t next_client_id;
76  uint64_t next_port_id;
77  uint64_t next_connection_id;
78
79  void * context;
80  ladish_graph_connect_request_handler connect_handler;
81  ladish_graph_disconnect_request_handler disconnect_handler;
82};
83
84struct ladish_graph_port * ladish_graph_find_port_by_id_internal(struct ladish_graph * graph_ptr, uint64_t port_id)
85{
86  struct list_head * node_ptr;
87  struct ladish_graph_port * port_ptr;
88
89  list_for_each(node_ptr, &graph_ptr->ports)
90  {
91    port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph);
92    if (port_ptr->id == port_id)
93    {
94      return port_ptr;
95    }
96  }
97
98  return NULL;
99}
100
101struct ladish_graph_connection * ladish_graph_find_connection_by_id(struct ladish_graph * graph_ptr, uint64_t connection_id)
102{
103  struct list_head * node_ptr;
104  struct ladish_graph_connection * connection_ptr;
105
106  list_for_each(node_ptr, &graph_ptr->connections)
107  {
108    connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
109    if (connection_ptr->id == connection_id)
110    {
111      return connection_ptr;
112    }
113  }
114
115  return NULL;
116}
117
118struct ladish_graph_connection *
119ladish_graph_find_connection_by_ports(
120  struct ladish_graph * graph_ptr,
121  struct ladish_graph_port * port1_ptr,
122  struct ladish_graph_port * port2_ptr)
123{
124  struct list_head * node_ptr;
125  struct ladish_graph_connection * connection_ptr;
126
127  list_for_each(node_ptr, &graph_ptr->connections)
128  {
129    connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
130    if ((connection_ptr->port1_ptr == port1_ptr && connection_ptr->port2_ptr == port2_ptr) ||
131        (connection_ptr->port1_ptr == port2_ptr && connection_ptr->port2_ptr == port1_ptr))
132    {
133      return connection_ptr;
134    }
135  }
136
137  return NULL;
138}
139
140#define graph_ptr ((struct ladish_graph *)call_ptr->iface_context)
141
142static void get_all_ports(struct dbus_method_call * call_ptr)
143{
144  DBusMessageIter iter, sub_iter;
145
146  call_ptr->reply = dbus_message_new_method_return(call_ptr->message);
147  if (call_ptr->reply == NULL)
148  {
149    goto fail;
150  }
151
152  dbus_message_iter_init_append(call_ptr->reply, &iter);
153
154  if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub_iter))
155  {
156    goto fail_unref;
157  }
158
159  if (!dbus_message_iter_close_container(&iter, &sub_iter))
160  {
161    goto fail_unref;
162  }
163
164  return;
165
166fail_unref:
167  dbus_message_unref(call_ptr->reply);
168  call_ptr->reply = NULL;
169
170fail:
171  log_error("Ran out of memory trying to construct method return");
172}
173
174static void get_graph(struct dbus_method_call * call_ptr)
175{
176  dbus_uint64_t known_version;
177  dbus_uint64_t current_version;
178  DBusMessageIter iter;
179  DBusMessageIter clients_array_iter;
180  DBusMessageIter connections_array_iter;
181  DBusMessageIter client_struct_iter;
182  struct list_head * client_node_ptr;
183  struct ladish_graph_client * client_ptr;
184  DBusMessageIter ports_array_iter;
185  struct list_head * port_node_ptr;
186  struct ladish_graph_port * port_ptr;
187  DBusMessageIter port_struct_iter;
188  struct list_head * connection_node_ptr;
189  struct ladish_graph_connection * connection_ptr;
190  DBusMessageIter connection_struct_iter;
191
192  //log_info("get_graph() called");
193
194  if (!dbus_message_get_args(call_ptr->message, &g_dbus_error, DBUS_TYPE_UINT64, &known_version, DBUS_TYPE_INVALID))
195  {
196    lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s",  call_ptr->method_name, g_dbus_error.message);
197    dbus_error_free(&g_dbus_error);
198    return;
199  }
200
201  //log_info("Getting graph, known version is %" PRIu64, known_version);
202
203  call_ptr->reply = dbus_message_new_method_return(call_ptr->message);
204  if (call_ptr->reply == NULL)
205  {
206    log_error("Ran out of memory trying to construct method return");
207    goto exit;
208  }
209
210  dbus_message_iter_init_append(call_ptr->reply, &iter);
211
212  current_version = graph_ptr->graph_version;
213  if (known_version > current_version)
214  {
215    lash_dbus_error(
216      call_ptr,
217      LASH_DBUS_ERROR_INVALID_ARGS,
218      "known graph version %" PRIu64 " is newer than actual version %" PRIu64,
219      known_version,
220      current_version);
221    goto exit;
222  }
223
224  if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT64, &current_version))
225  {
226    goto nomem;
227  }
228
229  if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(tsa(tsuu))", &clients_array_iter))
230  {
231    goto nomem;
232  }
233
234  if (known_version < current_version)
235  {
236    list_for_each(client_node_ptr, &graph_ptr->clients)
237    {
238      client_ptr = list_entry(client_node_ptr, struct ladish_graph_client, siblings);
239
240      if (client_ptr->hidden)
241      {
242        continue;
243      }
244
245      if (!dbus_message_iter_open_container (&clients_array_iter, DBUS_TYPE_STRUCT, NULL, &client_struct_iter))
246      {
247        goto nomem_close_clients_array;
248      }
249
250      if (!dbus_message_iter_append_basic(&client_struct_iter, DBUS_TYPE_UINT64, &client_ptr->id))
251      {
252        goto nomem_close_client_struct;
253      }
254
255      log_info("client '%s' (%llu)", client_ptr->name, (unsigned long long)client_ptr->id);
256      if (!dbus_message_iter_append_basic(&client_struct_iter, DBUS_TYPE_STRING, &client_ptr->name))
257      {
258        goto nomem_close_client_struct;
259      }
260
261      if (!dbus_message_iter_open_container(&client_struct_iter, DBUS_TYPE_ARRAY, "(tsuu)", &ports_array_iter))
262      {
263        goto nomem_close_client_struct;
264      }
265
266      list_for_each(port_node_ptr, &client_ptr->ports)
267      {
268        port_ptr = list_entry(port_node_ptr, struct ladish_graph_port, siblings_client);
269
270        if (port_ptr->hidden)
271        {
272          continue;
273        }
274
275        if (!dbus_message_iter_open_container(&ports_array_iter, DBUS_TYPE_STRUCT, NULL, &port_struct_iter))
276        {
277          goto nomem_close_ports_array;
278        }
279
280        if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT64, &port_ptr->id))
281        {
282          goto nomem_close_port_struct;
283        }
284
285        if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_STRING, &port_ptr->name))
286        {
287          goto nomem_close_port_struct;
288        }
289
290        if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT32, &port_ptr->flags))
291        {
292          goto nomem_close_port_struct;
293        }
294
295        if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT32, &port_ptr->type))
296        {
297          goto nomem_close_port_struct;
298        }
299
300        if (!dbus_message_iter_close_container(&ports_array_iter, &port_struct_iter))
301        {
302          goto nomem_close_ports_array;
303        }
304      }
305
306      if (!dbus_message_iter_close_container(&client_struct_iter, &ports_array_iter))
307      {
308        goto nomem_close_client_struct;
309      }
310
311      if (!dbus_message_iter_close_container(&clients_array_iter, &client_struct_iter))
312      {
313        goto nomem_close_clients_array;
314      }
315    }
316  }
317
318  if (!dbus_message_iter_close_container(&iter, &clients_array_iter))
319  {
320    goto nomem;
321  }
322
323  if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(tstststst)", &connections_array_iter))
324  {
325    goto nomem;
326  }
327
328  if (known_version < current_version)
329  {
330    list_for_each(connection_node_ptr, &graph_ptr->connections)
331    {
332      connection_ptr = list_entry(connection_node_ptr, struct ladish_graph_connection, siblings);
333
334      if (connection_ptr->hidden)
335      {
336        continue;
337      }
338
339      if (!dbus_message_iter_open_container(&connections_array_iter, DBUS_TYPE_STRUCT, NULL, &connection_struct_iter))
340      {
341        goto nomem_close_connections_array;
342      }
343
344      if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port1_ptr->client_ptr->id))
345      {
346        goto nomem_close_connection_struct;
347      }
348
349      if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port1_ptr->client_ptr->name))
350      {
351        goto nomem_close_connection_struct;
352      }
353
354      if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port1_ptr->id))
355      {
356        goto nomem_close_connection_struct;
357      }
358
359      if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port1_ptr->name))
360      {
361        goto nomem_close_connection_struct;
362      }
363
364      if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port2_ptr->client_ptr->id))
365      {
366        goto nomem_close_connection_struct;
367      }
368
369      if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port2_ptr->client_ptr->name))
370      {
371        goto nomem_close_connection_struct;
372      }
373
374      if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port2_ptr->id))
375      {
376        goto nomem_close_connection_struct;
377      }
378
379      if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port2_ptr->name))
380      {
381        goto nomem_close_connection_struct;
382      }
383
384      if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->id))
385      {
386        goto nomem_close_connection_struct;
387      }
388
389      if (!dbus_message_iter_close_container(&connections_array_iter, &connection_struct_iter))
390      {
391        goto nomem_close_connections_array;
392      }
393    }
394  }
395
396  if (!dbus_message_iter_close_container(&iter, &connections_array_iter))
397  {
398    goto nomem;
399  }
400
401  return;
402
403nomem_close_connection_struct:
404  dbus_message_iter_close_container(&connections_array_iter, &connection_struct_iter);
405
406nomem_close_connections_array:
407  dbus_message_iter_close_container(&iter, &connections_array_iter);
408  goto nomem;
409
410nomem_close_port_struct:
411  dbus_message_iter_close_container(&ports_array_iter, &port_struct_iter);
412
413nomem_close_ports_array:
414  dbus_message_iter_close_container(&client_struct_iter, &ports_array_iter);
415
416nomem_close_client_struct:
417  dbus_message_iter_close_container(&clients_array_iter, &client_struct_iter);
418
419nomem_close_clients_array:
420  dbus_message_iter_close_container(&iter, &clients_array_iter);
421
422nomem:
423  dbus_message_unref(call_ptr->reply);
424  call_ptr->reply = NULL;
425  log_error("Ran out of memory trying to construct method return");
426
427exit:
428  return;
429}
430
431static void connect_ports_by_name(struct dbus_method_call * call_ptr)
432{
433  log_info("connect_ports_by_name() called.");
434  lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "connect by name is not implemented yet");
435}
436
437static void connect_ports_by_id(struct dbus_method_call * call_ptr)
438{
439  dbus_uint64_t port1_id;
440  dbus_uint64_t port2_id;
441  struct ladish_graph_port * port1_ptr;
442  struct ladish_graph_port * port2_ptr;
443
444  if (!dbus_message_get_args(call_ptr->message, &g_dbus_error, DBUS_TYPE_UINT64, &port1_id, DBUS_TYPE_UINT64, &port2_id, DBUS_TYPE_INVALID))
445  {
446    lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, g_dbus_error.message);
447    dbus_error_free(&g_dbus_error);
448    return;
449  }
450
451  log_info("connect_ports_by_id(%"PRIu64",%"PRIu64") called.", port1_id, port2_id);
452
453  if (graph_ptr->connect_handler == NULL)
454  {
455    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");
456    return;
457  }
458
459  port1_ptr = ladish_graph_find_port_by_id_internal(graph_ptr, port1_id);
460  if (port1_ptr == NULL)
461  {
462    lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot connect unknown port with id %"PRIu64, port1_id);
463    return;
464  }
465
466  port2_ptr = ladish_graph_find_port_by_id_internal(graph_ptr, port2_id);
467  if (port2_ptr == NULL)
468  {
469    lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot connect unknown port with id %"PRIu64, port2_id);
470    return;
471  }
472
473  log_info("connecting '%s':'%s' to '%s':'%s'", port1_ptr->client_ptr->name, port1_ptr->name, port2_ptr->client_ptr->name, port2_ptr->name);
474
475  if (graph_ptr->connect_handler(graph_ptr->context, (ladish_graph_handle)graph_ptr, port1_ptr->port, port2_ptr->port))
476  {
477    method_return_new_void(call_ptr);
478  }
479  else
480  {
481    lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "connect failed");
482  }
483}
484
485static void disconnect_ports(struct dbus_method_call * call_ptr, struct ladish_graph_connection * connection_ptr)
486{
487  log_info(
488    "disconnecting '%s':'%s' from '%s':'%s'",
489    connection_ptr->port1_ptr->client_ptr->name,
490    connection_ptr->port1_ptr->name,
491    connection_ptr->port2_ptr->client_ptr->name,
492    connection_ptr->port2_ptr->name);
493
494  connection_ptr->changing = true;
495  if (graph_ptr->disconnect_handler(graph_ptr->context, (ladish_graph_handle)graph_ptr, connection_ptr->id))
496  {
497    method_return_new_void(call_ptr);
498  }
499  else
500  {
501    connection_ptr->changing = false;
502    lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "disconnect failed");
503  }
504}
505
506static void disconnect_ports_by_name(struct dbus_method_call * call_ptr)
507{
508  log_info("disconnect_ports_by_name() called.");
509  lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "disconnect by name is not implemented yet");
510}
511
512static void disconnect_ports_by_id(struct dbus_method_call * call_ptr)
513{
514  dbus_uint64_t port1_id;
515  dbus_uint64_t port2_id;
516  struct ladish_graph_port * port1_ptr;
517  struct ladish_graph_port * port2_ptr;
518  struct ladish_graph_connection * connection_ptr;
519
520  if (!dbus_message_get_args(call_ptr->message, &g_dbus_error, DBUS_TYPE_UINT64, &port1_id, DBUS_TYPE_UINT64, &port2_id, DBUS_TYPE_INVALID))
521  {
522    lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, g_dbus_error.message);
523    dbus_error_free(&g_dbus_error);
524    return;
525  }
526
527  log_info("disconnect_ports_by_id(%"PRIu64",%"PRIu64") called.", port1_id, port2_id);
528
529  if (graph_ptr->disconnect_handler == NULL)
530  {
531    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");
532    return;
533  }
534
535  port1_ptr = ladish_graph_find_port_by_id_internal(graph_ptr, port1_id);
536  if (port1_ptr == NULL)
537  {
538    lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot disconnect unknown port with id %"PRIu64, port1_id);
539    return;
540  }
541
542  port2_ptr = ladish_graph_find_port_by_id_internal(graph_ptr, port2_id);
543  if (port2_ptr == NULL)
544  {
545    lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot disconnect unknown port with id %"PRIu64, port2_id);
546    return;
547  }
548
549  connection_ptr = ladish_graph_find_connection_by_ports(graph_ptr, port1_ptr, port2_ptr);
550  if (connection_ptr == NULL)
551  {
552    lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot disconnect not connected ports %"PRIu64" and %"PRIu64, port1_id, port2_id);
553    return;
554  }
555
556  disconnect_ports(call_ptr, connection_ptr);
557}
558
559static void disconnect_ports_by_connection_id(struct dbus_method_call * call_ptr)
560{
561  dbus_uint64_t connection_id;
562  struct ladish_graph_connection * connection_ptr;
563
564  if (!dbus_message_get_args(call_ptr->message, &g_dbus_error, DBUS_TYPE_UINT64, &connection_id, DBUS_TYPE_INVALID))
565  {
566    lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, g_dbus_error.message);
567    dbus_error_free(&g_dbus_error);
568    return;
569  }
570
571  log_info("disconnect_ports_by_connection_id(%"PRIu64") called.", connection_id);
572
573  connection_ptr = ladish_graph_find_connection_by_id(graph_ptr, connection_id);
574  if (connection_ptr == NULL)
575  {
576    lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot find connection with id %"PRIu64, connection_id);
577    return;
578  }
579
580  disconnect_ports(call_ptr, connection_ptr);
581}
582
583static void get_client_pid(struct dbus_method_call * call_ptr)
584{
585  int64_t pid = 0;
586  method_return_new_single(call_ptr, DBUS_TYPE_INT64, &pid);
587}
588
589#undef graph_ptr
590
591bool ladish_graph_create(ladish_graph_handle * graph_handle_ptr, const char * opath)
592{
593  struct ladish_graph * graph_ptr;
594
595  graph_ptr = malloc(sizeof(struct ladish_graph));
596  if (graph_ptr == NULL)
597  {
598    log_error("malloc() failed to allocate struct graph_implementator");
599    return false;
600  }
601
602  if (opath != NULL)
603  {
604    graph_ptr->opath = strdup(opath);
605    if (graph_ptr->opath == NULL)
606    {
607      log_error("strdup() failed for graph opath");
608      free(graph_ptr);
609      return false;
610    }
611  }
612  else
613  {
614    graph_ptr->opath = NULL;
615  }
616
617  if (!ladish_dict_create(&graph_ptr->dict))
618  {
619    log_error("ladish_dict_create() failed for graph");
620    if (graph_ptr->opath != NULL)
621    {
622      free(graph_ptr->opath);
623    }
624    free(graph_ptr);
625    return false;
626  }
627
628  INIT_LIST_HEAD(&graph_ptr->clients);
629  INIT_LIST_HEAD(&graph_ptr->ports);
630  INIT_LIST_HEAD(&graph_ptr->connections);
631
632  graph_ptr->graph_version = 1;
633  graph_ptr->next_client_id = 1;
634  graph_ptr->next_port_id = 1;
635  graph_ptr->next_connection_id = 1;
636
637  graph_ptr->context = NULL;
638  graph_ptr->connect_handler = NULL;
639  graph_ptr->disconnect_handler = NULL;
640
641  *graph_handle_ptr = (ladish_graph_handle)graph_ptr;
642  return true;
643}
644
645static
646struct ladish_graph_client *
647ladish_graph_find_client(
648  struct ladish_graph * graph_ptr,
649  ladish_client_handle client)
650{
651  struct list_head * node_ptr;
652  struct ladish_graph_client * client_ptr;
653
654  list_for_each(node_ptr, &graph_ptr->clients)
655  {
656    client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
657    if (client_ptr->client == client)
658    {
659      return client_ptr;
660    }
661  }
662
663  return NULL;
664}
665
666static
667struct ladish_graph_port *
668ladish_graph_find_port(
669  struct ladish_graph * graph_ptr,
670  ladish_port_handle port)
671{
672  struct list_head * node_ptr;
673  struct ladish_graph_port * port_ptr;
674
675  list_for_each(node_ptr, &graph_ptr->ports)
676  {
677    port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph);
678    if (port_ptr->port == port)
679    {
680      return port_ptr;
681    }
682  }
683
684  return NULL;
685}
686
687#if 0
688static
689struct ladish_graph_port *
690ladish_graph_find_client_port(
691  struct ladish_graph * graph_ptr,
692  struct ladish_graph_client * client_ptr,
693  ladish_port_handle port)
694{
695  struct list_head * node_ptr;
696  struct ladish_graph_port * port_ptr;
697
698  list_for_each(node_ptr, &client_ptr->ports)
699  {
700    port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_client);
701    if (port_ptr->port == port)
702    {
703      return port_ptr;
704    }
705  }
706
707  return NULL;
708}
709#endif
710
711static void ladish_graph_hide_connection_internal(struct ladish_graph * graph_ptr, struct ladish_graph_connection * connection_ptr)
712{
713  ASSERT(!connection_ptr->hidden);
714  connection_ptr->hidden = true;
715  graph_ptr->graph_version++;
716
717  if (graph_ptr->opath != NULL)
718  {
719    dbus_signal_emit(
720      g_dbus_connection,
721      graph_ptr->opath,
722      JACKDBUS_IFACE_PATCHBAY,
723      "PortsDisconnected",
724      "ttstststst",
725      &graph_ptr->graph_version,
726      &connection_ptr->port1_ptr->client_ptr->id,
727      &connection_ptr->port1_ptr->client_ptr->name,
728      &connection_ptr->port1_ptr->id,
729      &connection_ptr->port1_ptr->name,
730      &connection_ptr->port2_ptr->client_ptr->id,
731      &connection_ptr->port2_ptr->client_ptr->name,
732      &connection_ptr->port2_ptr->id,
733      &connection_ptr->port2_ptr->name,
734      &connection_ptr->id);
735  }
736}
737
738void ladish_graph_show_port_internal(struct ladish_graph * graph_ptr, struct ladish_graph_port * port_ptr)
739{
740  if (port_ptr->client_ptr->hidden)
741  {
742    port_ptr->client_ptr->hidden = false;
743    graph_ptr->graph_version++;
744    if (graph_ptr->opath != NULL)
745    {
746      dbus_signal_emit(
747        g_dbus_connection,
748        graph_ptr->opath,
749        JACKDBUS_IFACE_PATCHBAY,
750        "ClientAppeared",
751        "tts",
752        &graph_ptr->graph_version,
753        &port_ptr->client_ptr->id,
754        &port_ptr->client_ptr->name);
755    }
756  }
757
758  ASSERT(port_ptr->hidden);
759  port_ptr->hidden = false;
760  graph_ptr->graph_version++;
761  if (graph_ptr->opath != NULL)
762  {
763    dbus_signal_emit(
764      g_dbus_connection,
765      graph_ptr->opath,
766      JACKDBUS_IFACE_PATCHBAY,
767      "PortAppeared",
768      "ttstsuu",
769      &graph_ptr->graph_version,
770      &port_ptr->client_ptr->id,
771      &port_ptr->client_ptr->name,
772      &port_ptr->id,
773      &port_ptr->name,
774      &port_ptr->flags,
775      &port_ptr->type);
776
777    ladish_try_connect_hidden_connections((ladish_graph_handle)graph_ptr);
778  }
779}
780
781void ladish_graph_hide_port_internal(struct ladish_graph * graph_ptr, struct ladish_graph_port * port_ptr)
782{
783  ASSERT(!port_ptr->hidden);
784  port_ptr->hidden = true;
785  graph_ptr->graph_version++;
786
787  if (graph_ptr->opath != NULL)
788  {
789    dbus_signal_emit(
790      g_dbus_connection,
791      graph_ptr->opath,
792      JACKDBUS_IFACE_PATCHBAY,
793      "PortDisappeared",
794      "ttsts",
795      &graph_ptr->graph_version,
796      &port_ptr->client_ptr->id,
797      &port_ptr->client_ptr->name,
798      &port_ptr->id,
799      &port_ptr->name);
800  }
801}
802
803void ladish_graph_hide_client_internal(struct ladish_graph * graph_ptr, struct ladish_graph_client * client_ptr)
804{
805  ASSERT(!client_ptr->hidden);
806  client_ptr->hidden = true;
807  graph_ptr->graph_version++;
808
809  if (graph_ptr->opath != NULL)
810  {
811    dbus_signal_emit(
812      g_dbus_connection,
813      graph_ptr->opath,
814      JACKDBUS_IFACE_PATCHBAY,
815      "ClientDisappeared",
816      "tts",
817      &graph_ptr->graph_version,
818      &client_ptr->id,
819      &client_ptr->name);
820  }
821}
822
823void ladish_hide_connections(struct ladish_graph * graph_ptr, struct ladish_graph_port * port_ptr)
824{
825  struct list_head * node_ptr;
826  struct ladish_graph_connection * connection_ptr;
827
828  log_info("hidding connections of port %"PRIu64, port_ptr->id);
829
830  ASSERT(graph_ptr->opath != NULL);
831
832  list_for_each(node_ptr, &graph_ptr->connections)
833  {
834    connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
835    if (!connection_ptr->hidden && (connection_ptr->port1_ptr == port_ptr || connection_ptr->port2_ptr == port_ptr))
836    {
837      log_info("hidding connection between ports %"PRIu64" and %"PRIu64, connection_ptr->port1_ptr->id, connection_ptr->port2_ptr->id);
838      ladish_graph_hide_connection_internal(graph_ptr, connection_ptr);
839    }
840  }
841}
842
843static void ladish_graph_remove_connection_internal(struct ladish_graph * graph_ptr, struct ladish_graph_connection * connection_ptr)
844{
845  list_del(&connection_ptr->siblings);
846  graph_ptr->graph_version++;
847
848  if (!connection_ptr->hidden && graph_ptr->opath != NULL)
849  {
850    dbus_signal_emit(
851      g_dbus_connection,
852      graph_ptr->opath,
853      JACKDBUS_IFACE_PATCHBAY,
854      "PortsDisconnected",
855      "ttstststst",
856      &graph_ptr->graph_version,
857      &connection_ptr->port1_ptr->client_ptr->id,
858      &connection_ptr->port1_ptr->client_ptr->name,
859      &connection_ptr->port1_ptr->id,
860      &connection_ptr->port1_ptr->name,
861      &connection_ptr->port2_ptr->client_ptr->id,
862      &connection_ptr->port2_ptr->client_ptr->name,
863      &connection_ptr->port2_ptr->id,
864      &connection_ptr->port2_ptr->name,
865      &connection_ptr->id);
866  }
867
868  ladish_dict_destroy(connection_ptr->dict);
869  free(connection_ptr);
870}
871
872void
873ladish_graph_remove_port_internal(
874  struct ladish_graph * graph_ptr,
875  struct ladish_graph_client * client_ptr,
876  struct ladish_graph_port * port_ptr)
877{
878  ladish_port_del_ref(port_ptr->port);
879
880  list_del(&port_ptr->siblings_client);
881  list_del(&port_ptr->siblings_graph);
882
883  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");
884  if (graph_ptr->opath != NULL && !port_ptr->hidden)
885  {
886    dbus_signal_emit(
887      g_dbus_connection,
888      graph_ptr->opath,
889      JACKDBUS_IFACE_PATCHBAY,
890      "PortDisappeared",
891      "ttsts",
892      &graph_ptr->graph_version,
893      &client_ptr->id,
894      &client_ptr->name,
895      &port_ptr->id,
896      &port_ptr->name);
897  }
898
899  free(port_ptr->name);
900  free(port_ptr);
901}
902
903static
904void
905ladish_graph_remove_client_internal(
906  struct ladish_graph * graph_ptr,
907  struct ladish_graph_client * client_ptr,
908  bool destroy_client)
909{
910  struct ladish_graph_port * port_ptr;
911
912  while (!list_empty(&client_ptr->ports))
913  {
914    port_ptr = list_entry(client_ptr->ports.next, struct ladish_graph_port, siblings_client);
915    ladish_graph_remove_port_internal(graph_ptr, client_ptr, port_ptr);
916  }
917
918  graph_ptr->graph_version++;
919  list_del(&client_ptr->siblings);
920  log_info("removing client '%s' (%"PRIu64") from graph %s", client_ptr->name, client_ptr->id, graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
921  if (graph_ptr->opath != NULL && !client_ptr->hidden)
922  {
923    dbus_signal_emit(
924      g_dbus_connection,
925      graph_ptr->opath,
926      JACKDBUS_IFACE_PATCHBAY,
927      "ClientDisappeared",
928      "tts",
929      &graph_ptr->graph_version,
930      &client_ptr->id,
931      &client_ptr->name);
932  }
933
934  free(client_ptr->name);
935
936  if (destroy_client)
937  {
938    ladish_client_destroy(client_ptr->client);
939  }
940
941  free(client_ptr);
942}
943
944#define graph_ptr ((struct ladish_graph *)graph_handle)
945
946void ladish_graph_destroy(ladish_graph_handle graph_handle)
947{
948  ladish_graph_clear(graph_handle);
949  ladish_dict_destroy(graph_ptr->dict);
950  if (graph_ptr->opath != NULL)
951  {
952    free(graph_ptr->opath);
953  }
954  free(graph_ptr);
955}
956
957const char * ladish_graph_get_opath(ladish_graph_handle graph_handle)
958{
959  return graph_ptr->opath;
960}
961
962void
963ladish_graph_set_connection_handlers(
964  ladish_graph_handle graph_handle,
965  void * graph_context,
966  ladish_graph_connect_request_handler connect_handler,
967  ladish_graph_disconnect_request_handler disconnect_handler)
968{
969  graph_ptr->context = graph_context;
970  graph_ptr->connect_handler = connect_handler;
971  graph_ptr->disconnect_handler = disconnect_handler;
972}
973
974void ladish_graph_clear(ladish_graph_handle graph_handle)
975{
976  struct ladish_graph_client * client_ptr;
977  struct ladish_graph_connection * connection_ptr;
978
979  log_info("ladish_graph_clear() called for graph '%s'", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
980
981  while (!list_empty(&graph_ptr->connections))
982  {
983    connection_ptr = list_entry(graph_ptr->connections.next, struct ladish_graph_connection, siblings);
984    ladish_graph_remove_connection_internal(graph_ptr, connection_ptr);
985  }
986
987  while (!list_empty(&graph_ptr->clients))
988  {
989    client_ptr = list_entry(graph_ptr->clients.next, struct ladish_graph_client, siblings);
990    ladish_graph_remove_client_internal(graph_ptr, client_ptr, true);
991  }
992}
993
994void * ladish_graph_get_dbus_context(ladish_graph_handle graph_handle)
995{
996  return graph_handle;
997}
998
999ladish_dict_handle ladish_graph_get_dict(ladish_graph_handle graph_handle)
1000{
1001  return graph_ptr->dict;
1002}
1003
1004void ladish_graph_show_connection(ladish_graph_handle graph_handle, uint64_t connection_id)
1005{
1006  struct ladish_graph_connection * connection_ptr;
1007
1008  log_info("ladish_graph_show_connection() called.");
1009
1010  connection_ptr = ladish_graph_find_connection_by_id(graph_ptr, connection_id);
1011  if (connection_ptr == NULL)
1012  {
1013    ASSERT_NO_PASS;
1014    return;
1015  }
1016
1017  ASSERT(graph_ptr->opath != NULL);
1018  ASSERT(connection_ptr->hidden);
1019  connection_ptr->hidden = false;
1020  connection_ptr->changing = false;
1021  graph_ptr->graph_version++;
1022
1023  dbus_signal_emit(
1024    g_dbus_connection,
1025    graph_ptr->opath,
1026    JACKDBUS_IFACE_PATCHBAY,
1027    "PortsConnected",
1028    "ttstststst",
1029    &graph_ptr->graph_version,
1030    &connection_ptr->port1_ptr->client_ptr->id,
1031    &connection_ptr->port1_ptr->client_ptr->name,
1032    &connection_ptr->port1_ptr->id,
1033    &connection_ptr->port1_ptr->name,
1034    &connection_ptr->port2_ptr->client_ptr->id,
1035    &connection_ptr->port2_ptr->client_ptr->name,
1036    &connection_ptr->port2_ptr->id,
1037    &connection_ptr->port2_ptr->name,
1038    &connection_ptr->id);
1039}
1040
1041void ladish_graph_show_port(ladish_graph_handle graph_handle, ladish_port_handle port_handle)
1042{
1043  struct ladish_graph_port * port_ptr;
1044
1045  //log_info("ladish_graph_show_port() called.");
1046
1047  port_ptr = ladish_graph_find_port(graph_ptr, port_handle);
1048  if (port_ptr == NULL)
1049  {
1050    ASSERT_NO_PASS;
1051    return;
1052  }
1053
1054  //log_info("port '%s' is %s", port_ptr->name, port_ptr->hidden ? "invisible" : "visible");
1055
1056  ladish_graph_show_port_internal(graph_ptr, port_ptr);
1057}
1058
1059void ladish_graph_hide_port(ladish_graph_handle graph_handle, ladish_port_handle port_handle)
1060{
1061  struct ladish_graph_port * port_ptr;
1062
1063  log_info("ladish_graph_hide_port() called.");
1064
1065  port_ptr = ladish_graph_find_port(graph_ptr, port_handle);
1066  if (port_ptr == NULL)
1067  {
1068    ASSERT_NO_PASS;
1069    return;
1070  }
1071
1072  log_info("Hidding port %"PRIu64, port_ptr->id);
1073
1074  ASSERT(!port_ptr->hidden);
1075
1076  if (graph_ptr->opath != NULL)
1077  {
1078    ladish_hide_connections(graph_ptr, port_ptr);
1079  }
1080
1081  ladish_graph_hide_port_internal(graph_ptr, port_ptr);
1082}
1083
1084void ladish_graph_hide_client(ladish_graph_handle graph_handle, ladish_client_handle client_handle)
1085{
1086  struct ladish_graph_client * client_ptr;
1087
1088  log_info("ladish_graph_hide_client() called.");
1089
1090  client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1091  if (client_ptr == NULL)
1092  {
1093    ASSERT_NO_PASS;
1094    return;
1095  }
1096
1097  ladish_graph_hide_client_internal(graph_ptr, client_ptr);
1098}
1099
1100void ladish_graph_show_client(ladish_graph_handle graph_handle, ladish_client_handle client_handle)
1101{
1102  struct ladish_graph_client * client_ptr;
1103
1104  log_info("ladish_graph_show_client() called.");
1105
1106  client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1107  if (client_ptr == NULL)
1108  {
1109    ASSERT_NO_PASS;
1110    return;
1111  }
1112
1113  ASSERT(client_ptr->hidden);
1114  client_ptr->hidden = false;
1115  graph_ptr->graph_version++;
1116
1117  if (graph_ptr->opath != NULL)
1118  {
1119    dbus_signal_emit(
1120      g_dbus_connection,
1121      graph_ptr->opath,
1122      JACKDBUS_IFACE_PATCHBAY,
1123      "ClientAppeared",
1124      "tts",
1125      &graph_ptr->graph_version,
1126      &client_ptr->id,
1127      &client_ptr->name);
1128  }
1129}
1130
1131void ladish_graph_adjust_port(ladish_graph_handle graph_handle, ladish_port_handle port_handle, uint32_t type, uint32_t flags)
1132{
1133  struct ladish_graph_port * port_ptr;
1134
1135  //log_info("ladish_graph_adjust_port() called.");
1136
1137  port_ptr = ladish_graph_find_port(graph_ptr, port_handle);
1138  if (port_ptr == NULL)
1139  {
1140    ASSERT_NO_PASS;
1141    return;
1142  }
1143
1144  port_ptr->type = type;
1145  port_ptr->flags = flags;
1146}
1147
1148bool ladish_graph_add_client(ladish_graph_handle graph_handle, ladish_client_handle client_handle, const char * name, bool hidden)
1149{
1150  struct ladish_graph_client * client_ptr;
1151
1152  log_info("adding client '%s' (%p) to graph %s", name, client_handle, graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
1153
1154  client_ptr = malloc(sizeof(struct ladish_graph_client));
1155  if (client_ptr == NULL)
1156  {
1157    log_error("malloc() failed for struct ladish_graph_client");
1158    return false;
1159  }
1160
1161  client_ptr->name = strdup(name);
1162  if (client_ptr->name == NULL)
1163  {
1164    log_error("strdup() failed for graph client name");
1165    free(client_ptr);
1166    return false;
1167  }
1168
1169  client_ptr->id = graph_ptr->next_client_id++;
1170  client_ptr->client = client_handle;
1171  client_ptr->hidden = hidden;
1172  graph_ptr->graph_version++;
1173
1174  INIT_LIST_HEAD(&client_ptr->ports);
1175
1176  list_add_tail(&client_ptr->siblings, &graph_ptr->clients);
1177
1178  if (!hidden && graph_ptr->opath != NULL)
1179  {
1180    dbus_signal_emit(
1181      g_dbus_connection,
1182      graph_ptr->opath,
1183      JACKDBUS_IFACE_PATCHBAY,
1184      "ClientAppeared",
1185      "tts",
1186      &graph_ptr->graph_version,
1187      &client_ptr->id,
1188      &client_ptr->name);
1189  }
1190
1191  return true;
1192}
1193
1194void
1195ladish_graph_remove_client(
1196  ladish_graph_handle graph_handle,
1197  ladish_client_handle client_handle)
1198{
1199  struct ladish_graph_client * client_ptr;
1200
1201  log_info("ladish_graph_remove_client() called.");
1202
1203  client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1204  if (client_ptr != NULL)
1205  {
1206    ladish_graph_remove_client_internal(graph_ptr, client_ptr, false);
1207  }
1208  else
1209  {
1210    ASSERT_NO_PASS;
1211  }
1212}
1213
1214bool
1215ladish_graph_add_port(
1216  ladish_graph_handle graph_handle,
1217  ladish_client_handle client_handle,
1218  ladish_port_handle port_handle,
1219  const char * name,
1220  uint32_t type,
1221  uint32_t flags,
1222  bool hidden)
1223{
1224  struct ladish_graph_client * client_ptr;
1225  struct ladish_graph_port * port_ptr;
1226
1227  client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1228  if (client_ptr == NULL)
1229  {
1230    log_error("cannot find client to add port to. graph is %s", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
1231    ASSERT_NO_PASS;
1232    return false;
1233  }
1234
1235  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");
1236
1237  port_ptr = malloc(sizeof(struct ladish_graph_port));
1238  if (port_ptr == NULL)
1239  {
1240    log_error("malloc() failed for struct ladish_graph_port");
1241    return false;
1242  }
1243
1244  port_ptr->name = strdup(name);
1245  if (port_ptr->name == NULL)
1246  {
1247    log_error("strdup() failed for graph port name");
1248    free(port_ptr);
1249    return false;
1250  }
1251
1252  port_ptr->type = type;
1253  port_ptr->flags = flags;
1254
1255  port_ptr->id = graph_ptr->next_port_id++;
1256  port_ptr->port = port_handle;
1257  ladish_port_add_ref(port_ptr->port);
1258  port_ptr->hidden = true;
1259
1260  port_ptr->client_ptr = client_ptr;
1261  list_add_tail(&port_ptr->siblings_client, &client_ptr->ports);
1262  list_add_tail(&port_ptr->siblings_graph, &graph_ptr->ports);
1263
1264  if (!hidden)
1265  {
1266    ladish_graph_show_port_internal(graph_ptr, port_ptr);
1267  }
1268
1269  return true;
1270}
1271
1272uint64_t
1273ladish_graph_add_connection(
1274  ladish_graph_handle graph_handle,
1275  ladish_port_handle port1_handle,
1276  ladish_port_handle port2_handle,
1277  bool hidden)
1278{
1279  struct ladish_graph_port * port1_ptr;
1280  struct ladish_graph_port * port2_ptr;
1281  struct ladish_graph_connection * connection_ptr;
1282
1283  port1_ptr = ladish_graph_find_port(graph_ptr, port1_handle);
1284  ASSERT(port1_ptr != NULL);
1285  port2_ptr = ladish_graph_find_port(graph_ptr, port2_handle);
1286  ASSERT(port2_ptr != NULL);
1287
1288  connection_ptr = malloc(sizeof(struct ladish_graph_connection));
1289  if (connection_ptr == NULL)
1290  {
1291    log_error("malloc() failed for struct ladish_graph_connection");
1292    return 0;
1293  }
1294
1295  if (!ladish_dict_create(&connection_ptr->dict))
1296  {
1297    log_error("ladish_dict_create() failed for connection");
1298    free(connection_ptr);
1299    return 0;
1300  }
1301
1302  connection_ptr->id = graph_ptr->next_connection_id++;
1303  connection_ptr->port1_ptr = port1_ptr;
1304  connection_ptr->port2_ptr = port2_ptr;
1305  connection_ptr->hidden = hidden;
1306  connection_ptr->changing = false;
1307  graph_ptr->graph_version++;
1308
1309  list_add_tail(&connection_ptr->siblings, &graph_ptr->connections);
1310
1311  /* log_info( */
1312  /*   "new connection %"PRIu64" between '%s':'%s' and '%s':'%s'", */
1313  /*   connection_ptr->id, */
1314  /*   port1_ptr->client_ptr->name, */
1315  /*   port1_ptr->name, */
1316  /*   port2_ptr->client_ptr->name, */
1317  /*   port2_ptr->name); */
1318
1319  if (!hidden && graph_ptr->opath != NULL)
1320  {
1321    dbus_signal_emit(
1322      g_dbus_connection,
1323      graph_ptr->opath,
1324      JACKDBUS_IFACE_PATCHBAY,
1325      "PortsConnected",
1326      "ttstststst",
1327      &graph_ptr->graph_version,
1328      &port1_ptr->client_ptr->id,
1329      &port1_ptr->client_ptr->name,
1330      &port1_ptr->id,
1331      &port1_ptr->name,
1332      &port2_ptr->client_ptr->id,
1333      &port2_ptr->client_ptr->name,
1334      &port2_ptr->id,
1335      &port2_ptr->name,
1336      &connection_ptr->id);
1337  }
1338
1339  return connection_ptr->id;
1340}
1341
1342void
1343ladish_graph_remove_connection(
1344  ladish_graph_handle graph_handle,
1345  uint64_t connection_id,
1346  bool force)
1347{
1348  struct ladish_graph_connection * connection_ptr;
1349
1350  connection_ptr = ladish_graph_find_connection_by_id(graph_ptr, connection_id);
1351  if (connection_ptr == NULL)
1352  {
1353    ASSERT_NO_PASS;
1354    return;
1355  }
1356
1357  if (force || connection_ptr->changing)
1358  {
1359    /* log_info( */
1360    /*   "removing connection '%s':'%s' - '%s':'%s'", */
1361    /*   connection_ptr->port1_ptr->client_ptr->name, */
1362    /*   connection_ptr->port1_ptr->name, */
1363    /*   connection_ptr->port2_ptr->client_ptr->name, */
1364    /*   connection_ptr->port2_ptr->name); */
1365
1366    ladish_graph_remove_connection_internal(graph_ptr, connection_ptr);
1367  }
1368  else
1369  {
1370    /* log_info( */
1371    /*   "hiding connection '%s':'%s' - '%s':'%s'", */
1372    /*   connection_ptr->port1_ptr->client_ptr->name, */
1373    /*   connection_ptr->port1_ptr->name, */
1374    /*   connection_ptr->port2_ptr->client_ptr->name, */
1375    /*   connection_ptr->port2_ptr->name); */
1376
1377    ladish_graph_hide_connection_internal(graph_ptr, connection_ptr);
1378  }
1379}
1380
1381bool
1382ladish_graph_get_connection_ports(
1383  ladish_graph_handle graph_handle,
1384  uint64_t connection_id,
1385  ladish_port_handle * port1_handle_ptr,
1386  ladish_port_handle * port2_handle_ptr)
1387{
1388  struct ladish_graph_connection * connection_ptr;
1389
1390  connection_ptr = ladish_graph_find_connection_by_id(graph_ptr, connection_id);
1391  if (connection_ptr == NULL)
1392  {
1393    return false;
1394  }
1395
1396  *port1_handle_ptr = connection_ptr->port1_ptr->port;
1397  *port2_handle_ptr = connection_ptr->port2_ptr->port;
1398
1399  return true;
1400}
1401
1402ladish_dict_handle ladish_graph_get_connection_dict(ladish_graph_handle graph_handle, uint64_t connection_id)
1403{
1404  struct ladish_graph_connection * connection_ptr;
1405
1406  connection_ptr = ladish_graph_find_connection_by_id(graph_ptr, connection_id);
1407  if (connection_ptr == NULL)
1408  {
1409    return NULL;
1410  }
1411
1412  return connection_ptr->dict;
1413}
1414
1415bool
1416ladish_graph_find_connection(
1417  ladish_graph_handle graph_handle,
1418  ladish_port_handle port1_handle,
1419  ladish_port_handle port2_handle,
1420  uint64_t * connection_id_ptr)
1421{
1422  struct ladish_graph_port * port1_ptr;
1423  struct ladish_graph_port * port2_ptr;
1424  struct ladish_graph_connection * connection_ptr;
1425
1426  port1_ptr = ladish_graph_find_port(graph_ptr, port1_handle);
1427  if (port1_ptr == NULL)
1428  {
1429    return false;
1430  }
1431     
1432  port2_ptr = ladish_graph_find_port(graph_ptr, port2_handle);
1433  if (port1_ptr == NULL)
1434  {
1435    return false;
1436  }
1437
1438  connection_ptr = ladish_graph_find_connection_by_ports(graph_ptr, port1_ptr, port2_ptr);
1439  if (connection_ptr == NULL)
1440  {
1441    return false;
1442  }
1443
1444  *connection_id_ptr = connection_ptr->id;
1445
1446  return true;
1447}
1448
1449ladish_client_handle ladish_graph_find_client_by_name(ladish_graph_handle graph_handle, const char * name)
1450{
1451  struct list_head * node_ptr;
1452  struct ladish_graph_client * client_ptr;
1453
1454  list_for_each(node_ptr, &graph_ptr->clients)
1455  {
1456    client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
1457    if (strcmp(client_ptr->name, name) == 0)
1458    {
1459      return client_ptr->client;
1460    }
1461  }
1462
1463  return NULL;
1464}
1465
1466ladish_port_handle ladish_graph_find_port_by_name(ladish_graph_handle graph_handle, ladish_client_handle client_handle, const char * name)
1467{
1468  struct ladish_graph_client * client_ptr;
1469  struct list_head * node_ptr;
1470  struct ladish_graph_port * port_ptr;
1471
1472  client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1473  if (client_ptr != NULL)
1474  {
1475    list_for_each(node_ptr, &client_ptr->ports)
1476    {
1477      port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_client);
1478      if (strcmp(port_ptr->name, name) == 0)
1479      {
1480        return port_ptr->port;
1481      }
1482    }
1483  }
1484  else
1485  {
1486    ASSERT_NO_PASS;
1487  }
1488
1489  return NULL;
1490}
1491
1492ladish_client_handle ladish_graph_find_client_by_uuid(ladish_graph_handle graph_handle, const uuid_t uuid)
1493{
1494  struct list_head * node_ptr;
1495  struct ladish_graph_client * client_ptr;
1496  uuid_t current_uuid;
1497
1498  list_for_each(node_ptr, &graph_ptr->clients)
1499  {
1500    client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
1501    ladish_client_get_uuid(client_ptr->client, current_uuid);
1502    if (uuid_compare(current_uuid, uuid) == 0)
1503    {
1504      return client_ptr->client;
1505    }
1506  }
1507
1508  return NULL;
1509}
1510
1511ladish_port_handle ladish_graph_find_port_by_uuid(ladish_graph_handle graph_handle, const uuid_t uuid)
1512{
1513  struct list_head * node_ptr;
1514  struct ladish_graph_port * port_ptr;
1515  uuid_t current_uuid;
1516
1517  list_for_each(node_ptr, &graph_ptr->ports)
1518  {
1519    port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph);
1520    ladish_port_get_uuid(port_ptr->port, current_uuid);
1521    if (uuid_compare(current_uuid, uuid) == 0)
1522    {
1523      return port_ptr->port;
1524    }
1525  }
1526
1527  return NULL;
1528}
1529
1530ladish_client_handle ladish_graph_get_port_client(ladish_graph_handle graph_handle, ladish_port_handle port_handle)
1531{
1532  struct ladish_graph_port * port_ptr;
1533
1534  port_ptr = ladish_graph_find_port(graph_ptr, port_handle);
1535  if (port_ptr == NULL)
1536  {
1537    return NULL;
1538  }
1539
1540  return port_ptr->client_ptr->client;
1541}
1542
1543bool ladish_graph_is_port_present(ladish_graph_handle graph_handle, ladish_port_handle port_handle)
1544{
1545  return ladish_graph_find_port(graph_ptr, port_handle) != NULL;
1546}
1547
1548ladish_client_handle ladish_graph_find_client_by_id(ladish_graph_handle graph_handle, uint64_t client_id)
1549{
1550  struct list_head * node_ptr;
1551  struct ladish_graph_client * client_ptr;
1552
1553  list_for_each(node_ptr, &graph_ptr->clients)
1554  {
1555    client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
1556    if (client_ptr->id == client_id)
1557    {
1558      return client_ptr->client;
1559    }
1560  }
1561
1562  return NULL;
1563}
1564
1565ladish_port_handle ladish_graph_find_port_by_id(ladish_graph_handle graph_handle, uint64_t port_id)
1566{
1567  struct ladish_graph_port * port_ptr;
1568
1569  port_ptr = ladish_graph_find_port_by_id_internal(graph_ptr, port_id);
1570  if (port_ptr == NULL)
1571  {
1572    return NULL;
1573  }
1574
1575  return port_ptr->port;
1576}
1577
1578ladish_client_handle ladish_graph_find_client_by_jack_id(ladish_graph_handle graph_handle, uint64_t client_id)
1579{
1580  struct list_head * node_ptr;
1581  struct ladish_graph_client * client_ptr;
1582
1583  list_for_each(node_ptr, &graph_ptr->clients)
1584  {
1585    client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
1586    if (ladish_client_get_jack_id(client_ptr->client) == client_id)
1587    {
1588      return client_ptr->client;
1589    }
1590  }
1591
1592  return NULL;
1593}
1594
1595ladish_port_handle ladish_graph_find_port_by_jack_id(ladish_graph_handle graph_handle, uint64_t port_id)
1596{
1597  struct list_head * node_ptr;
1598  struct ladish_graph_port * port_ptr;
1599
1600  list_for_each(node_ptr, &graph_ptr->ports)
1601  {
1602    port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph);
1603    if (ladish_port_get_jack_id(port_ptr->port) == port_id)
1604    {
1605      return port_ptr->port;
1606    }
1607  }
1608
1609  return NULL;
1610}
1611
1612ladish_client_handle
1613ladish_graph_remove_port(
1614  ladish_graph_handle graph_handle,
1615  ladish_port_handle port)
1616{
1617  struct ladish_graph_port * port_ptr;
1618
1619  port_ptr = ladish_graph_find_port(graph_ptr, port);
1620  if (port_ptr == NULL)
1621  {
1622    return NULL;
1623  }
1624
1625  ladish_graph_remove_port_internal(graph_ptr, port_ptr->client_ptr, port_ptr);
1626  return port_ptr->client_ptr->client;
1627}
1628
1629bool
1630ladish_graph_rename_client(
1631  ladish_graph_handle graph_handle,
1632  ladish_client_handle client_handle,
1633  const char * new_client_name)
1634{
1635  char * name;
1636  struct ladish_graph_client * client_ptr;
1637  char * old_name;
1638
1639  name = strdup(new_client_name);
1640  if (name == NULL)
1641  {
1642    log_error("strdup('%s') failed.", new_client_name);
1643    return false;
1644  }
1645
1646  client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1647  if (client_ptr == NULL)
1648  {
1649    free(name);
1650    ASSERT_NO_PASS;
1651    return false;
1652  }
1653
1654  old_name = client_ptr->name;
1655  client_ptr->name = name;
1656
1657  graph_ptr->graph_version++;
1658
1659  if (!client_ptr->hidden && graph_ptr->opath != NULL)
1660  {
1661    dbus_signal_emit(
1662      g_dbus_connection,
1663      graph_ptr->opath,
1664      JACKDBUS_IFACE_PATCHBAY,
1665      "ClientRenamed",
1666      "ttss",
1667      &graph_ptr->graph_version,
1668      &client_ptr->id,
1669      &old_name,
1670      &client_ptr->name);
1671  }
1672
1673  free(old_name);
1674
1675  return true;
1676}
1677
1678bool
1679ladish_graph_rename_port(
1680  ladish_graph_handle graph_handle,
1681  ladish_port_handle port_handle,
1682  const char * new_port_name)
1683{
1684  char * name;
1685  struct ladish_graph_port * port_ptr;
1686  char * old_name;
1687
1688  name = strdup(new_port_name);
1689  if (name == NULL)
1690  {
1691    log_error("strdup('%s') failed.", new_port_name);
1692    return false;
1693  }
1694
1695  port_ptr = ladish_graph_find_port(graph_ptr, port_handle);
1696  if (port_ptr == NULL)
1697  {
1698    ASSERT_NO_PASS;
1699    free(name);
1700    return false;
1701  }
1702
1703  old_name = port_ptr->name;
1704  port_ptr->name = name;
1705
1706  graph_ptr->graph_version++;
1707
1708  if (!port_ptr->hidden && graph_ptr->opath != NULL)
1709  {
1710    dbus_signal_emit(
1711      g_dbus_connection,
1712      graph_ptr->opath,
1713      JACKDBUS_IFACE_PATCHBAY,
1714      "PortRenamed",
1715      "ttstss",
1716      &graph_ptr->graph_version,
1717      &port_ptr->client_ptr->id,
1718      &port_ptr->client_ptr->name,
1719      &port_ptr->id,
1720      &old_name,
1721      &port_ptr->name);
1722  }
1723
1724  free(old_name);
1725
1726  return true;
1727}
1728
1729const char * ladish_graph_get_client_name(ladish_graph_handle graph_handle, ladish_client_handle client_handle)
1730{
1731  struct ladish_graph_client * client_ptr;
1732
1733  client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1734  if (client_ptr != NULL)
1735  {
1736      return client_ptr->name;
1737  }
1738
1739  ASSERT_NO_PASS;
1740  return NULL;
1741}
1742
1743bool ladish_graph_is_client_empty(ladish_graph_handle graph_handle, ladish_client_handle client_handle)
1744{
1745  struct ladish_graph_client * client_ptr;
1746
1747  client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1748  if (client_ptr != NULL)
1749  {
1750    return list_empty(&client_ptr->ports);
1751  }
1752
1753  ASSERT_NO_PASS;
1754  return true;
1755}
1756
1757bool ladish_graph_is_client_looks_empty(ladish_graph_handle graph_handle, ladish_client_handle client_handle)
1758{
1759  struct ladish_graph_client * client_ptr;
1760  struct list_head * node_ptr;
1761  struct ladish_graph_port * port_ptr;
1762
1763  client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1764  if (client_ptr != NULL)
1765  {
1766    list_for_each(node_ptr, &client_ptr->ports)
1767    {
1768      port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_client);
1769      if (!port_ptr->hidden)
1770      {
1771        //log_info("port '%s' is visible, client '%s' does not look empty", port_ptr->name, client_ptr->name);
1772        return false;
1773      }
1774      else
1775      {
1776        //log_info("port '%s' is invisible", port_ptr->name);
1777      }
1778    }
1779
1780    log_info("client '%s' looks empty in graph %s", client_ptr->name, graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
1781    return true;
1782  }
1783
1784  ASSERT_NO_PASS;
1785  return true;
1786}
1787
1788void ladish_try_connect_hidden_connections(ladish_graph_handle graph_handle)
1789{
1790  struct list_head * node_ptr;
1791  struct ladish_graph_connection * connection_ptr;
1792
1793  if (!list_empty(&graph_ptr->connections) && graph_ptr->connect_handler == NULL)
1794  {
1795    ASSERT_NO_PASS;
1796    return;
1797  }
1798
1799  ASSERT(graph_ptr->opath != NULL);
1800
1801  list_for_each(node_ptr, &graph_ptr->connections)
1802  {
1803    connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
1804    if (connection_ptr->hidden &&
1805        !connection_ptr->changing &&
1806        !connection_ptr->port1_ptr->hidden &&
1807        !connection_ptr->port2_ptr->hidden)
1808    {
1809      log_info(
1810        "auto connecting '%s':'%s' to '%s':'%s'",
1811        connection_ptr->port1_ptr->client_ptr->name,
1812        connection_ptr->port1_ptr->name,
1813        connection_ptr->port2_ptr->client_ptr->name,
1814        connection_ptr->port2_ptr->name);
1815
1816      connection_ptr->changing = true;
1817      if (!graph_ptr->connect_handler(graph_ptr->context, graph_handle, connection_ptr->port1_ptr->port, connection_ptr->port2_ptr->port))
1818      {
1819        connection_ptr->changing = false;
1820        log_error("auto connect failed.");
1821      }
1822    }
1823  }
1824}
1825
1826void ladish_graph_hide_all(ladish_graph_handle graph_handle)
1827{
1828  struct list_head * node_ptr;
1829  struct ladish_graph_connection * connection_ptr;
1830  struct ladish_graph_port * port_ptr;
1831  struct ladish_graph_client * client_ptr;
1832
1833  log_info("hiding everything in graph %s", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
1834
1835  list_for_each(node_ptr, &graph_ptr->connections)
1836  {
1837    connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
1838    if (!connection_ptr->hidden)
1839    {
1840      log_debug("hidding connection between ports %"PRIu64" and %"PRIu64, connection_ptr->port1_ptr->id, connection_ptr->port2_ptr->id);
1841      ladish_graph_hide_connection_internal(graph_ptr, connection_ptr);
1842    }
1843  }
1844
1845  list_for_each(node_ptr, &graph_ptr->ports)
1846  {
1847    port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph);
1848    if (!port_ptr->hidden)
1849    {
1850      ladish_port_set_jack_id(port_ptr->port, 0);
1851      ladish_graph_hide_port_internal(graph_ptr, port_ptr);
1852    }
1853  }
1854
1855  list_for_each(node_ptr, &graph_ptr->clients)
1856  {
1857    client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
1858    if (!client_ptr->hidden)
1859    {
1860      ladish_client_set_jack_id(client_ptr->client, 0);
1861      ladish_graph_hide_client_internal(graph_ptr, client_ptr);
1862    }
1863  }
1864}
1865
1866bool
1867ladish_graph_iterate_nodes(
1868  ladish_graph_handle graph_handle,
1869  void * callback_context,
1870  bool
1871  (* client_begin_callback)(
1872    void * context,
1873    ladish_client_handle client_handle,
1874    const char * client_name,
1875    void ** client_iteration_context_ptr_ptr),
1876  bool
1877  (* port_callback)(
1878    void * context,
1879    void * client_iteration_context_ptr,
1880    ladish_client_handle client_handle,
1881    const char * client_name,
1882    ladish_port_handle port_handle,
1883    const char * port_name,
1884    uint32_t port_type,
1885    uint32_t port_flags),
1886  bool
1887  (* client_end_callback)(
1888    void * context,
1889    ladish_client_handle client_handle,
1890    const char * client_name,
1891    void * client_iteration_context_ptr))
1892{
1893  struct list_head * client_node_ptr;
1894  struct ladish_graph_client * client_ptr;
1895  void * client_context;
1896  struct list_head * port_node_ptr;
1897  struct ladish_graph_port * port_ptr;
1898
1899  list_for_each(client_node_ptr, &graph_ptr->clients)
1900  {
1901    client_ptr = list_entry(client_node_ptr, struct ladish_graph_client, siblings);
1902
1903    if (client_ptr->hidden)
1904    {
1905      continue;
1906    }
1907
1908    if (client_begin_callback != NULL)
1909    {
1910      if (!client_begin_callback(callback_context, client_ptr->client, client_ptr->name, &client_context))
1911      {
1912        return false;
1913      }
1914    }
1915    else
1916    {
1917      client_context = NULL;
1918    }
1919
1920    if (port_callback == NULL)
1921    {
1922      continue;
1923    }
1924
1925    list_for_each(port_node_ptr, &client_ptr->ports)
1926    {
1927      port_ptr = list_entry(port_node_ptr, struct ladish_graph_port, siblings_client);
1928
1929      if (port_ptr->hidden)
1930      {
1931        continue;
1932      }
1933
1934      if (!port_callback(
1935            callback_context,
1936            client_context,
1937            client_ptr->client,
1938            client_ptr->name,
1939            port_ptr->port,
1940            port_ptr->name,
1941            port_ptr->type,
1942            port_ptr->flags))
1943      {
1944        return false;
1945      }
1946    }
1947
1948    if (client_end_callback != NULL)
1949    {
1950      if (!client_end_callback(callback_context, client_ptr->client, client_ptr->name, &client_context))
1951      {
1952        return false;
1953      }
1954    }
1955  }
1956
1957  return true;
1958}
1959
1960bool
1961ladish_graph_iterate_connections(
1962  ladish_graph_handle graph_handle,
1963  void * callback_context,
1964  bool (* callback)(void * context, ladish_port_handle port1_handle, ladish_port_handle port2_handle, ladish_dict_handle dict))
1965{
1966  struct list_head * node_ptr;
1967  struct ladish_graph_connection * connection_ptr;
1968
1969  list_for_each(node_ptr, &graph_ptr->connections)
1970  {
1971    connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
1972
1973    if (connection_ptr->hidden)
1974    {
1975      continue;
1976    }
1977
1978    if (!callback(callback_context, connection_ptr->port1_ptr->port, connection_ptr->port2_ptr->port, connection_ptr->dict))
1979    {
1980      return false;
1981    }
1982  }
1983
1984  return true;
1985}
1986
1987static
1988bool
1989dump_dict_entry(
1990  void * context,
1991  const char * key,
1992  const char * value)
1993{
1994  log_info("%s  key '%s' with value '%s'", (const char *)context, key, value);
1995  return true;
1996}
1997
1998static
1999void
2000dump_dict(
2001  const char * indent,
2002  ladish_dict_handle dict)
2003{
2004  if (ladish_dict_is_empty(dict))
2005  {
2006    return;
2007  }
2008
2009  log_info("%sdict:", indent);
2010  ladish_dict_iterate(dict, (void *)indent, dump_dict_entry);
2011}
2012
2013void ladish_graph_dump(ladish_graph_handle graph_handle)
2014{
2015  struct list_head * client_node_ptr;
2016  struct ladish_graph_client * client_ptr;
2017  struct list_head * port_node_ptr;
2018  struct ladish_graph_port * port_ptr;
2019  struct list_head * connection_node_ptr;
2020  struct ladish_graph_connection * connection_ptr;
2021
2022  log_info("graph %s", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
2023  log_info("  version %"PRIu64, graph_ptr->graph_version);
2024  dump_dict("  ", graph_ptr->dict);
2025  log_info("  clients:");
2026  list_for_each(client_node_ptr, &graph_ptr->clients)
2027  {
2028    client_ptr = list_entry(client_node_ptr, struct ladish_graph_client, siblings);
2029    log_info("    %s client '%s', id=%"PRIu64", ptr=%p", client_ptr->hidden ? "invisible" : "visible", client_ptr->name, client_ptr->id, client_ptr->client);
2030    dump_dict("      ", ladish_client_get_dict(client_ptr->client));
2031    log_info("      ports:");
2032    list_for_each(port_node_ptr, &client_ptr->ports)
2033    {
2034      port_ptr = list_entry(port_node_ptr, struct ladish_graph_port, siblings_client);
2035
2036      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);
2037      dump_dict("        ", ladish_port_get_dict(port_ptr->port));
2038    }
2039  }
2040  log_info("  connections:");
2041  list_for_each(connection_node_ptr, &graph_ptr->connections)
2042  {
2043    connection_ptr = list_entry(connection_node_ptr, struct ladish_graph_connection, siblings);
2044
2045    log_info(
2046      "    %s connection '%s':'%s' - '%s':'%s'%s",
2047      connection_ptr->hidden ? "invisible" : "visible",
2048      connection_ptr->port1_ptr->client_ptr->name,
2049      connection_ptr->port1_ptr->name,
2050      connection_ptr->port2_ptr->client_ptr->name,
2051      connection_ptr->port2_ptr->name,
2052      connection_ptr->changing ? " [changing]" : "");
2053    dump_dict("      ", connection_ptr->dict);
2054  }
2055}
2056
2057#undef graph_ptr
2058#define graph_ptr ((struct ladish_graph *)context)
2059
2060static
2061bool
2062ladish_graph_copy_client_begin_callback(
2063  void * context,
2064  ladish_client_handle client_handle,
2065  const char * client_name,
2066  void ** client_iteration_context_ptr_ptr)
2067{
2068  ladish_client_handle copy;
2069
2070  if (!ladish_client_create_copy(client_handle, &copy))
2071  {
2072    return false;
2073  }
2074
2075  if (!ladish_graph_add_client(context, copy, client_name, false))
2076  {
2077    ladish_client_destroy(copy);
2078    return false;
2079  }
2080
2081  *client_iteration_context_ptr_ptr = copy;
2082
2083  return true;
2084}
2085
2086static
2087bool
2088ladish_graph_copy_port_callback(
2089  void * context,
2090  void * client_iteration_context_ptr,
2091  ladish_client_handle client_handle,
2092  const char * client_name,
2093  ladish_port_handle port_handle,
2094  const char * port_name,
2095  uint32_t port_type,
2096  uint32_t port_flags)
2097{
2098  ladish_port_handle copy;
2099
2100  if (!ladish_port_create_copy(port_handle, &copy))
2101  {
2102    return false;
2103  }
2104
2105  if (!ladish_graph_add_port(context, client_iteration_context_ptr, copy, port_name, port_type, port_flags, false))
2106  {
2107    ladish_port_destroy(copy);
2108    return false;
2109  }
2110
2111  return true;
2112}
2113
2114#undef graph_ptr
2115
2116bool ladish_graph_copy(ladish_graph_handle src, ladish_graph_handle dest)
2117{
2118  return ladish_graph_iterate_nodes(
2119    src,
2120    dest,
2121    ladish_graph_copy_client_begin_callback,
2122    ladish_graph_copy_port_callback,
2123    NULL);
2124}
2125
2126METHOD_ARGS_BEGIN(GetAllPorts, "Get all ports")
2127  METHOD_ARG_DESCRIBE_IN("ports_list", "as", "List of all ports")
2128METHOD_ARGS_END
2129
2130METHOD_ARGS_BEGIN(GetGraph, "Get whole graph")
2131METHOD_ARG_DESCRIBE_IN("known_graph_version", DBUS_TYPE_UINT64_AS_STRING, "Known graph version")
2132  METHOD_ARG_DESCRIBE_OUT("current_graph_version", DBUS_TYPE_UINT64_AS_STRING, "Current graph version")
2133  METHOD_ARG_DESCRIBE_OUT("clients_and_ports", "a(tsa(tsuu))", "Clients and their ports")
2134  METHOD_ARG_DESCRIBE_OUT("connections", "a(tstststst)", "Connections array")
2135METHOD_ARGS_END
2136
2137METHOD_ARGS_BEGIN(ConnectPortsByName, "Connect ports")
2138  METHOD_ARG_DESCRIBE_IN("client1_name", DBUS_TYPE_STRING_AS_STRING, "name first port client")
2139  METHOD_ARG_DESCRIBE_IN("port1_name", DBUS_TYPE_STRING_AS_STRING, "name of first port")
2140  METHOD_ARG_DESCRIBE_IN("client2_name", DBUS_TYPE_STRING_AS_STRING, "name second port client")
2141  METHOD_ARG_DESCRIBE_IN("port2_name", DBUS_TYPE_STRING_AS_STRING, "name of second port")
2142METHOD_ARGS_END
2143
2144METHOD_ARGS_BEGIN(ConnectPortsByID, "Connect ports")
2145  METHOD_ARG_DESCRIBE_IN("port1_id", DBUS_TYPE_UINT64_AS_STRING, "id of first port")
2146  METHOD_ARG_DESCRIBE_IN("port2_id", DBUS_TYPE_UINT64_AS_STRING, "if of second port")
2147METHOD_ARGS_END
2148
2149METHOD_ARGS_BEGIN(DisconnectPortsByName, "Disconnect ports")
2150  METHOD_ARG_DESCRIBE_IN("client1_name", DBUS_TYPE_STRING_AS_STRING, "name first port client")
2151  METHOD_ARG_DESCRIBE_IN("port1_name", DBUS_TYPE_STRING_AS_STRING, "name of first port")
2152  METHOD_ARG_DESCRIBE_IN("client2_name", DBUS_TYPE_STRING_AS_STRING, "name second port client")
2153  METHOD_ARG_DESCRIBE_IN("port2_name", DBUS_TYPE_STRING_AS_STRING, "name of second port")
2154METHOD_ARGS_END
2155
2156METHOD_ARGS_BEGIN(DisconnectPortsByID, "Disconnect ports")
2157  METHOD_ARG_DESCRIBE_IN("port1_id", DBUS_TYPE_UINT64_AS_STRING, "id of first port")
2158  METHOD_ARG_DESCRIBE_IN("port2_id", DBUS_TYPE_UINT64_AS_STRING, "if of second port")
2159METHOD_ARGS_END
2160
2161METHOD_ARGS_BEGIN(DisconnectPortsByConnectionID, "Disconnect ports")
2162  METHOD_ARG_DESCRIBE_IN("connection_id", DBUS_TYPE_UINT64_AS_STRING, "id of connection to disconnect")
2163METHOD_ARGS_END
2164
2165METHOD_ARGS_BEGIN(GetClientPID, "get process id of client")
2166  METHOD_ARG_DESCRIBE_IN("client_id", DBUS_TYPE_UINT64_AS_STRING, "id of client")
2167  METHOD_ARG_DESCRIBE_OUT("process_id", DBUS_TYPE_INT64_AS_STRING, "pid of client")
2168METHOD_ARGS_END
2169
2170METHODS_BEGIN
2171  METHOD_DESCRIBE(GetAllPorts, get_all_ports)
2172  METHOD_DESCRIBE(GetGraph, get_graph)
2173  METHOD_DESCRIBE(ConnectPortsByName, connect_ports_by_name)
2174  METHOD_DESCRIBE(ConnectPortsByID, connect_ports_by_id)
2175  METHOD_DESCRIBE(DisconnectPortsByName, disconnect_ports_by_name)
2176  METHOD_DESCRIBE(DisconnectPortsByID, disconnect_ports_by_id)
2177  METHOD_DESCRIBE(DisconnectPortsByConnectionID, disconnect_ports_by_connection_id)
2178  METHOD_DESCRIBE(GetClientPID, get_client_pid)
2179METHODS_END
2180
2181SIGNAL_ARGS_BEGIN(GraphChanged, "")
2182  SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
2183SIGNAL_ARGS_END
2184
2185SIGNAL_ARGS_BEGIN(ClientAppeared, "")
2186  SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
2187  SIGNAL_ARG_DESCRIBE("client_id", DBUS_TYPE_UINT64_AS_STRING, "")
2188  SIGNAL_ARG_DESCRIBE("client_name", DBUS_TYPE_STRING_AS_STRING, "")
2189SIGNAL_ARGS_END
2190
2191SIGNAL_ARGS_BEGIN(ClientDisappeared, "")
2192  SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
2193  SIGNAL_ARG_DESCRIBE("client_id", DBUS_TYPE_UINT64_AS_STRING, "")
2194  SIGNAL_ARG_DESCRIBE("client_name", DBUS_TYPE_STRING_AS_STRING, "")
2195SIGNAL_ARGS_END
2196
2197SIGNAL_ARGS_BEGIN(PortAppeared, "")
2198  SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
2199  SIGNAL_ARG_DESCRIBE("client_id", DBUS_TYPE_UINT64_AS_STRING, "")
2200  SIGNAL_ARG_DESCRIBE("client_name", DBUS_TYPE_STRING_AS_STRING, "")
2201  SIGNAL_ARG_DESCRIBE("port_id", DBUS_TYPE_UINT64_AS_STRING, "")
2202  SIGNAL_ARG_DESCRIBE("port_name", DBUS_TYPE_STRING_AS_STRING, "")
2203  SIGNAL_ARG_DESCRIBE("port_flags", DBUS_TYPE_UINT32_AS_STRING, "")
2204  SIGNAL_ARG_DESCRIBE("port_type", DBUS_TYPE_UINT32_AS_STRING, "")
2205SIGNAL_ARGS_END
2206
2207SIGNAL_ARGS_BEGIN(PortDisappeared, "")
2208  SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
2209  SIGNAL_ARG_DESCRIBE("client_id", DBUS_TYPE_UINT64_AS_STRING, "")
2210  SIGNAL_ARG_DESCRIBE("client_name", DBUS_TYPE_STRING_AS_STRING, "")
2211  SIGNAL_ARG_DESCRIBE("port_id", DBUS_TYPE_UINT64_AS_STRING, "")
2212  SIGNAL_ARG_DESCRIBE("port_name", DBUS_TYPE_STRING_AS_STRING, "")
2213SIGNAL_ARGS_END
2214
2215SIGNAL_ARGS_BEGIN(PortsConnected, "")
2216  SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
2217  SIGNAL_ARG_DESCRIBE("client1_id", DBUS_TYPE_UINT64_AS_STRING, "")
2218  SIGNAL_ARG_DESCRIBE("client1_name", DBUS_TYPE_STRING_AS_STRING, "")
2219  SIGNAL_ARG_DESCRIBE("port1_id", DBUS_TYPE_UINT64_AS_STRING, "")
2220  SIGNAL_ARG_DESCRIBE("port1_name", DBUS_TYPE_STRING_AS_STRING, "")
2221  SIGNAL_ARG_DESCRIBE("client2_id", DBUS_TYPE_UINT64_AS_STRING, "")
2222  SIGNAL_ARG_DESCRIBE("client2_name", DBUS_TYPE_STRING_AS_STRING, "")
2223  SIGNAL_ARG_DESCRIBE("port2_id", DBUS_TYPE_UINT64_AS_STRING, "")
2224  SIGNAL_ARG_DESCRIBE("port2_name", DBUS_TYPE_STRING_AS_STRING, "")
2225  SIGNAL_ARG_DESCRIBE("connection_id", DBUS_TYPE_UINT64_AS_STRING, "")
2226SIGNAL_ARGS_END
2227
2228SIGNAL_ARGS_BEGIN(PortsDisconnected, "")
2229  SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
2230  SIGNAL_ARG_DESCRIBE("client1_id", DBUS_TYPE_UINT64_AS_STRING, "")
2231  SIGNAL_ARG_DESCRIBE("client1_name", DBUS_TYPE_STRING_AS_STRING, "")
2232  SIGNAL_ARG_DESCRIBE("port1_id", DBUS_TYPE_UINT64_AS_STRING, "")
2233  SIGNAL_ARG_DESCRIBE("port1_name", DBUS_TYPE_STRING_AS_STRING, "")
2234  SIGNAL_ARG_DESCRIBE("client2_id", DBUS_TYPE_UINT64_AS_STRING, "")
2235  SIGNAL_ARG_DESCRIBE("client2_name", DBUS_TYPE_STRING_AS_STRING, "")
2236  SIGNAL_ARG_DESCRIBE("port2_id", DBUS_TYPE_UINT64_AS_STRING, "")
2237  SIGNAL_ARG_DESCRIBE("port2_name", DBUS_TYPE_STRING_AS_STRING, "")
2238  SIGNAL_ARG_DESCRIBE("connection_id", DBUS_TYPE_UINT64_AS_STRING, "")
2239SIGNAL_ARGS_END
2240
2241SIGNALS_BEGIN
2242  SIGNAL_DESCRIBE(GraphChanged)
2243  SIGNAL_DESCRIBE(ClientAppeared)
2244  SIGNAL_DESCRIBE(ClientDisappeared)
2245  SIGNAL_DESCRIBE(PortAppeared)
2246  SIGNAL_DESCRIBE(PortDisappeared)
2247  SIGNAL_DESCRIBE(PortsConnected)
2248  SIGNAL_DESCRIBE(PortsDisconnected)
2249SIGNALS_END
2250
2251INTERFACE_BEGIN(g_interface_patchbay, JACKDBUS_IFACE_PATCHBAY)
2252  INTERFACE_DEFAULT_HANDLER
2253  INTERFACE_EXPOSE_METHODS
2254  INTERFACE_EXPOSE_SIGNALS
2255INTERFACE_END
Note: See TracBrowser for help on using the browser.