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"
50 /* JackEngine::CheckPortsConnect() has some assumptions about char values */
51 static struct jack_constraint_enum_char_descriptor self_connect_mode_constraint_descr_array
[] =
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" },
67 class JackServer
* engine
;
69 /* string, server name */
70 union jackctl_parameter_value name
;
71 union jackctl_parameter_value default_name
;
73 /* bool, whether to be "realtime" */
74 union jackctl_parameter_value realtime
;
75 union jackctl_parameter_value default_realtime
;
78 union jackctl_parameter_value realtime_priority
;
79 union jackctl_parameter_value default_realtime_priority
;
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
;
85 /* bool, whether to be verbose */
86 union jackctl_parameter_value verbose
;
87 union jackctl_parameter_value default_verbose
;
89 /* int32_t, msecs; if zero, use period size. */
90 union jackctl_parameter_value client_timeout
;
91 union jackctl_parameter_value default_client_timeout
;
93 /* uint32_t, clock source type */
94 union jackctl_parameter_value clock_source
;
95 union jackctl_parameter_value default_clock_source
;
97 /* uint32_t, max port number */
98 union jackctl_parameter_value port_max
;
99 union jackctl_parameter_value default_port_max
;
102 union jackctl_parameter_value replace_registry
;
103 union jackctl_parameter_value default_replace_registry
;
105 /* bool, synchronous or asynchronous engine mode */
106 union jackctl_parameter_value sync
;
107 union jackctl_parameter_value default_sync
;
109 /* char enum, self connect mode mode */
110 union jackctl_parameter_value self_connect_mode
;
111 union jackctl_parameter_value default_self_connect_mode
;
114 struct jackctl_driver
116 jack_driver_desc_t
* desc_ptr
;
121 struct jackctl_internal
123 jack_driver_desc_t
* desc_ptr
;
128 struct jackctl_parameter
131 const char * short_description
;
132 const char * long_description
;
133 jackctl_param_type_t type
;
135 union jackctl_parameter_value
* value_ptr
;
136 union jackctl_parameter_value
* default_value_ptr
;
138 union jackctl_parameter_value value
;
139 union jackctl_parameter_value default_value
;
140 struct jackctl_driver
* driver_ptr
;
142 jack_driver_param_constraint_desc_t
* constraint_ptr
;
145 const char * jack_get_self_connect_mode_description(char mode
)
147 struct jack_constraint_enum_char_descriptor
* descr_ptr
;
149 for (descr_ptr
= self_connect_mode_constraint_descr_array
;
152 if (descr_ptr
->value
== mode
) return descr_ptr
->short_desc
;
158 struct jackctl_parameter
*
159 jackctl_add_parameter(
160 JSList
** parameters_list_ptr_ptr
,
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
)
170 struct jackctl_parameter
* parameter_ptr
;
172 parameter_ptr
= (struct jackctl_parameter
*)malloc(sizeof(struct jackctl_parameter
));
173 if (parameter_ptr
== NULL
)
175 jack_error("Cannot allocate memory for jackctl_parameter structure.");
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;
185 if (value_ptr
== NULL
)
187 value_ptr
= ¶meter_ptr
->value
;
190 if (default_value_ptr
== NULL
)
192 default_value_ptr
= ¶meter_ptr
->default_value
;
195 parameter_ptr
->value_ptr
= value_ptr
;
196 parameter_ptr
->default_value_ptr
= default_value_ptr
;
198 *value_ptr
= *default_value_ptr
= value
;
200 parameter_ptr
->driver_ptr
= NULL
;
201 parameter_ptr
->id
= 0;
202 parameter_ptr
->constraint_ptr
= constraint_ptr
;
204 *parameters_list_ptr_ptr
= jack_slist_append(*parameters_list_ptr_ptr
, parameter_ptr
);
206 return parameter_ptr
;
214 jackctl_free_driver_parameters(
215 struct jackctl_driver
* driver_ptr
)
217 JSList
* next_node_ptr
;
219 while (driver_ptr
->parameters
)
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
;
231 jackctl_add_driver_parameters(
232 struct jackctl_driver
* driver_ptr
)
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
;
241 for (i
= 0 ; i
< driver_ptr
->desc_ptr
->nparams
; i
++)
243 descriptor_ptr
= driver_ptr
->desc_ptr
->params
+ i
;
245 switch (descriptor_ptr
->type
)
247 case JackDriverParamInt
:
248 jackctl_type
= JackParamInt
;
249 jackctl_value
.i
= descriptor_ptr
->value
.i
;
251 case JackDriverParamUInt
:
252 jackctl_type
= JackParamUInt
;
253 jackctl_value
.ui
= descriptor_ptr
->value
.ui
;
255 case JackDriverParamChar
:
256 jackctl_type
= JackParamChar
;
257 jackctl_value
.c
= descriptor_ptr
->value
.c
;
259 case JackDriverParamString
:
260 jackctl_type
= JackParamString
;
261 strcpy(jackctl_value
.str
, descriptor_ptr
->value
.str
);
263 case JackDriverParamBool
:
264 jackctl_type
= JackParamBool
;
265 jackctl_value
.b
= descriptor_ptr
->value
.i
;
268 jack_error("Unknown driver parameter type %i", (int)descriptor_ptr
->type
);
273 parameter_ptr
= jackctl_add_parameter(
274 &driver_ptr
->parameters
,
275 descriptor_ptr
->name
,
276 descriptor_ptr
->short_desc
,
277 descriptor_ptr
->long_desc
,
282 descriptor_ptr
->constraint
);
284 if (parameter_ptr
== NULL
)
289 parameter_ptr
->driver_ptr
= driver_ptr
;
290 parameter_ptr
->id
= descriptor_ptr
->character
;
296 jackctl_free_driver_parameters(driver_ptr
);
301 /* destroy jack_driver_param_desc_t list created by jackctl_create_param_list() */
303 jackctl_destroy_param_list(
317 /* for drivers and internals are configured through jack_driver_param_t JSList */
318 /* this function creates such list from a jackctl_parameter list */
321 jackctl_create_param_list(
322 const JSList
* paramlist
,
323 JSList
** retparamlist
)
325 jackctl_parameter
* param_ptr
;
326 jack_driver_param_t
* retparam_ptr
;
328 *retparamlist
= NULL
;
329 while (paramlist
!= NULL
)
331 param_ptr
= (jackctl_parameter
*)paramlist
->data
;
332 if (param_ptr
->is_set
)
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
)
338 jack_error ("Allocation of jack_driver_param_t structure failed");
342 retparam_ptr
->character
= param_ptr
->id
;
344 switch (param_ptr
->type
)
347 retparam_ptr
->value
.i
= param_ptr
->value_ptr
->i
;
350 retparam_ptr
->value
.ui
= param_ptr
->value_ptr
->ui
;
353 retparam_ptr
->value
.c
= param_ptr
->value_ptr
->c
;
355 case JackParamString
:
356 strcpy(retparam_ptr
->value
.str
, param_ptr
->value_ptr
->str
);
359 retparam_ptr
->value
.i
= param_ptr
->value_ptr
->b
;
362 jack_error("Unknown parameter type %i", (int)param_ptr
->type
);
367 *retparamlist
= jack_slist_append(*retparamlist
, retparam_ptr
);
370 paramlist
= paramlist
->next
;
378 jackctl_destroy_param_list(*retparamlist
);
383 jackctl_drivers_load(
384 struct jackctl_server
* server_ptr
)
386 struct jackctl_driver
* driver_ptr
;
388 JSList
*descriptor_node_ptr
;
390 descriptor_node_ptr
= jack_drivers_load(NULL
);
391 if (descriptor_node_ptr
== NULL
)
393 jack_error("Could not find any drivers in driver directory!");
397 while (descriptor_node_ptr
!= NULL
)
399 driver_ptr
= (struct jackctl_driver
*)malloc(sizeof(struct jackctl_driver
));
400 if (driver_ptr
== NULL
)
402 jack_error("Memory allocation of jackctl_driver structure failed.");
406 driver_ptr
->desc_ptr
= (jack_driver_desc_t
*)descriptor_node_ptr
->data
;
407 driver_ptr
->parameters
= NULL
;
408 driver_ptr
->infos
= NULL
;
410 if (!jackctl_add_driver_parameters(driver_ptr
))
412 assert(driver_ptr
->parameters
== NULL
);
417 server_ptr
->drivers
= jack_slist_append(server_ptr
->drivers
, driver_ptr
);
420 node_ptr
= descriptor_node_ptr
;
421 descriptor_node_ptr
= descriptor_node_ptr
->next
;
430 jackctl_server_free_drivers(
431 struct jackctl_server
* server_ptr
)
433 JSList
* next_node_ptr
;
434 struct jackctl_driver
* driver_ptr
;
436 while (server_ptr
->drivers
)
438 next_node_ptr
= server_ptr
->drivers
->next
;
439 driver_ptr
= (struct jackctl_driver
*)server_ptr
->drivers
->data
;
441 jackctl_free_driver_parameters(driver_ptr
);
442 free(driver_ptr
->desc_ptr
->params
);
443 free(driver_ptr
->desc_ptr
);
446 free(server_ptr
->drivers
);
447 server_ptr
->drivers
= next_node_ptr
;
452 jackctl_internals_load(
453 struct jackctl_server
* server_ptr
)
455 struct jackctl_internal
* internal_ptr
;
457 JSList
*descriptor_node_ptr
;
459 descriptor_node_ptr
= jack_internals_load(NULL
);
460 if (descriptor_node_ptr
== NULL
)
462 jack_error("Could not find any internals in driver directory!");
466 while (descriptor_node_ptr
!= NULL
)
468 internal_ptr
= (struct jackctl_internal
*)malloc(sizeof(struct jackctl_internal
));
469 if (internal_ptr
== NULL
)
471 jack_error("Memory allocation of jackctl_driver structure failed.");
475 internal_ptr
->desc_ptr
= (jack_driver_desc_t
*)descriptor_node_ptr
->data
;
476 internal_ptr
->parameters
= NULL
;
477 internal_ptr
->refnum
= -1;
479 if (!jackctl_add_driver_parameters((struct jackctl_driver
*)internal_ptr
))
481 assert(internal_ptr
->parameters
== NULL
);
486 server_ptr
->internals
= jack_slist_append(server_ptr
->internals
, internal_ptr
);
489 node_ptr
= descriptor_node_ptr
;
490 descriptor_node_ptr
= descriptor_node_ptr
->next
;
499 jackctl_server_free_internals(
500 struct jackctl_server
* server_ptr
)
502 JSList
* next_node_ptr
;
503 struct jackctl_internal
* internal_ptr
;
505 while (server_ptr
->internals
)
507 next_node_ptr
= server_ptr
->internals
->next
;
508 internal_ptr
= (struct jackctl_internal
*)server_ptr
->internals
->data
;
510 jackctl_free_driver_parameters((struct jackctl_driver
*)internal_ptr
);
511 free(internal_ptr
->desc_ptr
->params
);
512 free(internal_ptr
->desc_ptr
);
515 free(server_ptr
->internals
);
516 server_ptr
->internals
= next_node_ptr
;
522 jackctl_server_free_parameters(
523 struct jackctl_server
* server_ptr
)
525 JSList
* next_node_ptr
;
527 while (server_ptr
->parameters
)
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
;
539 struct jackctl_sigmask
544 static jackctl_sigmask sigmask
;
546 static void signal_handler(int signum
)
548 printf("Jack main caught signal %d\n", signum
);
549 (void) signal(SIGINT
, SIG_DFL
);
550 SetEvent(sigmask
.wait_event
);
554 jackctl_setup_signals(
557 if ((sigmask
.wait_event
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
)) == NULL
) {
558 jack_error("CreateEvent fails err = %ld", GetLastError());
562 (void) signal(SIGINT
, signal_handler
);
563 (void) signal(SIGABRT
, signal_handler
);
564 (void) signal(SIGTERM
, signal_handler
);
569 void jackctl_wait_signals(jackctl_sigmask_t
* signals
)
571 if (WaitForSingleObject(signals
->wait_event
, INFINITE
) != WAIT_OBJECT_0
) {
572 jack_error("WaitForSingleObject fails err = %ld", GetLastError());
578 struct jackctl_sigmask
583 static jackctl_sigmask sigmask
;
587 signal_handler(int sig
)
589 /* this is used by the child (active) process, but it never
590 gets called unless we are already shutting down after
594 snprintf(buf
, sizeof(buf
), "Received signal %d during shutdown (ignored)\n", sig
);
597 SERVER_EXPORT jackctl_sigmask_t
*
598 jackctl_setup_signals(
602 struct sigaction action
;
605 /* ensure that we are in our own process group so that
606 kill (SIG, -pgrp) does the right thing.
611 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, NULL
);
615 POSIX says that signals are delivered like this:
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.
622 this means that a simple-minded multi-threaded program can
623 expect to get POSIX signals delivered randomly to any one
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().
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
);
646 /* android's bionic c doesn't provide pthread_cancel() and related functions.
647 * to solve this issue, use pthread_kill() & SIGUSR1 instead.
649 sigaddset(&sigmask
.signals
, SIGUSR1
);
651 sigaddset(&sigmask
.signals
, SIGUSR2
);
653 /* all child threads will inherit this mask unless they
654 * explicitly reset it
657 pthread_sigmask(SIG_BLOCK
, &sigmask
.signals
, 0);
659 /* install a do-nothing handler because otherwise pthreads
660 behaviour is undefined when we enter sigwait.
663 sigfillset(&allsignals
);
664 action
.sa_handler
= signal_handler
;
665 action
.sa_mask
= allsignals
;
666 action
.sa_flags
= SA_RESTART
|SA_RESETHAND
;
668 for (i
= 1; i
< NSIG
; i
++)
670 if (sigismember (&sigmask
.signals
, i
))
672 sigaction(i
, &action
, 0);
680 jackctl_wait_signals(jackctl_sigmask_t
* sigmask
)
686 #if defined(sun) && !defined(__sun__) // SUN compiler only, to check
687 sigwait(&sigmask
->signals
);
689 sigwait(&sigmask
->signals
, &sig
);
691 fprintf(stderr
, "Jack main caught signal %d\n", sig
);
695 //jack_dump_configuration(engine, 1);
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);
719 jack_driver_param_constraint_desc_t
*
720 get_realtime_priority_constraint()
722 jack_driver_param_constraint_desc_t
* constraint_ptr
;
725 if (!jack_get_thread_realtime_priority_range(&min
, &max
))
730 //jack_info("realtime priority range is (%d,%d)", min, max);
732 constraint_ptr
= (jack_driver_param_constraint_desc_t
*)calloc(1, sizeof(jack_driver_param_constraint_desc_t
));
733 if (constraint_ptr
== NULL
)
735 jack_error("Cannot allocate memory for jack_driver_param_constraint_desc_t structure.");
738 constraint_ptr
->flags
= JACK_CONSTRAINT_FLAG_RANGE
;
740 constraint_ptr
->constraint
.range
.min
.i
= min
;
741 constraint_ptr
->constraint
.range
.max
.i
= max
;
743 return constraint_ptr
;
746 SERVER_EXPORT jackctl_server_t
* jackctl_server_create(
747 bool (* on_device_acquire
)(const char * device_name
),
748 void (* on_device_release
)(const char * device_name
))
750 struct jackctl_server
* server_ptr
;
751 union jackctl_parameter_value value
;
753 server_ptr
= (struct jackctl_server
*)malloc(sizeof(struct jackctl_server
));
754 if (server_ptr
== NULL
)
756 jack_error("Cannot allocate memory for jackctl_server structure.");
760 server_ptr
->drivers
= NULL
;
761 server_ptr
->internals
= NULL
;
762 server_ptr
->parameters
= NULL
;
763 server_ptr
->engine
= NULL
;
765 strcpy(value
.str
, JackTools::DefaultServerName());
766 if (jackctl_add_parameter(
767 &server_ptr
->parameters
,
769 "Server name to use.",
773 &server_ptr
->default_name
,
776 goto fail_free_parameters
;
780 if (jackctl_add_parameter(
781 &server_ptr
->parameters
,
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
,
790 goto fail_free_parameters
;
794 if (jackctl_add_parameter(
795 &server_ptr
->parameters
,
797 "Scheduler priority when running in realtime mode.",
800 &server_ptr
->realtime_priority
,
801 &server_ptr
->default_realtime_priority
,
803 get_realtime_priority_constraint()) == NULL
)
805 goto fail_free_parameters
;
809 if (jackctl_add_parameter(
810 &server_ptr
->parameters
,
812 "Exit once all clients have closed their connections.",
815 &server_ptr
->temporary
,
816 &server_ptr
->default_temporary
,
819 goto fail_free_parameters
;
823 if (jackctl_add_parameter(
824 &server_ptr
->parameters
,
829 &server_ptr
->verbose
,
830 &server_ptr
->default_verbose
,
833 goto fail_free_parameters
;
837 if (jackctl_add_parameter(
838 &server_ptr
->parameters
,
840 "Client timeout limit in milliseconds.",
843 &server_ptr
->client_timeout
,
844 &server_ptr
->default_client_timeout
,
847 goto fail_free_parameters
;
851 if (jackctl_add_parameter(
852 &server_ptr
->parameters
,
854 "Clocksource type : c(ycle) | h(pet) | s(ystem).",
857 &server_ptr
->clock_source
,
858 &server_ptr
->default_clock_source
,
861 goto fail_free_parameters
;
865 if (jackctl_add_parameter(
866 &server_ptr
->parameters
,
868 "Maximum number of ports.",
871 &server_ptr
->port_max
,
872 &server_ptr
->default_port_max
,
875 goto fail_free_parameters
;
879 if (jackctl_add_parameter(
880 &server_ptr
->parameters
,
882 "Replace shared memory registry.",
885 &server_ptr
->replace_registry
,
886 &server_ptr
->default_replace_registry
,
889 goto fail_free_parameters
;
893 if (jackctl_add_parameter(
894 &server_ptr
->parameters
,
896 "Use server synchronous mode.",
900 &server_ptr
->default_sync
,
903 goto fail_free_parameters
;
906 value
.c
= JACK_DEFAULT_SELF_CONNECT_MODE
;
907 if (jackctl_add_parameter(
908 &server_ptr
->parameters
,
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
,
916 jack_constraint_compose_enum_char(
917 JACK_CONSTRAINT_FLAG_STRICT
| JACK_CONSTRAINT_FLAG_FAKE_VALUE
,
918 self_connect_mode_constraint_descr_array
)) == NULL
)
920 goto fail_free_parameters
;
923 JackServerGlobals::on_device_acquire
= on_device_acquire
;
924 JackServerGlobals::on_device_release
= on_device_release
;
926 if (!jackctl_drivers_load(server_ptr
))
928 goto fail_free_parameters
;
931 /* Allowed to fail */
932 jackctl_internals_load(server_ptr
);
936 fail_free_parameters
:
937 jackctl_server_free_parameters(server_ptr
);
945 SERVER_EXPORT
void jackctl_server_destroy(jackctl_server
*server_ptr
)
948 jackctl_server_free_drivers(server_ptr
);
949 jackctl_server_free_internals(server_ptr
);
950 jackctl_server_free_parameters(server_ptr
);
955 SERVER_EXPORT
const JSList
* jackctl_server_get_drivers_list(jackctl_server
*server_ptr
)
957 return (server_ptr
) ? server_ptr
->drivers
: NULL
;
960 SERVER_EXPORT
bool jackctl_server_stop(jackctl_server
*server_ptr
)
963 server_ptr
->engine
->Stop();
970 SERVER_EXPORT
bool jackctl_server_close(jackctl_server
*server_ptr
)
973 server_ptr
->engine
->Close();
974 delete server_ptr
->engine
;
976 /* clean up shared memory and files from this server instance */
977 jack_log("Cleaning up shared memory");
981 jack_log("Cleaning up files");
983 JackTools::CleanupFiles(server_ptr
->name
.str
);
985 jack_log("Unregistering server `%s'", server_ptr
->name
.str
);
987 jack_unregister_server(server_ptr
->name
.str
);
989 server_ptr
->engine
= NULL
;
997 SERVER_EXPORT
const JSList
* jackctl_server_get_parameters(jackctl_server
*server_ptr
)
999 return (server_ptr
) ? server_ptr
->parameters
: NULL
;
1003 jackctl_server_open(
1004 jackctl_server
*server_ptr
,
1005 jackctl_driver
*driver_ptr
)
1007 JSList
* paramlist
= NULL
;
1011 if (!server_ptr
|| !driver_ptr
) {
1015 int rc
= jack_register_server(server_ptr
->name
.str
, server_ptr
->replace_registry
.b
);
1019 jack_error("`%s' server already active", server_ptr
->name
.str
);
1022 jack_error("Too many servers already active");
1025 jack_error("No access to shm registry");
1029 jack_log("Server `%s' registered", server_ptr
->name
.str
);
1031 /* clean up shared memory and files from any previous
1032 * instance of this server name */
1034 JackTools::CleanupFiles(server_ptr
->name
.str
);
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. */
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
);
1046 /* get the engine/driver started */
1047 server_ptr
->engine
= new JackServer(
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
)
1060 jack_error("Failed to create new JackServer object");
1061 goto fail_unregister
;
1064 if (!jackctl_create_param_list(driver_ptr
->parameters
, ¶mlist
)) goto fail_delete
;
1065 rc
= server_ptr
->engine
->Open(driver_ptr
->desc_ptr
, paramlist
);
1066 jackctl_destroy_param_list(paramlist
);
1069 jack_error("JackServer::Open failed with %d", rc
);
1075 } catch (std::exception
&) {
1076 jack_error("jackctl_server_open error...");
1077 jackctl_destroy_param_list(paramlist
);
1081 delete server_ptr
->engine
;
1082 server_ptr
->engine
= NULL
;
1085 jack_log("Cleaning up shared memory");
1089 jack_log("Cleaning up files");
1091 JackTools::CleanupFiles(server_ptr
->name
.str
);
1093 jack_log("Unregistering server `%s'", server_ptr
->name
.str
);
1095 jack_unregister_server(server_ptr
->name
.str
);
1102 jackctl_server_start(
1103 jackctl_server
*server_ptr
)
1108 int rc
= server_ptr
->engine
->Start();
1109 bool result
= rc
>= 0;
1112 jack_error("JackServer::Start() failed with %d", rc
);
1118 SERVER_EXPORT
const char * jackctl_driver_get_name(jackctl_driver
*driver_ptr
)
1120 return (driver_ptr
) ? driver_ptr
->desc_ptr
->name
: NULL
;
1123 SERVER_EXPORT jackctl_driver_type_t
jackctl_driver_get_type(jackctl_driver
*driver_ptr
)
1125 return (driver_ptr
) ? (jackctl_driver_type_t
)driver_ptr
->desc_ptr
->type
: (jackctl_driver_type_t
)0;
1128 SERVER_EXPORT
const JSList
* jackctl_driver_get_parameters(jackctl_driver
*driver_ptr
)
1130 return (driver_ptr
) ? driver_ptr
->parameters
: NULL
;
1133 SERVER_EXPORT jack_driver_desc_t
* jackctl_driver_get_desc(jackctl_driver
*driver_ptr
)
1135 return (driver_ptr
) ? driver_ptr
->desc_ptr
: NULL
;
1138 SERVER_EXPORT
const char * jackctl_parameter_get_name(jackctl_parameter
*parameter_ptr
)
1140 return (parameter_ptr
) ? parameter_ptr
->name
: NULL
;
1143 SERVER_EXPORT
const char * jackctl_parameter_get_short_description(jackctl_parameter
*parameter_ptr
)
1145 return (parameter_ptr
) ? parameter_ptr
->short_description
: NULL
;
1148 SERVER_EXPORT
const char * jackctl_parameter_get_long_description(jackctl_parameter
*parameter_ptr
)
1150 return (parameter_ptr
) ? parameter_ptr
->long_description
: NULL
;
1153 SERVER_EXPORT
bool jackctl_parameter_has_range_constraint(jackctl_parameter
*parameter_ptr
)
1155 return (parameter_ptr
) ? (parameter_ptr
->constraint_ptr
!= NULL
&& (parameter_ptr
->constraint_ptr
->flags
& JACK_CONSTRAINT_FLAG_RANGE
) != 0) : false;
1158 SERVER_EXPORT
bool jackctl_parameter_has_enum_constraint(jackctl_parameter
*parameter_ptr
)
1160 return (parameter_ptr
) ? (parameter_ptr
->constraint_ptr
!= NULL
&& (parameter_ptr
->constraint_ptr
->flags
& JACK_CONSTRAINT_FLAG_RANGE
) == 0): false;
1163 SERVER_EXPORT
uint32_t jackctl_parameter_get_enum_constraints_count(jackctl_parameter
*parameter_ptr
)
1165 if (!parameter_ptr
) {
1169 if (!jackctl_parameter_has_enum_constraint(parameter_ptr
))
1174 return parameter_ptr
->constraint_ptr
->constraint
.enumeration
.count
;
1177 SERVER_EXPORT
union jackctl_parameter_value
jackctl_parameter_get_enum_constraint_value(jackctl_parameter
*parameter_ptr
, uint32_t index
)
1179 jack_driver_param_value_t
* value_ptr
;
1180 union jackctl_parameter_value jackctl_value
;
1182 if (!parameter_ptr
) {
1183 memset(&jackctl_value
, 0, sizeof(jackctl_value
));
1184 return jackctl_value
;
1187 value_ptr
= ¶meter_ptr
->constraint_ptr
->constraint
.enumeration
.possible_values_array
[index
].value
;
1189 switch (parameter_ptr
->type
)
1192 jackctl_value
.i
= value_ptr
->i
;
1195 jackctl_value
.ui
= value_ptr
->ui
;
1198 jackctl_value
.c
= value_ptr
->c
;
1200 case JackParamString
:
1201 strcpy(jackctl_value
.str
, value_ptr
->str
);
1204 jack_error("Bad driver parameter type %i (enum constraint)", (int)parameter_ptr
->type
);
1208 return jackctl_value
;
1211 SERVER_EXPORT
const char * jackctl_parameter_get_enum_constraint_description(jackctl_parameter
*parameter_ptr
, uint32_t index
)
1213 return (parameter_ptr
) ? parameter_ptr
->constraint_ptr
->constraint
.enumeration
.possible_values_array
[index
].short_desc
: NULL
;
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
)
1218 if (!parameter_ptr
|| !min_ptr
|| !max_ptr
) {
1222 switch (parameter_ptr
->type
)
1225 min_ptr
->i
= parameter_ptr
->constraint_ptr
->constraint
.range
.min
.i
;
1226 max_ptr
->i
= parameter_ptr
->constraint_ptr
->constraint
.range
.max
.i
;
1229 min_ptr
->ui
= parameter_ptr
->constraint_ptr
->constraint
.range
.min
.ui
;
1230 max_ptr
->ui
= parameter_ptr
->constraint_ptr
->constraint
.range
.max
.ui
;
1233 jack_error("Bad driver parameter type %i (range constraint)", (int)parameter_ptr
->type
);
1238 SERVER_EXPORT
bool jackctl_parameter_constraint_is_strict(jackctl_parameter_t
* parameter_ptr
)
1240 return (parameter_ptr
) ? (parameter_ptr
->constraint_ptr
!= NULL
&& (parameter_ptr
->constraint_ptr
->flags
& JACK_CONSTRAINT_FLAG_STRICT
) != 0) : false;
1243 SERVER_EXPORT
bool jackctl_parameter_constraint_is_fake_value(jackctl_parameter_t
* parameter_ptr
)
1245 return (parameter_ptr
) ? (parameter_ptr
->constraint_ptr
!= NULL
&& (parameter_ptr
->constraint_ptr
->flags
& JACK_CONSTRAINT_FLAG_FAKE_VALUE
) != 0) : false;
1248 SERVER_EXPORT jackctl_param_type_t
jackctl_parameter_get_type(jackctl_parameter
*parameter_ptr
)
1250 return (parameter_ptr
) ? parameter_ptr
->type
: (jackctl_param_type_t
)0;
1253 SERVER_EXPORT
char jackctl_parameter_get_id(jackctl_parameter_t
* parameter_ptr
)
1255 return (parameter_ptr
) ? parameter_ptr
->id
: 0;
1258 SERVER_EXPORT
bool jackctl_parameter_is_set(jackctl_parameter
*parameter_ptr
)
1260 return (parameter_ptr
) ? parameter_ptr
->is_set
: false;
1263 SERVER_EXPORT
union jackctl_parameter_value
jackctl_parameter_get_value(jackctl_parameter
*parameter_ptr
)
1265 if (parameter_ptr
) {
1266 return *parameter_ptr
->value_ptr
;
1268 union jackctl_parameter_value jackctl_value
;
1269 memset(&jackctl_value
, 0, sizeof(jackctl_value
));
1270 return jackctl_value
;
1274 SERVER_EXPORT
bool jackctl_parameter_reset(jackctl_parameter
*parameter_ptr
)
1276 if (!parameter_ptr
) {
1280 if (!parameter_ptr
->is_set
)
1285 parameter_ptr
->is_set
= false;
1287 *parameter_ptr
->value_ptr
= *parameter_ptr
->default_value_ptr
;
1292 SERVER_EXPORT
bool jackctl_parameter_set_value(jackctl_parameter
*parameter_ptr
, const union jackctl_parameter_value
* value_ptr
)
1294 if (!parameter_ptr
|| !value_ptr
) {
1298 parameter_ptr
->is_set
= true;
1299 *parameter_ptr
->value_ptr
= *value_ptr
;
1304 SERVER_EXPORT
union jackctl_parameter_value
jackctl_parameter_get_default_value(jackctl_parameter
*parameter_ptr
)
1306 if (parameter_ptr
) {
1307 return *parameter_ptr
->default_value_ptr
;
1309 union jackctl_parameter_value jackctl_value
;
1310 memset(&jackctl_value
, 0, sizeof(jackctl_value
));
1311 return jackctl_value
;
1315 // Internals clients
1317 SERVER_EXPORT
const JSList
* jackctl_server_get_internals_list(jackctl_server
*server_ptr
)
1319 return (server_ptr
) ? server_ptr
->internals
: NULL
;
1322 SERVER_EXPORT
const char * jackctl_internal_get_name(jackctl_internal
*internal_ptr
)
1324 return (internal_ptr
) ? internal_ptr
->desc_ptr
->name
: NULL
;
1327 SERVER_EXPORT
const JSList
* jackctl_internal_get_parameters(jackctl_internal
*internal_ptr
)
1329 return (internal_ptr
) ? internal_ptr
->parameters
: NULL
;
1332 SERVER_EXPORT
bool jackctl_server_load_internal(
1333 jackctl_server
* server_ptr
,
1334 jackctl_internal
* internal
)
1336 if (!server_ptr
|| !internal
) {
1341 if (server_ptr
->engine
!= NULL
) {
1343 if (!jackctl_create_param_list(internal
->parameters
, ¶mlist
)) 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);
1352 SERVER_EXPORT
bool jackctl_server_unload_internal(
1353 jackctl_server
* server_ptr
,
1354 jackctl_internal
* internal
)
1356 if (!server_ptr
|| !internal
) {
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);
1369 SERVER_EXPORT
bool jackctl_server_load_session_file(
1370 jackctl_server
* server_ptr
,
1373 if (!server_ptr
|| !file
|| !server_ptr
->engine
) {
1377 return (server_ptr
->engine
->LoadInternalSessionFile(file
) >= 0);
1380 SERVER_EXPORT
bool jackctl_server_add_slave(jackctl_server
* server_ptr
, jackctl_driver
* driver_ptr
)
1382 if (server_ptr
&& server_ptr
->engine
) {
1383 if (server_ptr
->engine
->IsRunning()) {
1384 jack_error("Cannot add a slave in a running server");
1388 if (!jackctl_create_param_list(driver_ptr
->parameters
, ¶mlist
)) return false;
1389 JackDriverInfo
* info
= server_ptr
->engine
->AddSlave(driver_ptr
->desc_ptr
, paramlist
);
1390 jackctl_destroy_param_list(paramlist
);
1392 driver_ptr
->infos
= jack_slist_append(driver_ptr
->infos
, info
);
1403 SERVER_EXPORT
bool jackctl_server_remove_slave(jackctl_server
* server_ptr
, jackctl_driver
* driver_ptr
)
1405 if (server_ptr
&& server_ptr
->engine
) {
1406 if (server_ptr
->engine
->IsRunning()) {
1407 jack_error("Cannot remove a slave from a running server");
1410 if (driver_ptr
->infos
) {
1411 JackDriverInfo
* info
= (JackDriverInfo
*)driver_ptr
->infos
->data
;
1413 driver_ptr
->infos
= jack_slist_remove(driver_ptr
->infos
, info
);
1414 server_ptr
->engine
->RemoveSlave(info
);
1426 SERVER_EXPORT
bool jackctl_server_switch_master(jackctl_server
* server_ptr
, jackctl_driver
* driver_ptr
)
1428 if (server_ptr
&& server_ptr
->engine
) {
1430 if (!jackctl_create_param_list(driver_ptr
->parameters
, ¶mlist
)) return false;
1431 bool ret
= (server_ptr
->engine
->SwitchMaster(driver_ptr
->desc_ptr
, paramlist
) == 0);
1432 jackctl_destroy_param_list(paramlist
);