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()
40 HMODULE libjack_handle = LoadLibrary(
"libjackserver64.dll");
42 HMODULE libjack_handle = LoadLibrary(
"libjackserver.dll");
46 char driver_dir_storage[512];
47 if (3 < GetModuleFileName(libjack_handle, driver_dir_storage, 512)) {
48 char *p = strrchr(driver_dir_storage,
'\\');
49 if (p && (p != driver_dir_storage)) {
52 jack_info(
"Drivers/internals found in : %s", driver_dir_storage);
53 strcat(driver_dir_storage,
"/");
54 strcat(driver_dir_storage, ADDON_DIR);
55 FreeLibrary(libjack_handle);
56 return strdup(driver_dir_storage);
58 jack_error(
"Cannot get JACK dll directory : %d", GetLastError());
59 FreeLibrary(libjack_handle);
64 static char* locate_driver_dir(HANDLE& file, WIN32_FIND_DATA& filedata)
67 char* driver_dir = locate_dll_driver_dir();
68 char dll_filename[512];
69 snprintf(dll_filename,
sizeof(dll_filename),
"%s/*.dll", driver_dir);
70 file = (HANDLE)FindFirstFile(dll_filename, &filedata);
72 if (file == INVALID_HANDLE_VALUE) {
88 char arg_default[JACK_DRIVER_PARAM_STRING_MAX + 1];
90 for (i = 0; i < desc->
nparams; i++) {
92 case JackDriverParamInt:
93 sprintf (arg_default,
"%" "i", desc->
params[i].
value.i);
95 case JackDriverParamUInt:
96 sprintf (arg_default,
"%" "u", desc->
params[i].
value.ui);
98 case JackDriverParamChar:
99 sprintf (arg_default,
"%c", desc->
params[i].
value.c);
101 case JackDriverParamString:
103 sprintf (arg_default,
"%s", desc->
params[i].
value.str);
105 sprintf (arg_default,
"none");
108 case JackDriverParamBool:
109 sprintf (arg_default,
"%s", desc->
params[i].
value.i ?
"true" :
"false");
113 fprintf(file,
"\t-%c, --%s \t%s (default: %s)\n",
121 static void jack_print_driver_param_usage (
jack_driver_desc_t* desc,
unsigned long param, FILE *file)
123 fprintf (file,
"Usage information for the '%s' parameter for driver '%s':\n",
128 void jack_free_driver_params(
JSList * driver_params)
130 JSList*node_ptr = driver_params;
134 next_node_ptr = node_ptr->next;
135 free(node_ptr->data);
137 node_ptr = next_node_ptr;
143 struct option * long_options;
144 char* options, * options_ptr;
147 unsigned int param_index;
157 if (strcmp (argv[1],
"-h") == 0 || strcmp (argv[1],
"--help") == 0) {
159 for (i = 0; i < desc->
nparams; i++) {
160 if (strcmp (desc->
params[i].
name, argv[2]) == 0) {
161 jack_print_driver_param_usage (desc, i, stdout);
166 fprintf (stderr,
"Jackd: unknown option '%s' "
167 "for driver '%s'\n", argv[2],
171 jack_log(
"Parameters for driver '%s' (all parameters are optional):", desc->
name);
172 jack_print_driver_options (desc, stdout);
177 options = (
char*)calloc (desc->
nparams * 3 + 1, sizeof (
char));
180 options_ptr = options;
181 for (i = 0; i < desc->
nparams; i++) {
185 long_options[i].flag = NULL;
187 long_options[i].has_arg = optional_argument;
193 while ((opt = getopt_long(argc, argv, options, long_options, NULL)) != -1) {
195 if (opt ==
':' || opt ==
'?') {
197 fprintf (stderr,
"Missing option to argument '%c'\n", optopt);
199 fprintf (stderr,
"Unknownage with option '%c'\n", optopt);
202 fprintf (stderr,
"Options for driver '%s':\n", desc->
name);
203 jack_print_driver_options (desc, stderr);
207 for (param_index = 0; param_index < desc->
nparams; param_index++) {
216 if (!optarg && optind < argc &&
217 strlen(argv[optind]) &&
218 argv[optind][0] !=
'-') {
219 optarg = argv[optind];
224 case JackDriverParamInt:
225 driver_param->value.i = atoi(optarg);
227 case JackDriverParamUInt:
228 driver_param->value.ui = strtoul(optarg, NULL, 10);
230 case JackDriverParamChar:
231 driver_param->value.c = optarg[0];
233 case JackDriverParamString:
234 strncpy (driver_param->value.str, optarg, JACK_DRIVER_PARAM_STRING_MAX);
236 case JackDriverParamBool:
237 if (strcasecmp(
"false", optarg) == 0 ||
238 strcasecmp(
"off", optarg) == 0 ||
239 strcasecmp(
"no", optarg) == 0 ||
240 strcasecmp(
"0", optarg) == 0 ||
241 strcasecmp(
"(null)", optarg) == 0 ) {
242 driver_param->value.i =
false;
244 driver_param->value.i =
true;
249 if (desc->
params[param_index].
type == JackDriverParamBool) {
250 driver_param->value.i =
true;
252 driver_param->value = desc->
params[param_index].
value;
256 params = jack_slist_append (params, driver_param);
270 struct option* long_options;
271 char* options, * options_ptr;
283 if (driver_params == NULL) {
290 if (strcmp (argv[1],
"-h") == 0 || strcmp (argv[1],
"--help") == 0) {
292 for (i = 0; i < desc->
nparams; i++) {
293 if (strcmp (desc->
params[i].
name, argv[2]) == 0) {
294 jack_print_driver_param_usage (desc, i, stdout);
299 fprintf (stderr,
"Jackd: unknown option '%s' "
300 "for driver '%s'\n", argv[2],
304 jack_log(
"Parameters for driver '%s' (all parameters are optional):", desc->
name);
305 jack_print_driver_options (desc, stdout);
310 options = (
char*)calloc (desc->
nparams * 3 + 1, sizeof (
char));
313 options_ptr = options;
314 for (i = 0; i < desc->
nparams; i++) {
318 long_options[
i].flag = NULL;
320 long_options[
i].has_arg = optional_argument;
326 while ((opt = getopt_long(argc, argv, options, long_options, NULL)) != -1) {
328 if (opt ==
':' || opt ==
'?') {
330 fprintf (stderr,
"Missing option to argument '%c'\n", optopt);
332 fprintf (stderr,
"Unknownage with option '%c'\n", optopt);
335 fprintf (stderr,
"Options for driver '%s':\n", desc->
name);
336 jack_print_driver_options(desc, stderr);
340 node_ptr = (
JSList *)driver_params;
346 node_ptr = node_ptr->next;
349 if (!optarg && optind < argc &&
350 strlen(argv[optind]) &&
351 argv[optind][0] !=
'-') {
352 optarg = argv[optind];
357 case JackDriverParamInt:
358 value.
i = atoi(optarg);
361 case JackDriverParamUInt:
362 value.
ui = strtoul(optarg, NULL, 10);
365 case JackDriverParamChar:
369 case JackDriverParamString:
370 strncpy(value.
str, optarg, JACK_DRIVER_PARAM_STRING_MAX);
373 case JackDriverParamBool:
374 if (strcasecmp(
"false", optarg) == 0 ||
375 strcasecmp(
"off", optarg) == 0 ||
376 strcasecmp(
"no", optarg) == 0 ||
377 strcasecmp(
"0", optarg) == 0 ||
378 strcasecmp(
"(null)", optarg) == 0 ) {
406 for (node = drivers; node; node = jack_slist_next (node)) {
409 if (strcmp (desc->
name, name) != 0) {
419 static void* check_symbol(
const char* sofile,
const char* symbol,
const char* driver_dir,
void** res_dllhandle = NULL)
424 sprintf(filename,
"%s/%s", driver_dir, sofile);
426 if ((dlhandle = LoadDriverModule(filename)) == NULL) {
428 jack_error (
"Could not open component .dll '%s': %ld", filename, GetLastError());
430 jack_error (
"Could not open component .so '%s': %s", filename, dlerror());
433 res = (
void*)GetDriverProc(dlhandle, symbol);
435 *res_dllhandle = dlhandle;
437 UnloadDriverModule(dlhandle);
444 static jack_driver_desc_t* jack_get_descriptor (
JSList* drivers,
const char* sofile,
const char* symbol,
const char* driver_dir)
448 JackDriverDescFunction so_get_descriptor = NULL;
453 sprintf(filename,
"%s/%s", driver_dir, sofile);
454 so_get_descriptor = (JackDriverDescFunction)check_symbol(sofile, symbol, driver_dir, &dlhandle);
456 if (so_get_descriptor == NULL) {
457 jack_error(
"jack_get_descriptor : dll %s is not a driver", sofile);
461 if ((descriptor = so_get_descriptor ()) == NULL) {
462 jack_error(
"Driver from '%s' returned NULL descriptor", filename);
467 for (node = drivers; node; node = jack_slist_next (node)) {
469 if (strcmp(descriptor->
name, other_descriptor->
name) == 0) {
470 jack_error(
"The drivers in '%s' and '%s' both have the name '%s'; using the first",
471 other_descriptor->
file, filename, other_descriptor->
name);
477 strncpy(descriptor->
file, filename, JACK_PATH_MAX);
481 UnloadDriverModule(dlhandle);
490 WIN32_FIND_DATA filedata;
492 const char* ptr = NULL;
493 JSList* driver_list = NULL;
496 char* driver_dir = locate_driver_dir(file, filedata);
504 if (strncmp (
"jack_", filedata.cFileName, 5) != 0) {
508 ptr = strrchr (filedata.cFileName,
'.');
514 if (strncmp (
"dll", ptr, 3) != 0) {
519 if (check_symbol(filedata.cFileName,
"jack_internal_initialize", driver_dir) != NULL) {
523 desc = jack_get_descriptor (drivers, filedata.cFileName,
"driver_get_descriptor", driver_dir);
525 driver_list = jack_slist_append (driver_list, desc);
527 jack_error (
"jack_get_descriptor returns null for \'%s\'", filedata.cFileName);
530 }
while (FindNextFile(file, &filedata));
533 jack_error (
"Could not find any drivers in %s!", driver_dir);
548 struct dirent * dir_entry;
552 JSList* driver_list = NULL;
555 const char* driver_dir;
556 if ((driver_dir = getenv(
"JACK_DRIVER_DIR")) == 0) {
557 driver_dir = ADDON_DIR;
562 dir_stream = opendir (driver_dir);
564 jack_error (
"Could not open driver directory %s: %s",
565 driver_dir, strerror (errno));
569 while ((dir_entry = readdir(dir_stream))) {
572 if (strncmp (
"jack_", dir_entry->d_name, 5) != 0) {
576 ptr = strrchr (dir_entry->d_name,
'.');
581 if (strncmp (
"so", ptr, 2) != 0) {
586 if (check_symbol(dir_entry->d_name,
"jack_internal_initialize", driver_dir) != NULL) {
590 desc = jack_get_descriptor (drivers, dir_entry->d_name,
"driver_get_descriptor", driver_dir);
592 driver_list = jack_slist_append (driver_list, desc);
594 jack_error (
"jack_get_descriptor returns null for \'%s\'", dir_entry->d_name);
598 err = closedir (dir_stream);
600 jack_error (
"Error closing driver directory %s: %s",
601 driver_dir, strerror (errno));
605 jack_error (
"Could not find any drivers in %s!", driver_dir);
619 WIN32_FIND_DATA filedata;
621 const char* ptr = NULL;
622 JSList* driver_list = NULL;
625 char* driver_dir = locate_driver_dir(file, filedata);
633 ptr = strrchr (filedata.cFileName,
'.');
639 if (strncmp (
"dll", ptr, 3) != 0) {
644 if (check_symbol(filedata.cFileName,
"jack_internal_initialize", driver_dir) == NULL) {
648 desc = jack_get_descriptor (internals, filedata.cFileName,
"jack_get_descriptor", driver_dir);
650 driver_list = jack_slist_append (driver_list, desc);
652 jack_error (
"jack_get_descriptor returns null for \'%s\'", filedata.cFileName);
655 }
while (FindNextFile(file, &filedata));
658 jack_error (
"Could not find any internals in %s!", driver_dir);
673 struct dirent * dir_entry;
677 JSList* driver_list = NULL;
680 const char* driver_dir;
681 if ((driver_dir = getenv(
"JACK_DRIVER_DIR")) == 0) {
682 driver_dir = ADDON_DIR;
687 dir_stream = opendir (driver_dir);
689 jack_error (
"Could not open driver directory %s: %s\n",
690 driver_dir, strerror (errno));
694 while ((dir_entry = readdir(dir_stream))) {
696 ptr = strrchr (dir_entry->d_name,
'.');
702 if (strncmp (
"so", ptr, 2) != 0) {
707 if (check_symbol(dir_entry->d_name,
"jack_internal_initialize", driver_dir) == NULL) {
711 desc = jack_get_descriptor (internals, dir_entry->d_name,
"jack_get_descriptor", driver_dir);
713 driver_list = jack_slist_append (driver_list, desc);
715 jack_error (
"jack_get_descriptor returns null for \'%s\'", dir_entry->d_name);
719 err = closedir (dir_stream);
721 jack_error (
"Error closing internal directory %s: %s\n",
722 driver_dir, strerror (errno));
726 jack_error (
"Could not find any internals in %s!", driver_dir);
746 fHandle = LoadDriverModule (driver_desc->
file);
748 if (fHandle == NULL) {
750 if ((errstr = GetLastError ()) != 0) {
753 if ((errstr = dlerror ()) != 0) {
758 jack_error (
"Error loading driver shared object %s", driver_desc->
file);
763 fInitialize = (driverInitialize)GetDriverProc(fHandle,
"driver_initialize");
766 if ((fInitialize == NULL) && (errstr = GetLastError ()) != 0) {
768 if ((fInitialize == NULL) && (errstr = dlerror ()) != 0) {
770 jack_error(
"No initialize function in shared object %s\n", driver_desc->
file);
774 fBackend = fInitialize(engine, synchro, params);
778 JackDriverInfo::~JackDriverInfo()
782 UnloadDriverModule(fHandle);
788 jack_driver_type_t type,
789 const char * description,
793 size_t description_len;
796 name_len = strlen(name);
797 description_len = strlen(description);
799 if (name_len >
sizeof(desc_ptr->
name) - 1 ||
800 description_len >
sizeof(desc_ptr->
desc) - 1) {
806 if (desc_ptr == NULL) {
807 jack_error(
"Error calloc() failed to allocate memory for driver descriptor struct");
811 memcpy(desc_ptr->
name, name, name_len + 1);
812 memcpy(desc_ptr->
desc, description, description_len + 1);
815 desc_ptr->
type = type;
817 if (filler_ptr != NULL) {
818 filler_ptr->size = 0;
824 SERVER_EXPORT
int jack_driver_descriptor_add_parameter(
829 jack_driver_param_type_t type,
832 const char* short_desc,
833 const char* long_desc)
836 size_t short_desc_len;
837 size_t long_desc_len;
841 name_len = strlen(name);
842 short_desc_len = strlen(short_desc);
844 if (long_desc != NULL) {
845 long_desc_len = strlen(long_desc);
847 long_desc = short_desc;
848 long_desc_len = short_desc_len;
851 if (name_len >
sizeof(param_ptr->
name) - 1 ||
852 short_desc_len >
sizeof(param_ptr->
short_desc) - 1 ||
853 long_desc_len >
sizeof(param_ptr->
long_desc) - 1) {
858 if (desc_ptr->
nparams == filler_ptr->size) {
859 newsize = filler_ptr->size + 20;
861 if (param_ptr == NULL) {
862 jack_error(
"Error realloc() failed for parameter array of %zu elements", newsize);
865 filler_ptr->size = newsize;
866 desc_ptr->
params = param_ptr;
869 assert(desc_ptr->
nparams < filler_ptr->size);
872 memcpy(param_ptr->
name, name, name_len + 1);
874 param_ptr->
type = type;
875 param_ptr->
value = *value_ptr;
877 memcpy(param_ptr->
short_desc, short_desc, short_desc_len + 1);
878 memcpy(param_ptr->
long_desc, long_desc, long_desc_len + 1);
SERVER_EXPORT int jackctl_driver_params_parse(jackctl_driver *driver_ptr, int argc, char *argv[])
Inter process synchronization using using Mach semaphore.
Locked Engine, access to methods is serialized using a mutex.
char str[JACK_PARAM_STRING_MAX+1]
member used for JackParamString
SERVER_EXPORT union jackctl_parameter_value jackctl_parameter_get_default_value(jackctl_parameter *parameter_ptr)
char file[JACK_PATH_MAX+1]
SERVER_EXPORT void jack_error(const char *fmt,...)
uint32_t ui
member used for JackParamUInt
jack_driver_param_value_t value
SERVER_EXPORT void jack_info(const char *fmt,...)
int32_t i
member used for JackParamInt
Type for parameter value.
SERVER_EXPORT const JSList * jackctl_driver_get_parameters(jackctl_driver *driver_ptr)
jack_driver_param_constraint_desc_t * constraint
SERVER_EXPORT jackctl_param_type_t jackctl_parameter_get_type(jackctl_parameter *parameter_ptr)
char name[JACK_DRIVER_NAME_MAX+1]
char name[JACK_DRIVER_NAME_MAX+1]
SERVER_EXPORT bool jackctl_parameter_set_value(jackctl_parameter *parameter_ptr, const union jackctl_parameter_value *value_ptr)
The base interface for drivers clients.
char desc[JACK_DRIVER_PARAM_DESC+1]
jack_driver_param_type_t type
SERVER_EXPORT char jackctl_parameter_get_id(jackctl_parameter_t *parameter_ptr)
char c
member used for JackParamChar
SERVER_EXPORT void jack_log(const char *fmt,...)
jack_driver_param_desc_t * params