mirror of
https://github.com/alsa-project/alsa-utils
synced 2024-11-10 00:55:42 +01:00
alsactl: fix the check for additional elements
The driver may export only write-only elements. The previous heuristics code do not handle this use case correctly. Iterate through all elements and skip the write-only ones. Fixes: https://github.com/alsa-project/alsa-utils/issues/122 Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
parent
3b1b6863e7
commit
257f3063fa
1 changed files with 53 additions and 15 deletions
|
@ -1482,13 +1482,19 @@ static int set_controls(int card, snd_config_t *top, int doit)
|
||||||
{
|
{
|
||||||
snd_ctl_t *handle;
|
snd_ctl_t *handle;
|
||||||
snd_ctl_card_info_t *info;
|
snd_ctl_card_info_t *info;
|
||||||
|
snd_ctl_elem_list_t *list;
|
||||||
|
snd_ctl_elem_info_t *elem_info;
|
||||||
|
snd_ctl_elem_id_t *elem_id;
|
||||||
snd_config_t *control;
|
snd_config_t *control;
|
||||||
snd_config_iterator_t i, next;
|
snd_config_iterator_t i, next;
|
||||||
int err, maxnumid = -1;
|
int err, maxnumid = -1, maxnumid2 = -1;
|
||||||
|
unsigned int idx, count = 0;
|
||||||
char name[32], tmpid[16];
|
char name[32], tmpid[16];
|
||||||
const char *id;
|
const char *id;
|
||||||
snd_ctl_card_info_alloca(&info);
|
snd_ctl_card_info_alloca(&info);
|
||||||
|
snd_ctl_elem_list_alloca(&list);
|
||||||
|
snd_ctl_elem_info_alloca(&elem_info);
|
||||||
|
snd_ctl_elem_id_alloca(&elem_id);
|
||||||
sprintf(name, "hw:%d", card);
|
sprintf(name, "hw:%d", card);
|
||||||
dbg("device='%s', doit=%i", name, doit);
|
dbg("device='%s', doit=%i", name, doit);
|
||||||
err = snd_ctl_open(&handle, name, 0);
|
err = snd_ctl_open(&handle, name, 0);
|
||||||
|
@ -1528,22 +1534,54 @@ static int set_controls(int card, snd_config_t *top, int doit)
|
||||||
goto _close;
|
goto _close;
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg("maxnumid=%i", maxnumid);
|
if (doit)
|
||||||
/* check if we have additional controls in driver */
|
goto _close;
|
||||||
/* in this case we should go through init procedure */
|
|
||||||
if (!doit && maxnumid >= 0) {
|
err = snd_ctl_elem_list(handle, list);
|
||||||
snd_ctl_elem_info_t *info;
|
if (err < 0) {
|
||||||
snd_ctl_elem_info_alloca(&info);
|
error("Cannot determine controls: %s", snd_strerror(err));
|
||||||
snd_ctl_elem_info_set_numid(info, maxnumid+1);
|
goto _close;
|
||||||
if (snd_ctl_elem_info(handle, info) == 0) {
|
}
|
||||||
/* not very informative */
|
count = snd_ctl_elem_list_get_count(list);
|
||||||
/* but value is used for check only */
|
dbg("list count: %u", count);
|
||||||
err = -EAGAIN;
|
if (count == 0)
|
||||||
dbg("more controls than maxnumid?");
|
goto _check;
|
||||||
goto _close;
|
snd_ctl_elem_list_set_offset(list, 0);
|
||||||
|
if (snd_ctl_elem_list_alloc_space(list, count) < 0) {
|
||||||
|
error("No enough memory...");
|
||||||
|
goto _close;
|
||||||
|
}
|
||||||
|
if ((err = snd_ctl_elem_list(handle, list)) < 0) {
|
||||||
|
error("Cannot determine controls (2): %s", snd_strerror(err));
|
||||||
|
goto _free;
|
||||||
|
}
|
||||||
|
maxnumid2 = 0;
|
||||||
|
/* skip non-readable elements */
|
||||||
|
for (idx = 0; idx < count; ++idx) {
|
||||||
|
snd_ctl_elem_info_clear(elem_info);
|
||||||
|
snd_ctl_elem_list_get_id(list, idx, elem_id);
|
||||||
|
snd_ctl_elem_info_set_id(elem_info, elem_id);
|
||||||
|
if (snd_ctl_elem_info(handle, elem_info) == 0) {
|
||||||
|
if (!snd_ctl_elem_info_is_readable(elem_info))
|
||||||
|
continue;
|
||||||
|
maxnumid2++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check if we have additional controls in driver */
|
||||||
|
/* in this case we should go through init procedure */
|
||||||
|
_check:
|
||||||
|
dbg("maxnumid=%i maxnumid2=%i", maxnumid, maxnumid2);
|
||||||
|
if (maxnumid >= 0 && maxnumid != maxnumid2) {
|
||||||
|
/* not very informative */
|
||||||
|
/* but value is used for check only */
|
||||||
|
err = -EAGAIN;
|
||||||
|
dbg("more controls than maxnumid?");
|
||||||
|
}
|
||||||
|
|
||||||
|
_free:
|
||||||
|
if (count >= 0)
|
||||||
|
snd_ctl_elem_list_free_space(list);
|
||||||
_close:
|
_close:
|
||||||
snd_ctl_close(handle);
|
snd_ctl_close(handle);
|
||||||
dbg("result code: %i", err);
|
dbg("result code: %i", err);
|
||||||
|
|
Loading…
Reference in a new issue