Added snd_config_load_override().

Fixed problem with EOF detection in freestring parser.
Fixed problem with run-time argument parsing (snd_config_load()->snd_config_load_override() replace).
Added more documentation for configuration run-time arguments and hooks.
Fixed the behaviour of snd_config_search_definition() - implicit and explicit base.
This commit is contained in:
Jaroslav Kysela 2002-01-09 21:28:15 +00:00
parent b642a7c11e
commit d10bcbf76d
6 changed files with 146 additions and 34 deletions

1
TODO
View File

@ -1,4 +1,3 @@
H make snd_config_update thread safe
H add serious PCM test application to test various period/buffer size
combinations to determine possible problems in the lowlevel drivers
M think about xrun recovery helpers

View File

@ -39,6 +39,7 @@ may be placed in the library code instead of the kernel driver.</P>
<LI>Page \ref conf explains the syntax of library configuration files.
<LI>Page \ref confarg explains the run-time argument syntax.
<LI>Page \ref conffunc explains the run-time function definition and usage.
<LI>Page \ref confhooks explains the run-time hooks definition and usage.
</UL>
*/

View File

@ -69,6 +69,7 @@ extern snd_config_t *snd_config;
int snd_config_top(snd_config_t **config);
int snd_config_load(snd_config_t *config, snd_input_t *in);
int snd_config_load_override(snd_config_t *config, snd_input_t *in);
int snd_config_save(snd_config_t *config, snd_output_t *out);
int snd_config_update(void);
int snd_config_update_r(snd_config_t **top, snd_config_update_t **update, const char *path);

View File

