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.

869 lines
26KB

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