alsactl: add dump-cfg and dump-state commands

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
Jaroslav Kysela 2021-03-07 19:58:33 +01:00
parent 09c04f8935
commit c1474594dc
8 changed files with 103 additions and 34 deletions

View file

@ -41,6 +41,10 @@ control device.
\fIclean\fP clean the controls created by applications. \fIclean\fP clean the controls created by applications.
\fIdump-state\fP dump the current state (all cards).
\fIdump-cfg\fP dump the current configuration (all cards, hooks are evaluated).
If no soundcards are specified, setup for all cards will be saved, If no soundcards are specified, setup for all cards will be saved,
loaded or monitored. loaded or monitored.

View file

@ -29,7 +29,6 @@
#include <errno.h> #include <errno.h>
#include <syslog.h> #include <syslog.h>
#include <sched.h> #include <sched.h>
#include <alsa/asoundlib.h>
#include "alsactl.h" #include "alsactl.h"
#ifndef SYS_ASOUNDRC #ifndef SYS_ASOUNDRC
@ -111,6 +110,8 @@ static struct arg args[] = {
{ CARDCMD, "rdaemon", "like daemon but do the state restore at first" }, { CARDCMD, "rdaemon", "like daemon but do the state restore at first" },
{ KILLCMD, "kill", "notify daemon to quit, rescan or save_and_quit" }, { KILLCMD, "kill", "notify daemon to quit, rescan or save_and_quit" },
{ CARDCMD, "monitor", "monitor control events" }, { CARDCMD, "monitor", "monitor control events" },
{ EMPCMD, "dump-state", "dump the state (for all cards)" },
{ EMPCMD, "dump-cfg", "dump the configuration (expanded, for all cards)" },
{ 0, NULL, NULL } { 0, NULL, NULL }
}; };
@ -139,7 +140,7 @@ static void help(void)
strcat(buf, "<card>"); strcat(buf, "<card>");
else if (sarg & KILLCMD) else if (sarg & KILLCMD)
strcat(buf, "<cmd>"); strcat(buf, "<cmd>");
printf(" %-8s %-6s %s\n", larg ? larg : "", printf(" %-10s %-6s %s\n", larg ? larg : "",
buf, a->comment); buf, a->comment);
continue; continue;
} }
@ -154,6 +155,48 @@ static void help(void)
} }
} }
static int dump_config_tree(snd_config_t *top)
{
snd_output_t *out;
int err;
err = snd_output_stdio_attach(&out, stdout, 0);
if (err < 0)
return err;
err = snd_config_save(top, out);
snd_output_close(out);
return 0;
}
static int dump_state(const char *file)
{
snd_config_t *top;
int err;
err = load_configuration(file, &top, NULL);
if (err < 0)
return err;
err = dump_config_tree(top);
snd_config_delete(top);
snd_config_update_free_global();
return err;
}
static int dump_configuration(void)
{
snd_config_t *top, *cfg2;
int err;
err = snd_config_update_ref(&top);
if (err < 0)
return err;
/* expand cards.* tree */
snd_config_search_definition(top, "cards", "dummy", &cfg2);
err = dump_config_tree(top);
snd_config_unref(top);
return err;
}
#define NO_NICE (-100000) #define NO_NICE (-100000)
static void do_nice(int use_nice, int sched_idle) static void do_nice(int use_nice, int sched_idle)
@ -399,6 +442,10 @@ int main(int argc, char *argv[])
res = monitor(cardname); res = monitor(cardname);
} else if (!strcmp(cmd, "clean")) { } else if (!strcmp(cmd, "clean")) {
res = clean(cardname, extra_args); res = clean(cardname, extra_args);
} else if (!strcmp(cmd, "dump-state")) {
res = dump_state(cfgfile);
} else if (!strcmp(cmd, "dump-cfg")) {
res = dump_configuration();
} else { } else {
fprintf(stderr, "alsactl: Unknown command '%s'...\n", cmd); fprintf(stderr, "alsactl: Unknown command '%s'...\n", cmd);
res = -ENODEV; res = -ENODEV;

View file

@ -1,3 +1,5 @@
#include <alsa/asoundlib.h>
extern int debugflag; extern int debugflag;
extern int force_restore; extern int force_restore;
extern int ignore_nocards; extern int ignore_nocards;
@ -28,6 +30,7 @@ void error_handler(const char *file, int line, const char *function, int err, co
#define FLAG_UCM_DISABLED (1<<0) #define FLAG_UCM_DISABLED (1<<0)
#define FLAG_UCM_DEFAULTS (1<<1) #define FLAG_UCM_DEFAULTS (1<<1)
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(const char *file, int flags, const char *cardname);
int init_ucm(int flags, int cardno); int init_ucm(int flags, int cardno);
int state_lock(const char *file, int timeout); int state_lock(const char *file, int timeout);

View file

@ -26,7 +26,6 @@
#include <stdio.h> #include <stdio.h>
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
#include <alsa/asoundlib.h>
#include "alsactl.h" #include "alsactl.h"
static int clean_one_control(snd_ctl_t *handle, snd_ctl_elem_id_t *elem_id, static int clean_one_control(snd_ctl_t *handle, snd_ctl_elem_id_t *elem_id,

View file

@ -29,7 +29,6 @@
#include <signal.h> #include <signal.h>
#include <time.h> #include <time.h>
#include <poll.h> #include <poll.h>
#include <alsa/asoundlib.h>
#include "alsactl.h" #include "alsactl.h"
struct id_list { struct id_list {

View file

@ -37,7 +37,6 @@
#include <sys/types.h> #include <sys/types.h>
#include <dirent.h> #include <dirent.h>
#include <math.h> #include <math.h>
#include <alsa/asoundlib.h>
#include "aconfig.h" #include "aconfig.h"
#include "alsactl.h" #include "alsactl.h"
#include "list.h" #include "list.h"

View file

@ -27,7 +27,6 @@
#include <stdio.h> #include <stdio.h>
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
#include <alsa/asoundlib.h>
#include "alsactl.h" #include "alsactl.h"
@ -1648,38 +1647,17 @@ out:
int load_state(const char *file, const char *initfile, int initflags, int load_state(const char *file, const char *initfile, int initflags,
const char *cardname, int do_init) const char *cardname, int do_init)
{ {
int err, finalerr = 0; int err, finalerr = 0, open_failed;
snd_config_t *config; snd_config_t *config;
snd_input_t *in;
int stdio, lock_fd = -EINVAL;
err = snd_config_top(&config); err = load_configuration(file, &config, &open_failed);
if (err < 0) { if (err < 0 && !open_failed)
error("snd_config_top error: %s", snd_strerror(err));
return err; return err;
}
stdio = !strcmp(file, "-"); if (open_failed) {
if (stdio) {
err = snd_input_stdio_attach(&in, stdin, 0);
} else {
lock_fd = state_lock(file, 10);
err = lock_fd >= 0 ? snd_input_stdio_open(&in, file, "r") : lock_fd;
}
if (err >= 0) {
err = snd_config_load(config, in);
snd_input_close(in);
if (lock_fd >= 0)
state_unlock(lock_fd, file);
if (err < 0) {
error("snd_config_load error: %s", snd_strerror(err));
goto out;
}
} else {
int card, first = 1; int card, first = 1;
char cardname1[16]; char cardname1[16];
if (lock_fd >= 0)
state_unlock(lock_fd, file);
error("Cannot open %s for reading: %s", file, snd_strerror(err)); error("Cannot open %s for reading: %s", file, snd_strerror(err));
finalerr = err; finalerr = err;
if (cardname) { if (cardname) {

View file

@ -30,8 +30,6 @@
#include <syslog.h> #include <syslog.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <alsa/asoundlib.h>
#include "alsactl.h" #include "alsactl.h"
int file_map(const char *filename, char **buf, size_t *bufsize) int file_map(const char *filename, char **buf, size_t *bufsize)
@ -193,3 +191,45 @@ void error_handler(const char *file, int line, const char *function, int err, co
fprintf(stderr, "alsa-lib %s:%i:(%s) %s%s%s\n", file, line, function, fprintf(stderr, "alsa-lib %s:%i:(%s) %s%s%s\n", file, line, function,
buf, err ? ": " : "", err ? snd_strerror(err) : ""); buf, err ? ": " : "", err ? snd_strerror(err) : "");
} }
int load_configuration(const char *file, snd_config_t **top, int *open_failed)
{
snd_config_t *config;
snd_input_t *in;
int err, stdio_flag, lock_fd = -EINVAL;
*top = NULL;
if (open_failed)
*open_failed = 0;
err = snd_config_top(&config);
if (err < 0) {
error("snd_config_top error: %s", snd_strerror(err));
return err;
}
stdio_flag = !strcmp(file, "-");
if (stdio_flag) {
err = snd_input_stdio_attach(&in, stdin, 0);
} else {
lock_fd = state_lock(file, 10);
err = lock_fd >= 0 ? snd_input_stdio_open(&in, file, "r") : lock_fd;
}
if (err < 0) {
if (open_failed)
*open_failed = 1;
goto out;
}
err = snd_config_load(config, in);
snd_input_close(in);
if (lock_fd >= 0)
state_unlock(lock_fd, file);
if (err < 0) {
error("snd_config_load error: %s", snd_strerror(err));
out:
snd_config_delete(config);
snd_config_update_free_global();
return err;
} else {
*top = config;
return 0;
}
}