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.

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