@ -405,8 +405,8 @@ typedef struct snd_seq_result {
/** Queue skew values */
typedef struct snd_seq_queue_skew {
unsigned int value;
unsigned int base;
unsigned int value; /**< skew value */
unsigned int base; /**< skew base */
} snd_seq_queue_skew_t;
/** queue timer control */

View File

@ -219,6 +219,29 @@ a.0 "first"
a.1 "second"
\endcode
\section conf_mode Parsed node operation mode
By default, the node operation node is 'merge+create'. It means, if
a configuration node is not present a new one is created, otherwise
the latest assignment is merged (if possible - type checking). The
'merge+create' operation mode is specified with a prefix char plus (+).
The operation mode 'merge' merges the node with old one (which must
exists). Type checking is done, so string cannot be assigned to integer
and so on. This mode is specified with a prefix char minus (-).
The operation mode 'do not override' ignores a new configuration node
if a configuration node with same name exists. This mode is specified with
a prefix char note of interrogation (?).
The operation mode 'override' always overrides the old configuration node
with new contents. This mode is specified with a prefix char note of
exclamation (!).
\code
!defaults.pcm.device 1
\endcode
\section conf_syntax_summary Syntax summary
\code
@ -251,7 +274,11 @@ name.0 [=] value0 [,|;]
name.1 [=] value1 [,|;]
\endcode
\section conf_syntax_ref References
\ref confarg
\ref conffunc
\ref confhooks
*/
@ -291,6 +318,23 @@ Arguments are refered by dollar-sign ($) and name of argument:
card $CARD
\endcode
\section confarg_usage Usage
Arguments are replaced with real values when the key contains part after
colon (:). For example, all these names for PCM interface gives same result:
\code
hw:0,1
hw:CARD=0,DEV=1
hw:{CARD 0 DEV 1}
plug:"hw:0,1"
plug:{SLAVE="hw:{CARD 0 DEV 1}"}
\endcode
As you see, the argument can be specified by order or by name. Note that
arguments closed into braces are parsed in same way like configuration files,
but with the override method by default.
\section confarg_example Example
\code
@ -333,6 +377,40 @@ func.remove_first_char {
*/
/*! \page confhooks Configuration - hooks
<P>The hook extension in the ALSA library allows expanding of configuration
nodes at run-time lookup. The presence of a hook is determined with a @hooks
compound node.</P>
<P>The example definition a hook which loads two configuration files at beginning:</P>
\code
@hooks [
{
func load
files [
"/etc/asound.conf"
"~/.asoundrc"
]
errors false
}
]
\endcode
\section confhooks_ref Function reference
<UL>
<LI>The function load - snd_config_hook_load() - loads and parses the given
configuration files.
<LI>The function load_for_all_cards - snd_config_hook_load_for_all_cards() -
loads and parses the given configuration files for all installed soundcards.
The driver name (type of soundcard) is passed in the private configuration
node.
</UL>
*/
#include <stdarg.h>
#include <wordexp.h>
@ -500,8 +578,8 @@ static int get_char_skip_comments(input_t *input)
break;
while (1) {
c = get_char(input);
if (c == EOF)
return LOCAL_UNEXPECTED_EOF;
if (c < 0)
return c;
if (c == '\n')
break;
}
@ -577,7 +655,16 @@ static int get_freestring(char **string, int id, input_t *input)
while (1) {
c = get_char(input);
if (c < 0) {
if (buf != _buf)
if (c == LOCAL_UNEXPECTED_EOF) {
char *s = malloc(idx + 1);
if (!s)
return -ENOMEM;
memcpy(s, buf, idx);
s[idx] = '\0';
*string = s;
c = 0;
}
if (alloc > bufsize)
free(buf);
return c;
}
@ -852,10 +939,10 @@ static int parse_value(snd_config_t **_n, snd_config_t *father, input_t *input,
return 0;
}
static int parse_defs(snd_config_t *father, input_t *input, int skip);
static int parse_array_defs(snd_config_t *farther, input_t *input, int skip);
static int parse_defs(snd_config_t *father, input_t *input, int skip, int override);
static int parse_array_defs(snd_config_t *farther, input_t *input, int skip, int override);
static int parse_array_def(snd_config_t *father, input_t *input, int idx, int skip)
static int parse_array_def(snd_config_t *father, input_t *input, int idx, int skip, int override)
{
char static_id[12], *id = NULL;
int c;
@ -893,10 +980,10 @@ static int parse_array_def(snd_config_t *father, input_t *input, int idx, int sk
}
}
if (c == '{') {
err = parse_defs(n, input, skip);
err = parse_defs(n, input, skip, override);
endchr = '}';
} else {
err = parse_array_defs(n, input, skip);
err = parse_array_defs(n, input, skip, override);
endchr = ']';
}
c = get_nonwhite(input);
@ -926,7 +1013,7 @@ static int parse_array_def(snd_config_t *father, input_t *input, int idx, int sk
return err;
}
static int parse_array_defs(snd_config_t *father, input_t *input, int skip)
static int parse_array_defs(snd_config_t *father, input_t *input, int skip, int override)
{
int idx = 0;
while (1) {
@ -936,14 +1023,14 @@ static int parse_array_defs(snd_config_t *father, input_t *input, int skip)
unget_char(c, input);
if (c == ']')
return 0;
err = parse_array_def(father, input, idx++, skip);
err = parse_array_def(father, input, idx++, skip, override);
if (err < 0)
return err;
}
return 0;
}
static int parse_def(snd_config_t *father, input_t *input, int skip)
static int parse_def(snd_config_t *father, input_t *input, int skip, int override)
{
char *id = NULL;
int c;
@ -955,6 +1042,12 @@ static int parse_def(snd_config_t *father, input_t *input, int skip)
if (c < 0)
return c;
switch (c) {
case '+':
mode = MERGE_CREATE;
break;
case '-':
mode = MERGE;
break;
case '?':
mode = DONT_OVERRIDE;
break;
@ -962,7 +1055,7 @@ static int parse_def(snd_config_t *father, input_t *input, int skip)
mode = OVERRIDE;
break;
default:
mode = MERGE_CREATE;
mode = !override ? MERGE_CREATE : OVERRIDE;
unget_char(c, input);
}
err = get_string(&id, 1, input);
@ -1046,10 +1139,10 @@ static int parse_def(snd_config_t *father, input_t *input, int skip)
}
}
if (c == '{') {
err = parse_defs(n, input, skip);
err = parse_defs(n, input, skip, override);
endchr = '}';
} else {
err = parse_array_defs(n, input, skip);
err = parse_array_defs(n, input, skip, override);
endchr = ']';
}
c = get_nonwhite(input);
@ -1082,7 +1175,7 @@ static int parse_def(snd_config_t *father, input_t *input, int skip)
return err;
}
static int parse_defs(snd_config_t *father, input_t *input, int skip)
static int parse_defs(snd_config_t *father, input_t *input, int skip, int override)
{
int c, err;
while (1) {
@ -1092,7 +1185,7 @@ static int parse_defs(snd_config_t *father, input_t *input, int skip)
unget_char(c, input);
if (c == '}')
return 0;
err = parse_def(father, input, skip);
err = parse_def(father, input, skip, override);
if (err < 0)
return err;
}
@ -1387,13 +1480,7 @@ int snd_config_top(snd_config_t **config)
return _snd_config_make(config, 0, SND_CONFIG_TYPE_COMPOUND);
}
/**
* \brief Load a config tree
* \param config Config top node handle
* \param in Input handle
* \return 0 on success otherwise a negative error code
*/
int snd_config_load(snd_config_t *config, snd_input_t *in)
static int snd_config_load1(snd_config_t *config, snd_input_t *in, int override)
{
int err;
input_t input;
@ -1409,7 +1496,7 @@ int snd_config_load(snd_config_t *config, snd_input_t *in)
fd->next = NULL;
input.current = fd;
input.unget = 0;
err = parse_defs(config, &input, 0);
err = parse_defs(config, &input, 0, override);
fd = input.current;
if (err < 0) {
const char *str;
@ -1450,6 +1537,28 @@ int snd_config_load(snd_config_t *config, snd_input_t *in)
return err;
}
/**
* \brief Load a config tree
* \param config Config top node handle
* \param in Input handle
* \return 0 on success otherwise a negative error code
*/
int snd_config_load(snd_config_t *config, snd_input_t *in)
{
return snd_config_load1(config, in, 0);
}
/**
* \brief Load a config tree and override existing configuration nodes
* \param config Config top node handle
* \param in Input handle
* \return 0 on success otherwise a negative error code
*/
int snd_config_load_override(snd_config_t *config, snd_input_t *in)
{
return snd_config_load1(config, in, 1);
}
/**
* \brief Add a leaf to a config compound node
* \param father Config compound node handle
@ -3433,7 +3542,7 @@ static int parse_args(snd_config_t *subs, const char *str, snd_config_t *defs)
err = snd_input_buffer_open(&input, str + 1, len - 1);
if (err < 0)
return err;
err = snd_config_load(subs, input);
err = snd_config_load_override(subs, input);
snd_input_close(input);
if (err < 0)
return err;
@ -3609,7 +3718,7 @@ int snd_config_expand(snd_config_t *config, snd_config_t *root, const char *args
/**
* \brief Search a definition inside a config tree using alias and expand hooks and arguments
* \param config Config node handle
* \param base Key base (or NULL)
* \param base Implicit key base (or NULL - none)
* \param key Key suffix
* \param result Pointer to expanded found node
* \return 0 on success otherwise a negative error code
@ -3633,10 +3742,12 @@ int snd_config_search_definition(snd_config_t *config,
key[args - name - 1] = '\0';
} else {
key = (char *) name;
}
err = snd_config_search_alias_hooks(config, NULL, key, &conf);
if (err < 0)
err = snd_config_search_alias_hooks(config, base, key, &conf);
}
/*
* if key contains dot (.), the implicit base is ignored
* and the key starts from root given by the 'config' parameter
*/
err = snd_config_search_alias_hooks(config, strchr(key, '.') ? NULL : base, key, &conf);
if (err < 0)
return err;
return snd_config_expand(conf, config, args, NULL, result);

View File

@ -34,7 +34,7 @@
/*! \page conffunc
\section Function reference
\section conffunc_ref Function reference
<UL>
<LI>The getenv function - snd_func_getenv() - allows to obtain