Jack2 1.9.6

JackDriverLoader.cpp

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