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, "PREEMPT RT" ) )
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 return true;
00837 }
00838
00839 EXPORT bool jackctl_server_close(jackctl_server *server_ptr)
00840 {
00841 server_ptr->engine->Close();
00842 delete server_ptr->engine;
00843
00844
00845 jack_log("cleaning up shared memory");
00846
00847 jack_cleanup_shm();
00848
00849 jack_log("cleaning up files");
00850
00851 JackTools::CleanupFiles(server_ptr->name.str);
00852
00853 jack_log("unregistering server `%s'", server_ptr->name.str);
00854
00855 jack_unregister_server(server_ptr->name.str);
00856
00857 server_ptr->engine = NULL;
00858
00859 return true;
00860 }
00861
00862 EXPORT const JSList * jackctl_server_get_parameters(jackctl_server *server_ptr)
00863 {
00864 return server_ptr->parameters;
00865 }
00866
00867 EXPORT bool
00868 jackctl_server_open(
00869 jackctl_server *server_ptr,
00870 jackctl_driver *driver_ptr)
00871 {
00872 int rc;
00873
00874 rc = jack_register_server(server_ptr->name.str, server_ptr->replace_registry.b);
00875 switch (rc)
00876 {
00877 case EEXIST:
00878 jack_error("`%s' server already active", server_ptr->name.str);
00879 goto fail;
00880 case ENOSPC:
00881 jack_error("too many servers already active");
00882 goto fail;
00883 case ENOMEM:
00884 jack_error("no access to shm registry");
00885 goto fail;
00886 }
00887
00888 jack_log("server `%s' registered", server_ptr->name.str);
00889
00890
00891
00892 jack_cleanup_shm();
00893 JackTools::CleanupFiles(server_ptr->name.str);
00894
00895 if (!server_ptr->realtime.b && server_ptr->client_timeout.i == 0)
00896 server_ptr->client_timeout.i = 500;
00897
00898
00899 if (server_ptr->port_max.ui > PORT_NUM_MAX) {
00900 jack_error("JACK server started with too much ports %d (when port max can be %d)", server_ptr->port_max.ui, PORT_NUM_MAX);
00901 goto fail;
00902 }
00903
00904
00905 server_ptr->engine = new JackServer(
00906 server_ptr->sync.b,
00907 server_ptr->temporary.b,
00908 server_ptr->client_timeout.i,
00909 server_ptr->realtime.b,
00910 server_ptr->realtime_priority.i,
00911 server_ptr->port_max.ui,
00912 server_ptr->verbose.b,
00913 (jack_timer_type_t)server_ptr->clock_source.ui,
00914 server_ptr->name.str);
00915 if (server_ptr->engine == NULL)
00916 {
00917 jack_error("Failed to create new JackServer object");
00918 goto fail_unregister;
00919 }
00920
00921 rc = server_ptr->engine->Open(driver_ptr->desc_ptr, driver_ptr->set_parameters);
00922 if (rc < 0)
00923 {
00924 jack_error("JackServer::Open() failed with %d", rc);
00925 goto fail_delete;
00926 }
00927
00928 return true;
00929
00930 fail_delete:
00931 delete server_ptr->engine;
00932 server_ptr->engine = NULL;
00933
00934 fail_unregister:
00935 jack_log("cleaning up shared memory");
00936
00937 jack_cleanup_shm();
00938
00939 jack_log("cleaning up files");
00940
00941 JackTools::CleanupFiles(server_ptr->name.str);
00942
00943 jack_log("unregistering server `%s'", server_ptr->name.str);
00944
00945 jack_unregister_server(server_ptr->name.str);
00946
00947 fail:
00948 return false;
00949 }
00950
00951 EXPORT bool
00952 jackctl_server_start(
00953 jackctl_server *server_ptr)
00954 {
00955 int rc = server_ptr->engine->Start();
00956 bool result = rc >= 0;
00957 if (! result)
00958 {
00959 jack_error("JackServer::Start() failed with %d", rc);
00960 }
00961 return result;
00962 }
00963
00964 EXPORT const char * jackctl_driver_get_name(jackctl_driver *driver_ptr)
00965 {
00966 return driver_ptr->desc_ptr->name;
00967 }
00968
00969 EXPORT const JSList * jackctl_driver_get_parameters(jackctl_driver *driver_ptr)
00970 {
00971 return driver_ptr->parameters;
00972 }
00973
00974 EXPORT jack_driver_desc_t * jackctl_driver_get_desc(jackctl_driver *driver_ptr)
00975 {
00976 return driver_ptr->desc_ptr;
00977 }
00978
00979 EXPORT const char * jackctl_parameter_get_name(jackctl_parameter *parameter_ptr)
00980 {
00981 return parameter_ptr->name;
00982 }
00983
00984 EXPORT const char * jackctl_parameter_get_short_description(jackctl_parameter *parameter_ptr)
00985 {
00986 return parameter_ptr->short_description;
00987 }
00988
00989 EXPORT const char * jackctl_parameter_get_long_description(jackctl_parameter *parameter_ptr)
00990 {
00991 return parameter_ptr->long_description;
00992 }
00993
00994 EXPORT bool jackctl_parameter_has_range_constraint(jackctl_parameter *parameter_ptr)
00995 {
00996 return parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_RANGE) != 0;
00997 }
00998
00999 EXPORT bool jackctl_parameter_has_enum_constraint(jackctl_parameter *parameter_ptr)
01000 {
01001 return parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_RANGE) == 0;
01002 }
01003
01004 EXPORT uint32_t jackctl_parameter_get_enum_constraints_count(jackctl_parameter *parameter_ptr)
01005 {
01006 if (!jackctl_parameter_has_enum_constraint(parameter_ptr))
01007 {
01008 return 0;
01009 }
01010
01011 return parameter_ptr->constraint_ptr->constraint.enumeration.count;
01012 }
01013
01014 EXPORT union jackctl_parameter_value jackctl_parameter_get_enum_constraint_value(jackctl_parameter *parameter_ptr, uint32_t index)
01015 {
01016 jack_driver_param_value_t * value_ptr;
01017 union jackctl_parameter_value jackctl_value;
01018
01019 value_ptr = ¶meter_ptr->constraint_ptr->constraint.enumeration.possible_values_array[index].value;
01020
01021 switch (parameter_ptr->type)
01022 {
01023 case JackParamInt:
01024 jackctl_value.i = value_ptr->i;
01025 break;
01026 case JackParamUInt:
01027 jackctl_value.ui = value_ptr->ui;
01028 break;
01029 case JackParamChar:
01030 jackctl_value.c = value_ptr->c;
01031 break;
01032 case JackParamString:
01033 strcpy(jackctl_value.str, value_ptr->str);
01034 break;
01035 default:
01036 jack_error("bad driver parameter type %i (enum constraint)", (int)parameter_ptr->type);
01037 assert(0);
01038 }
01039
01040 return jackctl_value;
01041 }
01042
01043 EXPORT const char * jackctl_parameter_get_enum_constraint_description(jackctl_parameter *parameter_ptr, uint32_t index)
01044 {
01045 return parameter_ptr->constraint_ptr->constraint.enumeration.possible_values_array[index].short_desc;
01046 }
01047
01048 EXPORT void jackctl_parameter_get_range_constraint(jackctl_parameter *parameter_ptr, union jackctl_parameter_value * min_ptr, union jackctl_parameter_value * max_ptr)
01049 {
01050 switch (parameter_ptr->type)
01051 {
01052 case JackParamInt:
01053 min_ptr->i = parameter_ptr->constraint_ptr->constraint.range.min.i;
01054 max_ptr->i = parameter_ptr->constraint_ptr->constraint.range.max.i;
01055 return;
01056 case JackParamUInt:
01057 min_ptr->ui = parameter_ptr->constraint_ptr->constraint.range.min.ui;
01058 max_ptr->ui = parameter_ptr->constraint_ptr->constraint.range.max.ui;
01059 return;
01060 default:
01061 jack_error("bad driver parameter type %i (range constraint)", (int)parameter_ptr->type);
01062 assert(0);
01063 }
01064 }
01065
01066 EXPORT bool jackctl_parameter_constraint_is_strict(jackctl_parameter_t * parameter_ptr)
01067 {
01068 return parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_STRICT) != 0;
01069 }
01070
01071 EXPORT bool jackctl_parameter_constraint_is_fake_value(jackctl_parameter_t * parameter_ptr)
01072 {
01073 return parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_FAKE_VALUE) != 0;
01074 }
01075
01076 EXPORT jackctl_param_type_t jackctl_parameter_get_type(jackctl_parameter *parameter_ptr)
01077 {
01078 return parameter_ptr->type;
01079 }
01080
01081 EXPORT char jackctl_parameter_get_id(jackctl_parameter_t * parameter_ptr)
01082 {
01083 return parameter_ptr->id;
01084 }
01085
01086 EXPORT bool jackctl_parameter_is_set(jackctl_parameter *parameter_ptr)
01087 {
01088 return parameter_ptr->is_set;
01089 }
01090
01091 EXPORT union jackctl_parameter_value jackctl_parameter_get_value(jackctl_parameter *parameter_ptr)
01092 {
01093 return *parameter_ptr->value_ptr;
01094 }
01095
01096 EXPORT bool jackctl_parameter_reset(jackctl_parameter *parameter_ptr)
01097 {
01098 if (!parameter_ptr->is_set)
01099 {
01100 return true;
01101 }
01102
01103 parameter_ptr->is_set = false;
01104
01105 *parameter_ptr->value_ptr = *parameter_ptr->default_value_ptr;
01106
01107 return true;
01108 }
01109
01110 EXPORT bool jackctl_parameter_set_value(jackctl_parameter *parameter_ptr, const union jackctl_parameter_value * value_ptr)
01111 {
01112 bool new_driver_parameter;
01113
01114
01115 if (parameter_ptr->driver_ptr != NULL)
01116 {
01117
01118 new_driver_parameter = parameter_ptr->driver_parameter_ptr == NULL;
01119 if (new_driver_parameter)
01120 {
01121
01122 parameter_ptr->driver_parameter_ptr = (jack_driver_param_t *)malloc(sizeof(jack_driver_param_t));
01123 if (parameter_ptr->driver_parameter_ptr == NULL)
01124 {
01125 jack_error ("Allocation of jack_driver_param_t structure failed");
01126 return false;
01127 }
01128
01129 parameter_ptr->driver_parameter_ptr->character = parameter_ptr->id;
01130 parameter_ptr->driver_ptr->set_parameters = jack_slist_append(parameter_ptr->driver_ptr->set_parameters, parameter_ptr->driver_parameter_ptr);
01131 }
01132
01133 switch (parameter_ptr->type)
01134 {
01135 case JackParamInt:
01136 parameter_ptr->driver_parameter_ptr->value.i = value_ptr->i;
01137 break;
01138 case JackParamUInt:
01139 parameter_ptr->driver_parameter_ptr->value.ui = value_ptr->ui;
01140 break;
01141 case JackParamChar:
01142 parameter_ptr->driver_parameter_ptr->value.c = value_ptr->c;
01143 break;
01144 case JackParamString:
01145 strcpy(parameter_ptr->driver_parameter_ptr->value.str, value_ptr->str);
01146 break;
01147 case JackParamBool:
01148 parameter_ptr->driver_parameter_ptr->value.i = value_ptr->b;
01149 break;
01150 default:
01151 jack_error("unknown parameter type %i", (int)parameter_ptr->type);
01152 assert(0);
01153
01154 if (new_driver_parameter)
01155 {
01156 parameter_ptr->driver_ptr->set_parameters = jack_slist_remove(parameter_ptr->driver_ptr->set_parameters, parameter_ptr->driver_parameter_ptr);
01157 }
01158
01159 return false;
01160 }
01161 }
01162
01163 parameter_ptr->is_set = true;
01164 *parameter_ptr->value_ptr = *value_ptr;
01165
01166 return true;
01167 }
01168
01169 EXPORT union jackctl_parameter_value jackctl_parameter_get_default_value(jackctl_parameter *parameter_ptr)
01170 {
01171 return *parameter_ptr->default_value_ptr;
01172 }
01173
01174
01175
01176 EXPORT const JSList * jackctl_server_get_internals_list(jackctl_server *server_ptr)
01177 {
01178 return server_ptr->internals;
01179 }
01180
01181 EXPORT const char * jackctl_internal_get_name(jackctl_internal *internal_ptr)
01182 {
01183 return internal_ptr->desc_ptr->name;
01184 }
01185
01186 EXPORT const JSList * jackctl_internal_get_parameters(jackctl_internal *internal_ptr)
01187 {
01188 return internal_ptr->parameters;
01189 }
01190
01191 EXPORT bool jackctl_server_load_internal(
01192 jackctl_server * server_ptr,
01193 jackctl_internal * internal)
01194 {
01195 int status;
01196 if (server_ptr->engine != NULL) {
01197 server_ptr->engine->InternalClientLoad2(internal->desc_ptr->name, internal->desc_ptr->name, internal->set_parameters, JackNullOption, &internal->refnum, -1, &status);
01198 return (internal->refnum > 0);
01199 } else {
01200 return false;
01201 }
01202 }
01203
01204 EXPORT bool jackctl_server_unload_internal(
01205 jackctl_server * server_ptr,
01206 jackctl_internal * internal)
01207 {
01208 int status;
01209 if (server_ptr->engine != NULL && internal->refnum > 0) {
01210
01211 return ((server_ptr->engine->GetEngine()->InternalClientUnload(internal->refnum, &status)) == 0);
01212 } else {
01213 return false;
01214 }
01215 }
01216
01217 EXPORT bool jackctl_server_add_slave(jackctl_server * server_ptr, jackctl_driver * driver_ptr)
01218 {
01219 if (server_ptr->engine != NULL) {
01220 if (server_ptr->engine->IsRunning()) {
01221 jack_error("cannot add a slave in a running server");
01222 return false;
01223 } else {
01224 driver_ptr->info = server_ptr->engine->AddSlave(driver_ptr->desc_ptr, driver_ptr->set_parameters);
01225 return (driver_ptr->info != 0);
01226 }
01227 } else {
01228 return false;
01229 }
01230 }
01231
01232 EXPORT bool jackctl_server_remove_slave(jackctl_server * server_ptr, jackctl_driver * driver_ptr)
01233 {
01234 if (server_ptr->engine != NULL) {
01235 if (server_ptr->engine->IsRunning()) {
01236 jack_error("cannot remove a slave from a running server");
01237 return false;
01238 } else {
01239 server_ptr->engine->RemoveSlave(driver_ptr->info);
01240 delete driver_ptr->info;
01241 return true;
01242 }
01243 } else {
01244 return false;
01245 }
01246 }
01247
01248 EXPORT bool jackctl_server_switch_master(jackctl_server * server_ptr, jackctl_driver * driver_ptr)
01249 {
01250 if (server_ptr->engine != NULL) {
01251 return (server_ptr->engine->SwitchMaster(driver_ptr->desc_ptr, driver_ptr->set_parameters) == 0);
01252 } else {
01253 return false;
01254 }
01255 }
01256