Compiles on Windows again.
[jack2.git] / dbus / controller_iface_patchbay.c
blob9adb7cfafb3a44e6c8dd681ab2eacd276c3bbe99
1 /* -*- Mode: C ; c-basic-offset: 4 -*- */
2 /*
3 Copyright (C) 2008 Nedko Arnaudov
4 Copyright (C) 2008 Juuso Alasuutari
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #if defined(HAVE_CONFIG_H)
22 #include "config.h"
23 #endif
25 #define _GNU_SOURCE /* PTHREAD_MUTEX_RECURSIVE */
27 #include <stdint.h>
28 #include <inttypes.h>
29 #include <string.h>
30 #include <stdio.h>
31 #include <assert.h>
32 #include <dbus/dbus.h>
33 #include <pthread.h>
35 #include "jackdbus.h"
36 #include "controller_internal.h"
37 #include "list.h"
39 #define JACK_DBUS_IFACE_NAME "org.jackaudio.JackPatchbay"
41 /* FIXME: these need to be retrieved from common headers */
42 #define JACK_CLIENT_NAME_SIZE 64
43 #define JACK_PORT_NAME_SIZE 256
45 struct jack_graph
47 uint64_t version;
48 struct list_head clients;
49 struct list_head ports;
50 struct list_head connections;
53 struct jack_graph_client
55 uint64_t id;
56 char * name;
57 int pid;
58 struct list_head siblings;
59 struct list_head ports;
62 struct jack_graph_port
64 uint64_t id;
65 char * name;
66 uint32_t flags;
67 uint32_t type;
68 struct list_head siblings_graph;
69 struct list_head siblings_client;
70 struct jack_graph_client * client;
73 struct jack_graph_connection
75 uint64_t id;
76 struct jack_graph_port * port1;
77 struct jack_graph_port * port2;
78 struct list_head siblings;
81 struct jack_controller_patchbay
83 pthread_mutex_t lock;
84 struct jack_graph graph;
85 uint64_t next_client_id;
86 uint64_t next_port_id;
87 uint64_t next_connection_id;
90 void
91 jack_controller_patchbay_send_signal_graph_changed(
92 dbus_uint64_t new_graph_version)
95 jack_dbus_send_signal(
96 JACK_CONTROLLER_OBJECT_PATH,
97 JACK_DBUS_IFACE_NAME,
98 "GraphChanged",
99 DBUS_TYPE_UINT64,
100 &new_graph_version,
101 DBUS_TYPE_INVALID);
104 void
105 jack_controller_patchbay_send_signal_client_appeared(
106 dbus_uint64_t new_graph_version,
107 dbus_uint64_t client_id,
108 const char * client_name)
111 jack_dbus_send_signal(
112 JACK_CONTROLLER_OBJECT_PATH,
113 JACK_DBUS_IFACE_NAME,
114 "ClientAppeared",
115 DBUS_TYPE_UINT64,
116 &new_graph_version,
117 DBUS_TYPE_UINT64,
118 &client_id,
119 DBUS_TYPE_STRING,
120 &client_name,
121 DBUS_TYPE_INVALID);
124 void
125 jack_controller_patchbay_send_signal_client_disappeared(
126 dbus_uint64_t new_graph_version,
127 dbus_uint64_t client_id,
128 const char * client_name)
131 jack_dbus_send_signal(
132 JACK_CONTROLLER_OBJECT_PATH,
133 JACK_DBUS_IFACE_NAME,
134 "ClientDisappeared",
135 DBUS_TYPE_UINT64,
136 &new_graph_version,
137 DBUS_TYPE_UINT64,
138 &client_id,
139 DBUS_TYPE_STRING,
140 &client_name,
141 DBUS_TYPE_INVALID);
144 void
145 jack_controller_patchbay_send_signal_port_appeared(
146 dbus_uint64_t new_graph_version,
147 dbus_uint64_t client_id,
148 const char * client_name,
149 dbus_uint64_t port_id,
150 const char * port_name,
151 dbus_uint32_t port_flags,
152 dbus_uint32_t port_type)
155 jack_dbus_send_signal(
156 JACK_CONTROLLER_OBJECT_PATH,
157 JACK_DBUS_IFACE_NAME,
158 "PortAppeared",
159 DBUS_TYPE_UINT64,
160 &new_graph_version,
161 DBUS_TYPE_UINT64,
162 &client_id,
163 DBUS_TYPE_STRING,
164 &client_name,
165 DBUS_TYPE_UINT64,
166 &port_id,
167 DBUS_TYPE_STRING,
168 &port_name,
169 DBUS_TYPE_UINT32,
170 &port_flags,
171 DBUS_TYPE_UINT32,
172 &port_type,
173 DBUS_TYPE_INVALID);
176 void
177 jack_controller_patchbay_send_signal_port_disappeared(
178 dbus_uint64_t new_graph_version,
179 dbus_uint64_t client_id,
180 const char * client_name,
181 dbus_uint64_t port_id,
182 const char * port_name)
185 jack_dbus_send_signal(
186 JACK_CONTROLLER_OBJECT_PATH,
187 JACK_DBUS_IFACE_NAME,
188 "PortDisappeared",
189 DBUS_TYPE_UINT64,
190 &new_graph_version,
191 DBUS_TYPE_UINT64,
192 &client_id,
193 DBUS_TYPE_STRING,
194 &client_name,
195 DBUS_TYPE_UINT64,
196 &port_id,
197 DBUS_TYPE_STRING,
198 &port_name,
199 DBUS_TYPE_INVALID);
202 void
203 jack_controller_patchbay_send_signal_ports_connected(
204 dbus_uint64_t new_graph_version,
205 dbus_uint64_t client1_id,
206 const char * client1_name,
207 dbus_uint64_t port1_id,
208 const char * port1_name,
209 dbus_uint64_t client2_id,
210 const char * client2_name,
211 dbus_uint64_t port2_id,
212 const char * port2_name,
213 dbus_uint64_t connection_id)
216 jack_dbus_send_signal(
217 JACK_CONTROLLER_OBJECT_PATH,
218 JACK_DBUS_IFACE_NAME,
219 "PortsConnected",
220 DBUS_TYPE_UINT64,
221 &new_graph_version,
222 DBUS_TYPE_UINT64,
223 &client1_id,
224 DBUS_TYPE_STRING,
225 &client1_name,
226 DBUS_TYPE_UINT64,
227 &port1_id,
228 DBUS_TYPE_STRING,
229 &port1_name,
230 DBUS_TYPE_UINT64,
231 &client2_id,
232 DBUS_TYPE_STRING,
233 &client2_name,
234 DBUS_TYPE_UINT64,
235 &port2_id,
236 DBUS_TYPE_STRING,
237 &port2_name,
238 DBUS_TYPE_UINT64,
239 &connection_id,
240 DBUS_TYPE_INVALID);
243 void
244 jack_controller_patchbay_send_signal_ports_disconnected(
245 dbus_uint64_t new_graph_version,
246 dbus_uint64_t client1_id,
247 const char * client1_name,
248 dbus_uint64_t port1_id,
249 const char * port1_name,
250 dbus_uint64_t client2_id,
251 const char * client2_name,
252 dbus_uint64_t port2_id,
253 const char * port2_name,
254 dbus_uint64_t connection_id)
257 jack_dbus_send_signal(
258 JACK_CONTROLLER_OBJECT_PATH,
259 JACK_DBUS_IFACE_NAME,
260 "PortsDisconnected",
261 DBUS_TYPE_UINT64,
262 &new_graph_version,
263 DBUS_TYPE_UINT64,
264 &client1_id,
265 DBUS_TYPE_STRING,
266 &client1_name,
267 DBUS_TYPE_UINT64,
268 &port1_id,
269 DBUS_TYPE_STRING,
270 &port1_name,
271 DBUS_TYPE_UINT64,
272 &client2_id,
273 DBUS_TYPE_STRING,
274 &client2_name,
275 DBUS_TYPE_UINT64,
276 &port2_id,
277 DBUS_TYPE_STRING,
278 &port2_name,
279 DBUS_TYPE_UINT64,
280 &connection_id,
281 DBUS_TYPE_INVALID);
284 static
285 struct jack_graph_client *
286 jack_controller_patchbay_find_client(
287 struct jack_controller_patchbay *patchbay_ptr,
288 const char *client_name, /* not '\0' terminated */
289 size_t client_name_len) /* without terminating '\0' */
291 struct list_head *node_ptr;
292 struct jack_graph_client *client_ptr;
294 list_for_each(node_ptr, &patchbay_ptr->graph.clients)
296 client_ptr = list_entry(node_ptr, struct jack_graph_client, siblings);
297 if (strncmp(client_ptr->name, client_name, client_name_len) == 0)
299 return client_ptr;
303 return NULL;
306 static
307 struct jack_graph_client *
308 jack_controller_patchbay_find_client_by_id(
309 struct jack_controller_patchbay *patchbay_ptr,
310 uint64_t id)
312 struct list_head *node_ptr;
313 struct jack_graph_client *client_ptr;
315 list_for_each(node_ptr, &patchbay_ptr->graph.clients)
317 client_ptr = list_entry(node_ptr, struct jack_graph_client, siblings);
318 if (client_ptr->id == id)
320 return client_ptr;
324 return NULL;
327 static
328 struct jack_graph_client *
329 jack_controller_patchbay_create_client(
330 struct jack_controller_patchbay *patchbay_ptr,
331 const char *client_name, /* not '\0' terminated */
332 size_t client_name_len) /* without terminating '\0' */
334 struct jack_graph_client * client_ptr;
336 client_ptr = malloc(sizeof(struct jack_graph_client));
337 if (client_ptr == NULL)
339 jack_error("Memory allocation of jack_graph_client structure failed.");
340 goto fail;
343 client_ptr->name = malloc(client_name_len + 1);
344 if (client_ptr->name == NULL)
346 jack_error("malloc() failed to allocate memory for client name.");
347 goto fail_free_client;
350 memcpy(client_ptr->name, client_name, client_name_len);
351 client_ptr->name[client_name_len] = 0;
353 client_ptr->pid = jack_get_client_pid(client_ptr->name);
354 jack_info("New client '%s' with PID %d", client_ptr->name, client_ptr->pid);
356 client_ptr->id = patchbay_ptr->next_client_id++;
357 INIT_LIST_HEAD(&client_ptr->ports);
360 pthread_mutex_lock(&patchbay_ptr->lock);
361 list_add_tail(&client_ptr->siblings, &patchbay_ptr->graph.clients);
362 patchbay_ptr->graph.version++;
363 jack_controller_patchbay_send_signal_client_appeared(patchbay_ptr->graph.version, client_ptr->id, client_ptr->name);
364 jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version);
365 pthread_mutex_unlock(&patchbay_ptr->lock);
367 return client_ptr;
369 fail_free_client:
370 free(client_ptr);
372 fail:
373 return NULL;
376 static
377 void
378 jack_controller_patchbay_destroy_client(
379 struct jack_controller_patchbay *patchbay_ptr,
380 struct jack_graph_client *client_ptr)
382 jack_info("Client '%s' with PID %d is out", client_ptr->name, client_ptr->pid);
384 pthread_mutex_lock(&patchbay_ptr->lock);
385 list_del(&client_ptr->siblings);
386 patchbay_ptr->graph.version++;
387 jack_controller_patchbay_send_signal_client_disappeared(patchbay_ptr->graph.version, client_ptr->id, client_ptr->name);
388 jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version);
389 pthread_mutex_unlock(&patchbay_ptr->lock);
391 free(client_ptr->name);
392 free(client_ptr);
395 static
396 void
397 jack_controller_patchbay_destroy_client_by_name(
398 struct jack_controller_patchbay *patchbay_ptr,
399 const char *client_name) /* '\0' terminated */
401 struct jack_graph_client *client_ptr;
403 client_ptr = jack_controller_patchbay_find_client(patchbay_ptr, client_name, strlen(client_name));
404 if (client_ptr == NULL)
406 jack_error("Cannot destroy unknown client '%s'", client_name);
407 return;
410 jack_controller_patchbay_destroy_client(patchbay_ptr, client_ptr);
413 static
414 void
415 jack_controller_patchbay_new_port(
416 struct jack_controller_patchbay *patchbay_ptr,
417 const char *port_full_name,
418 uint32_t port_flags,
419 uint32_t port_type)
421 struct jack_graph_client *client_ptr;
422 struct jack_graph_port *port_ptr;
423 const char *port_short_name;
424 size_t client_name_len;
426 //jack_info("new port: %s", port_full_name);
428 port_short_name = strchr(port_full_name, ':');
429 if (port_short_name == NULL)
431 jack_error("port name '%s' does not contain ':' separator char", port_full_name);
432 return;
435 port_short_name++; /* skip ':' separator char */
437 client_name_len = port_short_name - port_full_name - 1; /* without terminating '\0' */
439 client_ptr = jack_controller_patchbay_find_client(patchbay_ptr, port_full_name, client_name_len);
440 if (client_ptr == NULL)
442 client_ptr = jack_controller_patchbay_create_client(patchbay_ptr, port_full_name, client_name_len);
443 if (client_ptr == NULL)
445 jack_error("Creation of new jack_graph client failed.");
446 return;
450 port_ptr = malloc(sizeof(struct jack_graph_port));
451 if (port_ptr == NULL)
453 jack_error("Memory allocation of jack_graph_port structure failed.");
454 return;
457 port_ptr->name = strdup(port_short_name);
458 if (port_ptr->name == NULL)
460 jack_error("strdup() call for port name '%s' failed.", port_short_name);
461 free(port_ptr);
462 return;
465 port_ptr->id = patchbay_ptr->next_port_id++;
466 port_ptr->flags = port_flags;
467 port_ptr->type = port_type;
468 port_ptr->client = client_ptr;
470 pthread_mutex_lock(&patchbay_ptr->lock);
471 list_add_tail(&port_ptr->siblings_client, &client_ptr->ports);
472 list_add_tail(&port_ptr->siblings_graph, &patchbay_ptr->graph.ports);
473 patchbay_ptr->graph.version++;
474 jack_controller_patchbay_send_signal_port_appeared(
475 patchbay_ptr->graph.version,
476 client_ptr->id,
477 client_ptr->name,
478 port_ptr->id,
479 port_ptr->name,
480 port_ptr->flags,
481 port_ptr->type);
482 jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version);
483 pthread_mutex_unlock(&patchbay_ptr->lock);
486 static
487 void
488 jack_controller_patchbay_remove_port(
489 struct jack_controller_patchbay *patchbay_ptr,
490 struct jack_graph_port *port_ptr)
492 //jack_info("remove port: %s", port_ptr->name);
494 pthread_mutex_lock(&patchbay_ptr->lock);
495 list_del(&port_ptr->siblings_client);
496 list_del(&port_ptr->siblings_graph);
497 patchbay_ptr->graph.version++;
498 jack_controller_patchbay_send_signal_port_disappeared(patchbay_ptr->graph.version, port_ptr->client->id, port_ptr->client->name, port_ptr->id, port_ptr->name);
499 jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version);
500 pthread_mutex_unlock(&patchbay_ptr->lock);
502 free(port_ptr->name);
503 free(port_ptr);
506 static
507 struct jack_graph_port *
508 jack_controller_patchbay_find_port_by_id(
509 struct jack_controller_patchbay *patchbay_ptr,
510 uint64_t port_id)
512 struct list_head *node_ptr;
513 struct jack_graph_port *port_ptr;
515 list_for_each(node_ptr, &patchbay_ptr->graph.ports)
517 port_ptr = list_entry(node_ptr, struct jack_graph_port, siblings_graph);
518 if (port_ptr->id == port_id)
520 return port_ptr;
524 return NULL;
527 static
528 struct jack_graph_port *
529 jack_controller_patchbay_find_client_port_by_name(
530 struct jack_controller_patchbay *patchbay_ptr,
531 struct jack_graph_client *client_ptr,
532 const char *port_name)
534 struct list_head *node_ptr;
535 struct jack_graph_port *port_ptr;
537 list_for_each(node_ptr, &client_ptr->ports)
539 port_ptr = list_entry(node_ptr, struct jack_graph_port, siblings_client);
540 if (strcmp(port_ptr->name, port_name) == 0)
542 return port_ptr;
546 return NULL;
549 static
550 struct jack_graph_port *
551 jack_controller_patchbay_find_port_by_full_name(
552 struct jack_controller_patchbay *patchbay_ptr,
553 const char *port_full_name)
555 const char *port_short_name;
556 size_t client_name_len;
557 struct jack_graph_client *client_ptr;
559 //jack_info("name: %s", port_full_name);
561 port_short_name = strchr(port_full_name, ':');
562 if (port_short_name == NULL)
564 jack_error("port name '%s' does not contain ':' separator char", port_full_name);
565 return NULL;
568 port_short_name++; /* skip ':' separator char */
570 client_name_len = port_short_name - port_full_name - 1; /* without terminating '\0' */
572 client_ptr = jack_controller_patchbay_find_client(patchbay_ptr, port_full_name, client_name_len);
573 if (client_ptr == NULL)
575 jack_error("cannot find client of port '%s'", port_full_name);
576 return NULL;
579 return jack_controller_patchbay_find_client_port_by_name(patchbay_ptr, client_ptr, port_short_name);
582 static
583 struct jack_graph_port *
584 jack_controller_patchbay_find_port_by_names(
585 struct jack_controller_patchbay *patchbay_ptr,
586 const char *client_name,
587 const char *port_name)
589 struct jack_graph_client *client_ptr;
591 client_ptr = jack_controller_patchbay_find_client(patchbay_ptr, client_name, strlen(client_name));
592 if (client_ptr == NULL)
594 jack_error("cannot find client '%s'", client_name);
595 return NULL;
598 return jack_controller_patchbay_find_client_port_by_name(patchbay_ptr, client_ptr, port_name);
601 static
602 struct jack_graph_connection *
603 jack_controller_patchbay_create_connection(
604 struct jack_controller_patchbay *patchbay_ptr,
605 struct jack_graph_port *port1_ptr,
606 struct jack_graph_port *port2_ptr)
608 struct jack_graph_connection * connection_ptr;
610 connection_ptr = malloc(sizeof(struct jack_graph_connection));
611 if (connection_ptr == NULL)
613 jack_error("Memory allocation of jack_graph_connection structure failed.");
614 return NULL;
617 connection_ptr->id = patchbay_ptr->next_connection_id++;
618 connection_ptr->port1 = port1_ptr;
619 connection_ptr->port2 = port2_ptr;
621 pthread_mutex_lock(&patchbay_ptr->lock);
622 list_add_tail(&connection_ptr->siblings, &patchbay_ptr->graph.connections);
623 patchbay_ptr->graph.version++;
624 jack_controller_patchbay_send_signal_ports_connected(
625 patchbay_ptr->graph.version,
626 port1_ptr->client->id,
627 port1_ptr->client->name,
628 port1_ptr->id,
629 port1_ptr->name,
630 port2_ptr->client->id,
631 port2_ptr->client->name,
632 port2_ptr->id,
633 port2_ptr->name,
634 connection_ptr->id);
635 jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version);
636 pthread_mutex_unlock(&patchbay_ptr->lock);
638 return connection_ptr;
641 static
642 void
643 jack_controller_patchbay_destroy_connection(
644 struct jack_controller_patchbay *patchbay_ptr,
645 struct jack_graph_connection *connection_ptr)
647 pthread_mutex_lock(&patchbay_ptr->lock);
648 list_del(&connection_ptr->siblings);
649 patchbay_ptr->graph.version++;
650 jack_controller_patchbay_send_signal_ports_disconnected(
651 patchbay_ptr->graph.version,
652 connection_ptr->port1->client->id,
653 connection_ptr->port1->client->name,
654 connection_ptr->port1->id,
655 connection_ptr->port1->name,
656 connection_ptr->port2->client->id,
657 connection_ptr->port2->client->name,
658 connection_ptr->port2->id,
659 connection_ptr->port2->name,
660 connection_ptr->id);
661 jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version);
662 pthread_mutex_unlock(&patchbay_ptr->lock);
664 free(connection_ptr);
667 static
668 struct jack_graph_connection *
669 jack_controller_patchbay_find_connection(
670 struct jack_controller_patchbay *patchbay_ptr,
671 struct jack_graph_port *port1_ptr,
672 struct jack_graph_port *port2_ptr)
674 struct list_head *node_ptr;
675 struct jack_graph_connection *connection_ptr;
677 list_for_each(node_ptr, &patchbay_ptr->graph.connections)
679 connection_ptr = list_entry(node_ptr, struct jack_graph_connection, siblings);
680 if ((connection_ptr->port1 == port1_ptr &&
681 connection_ptr->port2 == port2_ptr) ||
682 (connection_ptr->port1 == port2_ptr &&
683 connection_ptr->port2 == port1_ptr))
685 return connection_ptr;
689 return NULL;
692 static
693 struct jack_graph_connection *
694 jack_controller_patchbay_find_connection_by_id(
695 struct jack_controller_patchbay *patchbay_ptr,
696 uint64_t connection_id)
698 struct list_head *node_ptr;
699 struct jack_graph_connection *connection_ptr;
701 list_for_each(node_ptr, &patchbay_ptr->graph.connections)
703 connection_ptr = list_entry(node_ptr, struct jack_graph_connection, siblings);
704 if (connection_ptr->id == connection_id)
706 return connection_ptr;
710 return NULL;
713 static
714 bool
715 jack_controller_patchbay_connect(
716 struct jack_dbus_method_call *dbus_call_ptr,
717 struct jack_controller *controller_ptr,
718 struct jack_graph_port *port1_ptr,
719 struct jack_graph_port *port2_ptr)
721 int ret;
722 char port1_name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
723 char port2_name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
725 sprintf(port1_name, "%s:%s", port1_ptr->client->name, port1_ptr->name);
726 sprintf(port2_name, "%s:%s", port2_ptr->client->name, port2_ptr->name);
728 ret = jack_connect(controller_ptr->client, port1_name, port2_name);
729 if (ret != 0)
731 jack_dbus_error(dbus_call_ptr, JACK_DBUS_ERROR_GENERIC, "jack_connect() failed with %d", ret);
732 return false;
735 return true;
738 static
739 bool
740 jack_controller_patchbay_disconnect(
741 struct jack_dbus_method_call *dbus_call_ptr,
742 struct jack_controller *controller_ptr,
743 struct jack_graph_port *port1_ptr,
744 struct jack_graph_port *port2_ptr)
746 int ret;
747 char port1_name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
748 char port2_name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
750 sprintf(port1_name, "%s:%s", port1_ptr->client->name, port1_ptr->name);
751 sprintf(port2_name, "%s:%s", port2_ptr->client->name, port2_ptr->name);
753 ret = jack_disconnect(controller_ptr->client, port1_name, port2_name);
754 if (ret != 0)
756 jack_dbus_error(dbus_call_ptr, JACK_DBUS_ERROR_GENERIC, "jack_connect() failed with %d", ret);
757 return false;
760 return true;
763 #define controller_ptr ((struct jack_controller *)call->context)
764 #define patchbay_ptr ((struct jack_controller_patchbay *)controller_ptr->patchbay_context)
766 static
767 void
768 jack_controller_dbus_get_all_ports(
769 struct jack_dbus_method_call * call)
771 struct list_head * client_node_ptr;
772 struct list_head * port_node_ptr;
773 struct jack_graph_client * client_ptr;
774 struct jack_graph_port * port_ptr;
775 DBusMessageIter iter, sub_iter;
776 char fullname[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
777 char *fullname_var = fullname;
779 if (!controller_ptr->started)
781 jack_dbus_error(
782 call,
783 JACK_DBUS_ERROR_SERVER_NOT_RUNNING,
784 "Can't execute this method with stopped JACK server");
785 return;
788 call->reply = dbus_message_new_method_return (call->message);
789 if (!call->reply)
791 goto fail;
794 dbus_message_iter_init_append (call->reply, &iter);
796 if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s", &sub_iter))
798 goto fail_unref;
801 pthread_mutex_lock(&patchbay_ptr->lock);
803 list_for_each(client_node_ptr, &patchbay_ptr->graph.clients)
805 client_ptr = list_entry(client_node_ptr, struct jack_graph_client, siblings);
807 list_for_each(port_node_ptr, &client_ptr->ports)
809 port_ptr = list_entry(port_node_ptr, struct jack_graph_port, siblings_client);
811 jack_info("%s:%s", client_ptr->name, port_ptr->name);
812 sprintf(fullname, "%s:%s", client_ptr->name, port_ptr->name);
813 if (!dbus_message_iter_append_basic (&sub_iter, DBUS_TYPE_STRING, &fullname_var))
815 pthread_mutex_unlock(&patchbay_ptr->lock);
816 dbus_message_iter_close_container (&iter, &sub_iter);
817 goto fail_unref;
822 pthread_mutex_unlock(&patchbay_ptr->lock);
824 if (!dbus_message_iter_close_container (&iter, &sub_iter))
826 goto fail_unref;
829 return;
831 fail_unref:
832 dbus_message_unref (call->reply);
833 call->reply = NULL;
835 fail:
836 jack_error ("Ran out of memory trying to construct method return");
839 static
840 void
841 jack_controller_dbus_get_graph(
842 struct jack_dbus_method_call * call)
844 struct list_head * client_node_ptr;
845 struct list_head * port_node_ptr;
846 struct list_head * connection_node_ptr;
847 struct jack_graph_client * client_ptr;
848 struct jack_graph_port * port_ptr;
849 struct jack_graph_connection * connection_ptr;
850 DBusMessageIter iter;
851 DBusMessageIter clients_array_iter;
852 DBusMessageIter client_struct_iter;
853 DBusMessageIter ports_array_iter;
854 DBusMessageIter port_struct_iter;
855 dbus_uint64_t version;
856 DBusMessageIter connections_array_iter;
857 DBusMessageIter connection_struct_iter;
859 if (!controller_ptr->started)
861 jack_dbus_error(
862 call,
863 JACK_DBUS_ERROR_SERVER_NOT_RUNNING,
864 "Can't execute this method with stopped JACK server");
865 return;
868 if (!jack_dbus_get_method_args(call, DBUS_TYPE_UINT64, &version, DBUS_TYPE_INVALID))
870 /* The method call had invalid arguments meaning that
871 * jack_dbus_get_method_args() has constructed an error for us.
873 goto exit;
876 //jack_info("Getting graph, know version is %" PRIu32, version);
878 call->reply = dbus_message_new_method_return(call->message);
879 if (!call->reply)
881 jack_error("Ran out of memory trying to construct method return");
882 goto exit;
885 dbus_message_iter_init_append (call->reply, &iter);
887 pthread_mutex_lock(&patchbay_ptr->lock);
889 if (version > patchbay_ptr->graph.version)
891 jack_dbus_error(
892 call,
893 JACK_DBUS_ERROR_INVALID_ARGS,
894 "known graph version %" PRIu64 " is newer than actual version %" PRIu64,
895 version,
896 patchbay_ptr->graph.version);
897 pthread_mutex_unlock(&patchbay_ptr->lock);
898 goto exit;
901 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT64, &patchbay_ptr->graph.version))
903 goto nomem_unlock;
906 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(tsa(tsuu))", &clients_array_iter))
908 goto nomem_unlock;
911 if (version < patchbay_ptr->graph.version)
913 list_for_each(client_node_ptr, &patchbay_ptr->graph.clients)
915 client_ptr = list_entry(client_node_ptr, struct jack_graph_client, siblings);
917 if (!dbus_message_iter_open_container (&clients_array_iter, DBUS_TYPE_STRUCT, NULL, &client_struct_iter))
919 goto nomem_close_clients_array;
922 if (!dbus_message_iter_append_basic(&client_struct_iter, DBUS_TYPE_UINT64, &client_ptr->id))
924 goto nomem_close_client_struct;
927 if (!dbus_message_iter_append_basic(&client_struct_iter, DBUS_TYPE_STRING, &client_ptr->name))
929 goto nomem_close_client_struct;
932 if (!dbus_message_iter_open_container(&client_struct_iter, DBUS_TYPE_ARRAY, "(tsuu)", &ports_array_iter))
934 goto nomem_close_client_struct;
937 list_for_each(port_node_ptr, &client_ptr->ports)
939 port_ptr = list_entry(port_node_ptr, struct jack_graph_port, siblings_client);
941 if (!dbus_message_iter_open_container(&ports_array_iter, DBUS_TYPE_STRUCT, NULL, &port_struct_iter))
943 goto nomem_close_ports_array;
946 if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT64, &port_ptr->id))
948 goto nomem_close_port_struct;
951 if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_STRING, &port_ptr->name))
953 goto nomem_close_port_struct;
956 if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT32, &port_ptr->flags))
958 goto nomem_close_port_struct;
961 if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT32, &port_ptr->type))
963 goto nomem_close_port_struct;
966 if (!dbus_message_iter_close_container(&ports_array_iter, &port_struct_iter))
968 goto nomem_close_ports_array;
972 if (!dbus_message_iter_close_container(&client_struct_iter, &ports_array_iter))
974 goto nomem_close_client_struct;
977 if (!dbus_message_iter_close_container(&clients_array_iter, &client_struct_iter))
979 goto nomem_close_clients_array;
984 if (!dbus_message_iter_close_container(&iter, &clients_array_iter))
986 goto nomem_unlock;
989 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(tstststst)", &connections_array_iter))
991 goto nomem_unlock;
994 if (version < patchbay_ptr->graph.version)
996 list_for_each(connection_node_ptr, &patchbay_ptr->graph.connections)
998 connection_ptr = list_entry(connection_node_ptr, struct jack_graph_connection, siblings);
1000 if (!dbus_message_iter_open_container(&connections_array_iter, DBUS_TYPE_STRUCT, NULL, &connection_struct_iter))
1002 goto nomem_close_connections_array;
1005 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port1->client->id))
1007 goto nomem_close_connection_struct;
1010 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port1->client->name))
1012 goto nomem_close_connection_struct;
1015 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port1->id))
1017 goto nomem_close_connection_struct;
1020 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port1->name))
1022 goto nomem_close_connection_struct;
1025 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port2->client->id))
1027 goto nomem_close_connection_struct;
1030 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port2->client->name))
1032 goto nomem_close_connection_struct;
1035 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port2->id))
1037 goto nomem_close_connection_struct;
1040 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port2->name))
1042 goto nomem_close_connection_struct;
1045 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->id))
1047 goto nomem_close_connection_struct;
1050 if (!dbus_message_iter_close_container(&connections_array_iter, &connection_struct_iter))
1052 goto nomem_close_connections_array;
1057 if (!dbus_message_iter_close_container(&iter, &connections_array_iter))
1059 goto nomem_unlock;
1062 pthread_mutex_unlock(&patchbay_ptr->lock);
1064 return;
1066 nomem_close_connection_struct:
1067 dbus_message_iter_close_container(&connections_array_iter, &connection_struct_iter);
1069 nomem_close_connections_array:
1070 dbus_message_iter_close_container(&iter, &connections_array_iter);
1071 goto nomem_unlock;
1073 nomem_close_port_struct:
1074 dbus_message_iter_close_container(&ports_array_iter, &port_struct_iter);
1076 nomem_close_ports_array:
1077 dbus_message_iter_close_container(&client_struct_iter, &ports_array_iter);
1079 nomem_close_client_struct:
1080 dbus_message_iter_close_container(&clients_array_iter, &client_struct_iter);
1082 nomem_close_clients_array:
1083 dbus_message_iter_close_container(&iter, &clients_array_iter);
1085 nomem_unlock:
1086 pthread_mutex_unlock(&patchbay_ptr->lock);
1088 //nomem:
1089 dbus_message_unref(call->reply);
1090 call->reply = NULL;
1091 jack_error("Ran out of memory trying to construct method return");
1093 exit:
1094 return;
1097 static
1098 void
1099 jack_controller_dbus_connect_ports_by_name(
1100 struct jack_dbus_method_call * call)
1102 const char * client1_name;
1103 const char * port1_name;
1104 const char * client2_name;
1105 const char * port2_name;
1106 struct jack_graph_port *port1_ptr;
1107 struct jack_graph_port *port2_ptr;
1109 /* jack_info("jack_controller_dbus_connect_ports_by_name() called."); */
1111 if (!controller_ptr->started)
1113 jack_dbus_error(
1114 call,
1115 JACK_DBUS_ERROR_SERVER_NOT_RUNNING,
1116 "Can't execute this method with stopped JACK server");
1117 return;
1120 if (!jack_dbus_get_method_args(
1121 call,
1122 DBUS_TYPE_STRING,
1123 &client1_name,
1124 DBUS_TYPE_STRING,
1125 &port1_name,
1126 DBUS_TYPE_STRING,
1127 &client2_name,
1128 DBUS_TYPE_STRING,
1129 &port2_name,
1130 DBUS_TYPE_INVALID))
1132 /* The method call had invalid arguments meaning that
1133 * jack_dbus_get_method_args() has constructed an error for us.
1135 return;
1138 /* jack_info("connecting %s:%s and %s:%s", client1_name, port1_name, client2_name, port2_name); */
1140 pthread_mutex_lock(&patchbay_ptr->lock);
1142 port1_ptr = jack_controller_patchbay_find_port_by_names(patchbay_ptr, client1_name, port1_name);
1143 if (port1_ptr == NULL)
1145 jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port '%s':'%s'", client1_name, port1_name);
1146 goto unlock;
1149 port2_ptr = jack_controller_patchbay_find_port_by_names(patchbay_ptr, client2_name, port2_name);
1150 if (port2_ptr == NULL)
1152 jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port '%s':'%s'", client2_name, port2_name);
1153 goto unlock;
1156 if (!jack_controller_patchbay_connect(
1157 call,
1158 controller_ptr,
1159 port1_ptr,
1160 port2_ptr))
1162 /* jack_controller_patchbay_connect() constructed error reply */
1163 goto unlock;
1166 jack_dbus_construct_method_return_empty(call);
1168 unlock:
1169 pthread_mutex_unlock(&patchbay_ptr->lock);
1172 static
1173 void
1174 jack_controller_dbus_connect_ports_by_id(
1175 struct jack_dbus_method_call * call)
1177 dbus_uint64_t port1_id;
1178 dbus_uint64_t port2_id;
1179 struct jack_graph_port *port1_ptr;
1180 struct jack_graph_port *port2_ptr;
1182 /* jack_info("jack_controller_dbus_connect_ports_by_id() called."); */
1184 if (!controller_ptr->started)
1186 jack_dbus_error(
1187 call,
1188 JACK_DBUS_ERROR_SERVER_NOT_RUNNING,
1189 "Can't execute this method with stopped JACK server");
1190 return;
1193 if (!jack_dbus_get_method_args(
1194 call,
1195 DBUS_TYPE_UINT64,
1196 &port1_id,
1197 DBUS_TYPE_UINT64,
1198 &port2_id,
1199 DBUS_TYPE_INVALID))
1201 /* The method call had invalid arguments meaning that
1202 * jack_dbus_get_method_args() has constructed an error for us.
1204 return;
1207 pthread_mutex_lock(&patchbay_ptr->lock);
1209 port1_ptr = jack_controller_patchbay_find_port_by_id(patchbay_ptr, port1_id);
1210 if (port1_ptr == NULL)
1212 jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port %" PRIu64, port1_id);
1213 goto unlock;
1216 port2_ptr = jack_controller_patchbay_find_port_by_id(patchbay_ptr, port2_id);
1217 if (port2_ptr == NULL)
1219 jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port %" PRIu64, port2_id);
1220 goto unlock;
1223 if (!jack_controller_patchbay_connect(
1224 call,
1225 controller_ptr,
1226 port1_ptr,
1227 port2_ptr))
1229 /* jack_controller_patchbay_connect() constructed error reply */
1230 goto unlock;
1233 jack_dbus_construct_method_return_empty(call);
1235 unlock:
1236 pthread_mutex_unlock(&patchbay_ptr->lock);
1239 static
1240 void
1241 jack_controller_dbus_disconnect_ports_by_name(
1242 struct jack_dbus_method_call * call)
1244 const char * client1_name;
1245 const char * port1_name;
1246 const char * client2_name;
1247 const char * port2_name;
1248 struct jack_graph_port *port1_ptr;
1249 struct jack_graph_port *port2_ptr;
1251 /* jack_info("jack_controller_dbus_disconnect_ports_by_name() called."); */
1253 if (!controller_ptr->started)
1255 jack_dbus_error(
1256 call,
1257 JACK_DBUS_ERROR_SERVER_NOT_RUNNING,
1258 "Can't execute this method with stopped JACK server");
1259 return;
1262 if (!jack_dbus_get_method_args(
1263 call,
1264 DBUS_TYPE_STRING,
1265 &client1_name,
1266 DBUS_TYPE_STRING,
1267 &port1_name,
1268 DBUS_TYPE_STRING,
1269 &client2_name,
1270 DBUS_TYPE_STRING,
1271 &port2_name,
1272 DBUS_TYPE_INVALID))
1274 /* The method call had invalid arguments meaning that
1275 * jack_dbus_get_method_args() has constructed an error for us.
1277 return;
1280 /* jack_info("disconnecting %s:%s and %s:%s", client1_name, port1_name, client2_name, port2_name); */
1282 pthread_mutex_lock(&patchbay_ptr->lock);
1284 port1_ptr = jack_controller_patchbay_find_port_by_names(patchbay_ptr, client1_name, port1_name);
1285 if (port1_ptr == NULL)
1287 jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port '%s':'%s'", client1_name, port1_name);
1288 goto unlock;
1291 port2_ptr = jack_controller_patchbay_find_port_by_names(patchbay_ptr, client2_name, port2_name);
1292 if (port2_ptr == NULL)
1294 jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port '%s':'%s'", client2_name, port2_name);
1295 goto unlock;
1298 if (!jack_controller_patchbay_disconnect(
1299 call,
1300 controller_ptr,
1301 port1_ptr,
1302 port2_ptr))
1304 /* jack_controller_patchbay_connect() constructed error reply */
1305 goto unlock;
1308 jack_dbus_construct_method_return_empty(call);
1310 unlock:
1311 pthread_mutex_unlock(&patchbay_ptr->lock);
1314 static
1315 void
1316 jack_controller_dbus_disconnect_ports_by_id(
1317 struct jack_dbus_method_call * call)
1319 dbus_uint64_t port1_id;
1320 dbus_uint64_t port2_id;
1321 struct jack_graph_port *port1_ptr;
1322 struct jack_graph_port *port2_ptr;
1324 /* jack_info("jack_controller_dbus_disconnect_ports_by_id() called."); */
1326 if (!controller_ptr->started)
1328 jack_dbus_error(
1329 call,
1330 JACK_DBUS_ERROR_SERVER_NOT_RUNNING,
1331 "Can't execute this method with stopped JACK server");
1332 return;
1335 if (!jack_dbus_get_method_args(
1336 call,
1337 DBUS_TYPE_UINT64,
1338 &port1_id,
1339 DBUS_TYPE_UINT64,
1340 &port2_id,
1341 DBUS_TYPE_INVALID))
1343 /* The method call had invalid arguments meaning that
1344 * jack_dbus_get_method_args() has constructed an error for us.
1346 return;
1349 pthread_mutex_lock(&patchbay_ptr->lock);
1351 port1_ptr = jack_controller_patchbay_find_port_by_id(patchbay_ptr, port1_id);
1352 if (port1_ptr == NULL)
1354 jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port %" PRIu64, port1_id);
1355 goto unlock;
1358 port2_ptr = jack_controller_patchbay_find_port_by_id(patchbay_ptr, port2_id);
1359 if (port2_ptr == NULL)
1361 jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port %" PRIu64, port2_id);
1362 goto unlock;
1365 if (!jack_controller_patchbay_disconnect(
1366 call,
1367 controller_ptr,
1368 port1_ptr,
1369 port2_ptr))
1371 /* jack_controller_patchbay_connect() constructed error reply */
1372 goto unlock;
1375 jack_dbus_construct_method_return_empty(call);
1377 unlock:
1378 pthread_mutex_unlock(&patchbay_ptr->lock);
1381 static
1382 void
1383 jack_controller_dbus_disconnect_ports_by_connection_id(
1384 struct jack_dbus_method_call * call)
1386 dbus_uint64_t connection_id;
1387 struct jack_graph_connection *connection_ptr;
1389 /* jack_info("jack_controller_dbus_disconnect_ports_by_id() called."); */
1391 if (!jack_dbus_get_method_args(
1392 call,
1393 DBUS_TYPE_UINT64,
1394 &connection_id,
1395 DBUS_TYPE_INVALID))
1397 /* The method call had invalid arguments meaning that
1398 * jack_dbus_get_method_args() has constructed an error for us.
1400 return;
1403 pthread_mutex_lock(&patchbay_ptr->lock);
1405 connection_ptr = jack_controller_patchbay_find_connection_by_id(patchbay_ptr, connection_id);
1406 if (connection_ptr == NULL)
1408 jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find connection %" PRIu64, connection_id);
1409 goto unlock;
1412 if (!jack_controller_patchbay_disconnect(
1413 call,
1414 controller_ptr,
1415 connection_ptr->port1,
1416 connection_ptr->port2))
1418 /* jack_controller_patchbay_connect() constructed error reply */
1419 goto unlock;
1422 jack_dbus_construct_method_return_empty(call);
1424 unlock:
1425 pthread_mutex_unlock(&patchbay_ptr->lock);
1428 static
1429 void
1430 jack_controller_dbus_get_client_pid(
1431 struct jack_dbus_method_call * call)
1433 dbus_uint64_t client_id;
1434 struct jack_graph_client *client_ptr;
1435 message_arg_t arg;
1437 /* jack_info("jack_controller_dbus_get_client_pid() called."); */
1439 if (!jack_dbus_get_method_args(
1440 call,
1441 DBUS_TYPE_UINT64,
1442 &client_id,
1443 DBUS_TYPE_INVALID))
1445 /* The method call had invalid arguments meaning that
1446 * jack_dbus_get_method_args() has constructed an error for us.
1448 return;
1451 pthread_mutex_lock(&patchbay_ptr->lock);
1453 client_ptr = jack_controller_patchbay_find_client_by_id(patchbay_ptr, client_id);
1454 if (client_ptr == NULL)
1456 jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find client %" PRIu64, client_id);
1457 goto unlock;
1460 arg.int64 = client_ptr->pid;
1462 jack_dbus_construct_method_return_single(call, DBUS_TYPE_INT64, arg);
1464 unlock:
1465 pthread_mutex_unlock(&patchbay_ptr->lock);
1468 #undef controller_ptr
1469 #define controller_ptr ((struct jack_controller *)context)
1471 static
1473 jack_controller_graph_order_callback(
1474 void *context)
1476 const char **ports;
1477 int i;
1478 jack_port_t *port_ptr;
1480 if (patchbay_ptr->graph.version > 1)
1482 /* we use this only for initial catchup */
1483 return 0;
1486 ports = jack_get_ports(controller_ptr->client, NULL, NULL, 0);
1487 if (ports)
1489 for (i = 0; ports[i]; ++i)
1491 jack_info("graph reorder: new port '%s'", ports[i]);
1492 port_ptr = jack_port_by_name(controller_ptr->client, ports[i]);;
1493 jack_controller_patchbay_new_port(patchbay_ptr, ports[i], jack_port_flags(port_ptr), jack_port_type_id(port_ptr));
1496 free(ports);
1499 if (patchbay_ptr->graph.version == 1)
1501 /* we have empty initial graph, increment graph version,
1502 so we dont do jack_get_ports() again,
1503 on next next graph change */
1504 patchbay_ptr->graph.version++;
1507 return 0;
1510 void
1511 jack_controller_client_registration_callback(
1512 const char *client_name,
1513 int created,
1514 void *context)
1516 if (created)
1518 jack_log("client '%s' created", client_name);
1519 jack_controller_patchbay_create_client(patchbay_ptr, client_name, strlen(client_name));
1521 else
1523 jack_log("client '%s' destroyed", client_name);
1524 jack_controller_patchbay_destroy_client_by_name(patchbay_ptr, client_name);
1528 void
1529 jack_controller_port_registration_callback(
1530 jack_port_id_t port_id,
1531 int created,
1532 void *context)
1534 jack_port_t *port_ptr;
1535 struct jack_graph_port *graph_port_ptr;
1536 const char *port_name;
1538 port_ptr = jack_port_by_id(controller_ptr->client, port_id);
1539 port_name = jack_port_name(port_ptr);
1541 if (created)
1543 jack_log("port '%s' created", port_name);
1544 jack_controller_patchbay_new_port(patchbay_ptr, port_name, jack_port_flags(port_ptr), jack_port_type_id(port_ptr));
1546 else
1548 jack_log("port '%s' destroyed", port_name);
1549 graph_port_ptr = jack_controller_patchbay_find_port_by_full_name(patchbay_ptr, port_name);
1550 if (graph_port_ptr == NULL)
1552 jack_error("Failed to find port '%s' to destroy", port_name);
1553 return;
1556 jack_controller_patchbay_remove_port(patchbay_ptr, graph_port_ptr);
1560 void
1561 jack_controller_port_connect_callback(
1562 jack_port_id_t port1_id,
1563 jack_port_id_t port2_id,
1564 int connect,
1565 void *context)
1567 jack_port_t *port1;
1568 jack_port_t *port2;
1569 const char *port1_name;
1570 const char *port2_name;
1571 struct jack_graph_port *port1_ptr;
1572 struct jack_graph_port *port2_ptr;
1573 struct jack_graph_connection *connection_ptr;
1575 port1 = jack_port_by_id(controller_ptr->client, port1_id);
1576 port2 = jack_port_by_id(controller_ptr->client, port2_id);
1578 port1_name = jack_port_name(port1);
1579 port2_name = jack_port_name(port2);
1581 port1_ptr = jack_controller_patchbay_find_port_by_full_name(patchbay_ptr, port1_name);
1582 if (port1_ptr == NULL)
1584 jack_error("Failed to find port '%s' to [dis]connect", port1_name);
1585 return;
1588 port2_ptr = jack_controller_patchbay_find_port_by_full_name(patchbay_ptr, port2_name);
1589 if (port2_ptr == NULL)
1591 jack_error("Failed to find port '%s' to [dis]connect", port2_name);
1592 return;
1595 if (connect)
1597 jack_info("Connecting '%s' to '%s'", port1_name, port2_name);
1598 connection_ptr = jack_controller_patchbay_find_connection(patchbay_ptr, port1_ptr, port2_ptr);
1599 if (connection_ptr != NULL)
1601 jack_error("'%s' and '%s' are already connected", port1_name, port2_name);
1602 return;
1605 jack_controller_patchbay_create_connection(patchbay_ptr, port1_ptr, port2_ptr);
1607 else
1609 jack_info("Disconnecting '%s' from '%s'", port1_name, port2_name);
1610 connection_ptr = jack_controller_patchbay_find_connection(patchbay_ptr, port1_ptr, port2_ptr);
1611 if (connection_ptr == NULL)
1613 jack_error("Cannot find connection being removed");
1614 return;
1617 jack_controller_patchbay_destroy_connection(patchbay_ptr, connection_ptr);
1621 #undef controller_ptr
1623 void
1624 jack_controller_patchbay_uninit(
1625 struct jack_controller * controller_ptr)
1627 struct jack_graph_client *client_ptr;
1628 struct jack_graph_port *port_ptr;
1630 /* jack_info("jack_controller_patchbay_uninit() called"); */
1632 while (!list_empty(&patchbay_ptr->graph.ports))
1634 port_ptr = list_entry(patchbay_ptr->graph.ports.next, struct jack_graph_port, siblings_graph);
1635 jack_controller_patchbay_remove_port(patchbay_ptr, port_ptr);
1638 while (!list_empty(&patchbay_ptr->graph.clients))
1640 client_ptr = list_entry(patchbay_ptr->graph.clients.next, struct jack_graph_client, siblings);
1641 jack_controller_patchbay_destroy_client(patchbay_ptr, client_ptr);
1644 pthread_mutex_destroy(&patchbay_ptr->lock);
1647 #undef patchbay_ptr
1649 bool
1650 jack_controller_patchbay_init(
1651 struct jack_controller * controller_ptr)
1653 int ret;
1654 struct jack_controller_patchbay * patchbay_ptr;
1655 pthread_mutexattr_t attr;
1657 /* jack_info("jack_controller_patchbay_init() called"); */
1659 patchbay_ptr = malloc(sizeof(struct jack_controller_patchbay));
1660 if (patchbay_ptr == NULL)
1662 jack_error("Memory allocation of jack_controller_patchbay structure failed.");
1663 goto fail;
1666 ret = pthread_mutexattr_init(&attr);
1667 if (ret != 0)
1669 goto fail;
1672 ret = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
1673 if (ret != 0)
1675 goto fail;
1678 pthread_mutex_init(&patchbay_ptr->lock, &attr);
1679 INIT_LIST_HEAD(&patchbay_ptr->graph.clients);
1680 INIT_LIST_HEAD(&patchbay_ptr->graph.ports);
1681 INIT_LIST_HEAD(&patchbay_ptr->graph.connections);
1682 patchbay_ptr->graph.version = 1;
1683 patchbay_ptr->next_client_id = 1;
1684 patchbay_ptr->next_port_id = 1;
1685 patchbay_ptr->next_connection_id = 1;
1687 controller_ptr->patchbay_context = patchbay_ptr;
1689 ret = jack_set_graph_order_callback(controller_ptr->client, jack_controller_graph_order_callback, controller_ptr);
1690 if (ret != 0)
1692 jack_error("jack_set_graph_order_callback() failed with error %d", ret);
1693 goto fail_uninit_mutex;
1696 ret = jack_set_client_registration_callback(controller_ptr->client, jack_controller_client_registration_callback, controller_ptr);
1697 if (ret != 0)
1699 jack_error("jack_set_client_registration_callback() failed with error %d", ret);
1700 goto fail_uninit_mutex;
1703 ret = jack_set_port_registration_callback(controller_ptr->client, jack_controller_port_registration_callback, controller_ptr);
1704 if (ret != 0)
1706 jack_error("jack_set_port_registration_callback() failed with error %d", ret);
1707 goto fail_uninit_mutex;
1710 ret = jack_set_port_connect_callback(controller_ptr->client, jack_controller_port_connect_callback, controller_ptr);
1711 if (ret != 0)
1713 jack_error("jack_set_port_connect_callback() failed with error %d", ret);
1714 goto fail_uninit_mutex;
1717 return true;
1719 fail_uninit_mutex:
1720 pthread_mutex_destroy(&patchbay_ptr->lock);
1722 fail:
1723 return false;
1726 JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetAllPorts)
1727 JACK_DBUS_METHOD_ARGUMENT("ports_list", "as", true)
1728 JACK_DBUS_METHOD_ARGUMENTS_END
1730 JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetGraph)
1731 JACK_DBUS_METHOD_ARGUMENT("known_graph_version", DBUS_TYPE_UINT64_AS_STRING, false)
1732 JACK_DBUS_METHOD_ARGUMENT("current_graph_version", DBUS_TYPE_UINT64_AS_STRING, true)
1733 JACK_DBUS_METHOD_ARGUMENT("clients_and_ports", "a(tsa(tsuu))", true)
1734 JACK_DBUS_METHOD_ARGUMENT("connections", "a(tstststst)", true)
1735 JACK_DBUS_METHOD_ARGUMENTS_END
1737 JACK_DBUS_METHOD_ARGUMENTS_BEGIN(ConnectPortsByName)
1738 JACK_DBUS_METHOD_ARGUMENT("client1_name", DBUS_TYPE_STRING_AS_STRING, false)
1739 JACK_DBUS_METHOD_ARGUMENT("port1_name", DBUS_TYPE_STRING_AS_STRING, false)
1740 JACK_DBUS_METHOD_ARGUMENT("client2_name", DBUS_TYPE_STRING_AS_STRING, false)
1741 JACK_DBUS_METHOD_ARGUMENT("port2_name", DBUS_TYPE_STRING_AS_STRING, false)
1742 JACK_DBUS_METHOD_ARGUMENTS_END
1744 JACK_DBUS_METHOD_ARGUMENTS_BEGIN(ConnectPortsByID)
1745 JACK_DBUS_METHOD_ARGUMENT("port1_id", DBUS_TYPE_UINT64_AS_STRING, false)
1746 JACK_DBUS_METHOD_ARGUMENT("port2_id", DBUS_TYPE_UINT64_AS_STRING, false)
1747 JACK_DBUS_METHOD_ARGUMENTS_END
1749 JACK_DBUS_METHOD_ARGUMENTS_BEGIN(DisconnectPortsByName)
1750 JACK_DBUS_METHOD_ARGUMENT("client1_name", DBUS_TYPE_STRING_AS_STRING, false)
1751 JACK_DBUS_METHOD_ARGUMENT("port1_name", DBUS_TYPE_STRING_AS_STRING, false)
1752 JACK_DBUS_METHOD_ARGUMENT("client2_name", DBUS_TYPE_STRING_AS_STRING, false)
1753 JACK_DBUS_METHOD_ARGUMENT("port2_name", DBUS_TYPE_STRING_AS_STRING, false)
1754 JACK_DBUS_METHOD_ARGUMENTS_END
1756 JACK_DBUS_METHOD_ARGUMENTS_BEGIN(DisconnectPortsByID)
1757 JACK_DBUS_METHOD_ARGUMENT("port1_id", DBUS_TYPE_UINT64_AS_STRING, false)
1758 JACK_DBUS_METHOD_ARGUMENT("port2_id", DBUS_TYPE_UINT64_AS_STRING, false)
1759 JACK_DBUS_METHOD_ARGUMENTS_END
1761 JACK_DBUS_METHOD_ARGUMENTS_BEGIN(DisconnectPortsByConnectionID)
1762 JACK_DBUS_METHOD_ARGUMENT("connection_id", DBUS_TYPE_UINT64_AS_STRING, false)
1763 JACK_DBUS_METHOD_ARGUMENTS_END
1765 JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetClientPID)
1766 JACK_DBUS_METHOD_ARGUMENT("client_id", DBUS_TYPE_UINT64_AS_STRING, false)
1767 JACK_DBUS_METHOD_ARGUMENT("process_id", DBUS_TYPE_INT64_AS_STRING, true)
1768 JACK_DBUS_METHOD_ARGUMENTS_END
1770 JACK_DBUS_METHODS_BEGIN
1771 JACK_DBUS_METHOD_DESCRIBE(GetAllPorts, jack_controller_dbus_get_all_ports)
1772 JACK_DBUS_METHOD_DESCRIBE(GetGraph, jack_controller_dbus_get_graph)
1773 JACK_DBUS_METHOD_DESCRIBE(ConnectPortsByName, jack_controller_dbus_connect_ports_by_name)
1774 JACK_DBUS_METHOD_DESCRIBE(ConnectPortsByID, jack_controller_dbus_connect_ports_by_id)
1775 JACK_DBUS_METHOD_DESCRIBE(DisconnectPortsByName, jack_controller_dbus_disconnect_ports_by_name)
1776 JACK_DBUS_METHOD_DESCRIBE(DisconnectPortsByID, jack_controller_dbus_disconnect_ports_by_id)
1777 JACK_DBUS_METHOD_DESCRIBE(DisconnectPortsByConnectionID, jack_controller_dbus_disconnect_ports_by_connection_id)
1778 JACK_DBUS_METHOD_DESCRIBE(GetClientPID, jack_controller_dbus_get_client_pid)
1779 JACK_DBUS_METHODS_END
1781 JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(GraphChanged)
1782 JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING)
1783 JACK_DBUS_SIGNAL_ARGUMENTS_END
1785 JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(ClientAppeared)
1786 JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING)
1787 JACK_DBUS_SIGNAL_ARGUMENT("client_id", DBUS_TYPE_UINT64_AS_STRING)
1788 JACK_DBUS_SIGNAL_ARGUMENT("client_name", DBUS_TYPE_STRING_AS_STRING)
1789 JACK_DBUS_SIGNAL_ARGUMENTS_END
1791 JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(ClientDisappeared)
1792 JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING)
1793 JACK_DBUS_SIGNAL_ARGUMENT("client_id", DBUS_TYPE_UINT64_AS_STRING)
1794 JACK_DBUS_SIGNAL_ARGUMENT("client_name", DBUS_TYPE_STRING_AS_STRING)
1795 JACK_DBUS_SIGNAL_ARGUMENTS_END
1797 JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(PortAppeared)
1798 JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING)
1799 JACK_DBUS_SIGNAL_ARGUMENT("client_id", DBUS_TYPE_UINT64_AS_STRING)
1800 JACK_DBUS_SIGNAL_ARGUMENT("client_name", DBUS_TYPE_STRING_AS_STRING)
1801 JACK_DBUS_SIGNAL_ARGUMENT("port_id", DBUS_TYPE_UINT64_AS_STRING)
1802 JACK_DBUS_SIGNAL_ARGUMENT("port_name", DBUS_TYPE_STRING_AS_STRING)
1803 JACK_DBUS_SIGNAL_ARGUMENT("port_flags", DBUS_TYPE_UINT32_AS_STRING)
1804 JACK_DBUS_SIGNAL_ARGUMENT("port_type", DBUS_TYPE_UINT32_AS_STRING)
1805 JACK_DBUS_SIGNAL_ARGUMENTS_END
1807 JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(PortDisappeared)
1808 JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING)
1809 JACK_DBUS_SIGNAL_ARGUMENT("client_id", DBUS_TYPE_UINT64_AS_STRING)
1810 JACK_DBUS_SIGNAL_ARGUMENT("client_name", DBUS_TYPE_STRING_AS_STRING)
1811 JACK_DBUS_SIGNAL_ARGUMENT("port_id", DBUS_TYPE_UINT64_AS_STRING)
1812 JACK_DBUS_SIGNAL_ARGUMENT("port_name", DBUS_TYPE_STRING_AS_STRING)
1813 JACK_DBUS_SIGNAL_ARGUMENTS_END
1815 JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(PortsConnected)
1816 JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING)
1817 JACK_DBUS_SIGNAL_ARGUMENT("client1_id", DBUS_TYPE_UINT64_AS_STRING)
1818 JACK_DBUS_SIGNAL_ARGUMENT("client1_name", DBUS_TYPE_STRING_AS_STRING)
1819 JACK_DBUS_SIGNAL_ARGUMENT("port1_id", DBUS_TYPE_UINT64_AS_STRING)
1820 JACK_DBUS_SIGNAL_ARGUMENT("port1_name", DBUS_TYPE_STRING_AS_STRING)
1821 JACK_DBUS_SIGNAL_ARGUMENT("client2_id", DBUS_TYPE_UINT64_AS_STRING)
1822 JACK_DBUS_SIGNAL_ARGUMENT("client2_name", DBUS_TYPE_STRING_AS_STRING)
1823 JACK_DBUS_SIGNAL_ARGUMENT("port2_id", DBUS_TYPE_UINT64_AS_STRING)
1824 JACK_DBUS_SIGNAL_ARGUMENT("port2_name", DBUS_TYPE_STRING_AS_STRING)
1825 JACK_DBUS_SIGNAL_ARGUMENT("connection_id", DBUS_TYPE_UINT64_AS_STRING)
1826 JACK_DBUS_SIGNAL_ARGUMENTS_END
1828 JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(PortsDisconnected)
1829 JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING)
1830 JACK_DBUS_SIGNAL_ARGUMENT("client1_id", DBUS_TYPE_UINT64_AS_STRING)
1831 JACK_DBUS_SIGNAL_ARGUMENT("client1_name", DBUS_TYPE_STRING_AS_STRING)
1832 JACK_DBUS_SIGNAL_ARGUMENT("port1_id", DBUS_TYPE_UINT64_AS_STRING)
1833 JACK_DBUS_SIGNAL_ARGUMENT("port1_name", DBUS_TYPE_STRING_AS_STRING)
1834 JACK_DBUS_SIGNAL_ARGUMENT("client2_id", DBUS_TYPE_UINT64_AS_STRING)
1835 JACK_DBUS_SIGNAL_ARGUMENT("client2_name", DBUS_TYPE_STRING_AS_STRING)
1836 JACK_DBUS_SIGNAL_ARGUMENT("port2_id", DBUS_TYPE_UINT64_AS_STRING)
1837 JACK_DBUS_SIGNAL_ARGUMENT("port2_name", DBUS_TYPE_STRING_AS_STRING)
1838 JACK_DBUS_SIGNAL_ARGUMENT("connection_id", DBUS_TYPE_UINT64_AS_STRING)
1839 JACK_DBUS_SIGNAL_ARGUMENTS_END
1841 JACK_DBUS_SIGNALS_BEGIN
1842 JACK_DBUS_SIGNAL_DESCRIBE(GraphChanged)
1843 JACK_DBUS_SIGNAL_DESCRIBE(ClientAppeared)
1844 JACK_DBUS_SIGNAL_DESCRIBE(ClientDisappeared)
1845 JACK_DBUS_SIGNAL_DESCRIBE(PortAppeared)
1846 JACK_DBUS_SIGNAL_DESCRIBE(PortDisappeared)
1847 JACK_DBUS_SIGNAL_DESCRIBE(PortsConnected)
1848 JACK_DBUS_SIGNAL_DESCRIBE(PortsDisconnected)
1849 JACK_DBUS_SIGNALS_END
1851 JACK_DBUS_IFACE_BEGIN(g_jack_controller_iface_patchbay, JACK_DBUS_IFACE_NAME)
1852 JACK_DBUS_IFACE_EXPOSE_METHODS
1853 JACK_DBUS_IFACE_EXPOSE_SIGNALS
1854 JACK_DBUS_IFACE_END