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 "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
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
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
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
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
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
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
00393
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
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
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
00486
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
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
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
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
00617
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
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
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
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
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
00758
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
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;
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 }