Adjust asciidoc command-line for ladoc-py
[jackdbus.git] / dbus / controller_iface_patchbay.c
blob765d4690fd48775eea9451baf0a84bd5e570e064
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 void
285 jack_controller_patchbay_send_signal_port_renamed(
286 dbus_uint64_t new_graph_version,
287 dbus_uint64_t client_id,
288 const char * client_name,
289 dbus_uint64_t port_id,
290 const char * port_old_name,
291 const char * port_new_name)
294 jack_dbus_send_signal(
295 JACK_CONTROLLER_OBJECT_PATH,
296 JACK_DBUS_IFACE_NAME,
297 "PortRenamed",
298 DBUS_TYPE_UINT64,
299 &new_graph_version,
300 DBUS_TYPE_UINT64,
301 &client_id,
302 DBUS_TYPE_STRING,
303 &client_name,
304 DBUS_TYPE_UINT64,
305 &port_id,
306 DBUS_TYPE_STRING,
307 &port_old_name,
308 DBUS_TYPE_STRING,
309 &port_new_name,
310 DBUS_TYPE_INVALID);
313 static
314 struct jack_graph_client *
315 jack_controller_patchbay_find_client(
316 struct jack_controller_patchbay *patchbay_ptr,
317 const char *client_name, /* not '\0' terminated */
318 size_t client_name_len) /* without terminating '\0' */
320 struct list_head *node_ptr;
321 struct jack_graph_client *client_ptr;
323 list_for_each(node_ptr, &patchbay_ptr->graph.clients)
325 client_ptr = list_entry(node_ptr, struct jack_graph_client, siblings);
326 if (strlen(client_ptr->name) == client_name_len && strncmp(client_ptr->name, client_name, client_name_len) == 0)
328 return client_ptr;
332 return NULL;
335 static
336 struct jack_graph_client *
337 jack_controller_patchbay_find_client_by_id(
338 struct jack_controller_patchbay *patchbay_ptr,
339 uint64_t id)
341 struct list_head *node_ptr;
342 struct jack_graph_client *client_ptr;
344 list_for_each(node_ptr, &patchbay_ptr->graph.clients)
346 client_ptr = list_entry(node_ptr, struct jack_graph_client, siblings);
347 if (client_ptr->id == id)
349 return client_ptr;
353 return NULL;
356 static
357 struct jack_graph_client *
358 jack_controller_patchbay_create_client(
359 struct jack_controller_patchbay *patchbay_ptr,
360 const char *client_name, /* not '\0' terminated */
361 size_t client_name_len) /* without terminating '\0' */
363 struct jack_graph_client * client_ptr;
365 client_ptr = malloc(sizeof(struct jack_graph_client));
366 if (client_ptr == NULL)
368 jack_error("Memory allocation of jack_graph_client structure failed.");
369 goto fail;
372 client_ptr->name = malloc(client_name_len + 1);
373 if (client_ptr->name == NULL)
375 jack_error("malloc() failed to allocate memory for client name.");
376 goto fail_free_client;
379 memcpy(client_ptr->name, client_name, client_name_len);
380 client_ptr->name[client_name_len] = 0;
382 client_ptr->pid = jack_get_client_pid(client_ptr->name);
383 jack_info("New client '%s' with PID %d", client_ptr->name, client_ptr->pid);
385 client_ptr->id = patchbay_ptr->next_client_id++;
386 INIT_LIST_HEAD(&client_ptr->ports);
389 pthread_mutex_lock(&patchbay_ptr->lock);
390 list_add_tail(&client_ptr->siblings, &patchbay_ptr->graph.clients);
391 patchbay_ptr->graph.version++;
392 jack_controller_patchbay_send_signal_client_appeared(patchbay_ptr->graph.version, client_ptr->id, client_ptr->name);
393 jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version);
394 pthread_mutex_unlock(&patchbay_ptr->lock);
396 return client_ptr;
398 fail_free_client:
399 free(client_ptr);
401 fail:
402 return NULL;
405 static
406 void
407 jack_controller_patchbay_destroy_client(
408 struct jack_controller_patchbay *patchbay_ptr,
409 struct jack_graph_client *client_ptr)
411 jack_info("Client '%s' with PID %d is out", client_ptr->name, client_ptr->pid);
413 pthread_mutex_lock(&patchbay_ptr->lock);
414 list_del(&client_ptr->siblings);
415 patchbay_ptr->graph.version++;
416 jack_controller_patchbay_send_signal_client_disappeared(patchbay_ptr->graph.version, client_ptr->id, client_ptr->name);
417 jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version);
418 pthread_mutex_unlock(&patchbay_ptr->lock);
420 free(client_ptr->name);
421 free(client_ptr);
424 static
425 void
426 jack_controller_patchbay_destroy_client_by_name(
427 struct jack_controller_patchbay *patchbay_ptr,
428 const char *client_name) /* '\0' terminated */
430 struct jack_graph_client *client_ptr;
432 client_ptr = jack_controller_patchbay_find_client(patchbay_ptr, client_name, strlen(client_name));
433 if (client_ptr == NULL)
435 jack_error("Cannot destroy unknown client '%s'", client_name);
436 return;
439 jack_controller_patchbay_destroy_client(patchbay_ptr, client_ptr);
442 static
443 void
444 jack_controller_patchbay_new_port(
445 struct jack_controller_patchbay *patchbay_ptr,
446 const char *port_full_name,
447 uint32_t port_flags,
448 uint32_t port_type)
450 struct jack_graph_client *client_ptr;
451 struct jack_graph_port *port_ptr;
452 const char *port_short_name;
453 size_t client_name_len;
455 //jack_info("new port: %s", port_full_name);
457 port_short_name = strchr(port_full_name, ':');
458 if (port_short_name == NULL)
460 jack_error("port name '%s' does not contain ':' separator char", port_full_name);
461 return;
464 port_short_name++; /* skip ':' separator char */
466 client_name_len = port_short_name - port_full_name - 1; /* without terminating '\0' */
468 client_ptr = jack_controller_patchbay_find_client(patchbay_ptr, port_full_name, client_name_len);
469 if (client_ptr == NULL)
471 client_ptr = jack_controller_patchbay_create_client(patchbay_ptr, port_full_name, client_name_len);
472 if (client_ptr == NULL)
474 jack_error("Creation of new jack_graph client failed.");
475 return;
479 port_ptr = malloc(sizeof(struct jack_graph_port));
480 if (port_ptr == NULL)
482 jack_error("Memory allocation of jack_graph_port structure failed.");
483 return;
486 port_ptr->name = strdup(port_short_name);
487 if (port_ptr->name == NULL)
489 jack_error("strdup() call for port name '%s' failed.", port_short_name);
490 free(port_ptr);
491 return;
494 port_ptr->id = patchbay_ptr->next_port_id++;
495 port_ptr->flags = port_flags;
496 port_ptr->type = port_type;
497 port_ptr->client = client_ptr;
499 pthread_mutex_lock(&patchbay_ptr->lock);
500 list_add_tail(&port_ptr->siblings_client, &client_ptr->ports);
501 list_add_tail(&port_ptr->siblings_graph, &patchbay_ptr->graph.ports);
502 patchbay_ptr->graph.version++;
503 jack_controller_patchbay_send_signal_port_appeared(
504 patchbay_ptr->graph.version,
505 client_ptr->id,
506 client_ptr->name,
507 port_ptr->id,
508 port_ptr->name,
509 port_ptr->flags,
510 port_ptr->type);
511 jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version);
512 pthread_mutex_unlock(&patchbay_ptr->lock);
515 static
516 void
517 jack_controller_patchbay_remove_port(
518 struct jack_controller_patchbay *patchbay_ptr,
519 struct jack_graph_port *port_ptr)
521 //jack_info("remove port: %s", port_ptr->name);
523 pthread_mutex_lock(&patchbay_ptr->lock);
524 list_del(&port_ptr->siblings_client);
525 list_del(&port_ptr->siblings_graph);
526 patchbay_ptr->graph.version++;
527 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);
528 jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version);
529 pthread_mutex_unlock(&patchbay_ptr->lock);
531 free(port_ptr->name);
532 free(port_ptr);
535 static
536 struct jack_graph_port *
537 jack_controller_patchbay_find_port_by_id(
538 struct jack_controller_patchbay *patchbay_ptr,
539 uint64_t port_id)
541 struct list_head *node_ptr;
542 struct jack_graph_port *port_ptr;
544 list_for_each(node_ptr, &patchbay_ptr->graph.ports)
546 port_ptr = list_entry(node_ptr, struct jack_graph_port, siblings_graph);
547 if (port_ptr->id == port_id)
549 return port_ptr;
553 return NULL;
556 static
557 struct jack_graph_port *
558 jack_controller_patchbay_find_client_port_by_name(
559 struct jack_controller_patchbay *patchbay_ptr,
560 struct jack_graph_client *client_ptr,
561 const char *port_name)
563 struct list_head *node_ptr;
564 struct jack_graph_port *port_ptr;
566 list_for_each(node_ptr, &client_ptr->ports)
568 port_ptr = list_entry(node_ptr, struct jack_graph_port, siblings_client);
569 if (strcmp(port_ptr->name, port_name) == 0)
571 return port_ptr;
575 return NULL;
578 static
579 struct jack_graph_port *
580 jack_controller_patchbay_find_port_by_full_name(
581 struct jack_controller_patchbay *patchbay_ptr,
582 const char *port_full_name)
584 const char *port_short_name;
585 size_t client_name_len;
586 struct jack_graph_client *client_ptr;
588 //jack_info("name: %s", port_full_name);
590 port_short_name = strchr(port_full_name, ':');
591 if (port_short_name == NULL)
593 jack_error("port name '%s' does not contain ':' separator char", port_full_name);
594 return NULL;
597 port_short_name++; /* skip ':' separator char */
599 client_name_len = port_short_name - port_full_name - 1; /* without terminating '\0' */
601 client_ptr = jack_controller_patchbay_find_client(patchbay_ptr, port_full_name, client_name_len);
602 if (client_ptr == NULL)
604 jack_error("cannot find client of port '%s'", port_full_name);
605 return NULL;
608 return jack_controller_patchbay_find_client_port_by_name(patchbay_ptr, client_ptr, port_short_name);
611 static
612 struct jack_graph_port *
613 jack_controller_patchbay_find_port_by_names(
614 struct jack_controller_patchbay *patchbay_ptr,
615 const char *client_name,
616 const char *port_name)
618 struct jack_graph_client *client_ptr;
620 client_ptr = jack_controller_patchbay_find_client(patchbay_ptr, client_name, strlen(client_name));
621 if (client_ptr == NULL)
623 jack_error("cannot find client '%s'", client_name);
624 return NULL;
627 return jack_controller_patchbay_find_client_port_by_name(patchbay_ptr, client_ptr, port_name);
630 static
631 struct jack_graph_connection *
632 jack_controller_patchbay_create_connection(
633 struct jack_controller_patchbay *patchbay_ptr,
634 struct jack_graph_port *port1_ptr,
635 struct jack_graph_port *port2_ptr)
637 struct jack_graph_connection * connection_ptr;
639 connection_ptr = malloc(sizeof(struct jack_graph_connection));
640 if (connection_ptr == NULL)
642 jack_error("Memory allocation of jack_graph_connection structure failed.");
643 return NULL;
646 connection_ptr->id = patchbay_ptr->next_connection_id++;
647 connection_ptr->port1 = port1_ptr;
648 connection_ptr->port2 = port2_ptr;
650 pthread_mutex_lock(&patchbay_ptr->lock);
651 list_add_tail(&connection_ptr->siblings, &patchbay_ptr->graph.connections);
652 patchbay_ptr->graph.version++;
653 jack_controller_patchbay_send_signal_ports_connected(
654 patchbay_ptr->graph.version,
655 port1_ptr->client->id,
656 port1_ptr->client->name,
657 port1_ptr->id,
658 port1_ptr->name,
659 port2_ptr->client->id,
660 port2_ptr->client->name,
661 port2_ptr->id,
662 port2_ptr->name,
663 connection_ptr->id);
664 jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version);
665 pthread_mutex_unlock(&patchbay_ptr->lock);
667 return connection_ptr;
670 static
671 void
672 jack_controller_patchbay_destroy_connection(
673 struct jack_controller_patchbay *patchbay_ptr,
674 struct jack_graph_connection *connection_ptr)
676 pthread_mutex_lock(&patchbay_ptr->lock);
677 list_del(&connection_ptr->siblings);
678 patchbay_ptr->graph.version++;
679 jack_controller_patchbay_send_signal_ports_disconnected(
680 patchbay_ptr->graph.version,
681 connection_ptr->port1->client->id,
682 connection_ptr->port1->client->name,
683 connection_ptr->port1->id,
684 connection_ptr->port1->name,
685 connection_ptr->port2->client->id,
686 connection_ptr->port2->client->name,
687 connection_ptr->port2->id,
688 connection_ptr->port2->name,
689 connection_ptr->id);
690 jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version);
691 pthread_mutex_unlock(&patchbay_ptr->lock);
693 free(connection_ptr);
696 static
697 struct jack_graph_connection *
698 jack_controller_patchbay_find_connection(
699 struct jack_controller_patchbay *patchbay_ptr,
700 struct jack_graph_port *port1_ptr,
701 struct jack_graph_port *port2_ptr)
703 struct list_head *node_ptr;
704 struct jack_graph_connection *connection_ptr;
706 list_for_each(node_ptr, &patchbay_ptr->graph.connections)
708 connection_ptr = list_entry(node_ptr, struct jack_graph_connection, siblings);
709 if ((connection_ptr->port1 == port1_ptr &&
710 connection_ptr->port2 == port2_ptr) ||
711 (connection_ptr->port1 == port2_ptr &&
712 connection_ptr->port2 == port1_ptr))
714 return connection_ptr;
718 return NULL;
721 static
722 struct jack_graph_connection *
723 jack_controller_patchbay_find_connection_by_id(
724 struct jack_controller_patchbay *patchbay_ptr,
725 uint64_t connection_id)
727 struct list_head *node_ptr;
728 struct jack_graph_connection *connection_ptr;
730 list_for_each(node_ptr, &patchbay_ptr->graph.connections)
732 connection_ptr = list_entry(node_ptr, struct jack_graph_connection, siblings);
733 if (connection_ptr->id == connection_id)
735 return connection_ptr;
739 return NULL;
742 static
743 bool
744 jack_controller_patchbay_connect(
745 struct jack_dbus_method_call *dbus_call_ptr,
746 struct jack_controller *controller_ptr,
747 struct jack_graph_port *port1_ptr,
748 struct jack_graph_port *port2_ptr)
750 int ret;
751 char port1_name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
752 char port2_name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
754 sprintf(port1_name, "%s:%s", port1_ptr->client->name, port1_ptr->name);
755 sprintf(port2_name, "%s:%s", port2_ptr->client->name, port2_ptr->name);
757 ret = jack_connect(controller_ptr->client, port1_name, port2_name);
758 if (ret != 0)
760 jack_dbus_error(dbus_call_ptr, JACK_DBUS_ERROR_GENERIC, "jack_connect() failed with %d", ret);
761 return false;
764 return true;
767 static
768 bool
769 jack_controller_patchbay_disconnect(
770 struct jack_dbus_method_call *dbus_call_ptr,
771 struct jack_controller *controller_ptr,
772 struct jack_graph_port *port1_ptr,
773 struct jack_graph_port *port2_ptr)
775 int ret;
776 char port1_name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
777 char port2_name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
779 sprintf(port1_name, "%s:%s", port1_ptr->client->name, port1_ptr->name);
780 sprintf(port2_name, "%s:%s", port2_ptr->client->name, port2_ptr->name);
782 ret = jack_disconnect(controller_ptr->client, port1_name, port2_name);
783 if (ret != 0)
785 jack_dbus_error(dbus_call_ptr, JACK_DBUS_ERROR_GENERIC, "jack_disconnect() failed with %d", ret);
786 return false;
789 return true;
792 #define controller_ptr ((struct jack_controller *)call->context)
793 #define patchbay_ptr ((struct jack_controller_patchbay *)controller_ptr->patchbay_context)
795 static
796 void
797 jack_controller_dbus_get_all_ports(
798 struct jack_dbus_method_call * call)
800 struct list_head * client_node_ptr;
801 struct list_head * port_node_ptr;
802 struct jack_graph_client * client_ptr;
803 struct jack_graph_port * port_ptr;
804 DBusMessageIter iter, sub_iter;
805 char fullname[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
806 char *fullname_var = fullname;
808 if (!controller_ptr->started)
810 jack_dbus_error(
811 call,
812 JACK_DBUS_ERROR_SERVER_NOT_RUNNING,
813 "Can't execute this method with stopped JACK server");
814 return;
817 call->reply = dbus_message_new_method_return (call->message);
818 if (!call->reply)
820 goto fail;
823 dbus_message_iter_init_append (call->reply, &iter);
825 if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s", &sub_iter))
827 goto fail_unref;
830 pthread_mutex_lock(&patchbay_ptr->lock);
832 list_for_each(client_node_ptr, &patchbay_ptr->graph.clients)
834 client_ptr = list_entry(client_node_ptr, struct jack_graph_client, siblings);
836 list_for_each(port_node_ptr, &client_ptr->ports)
838 port_ptr = list_entry(port_node_ptr, struct jack_graph_port, siblings_client);
840 jack_info("%s:%s", client_ptr->name, port_ptr->name);
841 sprintf(fullname, "%s:%s", client_ptr->name, port_ptr->name);
842 if (!dbus_message_iter_append_basic (&sub_iter, DBUS_TYPE_STRING, &fullname_var))
844 pthread_mutex_unlock(&patchbay_ptr->lock);
845 dbus_message_iter_close_container (&iter, &sub_iter);
846 goto fail_unref;
851 pthread_mutex_unlock(&patchbay_ptr->lock);
853 if (!dbus_message_iter_close_container (&iter, &sub_iter))
855 goto fail_unref;
858 return;
860 fail_unref:
861 dbus_message_unref (call->reply);
862 call->reply = NULL;
864 fail:
865 jack_error ("Ran out of memory trying to construct method return");
868 static
869 void
870 jack_controller_dbus_get_graph(
871 struct jack_dbus_method_call * call)
873 struct list_head * client_node_ptr;
874 struct list_head * port_node_ptr;
875 struct list_head * connection_node_ptr;
876 struct jack_graph_client * client_ptr;
877 struct jack_graph_port * port_ptr;
878 struct jack_graph_connection * connection_ptr;
879 DBusMessageIter iter;
880 DBusMessageIter clients_array_iter;
881 DBusMessageIter client_struct_iter;
882 DBusMessageIter ports_array_iter;
883 DBusMessageIter port_struct_iter;
884 dbus_uint64_t version;
885 DBusMessageIter connections_array_iter;
886 DBusMessageIter connection_struct_iter;
888 if (!controller_ptr->started)
890 jack_dbus_error(
891 call,
892 JACK_DBUS_ERROR_SERVER_NOT_RUNNING,
893 "Can't execute this method with stopped JACK server");
894 return;
897 if (!jack_dbus_get_method_args(call, DBUS_TYPE_UINT64, &version, DBUS_TYPE_INVALID))
899 /* The method call had invalid arguments meaning that
900 * jack_dbus_get_method_args() has constructed an error for us.
902 goto exit;
905 //jack_info("Getting graph, know version is %" PRIu32, version);
907 call->reply = dbus_message_new_method_return(call->message);
908 if (!call->reply)
910 jack_error("Ran out of memory trying to construct method return");
911 goto exit;
914 dbus_message_iter_init_append (call->reply, &iter);
916 pthread_mutex_lock(&patchbay_ptr->lock);
918 if (version > patchbay_ptr->graph.version)
920 jack_dbus_error(
921 call,
922 JACK_DBUS_ERROR_INVALID_ARGS,
923 "known graph version %" PRIu64 " is newer than actual version %" PRIu64,
924 version,
925 patchbay_ptr->graph.version);
926 pthread_mutex_unlock(&patchbay_ptr->lock);
927 goto exit;
930 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT64, &patchbay_ptr->graph.version))
932 goto nomem_unlock;
935 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(tsa(tsuu))", &clients_array_iter))
937 goto nomem_unlock;
940 if (version < patchbay_ptr->graph.version)
942 list_for_each(client_node_ptr, &patchbay_ptr->graph.clients)
944 client_ptr = list_entry(client_node_ptr, struct jack_graph_client, siblings);
946 if (!dbus_message_iter_open_container (&clients_array_iter, DBUS_TYPE_STRUCT, NULL, &client_struct_iter))
948 goto nomem_close_clients_array;
951 if (!dbus_message_iter_append_basic(&client_struct_iter, DBUS_TYPE_UINT64, &client_ptr->id))
953 goto nomem_close_client_struct;
956 if (!dbus_message_iter_append_basic(&client_struct_iter, DBUS_TYPE_STRING, &client_ptr->name))
958 goto nomem_close_client_struct;
961 if (!dbus_message_iter_open_container(&client_struct_iter, DBUS_TYPE_ARRAY, "(tsuu)", &ports_array_iter))
963 goto nomem_close_client_struct;
966 list_for_each(port_node_ptr, &client_ptr->ports)
968 port_ptr = list_entry(port_node_ptr, struct jack_graph_port, siblings_client);
970 if (!dbus_message_iter_open_container(&ports_array_iter, DBUS_TYPE_STRUCT, NULL, &port_struct_iter))
972 goto nomem_close_ports_array;
975 if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT64, &port_ptr->id))
977 goto nomem_close_port_struct;
980 if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_STRING, &port_ptr->name))
982 goto nomem_close_port_struct;
985 if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT32, &port_ptr->flags))
987 goto nomem_close_port_struct;
990 if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT32, &port_ptr->type))
992 goto nomem_close_port_struct;
995 if (!dbus_message_iter_close_container(&ports_array_iter, &port_struct_iter))
997 goto nomem_close_ports_array;
1001 if (!dbus_message_iter_close_container(&client_struct_iter, &ports_array_iter))
1003 goto nomem_close_client_struct;
1006 if (!dbus_message_iter_close_container(&clients_array_iter, &client_struct_iter))
1008 goto nomem_close_clients_array;
1013 if (!dbus_message_iter_close_container(&iter, &clients_array_iter))
1015 goto nomem_unlock;
1018 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(tstststst)", &connections_array_iter))
1020 goto nomem_unlock;
1023 if (version < patchbay_ptr->graph.version)
1025 list_for_each(connection_node_ptr, &patchbay_ptr->graph.connections)
1027 connection_ptr = list_entry(connection_node_ptr, struct jack_graph_connection, siblings);
1029 if (!dbus_message_iter_open_container(&connections_array_iter, DBUS_TYPE_STRUCT, NULL, &connection_struct_iter))
1031 goto nomem_close_connections_array;
1034 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port1->client->id))
1036 goto nomem_close_connection_struct;
1039 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port1->client->name))
1041 goto nomem_close_connection_struct;
1044 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port1->id))
1046 goto nomem_close_connection_struct;
1049 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port1->name))
1051 goto nomem_close_connection_struct;
1054 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port2->client->id))
1056 goto nomem_close_connection_struct;
1059 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port2->client->name))
1061 goto nomem_close_connection_struct;
1064 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port2->id))
1066 goto nomem_close_connection_struct;
1069 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port2->name))
1071 goto nomem_close_connection_struct;
1074 if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->id))
1076 goto nomem_close_connection_struct;
1079 if (!dbus_message_iter_close_container(&connections_array_iter, &connection_struct_iter))
1081 goto nomem_close_connections_array;
1086 if (!dbus_message_iter_close_container(&iter, &connections_array_iter))
1088 goto nomem_unlock;
1091 pthread_mutex_unlock(&patchbay_ptr->lock);
1093 return;
1095 nomem_close_connection_struct:
1096 dbus_message_iter_close_container(&connections_array_iter, &connection_struct_iter);
1098 nomem_close_connections_array:
1099 dbus_message_iter_close_container(&iter, &connections_array_iter);
1100 goto nomem_unlock;
1102 nomem_close_port_struct:
1103 dbus_message_iter_close_container(&ports_array_iter, &port_struct_iter);
1105 nomem_close_ports_array:
1106 dbus_message_iter_close_container(&client_struct_iter, &ports_array_iter);
1108 nomem_close_client_struct:
1109 dbus_message_iter_close_container(&clients_array_iter, &client_struct_iter);
1111 nomem_close_clients_array:
1112 dbus_message_iter_close_container(&iter, &clients_array_iter);
1114 nomem_unlock:
1115 pthread_mutex_unlock(&patchbay_ptr->lock);
1117 //nomem:
1118 dbus_message_unref(call->reply);
1119 call->reply = NULL;
1120 jack_error("Ran out of memory trying to construct method return");
1122 exit:
1123 return;
1126 static
1127 void
1128 jack_controller_dbus_connect_ports_by_name(
1129 struct jack_dbus_method_call * call)
1131 const char * client1_name;
1132 const char * port1_name;
1133 const char * client2_name;
1134 const char * port2_name;
1135 struct jack_graph_port *port1_ptr;
1136 struct jack_graph_port *port2_ptr;
1138 /* jack_info("jack_controller_dbus_connect_ports_by_name() called."); */
1140 if (!controller_ptr->started)
1142 jack_dbus_error(
1143 call,
1144 JACK_DBUS_ERROR_SERVER_NOT_RUNNING,
1145 "Can't execute this method with stopped JACK server");
1146 return;
1149 if (!jack_dbus_get_method_args(
1150 call,
1151 DBUS_TYPE_STRING,
1152 &client1_name,
1153 DBUS_TYPE_STRING,
1154 &port1_name,
1155 DBUS_TYPE_STRING,
1156 &client2_name,
1157 DBUS_TYPE_STRING,
1158 &port2_name,
1159 DBUS_TYPE_INVALID))
1161 /* The method call had invalid arguments meaning that
1162 * jack_dbus_get_method_args() has constructed an error for us.
1164 return;
1167 /* jack_info("connecting %s:%s and %s:%s", client1_name, port1_name, client2_name, port2_name); */
1169 pthread_mutex_lock(&patchbay_ptr->lock);
1171 port1_ptr = jack_controller_patchbay_find_port_by_names(patchbay_ptr, client1_name, port1_name);
1172 if (port1_ptr == NULL)
1174 jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port '%s':'%s'", client1_name, port1_name);
1175 goto unlock;
1178 port2_ptr = jack_controller_patchbay_find_port_by_names(patchbay_ptr, client2_name, port2_name);
1179 if (port2_ptr == NULL)
1181 jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port '%s':'%s'", client2_name, port2_name);
1182 goto unlock;
1185 if (!jack_controller_patchbay_connect(
1186 call,
1187 controller_ptr,
1188 port1_ptr,
1189 port2_ptr))
1191 /* jack_controller_patchbay_connect() constructed error reply */
1192 goto unlock;
1195 jack_dbus_construct_method_return_empty(call);
1197 unlock:
1198 pthread_mutex_unlock(&patchbay_ptr->lock);
1201 static
1202 void
1203 jack_controller_dbus_connect_ports_by_id(
1204 struct jack_dbus_method_call * call)
1206 dbus_uint64_t port1_id;
1207 dbus_uint64_t port2_id;
1208 struct jack_graph_port *port1_ptr;
1209 struct jack_graph_port *port2_ptr;
1211 /* jack_info("jack_controller_dbus_connect_ports_by_id() called."); */
1213 if (!controller_ptr->started)
1215 jack_dbus_error(
1216 call,
1217 JACK_DBUS_ERROR_SERVER_NOT_RUNNING,
1218 "Can't execute this method with stopped JACK server");
1219 return;
1222 if (!jack_dbus_get_method_args(
1223 call,
1224 DBUS_TYPE_UINT64,
1225 &port1_id,
1226 DBUS_TYPE_UINT64,
1227 &port2_id,
1228 DBUS_TYPE_INVALID))
1230 /* The method call had invalid arguments meaning that
1231 * jack_dbus_get_method_args() has constructed an error for us.
1233 return;
1236 pthread_mutex_lock(&patchbay_ptr->lock);
1238 port1_ptr = jack_controller_patchbay_find_port_by_id(patchbay_ptr, port1_id);
1239 if (port1_ptr == NULL)
1241 jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port %" PRIu64, port1_id);
1242 goto unlock;
1245 port2_ptr = jack_controller_patchbay_find_port_by_id(patchbay_ptr, port2_id);
1246 if (port2_ptr == NULL)
1248 jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port %" PRIu64, port2_id);
1249 goto unlock;
1252 if (!jack_controller_patchbay_connect(
1253 call,
1254 controller_ptr,
1255 port1_ptr,
1256 port2_ptr))
1258 /* jack_controller_patchbay_connect() constructed error reply */
1259 goto unlock;
1262 jack_dbus_construct_method_return_empty(call);
1264 unlock:
1265 pthread_mutex_unlock(&patchbay_ptr->lock);
1268 static
1269 void
1270 jack_controller_dbus_disconnect_ports_by_name(
1271 struct jack_dbus_method_call * call)
1273 const char * client1_name;
1274 const char * port1_name;
1275 const char * client2_name;
1276 const char * port2_name;
1277 struct jack_graph_port *port1_ptr;
1278 struct jack_graph_port *port2_ptr;
1280 /* jack_info("jack_controller_dbus_disconnect_ports_by_name() called."); */
1282 if (!controller_ptr->started)
1284 jack_dbus_error(
1285 call,
1286 JACK_DBUS_ERROR_SERVER_NOT_RUNNING,
1287 "Can't execute this method with stopped JACK server");
1288 return;
1291 if (!jack_dbus_get_method_args(
1292 call,
1293 DBUS_TYPE_STRING,
1294 &client1_name,
1295 DBUS_TYPE_STRING,
1296 &port1_name,
1297 DBUS_TYPE_STRING,
1298 &client2_name,
1299 DBUS_TYPE_STRING,
1300 &port2_name,
1301 DBUS_TYPE_INVALID))
1303 /* The method call had invalid arguments meaning that
1304 * jack_dbus_get_method_args() has constructed an error for us.
1306 return;
1309 /* jack_info("disconnecting %s:%s and %s:%s", client1_name, port1_name, client2_name, port2_name); */
1311 pthread_mutex_lock(&patchbay_ptr->lock);
1313 port1_ptr = jack_controller_patchbay_find_port_by_names(patchbay_ptr, client1_name, port1_name);
1314 if (port1_ptr == NULL)
1316 jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port '%s':'%s'", client1_name, port1_name);
1317 goto unlock;
1320 port2_ptr = jack_controller_patchbay_find_port_by_names(patchbay_ptr, client2_name, port2_name);
1321 if (port2_ptr == NULL)
1323 jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port '%s':'%s'", client2_name, port2_name);
1324 goto unlock;
1327 if (!jack_controller_patchbay_disconnect(
1328 call,
1329 controller_ptr,
1330 port1_ptr,
1331 port2_ptr))
1333 /* jack_controller_patchbay_connect() constructed error reply */
1334 goto unlock;
1337 jack_dbus_construct_method_return_empty(call);
1339 unlock:
1340 pthread_mutex_unlock(&patchbay_ptr->lock);
1343 static
1344 void
1345 jack_controller_dbus_disconnect_ports_by_id(
1346 struct jack_dbus_method_call * call)
1348 dbus_uint64_t port1_id;
1349 dbus_uint64_t port2_id;
1350 struct jack_graph_port *port1_ptr;
1351 struct jack_graph_port *port2_ptr;
1353 /* jack_info("jack_controller_dbus_disconnect_ports_by_id() called."); */
1355 if (!controller_ptr->started)
1357 jack_dbus_error(
1358 call,
1359 JACK_DBUS_ERROR_SERVER_NOT_RUNNING,
1360 "Can't execute this method with stopped JACK server");
1361 return;
1364 if (!jack_dbus_get_method_args(
1365 call,
1366 DBUS_TYPE_UINT64,
1367 &port1_id,
1368 DBUS_TYPE_UINT64,
1369 &port2_id,
1370 DBUS_TYPE_INVALID))
1372 /* The method call had invalid arguments meaning that
1373 * jack_dbus_get_method_args() has constructed an error for us.
1375 return;
1378 pthread_mutex_lock(&patchbay_ptr->lock);
1380 port1_ptr = jack_controller_patchbay_find_port_by_id(patchbay_ptr, port1_id);
1381 if (port1_ptr == NULL)
1383 jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port %" PRIu64, port1_id);
1384 goto unlock;
1387 port2_ptr = jack_controller_patchbay_find_port_by_id(patchbay_ptr, port2_id);
1388 if (port2_ptr == NULL)
1390 jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port %" PRIu64, port2_id);
1391 goto unlock;
1394 if (!jack_controller_patchbay_disconnect(
1395 call,
1396 controller_ptr,
1397 port1_ptr,
1398 port2_ptr))
1400 /* jack_controller_patchbay_connect() constructed error reply */
1401 goto unlock;
1404 jack_dbus_construct_method_return_empty(call);
1406 unlock:
1407 pthread_mutex_unlock(&patchbay_ptr->lock);
1410 static
1411 void
1412 jack_controller_dbus_disconnect_ports_by_connection_id(
1413 struct jack_dbus_method_call * call)
1415 dbus_uint64_t connection_id;
1416 struct jack_graph_connection *connection_ptr;
1418 /* jack_info("jack_controller_dbus_disconnect_ports_by_id() called."); */
1420 if (!jack_dbus_get_method_args(
1421 call,
1422 DBUS_TYPE_UINT64,
1423 &connection_id,
1424 DBUS_TYPE_INVALID))
1426 /* The method call had invalid arguments meaning that
1427 * jack_dbus_get_method_args() has constructed an error for us.
1429 return;
1432 pthread_mutex_lock(&patchbay_ptr->lock);
1434 connection_ptr = jack_controller_patchbay_find_connection_by_id(patchbay_ptr, connection_id);
1435 if (connection_ptr == NULL)
1437 jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find connection %" PRIu64, connection_id);
1438 goto unlock;
1441 if (!jack_controller_patchbay_disconnect(
1442 call,
1443 controller_ptr,
1444 connection_ptr->port1,
1445 connection_ptr->port2))
1447 /* jack_controller_patchbay_connect() constructed error reply */
1448 goto unlock;
1451 jack_dbus_construct_method_return_empty(call);
1453 unlock:
1454 pthread_mutex_unlock(&patchbay_ptr->lock);
1457 static
1458 void
1459 jack_controller_dbus_get_client_pid(
1460 struct jack_dbus_method_call * call)
1462 dbus_uint64_t client_id;
1463 struct jack_graph_client *client_ptr;
1464 message_arg_t arg;
1466 /* jack_info("jack_controller_dbus_get_client_pid() called."); */
1468 if (!jack_dbus_get_method_args(
1469 call,
1470 DBUS_TYPE_UINT64,
1471 &client_id,
1472 DBUS_TYPE_INVALID))
1474 /* The method call had invalid arguments meaning that
1475 * jack_dbus_get_method_args() has constructed an error for us.
1477 return;
1480 pthread_mutex_lock(&patchbay_ptr->lock);
1482 client_ptr = jack_controller_patchbay_find_client_by_id(patchbay_ptr, client_id);
1483 if (client_ptr == NULL)
1485 jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find client %" PRIu64, client_id);
1486 goto unlock;
1489 arg.int64 = client_ptr->pid;
1491 jack_dbus_construct_method_return_single(call, DBUS_TYPE_INT64, arg);
1493 unlock:
1494 pthread_mutex_unlock(&patchbay_ptr->lock);
1497 #undef controller_ptr
1498 #define controller_ptr ((struct jack_controller *)context)
1500 static
1502 jack_controller_graph_order_callback(
1503 void *context)
1505 const char **ports;
1506 int i;
1507 jack_port_t *port_ptr;
1509 if (patchbay_ptr->graph.version > 1)
1511 /* we use this only for initial catchup */
1512 return 0;
1515 ports = jack_get_ports(controller_ptr->client, NULL, NULL, 0);
1516 if (ports)
1518 for (i = 0; ports[i]; ++i)
1520 jack_info("graph reorder: new port '%s'", ports[i]);
1521 port_ptr = jack_port_by_name(controller_ptr->client, ports[i]);;
1522 jack_controller_patchbay_new_port(patchbay_ptr, ports[i], jack_port_flags(port_ptr), jack_port_type_id(port_ptr));
1525 free(ports);
1528 if (patchbay_ptr->graph.version == 1)
1530 /* we have empty initial graph, increment graph version,
1531 so we don't do jack_get_ports() again,
1532 on next next graph change */
1533 patchbay_ptr->graph.version++;
1536 return 0;
1539 void
1540 jack_controller_client_registration_callback(
1541 const char *client_name,
1542 int created,
1543 void *context)
1545 if (created)
1547 jack_log("client '%s' created", client_name);
1548 jack_controller_patchbay_create_client(patchbay_ptr, client_name, strlen(client_name));
1550 else
1552 jack_log("client '%s' destroyed", client_name);
1553 jack_controller_patchbay_destroy_client_by_name(patchbay_ptr, client_name);
1557 void
1558 jack_controller_port_registration_callback(
1559 jack_port_id_t port_id,
1560 int created,
1561 void *context)
1563 jack_port_t *port_ptr;
1564 struct jack_graph_port *graph_port_ptr;
1565 const char *port_name;
1567 port_ptr = jack_port_by_id(controller_ptr->client, port_id);
1568 port_name = jack_port_name(port_ptr);
1570 if (created)
1572 jack_log("port '%s' created", port_name);
1573 jack_controller_patchbay_new_port(patchbay_ptr, port_name, jack_port_flags(port_ptr), jack_port_type_id(port_ptr));
1575 else
1577 jack_log("port '%s' destroyed", port_name);
1578 graph_port_ptr = jack_controller_patchbay_find_port_by_full_name(patchbay_ptr, port_name);
1579 if (graph_port_ptr == NULL)
1581 jack_error("Failed to find port '%s' to destroy", port_name);
1582 return;
1585 jack_controller_patchbay_remove_port(patchbay_ptr, graph_port_ptr);
1589 void
1590 jack_controller_port_connect_callback(
1591 jack_port_id_t port1_id,
1592 jack_port_id_t port2_id,
1593 int connect,
1594 void *context)
1596 jack_port_t *port1;
1597 jack_port_t *port2;
1598 const char *port1_name;
1599 const char *port2_name;
1600 struct jack_graph_port *port1_ptr;
1601 struct jack_graph_port *port2_ptr;
1602 struct jack_graph_connection *connection_ptr;
1604 port1 = jack_port_by_id(controller_ptr->client, port1_id);
1605 port2 = jack_port_by_id(controller_ptr->client, port2_id);
1607 port1_name = jack_port_name(port1);
1608 port2_name = jack_port_name(port2);
1610 port1_ptr = jack_controller_patchbay_find_port_by_full_name(patchbay_ptr, port1_name);
1611 if (port1_ptr == NULL)
1613 jack_error("Failed to find port '%s' to [dis]connect", port1_name);
1614 return;
1617 port2_ptr = jack_controller_patchbay_find_port_by_full_name(patchbay_ptr, port2_name);
1618 if (port2_ptr == NULL)
1620 jack_error("Failed to find port '%s' to [dis]connect", port2_name);
1621 return;
1624 if (connect)
1626 jack_info("Connecting '%s' to '%s'", port1_name, port2_name);
1627 connection_ptr = jack_controller_patchbay_find_connection(patchbay_ptr, port1_ptr, port2_ptr);
1628 if (connection_ptr != NULL)
1630 jack_error("'%s' and '%s' are already connected", port1_name, port2_name);
1631 return;
1634 jack_controller_patchbay_create_connection(patchbay_ptr, port1_ptr, port2_ptr);
1636 else
1638 jack_info("Disconnecting '%s' from '%s'", port1_name, port2_name);
1639 connection_ptr = jack_controller_patchbay_find_connection(patchbay_ptr, port1_ptr, port2_ptr);
1640 if (connection_ptr == NULL)
1642 jack_error("Cannot find connection being removed");
1643 return;
1646 jack_controller_patchbay_destroy_connection(patchbay_ptr, connection_ptr);
1650 void jack_controller_port_rename_callback(jack_port_id_t port, const char * old_name, const char * new_name, void * context)
1652 struct jack_graph_port * port_ptr;
1653 const char * port_new_short_name;
1654 const char * port_old_short_name;
1655 char * name_buffer;
1657 jack_info("port renamed: '%s' -> '%s'", old_name, new_name);
1659 port_new_short_name = strchr(new_name, ':');
1660 if (port_new_short_name == NULL)
1662 jack_error("renamed port new name '%s' does not contain ':' separator char", new_name);
1663 return;
1666 port_new_short_name++; /* skip ':' separator char */
1668 port_old_short_name = strchr(old_name, ':');
1669 if (port_old_short_name == NULL)
1671 jack_error("renamed port old name '%s' does not contain ':' separator char", old_name);
1672 return;
1675 port_old_short_name++; /* skip ':' separator char */
1677 port_ptr = jack_controller_patchbay_find_port_by_full_name(patchbay_ptr, old_name);
1678 if (port_ptr == NULL)
1680 jack_error("renamed port '%s' not found", old_name);
1681 return;
1684 name_buffer = strdup(port_new_short_name);
1685 if (name_buffer == NULL)
1687 jack_error("strdup() call for port name '%s' failed.", port_new_short_name);
1688 return;
1691 free(port_ptr->name);
1692 port_ptr->name = name_buffer;
1694 pthread_mutex_lock(&patchbay_ptr->lock);
1695 patchbay_ptr->graph.version++;
1696 jack_controller_patchbay_send_signal_port_renamed(
1697 patchbay_ptr->graph.version,
1698 port_ptr->client->id,
1699 port_ptr->client->name,
1700 port_ptr->id,
1701 port_old_short_name,
1702 port_ptr->name);
1703 jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version);
1704 pthread_mutex_unlock(&patchbay_ptr->lock);
1707 #undef controller_ptr
1709 void
1710 jack_controller_patchbay_uninit(
1711 struct jack_controller * controller_ptr)
1713 struct jack_graph_client *client_ptr;
1714 struct jack_graph_port *port_ptr;
1716 /* jack_info("jack_controller_patchbay_uninit() called"); */
1718 while (!list_empty(&patchbay_ptr->graph.ports))
1720 port_ptr = list_entry(patchbay_ptr->graph.ports.next, struct jack_graph_port, siblings_graph);
1721 jack_controller_patchbay_remove_port(patchbay_ptr, port_ptr);
1724 while (!list_empty(&patchbay_ptr->graph.clients))
1726 client_ptr = list_entry(patchbay_ptr->graph.clients.next, struct jack_graph_client, siblings);
1727 jack_controller_patchbay_destroy_client(patchbay_ptr, client_ptr);
1730 pthread_mutex_destroy(&patchbay_ptr->lock);
1733 #undef patchbay_ptr
1735 bool
1736 jack_controller_patchbay_init(
1737 struct jack_controller * controller_ptr)
1739 int ret;
1740 struct jack_controller_patchbay * patchbay_ptr;
1741 pthread_mutexattr_t attr;
1743 /* jack_info("jack_controller_patchbay_init() called"); */
1745 patchbay_ptr = malloc(sizeof(struct jack_controller_patchbay));
1746 if (patchbay_ptr == NULL)
1748 jack_error("Memory allocation of jack_controller_patchbay structure failed.");
1749 goto fail;
1752 ret = pthread_mutexattr_init(&attr);
1753 if (ret != 0)
1755 goto fail;
1758 ret = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
1759 if (ret != 0)
1761 goto fail;
1764 pthread_mutex_init(&patchbay_ptr->lock, &attr);
1765 INIT_LIST_HEAD(&patchbay_ptr->graph.clients);
1766 INIT_LIST_HEAD(&patchbay_ptr->graph.ports);
1767 INIT_LIST_HEAD(&patchbay_ptr->graph.connections);
1768 patchbay_ptr->graph.version = 1;
1769 patchbay_ptr->next_client_id = 1;
1770 patchbay_ptr->next_port_id = 1;
1771 patchbay_ptr->next_connection_id = 1;
1773 controller_ptr->patchbay_context = patchbay_ptr;
1775 ret = jack_set_graph_order_callback(controller_ptr->client, jack_controller_graph_order_callback, controller_ptr);
1776 if (ret != 0)
1778 jack_error("jack_set_graph_order_callback() failed with error %d", ret);
1779 goto fail_uninit_mutex;
1782 ret = jack_set_client_registration_callback(controller_ptr->client, jack_controller_client_registration_callback, controller_ptr);
1783 if (ret != 0)
1785 jack_error("jack_set_client_registration_callback() failed with error %d", ret);
1786 goto fail_uninit_mutex;
1789 ret = jack_set_port_registration_callback(controller_ptr->client, jack_controller_port_registration_callback, controller_ptr);
1790 if (ret != 0)
1792 jack_error("jack_set_port_registration_callback() failed with error %d", ret);
1793 goto fail_uninit_mutex;
1796 ret = jack_set_port_connect_callback(controller_ptr->client, jack_controller_port_connect_callback, controller_ptr);
1797 if (ret != 0)
1799 jack_error("jack_set_port_connect_callback() failed with error %d", ret);
1800 goto fail_uninit_mutex;
1803 ret = jack_set_port_rename_callback(controller_ptr->client, jack_controller_port_rename_callback, controller_ptr);
1804 if (ret != 0)
1806 jack_error("jack_set_port_rename_callback() failed with error %d", ret);
1807 goto fail_uninit_mutex;
1810 return true;
1812 fail_uninit_mutex:
1813 pthread_mutex_destroy(&patchbay_ptr->lock);
1815 fail:
1816 return false;
1819 JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetAllPorts)
1820 JACK_DBUS_METHOD_ARGUMENT("ports_list", "as", true)
1821 JACK_DBUS_METHOD_ARGUMENTS_END
1823 JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetGraph)
1824 JACK_DBUS_METHOD_ARGUMENT("known_graph_version", DBUS_TYPE_UINT64_AS_STRING, false)
1825 JACK_DBUS_METHOD_ARGUMENT("current_graph_version", DBUS_TYPE_UINT64_AS_STRING, true)
1826 JACK_DBUS_METHOD_ARGUMENT("clients_and_ports", "a(tsa(tsuu))", true)
1827 JACK_DBUS_METHOD_ARGUMENT("connections", "a(tstststst)", true)
1828 JACK_DBUS_METHOD_ARGUMENTS_END
1830 JACK_DBUS_METHOD_ARGUMENTS_BEGIN(ConnectPortsByName)
1831 JACK_DBUS_METHOD_ARGUMENT("client1_name", DBUS_TYPE_STRING_AS_STRING, false)
1832 JACK_DBUS_METHOD_ARGUMENT("port1_name", DBUS_TYPE_STRING_AS_STRING, false)
1833 JACK_DBUS_METHOD_ARGUMENT("client2_name", DBUS_TYPE_STRING_AS_STRING, false)
1834 JACK_DBUS_METHOD_ARGUMENT("port2_name", DBUS_TYPE_STRING_AS_STRING, false)
1835 JACK_DBUS_METHOD_ARGUMENTS_END
1837 JACK_DBUS_METHOD_ARGUMENTS_BEGIN(ConnectPortsByID)
1838 JACK_DBUS_METHOD_ARGUMENT("port1_id", DBUS_TYPE_UINT64_AS_STRING, false)
1839 JACK_DBUS_METHOD_ARGUMENT("port2_id", DBUS_TYPE_UINT64_AS_STRING, false)
1840 JACK_DBUS_METHOD_ARGUMENTS_END
1842 JACK_DBUS_METHOD_ARGUMENTS_BEGIN(DisconnectPortsByName)
1843 JACK_DBUS_METHOD_ARGUMENT("client1_name", DBUS_TYPE_STRING_AS_STRING, false)
1844 JACK_DBUS_METHOD_ARGUMENT("port1_name", DBUS_TYPE_STRING_AS_STRING, false)
1845 JACK_DBUS_METHOD_ARGUMENT("client2_name", DBUS_TYPE_STRING_AS_STRING, false)
1846 JACK_DBUS_METHOD_ARGUMENT("port2_name", DBUS_TYPE_STRING_AS_STRING, false)
1847 JACK_DBUS_METHOD_ARGUMENTS_END
1849 JACK_DBUS_METHOD_ARGUMENTS_BEGIN(DisconnectPortsByID)
1850 JACK_DBUS_METHOD_ARGUMENT("port1_id", DBUS_TYPE_UINT64_AS_STRING, false)
1851 JACK_DBUS_METHOD_ARGUMENT("port2_id", DBUS_TYPE_UINT64_AS_STRING, false)
1852 JACK_DBUS_METHOD_ARGUMENTS_END
1854 JACK_DBUS_METHOD_ARGUMENTS_BEGIN(DisconnectPortsByConnectionID)
1855 JACK_DBUS_METHOD_ARGUMENT("connection_id", DBUS_TYPE_UINT64_AS_STRING, false)
1856 JACK_DBUS_METHOD_ARGUMENTS_END
1858 JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetClientPID)
1859 JACK_DBUS_METHOD_ARGUMENT("client_id", DBUS_TYPE_UINT64_AS_STRING, false)
1860 JACK_DBUS_METHOD_ARGUMENT("process_id", DBUS_TYPE_INT64_AS_STRING, true)
1861 JACK_DBUS_METHOD_ARGUMENTS_END
1863 JACK_DBUS_METHODS_BEGIN
1864 JACK_DBUS_METHOD_DESCRIBE(GetAllPorts, jack_controller_dbus_get_all_ports)
1865 JACK_DBUS_METHOD_DESCRIBE(GetGraph, jack_controller_dbus_get_graph)
1866 JACK_DBUS_METHOD_DESCRIBE(ConnectPortsByName, jack_controller_dbus_connect_ports_by_name)
1867 JACK_DBUS_METHOD_DESCRIBE(ConnectPortsByID, jack_controller_dbus_connect_ports_by_id)
1868 JACK_DBUS_METHOD_DESCRIBE(DisconnectPortsByName, jack_controller_dbus_disconnect_ports_by_name)
1869 JACK_DBUS_METHOD_DESCRIBE(DisconnectPortsByID, jack_controller_dbus_disconnect_ports_by_id)
1870 JACK_DBUS_METHOD_DESCRIBE(DisconnectPortsByConnectionID, jack_controller_dbus_disconnect_ports_by_connection_id)
1871 JACK_DBUS_METHOD_DESCRIBE(GetClientPID, jack_controller_dbus_get_client_pid)
1872 JACK_DBUS_METHODS_END
1874 JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(GraphChanged)
1875 JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING)
1876 JACK_DBUS_SIGNAL_ARGUMENTS_END
1878 JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(ClientAppeared)
1879 JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING)
1880 JACK_DBUS_SIGNAL_ARGUMENT("client_id", DBUS_TYPE_UINT64_AS_STRING)
1881 JACK_DBUS_SIGNAL_ARGUMENT("client_name", DBUS_TYPE_STRING_AS_STRING)
1882 JACK_DBUS_SIGNAL_ARGUMENTS_END
1884 JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(ClientDisappeared)
1885 JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING)
1886 JACK_DBUS_SIGNAL_ARGUMENT("client_id", DBUS_TYPE_UINT64_AS_STRING)
1887 JACK_DBUS_SIGNAL_ARGUMENT("client_name", DBUS_TYPE_STRING_AS_STRING)
1888 JACK_DBUS_SIGNAL_ARGUMENTS_END
1890 JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(PortAppeared)
1891 JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING)
1892 JACK_DBUS_SIGNAL_ARGUMENT("client_id", DBUS_TYPE_UINT64_AS_STRING)
1893 JACK_DBUS_SIGNAL_ARGUMENT("client_name", DBUS_TYPE_STRING_AS_STRING)
1894 JACK_DBUS_SIGNAL_ARGUMENT("port_id", DBUS_TYPE_UINT64_AS_STRING)
1895 JACK_DBUS_SIGNAL_ARGUMENT("port_name", DBUS_TYPE_STRING_AS_STRING)
1896 JACK_DBUS_SIGNAL_ARGUMENT("port_flags", DBUS_TYPE_UINT32_AS_STRING)
1897 JACK_DBUS_SIGNAL_ARGUMENT("port_type", DBUS_TYPE_UINT32_AS_STRING)
1898 JACK_DBUS_SIGNAL_ARGUMENTS_END
1900 JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(PortDisappeared)
1901 JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING)
1902 JACK_DBUS_SIGNAL_ARGUMENT("client_id", DBUS_TYPE_UINT64_AS_STRING)
1903 JACK_DBUS_SIGNAL_ARGUMENT("client_name", DBUS_TYPE_STRING_AS_STRING)
1904 JACK_DBUS_SIGNAL_ARGUMENT("port_id", DBUS_TYPE_UINT64_AS_STRING)
1905 JACK_DBUS_SIGNAL_ARGUMENT("port_name", DBUS_TYPE_STRING_AS_STRING)
1906 JACK_DBUS_SIGNAL_ARGUMENTS_END
1908 JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(PortsConnected)
1909 JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING)
1910 JACK_DBUS_SIGNAL_ARGUMENT("client1_id", DBUS_TYPE_UINT64_AS_STRING)
1911 JACK_DBUS_SIGNAL_ARGUMENT("client1_name", DBUS_TYPE_STRING_AS_STRING)
1912 JACK_DBUS_SIGNAL_ARGUMENT("port1_id", DBUS_TYPE_UINT64_AS_STRING)
1913 JACK_DBUS_SIGNAL_ARGUMENT("port1_name", DBUS_TYPE_STRING_AS_STRING)
1914 JACK_DBUS_SIGNAL_ARGUMENT("client2_id", DBUS_TYPE_UINT64_AS_STRING)
1915 JACK_DBUS_SIGNAL_ARGUMENT("client2_name", DBUS_TYPE_STRING_AS_STRING)
1916 JACK_DBUS_SIGNAL_ARGUMENT("port2_id", DBUS_TYPE_UINT64_AS_STRING)
1917 JACK_DBUS_SIGNAL_ARGUMENT("port2_name", DBUS_TYPE_STRING_AS_STRING)
1918 JACK_DBUS_SIGNAL_ARGUMENT("connection_id", DBUS_TYPE_UINT64_AS_STRING)
1919 JACK_DBUS_SIGNAL_ARGUMENTS_END
1921 JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(PortsDisconnected)
1922 JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING)
1923 JACK_DBUS_SIGNAL_ARGUMENT("client1_id", DBUS_TYPE_UINT64_AS_STRING)
1924 JACK_DBUS_SIGNAL_ARGUMENT("client1_name", DBUS_TYPE_STRING_AS_STRING)
1925 JACK_DBUS_SIGNAL_ARGUMENT("port1_id", DBUS_TYPE_UINT64_AS_STRING)
1926 JACK_DBUS_SIGNAL_ARGUMENT("port1_name", DBUS_TYPE_STRING_AS_STRING)
1927 JACK_DBUS_SIGNAL_ARGUMENT("client2_id", DBUS_TYPE_UINT64_AS_STRING)
1928 JACK_DBUS_SIGNAL_ARGUMENT("client2_name", DBUS_TYPE_STRING_AS_STRING)
1929 JACK_DBUS_SIGNAL_ARGUMENT("port2_id", DBUS_TYPE_UINT64_AS_STRING)
1930 JACK_DBUS_SIGNAL_ARGUMENT("port2_name", DBUS_TYPE_STRING_AS_STRING)
1931 JACK_DBUS_SIGNAL_ARGUMENT("connection_id", DBUS_TYPE_UINT64_AS_STRING)
1932 JACK_DBUS_SIGNAL_ARGUMENTS_END
1934 JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(PortRenamed)
1935 JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING)
1936 JACK_DBUS_SIGNAL_ARGUMENT("port_id", DBUS_TYPE_UINT64_AS_STRING)
1937 JACK_DBUS_SIGNAL_ARGUMENT("client_id", DBUS_TYPE_UINT64_AS_STRING)
1938 JACK_DBUS_SIGNAL_ARGUMENT("client_name", DBUS_TYPE_STRING_AS_STRING)
1939 JACK_DBUS_SIGNAL_ARGUMENT("port_old_name", DBUS_TYPE_STRING_AS_STRING)
1940 JACK_DBUS_SIGNAL_ARGUMENT("port_new_name", DBUS_TYPE_STRING_AS_STRING)
1941 JACK_DBUS_SIGNAL_ARGUMENTS_END
1943 JACK_DBUS_SIGNALS_BEGIN
1944 JACK_DBUS_SIGNAL_DESCRIBE(GraphChanged)
1945 JACK_DBUS_SIGNAL_DESCRIBE(ClientAppeared)
1946 JACK_DBUS_SIGNAL_DESCRIBE(ClientDisappeared)
1947 JACK_DBUS_SIGNAL_DESCRIBE(PortAppeared)
1948 JACK_DBUS_SIGNAL_DESCRIBE(PortDisappeared)
1949 JACK_DBUS_SIGNAL_DESCRIBE(PortsConnected)
1950 JACK_DBUS_SIGNAL_DESCRIBE(PortsDisconnected)
1951 JACK_DBUS_SIGNAL_DESCRIBE(PortRenamed)
1952 JACK_DBUS_SIGNALS_END
1954 JACK_DBUS_IFACE_BEGIN(g_jack_controller_iface_patchbay, JACK_DBUS_IFACE_NAME)
1955 JACK_DBUS_IFACE_EXPOSE_METHODS
1956 JACK_DBUS_IFACE_EXPOSE_SIGNALS
1957 JACK_DBUS_IFACE_END