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.

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