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 if (constraint_ptr == NULL)
00615 {
00616 jack_error("Cannot allocate memory for jack_driver_param_constraint_desc_t structure.");
00617 return NULL;
00618 }
00619 constraint_ptr->flags = JACK_CONSTRAINT_FLAG_RANGE;
00620
00621 constraint_ptr->constraint.range.min.i = min;
00622 constraint_ptr->constraint.range.max.i = max;
00623
00624 return constraint_ptr;
00625 }
00626
00627 EXPORT jackctl_server_t * jackctl_server_create(
00628 bool (* on_device_acquire)(const char * device_name),
00629 void (* on_device_release)(const char * device_name))
00630 {
00631 struct jackctl_server * server_ptr;
00632 union jackctl_parameter_value value;
00633
00634 server_ptr = (struct jackctl_server *)malloc(sizeof(struct jackctl_server));
00635 if (server_ptr == NULL)
00636 {
00637 jack_error("Cannot allocate memory for jackctl_server structure.");
00638 goto fail;
00639 }
00640
00641 server_ptr->drivers = NULL;
00642 server_ptr->internals = NULL;
00643 server_ptr->parameters = NULL;
00644 server_ptr->engine = NULL;
00645
00646 strcpy(value.str, JACK_DEFAULT_SERVER_NAME);
00647 if (jackctl_add_parameter(
00648 &server_ptr->parameters,
00649 "name",
00650 "Server name to use.",
00651 "",
00652 JackParamString,
00653 &server_ptr->name,
00654 &server_ptr->default_name,
00655 value) == NULL)
00656 {
00657 goto fail_free_parameters;
00658 }
00659
00660 value.b = false;
00661 if (jackctl_add_parameter(
00662 &server_ptr->parameters,
00663 "realtime",
00664 "Whether to use realtime mode.",
00665 "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.",
00666 JackParamBool,
00667 &server_ptr->realtime,
00668 &server_ptr->default_realtime,
00669 value) == NULL)
00670 {
00671 goto fail_free_parameters;
00672 }
00673
00674 value.i = 60;
00675 if (jackctl_add_parameter(
00676 &server_ptr->parameters,
00677 "realtime-priority",
00678 "Scheduler priority when running in realtime mode.",
00679 "",
00680 JackParamInt,
00681 &server_ptr->realtime_priority,
00682 &server_ptr->default_realtime_priority,
00683 value,
00684 get_realtime_priority_constraint()) == NULL)
00685 {
00686 goto fail_free_parameters;
00687 }
00688
00689 value.b = false;
00690 if (jackctl_add_parameter(
00691 &server_ptr->parameters,
00692 "temporary",
00693 "Exit once all clients have closed their connections.",
00694 "",
00695 JackParamBool,
00696 &server_ptr->temporary,
00697 &server_ptr->default_temporary,
00698 value) == NULL)
00699 {
00700 goto fail_free_parameters;
00701 }
00702
00703 value.b = false;
00704 if (jackctl_add_parameter(
00705 &server_ptr->parameters,
00706 "verbose",
00707 "Verbose mode.",
00708 "",
00709 JackParamBool,
00710 &server_ptr->verbose,
00711 &server_ptr->default_verbose,
00712 value) == NULL)
00713 {
00714 goto fail_free_parameters;
00715 }
00716
00717 value.i = 0;
00718 if (jackctl_add_parameter(
00719 &server_ptr->parameters,
00720 "client-timeout",
00721 "Client timeout limit in milliseconds.",
00722 "",
00723 JackParamInt,
00724 &server_ptr->client_timeout,
00725 &server_ptr->default_client_timeout,
00726 value) == NULL)
00727 {
00728 goto fail_free_parameters;
00729 }
00730
00731 value.ui = 0;
00732 if (jackctl_add_parameter(
00733 &server_ptr->parameters,
00734 "clock-source",
00735 "Clocksource type : c(ycle) | h(pet) | s(ystem).",
00736 "",
00737 JackParamUInt,
00738 &server_ptr->clock_source,
00739 &server_ptr->default_clock_source,
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 "replace-registry",
00749 "Replace shared memory registry.",
00750 "",
00751 JackParamBool,
00752 &server_ptr->replace_registry,
00753 &server_ptr->default_replace_registry,
00754 value) == NULL)
00755 {
00756 goto fail_free_parameters;
00757 }
00758
00759 value.b = false;
00760 if (jackctl_add_parameter(
00761 &server_ptr->parameters,
00762 "sync",
00763 "Use server synchronous mode.",
00764 "",
00765 JackParamBool,
00766 &server_ptr->sync,
00767 &server_ptr->default_sync,
00768 value) == NULL)
00769 {
00770 goto fail_free_parameters;
00771 }
00772
00773 JackServerGlobals::on_device_acquire = on_device_acquire;
00774 JackServerGlobals::on_device_release = on_device_release;
00775
00776 if (!jackctl_drivers_load(server_ptr))
00777 {
00778 goto fail_free_parameters;
00779 }
00780
00781
00782 jackctl_internals_load(server_ptr);
00783
00784 return server_ptr;
00785
00786 fail_free_parameters:
00787 jackctl_server_free_parameters(server_ptr);
00788
00789 free(server_ptr);
00790
00791 fail:
00792 return NULL;
00793 }
00794
00795 EXPORT void jackctl_server_destroy(jackctl_server *server_ptr)
00796 {
00797 jackctl_server_free_drivers(server_ptr);
00798 jackctl_server_free_internals(server_ptr);
00799 jackctl_server_free_parameters(server_ptr);
00800 free(server_ptr);
00801 }
00802
00803 EXPORT const JSList * jackctl_server_get_drivers_list(jackctl_server *server_ptr)
00804 {
00805 return server_ptr->drivers;
00806 }
00807
00808 EXPORT bool jackctl_server_stop(jackctl_server *server_ptr)
00809 {
00810 server_ptr->engine->Stop();
00811 server_ptr->engine->Close();
00812 delete server_ptr->engine;
00813
00814
00815 jack_log("cleaning up shared memory");
00816
00817 jack_cleanup_shm();
00818
00819 jack_log("cleaning up files");
00820
00821 JackTools::CleanupFiles(server_ptr->name.str);
00822
00823 jack_log("unregistering server `%s'", server_ptr->name.str);
00824
00825 jack_unregister_server(server_ptr->name.str);
00826
00827 server_ptr->engine = NULL;
00828
00829 return true;
00830 }
00831
00832 EXPORT const JSList * jackctl_server_get_parameters(jackctl_server *server_ptr)
00833 {
00834 return server_ptr->parameters;
00835 }
00836
00837 EXPORT bool
00838 jackctl_server_start(
00839 jackctl_server *server_ptr,
00840 jackctl_driver *driver_ptr)
00841 {
00842 int rc;
00843
00844 rc = jack_register_server(server_ptr->name.str, server_ptr->replace_registry.b);
00845 switch (rc)
00846 {
00847 case EEXIST:
00848 jack_error("`%s' server already active", server_ptr->name.str);
00849 goto fail;
00850 case ENOSPC:
00851 jack_error("too many servers already active");
00852 goto fail;
00853 case ENOMEM:
00854 jack_error("no access to shm registry");
00855 goto fail;
00856 }
00857
00858 jack_log("server `%s' registered", server_ptr->name.str);
00859
00860
00861
00862 jack_cleanup_shm();
00863 JackTools::CleanupFiles(server_ptr->name.str);
00864
00865 if (!server_ptr->realtime.b && server_ptr->client_timeout.i == 0)
00866 server_ptr->client_timeout.i = 500;
00867
00868
00869
00870 server_ptr->engine = new JackServer(
00871 server_ptr->sync.b,
00872 server_ptr->temporary.b,
00873 server_ptr->client_timeout.i,
00874 server_ptr->realtime.b,
00875 server_ptr->realtime_priority.i,
00876 server_ptr->verbose.b,
00877 (jack_timer_type_t)server_ptr->clock_source.ui,
00878 server_ptr->name.str);
00879 if (server_ptr->engine == NULL)
00880 {
00881 jack_error("Failed to create new JackServer object");
00882 goto fail_unregister;
00883 }
00884
00885 rc = server_ptr->engine->Open(driver_ptr->desc_ptr, driver_ptr->set_parameters);
00886 if (rc < 0)
00887 {
00888 jack_error("JackServer::Open() failed with %d", rc);
00889 goto fail_delete;
00890 }
00891
00892 rc = server_ptr->engine->Start();
00893 if (rc < 0)
00894 {
00895 jack_error("JackServer::Start() failed with %d", rc);
00896 goto fail_close;
00897 }
00898
00899 return true;
00900
00901 fail_close:
00902 server_ptr->engine->Close();
00903
00904 fail_delete:
00905 delete server_ptr->engine;
00906 server_ptr->engine = NULL;
00907
00908 fail_unregister:
00909 jack_log("cleaning up shared memory");
00910
00911 jack_cleanup_shm();
00912
00913 jack_log("cleaning up files");
00914
00915 JackTools::CleanupFiles(server_ptr->name.str);
00916
00917 jack_log("unregistering server `%s'", server_ptr->name.str);
00918
00919 jack_unregister_server(server_ptr->name.str);
00920
00921 fail:
00922 return false;
00923 }
00924
00925 EXPORT const char * jackctl_driver_get_name(jackctl_driver *driver_ptr)
00926 {
00927 return driver_ptr->desc_ptr->name;
00928 }
00929
00930 EXPORT const JSList * jackctl_driver_get_parameters(jackctl_driver *driver_ptr)
00931 {
00932 return driver_ptr->parameters;
00933 }
00934
00935 EXPORT jack_driver_desc_t * jackctl_driver_get_desc(jackctl_driver *driver_ptr)
00936 {
00937 return driver_ptr->desc_ptr;
00938 }
00939
00940 EXPORT const char * jackctl_parameter_get_name(jackctl_parameter *parameter_ptr)
00941 {
00942 return parameter_ptr->name;
00943 }
00944
00945 EXPORT const char * jackctl_parameter_get_short_description(jackctl_parameter *parameter_ptr)
00946 {
00947 return parameter_ptr->short_description;
00948 }
00949
00950 EXPORT const char * jackctl_parameter_get_long_description(jackctl_parameter *parameter_ptr)
00951 {
00952 return parameter_ptr->long_description;
00953 }
00954
00955 EXPORT bool jackctl_parameter_has_range_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 bool jackctl_parameter_has_enum_constraint(jackctl_parameter *parameter_ptr)
00961 {
00962 return parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_RANGE) == 0;
00963 }
00964
00965 EXPORT uint32_t jackctl_parameter_get_enum_constraints_count(jackctl_parameter *parameter_ptr)
00966 {
00967 if (!jackctl_parameter_has_enum_constraint(parameter_ptr))
00968 {
00969 return 0;
00970 }
00971
00972 return parameter_ptr->constraint_ptr->constraint.enumeration.count;
00973 }
00974
00975 EXPORT union jackctl_parameter_value jackctl_parameter_get_enum_constraint_value(jackctl_parameter *parameter_ptr, uint32_t index)
00976 {
00977 jack_driver_param_value_t * value_ptr;
00978 union jackctl_parameter_value jackctl_value;
00979
00980 value_ptr = ¶meter_ptr->constraint_ptr->constraint.enumeration.possible_values_array[index].value;
00981
00982 switch (parameter_ptr->type)
00983 {
00984 case JackParamInt:
00985 jackctl_value.i = value_ptr->i;
00986 break;
00987 case JackParamUInt:
00988 jackctl_value.ui = value_ptr->ui;
00989 break;
00990 case JackParamChar:
00991 jackctl_value.c = value_ptr->c;
00992 break;
00993 case JackParamString:
00994 strcpy(jackctl_value.str, value_ptr->str);
00995 break;
00996 default:
00997 jack_error("bad driver parameter type %i (enum constraint)", (int)parameter_ptr->type);
00998 assert(0);
00999 }
01000
01001 return jackctl_value;
01002 }
01003
01004 EXPORT const char * jackctl_parameter_get_enum_constraint_description(jackctl_parameter *parameter_ptr, uint32_t index)
01005 {
01006 return parameter_ptr->constraint_ptr->constraint.enumeration.possible_values_array[index].short_desc;
01007 }
01008
01009 EXPORT void jackctl_parameter_get_range_constraint(jackctl_parameter *parameter_ptr, union jackctl_parameter_value * min_ptr, union jackctl_parameter_value * max_ptr)
01010 {
01011 switch (parameter_ptr->type)
01012 {
01013 case JackParamInt:
01014 min_ptr->i = parameter_ptr->constraint_ptr->constraint.range.min.i;
01015 max_ptr->i = parameter_ptr->constraint_ptr->constraint.range.max.i;
01016 return;
01017 case JackParamUInt:
01018 min_ptr->ui = parameter_ptr->constraint_ptr->constraint.range.min.ui;
01019 max_ptr->ui = parameter_ptr->constraint_ptr->constraint.range.max.ui;
01020 return;
01021 default:
01022 jack_error("bad driver parameter type %i (range constraint)", (int)parameter_ptr->type);
01023 assert(0);
01024 }
01025 }
01026
01027 EXPORT bool jackctl_parameter_constraint_is_strict(jackctl_parameter_t * parameter_ptr)
01028 {
01029 return parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_STRICT) != 0;
01030 }
01031
01032 EXPORT bool jackctl_parameter_constraint_is_fake_value(jackctl_parameter_t * parameter_ptr)
01033 {
01034 return parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_FAKE_VALUE) != 0;
01035 }
01036
01037 EXPORT jackctl_param_type_t jackctl_parameter_get_type(jackctl_parameter *parameter_ptr)
01038 {
01039 return parameter_ptr->type;
01040 }
01041
01042 EXPORT char jackctl_parameter_get_id(jackctl_parameter_t * parameter_ptr)
01043 {
01044 return parameter_ptr->id;
01045 }
01046
01047 EXPORT bool jackctl_parameter_is_set(jackctl_parameter *parameter_ptr)
01048 {
01049 return parameter_ptr->is_set;
01050 }
01051
01052 EXPORT union jackctl_parameter_value jackctl_parameter_get_value(jackctl_parameter *parameter_ptr)
01053 {
01054 return *parameter_ptr->value_ptr;
01055 }
01056
01057 EXPORT bool jackctl_parameter_reset(jackctl_parameter *parameter_ptr)
01058 {
01059 if (!parameter_ptr->is_set)
01060 {
01061 return true;
01062 }
01063
01064 parameter_ptr->is_set = false;
01065
01066 *parameter_ptr->value_ptr = *parameter_ptr->default_value_ptr;
01067
01068 return true;
01069 }
01070
01071 EXPORT bool jackctl_parameter_set_value(jackctl_parameter *parameter_ptr, const union jackctl_parameter_value * value_ptr)
01072 {
01073 bool new_driver_parameter;
01074
01075
01076 if (parameter_ptr->driver_ptr != NULL)
01077 {
01078
01079 new_driver_parameter = parameter_ptr->driver_parameter_ptr == NULL;
01080 if (new_driver_parameter)
01081 {
01082
01083 parameter_ptr->driver_parameter_ptr = (jack_driver_param_t *)malloc(sizeof(jack_driver_param_t));
01084 if (parameter_ptr->driver_parameter_ptr == NULL)
01085 {
01086 jack_error ("Allocation of jack_driver_param_t structure failed");
01087 return false;
01088 }
01089
01090 parameter_ptr->driver_parameter_ptr->character = parameter_ptr->id;
01091 parameter_ptr->driver_ptr->set_parameters = jack_slist_append(parameter_ptr->driver_ptr->set_parameters, parameter_ptr->driver_parameter_ptr);
01092 }
01093
01094 switch (parameter_ptr->type)
01095 {
01096 case JackParamInt:
01097 parameter_ptr->driver_parameter_ptr->value.i = value_ptr->i;
01098 break;
01099 case JackParamUInt:
01100 parameter_ptr->driver_parameter_ptr->value.ui = value_ptr->ui;
01101 break;
01102 case JackParamChar:
01103 parameter_ptr->driver_parameter_ptr->value.c = value_ptr->c;
01104 break;
01105 case JackParamString:
01106 strcpy(parameter_ptr->driver_parameter_ptr->value.str, value_ptr->str);
01107 break;
01108 case JackParamBool:
01109 parameter_ptr->driver_parameter_ptr->value.i = value_ptr->b;
01110 break;
01111 default:
01112 jack_error("unknown parameter type %i", (int)parameter_ptr->type);
01113 assert(0);
01114
01115 if (new_driver_parameter)
01116 {
01117 parameter_ptr->driver_ptr->set_parameters = jack_slist_remove(parameter_ptr->driver_ptr->set_parameters, parameter_ptr->driver_parameter_ptr);
01118 }
01119
01120 return false;
01121 }
01122 }
01123
01124 parameter_ptr->is_set = true;
01125 *parameter_ptr->value_ptr = *value_ptr;
01126
01127 return true;
01128 }
01129
01130 EXPORT union jackctl_parameter_value jackctl_parameter_get_default_value(jackctl_parameter *parameter_ptr)
01131 {
01132 return *parameter_ptr->default_value_ptr;
01133 }
01134
01135
01136
01137 EXPORT const JSList * jackctl_server_get_internals_list(jackctl_server *server_ptr)
01138 {
01139 return server_ptr->internals;
01140 }
01141
01142 EXPORT const char * jackctl_internal_get_name(jackctl_internal *internal_ptr)
01143 {
01144 return internal_ptr->desc_ptr->name;
01145 }
01146
01147 EXPORT const JSList * jackctl_internal_get_parameters(jackctl_internal *internal_ptr)
01148 {
01149 return internal_ptr->parameters;
01150 }
01151
01152 EXPORT bool jackctl_server_load_internal(
01153 jackctl_server * server_ptr,
01154 jackctl_internal * internal)
01155 {
01156 int status;
01157 if (server_ptr->engine != NULL) {
01158 server_ptr->engine->InternalClientLoad(internal->desc_ptr->name, internal->desc_ptr->name, internal->set_parameters, JackNullOption, &internal->refnum, &status);
01159 return (internal->refnum > 0);
01160 } else {
01161 return false;
01162 }
01163 }
01164
01165 EXPORT bool jackctl_server_unload_internal(
01166 jackctl_server * server_ptr,
01167 jackctl_internal * internal)
01168 {
01169 int status;
01170 if (server_ptr->engine != NULL && internal->refnum > 0) {
01171 return ((server_ptr->engine->GetEngine()->InternalClientUnload(internal->refnum, &status)) == 0);
01172 } else {
01173 return false;
01174 }
01175 }
01176
01177 EXPORT bool jackctl_server_add_slave(jackctl_server * server_ptr, jackctl_driver * driver_ptr)
01178 {
01179 if (server_ptr->engine != NULL) {
01180 driver_ptr->info = server_ptr->engine->AddSlave(driver_ptr->desc_ptr, driver_ptr->set_parameters);
01181 return (driver_ptr->info != 0);
01182 } else {
01183 return false;
01184 }
01185 }
01186
01187 EXPORT bool jackctl_server_remove_slave(jackctl_server * server_ptr, jackctl_driver * driver_ptr)
01188 {
01189 if (server_ptr->engine != NULL) {
01190 server_ptr->engine->RemoveSlave(driver_ptr->info);
01191 delete driver_ptr->info;
01192 return true;
01193 } else {
01194 return false;
01195 }
01196 }
01197
01198 EXPORT bool jackctl_server_switch_master(jackctl_server * server_ptr, jackctl_driver * driver_ptr)
01199 {
01200 if (server_ptr->engine != NULL) {
01201 return (server_ptr->engine->SwitchMaster(driver_ptr->desc_ptr, driver_ptr->set_parameters) == 0);
01202 } else {
01203 return false;
01204 }
01205 }
01206