root/daemon/graph.c @ c78c4c64837adcb243297a79121ddff2e683e796

Revision c78c4c64837adcb243297a79121ddff2e683e796, 62.0 KB (checked in by Nedko Arnaudov <nedko@…>, 3 years ago)

daemon: register virtualizer graph connection handlers for rooms

  • 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  log_info("setting connection handlers for graph '%s'", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
970  graph_ptr->context = graph_context;
971  graph_ptr->connect_handler = connect_handler;
972  graph_ptr->disconnect_handler = disconnect_handler;
973}
974
975void ladish_graph_clear(ladish_graph_handle graph_handle)
976{
977  struct ladish_graph_client * client_ptr;
978  struct ladish_graph_connection * connection_ptr;
979
980  log_info("ladish_graph_clear() called for graph '%s'", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
981
982  while (!list_empty(&graph_ptr->connections))
983  {
984    connection_ptr = list_entry(graph_ptr->connections.next, struct ladish_graph_connection, siblings);
985    ladish_graph_remove_connection_internal(graph_ptr, connection_ptr);
986  }
987
988  while (!list_empty(&graph_ptr->clients))
989  {
990    client_ptr = list_entry(graph_ptr->clients.next, struct ladish_graph_client, siblings);
991    ladish_graph_remove_client_internal(graph_ptr, client_ptr, true);
992  }
993}
994
995void * ladish_graph_get_dbus_context(ladish_graph_handle graph_handle)
996{
997  return graph_handle;
998}
999
1000ladish_dict_handle ladish_graph_get_dict(ladish_graph_handle graph_handle)
1001{
1002  return graph_ptr->dict;
1003}
1004
1005void ladish_graph_show_connection(ladish_graph_handle graph_handle, uint64_t connection_id)
1006{
1007  struct ladish_graph_connection * connection_ptr;
1008
1009  log_info("ladish_graph_show_connection() called.");
1010
1011  connection_ptr = ladish_graph_find_connection_by_id(graph_ptr, connection_id);
1012  if (connection_ptr == NULL)
1013  {
1014    ASSERT_NO_PASS;
1015    return;
1016  }
1017
1018  ASSERT(graph_ptr->opath != NULL);
1019  ASSERT(connection_ptr->hidden);
1020  connection_ptr->hidden = false;
1021  connection_ptr->changing = false;
1022  graph_ptr->graph_version++;
1023
1024  dbus_signal_emit(
1025    g_dbus_connection,
1026    graph_ptr->opath,
1027    JACKDBUS_IFACE_PATCHBAY,
1028    "PortsConnected",
1029    "ttstststst",
1030    &graph_ptr->graph_version,
1031    &connection_ptr->port1_ptr->client_ptr->id,
1032    &connection_ptr->port1_ptr->client_ptr->name,
1033    &connection_ptr->port1_ptr->id,
1034    &connection_ptr->port1_ptr->name,
1035    &connection_ptr->port2_ptr->client_ptr->id,
1036    &connection_ptr->port2_ptr->client_ptr->name,
1037    &connection_ptr->port2_ptr->id,
1038    &connection_ptr->port2_ptr->name,
1039    &connection_ptr->id);
1040}
1041
1042void ladish_graph_show_port(ladish_graph_handle graph_handle, ladish_port_handle port_handle)
1043{
1044  struct ladish_graph_port * port_ptr;
1045
1046  //log_info("ladish_graph_show_port() called.");
1047
1048  port_ptr = ladish_graph_find_port(graph_ptr, port_handle);
1049  if (port_ptr == NULL)
1050  {
1051    ASSERT_NO_PASS;
1052    return;
1053  }
1054
1055  //log_info("port '%s' is %s", port_ptr->name, port_ptr->hidden ? "invisible" : "visible");
1056
1057  ladish_graph_show_port_internal(graph_ptr, port_ptr);
1058}
1059
1060void ladish_graph_hide_port(ladish_graph_handle graph_handle, ladish_port_handle port_handle)
1061{
1062  struct ladish_graph_port * port_ptr;
1063
1064  log_info("ladish_graph_hide_port() called.");
1065
1066  port_ptr = ladish_graph_find_port(graph_ptr, port_handle);
1067  if (port_ptr == NULL)
1068  {
1069    ASSERT_NO_PASS;
1070    return;
1071  }
1072
1073  log_info("Hidding port %"PRIu64, port_ptr->id);
1074
1075  ASSERT(!port_ptr->hidden);
1076
1077  if (graph_ptr->opath != NULL)
1078  {
1079    ladish_hide_connections(graph_ptr, port_ptr);
1080  }
1081
1082  ladish_graph_hide_port_internal(graph_ptr, port_ptr);
1083}
1084
1085void ladish_graph_hide_client(ladish_graph_handle graph_handle, ladish_client_handle client_handle)
1086{
1087  struct ladish_graph_client * client_ptr;
1088
1089  log_info("ladish_graph_hide_client() called.");
1090
1091  client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1092  if (client_ptr == NULL)
1093  {
1094    ASSERT_NO_PASS;
1095    return;
1096  }
1097
1098  ladish_graph_hide_client_internal(graph_ptr, client_ptr);
1099}
1100
1101void ladish_graph_show_client(ladish_graph_handle graph_handle, ladish_client_handle client_handle)
1102{
1103  struct ladish_graph_client * client_ptr;
1104
1105  log_info("ladish_graph_show_client() called.");
1106
1107  client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1108  if (client_ptr == NULL)
1109  {
1110    ASSERT_NO_PASS;
1111    return;
1112  }
1113
1114  ASSERT(client_ptr->hidden);
1115  client_ptr->hidden = false;
1116  graph_ptr->graph_version++;
1117
1118  if (graph_ptr->opath != NULL)
1119  {
1120    dbus_signal_emit(
1121      g_dbus_connection,
1122      graph_ptr->opath,
1123      JACKDBUS_IFACE_PATCHBAY,
1124      "ClientAppeared",
1125      "tts",
1126      &graph_ptr->graph_version,
1127      &client_ptr->id,
1128      &client_ptr->name);
1129  }
1130}
1131
1132void ladish_graph_adjust_port(ladish_graph_handle graph_handle, ladish_port_handle port_handle, uint32_t type, uint32_t flags)
1133{
1134  struct ladish_graph_port * port_ptr;
1135
1136  //log_info("ladish_graph_adjust_port() called.");
1137
1138  port_ptr = ladish_graph_find_port(graph_ptr, port_handle);
1139  if (port_ptr == NULL)
1140  {
1141    ASSERT_NO_PASS;
1142    return;
1143  }
1144
1145  port_ptr->type = type;
1146  port_ptr->flags = flags;
1147}
1148
1149bool ladish_graph_add_client(ladish_graph_handle graph_handle, ladish_client_handle client_handle, const char * name, bool hidden)
1150{
1151  struct ladish_graph_client * client_ptr;
1152
1153  log_info("adding client '%s' (%p) to graph %s", name, client_handle, graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
1154
1155  client_ptr = malloc(sizeof(struct ladish_graph_client));
1156  if (client_ptr == NULL)
1157  {
1158    log_error("malloc() failed for struct ladish_graph_client");
1159    return false;
1160  }
1161
1162  client_ptr->name = strdup(name);
1163  if (client_ptr->name == NULL)
1164  {
1165    log_error("strdup() failed for graph client name");
1166    free(client_ptr);
1167    return false;
1168  }
1169
1170  client_ptr->id = graph_ptr->next_client_id++;
1171  client_ptr->client = client_handle;
1172  client_ptr->hidden = hidden;
1173  graph_ptr->graph_version++;
1174
1175  INIT_LIST_HEAD(&client_ptr->ports);
1176
1177  list_add_tail(&client_ptr->siblings, &graph_ptr->clients);
1178
1179  if (!hidden && graph_ptr->opath != NULL)
1180  {
1181    dbus_signal_emit(
1182      g_dbus_connection,
1183      graph_ptr->opath,
1184      JACKDBUS_IFACE_PATCHBAY,
1185      "ClientAppeared",
1186      "tts",
1187      &graph_ptr->graph_version,
1188      &client_ptr->id,
1189      &client_ptr->name);
1190  }
1191
1192  return true;
1193}
1194
1195void
1196ladish_graph_remove_client(
1197  ladish_graph_handle graph_handle,
1198  ladish_client_handle client_handle)
1199{
1200  struct ladish_graph_client * client_ptr;
1201
1202  log_info("ladish_graph_remove_client() called.");
1203
1204  client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1205  if (client_ptr != NULL)
1206  {
1207    ladish_graph_remove_client_internal(graph_ptr, client_ptr, false);
1208  }
1209  else
1210  {
1211    ASSERT_NO_PASS;
1212  }
1213}
1214
1215bool
1216ladish_graph_add_port(
1217  ladish_graph_handle graph_handle,
1218  ladish_client_handle client_handle,
1219  ladish_port_handle port_handle,
1220  const char * name,
1221  uint32_t type,
1222  uint32_t flags,
1223  bool hidden)
1224{
1225  struct ladish_graph_client * client_ptr;
1226  struct ladish_graph_port * port_ptr;
1227
1228  client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1229  if (client_ptr == NULL)
1230  {
1231    log_error("cannot find client to add port to. graph is %s", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
1232    ASSERT_NO_PASS;
1233    return false;
1234  }
1235
1236  log_info("adding port '%s' (%p) to client '%s' in graph %s", name, port_handle, client_ptr->name, graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
1237
1238  port_ptr = malloc(sizeof(struct ladish_graph_port));
1239  if (port_ptr == NULL)
1240  {
1241    log_error("malloc() failed for struct ladish_graph_port");
1242    return false;
1243  }
1244
1245  port_ptr->name = strdup(name);
1246  if (port_ptr->name == NULL)
1247  {
1248    log_error("strdup() failed for graph port name");
1249    free(port_ptr);
1250    return false;
1251  }
1252
1253  port_ptr->type = type;
1254  port_ptr->flags = flags;
1255
1256  port_ptr->id = graph_ptr->next_port_id++;
1257  port_ptr->port = port_handle;
1258  ladish_port_add_ref(port_ptr->port);
1259  port_ptr->hidden = true;
1260
1261  port_ptr->client_ptr = client_ptr;
1262  list_add_tail(&port_ptr->siblings_client, &client_ptr->ports);
1263  list_add_tail(&port_ptr->siblings_graph, &graph_ptr->ports);
1264
1265  if (!hidden)
1266  {
1267    ladish_graph_show_port_internal(graph_ptr, port_ptr);
1268  }
1269
1270  return true;
1271}
1272
1273uint64_t
1274ladish_graph_add_connection(
1275  ladish_graph_handle graph_handle,
1276  ladish_port_handle port1_handle,
1277  ladish_port_handle port2_handle,
1278  bool hidden)
1279{
1280  struct ladish_graph_port * port1_ptr;
1281  struct ladish_graph_port * port2_ptr;
1282  struct ladish_graph_connection * connection_ptr;
1283
1284  port1_ptr = ladish_graph_find_port(graph_ptr, port1_handle);
1285  ASSERT(port1_ptr != NULL);
1286  port2_ptr = ladish_graph_find_port(graph_ptr, port2_handle);
1287  ASSERT(port2_ptr != NULL);
1288
1289  connection_ptr = malloc(sizeof(struct ladish_graph_connection));
1290  if (connection_ptr == NULL)
1291  {
1292    log_error("malloc() failed for struct ladish_graph_connection");
1293    return 0;
1294  }
1295
1296  if (!ladish_dict_create(&connection_ptr->dict))
1297  {
1298    log_error("ladish_dict_create() failed for connection");
1299    free(connection_ptr);
1300    return 0;
1301  }
1302
1303  connection_ptr->id = graph_ptr->next_connection_id++;
1304  connection_ptr->port1_ptr = port1_ptr;
1305  connection_ptr->port2_ptr = port2_ptr;
1306  connection_ptr->hidden = hidden;
1307  connection_ptr->changing = false;
1308  graph_ptr->graph_version++;
1309
1310  list_add_tail(&connection_ptr->siblings, &graph_ptr->connections);
1311
1312  /* log_info( */
1313  /*   "new connection %"PRIu64" between '%s':'%s' and '%s':'%s'", */
1314  /*   connection_ptr->id, */
1315  /*   port1_ptr->client_ptr->name, */
1316  /*   port1_ptr->name, */
1317  /*   port2_ptr->client_ptr->name, */
1318  /*   port2_ptr->name); */
1319
1320  if (!hidden && graph_ptr->opath != NULL)
1321  {
1322    dbus_signal_emit(
1323      g_dbus_connection,
1324      graph_ptr->opath,
1325      JACKDBUS_IFACE_PATCHBAY,
1326      "PortsConnected",
1327      "ttstststst",
1328      &graph_ptr->graph_version,
1329      &port1_ptr->client_ptr->id,
1330      &port1_ptr->client_ptr->name,
1331      &port1_ptr->id,
1332      &port1_ptr->name,
1333      &port2_ptr->client_ptr->id,
1334      &port2_ptr->client_ptr->name,
1335      &port2_ptr->id,
1336      &port2_ptr->name,
1337      &connection_ptr->id);
1338  }
1339
1340  return connection_ptr->id;
1341}
1342
1343void
1344ladish_graph_remove_connection(
1345  ladish_graph_handle graph_handle,
1346  uint64_t connection_id,
1347  bool force)
1348{
1349  struct ladish_graph_connection * connection_ptr;
1350
1351  connection_ptr = ladish_graph_find_connection_by_id(graph_ptr, connection_id);
1352  if (connection_ptr == NULL)
1353  {
1354    ASSERT_NO_PASS;
1355    return;
1356  }
1357
1358  if (force || connection_ptr->changing)
1359  {
1360    /* log_info( */
1361    /*   "removing connection '%s':'%s' - '%s':'%s'", */
1362    /*   connection_ptr->port1_ptr->client_ptr->name, */
1363    /*   connection_ptr->port1_ptr->name, */
1364    /*   connection_ptr->port2_ptr->client_ptr->name, */
1365    /*   connection_ptr->port2_ptr->name); */
1366
1367    ladish_graph_remove_connection_internal(graph_ptr, connection_ptr);
1368  }
1369  else
1370  {
1371    /* log_info( */
1372    /*   "hiding connection '%s':'%s' - '%s':'%s'", */
1373    /*   connection_ptr->port1_ptr->client_ptr->name, */
1374    /*   connection_ptr->port1_ptr->name, */
1375    /*   connection_ptr->port2_ptr->client_ptr->name, */
1376    /*   connection_ptr->port2_ptr->name); */
1377
1378    ladish_graph_hide_connection_internal(graph_ptr, connection_ptr);
1379  }
1380}
1381
1382bool
1383ladish_graph_get_connection_ports(
1384  ladish_graph_handle graph_handle,
1385  uint64_t connection_id,
1386  ladish_port_handle * port1_handle_ptr,
1387  ladish_port_handle * port2_handle_ptr)
1388{
1389  struct ladish_graph_connection * connection_ptr;
1390
1391  connection_ptr = ladish_graph_find_connection_by_id(graph_ptr, connection_id);
1392  if (connection_ptr == NULL)
1393  {
1394    return false;
1395  }
1396
1397  *port1_handle_ptr = connection_ptr->port1_ptr->port;
1398  *port2_handle_ptr = connection_ptr->port2_ptr->port;
1399
1400  return true;
1401}
1402
1403ladish_dict_handle ladish_graph_get_connection_dict(ladish_graph_handle graph_handle, uint64_t connection_id)
1404{
1405  struct ladish_graph_connection * connection_ptr;
1406
1407  connection_ptr = ladish_graph_find_connection_by_id(graph_ptr, connection_id);
1408  if (connection_ptr == NULL)
1409  {
1410    return NULL;
1411  }
1412
1413  return connection_ptr->dict;
1414}
1415
1416bool
1417ladish_graph_find_connection(
1418  ladish_graph_handle graph_handle,
1419  ladish_port_handle port1_handle,
1420  ladish_port_handle port2_handle,
1421  uint64_t * connection_id_ptr)
1422{
1423  struct ladish_graph_port * port1_ptr;
1424  struct ladish_graph_port * port2_ptr;
1425  struct ladish_graph_connection * connection_ptr;
1426
1427  port1_ptr = ladish_graph_find_port(graph_ptr, port1_handle);
1428  if (port1_ptr == NULL)
1429  {
1430    return false;
1431  }
1432     
1433  port2_ptr = ladish_graph_find_port(graph_ptr, port2_handle);
1434  if (port1_ptr == NULL)
1435  {
1436    return false;
1437  }
1438
1439  connection_ptr = ladish_graph_find_connection_by_ports(graph_ptr, port1_ptr, port2_ptr);
1440  if (connection_ptr == NULL)
1441  {
1442    return false;
1443  }
1444
1445  *connection_id_ptr = connection_ptr->id;
1446
1447  return true;
1448}
1449
1450ladish_client_handle ladish_graph_find_client_by_name(ladish_graph_handle graph_handle, const char * name)
1451{
1452  struct list_head * node_ptr;
1453  struct ladish_graph_client * client_ptr;
1454
1455  list_for_each(node_ptr, &graph_ptr->clients)
1456  {
1457    client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
1458    if (strcmp(client_ptr->name, name) == 0)
1459    {
1460      return client_ptr->client;
1461    }
1462  }
1463
1464  return NULL;
1465}
1466
1467ladish_port_handle ladish_graph_find_port_by_name(ladish_graph_handle graph_handle, ladish_client_handle client_handle, const char * name)
1468{
1469  struct ladish_graph_client * client_ptr;
1470  struct list_head * node_ptr;
1471  struct ladish_graph_port * port_ptr;
1472
1473  client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1474  if (client_ptr != NULL)
1475  {
1476    list_for_each(node_ptr, &client_ptr->ports)
1477    {
1478      port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_client);
1479      if (strcmp(port_ptr->name, name) == 0)
1480      {
1481        return port_ptr->port;
1482      }
1483    }
1484  }
1485  else
1486  {
1487    ASSERT_NO_PASS;
1488  }
1489
1490  return NULL;
1491}
1492
1493ladish_client_handle ladish_graph_find_client_by_uuid(ladish_graph_handle graph_handle, const uuid_t uuid)
1494{
1495  struct list_head * node_ptr;
1496  struct ladish_graph_client * client_ptr;
1497  uuid_t current_uuid;
1498
1499  list_for_each(node_ptr, &graph_ptr->clients)
1500  {
1501    client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
1502    ladish_client_get_uuid(client_ptr->client, current_uuid);
1503    if (uuid_compare(current_uuid, uuid) == 0)
1504    {
1505      return client_ptr->client;
1506    }
1507  }
1508
1509  return NULL;
1510}
1511
1512ladish_port_handle ladish_graph_find_port_by_uuid(ladish_graph_handle graph_handle, const uuid_t uuid)
1513{
1514  struct list_head * node_ptr;
1515  struct ladish_graph_port * port_ptr;
1516  uuid_t current_uuid;
1517
1518  list_for_each(node_ptr, &graph_ptr->ports)
1519  {
1520    port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph);
1521    ladish_port_get_uuid(port_ptr->port, current_uuid);
1522    if (uuid_compare(current_uuid, uuid) == 0)
1523    {
1524      return port_ptr->port;
1525    }
1526  }
1527
1528  return NULL;
1529}
1530
1531ladish_client_handle ladish_graph_get_port_client(ladish_graph_handle graph_handle, ladish_port_handle port_handle)
1532{
1533  struct ladish_graph_port * port_ptr;
1534
1535  port_ptr = ladish_graph_find_port(graph_ptr, port_handle);
1536  if (port_ptr == NULL)
1537  {
1538    return NULL;
1539  }
1540
1541  return port_ptr->client_ptr->client;
1542}
1543
1544bool ladish_graph_is_port_present(ladish_graph_handle graph_handle, ladish_port_handle port_handle)
1545{
1546  return ladish_graph_find_port(graph_ptr, port_handle) != NULL;
1547}
1548
1549ladish_client_handle ladish_graph_find_client_by_id(ladish_graph_handle graph_handle, uint64_t client_id)
1550{
1551  struct list_head * node_ptr;
1552  struct ladish_graph_client * client_ptr;
1553
1554  list_for_each(node_ptr, &graph_ptr->clients)
1555  {
1556    client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
1557    if (client_ptr->id == client_id)
1558    {
1559      return client_ptr->client;
1560    }
1561  }
1562
1563  return NULL;
1564}
1565
1566ladish_port_handle ladish_graph_find_port_by_id(ladish_graph_handle graph_handle, uint64_t port_id)
1567{
1568  struct ladish_graph_port * port_ptr;
1569
1570  port_ptr = ladish_graph_find_port_by_id_internal(graph_ptr, port_id);
1571  if (port_ptr == NULL)
1572  {
1573    return NULL;
1574  }
1575
1576  return port_ptr->port;
1577}
1578
1579ladish_client_handle ladish_graph_find_client_by_jack_id(ladish_graph_handle graph_handle, uint64_t client_id)
1580{
1581  struct list_head * node_ptr;
1582  struct ladish_graph_client * client_ptr;
1583
1584  list_for_each(node_ptr, &graph_ptr->clients)
1585  {
1586    client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
1587    if (ladish_client_get_jack_id(client_ptr->client) == client_id)
1588    {
1589      return client_ptr->client;
1590    }
1591  }
1592
1593  return NULL;
1594}
1595
1596ladish_port_handle ladish_graph_find_port_by_jack_id(ladish_graph_handle graph_handle, uint64_t port_id)
1597{
1598  struct list_head * node_ptr;
1599  struct ladish_graph_port * port_ptr;
1600
1601  list_for_each(node_ptr, &graph_ptr->ports)
1602  {
1603    port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph);
1604    if (ladish_port_get_jack_id(port_ptr->port) == port_id)
1605    {
1606      return port_ptr->port;
1607    }
1608  }
1609
1610  return NULL;
1611}
1612
1613ladish_client_handle
1614ladish_graph_remove_port(
1615  ladish_graph_handle graph_handle,
1616  ladish_port_handle port)
1617{
1618  struct ladish_graph_port * port_ptr;
1619
1620  port_ptr = ladish_graph_find_port(graph_ptr, port);
1621  if (port_ptr == NULL)
1622  {
1623    return NULL;
1624  }
1625
1626  ladish_graph_remove_port_internal(graph_ptr, port_ptr->client_ptr, port_ptr);
1627  return port_ptr->client_ptr->client;
1628}
1629
1630bool
1631ladish_graph_rename_client(
1632  ladish_graph_handle graph_handle,
1633  ladish_client_handle client_handle,
1634  const char * new_client_name)
1635{
1636  char * name;
1637  struct ladish_graph_client * client_ptr;
1638  char * old_name;
1639
1640  name = strdup(new_client_name);
1641  if (name == NULL)
1642  {
1643    log_error("strdup('%s') failed.", new_client_name);
1644    return false;
1645  }
1646
1647  client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1648  if (client_ptr == NULL)
1649  {
1650    free(name);
1651    ASSERT_NO_PASS;
1652    return false;
1653  }
1654
1655  old_name = client_ptr->name;
1656  client_ptr->name = name;
1657
1658  graph_ptr->graph_version++;
1659
1660  if (!client_ptr->hidden && graph_ptr->opath != NULL)
1661  {
1662    dbus_signal_emit(
1663      g_dbus_connection,
1664      graph_ptr->opath,
1665      JACKDBUS_IFACE_PATCHBAY,
1666      "ClientRenamed",
1667      "ttss",
1668      &graph_ptr->graph_version,
1669      &client_ptr->id,
1670      &old_name,
1671      &client_ptr->name);
1672  }
1673
1674  free(old_name);
1675
1676  return true;
1677}
1678
1679bool
1680ladish_graph_rename_port(
1681  ladish_graph_handle graph_handle,
1682  ladish_port_handle port_handle,
1683  const char * new_port_name)
1684{
1685  char * name;
1686  struct ladish_graph_port * port_ptr;
1687  char * old_name;
1688
1689  name = strdup(new_port_name);
1690  if (name == NULL)
1691  {
1692    log_error("strdup('%s') failed.", new_port_name);
1693    return false;
1694  }
1695
1696  port_ptr = ladish_graph_find_port(graph_ptr, port_handle);
1697  if (port_ptr == NULL)
1698  {
1699    ASSERT_NO_PASS;
1700    free(name);
1701    return false;
1702  }
1703
1704  old_name = port_ptr->name;
1705  port_ptr->name = name;
1706
1707  graph_ptr->graph_version++;
1708
1709  if (!port_ptr->hidden && graph_ptr->opath != NULL)
1710  {
1711    dbus_signal_emit(
1712      g_dbus_connection,
1713      graph_ptr->opath,
1714      JACKDBUS_IFACE_PATCHBAY,
1715      "PortRenamed",
1716      "ttstss",
1717      &graph_ptr->graph_version,
1718      &port_ptr->client_ptr->id,
1719      &port_ptr->client_ptr->name,
1720      &port_ptr->id,
1721      &old_name,
1722      &port_ptr->name);
1723  }
1724
1725  free(old_name);
1726
1727  return true;
1728}
1729
1730const char * ladish_graph_get_client_name(ladish_graph_handle graph_handle, ladish_client_handle client_handle)
1731{
1732  struct ladish_graph_client * client_ptr;
1733
1734  client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1735  if (client_ptr != NULL)
1736  {
1737      return client_ptr->name;
1738  }
1739
1740  ASSERT_NO_PASS;
1741  return NULL;
1742}
1743
1744bool ladish_graph_is_client_empty(ladish_graph_handle graph_handle, ladish_client_handle client_handle)
1745{
1746  struct ladish_graph_client * client_ptr;
1747
1748  client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1749  if (client_ptr != NULL)
1750  {
1751    return list_empty(&client_ptr->ports);
1752  }
1753
1754  ASSERT_NO_PASS;
1755  return true;
1756}
1757
1758bool ladish_graph_is_client_looks_empty(ladish_graph_handle graph_handle, ladish_client_handle client_handle)
1759{
1760  struct ladish_graph_client * client_ptr;
1761  struct list_head * node_ptr;
1762  struct ladish_graph_port * port_ptr;
1763
1764  client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
1765  if (client_ptr != NULL)
1766  {
1767    list_for_each(node_ptr, &client_ptr->ports)
1768    {
1769      port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_client);
1770      if (!port_ptr->hidden)
1771      {
1772        //log_info("port '%s' is visible, client '%s' does not look empty", port_ptr->name, client_ptr->name);
1773        return false;
1774      }
1775      else
1776      {
1777        //log_info("port '%s' is invisible", port_ptr->name);
1778      }
1779    }
1780
1781    log_info("client '%s' looks empty in graph %s", client_ptr->name, graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
1782    return true;
1783  }
1784
1785  ASSERT_NO_PASS;
1786  return true;
1787}
1788
1789void ladish_try_connect_hidden_connections(ladish_graph_handle graph_handle)
1790{
1791  struct list_head * node_ptr;
1792  struct ladish_graph_connection * connection_ptr;
1793
1794  if (!list_empty(&graph_ptr->connections) && graph_ptr->connect_handler == NULL)
1795  {
1796    ASSERT_NO_PASS;
1797    return;
1798  }
1799
1800  ASSERT(graph_ptr->opath != NULL);
1801
1802  list_for_each(node_ptr, &graph_ptr->connections)
1803  {
1804    connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
1805    if (connection_ptr->hidden &&
1806        !connection_ptr->changing &&
1807        !connection_ptr->port1_ptr->hidden &&
1808        !connection_ptr->port2_ptr->hidden)
1809    {
1810      log_info(
1811        "auto connecting '%s':'%s' to '%s':'%s'",
1812        connection_ptr->port1_ptr->client_ptr->name,
1813        connection_ptr->port1_ptr->name,
1814        connection_ptr->port2_ptr->client_ptr->name,
1815        connection_ptr->port2_ptr->name);
1816
1817      connection_ptr->changing = true;
1818      if (!graph_ptr->connect_handler(graph_ptr->context, graph_handle, connection_ptr->port1_ptr->port, connection_ptr->port2_ptr->port))
1819      {
1820        connection_ptr->changing = false;
1821        log_error("auto connect failed.");
1822      }
1823    }
1824  }
1825}
1826
1827void ladish_graph_hide_all(ladish_graph_handle graph_handle)
1828{
1829  struct list_head * node_ptr;
1830  struct ladish_graph_connection * connection_ptr;
1831  struct ladish_graph_port * port_ptr;
1832  struct ladish_graph_client * client_ptr;
1833
1834  log_info("hiding everything in graph %s", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
1835
1836  list_for_each(node_ptr, &graph_ptr->connections)
1837  {
1838    connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
1839    if (!connection_ptr->hidden)
1840    {
1841      log_debug("hidding connection between ports %"PRIu64" and %"PRIu64, connection_ptr->port1_ptr->id, connection_ptr->port2_ptr->id);
1842      ladish_graph_hide_connection_internal(graph_ptr, connection_ptr);
1843    }
1844  }
1845
1846  list_for_each(node_ptr, &graph_ptr->ports)
1847  {
1848    port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_graph);
1849    if (!port_ptr->hidden)
1850    {
1851      ladish_port_set_jack_id(port_ptr->port, 0);
1852      ladish_graph_hide_port_internal(graph_ptr, port_ptr);
1853    }
1854  }
1855
1856  list_for_each(node_ptr, &graph_ptr->clients)
1857  {
1858    client_ptr = list_entry(node_ptr, struct ladish_graph_client, siblings);
1859    if (!client_ptr->hidden)
1860    {
1861      ladish_client_set_jack_id(client_ptr->client, 0);
1862      ladish_graph_hide_client_internal(graph_ptr, client_ptr);
1863    }
1864  }
1865}
1866
1867bool
1868ladish_graph_iterate_nodes(
1869  ladish_graph_handle graph_handle,
1870  void * callback_context,
1871  bool
1872  (* client_begin_callback)(
1873    void * context,
1874    ladish_client_handle client_handle,
1875    const char * client_name,
1876    void ** client_iteration_context_ptr_ptr),
1877  bool
1878  (* port_callback)(
1879    void * context,
1880    void * client_iteration_context_ptr,
1881    ladish_client_handle client_handle,
1882    const char * client_name,
1883    ladish_port_handle port_handle,
1884    const char * port_name,
1885    uint32_t port_type,
1886    uint32_t port_flags),
1887  bool
1888  (* client_end_callback)(
1889    void * context,
1890    ladish_client_handle client_handle,
1891    const char * client_name,
1892    void * client_iteration_context_ptr))
1893{
1894  struct list_head * client_node_ptr;
1895  struct ladish_graph_client * client_ptr;
1896  void * client_context;
1897  struct list_head * port_node_ptr;
1898  struct ladish_graph_port * port_ptr;
1899
1900  list_for_each(client_node_ptr, &graph_ptr->clients)
1901  {
1902    client_ptr = list_entry(client_node_ptr, struct ladish_graph_client, siblings);
1903
1904    if (client_ptr->hidden)
1905    {
1906      continue;
1907    }
1908
1909    if (client_begin_callback != NULL)
1910    {
1911      if (!client_begin_callback(callback_context, client_ptr->client, client_ptr->name, &client_context))
1912      {
1913        return false;
1914      }
1915    }
1916    else
1917    {
1918      client_context = NULL;
1919    }
1920
1921    if (port_callback == NULL)
1922    {
1923      continue;
1924    }
1925
1926    list_for_each(port_node_ptr, &client_ptr->ports)
1927    {
1928      port_ptr = list_entry(port_node_ptr, struct ladish_graph_port, siblings_client);
1929
1930      if (port_ptr->hidden)
1931      {
1932        continue;
1933      }
1934
1935      if (!port_callback(
1936            callback_context,
1937            client_context,
1938            client_ptr->client,
1939            client_ptr->name,
1940            port_ptr->port,
1941            port_ptr->name,
1942            port_ptr->type,
1943            port_ptr->flags))
1944      {
1945        return false;
1946      }
1947    }
1948
1949    if (client_end_callback != NULL)
1950    {
1951      if (!client_end_callback(callback_context, client_ptr->client, client_ptr->name, &client_context))
1952      {
1953        return false;
1954      }
1955    }
1956  }
1957
1958  return true;
1959}
1960
1961bool
1962ladish_graph_iterate_connections(
1963  ladish_graph_handle graph_handle,
1964  void * callback_context,
1965  bool (* callback)(void * context, ladish_port_handle port1_handle, ladish_port_handle port2_handle, ladish_dict_handle dict))
1966{
1967  struct list_head * node_ptr;
1968  struct ladish_graph_connection * connection_ptr;
1969
1970  list_for_each(node_ptr, &graph_ptr->connections)
1971  {
1972    connection_ptr = list_entry(node_ptr, struct ladish_graph_connection, siblings);
1973
1974    if (connection_ptr->hidden)
1975    {
1976      continue;
1977    }
1978
1979    if (!callback(callback_context, connection_ptr->port1_ptr->port, connection_ptr->port2_ptr->port, connection_ptr->dict))
1980    {
1981      return false;
1982    }
1983  }
1984
1985  return true;
1986}
1987
1988static
1989bool
1990dump_dict_entry(
1991  void * context,
1992  const char * key,
1993  const char * value)
1994{
1995  log_info("%s  key '%s' with value '%s'", (const char *)context, key, value);
1996  return true;
1997}
1998
1999static
2000void
2001dump_dict(
2002  const char * indent,
2003  ladish_dict_handle dict)
2004{
2005  if (ladish_dict_is_empty(dict))
2006  {
2007    return;
2008  }
2009
2010  log_info("%sdict:", indent);
2011  ladish_dict_iterate(dict, (void *)indent, dump_dict_entry);
2012}
2013
2014void ladish_graph_dump(ladish_graph_handle graph_handle)
2015{
2016  struct list_head * client_node_ptr;
2017  struct ladish_graph_client * client_ptr;
2018  struct list_head * port_node_ptr;
2019  struct ladish_graph_port * port_ptr;
2020  struct list_head * connection_node_ptr;
2021  struct ladish_graph_connection * connection_ptr;
2022
2023  log_info("graph %s", graph_ptr->opath != NULL ? graph_ptr->opath : "JACK");
2024  log_info("  version %"PRIu64, graph_ptr->graph_version);
2025  dump_dict("  ", graph_ptr->dict);
2026  log_info("  clients:");
2027  list_for_each(client_node_ptr, &graph_ptr->clients)
2028  {
2029    client_ptr = list_entry(client_node_ptr, struct ladish_graph_client, siblings);
2030    log_info("    %s client '%s', id=%"PRIu64", ptr=%p", client_ptr->hidden ? "invisible" : "visible", client_ptr->name, client_ptr->id, client_ptr->client);
2031    dump_dict("      ", ladish_client_get_dict(client_ptr->client));
2032    log_info("      ports:");
2033    list_for_each(port_node_ptr, &client_ptr->ports)
2034    {
2035      port_ptr = list_entry(port_node_ptr, struct ladish_graph_port, siblings_client);
2036
2037      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);
2038      dump_dict("        ", ladish_port_get_dict(port_ptr->port));
2039    }
2040  }
2041  log_info("  connections:");
2042  list_for_each(connection_node_ptr, &graph_ptr->connections)
2043  {
2044    connection_ptr = list_entry(connection_node_ptr, struct ladish_graph_connection, siblings);
2045
2046    log_info(
2047      "    %s connection '%s':'%s' - '%s':'%s'%s",
2048      connection_ptr->hidden ? "invisible" : "visible",
2049      connection_ptr->port1_ptr->client_ptr->name,
2050      connection_ptr->port1_ptr->name,
2051      connection_ptr->port2_ptr->client_ptr->name,
2052      connection_ptr->port2_ptr->name,
2053      connection_ptr->changing ? " [changing]" : "");
2054    dump_dict("      ", connection_ptr->dict);
2055  }
2056}
2057
2058#undef graph_ptr
2059#define graph_ptr ((struct ladish_graph *)context)
2060
2061static
2062bool
2063ladish_graph_copy_client_begin_callback(
2064  void * context,
2065  ladish_client_handle client_handle,
2066  const char * client_name,
2067  void ** client_iteration_context_ptr_ptr)
2068{
2069  ladish_client_handle copy;
2070
2071  if (!ladish_client_create_copy(client_handle, &copy))
2072  {
2073    return false;
2074  }
2075
2076  if (!ladish_graph_add_client(context, copy, client_name, false))
2077  {
2078    ladish_client_destroy(copy);
2079    return false;
2080  }
2081
2082  *client_iteration_context_ptr_ptr = copy;
2083
2084  return true;
2085}
2086
2087static
2088bool
2089ladish_graph_copy_port_callback(
2090  void * context,
2091  void * client_iteration_context_ptr,
2092  ladish_client_handle client_handle,
2093  const char * client_name,
2094  ladish_port_handle port_handle,
2095  const char * port_name,
2096  uint32_t port_type,
2097  uint32_t port_flags)
2098{
2099  ladish_port_handle copy;
2100
2101  if (!ladish_port_create_copy(port_handle, &copy))
2102  {
2103    return false;
2104  }
2105
2106  if (!ladish_graph_add_port(context, client_iteration_context_ptr, copy, port_name, port_type, port_flags, false))
2107  {
2108    ladish_port_destroy(copy);
2109    return false;
2110  }
2111
2112  return true;
2113}
2114
2115#undef graph_ptr
2116
2117bool ladish_graph_copy(ladish_graph_handle src, ladish_graph_handle dest)
2118{
2119  return ladish_graph_iterate_nodes(
2120    src,
2121    dest,
2122    ladish_graph_copy_client_begin_callback,
2123    ladish_graph_copy_port_callback,
2124    NULL);
2125}
2126
2127METHOD_ARGS_BEGIN(GetAllPorts, "Get all ports")
2128  METHOD_ARG_DESCRIBE_IN("ports_list", "as", "List of all ports")
2129METHOD_ARGS_END
2130
2131METHOD_ARGS_BEGIN(GetGraph, "Get whole graph")
2132METHOD_ARG_DESCRIBE_IN("known_graph_version", DBUS_TYPE_UINT64_AS_STRING, "Known graph version")
2133  METHOD_ARG_DESCRIBE_OUT("current_graph_version", DBUS_TYPE_UINT64_AS_STRING, "Current graph version")
2134  METHOD_ARG_DESCRIBE_OUT("clients_and_ports", "a(tsa(tsuu))", "Clients and their ports")
2135  METHOD_ARG_DESCRIBE_OUT("connections", "a(tstststst)", "Connections array")
2136METHOD_ARGS_END
2137
2138METHOD_ARGS_BEGIN(ConnectPortsByName, "Connect ports")
2139  METHOD_ARG_DESCRIBE_IN("client1_name", DBUS_TYPE_STRING_AS_STRING, "name first port client")
2140  METHOD_ARG_DESCRIBE_IN("port1_name", DBUS_TYPE_STRING_AS_STRING, "name of first port")
2141  METHOD_ARG_DESCRIBE_IN("client2_name", DBUS_TYPE_STRING_AS_STRING, "name second port client")
2142  METHOD_ARG_DESCRIBE_IN("port2_name", DBUS_TYPE_STRING_AS_STRING, "name of second port")
2143METHOD_ARGS_END
2144
2145METHOD_ARGS_BEGIN(ConnectPortsByID, "Connect ports")
2146  METHOD_ARG_DESCRIBE_IN("port1_id", DBUS_TYPE_UINT64_AS_STRING, "id of first port")
2147  METHOD_ARG_DESCRIBE_IN("port2_id", DBUS_TYPE_UINT64_AS_STRING, "if of second port")
2148METHOD_ARGS_END
2149
2150METHOD_ARGS_BEGIN(DisconnectPortsByName, "Disconnect ports")
2151  METHOD_ARG_DESCRIBE_IN("client1_name", DBUS_TYPE_STRING_AS_STRING, "name first port client")
2152  METHOD_ARG_DESCRIBE_IN("port1_name", DBUS_TYPE_STRING_AS_STRING, "name of first port")
2153  METHOD_ARG_DESCRIBE_IN("client2_name", DBUS_TYPE_STRING_AS_STRING, "name second port client")
2154  METHOD_ARG_DESCRIBE_IN("port2_name", DBUS_TYPE_STRING_AS_STRING, "name of second port")
2155METHOD_ARGS_END
2156
2157METHOD_ARGS_BEGIN(DisconnectPortsByID, "Disconnect ports")
2158  METHOD_ARG_DESCRIBE_IN("port1_id", DBUS_TYPE_UINT64_AS_STRING, "id of first port")
2159  METHOD_ARG_DESCRIBE_IN("port2_id", DBUS_TYPE_UINT64_AS_STRING, "if of second port")
2160METHOD_ARGS_END
2161
2162METHOD_ARGS_BEGIN(DisconnectPortsByConnectionID, "Disconnect ports")
2163  METHOD_ARG_DESCRIBE_IN("connection_id", DBUS_TYPE_UINT64_AS_STRING, "id of connection to disconnect")
2164METHOD_ARGS_END
2165
2166METHOD_ARGS_BEGIN(GetClientPID, "get process id of client")
2167  METHOD_ARG_DESCRIBE_IN("client_id", DBUS_TYPE_UINT64_AS_STRING, "id of client")
2168  METHOD_ARG_DESCRIBE_OUT("process_id", DBUS_TYPE_INT64_AS_STRING, "pid of client")
2169METHOD_ARGS_END
2170
2171METHODS_BEGIN
2172  METHOD_DESCRIBE(GetAllPorts, get_all_ports)
2173  METHOD_DESCRIBE(GetGraph, get_graph)
2174  METHOD_DESCRIBE(ConnectPortsByName, connect_ports_by_name)
2175  METHOD_DESCRIBE(ConnectPortsByID, connect_ports_by_id)
2176  METHOD_DESCRIBE(DisconnectPortsByName, disconnect_ports_by_name)
2177  METHOD_DESCRIBE(DisconnectPortsByID, disconnect_ports_by_id)
2178  METHOD_DESCRIBE(DisconnectPortsByConnectionID, disconnect_ports_by_connection_id)
2179  METHOD_DESCRIBE(GetClientPID, get_client_pid)
2180METHODS_END
2181
2182SIGNAL_ARGS_BEGIN(GraphChanged, "")
2183  SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
2184SIGNAL_ARGS_END
2185
2186SIGNAL_ARGS_BEGIN(ClientAppeared, "")
2187  SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
2188  SIGNAL_ARG_DESCRIBE("client_id", DBUS_TYPE_UINT64_AS_STRING, "")
2189  SIGNAL_ARG_DESCRIBE("client_name", DBUS_TYPE_STRING_AS_STRING, "")
2190SIGNAL_ARGS_END
2191
2192SIGNAL_ARGS_BEGIN(ClientDisappeared, "")
2193  SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
2194  SIGNAL_ARG_DESCRIBE("client_id", DBUS_TYPE_UINT64_AS_STRING, "")
2195  SIGNAL_ARG_DESCRIBE("client_name", DBUS_TYPE_STRING_AS_STRING, "")
2196SIGNAL_ARGS_END
2197
2198SIGNAL_ARGS_BEGIN(PortAppeared, "")
2199  SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
2200  SIGNAL_ARG_DESCRIBE("client_id", DBUS_TYPE_UINT64_AS_STRING, "")
2201  SIGNAL_ARG_DESCRIBE("client_name", DBUS_TYPE_STRING_AS_STRING, "")
2202  SIGNAL_ARG_DESCRIBE("port_id", DBUS_TYPE_UINT64_AS_STRING, "")
2203  SIGNAL_ARG_DESCRIBE("port_name", DBUS_TYPE_STRING_AS_STRING, "")
2204  SIGNAL_ARG_DESCRIBE("port_flags", DBUS_TYPE_UINT32_AS_STRING, "")
2205  SIGNAL_ARG_DESCRIBE("port_type", DBUS_TYPE_UINT32_AS_STRING, "")
2206SIGNAL_ARGS_END
2207
2208SIGNAL_ARGS_BEGIN(PortDisappeared, "")
2209  SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
2210  SIGNAL_ARG_DESCRIBE("client_id", DBUS_TYPE_UINT64_AS_STRING, "")
2211  SIGNAL_ARG_DESCRIBE("client_name", DBUS_TYPE_STRING_AS_STRING, "")
2212  SIGNAL_ARG_DESCRIBE("port_id", DBUS_TYPE_UINT64_AS_STRING, "")
2213  SIGNAL_ARG_DESCRIBE("port_name", DBUS_TYPE_STRING_AS_STRING, "")
2214SIGNAL_ARGS_END
2215
2216SIGNAL_ARGS_BEGIN(PortsConnected, "")
2217  SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
2218  SIGNAL_ARG_DESCRIBE("client1_id", DBUS_TYPE_UINT64_AS_STRING, "")
2219  SIGNAL_ARG_DESCRIBE("client1_name", DBUS_TYPE_STRING_AS_STRING, "")
2220  SIGNAL_ARG_DESCRIBE("port1_id", DBUS_TYPE_UINT64_AS_STRING, "")
2221  SIGNAL_ARG_DESCRIBE("port1_name", DBUS_TYPE_STRING_AS_STRING, "")
2222  SIGNAL_ARG_DESCRIBE("client2_id", DBUS_TYPE_UINT64_AS_STRING, "")
2223  SIGNAL_ARG_DESCRIBE("client2_name", DBUS_TYPE_STRING_AS_STRING, "")
2224  SIGNAL_ARG_DESCRIBE("port2_id", DBUS_TYPE_UINT64_AS_STRING, "")
2225  SIGNAL_ARG_DESCRIBE("port2_name", DBUS_TYPE_STRING_AS_STRING, "")
2226  SIGNAL_ARG_DESCRIBE("connection_id", DBUS_TYPE_UINT64_AS_STRING, "")
2227SIGNAL_ARGS_END
2228
2229SIGNAL_ARGS_BEGIN(PortsDisconnected, "")
2230  SIGNAL_ARG_DESCRIBE("new_graph_version", DBUS_TYPE_UINT64_AS_STRING, "")
2231  SIGNAL_ARG_DESCRIBE("client1_id", DBUS_TYPE_UINT64_AS_STRING, "")
2232  SIGNAL_ARG_DESCRIBE("client1_name", DBUS_TYPE_STRING_AS_STRING, "")
2233  SIGNAL_ARG_DESCRIBE("port1_id", DBUS_TYPE_UINT64_AS_STRING, "")
2234  SIGNAL_ARG_DESCRIBE("port1_name", DBUS_TYPE_STRING_AS_STRING, "")
2235  SIGNAL_ARG_DESCRIBE("client2_id", DBUS_TYPE_UINT64_AS_STRING, "")
2236  SIGNAL_ARG_DESCRIBE("client2_name", DBUS_TYPE_STRING_AS_STRING, "")
2237  SIGNAL_ARG_DESCRIBE("port2_id", DBUS_TYPE_UINT64_AS_STRING, "")
2238  SIGNAL_ARG_DESCRIBE("port2_name", DBUS_TYPE_STRING_AS_STRING, "")
2239  SIGNAL_ARG_DESCRIBE("connection_id", DBUS_TYPE_UINT64_AS_STRING, "")
2240SIGNAL_ARGS_END
2241
2242SIGNALS_BEGIN
2243  SIGNAL_DESCRIBE(GraphChanged)
2244  SIGNAL_DESCRIBE(ClientAppeared)
2245  SIGNAL_DESCRIBE(ClientDisappeared)
2246  SIGNAL_DESCRIBE(PortAppeared)
2247  SIGNAL_DESCRIBE(PortDisappeared)
2248  SIGNAL_DESCRIBE(PortsConnected)
2249  SIGNAL_DESCRIBE(PortsDisconnected)
2250SIGNALS_END
2251
2252INTERFACE_BEGIN(g_interface_patchbay, JACKDBUS_IFACE_PATCHBAY)
2253  INTERFACE_DEFAULT_HANDLER
2254  INTERFACE_EXPOSE_METHODS
2255  INTERFACE_EXPOSE_SIGNALS
2256INTERFACE_END
Note: See TracBrowser for help on using the browser.