Jack2: JackDriverLoader.cpp Source File

Jack2 1.9.12

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