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.

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