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