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.

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