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