00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef WIN32
00024 #include <stdbool.h>
00025 #include <stdint.h>
00026 #include <dirent.h>
00027 #include <pthread.h>
00028 #endif
00029
00030 #include "types.h"
00031 #include <string.h>
00032 #include <errno.h>
00033 #include <stdio.h>
00034 #include <assert.h>
00035 #include <signal.h>
00036
00037 #include "jslist.h"
00038 #include "driver_interface.h"
00039 #include "JackError.h"
00040 #include "JackServer.h"
00041 #include "shm.h"
00042 #include "JackTools.h"
00043 #include "JackControlAPI.h"
00044 #include "JackLockedEngine.h"
00045
00046 using namespace Jack;
00047
00048 struct jackctl_server
00049 {
00050 JSList * drivers;
00051 JSList * internals;
00052 JSList * parameters;
00053
00054 class JackServer * engine;
00055
00056
00057 union jackctl_parameter_value name;
00058 union jackctl_parameter_value default_name;
00059
00060
00061 union jackctl_parameter_value realtime;
00062 union jackctl_parameter_value default_realtime;
00063
00064
00065 union jackctl_parameter_value realtime_priority;
00066 union jackctl_parameter_value default_realtime_priority;
00067
00068
00069 union jackctl_parameter_value temporary;
00070 union jackctl_parameter_value default_temporary;
00071
00072
00073 union jackctl_parameter_value verbose;
00074 union jackctl_parameter_value default_verbose;
00075
00076
00077 union jackctl_parameter_value client_timeout;
00078 union jackctl_parameter_value default_client_timeout;
00079
00080
00081 union jackctl_parameter_value loopback_ports;
00082 union jackctl_parameter_value default_loopback_ports;
00083
00084
00085 union jackctl_parameter_value replace_registry;
00086 union jackctl_parameter_value default_replace_registry;
00087
00088
00089 union jackctl_parameter_value sync;
00090 union jackctl_parameter_value default_sync;
00091 };
00092
00093 struct jackctl_driver
00094 {
00095 jack_driver_desc_t * desc_ptr;
00096 JSList * parameters;
00097 JSList * set_parameters;
00098 };
00099
00100 struct jackctl_internal
00101 {
00102 jack_driver_desc_t * desc_ptr;
00103 JSList * parameters;
00104 JSList * set_parameters;
00105 int refnum;
00106 };
00107
00108 struct jackctl_parameter
00109 {
00110 const char * name;
00111 const char * short_description;
00112 const char * long_description;
00113 jackctl_param_type_t type;
00114 bool is_set;
00115 union jackctl_parameter_value * value_ptr;
00116 union jackctl_parameter_value * default_value_ptr;
00117
00118 union jackctl_parameter_value value;
00119 union jackctl_parameter_value default_value;
00120 struct jackctl_driver * driver_ptr;
00121 char id;
00122 jack_driver_param_t * driver_parameter_ptr;
00123 jack_driver_param_constraint_desc_t * constraint_ptr;
00124 };
00125
00126 static
00127 struct jackctl_parameter *
00128 jackctl_add_parameter(
00129 JSList ** parameters_list_ptr_ptr,
00130 const char * name,
00131 const char * short_description,
00132 const char * long_description,
00133 jackctl_param_type_t type,
00134 union jackctl_parameter_value * value_ptr,
00135 union jackctl_parameter_value * default_value_ptr,
00136 union jackctl_parameter_value value,
00137 jack_driver_param_constraint_desc_t * constraint_ptr = NULL)
00138 {
00139 struct jackctl_parameter * parameter_ptr;
00140
00141 parameter_ptr = (struct jackctl_parameter *)malloc(sizeof(struct jackctl_parameter));
00142 if (parameter_ptr == NULL)
00143 {
00144 jack_error("Cannot allocate memory for jackctl_parameter structure.");
00145 goto fail;
00146 }
00147
00148 parameter_ptr->name = name;
00149 parameter_ptr->short_description = short_description;
00150 parameter_ptr->long_description = long_description;
00151 parameter_ptr->type = type;
00152 parameter_ptr->is_set = false;
00153
00154 if (value_ptr == NULL)
00155 {
00156 value_ptr = ¶meter_ptr->value;
00157 }
00158
00159 if (default_value_ptr == NULL)
00160 {
00161 default_value_ptr = ¶meter_ptr->default_value;
00162 }
00163
00164 parameter_ptr->value_ptr = value_ptr;
00165 parameter_ptr->default_value_ptr = default_value_ptr;
00166
00167 *value_ptr = *default_value_ptr = value;
00168
00169 parameter_ptr->driver_ptr = NULL;
00170 parameter_ptr->driver_parameter_ptr = NULL;
00171 parameter_ptr->id = 0;
00172 parameter_ptr->constraint_ptr = constraint_ptr;
00173
00174 *parameters_list_ptr_ptr = jack_slist_append(*parameters_list_ptr_ptr, parameter_ptr);
00175
00176 return parameter_ptr;
00177
00178 fail:
00179 return NULL;
00180 }
00181
00182 static
00183 void
00184 jackctl_free_driver_parameters(
00185 struct jackctl_driver * driver_ptr)
00186 {
00187 JSList * next_node_ptr;
00188
00189 while (driver_ptr->parameters)
00190 {
00191 next_node_ptr = driver_ptr->parameters->next;
00192 free(driver_ptr->parameters->data);
00193 free(driver_ptr->parameters);
00194 driver_ptr->parameters = next_node_ptr;
00195 }
00196
00197 while (driver_ptr->set_parameters)
00198 {
00199 next_node_ptr = driver_ptr->set_parameters->next;
00200 free(driver_ptr->set_parameters->data);
00201 free(driver_ptr->set_parameters);
00202 driver_ptr->set_parameters = next_node_ptr;
00203 }
00204 }
00205
00206 static
00207 bool
00208 jackctl_add_driver_parameters(
00209 struct jackctl_driver * driver_ptr)
00210 {
00211 uint32_t i;
00212 union jackctl_parameter_value jackctl_value;
00213 jackctl_param_type_t jackctl_type;
00214 struct jackctl_parameter * parameter_ptr;
00215 jack_driver_param_desc_t * descriptor_ptr;
00216
00217 for (i = 0 ; i < driver_ptr->desc_ptr->nparams ; i++)
00218 {
00219 descriptor_ptr = driver_ptr->desc_ptr->params + i;
00220
00221 switch (descriptor_ptr->type)
00222 {
00223 case JackDriverParamInt:
00224 jackctl_type = JackParamInt;
00225 jackctl_value.i = descriptor_ptr->value.i;
00226 break;
00227 case JackDriverParamUInt:
00228 jackctl_type = JackParamUInt;
00229 jackctl_value.ui = descriptor_ptr->value.ui;
00230 break;
00231 case JackDriverParamChar:
00232 jackctl_type = JackParamChar;
00233 jackctl_value.c = descriptor_ptr->value.c;
00234 break;
00235 case JackDriverParamString:
00236 jackctl_type = JackParamString;
00237 strcpy(jackctl_value.str, descriptor_ptr->value.str);
00238 break;
00239 case JackDriverParamBool:
00240 jackctl_type = JackParamBool;
00241 jackctl_value.b = descriptor_ptr->value.i;
00242 break;
00243 default:
00244 jack_error("unknown driver parameter type %i", (int)descriptor_ptr->type);
00245 assert(0);
00246 goto fail;
00247 }
00248
00249 parameter_ptr = jackctl_add_parameter(
00250 &driver_ptr->parameters,
00251 descriptor_ptr->name,
00252 descriptor_ptr->short_desc,
00253 descriptor_ptr->long_desc,
00254 jackctl_type,
00255 NULL,
00256 NULL,
00257 jackctl_value,
00258 descriptor_ptr->constraint);
00259
00260 if (parameter_ptr == NULL)
00261 {
00262 goto fail;
00263 }
00264
00265 parameter_ptr->driver_ptr = driver_ptr;
00266 parameter_ptr->id = descriptor_ptr->character;
00267 }
00268
00269 return true;
00270
00271 fail:
00272 jackctl_free_driver_parameters(driver_ptr);
00273
00274 return false;
00275 }
00276
00277 static int
00278 jackctl_drivers_load(
00279 struct jackctl_server * server_ptr)
00280 {
00281 struct jackctl_driver * driver_ptr;
00282 JSList *node_ptr;
00283 JSList *descriptor_node_ptr;
00284
00285 descriptor_node_ptr = jack_drivers_load(NULL);
00286 if (descriptor_node_ptr == NULL)
00287 {
00288 jack_error("could not find any drivers in driver directory!");
00289 return false;
00290 }
00291
00292 while (descriptor_node_ptr != NULL)
00293 {
00294 driver_ptr = (struct jackctl_driver *)malloc(sizeof(struct jackctl_driver));
00295 if (driver_ptr == NULL)
00296 {
00297 jack_error("memory allocation of jackctl_driver structure failed.");
00298 goto next;
00299 }
00300
00301 driver_ptr->desc_ptr = (jack_driver_desc_t *)descriptor_node_ptr->data;
00302 driver_ptr->parameters = NULL;
00303 driver_ptr->set_parameters = NULL;
00304
00305 if (!jackctl_add_driver_parameters(driver_ptr))
00306 {
00307 assert(driver_ptr->parameters == NULL);
00308 free(driver_ptr);
00309 goto next;
00310 }
00311
00312 server_ptr->drivers = jack_slist_append(server_ptr->drivers, driver_ptr);
00313
00314 next:
00315 node_ptr = descriptor_node_ptr;
00316 descriptor_node_ptr = descriptor_node_ptr->next;
00317 free(node_ptr);
00318 }
00319
00320 return true;
00321 }
00322
00323 static
00324 void
00325 jackctl_server_free_drivers(
00326 struct jackctl_server * server_ptr)
00327 {
00328 JSList * next_node_ptr;
00329 struct jackctl_driver * driver_ptr;
00330
00331 while (server_ptr->drivers)
00332 {
00333 next_node_ptr = server_ptr->drivers->next;
00334 driver_ptr = (struct jackctl_driver *)server_ptr->drivers->data;
00335
00336 jackctl_free_driver_parameters(driver_ptr);
00337 free(driver_ptr->desc_ptr->params);
00338 free(driver_ptr->desc_ptr);
00339 free(driver_ptr);
00340
00341 free(server_ptr->drivers);
00342 server_ptr->drivers = next_node_ptr;
00343 }
00344 }
00345
00346 static int
00347 jackctl_internals_load(
00348 struct jackctl_server * server_ptr)
00349 {
00350 struct jackctl_internal * internal_ptr;
00351 JSList *node_ptr;
00352 JSList *descriptor_node_ptr;
00353
00354 descriptor_node_ptr = jack_internals_load(NULL);
00355 if (descriptor_node_ptr == NULL)
00356 {
00357 jack_error("could not find any internals in driver directory!");
00358 return false;
00359 }
00360
00361 while (descriptor_node_ptr != NULL)
00362 {
00363 internal_ptr = (struct jackctl_internal *)malloc(sizeof(struct jackctl_internal));
00364 if (internal_ptr == NULL)
00365 {
00366 jack_error("memory allocation of jackctl_driver structure failed.");
00367 goto next;
00368 }
00369
00370 internal_ptr->desc_ptr = (jack_driver_desc_t *)descriptor_node_ptr->data;
00371 internal_ptr->parameters = NULL;
00372 internal_ptr->set_parameters = NULL;
00373
00374 if (!jackctl_add_driver_parameters((struct jackctl_driver *)internal_ptr))
00375 {
00376 assert(internal_ptr->parameters == NULL);
00377 free(internal_ptr);
00378 goto next;
00379 }
00380
00381 server_ptr->internals = jack_slist_append(server_ptr->internals, internal_ptr);
00382
00383 next:
00384 node_ptr = descriptor_node_ptr;
00385 descriptor_node_ptr = descriptor_node_ptr->next;
00386 free(node_ptr);
00387 }
00388
00389 return true;
00390 }
00391
00392 static
00393 void
00394 jackctl_server_free_internals(
00395 struct jackctl_server * server_ptr)
00396 {
00397 JSList * next_node_ptr;
00398 struct jackctl_internal * internal_ptr;
00399
00400 while (server_ptr->internals)
00401 {
00402 next_node_ptr = server_ptr->internals->next;
00403 internal_ptr = (struct jackctl_internal *)server_ptr->internals->data;
00404
00405 jackctl_free_driver_parameters((struct jackctl_driver *)internal_ptr);
00406 free(internal_ptr->desc_ptr->params);
00407 free(internal_ptr->desc_ptr);
00408 free(internal_ptr);
00409
00410 free(server_ptr->internals);
00411 server_ptr->internals = next_node_ptr;
00412 }
00413 }
00414
00415 static
00416 void
00417 jackctl_server_free_parameters(
00418 struct jackctl_server * server_ptr)
00419 {
00420 JSList * next_node_ptr;
00421
00422 while (server_ptr->parameters)
00423 {
00424 next_node_ptr = server_ptr->parameters->next;
00425 free(server_ptr->parameters->data);
00426 free(server_ptr->parameters);
00427 server_ptr->parameters = next_node_ptr;
00428 }
00429 }
00430
00431 #ifdef WIN32
00432
00433 static HANDLE waitEvent;
00434
00435 static void do_nothing_handler(int signum)
00436 {
00437 printf("jack main caught signal %d\n", signum);
00438 (void) signal(SIGINT, SIG_DFL);
00439 SetEvent(waitEvent);
00440 }
00441
00442 sigset_t
00443 jackctl_setup_signals(
00444 unsigned int flags)
00445 {
00446 if ((waitEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL) {
00447 jack_error("CreateEvent fails err = %ld", GetLastError());
00448 return 0;
00449 }
00450
00451 (void) signal(SIGINT, do_nothing_handler);
00452 (void) signal(SIGABRT, do_nothing_handler);
00453 (void) signal(SIGTERM, do_nothing_handler);
00454
00455 return (sigset_t)waitEvent;
00456 }
00457
00458 void jackctl_wait_signals(sigset_t signals)
00459 {
00460 if (WaitForSingleObject(waitEvent, INFINITE) != WAIT_OBJECT_0) {
00461 jack_error("WaitForSingleObject fails err = %ld", GetLastError());
00462 }
00463 }
00464
00465 #else
00466
00467 static
00468 void
00469 do_nothing_handler(int sig)
00470 {
00471
00472
00473
00474
00475 char buf[64];
00476 snprintf (buf, sizeof(buf), "received signal %d during shutdown (ignored)\n", sig);
00477 }
00478
00479 EXPORT sigset_t
00480 jackctl_setup_signals(
00481 unsigned int flags)
00482 {
00483 sigset_t signals;
00484 sigset_t allsignals;
00485 struct sigaction action;
00486 int i;
00487
00488
00489
00490
00491
00492 setsid();
00493
00494 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522 sigemptyset(&signals);
00523 sigaddset(&signals, SIGHUP);
00524 sigaddset(&signals, SIGINT);
00525 sigaddset(&signals, SIGQUIT);
00526 sigaddset(&signals, SIGPIPE);
00527 sigaddset(&signals, SIGTERM);
00528 sigaddset(&signals, SIGUSR1);
00529 sigaddset(&signals, SIGUSR2);
00530
00531
00532
00533
00534
00535 pthread_sigmask(SIG_BLOCK, &signals, 0);
00536
00537
00538
00539
00540
00541 sigfillset(&allsignals);
00542 action.sa_handler = do_nothing_handler;
00543 action.sa_mask = allsignals;
00544 action.sa_flags = SA_RESTART|SA_RESETHAND;
00545
00546 for (i = 1; i < NSIG; i++)
00547 {
00548 if (sigismember (&signals, i))
00549 {
00550 sigaction(i, &action, 0);
00551 }
00552 }
00553
00554 return signals;
00555 }
00556
00557 EXPORT void
00558 jackctl_wait_signals(sigset_t signals)
00559 {
00560 int sig;
00561 bool waiting = true;
00562
00563 while (waiting) {
00564 sigwait(&signals, &sig);
00565 fprintf(stderr, "jack main caught signal %d\n", sig);
00566
00567 switch (sig) {
00568 case SIGUSR1:
00569
00570 break;
00571 case SIGUSR2:
00572
00573 waiting = false;
00574 break;
00575 case SIGTTOU:
00576 break;
00577 default:
00578 waiting = false;
00579 break;
00580 }
00581 }
00582
00583 if (sig != SIGSEGV) {
00584
00585
00586
00587 sigprocmask(SIG_UNBLOCK, &signals, 0);
00588 }
00589 }
00590 #endif
00591
00592 static
00593 jack_driver_param_constraint_desc_t *
00594 get_realtime_priority_constraint()
00595 {
00596 jack_driver_param_constraint_desc_t * constraint_ptr;
00597 int min, max;
00598
00599 if (!jack_get_thread_realtime_priority_range(&min, &max))
00600 {
00601 return NULL;
00602 }
00603
00604
00605
00606 constraint_ptr = (jack_driver_param_constraint_desc_t *)calloc(1, sizeof(jack_driver_param_value_enum_t));
00607 constraint_ptr->flags = JACK_CONSTRAINT_FLAG_RANGE;
00608
00609 constraint_ptr->constraint.range.min.i = min;
00610 constraint_ptr->constraint.range.max.i = max;
00611
00612 return constraint_ptr;
00613 }
00614
00615 EXPORT jackctl_server_t * jackctl_server_create()
00616 {
00617 struct jackctl_server * server_ptr;
00618 union jackctl_parameter_value value;
00619
00620 server_ptr = (struct jackctl_server *)malloc(sizeof(struct jackctl_server));
00621 if (server_ptr == NULL)
00622 {
00623 jack_error("Cannot allocate memory for jackctl_server structure.");
00624 goto fail;
00625 }
00626
00627 server_ptr->drivers = NULL;
00628 server_ptr->internals = NULL;
00629 server_ptr->parameters = NULL;
00630 server_ptr->engine = NULL;
00631
00632 strcpy(value.str, JACK_DEFAULT_SERVER_NAME);
00633 if (jackctl_add_parameter(
00634 &server_ptr->parameters,
00635 "name",
00636 "server name to use",
00637 "",
00638 JackParamString,
00639 &server_ptr->name,
00640 &server_ptr->default_name,
00641 value) == NULL)
00642 {
00643 goto fail_free_parameters;
00644 }
00645
00646 value.b = false;
00647 if (jackctl_add_parameter(
00648 &server_ptr->parameters,
00649 "realtime",
00650 "Whether to use realtime mode",
00651 "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.",
00652 JackParamBool,
00653 &server_ptr->realtime,
00654 &server_ptr->default_realtime,
00655 value) == NULL)
00656 {
00657 goto fail_free_parameters;
00658 }
00659
00660 value.i = 10;
00661 if (jackctl_add_parameter(
00662 &server_ptr->parameters,
00663 "realtime-priority",
00664 "Scheduler priority when running in realtime mode.",
00665 "",
00666 JackParamInt,
00667 &server_ptr->realtime_priority,
00668 &server_ptr->default_realtime_priority,
00669 value,
00670 get_realtime_priority_constraint()) == NULL)
00671 {
00672 goto fail_free_parameters;
00673 }
00674
00675 value.b = false;
00676 if (jackctl_add_parameter(
00677 &server_ptr->parameters,
00678 "temporary",
00679 "Exit once all clients have closed their connections.",
00680 "",
00681 JackParamBool,
00682 &server_ptr->temporary,
00683 &server_ptr->default_temporary,
00684 value) == NULL)
00685 {
00686 goto fail_free_parameters;
00687 }
00688
00689 value.b = false;
00690 if (jackctl_add_parameter(
00691 &server_ptr->parameters,
00692 "verbose",
00693 "Verbose mode.",
00694 "",
00695 JackParamBool,
00696 &server_ptr->verbose,
00697 &server_ptr->default_verbose,
00698 value) == NULL)
00699 {
00700 goto fail_free_parameters;
00701 }
00702
00703 value.i = 0;
00704 if (jackctl_add_parameter(
00705 &server_ptr->parameters,
00706 "client-timeout",
00707 "Client timeout limit in milliseconds",
00708 "",
00709 JackParamInt,
00710 &server_ptr->client_timeout,
00711 &server_ptr->default_client_timeout,
00712 value) == NULL)
00713 {
00714 goto fail_free_parameters;
00715 }
00716
00717 value.ui = 0;
00718 if (jackctl_add_parameter(
00719 &server_ptr->parameters,
00720 "loopback-ports",
00721 "Number of loopback ports",
00722 "",
00723 JackParamUInt,
00724 &server_ptr->loopback_ports,
00725 &server_ptr->default_loopback_ports,
00726 value) == NULL)
00727 {
00728 goto fail_free_parameters;
00729 }
00730
00731 value.b = false;
00732 if (jackctl_add_parameter(
00733 &server_ptr->parameters,
00734 "replace-registry",
00735 "Replace registry",
00736 "",
00737 JackParamBool,
00738 &server_ptr->replace_registry,
00739 &server_ptr->default_replace_registry,
00740 value) == NULL)
00741 {
00742 goto fail_free_parameters;
00743 }
00744
00745 value.b = false;
00746 if (jackctl_add_parameter(
00747 &server_ptr->parameters,
00748 "sync",
00749 "Use synchronous mode",
00750 "",
00751 JackParamBool,
00752 &server_ptr->sync,
00753 &server_ptr->default_sync,
00754 value) == NULL)
00755 {
00756 goto fail_free_parameters;
00757 }
00758
00759 if (!jackctl_drivers_load(server_ptr))
00760 {
00761 goto fail_free_parameters;
00762 }
00763
00764
00765 jackctl_internals_load(server_ptr);
00766
00767 return server_ptr;
00768
00769 fail_free_parameters:
00770 jackctl_server_free_parameters(server_ptr);
00771
00772 free(server_ptr);
00773
00774 fail:
00775 return NULL;
00776 }
00777
00778 EXPORT void jackctl_server_destroy(jackctl_server *server_ptr)
00779 {
00780 jackctl_server_free_drivers(server_ptr);
00781 jackctl_server_free_internals(server_ptr);
00782 jackctl_server_free_parameters(server_ptr);
00783 free(server_ptr);
00784 }
00785
00786 EXPORT const JSList * jackctl_server_get_drivers_list(jackctl_server *server_ptr)
00787 {
00788 return server_ptr->drivers;
00789 }
00790
00791 EXPORT bool jackctl_server_stop(jackctl_server *server_ptr)
00792 {
00793 server_ptr->engine->Stop();
00794 server_ptr->engine->Close();
00795 delete server_ptr->engine;
00796
00797
00798 jack_log("cleaning up shared memory");
00799
00800 jack_cleanup_shm();
00801
00802 jack_log("cleaning up files");
00803
00804 JackTools::CleanupFiles(server_ptr->name.str);
00805
00806 jack_log("unregistering server `%s'", server_ptr->name.str);
00807
00808 jack_unregister_server(server_ptr->name.str);
00809
00810 server_ptr->engine = NULL;
00811
00812 return true;
00813 }
00814
00815 EXPORT const JSList * jackctl_server_get_parameters(jackctl_server *server_ptr)
00816 {
00817 return server_ptr->parameters;
00818 }
00819
00820 EXPORT bool
00821 jackctl_server_start(
00822 jackctl_server *server_ptr,
00823 jackctl_driver *driver_ptr)
00824 {
00825 int rc;
00826
00827 rc = jack_register_server(server_ptr->name.str, server_ptr->replace_registry.b);
00828 switch (rc)
00829 {
00830 case EEXIST:
00831 jack_error("`%s' server already active", server_ptr->name.str);
00832 goto fail;
00833 case ENOSPC:
00834 jack_error("too many servers already active");
00835 goto fail;
00836 case ENOMEM:
00837 jack_error("no access to shm registry");
00838 goto fail;
00839 }
00840
00841 jack_log("server `%s' registered", server_ptr->name.str);
00842
00843
00844
00845 jack_cleanup_shm();
00846 JackTools::CleanupFiles(server_ptr->name.str);
00847
00848 if (!server_ptr->realtime.b && server_ptr->client_timeout.i == 0)
00849 server_ptr->client_timeout.i = 500;
00850
00851
00852
00853 server_ptr->engine = new JackServer(
00854 server_ptr->sync.b,
00855 server_ptr->temporary.b,
00856 server_ptr->client_timeout.i,
00857 server_ptr->realtime.b,
00858 server_ptr->realtime_priority.i,
00859 server_ptr->loopback_ports.ui,
00860 server_ptr->verbose.b,
00861 server_ptr->name.str);
00862 if (server_ptr->engine == NULL)
00863 {
00864 jack_error("Failed to create new JackServer object");
00865 goto fail_unregister;
00866 }
00867
00868 rc = server_ptr->engine->Open(driver_ptr->desc_ptr, driver_ptr->set_parameters);
00869 if (rc < 0)
00870 {
00871 jack_error("JackServer::Open() failed with %d", rc);
00872 goto fail_delete;
00873 }
00874
00875 rc = server_ptr->engine->Start();
00876 if (rc < 0)
00877 {
00878 jack_error("JackServer::Start() failed with %d", rc);
00879 goto fail_close;
00880 }
00881
00882 return true;
00883
00884 fail_close:
00885 server_ptr->engine->Close();
00886
00887 fail_delete:
00888 delete server_ptr->engine;
00889 server_ptr->engine = NULL;
00890
00891 fail_unregister:
00892 jack_log("cleaning up shared memory");
00893
00894 jack_cleanup_shm();
00895
00896 jack_log("cleaning up files");
00897
00898 JackTools::CleanupFiles(server_ptr->name.str);
00899
00900 jack_log("unregistering server `%s'", server_ptr->name.str);
00901
00902 jack_unregister_server(server_ptr->name.str);
00903
00904 fail:
00905 return false;
00906 }
00907
00908 EXPORT const char * jackctl_driver_get_name(jackctl_driver *driver_ptr)
00909 {
00910 return driver_ptr->desc_ptr->name;
00911 }
00912
00913 EXPORT const JSList * jackctl_driver_get_parameters(jackctl_driver *driver_ptr)
00914 {
00915 return driver_ptr->parameters;
00916 }
00917
00918 EXPORT jack_driver_desc_t * jackctl_driver_get_desc(jackctl_driver *driver_ptr)
00919 {
00920 return driver_ptr->desc_ptr;
00921 }
00922
00923 EXPORT const char * jackctl_parameter_get_name(jackctl_parameter *parameter_ptr)
00924 {
00925 return parameter_ptr->name;
00926 }
00927
00928 EXPORT const char * jackctl_parameter_get_short_description(jackctl_parameter *parameter_ptr)
00929 {
00930 return parameter_ptr->short_description;
00931 }
00932
00933 EXPORT const char * jackctl_parameter_get_long_description(jackctl_parameter *parameter_ptr)
00934 {
00935 return parameter_ptr->long_description;
00936 }
00937
00938 EXPORT bool jackctl_parameter_has_range_constraint(jackctl_parameter *parameter_ptr)
00939 {
00940 return parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_RANGE) != 0;
00941 }
00942
00943 EXPORT bool jackctl_parameter_has_enum_constraint(jackctl_parameter *parameter_ptr)
00944 {
00945 return parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_RANGE) == 0;
00946 }
00947
00948 EXPORT uint32_t jackctl_parameter_get_enum_constraints_count(jackctl_parameter *parameter_ptr)
00949 {
00950 if (!jackctl_parameter_has_enum_constraint(parameter_ptr))
00951 {
00952 return 0;
00953 }
00954
00955 return parameter_ptr->constraint_ptr->constraint.enumeration.count;
00956 }
00957
00958 EXPORT union jackctl_parameter_value jackctl_parameter_get_enum_constraint_value(jackctl_parameter *parameter_ptr, uint32_t index)
00959 {
00960 jack_driver_param_value_t * value_ptr;
00961 union jackctl_parameter_value jackctl_value;
00962
00963 value_ptr = ¶meter_ptr->constraint_ptr->constraint.enumeration.possible_values_array[index].value;
00964
00965 switch (parameter_ptr->type)
00966 {
00967 case JackParamInt:
00968 jackctl_value.i = value_ptr->i;
00969 break;
00970 case JackParamUInt:
00971 jackctl_value.ui = value_ptr->ui;
00972 break;
00973 case JackParamChar:
00974 jackctl_value.c = value_ptr->c;
00975 break;
00976 case JackParamString:
00977 strcpy(jackctl_value.str, value_ptr->str);
00978 break;
00979 default:
00980 jack_error("bad driver parameter type %i (enum constraint)", (int)parameter_ptr->type);
00981 assert(0);
00982 }
00983
00984 return jackctl_value;
00985 }
00986
00987 EXPORT const char * jackctl_parameter_get_enum_constraint_description(jackctl_parameter *parameter_ptr, uint32_t index)
00988 {
00989 return parameter_ptr->constraint_ptr->constraint.enumeration.possible_values_array[index].short_desc;
00990 }
00991
00992 EXPORT void jackctl_parameter_get_range_constraint(jackctl_parameter *parameter_ptr, union jackctl_parameter_value * min_ptr, union jackctl_parameter_value * max_ptr)
00993 {
00994 switch (parameter_ptr->type)
00995 {
00996 case JackParamInt:
00997 min_ptr->i = parameter_ptr->constraint_ptr->constraint.range.min.i;
00998 max_ptr->i = parameter_ptr->constraint_ptr->constraint.range.max.i;
00999 return;
01000 case JackParamUInt:
01001 min_ptr->ui = parameter_ptr->constraint_ptr->constraint.range.min.ui;
01002 max_ptr->ui = parameter_ptr->constraint_ptr->constraint.range.max.ui;
01003 return;
01004 default:
01005 jack_error("bad driver parameter type %i (range constraint)", (int)parameter_ptr->type);
01006 assert(0);
01007 }
01008 }
01009
01010 EXPORT bool jackctl_parameter_constraint_is_strict(jackctl_parameter_t * parameter_ptr)
01011 {
01012 return parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_STRICT) != 0;
01013 }
01014
01015 EXPORT bool jackctl_parameter_constraint_is_fake_value(jackctl_parameter_t * parameter_ptr)
01016 {
01017 return parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_FAKE_VALUE) != 0;
01018 }
01019
01020 EXPORT jackctl_param_type_t jackctl_parameter_get_type(jackctl_parameter *parameter_ptr)
01021 {
01022 return parameter_ptr->type;
01023 }
01024
01025 EXPORT char jackctl_parameter_get_id(jackctl_parameter_t * parameter_ptr)
01026 {
01027 return parameter_ptr->id;
01028 }
01029
01030 EXPORT bool jackctl_parameter_is_set(jackctl_parameter *parameter_ptr)
01031 {
01032 return parameter_ptr->is_set;
01033 }
01034
01035 EXPORT union jackctl_parameter_value jackctl_parameter_get_value(jackctl_parameter *parameter_ptr)
01036 {
01037 return *parameter_ptr->value_ptr;
01038 }
01039
01040 EXPORT bool jackctl_parameter_reset(jackctl_parameter *parameter_ptr)
01041 {
01042 if (!parameter_ptr->is_set)
01043 {
01044 return true;
01045 }
01046
01047 parameter_ptr->is_set = false;
01048
01049 *parameter_ptr->value_ptr = *parameter_ptr->default_value_ptr;
01050
01051 return true;
01052 }
01053
01054 EXPORT bool jackctl_parameter_set_value(jackctl_parameter *parameter_ptr, const union jackctl_parameter_value * value_ptr)
01055 {
01056 bool new_driver_parameter;
01057
01058
01059 if (parameter_ptr->driver_ptr != NULL)
01060 {
01061
01062 new_driver_parameter = parameter_ptr->driver_parameter_ptr == NULL;
01063 if (new_driver_parameter)
01064 {
01065
01066 parameter_ptr->driver_parameter_ptr = (jack_driver_param_t *)malloc(sizeof(jack_driver_param_t));
01067 if (parameter_ptr->driver_parameter_ptr == NULL)
01068 {
01069 jack_error ("Allocation of jack_driver_param_t structure failed");
01070 return false;
01071 }
01072
01073 parameter_ptr->driver_parameter_ptr->character = parameter_ptr->id;
01074 parameter_ptr->driver_ptr->set_parameters = jack_slist_append(parameter_ptr->driver_ptr->set_parameters, parameter_ptr->driver_parameter_ptr);
01075 }
01076
01077 switch (parameter_ptr->type)
01078 {
01079 case JackParamInt:
01080 parameter_ptr->driver_parameter_ptr->value.i = value_ptr->i;
01081 break;
01082 case JackParamUInt:
01083 parameter_ptr->driver_parameter_ptr->value.ui = value_ptr->ui;
01084 break;
01085 case JackParamChar:
01086 parameter_ptr->driver_parameter_ptr->value.c = value_ptr->c;
01087 break;
01088 case JackParamString:
01089 strcpy(parameter_ptr->driver_parameter_ptr->value.str, value_ptr->str);
01090 break;
01091 case JackParamBool:
01092 parameter_ptr->driver_parameter_ptr->value.i = value_ptr->b;
01093 break;
01094 default:
01095 jack_error("unknown parameter type %i", (int)parameter_ptr->type);
01096 assert(0);
01097
01098 if (new_driver_parameter)
01099 {
01100 parameter_ptr->driver_ptr->set_parameters = jack_slist_remove(parameter_ptr->driver_ptr->set_parameters, parameter_ptr->driver_parameter_ptr);
01101 }
01102
01103 return false;
01104 }
01105 }
01106
01107 parameter_ptr->is_set = true;
01108 *parameter_ptr->value_ptr = *value_ptr;
01109
01110 return true;
01111 }
01112
01113 EXPORT union jackctl_parameter_value jackctl_parameter_get_default_value(jackctl_parameter *parameter_ptr)
01114 {
01115 return *parameter_ptr->default_value_ptr;
01116 }
01117
01118
01119
01120 EXPORT const JSList * jackctl_server_get_internals_list(jackctl_server *server_ptr)
01121 {
01122 return server_ptr->internals;
01123 }
01124
01125 EXPORT const char * jackctl_internal_get_name(jackctl_internal *internal_ptr)
01126 {
01127 return internal_ptr->desc_ptr->name;
01128 }
01129
01130 EXPORT const JSList * jackctl_internal_get_parameters(jackctl_internal *internal_ptr)
01131 {
01132 return internal_ptr->parameters;
01133 }
01134
01135 EXPORT bool jackctl_server_load_internal(
01136 jackctl_server * server_ptr,
01137 jackctl_internal * internal)
01138 {
01139 int status;
01140 if (server_ptr->engine != NULL) {
01141 server_ptr->engine->InternalClientLoad(internal->desc_ptr->name, internal->desc_ptr->name, internal->set_parameters, JackNullOption, &internal->refnum, &status);
01142 return (internal->refnum > 0);
01143 } else {
01144 return false;
01145 }
01146 }
01147
01148 EXPORT bool jackctl_server_unload_internal(
01149 jackctl_server * server_ptr,
01150 jackctl_internal * internal)
01151 {
01152 int status;
01153 if (server_ptr->engine != NULL && internal->refnum > 0) {
01154 return ((server_ptr->engine->GetEngine()->InternalClientUnload(internal->refnum, &status)) == 0);
01155 } else {
01156 return false;
01157 }
01158 }
01159
01160