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