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"
37 static char* locate_dll_driver_dir()
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
);
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
)) {
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
);
55 jack_error("Cannot get JACK dll directory : %d", GetLastError());
60 static char* locate_driver_dir(HANDLE
& file
, WIN32_FIND_DATA
& filedata
)
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
);
68 if (file
== INVALID_HANDLE_VALUE
) {
69 jack_error("Drivers not found ");
79 jack_driver_desc_t
* jackctl_driver_get_desc(jackctl_driver_t
* driver
);
81 void jack_print_driver_options(jack_driver_desc_t
* desc
, FILE* file
)
84 char arg_default
[JACK_DRIVER_PARAM_STRING_MAX
+ 1];
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
);
91 case JackDriverParamUInt
:
92 sprintf (arg_default
, "%" "u", desc
->params
[i
].value
.ui
);
94 case JackDriverParamChar
:
95 sprintf (arg_default
, "%c", desc
->params
[i
].value
.c
);
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
);
101 sprintf (arg_default
, "none");
104 case JackDriverParamBool
:
105 sprintf (arg_default
, "%s", desc
->params
[i
].value
.i
? "true" : "false");
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
,
117 static void jack_print_driver_param_usage (jack_driver_desc_t
* desc
, unsigned long param
, FILE *file
)
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
);
124 void jack_free_driver_params(JSList
* driver_params
)
126 JSList
*node_ptr
= driver_params
;
127 JSList
*next_node_ptr
;
130 next_node_ptr
= node_ptr
->next
;
131 free(node_ptr
->data
);
133 node_ptr
= next_node_ptr
;
137 int jack_parse_driver_params(jack_driver_desc_t
* desc
, int argc
, char* argv
[], JSList
** param_ptr
)
139 struct option
* long_options
;
140 char* options
, * options_ptr
;
143 unsigned int param_index
;
144 JSList
* params
= NULL
;
145 jack_driver_param_t
* driver_param
;
153 if (strcmp (argv
[1], "-h") == 0 || strcmp (argv
[1], "--help") == 0) {
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
);
162 fprintf (stderr
, "Jackd: unknown option '%s' "
163 "for driver '%s'\n", argv
[2],
167 jack_log("Parameters for driver '%s' (all parameters are optional):", desc
->name
);
168 jack_print_driver_options (desc
, stdout
);
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
));
176 options_ptr
= options
;
177 for (i
= 0; i
< desc
->nparams
; i
++) {
178 sprintf (options_ptr
, "%c::", desc
->params
[i
].character
);
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
;
186 /* create the params */
189 while ((opt
= getopt_long(argc
, argv
, options
, long_options
, NULL
)) != -1) {
191 if (opt
== ':' || opt
== '?') {
193 fprintf (stderr
, "Missing option to argument '%c'\n", optopt
);
195 fprintf (stderr
, "Unknownage with option '%c'\n", optopt
);
198 fprintf (stderr
, "Options for driver '%s':\n", desc
->name
);
199 jack_print_driver_options (desc
, stderr
);
203 for (param_index
= 0; param_index
< desc
->nparams
; param_index
++) {
204 if (opt
== desc
->params
[param_index
].character
) {
209 driver_param
= (jack_driver_param_t
*)calloc (1, sizeof (jack_driver_param_t
));
210 driver_param
->character
= desc
->params
[param_index
].character
;
212 if (!optarg
&& optind
< argc
&&
213 strlen(argv
[optind
]) &&
214 argv
[optind
][0] != '-') {
215 optarg
= argv
[optind
];
219 switch (desc
->params
[param_index
].type
) {
220 case JackDriverParamInt
:
221 driver_param
->value
.i
= atoi(optarg
);
223 case JackDriverParamUInt
:
224 driver_param
->value
.ui
= strtoul(optarg
, NULL
, 10);
226 case JackDriverParamChar
:
227 driver_param
->value
.c
= optarg
[0];
229 case JackDriverParamString
:
230 strncpy (driver_param
->value
.str
, optarg
, JACK_DRIVER_PARAM_STRING_MAX
);
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;
240 driver_param
->value
.i
= true;
245 if (desc
->params
[param_index
].type
== JackDriverParamBool
) {
246 driver_param
->value
.i
= true;
248 driver_param
->value
= desc
->params
[param_index
].value
;
252 params
= jack_slist_append (params
, driver_param
);
264 SERVER_EXPORT
int jackctl_driver_params_parse(jackctl_driver
*driver_ptr
, int argc
, char* argv
[])
266 struct option
* long_options
;
267 char* options
, * options_ptr
;
271 jackctl_parameter_t
* param
= NULL
;
272 union jackctl_parameter_value value
;
278 const JSList
* driver_params
= jackctl_driver_get_parameters(driver_ptr
);
279 if (driver_params
== NULL
) {
283 jack_driver_desc_t
* desc
= jackctl_driver_get_desc(driver_ptr
);
286 if (strcmp (argv
[1], "-h") == 0 || strcmp (argv
[1], "--help") == 0) {
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
);
295 fprintf (stderr
, "Jackd: unknown option '%s' "
296 "for driver '%s'\n", argv
[2],
300 jack_log("Parameters for driver '%s' (all parameters are optional):", desc
->name
);
301 jack_print_driver_options (desc
, stdout
);
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
));
309 options_ptr
= options
;
310 for (i
= 0; i
< desc
->nparams
; i
++) {
311 sprintf(options_ptr
, "%c::", desc
->params
[i
].character
);
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
;
319 /* create the params */
322 while ((opt
= getopt_long(argc
, argv
, options
, long_options
, NULL
)) != -1) {
324 if (opt
== ':' || opt
== '?') {
326 fprintf (stderr
, "Missing option to argument '%c'\n", optopt
);
328 fprintf (stderr
, "Unknownage with option '%c'\n", optopt
);
331 fprintf (stderr
, "Options for driver '%s':\n", desc
->name
);
332 jack_print_driver_options(desc
, stderr
);
336 node_ptr
= (JSList
*)driver_params
;
338 param
= (jackctl_parameter_t
*)node_ptr
->data
;
339 if (opt
== jackctl_parameter_get_id(param
)) {
342 node_ptr
= node_ptr
->next
;
345 if (!optarg
&& optind
< argc
&&
346 strlen(argv
[optind
]) &&
347 argv
[optind
][0] != '-') {
348 optarg
= argv
[optind
];
352 switch (jackctl_parameter_get_type(param
)) {
353 case JackDriverParamInt
:
354 value
.i
= atoi(optarg
);
355 jackctl_parameter_set_value(param
, &value
);
357 case JackDriverParamUInt
:
358 value
.ui
= strtoul(optarg
, NULL
, 10);
359 jackctl_parameter_set_value(param
, &value
);
361 case JackDriverParamChar
:
363 jackctl_parameter_set_value(param
, &value
);
365 case JackDriverParamString
:
366 strncpy(value
.str
, optarg
, JACK_DRIVER_PARAM_STRING_MAX
);
367 jackctl_parameter_set_value(param
, &value
);
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 ) {
379 jackctl_parameter_set_value(param
, &value
);
383 if (jackctl_parameter_get_type(param
) == JackParamBool
) {
386 value
= jackctl_parameter_get_default_value(param
);
388 jackctl_parameter_set_value(param
, &value
);
397 jack_driver_desc_t
* jack_find_driver_descriptor (JSList
* drivers
, const char* name
)
399 jack_driver_desc_t
* desc
= 0;
402 for (node
= drivers
; node
; node
= jack_slist_next (node
)) {
403 desc
= (jack_driver_desc_t
*) node
->data
;
405 if (strcmp (desc
->name
, name
) != 0) {
415 static void* check_symbol(const char* sofile
, const char* symbol
, const char* driver_dir
, void** res_dllhandle
= NULL
)
420 sprintf(filename
, "%s/%s", driver_dir
, sofile
);
422 if ((dlhandle
= LoadDriverModule(filename
)) == NULL
) {
424 jack_error ("Could not open component .dll '%s': %ld", filename
, GetLastError());
426 jack_error ("Could not open component .so '%s': %s", filename
, dlerror());
429 res
= (void*)GetDriverProc(dlhandle
, symbol
);
431 *res_dllhandle
= dlhandle
;
433 UnloadDriverModule(dlhandle
);
440 static jack_driver_desc_t
* jack_get_descriptor (JSList
* drivers
, const char* sofile
, const char* symbol
, const char* driver_dir
)
442 jack_driver_desc_t
* descriptor
= NULL
;
443 jack_driver_desc_t
* other_descriptor
;
444 JackDriverDescFunction so_get_descriptor
= NULL
;
447 void* dlhandle
= NULL
;
449 sprintf(filename
, "%s/%s", driver_dir
, sofile
);
450 so_get_descriptor
= (JackDriverDescFunction
)check_symbol(sofile
, symbol
, driver_dir
, &dlhandle
);
452 if (so_get_descriptor
== NULL
) {
453 jack_error("jack_get_descriptor : dll %s is not a driver", sofile
);
457 if ((descriptor
= so_get_descriptor ()) == NULL
) {
458 jack_error("Driver from '%s' returned NULL descriptor", filename
);
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 */
473 strncpy(descriptor
->file
, filename
, JACK_PATH_MAX
);
477 UnloadDriverModule(dlhandle
);
484 JSList
* jack_drivers_load(JSList
* drivers
)
486 //char dll_filename[512];
487 WIN32_FIND_DATA filedata
;
489 const char* ptr
= NULL
;
490 JSList
* driver_list
= NULL
;
491 jack_driver_desc_t
* desc
= NULL
;
493 char* driver_dir
= locate_driver_dir(file
, filedata
);
495 jack_error("Driver folder not found");
500 /* check the filename is of the right format */
501 if (strncmp ("jack_", filedata
.cFileName
, 5) != 0) {
505 ptr
= strrchr (filedata
.cFileName
, '.');
511 if (strncmp ("dll", ptr
, 3) != 0) {
515 /* check if dll is an internal client */
516 if (check_symbol(filedata
.cFileName
, "jack_internal_initialize", driver_dir
) != NULL
) {
520 desc
= jack_get_descriptor (drivers
, filedata
.cFileName
, "driver_get_descriptor", driver_dir
);
522 driver_list
= jack_slist_append (driver_list
, desc
);
524 jack_error ("jack_get_descriptor returns null for \'%s\'", filedata
.cFileName
);
527 } while (FindNextFile(file
, &filedata
));
530 jack_error ("Could not find any drivers in %s!", driver_dir
);
543 JSList
* jack_drivers_load (JSList
* drivers
)
545 struct dirent
* dir_entry
;
549 JSList
* driver_list
= NULL
;
550 jack_driver_desc_t
* desc
= NULL
;
552 const char* driver_dir
;
553 if ((driver_dir
= getenv("JACK_DRIVER_DIR")) == 0) {
554 driver_dir
= ADDON_DIR
;
557 /* search through the driver_dir and add get descriptors
558 from the .so files in it */
559 dir_stream
= opendir (driver_dir
);
561 jack_error ("Could not open driver directory %s: %s",
562 driver_dir
, strerror (errno
));
566 while ((dir_entry
= readdir(dir_stream
))) {
568 /* check the filename is of the right format */
569 if (strncmp ("jack_", dir_entry
->d_name
, 5) != 0) {
573 ptr
= strrchr (dir_entry
->d_name
, '.');
578 if (strncmp ("so", ptr
, 2) != 0) {
582 /* check if dll is an internal client */
583 if (check_symbol(dir_entry
->d_name
, "jack_internal_initialize", driver_dir
) != NULL
) {
587 desc
= jack_get_descriptor (drivers
, dir_entry
->d_name
, "driver_get_descriptor", driver_dir
);
589 driver_list
= jack_slist_append (driver_list
, desc
);
591 jack_error ("jack_get_descriptor returns null for \'%s\'", dir_entry
->d_name
);
595 err
= closedir (dir_stream
);
597 jack_error ("Error closing driver directory %s: %s",
598 driver_dir
, strerror (errno
));
602 jack_error ("Could not find any drivers in %s!", driver_dir
);
613 JSList
* jack_internals_load(JSList
* internals
)
615 ///char dll_filename[512];
616 WIN32_FIND_DATA filedata
;
618 const char* ptr
= NULL
;
619 JSList
* driver_list
= NULL
;
620 jack_driver_desc_t
* desc
;
622 char* driver_dir
= locate_driver_dir(file
, filedata
);
624 jack_error("Driver folder not found");
630 ptr
= strrchr (filedata
.cFileName
, '.');
636 if (strncmp ("dll", ptr
, 3) != 0) {
640 /* check if dll is an internal client */
641 if (check_symbol(filedata
.cFileName
, "jack_internal_initialize", driver_dir
) == NULL
) {
645 desc
= jack_get_descriptor (internals
, filedata
.cFileName
, "jack_get_descriptor", driver_dir
);
647 driver_list
= jack_slist_append (driver_list
, desc
);
649 jack_error ("jack_get_descriptor returns null for \'%s\'", filedata
.cFileName
);
652 } while (FindNextFile(file
, &filedata
));
655 jack_error ("Could not find any internals in %s!", driver_dir
);
668 JSList
* jack_internals_load(JSList
* internals
)
670 struct dirent
* dir_entry
;
674 JSList
* driver_list
= NULL
;
675 jack_driver_desc_t
* desc
;
677 const char* driver_dir
;
678 if ((driver_dir
= getenv("JACK_DRIVER_DIR")) == 0) {
679 driver_dir
= ADDON_DIR
;
682 /* search through the driver_dir and add get descriptors
683 from the .so files in it */
684 dir_stream
= opendir (driver_dir
);
686 jack_error ("Could not open driver directory %s: %s\n",
687 driver_dir
, strerror (errno
));
691 while ((dir_entry
= readdir(dir_stream
))) {
693 ptr
= strrchr (dir_entry
->d_name
, '.');
699 if (strncmp ("so", ptr
, 2) != 0) {
703 /* check if dll is an internal client */
704 if (check_symbol(dir_entry
->d_name
, "jack_internal_initialize", driver_dir
) == NULL
) {
708 desc
= jack_get_descriptor (internals
, dir_entry
->d_name
, "jack_get_descriptor", driver_dir
);
710 driver_list
= jack_slist_append (driver_list
, desc
);
712 jack_error ("jack_get_descriptor returns null for \'%s\'", dir_entry
->d_name
);
716 err
= closedir (dir_stream
);
718 jack_error ("Error closing internal directory %s: %s\n",
719 driver_dir
, strerror (errno
));
723 jack_error ("Could not find any internals in %s!", driver_dir
);
732 Jack::JackDriverClientInterface
* JackDriverInfo::Open(jack_driver_desc_t
* driver_desc
,
733 Jack::JackLockedEngine
* engine
,
734 Jack::JackSynchro
* synchro
,
735 const JSList
* params
)
743 fHandle
= LoadDriverModule (driver_desc
->file
);
745 if (fHandle
== NULL
) {
747 if ((errstr
= GetLastError ()) != 0) {
748 jack_error ("Can't load \"%s\": %ld", driver_desc
->file
, errstr
);
750 if ((errstr
= dlerror ()) != 0) {
751 jack_error ("Can't load \"%s\": %s", driver_desc
->file
, errstr
);
755 jack_error ("Error loading driver shared object %s", driver_desc
->file
);
760 fInitialize
= (driverInitialize
)GetDriverProc(fHandle
, "driver_initialize");
763 if ((fInitialize
== NULL
) && (errstr
= GetLastError ()) != 0) {
765 if ((fInitialize
== NULL
) && (errstr
= dlerror ()) != 0) {
767 jack_error("No initialize function in shared object %s\n", driver_desc
->file
);
771 fBackend
= fInitialize(engine
, synchro
, params
);
775 JackDriverInfo::~JackDriverInfo()
779 UnloadDriverModule(fHandle
);
783 SERVER_EXPORT jack_driver_desc_t
* jack_driver_descriptor_construct(
785 jack_driver_type_t type
,
786 const char * description
,
787 jack_driver_desc_filler_t
* filler_ptr
)
790 size_t description_len
;
791 jack_driver_desc_t
* desc_ptr
;
793 name_len
= strlen(name
);
794 description_len
= strlen(description
);
796 if (name_len
> sizeof(desc_ptr
->name
) - 1 ||
797 description_len
> sizeof(desc_ptr
->desc
) - 1) {
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");
808 memcpy(desc_ptr
->name
, name
, name_len
+ 1);
809 memcpy(desc_ptr
->desc
, description
, description_len
+ 1);
811 desc_ptr
->nparams
= 0;
812 desc_ptr
->type
= type
;
814 if (filler_ptr
!= NULL
) {
815 filler_ptr
->size
= 0;
821 SERVER_EXPORT
int jack_driver_descriptor_add_parameter(
822 jack_driver_desc_t
* desc_ptr
,
823 jack_driver_desc_filler_t
* filler_ptr
,
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
)
833 size_t short_desc_len
;
834 size_t long_desc_len
;
835 jack_driver_param_desc_t
* param_ptr
;
838 name_len
= strlen(name
);
839 short_desc_len
= strlen(short_desc
);
841 if (long_desc
!= NULL
) {
842 long_desc_len
= strlen(long_desc
);
844 long_desc
= short_desc
;
845 long_desc_len
= short_desc_len
;
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) {
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
);
862 filler_ptr
->size
= newsize
;
863 desc_ptr
->params
= param_ptr
;
866 assert(desc_ptr
->nparams
< filler_ptr
->size
);
867 param_ptr
= desc_ptr
->params
+ desc_ptr
->nparams
;
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);
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
)
889 jack_driver_param_constraint_desc_t
* constraint_ptr
;
891 jack_driver_param_value_enum_t
* possible_value_ptr
;
894 len
= strlen(short_desc
) + 1;
895 if (len
> sizeof(possible_value_ptr
->short_desc
))
901 constraint_ptr
= *constraint_ptr_ptr
;
902 if (constraint_ptr
== NULL
)
904 constraint_ptr
= (jack_driver_param_constraint_desc_t
*)calloc(1, sizeof(jack_driver_param_constraint_desc_t
));
905 if (constraint_ptr
== NULL
)
907 jack_error("calloc() failed to allocate memory for param constraint struct");
915 array_size
= *array_size_ptr
;
918 if (constraint_ptr
->constraint
.enumeration
.count
== array_size
)
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
)
927 jack_error("realloc() failed to (re)allocate memory for possible values array");
930 constraint_ptr
->constraint
.enumeration
.possible_values_array
= possible_value_ptr
;
934 possible_value_ptr
= constraint_ptr
->constraint
.enumeration
.possible_values_array
;
937 possible_value_ptr
+= constraint_ptr
->constraint
.enumeration
.count
;
938 constraint_ptr
->constraint
.enumeration
.count
++;
940 possible_value_ptr
->value
= *value_ptr
;
941 memcpy(possible_value_ptr
->short_desc
, short_desc
, len
);
943 *constraint_ptr_ptr
= constraint_ptr
;
944 *array_size_ptr
= array_size
;
951 jack_constraint_free(
952 jack_driver_param_constraint_desc_t
* constraint_ptr
)
954 if (constraint_ptr
!= NULL
)
956 if ((constraint_ptr
->flags
& JACK_CONSTRAINT_FLAG_RANGE
) == 0)
958 free(constraint_ptr
->constraint
.enumeration
.possible_values_array
);
961 free(constraint_ptr
);
965 #define JACK_CONSTRAINT_COMPOSE_ENUM_IMPL(type, copy) \
966 JACK_CONSTRAINT_COMPOSE_ENUM(type) \
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; \
973 constraint_ptr = NULL; \
974 for (descr_ptr = descr_array_ptr; \
979 if (!jack_constraint_add_enum( \
983 descr_ptr->short_desc)) \
985 jack_constraint_free(constraint_ptr); \
990 constraint_ptr->flags = flags; \
992 return constraint_ptr; \
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
));