00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "JackSystemDeps.h"
00022 #include "JackDriverLoader.h"
00023 #include "JackDriverInfo.h"
00024 #include "JackConstants.h"
00025 #include "JackError.h"
00026 #include <getopt.h>
00027 #include <stdio.h>
00028 #include <errno.h>
00029 #include <string.h>
00030
00031 #ifndef WIN32
00032 #include <dirent.h>
00033 #endif
00034
00035 #ifdef WIN32
00036
00037 static char* locate_dll_driver_dir()
00038 {
00039 #ifdef _WIN64
00040 HMODULE libjack_handle = LoadLibrary("libjackserver64.dll");
00041 #else
00042 HMODULE libjack_handle = LoadLibrary("libjackserver.dll");
00043 #endif
00044
00045
00046 char driver_dir_storage[512];
00047 if (3 < GetModuleFileName(libjack_handle, driver_dir_storage, 512)) {
00048 char *p = strrchr(driver_dir_storage, '\\');
00049 if (p && (p != driver_dir_storage)) {
00050 *p = 0;
00051 }
00052 jack_info("Drivers/internals found in : %s", driver_dir_storage);
00053 strcat(driver_dir_storage, "/");
00054 strcat(driver_dir_storage, ADDON_DIR);
00055 FreeLibrary(libjack_handle);
00056 return strdup(driver_dir_storage);
00057 } else {
00058 jack_error("Cannot get JACK dll directory : %d", GetLastError());
00059 FreeLibrary(libjack_handle);
00060 return NULL;
00061 }
00062 }
00063
00064 static char* locate_driver_dir(HANDLE& file, WIN32_FIND_DATA& filedata)
00065 {
00066
00067 char* driver_dir = locate_dll_driver_dir();
00068 char dll_filename[512];
00069 snprintf(dll_filename, sizeof(dll_filename), "%s/*.dll", driver_dir);
00070 file = (HANDLE)FindFirstFile(dll_filename, &filedata);
00071
00072 if (file == INVALID_HANDLE_VALUE) {
00073 jack_error("Drivers not found ");
00074 free(driver_dir);
00075 return NULL;
00076 } else {
00077 return driver_dir;
00078 }
00079 }
00080
00081 #endif
00082
00083 jack_driver_desc_t* jackctl_driver_get_desc(jackctl_driver_t * driver);
00084
00085 void jack_print_driver_options(jack_driver_desc_t* desc, FILE* file)
00086 {
00087 unsigned long i;
00088 char arg_default[JACK_DRIVER_PARAM_STRING_MAX + 1];
00089
00090 for (i = 0; i < desc->nparams; i++) {
00091 switch (desc->params[i].type) {
00092 case JackDriverParamInt:
00093 sprintf (arg_default, "%" "i", desc->params[i].value.i);
00094 break;
00095 case JackDriverParamUInt:
00096 sprintf (arg_default, "%" "u", desc->params[i].value.ui);
00097 break;
00098 case JackDriverParamChar:
00099 sprintf (arg_default, "%c", desc->params[i].value.c);
00100 break;
00101 case JackDriverParamString:
00102 if (desc->params[i].value.str && strcmp (desc->params[i].value.str, "") != 0) {
00103 sprintf (arg_default, "%s", desc->params[i].value.str);
00104 } else {
00105 sprintf (arg_default, "none");
00106 }
00107 break;
00108 case JackDriverParamBool:
00109 sprintf (arg_default, "%s", desc->params[i].value.i ? "true" : "false");
00110 break;
00111 }
00112
00113 fprintf(file, "\t-%c, --%s \t%s (default: %s)\n",
00114 desc->params[i].character,
00115 desc->params[i].name,
00116 desc->params[i].long_desc,
00117 arg_default);
00118 }
00119 }
00120
00121 static void jack_print_driver_param_usage (jack_driver_desc_t* desc, unsigned long param, FILE *file)
00122 {
00123 fprintf (file, "Usage information for the '%s' parameter for driver '%s':\n",
00124 desc->params[param].name, desc->name);
00125 fprintf (file, "%s\n", desc->params[param].long_desc);
00126 }
00127
00128 void jack_free_driver_params(JSList * driver_params)
00129 {
00130 JSList*node_ptr = driver_params;
00131 JSList*next_node_ptr;
00132
00133 while (node_ptr) {
00134 next_node_ptr = node_ptr->next;
00135 free(node_ptr->data);
00136 free(node_ptr);
00137 node_ptr = next_node_ptr;
00138 }
00139 }
00140
00141 int jack_parse_driver_params(jack_driver_desc_t* desc, int argc, char* argv[], JSList** param_ptr)
00142 {
00143 struct option * long_options;
00144 char* options, * options_ptr;
00145 unsigned long i;
00146 int opt;
00147 unsigned int param_index;
00148 JSList* params = NULL;
00149 jack_driver_param_t * driver_param;
00150
00151 if (argc <= 1) {
00152 *param_ptr = NULL;
00153 return 0;
00154 }
00155
00156
00157 if (strcmp (argv[1], "-h") == 0 || strcmp (argv[1], "--help") == 0) {
00158 if (argc > 2) {
00159 for (i = 0; i < desc->nparams; i++) {
00160 if (strcmp (desc->params[i].name, argv[2]) == 0) {
00161 jack_print_driver_param_usage (desc, i, stdout);
00162 return 1;
00163 }
00164 }
00165
00166 fprintf (stderr, "Jackd: unknown option '%s' "
00167 "for driver '%s'\n", argv[2],
00168 desc->name);
00169 }
00170
00171 jack_log("Parameters for driver '%s' (all parameters are optional):", desc->name);
00172 jack_print_driver_options (desc, stdout);
00173 return 1;
00174 }
00175
00176
00177 options = (char*)calloc (desc->nparams * 3 + 1, sizeof (char));
00178 long_options = (option*)calloc (desc->nparams + 1, sizeof (struct option));
00179
00180 options_ptr = options;
00181 for (i = 0; i < desc->nparams; i++) {
00182 sprintf (options_ptr, "%c::", desc->params[i].character);
00183 options_ptr += 3;
00184 long_options[i].name = desc->params[i].name;
00185 long_options[i].flag = NULL;
00186 long_options[i].val = desc->params[i].character;
00187 long_options[i].has_arg = optional_argument;
00188 }
00189
00190
00191 optind = 0;
00192 opterr = 0;
00193 while ((opt = getopt_long(argc, argv, options, long_options, NULL)) != -1) {
00194
00195 if (opt == ':' || opt == '?') {
00196 if (opt == ':') {
00197 fprintf (stderr, "Missing option to argument '%c'\n", optopt);
00198 } else {
00199 fprintf (stderr, "Unknownage with option '%c'\n", optopt);
00200 }
00201
00202 fprintf (stderr, "Options for driver '%s':\n", desc->name);
00203 jack_print_driver_options (desc, stderr);
00204 return 1;
00205 }
00206
00207 for (param_index = 0; param_index < desc->nparams; param_index++) {
00208 if (opt == desc->params[param_index].character) {
00209 break;
00210 }
00211 }
00212
00213 driver_param = (jack_driver_param_t*)calloc (1, sizeof (jack_driver_param_t));
00214 driver_param->character = desc->params[param_index].character;
00215
00216 if (!optarg && optind < argc &&
00217 strlen(argv[optind]) &&
00218 argv[optind][0] != '-') {
00219 optarg = argv[optind];
00220 }
00221
00222 if (optarg) {
00223 switch (desc->params[param_index].type) {
00224 case JackDriverParamInt:
00225 driver_param->value.i = atoi(optarg);
00226 break;
00227 case JackDriverParamUInt:
00228 driver_param->value.ui = strtoul(optarg, NULL, 10);
00229 break;
00230 case JackDriverParamChar:
00231 driver_param->value.c = optarg[0];
00232 break;
00233 case JackDriverParamString:
00234 strncpy (driver_param->value.str, optarg, JACK_DRIVER_PARAM_STRING_MAX);
00235 break;
00236 case JackDriverParamBool:
00237 if (strcasecmp("false", optarg) == 0 ||
00238 strcasecmp("off", optarg) == 0 ||
00239 strcasecmp("no", optarg) == 0 ||
00240 strcasecmp("0", optarg) == 0 ||
00241 strcasecmp("(null)", optarg) == 0 ) {
00242 driver_param->value.i = false;
00243 } else {
00244 driver_param->value.i = true;
00245 }
00246 break;
00247 }
00248 } else {
00249 if (desc->params[param_index].type == JackDriverParamBool) {
00250 driver_param->value.i = true;
00251 } else {
00252 driver_param->value = desc->params[param_index].value;
00253 }
00254 }
00255
00256 params = jack_slist_append (params, driver_param);
00257 }
00258
00259 free (options);
00260 free (long_options);
00261
00262 if (param_ptr) {
00263 *param_ptr = params;
00264 }
00265 return 0;
00266 }
00267
00268 SERVER_EXPORT int jackctl_driver_params_parse(jackctl_driver *driver_ptr, int argc, char* argv[])
00269 {
00270 struct option* long_options;
00271 char* options, * options_ptr;
00272 unsigned long i;
00273 int opt;
00274 JSList* node_ptr;
00275 jackctl_parameter_t * param = NULL;
00276 union jackctl_parameter_value value;
00277
00278 if (argc <= 1) {
00279 return 0;
00280 }
00281
00282 const JSList* driver_params = jackctl_driver_get_parameters(driver_ptr);
00283 if (driver_params == NULL) {
00284 return 1;
00285 }
00286
00287 jack_driver_desc_t* desc = jackctl_driver_get_desc(driver_ptr);
00288
00289
00290 if (strcmp (argv[1], "-h") == 0 || strcmp (argv[1], "--help") == 0) {
00291 if (argc > 2) {
00292 for (i = 0; i < desc->nparams; i++) {
00293 if (strcmp (desc->params[i].name, argv[2]) == 0) {
00294 jack_print_driver_param_usage (desc, i, stdout);
00295 return 1;
00296 }
00297 }
00298
00299 fprintf (stderr, "Jackd: unknown option '%s' "
00300 "for driver '%s'\n", argv[2],
00301 desc->name);
00302 }
00303
00304 jack_log("Parameters for driver '%s' (all parameters are optional):", desc->name);
00305 jack_print_driver_options (desc, stdout);
00306 return 1;
00307 }
00308
00309
00310 options = (char*)calloc (desc->nparams * 3 + 1, sizeof (char));
00311 long_options = (option*)calloc (desc->nparams + 1, sizeof (struct option));
00312
00313 options_ptr = options;
00314 for (i = 0; i < desc->nparams; i++) {
00315 sprintf(options_ptr, "%c::", desc->params[i].character);
00316 options_ptr += 3;
00317 long_options[i].name = desc->params[i].name;
00318 long_options[i].flag = NULL;
00319 long_options[i].val = desc->params[i].character;
00320 long_options[i].has_arg = optional_argument;
00321 }
00322
00323
00324 optind = 0;
00325 opterr = 0;
00326 while ((opt = getopt_long(argc, argv, options, long_options, NULL)) != -1) {
00327
00328 if (opt == ':' || opt == '?') {
00329 if (opt == ':') {
00330 fprintf (stderr, "Missing option to argument '%c'\n", optopt);
00331 } else {
00332 fprintf (stderr, "Unknownage with option '%c'\n", optopt);
00333 }
00334
00335 fprintf (stderr, "Options for driver '%s':\n", desc->name);
00336 jack_print_driver_options(desc, stderr);
00337 return 1;
00338 }
00339
00340 node_ptr = (JSList *)driver_params;
00341 while (node_ptr) {
00342 param = (jackctl_parameter_t*)node_ptr->data;
00343 if (opt == jackctl_parameter_get_id(param)) {
00344 break;
00345 }
00346 node_ptr = node_ptr->next;
00347 }
00348
00349 if (!optarg && optind < argc &&
00350 strlen(argv[optind]) &&
00351 argv[optind][0] != '-') {
00352 optarg = argv[optind];
00353 }
00354
00355 if (optarg) {
00356 switch (jackctl_parameter_get_type(param)) {
00357 case JackDriverParamInt:
00358 value.i = atoi(optarg);
00359 jackctl_parameter_set_value(param, &value);
00360 break;
00361 case JackDriverParamUInt:
00362 value.ui = strtoul(optarg, NULL, 10);
00363 jackctl_parameter_set_value(param, &value);
00364 break;
00365 case JackDriverParamChar:
00366 value.c = optarg[0];
00367 jackctl_parameter_set_value(param, &value);
00368 break;
00369 case JackDriverParamString:
00370 strncpy(value.str, optarg, JACK_DRIVER_PARAM_STRING_MAX);
00371 jackctl_parameter_set_value(param, &value);
00372 break;
00373 case JackDriverParamBool:
00374 if (strcasecmp("false", optarg) == 0 ||
00375 strcasecmp("off", optarg) == 0 ||
00376 strcasecmp("no", optarg) == 0 ||
00377 strcasecmp("0", optarg) == 0 ||
00378 strcasecmp("(null)", optarg) == 0 ) {
00379 value.i = false;
00380 } else {
00381 value.i = true;
00382 }
00383 jackctl_parameter_set_value(param, &value);
00384 break;
00385 }
00386 } else {
00387 if (jackctl_parameter_get_type(param) == JackParamBool) {
00388 value.i = true;
00389 } else {
00390 value = jackctl_parameter_get_default_value(param);
00391 }
00392 jackctl_parameter_set_value(param, &value);
00393 }
00394 }
00395
00396 free(options);
00397 free(long_options);
00398 return 0;
00399 }
00400
00401 jack_driver_desc_t* jack_find_driver_descriptor (JSList * drivers, const char* name)
00402 {
00403 jack_driver_desc_t* desc = 0;
00404 JSList* node;
00405
00406 for (node = drivers; node; node = jack_slist_next (node)) {
00407 desc = (jack_driver_desc_t*) node->data;
00408
00409 if (strcmp (desc->name, name) != 0) {
00410 desc = NULL;
00411 } else {
00412 break;
00413 }
00414 }
00415
00416 return desc;
00417 }
00418
00419 static void* check_symbol(const char* sofile, const char* symbol, const char* driver_dir, void** res_dllhandle = NULL)
00420 {
00421 void* dlhandle;
00422 void* res = NULL;
00423 char filename[1024];
00424 sprintf(filename, "%s/%s", driver_dir, sofile);
00425
00426 if ((dlhandle = LoadDriverModule(filename)) == NULL) {
00427 #ifdef WIN32
00428 jack_error ("Could not open component .dll '%s': %ld", filename, GetLastError());
00429 #else
00430 jack_error ("Could not open component .so '%s': %s", filename, dlerror());
00431 #endif
00432 } else {
00433 res = (void*)GetDriverProc(dlhandle, symbol);
00434 if (res_dllhandle) {
00435 *res_dllhandle = dlhandle;
00436 } else {
00437 UnloadDriverModule(dlhandle);
00438 }
00439 }
00440
00441 return res;
00442 }
00443
00444 static jack_driver_desc_t* jack_get_descriptor (JSList* drivers, const char* sofile, const char* symbol, const char* driver_dir)
00445 {
00446 jack_driver_desc_t* descriptor = NULL;
00447 jack_driver_desc_t* other_descriptor;
00448 JackDriverDescFunction so_get_descriptor = NULL;
00449 char filename[1024];
00450 JSList* node;
00451 void* dlhandle = NULL;
00452
00453 sprintf(filename, "%s/%s", driver_dir, sofile);
00454 so_get_descriptor = (JackDriverDescFunction)check_symbol(sofile, symbol, driver_dir, &dlhandle);
00455
00456 if (so_get_descriptor == NULL) {
00457 jack_error("jack_get_descriptor : dll %s is not a driver", sofile);
00458 goto error;
00459 }
00460
00461 if ((descriptor = so_get_descriptor ()) == NULL) {
00462 jack_error("Driver from '%s' returned NULL descriptor", filename);
00463 goto error;
00464 }
00465
00466
00467 for (node = drivers; node; node = jack_slist_next (node)) {
00468 other_descriptor = (jack_driver_desc_t*) node->data;
00469 if (strcmp(descriptor->name, other_descriptor->name) == 0) {
00470 jack_error("The drivers in '%s' and '%s' both have the name '%s'; using the first",
00471 other_descriptor->file, filename, other_descriptor->name);
00472
00473 goto error;
00474 }
00475 }
00476
00477 strncpy(descriptor->file, filename, JACK_PATH_MAX);
00478
00479 error:
00480 if (dlhandle) {
00481 UnloadDriverModule(dlhandle);
00482 }
00483 return descriptor;
00484 }
00485
00486 #ifdef WIN32
00487
00488 JSList * jack_drivers_load(JSList * drivers)
00489 {
00490
00491 WIN32_FIND_DATA filedata;
00492 HANDLE file;
00493 const char* ptr = NULL;
00494 JSList* driver_list = NULL;
00495 jack_driver_desc_t* desc = NULL;
00496
00497 char* driver_dir = locate_driver_dir(file, filedata);
00498 if (!driver_dir) {
00499 jack_error("Driver folder not found");
00500 goto error;
00501 }
00502
00503 do {
00504
00505 if (strncmp ("jack_", filedata.cFileName, 5) != 0) {
00506 continue;
00507 }
00508
00509 ptr = strrchr (filedata.cFileName, '.');
00510 if (!ptr) {
00511 continue;
00512 }
00513
00514 ptr++;
00515 if (strncmp ("dll", ptr, 3) != 0) {
00516 continue;
00517 }
00518
00519
00520 if (check_symbol(filedata.cFileName, "jack_internal_initialize", driver_dir) != NULL) {
00521 continue;
00522 }
00523
00524 desc = jack_get_descriptor (drivers, filedata.cFileName, "driver_get_descriptor", driver_dir);
00525 if (desc) {
00526 driver_list = jack_slist_append (driver_list, desc);
00527 } else {
00528 jack_error ("jack_get_descriptor returns null for \'%s\'", filedata.cFileName);
00529 }
00530
00531 } while (FindNextFile(file, &filedata));
00532
00533 if (!driver_list) {
00534 jack_error ("Could not find any drivers in %s!", driver_dir);
00535 }
00536
00537 error:
00538 if (driver_dir) {
00539 free(driver_dir);
00540 }
00541 FindClose(file);
00542 return driver_list;
00543 }
00544
00545 #else
00546
00547 JSList* jack_drivers_load (JSList * drivers)
00548 {
00549 struct dirent * dir_entry;
00550 DIR * dir_stream;
00551 const char* ptr;
00552 int err;
00553 JSList* driver_list = NULL;
00554 jack_driver_desc_t* desc = NULL;
00555
00556 const char* driver_dir;
00557 if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) {
00558 driver_dir = ADDON_DIR;
00559 }
00560
00561
00562
00563 dir_stream = opendir (driver_dir);
00564 if (!dir_stream) {
00565 jack_error ("Could not open driver directory %s: %s",
00566 driver_dir, strerror (errno));
00567 return NULL;
00568 }
00569
00570 while ((dir_entry = readdir(dir_stream))) {
00571
00572
00573 if (strncmp ("jack_", dir_entry->d_name, 5) != 0) {
00574 continue;
00575 }
00576
00577 ptr = strrchr (dir_entry->d_name, '.');
00578 if (!ptr) {
00579 continue;
00580 }
00581 ptr++;
00582 if (strncmp ("so", ptr, 2) != 0) {
00583 continue;
00584 }
00585
00586
00587 if (check_symbol(dir_entry->d_name, "jack_internal_initialize", driver_dir) != NULL) {
00588 continue;
00589 }
00590
00591 desc = jack_get_descriptor (drivers, dir_entry->d_name, "driver_get_descriptor", driver_dir);
00592 if (desc) {
00593 driver_list = jack_slist_append (driver_list, desc);
00594 } else {
00595 jack_error ("jack_get_descriptor returns null for \'%s\'", dir_entry->d_name);
00596 }
00597 }
00598
00599 err = closedir (dir_stream);
00600 if (err) {
00601 jack_error ("Error closing driver directory %s: %s",
00602 driver_dir, strerror (errno));
00603 }
00604
00605 if (!driver_list) {
00606 jack_error ("Could not find any drivers in %s!", driver_dir);
00607 return NULL;
00608 }
00609
00610 return driver_list;
00611 }
00612
00613 #endif
00614
00615 #ifdef WIN32
00616
00617 JSList* jack_internals_load(JSList * internals)
00618 {
00620 WIN32_FIND_DATA filedata;
00621 HANDLE file;
00622 const char* ptr = NULL;
00623 JSList* driver_list = NULL;
00624 jack_driver_desc_t* desc;
00625
00626 char* driver_dir = locate_driver_dir(file, filedata);
00627 if (!driver_dir) {
00628 jack_error("Driver folder not found");
00629 goto error;
00630 }
00631
00632 do {
00633
00634 ptr = strrchr (filedata.cFileName, '.');
00635 if (!ptr) {
00636 continue;
00637 }
00638
00639 ptr++;
00640 if (strncmp ("dll", ptr, 3) != 0) {
00641 continue;
00642 }
00643
00644
00645 if (check_symbol(filedata.cFileName, "jack_internal_initialize", driver_dir) == NULL) {
00646 continue;
00647 }
00648
00649 desc = jack_get_descriptor (internals, filedata.cFileName, "jack_get_descriptor", driver_dir);
00650 if (desc) {
00651 driver_list = jack_slist_append (driver_list, desc);
00652 } else {
00653 jack_error ("jack_get_descriptor returns null for \'%s\'", filedata.cFileName);
00654 }
00655
00656 } while (FindNextFile(file, &filedata));
00657
00658 if (!driver_list) {
00659 jack_error ("Could not find any internals in %s!", driver_dir);
00660 }
00661
00662 error:
00663 if (driver_dir) {
00664 free(driver_dir);
00665 }
00666 FindClose(file);
00667 return driver_list;
00668 }
00669
00670 #else
00671
00672 JSList* jack_internals_load(JSList * internals)
00673 {
00674 struct dirent * dir_entry;
00675 DIR * dir_stream;
00676 const char* ptr;
00677 int err;
00678 JSList* driver_list = NULL;
00679 jack_driver_desc_t* desc;
00680
00681 const char* driver_dir;
00682 if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) {
00683 driver_dir = ADDON_DIR;
00684 }
00685
00686
00687
00688 dir_stream = opendir (driver_dir);
00689 if (!dir_stream) {
00690 jack_error ("Could not open driver directory %s: %s\n",
00691 driver_dir, strerror (errno));
00692 return NULL;
00693 }
00694
00695 while ((dir_entry = readdir(dir_stream))) {
00696
00697 ptr = strrchr (dir_entry->d_name, '.');
00698 if (!ptr) {
00699 continue;
00700 }
00701
00702 ptr++;
00703 if (strncmp ("so", ptr, 2) != 0) {
00704 continue;
00705 }
00706
00707
00708 if (check_symbol(dir_entry->d_name, "jack_internal_initialize", driver_dir) == NULL) {
00709 continue;
00710 }
00711
00712 desc = jack_get_descriptor (internals, dir_entry->d_name, "jack_get_descriptor", driver_dir);
00713 if (desc) {
00714 driver_list = jack_slist_append (driver_list, desc);
00715 } else {
00716 jack_error ("jack_get_descriptor returns null for \'%s\'", dir_entry->d_name);
00717 }
00718 }
00719
00720 err = closedir (dir_stream);
00721 if (err) {
00722 jack_error ("Error closing internal directory %s: %s\n",
00723 driver_dir, strerror (errno));
00724 }
00725
00726 if (!driver_list) {
00727 jack_error ("Could not find any internals in %s!", driver_dir);
00728 return NULL;
00729 }
00730
00731 return driver_list;
00732 }
00733
00734 #endif
00735
00736 Jack::JackDriverClientInterface* JackDriverInfo::Open(jack_driver_desc_t* driver_desc,
00737 Jack::JackLockedEngine* engine,
00738 Jack::JackSynchro* synchro,
00739 const JSList* params)
00740 {
00741 #ifdef WIN32
00742 int errstr;
00743 #else
00744 const char* errstr;
00745 #endif
00746
00747 fHandle = LoadDriverModule (driver_desc->file);
00748
00749 if (fHandle == NULL) {
00750 #ifdef WIN32
00751 if ((errstr = GetLastError ()) != 0) {
00752 jack_error ("Can't load \"%s\": %ld", driver_desc->file, errstr);
00753 #else
00754 if ((errstr = dlerror ()) != 0) {
00755 jack_error ("Can't load \"%s\": %s", driver_desc->file, errstr);
00756 #endif
00757
00758 } else {
00759 jack_error ("Error loading driver shared object %s", driver_desc->file);
00760 }
00761 return NULL;
00762 }
00763
00764 fInitialize = (driverInitialize)GetDriverProc(fHandle, "driver_initialize");
00765
00766 #ifdef WIN32
00767 if ((fInitialize == NULL) && (errstr = GetLastError ()) != 0) {
00768 #else
00769 if ((fInitialize == NULL) && (errstr = dlerror ()) != 0) {
00770 #endif
00771 jack_error("No initialize function in shared object %s\n", driver_desc->file);
00772 return NULL;
00773 }
00774
00775 fBackend = fInitialize(engine, synchro, params);
00776 return fBackend;
00777 }
00778
00779 JackDriverInfo::~JackDriverInfo()
00780 {
00781 delete fBackend;
00782 if (fHandle) {
00783 UnloadDriverModule(fHandle);
00784 }
00785 }
00786
00787 SERVER_EXPORT jack_driver_desc_t* jack_driver_descriptor_construct(
00788 const char * name,
00789 jack_driver_type_t type,
00790 const char * description,
00791 jack_driver_desc_filler_t * filler_ptr)
00792 {
00793 size_t name_len;
00794 size_t description_len;
00795 jack_driver_desc_t* desc_ptr;
00796
00797 name_len = strlen(name);
00798 description_len = strlen(description);
00799
00800 if (name_len > sizeof(desc_ptr->name) - 1 ||
00801 description_len > sizeof(desc_ptr->desc) - 1) {
00802 assert(false);
00803 return 0;
00804 }
00805
00806 desc_ptr = (jack_driver_desc_t*)calloc (1, sizeof (jack_driver_desc_t));
00807 if (desc_ptr == NULL) {
00808 jack_error("Error calloc() failed to allocate memory for driver descriptor struct");
00809 return 0;
00810 }
00811
00812 memcpy(desc_ptr->name, name, name_len + 1);
00813 memcpy(desc_ptr->desc, description, description_len + 1);
00814
00815 desc_ptr->nparams = 0;
00816 desc_ptr->type = type;
00817
00818 if (filler_ptr != NULL) {
00819 filler_ptr->size = 0;
00820 }
00821
00822 return desc_ptr;
00823 }
00824
00825 SERVER_EXPORT int jack_driver_descriptor_add_parameter(
00826 jack_driver_desc_t* desc_ptr,
00827 jack_driver_desc_filler_t * filler_ptr,
00828 const char* name,
00829 char character,
00830 jack_driver_param_type_t type,
00831 const jack_driver_param_value_t * value_ptr,
00832 jack_driver_param_constraint_desc_t * constraint,
00833 const char* short_desc,
00834 const char* long_desc)
00835 {
00836 size_t name_len;
00837 size_t short_desc_len;
00838 size_t long_desc_len;
00839 jack_driver_param_desc_t * param_ptr;
00840 size_t newsize;
00841
00842 name_len = strlen(name);
00843 short_desc_len = strlen(short_desc);
00844
00845 if (long_desc != NULL) {
00846 long_desc_len = strlen(long_desc);
00847 } else {
00848 long_desc = short_desc;
00849 long_desc_len = short_desc_len;
00850 }
00851
00852 if (name_len > sizeof(param_ptr->name) - 1 ||
00853 short_desc_len > sizeof(param_ptr->short_desc) - 1 ||
00854 long_desc_len > sizeof(param_ptr->long_desc) - 1) {
00855 assert(false);
00856 return 0;
00857 }
00858
00859 if (desc_ptr->nparams == filler_ptr->size) {
00860 newsize = filler_ptr->size + 20;
00861 param_ptr = (jack_driver_param_desc_t*)realloc (desc_ptr->params, newsize * sizeof (jack_driver_param_desc_t));
00862 if (param_ptr == NULL) {
00863 jack_error("Error realloc() failed for parameter array of %zu elements", newsize);
00864 return false;
00865 }
00866 filler_ptr->size = newsize;
00867 desc_ptr->params = param_ptr;
00868 }
00869
00870 assert(desc_ptr->nparams < filler_ptr->size);
00871 param_ptr = desc_ptr->params + desc_ptr->nparams;
00872
00873 memcpy(param_ptr->name, name, name_len + 1);
00874 param_ptr->character = character;
00875 param_ptr->type = type;
00876 param_ptr->value = *value_ptr;
00877 param_ptr->constraint = constraint;
00878 memcpy(param_ptr->short_desc, short_desc, short_desc_len + 1);
00879 memcpy(param_ptr->long_desc, long_desc, long_desc_len + 1);
00880
00881 desc_ptr->nparams++;
00882 return true;
00883 }
00884
00885 SERVER_EXPORT
00886 int
00887 jack_constraint_add_enum(
00888 jack_driver_param_constraint_desc_t ** constraint_ptr_ptr,
00889 uint32_t * array_size_ptr,
00890 jack_driver_param_value_t * value_ptr,
00891 const char * short_desc)
00892 {
00893 jack_driver_param_constraint_desc_t * constraint_ptr;
00894 uint32_t array_size;
00895 jack_driver_param_value_enum_t * possible_value_ptr;
00896 size_t len;
00897
00898 len = strlen(short_desc) + 1;
00899 if (len > sizeof(possible_value_ptr->short_desc))
00900 {
00901 assert(false);
00902 return false;
00903 }
00904
00905 constraint_ptr = *constraint_ptr_ptr;
00906 if (constraint_ptr == NULL)
00907 {
00908 constraint_ptr = (jack_driver_param_constraint_desc_t *)calloc(1, sizeof(jack_driver_param_constraint_desc_t));
00909 if (constraint_ptr == NULL)
00910 {
00911 jack_error("calloc() failed to allocate memory for param constraint struct");
00912 return false;
00913 }
00914
00915 array_size = 0;
00916 }
00917 else
00918 {
00919 array_size = *array_size_ptr;
00920 }
00921
00922 if (constraint_ptr->constraint.enumeration.count == array_size)
00923 {
00924 array_size += 10;
00925 possible_value_ptr =
00926 (jack_driver_param_value_enum_t *)realloc(
00927 constraint_ptr->constraint.enumeration.possible_values_array,
00928 sizeof(jack_driver_param_value_enum_t) * array_size);
00929 if (possible_value_ptr == NULL)
00930 {
00931 jack_error("calloc() failed to (re)allocate memory for possible values array");
00932 return false;
00933 }
00934 constraint_ptr->constraint.enumeration.possible_values_array = possible_value_ptr;
00935 }
00936 else
00937 {
00938 possible_value_ptr = constraint_ptr->constraint.enumeration.possible_values_array;
00939 }
00940
00941 possible_value_ptr += constraint_ptr->constraint.enumeration.count;
00942 constraint_ptr->constraint.enumeration.count++;
00943
00944 possible_value_ptr->value = *value_ptr;
00945 memcpy(possible_value_ptr->short_desc, short_desc, len);
00946
00947 *constraint_ptr_ptr = constraint_ptr;
00948 *array_size_ptr = array_size;
00949
00950 return true;
00951 }
00952
00953 SERVER_EXPORT
00954 void
00955 jack_constraint_free(
00956 jack_driver_param_constraint_desc_t * constraint_ptr)
00957 {
00958 if (constraint_ptr != NULL)
00959 {
00960 if ((constraint_ptr->flags & JACK_CONSTRAINT_FLAG_RANGE) == 0)
00961 {
00962 free(constraint_ptr->constraint.enumeration.possible_values_array);
00963 }
00964
00965 free(constraint_ptr);
00966 }
00967 }
00968
00969 #define JACK_CONSTRAINT_COMPOSE_ENUM_IMPL(type, copy) \
00970 JACK_CONSTRAINT_COMPOSE_ENUM(type) \
00971 { \
00972 jack_driver_param_constraint_desc_t * constraint_ptr; \
00973 uint32_t array_size; \
00974 jack_driver_param_value_t value; \
00975 struct jack_constraint_enum_ ## type ## _descriptor * descr_ptr; \
00976 \
00977 constraint_ptr = NULL; \
00978 for (descr_ptr = descr_array_ptr; \
00979 descr_ptr->value; \
00980 descr_ptr++) \
00981 { \
00982 copy; \
00983 if (!jack_constraint_add_enum( \
00984 &constraint_ptr, \
00985 &array_size, \
00986 &value, \
00987 descr_ptr->short_desc)) \
00988 { \
00989 jack_constraint_free(constraint_ptr); \
00990 return NULL; \
00991 } \
00992 } \
00993 \
00994 constraint_ptr->flags = flags; \
00995 \
00996 return constraint_ptr; \
00997 }
00998
00999 JACK_CONSTRAINT_COMPOSE_ENUM_IMPL(uint32, value.c = descr_ptr->value);
01000 JACK_CONSTRAINT_COMPOSE_ENUM_IMPL(sint32, value.c = descr_ptr->value);
01001 JACK_CONSTRAINT_COMPOSE_ENUM_IMPL(char, value.c = descr_ptr->value);
01002 JACK_CONSTRAINT_COMPOSE_ENUM_IMPL(str, strcpy(value.str, descr_ptr->value));