use descriptors for initializing enum constraints

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.
This commit is contained in:
Nedko Arnaudov 2014-03-10 20:17:44 +02:00
parent c8cac65cad
commit 00f468fa29
4 changed files with 219 additions and 144 deletions

View File

@ -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;
}

View File

@ -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));

View File

@ -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

View File

@ -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"