2 Copyright (C) 2001-2005 Paul Davis
3 Copyright (C) 2004-2008 Grame
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.
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.
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.
21 #include "JackSystemDeps.h"
22 #include "JackDriverLoader.h"
23 #include "JackDriverInfo.h"
24 #include "JackConstants.h"
25 #include "JackError.h"
36 typedef wchar_t file_char_t
;
38 typedef char file_char_t
;
43 static wchar_t* locate_dll_driver_dir()
45 HMODULE libjack_handle
= NULL
;
46 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
| GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT
,
47 reinterpret_cast<LPCWSTR
>(locate_dll_driver_dir
), &libjack_handle
);
49 // For WIN32 ADDON_DIR is defined in JackConstants.h as relative path
50 wchar_t driver_dir_storage
[512];
51 if (3 < GetModuleFileNameW(libjack_handle
, driver_dir_storage
, 512)) {
52 wchar_t *p
= wcsrchr(driver_dir_storage
, L
'\\');
53 if (p
&& (p
!= driver_dir_storage
)) {
56 jack_info("Drivers/internals found in : %S", driver_dir_storage
);
57 wcscat(driver_dir_storage
, L
"\\");
58 wcscat(driver_dir_storage
, ADDON_DIRW
);
59 return wcsdup(driver_dir_storage
);
61 jack_error("Cannot get JACK dll directory : %d", GetLastError());
66 static wchar_t* locate_driver_dir(HANDLE
& file
, WIN32_FIND_DATAW
& filedata
)
68 // Search drivers/internals iin the same folder of "libjackserver.dll"
69 wchar_t* driver_dir
= locate_dll_driver_dir();
70 wchar_t dll_filename
[512];
71 swprintf(dll_filename
, 510, L
"%S/*.dll", driver_dir
);
72 file
= (HANDLE
)FindFirstFileW(dll_filename
, &filedata
);
74 if (file
== INVALID_HANDLE_VALUE
) {
75 jack_error("Drivers not found in \"%S\": \"%S\"", driver_dir
, dll_filename
);
85 jack_driver_desc_t
* jackctl_driver_get_desc(jackctl_driver_t
* driver
);
87 void jack_print_driver_options(jack_driver_desc_t
* desc
, FILE* file
)
90 char arg_default
[JACK_DRIVER_PARAM_STRING_MAX
+ 1];
92 for (i
= 0; i
< desc
->nparams
; i
++) {
93 switch (desc
->params
[i
].type
) {
94 case JackDriverParamInt
:
95 sprintf (arg_default
, "%" "i", desc
->params
[i
].value
.i
);
97 case JackDriverParamUInt
:
98 sprintf (arg_default
, "%" "u", desc
->params
[i
].value
.ui
);
100 case JackDriverParamChar
:
101 sprintf (arg_default
, "%c", desc
->params
[i
].value
.c
);
103 case JackDriverParamString
:
104 if (desc
->params
[i
].value
.str
&& strcmp (desc
->params
[i
].value
.str
, "") != 0) {
105 sprintf (arg_default
, "%s", desc
->params
[i
].value
.str
);
107 sprintf (arg_default
, "none");
110 case JackDriverParamBool
:
111 sprintf (arg_default
, "%s", desc
->params
[i
].value
.i
? "true" : "false");
115 fprintf(file
, "\t-%c, --%s \t%s (default: %s)\n",
116 desc
->params
[i
].character
,
117 desc
->params
[i
].name
,
118 desc
->params
[i
].long_desc
,
123 static void jack_print_driver_param_usage (jack_driver_desc_t
* desc
, unsigned long param
, FILE *file
)
125 fprintf (file
, "Usage information for the '%s' parameter for driver '%s':\n",
126 desc
->params
[param
].name
, desc
->name
);
127 fprintf (file
, "%s\n", desc
->params
[param
].long_desc
);
130 void jack_free_driver_params(JSList
* driver_params
)
132 JSList
*node_ptr
= driver_params
;
133 JSList
*next_node_ptr
;
136 next_node_ptr
= node_ptr
->next
;
137 free(node_ptr
->data
);
139 node_ptr
= next_node_ptr
;
143 int jack_parse_driver_params(jack_driver_desc_t
* desc
, int argc
, char* argv
[], JSList
** param_ptr
)
145 struct option
* long_options
;
146 char* options
, * options_ptr
;
149 unsigned int param_index
;
150 JSList
* params
= NULL
;
151 jack_driver_param_t
* driver_param
;
159 if (strcmp (argv
[1], "-h") == 0 || strcmp (argv
[1], "--help") == 0) {
161 for (i
= 0; i
< desc
->nparams
; i
++) {
162 if (strcmp (desc
->params
[i
].name
, argv
[2]) == 0) {
163 jack_print_driver_param_usage (desc
, i
, stdout
);
168 fprintf (stderr
, "Jackd: unknown option '%s' "
169 "for driver '%s'\n", argv
[2],
173 jack_log("Parameters for driver '%s' (all parameters are optional):", desc
->name
);
174 jack_print_driver_options (desc
, stdout
);
178 /* set up the stuff for getopt */
179 options
= (char*)calloc (desc
->nparams
* 3 + 1, sizeof (char));
180 long_options
= (option
*)calloc (desc
->nparams
+ 1, sizeof (struct option
));
182 options_ptr
= options
;
183 for (i
= 0; i
< desc
->nparams
; i
++) {
184 sprintf (options_ptr
, "%c::", desc
->params
[i
].character
);
186 long_options
[i
].name
= desc
->params
[i
].name
;
187 long_options
[i
].flag
= NULL
;
188 long_options
[i
].val
= desc
->params
[i
].character
;
189 long_options
[i
].has_arg
= optional_argument
;
192 /* create the params */
195 while ((opt
= getopt_long(argc
, argv
, options
, long_options
, NULL
)) != -1) {
197 if (opt
== ':' || opt
== '?') {
199 fprintf (stderr
, "Missing option to argument '%c'\n", optopt
);
201 fprintf (stderr
, "Unknownage with option '%c'\n", optopt
);
204 fprintf (stderr
, "Options for driver '%s':\n", desc
->name
);
205 jack_print_driver_options (desc
, stderr
);
209 for (param_index
= 0; param_index
< desc
->nparams
; param_index
++) {
210 if (opt
== desc
->params
[param_index
].character
) {
215 driver_param
= (jack_driver_param_t
*)calloc (1, sizeof (jack_driver_param_t
));
216 driver_param
->character
= desc
->params
[param_index
].character
;
218 if (!optarg
&& optind
< argc
&&
219 strlen(argv
[optind
]) &&
220 argv
[optind
][0] != '-') {
221 optarg
= argv
[optind
];
225 switch (desc
->params
[param_index
].type
) {
226 case JackDriverParamInt
:
227 driver_param
->value
.i
= atoi(optarg
);
229 case JackDriverParamUInt
:
230 driver_param
->value
.ui
= strtoul(optarg
, NULL
, 10);
232 case JackDriverParamChar
:
233 driver_param
->value
.c
= optarg
[0];
235 case JackDriverParamString
:
236 strncpy (driver_param
->value
.str
, optarg
, JACK_DRIVER_PARAM_STRING_MAX
);
238 case JackDriverParamBool
:
239 if (strcasecmp("false", optarg
) == 0 ||
240 strcasecmp("off", optarg
) == 0 ||
241 strcasecmp("no", optarg
) == 0 ||
242 strcasecmp("0", optarg
) == 0 ||
243 strcasecmp("(null)", optarg
) == 0 ) {
244 driver_param
->value
.i
= false;
246 driver_param
->value
.i
= true;
251 if (desc
->params
[param_index
].type
== JackDriverParamBool
) {
252 driver_param
->value
.i
= true;
254 driver_param
->value
= desc
->params
[param_index
].value
;
258 params
= jack_slist_append (params
, driver_param
);
270 SERVER_EXPORT
int jackctl_driver_params_parse(jackctl_driver
*driver_ptr
, int argc
, char* argv
[])
272 struct option
* long_options
;
273 char* options
, * options_ptr
;
277 jackctl_parameter_t
* param
= NULL
;
278 union jackctl_parameter_value value
;
284 const JSList
* driver_params
= jackctl_driver_get_parameters(driver_ptr
);
285 if (driver_params
== NULL
) {
289 jack_driver_desc_t
* desc
= jackctl_driver_get_desc(driver_ptr
);
292 if (strcmp (argv
[1], "-h") == 0 || strcmp (argv
[1], "--help") == 0) {
294 for (i
= 0; i
< desc
->nparams
; i
++) {
295 if (strcmp (desc
->params
[i
].name
, argv
[2]) == 0) {
296 jack_print_driver_param_usage (desc
, i
, stdout
);
301 fprintf (stderr
, "Jackd: unknown option '%s' "
302 "for driver '%s'\n", argv
[2],
306 jack_log("Parameters for driver '%s' (all parameters are optional):", desc
->name
);
307 jack_print_driver_options (desc
, stdout
);
311 /* set up the stuff for getopt */
312 options
= (char*)calloc (desc
->nparams
* 3 + 1, sizeof (char));
313 long_options
= (option
*)calloc (desc
->nparams
+ 1, sizeof (struct option
));
315 options_ptr
= options
;
316 for (i
= 0; i
< desc
->nparams
; i
++) {
317 sprintf(options_ptr
, "%c::", desc
->params
[i
].character
);
319 long_options
[i
].name
= desc
->params
[i
].name
;
320 long_options
[i
].flag
= NULL
;
321 long_options
[i
].val
= desc
->params
[i
].character
;
322 long_options
[i
].has_arg
= optional_argument
;
325 /* create the params */
328 while ((opt
= getopt_long(argc
, argv
, options
, long_options
, NULL
)) != -1) {
330 if (opt
== ':' || opt
== '?') {
332 fprintf (stderr
, "Missing option to argument '%c'\n", optopt
);
334 fprintf (stderr
, "Unknownage with option '%c'\n", optopt
);
337 fprintf (stderr
, "Options for driver '%s':\n", desc
->name
);
338 jack_print_driver_options(desc
, stderr
);
342 node_ptr
= (JSList
*)driver_params
;
344 param
= (jackctl_parameter_t
*)node_ptr
->data
;
345 if (opt
== jackctl_parameter_get_id(param
)) {
348 node_ptr
= node_ptr
->next
;
351 if (!optarg
&& optind
< argc
&&
352 strlen(argv
[optind
]) &&
353 argv
[optind
][0] != '-') {
354 optarg
= argv
[optind
];
358 switch (jackctl_parameter_get_type(param
)) {
359 case JackDriverParamInt
:
360 value
.i
= atoi(optarg
);
361 jackctl_parameter_set_value(param
, &value
);
363 case JackDriverParamUInt
:
364 value
.ui
= strtoul(optarg
, NULL
, 10);
365 jackctl_parameter_set_value(param
, &value
);
367 case JackDriverParamChar
:
369 jackctl_parameter_set_value(param
, &value
);
371 case JackDriverParamString
:
372 strncpy(value
.str
, optarg
, JACK_DRIVER_PARAM_STRING_MAX
);
373 jackctl_parameter_set_value(param
, &value
);
375 case JackDriverParamBool
:
376 if (strcasecmp("false", optarg
) == 0 ||
377 strcasecmp("off", optarg
) == 0 ||
378 strcasecmp("no", optarg
) == 0 ||
379 strcasecmp("0", optarg
) == 0 ||
380 strcasecmp("(null)", optarg
) == 0 ) {
385 jackctl_parameter_set_value(param
, &value
);
389 if (jackctl_parameter_get_type(param
) == JackParamBool
) {
392 value
= jackctl_parameter_get_default_value(param
);
394 jackctl_parameter_set_value(param
, &value
);
403 jack_driver_desc_t
* jack_find_driver_descriptor (JSList
* drivers
, const char* name
)
405 jack_driver_desc_t
* desc
= 0;
408 for (node
= drivers
; node
; node
= jack_slist_next (node
)) {
409 desc
= (jack_driver_desc_t
*) node
->data
;
411 if (strcmp (desc
->name
, name
) != 0) {
421 static void* check_symbol(const file_char_t
* sofile
, const char* symbol
, const file_char_t
* driver_dir
, void** res_dllhandle
= NULL
)
425 file_char_t filename
[1024];
427 swprintf(filename
, 1022, L
"%S/%S", driver_dir
, sofile
);
429 snprintf(filename
, 1022, "%s/%s", driver_dir
, sofile
);
432 if ((dlhandle
= LoadDriverModule(filename
)) == NULL
) {
434 jack_error ("Could not open component .dll '%S': %ld", filename
, GetLastError());
436 jack_error ("Could not open component .so '%s': %s", filename
, dlerror());
439 res
= (void*)GetDriverProc(dlhandle
, symbol
);
441 *res_dllhandle
= dlhandle
;
443 UnloadDriverModule(dlhandle
);
450 static jack_driver_desc_t
* jack_get_descriptor (JSList
* drivers
, const file_char_t
* sofile
, const char* symbol
, const file_char_t
* driver_dir
)
452 jack_driver_desc_t
* descriptor
= NULL
;
453 jack_driver_desc_t
* other_descriptor
;
454 JackDriverDescFunction so_get_descriptor
= NULL
;
455 file_char_t filename
[1024];
457 void* dlhandle
= NULL
;
460 swprintf(filename
, 1022, L
"%S/%S", driver_dir
, sofile
);
462 snprintf(filename
, 1022, "%s/%s", driver_dir
, sofile
);
465 so_get_descriptor
= (JackDriverDescFunction
)check_symbol(sofile
, symbol
, driver_dir
, &dlhandle
);
467 if (so_get_descriptor
== NULL
) {
468 jack_error("jack_get_descriptor : dll %S is not a driver", sofile
);
472 if ((descriptor
= so_get_descriptor ()) == NULL
) {
473 jack_error("Driver from '%S' returned NULL descriptor", filename
);
477 /* check it doesn't exist already */
478 for (node
= drivers
; node
; node
= jack_slist_next (node
)) {
479 other_descriptor
= (jack_driver_desc_t
*) node
->data
;
480 if (strcmp(descriptor
->name
, other_descriptor
->name
) == 0) {
481 jack_error("The drivers in '%S' and '%S' both have the name '%S'; using the first",
482 other_descriptor
->file
, filename
, other_descriptor
->name
);
483 /* FIXME: delete the descriptor */
489 wcsncpy(descriptor
->file
, filename
, JACK_PATH_MAX
);
491 strncpy(descriptor
->file
, filename
, JACK_PATH_MAX
);
496 UnloadDriverModule(dlhandle
);
503 JSList
* jack_drivers_load(JSList
* drivers
)
505 //char dll_filename[512];
506 WIN32_FIND_DATAW filedata
;
508 const wchar_t* ptr
= NULL
;
509 JSList
* driver_list
= NULL
;
510 jack_driver_desc_t
* desc
= NULL
;
512 wchar_t* driver_dir
= locate_driver_dir(file
, filedata
);
514 jack_error("Driver folder not found");
519 /* check the filename is of the right format */
520 if (wcsncmp (L
"jack_", filedata
.cFileName
, 5) != 0) {
524 ptr
= wcsrchr (filedata
.cFileName
, L
'.');
530 if (wcsncmp (L
"dll", ptr
, 3) != 0) {
534 /* check if dll is an internal client */
535 if (check_symbol(filedata
.cFileName
, "jack_internal_initialize", driver_dir
) != NULL
) {
539 desc
= jack_get_descriptor (drivers
, filedata
.cFileName
, "driver_get_descriptor", driver_dir
);
541 driver_list
= jack_slist_append (driver_list
, desc
);
543 jack_error ("jack_get_descriptor returns null for \'%S\'", filedata
.cFileName
);
546 } while (FindNextFileW(file
, &filedata
));
549 jack_error ("Could not find any drivers in %S!", driver_dir
);
562 JSList
* jack_drivers_load (JSList
* drivers
)
564 struct dirent
* dir_entry
;
568 JSList
* driver_list
= NULL
;
569 jack_driver_desc_t
* desc
= NULL
;
571 const char* driver_dir
;
572 if ((driver_dir
= getenv("JACK_DRIVER_DIR")) == 0) {
573 driver_dir
= ADDON_DIR
;
576 /* search through the driver_dir and add get descriptors
577 from the .so files in it */
578 dir_stream
= opendir (driver_dir
);
580 jack_error ("Could not open driver directory %s: %s",
581 driver_dir
, strerror (errno
));
585 while ((dir_entry
= readdir(dir_stream
))) {
587 /* check the filename is of the right format */
588 if (strncmp ("jack_", dir_entry
->d_name
, 5) != 0) {
592 ptr
= strrchr (dir_entry
->d_name
, '.');
597 if (strncmp ("so", ptr
, 2) != 0) {
601 /* check if dll is an internal client */
602 if (check_symbol(dir_entry
->d_name
, "jack_internal_initialize", driver_dir
) != NULL
) {
606 desc
= jack_get_descriptor (drivers
, dir_entry
->d_name
, "driver_get_descriptor", driver_dir
);
608 driver_list
= jack_slist_append (driver_list
, desc
);
610 jack_error ("jack_get_descriptor returns null for \'%s\'", dir_entry
->d_name
);
614 err
= closedir (dir_stream
);
616 jack_error ("Error closing driver directory %s: %s",
617 driver_dir
, strerror (errno
));
621 jack_error ("Could not find any drivers in %s!", driver_dir
);
632 JSList
* jack_internals_load(JSList
* internals
)
634 ///char dll_filename[512];
635 WIN32_FIND_DATAW filedata
;
637 const wchar_t* ptr
= NULL
;
638 JSList
* driver_list
= NULL
;
639 jack_driver_desc_t
* desc
;
641 wchar_t* driver_dir
= locate_driver_dir(file
, filedata
);
643 jack_error("Driver folder not found");
649 ptr
= wcsrchr (filedata
.cFileName
, L
'.');
655 if (wcsncmp (L
"dll", ptr
, 3) != 0) {
659 /* check if dll is an internal client */
660 if (check_symbol(filedata
.cFileName
, "jack_internal_initialize", driver_dir
) == NULL
) {
664 desc
= jack_get_descriptor (internals
, filedata
.cFileName
, "jack_get_descriptor", driver_dir
);
666 driver_list
= jack_slist_append (driver_list
, desc
);
668 jack_error ("jack_get_descriptor returns null for \'%s\'", filedata
.cFileName
);
671 } while (FindNextFileW(file
, &filedata
));
674 jack_error ("Could not find any internals in %s!", driver_dir
);
687 JSList
* jack_internals_load(JSList
* internals
)
689 struct dirent
* dir_entry
;
693 JSList
* driver_list
= NULL
;
694 jack_driver_desc_t
* desc
;
696 const char* driver_dir
;
697 if ((driver_dir
= getenv("JACK_DRIVER_DIR")) == 0) {
698 driver_dir
= ADDON_DIR
;
701 /* search through the driver_dir and add get descriptors
702 from the .so files in it */
703 dir_stream
= opendir (driver_dir
);
705 jack_error ("Could not open driver directory %s: %s\n",
706 driver_dir
, strerror (errno
));
710 while ((dir_entry
= readdir(dir_stream
))) {
712 ptr
= strrchr (dir_entry
->d_name
, '.');
718 if (strncmp ("so", ptr
, 2) != 0) {
722 /* check if dll is an internal client */
723 if (check_symbol(dir_entry
->d_name
, "jack_internal_initialize", driver_dir
) == NULL
) {
727 desc
= jack_get_descriptor (internals
, dir_entry
->d_name
, "jack_get_descriptor", driver_dir
);
729 driver_list
= jack_slist_append (driver_list
, desc
);
731 jack_error ("jack_get_descriptor returns null for \'%s\'", dir_entry
->d_name
);
735 err
= closedir (dir_stream
);
737 jack_error ("Error closing internal directory %s: %s\n",
738 driver_dir
, strerror (errno
));
742 jack_error ("Could not find any internals in %s!", driver_dir
);
751 Jack::JackDriverClientInterface
* JackDriverInfo::Open(jack_driver_desc_t
* driver_desc
,
752 Jack::JackLockedEngine
* engine
,
753 Jack::JackSynchro
* synchro
,
754 const JSList
* params
)
762 fHandle
= LoadDriverModule (driver_desc
->file
);
764 if (fHandle
== NULL
) {
766 if ((errstr
= GetLastError ()) != 0) {
767 jack_error ("Can't load \"%S\": %ld", driver_desc
->file
, errstr
);
769 if ((errstr
= dlerror ()) != 0) {
770 jack_error ("Can't load \"%s\": %s", driver_desc
->file
, errstr
);
775 jack_error ("Error loading driver shared object %S", driver_desc
->file
);
777 jack_error ("Error loading driver shared object %s", driver_desc
->file
);
784 //jack_error (" --------------------------------- Successfully opened driver \"%S\"\n", driver_desc->file);
787 fInitialize
= (driverInitialize
)GetDriverProc(fHandle
, "driver_initialize");
790 if ((fInitialize
== NULL
) && (errstr
= GetLastError ()) != 0) {
792 if ((fInitialize
== NULL
) && (errstr
= dlerror ()) != 0) {
796 jack_error("No initialize function in shared object %S\n", driver_desc
->file
);
798 jack_error("No initialize function in shared object %s\n", driver_desc
->file
);
803 fBackend
= fInitialize(engine
, synchro
, params
);
807 JackDriverInfo::~JackDriverInfo()
811 UnloadDriverModule(fHandle
);
815 SERVER_EXPORT jack_driver_desc_t
* jack_driver_descriptor_construct(
817 jack_driver_type_t type
,
818 const char * description
,
819 jack_driver_desc_filler_t
* filler_ptr
)
822 size_t description_len
;
823 jack_driver_desc_t
* desc_ptr
;
825 name_len
= strlen(name
);
826 description_len
= strlen(description
);
828 if (name_len
> sizeof(desc_ptr
->name
) - 1 ||
829 description_len
> sizeof(desc_ptr
->desc
) - 1) {
834 desc_ptr
= (jack_driver_desc_t
*)calloc (1, sizeof (jack_driver_desc_t
));
835 if (desc_ptr
== NULL
) {
836 jack_error("Error calloc() failed to allocate memory for driver descriptor struct");
840 memcpy(desc_ptr
->name
, name
, name_len
+ 1);
841 memcpy(desc_ptr
->desc
, description
, description_len
+ 1);
843 desc_ptr
->nparams
= 0;
844 desc_ptr
->type
= type
;
846 if (filler_ptr
!= NULL
) {
847 filler_ptr
->size
= 0;
853 SERVER_EXPORT
int jack_driver_descriptor_add_parameter(
854 jack_driver_desc_t
* desc_ptr
,
855 jack_driver_desc_filler_t
* filler_ptr
,
858 jack_driver_param_type_t type
,
859 const jack_driver_param_value_t
* value_ptr
,
860 jack_driver_param_constraint_desc_t
* constraint
,
861 const char* short_desc
,
862 const char* long_desc
)
865 size_t short_desc_len
;
866 size_t long_desc_len
;
867 jack_driver_param_desc_t
* param_ptr
;
870 name_len
= strlen(name
);
871 short_desc_len
= strlen(short_desc
);
873 if (long_desc
!= NULL
) {
874 long_desc_len
= strlen(long_desc
);
876 long_desc
= short_desc
;
877 long_desc_len
= short_desc_len
;
880 if (name_len
> sizeof(param_ptr
->name
) - 1 ||
881 short_desc_len
> sizeof(param_ptr
->short_desc
) - 1 ||
882 long_desc_len
> sizeof(param_ptr
->long_desc
) - 1) {
887 if (desc_ptr
->nparams
== filler_ptr
->size
) {
888 newsize
= filler_ptr
->size
+ 20; // most drivers have less than 20 parameters
889 param_ptr
= (jack_driver_param_desc_t
*)realloc (desc_ptr
->params
, newsize
* sizeof (jack_driver_param_desc_t
));
890 if (param_ptr
== NULL
) {
891 jack_error("Error realloc() failed for parameter array of %zu elements", newsize
);
894 filler_ptr
->size
= newsize
;
895 desc_ptr
->params
= param_ptr
;
898 assert(desc_ptr
->nparams
< filler_ptr
->size
);
899 param_ptr
= desc_ptr
->params
+ desc_ptr
->nparams
;
901 memcpy(param_ptr
->name
, name
, name_len
+ 1);
902 param_ptr
->character
= character
;
903 param_ptr
->type
= type
;
904 param_ptr
->value
= *value_ptr
;
905 param_ptr
->constraint
= constraint
;
906 memcpy(param_ptr
->short_desc
, short_desc
, short_desc_len
+ 1);
907 memcpy(param_ptr
->long_desc
, long_desc
, long_desc_len
+ 1);
915 jack_constraint_add_enum(
916 jack_driver_param_constraint_desc_t
** constraint_ptr_ptr
,
917 uint32_t * array_size_ptr
,
918 jack_driver_param_value_t
* value_ptr
,
919 const char * short_desc
)
921 jack_driver_param_constraint_desc_t
* constraint_ptr
;
923 jack_driver_param_value_enum_t
* possible_value_ptr
;
926 len
= strlen(short_desc
) + 1;
927 if (len
> sizeof(possible_value_ptr
->short_desc
))
933 constraint_ptr
= *constraint_ptr_ptr
;
934 if (constraint_ptr
== NULL
)
936 constraint_ptr
= (jack_driver_param_constraint_desc_t
*)calloc(1, sizeof(jack_driver_param_constraint_desc_t
));
937 if (constraint_ptr
== NULL
)
939 jack_error("calloc() failed to allocate memory for param constraint struct");
947 array_size
= *array_size_ptr
;
950 if (constraint_ptr
->constraint
.enumeration
.count
== array_size
)
954 (jack_driver_param_value_enum_t
*)realloc(
955 constraint_ptr
->constraint
.enumeration
.possible_values_array
,
956 sizeof(jack_driver_param_value_enum_t
) * array_size
);
957 if (possible_value_ptr
== NULL
)
959 jack_error("realloc() failed to (re)allocate memory for possible values array");
962 constraint_ptr
->constraint
.enumeration
.possible_values_array
= possible_value_ptr
;
966 possible_value_ptr
= constraint_ptr
->constraint
.enumeration
.possible_values_array
;
969 possible_value_ptr
+= constraint_ptr
->constraint
.enumeration
.count
;
970 constraint_ptr
->constraint
.enumeration
.count
++;
972 possible_value_ptr
->value
= *value_ptr
;
973 memcpy(possible_value_ptr
->short_desc
, short_desc
, len
);
975 *constraint_ptr_ptr
= constraint_ptr
;
976 *array_size_ptr
= array_size
;
983 jack_constraint_free(
984 jack_driver_param_constraint_desc_t
* constraint_ptr
)
986 if (constraint_ptr
!= NULL
)
988 if ((constraint_ptr
->flags
& JACK_CONSTRAINT_FLAG_RANGE
) == 0)
990 free(constraint_ptr
->constraint
.enumeration
.possible_values_array
);
993 free(constraint_ptr
);
997 #define JACK_CONSTRAINT_COMPOSE_ENUM_IMPL(type, copy) \
998 JACK_CONSTRAINT_COMPOSE_ENUM(type) \
1000 jack_driver_param_constraint_desc_t * constraint_ptr; \
1001 uint32_t array_size; \
1002 jack_driver_param_value_t value; \
1003 struct jack_constraint_enum_ ## type ## _descriptor * descr_ptr; \
1005 constraint_ptr = NULL; \
1006 for (descr_ptr = descr_array_ptr; \
1011 if (!jack_constraint_add_enum( \
1015 descr_ptr->short_desc)) \
1017 jack_constraint_free(constraint_ptr); \
1022 constraint_ptr->flags = flags; \
1024 return constraint_ptr; \
1027 JACK_CONSTRAINT_COMPOSE_ENUM_IMPL(uint32
, value
.c
= descr_ptr
->value
);
1028 JACK_CONSTRAINT_COMPOSE_ENUM_IMPL(sint32
, value
.c
= descr_ptr
->value
);
1029 JACK_CONSTRAINT_COMPOSE_ENUM_IMPL(char, value
.c
= descr_ptr
->value
);
1030 JACK_CONSTRAINT_COMPOSE_ENUM_IMPL(str
, strcpy(value
.str
, descr_ptr
->value
));