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);
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)
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) {
84 char arg_default[JACK_DRIVER_PARAM_STRING_MAX + 1];
86 for (i = 0; i < desc->
nparams; i++) {
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:
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",
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",
124 void jack_free_driver_params(
JSList * driver_params)
126 JSList*node_ptr = driver_params;
130 next_node_ptr = node_ptr->next;
131 free(node_ptr->data);
133 node_ptr = next_node_ptr;
139 struct option * long_options;
140 char* options, * options_ptr;
143 unsigned int param_index;
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);
173 options = (
char*)calloc (desc->
nparams * 3 + 1, sizeof (
char));
176 options_ptr = options;
177 for (i = 0; i < desc->
nparams; i++) {
181 long_options[i].flag = NULL;
183 long_options[i].has_arg = optional_argument;
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++) {
212 if (!optarg && optind < argc &&
213 strlen(argv[optind]) &&
214 argv[optind][0] !=
'-') {
215 optarg = argv[optind];
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);
266 struct option* long_options;
267 char* options, * options_ptr;
279 if (driver_params == NULL) {
286 if (strcmp (argv[1],
"-h") == 0 || strcmp (argv[1],
"--help") == 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);
306 options = (
char*)calloc (desc->
nparams * 3 + 1, sizeof (
char));
309 options_ptr = options;
314 long_options[
i].flag = NULL;
316 long_options[
i].has_arg = optional_argument;
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;
342 node_ptr = node_ptr->next;
345 if (!optarg && optind < argc &&
346 strlen(argv[optind]) &&
347 argv[optind][0] !=
'-') {
348 optarg = argv[optind];
353 case JackDriverParamInt:
354 value.
i = atoi(optarg);
357 case JackDriverParamUInt:
358 value.
ui = strtoul(optarg, NULL, 10);
361 case JackDriverParamChar:
365 case JackDriverParamString:
366 strncpy(value.
str, optarg, JACK_DRIVER_PARAM_STRING_MAX);
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 ) {
402 for (node = drivers; node; node = jack_slist_next (node)) {
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)
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);
463 for (node = drivers; node; node = jack_slist_next (node)) {
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);
473 strncpy(descriptor->
file, filename, JACK_PATH_MAX);
477 UnloadDriverModule(dlhandle);
487 WIN32_FIND_DATA filedata;
489 const char* ptr = NULL;
490 JSList* driver_list = NULL;
493 char* driver_dir = locate_driver_dir(file, filedata);
501 if (strncmp (
"jack_", filedata.cFileName, 5) != 0) {
505 ptr = strrchr (filedata.cFileName,
'.');
511 if (strncmp (
"dll", ptr, 3) != 0) {
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);
545 struct dirent * dir_entry;
549 JSList* driver_list = NULL;
552 const char* driver_dir;
553 if ((driver_dir = getenv(
"JACK_DRIVER_DIR")) == 0) {
554 driver_dir = ADDON_DIR;
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))) {
569 if (strncmp (
"jack_", dir_entry->d_name, 5) != 0) {
573 ptr = strrchr (dir_entry->d_name,
'.');
578 if (strncmp (
"so", ptr, 2) != 0) {
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);
616 WIN32_FIND_DATA filedata;
618 const char* ptr = NULL;
619 JSList* driver_list = NULL;
622 char* driver_dir = locate_driver_dir(file, filedata);
630 ptr = strrchr (filedata.cFileName,
'.');
636 if (strncmp (
"dll", ptr, 3) != 0) {
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);
670 struct dirent * dir_entry;
674 JSList* driver_list = NULL;
677 const char* driver_dir;
678 if ((driver_dir = getenv(
"JACK_DRIVER_DIR")) == 0) {
679 driver_dir = ADDON_DIR;
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) {
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);
743 fHandle = LoadDriverModule (driver_desc->
file);
745 if (fHandle == NULL) {
747 if ((errstr = GetLastError ()) != 0) {
750 if ((errstr = dlerror ()) != 0) {
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);
785 jack_driver_type_t type,
786 const char * description,
790 size_t description_len;
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) {
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);
812 desc_ptr->
type = type;
814 if (filler_ptr != NULL) {
815 filler_ptr->size = 0;
821 SERVER_EXPORT
int jack_driver_descriptor_add_parameter(
826 jack_driver_param_type_t type,
829 const char* short_desc,
830 const char* long_desc)
833 size_t short_desc_len;
834 size_t long_desc_len;
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;
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);
869 memcpy(param_ptr->
name, name, name_len + 1);
871 param_ptr->
type = type;
872 param_ptr->
value = *value_ptr;
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(
885 uint32_t * array_size_ptr,
887 const char * short_desc)
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)
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)
923 constraint_ptr->constraint.
enumeration.possible_values_array,
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;
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(
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));