|
- /*
- Copyright (C) 2001-2005 Paul Davis
- Copyright (C) 2004-2008 Grame
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- */
-
- #if defined(HAVE_CONFIG_H)
- #include "config.h"
- #endif
-
- #ifdef WIN32
- #pragma warning (disable : 4786)
- #endif
-
- #ifndef WIN32
- #ifndef ADDON_DIR
- #include "config.h"
- #endif
- #endif
-
- #include "JackDriverLoader.h"
- #include "JackError.h"
- #include <getopt.h>
-
- #ifndef WIN32
- #include <dirent.h>
- #endif
-
- #include <errno.h>
-
- jack_driver_desc_t * jackctl_driver_get_desc(jackctl_driver_t * driver);
-
- static void
- jack_print_driver_options (jack_driver_desc_t * desc, FILE *file)
- {
- unsigned long i;
- char arg_default[JACK_DRIVER_PARAM_STRING_MAX + 1];
-
- for (i = 0; i < desc->nparams; i++) {
- switch (desc->params[i].type) {
- case JackDriverParamInt:
- sprintf (arg_default, "%" "i", desc->params[i].value.i);
- break;
- case JackDriverParamUInt:
- sprintf (arg_default, "%" "u", desc->params[i].value.ui);
- break;
- case JackDriverParamChar:
- sprintf (arg_default, "%c", desc->params[i].value.c);
- break;
- case JackDriverParamString:
- if (desc->params[i].value.str && strcmp (desc->params[i].value.str, "") != 0)
- sprintf (arg_default, "%s", desc->params[i].value.str);
- else
- sprintf (arg_default, "none");
- break;
- case JackDriverParamBool:
- sprintf (arg_default, "%s", desc->params[i].value.i ? "true" : "false");
- break;
- }
-
- fprintf (file, "\t-%c, --%s \t%s (default: %s)\n",
- desc->params[i].character,
- desc->params[i].name,
- desc->params[i].short_desc,
- arg_default);
- }
- }
-
- static void
- jack_print_driver_param_usage (jack_driver_desc_t * desc, unsigned long param, FILE *file)
- {
- fprintf (file, "Usage information for the '%s' parameter for driver '%s':\n",
- desc->params[param].name, desc->name);
- fprintf (file, "%s\n", desc->params[param].long_desc);
- }
-
- EXPORT int
- jack_parse_driver_params (jack_driver_desc_t * desc, int argc, char* argv[], JSList ** param_ptr)
- {
- struct option * long_options;
- char * options, * options_ptr;
- unsigned long i;
- int opt;
- unsigned int param_index;
- JSList * params = NULL;
- jack_driver_param_t * driver_param;
-
- if (argc <= 1) {
- *param_ptr = NULL;
- return 0;
- }
-
- /* check for help */
- if (strcmp (argv[1], "-h") == 0 || strcmp (argv[1], "--help") == 0) {
- if (argc > 2) {
- for (i = 0; i < desc->nparams; i++) {
- if (strcmp (desc->params[i].name, argv[2]) == 0) {
- jack_print_driver_param_usage (desc, i, stdout);
- return 1;
- }
- }
-
- fprintf (stderr, "jackd: unknown option '%s' "
- "for driver '%s'\n", argv[2],
- desc->name);
- }
-
- printf ("Parameters for driver '%s' (all parameters are optional):\n", desc->name);
- jack_print_driver_options (desc, stdout);
- return 1;
- }
-
- /* set up the stuff for getopt */
- options = (char*)calloc (desc->nparams * 3 + 1, sizeof (char));
- long_options = (option*)calloc (desc->nparams + 1, sizeof (struct option));
-
- options_ptr = options;
- for (i = 0; i < desc->nparams; i++) {
- sprintf (options_ptr, "%c::", desc->params[i].character);
- options_ptr += 3;
- long_options[i].name = desc->params[i].name;
- long_options[i].flag = NULL;
- long_options[i].val = desc->params[i].character;
- long_options[i].has_arg = optional_argument;
- }
-
- /* create the params */
- optind = 0;
- opterr = 0;
- while ((opt = getopt_long(argc, argv, options, long_options, NULL)) != -1) {
-
- if (opt == ':' || opt == '?') {
- if (opt == ':') {
- fprintf (stderr, "Missing option to argument '%c'\n", optopt);
- } else {
- fprintf (stderr, "Unknownage with option '%c'\n", optopt);
- }
-
- fprintf (stderr, "Options for driver '%s':\n", desc->name);
- jack_print_driver_options (desc, stderr);
- exit (1);
- }
-
- for (param_index = 0; param_index < desc->nparams; param_index++) {
- if (opt == desc->params[param_index].character) {
- break;
- }
- }
-
- driver_param = (jack_driver_param_t*)calloc (1, sizeof (jack_driver_param_t));
- driver_param->character = desc->params[param_index].character;
-
- if (!optarg && optind < argc &&
- strlen(argv[optind]) &&
- argv[optind][0] != '-') {
- optarg = argv[optind];
- }
-
- if (optarg) {
- switch (desc->params[param_index].type) {
- case JackDriverParamInt:
- driver_param->value.i = atoi (optarg);
- break;
- case JackDriverParamUInt:
- driver_param->value.ui = strtoul (optarg, NULL, 10);
- break;
- case JackDriverParamChar:
- driver_param->value.c = optarg[0];
- break;
- case JackDriverParamString:
- strncpy (driver_param->value.str, optarg, JACK_DRIVER_PARAM_STRING_MAX);
- break;
- case JackDriverParamBool:
-
- /*
- if (strcasecmp ("false", optarg) == 0 ||
- strcasecmp ("off", optarg) == 0 ||
- strcasecmp ("no", optarg) == 0 ||
- strcasecmp ("0", optarg) == 0 ||
- strcasecmp ("(null)", optarg) == 0 ) {
- */
- // steph
- if (strcmp ("false", optarg) == 0 ||
- strcmp ("off", optarg) == 0 ||
- strcmp ("no", optarg) == 0 ||
- strcmp ("0", optarg) == 0 ||
- strcmp ("(null)", optarg) == 0 ) {
- driver_param->value.i = false;
-
- } else {
-
- driver_param->value.i = true;
-
- }
- break;
- }
- } else {
- if (desc->params[param_index].type == JackDriverParamBool) {
- driver_param->value.i = true;
- } else {
- driver_param->value = desc->params[param_index].value;
- }
- }
-
- params = jack_slist_append (params, driver_param);
- }
-
- free (options);
- free (long_options);
-
- if (param_ptr)
- *param_ptr = params;
-
- return 0;
- }
-
- EXPORT int
- jackctl_parse_driver_params (jackctl_driver *driver_ptr, int argc, char* argv[])
- {
- struct option * long_options;
- char * options, * options_ptr;
- unsigned long i;
- int opt;
- JSList * node_ptr;
- jackctl_parameter_t * param;
- union jackctl_parameter_value value;
-
- if (argc <= 1)
- return 0;
-
- const JSList * driver_params = jackctl_driver_get_parameters(driver_ptr);
- if (driver_params == NULL)
- return 1;
-
- jack_driver_desc_t * desc = jackctl_driver_get_desc(driver_ptr);
-
- /* check for help */
- if (strcmp (argv[1], "-h") == 0 || strcmp (argv[1], "--help") == 0) {
- if (argc > 2) {
- for (i = 0; i < desc->nparams; i++) {
- if (strcmp (desc->params[i].name, argv[2]) == 0) {
- jack_print_driver_param_usage (desc, i, stdout);
- return 1;
- }
- }
-
- fprintf (stderr, "jackd: unknown option '%s' "
- "for driver '%s'\n", argv[2],
- desc->name);
- }
-
- printf ("Parameters for driver '%s' (all parameters are optional):\n", desc->name);
- jack_print_driver_options (desc, stdout);
- return 1;
- }
-
- /* set up the stuff for getopt */
- options = (char*)calloc (desc->nparams * 3 + 1, sizeof (char));
- long_options = (option*)calloc (desc->nparams + 1, sizeof (struct option));
-
- options_ptr = options;
- for (i = 0; i < desc->nparams; i++) {
- sprintf (options_ptr, "%c::", desc->params[i].character);
- options_ptr += 3;
- long_options[i].name = desc->params[i].name;
- long_options[i].flag = NULL;
- long_options[i].val = desc->params[i].character;
- long_options[i].has_arg = optional_argument;
- }
-
- /* create the params */
- optind = 0;
- opterr = 0;
- while ((opt = getopt_long(argc, argv, options, long_options, NULL)) != -1) {
-
- if (opt == ':' || opt == '?') {
- if (opt == ':') {
- fprintf (stderr, "Missing option to argument '%c'\n", optopt);
- } else {
- fprintf (stderr, "Unknownage with option '%c'\n", optopt);
- }
-
- fprintf (stderr, "Options for driver '%s':\n", desc->name);
- jack_print_driver_options (desc, stderr);
- exit (1);
- }
-
- node_ptr = (JSList *)driver_params;
- while (node_ptr) {
- param = (jackctl_parameter_t*)node_ptr->data;
- if (opt == jackctl_parameter_get_id(param)) {
- break;
- }
- node_ptr = node_ptr->next;
- }
-
- if (!optarg && optind < argc &&
- strlen(argv[optind]) &&
- argv[optind][0] != '-') {
- optarg = argv[optind];
- }
-
- if (optarg) {
- switch (jackctl_parameter_get_type(param)) {
- case JackDriverParamInt:
- value.i = atoi (optarg);
- jackctl_parameter_set_value(param, &value);
- break;
- case JackDriverParamUInt:
- value.ui = strtoul (optarg, NULL, 10);
- jackctl_parameter_set_value(param, &value);
- break;
- case JackDriverParamChar:
- value.c = optarg[0];
- jackctl_parameter_set_value(param, &value);
- break;
- case JackDriverParamString:
- strncpy (value.str, optarg, JACK_DRIVER_PARAM_STRING_MAX);
- jackctl_parameter_set_value(param, &value);
- break;
- case JackDriverParamBool:
-
- /*
- if (strcasecmp ("false", optarg) == 0 ||
- strcasecmp ("off", optarg) == 0 ||
- strcasecmp ("no", optarg) == 0 ||
- strcasecmp ("0", optarg) == 0 ||
- strcasecmp ("(null)", optarg) == 0 ) {
- */
- // steph
- if (strcmp ("false", optarg) == 0 ||
- strcmp ("off", optarg) == 0 ||
- strcmp ("no", optarg) == 0 ||
- strcmp ("0", optarg) == 0 ||
- strcmp ("(null)", optarg) == 0 ) {
- value.i = false;
- } else {
- value.i = true;
- }
- jackctl_parameter_set_value(param, &value);
- break;
- }
- } else {
- if (jackctl_parameter_get_type(param) == JackParamBool) {
- value.i = true;
- } else {
- value = jackctl_parameter_get_default_value(param);
- jackctl_parameter_set_value(param, &value);
- }
- }
- }
-
- free (options);
- free (long_options);
- return 0;
- }
-
- EXPORT jack_driver_desc_t *
- jack_find_driver_descriptor (JSList * drivers, const char * name)
- {
- jack_driver_desc_t * desc = 0;
- JSList * node;
-
- for (node = drivers; node; node = jack_slist_next (node)) {
- desc = (jack_driver_desc_t *) node->data;
-
- if (strcmp (desc->name, name) != 0) {
- desc = NULL;
- } else {
- break;
- }
- }
-
- return desc;
- }
-
- jack_driver_desc_t *
- jack_drivers_get_descriptor (JSList * drivers, const char * sofile)
- {
- jack_driver_desc_t * descriptor, * other_descriptor;
- JackDriverDescFunction so_get_descriptor = NULL;
- JSList * node;
- void * dlhandle;
- char * filename;
- #ifdef WIN32
- int dlerr;
- #else
- const char * dlerr;
- #endif
-
- int err;
- const char* driver_dir;
-
- if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) {
- // for WIN32 ADDON_DIR is defined in JackConstants.h as relative path
- // for posix systems, it is absolute path of default driver dir
- #ifdef WIN32
- char temp_driver_dir1[512];
- char temp_driver_dir2[512];
- GetCurrentDirectory(512, temp_driver_dir1);
- sprintf(temp_driver_dir2, "%s/%s", temp_driver_dir1, ADDON_DIR);
- driver_dir = temp_driver_dir2;
- #else
- driver_dir = ADDON_DIR;
- #endif
- }
-
- filename = (char *)malloc(strlen (driver_dir) + 1 + strlen(sofile) + 1);
- sprintf (filename, "%s/%s", driver_dir, sofile);
-
- if ((dlhandle = LoadDriverModule(filename)) == NULL) {
- #ifdef WIN32
- jack_error ("could not open driver .dll '%s': %ld\n", filename, GetLastError());
- #else
- jack_error ("could not open driver .so '%s': %s\n", filename, dlerror());
- #endif
-
- free(filename);
- return NULL;
- }
-
- so_get_descriptor = (JackDriverDescFunction)
- GetProc(dlhandle, "driver_get_descriptor");
-
- #ifdef WIN32
- if ((so_get_descriptor == NULL) && (dlerr = GetLastError()) != 0) {
- jack_error("%ld", dlerr);
- #else
- if ((so_get_descriptor == NULL) && (dlerr = dlerror ()) != NULL) {
- jack_error("%s", dlerr);
- #endif
-
- UnloadDriverModule(dlhandle);
- free(filename);
- return NULL;
- }
-
- if ((descriptor = so_get_descriptor ()) == NULL) {
- jack_error("driver from '%s' returned NULL descriptor\n", filename);
- UnloadDriverModule(dlhandle);
- free(filename);
- return NULL;
- }
-
- #ifdef WIN32
- if ((err = UnloadDriverModule(dlhandle)) == 0) {
- jack_error ("error closing driver .so '%s': %ld\n", filename, GetLastError ());
- }
- #else
- if ((err = UnloadDriverModule(dlhandle)) != 0) {
- jack_error ("error closing driver .so '%s': %s\n", filename, dlerror ());
- }
- #endif
-
- /* check it doesn't exist already */
- for (node = drivers; node; node = jack_slist_next (node)) {
- other_descriptor = (jack_driver_desc_t *) node->data;
-
- if (strcmp(descriptor->name, other_descriptor->name) == 0) {
- jack_error("the drivers in '%s' and '%s' both have the name '%s'; using the first\n",
- other_descriptor->file, filename, other_descriptor->name);
- /* FIXME: delete the descriptor */
- free(filename);
- return NULL;
- }
- }
-
- strncpy(descriptor->file, filename, PATH_MAX);
- free(filename);
- return descriptor;
- }
-
- #ifdef WIN32
-
- EXPORT JSList *
- jack_drivers_load (JSList * drivers) {
- char * driver_dir;
- char driver_dir_storage[512];
- char dll_filename[512];
- WIN32_FIND_DATA filedata;
- HANDLE file;
- const char * ptr = NULL;
- JSList * driver_list = NULL;
- jack_driver_desc_t * desc;
-
- if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) {
- // for WIN32 ADDON_DIR is defined in JackConstants.h as relative path
- GetCurrentDirectory(512, driver_dir_storage);
- strcat(driver_dir_storage, "/");
- strcat(driver_dir_storage, ADDON_DIR);
- driver_dir = driver_dir_storage;
- }
-
- sprintf(dll_filename, "%s/*.dll", driver_dir);
-
- file = (HANDLE )FindFirstFile(dll_filename, &filedata);
-
- if (file == INVALID_HANDLE_VALUE) {
- jack_error("error");
- return NULL;
- }
-
- do {
- ptr = strrchr (filedata.cFileName, '.');
- if (!ptr) {
- continue;
- }
- ptr++;
- if (strncmp ("dll", ptr, 3) != 0) {
- continue;
- }
-
- desc = jack_drivers_get_descriptor (drivers, filedata.cFileName);
- if (desc) {
- driver_list = jack_slist_append (driver_list, desc);
- }
-
- } while (FindNextFile(file, &filedata));
-
- if (!driver_list) {
- jack_error ("could not find any drivers in %s!\n", driver_dir);
- return NULL;
- }
-
- return driver_list;
- }
-
- #else
-
- JSList *
- jack_drivers_load (JSList * drivers) {
- struct dirent * dir_entry;
- DIR * dir_stream;
- const char * ptr;
- int err;
- JSList * driver_list = NULL;
- jack_driver_desc_t * desc;
-
- const char* driver_dir;
- if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) {
- driver_dir = ADDON_DIR;
- }
-
- /* search through the driver_dir and add get descriptors
- from the .so files in it */
- dir_stream = opendir (driver_dir);
- if (!dir_stream) {
- jack_error ("could not open driver directory %s: %s\n",
- driver_dir, strerror (errno));
- return NULL;
- }
-
- while ((dir_entry = readdir(dir_stream))) {
-
- /* check the filename is of the right format */
- if (strncmp ("jack_", dir_entry->d_name, 5) != 0) {
- continue;
- }
-
- ptr = strrchr (dir_entry->d_name, '.');
- if (!ptr) {
- continue;
- }
- ptr++;
- if (strncmp ("so", ptr, 2) != 0) {
- continue;
- }
-
- desc = jack_drivers_get_descriptor (drivers, dir_entry->d_name);
- if (desc) {
- driver_list = jack_slist_append (driver_list, desc);
- }
- }
-
- err = closedir (dir_stream);
- if (err) {
- jack_error ("error closing driver directory %s: %s\n",
- driver_dir, strerror (errno));
- }
-
- if (!driver_list) {
- jack_error ("could not find any drivers in %s!\n", driver_dir);
- return NULL;
- }
-
- return driver_list;
- }
-
- #endif
-
- jack_driver_info_t *
- jack_load_driver (jack_driver_desc_t * driver_desc) {
- #ifdef WIN32
- int errstr;
- #else
- const char * errstr;
- #endif
-
- jack_driver_info_t *info;
-
- info = (jack_driver_info_t *) calloc (1, sizeof (*info));
- info->handle = LoadDriverModule (driver_desc->file);
-
- if (info->handle == NULL) {
- #ifdef WIN32
- if ((errstr = GetLastError ()) != 0) {
- jack_error ("can't load \"%s\": %ld", driver_desc->file,
- errstr);
- #else
- if ((errstr = dlerror ()) != 0) {
- jack_error ("can't load \"%s\": %s", driver_desc->file,
- errstr);
- #endif
-
- } else {
- jack_error ("bizarre error loading driver shared "
- "object %s", driver_desc->file);
- }
- goto fail;
- }
-
- info->initialize = (initialize)GetProc(info->handle, "driver_initialize");
-
- #ifdef WIN32
- if ((info->initialize == NULL) && (errstr = GetLastError ()) != 0) {
- #else
- if ((info->initialize == NULL) && (errstr = dlerror ()) != 0) {
- #endif
- jack_error ("no initialize function in shared object %s\n",
- driver_desc->file);
- goto fail;
- }
-
- return info;
-
- fail:
- if (info->handle) {
- UnloadDriverModule(info->handle);
- }
- free (info);
- return NULL;
- }
|