00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifdef WIN32
00022 #pragma warning (disable : 4786)
00023 #endif
00024
00025 #ifndef WIN32
00026 #ifndef ADDON_DIR
00027 #include "config.h"
00028 #endif
00029 #endif
00030
00031 #include "JackDriverLoader.h"
00032 #include "JackError.h"
00033 #include <getopt.h>
00034
00035 #ifndef WIN32
00036 #include <dirent.h>
00037 #endif
00038
00039 static void
00040 jack_print_driver_options (jack_driver_desc_t * desc, FILE *file)
00041 {
00042 unsigned long i;
00043 char arg_default[JACK_DRIVER_PARAM_STRING_MAX + 1];
00044
00045 for (i = 0; i < desc->nparams; i++) {
00046 switch (desc->params[i].type) {
00047 case JackDriverParamInt:
00048
00049 sprintf (arg_default, "%" "i", desc->params[i].value.i);
00050 break;
00051 case JackDriverParamUInt:
00052
00053 sprintf (arg_default, "%" "u", desc->params[i].value.ui);
00054 break;
00055 case JackDriverParamChar:
00056 sprintf (arg_default, "%c", desc->params[i].value.c);
00057 break;
00058 case JackDriverParamString:
00059 if (desc->params[i].value.str && strcmp (desc->params[i].value.str, "") != 0)
00060 sprintf (arg_default, "%s", desc->params[i].value.str);
00061 else
00062 sprintf (arg_default, "none");
00063 break;
00064 case JackDriverParamBool:
00065 sprintf (arg_default, "%s", desc->params[i].value.i ? "true" : "false");
00066 break;
00067 }
00068
00069 fprintf (file, "\t-%c, --%s \t%s (default: %s)\n",
00070 desc->params[i].character,
00071 desc->params[i].name,
00072 desc->params[i].short_desc,
00073 arg_default);
00074 }
00075 }
00076
00077 static void
00078 jack_print_driver_param_usage (jack_driver_desc_t * desc, unsigned long param, FILE *file)
00079 {
00080 fprintf (file, "Usage information for the '%s' parameter for driver '%s':\n",
00081 desc->params[param].name, desc->name);
00082 fprintf (file, "%s\n", desc->params[param].long_desc);
00083 }
00084
00085 EXPORT int
00086 jack_parse_driver_params (jack_driver_desc_t * desc, int argc, char* argv[], JSList ** param_ptr)
00087 {
00088 struct option * long_options;
00089 char * options, * options_ptr;
00090 unsigned long i;
00091 int opt;
00092 unsigned int param_index;
00093 JSList * params = NULL;
00094 jack_driver_param_t * driver_param;
00095
00096 if (argc <= 1) {
00097 *param_ptr = NULL;
00098 return 0;
00099 }
00100
00101
00102 if (strcmp (argv[1], "-h") == 0 || strcmp (argv[1], "--help") == 0) {
00103 if (argc > 2) {
00104 for (i = 0; i < desc->nparams; i++) {
00105 if (strcmp (desc->params[i].name, argv[2]) == 0) {
00106 jack_print_driver_param_usage (desc, i, stdout);
00107 return 1;
00108 }
00109 }
00110
00111 fprintf (stderr, "jackd: unknown option '%s' "
00112 "for driver '%s'\n", argv[2],
00113 desc->name);
00114 }
00115
00116 printf ("Parameters for driver '%s' (all parameters are optional):\n", desc->name);
00117 jack_print_driver_options (desc, stdout);
00118 return 1;
00119 }
00120
00121
00122 options = (char*)calloc (desc->nparams * 3 + 1, sizeof (char));
00123 long_options = (option*)calloc (desc->nparams + 1, sizeof (struct option));
00124
00125 options_ptr = options;
00126 for (i = 0; i < desc->nparams; i++) {
00127 sprintf (options_ptr, "%c::", desc->params[i].character);
00128 options_ptr += 3;
00129 long_options[i].name = desc->params[i].name;
00130 long_options[i].flag = NULL;
00131 long_options[i].val = desc->params[i].character;
00132 long_options[i].has_arg = optional_argument;
00133 }
00134
00135
00136 optind = 0;
00137 opterr = 0;
00138 while ((opt = getopt_long(argc, argv, options, long_options, NULL)) != -1) {
00139
00140 if (opt == ':' || opt == '?') {
00141 if (opt == ':') {
00142 fprintf (stderr, "Missing option to argument '%c'\n", optopt);
00143 } else {
00144 fprintf (stderr, "Unknownage with option '%c'\n", optopt);
00145 }
00146
00147 fprintf (stderr, "Options for driver '%s':\n", desc->name);
00148 jack_print_driver_options (desc, stderr);
00149 exit (1);
00150 }
00151
00152 for (param_index = 0; param_index < desc->nparams; param_index++) {
00153 if (opt == desc->params[param_index].character) {
00154 break;
00155 }
00156 }
00157
00158 driver_param = (jack_driver_param_t*)calloc (1, sizeof (jack_driver_param_t));
00159 driver_param->character = desc->params[param_index].character;
00160
00161 if (!optarg && optind < argc &&
00162 strlen(argv[optind]) &&
00163 argv[optind][0] != '-') {
00164 optarg = argv[optind];
00165 }
00166
00167 if (optarg) {
00168 switch (desc->params[param_index].type) {
00169 case JackDriverParamInt:
00170 driver_param->value.i = atoi (optarg);
00171 break;
00172 case JackDriverParamUInt:
00173 driver_param->value.ui = strtoul (optarg, NULL, 10);
00174 break;
00175 case JackDriverParamChar:
00176 driver_param->value.c = optarg[0];
00177 break;
00178 case JackDriverParamString:
00179 strncpy (driver_param->value.str, optarg, JACK_DRIVER_PARAM_STRING_MAX);
00180 break;
00181 case JackDriverParamBool:
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191 if (strcmp ("false", optarg) == 0 ||
00192 strcmp ("off", optarg) == 0 ||
00193 strcmp ("no", optarg) == 0 ||
00194 strcmp ("0", optarg) == 0 ||
00195 strcmp ("(null)", optarg) == 0 ) {
00196 driver_param->value.i = false;
00197
00198 } else {
00199
00200 driver_param->value.i = true;
00201
00202 }
00203 break;
00204 }
00205 } else {
00206 if (desc->params[param_index].type == JackDriverParamBool) {
00207 driver_param->value.i = true;
00208 } else {
00209 driver_param->value = desc->params[param_index].value;
00210 }
00211 }
00212
00213 params = jack_slist_append (params, driver_param);
00214 }
00215
00216 free (options);
00217 free (long_options);
00218
00219 if (param_ptr)
00220 *param_ptr = params;
00221
00222 return 0;
00223 }
00224
00225 EXPORT jack_driver_desc_t *
00226 jack_find_driver_descriptor (JSList * drivers, const char * name)
00227 {
00228 jack_driver_desc_t * desc = 0;
00229 JSList * node;
00230
00231 for (node = drivers; node; node = jack_slist_next (node)) {
00232 desc = (jack_driver_desc_t *) node->data;
00233
00234 if (strcmp (desc->name, name) != 0) {
00235 desc = NULL;
00236 } else {
00237 break;
00238 }
00239 }
00240
00241 return desc;
00242 }
00243
00244 jack_driver_desc_t *
00245 jack_drivers_get_descriptor (JSList * drivers, const char * sofile)
00246 {
00247 jack_driver_desc_t * descriptor, * other_descriptor;
00248 JackDriverDescFunction so_get_descriptor = NULL;
00249 JSList * node;
00250 void * dlhandle;
00251 char * filename;
00252 #ifdef WIN32
00253 int dlerr;
00254 #else
00255 const char * dlerr;
00256 #endif
00257
00258 int err;
00259
00260
00261
00262
00263
00264
00265
00266 #ifdef WIN32
00267 char* driver_dir = ADDON_DIR;
00268 if (strcmp(ADDON_DIR, "") == 0) {
00269 char temp_driver_dir1[512];
00270 char temp_driver_dir2[512];
00271 GetCurrentDirectory(512, temp_driver_dir1);
00272 sprintf(temp_driver_dir2, "%s/%s", temp_driver_dir1, ADDON_DIR);
00273 driver_dir = temp_driver_dir2;
00274 }
00275 #else
00276 char driver_dir[512];
00277 snprintf(driver_dir, sizeof(driver_dir) - 1, "%s/%s/jackmp", ADDON_DIR, LIB_DIR);
00278 #endif
00279
00280 filename = (char *)malloc(strlen (driver_dir) + 1 + strlen(sofile) + 1);
00281 sprintf (filename, "%s/%s", driver_dir, sofile);
00282
00283 if ((dlhandle = LoadDriverModule(filename)) == NULL) {
00284 #ifdef WIN32
00285 jack_error ("could not open driver .dll '%s': %ld\n", filename, GetLastError());
00286 #else
00287 jack_error ("could not open driver .so '%s': %s\n", filename, dlerror());
00288 #endif
00289
00290 free(filename);
00291 return NULL;
00292 }
00293
00294 so_get_descriptor = (JackDriverDescFunction)
00295 GetProc(dlhandle, "driver_get_descriptor");
00296
00297 #ifdef WIN32
00298 if ((so_get_descriptor == NULL) && (dlerr = GetLastError()) != 0) {
00299 fprintf(stderr, "%ld\n", dlerr);
00300 #else
00301 if ((so_get_descriptor == NULL) && (dlerr = dlerror ()) != NULL) {
00302 fprintf(stderr, "%s\n", dlerr);
00303 #endif
00304
00305 UnloadDriverModule(dlhandle);
00306 free(filename);
00307 return NULL;
00308 }
00309
00310 if ((descriptor = so_get_descriptor ()) == NULL) {
00311 jack_error("driver from '%s' returned NULL descriptor\n", filename);
00312 UnloadDriverModule(dlhandle);
00313 free(filename);
00314 return NULL;
00315 }
00316
00317 #ifdef WIN32
00318 if ((err = UnloadDriverModule(dlhandle)) == 0) {
00319 jack_error ("error closing driver .so '%s': %ld\n", filename, GetLastError ());
00320 }
00321 #else
00322 if ((err = UnloadDriverModule(dlhandle)) != 0) {
00323 jack_error ("error closing driver .so '%s': %s\n", filename, dlerror ());
00324 }
00325 #endif
00326
00327
00328 for (node = drivers; node; node = jack_slist_next (node)) {
00329 other_descriptor = (jack_driver_desc_t *) node->data;
00330
00331 if (strcmp(descriptor->name, other_descriptor->name) == 0) {
00332 jack_error("the drivers in '%s' and '%s' both have the name '%s'; using the first\n",
00333 other_descriptor->file, filename, other_descriptor->name);
00334
00335 free(filename);
00336 return NULL;
00337 }
00338 }
00339
00340 strncpy(descriptor->file, filename, PATH_MAX);
00341 free(filename);
00342 return descriptor;
00343 }
00344
00345 #ifdef WIN32
00346
00347 EXPORT JSList *
00348 jack_drivers_load (JSList * drivers) {
00349 char driver_dir[512];
00350 char dll_filename[512];
00351 WIN32_FIND_DATA filedata;
00352 HANDLE file;
00353 const char * ptr = NULL;
00354 JSList * driver_list = NULL;
00355 jack_driver_desc_t * desc;
00356
00357 GetCurrentDirectory(512, driver_dir);
00358
00359 sprintf(dll_filename, "%s/%s", ADDON_DIR, "*.dll");
00360 file = (HANDLE )FindFirstFile(dll_filename, &filedata);
00361
00362 if (file == INVALID_HANDLE_VALUE) {
00363 printf("error\n");
00364 return NULL;
00365 }
00366
00367 do {
00368 ptr = strrchr (filedata.cFileName, '.');
00369 if (!ptr) {
00370 continue;
00371 }
00372 ptr++;
00373 if (strncmp ("dll", ptr, 3) != 0) {
00374 continue;
00375 }
00376
00377 desc = jack_drivers_get_descriptor (drivers, filedata.cFileName);
00378 if (desc) {
00379 driver_list = jack_slist_append (driver_list, desc);
00380 }
00381
00382 } while (FindNextFile(file, &filedata));
00383
00384 if (!driver_list) {
00385 jack_error ("could not find any drivers in %s!\n", driver_dir);
00386 return NULL;
00387 }
00388
00389 return driver_list;
00390 }
00391
00392 #else
00393
00394 JSList *
00395 jack_drivers_load (JSList * drivers) {
00396 struct dirent * dir_entry;
00397 DIR * dir_stream;
00398 const char * ptr;
00399 int err;
00400 JSList * driver_list = NULL;
00401 jack_driver_desc_t * desc;
00402
00403
00404
00405
00406
00407
00408
00409 char driver_dir[512];
00410 snprintf(driver_dir, sizeof(driver_dir) - 1, "%s/%s/jackmp", ADDON_DIR, LIB_DIR);
00411
00412
00413
00414 dir_stream = opendir (driver_dir);
00415 if (!dir_stream) {
00416 jack_error ("could not open driver directory %s: %s\n",
00417 driver_dir, strerror (errno));
00418 return NULL;
00419 }
00420
00421 while ((dir_entry = readdir(dir_stream))) {
00422
00423
00424 if (strncmp ("jack_", dir_entry->d_name, 5) != 0) {
00425 continue;
00426 }
00427
00428 ptr = strrchr (dir_entry->d_name, '.');
00429 if (!ptr) {
00430 continue;
00431 }
00432 ptr++;
00433 if (strncmp ("so", ptr, 2) != 0) {
00434 continue;
00435 }
00436
00437 desc = jack_drivers_get_descriptor (drivers, dir_entry->d_name);
00438 if (desc) {
00439 driver_list = jack_slist_append (driver_list, desc);
00440 }
00441 }
00442
00443 err = closedir (dir_stream);
00444 if (err) {
00445 jack_error ("error closing driver directory %s: %s\n",
00446 driver_dir, strerror (errno));
00447 }
00448
00449 if (!driver_list) {
00450 jack_error ("could not find any drivers in %s!\n", driver_dir);
00451 return NULL;
00452 }
00453
00454 return driver_list;
00455 }
00456
00457 #endif
00458
00459 jack_driver_info_t *
00460 jack_load_driver (jack_driver_desc_t * driver_desc) {
00461 #ifdef WIN32
00462 int errstr;
00463 #else
00464 const char * errstr;
00465 #endif
00466
00467 jack_driver_info_t *info;
00468
00469 info = (jack_driver_info_t *) calloc (1, sizeof (*info));
00470 info->handle = LoadDriverModule (driver_desc->file);
00471
00472 if (info->handle == NULL) {
00473 #ifdef WIN32
00474 if ((errstr = GetLastError ()) != 0) {
00475 jack_error ("can't load \"%s\": %ld", driver_desc->file,
00476 errstr);
00477 #else
00478 if ((errstr = dlerror ()) != 0) {
00479 jack_error ("can't load \"%s\": %s", driver_desc->file,
00480 errstr);
00481 #endif
00482
00483 } else {
00484 jack_error ("bizarre error loading driver shared "
00485 "object %s", driver_desc->file);
00486 }
00487 goto fail;
00488 }
00489
00490 info->initialize = (initialize)GetProc(info->handle, "driver_initialize");
00491
00492 #ifdef WIN32
00493 if ((info->initialize == NULL) && (errstr = GetLastError ()) != 0) {
00494 #else
00495 if ((info->initialize == NULL) && (errstr = dlerror ()) != 0) {
00496 #endif
00497 jack_error ("no initialize function in shared object %s\n",
00498 driver_desc->file);
00499 goto fail;
00500 }
00501
00502 return info;
00503
00504 fail:
00505 if (info->handle) {
00506 UnloadDriverModule(info->handle);
00507 }
00508 free (info);
00509 return NULL;
00510 }
00511