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.

956 lines
28KB

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