mirror of
https://github.com/alsa-project/alsa-utils
synced 2024-11-09 17:35: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_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_iterator_t i, next;
|
||||
int err, maxnumid = -1;
|
||||
int err, maxnumid = -1, maxnumid2 = -1;
|
||||
unsigned int idx, count = 0;
|
||||
char name[32], tmpid[16];
|
||||
const char *id;
|
||||
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);
|
||||
dbg("device='%s', doit=%i", name, doit);
|
||||
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;
|
||||
}
|
||||
|
||||
dbg("maxnumid=%i", maxnumid);
|
||||
if (doit)
|
||||
goto _close;
|
||||
|
||||
err = snd_ctl_elem_list(handle, list);
|
||||
if (err < 0) {
|
||||
error("Cannot determine controls: %s", snd_strerror(err));
|
||||
goto _close;
|
||||
}
|
||||
count = snd_ctl_elem_list_get_count(list);
|
||||
dbg("list count: %u", count);
|
||||
if (count == 0)
|
||||
goto _check;
|
||||
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 */
|
||||
if (!doit && maxnumid >= 0) {
|
||||
snd_ctl_elem_info_t *info;
|
||||
snd_ctl_elem_info_alloca(&info);
|
||||
snd_ctl_elem_info_set_numid(info, maxnumid+1);
|
||||
if (snd_ctl_elem_info(handle, info) == 0) {
|
||||
_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?");
|
||||
goto _close;
|
||||
}
|
||||
}
|
||||
|
||||
_free:
|
||||
if (count >= 0)
|
||||
snd_ctl_elem_list_free_space(list);
|
||||
_close:
|
||||
snd_ctl_close(handle);
|
||||
dbg("result code: %i", err);
|
||||
|
|
Loading…
Reference in a new issue