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.

1031 lines
31KB

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