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 #define SELF_CONNECT_MODE_ALLOW_CHAR ' '
51 #define SELF_CONNECT_MODE_FAIL_EXTERNAL_ONLY_CHAR 'E'
52 #define SELF_CONNECT_MODE_IGNORE_EXTERNAL_ONLY_CHAR 'e'
53 #define SELF_CONNECT_MODE_FAIL_ALL_CHAR 'A'
54 #define SELF_CONNECT_MODE_IGNORE_ALL_CHAR 'a'
55 #define SELF_CONNECT_MODES_COUNT 5
63 class JackServer
* engine
;
65 /* string, server name */
66 union jackctl_parameter_value name
;
67 union jackctl_parameter_value default_name
;
69 /* bool, whether to be "realtime" */
70 union jackctl_parameter_value realtime
;
71 union jackctl_parameter_value default_realtime
;
74 union jackctl_parameter_value realtime_priority
;
75 union jackctl_parameter_value default_realtime_priority
;
77 /* bool, whether to exit once all clients have closed their connections */
78 union jackctl_parameter_value temporary
;
79 union jackctl_parameter_value default_temporary
;
81 /* bool, whether to be verbose */
82 union jackctl_parameter_value verbose
;
83 union jackctl_parameter_value default_verbose
;
85 /* int32_t, msecs; if zero, use period size. */
86 union jackctl_parameter_value client_timeout
;
87 union jackctl_parameter_value default_client_timeout
;
89 /* uint32_t, clock source type */
90 union jackctl_parameter_value clock_source
;
91 union jackctl_parameter_value default_clock_source
;
94 union jackctl_parameter_value replace_registry
;
95 union jackctl_parameter_value default_replace_registry
;
97 /* bool, synchronous or asynchronous engine mode */
98 union jackctl_parameter_value sync
;
99 union jackctl_parameter_value default_sync
;
101 /* char enum, self connect mode mode */
102 union jackctl_parameter_value self_connect_mode
;
103 union jackctl_parameter_value default_self_connect_mode
;
104 jack_driver_param_value_enum_t self_connect_mode_possible_values
[SELF_CONNECT_MODES_COUNT
];
105 jack_driver_param_constraint_desc_t self_connect_mode_constraint
;
108 struct jackctl_driver
110 jack_driver_desc_t
* desc_ptr
;
112 JSList
* set_parameters
;
113 JackDriverInfo
* info
;
116 struct jackctl_internal
118 jack_driver_desc_t
* desc_ptr
;
120 JSList
* set_parameters
;
124 struct jackctl_parameter
127 const char * short_description
;
128 const char * long_description
;
129 jackctl_param_type_t type
;
131 union jackctl_parameter_value
* value_ptr
;
132 union jackctl_parameter_value
* default_value_ptr
;
134 union jackctl_parameter_value value
;
135 union jackctl_parameter_value default_value
;
136 struct jackctl_driver
* driver_ptr
;
138 jack_driver_param_t
* driver_parameter_ptr
;
139 jack_driver_param_constraint_desc_t
* constraint_ptr
;
143 struct jackctl_parameter
*
144 jackctl_add_parameter(
145 JSList
** parameters_list_ptr_ptr
,
147 const char * short_description
,
148 const char * long_description
,
149 jackctl_param_type_t type
,
150 union jackctl_parameter_value
* value_ptr
,
151 union jackctl_parameter_value
* default_value_ptr
,
152 union jackctl_parameter_value value
,
153 jack_driver_param_constraint_desc_t
* constraint_ptr
= NULL
)
155 struct jackctl_parameter
* parameter_ptr
;
157 parameter_ptr
= (struct jackctl_parameter
*)malloc(sizeof(struct jackctl_parameter
));
158 if (parameter_ptr
== NULL
)
160 jack_error("Cannot allocate memory for jackctl_parameter structure.");
164 parameter_ptr
->name
= name
;
165 parameter_ptr
->short_description
= short_description
;
166 parameter_ptr
->long_description
= long_description
;
167 parameter_ptr
->type
= type
;
168 parameter_ptr
->is_set
= false;
170 if (value_ptr
== NULL
)
172 value_ptr
= ¶meter_ptr
->value
;
175 if (default_value_ptr
== NULL
)
177 default_value_ptr
= ¶meter_ptr
->default_value
;
180 parameter_ptr
->value_ptr
= value_ptr
;
181 parameter_ptr
->default_value_ptr
= default_value_ptr
;
183 *value_ptr
= *default_value_ptr
= value
;
185 parameter_ptr
->driver_ptr
= NULL
;
186 parameter_ptr
->driver_parameter_ptr
= NULL
;
187 parameter_ptr
->id
= 0;
188 parameter_ptr
->constraint_ptr
= constraint_ptr
;
190 *parameters_list_ptr_ptr
= jack_slist_append(*parameters_list_ptr_ptr
, parameter_ptr
);
192 return parameter_ptr
;
200 jackctl_free_driver_parameters(
201 struct jackctl_driver
* driver_ptr
)
203 JSList
* next_node_ptr
;
205 while (driver_ptr
->parameters
)
207 next_node_ptr
= driver_ptr
->parameters
->next
;
208 free(driver_ptr
->parameters
->data
);
209 free(driver_ptr
->parameters
);
210 driver_ptr
->parameters
= next_node_ptr
;
213 while (driver_ptr
->set_parameters
)
215 next_node_ptr
= driver_ptr
->set_parameters
->next
;
216 free(driver_ptr
->set_parameters
->data
);
217 free(driver_ptr
->set_parameters
);
218 driver_ptr
->set_parameters
= next_node_ptr
;
224 jackctl_add_driver_parameters(
225 struct jackctl_driver
* driver_ptr
)
228 union jackctl_parameter_value jackctl_value
;
229 jackctl_param_type_t jackctl_type
;
230 struct jackctl_parameter
* parameter_ptr
;
231 jack_driver_param_desc_t
* descriptor_ptr
;
233 for (i
= 0 ; i
< driver_ptr
->desc_ptr
->nparams
; i
++)
235 descriptor_ptr
= driver_ptr
->desc_ptr
->params
+ i
;
237 switch (descriptor_ptr
->type
)
239 case JackDriverParamInt
:
240 jackctl_type
= JackParamInt
;
241 jackctl_value
.i
= descriptor_ptr
->value
.i
;
243 case JackDriverParamUInt
:
244 jackctl_type
= JackParamUInt
;
245 jackctl_value
.ui
= descriptor_ptr
->value
.ui
;
247 case JackDriverParamChar
:
248 jackctl_type
= JackParamChar
;
249 jackctl_value
.c
= descriptor_ptr
->value
.c
;
251 case JackDriverParamString
:
252 jackctl_type
= JackParamString
;
253 strcpy(jackctl_value
.str
, descriptor_ptr
->value
.str
);
255 case JackDriverParamBool
:
256 jackctl_type
= JackParamBool
;
257 jackctl_value
.b
= descriptor_ptr
->value
.i
;
260 jack_error("unknown driver parameter type %i", (int)descriptor_ptr
->type
);
265 parameter_ptr
= jackctl_add_parameter(
266 &driver_ptr
->parameters
,
267 descriptor_ptr
->name
,
268 descriptor_ptr
->short_desc
,
269 descriptor_ptr
->long_desc
,
274 descriptor_ptr
->constraint
);
276 if (parameter_ptr
== NULL
)
281 parameter_ptr
->driver_ptr
= driver_ptr
;
282 parameter_ptr
->id
= descriptor_ptr
->character
;
288 jackctl_free_driver_parameters(driver_ptr
);
294 jackctl_drivers_load(
295 struct jackctl_server
* server_ptr
)
297 struct jackctl_driver
* driver_ptr
;
299 JSList
*descriptor_node_ptr
;
301 descriptor_node_ptr
= jack_drivers_load(NULL
);
302 if (descriptor_node_ptr
== NULL
)
304 jack_error("could not find any drivers in driver directory!");
308 while (descriptor_node_ptr
!= NULL
)
310 driver_ptr
= (struct jackctl_driver
*)malloc(sizeof(struct jackctl_driver
));
311 if (driver_ptr
== NULL
)
313 jack_error("memory allocation of jackctl_driver structure failed.");
317 driver_ptr
->desc_ptr
= (jack_driver_desc_t
*)descriptor_node_ptr
->data
;
318 driver_ptr
->parameters
= NULL
;
319 driver_ptr
->set_parameters
= NULL
;
321 if (!jackctl_add_driver_parameters(driver_ptr
))
323 assert(driver_ptr
->parameters
== NULL
);
328 server_ptr
->drivers
= jack_slist_append(server_ptr
->drivers
, driver_ptr
);
331 node_ptr
= descriptor_node_ptr
;
332 descriptor_node_ptr
= descriptor_node_ptr
->next
;
341 jackctl_server_free_drivers(
342 struct jackctl_server
* server_ptr
)
344 JSList
* next_node_ptr
;
345 struct jackctl_driver
* driver_ptr
;
347 while (server_ptr
->drivers
)
349 next_node_ptr
= server_ptr
->drivers
->next
;
350 driver_ptr
= (struct jackctl_driver
*)server_ptr
->drivers
->data
;
352 jackctl_free_driver_parameters(driver_ptr
);
353 free(driver_ptr
->desc_ptr
->params
);
354 free(driver_ptr
->desc_ptr
);
357 free(server_ptr
->drivers
);
358 server_ptr
->drivers
= next_node_ptr
;
363 jackctl_internals_load(
364 struct jackctl_server
* server_ptr
)
366 struct jackctl_internal
* internal_ptr
;
368 JSList
*descriptor_node_ptr
;
370 descriptor_node_ptr
= jack_internals_load(NULL
);
371 if (descriptor_node_ptr
== NULL
)
373 jack_error("could not find any internals in driver directory!");
377 while (descriptor_node_ptr
!= NULL
)
379 internal_ptr
= (struct jackctl_internal
*)malloc(sizeof(struct jackctl_internal
));
380 if (internal_ptr
== NULL
)
382 jack_error("memory allocation of jackctl_driver structure failed.");
386 internal_ptr
->desc_ptr
= (jack_driver_desc_t
*)descriptor_node_ptr
->data
;
387 internal_ptr
->parameters
= NULL
;
388 internal_ptr
->set_parameters
= NULL
;
390 if (!jackctl_add_driver_parameters((struct jackctl_driver
*)internal_ptr
))
392 assert(internal_ptr
->parameters
== NULL
);
397 server_ptr
->internals
= jack_slist_append(server_ptr
->internals
, internal_ptr
);
400 node_ptr
= descriptor_node_ptr
;
401 descriptor_node_ptr
= descriptor_node_ptr
->next
;
410 jackctl_server_free_internals(
411 struct jackctl_server
* server_ptr
)
413 JSList
* next_node_ptr
;
414 struct jackctl_internal
* internal_ptr
;
416 while (server_ptr
->internals
)
418 next_node_ptr
= server_ptr
->internals
->next
;
419 internal_ptr
= (struct jackctl_internal
*)server_ptr
->internals
->data
;
421 jackctl_free_driver_parameters((struct jackctl_driver
*)internal_ptr
);
422 free(internal_ptr
->desc_ptr
->params
);
423 free(internal_ptr
->desc_ptr
);
426 free(server_ptr
->internals
);
427 server_ptr
->internals
= next_node_ptr
;
433 jackctl_server_free_parameters(
434 struct jackctl_server
* server_ptr
)
436 JSList
* next_node_ptr
;
438 while (server_ptr
->parameters
)
440 next_node_ptr
= server_ptr
->parameters
->next
;
441 free(server_ptr
->parameters
->data
);
442 free(server_ptr
->parameters
);
443 server_ptr
->parameters
= next_node_ptr
;
449 static HANDLE waitEvent
;
451 static void do_nothing_handler(int signum
)
453 printf("jack main caught signal %d\n", signum
);
454 (void) signal(SIGINT
, SIG_DFL
);
459 jackctl_setup_signals(
462 if ((waitEvent
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
)) == NULL
) {
463 jack_error("CreateEvent fails err = %ld", GetLastError());
467 (void) signal(SIGINT
, do_nothing_handler
);
468 (void) signal(SIGABRT
, do_nothing_handler
);
469 (void) signal(SIGTERM
, do_nothing_handler
);
471 return (sigset_t
)waitEvent
;
474 void jackctl_wait_signals(sigset_t signals
)
476 if (WaitForSingleObject(waitEvent
, INFINITE
) != WAIT_OBJECT_0
) {
477 jack_error("WaitForSingleObject fails err = %ld", GetLastError());
485 do_nothing_handler(int sig
)
487 /* this is used by the child (active) process, but it never
488 gets called unless we are already shutting down after
492 snprintf (buf
, sizeof(buf
), "received signal %d during shutdown (ignored)\n", sig
);
496 jackctl_setup_signals(
501 struct sigaction action
;
504 /* ensure that we are in our own process group so that
505 kill (SIG, -pgrp) does the right thing.
510 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, NULL
);
514 POSIX says that signals are delivered like this:
516 * if a thread has blocked that signal, it is not
517 a candidate to receive the signal.
518 * of all threads not blocking the signal, pick
519 one at random, and deliver the signal.
521 this means that a simple-minded multi-threaded program can
522 expect to get POSIX signals delivered randomly to any one
525 here, we block all signals that we think we might receive
526 and want to catch. all "child" threads will inherit this
527 setting. if we create a thread that calls sigwait() on the
528 same set of signals, implicitly unblocking all those
529 signals. any of those signals that are delivered to the
530 process will be delivered to that thread, and that thread
531 alone. this makes cleanup for a signal-driven exit much
532 easier, since we know which thread is doing it and more
533 importantly, we are free to call async-unsafe functions,
534 because the code is executing in normal thread context
535 after a return from sigwait().
538 sigemptyset(&signals
);
539 sigaddset(&signals
, SIGHUP
);
540 sigaddset(&signals
, SIGINT
);
541 sigaddset(&signals
, SIGQUIT
);
542 sigaddset(&signals
, SIGPIPE
);
543 sigaddset(&signals
, SIGTERM
);
544 sigaddset(&signals
, SIGUSR1
);
545 sigaddset(&signals
, SIGUSR2
);
547 /* all child threads will inherit this mask unless they
548 * explicitly reset it
551 pthread_sigmask(SIG_BLOCK
, &signals
, 0);
553 /* install a do-nothing handler because otherwise pthreads
554 behaviour is undefined when we enter sigwait.
557 sigfillset(&allsignals
);
558 action
.sa_handler
= do_nothing_handler
;
559 action
.sa_mask
= allsignals
;
560 action
.sa_flags
= SA_RESTART
|SA_RESETHAND
;
562 for (i
= 1; i
< NSIG
; i
++)
564 if (sigismember (&signals
, i
))
566 sigaction(i
, &action
, 0);
574 jackctl_wait_signals(sigset_t signals
)
580 #if defined(sun) && !defined(__sun__) // SUN compiler only, to check
583 sigwait(&signals
, &sig
);
585 fprintf(stderr
, "jack main caught signal %d\n", sig
);
589 //jack_dump_configuration(engine, 1);
603 if (sig
!= SIGSEGV
) {
604 // unblock signals so we can see them during shutdown.
605 // this will help prod developers not to lose sight of
606 // bugs that cause segfaults etc. during shutdown.
607 sigprocmask(SIG_UNBLOCK
, &signals
, 0);
613 jack_driver_param_constraint_desc_t
*
614 get_realtime_priority_constraint()
616 jack_driver_param_constraint_desc_t
* constraint_ptr
;
619 if (!jack_get_thread_realtime_priority_range(&min
, &max
))
624 //jack_info("realtime priority range is (%d,%d)", min, max);
626 constraint_ptr
= (jack_driver_param_constraint_desc_t
*)calloc(1, sizeof(jack_driver_param_value_enum_t
));
627 constraint_ptr
->flags
= JACK_CONSTRAINT_FLAG_RANGE
;
629 constraint_ptr
->constraint
.range
.min
.i
= min
;
630 constraint_ptr
->constraint
.range
.max
.i
= max
;
632 return constraint_ptr
;
635 EXPORT jackctl_server_t
* jackctl_server_create(
636 bool (* on_device_acquire
)(const char * device_name
),
637 void (* on_device_release
)(const char * device_name
))
639 struct jackctl_server
* server_ptr
;
640 union jackctl_parameter_value value
;
642 server_ptr
= (struct jackctl_server
*)malloc(sizeof(struct jackctl_server
));
643 if (server_ptr
== NULL
)
645 jack_error("Cannot allocate memory for jackctl_server structure.");
649 server_ptr
->drivers
= NULL
;
650 server_ptr
->internals
= NULL
;
651 server_ptr
->parameters
= NULL
;
652 server_ptr
->engine
= NULL
;
654 strcpy(value
.str
, JACK_DEFAULT_SERVER_NAME
);
655 if (jackctl_add_parameter(
656 &server_ptr
->parameters
,
658 "Server name to use.",
662 &server_ptr
->default_name
,
665 goto fail_free_parameters
;
669 if (jackctl_add_parameter(
670 &server_ptr
->parameters
,
672 "Whether to use realtime mode.",
673 "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.",
675 &server_ptr
->realtime
,
676 &server_ptr
->default_realtime
,
679 goto fail_free_parameters
;
683 if (jackctl_add_parameter(
684 &server_ptr
->parameters
,
686 "Scheduler priority when running in realtime mode.",
689 &server_ptr
->realtime_priority
,
690 &server_ptr
->default_realtime_priority
,
692 get_realtime_priority_constraint()) == NULL
)
694 goto fail_free_parameters
;
698 if (jackctl_add_parameter(
699 &server_ptr
->parameters
,
701 "Exit once all clients have closed their connections.",
704 &server_ptr
->temporary
,
705 &server_ptr
->default_temporary
,
708 goto fail_free_parameters
;
712 if (jackctl_add_parameter(
713 &server_ptr
->parameters
,
718 &server_ptr
->verbose
,
719 &server_ptr
->default_verbose
,
722 goto fail_free_parameters
;
726 if (jackctl_add_parameter(
727 &server_ptr
->parameters
,
729 "Client timeout limit in milliseconds.",
732 &server_ptr
->client_timeout
,
733 &server_ptr
->default_client_timeout
,
736 goto fail_free_parameters
;
740 if (jackctl_add_parameter(
741 &server_ptr
->parameters
,
743 "Clocksource type : c(ycle) | h(pet) | s(ystem).",
746 &server_ptr
->clock_source
,
747 &server_ptr
->default_clock_source
,
750 goto fail_free_parameters
;
754 if (jackctl_add_parameter(
755 &server_ptr
->parameters
,
757 "Replace shared memory registry.",
760 &server_ptr
->replace_registry
,
761 &server_ptr
->default_replace_registry
,
764 goto fail_free_parameters
;
768 if (jackctl_add_parameter(
769 &server_ptr
->parameters
,
771 "Use server synchronous mode.",
775 &server_ptr
->default_sync
,
778 goto fail_free_parameters
;
781 server_ptr
->self_connect_mode_constraint
.flags
= JACK_CONSTRAINT_FLAG_STRICT
| JACK_CONSTRAINT_FLAG_FAKE_VALUE
;
782 server_ptr
->self_connect_mode_constraint
.constraint
.enumeration
.count
= SELF_CONNECT_MODES_COUNT
;
783 server_ptr
->self_connect_mode_constraint
.constraint
.enumeration
.possible_values_array
= server_ptr
->self_connect_mode_possible_values
;
785 server_ptr
->self_connect_mode_possible_values
[0].value
.c
= SELF_CONNECT_MODE_ALLOW_CHAR
;
786 strcpy(server_ptr
->self_connect_mode_possible_values
[0].short_desc
, "Don't restrict self connect requests");
788 server_ptr
->self_connect_mode_possible_values
[1].value
.c
= SELF_CONNECT_MODE_FAIL_EXTERNAL_ONLY_CHAR
;
789 strcpy(server_ptr
->self_connect_mode_possible_values
[1].short_desc
, "Fail self connect requests to external ports only");
791 server_ptr
->self_connect_mode_possible_values
[2].value
.c
= SELF_CONNECT_MODE_IGNORE_EXTERNAL_ONLY_CHAR
;
792 strcpy(server_ptr
->self_connect_mode_possible_values
[2].short_desc
, "Ignore self connect requests to external ports only");
794 server_ptr
->self_connect_mode_possible_values
[3].value
.c
= SELF_CONNECT_MODE_FAIL_ALL_CHAR
;
795 strcpy(server_ptr
->self_connect_mode_possible_values
[3].short_desc
, "Fail all self connect requests");
797 server_ptr
->self_connect_mode_possible_values
[4].value
.c
= SELF_CONNECT_MODE_IGNORE_ALL_CHAR
;
798 strcpy(server_ptr
->self_connect_mode_possible_values
[4].short_desc
, "Ignore all self connect requests");
800 value
.c
= SELF_CONNECT_MODE_ALLOW_CHAR
;
801 if (jackctl_add_parameter(
802 &server_ptr
->parameters
,
804 "Self connect mode.",
805 "Whether JACK clients are allowed to connect their own ports",
807 &server_ptr
->self_connect_mode
,
808 &server_ptr
->default_self_connect_mode
,
810 &server_ptr
->self_connect_mode_constraint
) == NULL
)
812 goto fail_free_parameters
;
815 JackServerGlobals::on_device_acquire
= on_device_acquire
;
816 JackServerGlobals::on_device_release
= on_device_release
;
818 if (!jackctl_drivers_load(server_ptr
))
820 goto fail_free_parameters
;
823 /* Allowed to fail */
824 jackctl_internals_load(server_ptr
);
828 fail_free_parameters
:
829 jackctl_server_free_parameters(server_ptr
);
837 EXPORT
void jackctl_server_destroy(jackctl_server
*server_ptr
)
839 jackctl_server_free_drivers(server_ptr
);
840 jackctl_server_free_internals(server_ptr
);
841 jackctl_server_free_parameters(server_ptr
);
845 EXPORT
const JSList
* jackctl_server_get_drivers_list(jackctl_server
*server_ptr
)
847 return server_ptr
->drivers
;
850 EXPORT
bool jackctl_server_stop(jackctl_server
*server_ptr
)
852 server_ptr
->engine
->Stop();
853 server_ptr
->engine
->Close();
854 delete server_ptr
->engine
;
856 /* clean up shared memory and files from this server instance */
857 jack_log("cleaning up shared memory");
861 jack_log("cleaning up files");
863 JackTools::CleanupFiles(server_ptr
->name
.str
);
865 jack_log("unregistering server `%s'", server_ptr
->name
.str
);
867 jack_unregister_server(server_ptr
->name
.str
);
869 server_ptr
->engine
= NULL
;
874 EXPORT
const JSList
* jackctl_server_get_parameters(jackctl_server
*server_ptr
)
876 return server_ptr
->parameters
;
880 jackctl_server_start(
881 jackctl_server
*server_ptr
,
882 jackctl_driver
*driver_ptr
)
885 JackSelfConnectMode self_connect_mode
;
887 rc
= jack_register_server(server_ptr
->name
.str
, server_ptr
->replace_registry
.b
);
891 jack_error("`%s' server already active", server_ptr
->name
.str
);
894 jack_error("too many servers already active");
897 jack_error("no access to shm registry");
901 jack_log("server `%s' registered", server_ptr
->name
.str
);
903 /* clean up shared memory and files from any previous
904 * instance of this server name */
906 JackTools::CleanupFiles(server_ptr
->name
.str
);
908 if (!server_ptr
->realtime
.b
&& server_ptr
->client_timeout
.i
== 0)
909 server_ptr
->client_timeout
.i
= 500; /* 0.5 sec; usable when non realtime. */
911 switch (server_ptr
->self_connect_mode
.c
)
913 case SELF_CONNECT_MODE_ALLOW_CHAR
:
914 self_connect_mode
= JackSelfConnectAllow
;
916 case SELF_CONNECT_MODE_FAIL_EXTERNAL_ONLY_CHAR
:
917 self_connect_mode
= JackSelfConnectFailExternalOnly
;
919 case SELF_CONNECT_MODE_IGNORE_EXTERNAL_ONLY_CHAR
:
920 self_connect_mode
= JackSelfConnectIgnoreExternalOnly
;
922 case SELF_CONNECT_MODE_FAIL_ALL_CHAR
:
923 self_connect_mode
= JackSelfConnectFailAll
;
925 case SELF_CONNECT_MODE_IGNORE_ALL_CHAR
:
926 self_connect_mode
= JackSelfConnectIgnoreAll
;
929 self_connect_mode
= JACK_DEFAULT_SELF_CONNECT_MODE
;
932 /* get the engine/driver started */
934 server_ptr
->engine
= new JackServer(
936 server_ptr
->temporary
.b
,
937 server_ptr
->client_timeout
.i
,
938 server_ptr
->realtime
.b
,
939 server_ptr
->realtime_priority
.i
,
940 server_ptr
->verbose
.b
,
941 (jack_timer_type_t
)server_ptr
->clock_source
.ui
,
943 server_ptr
->name
.str
);
944 if (server_ptr
->engine
== NULL
)
946 jack_error("Failed to create new JackServer object");
947 goto fail_unregister
;
950 rc
= server_ptr
->engine
->Open(driver_ptr
->desc_ptr
, driver_ptr
->set_parameters
);
953 jack_error("JackServer::Open() failed with %d", rc
);
957 rc
= server_ptr
->engine
->Start();
960 jack_error("JackServer::Start() failed with %d", rc
);
967 server_ptr
->engine
->Close();
970 delete server_ptr
->engine
;
971 server_ptr
->engine
= NULL
;
974 jack_log("cleaning up shared memory");
978 jack_log("cleaning up files");
980 JackTools::CleanupFiles(server_ptr
->name
.str
);
982 jack_log("unregistering server `%s'", server_ptr
->name
.str
);
984 jack_unregister_server(server_ptr
->name
.str
);
990 EXPORT
const char * jackctl_driver_get_name(jackctl_driver
*driver_ptr
)
992 return driver_ptr
->desc_ptr
->name
;
995 EXPORT
const JSList
* jackctl_driver_get_parameters(jackctl_driver
*driver_ptr
)
997 return driver_ptr
->parameters
;
1000 EXPORT jack_driver_desc_t
* jackctl_driver_get_desc(jackctl_driver
*driver_ptr
)
1002 return driver_ptr
->desc_ptr
;
1005 EXPORT
const char * jackctl_parameter_get_name(jackctl_parameter
*parameter_ptr
)
1007 return parameter_ptr
->name
;
1010 EXPORT
const char * jackctl_parameter_get_short_description(jackctl_parameter
*parameter_ptr
)
1012 return parameter_ptr
->short_description
;
1015 EXPORT
const char * jackctl_parameter_get_long_description(jackctl_parameter
*parameter_ptr
)
1017 return parameter_ptr
->long_description
;
1020 EXPORT
bool jackctl_parameter_has_range_constraint(jackctl_parameter
*parameter_ptr
)
1022 return parameter_ptr
->constraint_ptr
!= NULL
&& (parameter_ptr
->constraint_ptr
->flags
& JACK_CONSTRAINT_FLAG_RANGE
) != 0;
1025 EXPORT
bool jackctl_parameter_has_enum_constraint(jackctl_parameter
*parameter_ptr
)
1027 return parameter_ptr
->constraint_ptr
!= NULL
&& (parameter_ptr
->constraint_ptr
->flags
& JACK_CONSTRAINT_FLAG_RANGE
) == 0;
1030 EXPORT
uint32_t jackctl_parameter_get_enum_constraints_count(jackctl_parameter
*parameter_ptr
)
1032 if (!jackctl_parameter_has_enum_constraint(parameter_ptr
))
1037 return parameter_ptr
->constraint_ptr
->constraint
.enumeration
.count
;
1040 EXPORT
union jackctl_parameter_value
jackctl_parameter_get_enum_constraint_value(jackctl_parameter
*parameter_ptr
, uint32_t index
)
1042 jack_driver_param_value_t
* value_ptr
;
1043 union jackctl_parameter_value jackctl_value
;
1045 value_ptr
= ¶meter_ptr
->constraint_ptr
->constraint
.enumeration
.possible_values_array
[index
].value
;
1047 switch (parameter_ptr
->type
)
1050 jackctl_value
.i
= value_ptr
->i
;
1053 jackctl_value
.ui
= value_ptr
->ui
;
1056 jackctl_value
.c
= value_ptr
->c
;
1058 case JackParamString
:
1059 strcpy(jackctl_value
.str
, value_ptr
->str
);
1062 jack_error("bad driver parameter type %i (enum constraint)", (int)parameter_ptr
->type
);
1066 return jackctl_value
;
1069 EXPORT
const char * jackctl_parameter_get_enum_constraint_description(jackctl_parameter
*parameter_ptr
, uint32_t index
)
1071 return parameter_ptr
->constraint_ptr
->constraint
.enumeration
.possible_values_array
[index
].short_desc
;
1074 EXPORT
void jackctl_parameter_get_range_constraint(jackctl_parameter
*parameter_ptr
, union jackctl_parameter_value
* min_ptr
, union jackctl_parameter_value
* max_ptr
)
1076 switch (parameter_ptr
->type
)
1079 min_ptr
->i
= parameter_ptr
->constraint_ptr
->constraint
.range
.min
.i
;
1080 max_ptr
->i
= parameter_ptr
->constraint_ptr
->constraint
.range
.max
.i
;
1083 min_ptr
->ui
= parameter_ptr
->constraint_ptr
->constraint
.range
.min
.ui
;
1084 max_ptr
->ui
= parameter_ptr
->constraint_ptr
->constraint
.range
.max
.ui
;
1087 jack_error("bad driver parameter type %i (range constraint)", (int)parameter_ptr
->type
);
1092 EXPORT
bool jackctl_parameter_constraint_is_strict(jackctl_parameter_t
* parameter_ptr
)
1094 return parameter_ptr
->constraint_ptr
!= NULL
&& (parameter_ptr
->constraint_ptr
->flags
& JACK_CONSTRAINT_FLAG_STRICT
) != 0;
1097 EXPORT
bool jackctl_parameter_constraint_is_fake_value(jackctl_parameter_t
* parameter_ptr
)
1099 return parameter_ptr
->constraint_ptr
!= NULL
&& (parameter_ptr
->constraint_ptr
->flags
& JACK_CONSTRAINT_FLAG_FAKE_VALUE
) != 0;
1102 EXPORT jackctl_param_type_t
jackctl_parameter_get_type(jackctl_parameter
*parameter_ptr
)
1104 return parameter_ptr
->type
;
1107 EXPORT
char jackctl_parameter_get_id(jackctl_parameter_t
* parameter_ptr
)
1109 return parameter_ptr
->id
;
1112 EXPORT
bool jackctl_parameter_is_set(jackctl_parameter
*parameter_ptr
)
1114 return parameter_ptr
->is_set
;
1117 EXPORT
union jackctl_parameter_value
jackctl_parameter_get_value(jackctl_parameter
*parameter_ptr
)
1119 return *parameter_ptr
->value_ptr
;
1122 EXPORT
bool jackctl_parameter_reset(jackctl_parameter
*parameter_ptr
)
1124 if (!parameter_ptr
->is_set
)
1129 parameter_ptr
->is_set
= false;
1131 *parameter_ptr
->value_ptr
= *parameter_ptr
->default_value_ptr
;
1136 EXPORT
bool jackctl_parameter_set_value(jackctl_parameter
*parameter_ptr
, const union jackctl_parameter_value
* value_ptr
)
1138 bool new_driver_parameter
;
1140 /* for driver parameters, set the parameter by adding jack_driver_param_t in the set_parameters list */
1141 if (parameter_ptr
->driver_ptr
!= NULL
)
1143 /* jack_info("setting driver parameter %p ...", parameter_ptr); */
1144 new_driver_parameter
= parameter_ptr
->driver_parameter_ptr
== NULL
;
1145 if (new_driver_parameter
)
1147 /* jack_info("new driver parameter..."); */
1148 parameter_ptr
->driver_parameter_ptr
= (jack_driver_param_t
*)malloc(sizeof(jack_driver_param_t
));
1149 if (parameter_ptr
->driver_parameter_ptr
== NULL
)
1151 jack_error ("Allocation of jack_driver_param_t structure failed");
1155 parameter_ptr
->driver_parameter_ptr
->character
= parameter_ptr
->id
;
1156 parameter_ptr
->driver_ptr
->set_parameters
= jack_slist_append(parameter_ptr
->driver_ptr
->set_parameters
, parameter_ptr
->driver_parameter_ptr
);
1159 switch (parameter_ptr
->type
)
1162 parameter_ptr
->driver_parameter_ptr
->value
.i
= value_ptr
->i
;
1165 parameter_ptr
->driver_parameter_ptr
->value
.ui
= value_ptr
->ui
;
1168 parameter_ptr
->driver_parameter_ptr
->value
.c
= value_ptr
->c
;
1170 case JackParamString
:
1171 strcpy(parameter_ptr
->driver_parameter_ptr
->value
.str
, value_ptr
->str
);
1174 parameter_ptr
->driver_parameter_ptr
->value
.i
= value_ptr
->b
;
1177 jack_error("unknown parameter type %i", (int)parameter_ptr
->type
);
1180 if (new_driver_parameter
)
1182 parameter_ptr
->driver_ptr
->set_parameters
= jack_slist_remove(parameter_ptr
->driver_ptr
->set_parameters
, parameter_ptr
->driver_parameter_ptr
);
1189 parameter_ptr
->is_set
= true;
1190 *parameter_ptr
->value_ptr
= *value_ptr
;
1195 EXPORT
union jackctl_parameter_value
jackctl_parameter_get_default_value(jackctl_parameter
*parameter_ptr
)
1197 return *parameter_ptr
->default_value_ptr
;
1200 // Internals clients
1202 EXPORT
const JSList
* jackctl_server_get_internals_list(jackctl_server
*server_ptr
)
1204 return server_ptr
->internals
;
1207 EXPORT
const char * jackctl_internal_get_name(jackctl_internal
*internal_ptr
)
1209 return internal_ptr
->desc_ptr
->name
;
1212 EXPORT
const JSList
* jackctl_internal_get_parameters(jackctl_internal
*internal_ptr
)
1214 return internal_ptr
->parameters
;
1217 EXPORT
bool jackctl_server_load_internal(
1218 jackctl_server
* server_ptr
,
1219 jackctl_internal
* internal
)
1222 if (server_ptr
->engine
!= NULL
) {
1223 server_ptr
->engine
->InternalClientLoad(internal
->desc_ptr
->name
, internal
->desc_ptr
->name
, internal
->set_parameters
, JackNullOption
, &internal
->refnum
, &status
);
1224 return (internal
->refnum
> 0);
1230 EXPORT
bool jackctl_server_unload_internal(
1231 jackctl_server
* server_ptr
,
1232 jackctl_internal
* internal
)
1235 if (server_ptr
->engine
!= NULL
&& internal
->refnum
> 0) {
1236 return ((server_ptr
->engine
->GetEngine()->InternalClientUnload(internal
->refnum
, &status
)) == 0);
1242 EXPORT
bool jackctl_server_add_slave(jackctl_server
* server_ptr
, jackctl_driver
* driver_ptr
)
1244 if (server_ptr
->engine
!= NULL
) {
1245 driver_ptr
->info
= server_ptr
->engine
->AddSlave(driver_ptr
->desc_ptr
, driver_ptr
->set_parameters
);
1246 return (driver_ptr
->info
!= 0);
1252 EXPORT
bool jackctl_server_remove_slave(jackctl_server
* server_ptr
, jackctl_driver
* driver_ptr
)
1254 if (server_ptr
->engine
!= NULL
) {
1255 server_ptr
->engine
->RemoveSlave(driver_ptr
->info
);
1256 delete driver_ptr
->info
;
1263 EXPORT
bool jackctl_server_switch_master(jackctl_server
* server_ptr
, jackctl_driver
* driver_ptr
)
1265 if (server_ptr
->engine
!= NULL
) {
1266 return (server_ptr
->engine
->SwitchMaster(driver_ptr
->desc_ptr
, driver_ptr
->set_parameters
) == 0);