mirror of
https://gitee.com/openharmony/third_party_alsa-lib
synced 2024-11-26 17:21:07 +00:00
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:
parent
b642a7c11e
commit
d10bcbf76d
1
TODO
1
TODO
@ -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
|
||||
|
@ -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>
|
||||
|
||||
*/
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
169
src/conf.c
169
src/conf.c
@ -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
|
||||
@ -3634,9 +3743,11 @@ int snd_config_search_definition(snd_config_t *config,
|
||||
} 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);
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user