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.

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