1 // u/* -*- Mode: C++ ; c-basic-offset: 4 -*- */
3 JACK control API implementation
5 Copyright (C) 2008 Nedko Arnaudov
6 Copyright (C) 2008 Grame
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.
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.
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.
37 #include "driver_interface.h"
38 #include "JackError.h"
39 #include "JackServer.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"
56 class JackServer
* engine
;
58 /* string, server name */
59 union jackctl_parameter_value name
;
60 union jackctl_parameter_value default_name
;
62 /* bool, whether to be "realtime" */
63 union jackctl_parameter_value realtime
;
64 union jackctl_parameter_value default_realtime
;
67 union jackctl_parameter_value realtime_priority
;
68 union jackctl_parameter_value default_realtime_priority
;
70 /* bool, whether to exit once all clients have closed their connections */
71 union jackctl_parameter_value temporary
;
72 union jackctl_parameter_value default_temporary
;
74 /* bool, whether to be verbose */
75 union jackctl_parameter_value verbose
;
76 union jackctl_parameter_value default_verbose
;
78 /* int32_t, msecs; if zero, use period size. */
79 union jackctl_parameter_value client_timeout
;
80 union jackctl_parameter_value default_client_timeout
;
82 /* uint32_t, clock source type */
83 union jackctl_parameter_value clock_source
;
84 union jackctl_parameter_value default_clock_source
;
87 union jackctl_parameter_value replace_registry
;
88 union jackctl_parameter_value default_replace_registry
;
90 /* bool, synchronous or asynchronous engine mode */
91 union jackctl_parameter_value sync
;
92 union jackctl_parameter_value default_sync
;
97 jack_driver_desc_t
* desc_ptr
;
99 JSList
* set_parameters
;
100 JackDriverInfo
* info
;
103 struct jackctl_internal
105 jack_driver_desc_t
* desc_ptr
;
107 JSList
* set_parameters
;
111 struct jackctl_parameter
114 const char * short_description
;
115 const char * long_description
;
116 jackctl_param_type_t type
;
118 union jackctl_parameter_value
* value_ptr
;
119 union jackctl_parameter_value
* default_value_ptr
;
121 union jackctl_parameter_value value
;
122 union jackctl_parameter_value default_value
;
123 struct jackctl_driver
* driver_ptr
;
125 jack_driver_param_t
* driver_parameter_ptr
;
126 jack_driver_param_constraint_desc_t
* constraint_ptr
;
130 struct jackctl_parameter
*
131 jackctl_add_parameter(
132 JSList
** parameters_list_ptr_ptr
,
134 const char * short_description
,
135 const char * long_description
,
136 jackctl_param_type_t type
,
137 union jackctl_parameter_value
* value_ptr
,
138 union jackctl_parameter_value
* default_value_ptr
,
139 union jackctl_parameter_value value
,
140 jack_driver_param_constraint_desc_t
* constraint_ptr
= NULL
)
142 struct jackctl_parameter
* parameter_ptr
;
144 parameter_ptr
= (struct jackctl_parameter
*)malloc(sizeof(struct jackctl_parameter
));
145 if (parameter_ptr
== NULL
)
147 jack_error("Cannot allocate memory for jackctl_parameter structure.");
151 parameter_ptr
->name
= name
;
152 parameter_ptr
->short_description
= short_description
;
153 parameter_ptr
->long_description
= long_description
;
154 parameter_ptr
->type
= type
;
155 parameter_ptr
->is_set
= false;
157 if (value_ptr
== NULL
)
159 value_ptr
= ¶meter_ptr
->value
;
162 if (default_value_ptr
== NULL
)
164 default_value_ptr
= ¶meter_ptr
->default_value
;
167 parameter_ptr
->value_ptr
= value_ptr
;
168 parameter_ptr
->default_value_ptr
= default_value_ptr
;
170 *value_ptr
= *default_value_ptr
= value
;
172 parameter_ptr
->driver_ptr
= NULL
;
173 parameter_ptr
->driver_parameter_ptr
= NULL
;
174 parameter_ptr
->id
= 0;
175 parameter_ptr
->constraint_ptr
= constraint_ptr
;
177 *parameters_list_ptr_ptr
= jack_slist_append(*parameters_list_ptr_ptr
, parameter_ptr
);
179 return parameter_ptr
;
187 jackctl_free_driver_parameters(
188 struct jackctl_driver
* driver_ptr
)
190 JSList
* next_node_ptr
;
192 while (driver_ptr
->parameters
)
194 next_node_ptr
= driver_ptr
->parameters
->next
;
195 free(driver_ptr
->parameters
->data
);
196 free(driver_ptr
->parameters
);
197 driver_ptr
->parameters
= next_node_ptr
;
200 while (driver_ptr
->set_parameters
)
202 next_node_ptr
= driver_ptr
->set_parameters
->next
;
203 free(driver_ptr
->set_parameters
->data
);
204 free(driver_ptr
->set_parameters
);
205 driver_ptr
->set_parameters
= next_node_ptr
;
211 jackctl_add_driver_parameters(
212 struct jackctl_driver
* driver_ptr
)
215 union jackctl_parameter_value jackctl_value
;
216 jackctl_param_type_t jackctl_type
;
217 struct jackctl_parameter
* parameter_ptr
;
218 jack_driver_param_desc_t
* descriptor_ptr
;
220 for (i
= 0 ; i
< driver_ptr
->desc_ptr
->nparams
; i
++)
222 descriptor_ptr
= driver_ptr
->desc_ptr
->params
+ i
;
224 switch (descriptor_ptr
->type
)
226 case JackDriverParamInt
:
227 jackctl_type
= JackParamInt
;
228 jackctl_value
.i
= descriptor_ptr
->value
.i
;
230 case JackDriverParamUInt
:
231 jackctl_type
= JackParamUInt
;
232 jackctl_value
.ui
= descriptor_ptr
->value
.ui
;
234 case JackDriverParamChar
:
235 jackctl_type
= JackParamChar
;
236 jackctl_value
.c
= descriptor_ptr
->value
.c
;
238 case JackDriverParamString
:
239 jackctl_type
= JackParamString
;
240 strcpy(jackctl_value
.str
, descriptor_ptr
->value
.str
);
242 case JackDriverParamBool
:
243 jackctl_type
= JackParamBool
;
244 jackctl_value
.b
= descriptor_ptr
->value
.i
;
247 jack_error("unknown driver parameter type %i", (int)descriptor_ptr
->type
);
252 parameter_ptr
= jackctl_add_parameter(
253 &driver_ptr
->parameters
,
254 descriptor_ptr
->name
,
255 descriptor_ptr
->short_desc
,
256 descriptor_ptr
->long_desc
,
261 descriptor_ptr
->constraint
);
263 if (parameter_ptr
== NULL
)
268 parameter_ptr
->driver_ptr
= driver_ptr
;
269 parameter_ptr
->id
= descriptor_ptr
->character
;
275 jackctl_free_driver_parameters(driver_ptr
);
281 jackctl_drivers_load(
282 struct jackctl_server
* server_ptr
)
284 struct jackctl_driver
* driver_ptr
;
286 JSList
*descriptor_node_ptr
;
288 descriptor_node_ptr
= jack_drivers_load(NULL
);
289 if (descriptor_node_ptr
== NULL
)
291 jack_error("could not find any drivers in driver directory!");
295 while (descriptor_node_ptr
!= NULL
)
297 driver_ptr
= (struct jackctl_driver
*)malloc(sizeof(struct jackctl_driver
));
298 if (driver_ptr
== NULL
)
300 jack_error("memory allocation of jackctl_driver structure failed.");
304 driver_ptr
->desc_ptr
= (jack_driver_desc_t
*)descriptor_node_ptr
->data
;
305 driver_ptr
->parameters
= NULL
;
306 driver_ptr
->set_parameters
= NULL
;
308 if (!jackctl_add_driver_parameters(driver_ptr
))
310 assert(driver_ptr
->parameters
== NULL
);
315 server_ptr
->drivers
= jack_slist_append(server_ptr
->drivers
, driver_ptr
);
318 node_ptr
= descriptor_node_ptr
;
319 descriptor_node_ptr
= descriptor_node_ptr
->next
;
328 jackctl_server_free_drivers(
329 struct jackctl_server
* server_ptr
)
331 JSList
* next_node_ptr
;
332 struct jackctl_driver
* driver_ptr
;
334 while (server_ptr
->drivers
)
336 next_node_ptr
= server_ptr
->drivers
->next
;
337 driver_ptr
= (struct jackctl_driver
*)server_ptr
->drivers
->data
;
339 jackctl_free_driver_parameters(driver_ptr
);
340 free(driver_ptr
->desc_ptr
->params
);
341 free(driver_ptr
->desc_ptr
);
344 free(server_ptr
->drivers
);
345 server_ptr
->drivers
= next_node_ptr
;
350 jackctl_internals_load(
351 struct jackctl_server
* server_ptr
)
353 struct jackctl_internal
* internal_ptr
;
355 JSList
*descriptor_node_ptr
;
357 descriptor_node_ptr
= jack_internals_load(NULL
);
358 if (descriptor_node_ptr
== NULL
)
360 jack_error("could not find any internals in driver directory!");
364 while (descriptor_node_ptr
!= NULL
)
366 internal_ptr
= (struct jackctl_internal
*)malloc(sizeof(struct jackctl_internal
));
367 if (internal_ptr
== NULL
)
369 jack_error("memory allocation of jackctl_driver structure failed.");
373 internal_ptr
->desc_ptr
= (jack_driver_desc_t
*)descriptor_node_ptr
->data
;
374 internal_ptr
->parameters
= NULL
;
375 internal_ptr
->set_parameters
= NULL
;
377 if (!jackctl_add_driver_parameters((struct jackctl_driver
*)internal_ptr
))
379 assert(internal_ptr
->parameters
== NULL
);
384 server_ptr
->internals
= jack_slist_append(server_ptr
->internals
, internal_ptr
);
387 node_ptr
= descriptor_node_ptr
;
388 descriptor_node_ptr
= descriptor_node_ptr
->next
;
397 jackctl_server_free_internals(
398 struct jackctl_server
* server_ptr
)
400 JSList
* next_node_ptr
;
401 struct jackctl_internal
* internal_ptr
;
403 while (server_ptr
->internals
)
405 next_node_ptr
= server_ptr
->internals
->next
;
406 internal_ptr
= (struct jackctl_internal
*)server_ptr
->internals
->data
;
408 jackctl_free_driver_parameters((struct jackctl_driver
*)internal_ptr
);
409 free(internal_ptr
->desc_ptr
->params
);
410 free(internal_ptr
->desc_ptr
);
413 free(server_ptr
->internals
);
414 server_ptr
->internals
= next_node_ptr
;
420 jackctl_server_free_parameters(
421 struct jackctl_server
* server_ptr
)
423 JSList
* next_node_ptr
;
425 while (server_ptr
->parameters
)
427 next_node_ptr
= server_ptr
->parameters
->next
;
428 free(server_ptr
->parameters
->data
);
429 free(server_ptr
->parameters
);
430 server_ptr
->parameters
= next_node_ptr
;
436 static HANDLE waitEvent
;
438 static void do_nothing_handler(int signum
)
440 printf("jack main caught signal %d\n", signum
);
441 (void) signal(SIGINT
, SIG_DFL
);
446 jackctl_setup_signals(
449 if ((waitEvent
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
)) == NULL
) {
450 jack_error("CreateEvent fails err = %ld", GetLastError());
454 (void) signal(SIGINT
, do_nothing_handler
);
455 (void) signal(SIGABRT
, do_nothing_handler
);
456 (void) signal(SIGTERM
, do_nothing_handler
);
458 return (sigset_t
)waitEvent
;
461 void jackctl_wait_signals(sigset_t signals
)
463 if (WaitForSingleObject(waitEvent
, INFINITE
) != WAIT_OBJECT_0
) {
464 jack_error("WaitForSingleObject fails err = %ld", GetLastError());
472 do_nothing_handler(int sig
)
474 /* this is used by the child (active) process, but it never
475 gets called unless we are already shutting down after
479 snprintf (buf
, sizeof(buf
), "received signal %d during shutdown (ignored)\n", sig
);
483 jackctl_setup_signals(
488 struct sigaction action
;
491 /* ensure that we are in our own process group so that
492 kill (SIG, -pgrp) does the right thing.
497 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, NULL
);
501 POSIX says that signals are delivered like this:
503 * if a thread has blocked that signal, it is not
504 a candidate to receive the signal.
505 * of all threads not blocking the signal, pick
506 one at random, and deliver the signal.
508 this means that a simple-minded multi-threaded program can
509 expect to get POSIX signals delivered randomly to any one
512 here, we block all signals that we think we might receive
513 and want to catch. all "child" threads will inherit this
514 setting. if we create a thread that calls sigwait() on the
515 same set of signals, implicitly unblocking all those
516 signals. any of those signals that are delivered to the
517 process will be delivered to that thread, and that thread
518 alone. this makes cleanup for a signal-driven exit much
519 easier, since we know which thread is doing it and more
520 importantly, we are free to call async-unsafe functions,
521 because the code is executing in normal thread context
522 after a return from sigwait().
525 sigemptyset(&signals
);
526 sigaddset(&signals
, SIGHUP
);
527 sigaddset(&signals
, SIGINT
);
528 sigaddset(&signals
, SIGQUIT
);
529 sigaddset(&signals
, SIGPIPE
);
530 sigaddset(&signals
, SIGTERM
);
531 sigaddset(&signals
, SIGUSR1
);
532 sigaddset(&signals
, SIGUSR2
);
534 /* all child threads will inherit this mask unless they
535 * explicitly reset it
538 pthread_sigmask(SIG_BLOCK
, &signals
, 0);
540 /* install a do-nothing handler because otherwise pthreads
541 behaviour is undefined when we enter sigwait.
544 sigfillset(&allsignals
);
545 action
.sa_handler
= do_nothing_handler
;
546 action
.sa_mask
= allsignals
;
547 action
.sa_flags
= SA_RESTART
|SA_RESETHAND
;
549 for (i
= 1; i
< NSIG
; i
++)
551 if (sigismember (&signals
, i
))
553 sigaction(i
, &action
, 0);
561 jackctl_wait_signals(sigset_t signals
)
567 #if defined(sun) && !defined(__sun__) // SUN compiler only, to check
570 sigwait(&signals
, &sig
);
572 fprintf(stderr
, "jack main caught signal %d\n", sig
);
576 //jack_dump_configuration(engine, 1);
590 if (sig
!= SIGSEGV
) {
591 // unblock signals so we can see them during shutdown.
592 // this will help prod developers not to lose sight of
593 // bugs that cause segfaults etc. during shutdown.
594 sigprocmask(SIG_UNBLOCK
, &signals
, 0);
600 jack_driver_param_constraint_desc_t
*
601 get_realtime_priority_constraint()
603 jack_driver_param_constraint_desc_t
* constraint_ptr
;
606 if (!jack_get_thread_realtime_priority_range(&min
, &max
))
611 //jack_info("realtime priority range is (%d,%d)", min, max);
613 constraint_ptr
= (jack_driver_param_constraint_desc_t
*)calloc(1, sizeof(jack_driver_param_value_enum_t
));
614 constraint_ptr
->flags
= JACK_CONSTRAINT_FLAG_RANGE
;
616 constraint_ptr
->constraint
.range
.min
.i
= min
;
617 constraint_ptr
->constraint
.range
.max
.i
= max
;
619 return constraint_ptr
;
622 EXPORT jackctl_server_t
* jackctl_server_create(
623 bool (* on_device_acquire
)(const char * device_name
),
624 void (* on_device_release
)(const char * device_name
))
626 struct jackctl_server
* server_ptr
;
627 union jackctl_parameter_value value
;
629 server_ptr
= (struct jackctl_server
*)malloc(sizeof(struct jackctl_server
));
630 if (server_ptr
== NULL
)
632 jack_error("Cannot allocate memory for jackctl_server structure.");
636 server_ptr
->drivers
= NULL
;
637 server_ptr
->internals
= NULL
;
638 server_ptr
->parameters
= NULL
;
639 server_ptr
->engine
= NULL
;
641 strcpy(value
.str
, JACK_DEFAULT_SERVER_NAME
);
642 if (jackctl_add_parameter(
643 &server_ptr
->parameters
,
645 "Server name to use.",
649 &server_ptr
->default_name
,
652 goto fail_free_parameters
;
656 if (jackctl_add_parameter(
657 &server_ptr
->parameters
,
659 "Whether to use realtime mode.",
660 "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.",
662 &server_ptr
->realtime
,
663 &server_ptr
->default_realtime
,
666 goto fail_free_parameters
;
670 if (jackctl_add_parameter(
671 &server_ptr
->parameters
,
673 "Scheduler priority when running in realtime mode.",
676 &server_ptr
->realtime_priority
,
677 &server_ptr
->default_realtime_priority
,
679 get_realtime_priority_constraint()) == NULL
)
681 goto fail_free_parameters
;
685 if (jackctl_add_parameter(
686 &server_ptr
->parameters
,
688 "Exit once all clients have closed their connections.",
691 &server_ptr
->temporary
,
692 &server_ptr
->default_temporary
,
695 goto fail_free_parameters
;
699 if (jackctl_add_parameter(
700 &server_ptr
->parameters
,
705 &server_ptr
->verbose
,
706 &server_ptr
->default_verbose
,
709 goto fail_free_parameters
;
713 if (jackctl_add_parameter(
714 &server_ptr
->parameters
,
716 "Client timeout limit in milliseconds.",
719 &server_ptr
->client_timeout
,
720 &server_ptr
->default_client_timeout
,
723 goto fail_free_parameters
;
727 if (jackctl_add_parameter(
728 &server_ptr
->parameters
,
730 "Clocksource type : c(ycle) | h(pet) | s(ystem).",
733 &server_ptr
->clock_source
,
734 &server_ptr
->default_clock_source
,
737 goto fail_free_parameters
;
741 if (jackctl_add_parameter(
742 &server_ptr
->parameters
,
744 "Replace shared memory registry.",
747 &server_ptr
->replace_registry
,
748 &server_ptr
->default_replace_registry
,
751 goto fail_free_parameters
;
755 if (jackctl_add_parameter(
756 &server_ptr
->parameters
,
758 "Use server synchronous mode.",
762 &server_ptr
->default_sync
,
765 goto fail_free_parameters
;
768 JackServerGlobals::on_device_acquire
= on_device_acquire
;
769 JackServerGlobals::on_device_release
= on_device_release
;
771 if (!jackctl_drivers_load(server_ptr
))
773 goto fail_free_parameters
;
776 /* Allowed to fail */
777 jackctl_internals_load(server_ptr
);
781 fail_free_parameters
:
782 jackctl_server_free_parameters(server_ptr
);
790 EXPORT
void jackctl_server_destroy(jackctl_server
*server_ptr
)
792 jackctl_server_free_drivers(server_ptr
);
793 jackctl_server_free_internals(server_ptr
);
794 jackctl_server_free_parameters(server_ptr
);
798 EXPORT
const JSList
* jackctl_server_get_drivers_list(jackctl_server
*server_ptr
)
800 return server_ptr
->drivers
;
803 EXPORT
bool jackctl_server_stop(jackctl_server
*server_ptr
)
805 server_ptr
->engine
->Stop();
806 server_ptr
->engine
->Close();
807 delete server_ptr
->engine
;
809 /* clean up shared memory and files from this server instance */
810 jack_log("cleaning up shared memory");
814 jack_log("cleaning up files");
816 JackTools::CleanupFiles(server_ptr
->name
.str
);
818 jack_log("unregistering server `%s'", server_ptr
->name
.str
);
820 jack_unregister_server(server_ptr
->name
.str
);
822 server_ptr
->engine
= NULL
;
827 EXPORT
const JSList
* jackctl_server_get_parameters(jackctl_server
*server_ptr
)
829 return server_ptr
->parameters
;
833 jackctl_server_start(
834 jackctl_server
*server_ptr
,
835 jackctl_driver
*driver_ptr
)
839 rc
= jack_register_server(server_ptr
->name
.str
, server_ptr
->replace_registry
.b
);
843 jack_error("`%s' server already active", server_ptr
->name
.str
);
846 jack_error("too many servers already active");
849 jack_error("no access to shm registry");
853 jack_log("server `%s' registered", server_ptr
->name
.str
);
855 /* clean up shared memory and files from any previous
856 * instance of this server name */
858 JackTools::CleanupFiles(server_ptr
->name
.str
);
860 if (!server_ptr
->realtime
.b
&& server_ptr
->client_timeout
.i
== 0)
861 server_ptr
->client_timeout
.i
= 500; /* 0.5 sec; usable when non realtime. */
863 /* get the engine/driver started */
865 server_ptr
->engine
= new JackServer(
867 server_ptr
->temporary
.b
,
868 server_ptr
->client_timeout
.i
,
869 server_ptr
->realtime
.b
,
870 server_ptr
->realtime_priority
.i
,
871 server_ptr
->verbose
.b
,
872 (jack_timer_type_t
)server_ptr
->clock_source
.ui
,
873 server_ptr
->name
.str
);
874 if (server_ptr
->engine
== NULL
)
876 jack_error("Failed to create new JackServer object");
877 goto fail_unregister
;
880 rc
= server_ptr
->engine
->Open(driver_ptr
->desc_ptr
, driver_ptr
->set_parameters
);
883 jack_error("JackServer::Open() failed with %d", rc
);
887 rc
= server_ptr
->engine
->Start();
890 jack_error("JackServer::Start() failed with %d", rc
);
897 server_ptr
->engine
->Close();
900 delete server_ptr
->engine
;
901 server_ptr
->engine
= NULL
;
904 jack_log("cleaning up shared memory");
908 jack_log("cleaning up files");
910 JackTools::CleanupFiles(server_ptr
->name
.str
);
912 jack_log("unregistering server `%s'", server_ptr
->name
.str
);
914 jack_unregister_server(server_ptr
->name
.str
);
920 EXPORT
const char * jackctl_driver_get_name(jackctl_driver
*driver_ptr
)
922 return driver_ptr
->desc_ptr
->name
;
925 EXPORT
const JSList
* jackctl_driver_get_parameters(jackctl_driver
*driver_ptr
)
927 return driver_ptr
->parameters
;
930 EXPORT jack_driver_desc_t
* jackctl_driver_get_desc(jackctl_driver
*driver_ptr
)
932 return driver_ptr
->desc_ptr
;
935 EXPORT
const char * jackctl_parameter_get_name(jackctl_parameter
*parameter_ptr
)
937 return parameter_ptr
->name
;
940 EXPORT
const char * jackctl_parameter_get_short_description(jackctl_parameter
*parameter_ptr
)
942 return parameter_ptr
->short_description
;
945 EXPORT
const char * jackctl_parameter_get_long_description(jackctl_parameter
*parameter_ptr
)
947 return parameter_ptr
->long_description
;
950 EXPORT
bool jackctl_parameter_has_range_constraint(jackctl_parameter
*parameter_ptr
)
952 return parameter_ptr
->constraint_ptr
!= NULL
&& (parameter_ptr
->constraint_ptr
->flags
& JACK_CONSTRAINT_FLAG_RANGE
) != 0;
955 EXPORT
bool jackctl_parameter_has_enum_constraint(jackctl_parameter
*parameter_ptr
)
957 return parameter_ptr
->constraint_ptr
!= NULL
&& (parameter_ptr
->constraint_ptr
->flags
& JACK_CONSTRAINT_FLAG_RANGE
) == 0;
960 EXPORT
uint32_t jackctl_parameter_get_enum_constraints_count(jackctl_parameter
*parameter_ptr
)
962 if (!jackctl_parameter_has_enum_constraint(parameter_ptr
))
967 return parameter_ptr
->constraint_ptr
->constraint
.enumeration
.count
;
970 EXPORT
union jackctl_parameter_value
jackctl_parameter_get_enum_constraint_value(jackctl_parameter
*parameter_ptr
, uint32_t index
)
972 jack_driver_param_value_t
* value_ptr
;
973 union jackctl_parameter_value jackctl_value
;
975 value_ptr
= ¶meter_ptr
->constraint_ptr
->constraint
.enumeration
.possible_values_array
[index
].value
;
977 switch (parameter_ptr
->type
)
980 jackctl_value
.i
= value_ptr
->i
;
983 jackctl_value
.ui
= value_ptr
->ui
;
986 jackctl_value
.c
= value_ptr
->c
;
988 case JackParamString
:
989 strcpy(jackctl_value
.str
, value_ptr
->str
);
992 jack_error("bad driver parameter type %i (enum constraint)", (int)parameter_ptr
->type
);
996 return jackctl_value
;
999 EXPORT
const char * jackctl_parameter_get_enum_constraint_description(jackctl_parameter
*parameter_ptr
, uint32_t index
)
1001 return parameter_ptr
->constraint_ptr
->constraint
.enumeration
.possible_values_array
[index
].short_desc
;
1004 EXPORT
void jackctl_parameter_get_range_constraint(jackctl_parameter
*parameter_ptr
, union jackctl_parameter_value
* min_ptr
, union jackctl_parameter_value
* max_ptr
)
1006 switch (parameter_ptr
->type
)
1009 min_ptr
->i
= parameter_ptr
->constraint_ptr
->constraint
.range
.min
.i
;
1010 max_ptr
->i
= parameter_ptr
->constraint_ptr
->constraint
.range
.max
.i
;
1013 min_ptr
->ui
= parameter_ptr
->constraint_ptr
->constraint
.range
.min
.ui
;
1014 max_ptr
->ui
= parameter_ptr
->constraint_ptr
->constraint
.range
.max
.ui
;
1017 jack_error("bad driver parameter type %i (range constraint)", (int)parameter_ptr
->type
);
1022 EXPORT
bool jackctl_parameter_constraint_is_strict(jackctl_parameter_t
* parameter_ptr
)
1024 return parameter_ptr
->constraint_ptr
!= NULL
&& (parameter_ptr
->constraint_ptr
->flags
& JACK_CONSTRAINT_FLAG_STRICT
) != 0;
1027 EXPORT
bool jackctl_parameter_constraint_is_fake_value(jackctl_parameter_t
* parameter_ptr
)
1029 return parameter_ptr
->constraint_ptr
!= NULL
&& (parameter_ptr
->constraint_ptr
->flags
& JACK_CONSTRAINT_FLAG_FAKE_VALUE
) != 0;
1032 EXPORT jackctl_param_type_t
jackctl_parameter_get_type(jackctl_parameter
*parameter_ptr
)
1034 return parameter_ptr
->type
;
1037 EXPORT
char jackctl_parameter_get_id(jackctl_parameter_t
* parameter_ptr
)
1039 return parameter_ptr
->id
;
1042 EXPORT
bool jackctl_parameter_is_set(jackctl_parameter
*parameter_ptr
)
1044 return parameter_ptr
->is_set
;
1047 EXPORT
union jackctl_parameter_value
jackctl_parameter_get_value(jackctl_parameter
*parameter_ptr
)
1049 return *parameter_ptr
->value_ptr
;
1052 EXPORT
bool jackctl_parameter_reset(jackctl_parameter
*parameter_ptr
)
1054 if (!parameter_ptr
->is_set
)
1059 parameter_ptr
->is_set
= false;
1061 *parameter_ptr
->value_ptr
= *parameter_ptr
->default_value_ptr
;
1066 EXPORT
bool jackctl_parameter_set_value(jackctl_parameter
*parameter_ptr
, const union jackctl_parameter_value
* value_ptr
)
1068 bool new_driver_parameter
;
1070 /* for driver parameters, set the parameter by adding jack_driver_param_t in the set_parameters list */
1071 if (parameter_ptr
->driver_ptr
!= NULL
)
1073 /* jack_info("setting driver parameter %p ...", parameter_ptr); */
1074 new_driver_parameter
= parameter_ptr
->driver_parameter_ptr
== NULL
;
1075 if (new_driver_parameter
)
1077 /* jack_info("new driver parameter..."); */
1078 parameter_ptr
->driver_parameter_ptr
= (jack_driver_param_t
*)malloc(sizeof(jack_driver_param_t
));
1079 if (parameter_ptr
->driver_parameter_ptr
== NULL
)
1081 jack_error ("Allocation of jack_driver_param_t structure failed");
1085 parameter_ptr
->driver_parameter_ptr
->character
= parameter_ptr
->id
;
1086 parameter_ptr
->driver_ptr
->set_parameters
= jack_slist_append(parameter_ptr
->driver_ptr
->set_parameters
, parameter_ptr
->driver_parameter_ptr
);
1089 switch (parameter_ptr
->type
)
1092 parameter_ptr
->driver_parameter_ptr
->value
.i
= value_ptr
->i
;
1095 parameter_ptr
->driver_parameter_ptr
->value
.ui
= value_ptr
->ui
;
1098 parameter_ptr
->driver_parameter_ptr
->value
.c
= value_ptr
->c
;
1100 case JackParamString
:
1101 strcpy(parameter_ptr
->driver_parameter_ptr
->value
.str
, value_ptr
->str
);
1104 parameter_ptr
->driver_parameter_ptr
->value
.i
= value_ptr
->b
;
1107 jack_error("unknown parameter type %i", (int)parameter_ptr
->type
);
1110 if (new_driver_parameter
)
1112 parameter_ptr
->driver_ptr
->set_parameters
= jack_slist_remove(parameter_ptr
->driver_ptr
->set_parameters
, parameter_ptr
->driver_parameter_ptr
);
1119 parameter_ptr
->is_set
= true;
1120 *parameter_ptr
->value_ptr
= *value_ptr
;
1125 EXPORT
union jackctl_parameter_value
jackctl_parameter_get_default_value(jackctl_parameter
*parameter_ptr
)
1127 return *parameter_ptr
->default_value_ptr
;
1130 // Internals clients
1132 EXPORT
const JSList
* jackctl_server_get_internals_list(jackctl_server
*server_ptr
)
1134 return server_ptr
->internals
;
1137 EXPORT
const char * jackctl_internal_get_name(jackctl_internal
*internal_ptr
)
1139 return internal_ptr
->desc_ptr
->name
;
1142 EXPORT
const JSList
* jackctl_internal_get_parameters(jackctl_internal
*internal_ptr
)
1144 return internal_ptr
->parameters
;
1147 EXPORT
bool jackctl_server_load_internal(
1148 jackctl_server
* server_ptr
,
1149 jackctl_internal
* internal
)
1152 if (server_ptr
->engine
!= NULL
) {
1153 server_ptr
->engine
->InternalClientLoad(internal
->desc_ptr
->name
, internal
->desc_ptr
->name
, internal
->set_parameters
, JackNullOption
, &internal
->refnum
, &status
);
1154 return (internal
->refnum
> 0);
1160 EXPORT
bool jackctl_server_unload_internal(
1161 jackctl_server
* server_ptr
,
1162 jackctl_internal
* internal
)
1165 if (server_ptr
->engine
!= NULL
&& internal
->refnum
> 0) {
1166 return ((server_ptr
->engine
->GetEngine()->InternalClientUnload(internal
->refnum
, &status
)) == 0);
1172 EXPORT
bool jackctl_server_add_slave(jackctl_server
* server_ptr
, jackctl_driver
* driver_ptr
)
1174 if (server_ptr
->engine
!= NULL
) {
1175 driver_ptr
->info
= server_ptr
->engine
->AddSlave(driver_ptr
->desc_ptr
, driver_ptr
->set_parameters
);
1176 return (driver_ptr
->info
!= 0);
1182 EXPORT
bool jackctl_server_remove_slave(jackctl_server
* server_ptr
, jackctl_driver
* driver_ptr
)
1184 if (server_ptr
->engine
!= NULL
) {
1185 server_ptr
->engine
->RemoveSlave(driver_ptr
->info
);
1186 delete driver_ptr
->info
;
1193 EXPORT
bool jackctl_server_switch_master(jackctl_server
* server_ptr
, jackctl_driver
* driver_ptr
)
1195 if (server_ptr
->engine
!= NULL
) {
1196 return (server_ptr
->engine
->SwitchMaster(driver_ptr
->desc_ptr
, driver_ptr
->set_parameters
) == 0);