alsactl: use card iterator functions for all card loops

Take the card iterator idea from the monitor code and
use it for all card loops. It reduces the code duplications
and makes things easy to review.

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
Jaroslav Kysela 2021-03-10 20:06:24 +01:00
parent 9a2115b5cc
commit eefc2c61cf
6 changed files with 131 additions and 237 deletions

View file

@ -1,3 +1,4 @@
#include <stdbool.h>
#include <alsa/asoundlib.h>
extern int debugflag;
@ -9,6 +10,13 @@ extern char *command;
extern char *statefile;
extern char *lockfile;
struct snd_card_iterator {
int card;
char name[16];
bool single;
bool first;
};
void info_(const char *fcn, long line, const char *fmt, ...);
void error_(const char *fcn, long line, const char *fmt, ...);
void cerror_(const char *fcn, long line, int cond, const char *fmt, ...);
@ -32,6 +40,11 @@ void error_handler(const char *file, int line, const char *function, int err, co
#define FLAG_UCM_BOOT (1<<2)
#define FLAG_UCM_DEFAULTS (1<<3)
void snd_card_iterator_init(struct snd_card_iterator *iter, int cardno);
int snd_card_iterator_sinit(struct snd_card_iterator *iter, const char *cardname);
const char *snd_card_iterator_next(struct snd_card_iterator *iter);
int snd_card_iterator_error(struct snd_card_iterator *iter);
int load_configuration(const char *file, snd_config_t **top, int *open_failed);
int init(const char *file, int flags, const char *cardname);
int init_ucm(int flags, int cardno);

View file

@ -182,46 +182,15 @@ fin_err:
int clean(const char *cardname, char *const *extra_args)
{
struct snd_card_iterator iter;
int err;
if (!cardname) {
int card, first = 1;
card = -1;
/* find each installed soundcards */
while (1) {
if (snd_card_next(&card) < 0)
break;
if (card < 0) {
if (first) {
if (ignore_nocards) {
err = 0;
goto out;
} else {
error("No soundcards found...");
err = -ENODEV;
goto out;
}
}
break;
}
first = 0;
if ((err = clean_controls(card, extra_args)))
goto out;
}
} else {
int cardno;
cardno = snd_card_get_index(cardname);
if (cardno < 0) {
error("Cannot find soundcard '%s'...", cardname);
err = cardno;
goto out;
}
if ((err = clean_controls(cardno, extra_args))) {
goto out;
}
err = snd_card_iterator_sinit(&iter, cardname);
if (err < 0)
return err;
while (snd_card_iterator_next(&iter)) {
if ((err = clean_controls(iter.card, extra_args)))
return err;
}
out:
return err;
return snd_card_iterator_error(&iter);
}

View file

@ -1746,63 +1746,33 @@ static int parse(struct space *space, const char *filename)
int init(const char *filename, int flags, const char *cardname)
{
struct space *space;
int err = 0, lasterr = 0, card, first;
struct snd_card_iterator iter;
int err = 0, lasterr = 0;
sysfs_init();
if (!cardname) {
first = 1;
card = -1;
while (1) {
if (snd_card_next(&card) < 0)
break;
if (card < 0) {
if (first) {
if (ignore_nocards)
return 0;
error("No soundcards found...");
return -ENODEV;
}
break;
}
first = 0;
err = init_ucm(flags, card);
if (err == 0)
continue;
err = init_space(&space, card);
if (err == 0) {
space->rootdir = new_root_dir(filename);
if (space->rootdir != NULL)
err = parse(space, filename);
if (err <= -99) { /* non-fatal errors */
if (lasterr == 0)
lasterr = err;
err = 0;
}
free_space(space);
}
if (err < 0)
break;
}
err = lasterr;
} else {
card = snd_card_get_index(cardname);
if (card < 0) {
error("Cannot find soundcard '%s'...", cardname);
goto error;
}
err = init_ucm(flags, card);
err = snd_card_iterator_sinit(&iter, cardname);
while (snd_card_iterator_next(&iter)) {
err = init_ucm(flags, iter.card);
if (err == 0)
return 0;
memset(&space, 0, sizeof(space));
err = init_space(&space, card);
if (err == 0) {
space->rootdir = new_root_dir(filename);
if (space->rootdir != NULL)
err = parse(space, filename);
free_space(space);
continue;
err = init_space(&space, iter.card);
if (err != 0)
continue;
space->rootdir = new_root_dir(filename);
if (space->rootdir != NULL) {
err = parse(space, filename);
if (!cardname && err <= -99) { /* non-fatal errors */
if (lasterr == 0)
lasterr = err;
err = 0;
}
}
free_space(space);
if (err < 0)
goto out;
}
error:
err = lasterr ? lasterr : snd_card_iterator_error(&iter);
out:
sysfs_cleanup();
return err;
}

View file

@ -28,11 +28,12 @@
#include <time.h>
#include <signal.h>
#include <sys/signalfd.h>
#include <alsa/asoundlib.h>
#include <stddef.h>
#include "list.h"
#include "alsactl.h"
struct src_entry {
snd_ctl_t *handle;
char *name;
@ -40,29 +41,6 @@ struct src_entry {
struct list_head list;
};
struct snd_card_iterator {
int card;
char name[16];
};
void snd_card_iterator_init(struct snd_card_iterator *iter)
{
iter->card = -1;
memset(iter->name, 0, sizeof(iter->name));
}
static const char *snd_card_iterator_next(struct snd_card_iterator *iter)
{
if (snd_card_next(&iter->card) < 0)
return NULL;
if (iter->card < 0)
return NULL;
snprintf(iter->name, sizeof(iter->name), "hw:%d", iter->card);
return (const char *)iter->name;
}
static void remove_source_entry(struct src_entry *entry)
{
list_del(&entry->list);
@ -159,7 +137,7 @@ static int prepare_source_entry(struct list_head *srcs, const char *name)
struct snd_card_iterator iter;
const char *cardname;
snd_card_iterator_init(&iter);
snd_card_iterator_init(&iter, -1);
while ((cardname = snd_card_iterator_next(&iter))) {
if (seek_entry_by_name(srcs, cardname))
continue;

View file

@ -1544,6 +1544,7 @@ int save_state(const char *file, const char *cardname)
int stdio;
char *nfile = NULL;
int lock_fd = -EINVAL;
struct snd_card_iterator iter;
err = snd_config_top(&config);
if (err < 0) {
@ -1577,45 +1578,18 @@ int save_state(const char *file, const char *cardname)
#endif
}
if (!cardname) {
int card, first = 1;
card = -1;
/* find each installed soundcards */
while (1) {
if (snd_card_next(&card) < 0)
break;
if (card < 0) {
if (first) {
if (ignore_nocards) {
err = 0;
goto out;
} else {
error("No soundcards found...");
err = -ENODEV;
goto out;
}
}
break;
}
first = 0;
if ((err = get_controls(card, config)))
goto out;
}
} else {
int cardno;
cardno = snd_card_get_index(cardname);
if (cardno < 0) {
error("Cannot find soundcard '%s'...", cardname);
err = cardno;
err = snd_card_iterator_sinit(&iter, cardname);
if (err < 0)
goto out;
while (snd_card_iterator_next(&iter)) {
if ((err = get_controls(iter.card, config)))
goto out;
}
if ((err = get_controls(cardno, config))) {
goto out;
}
}
if (iter.first) {
err = snd_card_iterator_error(&iter);
goto out;
}
if (stdio) {
err = snd_output_stdio_attach(&out, stdout, 0);
} else {
@ -1648,119 +1622,58 @@ int load_state(const char *file, const char *initfile, int initflags,
const char *cardname, int do_init)
{
int err, finalerr = 0, open_failed;
struct snd_card_iterator iter;
snd_config_t *config;
const char *cardname1;
err = load_configuration(file, &config, &open_failed);
if (err < 0 && !open_failed)
return err;
if (open_failed) {
int card, first = 1;
char cardname1[16];
error("Cannot open %s for reading: %s", file, snd_strerror(err));
finalerr = err;
if (cardname) {
card = snd_card_get_index(cardname);
if (card < 0) {
error("Cannot find soundcard '%s'...", cardname);
err = -ENODEV;
goto out;
}
goto single;
} else {
card = -1;
}
/* find each installed soundcards */
while (!cardname) {
if (snd_card_next(&card) < 0)
break;
if (card < 0)
break;
single:
first = 0;
err = snd_card_iterator_sinit(&iter, cardname);
if (err < 0)
return err;
while ((cardname1 = snd_card_iterator_next(&iter)) != NULL) {
if (!do_init)
break;
sprintf(cardname1, "%i", card);
err = init(initfile, initflags | FLAG_UCM_FBOOT | FLAG_UCM_BOOT, cardname1);
if (err < 0) {
finalerr = err;
initfailed(card, "init", err);
initfailed(iter.card, "init", err);
}
initfailed(card, "restore", -ENOENT);
initfailed(iter.card, "restore", -ENOENT);
}
if (first)
finalerr = 0; /* no cards, no error code */
err = finalerr;
if (iter.first)
err = 0; /* no cards, no error code */
goto out;
}
if (!cardname) {
int card, first = 1;
char cardname1[16];
card = -1;
/* find each installed soundcards */
while (1) {
if (snd_card_next(&card) < 0)
break;
if (card < 0) {
if (first) {
if (ignore_nocards) {
err = 0;
goto out;
} else {
error("No soundcards found...");
err = -ENODEV;
goto out;
}
}
break;
}
first = 0;
/* error is ignored */
init_ucm(initflags | FLAG_UCM_FBOOT, card);
/* do a check if controls matches state file */
if (do_init && set_controls(card, config, 0)) {
sprintf(cardname1, "%i", card);
err = init(initfile, initflags | FLAG_UCM_BOOT, cardname1);
if (err < 0) {
initfailed(card, "init", err);
finalerr = err;
}
}
if ((err = set_controls(card, config, 1))) {
if (!force_restore)
finalerr = err;
initfailed(card, "restore", err);
}
}
} else {
int cardno;
cardno = snd_card_get_index(cardname);
if (cardno < 0) {
error("Cannot find soundcard '%s'...", cardname);
err = -ENODEV;
goto out;
}
err = snd_card_iterator_sinit(&iter, cardname);
if (err < 0)
goto out;
while ((cardname1 = snd_card_iterator_next(&iter)) != NULL) {
/* error is ignored */
init_ucm(initflags | FLAG_UCM_FBOOT, cardno);
init_ucm(initflags | FLAG_UCM_FBOOT, iter.card);
/* do a check if controls matches state file */
if (do_init && set_controls(cardno, config, 0)) {
err = init(initfile, initflags | FLAG_UCM_BOOT, cardname);
if (do_init && set_controls(iter.card, config, 0)) {
err = init(initfile, initflags | FLAG_UCM_BOOT, cardname1);
if (err < 0) {
initfailed(cardno, "init", err);
initfailed(iter.card, "init", err);
finalerr = err;
}
}
if ((err = set_controls(cardno, config, 1))) {
initfailed(cardno, "restore", err);
if ((err = set_controls(iter.card, config, 1))) {
if (!force_restore)
goto out;
finalerr = err;
initfailed(iter.card, "restore", err);
}
}
err = finalerr;
err = finalerr ? finalerr : snd_card_iterator_error(&iter);
out:
snd_config_delete(config);
snd_config_update_free_global();

View file

@ -233,3 +233,54 @@ out:
return 0;
}
}
void snd_card_iterator_init(struct snd_card_iterator *iter, int cardno)
{
iter->card = cardno;
iter->single = cardno >= 0;
iter->first = true;
iter->name[0] = '\0';
}
int snd_card_iterator_sinit(struct snd_card_iterator *iter, const char *cardname)
{
int cardno = -1;
if (cardname) {
cardno = snd_card_get_index(cardname);
if (cardno < 0) {
error("Cannot find soundcard '%s'...", cardname);
return cardno;
}
}
snd_card_iterator_init(iter, cardno);
return 0;
}
const char *snd_card_iterator_next(struct snd_card_iterator *iter)
{
if (iter->single) {
if (iter->first) {
iter->first = false;
goto retval;
}
return NULL;
}
if (snd_card_next(&iter->card) < 0) {
if (!ignore_nocards && iter->first)
error("No soundcards found...");
return NULL;
}
iter->first = false;
if (iter->card < 0)
return NULL;
retval:
snprintf(iter->name, sizeof(iter->name), "hw:%d", iter->card);
return (const char *)iter->name;
}
int snd_card_iterator_error(struct snd_card_iterator *iter)
{
return iter->first ? (ignore_nocards ? 0 : -ENODEV) : 0;
}