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.

836 lines
24KB

  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. static jack_driver_desc_t *
  348. jack_get_descriptor (JSList * drivers, const char * sofile, const char * symbol)
  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, symbol);
  388. #ifdef WIN32
  389. if ((so_get_descriptor == NULL) && (dlerr = GetLastError()) != 0) {
  390. jack_error("jack_get_descriptor err = %ld", dlerr);
  391. #else
  392. if ((so_get_descriptor == NULL) && (dlerr = dlerror ()) != NULL) {
  393. jack_error("jack_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* sofile, const char* symbol)
  430. {
  431. void * dlhandle;
  432. bool res = false;
  433. const char* driver_dir;
  434. if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) {
  435. // for WIN32 ADDON_DIR is defined in JackConstants.h as relative path
  436. // for posix systems, it is absolute path of default driver dir
  437. #ifdef WIN32
  438. char temp_driver_dir1[512];
  439. char temp_driver_dir2[512];
  440. GetCurrentDirectory(512, temp_driver_dir1);
  441. sprintf(temp_driver_dir2, "%s/%s", temp_driver_dir1, ADDON_DIR);
  442. driver_dir = temp_driver_dir2;
  443. #else
  444. driver_dir = ADDON_DIR;
  445. #endif
  446. }
  447. char* filename = (char *)malloc(strlen (driver_dir) + 1 + strlen(sofile) + 1);
  448. sprintf (filename, "%s/%s", driver_dir, sofile);
  449. if ((dlhandle = LoadDriverModule(filename)) == NULL) {
  450. #ifdef WIN32
  451. jack_error ("could not open component .dll '%s': %ld\n", filename, GetLastError());
  452. #else
  453. jack_error ("could not open component .so '%s': %s\n", filename, dlerror());
  454. #endif
  455. } else {
  456. res = (GetProc(dlhandle, symbol)) ? true : false;
  457. UnloadDriverModule(dlhandle);
  458. }
  459. free(filename);
  460. return res;
  461. }
  462. #ifdef WIN32
  463. JSList *
  464. jack_drivers_load (JSList * drivers) {
  465. char * driver_dir;
  466. char driver_dir_storage[512];
  467. char dll_filename[512];
  468. WIN32_FIND_DATA filedata;
  469. HANDLE file;
  470. const char * ptr = NULL;
  471. JSList * driver_list = NULL;
  472. jack_driver_desc_t * desc;
  473. if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) {
  474. // for WIN32 ADDON_DIR is defined in JackConstants.h as relative path
  475. GetCurrentDirectory(512, driver_dir_storage);
  476. strcat(driver_dir_storage, "/");
  477. strcat(driver_dir_storage, ADDON_DIR);
  478. driver_dir = driver_dir_storage;
  479. }
  480. sprintf(dll_filename, "%s/*.dll", driver_dir);
  481. file = (HANDLE )FindFirstFile(dll_filename, &filedata);
  482. if (file == INVALID_HANDLE_VALUE) {
  483. jack_error("error");
  484. return NULL;
  485. }
  486. do {
  487. ptr = strrchr (filedata.cFileName, '.');
  488. if (!ptr) {
  489. continue;
  490. }
  491. ptr++;
  492. if (strncmp ("dll", ptr, 3) != 0) {
  493. continue;
  494. }
  495. desc = jack_get_descriptor (drivers, filedata.cFileName, "driver_get_descriptor");
  496. if (desc) {
  497. driver_list = jack_slist_append (driver_list, desc);
  498. }
  499. } while (FindNextFile(file, &filedata));
  500. if (!driver_list) {
  501. jack_error ("could not find any drivers in %s!\n", driver_dir);
  502. return NULL;
  503. }
  504. return driver_list;
  505. }
  506. #else
  507. JSList *
  508. jack_drivers_load (JSList * drivers) {
  509. struct dirent * dir_entry;
  510. DIR * dir_stream;
  511. const char * ptr;
  512. int err;
  513. JSList * driver_list = NULL;
  514. jack_driver_desc_t * desc;
  515. const char* driver_dir;
  516. if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) {
  517. driver_dir = ADDON_DIR;
  518. }
  519. /* search through the driver_dir and add get descriptors
  520. from the .so files in it */
  521. dir_stream = opendir (driver_dir);
  522. if (!dir_stream) {
  523. jack_error ("could not open driver directory %s: %s\n",
  524. driver_dir, strerror (errno));
  525. return NULL;
  526. }
  527. while ((dir_entry = readdir(dir_stream))) {
  528. /* check the filename is of the right format */
  529. if (strncmp ("jack_", dir_entry->d_name, 5) != 0) {
  530. continue;
  531. }
  532. ptr = strrchr (dir_entry->d_name, '.');
  533. if (!ptr) {
  534. continue;
  535. }
  536. ptr++;
  537. if (strncmp ("so", ptr, 2) != 0) {
  538. continue;
  539. }
  540. desc = jack_get_descriptor (drivers, dir_entry->d_name, "driver_get_descriptor");
  541. if (desc) {
  542. driver_list = jack_slist_append (driver_list, desc);
  543. }
  544. }
  545. err = closedir (dir_stream);
  546. if (err) {
  547. jack_error ("error closing driver directory %s: %s\n",
  548. driver_dir, strerror (errno));
  549. }
  550. if (!driver_list) {
  551. jack_error ("could not find any drivers in %s!\n", driver_dir);
  552. return NULL;
  553. }
  554. return driver_list;
  555. }
  556. #endif
  557. #ifdef WIN32
  558. JSList *
  559. jack_internals_load (JSList * internals) {
  560. char * driver_dir;
  561. char driver_dir_storage[512];
  562. char dll_filename[512];
  563. WIN32_FIND_DATA filedata;
  564. HANDLE file;
  565. const char * ptr = NULL;
  566. JSList * driver_list = NULL;
  567. jack_driver_desc_t * desc;
  568. if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) {
  569. // for WIN32 ADDON_DIR is defined in JackConstants.h as relative path
  570. GetCurrentDirectory(512, driver_dir_storage);
  571. strcat(driver_dir_storage, "/");
  572. strcat(driver_dir_storage, ADDON_DIR);
  573. driver_dir = driver_dir_storage;
  574. }
  575. sprintf(dll_filename, "%s/*.dll", driver_dir);
  576. file = (HANDLE )FindFirstFile(dll_filename, &filedata);
  577. if (file == INVALID_HANDLE_VALUE) {
  578. jack_error("error");
  579. return NULL;
  580. }
  581. do {
  582. ptr = strrchr (filedata.cFileName, '.');
  583. if (!ptr) {
  584. continue;
  585. }
  586. ptr++;
  587. if (strncmp ("dll", ptr, 3) != 0) {
  588. continue;
  589. }
  590. /* check if dll is an internal client */
  591. if (!check_symbol(filedata.cFileName, "jack_internal_initialize")) {
  592. continue;
  593. }
  594. desc = jack_get_descriptor (internals, filedata.cFileName, "jack_get_descriptor");
  595. if (desc) {
  596. driver_list = jack_slist_append (driver_list, desc);
  597. }
  598. } while (FindNextFile(file, &filedata));
  599. if (!driver_list) {
  600. jack_error ("could not find any internals in %s!\n", driver_dir);
  601. return NULL;
  602. }
  603. return driver_list;
  604. }
  605. #else
  606. JSList *
  607. jack_internals_load (JSList * internals) {
  608. struct dirent * dir_entry;
  609. DIR * dir_stream;
  610. const char * ptr;
  611. int err;
  612. JSList * driver_list = NULL;
  613. jack_driver_desc_t * desc;
  614. const char* driver_dir;
  615. if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) {
  616. driver_dir = ADDON_DIR;
  617. }
  618. /* search through the driver_dir and add get descriptors
  619. from the .so files in it */
  620. dir_stream = opendir (driver_dir);
  621. if (!dir_stream) {
  622. jack_error ("could not open driver directory %s: %s\n",
  623. driver_dir, strerror (errno));
  624. return NULL;
  625. }
  626. while ((dir_entry = readdir(dir_stream))) {
  627. ptr = strrchr (dir_entry->d_name, '.');
  628. if (!ptr) {
  629. continue;
  630. }
  631. ptr++;
  632. if (strncmp ("so", ptr, 2) != 0) {
  633. continue;
  634. }
  635. /* check if dll is an internal client */
  636. if (!check_symbol(dir_entry->d_name, "jack_internal_initialize")) {
  637. continue;
  638. }
  639. desc = jack_get_descriptor (internals, dir_entry->d_name, "jack_get_descriptor");
  640. if (desc) {
  641. driver_list = jack_slist_append (driver_list, desc);
  642. }
  643. }
  644. err = closedir (dir_stream);
  645. if (err) {
  646. jack_error ("error closing internal directory %s: %s\n",
  647. driver_dir, strerror (errno));
  648. }
  649. if (!driver_list) {
  650. jack_error ("could not find any internals in %s!\n", driver_dir);
  651. return NULL;
  652. }
  653. return driver_list;
  654. }
  655. #endif
  656. jack_driver_info_t *
  657. jack_load_driver (jack_driver_desc_t * driver_desc) {
  658. #ifdef WIN32
  659. int errstr;
  660. #else
  661. const char * errstr;
  662. #endif
  663. jack_driver_info_t *info;
  664. info = (jack_driver_info_t *) calloc (1, sizeof (*info));
  665. info->handle = LoadDriverModule (driver_desc->file);
  666. if (info->handle == NULL) {
  667. #ifdef WIN32
  668. if ((errstr = GetLastError ()) != 0) {
  669. jack_error ("can't load \"%s\": %ld", driver_desc->file,
  670. errstr);
  671. #else
  672. if ((errstr = dlerror ()) != 0) {
  673. jack_error ("can't load \"%s\": %s", driver_desc->file,
  674. errstr);
  675. #endif
  676. } else {
  677. jack_error ("bizarre error loading driver shared "
  678. "object %s", driver_desc->file);
  679. }
  680. goto fail;
  681. }
  682. info->initialize = (initialize)GetProc(info->handle, "driver_initialize");
  683. #ifdef WIN32
  684. if ((info->initialize == NULL) && (errstr = GetLastError ()) != 0) {
  685. #else
  686. if ((info->initialize == NULL) && (errstr = dlerror ()) != 0) {
  687. #endif
  688. jack_error ("no initialize function in shared object %s\n",
  689. driver_desc->file);
  690. goto fail;
  691. }
  692. return info;
  693. fail:
  694. if (info->handle) {
  695. UnloadDriverModule(info->handle);
  696. }
  697. free (info);
  698. return NULL;
  699. }