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.

922 lines
27KB

  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. SERVER_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. SERVER_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. SERVER_EXPORT 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. if (strcasecmp("false", optarg) == 0 ||
  162. strcasecmp("off", optarg) == 0 ||
  163. strcasecmp("no", optarg) == 0 ||
  164. strcasecmp("0", optarg) == 0 ||
  165. strcasecmp("(null)", optarg) == 0 ) {
  166. driver_param->value.i = false;
  167. } else {
  168. driver_param->value.i = true;
  169. }
  170. break;
  171. }
  172. } else {
  173. if (desc->params[param_index].type == JackDriverParamBool) {
  174. driver_param->value.i = true;
  175. } else {
  176. driver_param->value = desc->params[param_index].value;
  177. }
  178. }
  179. params = jack_slist_append (params, driver_param);
  180. }
  181. free (options);
  182. free (long_options);
  183. if (param_ptr)
  184. *param_ptr = params;
  185. return 0;
  186. }
  187. SERVER_EXPORT int
  188. jackctl_parse_driver_params(jackctl_driver *driver_ptr, int argc, char* argv[])
  189. {
  190. struct option * long_options;
  191. char * options, * options_ptr;
  192. unsigned long i;
  193. int opt;
  194. JSList * node_ptr;
  195. jackctl_parameter_t * param = NULL;
  196. union jackctl_parameter_value value;
  197. if (argc <= 1)
  198. return 0;
  199. const JSList * driver_params = jackctl_driver_get_parameters(driver_ptr);
  200. if (driver_params == NULL)
  201. return 1;
  202. jack_driver_desc_t * desc = jackctl_driver_get_desc(driver_ptr);
  203. /* check for help */
  204. if (strcmp (argv[1], "-h") == 0 || strcmp (argv[1], "--help") == 0) {
  205. if (argc > 2) {
  206. for (i = 0; i < desc->nparams; i++) {
  207. if (strcmp (desc->params[i].name, argv[2]) == 0) {
  208. jack_print_driver_param_usage (desc, i, stdout);
  209. return 1;
  210. }
  211. }
  212. fprintf (stderr, "jackd: unknown option '%s' "
  213. "for driver '%s'\n", argv[2],
  214. desc->name);
  215. }
  216. jack_log("Parameters for driver '%s' (all parameters are optional):", desc->name);
  217. jack_print_driver_options (desc, stdout);
  218. return 1;
  219. }
  220. /* set up the stuff for getopt */
  221. options = (char*)calloc (desc->nparams * 3 + 1, sizeof (char));
  222. long_options = (option*)calloc (desc->nparams + 1, sizeof (struct option));
  223. options_ptr = options;
  224. for (i = 0; i < desc->nparams; i++) {
  225. sprintf (options_ptr, "%c::", desc->params[i].character);
  226. options_ptr += 3;
  227. long_options[i].name = desc->params[i].name;
  228. long_options[i].flag = NULL;
  229. long_options[i].val = desc->params[i].character;
  230. long_options[i].has_arg = optional_argument;
  231. }
  232. /* create the params */
  233. optind = 0;
  234. opterr = 0;
  235. while ((opt = getopt_long(argc, argv, options, long_options, NULL)) != -1) {
  236. if (opt == ':' || opt == '?') {
  237. if (opt == ':') {
  238. fprintf (stderr, "Missing option to argument '%c'\n", optopt);
  239. } else {
  240. fprintf (stderr, "Unknownage with option '%c'\n", optopt);
  241. }
  242. fprintf (stderr, "Options for driver '%s':\n", desc->name);
  243. jack_print_driver_options(desc, stderr);
  244. return 1;
  245. }
  246. node_ptr = (JSList *)driver_params;
  247. while (node_ptr) {
  248. param = (jackctl_parameter_t*)node_ptr->data;
  249. if (opt == jackctl_parameter_get_id(param)) {
  250. break;
  251. }
  252. node_ptr = node_ptr->next;
  253. }
  254. if (!optarg && optind < argc &&
  255. strlen(argv[optind]) &&
  256. argv[optind][0] != '-') {
  257. optarg = argv[optind];
  258. }
  259. if (optarg) {
  260. switch (jackctl_parameter_get_type(param)) {
  261. case JackDriverParamInt:
  262. value.i = atoi(optarg);
  263. jackctl_parameter_set_value(param, &value);
  264. break;
  265. case JackDriverParamUInt:
  266. value.ui = strtoul(optarg, NULL, 10);
  267. jackctl_parameter_set_value(param, &value);
  268. break;
  269. case JackDriverParamChar:
  270. value.c = optarg[0];
  271. jackctl_parameter_set_value(param, &value);
  272. break;
  273. case JackDriverParamString:
  274. strncpy(value.str, optarg, JACK_DRIVER_PARAM_STRING_MAX);
  275. jackctl_parameter_set_value(param, &value);
  276. break;
  277. case JackDriverParamBool:
  278. if (strcasecmp("false", optarg) == 0 ||
  279. strcasecmp("off", optarg) == 0 ||
  280. strcasecmp("no", optarg) == 0 ||
  281. strcasecmp("0", optarg) == 0 ||
  282. strcasecmp("(null)", optarg) == 0 ) {
  283. value.i = false;
  284. } else {
  285. value.i = true;
  286. }
  287. jackctl_parameter_set_value(param, &value);
  288. break;
  289. }
  290. } else {
  291. if (jackctl_parameter_get_type(param) == JackParamBool) {
  292. value.i = true;
  293. } else {
  294. value = jackctl_parameter_get_default_value(param);
  295. }
  296. jackctl_parameter_set_value(param, &value);
  297. }
  298. }
  299. free(options);
  300. free(long_options);
  301. return 0;
  302. }
  303. jack_driver_desc_t *
  304. jack_find_driver_descriptor (JSList * drivers, const char * name)
  305. {
  306. jack_driver_desc_t * desc = 0;
  307. JSList * node;
  308. for (node = drivers; node; node = jack_slist_next (node)) {
  309. desc = (jack_driver_desc_t *) node->data;
  310. if (strcmp (desc->name, name) != 0) {
  311. desc = NULL;
  312. } else {
  313. break;
  314. }
  315. }
  316. return desc;
  317. }
  318. static jack_driver_desc_t *
  319. jack_get_descriptor (JSList * drivers, const char * sofile, const char * symbol)
  320. {
  321. jack_driver_desc_t * descriptor, * other_descriptor;
  322. JackDriverDescFunction so_get_descriptor = NULL;
  323. JSList * node;
  324. void * dlhandle;
  325. char * filename;
  326. #ifdef WIN32
  327. int dlerr;
  328. #else
  329. const char * dlerr;
  330. #endif
  331. int err;
  332. const char* driver_dir;
  333. if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) {
  334. // for WIN32 ADDON_DIR is defined in JackConstants.h as relative path
  335. // for posix systems, it is absolute path of default driver dir
  336. #ifdef WIN32
  337. char temp_driver_dir1[512];
  338. char temp_driver_dir2[512];
  339. GetCurrentDirectory(512, temp_driver_dir1);
  340. sprintf(temp_driver_dir2, "%s/%s", temp_driver_dir1, ADDON_DIR);
  341. driver_dir = temp_driver_dir2;
  342. #else
  343. driver_dir = ADDON_DIR;
  344. #endif
  345. }
  346. filename = (char *)malloc(strlen (driver_dir) + 1 + strlen(sofile) + 1);
  347. sprintf (filename, "%s/%s", driver_dir, sofile);
  348. if ((dlhandle = LoadDriverModule(filename)) == NULL) {
  349. #ifdef WIN32
  350. jack_error ("could not open driver .dll '%s': %ld", filename, GetLastError());
  351. #else
  352. jack_error ("could not open driver .so '%s': %s", filename, dlerror());
  353. #endif
  354. free(filename);
  355. return NULL;
  356. }
  357. so_get_descriptor = (JackDriverDescFunction)GetDriverProc(dlhandle, symbol);
  358. #ifdef WIN32
  359. if ((so_get_descriptor == NULL) && (dlerr = GetLastError()) != 0) {
  360. jack_error("jack_get_descriptor : dll is not a driver, err = %ld", dlerr);
  361. #else
  362. if ((so_get_descriptor == NULL) && (dlerr = dlerror ()) != NULL) {
  363. jack_error("jack_get_descriptor err = %s", dlerr);
  364. #endif
  365. UnloadDriverModule(dlhandle);
  366. free(filename);
  367. return NULL;
  368. }
  369. if ((descriptor = so_get_descriptor ()) == NULL) {
  370. jack_error("driver from '%s' returned NULL descriptor", filename);
  371. UnloadDriverModule(dlhandle);
  372. free(filename);
  373. return NULL;
  374. }
  375. #ifdef WIN32
  376. if ((err = UnloadDriverModule(dlhandle)) == 0) {
  377. jack_error ("error closing driver .so '%s': %ld", filename, GetLastError ());
  378. }
  379. #else
  380. if ((err = UnloadDriverModule(dlhandle)) != 0) {
  381. jack_error ("error closing driver .so '%s': %s", filename, dlerror ());
  382. }
  383. #endif
  384. /* check it doesn't exist already */
  385. for (node = drivers; node; node = jack_slist_next (node)) {
  386. other_descriptor = (jack_driver_desc_t *) node->data;
  387. if (strcmp(descriptor->name, other_descriptor->name) == 0) {
  388. jack_error("the drivers in '%s' and '%s' both have the name '%s'; using the first",
  389. other_descriptor->file, filename, other_descriptor->name);
  390. /* FIXME: delete the descriptor */
  391. free(filename);
  392. return NULL;
  393. }
  394. }
  395. strncpy(descriptor->file, filename, JACK_PATH_MAX);
  396. free(filename);
  397. return descriptor;
  398. }
  399. static bool check_symbol(const char* sofile, const char* symbol)
  400. {
  401. void * dlhandle;
  402. bool res = false;
  403. const char* driver_dir;
  404. if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) {
  405. // for WIN32 ADDON_DIR is defined in JackConstants.h as relative path
  406. // for posix systems, it is absolute path of default driver dir
  407. #ifdef WIN32
  408. char temp_driver_dir1[512];
  409. char temp_driver_dir2[512];
  410. GetCurrentDirectory(512, temp_driver_dir1);
  411. sprintf(temp_driver_dir2, "%s/%s", temp_driver_dir1, ADDON_DIR);
  412. driver_dir = temp_driver_dir2;
  413. #else
  414. driver_dir = ADDON_DIR;
  415. #endif
  416. }
  417. char* filename = (char *)malloc(strlen (driver_dir) + 1 + strlen(sofile) + 1);
  418. sprintf (filename, "%s/%s", driver_dir, sofile);
  419. if ((dlhandle = LoadDriverModule(filename)) == NULL) {
  420. #ifdef WIN32
  421. jack_error ("could not open component .dll '%s': %ld", filename, GetLastError());
  422. #else
  423. jack_error ("could not open component .so '%s': %s", filename, dlerror());
  424. #endif
  425. } else {
  426. res = (GetDriverProc(dlhandle, symbol)) ? true : false;
  427. UnloadDriverModule(dlhandle);
  428. }
  429. free(filename);
  430. return res;
  431. }
  432. #ifdef WIN32
  433. JSList *
  434. jack_drivers_load (JSList * drivers) {
  435. char * driver_dir;
  436. char driver_dir_storage[512];
  437. char dll_filename[512];
  438. WIN32_FIND_DATA filedata;
  439. HANDLE file;
  440. const char * ptr = NULL;
  441. JSList * driver_list = NULL;
  442. jack_driver_desc_t * desc = NULL;
  443. if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) {
  444. // for WIN32 ADDON_DIR is defined in JackConstants.h as relative path
  445. GetCurrentDirectory(512, driver_dir_storage);
  446. strcat(driver_dir_storage, "/");
  447. strcat(driver_dir_storage, ADDON_DIR);
  448. driver_dir = driver_dir_storage;
  449. }
  450. sprintf(dll_filename, "%s/*.dll", driver_dir);
  451. file = (HANDLE )FindFirstFile(dll_filename, &filedata);
  452. if (file == INVALID_HANDLE_VALUE) {
  453. jack_error("error invalid handle");
  454. return NULL;
  455. }
  456. do {
  457. /* check the filename is of the right format */
  458. if (strncmp ("jack_", filedata.cFileName, 5) != 0) {
  459. continue;
  460. }
  461. ptr = strrchr (filedata.cFileName, '.');
  462. if (!ptr) {
  463. continue;
  464. }
  465. ptr++;
  466. if (strncmp ("dll", ptr, 3) != 0) {
  467. continue;
  468. }
  469. /* check if dll is an internal client */
  470. if (check_symbol(filedata.cFileName, "jack_internal_initialize")) {
  471. continue;
  472. }
  473. desc = jack_get_descriptor (drivers, filedata.cFileName, "driver_get_descriptor");
  474. if (desc) {
  475. driver_list = jack_slist_append (driver_list, desc);
  476. } else {
  477. jack_error ("jack_get_descriptor returns null for \'%s\'", filedata.cFileName);
  478. }
  479. } while (FindNextFile(file, &filedata));
  480. if (!driver_list) {
  481. jack_error ("could not find any drivers in %s!", driver_dir);
  482. return NULL;
  483. }
  484. return driver_list;
  485. }
  486. #else
  487. JSList *
  488. jack_drivers_load (JSList * drivers) {
  489. struct dirent * dir_entry;
  490. DIR * dir_stream;
  491. const char * ptr;
  492. int err;
  493. JSList * driver_list = NULL;
  494. jack_driver_desc_t * desc = NULL;
  495. const char* driver_dir;
  496. if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) {
  497. driver_dir = ADDON_DIR;
  498. }
  499. /* search through the driver_dir and add get descriptors
  500. from the .so files in it */
  501. dir_stream = opendir (driver_dir);
  502. if (!dir_stream) {
  503. jack_error ("could not open driver directory %s: %s",
  504. driver_dir, strerror (errno));
  505. return NULL;
  506. }
  507. while ((dir_entry = readdir(dir_stream))) {
  508. /* check the filename is of the right format */
  509. if (strncmp ("jack_", dir_entry->d_name, 5) != 0) {
  510. continue;
  511. }
  512. ptr = strrchr (dir_entry->d_name, '.');
  513. if (!ptr) {
  514. continue;
  515. }
  516. ptr++;
  517. if (strncmp ("so", ptr, 2) != 0) {
  518. continue;
  519. }
  520. /* check if dll is an internal client */
  521. if (check_symbol(dir_entry->d_name, "jack_internal_initialize")) {
  522. continue;
  523. }
  524. desc = jack_get_descriptor (drivers, dir_entry->d_name, "driver_get_descriptor");
  525. if (desc) {
  526. driver_list = jack_slist_append (driver_list, desc);
  527. } else {
  528. jack_error ("jack_get_descriptor returns null for \'%s\'", dir_entry->d_name);
  529. }
  530. }
  531. err = closedir (dir_stream);
  532. if (err) {
  533. jack_error ("error closing driver directory %s: %s",
  534. driver_dir, strerror (errno));
  535. }
  536. if (!driver_list) {
  537. jack_error ("could not find any drivers in %s!", driver_dir);
  538. return NULL;
  539. }
  540. return driver_list;
  541. }
  542. #endif
  543. #ifdef WIN32
  544. JSList *
  545. jack_internals_load (JSList * internals) {
  546. char * driver_dir;
  547. char driver_dir_storage[512];
  548. char dll_filename[512];
  549. WIN32_FIND_DATA filedata;
  550. HANDLE file;
  551. const char * ptr = NULL;
  552. JSList * driver_list = NULL;
  553. jack_driver_desc_t * desc;
  554. if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) {
  555. // for WIN32 ADDON_DIR is defined in JackConstants.h as relative path
  556. GetCurrentDirectory(512, driver_dir_storage);
  557. strcat(driver_dir_storage, "/");
  558. strcat(driver_dir_storage, ADDON_DIR);
  559. driver_dir = driver_dir_storage;
  560. }
  561. sprintf(dll_filename, "%s/*.dll", driver_dir);
  562. file = (HANDLE )FindFirstFile(dll_filename, &filedata);
  563. if (file == INVALID_HANDLE_VALUE) {
  564. jack_error("could not open driver directory %s", driver_dir);
  565. return NULL;
  566. }
  567. do {
  568. ptr = strrchr (filedata.cFileName, '.');
  569. if (!ptr) {
  570. continue;
  571. }
  572. ptr++;
  573. if (strncmp ("dll", ptr, 3) != 0) {
  574. continue;
  575. }
  576. /* check if dll is an internal client */
  577. if (!check_symbol(filedata.cFileName, "jack_internal_initialize")) {
  578. continue;
  579. }
  580. desc = jack_get_descriptor (internals, filedata.cFileName, "jack_get_descriptor");
  581. if (desc) {
  582. driver_list = jack_slist_append (driver_list, desc);
  583. } else {
  584. jack_error ("jack_get_descriptor returns null for \'%s\'", filedata.cFileName);
  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. } else {
  631. jack_error ("jack_get_descriptor returns null for \'%s\'", dir_entry->d_name);
  632. }
  633. }
  634. err = closedir (dir_stream);
  635. if (err) {
  636. jack_error ("error closing internal directory %s: %s\n",
  637. driver_dir, strerror (errno));
  638. }
  639. if (!driver_list) {
  640. jack_error ("could not find any internals in %s!", driver_dir);
  641. return NULL;
  642. }
  643. return driver_list;
  644. }
  645. #endif
  646. Jack::JackDriverClientInterface* JackDriverInfo::Open(jack_driver_desc_t* driver_desc,
  647. Jack::JackLockedEngine* engine,
  648. Jack::JackSynchro* synchro,
  649. const JSList* params)
  650. {
  651. #ifdef WIN32
  652. int errstr;
  653. #else
  654. const char * errstr;
  655. #endif
  656. fHandle = LoadDriverModule (driver_desc->file);
  657. if (fHandle == NULL) {
  658. #ifdef WIN32
  659. if ((errstr = GetLastError ()) != 0) {
  660. jack_error ("can't load \"%s\": %ld", driver_desc->file, errstr);
  661. #else
  662. if ((errstr = dlerror ()) != 0) {
  663. jack_error ("can't load \"%s\": %s", driver_desc->file, errstr);
  664. #endif
  665. } else {
  666. jack_error ("bizarre error loading driver shared object %s", driver_desc->file);
  667. }
  668. return NULL;
  669. }
  670. fInitialize = (driverInitialize)GetDriverProc(fHandle, "driver_initialize");
  671. #ifdef WIN32
  672. if ((fInitialize == NULL) && (errstr = GetLastError ()) != 0) {
  673. #else
  674. if ((fInitialize == NULL) && (errstr = dlerror ()) != 0) {
  675. #endif
  676. jack_error("no initialize function in shared object %s\n", driver_desc->file);
  677. return NULL;
  678. }
  679. fBackend = fInitialize(engine, synchro, params);
  680. return fBackend;
  681. }
  682. JackDriverInfo::~JackDriverInfo()
  683. {
  684. delete fBackend;
  685. if (fHandle)
  686. UnloadDriverModule(fHandle);
  687. }
  688. SERVER_EXPORT
  689. jack_driver_desc_t *
  690. jack_driver_descriptor_construct(
  691. const char * name,
  692. jack_driver_type_t type,
  693. const char * description,
  694. jack_driver_desc_filler_t * filler_ptr)
  695. {
  696. size_t name_len;
  697. size_t description_len;
  698. jack_driver_desc_t * desc_ptr;
  699. name_len = strlen(name);
  700. description_len = strlen(description);
  701. if (name_len > sizeof(desc_ptr->name) - 1 ||
  702. description_len > sizeof(desc_ptr->desc) - 1) {
  703. assert(false);
  704. return 0;
  705. }
  706. desc_ptr = (jack_driver_desc_t*)calloc (1, sizeof (jack_driver_desc_t));
  707. if (desc_ptr == NULL) {
  708. jack_error("calloc() failed to allocate memory for driver descriptor struct");
  709. return 0;
  710. }
  711. memcpy(desc_ptr->name, name, name_len + 1);
  712. memcpy(desc_ptr->desc, description, description_len + 1);
  713. desc_ptr->nparams = 0;
  714. if (filler_ptr != NULL) {
  715. filler_ptr->size = 0;
  716. }
  717. return desc_ptr;
  718. }
  719. SERVER_EXPORT
  720. int
  721. jack_driver_descriptor_add_parameter(
  722. jack_driver_desc_t * desc_ptr,
  723. jack_driver_desc_filler_t * filler_ptr,
  724. const char * name,
  725. char character,
  726. jack_driver_param_type_t type,
  727. const jack_driver_param_value_t * value_ptr,
  728. jack_driver_param_constraint_desc_t * constraint,
  729. const char * short_desc,
  730. const char * long_desc)
  731. {
  732. size_t name_len;
  733. size_t short_desc_len;
  734. size_t long_desc_len;
  735. jack_driver_param_desc_t * param_ptr;
  736. size_t newsize;
  737. name_len = strlen(name);
  738. short_desc_len = strlen(short_desc);
  739. if (long_desc != NULL) {
  740. long_desc_len = strlen(long_desc);
  741. } else {
  742. long_desc = short_desc;
  743. long_desc_len = short_desc_len;
  744. }
  745. if (name_len > sizeof(param_ptr->name) - 1 ||
  746. short_desc_len > sizeof(param_ptr->short_desc) - 1 ||
  747. long_desc_len > sizeof(param_ptr->long_desc) - 1) {
  748. assert(false);
  749. return 0;
  750. }
  751. if (desc_ptr->nparams == filler_ptr->size) {
  752. newsize = filler_ptr->size + 20; // most drivers have less than 20 parameters
  753. param_ptr = (jack_driver_param_desc_t*)realloc (desc_ptr->params, newsize * sizeof (jack_driver_param_desc_t));
  754. if (param_ptr == NULL) {
  755. jack_error("realloc() failed for parameter array of %zu elements", newsize);
  756. return false;
  757. }
  758. filler_ptr->size = newsize;
  759. desc_ptr->params = param_ptr;
  760. }
  761. assert(desc_ptr->nparams < filler_ptr->size);
  762. param_ptr = desc_ptr->params + desc_ptr->nparams;
  763. memcpy(param_ptr->name, name, name_len + 1);
  764. param_ptr->character = character;
  765. param_ptr->type = type;
  766. param_ptr->value = *value_ptr;
  767. param_ptr->constraint = constraint;
  768. memcpy(param_ptr->short_desc, short_desc, short_desc_len + 1);
  769. memcpy(param_ptr->long_desc, long_desc, long_desc_len + 1);
  770. desc_ptr->nparams++;
  771. return true;
  772. }