Jack2  1.9.13
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 
36 #include "jslist.h"
37 #include "driver_interface.h"
38 #include "JackError.h"
39 #include "JackServer.h"
40 #include "shm.h"
41 #include "JackTools.h"
42 #include "JackControlAPI.h"
43 #include "JackLockedEngine.h"
44 #include "JackConstants.h"
45 #include "JackDriverLoader.h"
46 #include "JackServerGlobals.h"
47 
48 using namespace Jack;
49 
50 /* JackEngine::CheckPortsConnect() has some assumptions about char values */
51 static struct jack_constraint_enum_char_descriptor self_connect_mode_constraint_descr_array[] =
52 {
53  { ' ', "Don't restrict self connect requests" },
54  { 'E', "Fail self connect requests to external ports only" },
55  { 'e', "Ignore self connect requests to external ports only" },
56  { 'A', "Fail all self connect requests" },
57  { 'a', "Ignore all self connect requests" },
58  { 0 }
59 };
60 
62 {
63  JSList * drivers;
64  JSList * internals;
65  JSList * parameters;
66 
67  class JackServer * engine;
68 
69  /* string, server name */
70  union jackctl_parameter_value name;
71  union jackctl_parameter_value default_name;
72 
73  /* bool, whether to be "realtime" */
74  union jackctl_parameter_value realtime;
75  union jackctl_parameter_value default_realtime;
76 
77  /* int32_t */
78  union jackctl_parameter_value realtime_priority;
79  union jackctl_parameter_value default_realtime_priority;
80 
81  /* bool, whether to exit once all clients have closed their connections */
82  union jackctl_parameter_value temporary;
83  union jackctl_parameter_value default_temporary;
84 
85  /* bool, whether to be verbose */
86  union jackctl_parameter_value verbose;
87  union jackctl_parameter_value default_verbose;
88 
89  /* int32_t, msecs; if zero, use period size. */
90  union jackctl_parameter_value client_timeout;
91  union jackctl_parameter_value default_client_timeout;
92 
93  /* uint32_t, clock source type */
94  union jackctl_parameter_value clock_source;
95  union jackctl_parameter_value default_clock_source;
96 
97  /* uint32_t, max port number */
98  union jackctl_parameter_value port_max;
99  union jackctl_parameter_value default_port_max;
100 
101  /* bool */
102  union jackctl_parameter_value replace_registry;
103  union jackctl_parameter_value default_replace_registry;
104 
105  /* bool, synchronous or asynchronous engine mode */
106  union jackctl_parameter_value sync;
107  union jackctl_parameter_value default_sync;
108 
109  /* char enum, self connect mode mode */
110  union jackctl_parameter_value self_connect_mode;
111  union jackctl_parameter_value default_self_connect_mode;
112 };
113 
115 {
116  jack_driver_desc_t * desc_ptr;
117  JSList * parameters;
118  JSList * infos;
119 };
120 
122 {
123  jack_driver_desc_t * desc_ptr;
124  JSList * parameters;
125  int refnum;
126 };
127 
129 {
130  const char * name;
131  const char * short_description;
132  const char * long_description;
133  jackctl_param_type_t type;
134  bool is_set;
135  union jackctl_parameter_value * value_ptr;
136  union jackctl_parameter_value * default_value_ptr;
137 
138  union jackctl_parameter_value value;
139  union jackctl_parameter_value default_value;
140  struct jackctl_driver * driver_ptr;
141  char id;
142  jack_driver_param_constraint_desc_t * constraint_ptr;
143 };
144 
145 const char * jack_get_self_connect_mode_description(char mode)
146 {
147  struct jack_constraint_enum_char_descriptor * descr_ptr;
148 
149  for (descr_ptr = self_connect_mode_constraint_descr_array;
150  descr_ptr->value;
151  descr_ptr++)
152  if (descr_ptr->value == mode) return descr_ptr->short_desc;
153 
154  return NULL;
155 }
156 
157 static
158 struct jackctl_parameter *
159 jackctl_add_parameter(
160  JSList ** parameters_list_ptr_ptr,
161  const char * name,
162  const char * short_description,
163  const char * long_description,
164  jackctl_param_type_t type,
165  union jackctl_parameter_value * value_ptr,
166  union jackctl_parameter_value * default_value_ptr,
167  union jackctl_parameter_value value,
168  jack_driver_param_constraint_desc_t * constraint_ptr = NULL)
169 {
170  struct jackctl_parameter * parameter_ptr;
171 
172  parameter_ptr = (struct jackctl_parameter *)malloc(sizeof(struct jackctl_parameter));
173  if (parameter_ptr == NULL)
174  {
175  jack_error("Cannot allocate memory for jackctl_parameter structure.");
176  goto fail;
177  }
178 
179  parameter_ptr->name = name;
180  parameter_ptr->short_description = short_description;
181  parameter_ptr->long_description = long_description;
182  parameter_ptr->type = type;
183  parameter_ptr->is_set = false;
184 
185  if (value_ptr == NULL)
186  {
187  value_ptr = &parameter_ptr->value;
188  }
189 
190  if (default_value_ptr == NULL)
191  {
192  default_value_ptr = &parameter_ptr->default_value;
193  }
194 
195  parameter_ptr->value_ptr = value_ptr;
196  parameter_ptr->default_value_ptr = default_value_ptr;
197 
198  *value_ptr = *default_value_ptr = value;
199 
200  parameter_ptr->driver_ptr = NULL;
201  parameter_ptr->id = 0;
202  parameter_ptr->constraint_ptr = constraint_ptr;
203 
204  *parameters_list_ptr_ptr = jack_slist_append(*parameters_list_ptr_ptr, parameter_ptr);
205 
206  return parameter_ptr;
207 
208 fail:
209  return NULL;
210 }
211 
212 static
213 void
214 jackctl_free_driver_parameters(
215  struct jackctl_driver * driver_ptr)
216 {
217  JSList * next_node_ptr;
218 
219  while (driver_ptr->parameters)
220  {
221  next_node_ptr = driver_ptr->parameters->next;
222  jack_constraint_free(((jackctl_parameter *)driver_ptr->parameters->data)->constraint_ptr);
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  jack_constraint_free(((jackctl_parameter *)server_ptr->parameters->data)->constraint_ptr);
531  free(server_ptr->parameters->data);
532  free(server_ptr->parameters);
533  server_ptr->parameters = next_node_ptr;
534  }
535 }
536 
537 #ifdef WIN32
538 
539 struct jackctl_sigmask
540 {
541  HANDLE wait_event;
542 };
543 
544 static jackctl_sigmask sigmask;
545 
546 static void signal_handler(int signum)
547 {
548  printf("Jack main caught signal %d\n", signum);
549  (void) signal(SIGINT, SIG_DFL);
550  SetEvent(sigmask.wait_event);
551 }
552 
555  unsigned int flags)
556 {
557  if ((sigmask.wait_event = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL) {
558  jack_error("CreateEvent fails err = %ld", GetLastError());
559  return 0;
560  }
561 
562  (void) signal(SIGINT, signal_handler);
563  (void) signal(SIGABRT, signal_handler);
564  (void) signal(SIGTERM, signal_handler);
565 
566  return &sigmask;
567 }
568 
570 {
571  if (WaitForSingleObject(signals->wait_event, INFINITE) != WAIT_OBJECT_0) {
572  jack_error("WaitForSingleObject fails err = %ld", GetLastError());
573  }
574 }
575 
576 #else
577 
579 {
580  sigset_t signals;
581 };
582 
583 static jackctl_sigmask sigmask;
584 
585 static
586 void
587 signal_handler(int sig)
588 {
589  /* this is used by the child (active) process, but it never
590  gets called unless we are already shutting down after
591  another signal.
592  */
593  char buf[64];
594  snprintf(buf, sizeof(buf), "Received signal %d during shutdown (ignored)\n", sig);
595 }
596 
597 SERVER_EXPORT jackctl_sigmask_t *
599  unsigned int flags)
600 {
601  sigset_t allsignals;
602  struct sigaction action;
603  int i;
604 
605  /* ensure that we are in our own process group so that
606  kill (SIG, -pgrp) does the right thing.
607  */
608 
609  setsid();
610 
611  pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
612 
613  /* what's this for?
614 
615  POSIX says that signals are delivered like this:
616 
617  * if a thread has blocked that signal, it is not
618  a candidate to receive the signal.
619  * of all threads not blocking the signal, pick
620  one at random, and deliver the signal.
621 
622  this means that a simple-minded multi-threaded program can
623  expect to get POSIX signals delivered randomly to any one
624  of its threads,
625 
626  here, we block all signals that we think we might receive
627  and want to catch. all "child" threads will inherit this
628  setting. if we create a thread that calls sigwait() on the
629  same set of signals, implicitly unblocking all those
630  signals. any of those signals that are delivered to the
631  process will be delivered to that thread, and that thread
632  alone. this makes cleanup for a signal-driven exit much
633  easier, since we know which thread is doing it and more
634  importantly, we are free to call async-unsafe functions,
635  because the code is executing in normal thread context
636  after a return from sigwait().
637  */
638 
639  sigemptyset(&sigmask.signals);
640  sigaddset(&sigmask.signals, SIGHUP);
641  sigaddset(&sigmask.signals, SIGINT);
642  sigaddset(&sigmask.signals, SIGQUIT);
643  sigaddset(&sigmask.signals, SIGPIPE);
644  sigaddset(&sigmask.signals, SIGTERM);
645 #ifndef __ANDROID__
646  /* android's bionic c doesn't provide pthread_cancel() and related functions.
647  * to solve this issue, use pthread_kill() & SIGUSR1 instead.
648  */
649  sigaddset(&sigmask.signals, SIGUSR1);
650 #endif
651  sigaddset(&sigmask.signals, SIGUSR2);
652 
653  /* all child threads will inherit this mask unless they
654  * explicitly reset it
655  */
656 
657  pthread_sigmask(SIG_BLOCK, &sigmask.signals, 0);
658 
659  /* install a do-nothing handler because otherwise pthreads
660  behaviour is undefined when we enter sigwait.
661  */
662 
663  sigfillset(&allsignals);
664  action.sa_handler = signal_handler;
665  action.sa_mask = allsignals;
666  action.sa_flags = SA_RESTART|SA_RESETHAND;
667 
668  for (i = 1; i < NSIG; i++)
669  {
670  if (sigismember (&sigmask.signals, i))
671  {
672  sigaction(i, &action, 0);
673  }
674  }
675 
676  return &sigmask;
677 }
678 
679 SERVER_EXPORT void
681 {
682  int sig;
683  bool waiting = true;
684 
685  while (waiting) {
686  #if defined(sun) && !defined(__sun__) // SUN compiler only, to check
687  sigwait(&sigmask->signals);
688  #else
689  sigwait(&sigmask->signals, &sig);
690  #endif
691  fprintf(stderr, "Jack main caught signal %d\n", sig);
692 
693  switch (sig) {
694  case SIGUSR1:
695  //jack_dump_configuration(engine, 1);
696  break;
697  case SIGUSR2:
698  // driver exit
699  waiting = false;
700  break;
701  case SIGTTOU:
702  break;
703  default:
704  waiting = false;
705  break;
706  }
707  }
708 
709  if (sig != SIGSEGV) {
710  // unblock signals so we can see them during shutdown.
711  // this will help prod developers not to lose sight of
712  // bugs that cause segfaults etc. during shutdown.
713  sigprocmask(SIG_UNBLOCK, &sigmask->signals, 0);
714  }
715 }
716 #endif
717 
718 static
720 get_realtime_priority_constraint()
721 {
722  jack_driver_param_constraint_desc_t * constraint_ptr;
723  int min, max;
724 
725  if (!jack_get_thread_realtime_priority_range(&min, &max))
726  {
727  return NULL;
728  }
729 
730  //jack_info("realtime priority range is (%d,%d)", min, max);
731 
732  constraint_ptr = (jack_driver_param_constraint_desc_t *)calloc(1, sizeof(jack_driver_param_constraint_desc_t));
733  if (constraint_ptr == NULL)
734  {
735  jack_error("Cannot allocate memory for jack_driver_param_constraint_desc_t structure.");
736  return NULL;
737  }
738  constraint_ptr->flags = JACK_CONSTRAINT_FLAG_RANGE;
739 
740  constraint_ptr->constraint.range.min.i = min;
741  constraint_ptr->constraint.range.max.i = max;
742 
743  return constraint_ptr;
744 }
745 
747  bool (* on_device_acquire)(const char * device_name),
748  void (* on_device_release)(const char * device_name))
749 {
750  struct jackctl_server * server_ptr;
751  union jackctl_parameter_value value;
752 
753  server_ptr = (struct jackctl_server *)malloc(sizeof(struct jackctl_server));
754  if (server_ptr == NULL)
755  {
756  jack_error("Cannot allocate memory for jackctl_server structure.");
757  goto fail;
758  }
759 
760  server_ptr->drivers = NULL;
761  server_ptr->internals = NULL;
762  server_ptr->parameters = NULL;
763  server_ptr->engine = NULL;
764 
765  strcpy(value.str, JackTools::DefaultServerName());
766  if (jackctl_add_parameter(
767  &server_ptr->parameters,
768  "name",
769  "Server name to use.",
770  "",
772  &server_ptr->name,
773  &server_ptr->default_name,
774  value) == NULL)
775  {
776  goto fail_free_parameters;
777  }
778 
779  value.b = true;
780  if (jackctl_add_parameter(
781  &server_ptr->parameters,
782  "realtime",
783  "Whether to use realtime mode.",
784  "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.",
786  &server_ptr->realtime,
787  &server_ptr->default_realtime,
788  value) == NULL)
789  {
790  goto fail_free_parameters;
791  }
792 
793  value.i = 10;
794  if (jackctl_add_parameter(
795  &server_ptr->parameters,
796  "realtime-priority",
797  "Scheduler priority when running in realtime mode.",
798  "",
799  JackParamInt,
800  &server_ptr->realtime_priority,
801  &server_ptr->default_realtime_priority,
802  value,
803  get_realtime_priority_constraint()) == NULL)
804  {
805  goto fail_free_parameters;
806  }
807 
808  value.b = false;
809  if (jackctl_add_parameter(
810  &server_ptr->parameters,
811  "temporary",
812  "Exit once all clients have closed their connections.",
813  "",
815  &server_ptr->temporary,
816  &server_ptr->default_temporary,
817  value) == NULL)
818  {
819  goto fail_free_parameters;
820  }
821 
822  value.b = false;
823  if (jackctl_add_parameter(
824  &server_ptr->parameters,
825  "verbose",
826  "Verbose mode.",
827  "",
829  &server_ptr->verbose,
830  &server_ptr->default_verbose,
831  value) == NULL)
832  {
833  goto fail_free_parameters;
834  }
835 
836  value.i = 0;
837  if (jackctl_add_parameter(
838  &server_ptr->parameters,
839  "client-timeout",
840  "Client timeout limit in milliseconds.",
841  "",
842  JackParamInt,
843  &server_ptr->client_timeout,
844  &server_ptr->default_client_timeout,
845  value) == NULL)
846  {
847  goto fail_free_parameters;
848  }
849 
850  value.ui = 0;
851  if (jackctl_add_parameter(
852  &server_ptr->parameters,
853  "clock-source",
854  "Clocksource type : c(ycle) | h(pet) | s(ystem).",
855  "",
857  &server_ptr->clock_source,
858  &server_ptr->default_clock_source,
859  value) == NULL)
860  {
861  goto fail_free_parameters;
862  }
863 
864  value.ui = PORT_NUM;
865  if (jackctl_add_parameter(
866  &server_ptr->parameters,
867  "port-max",
868  "Maximum number of ports.",
869  "",
871  &server_ptr->port_max,
872  &server_ptr->default_port_max,
873  value) == NULL)
874  {
875  goto fail_free_parameters;
876  }
877 
878  value.b = false;
879  if (jackctl_add_parameter(
880  &server_ptr->parameters,
881  "replace-registry",
882  "Replace shared memory registry.",
883  "",
885  &server_ptr->replace_registry,
886  &server_ptr->default_replace_registry,
887  value) == NULL)
888  {
889  goto fail_free_parameters;
890  }
891 
892  value.b = false;
893  if (jackctl_add_parameter(
894  &server_ptr->parameters,
895  "sync",
896  "Use server synchronous mode.",
897  "",
899  &server_ptr->sync,
900  &server_ptr->default_sync,
901  value) == NULL)
902  {
903  goto fail_free_parameters;
904  }
905 
906  value.c = JACK_DEFAULT_SELF_CONNECT_MODE;
907  if (jackctl_add_parameter(
908  &server_ptr->parameters,
909  "self-connect-mode",
910  "Self connect mode.",
911  "Whether JACK clients are allowed to connect their own ports",
913  &server_ptr->self_connect_mode,
914  &server_ptr->default_self_connect_mode,
915  value,
916  jack_constraint_compose_enum_char(
917  JACK_CONSTRAINT_FLAG_STRICT | JACK_CONSTRAINT_FLAG_FAKE_VALUE,
918  self_connect_mode_constraint_descr_array)) == NULL)
919  {
920  goto fail_free_parameters;
921  }
922 
923  JackServerGlobals::on_device_acquire = on_device_acquire;
924  JackServerGlobals::on_device_release = on_device_release;
925 
926  if (!jackctl_drivers_load(server_ptr))
927  {
928  goto fail_free_parameters;
929  }
930 
931  /* Allowed to fail */
932  jackctl_internals_load(server_ptr);
933 
934  return server_ptr;
935 
936 fail_free_parameters:
937  jackctl_server_free_parameters(server_ptr);
938 
939  free(server_ptr);
940 
941 fail:
942  return NULL;
943 }
944 
945 SERVER_EXPORT void jackctl_server_destroy(jackctl_server *server_ptr)
946 {
947  if (server_ptr) {
948  jackctl_server_free_drivers(server_ptr);
949  jackctl_server_free_internals(server_ptr);
950  jackctl_server_free_parameters(server_ptr);
951  free(server_ptr);
952  }
953 }
954 
955 SERVER_EXPORT const JSList * jackctl_server_get_drivers_list(jackctl_server *server_ptr)
956 {
957  return (server_ptr) ? server_ptr->drivers : NULL;
958 }
959 
960 SERVER_EXPORT bool jackctl_server_stop(jackctl_server *server_ptr)
961 {
962  if (server_ptr) {
963  server_ptr->engine->Stop();
964  return true;
965  } else {
966  return false;
967  }
968 }
969 
970 SERVER_EXPORT bool jackctl_server_close(jackctl_server *server_ptr)
971 {
972  if (server_ptr) {
973  server_ptr->engine->Close();
974  delete server_ptr->engine;
975 
976  /* clean up shared memory and files from this server instance */
977  jack_log("Cleaning up shared memory");
978 
979  jack_cleanup_shm();
980 
981  jack_log("Cleaning up files");
982 
983  JackTools::CleanupFiles(server_ptr->name.str);
984 
985  jack_log("Unregistering server `%s'", server_ptr->name.str);
986 
987  jack_unregister_server(server_ptr->name.str);
988 
989  server_ptr->engine = NULL;
990 
991  return true;
992  } else {
993  return false;
994  }
995 }
996 
997 SERVER_EXPORT const JSList * jackctl_server_get_parameters(jackctl_server *server_ptr)
998 {
999  return (server_ptr) ? server_ptr->parameters : NULL;
1000 }
1001 
1002 SERVER_EXPORT bool
1004  jackctl_server *server_ptr,
1005  jackctl_driver *driver_ptr)
1006 {
1007  JSList * paramlist = NULL;
1008 
1009  try {
1010 
1011  if (!server_ptr || !driver_ptr) {
1012  return false;
1013  }
1014 
1015  int rc = jack_register_server(server_ptr->name.str, server_ptr->replace_registry.b);
1016  switch (rc)
1017  {
1018  case EEXIST:
1019  jack_error("`%s' server already active", server_ptr->name.str);
1020  goto fail;
1021  case ENOSPC:
1022  jack_error("Too many servers already active");
1023  goto fail;
1024  case ENOMEM:
1025  jack_error("No access to shm registry");
1026  goto fail;
1027  }
1028 
1029  jack_log("Server `%s' registered", server_ptr->name.str);
1030 
1031  /* clean up shared memory and files from any previous
1032  * instance of this server name */
1033  jack_cleanup_shm();
1034  JackTools::CleanupFiles(server_ptr->name.str);
1035 
1036  if (!server_ptr->realtime.b && server_ptr->client_timeout.i == 0) {
1037  server_ptr->client_timeout.i = 500; /* 0.5 sec; usable when non realtime. */
1038  }
1039 
1040  /* check port max value before allocating server */
1041  if (server_ptr->port_max.ui > PORT_NUM_MAX) {
1042  jack_error("Jack server started with too much ports %d (when port max can be %d)", server_ptr->port_max.ui, PORT_NUM_MAX);
1043  goto fail;
1044  }
1045 
1046  /* get the engine/driver started */
1047  server_ptr->engine = new JackServer(
1048  server_ptr->sync.b,
1049  server_ptr->temporary.b,
1050  server_ptr->client_timeout.i,
1051  server_ptr->realtime.b,
1052  server_ptr->realtime_priority.i,
1053  server_ptr->port_max.ui,
1054  server_ptr->verbose.b,
1055  (jack_timer_type_t)server_ptr->clock_source.ui,
1056  server_ptr->self_connect_mode.c,
1057  server_ptr->name.str);
1058  if (server_ptr->engine == NULL)
1059  {
1060  jack_error("Failed to create new JackServer object");
1061  goto fail_unregister;
1062  }
1063 
1064  if (!jackctl_create_param_list(driver_ptr->parameters, &paramlist)) goto fail_delete;
1065  rc = server_ptr->engine->Open(driver_ptr->desc_ptr, paramlist);
1066  jackctl_destroy_param_list(paramlist);
1067  if (rc < 0)
1068  {
1069  jack_error("JackServer::Open failed with %d", rc);
1070  goto fail_delete;
1071  }
1072 
1073  return true;
1074 
1075  } catch (std::exception&) {
1076  jack_error("jackctl_server_open error...");
1077  jackctl_destroy_param_list(paramlist);
1078  }
1079 
1080 fail_delete:
1081  delete server_ptr->engine;
1082  server_ptr->engine = NULL;
1083 
1084 fail_unregister:
1085  jack_log("Cleaning up shared memory");
1086 
1087  jack_cleanup_shm();
1088 
1089  jack_log("Cleaning up files");
1090 
1091  JackTools::CleanupFiles(server_ptr->name.str);
1092 
1093  jack_log("Unregistering server `%s'", server_ptr->name.str);
1094 
1095  jack_unregister_server(server_ptr->name.str);
1096 
1097 fail:
1098  return false;
1099 }
1100 
1101 SERVER_EXPORT bool
1103  jackctl_server *server_ptr)
1104 {
1105  if (!server_ptr) {
1106  return false;
1107  } else {
1108  int rc = server_ptr->engine->Start();
1109  bool result = rc >= 0;
1110  if (! result)
1111  {
1112  jack_error("JackServer::Start() failed with %d", rc);
1113  }
1114  return result;
1115  }
1116 }
1117 
1118 SERVER_EXPORT const char * jackctl_driver_get_name(jackctl_driver *driver_ptr)
1119 {
1120  return (driver_ptr) ? driver_ptr->desc_ptr->name : NULL;
1121 }
1122 
1123 SERVER_EXPORT jackctl_driver_type_t jackctl_driver_get_type(jackctl_driver *driver_ptr)
1124 {
1125  return (driver_ptr) ? (jackctl_driver_type_t)driver_ptr->desc_ptr->type : (jackctl_driver_type_t)0;
1126 }
1127 
1128 SERVER_EXPORT const JSList * jackctl_driver_get_parameters(jackctl_driver *driver_ptr)
1129 {
1130  return (driver_ptr) ? driver_ptr->parameters : NULL;
1131 }
1132 
1133 SERVER_EXPORT jack_driver_desc_t * jackctl_driver_get_desc(jackctl_driver *driver_ptr)
1134 {
1135  return (driver_ptr) ? driver_ptr->desc_ptr : NULL;
1136 }
1137 
1138 SERVER_EXPORT const char * jackctl_parameter_get_name(jackctl_parameter *parameter_ptr)
1139 {
1140  return (parameter_ptr) ? parameter_ptr->name : NULL;
1141 }
1142 
1143 SERVER_EXPORT const char * jackctl_parameter_get_short_description(jackctl_parameter *parameter_ptr)
1144 {
1145  return (parameter_ptr) ? parameter_ptr->short_description : NULL;
1146 }
1147 
1148 SERVER_EXPORT const char * jackctl_parameter_get_long_description(jackctl_parameter *parameter_ptr)
1149 {
1150  return (parameter_ptr) ? parameter_ptr->long_description : NULL;
1151 }
1152 
1154 {
1155  return (parameter_ptr) ? (parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_RANGE) != 0) : false;
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  if (!parameter_ptr) {
1166  return 0;
1167  }
1168 
1169  if (!jackctl_parameter_has_enum_constraint(parameter_ptr))
1170  {
1171  return 0;
1172  }
1173 
1174  return parameter_ptr->constraint_ptr->constraint.enumeration.count;
1175  }
1176 
1178 {
1179  jack_driver_param_value_t * value_ptr;
1180  union jackctl_parameter_value jackctl_value;
1181 
1182  if (!parameter_ptr) {
1183  memset(&jackctl_value, 0, sizeof(jackctl_value));
1184  return jackctl_value;
1185  }
1186 
1187  value_ptr = &parameter_ptr->constraint_ptr->constraint.enumeration.possible_values_array[index].value;
1188 
1189  switch (parameter_ptr->type)
1190  {
1191  case JackParamInt:
1192  jackctl_value.i = value_ptr->i;
1193  break;
1194  case JackParamUInt:
1195  jackctl_value.ui = value_ptr->ui;
1196  break;
1197  case JackParamChar:
1198  jackctl_value.c = value_ptr->c;
1199  break;
1200  case JackParamString:
1201  strcpy(jackctl_value.str, value_ptr->str);
1202  break;
1203  default:
1204  jack_error("Bad driver parameter type %i (enum constraint)", (int)parameter_ptr->type);
1205  assert(0);
1206  }
1207 
1208  return jackctl_value;
1209 }
1210 
1211 SERVER_EXPORT const char * jackctl_parameter_get_enum_constraint_description(jackctl_parameter *parameter_ptr, uint32_t index)
1212 {
1213  return (parameter_ptr) ? parameter_ptr->constraint_ptr->constraint.enumeration.possible_values_array[index].short_desc : NULL;
1214 }
1215 
1216 SERVER_EXPORT void jackctl_parameter_get_range_constraint(jackctl_parameter *parameter_ptr, union jackctl_parameter_value * min_ptr, union jackctl_parameter_value * max_ptr)
1217 {
1218  if (!parameter_ptr || !min_ptr || !max_ptr) {
1219  return;
1220  }
1221 
1222  switch (parameter_ptr->type)
1223  {
1224  case JackParamInt:
1225  min_ptr->i = parameter_ptr->constraint_ptr->constraint.range.min.i;
1226  max_ptr->i = parameter_ptr->constraint_ptr->constraint.range.max.i;
1227  return;
1228  case JackParamUInt:
1229  min_ptr->ui = parameter_ptr->constraint_ptr->constraint.range.min.ui;
1230  max_ptr->ui = parameter_ptr->constraint_ptr->constraint.range.max.ui;
1231  return;
1232  default:
1233  jack_error("Bad driver parameter type %i (range constraint)", (int)parameter_ptr->type);
1234  assert(0);
1235  }
1236 }
1237 
1239 {
1240  return (parameter_ptr) ? (parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_STRICT) != 0) : false;
1241 }
1242 
1244 {
1245  return (parameter_ptr) ? (parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_FAKE_VALUE) != 0) : false;
1246 }
1247 
1248 SERVER_EXPORT jackctl_param_type_t jackctl_parameter_get_type(jackctl_parameter *parameter_ptr)
1249 {
1250  return (parameter_ptr) ? parameter_ptr->type : (jackctl_param_type_t)0;
1251 }
1252 
1253 SERVER_EXPORT char jackctl_parameter_get_id(jackctl_parameter_t * parameter_ptr)
1254 {
1255  return (parameter_ptr) ? parameter_ptr->id : 0;
1256 }
1257 
1258 SERVER_EXPORT bool jackctl_parameter_is_set(jackctl_parameter *parameter_ptr)
1259 {
1260  return (parameter_ptr) ? parameter_ptr->is_set : false;
1261 }
1262 
1264 {
1265  if (parameter_ptr) {
1266  return *parameter_ptr->value_ptr;
1267  } else {
1268  union jackctl_parameter_value jackctl_value;
1269  memset(&jackctl_value, 0, sizeof(jackctl_value));
1270  return jackctl_value;
1271  }
1272 }
1273 
1274 SERVER_EXPORT bool jackctl_parameter_reset(jackctl_parameter *parameter_ptr)
1275 {
1276  if (!parameter_ptr) {
1277  return NULL;
1278  }
1279 
1280  if (!parameter_ptr->is_set)
1281  {
1282  return true;
1283  }
1284 
1285  parameter_ptr->is_set = false;
1286 
1287  *parameter_ptr->value_ptr = *parameter_ptr->default_value_ptr;
1288 
1289  return true;
1290 }
1291 
1292 SERVER_EXPORT bool jackctl_parameter_set_value(jackctl_parameter *parameter_ptr, const union jackctl_parameter_value * value_ptr)
1293 {
1294  if (!parameter_ptr || !value_ptr) {
1295  return NULL;
1296  }
1297 
1298  parameter_ptr->is_set = true;
1299  *parameter_ptr->value_ptr = *value_ptr;
1300 
1301  return true;
1302 }
1303 
1305 {
1306  if (parameter_ptr) {
1307  return *parameter_ptr->default_value_ptr;
1308  } else {
1309  union jackctl_parameter_value jackctl_value;
1310  memset(&jackctl_value, 0, sizeof(jackctl_value));
1311  return jackctl_value;
1312  }
1313 }
1314 
1315 // Internals clients
1316 
1317 SERVER_EXPORT const JSList * jackctl_server_get_internals_list(jackctl_server *server_ptr)
1318 {
1319  return (server_ptr) ? server_ptr->internals : NULL;
1320 }
1321 
1322 SERVER_EXPORT const char * jackctl_internal_get_name(jackctl_internal *internal_ptr)
1323 {
1324  return (internal_ptr) ? internal_ptr->desc_ptr->name : NULL;
1325 }
1326 
1327 SERVER_EXPORT const JSList * jackctl_internal_get_parameters(jackctl_internal *internal_ptr)
1328 {
1329  return (internal_ptr) ? internal_ptr->parameters : NULL;
1330 }
1331 
1332 SERVER_EXPORT bool jackctl_server_load_internal(
1333  jackctl_server * server_ptr,
1334  jackctl_internal * internal)
1335 {
1336  if (!server_ptr || !internal) {
1337  return false;
1338  }
1339 
1340  int status;
1341  if (server_ptr->engine != NULL) {
1342  JSList * paramlist;
1343  if (!jackctl_create_param_list(internal->parameters, &paramlist)) return false;
1344  server_ptr->engine->InternalClientLoad2(internal->desc_ptr->name, internal->desc_ptr->name, paramlist, JackNullOption, &internal->refnum, -1, &status);
1345  jackctl_destroy_param_list(paramlist);
1346  return (internal->refnum > 0);
1347  } else {
1348  return false;
1349  }
1350 }
1351 
1353  jackctl_server * server_ptr,
1354  jackctl_internal * internal)
1355 {
1356  if (!server_ptr || !internal) {
1357  return false;
1358  }
1359 
1360  int status;
1361  if (server_ptr->engine != NULL && internal->refnum > 0) {
1362  // Client object is internally kept in JackEngine, and will be deallocated in InternalClientUnload
1363  return ((server_ptr->engine->GetEngine()->InternalClientUnload(internal->refnum, &status)) == 0);
1364  } else {
1365  return false;
1366  }
1367 }
1368 
1370  jackctl_server * server_ptr,
1371  const char * file)
1372 {
1373  if (!server_ptr || !file || !server_ptr->engine) {
1374  return false;
1375  }
1376 
1377  return (server_ptr->engine->LoadInternalSessionFile(file) >= 0);
1378 }
1379 
1380 SERVER_EXPORT bool jackctl_server_add_slave(jackctl_server * server_ptr, jackctl_driver * driver_ptr)
1381 {
1382  if (server_ptr && server_ptr->engine) {
1383  if (server_ptr->engine->IsRunning()) {
1384  jack_error("Cannot add a slave in a running server");
1385  return false;
1386  } else {
1387  JSList * paramlist;
1388  if (!jackctl_create_param_list(driver_ptr->parameters, &paramlist)) return false;
1389  JackDriverInfo* info = server_ptr->engine->AddSlave(driver_ptr->desc_ptr, paramlist);
1390  jackctl_destroy_param_list(paramlist);
1391  if (info) {
1392  driver_ptr->infos = jack_slist_append(driver_ptr->infos, info);
1393  return true;
1394  } else {
1395  return false;
1396  }
1397  }
1398  } else {
1399  return false;
1400  }
1401 }
1402 
1403 SERVER_EXPORT bool jackctl_server_remove_slave(jackctl_server * server_ptr, jackctl_driver * driver_ptr)
1404 {
1405  if (server_ptr && server_ptr->engine) {
1406  if (server_ptr->engine->IsRunning()) {
1407  jack_error("Cannot remove a slave from a running server");
1408  return false;
1409  } else {
1410  if (driver_ptr->infos) {
1411  JackDriverInfo* info = (JackDriverInfo*)driver_ptr->infos->data;
1412  assert(info);
1413  driver_ptr->infos = jack_slist_remove(driver_ptr->infos, info);
1414  server_ptr->engine->RemoveSlave(info);
1415  delete info;
1416  return true;
1417  } else {
1418  return false;
1419  }
1420  }
1421  } else {
1422  return false;
1423  }
1424 }
1425 
1426 SERVER_EXPORT bool jackctl_server_switch_master(jackctl_server * server_ptr, jackctl_driver * driver_ptr)
1427 {
1428  if (server_ptr && server_ptr->engine) {
1429  JSList * paramlist;
1430  if (!jackctl_create_param_list(driver_ptr->parameters, &paramlist)) return false;
1431  bool ret = (server_ptr->engine->SwitchMaster(driver_ptr->desc_ptr, paramlist) == 0);
1432  jackctl_destroy_param_list(paramlist);
1433  return ret;
1434  } else {
1435  return false;
1436  }
1437 }
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