root/daemon/virtualizer.c @ e498a65b6f272464488deeeebda0db200e0a185e

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

daemon: fix use of uninitialized vars

  • Property mode set to 100644
Line 
1/* -*- Mode: C ; c-basic-offset: 2 -*- */
2/*
3 * LADI Session Handler (ladish)
4 *
5 * Copyright (C) 2009, 2010 Nedko Arnaudov <nedko@arnaudov.name>
6 *
7 **************************************************************************
8 * This file contains implementation of the graph virtualizer object
9 **************************************************************************
10 *
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.
15 *
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.
20 *
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.
25 */
26
27#include "virtualizer.h"
28#include "../dbus_constants.h"
29#include "../proxies/a2j_proxy.h"
30#include "procfs.h"
31#include "app_supervisor.h"
32#include "studio_internal.h"
33#include "../catdup.h"
34#include "room.h"
35#include "studio.h"
36
37struct virtualizer
38{
39
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;
44};
45
46/* 47c1cd18-7b21-4389-bec4-6e0658e1d6b1 */
47UUID_DEFINE(g_system_capture_uuid,0x47,0xC1,0xCD,0x18,0x7B,0x21,0x43,0x89,0xBE,0xC4,0x6E,0x06,0x58,0xE1,0xD6,0xB1);
48
49/* b2a0bb06-28d8-4bfe-956e-eb24378f9629 */
50UUID_DEFINE(g_system_playback_uuid,0xB2,0xA0,0xBB,0x06,0x28,0xD8,0x4B,0xFE,0x95,0x6E,0xEB,0x24,0x37,0x8F,0x96,0x29);
51
52/* be23a242-e2b2-11de-b795-002618af5e42 */
53UUID_DEFINE(g_a2j_uuid,0xBE,0x23,0xA2,0x42,0xE2,0xB2,0x11,0xDE,0xB7,0x95,0x00,0x26,0x18,0xAF,0x5E,0x42);
54
55struct app_find_context
56{
57  pid_t pid;
58  char * app_name;
59  ladish_graph_handle graph;
60};
61
62#define app_find_context_ptr ((struct app_find_context *)context)
63
64bool get_app_name_from_supervisor(void * context, ladish_graph_handle graph, ladish_app_supervisor_handle app_supervisor)
65{
66  pid_t pid;
67  char * app_name;
68
69  ASSERT(app_find_context_ptr->app_name == NULL); /* we stop iteration when app is found */
70
71  //log_info("checking app supervisor \"%s\" for pid %llu", ladish_app_supervisor_get_name(app_supervisor), (unsigned long long)pid);
72
73  pid = app_find_context_ptr->pid;
74  do
75  {
76    app_name = ladish_app_supervisor_search_app(app_supervisor, pid);
77    if (app_name != NULL)
78      break;
79
80    pid = (pid_t)procfs_get_process_parent((unsigned long long)pid);
81#if 0
82    if (pid != 0)
83    {
84      log_info("parent pid %llu", (unsigned long long)pid);
85    }
86#endif
87  }
88  while (pid != 0);
89
90  if (app_name != NULL)
91  {
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 */
96  }
97
98  return true;                  /* continue app supervisor iteration */
99}
100
101#undef app_find_context_ptr
102
103char * get_app_name(struct virtualizer * virtualizer_ptr, uint64_t client_id, pid_t * app_pid_ptr, ladish_graph_handle * graph_ptr)
104{
105  int64_t pid;
106  struct app_find_context context;
107
108  if (!graph_proxy_get_client_pid(virtualizer_ptr->jack_graph_proxy, client_id, &pid))
109  {
110    log_info("client %"PRIu64" pid is unknown", client_id);
111    *app_pid_ptr = 0;
112    return NULL;
113  }
114
115  log_info("client pid is %"PRId64, pid);
116
117  context.pid = (pid_t)pid;
118  context.app_name = NULL;
119  context.graph = NULL;
120
121  if (pid != 0)                 /* skip internal clients that will match the pending clients in the graph, both have zero pid */
122  {
123    studio_iterate_virtual_graphs(&context, get_app_name_from_supervisor);
124  }
125
126  if (context.app_name != NULL)
127  {
128    ASSERT(context.graph != NULL);
129    ASSERT(context.pid != 0);
130    *graph_ptr = context.graph;
131    *app_pid_ptr = context.pid;
132  }
133  else
134  {
135    *app_pid_ptr = 0;
136  }
137
138  return context.app_name;
139}
140
141static
142bool
143lookup_port(
144  struct virtualizer * virtualizer_ptr,
145  uint64_t port_id,
146  ladish_port_handle * port_ptr,
147  ladish_graph_handle * vgraph_ptr)
148{
149  ladish_port_handle port;
150  ladish_client_handle jclient;
151  ladish_graph_handle vgraph;
152
153  port = ladish_graph_find_port_by_jack_id(virtualizer_ptr->jack_graph, port_id);
154  if (port == NULL)
155  {
156    log_error("Unknown JACK port with id %"PRIu64" (dis)connected", port_id);
157    return false;
158  }
159
160  jclient = ladish_graph_get_port_client(virtualizer_ptr->jack_graph, port);
161  if (jclient == NULL)
162  {
163    log_error("Port %"PRIu64" without jack client was (dis)connected");
164    return false;
165  }
166
167  vgraph = ladish_client_get_vgraph(jclient);
168  if (vgraph == NULL)
169  {
170    log_error("port %"PRIu64" of jack client without vgraph was (dis)connected");
171    return false;
172  }
173
174  *port_ptr = port;
175  *vgraph_ptr = vgraph;
176  return true;
177}
178
179#define virtualizer_ptr ((struct virtualizer *)context)
180
181static void clear(void * context)
182{
183  log_info("clear");
184}
185
186static void client_appeared(void * context, uint64_t id, const char * jack_name)
187{
188  ladish_client_handle client;
189  const char * a2j_name;
190  bool is_a2j;
191  char * app_name;
192  const char * name;
193  pid_t pid;
194  ladish_graph_handle graph;
195
196  log_info("client_appeared(%"PRIu64", %s)", id, jack_name);
197
198  a2j_name = a2j_proxy_get_jack_client_name_cached();
199  is_a2j = a2j_name != NULL && strcmp(a2j_name, jack_name) == 0;
200
201  app_name = get_app_name(virtualizer_ptr, id, &pid, &graph);
202  if (app_name != NULL)
203  {
204    log_info("app name is '%s'", app_name);
205    name = app_name;
206  }
207  else
208  {
209    name = jack_name;
210  }
211
212  if (is_a2j)
213  {
214    client = ladish_graph_find_client_by_uuid(virtualizer_ptr->jack_graph, g_a2j_uuid);
215  }
216  else
217  {
218    client = ladish_graph_find_client_by_name(virtualizer_ptr->jack_graph, name);
219  }
220
221  if (client != NULL)
222  {
223    log_info("found existing client");
224    if (ladish_client_get_jack_id(client) != 0)
225    {
226      log_error("Ignoring client with duplicate name '%s' ('%s')", name, jack_name);
227      goto free_app_name;
228    }
229
230    ladish_client_set_jack_id(client, id);
231    ladish_graph_show_client(virtualizer_ptr->jack_graph, client);
232    goto done;
233  }
234
235  if (!ladish_client_create(is_a2j ? g_a2j_uuid : NULL, &client))
236  {
237    log_error("ladish_client_create() failed. Ignoring client %"PRIu64" (%s)", id, jack_name);
238    goto free_app_name;
239  }
240
241  ladish_client_set_jack_id(client, id);
242
243  if (!ladish_graph_add_client(virtualizer_ptr->jack_graph, client, name, false))
244  {
245    log_error("ladish_graph_add_client() failed to add client %"PRIu64" (%s) to JACK graph", id, name);
246    ladish_client_destroy(client);
247    goto free_app_name;
248  }
249
250done:
251  if (strcmp(jack_name, "system") == 0)
252  {
253    virtualizer_ptr->system_client_id = id;
254  }
255
256  if (app_name != NULL)
257  {
258    ladish_client_set_pid(client, pid);
259    ladish_client_set_vgraph(client, graph);
260    virtualizer_ptr->our_clients_count++;
261  }
262  else
263  {
264    /* unknown and internal clients appear in the studio graph */
265    ladish_client_set_vgraph(client, g_studio.studio_graph);
266  }
267
268free_app_name:
269  if (app_name != NULL)
270  {
271    free(app_name);
272  }
273}
274
275static void client_disappeared(void * context, uint64_t id)
276{
277  ladish_client_handle client;
278  pid_t pid;
279
280  log_info("client_disappeared(%"PRIu64")", id);
281
282  client = ladish_graph_find_client_by_jack_id(virtualizer_ptr->jack_graph, id);
283  if (client == NULL)
284  {
285    log_error("Unknown JACK client with id %"PRIu64" disappeared", id);
286    return;
287  }
288
289  log_info("client disappeared: '%s'", ladish_graph_get_client_name(virtualizer_ptr->jack_graph, client));
290
291  pid = ladish_client_get_pid(client);
292  if (pid != 0)
293  {
294    virtualizer_ptr->our_clients_count--;
295  }
296
297  if (id == virtualizer_ptr->system_client_id)
298  {
299    virtualizer_ptr->system_client_id = 0;
300  }
301
302  if (true)                     /* if client is supposed to be persisted */
303  {
304    ladish_client_set_jack_id(client, 0);
305    ladish_graph_hide_client(virtualizer_ptr->jack_graph, client);
306  }
307  else
308  {
309    ladish_graph_remove_client(virtualizer_ptr->jack_graph, client);
310    ladish_client_destroy(client);
311  }
312}
313
314static
315void
316port_appeared(
317  void * context,
318  uint64_t client_id,
319  uint64_t port_id,
320  const char * real_jack_port_name,
321  bool is_input,
322  bool is_terminal,
323  bool is_midi)
324{
325  ladish_client_handle jack_client;
326  ladish_client_handle vclient;
327  ladish_port_handle port;
328  uint32_t type;
329  uint32_t flags;
330  const char * jack_client_name;
331  bool is_a2j;
332  uuid_t client_uuid;
333  char * alsa_client_name;
334  char * alsa_port_name;
335  char * a2j_fake_jack_port_name = NULL;
336  uint32_t alsa_client_id;
337  const char * jack_port_name;
338  const char * vport_name;
339  ladish_graph_handle vgraph;
340
341  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");
342
343  /********************/
344  /* gather info about the appeared port */
345
346  jack_client = ladish_graph_find_client_by_jack_id(virtualizer_ptr->jack_graph, client_id);
347  if (jack_client == NULL)
348  {
349    log_error("Port of unknown JACK client with id %"PRIu64" appeared", client_id);
350    goto fail;
351  }
352
353  /* find the virtual graph that owns the app that owns the client that owns the appeared port */
354  vgraph = ladish_client_get_vgraph(jack_client);
355
356  ladish_client_get_uuid(jack_client, client_uuid);
357  is_a2j = uuid_compare(client_uuid, g_a2j_uuid) == 0;
358  if (is_a2j)
359  {
360    log_info("a2j port appeared");
361    if (!a2j_proxy_map_jack_port(real_jack_port_name, &alsa_client_name, &alsa_port_name, &alsa_client_id))
362    {
363      is_a2j = false;
364    }
365    else
366    {
367      log_info("a2j: '%s':'%s' (%"PRIu32")", alsa_client_name, alsa_port_name, alsa_client_id);
368    }
369
370    a2j_fake_jack_port_name = catdup4(alsa_client_name, is_input ? " (playback)" : " (capture)", ": ", alsa_port_name);
371    if (a2j_fake_jack_port_name == NULL)
372    {
373      log_error("catdup4() failed");
374      goto free_alsa_names;
375    }
376
377    jack_port_name = a2j_fake_jack_port_name;
378  }
379  else
380  {
381    jack_port_name = real_jack_port_name;
382  }
383
384  jack_client_name = ladish_graph_get_client_name(virtualizer_ptr->jack_graph, jack_client);
385
386  type = is_midi ? JACKDBUS_PORT_TYPE_MIDI : JACKDBUS_PORT_TYPE_AUDIO;
387  flags = is_input ? JACKDBUS_PORT_FLAG_INPUT : JACKDBUS_PORT_FLAG_OUTPUT;
388  if (is_terminal)
389  {
390    flags |= JACKDBUS_PORT_FLAG_TERMINAL;
391  }
392
393  /********************/
394
395  /* search (by name) the appeared port in jack graph
396   * if found - show it in both graphs.
397   * if not found - create new port and add it to the jack graph.
398   * Then process to adding it to virtual graph */
399
400  port = ladish_graph_find_port_by_name(virtualizer_ptr->jack_graph, jack_client, jack_port_name);
401  if (port != NULL)
402  {
403    log_info("found existing port");
404
405    if (ladish_port_get_jack_id(port) != 0)
406    {
407      log_error("Ignoring duplicate JACK port '%s':'%s'", jack_client_name, jack_port_name);
408      goto free_alsa_names;
409    }
410
411    ladish_port_set_jack_id(port, port_id);
412    ladish_graph_adjust_port(virtualizer_ptr->jack_graph, port, type, flags);
413    ladish_graph_show_port(virtualizer_ptr->jack_graph, port);
414
415    vclient = ladish_graph_get_port_client(vgraph, port);
416    if (vclient == NULL)
417    {
418      log_error("JACK port not found in virtual graph");
419      ASSERT_NO_PASS;
420      goto free_alsa_names;
421    }
422
423    ladish_client_set_jack_id(vclient, client_id);
424    ladish_graph_adjust_port(vgraph, port, type, flags);
425    ladish_graph_show_port(vgraph, port);
426    goto free_alsa_names;
427  }
428
429  if (!ladish_port_create(NULL, &port))
430  {
431    log_error("ladish_port_create() failed.");
432    goto free_alsa_names;
433  }
434
435  /* set port jack id so invisible connections to/from it can be restored */
436  ladish_port_set_jack_id(port, port_id);
437
438  if (!ladish_graph_add_port(virtualizer_ptr->jack_graph, jack_client, port, jack_port_name, type, flags, false))
439  {
440    log_error("ladish_graph_add_port() failed.");
441    ladish_port_destroy(port);
442    goto free_alsa_names;
443  }
444
445  /********************/
446  /* find/create the virtual client where port will be added */
447
448  if (is_a2j)
449  {
450    vclient = ladish_graph_find_client_by_name(vgraph, alsa_client_name);
451    if (vclient == NULL)
452    {
453        if (!ladish_client_create(NULL, &vclient))
454        {
455          log_error("ladish_client_create() failed.");
456          goto free_alsa_names;
457        }
458
459        if (!ladish_graph_add_client(vgraph, vclient, alsa_client_name, false))
460        {
461          log_error("ladish_graph_add_client() failed.");
462          ladish_client_destroy(vclient);
463          goto free_alsa_names;
464        }
465    }
466
467  }
468  else if (client_id == virtualizer_ptr->system_client_id)
469  {
470    log_info("system client port appeared");
471
472    if (!is_input)
473    { /* output capture port */
474
475      vclient = ladish_graph_find_client_by_uuid(vgraph, g_system_capture_uuid);
476      if (vclient == NULL)
477      {
478        if (!ladish_client_create(g_system_capture_uuid, &vclient))
479        {
480          log_error("ladish_client_create() failed.");
481          goto free_alsa_names;
482        }
483
484        if (!ladish_graph_add_client(vgraph, vclient, "Hardware Capture", false))
485        {
486          log_error("ladish_graph_add_client() failed.");
487          ladish_client_destroy(vclient);
488          goto free_alsa_names;
489        }
490      }
491    }
492    else
493    { /* input playback port */
494      vclient = ladish_graph_find_client_by_uuid(vgraph, g_system_playback_uuid);
495      if (vclient == NULL)
496      {
497        if (!ladish_client_create(g_system_playback_uuid, &vclient))
498        {
499          log_error("ladish_client_create() failed.");
500          goto free_alsa_names;
501        }
502
503        if (!ladish_graph_add_client(vgraph, vclient, "Hardware Playback", false))
504        {
505          ladish_client_destroy(vclient);
506          goto free_alsa_names;
507        }
508      }
509    }
510  }
511  else
512  { /* non-system client */
513    log_info("non-system client port appeared");
514
515    vclient = ladish_graph_find_client_by_jack_id(vgraph, client_id);
516    if (vclient == NULL)
517    {
518      if (!ladish_client_create(NULL, &vclient))
519      {
520        log_error("ladish_client_create() failed.");
521        goto free_alsa_names;
522      }
523
524      ladish_client_set_jack_id(vclient, client_id);
525
526      if (!ladish_graph_add_client(vgraph, vclient, jack_client_name, false))
527      {
528        log_error("ladish_graph_add_client() failed to add client '%s' to virtual graph", jack_client_name);
529        ladish_client_destroy(vclient);
530        goto free_alsa_names;
531      }
532    }
533  }
534
535  /********************/
536  /* add newly appeared port to the virtual graph */
537
538  if (is_a2j)
539  {
540    vport_name = alsa_port_name;
541  }
542  else
543  {
544    vport_name = jack_port_name;
545  }
546
547  if (!ladish_graph_add_port(vgraph, vclient, port, vport_name, type, flags, false))
548  {
549    log_error("ladish_graph_add_port() failed.");
550    goto free_alsa_names;
551  }
552
553free_alsa_names:
554  if (a2j_fake_jack_port_name != NULL)
555  {
556    free(a2j_fake_jack_port_name);
557  }
558
559  if (is_a2j)
560  {
561    free(alsa_client_name);
562    free(alsa_port_name);
563  }
564
565fail:
566  return;
567}
568
569static void port_disappeared(void * context, uint64_t client_id, uint64_t port_id)
570{
571  ladish_client_handle client;
572  ladish_port_handle port;
573  ladish_graph_handle vgraph;
574
575  log_info("port_disappeared(%"PRIu64")", port_id);
576
577  client = ladish_graph_find_client_by_jack_id(virtualizer_ptr->jack_graph, client_id);
578  if (client == NULL)
579  {
580    log_error("Port of unknown JACK client with id %"PRIu64" disappeared", client_id);
581    return;
582  }
583
584  /* find the virtual graph that owns the app that owns the client that owns the disappeared port */
585  vgraph = ladish_client_get_vgraph(client);
586
587  port = ladish_graph_find_port_by_jack_id(virtualizer_ptr->jack_graph, port_id);
588  if (port == NULL)
589  {
590    log_error("Unknown JACK port with id %"PRIu64" disappeared", port_id);
591    return;
592  }
593
594  if (true)                     /* if client is supposed to be persisted */
595  {
596    ladish_port_set_jack_id(port, 0);
597    ladish_graph_hide_port(virtualizer_ptr->jack_graph, port);
598    ladish_graph_hide_port(vgraph, port);
599    client = ladish_graph_get_port_client(vgraph, port);
600    if (ladish_graph_is_client_looks_empty(vgraph, client))
601    {
602        ladish_graph_hide_client(vgraph, client);
603    }
604  }
605  else
606  {
607    ladish_graph_remove_port(virtualizer_ptr->jack_graph, port);
608
609    client = ladish_graph_remove_port(vgraph, port);
610    if (client != NULL)
611    {
612      if (ladish_graph_is_client_empty(vgraph, client))
613      {
614        ladish_graph_remove_client(vgraph, client);
615      }
616    }
617  }
618}
619
620static void port_renamed(void * context, uint64_t client_id, uint64_t port_id, const char * old_port_name, const char * new_port_name)
621{
622  ladish_client_handle client;
623  ladish_port_handle port;
624  ladish_graph_handle vgraph;
625
626  log_info("port_renamed(%"PRIu64", '%s', '%s')", port_id, old_port_name, new_port_name);
627
628  client = ladish_graph_find_client_by_jack_id(virtualizer_ptr->jack_graph, client_id);
629  if (client == NULL)
630  {
631    log_error("Port of unknown JACK client with id %"PRIu64" was renamed", client_id);
632    return;
633  }
634
635  /* find the virtual graph that owns the app that owns the client that owns the renamed port */
636  vgraph = ladish_client_get_vgraph(client);
637
638  port = ladish_graph_find_port_by_jack_id(virtualizer_ptr->jack_graph, port_id);
639  if (port == NULL)
640  {
641    log_error("Unknown JACK port with id %"PRIu64" was renamed", port_id);
642    return;
643  }
644
645  if (!ladish_graph_rename_port(virtualizer_ptr->jack_graph, port, new_port_name))
646  {
647    log_error("renaming of port in jack graph failed");
648  }
649
650  if (!ladish_graph_rename_port(vgraph, port, new_port_name))
651  {
652    log_error("renaming of port in virtual graph failed");
653  }
654}
655
656static bool ports_connect_request(void * context, ladish_graph_handle graph_handle, ladish_port_handle port1, ladish_port_handle port2)
657{
658  uint64_t port1_id;
659  uint64_t port2_id;
660
661  ASSERT(ladish_graph_get_opath(graph_handle)); /* studio or room virtual graph */
662  log_info("virtualizer: ports connect request");
663
664  port1_id = ladish_port_get_jack_id(port1);
665  port2_id = ladish_port_get_jack_id(port2);
666
667  if (port1_id == 0 || port2_id == 0)
668  {
669    /* TODO */
670    log_error("connecting room-studio link ports is not implemented yet");
671    return false;
672  }
673
674  graph_proxy_connect_ports(virtualizer_ptr->jack_graph_proxy, port1_id, port2_id);
675
676  return true;
677}
678
679static bool ports_disconnect_request(void * context, ladish_graph_handle graph_handle, uint64_t connection_id)
680{
681  ladish_port_handle port1;
682  ladish_port_handle port2;
683  uint64_t port1_id;
684  uint64_t port2_id;
685
686  ASSERT(ladish_graph_get_opath(graph_handle)); /* studio or room virtual graph */
687  log_info("virtualizer: ports disconnect request");
688
689  if (!ladish_graph_get_connection_ports(graph_handle, connection_id, &port1, &port2))
690  {
691    log_error("cannot find ports that are disconnect-requested");
692    ASSERT_NO_PASS;
693    return false;
694  }
695
696  port1_id = ladish_port_get_jack_id(port1);
697  port2_id = ladish_port_get_jack_id(port2);
698
699  if (port1_id == 0 || port2_id == 0)
700  {
701    /* TODO */
702    log_error("disconnecting room-studio link ports is not implemented yet");
703    return false;
704  }
705
706  graph_proxy_disconnect_ports(virtualizer_ptr->jack_graph_proxy, port1_id, port2_id);
707
708  return true;
709}
710
711static void ports_connected(void * context, uint64_t client1_id, uint64_t port1_id, uint64_t client2_id, uint64_t port2_id)
712{
713  ladish_port_handle port1;
714  ladish_port_handle port2;
715  uint64_t connection_id;
716  ladish_graph_handle vgraph1;
717  ladish_graph_handle vgraph2;
718
719  log_info("ports_connected %"PRIu64":%"PRIu64" %"PRIu64":%"PRIu64"", client1_id, port1_id, client2_id, port2_id);
720
721  if (!lookup_port(virtualizer_ptr, port1_id, &port1, &vgraph1))
722  {
723    return;
724  }
725
726  if (!lookup_port(virtualizer_ptr, port2_id, &port2, &vgraph2))
727  {
728    return;
729  }
730
731  if (vgraph1 != vgraph2)
732  {
733    /* TODO */
734    log_error("ignoring connection with endpoints in different vgraphs");
735    return;
736  }
737
738  ladish_graph_add_connection(virtualizer_ptr->jack_graph, port1, port2, false);
739
740  if (ladish_graph_find_connection(vgraph1, port1, port2, &connection_id))
741  {
742    log_info("showing hidden virtual connection");
743    ladish_graph_show_connection(vgraph1, connection_id);
744  }
745  else
746  {
747    log_info("creating new virtual connection");
748    ladish_graph_add_connection(vgraph1, port1, port2, false);
749  }
750}
751
752static void ports_disconnected(void * context, uint64_t client1_id, uint64_t port1_id, uint64_t client2_id, uint64_t port2_id)
753{
754  ladish_port_handle port1;
755  ladish_port_handle port2;
756  uint64_t connection_id;
757  ladish_graph_handle vgraph1;
758  ladish_graph_handle vgraph2;
759
760  log_info("ports_disconnected %"PRIu64":%"PRIu64" %"PRIu64":%"PRIu64"", client1_id, port1_id, client2_id, port2_id);
761
762  if (!lookup_port(virtualizer_ptr, port1_id, &port1, &vgraph1))
763  {
764    return;
765  }
766
767  if (!lookup_port(virtualizer_ptr, port2_id, &port2, &vgraph2))
768  {
769    return;
770  }
771
772  if (vgraph1 != vgraph2)
773  {
774    /* TODO */
775    log_error("ignoring connection with endpoints in different vgraphs");
776    return;
777  }
778
779  if (ladish_graph_find_connection(virtualizer_ptr->jack_graph, port1, port2, &connection_id))
780  {
781    ladish_graph_remove_connection(virtualizer_ptr->jack_graph, connection_id, true);
782  }
783  else
784  {
785    log_error("ports %"PRIu64":%"PRIu64" and %"PRIu64":%"PRIu64" are not connected in the JACK graph", client1_id, port1_id, client2_id, port2_id);
786  }
787
788  if (ladish_graph_find_connection(vgraph1, port1, port2, &connection_id))
789  {
790    ladish_graph_remove_connection(vgraph1, connection_id, false);
791  }
792  else
793  {
794    log_error("ports %"PRIu64":%"PRIu64" and %"PRIu64":%"PRIu64" are not connected in the virtual graph", client1_id, port1_id, client2_id, port2_id);
795  }
796}
797
798#undef virtualizer_ptr
799
800bool
801ladish_virtualizer_create(
802  graph_proxy_handle jack_graph_proxy,
803  ladish_graph_handle jack_graph,
804  ladish_graph_handle studio_graph,
805  ladish_virtualizer_handle * handle_ptr)
806{
807  struct virtualizer * virtualizer_ptr;
808
809  virtualizer_ptr = malloc(sizeof(struct virtualizer));
810  if (virtualizer_ptr == NULL)
811  {
812    log_error("malloc() failed for struct virtualizer");
813    return false;
814  }
815
816  virtualizer_ptr->jack_graph_proxy = jack_graph_proxy;
817  virtualizer_ptr->jack_graph = jack_graph;
818  virtualizer_ptr->system_client_id = 0;
819  virtualizer_ptr->our_clients_count = 0;
820
821  if (!graph_proxy_attach(
822        jack_graph_proxy,
823        virtualizer_ptr,
824        clear,
825        client_appeared,
826        NULL,                   /* jackdbus does not have client rename functionality (yet) */
827        client_disappeared,
828        port_appeared,
829        port_renamed,
830        port_disappeared,
831        ports_connected,
832        ports_disconnected))
833  {
834    free(virtualizer_ptr);
835    return false;
836  }
837
838  ladish_graph_set_connection_handlers(studio_graph, virtualizer_ptr, ports_connect_request, ports_disconnect_request);
839
840  *handle_ptr = (ladish_virtualizer_handle)virtualizer_ptr;
841  return true;
842}
843
844#define virtualizer_ptr ((struct virtualizer *)handle)
845
846unsigned int
847ladish_virtualizer_get_our_clients_count(
848  ladish_virtualizer_handle handle)
849{
850  return virtualizer_ptr->our_clients_count;
851}
852
853void
854ladish_virtualizer_destroy(
855  ladish_virtualizer_handle handle)
856{
857  log_info("ladish_virtualizer_destroy() called");
858
859  graph_proxy_detach((graph_proxy_handle)handle, virtualizer_ptr);
860  free(virtualizer_ptr);
861}
862
863#undef virtualizer_ptr
Note: See TracBrowser for help on using the browser.