Descriptor initialization reduces risk of mismatch between array size and element initialization. It also improves code readability by separating the parameter descriptions separate from the code that composes the enum constraint structures. As a side effect this commit makes the self-connect-mode constraint allocated in dedicated memory chunks, like others enum constraints.tags/v1.9.10
@@ -47,13 +47,16 @@ | |||
using namespace Jack; | |||
/* JackEngine::CheckPortsConnect() has some assumptions about values of these */ | |||
#define SELF_CONNECT_MODE_ALLOW_CHAR ' ' | |||
#define SELF_CONNECT_MODE_FAIL_EXTERNAL_ONLY_CHAR 'E' | |||
#define SELF_CONNECT_MODE_IGNORE_EXTERNAL_ONLY_CHAR 'e' | |||
#define SELF_CONNECT_MODE_FAIL_ALL_CHAR 'A' | |||
#define SELF_CONNECT_MODE_IGNORE_ALL_CHAR 'a' | |||
#define SELF_CONNECT_MODES_COUNT 5 | |||
/* JackEngine::CheckPortsConnect() has some assumptions about char values */ | |||
static struct jack_constraint_enum_char_descriptor self_connect_mode_constraint_descr_array[] = | |||
{ | |||
{ ' ', "Don't restrict self connect requests" }, | |||
{ 'E', "Fail self connect requests to external ports only" }, | |||
{ 'e', "Ignore self connect requests to external ports only" }, | |||
{ 'A', "Fail all self connect requests" }, | |||
{ 'a', "Ignore all self connect requests" }, | |||
{ 0 } | |||
}; | |||
struct jackctl_server | |||
{ | |||
@@ -106,8 +109,6 @@ struct jackctl_server | |||
/* char enum, self connect mode mode */ | |||
union jackctl_parameter_value self_connect_mode; | |||
union jackctl_parameter_value default_self_connect_mode; | |||
jack_driver_param_value_enum_t self_connect_mode_possible_values[SELF_CONNECT_MODES_COUNT]; | |||
jack_driver_param_constraint_desc_t self_connect_mode_constraint; | |||
}; | |||
struct jackctl_driver | |||
@@ -883,26 +884,7 @@ SERVER_EXPORT jackctl_server_t * jackctl_server_create( | |||
goto fail_free_parameters; | |||
} | |||
server_ptr->self_connect_mode_constraint.flags = JACK_CONSTRAINT_FLAG_STRICT | JACK_CONSTRAINT_FLAG_FAKE_VALUE; | |||
server_ptr->self_connect_mode_constraint.constraint.enumeration.count = SELF_CONNECT_MODES_COUNT; | |||
server_ptr->self_connect_mode_constraint.constraint.enumeration.possible_values_array = server_ptr->self_connect_mode_possible_values; | |||
server_ptr->self_connect_mode_possible_values[0].value.c = SELF_CONNECT_MODE_ALLOW_CHAR; | |||
strcpy(server_ptr->self_connect_mode_possible_values[0].short_desc, "Don't restrict self connect requests"); | |||
server_ptr->self_connect_mode_possible_values[1].value.c = SELF_CONNECT_MODE_FAIL_EXTERNAL_ONLY_CHAR ; | |||
strcpy(server_ptr->self_connect_mode_possible_values[1].short_desc, "Fail self connect requests to external ports only"); | |||
server_ptr->self_connect_mode_possible_values[2].value.c = SELF_CONNECT_MODE_IGNORE_EXTERNAL_ONLY_CHAR; | |||
strcpy(server_ptr->self_connect_mode_possible_values[2].short_desc, "Ignore self connect requests to external ports only"); | |||
server_ptr->self_connect_mode_possible_values[3].value.c = SELF_CONNECT_MODE_FAIL_ALL_CHAR; | |||
strcpy(server_ptr->self_connect_mode_possible_values[3].short_desc, "Fail all self connect requests"); | |||
server_ptr->self_connect_mode_possible_values[4].value.c = SELF_CONNECT_MODE_IGNORE_ALL_CHAR; | |||
strcpy(server_ptr->self_connect_mode_possible_values[4].short_desc, "Ignore all self connect requests"); | |||
value.c = SELF_CONNECT_MODE_ALLOW_CHAR; | |||
value.c = JACK_DEFAULT_SELF_CONNECT_MODE; | |||
if (jackctl_add_parameter( | |||
&server_ptr->parameters, | |||
"self-connect-mode", | |||
@@ -912,7 +894,9 @@ SERVER_EXPORT jackctl_server_t * jackctl_server_create( | |||
&server_ptr->self_connect_mode, | |||
&server_ptr->default_self_connect_mode, | |||
value, | |||
&server_ptr->self_connect_mode_constraint) == NULL) | |||
jack_constraint_compose_enum_char( | |||
JACK_CONSTRAINT_FLAG_STRICT | JACK_CONSTRAINT_FLAG_FAKE_VALUE, | |||
self_connect_mode_constraint_descr_array)) == NULL) | |||
{ | |||
goto fail_free_parameters; | |||
} | |||
@@ -880,3 +880,122 @@ SERVER_EXPORT int jack_driver_descriptor_add_parameter( | |||
desc_ptr->nparams++; | |||
return true; | |||
} | |||
SERVER_EXPORT | |||
int | |||
jack_constraint_add_enum( | |||
jack_driver_param_constraint_desc_t ** constraint_ptr_ptr, | |||
uint32_t * array_size_ptr, | |||
jack_driver_param_value_t * value_ptr, | |||
const char * short_desc) | |||
{ | |||
jack_driver_param_constraint_desc_t * constraint_ptr; | |||
uint32_t array_size; | |||
jack_driver_param_value_enum_t * possible_value_ptr; | |||
size_t len; | |||
len = strlen(short_desc) + 1; | |||
if (len > sizeof(possible_value_ptr->short_desc)) | |||
{ | |||
assert(false); | |||
return false; | |||
} | |||
constraint_ptr = *constraint_ptr_ptr; | |||
if (constraint_ptr == NULL) | |||
{ | |||
constraint_ptr = (jack_driver_param_constraint_desc_t *)calloc(1, sizeof(jack_driver_param_constraint_desc_t)); | |||
if (constraint_ptr == NULL) | |||
{ | |||
jack_error("calloc() failed to allocate memory for param constraint struct"); | |||
return false; | |||
} | |||
array_size = 0; | |||
} | |||
else | |||
{ | |||
array_size = *array_size_ptr; | |||
} | |||
if (constraint_ptr->constraint.enumeration.count == array_size) | |||
{ | |||
array_size += 10; | |||
possible_value_ptr = | |||
(jack_driver_param_value_enum_t *)realloc( | |||
constraint_ptr->constraint.enumeration.possible_values_array, | |||
sizeof(jack_driver_param_value_enum_t) * array_size); | |||
if (possible_value_ptr == NULL) | |||
{ | |||
jack_error("calloc() failed to (re)allocate memory for possible values array"); | |||
return false; | |||
} | |||
constraint_ptr->constraint.enumeration.possible_values_array = possible_value_ptr; | |||
} | |||
else | |||
{ | |||
possible_value_ptr = constraint_ptr->constraint.enumeration.possible_values_array; | |||
} | |||
possible_value_ptr += constraint_ptr->constraint.enumeration.count; | |||
constraint_ptr->constraint.enumeration.count++; | |||
possible_value_ptr->value = *value_ptr; | |||
memcpy(possible_value_ptr->short_desc, short_desc, len); | |||
*constraint_ptr_ptr = constraint_ptr; | |||
*array_size_ptr = array_size; | |||
return true; | |||
} | |||
SERVER_EXPORT | |||
void | |||
jack_constraint_free( | |||
jack_driver_param_constraint_desc_t * constraint_ptr) | |||
{ | |||
if (constraint_ptr != NULL) | |||
{ | |||
if ((constraint_ptr->flags & JACK_CONSTRAINT_FLAG_RANGE) == 0) | |||
{ | |||
free(constraint_ptr->constraint.enumeration.possible_values_array); | |||
} | |||
free(constraint_ptr); | |||
} | |||
} | |||
#define JACK_CONSTRAINT_COMPOSE_ENUM_IMPL(type, copy) \ | |||
JACK_CONSTRAINT_COMPOSE_ENUM(type) \ | |||
{ \ | |||
jack_driver_param_constraint_desc_t * constraint_ptr; \ | |||
uint32_t array_size; \ | |||
jack_driver_param_value_t value; \ | |||
struct jack_constraint_enum_ ## type ## _descriptor * descr_ptr; \ | |||
\ | |||
constraint_ptr = NULL; \ | |||
for (descr_ptr = descr_array_ptr; \ | |||
descr_ptr->value; \ | |||
descr_ptr++) \ | |||
{ \ | |||
copy; \ | |||
if (!jack_constraint_add_enum( \ | |||
&constraint_ptr, \ | |||
&array_size, \ | |||
&value, \ | |||
descr_ptr->short_desc)) \ | |||
{ \ | |||
jack_constraint_free(constraint_ptr); \ | |||
return NULL; \ | |||
} \ | |||
} \ | |||
\ | |||
constraint_ptr->flags = flags; \ | |||
\ | |||
return constraint_ptr; \ | |||
} | |||
JACK_CONSTRAINT_COMPOSE_ENUM_IMPL(uint32, value.c = descr_ptr->value); | |||
JACK_CONSTRAINT_COMPOSE_ENUM_IMPL(sint32, value.c = descr_ptr->value); | |||
JACK_CONSTRAINT_COMPOSE_ENUM_IMPL(char, value.c = descr_ptr->value); | |||
JACK_CONSTRAINT_COMPOSE_ENUM_IMPL(str, strcpy(value.str, descr_ptr->value)); |
@@ -74,6 +74,26 @@ typedef struct { | |||
char short_desc[64]; /**< A short (~30 chars) description for the user */ | |||
} jack_driver_param_value_enum_t; | |||
struct jack_constraint_enum_uint32_descriptor { | |||
uint32_t value; | |||
const char * short_desc; | |||
}; | |||
struct jack_constraint_enum_sint32_descriptor { | |||
int32_t value; | |||
const char * short_desc; | |||
}; | |||
struct jack_constraint_enum_char_descriptor { | |||
char value; | |||
const char * short_desc; | |||
}; | |||
struct jack_constraint_enum_str_descriptor { | |||
const char * value; | |||
const char * short_desc; | |||
}; | |||
typedef struct { | |||
uint32_t flags; /**< JACK_CONSTRAINT_FLAG_XXX */ | |||
union { | |||
@@ -148,6 +168,28 @@ jack_driver_descriptor_add_parameter( | |||
const char * short_desc, /* A short (~30 chars) description for the user */ | |||
const char * long_desc); /* A longer description for the user, if NULL short_desc will be used */ | |||
SERVER_EXPORT | |||
int jack_constraint_add_enum( | |||
jack_driver_param_constraint_desc_t ** constraint_ptr_ptr, | |||
uint32_t * array_size_ptr, | |||
jack_driver_param_value_t * value_ptr, | |||
const char * short_desc); | |||
SERVER_EXPORT | |||
void jack_constraint_free(jack_driver_param_constraint_desc_t * constraint_ptr); | |||
#define JACK_CONSTRAINT_COMPOSE_ENUM(type) \ | |||
SERVER_EXPORT \ | |||
jack_driver_param_constraint_desc_t * \ | |||
jack_constraint_compose_enum_ ## type( \ | |||
uint32_t flags, \ | |||
struct jack_constraint_enum_ ## type ## _descriptor * descr_array_ptr) | |||
JACK_CONSTRAINT_COMPOSE_ENUM(uint32); | |||
JACK_CONSTRAINT_COMPOSE_ENUM(sint32); | |||
JACK_CONSTRAINT_COMPOSE_ENUM(char); | |||
JACK_CONSTRAINT_COMPOSE_ENUM(str); | |||
typedef jack_driver_desc_t * (*JackDriverDescFunction) (); | |||
#ifdef __cplusplus | |||
@@ -47,6 +47,23 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
#include "JackCompilerDeps.h" | |||
#include "JackServerGlobals.h" | |||
static struct jack_constraint_enum_str_descriptor midi_constraint_descr_array[] = | |||
{ | |||
{ "none", "no MIDI driver" }, | |||
{ "seq", "ALSA Sequencer driver" }, | |||
{ "raw", "ALSA RawMIDI driver" }, | |||
{ 0 } | |||
}; | |||
static struct jack_constraint_enum_char_descriptor dither_constraint_descr_array[] = | |||
{ | |||
{ 'n', "none" }, | |||
{ 'r', "rectangular" }, | |||
{ 's', "shaped" }, | |||
{ 't', "triangular" }, | |||
{ 0 } | |||
}; | |||
namespace Jack | |||
{ | |||
@@ -529,39 +546,6 @@ extern "C" | |||
{ | |||
#endif | |||
static | |||
void | |||
fill_device( | |||
jack_driver_param_constraint_desc_t ** constraint_ptr_ptr, | |||
uint32_t * array_size_ptr, | |||
const char * device_id, | |||
const char * device_description) | |||
{ | |||
jack_driver_param_value_enum_t * possible_value_ptr; | |||
//jack_info("%6s - %s", device_id, device_description); | |||
if (*constraint_ptr_ptr == NULL) | |||
{ | |||
*constraint_ptr_ptr = (jack_driver_param_constraint_desc_t *)calloc(1, sizeof(jack_driver_param_constraint_desc_t)); | |||
*array_size_ptr = 0; | |||
} | |||
if ((*constraint_ptr_ptr)->constraint.enumeration.count == *array_size_ptr) | |||
{ | |||
*array_size_ptr += 10; | |||
(*constraint_ptr_ptr)->constraint.enumeration.possible_values_array = | |||
(jack_driver_param_value_enum_t *)realloc( | |||
(*constraint_ptr_ptr)->constraint.enumeration.possible_values_array, | |||
sizeof(jack_driver_param_value_enum_t) * *array_size_ptr); | |||
} | |||
possible_value_ptr = (*constraint_ptr_ptr)->constraint.enumeration.possible_values_array + (*constraint_ptr_ptr)->constraint.enumeration.count; | |||
(*constraint_ptr_ptr)->constraint.enumeration.count++; | |||
strcpy(possible_value_ptr->value.str, device_id); | |||
strcpy(possible_value_ptr->short_desc, device_description); | |||
} | |||
static | |||
jack_driver_param_constraint_desc_t * | |||
enum_alsa_devices() | |||
@@ -571,8 +555,8 @@ enum_alsa_devices() | |||
snd_pcm_info_t * pcminfo_capture; | |||
snd_pcm_info_t * pcminfo_playback; | |||
int card_no = -1; | |||
char card_id[JACK_DRIVER_PARAM_STRING_MAX + 1]; | |||
char device_id[JACK_DRIVER_PARAM_STRING_MAX + 1]; | |||
jack_driver_param_value_t card_id; | |||
jack_driver_param_value_t device_id; | |||
char description[64]; | |||
int device_no; | |||
bool has_capture; | |||
@@ -588,19 +572,24 @@ enum_alsa_devices() | |||
while(snd_card_next(&card_no) >= 0 && card_no >= 0) | |||
{ | |||
snprintf(card_id, sizeof(card_id), "hw:%d", card_no); | |||
snprintf(card_id.str, sizeof(card_id.str), "hw:%d", card_no); | |||
if (snd_ctl_open(&handle, card_id, 0) >= 0 && | |||
if (snd_ctl_open(&handle, card_id.str, 0) >= 0 && | |||
snd_ctl_card_info(handle, info) >= 0) | |||
{ | |||
snprintf(card_id, sizeof(card_id), "hw:%s", snd_ctl_card_info_get_id(info)); | |||
fill_device(&constraint_ptr, &array_size, card_id, snd_ctl_card_info_get_name(info)); | |||
snprintf(card_id.str, sizeof(card_id.str), "hw:%s", snd_ctl_card_info_get_id(info)); | |||
if (!jack_constraint_add_enum( | |||
&constraint_ptr, | |||
&array_size, | |||
&card_id, | |||
snd_ctl_card_info_get_name(info))) | |||
goto fail; | |||
device_no = -1; | |||
while (snd_ctl_pcm_next_device(handle, &device_no) >= 0 && device_no != -1) | |||
{ | |||
snprintf(device_id, sizeof(device_id), "%s,%d", card_id, device_no); | |||
snprintf(device_id.str, sizeof(device_id.str), "%s,%d", card_id.str, device_no); | |||
snd_pcm_info_set_device(pcminfo_capture, device_no); | |||
snd_pcm_info_set_subdevice(pcminfo_capture, 0); | |||
@@ -629,7 +618,12 @@ enum_alsa_devices() | |||
continue; | |||
} | |||
fill_device(&constraint_ptr, &array_size, device_id, description); | |||
if (!jack_constraint_add_enum( | |||
&constraint_ptr, | |||
&array_size, | |||
&device_id, | |||
description)) | |||
goto fail; | |||
} | |||
snd_ctl_close(handle); | |||
@@ -637,77 +631,9 @@ enum_alsa_devices() | |||
} | |||
return constraint_ptr; | |||
} | |||
static | |||
jack_driver_param_constraint_desc_t * | |||
get_midi_driver_constraint() | |||
{ | |||
jack_driver_param_constraint_desc_t * constraint_ptr; | |||
jack_driver_param_value_enum_t * possible_value_ptr; | |||
//jack_info("%6s - %s", device_id, device_description); | |||
constraint_ptr = (jack_driver_param_constraint_desc_t *)calloc(1, sizeof(jack_driver_param_value_enum_t)); | |||
constraint_ptr->flags = JACK_CONSTRAINT_FLAG_STRICT | JACK_CONSTRAINT_FLAG_FAKE_VALUE; | |||
constraint_ptr->constraint.enumeration.possible_values_array = (jack_driver_param_value_enum_t *)malloc(3 * sizeof(jack_driver_param_value_enum_t)); | |||
constraint_ptr->constraint.enumeration.count = 3; | |||
possible_value_ptr = constraint_ptr->constraint.enumeration.possible_values_array; | |||
strcpy(possible_value_ptr->value.str, "none"); | |||
strcpy(possible_value_ptr->short_desc, "no MIDI driver"); | |||
possible_value_ptr++; | |||
strcpy(possible_value_ptr->value.str, "seq"); | |||
strcpy(possible_value_ptr->short_desc, "ALSA Sequencer driver"); | |||
possible_value_ptr++; | |||
strcpy(possible_value_ptr->value.str, "raw"); | |||
strcpy(possible_value_ptr->short_desc, "ALSA RawMIDI driver"); | |||
return constraint_ptr; | |||
} | |||
static | |||
jack_driver_param_constraint_desc_t * | |||
get_dither_constraint() | |||
{ | |||
jack_driver_param_constraint_desc_t * constraint_ptr; | |||
jack_driver_param_value_enum_t * possible_value_ptr; | |||
//jack_info("%6s - %s", device_id, device_description); | |||
constraint_ptr = (jack_driver_param_constraint_desc_t *)calloc(1, sizeof(jack_driver_param_value_enum_t)); | |||
constraint_ptr->flags = JACK_CONSTRAINT_FLAG_STRICT | JACK_CONSTRAINT_FLAG_FAKE_VALUE; | |||
constraint_ptr->constraint.enumeration.possible_values_array = (jack_driver_param_value_enum_t *)malloc(4 * sizeof(jack_driver_param_value_enum_t)); | |||
constraint_ptr->constraint.enumeration.count = 4; | |||
possible_value_ptr = constraint_ptr->constraint.enumeration.possible_values_array; | |||
possible_value_ptr->value.c = 'n'; | |||
strcpy(possible_value_ptr->short_desc, "none"); | |||
possible_value_ptr++; | |||
possible_value_ptr->value.c = 'r'; | |||
strcpy(possible_value_ptr->short_desc, "rectangular"); | |||
possible_value_ptr++; | |||
possible_value_ptr->value.c = 's'; | |||
strcpy(possible_value_ptr->short_desc, "shaped"); | |||
possible_value_ptr++; | |||
possible_value_ptr->value.c = 't'; | |||
strcpy(possible_value_ptr->short_desc, "triangular"); | |||
return constraint_ptr; | |||
fail: | |||
jack_constraint_free(constraint_ptr); | |||
return NULL; | |||
} | |||
static int | |||
@@ -789,7 +715,9 @@ SERVER_EXPORT const jack_driver_desc_t* driver_get_descriptor () | |||
'z', | |||
JackDriverParamChar, | |||
&value, | |||
get_dither_constraint(), | |||
jack_constraint_compose_enum_char( | |||
JACK_CONSTRAINT_FLAG_STRICT | JACK_CONSTRAINT_FLAG_FAKE_VALUE, | |||
dither_constraint_descr_array), | |||
"Dithering mode", | |||
"Dithering mode:\n" | |||
" n - none\n" | |||
@@ -816,7 +744,9 @@ SERVER_EXPORT const jack_driver_desc_t* driver_get_descriptor () | |||
'X', | |||
JackDriverParamString, | |||
&value, | |||
get_midi_driver_constraint(), | |||
jack_constraint_compose_enum_str( | |||
JACK_CONSTRAINT_FLAG_STRICT | JACK_CONSTRAINT_FLAG_FAKE_VALUE, | |||
midi_constraint_descr_array), | |||
"ALSA device name", | |||
"ALSA MIDI driver:\n" | |||
" none - no MIDI driver\n" | |||