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.

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