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.

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