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.

837 lines
25KB

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