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.

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