Jack2  1.9.12
JackControlAPI.cpp
1 // u/* -*- Mode: C++ ; c-basic-offset: 4 -*- */
2 /*
3  JACK control API implementation
4 
5  Copyright (C) 2008 Nedko Arnaudov
6  Copyright (C) 2008 Grame
7 
8  This program is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; version 2 of the License.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 */
22 
23 #ifndef WIN32
24 #include <stdint.h>
25 #include <dirent.h>
26 #include <pthread.h>
27 #endif
28 
29 #include "types.h"
30 #include <string.h>
31 #include <errno.h>
32 #include <stdio.h>
33 #include <assert.h>
34 #include <signal.h>
35 #include <sys/utsname.h>
36 
37 #include "jslist.h"
38 #include "driver_interface.h"
39 #include "JackError.h"
40 #include "JackServer.h"
41 #include "shm.h"
42 #include "JackTools.h"
43 #include "JackControlAPI.h"
44 #include "JackLockedEngine.h"
45 #include "JackConstants.h"
46 #include "JackDriverLoader.h"
47 #include "JackServerGlobals.h"
48 
49 using namespace Jack;
50 
51 /* JackEngine::CheckPortsConnect() has some assumptions about char values */
52 static struct jack_constraint_enum_char_descriptor self_connect_mode_constraint_descr_array[] =
53 {
54  { ' ', "Don't restrict self connect requests" },
55  { 'E', "Fail self connect requests to external ports only" },
56  { 'e', "Ignore self connect requests to external ports only" },
57  { 'A', "Fail all self connect requests" },
58  { 'a', "Ignore all self connect requests" },
59  { 0 }
60 };
61 
63 {
64  JSList * drivers;
65  JSList * internals;
66  JSList * parameters;
67 
68  class JackServer * engine;
69 
70  /* string, server name */
71  union jackctl_parameter_value name;
72  union jackctl_parameter_value default_name;
73 
74  /* bool, whether to be "realtime" */
75  union jackctl_parameter_value realtime;
76  union jackctl_parameter_value default_realtime;
77 
78  /* int32_t */
79  union jackctl_parameter_value realtime_priority;
80  union jackctl_parameter_value default_realtime_priority;
81 
82  /* bool, whether to exit once all clients have closed their connections */
83  union jackctl_parameter_value temporary;
84  union jackctl_parameter_value default_temporary;
85 
86  /* bool, whether to be verbose */
87  union jackctl_parameter_value verbose;
88  union jackctl_parameter_value default_verbose;
89 
90  /* int32_t, msecs; if zero, use period size. */
91  union jackctl_parameter_value client_timeout;
92  union jackctl_parameter_value default_client_timeout;
93 
94  /* uint32_t, clock source type */
95  union jackctl_parameter_value clock_source;
96  union jackctl_parameter_value default_clock_source;
97 
98  /* uint32_t, max port number */
99  union jackctl_parameter_value port_max;
100  union jackctl_parameter_value default_port_max;
101 
102  /* bool */
103  union jackctl_parameter_value replace_registry;
104  union jackctl_parameter_value default_replace_registry;
105 
106  /* bool, synchronous or asynchronous engine mode */
107  union jackctl_parameter_value sync;
108  union jackctl_parameter_value default_sync;
109 
110  /* char enum, self connect mode mode */
111  union jackctl_parameter_value self_connect_mode;
112  union jackctl_parameter_value default_self_connect_mode;
113 };
114 
116 {
117  jack_driver_desc_t * desc_ptr;
118  JSList * parameters;
119  JSList * infos;
120 };
121 
123 {
124  jack_driver_desc_t * desc_ptr;
125  JSList * parameters;
126  int refnum;
127 };
128 
130 {
131  const char * name;
132  const char * short_description;
133  const char * long_description;
134  jackctl_param_type_t type;
135  bool is_set;
136  union jackctl_parameter_value * value_ptr;
137  union jackctl_parameter_value * default_value_ptr;
138 
139  union jackctl_parameter_value value;
140  union jackctl_parameter_value default_value;
141  struct jackctl_driver * driver_ptr;
142  char id;
143  jack_driver_param_constraint_desc_t * constraint_ptr;
144 };
145 
146 const char * jack_get_self_connect_mode_description(char mode)
147 {
148  struct jack_constraint_enum_char_descriptor * descr_ptr;
149 
150  for (descr_ptr = self_connect_mode_constraint_descr_array;
151  descr_ptr->value;
152  descr_ptr++)
153  if (descr_ptr->value == mode) return descr_ptr->short_desc;
154 
155  return NULL;
156 }
157 
158 static
159 struct jackctl_parameter *
160 jackctl_add_parameter(
161  JSList ** parameters_list_ptr_ptr,
162  const char * name,
163  const char * short_description,
164  const char * long_description,
165  jackctl_param_type_t type,
166  union jackctl_parameter_value * value_ptr,
167  union jackctl_parameter_value * default_value_ptr,
168  union jackctl_parameter_value value,
169  jack_driver_param_constraint_desc_t * constraint_ptr = NULL)
170 {
171  struct jackctl_parameter * parameter_ptr;
172 
173  parameter_ptr = (struct jackctl_parameter *)malloc(sizeof(struct jackctl_parameter));
174  if (parameter_ptr == NULL)
175  {
176  jack_error("Cannot allocate memory for jackctl_parameter structure.");
177  goto fail;
178  }
179 
180  parameter_ptr->name = name;
181  parameter_ptr->short_description = short_description;
182  parameter_ptr->long_description = long_description;
183  parameter_ptr->type = type;
184  parameter_ptr->is_set = false;
185 
186  if (value_ptr == NULL)
187  {
188  value_ptr = &parameter_ptr->value;
189  }
190 
191  if (default_value_ptr == NULL)
192  {
193  default_value_ptr = &parameter_ptr->default_value;
194  }
195 
196  parameter_ptr->value_ptr = value_ptr;
197  parameter_ptr->default_value_ptr = default_value_ptr;
198 
199  *value_ptr = *default_value_ptr = value;
200 
201  parameter_ptr->driver_ptr = NULL;
202  parameter_ptr->id = 0;
203  parameter_ptr->constraint_ptr = constraint_ptr;
204 
205  *parameters_list_ptr_ptr = jack_slist_append(*parameters_list_ptr_ptr, parameter_ptr);
206 
207  return parameter_ptr;
208 
209 fail:
210  return NULL;
211 }
212 
213 static
214 void
215 jackctl_free_driver_parameters(
216  struct jackctl_driver * driver_ptr)
217 {
218  JSList * next_node_ptr;
219 
220  while (driver_ptr->parameters)
221  {
222  next_node_ptr = driver_ptr->parameters->next;
223  free(driver_ptr->parameters->data);
224  free(driver_ptr->parameters);
225  driver_ptr->parameters = next_node_ptr;
226  }
227 }
228 
229 static
230 bool
231 jackctl_add_driver_parameters(
232  struct jackctl_driver * driver_ptr)
233 {
234  unsigned int i;
235 
236  union jackctl_parameter_value jackctl_value;
237  jackctl_param_type_t jackctl_type;
238  struct jackctl_parameter * parameter_ptr;
239  jack_driver_param_desc_t * descriptor_ptr;
240 
241  for (i = 0 ; i < driver_ptr->desc_ptr->nparams ; i++)
242  {
243  descriptor_ptr = driver_ptr->desc_ptr->params + i;
244 
245  switch (descriptor_ptr->type)
246  {
247  case JackDriverParamInt:
248  jackctl_type = JackParamInt;
249  jackctl_value.i = descriptor_ptr->value.i;
250  break;
251  case JackDriverParamUInt:
252  jackctl_type = JackParamUInt;
253  jackctl_value.ui = descriptor_ptr->value.ui;
254  break;
255  case JackDriverParamChar:
256  jackctl_type = JackParamChar;
257  jackctl_value.c = descriptor_ptr->value.c;
258  break;
259  case JackDriverParamString:
260  jackctl_type = JackParamString;
261  strcpy(jackctl_value.str, descriptor_ptr->value.str);
262  break;
263  case JackDriverParamBool:
264  jackctl_type = JackParamBool;
265  jackctl_value.b = descriptor_ptr->value.i;
266  break;
267  default:
268  jack_error("Unknown driver parameter type %i", (int)descriptor_ptr->type);
269  assert(0);
270  goto fail;
271  }
272 
273  parameter_ptr = jackctl_add_parameter(
274  &driver_ptr->parameters,
275  descriptor_ptr->name,
276  descriptor_ptr->short_desc,
277  descriptor_ptr->long_desc,
278  jackctl_type,
279  NULL,
280  NULL,
281  jackctl_value,
282  descriptor_ptr->constraint);
283 
284  if (parameter_ptr == NULL)
285  {
286  goto fail;
287  }
288 
289  parameter_ptr->driver_ptr = driver_ptr;
290  parameter_ptr->id = descriptor_ptr->character;
291  }
292 
293  return true;
294 
295 fail:
296  jackctl_free_driver_parameters(driver_ptr);
297 
298  return false;
299 }
300 
301 /* destroy jack_driver_param_desc_t list created by jackctl_create_param_list() */
302 static void
303 jackctl_destroy_param_list(
304  JSList * params)
305 {
306  JSList * next;
307 
308  while (params)
309  {
310  next = params->next;
311  free(params->data);
312  free(params);
313  params = next;
314  }
315 }
316 
317 /* for drivers and internals are configured through jack_driver_param_t JSList */
318 /* this function creates such list from a jackctl_parameter list */
319 static
320 bool
321 jackctl_create_param_list(
322  const JSList * paramlist,
323  JSList ** retparamlist)
324 {
325  jackctl_parameter * param_ptr;
326  jack_driver_param_t * retparam_ptr;
327 
328  *retparamlist = NULL;
329  while (paramlist != NULL)
330  {
331  param_ptr = (jackctl_parameter *)paramlist->data;
332  if (param_ptr->is_set)
333  {
334  /* jack_info("setting driver parameter %p ...", parameter_ptr); */
335  retparam_ptr = (jack_driver_param_t *)malloc(sizeof(jack_driver_param_t));
336  if (retparam_ptr == NULL)
337  {
338  jack_error ("Allocation of jack_driver_param_t structure failed");
339  goto destroy;
340  }
341 
342  retparam_ptr->character = param_ptr->id;
343 
344  switch (param_ptr->type)
345  {
346  case JackParamInt:
347  retparam_ptr->value.i = param_ptr->value_ptr->i;
348  break;
349  case JackParamUInt:
350  retparam_ptr->value.ui = param_ptr->value_ptr->ui;
351  break;
352  case JackParamChar:
353  retparam_ptr->value.c = param_ptr->value_ptr->c;
354  break;
355  case JackParamString:
356  strcpy(retparam_ptr->value.str, param_ptr->value_ptr->str);
357  break;
358  case JackParamBool:
359  retparam_ptr->value.i = param_ptr->value_ptr->b;
360  break;
361  default:
362  jack_error("Unknown parameter type %i", (int)param_ptr->type);
363  assert(0);
364  goto free;
365  }
366 
367  *retparamlist = jack_slist_append(*retparamlist, retparam_ptr);
368  }
369 
370  paramlist = paramlist->next;
371  }
372 
373  return true;
374 
375 free:
376  free(retparam_ptr);
377 destroy:
378  jackctl_destroy_param_list(*retparamlist);
379  return false;
380 }
381 
382 static int
383 jackctl_drivers_load(
384  struct jackctl_server * server_ptr)
385 {
386  struct jackctl_driver * driver_ptr;
387  JSList *node_ptr;
388  JSList *descriptor_node_ptr;
389 
390  descriptor_node_ptr = jack_drivers_load(NULL);
391  if (descriptor_node_ptr == NULL)
392  {
393  jack_error("Could not find any drivers in driver directory!");
394  return false;
395  }
396 
397  while (descriptor_node_ptr != NULL)
398  {
399  driver_ptr = (struct jackctl_driver *)malloc(sizeof(struct jackctl_driver));
400  if (driver_ptr == NULL)
401  {
402  jack_error("Memory allocation of jackctl_driver structure failed.");
403  goto next;
404  }
405 
406  driver_ptr->desc_ptr = (jack_driver_desc_t *)descriptor_node_ptr->data;
407  driver_ptr->parameters = NULL;
408  driver_ptr->infos = NULL;
409 
410  if (!jackctl_add_driver_parameters(driver_ptr))
411  {
412  assert(driver_ptr->parameters == NULL);
413  free(driver_ptr);
414  goto next;
415  }
416 
417  server_ptr->drivers = jack_slist_append(server_ptr->drivers, driver_ptr);
418 
419  next:
420  node_ptr = descriptor_node_ptr;
421  descriptor_node_ptr = descriptor_node_ptr->next;
422  free(node_ptr);
423  }
424 
425  return true;
426 }
427 
428 static
429 void
430 jackctl_server_free_drivers(
431  struct jackctl_server * server_ptr)
432 {
433  JSList * next_node_ptr;
434  struct jackctl_driver * driver_ptr;
435 
436  while (server_ptr->drivers)
437  {
438  next_node_ptr = server_ptr->drivers->next;
439  driver_ptr = (struct jackctl_driver *)server_ptr->drivers->data;
440 
441  jackctl_free_driver_parameters(driver_ptr);
442  free(driver_ptr->desc_ptr->params);
443  free(driver_ptr->desc_ptr);
444  free(driver_ptr);
445 
446  free(server_ptr->drivers);
447  server_ptr->drivers = next_node_ptr;
448  }
449 }
450 
451 static int
452 jackctl_internals_load(
453  struct jackctl_server * server_ptr)
454 {
455  struct jackctl_internal * internal_ptr;
456  JSList *node_ptr;
457  JSList *descriptor_node_ptr;
458 
459  descriptor_node_ptr = jack_internals_load(NULL);
460  if (descriptor_node_ptr == NULL)
461  {
462  jack_error("Could not find any internals in driver directory!");
463  return false;
464  }
465 
466  while (descriptor_node_ptr != NULL)
467  {
468  internal_ptr = (struct jackctl_internal *)malloc(sizeof(struct jackctl_internal));
469  if (internal_ptr == NULL)
470  {
471  jack_error("Memory allocation of jackctl_driver structure failed.");
472  goto next;
473  }
474 
475  internal_ptr->desc_ptr = (jack_driver_desc_t *)descriptor_node_ptr->data;
476  internal_ptr->parameters = NULL;
477  internal_ptr->refnum = -1;
478 
479  if (!jackctl_add_driver_parameters((struct jackctl_driver *)internal_ptr))
480  {
481  assert(internal_ptr->parameters == NULL);
482  free(internal_ptr);
483  goto next;
484  }
485 
486  server_ptr->internals = jack_slist_append(server_ptr->internals, internal_ptr);
487 
488  next:
489  node_ptr = descriptor_node_ptr;
490  descriptor_node_ptr = descriptor_node_ptr->next;
491  free(node_ptr);
492  }
493 
494  return true;
495 }
496 
497 static
498 void
499 jackctl_server_free_internals(
500  struct jackctl_server * server_ptr)
501 {
502  JSList * next_node_ptr;
503  struct jackctl_internal * internal_ptr;
504 
505  while (server_ptr->internals)
506  {
507  next_node_ptr = server_ptr->internals->next;
508  internal_ptr = (struct jackctl_internal *)server_ptr->internals->data;
509 
510  jackctl_free_driver_parameters((struct jackctl_driver *)internal_ptr);
511  free(internal_ptr->desc_ptr->params);
512  free(internal_ptr->desc_ptr);
513  free(internal_ptr);
514 
515  free(server_ptr->internals);
516  server_ptr->internals = next_node_ptr;
517  }
518 }
519 
520 static
521 void
522 jackctl_server_free_parameters(
523  struct jackctl_server * server_ptr)
524 {
525  JSList * next_node_ptr;
526 
527  while (server_ptr->parameters)
528  {
529  next_node_ptr = server_ptr->parameters->next;
530  free(server_ptr->parameters->data);
531  free(server_ptr->parameters);
532  server_ptr->parameters = next_node_ptr;
533  }
534 }
535 
536 #ifdef WIN32
537 
538 struct jackctl_sigmask
539 {
540  HANDLE wait_event;
541 };
542 
543 static jackctl_sigmask sigmask;
544 
545 static void signal_handler(int signum)
546 {
547  printf("Jack main caught signal %d\n", signum);
548  (void) signal(SIGINT, SIG_DFL);
549  SetEvent(sigmask.wait_event);
550 }
551 
554  unsigned int flags)
555 {
556  if ((sigmask.wait_event = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL) {
557  jack_error("CreateEvent fails err = %ld", GetLastError());
558  return 0;
559  }
560 
561  (void) signal(SIGINT, signal_handler);
562  (void) signal(SIGABRT, signal_handler);
563  (void) signal(SIGTERM, signal_handler);
564 
565  return &sigmask;
566 }
567 
569 {
570  if (WaitForSingleObject(signals->wait_event, INFINITE) != WAIT_OBJECT_0) {
571  jack_error("WaitForSingleObject fails err = %ld", GetLastError());
572  }
573 }
574 
575 #else
576 
578 {
579  sigset_t signals;
580 };
581 
582 static jackctl_sigmask sigmask;
583 
584 static
585 void
586 signal_handler(int sig)
587 {
588  /* this is used by the child (active) process, but it never
589  gets called unless we are already shutting down after
590  another signal.
591  */
592  char buf[64];
593  snprintf(buf, sizeof(buf), "Received signal %d during shutdown (ignored)\n", sig);
594 }
595 
596 SERVER_EXPORT jackctl_sigmask_t *
598  unsigned int flags)
599 {
600  sigset_t allsignals;
601  struct sigaction action;
602  int i;
603 
604  /* ensure that we are in our own process group so that
605  kill (SIG, -pgrp) does the right thing.
606  */
607 
608  setsid();
609 
610  pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
611 
612  /* what's this for?
613 
614  POSIX says that signals are delivered like this:
615 
616  * if a thread has blocked that signal, it is not
617  a candidate to receive the signal.
618  * of all threads not blocking the signal, pick
619  one at random, and deliver the signal.
620 
621  this means that a simple-minded multi-threaded program can
622  expect to get POSIX signals delivered randomly to any one
623  of its threads,
624 
625  here, we block all signals that we think we might receive
626  and want to catch. all "child" threads will inherit this
627  setting. if we create a thread that calls sigwait() on the
628  same set of signals, implicitly unblocking all those
629  signals. any of those signals that are delivered to the
630  process will be delivered to that thread, and that thread
631  alone. this makes cleanup for a signal-driven exit much
632  easier, since we know which thread is doing it and more
633  importantly, we are free to call async-unsafe functions,
634  because the code is executing in normal thread context
635  after a return from sigwait().
636  */
637 
638  sigemptyset(&sigmask.signals);
639  sigaddset(&sigmask.signals, SIGHUP);
640  sigaddset(&sigmask.signals, SIGINT);
641  sigaddset(&sigmask.signals, SIGQUIT);
642  sigaddset(&sigmask.signals, SIGPIPE);
643  sigaddset(&sigmask.signals, SIGTERM);
644 #ifndef __ANDROID__
645  /* android's bionic c doesn't provide pthread_cancel() and related functions.
646  * to solve this issue, use pthread_kill() & SIGUSR1 instead.
647  */
648  sigaddset(&sigmask.signals, SIGUSR1);
649 #endif
650  sigaddset(&sigmask.signals, SIGUSR2);
651 
652  /* all child threads will inherit this mask unless they
653  * explicitly reset it
654  */
655 
656  pthread_sigmask(SIG_BLOCK, &sigmask.signals, 0);
657 
658  /* install a do-nothing handler because otherwise pthreads
659  behaviour is undefined when we enter sigwait.
660  */
661 
662  sigfillset(&allsignals);
663  action.sa_handler = signal_handler;
664  action.sa_mask = allsignals;
665  action.sa_flags = SA_RESTART|SA_RESETHAND;
666 
667  for (i = 1; i < NSIG; i++)
668  {
669  if (sigismember (&sigmask.signals, i))
670  {
671  sigaction(i, &action, 0);
672  }
673  }
674 
675  return &sigmask;
676 }
677 
678 SERVER_EXPORT void
680 {
681  int sig;
682  bool waiting = true;
683 
684  while (waiting) {
685  #if defined(sun) && !defined(__sun__) // SUN compiler only, to check
686  sigwait(&sigmask->signals);
687  #else
688  sigwait(&sigmask->signals, &sig);
689  #endif
690  fprintf(stderr, "Jack main caught signal %d\n", sig);
691 
692  switch (sig) {
693  case SIGUSR1:
694  //jack_dump_configuration(engine, 1);
695  break;
696  case SIGUSR2:
697  // driver exit
698  waiting = false;
699  break;
700  case SIGTTOU:
701  break;
702  default:
703  waiting = false;
704  break;
705  }
706  }
707 
708  if (sig != SIGSEGV) {
709  // unblock signals so we can see them during shutdown.
710  // this will help prod developers not to lose sight of
711  // bugs that cause segfaults etc. during shutdown.
712  sigprocmask(SIG_UNBLOCK, &sigmask->signals, 0);
713  }
714 }
715 #endif
716 
717 static
719 get_realtime_priority_constraint()
720 {
721  jack_driver_param_constraint_desc_t * constraint_ptr;
722  int min, max;
723 
724  if (!jack_get_thread_realtime_priority_range(&min, &max))
725  {
726  return NULL;
727  }
728 
729  //jack_info("realtime priority range is (%d,%d)", min, max);
730 
731  constraint_ptr = (jack_driver_param_constraint_desc_t *)calloc(1, sizeof(jack_driver_param_constraint_desc_t));
732  if (constraint_ptr == NULL)
733  {
734  jack_error("Cannot allocate memory for jack_driver_param_constraint_desc_t structure.");
735  return NULL;
736  }
737  constraint_ptr->flags = JACK_CONSTRAINT_FLAG_RANGE;
738 
739  constraint_ptr->constraint.range.min.i = min;
740  constraint_ptr->constraint.range.max.i = max;
741 
742  return constraint_ptr;
743 }
744 
746  bool (* on_device_acquire)(const char * device_name),
747  void (* on_device_release)(const char * device_name))
748 {
749  struct jackctl_server * server_ptr;
750  union jackctl_parameter_value value;
751 
752  server_ptr = (struct jackctl_server *)malloc(sizeof(struct jackctl_server));
753  if (server_ptr == NULL)
754  {
755  jack_error("Cannot allocate memory for jackctl_server structure.");
756  goto fail;
757  }
758 
759  server_ptr->drivers = NULL;
760  server_ptr->internals = NULL;
761  server_ptr->parameters = NULL;
762  server_ptr->engine = NULL;
763 
764  strcpy(value.str, JackTools::DefaultServerName());
765  if (jackctl_add_parameter(
766  &server_ptr->parameters,
767  "name",
768  "Server name to use.",
769  "",
771  &server_ptr->name,
772  &server_ptr->default_name,
773  value) == NULL)
774  {
775  goto fail_free_parameters;
776  }
777 
778  value.b = true;
779  if (jackctl_add_parameter(
780  &server_ptr->parameters,
781  "realtime",
782  "Whether to use realtime mode.",
783  "Use realtime scheduling. This is needed for reliable low-latency performance. On most systems, it requires JACK to run with special scheduler and memory allocation privileges, which may be obtained in several ways. On Linux you should use PAM.",
785  &server_ptr->realtime,
786  &server_ptr->default_realtime,
787  value) == NULL)
788  {
789  goto fail_free_parameters;
790  }
791 
792  struct utsname utsname;
793  int success;
794  success = uname( &utsname );
795  if( success == 0 && strstr( utsname.version, "ccrma" ) )
796  value.i = 60;
797  else
798  value.i = 20;
799  if (jackctl_add_parameter(
800  &server_ptr->parameters,
801  "realtime-priority",
802  "Scheduler priority when running in realtime mode.",
803  "",
804  JackParamInt,
805  &server_ptr->realtime_priority,
806  &server_ptr->default_realtime_priority,
807  value,
808  get_realtime_priority_constraint()) == NULL)
809  {
810  goto fail_free_parameters;
811  }
812 
813  value.b = false;
814  if (jackctl_add_parameter(
815  &server_ptr->parameters,
816  "temporary",
817  "Exit once all clients have closed their connections.",
818  "",
820  &server_ptr->temporary,
821  &server_ptr->default_temporary,
822  value) == NULL)
823  {
824  goto fail_free_parameters;
825  }
826 
827  value.b = false;
828  if (jackctl_add_parameter(
829  &server_ptr->parameters,
830  "verbose",
831  "Verbose mode.",
832  "",
834  &server_ptr->verbose,
835  &server_ptr->default_verbose,
836  value) == NULL)
837  {
838  goto fail_free_parameters;
839  }
840 
841  value.i = 0;
842  if (jackctl_add_parameter(
843  &server_ptr->parameters,
844  "client-timeout",
845  "Client timeout limit in milliseconds.",
846  "",
847  JackParamInt,
848  &server_ptr->client_timeout,
849  &server_ptr->default_client_timeout,
850  value) == NULL)
851  {
852  goto fail_free_parameters;
853  }
854 
855  value.ui = 0;
856  if (jackctl_add_parameter(
857  &server_ptr->parameters,
858  "clock-source",
859  "Clocksource type : c(ycle) | h(pet) | s(ystem).",
860  "",
862  &server_ptr->clock_source,
863  &server_ptr->default_clock_source,
864  value) == NULL)
865  {
866  goto fail_free_parameters;
867  }
868 
869  value.ui = PORT_NUM;
870  if (jackctl_add_parameter(
871  &server_ptr->parameters,
872  "port-max",
873  "Maximum number of ports.",
874  "",
876  &server_ptr->port_max,
877  &server_ptr->default_port_max,
878  value) == NULL)
879  {
880  goto fail_free_parameters;
881  }
882 
883  value.b = false;
884  if (jackctl_add_parameter(
885  &server_ptr->parameters,
886  "replace-registry",
887  "Replace shared memory registry.",
888  "",
890  &server_ptr->replace_registry,
891  &server_ptr->default_replace_registry,
892  value) == NULL)
893  {
894  goto fail_free_parameters;
895  }
896 
897  value.b = false;
898  if (jackctl_add_parameter(
899  &server_ptr->parameters,
900  "sync",
901  "Use server synchronous mode.",
902  "",
904  &server_ptr->sync,
905  &server_ptr->default_sync,
906  value) == NULL)
907  {
908  goto fail_free_parameters;
909  }
910 
911  value.c = JACK_DEFAULT_SELF_CONNECT_MODE;
912  if (jackctl_add_parameter(
913  &server_ptr->parameters,
914  "self-connect-mode",
915  "Self connect mode.",
916  "Whether JACK clients are allowed to connect their own ports",
918  &server_ptr->self_connect_mode,
919  &server_ptr->default_self_connect_mode,
920  value,
921  jack_constraint_compose_enum_char(
922  JACK_CONSTRAINT_FLAG_STRICT | JACK_CONSTRAINT_FLAG_FAKE_VALUE,
923  self_connect_mode_constraint_descr_array)) == NULL)
924  {
925  goto fail_free_parameters;
926  }
927 
928  JackServerGlobals::on_device_acquire = on_device_acquire;
929  JackServerGlobals::on_device_release = on_device_release;
930 
931  if (!jackctl_drivers_load(server_ptr))
932  {
933  goto fail_free_parameters;
934  }
935 
936  /* Allowed to fail */
937  jackctl_internals_load(server_ptr);
938 
939  return server_ptr;
940 
941 fail_free_parameters:
942  jackctl_server_free_parameters(server_ptr);
943 
944  free(server_ptr);
945 
946 fail:
947  return NULL;
948 }
949 
950 SERVER_EXPORT void jackctl_server_destroy(jackctl_server *server_ptr)
951 {
952  if (server_ptr) {
953  jackctl_server_free_drivers(server_ptr);
954  jackctl_server_free_internals(server_ptr);
955  jackctl_server_free_parameters(server_ptr);
956  free(server_ptr);
957  }
958 }
959 
960 SERVER_EXPORT const JSList * jackctl_server_get_drivers_list(jackctl_server *server_ptr)
961 {
962  return (server_ptr) ? server_ptr->drivers : NULL;
963 }
964 
965 SERVER_EXPORT bool jackctl_server_stop(jackctl_server *server_ptr)
966 {
967  if (server_ptr) {
968  server_ptr->engine->Stop();
969  return true;
970  } else {
971  return false;
972  }
973 }
974 
975 SERVER_EXPORT bool jackctl_server_close(jackctl_server *server_ptr)
976 {
977  if (server_ptr) {
978  server_ptr->engine->Close();
979  delete server_ptr->engine;
980 
981  /* clean up shared memory and files from this server instance */
982  jack_log("Cleaning up shared memory");
983 
984  jack_cleanup_shm();
985 
986  jack_log("Cleaning up files");
987 
988  JackTools::CleanupFiles(server_ptr->name.str);
989 
990  jack_log("Unregistering server `%s'", server_ptr->name.str);
991 
992  jack_unregister_server(server_ptr->name.str);
993 
994  server_ptr->engine = NULL;
995 
996  return true;
997  } else {
998  return false;
999  }
1000 }
1001 
1002 SERVER_EXPORT const JSList * jackctl_server_get_parameters(jackctl_server *server_ptr)
1003 {
1004  return (server_ptr) ? server_ptr->parameters : NULL;
1005 }
1006 
1007 SERVER_EXPORT bool
1009  jackctl_server *server_ptr,
1010  jackctl_driver *driver_ptr)
1011 {
1012  JSList * paramlist = NULL;
1013 
1014  try {
1015 
1016  if (!server_ptr || !driver_ptr) {
1017  return false;
1018  }
1019 
1020  int rc = jack_register_server(server_ptr->name.str, server_ptr->replace_registry.b);
1021  switch (rc)
1022  {
1023  case EEXIST:
1024  jack_error("`%s' server already active", server_ptr->name.str);
1025  goto fail;
1026  case ENOSPC:
1027  jack_error("Too many servers already active");
1028  goto fail;
1029  case ENOMEM:
1030  jack_error("No access to shm registry");
1031  goto fail;
1032  }
1033 
1034  jack_log("Server `%s' registered", server_ptr->name.str);
1035 
1036  /* clean up shared memory and files from any previous
1037  * instance of this server name */
1038  jack_cleanup_shm();
1039  JackTools::CleanupFiles(server_ptr->name.str);
1040 
1041  if (!server_ptr->realtime.b && server_ptr->client_timeout.i == 0) {
1042  server_ptr->client_timeout.i = 500; /* 0.5 sec; usable when non realtime. */
1043  }
1044 
1045  /* check port max value before allocating server */
1046  if (server_ptr->port_max.ui > PORT_NUM_MAX) {
1047  jack_error("Jack server started with too much ports %d (when port max can be %d)", server_ptr->port_max.ui, PORT_NUM_MAX);
1048  goto fail;
1049  }
1050 
1051  /* get the engine/driver started */
1052  server_ptr->engine = new JackServer(
1053  server_ptr->sync.b,
1054  server_ptr->temporary.b,
1055  server_ptr->client_timeout.i,
1056  server_ptr->realtime.b,
1057  server_ptr->realtime_priority.i,
1058  server_ptr->port_max.ui,
1059  server_ptr->verbose.b,
1060  (jack_timer_type_t)server_ptr->clock_source.ui,
1061  server_ptr->self_connect_mode.c,
1062  server_ptr->name.str);
1063  if (server_ptr->engine == NULL)
1064  {
1065  jack_error("Failed to create new JackServer object");
1066  goto fail_unregister;
1067  }
1068 
1069  if (!jackctl_create_param_list(driver_ptr->parameters, &paramlist)) goto fail_delete;
1070  rc = server_ptr->engine->Open(driver_ptr->desc_ptr, paramlist);
1071  jackctl_destroy_param_list(paramlist);
1072  if (rc < 0)
1073  {
1074  jack_error("JackServer::Open failed with %d", rc);
1075  goto fail_delete;
1076  }
1077 
1078  return true;
1079 
1080  } catch (std::exception e) {
1081  jack_error("jackctl_server_open error...");
1082  jackctl_destroy_param_list(paramlist);
1083  }
1084 
1085 fail_delete:
1086  delete server_ptr->engine;
1087  server_ptr->engine = NULL;
1088 
1089 fail_unregister:
1090  jack_log("Cleaning up shared memory");
1091 
1092  jack_cleanup_shm();
1093 
1094  jack_log("Cleaning up files");
1095 
1096  JackTools::CleanupFiles(server_ptr->name.str);
1097 
1098  jack_log("Unregistering server `%s'", server_ptr->name.str);
1099 
1100  jack_unregister_server(server_ptr->name.str);
1101 
1102 fail:
1103  return false;
1104 }
1105 
1106 SERVER_EXPORT bool
1108  jackctl_server *server_ptr)
1109 {
1110  if (!server_ptr) {
1111  return false;
1112  } else {
1113  int rc = server_ptr->engine->Start();
1114  bool result = rc >= 0;
1115  if (! result)
1116  {
1117  jack_error("JackServer::Start() failed with %d", rc);
1118  }
1119  return result;
1120  }
1121 }
1122 
1123 SERVER_EXPORT const char * jackctl_driver_get_name(jackctl_driver *driver_ptr)
1124 {
1125  return (driver_ptr) ? driver_ptr->desc_ptr->name : NULL;
1126 }
1127 
1128 SERVER_EXPORT jackctl_driver_type_t jackctl_driver_get_type(jackctl_driver *driver_ptr)
1129 {
1130  return (driver_ptr) ? (jackctl_driver_type_t)driver_ptr->desc_ptr->type : (jackctl_driver_type_t)0;
1131 }
1132 
1133 SERVER_EXPORT const JSList * jackctl_driver_get_parameters(jackctl_driver *driver_ptr)
1134 {
1135  return (driver_ptr) ? driver_ptr->parameters : NULL;
1136 }
1137 
1138 SERVER_EXPORT jack_driver_desc_t * jackctl_driver_get_desc(jackctl_driver *driver_ptr)
1139 {
1140  return (driver_ptr) ? driver_ptr->desc_ptr : NULL;
1141 }
1142 
1143 SERVER_EXPORT const char * jackctl_parameter_get_name(jackctl_parameter *parameter_ptr)
1144 {
1145  return (parameter_ptr) ? parameter_ptr->name : NULL;
1146 }
1147 
1148 SERVER_EXPORT const char * jackctl_parameter_get_short_description(jackctl_parameter *parameter_ptr)
1149 {
1150  return (parameter_ptr) ? parameter_ptr->short_description : NULL;
1151 }
1152 
1153 SERVER_EXPORT const char * jackctl_parameter_get_long_description(jackctl_parameter *parameter_ptr)
1154 {
1155  return (parameter_ptr) ? parameter_ptr->long_description : NULL;
1156 }
1157 
1159 {
1160  return (parameter_ptr) ? (parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_RANGE) != 0) : false;
1161 }
1162 
1164 {
1165  return (parameter_ptr) ? (parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_RANGE) == 0): false;
1166 }
1167 
1169 {
1170  if (!parameter_ptr) {
1171  return 0;
1172  }
1173 
1174  if (!jackctl_parameter_has_enum_constraint(parameter_ptr))
1175  {
1176  return 0;
1177  }
1178 
1179  return parameter_ptr->constraint_ptr->constraint.enumeration.count;
1180  }
1181 
1183 {
1184  jack_driver_param_value_t * value_ptr;
1185  union jackctl_parameter_value jackctl_value;
1186 
1187  if (!parameter_ptr) {
1188  memset(&jackctl_value, 0, sizeof(jackctl_value));
1189  return jackctl_value;
1190  }
1191 
1192  value_ptr = &parameter_ptr->constraint_ptr->constraint.enumeration.possible_values_array[index].value;
1193 
1194  switch (parameter_ptr->type)
1195  {
1196  case JackParamInt:
1197  jackctl_value.i = value_ptr->i;
1198  break;
1199  case JackParamUInt:
1200  jackctl_value.ui = value_ptr->ui;
1201  break;
1202  case JackParamChar:
1203  jackctl_value.c = value_ptr->c;
1204  break;
1205  case JackParamString:
1206  strcpy(jackctl_value.str, value_ptr->str);
1207  break;
1208  default:
1209  jack_error("Bad driver parameter type %i (enum constraint)", (int)parameter_ptr->type);
1210  assert(0);
1211  }
1212 
1213  return jackctl_value;
1214 }
1215 
1216 SERVER_EXPORT const char * jackctl_parameter_get_enum_constraint_description(jackctl_parameter *parameter_ptr, uint32_t index)
1217 {
1218  return (parameter_ptr) ? parameter_ptr->constraint_ptr->constraint.enumeration.possible_values_array[index].short_desc : NULL;
1219 }
1220 
1221 SERVER_EXPORT void jackctl_parameter_get_range_constraint(jackctl_parameter *parameter_ptr, union jackctl_parameter_value * min_ptr, union jackctl_parameter_value * max_ptr)
1222 {
1223  if (!parameter_ptr || !min_ptr || !max_ptr) {
1224  return;
1225  }
1226 
1227  switch (parameter_ptr->type)
1228  {
1229  case JackParamInt:
1230  min_ptr->i = parameter_ptr->constraint_ptr->constraint.range.min.i;
1231  max_ptr->i = parameter_ptr->constraint_ptr->constraint.range.max.i;
1232  return;
1233  case JackParamUInt:
1234  min_ptr->ui = parameter_ptr->constraint_ptr->constraint.range.min.ui;
1235  max_ptr->ui = parameter_ptr->constraint_ptr->constraint.range.max.ui;
1236  return;
1237  default:
1238  jack_error("Bad driver parameter type %i (range constraint)", (int)parameter_ptr->type);
1239  assert(0);
1240  }
1241 }
1242 
1244 {
1245  return (parameter_ptr) ? (parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_STRICT) != 0) : false;
1246 }
1247 
1249 {
1250  return (parameter_ptr) ? (parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_FAKE_VALUE) != 0) : false;
1251 }
1252 
1253 SERVER_EXPORT jackctl_param_type_t jackctl_parameter_get_type(jackctl_parameter *parameter_ptr)
1254 {
1255  return (parameter_ptr) ? parameter_ptr->type : (jackctl_param_type_t)0;
1256 }
1257 
1258 SERVER_EXPORT char jackctl_parameter_get_id(jackctl_parameter_t * parameter_ptr)
1259 {
1260  return (parameter_ptr) ? parameter_ptr->id : 0;
1261 }
1262 
1263 SERVER_EXPORT bool jackctl_parameter_is_set(jackctl_parameter *parameter_ptr)
1264 {
1265  return (parameter_ptr) ? parameter_ptr->is_set : false;
1266 }
1267 
1269 {
1270  if (parameter_ptr) {
1271  return *parameter_ptr->value_ptr;
1272  } else {
1273  union jackctl_parameter_value jackctl_value;
1274  memset(&jackctl_value, 0, sizeof(jackctl_value));
1275  return jackctl_value;
1276  }
1277 }
1278 
1279 SERVER_EXPORT bool jackctl_parameter_reset(jackctl_parameter *parameter_ptr)
1280 {
1281  if (!parameter_ptr) {
1282  return NULL;
1283  }
1284 
1285  if (!parameter_ptr->is_set)
1286  {
1287  return true;
1288  }
1289 
1290  parameter_ptr->is_set = false;
1291 
1292  *parameter_ptr->value_ptr = *parameter_ptr->default_value_ptr;
1293 
1294  return true;
1295 }
1296 
1297 SERVER_EXPORT bool jackctl_parameter_set_value(jackctl_parameter *parameter_ptr, const union jackctl_parameter_value * value_ptr)
1298 {
1299  if (!parameter_ptr || !value_ptr) {
1300  return NULL;
1301  }
1302 
1303  parameter_ptr->is_set = true;
1304  *parameter_ptr->value_ptr = *value_ptr;
1305 
1306  return true;
1307 }
1308 
1310 {
1311  if (parameter_ptr) {
1312  return *parameter_ptr->default_value_ptr;
1313  } else {
1314  union jackctl_parameter_value jackctl_value;
1315  memset(&jackctl_value, 0, sizeof(jackctl_value));
1316  return jackctl_value;
1317  }
1318 }
1319 
1320 // Internals clients
1321 
1322 SERVER_EXPORT const JSList * jackctl_server_get_internals_list(jackctl_server *server_ptr)
1323 {
1324  return (server_ptr) ? server_ptr->internals : NULL;
1325 }
1326 
1327 SERVER_EXPORT const char * jackctl_internal_get_name(jackctl_internal *internal_ptr)
1328 {
1329  return (internal_ptr) ? internal_ptr->desc_ptr->name : NULL;
1330 }
1331 
1332 SERVER_EXPORT const JSList * jackctl_internal_get_parameters(jackctl_internal *internal_ptr)
1333 {
1334  return (internal_ptr) ? internal_ptr->parameters : NULL;
1335 }
1336 
1337 SERVER_EXPORT bool jackctl_server_load_internal(
1338  jackctl_server * server_ptr,
1339  jackctl_internal * internal)
1340 {
1341  if (!server_ptr || !internal) {
1342  return false;
1343  }
1344 
1345  int status;
1346  if (server_ptr->engine != NULL) {
1347  JSList * paramlist;
1348  if (!jackctl_create_param_list(internal->parameters, &paramlist)) return false;
1349  server_ptr->engine->InternalClientLoad2(internal->desc_ptr->name, internal->desc_ptr->name, paramlist, JackNullOption, &internal->refnum, -1, &status);
1350  jackctl_destroy_param_list(paramlist);
1351  return (internal->refnum > 0);
1352  } else {
1353  return false;
1354  }
1355 }
1356 
1358  jackctl_server * server_ptr,
1359  jackctl_internal * internal)
1360 {
1361  if (!server_ptr || !internal) {
1362  return false;
1363  }
1364 
1365  int status;
1366  if (server_ptr->engine != NULL && internal->refnum > 0) {
1367  // Client object is internally kept in JackEngine, and will be deallocated in InternalClientUnload
1368  return ((server_ptr->engine->GetEngine()->InternalClientUnload(internal->refnum, &status)) == 0);
1369  } else {
1370  return false;
1371  }
1372 }
1373 
1375  jackctl_server * server_ptr,
1376  const char * file)
1377 {
1378  if (!server_ptr || !file || !server_ptr->engine) {
1379  return false;
1380  }
1381 
1382  return (server_ptr->engine->LoadInternalSessionFile(file) >= 0);
1383 }
1384 
1385 SERVER_EXPORT bool jackctl_server_add_slave(jackctl_server * server_ptr, jackctl_driver * driver_ptr)
1386 {
1387  if (server_ptr && server_ptr->engine) {
1388  if (server_ptr->engine->IsRunning()) {
1389  jack_error("Cannot add a slave in a running server");
1390  return false;
1391  } else {
1392  JSList * paramlist;
1393  if (!jackctl_create_param_list(driver_ptr->parameters, &paramlist)) return false;
1394  JackDriverInfo* info = server_ptr->engine->AddSlave(driver_ptr->desc_ptr, paramlist);
1395  jackctl_destroy_param_list(paramlist);
1396  if (info) {
1397  driver_ptr->infos = jack_slist_append(driver_ptr->infos, info);
1398  return true;
1399  } else {
1400  return false;
1401  }
1402  }
1403  } else {
1404  return false;
1405  }
1406 }
1407 
1408 SERVER_EXPORT bool jackctl_server_remove_slave(jackctl_server * server_ptr, jackctl_driver * driver_ptr)
1409 {
1410  if (server_ptr && server_ptr->engine) {
1411  if (server_ptr->engine->IsRunning()) {
1412  jack_error("Cannot remove a slave from a running server");
1413  return false;
1414  } else {
1415  if (driver_ptr->infos) {
1416  JackDriverInfo* info = (JackDriverInfo*)driver_ptr->infos->data;
1417  assert(info);
1418  driver_ptr->infos = jack_slist_remove(driver_ptr->infos, info);
1419  server_ptr->engine->RemoveSlave(info);
1420  delete info;
1421  return true;
1422  } else {
1423  return false;
1424  }
1425  }
1426  } else {
1427  return false;
1428  }
1429 }
1430 
1431 SERVER_EXPORT bool jackctl_server_switch_master(jackctl_server * server_ptr, jackctl_driver * driver_ptr)
1432 {
1433  if (server_ptr && server_ptr->engine) {
1434  JSList * paramlist;
1435  if (!jackctl_create_param_list(driver_ptr->parameters, &paramlist)) return false;
1436  bool ret = (server_ptr->engine->SwitchMaster(driver_ptr->desc_ptr, paramlist) == 0);
1437  jackctl_destroy_param_list(paramlist);
1438  return ret;
1439  } else {
1440  return false;
1441  }
1442 }
1443 
1444 
SERVER_EXPORT const char * jackctl_parameter_get_long_description(jackctl_parameter *parameter_ptr)
jackctl_driver_type_t
Definition: control.h:50
value type is a signed integer
Definition: control.h:42
SERVER_EXPORT bool jackctl_parameter_is_set(jackctl_parameter *parameter_ptr)
SERVER_EXPORT union jackctl_parameter_value jackctl_parameter_get_value(jackctl_parameter *parameter_ptr)
SERVER_EXPORT jackctl_sigmask_t * jackctl_setup_signals(unsigned int flags)
char str[JACK_PARAM_STRING_MAX+1]
member used for JackParamString
SERVER_EXPORT union jackctl_parameter_value jackctl_parameter_get_default_value(jackctl_parameter *parameter_ptr)
value type is an unsigned integer
Definition: control.h:43
SERVER_EXPORT bool jackctl_server_open(jackctl_server *server_ptr, jackctl_driver *driver_ptr)
SERVER_EXPORT void jackctl_parameter_get_range_constraint(jackctl_parameter *parameter_ptr, union jackctl_parameter_value *min_ptr, union jackctl_parameter_value *max_ptr)
value type is a char
Definition: control.h:44
SERVER_EXPORT void jack_error(const char *fmt,...)
Definition: JackError.cpp:92
SERVER_EXPORT jackctl_server_t * jackctl_server_create(bool(*on_device_acquire)(const char *device_name), void(*on_device_release)(const char *device_name))
SERVER_EXPORT bool jackctl_parameter_reset(jackctl_parameter *parameter_ptr)
uint32_t ui
member used for JackParamUInt
jack_driver_type_t type
jack_driver_param_value_t value
SERVER_EXPORT bool jackctl_server_switch_master(jackctl_server *server_ptr, jackctl_driver *driver_ptr)
value type is a boolean
Definition: control.h:46
SERVER_EXPORT const char * jackctl_internal_get_name(jackctl_internal *internal_ptr)
int32_t i
member used for JackParamInt
SERVER_EXPORT const char * jackctl_parameter_get_name(jackctl_parameter *parameter_ptr)
SERVER_EXPORT bool jackctl_server_stop(jackctl_server *server_ptr)
bool b
member used for JackParamBool
Type for parameter value.
SERVER_EXPORT const JSList * jackctl_driver_get_parameters(jackctl_driver *driver_ptr)
value type is a string with max size of JACK_PARAM_STRING_MAX+1 chars
Definition: control.h:45
SERVER_EXPORT bool jackctl_parameter_has_range_constraint(jackctl_parameter *parameter_ptr)
SERVER_EXPORT bool jackctl_server_close(jackctl_server *server_ptr)
SERVER_EXPORT bool jackctl_server_remove_slave(jackctl_server *server_ptr, jackctl_driver *driver_ptr)
SERVER_EXPORT const char * jackctl_parameter_get_enum_constraint_description(jackctl_parameter *parameter_ptr, uint32_t index)
SERVER_EXPORT const JSList * jackctl_server_get_internals_list(jackctl_server *server_ptr)
jack_driver_param_constraint_desc_t * constraint
SERVER_EXPORT const char * jackctl_parameter_get_short_description(jackctl_parameter *parameter_ptr)
SERVER_EXPORT bool jackctl_parameter_constraint_is_fake_value(jackctl_parameter_t *parameter_ptr)
struct jack_driver_param_constraint_desc_t::@0::@1 range
SERVER_EXPORT jackctl_param_type_t jackctl_parameter_get_type(jackctl_parameter *parameter_ptr)
SERVER_EXPORT const JSList * jackctl_server_get_drivers_list(jackctl_server *server_ptr)
char name[JACK_DRIVER_NAME_MAX+1]
char name[JACK_DRIVER_NAME_MAX+1]
SERVER_EXPORT bool jackctl_server_start(jackctl_server *server_ptr)
The Jack server.
Definition: JackServer.h:46
SERVER_EXPORT bool jackctl_parameter_constraint_is_strict(jackctl_parameter_t *parameter_ptr)
SERVER_EXPORT uint32_t jackctl_parameter_get_enum_constraints_count(jackctl_parameter *parameter_ptr)
SERVER_EXPORT bool jackctl_parameter_set_value(jackctl_parameter *parameter_ptr, const union jackctl_parameter_value *value_ptr)
SERVER_EXPORT bool jackctl_server_add_slave(jackctl_server *server_ptr, jackctl_driver *driver_ptr)
SERVER_EXPORT bool jackctl_server_load_session_file(jackctl_server *server_ptr, const char *file)
jackctl_param_type_t
Definition: control.h:40
SERVER_EXPORT const char * jackctl_driver_get_name(jackctl_driver *driver_ptr)
SERVER_EXPORT union jackctl_parameter_value jackctl_parameter_get_enum_constraint_value(jackctl_parameter *parameter_ptr, uint32_t index)
SERVER_EXPORT bool jackctl_server_unload_internal(jackctl_server *server_ptr, jackctl_internal *internal)
jack_driver_param_type_t type
SERVER_EXPORT char jackctl_parameter_get_id(jackctl_parameter_t *parameter_ptr)
SERVER_EXPORT const JSList * jackctl_internal_get_parameters(jackctl_internal *internal_ptr)
struct jack_driver_param_constraint_desc_t::@0::@2 enumeration
SERVER_EXPORT void jackctl_server_destroy(jackctl_server *server_ptr)
SERVER_EXPORT jackctl_driver_type_t jackctl_driver_get_type(jackctl_driver *driver_ptr)
char c
member used for JackParamChar
SERVER_EXPORT const JSList * jackctl_server_get_parameters(jackctl_server *server_ptr)
SERVER_EXPORT bool jackctl_parameter_has_enum_constraint(jackctl_parameter *parameter_ptr)
SERVER_EXPORT void jackctl_wait_signals(jackctl_sigmask_t *sigmask)
SERVER_EXPORT void jack_log(const char *fmt,...)
Definition: JackError.cpp:108
SERVER_EXPORT bool jackctl_server_load_internal(jackctl_server *server_ptr, jackctl_internal *internal)
jack_driver_param_desc_t * params