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