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),
00477 "received signal %d during shutdown (ignored)\n", sig);
00478 write (1, buf, strlen (buf));
00479 }
00480
00481 EXPORT sigset_t
00482 jackctl_setup_signals(
00483 unsigned int flags)
00484 {
00485 sigset_t signals;
00486 sigset_t allsignals;
00487 struct sigaction action;
00488 int i;
00489
00490
00491
00492
00493
00494 setsid();
00495
00496 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
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
00523
00524 sigemptyset(&signals);
00525 sigaddset(&signals, SIGHUP);
00526 sigaddset(&signals, SIGINT);
00527 sigaddset(&signals, SIGQUIT);
00528 sigaddset(&signals, SIGPIPE);
00529 sigaddset(&signals, SIGTERM);
00530 sigaddset(&signals, SIGUSR1);
00531 sigaddset(&signals, SIGUSR2);
00532
00533
00534
00535
00536
00537 pthread_sigmask(SIG_BLOCK, &signals, 0);
00538
00539
00540
00541
00542
00543 sigfillset(&allsignals);
00544 action.sa_handler = do_nothing_handler;
00545 action.sa_mask = allsignals;
00546 action.sa_flags = SA_RESTART|SA_RESETHAND;
00547
00548 for (i = 1; i < NSIG; i++)
00549 {
00550 if (sigismember (&signals, i))
00551 {
00552 sigaction(i, &action, 0);
00553 }
00554 }
00555
00556 return signals;
00557 }
00558
00559 EXPORT void
00560 jackctl_wait_signals(sigset_t signals)
00561 {
00562 int sig;
00563 bool waiting = true;
00564
00565 while (waiting) {
00566 sigwait(&signals, &sig);
00567 fprintf(stderr, "jack main caught signal %d\n", sig);
00568
00569 switch (sig) {
00570 case SIGUSR1:
00571
00572 break;
00573 case SIGUSR2:
00574
00575 waiting = false;
00576 break;
00577 case SIGTTOU:
00578 break;
00579 default:
00580 waiting = false;
00581 break;
00582 }
00583 }
00584
00585 if (sig != SIGSEGV) {
00586
00587
00588
00589 sigprocmask(SIG_UNBLOCK, &signals, 0);
00590 }
00591 }
00592 #endif
00593
00594 static
00595 jack_driver_param_constraint_desc_t *
00596 get_realtime_priority_constraint()
00597 {
00598 jack_driver_param_constraint_desc_t * constraint_ptr;
00599 int min, max;
00600
00601 if (!jack_get_thread_realtime_priority_range(&min, &max))
00602 {
00603 return NULL;
00604 }
00605
00606
00607
00608 constraint_ptr = (jack_driver_param_constraint_desc_t *)calloc(1, sizeof(jack_driver_param_value_enum_t));
00609 constraint_ptr->flags = JACK_CONSTRAINT_FLAG_RANGE;
00610
00611 constraint_ptr->constraint.range.min.i = min;
00612 constraint_ptr->constraint.range.max.i = max;
00613
00614 return constraint_ptr;
00615 }
00616
00617 EXPORT jackctl_server_t * jackctl_server_create()
00618 {
00619 struct jackctl_server * server_ptr;
00620 union jackctl_parameter_value value;
00621
00622 server_ptr = (struct jackctl_server *)malloc(sizeof(struct jackctl_server));
00623 if (server_ptr == NULL)
00624 {
00625 jack_error("Cannot allocate memory for jackctl_server structure.");
00626 goto fail;
00627 }
00628
00629 server_ptr->drivers = NULL;
00630 server_ptr->internals = NULL;
00631 server_ptr->parameters = NULL;
00632 server_ptr->engine = NULL;
00633
00634 strcpy(value.str, JACK_DEFAULT_SERVER_NAME);
00635 if (jackctl_add_parameter(
00636 &server_ptr->parameters,
00637 "name",
00638 "server name to use",
00639 "",
00640 JackParamString,
00641 &server_ptr->name,
00642 &server_ptr->default_name,
00643 value) == NULL)
00644 {
00645 goto fail_free_parameters;
00646 }
00647
00648 value.b = false;
00649 if (jackctl_add_parameter(
00650 &server_ptr->parameters,
00651 "realtime",
00652 "Whether to use realtime mode",
00653 "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.",
00654 JackParamBool,
00655 &server_ptr->realtime,
00656 &server_ptr->default_realtime,
00657 value) == NULL)
00658 {
00659 goto fail_free_parameters;
00660 }
00661
00662 value.i = 10;
00663 if (jackctl_add_parameter(
00664 &server_ptr->parameters,
00665 "realtime-priority",
00666 "Scheduler priority when running in realtime mode.",
00667 "",
00668 JackParamInt,
00669 &server_ptr->realtime_priority,
00670 &server_ptr->default_realtime_priority,
00671 value,
00672 get_realtime_priority_constraint()) == NULL)
00673 {
00674 goto fail_free_parameters;
00675 }
00676
00677 value.b = false;
00678 if (jackctl_add_parameter(
00679 &server_ptr->parameters,
00680 "temporary",
00681 "Exit once all clients have closed their connections.",
00682 "",
00683 JackParamBool,
00684 &server_ptr->temporary,
00685 &server_ptr->default_temporary,
00686 value) == NULL)
00687 {
00688 goto fail_free_parameters;
00689 }
00690
00691 value.b = false;
00692 if (jackctl_add_parameter(
00693 &server_ptr->parameters,
00694 "verbose",
00695 "Verbose mode.",
00696 "",
00697 JackParamBool,
00698 &server_ptr->verbose,
00699 &server_ptr->default_verbose,
00700 value) == NULL)
00701 {
00702 goto fail_free_parameters;
00703 }
00704
00705 value.i = 0;
00706 if (jackctl_add_parameter(
00707 &server_ptr->parameters,
00708 "client-timeout",
00709 "Client timeout limit in milliseconds",
00710 "",
00711 JackParamInt,
00712 &server_ptr->client_timeout,
00713 &server_ptr->default_client_timeout,
00714 value) == NULL)
00715 {
00716 goto fail_free_parameters;
00717 }
00718
00719 value.ui = 0;
00720 if (jackctl_add_parameter(
00721 &server_ptr->parameters,
00722 "loopback-ports",
00723 "Number of loopback ports",
00724 "",
00725 JackParamUInt,
00726 &server_ptr->loopback_ports,
00727 &server_ptr->default_loopback_ports,
00728 value) == NULL)
00729 {
00730 goto fail_free_parameters;
00731 }
00732
00733 value.b = false;
00734 if (jackctl_add_parameter(
00735 &server_ptr->parameters,
00736 "replace-registry",
00737 "Replace registry",
00738 "",
00739 JackParamBool,
00740 &server_ptr->replace_registry,
00741 &server_ptr->default_replace_registry,
00742 value) == NULL)
00743 {
00744 goto fail_free_parameters;
00745 }
00746
00747 value.b = false;
00748 if (jackctl_add_parameter(
00749 &server_ptr->parameters,
00750 "sync",
00751 "Use synchronous mode",
00752 "",
00753 JackParamBool,
00754 &server_ptr->sync,
00755 &server_ptr->default_sync,
00756 value) == NULL)
00757 {
00758 goto fail_free_parameters;
00759 }
00760
00761 if (!jackctl_drivers_load(server_ptr))
00762 {
00763 goto fail_free_parameters;
00764 }
00765
00766
00767 jackctl_internals_load(server_ptr);
00768
00769 return server_ptr;
00770
00771 fail_free_parameters:
00772 jackctl_server_free_parameters(server_ptr);
00773
00774 free(server_ptr);
00775
00776 fail:
00777 return NULL;
00778 }
00779
00780 EXPORT void jackctl_server_destroy(jackctl_server *server_ptr)
00781 {
00782 jackctl_server_free_drivers(server_ptr);
00783 jackctl_server_free_internals(server_ptr);
00784 jackctl_server_free_parameters(server_ptr);
00785 free(server_ptr);
00786 }
00787
00788 EXPORT const JSList * jackctl_server_get_drivers_list(jackctl_server *server_ptr)
00789 {
00790 return server_ptr->drivers;
00791 }
00792
00793 EXPORT bool jackctl_server_stop(jackctl_server *server_ptr)
00794 {
00795 server_ptr->engine->Stop();
00796 server_ptr->engine->Close();
00797 delete server_ptr->engine;
00798
00799
00800 jack_log("cleaning up shared memory");
00801
00802 jack_cleanup_shm();
00803
00804 jack_log("cleaning up files");
00805
00806 JackTools::CleanupFiles(server_ptr->name.str);
00807
00808 jack_log("unregistering server `%s'", server_ptr->name.str);
00809
00810 jack_unregister_server(server_ptr->name.str);
00811
00812 server_ptr->engine = NULL;
00813
00814 return true;
00815 }
00816
00817 EXPORT const JSList * jackctl_server_get_parameters(jackctl_server *server_ptr)
00818 {
00819 return server_ptr->parameters;
00820 }
00821
00822 EXPORT bool
00823 jackctl_server_start(
00824 jackctl_server *server_ptr,
00825 jackctl_driver *driver_ptr)
00826 {
00827 int rc;
00828
00829 rc = jack_register_server(server_ptr->name.str, server_ptr->replace_registry.b);
00830 switch (rc)
00831 {
00832 case EEXIST:
00833 jack_error("`%s' server already active", server_ptr->name.str);
00834 goto fail;
00835 case ENOSPC:
00836 jack_error("too many servers already active");
00837 goto fail;
00838 case ENOMEM:
00839 jack_error("no access to shm registry");
00840 goto fail;
00841 }
00842
00843 jack_log("server `%s' registered", server_ptr->name.str);
00844
00845
00846
00847 jack_cleanup_shm();
00848 JackTools::CleanupFiles(server_ptr->name.str);
00849
00850 if (!server_ptr->realtime.b && server_ptr->client_timeout.i == 0)
00851 server_ptr->client_timeout.i = 500;
00852
00853
00854
00855 server_ptr->engine = new JackServer(
00856 server_ptr->sync.b,
00857 server_ptr->temporary.b,
00858 server_ptr->client_timeout.i,
00859 server_ptr->realtime.b,
00860 server_ptr->realtime_priority.i,
00861 server_ptr->loopback_ports.ui,
00862 server_ptr->verbose.b,
00863 server_ptr->name.str);
00864 if (server_ptr->engine == NULL)
00865 {
00866 jack_error("Failed to create new JackServer object");
00867 goto fail_unregister;
00868 }
00869
00870 rc = server_ptr->engine->Open(driver_ptr->desc_ptr, driver_ptr->set_parameters);
00871 if (rc < 0)
00872 {
00873 jack_error("JackServer::Open() failed with %d", rc);
00874 goto fail_delete;
00875 }
00876
00877 rc = server_ptr->engine->Start();
00878 if (rc < 0)
00879 {
00880 jack_error("JackServer::Start() failed with %d", rc);
00881 goto fail_close;
00882 }
00883
00884 return true;
00885
00886 fail_close:
00887 server_ptr->engine->Close();
00888
00889 fail_delete:
00890 delete server_ptr->engine;
00891 server_ptr->engine = NULL;
00892
00893 fail_unregister:
00894 jack_log("cleaning up shared memory");
00895
00896 jack_cleanup_shm();
00897
00898 jack_log("cleaning up files");
00899
00900 JackTools::CleanupFiles(server_ptr->name.str);
00901
00902 jack_log("unregistering server `%s'", server_ptr->name.str);
00903
00904 jack_unregister_server(server_ptr->name.str);
00905
00906 fail:
00907 return false;
00908 }
00909
00910 EXPORT const char * jackctl_driver_get_name(jackctl_driver *driver_ptr)
00911 {
00912 return driver_ptr->desc_ptr->name;
00913 }
00914
00915 EXPORT const JSList * jackctl_driver_get_parameters(jackctl_driver *driver_ptr)
00916 {
00917 return driver_ptr->parameters;
00918 }
00919
00920 EXPORT jack_driver_desc_t * jackctl_driver_get_desc(jackctl_driver *driver_ptr)
00921 {
00922 return driver_ptr->desc_ptr;
00923 }
00924
00925 EXPORT const char * jackctl_parameter_get_name(jackctl_parameter *parameter_ptr)
00926 {
00927 return parameter_ptr->name;
00928 }
00929
00930 EXPORT const char * jackctl_parameter_get_short_description(jackctl_parameter *parameter_ptr)
00931 {
00932 return parameter_ptr->short_description;
00933 }
00934
00935 EXPORT const char * jackctl_parameter_get_long_description(jackctl_parameter *parameter_ptr)
00936 {
00937 return parameter_ptr->long_description;
00938 }
00939
00940 EXPORT bool jackctl_parameter_has_range_constraint(jackctl_parameter *parameter_ptr)
00941 {
00942 return parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_RANGE) != 0;
00943 }
00944
00945 EXPORT bool jackctl_parameter_has_enum_constraint(jackctl_parameter *parameter_ptr)
00946 {
00947 return parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_RANGE) == 0;
00948 }
00949
00950 EXPORT uint32_t jackctl_parameter_get_enum_constraints_count(jackctl_parameter *parameter_ptr)
00951 {
00952 if (!jackctl_parameter_has_enum_constraint(parameter_ptr))
00953 {
00954 return 0;
00955 }
00956
00957 return parameter_ptr->constraint_ptr->constraint.enumeration.count;
00958 }
00959
00960 EXPORT union jackctl_parameter_value jackctl_parameter_get_enum_constraint_value(jackctl_parameter *parameter_ptr, uint32_t index)
00961 {
00962 jack_driver_param_value_t * value_ptr;
00963 union jackctl_parameter_value jackctl_value;
00964
00965 value_ptr = ¶meter_ptr->constraint_ptr->constraint.enumeration.possible_values_array[index].value;
00966
00967 switch (parameter_ptr->type)
00968 {
00969 case JackParamInt:
00970 jackctl_value.i = value_ptr->i;
00971 break;
00972 case JackParamUInt:
00973 jackctl_value.ui = value_ptr->ui;
00974 break;
00975 case JackParamChar:
00976 jackctl_value.c = value_ptr->c;
00977 break;
00978 case JackParamString:
00979 strcpy(jackctl_value.str, value_ptr->str);
00980 break;
00981 default:
00982 jack_error("bad driver parameter type %i (enum constraint)", (int)parameter_ptr->type);
00983 assert(0);
00984 }
00985
00986 return jackctl_value;
00987 }
00988
00989 EXPORT const char * jackctl_parameter_get_enum_constraint_description(jackctl_parameter *parameter_ptr, uint32_t index)
00990 {
00991 return parameter_ptr->constraint_ptr->constraint.enumeration.possible_values_array[index].short_desc;
00992 }
00993
00994 EXPORT void jackctl_parameter_get_range_constraint(jackctl_parameter *parameter_ptr, union jackctl_parameter_value * min_ptr, union jackctl_parameter_value * max_ptr)
00995 {
00996 switch (parameter_ptr->type)
00997 {
00998 case JackParamInt:
00999 min_ptr->i = parameter_ptr->constraint_ptr->constraint.range.min.i;
01000 max_ptr->i = parameter_ptr->constraint_ptr->constraint.range.max.i;
01001 return;
01002 case JackParamUInt:
01003 min_ptr->ui = parameter_ptr->constraint_ptr->constraint.range.min.ui;
01004 max_ptr->ui = parameter_ptr->constraint_ptr->constraint.range.max.ui;
01005 return;
01006 default:
01007 jack_error("bad driver parameter type %i (range constraint)", (int)parameter_ptr->type);
01008 assert(0);
01009 }
01010 }
01011
01012 EXPORT bool jackctl_parameter_constraint_is_strict(jackctl_parameter_t * parameter_ptr)
01013 {
01014 return parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_STRICT) != 0;
01015 }
01016
01017 EXPORT bool jackctl_parameter_constraint_is_fake_value(jackctl_parameter_t * parameter_ptr)
01018 {
01019 return parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_FAKE_VALUE) != 0;
01020 }
01021
01022 EXPORT jackctl_param_type_t jackctl_parameter_get_type(jackctl_parameter *parameter_ptr)
01023 {
01024 return parameter_ptr->type;
01025 }
01026
01027 EXPORT char jackctl_parameter_get_id(jackctl_parameter_t * parameter_ptr)
01028 {
01029 return parameter_ptr->id;
01030 }
01031
01032 EXPORT bool jackctl_parameter_is_set(jackctl_parameter *parameter_ptr)
01033 {
01034 return parameter_ptr->is_set;
01035 }
01036
01037 EXPORT union jackctl_parameter_value jackctl_parameter_get_value(jackctl_parameter *parameter_ptr)
01038 {
01039 return *parameter_ptr->value_ptr;
01040 }
01041
01042 EXPORT bool jackctl_parameter_reset(jackctl_parameter *parameter_ptr)
01043 {
01044 if (!parameter_ptr->is_set)
01045 {
01046 return true;
01047 }
01048
01049 parameter_ptr->is_set = false;
01050
01051 *parameter_ptr->value_ptr = *parameter_ptr->default_value_ptr;
01052
01053 return true;
01054 }
01055
01056 EXPORT bool jackctl_parameter_set_value(jackctl_parameter *parameter_ptr, const union jackctl_parameter_value * value_ptr)
01057 {
01058 bool new_driver_parameter;
01059
01060
01061 if (parameter_ptr->driver_ptr != NULL)
01062 {
01063
01064 new_driver_parameter = parameter_ptr->driver_parameter_ptr == NULL;
01065 if (new_driver_parameter)
01066 {
01067
01068 parameter_ptr->driver_parameter_ptr = (jack_driver_param_t *)malloc(sizeof(jack_driver_param_t));
01069 if (parameter_ptr->driver_parameter_ptr == NULL)
01070 {
01071 jack_error ("Allocation of jack_driver_param_t structure failed");
01072 return false;
01073 }
01074
01075 parameter_ptr->driver_parameter_ptr->character = parameter_ptr->id;
01076 parameter_ptr->driver_ptr->set_parameters = jack_slist_append(parameter_ptr->driver_ptr->set_parameters, parameter_ptr->driver_parameter_ptr);
01077 }
01078
01079 switch (parameter_ptr->type)
01080 {
01081 case JackParamInt:
01082 parameter_ptr->driver_parameter_ptr->value.i = value_ptr->i;
01083 break;
01084 case JackParamUInt:
01085 parameter_ptr->driver_parameter_ptr->value.ui = value_ptr->ui;
01086 break;
01087 case JackParamChar:
01088 parameter_ptr->driver_parameter_ptr->value.c = value_ptr->c;
01089 break;
01090 case JackParamString:
01091 strcpy(parameter_ptr->driver_parameter_ptr->value.str, value_ptr->str);
01092 break;
01093 case JackParamBool:
01094 parameter_ptr->driver_parameter_ptr->value.i = value_ptr->b;
01095 break;
01096 default:
01097 jack_error("unknown parameter type %i", (int)parameter_ptr->type);
01098 assert(0);
01099
01100 if (new_driver_parameter)
01101 {
01102 parameter_ptr->driver_ptr->set_parameters = jack_slist_remove(parameter_ptr->driver_ptr->set_parameters, parameter_ptr->driver_parameter_ptr);
01103 }
01104
01105 return false;
01106 }
01107 }
01108
01109 parameter_ptr->is_set = true;
01110 *parameter_ptr->value_ptr = *value_ptr;
01111
01112 return true;
01113 }
01114
01115 EXPORT union jackctl_parameter_value jackctl_parameter_get_default_value(jackctl_parameter *parameter_ptr)
01116 {
01117 return *parameter_ptr->default_value_ptr;
01118 }
01119
01120
01121
01122 EXPORT const JSList * jackctl_server_get_internals_list(jackctl_server *server_ptr)
01123 {
01124 return server_ptr->internals;
01125 }
01126
01127 EXPORT const char * jackctl_internal_get_name(jackctl_internal *internal_ptr)
01128 {
01129 return internal_ptr->desc_ptr->name;
01130 }
01131
01132 EXPORT const JSList * jackctl_internal_get_parameters(jackctl_internal *internal_ptr)
01133 {
01134 return internal_ptr->parameters;
01135 }
01136
01137 EXPORT bool jackctl_server_load_internal(
01138 jackctl_server * server_ptr,
01139 jackctl_internal * internal)
01140 {
01141 int status;
01142 if (server_ptr->engine != NULL) {
01143 server_ptr->engine->InternalClientLoad(internal->desc_ptr->name, internal->desc_ptr->name, internal->set_parameters, JackNullOption, &internal->refnum, &status);
01144 return (internal->refnum > 0);
01145 } else {
01146 return false;
01147 }
01148 }
01149
01150 EXPORT bool jackctl_server_unload_internal(
01151 jackctl_server * server_ptr,
01152 jackctl_internal * internal)
01153 {
01154 int status;
01155 if (server_ptr->engine != NULL && internal->refnum > 0) {
01156 return ((server_ptr->engine->GetEngine()->InternalClientUnload(internal->refnum, &status)) == 0);
01157 } else {
01158 return false;
01159 }
01160 }
01161
01162