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.

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