jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

818 lines
23KB

  1. /*
  2. Copyright (C) 2001-2005 Paul Davis
  3. Copyright (C) 2004-2008 Grame
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. */
  16. #if defined(HAVE_CONFIG_H)
  17. #include "config.h"
  18. #endif
  19. #ifdef WIN32
  20. #pragma warning (disable : 4786)
  21. #endif
  22. /*
  23. #ifndef WIN32
  24. #ifndef ADDON_DIR
  25. #include "config.h"
  26. #endif
  27. #endif
  28. */
  29. #include "JackDriverLoader.h"
  30. #include "JackConstants.h"
  31. #include "JackError.h"
  32. #include <getopt.h>
  33. #include <stdio.h>
  34. #ifndef WIN32
  35. #include <dirent.h>
  36. #endif
  37. #include <errno.h>
  38. jack_driver_desc_t * jackctl_driver_get_desc(jackctl_driver_t * driver);
  39. static void
  40. jack_print_driver_options (jack_driver_desc_t * desc, FILE *file)
  41. {
  42. unsigned long i;
  43. char arg_default[JACK_DRIVER_PARAM_STRING_MAX + 1];
  44. for (i = 0; i < desc->nparams; i++) {
  45. switch (desc->params[i].type) {
  46. case JackDriverParamInt:
  47. sprintf (arg_default, "%" "i", desc->params[i].value.i);
  48. break;
  49. case JackDriverParamUInt:
  50. sprintf (arg_default, "%" "u", desc->params[i].value.ui);
  51. break;
  52. case JackDriverParamChar:
  53. sprintf (arg_default, "%c", desc->params[i].value.c);
  54. break;
  55. case JackDriverParamString:
  56. if (desc->params[i].value.str && strcmp (desc->params[i].value.str, "") != 0)
  57. sprintf (arg_default, "%s", desc->params[i].value.str);
  58. else
  59. sprintf (arg_default, "none");
  60. break;
  61. case JackDriverParamBool:
  62. sprintf (arg_default, "%s", desc->params[i].value.i ? "true" : "false");
  63. break;
  64. }
  65. fprintf (file, "\t-%c, --%s \t%s (default: %s)\n",
  66. desc->params[i].character,
  67. desc->params[i].name,
  68. desc->params[i].short_desc,
  69. arg_default);
  70. }
  71. }
  72. static void
  73. jack_print_driver_param_usage (jack_driver_desc_t * desc, unsigned long param, FILE *file)
  74. {
  75. fprintf (file, "Usage information for the '%s' parameter for driver '%s':\n",
  76. desc->params[param].name, desc->name);
  77. fprintf (file, "%s\n", desc->params[param].long_desc);
  78. }
  79. EXPORT void jack_free_driver_params(JSList * driver_params)
  80. {
  81. JSList *node_ptr = driver_params;
  82. JSList *next_node_ptr;
  83. while (node_ptr) {
  84. next_node_ptr = node_ptr->next;
  85. free(node_ptr->data);
  86. free(node_ptr);
  87. node_ptr = next_node_ptr;
  88. }
  89. }
  90. int
  91. jack_parse_driver_params (jack_driver_desc_t * desc, int argc, char* argv[], JSList ** param_ptr)
  92. {
  93. struct option * long_options;
  94. char * options, * options_ptr;
  95. unsigned long i;
  96. int opt;
  97. unsigned int param_index;
  98. JSList * params = NULL;
  99. jack_driver_param_t * driver_param;
  100. if (argc <= 1) {
  101. *param_ptr = NULL;
  102. return 0;
  103. }
  104. /* check for help */
  105. if (strcmp (argv[1], "-h") == 0 || strcmp (argv[1], "--help") == 0) {
  106. if (argc > 2) {
  107. for (i = 0; i < desc->nparams; i++) {
  108. if (strcmp (desc->params[i].name, argv[2]) == 0) {
  109. jack_print_driver_param_usage (desc, i, stdout);
  110. return 1;
  111. }
  112. }
  113. fprintf (stderr, "jackd: unknown option '%s' "
  114. "for driver '%s'\n", argv[2],
  115. desc->name);
  116. }
  117. printf ("Parameters for driver '%s' (all parameters are optional):\n", desc->name);
  118. jack_print_driver_options (desc, stdout);
  119. return 1;
  120. }
  121. /* set up the stuff for getopt */
  122. options = (char*)calloc (desc->nparams * 3 + 1, sizeof (char));
  123. long_options = (option*)calloc (desc->nparams + 1, sizeof (struct option));
  124. options_ptr = options;
  125. for (i = 0; i < desc->nparams; i++) {
  126. sprintf (options_ptr, "%c::", desc->params[i].character);
  127. options_ptr += 3;
  128. long_options[i].name = desc->params[i].name;
  129. long_options[i].flag = NULL;
  130. long_options[i].val = desc->params[i].character;
  131. long_options[i].has_arg = optional_argument;
  132. }
  133. /* create the params */
  134. optind = 0;
  135. opterr = 0;
  136. while ((opt = getopt_long(argc, argv, options, long_options, NULL)) != -1) {
  137. if (opt == ':' || opt == '?') {
  138. if (opt == ':') {
  139. fprintf (stderr, "Missing option to argument '%c'\n", optopt);
  140. } else {
  141. fprintf (stderr, "Unknownage with option '%c'\n", optopt);
  142. }
  143. fprintf (stderr, "Options for driver '%s':\n", desc->name);
  144. jack_print_driver_options (desc, stderr);
  145. exit (1);
  146. }
  147. for (param_index = 0; param_index < desc->nparams; param_index++) {
  148. if (opt == desc->params[param_index].character) {
  149. break;
  150. }
  151. }
  152. driver_param = (jack_driver_param_t*)calloc (1, sizeof (jack_driver_param_t));
  153. driver_param->character = desc->params[param_index].character;
  154. if (!optarg && optind < argc &&
  155. strlen(argv[optind]) &&
  156. argv[optind][0] != '-') {
  157. optarg = argv[optind];
  158. }
  159. if (optarg) {
  160. switch (desc->params[param_index].type) {
  161. case JackDriverParamInt:
  162. driver_param->value.i = atoi (optarg);
  163. break;
  164. case JackDriverParamUInt:
  165. driver_param->value.ui = strtoul (optarg, NULL, 10);
  166. break;
  167. case JackDriverParamChar:
  168. driver_param->value.c = optarg[0];
  169. break;
  170. case JackDriverParamString:
  171. strncpy (driver_param->value.str, optarg, JACK_DRIVER_PARAM_STRING_MAX);
  172. break;
  173. case JackDriverParamBool:
  174. /*
  175. if (strcasecmp ("false", optarg) == 0 ||
  176. strcasecmp ("off", optarg) == 0 ||
  177. strcasecmp ("no", optarg) == 0 ||
  178. strcasecmp ("0", optarg) == 0 ||
  179. strcasecmp ("(null)", optarg) == 0 ) {
  180. */
  181. // steph
  182. if (strcmp ("false", optarg) == 0 ||
  183. strcmp ("off", optarg) == 0 ||
  184. strcmp ("no", optarg) == 0 ||
  185. strcmp ("0", optarg) == 0 ||
  186. strcmp ("(null)", optarg) == 0 ) {
  187. driver_param->value.i = false;
  188. } else {
  189. driver_param->value.i = true;
  190. }
  191. break;
  192. }
  193. } else {
  194. if (desc->params[param_index].type == JackDriverParamBool) {
  195. driver_param->value.i = true;
  196. } else {
  197. driver_param->value = desc->params[param_index].value;
  198. }
  199. }
  200. params = jack_slist_append (params, driver_param);
  201. }
  202. free (options);
  203. free (long_options);
  204. if (param_ptr)
  205. *param_ptr = params;
  206. return 0;
  207. }
  208. EXPORT int
  209. jackctl_parse_driver_params (jackctl_driver *driver_ptr, int argc, char* argv[])
  210. {
  211. struct option * long_options;
  212. char * options, * options_ptr;
  213. unsigned long i;
  214. int opt;
  215. JSList * node_ptr;
  216. jackctl_parameter_t * param = NULL;
  217. union jackctl_parameter_value value;
  218. if (argc <= 1)
  219. return 0;
  220. const JSList * driver_params = jackctl_driver_get_parameters(driver_ptr);
  221. if (driver_params == NULL)
  222. return 1;
  223. jack_driver_desc_t * desc = jackctl_driver_get_desc(driver_ptr);
  224. /* check for help */
  225. if (strcmp (argv[1], "-h") == 0 || strcmp (argv[1], "--help") == 0) {
  226. if (argc > 2) {
  227. for (i = 0; i < desc->nparams; i++) {
  228. if (strcmp (desc->params[i].name, argv[2]) == 0) {
  229. jack_print_driver_param_usage (desc, i, stdout);
  230. return 1;
  231. }
  232. }
  233. fprintf (stderr, "jackd: unknown option '%s' "
  234. "for driver '%s'\n", argv[2],
  235. desc->name);
  236. }
  237. printf ("Parameters for driver '%s' (all parameters are optional):\n", desc->name);
  238. jack_print_driver_options (desc, stdout);
  239. return 1;
  240. }
  241. /* set up the stuff for getopt */
  242. options = (char*)calloc (desc->nparams * 3 + 1, sizeof (char));
  243. long_options = (option*)calloc (desc->nparams + 1, sizeof (struct option));
  244. options_ptr = options;
  245. for (i = 0; i < desc->nparams; i++) {
  246. sprintf (options_ptr, "%c::", desc->params[i].character);
  247. options_ptr += 3;
  248. long_options[i].name = desc->params[i].name;
  249. long_options[i].flag = NULL;
  250. long_options[i].val = desc->params[i].character;
  251. long_options[i].has_arg = optional_argument;
  252. }
  253. /* create the params */
  254. optind = 0;
  255. opterr = 0;
  256. while ((opt = getopt_long(argc, argv, options, long_options, NULL)) != -1) {
  257. if (opt == ':' || opt == '?') {
  258. if (opt == ':') {
  259. fprintf (stderr, "Missing option to argument '%c'\n", optopt);
  260. } else {
  261. fprintf (stderr, "Unknownage with option '%c'\n", optopt);
  262. }
  263. fprintf (stderr, "Options for driver '%s':\n", desc->name);
  264. jack_print_driver_options(desc, stderr);
  265. return 1;
  266. }
  267. node_ptr = (JSList *)driver_params;
  268. while (node_ptr) {
  269. param = (jackctl_parameter_t*)node_ptr->data;
  270. if (opt == jackctl_parameter_get_id(param)) {
  271. break;
  272. }
  273. node_ptr = node_ptr->next;
  274. }
  275. if (!optarg && optind < argc &&
  276. strlen(argv[optind]) &&
  277. argv[optind][0] != '-') {
  278. optarg = argv[optind];
  279. }
  280. if (optarg) {
  281. switch (jackctl_parameter_get_type(param)) {
  282. case JackDriverParamInt:
  283. value.i = atoi (optarg);
  284. jackctl_parameter_set_value(param, &value);
  285. break;
  286. case JackDriverParamUInt:
  287. value.ui = strtoul (optarg, NULL, 10);
  288. jackctl_parameter_set_value(param, &value);
  289. break;
  290. case JackDriverParamChar:
  291. value.c = optarg[0];
  292. jackctl_parameter_set_value(param, &value);
  293. break;
  294. case JackDriverParamString:
  295. strncpy (value.str, optarg, JACK_DRIVER_PARAM_STRING_MAX);
  296. jackctl_parameter_set_value(param, &value);
  297. break;
  298. case JackDriverParamBool:
  299. /*
  300. if (strcasecmp ("false", optarg) == 0 ||
  301. strcasecmp ("off", optarg) == 0 ||
  302. strcasecmp ("no", optarg) == 0 ||
  303. strcasecmp ("0", optarg) == 0 ||
  304. strcasecmp ("(null)", optarg) == 0 ) {
  305. */
  306. // steph
  307. if (strcmp ("false", optarg) == 0 ||
  308. strcmp ("off", optarg) == 0 ||
  309. strcmp ("no", optarg) == 0 ||
  310. strcmp ("0", optarg) == 0 ||
  311. strcmp ("(null)", optarg) == 0 ) {
  312. value.i = false;
  313. } else {
  314. value.i = true;
  315. }
  316. jackctl_parameter_set_value(param, &value);
  317. break;
  318. }
  319. } else {
  320. if (jackctl_parameter_get_type(param) == JackParamBool) {
  321. value.i = true;
  322. } else {
  323. value = jackctl_parameter_get_default_value(param);
  324. }
  325. jackctl_parameter_set_value(param, &value);
  326. }
  327. }
  328. free(options);
  329. free(long_options);
  330. return 0;
  331. }
  332. jack_driver_desc_t *
  333. jack_find_driver_descriptor (JSList * drivers, const char * name)
  334. {
  335. jack_driver_desc_t * desc = 0;
  336. JSList * node;
  337. for (node = drivers; node; node = jack_slist_next (node)) {
  338. desc = (jack_driver_desc_t *) node->data;
  339. if (strcmp (desc->name, name) != 0) {
  340. desc = NULL;
  341. } else {
  342. break;
  343. }
  344. }
  345. return desc;
  346. }
  347. jack_driver_desc_t *
  348. jack_drivers_get_descriptor (JSList * drivers, const char * sofile)
  349. {
  350. jack_driver_desc_t * descriptor, * other_descriptor;
  351. JackDriverDescFunction so_get_descriptor = NULL;
  352. JSList * node;
  353. void * dlhandle;
  354. char * filename;
  355. #ifdef WIN32
  356. int dlerr;
  357. #else
  358. const char * dlerr;
  359. #endif
  360. int err;
  361. const char* driver_dir;
  362. if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) {
  363. // for WIN32 ADDON_DIR is defined in JackConstants.h as relative path
  364. // for posix systems, it is absolute path of default driver dir
  365. #ifdef WIN32
  366. char temp_driver_dir1[512];
  367. char temp_driver_dir2[512];
  368. GetCurrentDirectory(512, temp_driver_dir1);
  369. sprintf(temp_driver_dir2, "%s/%s", temp_driver_dir1, ADDON_DIR);
  370. driver_dir = temp_driver_dir2;
  371. #else
  372. driver_dir = ADDON_DIR;
  373. #endif
  374. }
  375. filename = (char *)malloc(strlen (driver_dir) + 1 + strlen(sofile) + 1);
  376. sprintf (filename, "%s/%s", driver_dir, sofile);
  377. if ((dlhandle = LoadDriverModule(filename)) == NULL) {
  378. #ifdef WIN32
  379. jack_error ("could not open driver .dll '%s': %ld\n", filename, GetLastError());
  380. #else
  381. jack_error ("could not open driver .so '%s': %s\n", filename, dlerror());
  382. #endif
  383. free(filename);
  384. return NULL;
  385. }
  386. so_get_descriptor = (JackDriverDescFunction)
  387. GetProc(dlhandle, "driver_get_descriptor");
  388. #ifdef WIN32
  389. if ((so_get_descriptor == NULL) && (dlerr = GetLastError()) != 0) {
  390. jack_error("jack_drivers_get_descriptor err = %ld", dlerr);
  391. #else
  392. if ((so_get_descriptor == NULL) && (dlerr = dlerror ()) != NULL) {
  393. jack_error("jack_drivers_get_descriptor err = %s", dlerr);
  394. #endif
  395. UnloadDriverModule(dlhandle);
  396. free(filename);
  397. return NULL;
  398. }
  399. if ((descriptor = so_get_descriptor ()) == NULL) {
  400. jack_error("driver from '%s' returned NULL descriptor\n", filename);
  401. UnloadDriverModule(dlhandle);
  402. free(filename);
  403. return NULL;
  404. }
  405. #ifdef WIN32
  406. if ((err = UnloadDriverModule(dlhandle)) == 0) {
  407. jack_error ("error closing driver .so '%s': %ld\n", filename, GetLastError ());
  408. }
  409. #else
  410. if ((err = UnloadDriverModule(dlhandle)) != 0) {
  411. jack_error ("error closing driver .so '%s': %s\n", filename, dlerror ());
  412. }
  413. #endif
  414. /* check it doesn't exist already */
  415. for (node = drivers; node; node = jack_slist_next (node)) {
  416. other_descriptor = (jack_driver_desc_t *) node->data;
  417. if (strcmp(descriptor->name, other_descriptor->name) == 0) {
  418. jack_error("the drivers in '%s' and '%s' both have the name '%s'; using the first\n",
  419. other_descriptor->file, filename, other_descriptor->name);
  420. /* FIXME: delete the descriptor */
  421. free(filename);
  422. return NULL;
  423. }
  424. }
  425. strncpy(descriptor->file, filename, PATH_MAX);
  426. free(filename);
  427. return descriptor;
  428. }
  429. static bool check_symbol(const char* filename, const char* symbol)
  430. {
  431. void * dlhandle;
  432. bool res = false;
  433. if ((dlhandle = LoadDriverModule(filename)) == NULL) {
  434. #ifdef WIN32
  435. jack_error ("could not open driver .dll '%s': %ld\n", filename, GetLastError());
  436. #else
  437. jack_error ("could not open driver .so '%s': %s\n", filename, dlerror());
  438. #endif
  439. } else {
  440. res = (GetProc(dlhandle, symbol)) ? true : false;
  441. UnloadDriverModule(dlhandle);
  442. }
  443. return res;
  444. }
  445. #ifdef WIN32
  446. JSList *
  447. jack_drivers_load (JSList * drivers) {
  448. char * driver_dir;
  449. char driver_dir_storage[512];
  450. char dll_filename[512];
  451. WIN32_FIND_DATA filedata;
  452. HANDLE file;
  453. const char * ptr = NULL;
  454. JSList * driver_list = NULL;
  455. jack_driver_desc_t * desc;
  456. if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) {
  457. // for WIN32 ADDON_DIR is defined in JackConstants.h as relative path
  458. GetCurrentDirectory(512, driver_dir_storage);
  459. strcat(driver_dir_storage, "/");
  460. strcat(driver_dir_storage, ADDON_DIR);
  461. driver_dir = driver_dir_storage;
  462. }
  463. sprintf(dll_filename, "%s/*.dll", driver_dir);
  464. file = (HANDLE )FindFirstFile(dll_filename, &filedata);
  465. if (file == INVALID_HANDLE_VALUE) {
  466. jack_error("error");
  467. return NULL;
  468. }
  469. do {
  470. ptr = strrchr (filedata.cFileName, '.');
  471. if (!ptr) {
  472. continue;
  473. }
  474. ptr++;
  475. if (strncmp ("dll", ptr, 3) != 0) {
  476. continue;
  477. }
  478. desc = jack_drivers_get_descriptor (drivers, filedata.cFileName);
  479. if (desc) {
  480. driver_list = jack_slist_append (driver_list, desc);
  481. }
  482. } while (FindNextFile(file, &filedata));
  483. if (!driver_list) {
  484. jack_error ("could not find any drivers in %s!\n", driver_dir);
  485. return NULL;
  486. }
  487. return driver_list;
  488. }
  489. #else
  490. JSList *
  491. jack_drivers_load (JSList * drivers) {
  492. struct dirent * dir_entry;
  493. DIR * dir_stream;
  494. const char * ptr;
  495. int err;
  496. JSList * driver_list = NULL;
  497. jack_driver_desc_t * desc;
  498. const char* driver_dir;
  499. if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) {
  500. driver_dir = ADDON_DIR;
  501. }
  502. /* search through the driver_dir and add get descriptors
  503. from the .so files in it */
  504. dir_stream = opendir (driver_dir);
  505. if (!dir_stream) {
  506. jack_error ("could not open driver directory %s: %s\n",
  507. driver_dir, strerror (errno));
  508. return NULL;
  509. }
  510. while ((dir_entry = readdir(dir_stream))) {
  511. /* check the filename is of the right format */
  512. if (strncmp ("jack_", dir_entry->d_name, 5) != 0) {
  513. continue;
  514. }
  515. ptr = strrchr (dir_entry->d_name, '.');
  516. if (!ptr) {
  517. continue;
  518. }
  519. ptr++;
  520. if (strncmp ("so", ptr, 2) != 0) {
  521. continue;
  522. }
  523. desc = jack_drivers_get_descriptor (drivers, dir_entry->d_name);
  524. if (desc) {
  525. driver_list = jack_slist_append (driver_list, desc);
  526. }
  527. }
  528. err = closedir (dir_stream);
  529. if (err) {
  530. jack_error ("error closing driver directory %s: %s\n",
  531. driver_dir, strerror (errno));
  532. }
  533. if (!driver_list) {
  534. jack_error ("could not find any drivers in %s!\n", driver_dir);
  535. return NULL;
  536. }
  537. return driver_list;
  538. }
  539. #endif
  540. #ifdef WIN32
  541. JSList *
  542. jack_internals_load (JSList * internals) {
  543. char * driver_dir;
  544. char driver_dir_storage[512];
  545. char dll_filename[512];
  546. WIN32_FIND_DATA filedata;
  547. HANDLE file;
  548. const char * ptr = NULL;
  549. JSList * driver_list = NULL;
  550. jack_driver_desc_t * desc;
  551. if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) {
  552. // for WIN32 ADDON_DIR is defined in JackConstants.h as relative path
  553. GetCurrentDirectory(512, driver_dir_storage);
  554. strcat(driver_dir_storage, "/");
  555. strcat(driver_dir_storage, ADDON_DIR);
  556. driver_dir = driver_dir_storage;
  557. }
  558. sprintf(dll_filename, "%s/*.dll", driver_dir);
  559. file = (HANDLE )FindFirstFile(dll_filename, &filedata);
  560. if (file == INVALID_HANDLE_VALUE) {
  561. jack_error("error");
  562. return NULL;
  563. }
  564. do {
  565. /* check if dll is an internal client */
  566. if (!check_symbol(filedata.cFileName, "jack_internal_initialize")) {
  567. continue;
  568. }
  569. ptr = strrchr (filedata.cFileName, '.');
  570. if (!ptr) {
  571. continue;
  572. }
  573. ptr++;
  574. if (strncmp ("dll", ptr, 3) != 0) {
  575. continue;
  576. }
  577. desc = jack_drivers_get_descriptor (internals, filedata.cFileName);
  578. if (desc) {
  579. driver_list = jack_slist_append (driver_list, desc);
  580. }
  581. } while (FindNextFile(file, &filedata));
  582. if (!driver_list) {
  583. jack_error ("could not find any internals in %s!\n", driver_dir);
  584. return NULL;
  585. }
  586. return driver_list;
  587. }
  588. #else
  589. JSList *
  590. jack_internals_load (JSList * internals) {
  591. struct dirent * dir_entry;
  592. DIR * dir_stream;
  593. const char * ptr;
  594. int err;
  595. JSList * driver_list = NULL;
  596. jack_driver_desc_t * desc;
  597. const char* driver_dir;
  598. if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) {
  599. driver_dir = ADDON_DIR;
  600. }
  601. /* search through the driver_dir and add get descriptors
  602. from the .so files in it */
  603. dir_stream = opendir (driver_dir);
  604. if (!dir_stream) {
  605. jack_error ("could not open driver directory %s: %s\n",
  606. driver_dir, strerror (errno));
  607. return NULL;
  608. }
  609. while ((dir_entry = readdir(dir_stream))) {
  610. /* check if dll is an internal client */
  611. if (!check_symbol(dir_entry->d_name, "jack_internal_initialize")) {
  612. continue;
  613. }
  614. ptr = strrchr (dir_entry->d_name, '.');
  615. if (!ptr) {
  616. continue;
  617. }
  618. ptr++;
  619. if (strncmp ("so", ptr, 2) != 0) {
  620. continue;
  621. }
  622. desc = jack_drivers_get_descriptor (internals, dir_entry->d_name);
  623. if (desc) {
  624. driver_list = jack_slist_append (driver_list, desc);
  625. }
  626. }
  627. err = closedir (dir_stream);
  628. if (err) {
  629. jack_error ("error closing internal directory %s: %s\n",
  630. driver_dir, strerror (errno));
  631. }
  632. if (!driver_list) {
  633. jack_error ("could not find any internals in %s!\n", driver_dir);
  634. return NULL;
  635. }
  636. return driver_list;
  637. }
  638. #endif
  639. jack_driver_info_t *
  640. jack_load_driver (jack_driver_desc_t * driver_desc) {
  641. #ifdef WIN32
  642. int errstr;
  643. #else
  644. const char * errstr;
  645. #endif
  646. jack_driver_info_t *info;
  647. info = (jack_driver_info_t *) calloc (1, sizeof (*info));
  648. info->handle = LoadDriverModule (driver_desc->file);
  649. if (info->handle == NULL) {
  650. #ifdef WIN32
  651. if ((errstr = GetLastError ()) != 0) {
  652. jack_error ("can't load \"%s\": %ld", driver_desc->file,
  653. errstr);
  654. #else
  655. if ((errstr = dlerror ()) != 0) {
  656. jack_error ("can't load \"%s\": %s", driver_desc->file,
  657. errstr);
  658. #endif
  659. } else {
  660. jack_error ("bizarre error loading driver shared "
  661. "object %s", driver_desc->file);
  662. }
  663. goto fail;
  664. }
  665. info->initialize = (initialize)GetProc(info->handle, "driver_initialize");
  666. #ifdef WIN32
  667. if ((info->initialize == NULL) && (errstr = GetLastError ()) != 0) {
  668. #else
  669. if ((info->initialize == NULL) && (errstr = dlerror ()) != 0) {
  670. #endif
  671. jack_error ("no initialize function in shared object %s\n",
  672. driver_desc->file);
  673. goto fail;
  674. }
  675. return info;
  676. fail:
  677. if (info->handle) {
  678. UnloadDriverModule(info->handle);
  679. }
  680. free (info);
  681. return NULL;
  682. }