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