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.

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