Jack2 1.9.10
|
00001 /* 00002 Copyright (C) 2001-2005 Paul Davis 00003 Copyright (C) 2004-2008 Grame 00004 00005 This program is free software; you can redistribute it and/or modify 00006 it under the terms of the GNU General Public License as published by 00007 the Free Software Foundation; either version 2 of the License, or 00008 (at your option) any later version. 00009 00010 This program is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License 00016 along with this program; if not, write to the Free Software 00017 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 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 // For WIN32 ADDON_DIR is defined in JackConstants.h as relative path 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 // Search drivers/internals iin the same folder of "libjackserver.dll" 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 /* check for help */ 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 /* set up the stuff for getopt */ 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 /* create the params */ 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 /* check for help */ 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 /* set up the stuff for getopt */ 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 /* create the params */ 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 /* check it doesn't exist already */ 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 /* FIXME: delete the descriptor */ 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 //char dll_filename[512]; 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 /* check the filename is of the right format */ 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 /* check if dll is an internal client */ 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 /* search through the driver_dir and add get descriptors 00562 from the .so files in it */ 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 /* check the filename is of the right format */ 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 /* check if dll is an internal client */ 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 /* check if dll is an internal client */ 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 /* search through the driver_dir and add get descriptors 00687 from the .so files in it */ 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 /* check if dll is an internal client */ 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; // most drivers have less than 20 parameters 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));