mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2026-03-14 05:33:43 -04:00
ucm: Improve cset command parsing
The cset command parsing in ucm/main.c assumes implicitly that the
argument contains no space, thus an example below wouldn't work:
cset "name='Input Select' Digital Mic"
This patch introduces a new internal API function
__snd_ctl_ascii_elem_id_parse() to improve the cset parser.
Reported-by: Tanu Kaskinen <tanu.kaskinen@digia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
c34f74c818
commit
58d10c09e1
2 changed files with 46 additions and 24 deletions
|
|
@ -143,21 +143,19 @@ char *snd_ctl_ascii_elem_id_get(snd_ctl_elem_id_t *id)
|
||||||
return strdup(buf);
|
return strdup(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#ifndef DOC_HIDDEN
|
||||||
* \brief parse ASCII string as CTL element identifier
|
/* used by UCM parser, too */
|
||||||
* \param dst destination CTL identifier
|
int __snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst, const char *str,
|
||||||
* \param str source ASCII string
|
const char **ret_ptr)
|
||||||
* \return zero on success, otherwise a negative error code
|
|
||||||
*/
|
|
||||||
int snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst, const char *str)
|
|
||||||
{
|
{
|
||||||
int c, size, numid;
|
int c, size, numid;
|
||||||
|
int err = -EINVAL;
|
||||||
char *ptr;
|
char *ptr;
|
||||||
|
|
||||||
while (*str == ' ' || *str == '\t')
|
while (isspace(*str))
|
||||||
str++;
|
str++;
|
||||||
if (!(*str))
|
if (!(*str))
|
||||||
return -EINVAL;
|
goto out;
|
||||||
snd_ctl_elem_id_set_interface(dst, SND_CTL_ELEM_IFACE_MIXER); /* default */
|
snd_ctl_elem_id_set_interface(dst, SND_CTL_ELEM_IFACE_MIXER); /* default */
|
||||||
while (*str) {
|
while (*str) {
|
||||||
if (!strncasecmp(str, "numid=", 6)) {
|
if (!strncasecmp(str, "numid=", 6)) {
|
||||||
|
|
@ -165,7 +163,7 @@ int snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst, const char *str)
|
||||||
numid = atoi(str);
|
numid = atoi(str);
|
||||||
if (numid <= 0) {
|
if (numid <= 0) {
|
||||||
fprintf(stderr, "amixer: Invalid numid %d\n", numid);
|
fprintf(stderr, "amixer: Invalid numid %d\n", numid);
|
||||||
return -EINVAL;
|
goto out;
|
||||||
}
|
}
|
||||||
snd_ctl_elem_id_set_numid(dst, atoi(str));
|
snd_ctl_elem_id_set_numid(dst, atoi(str));
|
||||||
while (isdigit(*str))
|
while (isdigit(*str))
|
||||||
|
|
@ -191,7 +189,7 @@ int snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst, const char *str)
|
||||||
snd_ctl_elem_id_set_interface(dst, SND_CTL_ELEM_IFACE_SEQUENCER);
|
snd_ctl_elem_id_set_interface(dst, SND_CTL_ELEM_IFACE_SEQUENCER);
|
||||||
str += 9;
|
str += 9;
|
||||||
} else {
|
} else {
|
||||||
return -EINVAL;
|
goto out;
|
||||||
}
|
}
|
||||||
} else if (!strncasecmp(str, "name=", 5)) {
|
} else if (!strncasecmp(str, "name=", 5)) {
|
||||||
char buf[64];
|
char buf[64];
|
||||||
|
|
@ -239,11 +237,33 @@ int snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst, const char *str)
|
||||||
if (*str == ',') {
|
if (*str == ',') {
|
||||||
str++;
|
str++;
|
||||||
} else {
|
} else {
|
||||||
|
/* when ret_ptr is given, allow to terminate gracefully
|
||||||
|
* at the next space letter
|
||||||
|
*/
|
||||||
|
if (ret_ptr && isspace(*str))
|
||||||
|
break;
|
||||||
if (*str)
|
if (*str)
|
||||||
return -EINVAL;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
err = 0;
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (ret_ptr)
|
||||||
|
*ret_ptr = str;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief parse ASCII string as CTL element identifier
|
||||||
|
* \param dst destination CTL identifier
|
||||||
|
* \param str source ASCII string
|
||||||
|
* \return zero on success, otherwise a negative error code
|
||||||
|
*/
|
||||||
|
int snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst, const char *str)
|
||||||
|
{
|
||||||
|
return __snd_ctl_ascii_elem_id_parse(dst, str, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_ctl_enum_item_index(snd_ctl_t *handle,
|
static int get_ctl_enum_item_index(snd_ctl_t *handle,
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ucm_local.h"
|
#include "ucm_local.h"
|
||||||
|
#include <ctype.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
|
|
@ -158,9 +159,13 @@ static int open_ctl(snd_use_case_mgr_t *uc_mgr,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern int __snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst,
|
||||||
|
const char *str,
|
||||||
|
const char **ret_ptr);
|
||||||
|
|
||||||
static int execute_cset(snd_ctl_t *ctl, char *cset)
|
static int execute_cset(snd_ctl_t *ctl, char *cset)
|
||||||
{
|
{
|
||||||
char *pos;
|
const char *pos;
|
||||||
int err;
|
int err;
|
||||||
snd_ctl_elem_id_t *id;
|
snd_ctl_elem_id_t *id;
|
||||||
snd_ctl_elem_value_t *value;
|
snd_ctl_elem_value_t *value;
|
||||||
|
|
@ -170,16 +175,16 @@ static int execute_cset(snd_ctl_t *ctl, char *cset)
|
||||||
snd_ctl_elem_value_malloc(&value);
|
snd_ctl_elem_value_malloc(&value);
|
||||||
snd_ctl_elem_info_malloc(&info);
|
snd_ctl_elem_info_malloc(&info);
|
||||||
|
|
||||||
pos = strrchr(cset, ' ');
|
err = __snd_ctl_ascii_elem_id_parse(id, cset, &pos);
|
||||||
if (pos == NULL) {
|
if (err < 0)
|
||||||
|
goto __fail;
|
||||||
|
while (*pos && isspace(*pos))
|
||||||
|
pos++;
|
||||||
|
if (!*pos) {
|
||||||
uc_error("undefined value for cset >%s<", cset);
|
uc_error("undefined value for cset >%s<", cset);
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
goto __fail;
|
goto __fail;
|
||||||
}
|
}
|
||||||
*pos = '\0';
|
|
||||||
err = snd_ctl_ascii_elem_id_parse(id, cset);
|
|
||||||
if (err < 0)
|
|
||||||
goto __fail;
|
|
||||||
snd_ctl_elem_value_set_id(value, id);
|
snd_ctl_elem_value_set_id(value, id);
|
||||||
snd_ctl_elem_info_set_id(info, id);
|
snd_ctl_elem_info_set_id(info, id);
|
||||||
err = snd_ctl_elem_read(ctl, value);
|
err = snd_ctl_elem_read(ctl, value);
|
||||||
|
|
@ -188,7 +193,7 @@ static int execute_cset(snd_ctl_t *ctl, char *cset)
|
||||||
err = snd_ctl_elem_info(ctl, info);
|
err = snd_ctl_elem_info(ctl, info);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto __fail;
|
goto __fail;
|
||||||
err = snd_ctl_ascii_value_parse(ctl, value, info, pos + 1);
|
err = snd_ctl_ascii_value_parse(ctl, value, info, pos);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto __fail;
|
goto __fail;
|
||||||
err = snd_ctl_elem_write(ctl, value);
|
err = snd_ctl_elem_write(ctl, value);
|
||||||
|
|
@ -196,9 +201,6 @@ static int execute_cset(snd_ctl_t *ctl, char *cset)
|
||||||
goto __fail;
|
goto __fail;
|
||||||
err = 0;
|
err = 0;
|
||||||
__fail:
|
__fail:
|
||||||
if (pos != NULL)
|
|
||||||
*pos = ' ';
|
|
||||||
|
|
||||||
if (id != NULL)
|
if (id != NULL)
|
||||||
free(id);
|
free(id);
|
||||||
if (value != NULL)
|
if (value != NULL)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue