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