1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
3 * LADI Session Handler (ladish)
5 * Copyright (C) 2009, 2010 Nedko Arnaudov <nedko@arnaudov.name>
7 **************************************************************************
8 * This file contains implementation of the graph virtualizer object
9 **************************************************************************
11 * LADI Session Handler is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * LADI Session Handler is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with LADI Session Handler. If not, see <http://www.gnu.org/licenses/>
23 * or write to the Free Software Foundation, Inc.,
24 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include "virtualizer.h"
28 #include "../dbus_constants.h"
29 #include "../proxies/a2j_proxy.h"
30 #include "../proxies/jmcore_proxy.h"
32 #include "app_supervisor.h"
33 #include "studio_internal.h"
34 #include "../catdup.h"
40 graph_proxy_handle jack_graph_proxy
;
41 ladish_graph_handle jack_graph
;
42 uint64_t system_client_id
;
43 unsigned int our_clients_count
;
46 /* 47c1cd18-7b21-4389-bec4-6e0658e1d6b1 */
47 UUID_DEFINE(g_system_capture_uuid
,0x47,0xC1,0xCD,0x18,0x7B,0x21,0x43,0x89,0xBE,0xC4,0x6E,0x06,0x58,0xE1,0xD6,0xB1);
49 /* b2a0bb06-28d8-4bfe-956e-eb24378f9629 */
50 UUID_DEFINE(g_system_playback_uuid
,0xB2,0xA0,0xBB,0x06,0x28,0xD8,0x4B,0xFE,0x95,0x6E,0xEB,0x24,0x37,0x8F,0x96,0x29);
52 /* be23a242-e2b2-11de-b795-002618af5e42 */
53 UUID_DEFINE(g_a2j_uuid
,0xBE,0x23,0xA2,0x42,0xE2,0xB2,0x11,0xDE,0xB7,0x95,0x00,0x26,0x18,0xAF,0x5E,0x42);
55 struct app_find_context
59 ladish_graph_handle graph
;
62 #define app_find_context_ptr ((struct app_find_context *)context)
64 bool get_app_name_from_supervisor(void * context
, ladish_graph_handle graph
, ladish_app_supervisor_handle app_supervisor
)
69 ASSERT(app_find_context_ptr
->app_name
== NULL
); /* we stop iteration when app is found */
71 //log_info("checking app supervisor \"%s\" for pid %llu", ladish_app_supervisor_get_name(app_supervisor), (unsigned long long)pid);
73 pid
= app_find_context_ptr
->pid
;
76 app_name
= ladish_app_supervisor_search_app(app_supervisor
, pid
);
80 pid
= (pid_t
)procfs_get_process_parent((unsigned long long)pid
);
84 log_info("parent pid %llu", (unsigned long long)pid
);
92 app_find_context_ptr
->app_name
= app_name
;
93 app_find_context_ptr
->pid
= pid
;
94 app_find_context_ptr
->graph
= graph
;
95 return false; /* stop app supervisor iteration */
98 return true; /* continue app supervisor iteration */
101 #undef app_find_context_ptr
103 char * get_app_name(struct virtualizer
* virtualizer_ptr
, uint64_t client_id
, pid_t pid
, ladish_graph_handle
* graph_ptr
)
105 struct app_find_context context
;
107 context
.pid
= (pid_t
)pid
;
108 context
.app_name
= NULL
;
109 context
.graph
= NULL
;
111 studio_iterate_virtual_graphs(&context
, get_app_name_from_supervisor
);
113 if (context
.app_name
!= NULL
)
115 ASSERT(context
.graph
!= NULL
);
116 *graph_ptr
= context
.graph
;
119 return context
.app_name
;
122 struct find_link_port_context
126 ladish_port_handle port
;
127 ladish_graph_handle graph
;
130 #define find_link_port_context_ptr ((struct find_link_port_context *)context)
132 static bool find_link_port_vgraph_callback_by_uuid(void * context
, ladish_graph_handle graph
, ladish_app_supervisor_handle app_supervisor
)
134 ladish_port_handle port
;
136 port
= ladish_graph_find_port_by_uuid(graph
, find_link_port_context_ptr
->uuid
, true);
139 find_link_port_context_ptr
->port
= port
;
140 find_link_port_context_ptr
->graph
= graph
;
144 return true; /* continue vgraph iteration */
147 static bool find_link_port_vgraph_callback_by_jack_id(void * context
, ladish_graph_handle graph
, ladish_app_supervisor_handle app_supervisor
)
149 ladish_port_handle port
;
152 log_info("searching link port with jack id %"PRIu64
" in graph %s", find_link_port_context_ptr
->jack_id
, ladish_graph_get_description(graph
));
154 room
= graph
!= g_studio
.studio_graph
;
156 port
= ladish_graph_find_port_by_jack_id(graph
, find_link_port_context_ptr
->jack_id
, room
, !room
);
159 find_link_port_context_ptr
->port
= port
;
160 find_link_port_context_ptr
->graph
= graph
;
164 return true; /* continue vgraph iteration */
167 #undef find_link_port_context_ptr
169 static ladish_graph_handle
find_link_port_vgraph_by_uuid(struct virtualizer
* virtualizer_ptr
, const char * port_name
, ladish_port_handle
* port_ptr
)
171 struct find_link_port_context context
;
173 uuid_parse(port_name
, context
.uuid
);
174 context
.graph
= NULL
;
177 studio_iterate_virtual_graphs(&context
, find_link_port_vgraph_callback_by_uuid
);
179 if (port_ptr
!= NULL
&& context
.graph
!= NULL
)
181 *port_ptr
= context
.port
;
184 return context
.graph
;
187 static ladish_graph_handle
find_link_port_vgraph_by_jack_id(struct virtualizer
* virtualizer_ptr
, uint64_t jack_id
, ladish_port_handle
* port_ptr
)
189 struct find_link_port_context context
;
191 context
.jack_id
= jack_id
;
192 context
.graph
= NULL
;
195 studio_iterate_virtual_graphs(&context
, find_link_port_vgraph_callback_by_jack_id
);
197 if (port_ptr
!= NULL
&& context
.graph
!= NULL
)
199 *port_ptr
= context
.port
;
202 return context
.graph
;
208 struct virtualizer
* virtualizer_ptr
,
210 ladish_port_handle
* port_ptr
,
211 ladish_graph_handle
* vgraph_ptr
)
213 ladish_port_handle port
;
214 ladish_client_handle jclient
;
215 ladish_graph_handle vgraph
;
217 port
= ladish_graph_find_port_by_jack_id(virtualizer_ptr
->jack_graph
, port_id
, true, true);
220 log_error("Unknown JACK port with id %"PRIu64
" (dis)connected", port_id
);
224 jclient
= ladish_graph_get_port_client(virtualizer_ptr
->jack_graph
, port
);
227 log_error("Port %"PRIu64
" without jack client was (dis)connected", port_id
);
231 vgraph
= ladish_client_get_vgraph(jclient
);
234 vgraph
= find_link_port_vgraph_by_jack_id(virtualizer_ptr
, port_id
, NULL
);
237 log_error("Cannot find vgraph for (dis)connected jmcore port");
241 log_info("link port found in graph %s", ladish_graph_get_description(vgraph
));
245 *vgraph_ptr
= vgraph
;
249 #define virtualizer_ptr ((struct virtualizer *)context)
251 static void clear(void * context
)
256 static void client_appeared(void * context
, uint64_t id
, const char * jack_name
)
258 ladish_client_handle client
;
259 const char * a2j_name
;
264 ladish_graph_handle graph
;
267 log_info("client_appeared(%"PRIu64
", %s)", id
, jack_name
);
269 a2j_name
= a2j_proxy_get_jack_client_name_cached();
270 is_a2j
= a2j_name
!= NULL
&& strcmp(a2j_name
, jack_name
) == 0;
276 if (!graph_proxy_get_client_pid(virtualizer_ptr
->jack_graph_proxy
, id
, &pid
))
278 log_info("client %"PRIu64
" pid is unknown", id
);
282 log_info("client pid is %"PRId64
, (int64_t)pid
);
284 if (pid
!= 0) /* skip internal clients that will match the pending clients in the graph, both have zero pid */
286 jmcore
= pid
== jmcore_proxy_get_pid_cached();
289 log_info("jmcore client appeared");
293 app_name
= get_app_name(virtualizer_ptr
, id
, pid
, &graph
);
294 if (app_name
!= NULL
)
296 log_info("app name is '%s'", app_name
);
307 client
= ladish_graph_find_client_by_uuid(virtualizer_ptr
->jack_graph
, g_a2j_uuid
);
311 client
= ladish_graph_find_client_by_name(virtualizer_ptr
->jack_graph
, name
);
316 log_info("found existing client");
317 if (ladish_client_get_jack_id(client
) != 0)
319 log_error("Ignoring client with duplicate name '%s' ('%s')", name
, jack_name
);
323 ladish_client_set_jack_id(client
, id
);
324 ladish_graph_show_client(virtualizer_ptr
->jack_graph
, client
);
329 if (!ladish_client_create(is_a2j
? g_a2j_uuid
: NULL
, &client
))
331 log_error("ladish_client_create() failed. Ignoring client %"PRIu64
" (%s)", id
, jack_name
);
335 ladish_client_set_jack_id(client
, id
);
337 if (!ladish_graph_add_client(virtualizer_ptr
->jack_graph
, client
, name
, false))
339 log_error("ladish_graph_add_client() failed to add client %"PRIu64
" (%s) to JACK graph", id
, name
);
340 ladish_client_destroy(client
);
345 if (strcmp(jack_name
, "system") == 0)
347 virtualizer_ptr
->system_client_id
= id
;
350 if (app_name
!= NULL
)
352 ladish_client_set_pid(client
, pid
);
353 ladish_client_set_vgraph(client
, graph
);
354 virtualizer_ptr
->our_clients_count
++;
358 ladish_client_set_pid(client
, pid
);
359 ASSERT(ladish_client_get_vgraph(client
) == NULL
);
363 /* unknown and internal clients appear in the studio graph */
364 ladish_client_set_vgraph(client
, g_studio
.studio_graph
);
368 if (app_name
!= NULL
)
374 static void client_disappeared(void * context
, uint64_t id
)
376 ladish_client_handle client
;
379 log_info("client_disappeared(%"PRIu64
")", id
);
381 client
= ladish_graph_find_client_by_jack_id(virtualizer_ptr
->jack_graph
, id
);
384 log_error("Unknown JACK client with id %"PRIu64
" disappeared", id
);
388 log_info("client disappeared: '%s'", ladish_graph_get_client_name(virtualizer_ptr
->jack_graph
, client
));
390 if (ladish_client_get_vgraph(client
) == NULL
)
391 { /* remove jmcore clients, the are not persisted in the jack graph */
392 ladish_graph_remove_client(virtualizer_ptr
->jack_graph
, client
);
393 ladish_client_destroy(client
);
397 pid
= ladish_client_get_pid(client
);
400 virtualizer_ptr
->our_clients_count
--;
403 if (id
== virtualizer_ptr
->system_client_id
)
405 virtualizer_ptr
->system_client_id
= 0;
408 if (true) /* if client is supposed to be persisted */
410 ladish_client_set_jack_id(client
, 0);
411 ladish_graph_hide_client(virtualizer_ptr
->jack_graph
, client
);
415 ladish_graph_remove_client(virtualizer_ptr
->jack_graph
, client
);
416 ladish_client_destroy(client
);
426 const char * real_jack_port_name
,
431 ladish_client_handle jack_client
;
432 ladish_client_handle vclient
;
433 ladish_port_handle port
;
436 const char * jack_client_name
;
439 char * alsa_client_name
;
440 char * alsa_port_name
;
441 char * a2j_fake_jack_port_name
= NULL
;
442 uint32_t alsa_client_id
;
443 const char * jack_port_name
;
444 const char * vport_name
;
445 ladish_graph_handle vgraph
;
447 log_info("port_appeared(%"PRIu64
", %"PRIu64
", %s (%s, %s))", client_id
, port_id
, real_jack_port_name
, is_input
? "in" : "out", is_midi
? "midi" : "audio");
449 type
= is_midi
? JACKDBUS_PORT_TYPE_MIDI
: JACKDBUS_PORT_TYPE_AUDIO
;
450 flags
= is_input
? JACKDBUS_PORT_FLAG_INPUT
: JACKDBUS_PORT_FLAG_OUTPUT
;
453 flags
|= JACKDBUS_PORT_FLAG_TERMINAL
;
456 /********************/
457 /* gather info about the appeared port */
459 jack_client
= ladish_graph_find_client_by_jack_id(virtualizer_ptr
->jack_graph
, client_id
);
460 if (jack_client
== NULL
)
462 log_error("Port of unknown JACK client with id %"PRIu64
" appeared", client_id
);
466 /* find the virtual graph that owns the app that owns the client that owns the appeared port */
467 vgraph
= ladish_client_get_vgraph(jack_client
);
470 vgraph
= find_link_port_vgraph_by_uuid(virtualizer_ptr
, real_jack_port_name
, &port
);
473 log_error("Cannot find vgraph for appeared jmcore port '%s'", real_jack_port_name
);
477 /* jmcore port appeared */
479 log_info("jmcore port appeared in vgraph %s", ladish_graph_get_description(vgraph
));
481 if (!ladish_graph_add_port(virtualizer_ptr
->jack_graph
, jack_client
, port
, real_jack_port_name
, type
, flags
, false))
483 log_error("ladish_graph_add_port() failed.");
487 if (vgraph
== g_studio
.studio_graph
)
489 ladish_port_set_jack_id(port
, port_id
);
493 ladish_port_set_jack_id_room(port
, port_id
);
496 vclient
= ladish_graph_get_port_client(vgraph
, port
);
499 log_error("link port client not found in vgraph %s", ladish_graph_get_description(vgraph
));
504 ladish_graph_show_port(vgraph
, port
);
508 ladish_client_get_uuid(jack_client
, client_uuid
);
509 is_a2j
= uuid_compare(client_uuid
, g_a2j_uuid
) == 0;
512 log_info("a2j port appeared");
513 if (!a2j_proxy_map_jack_port(real_jack_port_name
, &alsa_client_name
, &alsa_port_name
, &alsa_client_id
))
519 log_info("a2j: '%s':'%s' (%"PRIu32
")", alsa_client_name
, alsa_port_name
, alsa_client_id
);
522 a2j_fake_jack_port_name
= catdup4(alsa_client_name
, is_input
? " (playback)" : " (capture)", ": ", alsa_port_name
);
523 if (a2j_fake_jack_port_name
== NULL
)
525 log_error("catdup4() failed");
526 goto free_alsa_names
;
529 jack_port_name
= a2j_fake_jack_port_name
;
533 jack_port_name
= real_jack_port_name
;
536 jack_client_name
= ladish_graph_get_client_name(virtualizer_ptr
->jack_graph
, jack_client
);
538 /********************/
540 /* search (by name) the appeared port in jack graph
541 * if found - show it in both graphs.
542 * if not found - create new port and add it to the jack graph.
543 * Then process to adding it to virtual graph */
545 port
= ladish_graph_find_port_by_name(virtualizer_ptr
->jack_graph
, jack_client
, jack_port_name
);
548 log_info("found existing port");
550 if (ladish_port_get_jack_id(port
) != 0)
552 log_error("Ignoring duplicate JACK port '%s':'%s'", jack_client_name
, jack_port_name
);
553 goto free_alsa_names
;
556 ladish_port_set_jack_id(port
, port_id
);
557 ladish_graph_adjust_port(virtualizer_ptr
->jack_graph
, port
, type
, flags
);
558 ladish_graph_show_port(virtualizer_ptr
->jack_graph
, port
);
560 vclient
= ladish_graph_get_port_client(vgraph
, port
);
563 log_error("JACK port not found in virtual graph");
565 goto free_alsa_names
;
568 ladish_client_set_jack_id(vclient
, client_id
);
569 ladish_graph_adjust_port(vgraph
, port
, type
, flags
);
570 ladish_graph_show_port(vgraph
, port
);
571 goto free_alsa_names
;
574 if (!ladish_port_create(NULL
, false, &port
))
576 log_error("ladish_port_create() failed.");
577 goto free_alsa_names
;
580 /* set port jack id so invisible connections to/from it can be restored */
581 ladish_port_set_jack_id(port
, port_id
);
583 if (!ladish_graph_add_port(virtualizer_ptr
->jack_graph
, jack_client
, port
, jack_port_name
, type
, flags
, false))
585 log_error("ladish_graph_add_port() failed.");
586 ladish_port_destroy(port
);
587 goto free_alsa_names
;
590 /********************/
591 /* find/create the virtual client where port will be added */
595 vclient
= ladish_graph_find_client_by_name(vgraph
, alsa_client_name
);
598 if (!ladish_client_create(NULL
, &vclient
))
600 log_error("ladish_client_create() failed.");
601 goto free_alsa_names
;
604 if (!ladish_graph_add_client(vgraph
, vclient
, alsa_client_name
, false))
606 log_error("ladish_graph_add_client() failed.");
607 ladish_client_destroy(vclient
);
608 goto free_alsa_names
;
613 else if (client_id
== virtualizer_ptr
->system_client_id
)
615 log_info("system client port appeared");
618 { /* output capture port */
620 vclient
= ladish_graph_find_client_by_uuid(vgraph
, g_system_capture_uuid
);
623 if (!ladish_client_create(g_system_capture_uuid
, &vclient
))
625 log_error("ladish_client_create() failed.");
626 goto free_alsa_names
;
629 if (!ladish_graph_add_client(vgraph
, vclient
, "Hardware Capture", false))
631 log_error("ladish_graph_add_client() failed.");
632 ladish_client_destroy(vclient
);
633 goto free_alsa_names
;
638 { /* input playback port */
639 vclient
= ladish_graph_find_client_by_uuid(vgraph
, g_system_playback_uuid
);
642 if (!ladish_client_create(g_system_playback_uuid
, &vclient
))
644 log_error("ladish_client_create() failed.");
645 goto free_alsa_names
;
648 if (!ladish_graph_add_client(vgraph
, vclient
, "Hardware Playback", false))
650 ladish_client_destroy(vclient
);
651 goto free_alsa_names
;
657 { /* non-system client */
658 log_info("non-system client port appeared");
660 vclient
= ladish_graph_find_client_by_jack_id(vgraph
, client_id
);
663 if (!ladish_client_create(NULL
, &vclient
))
665 log_error("ladish_client_create() failed.");
666 goto free_alsa_names
;
669 ladish_client_set_jack_id(vclient
, client_id
);
671 if (!ladish_graph_add_client(vgraph
, vclient
, jack_client_name
, false))
673 log_error("ladish_graph_add_client() failed to add client '%s' to virtual graph", jack_client_name
);
674 ladish_client_destroy(vclient
);
675 goto free_alsa_names
;
680 /********************/
681 /* add newly appeared port to the virtual graph */
685 vport_name
= alsa_port_name
;
689 vport_name
= jack_port_name
;
692 if (!ladish_graph_add_port(vgraph
, vclient
, port
, vport_name
, type
, flags
, false))
694 log_error("ladish_graph_add_port() failed.");
695 goto free_alsa_names
;
699 if (a2j_fake_jack_port_name
!= NULL
)
701 free(a2j_fake_jack_port_name
);
706 free(alsa_client_name
);
707 free(alsa_port_name
);
714 static void port_disappeared(void * context
, uint64_t client_id
, uint64_t port_id
)
716 ladish_client_handle client
;
717 ladish_port_handle port
;
718 ladish_graph_handle vgraph
;
721 log_info("port_disappeared(%"PRIu64
", %"PRIu64
")", client_id
, port_id
);
723 client
= ladish_graph_find_client_by_jack_id(virtualizer_ptr
->jack_graph
, client_id
);
726 log_error("Port of unknown JACK client with id %"PRIu64
" disappeared", client_id
);
730 port
= ladish_graph_find_port_by_jack_id(virtualizer_ptr
->jack_graph
, port_id
, true, true);
733 log_error("Unknown JACK port with id %"PRIu64
" disappeared", port_id
);
737 /* find the virtual graph that owns the app that owns the client that owns the disappeared port */
739 vgraph
= ladish_client_get_vgraph(client
);
742 vgraph
= find_link_port_vgraph_by_uuid(virtualizer_ptr
, ladish_graph_get_port_name(virtualizer_ptr
->jack_graph
, port
), NULL
);
745 log_error("Cannot find vgraph for disappeared jmcore port");
750 ladish_graph_remove_port_by_jack_id(virtualizer_ptr
->jack_graph
, port_id
, true, true);
754 if (true) /* if client is supposed to be persisted */
758 ladish_port_set_jack_id(port
, 0);
759 ladish_graph_hide_port(virtualizer_ptr
->jack_graph
, port
);
763 ladish_graph_hide_port(vgraph
, port
);
764 client
= ladish_graph_get_port_client(vgraph
, port
);
765 if (ladish_graph_is_client_looks_empty(vgraph
, client
))
767 ladish_graph_hide_client(vgraph
, client
);
775 ladish_graph_remove_port(virtualizer_ptr
->jack_graph
, port
);
780 client
= ladish_graph_remove_port(vgraph
, port
);
783 if (ladish_graph_is_client_empty(vgraph
, client
))
785 ladish_graph_remove_client(vgraph
, client
);
792 static void port_renamed(void * context
, uint64_t client_id
, uint64_t port_id
, const char * old_port_name
, const char * new_port_name
)
794 ladish_client_handle client
;
795 ladish_port_handle port
;
796 ladish_graph_handle vgraph
;
798 log_info("port_renamed(%"PRIu64
", '%s', '%s')", port_id
, old_port_name
, new_port_name
);
800 client
= ladish_graph_find_client_by_jack_id(virtualizer_ptr
->jack_graph
, client_id
);
803 log_error("Port of unknown JACK client with id %"PRIu64
" was renamed", client_id
);
807 /* find the virtual graph that owns the app that owns the client that owns the renamed port */
808 vgraph
= ladish_client_get_vgraph(client
);
810 port
= ladish_graph_find_port_by_jack_id(virtualizer_ptr
->jack_graph
, port_id
, true, true);
813 log_error("Unknown JACK port with id %"PRIu64
" was renamed", port_id
);
817 if (!ladish_graph_rename_port(virtualizer_ptr
->jack_graph
, port
, new_port_name
))
819 log_error("renaming of port in jack graph failed");
822 if (!ladish_graph_rename_port(vgraph
, port
, new_port_name
))
824 log_error("renaming of port in virtual graph failed");
828 static bool ports_connect_request(void * context
, ladish_graph_handle graph_handle
, ladish_port_handle port1
, ladish_port_handle port2
)
833 ASSERT(ladish_graph_get_opath(graph_handle
)); /* studio or room virtual graph */
834 log_info("virtualizer: ports connect request");
836 if (graph_handle
== g_studio
.studio_graph
)
838 port1_id
= ladish_port_get_jack_id(port1
);
839 port2_id
= ladish_port_get_jack_id(port2
);
843 port1_id
= ladish_port_get_jack_id_room(port1
);
844 port2_id
= ladish_port_get_jack_id_room(port2
);
847 graph_proxy_connect_ports(virtualizer_ptr
->jack_graph_proxy
, port1_id
, port2_id
);
852 static bool ports_disconnect_request(void * context
, ladish_graph_handle graph_handle
, uint64_t connection_id
)
854 ladish_port_handle port1
;
855 ladish_port_handle port2
;
859 ASSERT(ladish_graph_get_opath(graph_handle
)); /* studio or room virtual graph */
860 log_info("virtualizer: ports disconnect request");
862 if (!ladish_graph_get_connection_ports(graph_handle
, connection_id
, &port1
, &port2
))
864 log_error("cannot find ports that are disconnect-requested");
869 if (graph_handle
== g_studio
.studio_graph
)
871 port1_id
= ladish_port_get_jack_id(port1
);
872 port2_id
= ladish_port_get_jack_id(port2
);
876 port1_id
= ladish_port_get_jack_id_room(port1
);
877 port2_id
= ladish_port_get_jack_id_room(port2
);
880 graph_proxy_disconnect_ports(virtualizer_ptr
->jack_graph_proxy
, port1_id
, port2_id
);
885 static void ports_connected(void * context
, uint64_t client1_id
, uint64_t port1_id
, uint64_t client2_id
, uint64_t port2_id
)
887 ladish_port_handle port1
;
888 ladish_port_handle port2
;
889 uint64_t connection_id
;
890 ladish_graph_handle vgraph1
;
891 ladish_graph_handle vgraph2
;
893 log_info("ports_connected %"PRIu64
":%"PRIu64
" %"PRIu64
":%"PRIu64
"", client1_id
, port1_id
, client2_id
, port2_id
);
895 if (!lookup_port(virtualizer_ptr
, port1_id
, &port1
, &vgraph1
))
900 if (!lookup_port(virtualizer_ptr
, port2_id
, &port2
, &vgraph2
))
905 if (vgraph1
!= vgraph2
)
908 log_error("ignoring connection with endpoints in different vgraphs");
912 ladish_graph_add_connection(virtualizer_ptr
->jack_graph
, port1
, port2
, false);
914 if (ladish_graph_find_connection(vgraph1
, port1
, port2
, &connection_id
))
916 log_info("showing hidden virtual connection");
917 ladish_graph_show_connection(vgraph1
, connection_id
);
921 log_info("creating new virtual connection");
922 ladish_graph_add_connection(vgraph1
, port1
, port2
, false);
926 static void ports_disconnected(void * context
, uint64_t client1_id
, uint64_t port1_id
, uint64_t client2_id
, uint64_t port2_id
)
928 ladish_port_handle port1
;
929 ladish_port_handle port2
;
930 uint64_t connection_id
;
931 ladish_graph_handle vgraph1
;
932 ladish_graph_handle vgraph2
;
934 log_info("ports_disconnected %"PRIu64
":%"PRIu64
" %"PRIu64
":%"PRIu64
"", client1_id
, port1_id
, client2_id
, port2_id
);
936 if (!lookup_port(virtualizer_ptr
, port1_id
, &port1
, &vgraph1
))
941 if (!lookup_port(virtualizer_ptr
, port2_id
, &port2
, &vgraph2
))
946 if (vgraph1
!= vgraph2
)
949 log_error("ignoring connection with endpoints in different vgraphs");
953 if (ladish_graph_find_connection(virtualizer_ptr
->jack_graph
, port1
, port2
, &connection_id
))
955 ladish_graph_remove_connection(virtualizer_ptr
->jack_graph
, connection_id
, true);
959 log_error("ports %"PRIu64
":%"PRIu64
" and %"PRIu64
":%"PRIu64
" are not connected in the JACK graph", client1_id
, port1_id
, client2_id
, port2_id
);
962 if (ladish_graph_find_connection(vgraph1
, port1
, port2
, &connection_id
))
964 ladish_graph_remove_connection(vgraph1
, connection_id
, false);
968 log_error("ports %"PRIu64
":%"PRIu64
" and %"PRIu64
":%"PRIu64
" are not connected in the virtual graph", client1_id
, port1_id
, client2_id
, port2_id
);
972 #undef virtualizer_ptr
975 ladish_virtualizer_create(
976 graph_proxy_handle jack_graph_proxy
,
977 ladish_graph_handle jack_graph
,
978 ladish_virtualizer_handle
* handle_ptr
)
980 struct virtualizer
* virtualizer_ptr
;
982 virtualizer_ptr
= malloc(sizeof(struct virtualizer
));
983 if (virtualizer_ptr
== NULL
)
985 log_error("malloc() failed for struct virtualizer");
989 virtualizer_ptr
->jack_graph_proxy
= jack_graph_proxy
;
990 virtualizer_ptr
->jack_graph
= jack_graph
;
991 virtualizer_ptr
->system_client_id
= 0;
992 virtualizer_ptr
->our_clients_count
= 0;
994 if (!graph_proxy_attach(
999 NULL
, /* jackdbus does not have client rename functionality (yet) */
1005 ports_disconnected
))
1007 free(virtualizer_ptr
);
1011 *handle_ptr
= (ladish_virtualizer_handle
)virtualizer_ptr
;
1015 #define virtualizer_ptr ((struct virtualizer *)handle)
1018 ladish_virtualizer_set_graph_connection_handlers(
1019 ladish_virtualizer_handle handle
,
1020 ladish_graph_handle graph
)
1022 ladish_graph_set_connection_handlers(graph
, virtualizer_ptr
, ports_connect_request
, ports_disconnect_request
);
1026 ladish_virtualizer_get_our_clients_count(
1027 ladish_virtualizer_handle handle
)
1029 return virtualizer_ptr
->our_clients_count
;
1033 ladish_virtualizer_destroy(
1034 ladish_virtualizer_handle handle
)
1036 log_info("ladish_virtualizer_destroy() called");
1038 graph_proxy_detach((graph_proxy_handle
)handle
, virtualizer_ptr
);
1039 free(virtualizer_ptr
);
1042 #undef virtualizer_ptr