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