mirror of
https://github.com/alsa-project/alsa-utils
synced 2024-12-23 03:46:31 +01:00
alsactl init - restore calls also init on failure
The initialization procedure consist from default initialization and state restoration. When restore fails for a reason or the config file contains inaccurate information, then init is called. Also, if something fails (init or restore), a file specified using -r option can be created with description what failed. It can be useful when user space decides to notify user to set the sound driver properly. Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
parent
ec73719ec6
commit
b8560a6bbb
5 changed files with 202 additions and 89 deletions
|
@ -36,6 +36,7 @@
|
||||||
int debugflag = 0;
|
int debugflag = 0;
|
||||||
int force_restore = 1;
|
int force_restore = 1;
|
||||||
char *command;
|
char *command;
|
||||||
|
char *statefile = NULL;
|
||||||
|
|
||||||
static void help(void)
|
static void help(void)
|
||||||
{
|
{
|
||||||
|
@ -49,6 +50,8 @@ static void help(void)
|
||||||
printf(" -F,--force try to restore the matching controls as much as possible\n");
|
printf(" -F,--force try to restore the matching controls as much as possible\n");
|
||||||
printf(" (default mode)\n");
|
printf(" (default mode)\n");
|
||||||
printf(" -P,--pedantic don't restore mismatching controls (old default)\n");
|
printf(" -P,--pedantic don't restore mismatching controls (old default)\n");
|
||||||
|
printf(" -r,--runstate # save restore and init state to this file (only errors)\n");
|
||||||
|
printf(" default settings is 'no file set'\n");
|
||||||
printf("\nAvailable init options:\n");
|
printf("\nAvailable init options:\n");
|
||||||
printf(" -E,--env #=# set environment variable for init phase (NAME=VALUE)\n");
|
printf(" -E,--env #=# set environment variable for init phase (NAME=VALUE)\n");
|
||||||
printf(" -i,--initfile # main configuation file for init phase (default " DATADIR "/init/00main)\n");
|
printf(" -i,--initfile # main configuation file for init phase (default " DATADIR "/init/00main)\n");
|
||||||
|
@ -73,19 +76,21 @@ int main(int argc, char *argv[])
|
||||||
{"initfile", 1, NULL, 'i'},
|
{"initfile", 1, NULL, 'i'},
|
||||||
{"force", 0, NULL, 'F'},
|
{"force", 0, NULL, 'F'},
|
||||||
{"pedantic", 0, NULL, 'P'},
|
{"pedantic", 0, NULL, 'P'},
|
||||||
|
{"runstate", 0, NULL, 'r'},
|
||||||
{"debug", 0, NULL, 'd'},
|
{"debug", 0, NULL, 'd'},
|
||||||
{"version", 0, NULL, 'v'},
|
{"version", 0, NULL, 'v'},
|
||||||
{NULL, 0, NULL, 0},
|
{NULL, 0, NULL, 0},
|
||||||
};
|
};
|
||||||
char *cfgfile = SYS_ASOUNDRC;
|
char *cfgfile = SYS_ASOUNDRC;
|
||||||
char *initfile = DATADIR "/init/00main";
|
char *initfile = DATADIR "/init/00main";
|
||||||
|
char *cardname;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
command = argv[0];
|
command = argv[0];
|
||||||
while (1) {
|
while (1) {
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
if ((c = getopt_long(argc, argv, "hdvf:FE:i:", long_option, NULL)) < 0)
|
if ((c = getopt_long(argc, argv, "hdvf:FE:i:Pr:", long_option, NULL)) < 0)
|
||||||
break;
|
break;
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'h':
|
case 'h':
|
||||||
|
@ -106,6 +111,9 @@ int main(int argc, char *argv[])
|
||||||
case 'i':
|
case 'i':
|
||||||
initfile = optarg;
|
initfile = optarg;
|
||||||
break;
|
break;
|
||||||
|
case 'r':
|
||||||
|
statefile = optarg;
|
||||||
|
break;
|
||||||
case 'P':
|
case 'P':
|
||||||
force_restore = 0;
|
force_restore = 0;
|
||||||
break;
|
break;
|
||||||
|
@ -129,15 +137,14 @@ int main(int argc, char *argv[])
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cardname = argc - optind > 1 ? argv[optind + 1] : NULL;
|
||||||
if (!strcmp(argv[optind], "init")) {
|
if (!strcmp(argv[optind], "init")) {
|
||||||
res = init(initfile,
|
res = init(initfile, cardname);
|
||||||
argc - optind > 1 ? argv[optind + 1] : NULL);
|
|
||||||
} else if (!strcmp(argv[optind], "store")) {
|
} else if (!strcmp(argv[optind], "store")) {
|
||||||
res = save_state(cfgfile,
|
res = save_state(cfgfile, cardname);
|
||||||
argc - optind > 1 ? argv[optind + 1] : NULL);
|
|
||||||
} else if (!strcmp(argv[optind], "restore")) {
|
} else if (!strcmp(argv[optind], "restore")) {
|
||||||
res = load_state(cfgfile,
|
remove(statefile);
|
||||||
argc - optind > 1 ? argv[optind + 1] : NULL);
|
res = load_state(cfgfile, initfile, cardname);
|
||||||
} else if (!strcmp(argv[optind], "names")) {
|
} else if (!strcmp(argv[optind], "names")) {
|
||||||
if (!strcmp(cfgfile, SYS_ASOUNDRC))
|
if (!strcmp(cfgfile, SYS_ASOUNDRC))
|
||||||
cfgfile = SYS_ASOUNDNAMES;
|
cfgfile = SYS_ASOUNDNAMES;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
extern int debugflag;
|
extern int debugflag;
|
||||||
extern int force_restore;
|
extern int force_restore;
|
||||||
extern char *command;
|
extern char *command;
|
||||||
|
extern char *statefile;
|
||||||
|
|
||||||
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
|
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
|
||||||
#define info(...) do {\
|
#define info(...) do {\
|
||||||
|
@ -30,6 +31,24 @@ extern char *command;
|
||||||
} while (0)
|
} while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
|
||||||
|
#define cerror(cond, ...) do {\
|
||||||
|
if (cond) { \
|
||||||
|
fprintf(stderr, "%s: %s:%d: ", command, __FUNCTION__, __LINE__); \
|
||||||
|
fprintf(stderr, __VA_ARGS__); \
|
||||||
|
putc('\n', stderr); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
#else
|
||||||
|
#define cerror(cond, args...) do {\
|
||||||
|
if (cond) { \
|
||||||
|
fprintf(stderr, "%s: %s:%d: ", command, __FUNCTION__, __LINE__); \
|
||||||
|
fprintf(stderr, ##args); \
|
||||||
|
putc('\n', stderr); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
|
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
|
||||||
#define dbg(...) do {\
|
#define dbg(...) do {\
|
||||||
if (!debugflag) break; \
|
if (!debugflag) break; \
|
||||||
|
@ -48,7 +67,7 @@ extern char *command;
|
||||||
|
|
||||||
int init(const char *file, const char *cardname);
|
int init(const char *file, const char *cardname);
|
||||||
int save_state(const char *file, const char *cardname);
|
int save_state(const char *file, const char *cardname);
|
||||||
int load_state(const char *file, const char *cardname);
|
int load_state(const char *file, const char *initfile, const char *cardname);
|
||||||
int power(const char *argv[], int argc);
|
int power(const char *argv[], int argc);
|
||||||
int generate_names(const char *cfgfile);
|
int generate_names(const char *cfgfile);
|
||||||
|
|
||||||
|
@ -57,6 +76,7 @@ int generate_names(const char *cfgfile);
|
||||||
int file_map(const char *filename, char **buf, size_t *bufsize);
|
int file_map(const char *filename, char **buf, size_t *bufsize);
|
||||||
void file_unmap(void *buf, size_t bufsize);
|
void file_unmap(void *buf, size_t bufsize);
|
||||||
size_t line_width(const char *buf, size_t bufsize, size_t pos);
|
size_t line_width(const char *buf, size_t bufsize, size_t pos);
|
||||||
|
void initfailed(int cardnumber, const char *reason);
|
||||||
|
|
||||||
static inline int hextodigit(int c)
|
static inline int hextodigit(int c)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1627,7 +1627,7 @@ static int parse(struct space *space, const char *filename)
|
||||||
space->linenum = -1;
|
space->linenum = -1;
|
||||||
file_unmap(buf, bufsize);
|
file_unmap(buf, bufsize);
|
||||||
dbg("end of file '%s'", filename);
|
dbg("end of file '%s'", filename);
|
||||||
return err;
|
return err ? err : -abs(space->exit_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
int init(const char *filename, const char *cardname)
|
int init(const char *filename, const char *cardname)
|
||||||
|
|
227
alsactl/state.c
227
alsactl/state.c
|
@ -665,7 +665,7 @@ static long config_iface(snd_config_t *n)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int config_bool(snd_config_t *n)
|
static int config_bool(snd_config_t *n, int doit)
|
||||||
{
|
{
|
||||||
const char *str;
|
const char *str;
|
||||||
long val;
|
long val;
|
||||||
|
@ -686,10 +686,10 @@ static int config_bool(snd_config_t *n)
|
||||||
snd_config_get_string(n, &str);
|
snd_config_get_string(n, &str);
|
||||||
break;
|
break;
|
||||||
case SND_CONFIG_TYPE_COMPOUND:
|
case SND_CONFIG_TYPE_COMPOUND:
|
||||||
if (!force_restore)
|
if (!force_restore || !doit)
|
||||||
return -1;
|
return -1;
|
||||||
n = snd_config_iterator_entry(snd_config_iterator_first(n));
|
n = snd_config_iterator_entry(snd_config_iterator_first(n));
|
||||||
return config_bool(n);
|
return config_bool(n, doit);
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -701,7 +701,7 @@ static int config_bool(snd_config_t *n)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int config_enumerated(snd_config_t *n, snd_ctl_t *handle,
|
static int config_enumerated(snd_config_t *n, snd_ctl_t *handle,
|
||||||
snd_ctl_elem_info_t *info)
|
snd_ctl_elem_info_t *info, int doit)
|
||||||
{
|
{
|
||||||
const char *str;
|
const char *str;
|
||||||
long val;
|
long val;
|
||||||
|
@ -719,10 +719,10 @@ static int config_enumerated(snd_config_t *n, snd_ctl_t *handle,
|
||||||
snd_config_get_string(n, &str);
|
snd_config_get_string(n, &str);
|
||||||
break;
|
break;
|
||||||
case SND_CONFIG_TYPE_COMPOUND:
|
case SND_CONFIG_TYPE_COMPOUND:
|
||||||
if (!force_restore)
|
if (!force_restore || !doit)
|
||||||
return -1;
|
return -1;
|
||||||
n = snd_config_iterator_entry(snd_config_iterator_first(n));
|
n = snd_config_iterator_entry(snd_config_iterator_first(n));
|
||||||
return config_enumerated(n, handle, info);
|
return config_enumerated(n, handle, info, doit);
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -741,26 +741,26 @@ static int config_enumerated(snd_config_t *n, snd_ctl_t *handle,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int config_integer(snd_config_t *n, long *val)
|
static int config_integer(snd_config_t *n, long *val, int doit)
|
||||||
{
|
{
|
||||||
int err = snd_config_get_integer(n, val);
|
int err = snd_config_get_integer(n, val);
|
||||||
if (err < 0 && force_restore) {
|
if (err < 0 && force_restore && doit) {
|
||||||
if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND)
|
if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND)
|
||||||
return err;
|
return err;
|
||||||
n = snd_config_iterator_entry(snd_config_iterator_first(n));
|
n = snd_config_iterator_entry(snd_config_iterator_first(n));
|
||||||
return config_integer(n, val);
|
return config_integer(n, val, doit);
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int config_integer64(snd_config_t *n, long long *val)
|
static int config_integer64(snd_config_t *n, long long *val, int doit)
|
||||||
{
|
{
|
||||||
int err = snd_config_get_integer64(n, val);
|
int err = snd_config_get_integer64(n, val);
|
||||||
if (err < 0 && force_restore) {
|
if (err < 0 && force_restore && doit) {
|
||||||
if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND)
|
if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND)
|
||||||
return err;
|
return err;
|
||||||
n = snd_config_iterator_entry(snd_config_iterator_first(n));
|
n = snd_config_iterator_entry(snd_config_iterator_first(n));
|
||||||
return config_integer64(n, val);
|
return config_integer64(n, val, doit);
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -966,10 +966,11 @@ static int check_comment_type(snd_config_t *conf, int type)
|
||||||
static int convert_to_new_db(snd_config_t *value, long omin, long omax,
|
static int convert_to_new_db(snd_config_t *value, long omin, long omax,
|
||||||
long nmin, long nmax,
|
long nmin, long nmax,
|
||||||
long odbmin, long odbmax,
|
long odbmin, long odbmax,
|
||||||
long ndbmin, long ndbmax)
|
long ndbmin, long ndbmax,
|
||||||
|
int doit)
|
||||||
{
|
{
|
||||||
long val;
|
long val;
|
||||||
if (config_integer(value, &val) < 0)
|
if (config_integer(value, &val, doit) < 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (val < omin || val > omax)
|
if (val < omin || val > omax)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -988,7 +989,8 @@ static int convert_to_new_db(snd_config_t *value, long omin, long omax,
|
||||||
* if any change occurs, try to keep the same dB level.
|
* if any change occurs, try to keep the same dB level.
|
||||||
*/
|
*/
|
||||||
static int check_comment_range(snd_ctl_t *handle, snd_config_t *conf,
|
static int check_comment_range(snd_ctl_t *handle, snd_config_t *conf,
|
||||||
snd_ctl_elem_info_t *info, snd_config_t *value)
|
snd_ctl_elem_info_t *info, snd_config_t *value,
|
||||||
|
int doit)
|
||||||
{
|
{
|
||||||
snd_config_t *n;
|
snd_config_t *n;
|
||||||
long omin, omax, ostep;
|
long omin, omax, ostep;
|
||||||
|
@ -1007,7 +1009,7 @@ static int check_comment_range(snd_ctl_t *handle, snd_config_t *conf,
|
||||||
nmax = snd_ctl_elem_info_get_max(info);
|
nmax = snd_ctl_elem_info_get_max(info);
|
||||||
if (omin != nmin && omax != nmax) {
|
if (omin != nmin && omax != nmax) {
|
||||||
/* Hey, the range mismatches */
|
/* Hey, the range mismatches */
|
||||||
if (!force_restore)
|
if (!force_restore || !doit)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (omin >= omax || nmin >= nmax)
|
if (omin >= omax || nmin >= nmax)
|
||||||
|
@ -1016,12 +1018,12 @@ static int check_comment_range(snd_ctl_t *handle, snd_config_t *conf,
|
||||||
n = search_comment_item(conf, "dbmin");
|
n = search_comment_item(conf, "dbmin");
|
||||||
if (!n)
|
if (!n)
|
||||||
return 0;
|
return 0;
|
||||||
if (config_integer(n, &odbmin) < 0)
|
if (config_integer(n, &odbmin, doit) < 0)
|
||||||
return 0;
|
return 0;
|
||||||
n = search_comment_item(conf, "dbmax");
|
n = search_comment_item(conf, "dbmax");
|
||||||
if (!n)
|
if (!n)
|
||||||
return 0;
|
return 0;
|
||||||
if (config_integer(n, &odbmax) < 0)
|
if (config_integer(n, &odbmax, doit) < 0)
|
||||||
return 0;
|
return 0;
|
||||||
if (odbmin >= odbmax)
|
if (odbmin >= odbmax)
|
||||||
return 0; /* invalid values */
|
return 0; /* invalid values */
|
||||||
|
@ -1041,18 +1043,19 @@ static int check_comment_range(snd_ctl_t *handle, snd_config_t *conf,
|
||||||
snd_config_for_each(i, next, value) {
|
snd_config_for_each(i, next, value) {
|
||||||
snd_config_t *n = snd_config_iterator_entry(i);
|
snd_config_t *n = snd_config_iterator_entry(i);
|
||||||
convert_to_new_db(n, omin, omax, nmin, nmax,
|
convert_to_new_db(n, omin, omax, nmin, nmax,
|
||||||
odbmin, odbmax, ndbmin, ndbmax);
|
odbmin, odbmax, ndbmin, ndbmax, doit);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
convert_to_new_db(value, omin, omax, nmin, nmax,
|
convert_to_new_db(value, omin, omax, nmin, nmax,
|
||||||
odbmin, odbmax, ndbmin, ndbmax);
|
odbmin, odbmax, ndbmin, ndbmax, doit);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int restore_config_value(snd_ctl_t *handle, snd_ctl_elem_info_t *info,
|
static int restore_config_value(snd_ctl_t *handle, snd_ctl_elem_info_t *info,
|
||||||
snd_ctl_elem_iface_t type,
|
snd_ctl_elem_iface_t type,
|
||||||
snd_config_t *value,
|
snd_config_t *value,
|
||||||
snd_ctl_elem_value_t *ctl, int idx)
|
snd_ctl_elem_value_t *ctl, int idx,
|
||||||
|
int doit)
|
||||||
{
|
{
|
||||||
long val;
|
long val;
|
||||||
long long lval;
|
long long lval;
|
||||||
|
@ -1060,28 +1063,28 @@ static int restore_config_value(snd_ctl_t *handle, snd_ctl_elem_info_t *info,
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SND_CTL_ELEM_TYPE_BOOLEAN:
|
case SND_CTL_ELEM_TYPE_BOOLEAN:
|
||||||
val = config_bool(value);
|
val = config_bool(value, doit);
|
||||||
if (val >= 0) {
|
if (val >= 0) {
|
||||||
snd_ctl_elem_value_set_boolean(ctl, idx, val);
|
snd_ctl_elem_value_set_boolean(ctl, idx, val);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SND_CTL_ELEM_TYPE_INTEGER:
|
case SND_CTL_ELEM_TYPE_INTEGER:
|
||||||
err = config_integer(value, &val);
|
err = config_integer(value, &val, doit);
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
snd_ctl_elem_value_set_integer(ctl, idx, val);
|
snd_ctl_elem_value_set_integer(ctl, idx, val);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SND_CTL_ELEM_TYPE_INTEGER64:
|
case SND_CTL_ELEM_TYPE_INTEGER64:
|
||||||
err = config_integer64(value, &lval);
|
err = config_integer64(value, &lval, doit);
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
snd_ctl_elem_value_set_integer64(ctl, idx, lval);
|
snd_ctl_elem_value_set_integer64(ctl, idx, lval);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SND_CTL_ELEM_TYPE_ENUMERATED:
|
case SND_CTL_ELEM_TYPE_ENUMERATED:
|
||||||
val = config_enumerated(value, handle, info);
|
val = config_enumerated(value, handle, info, doit);
|
||||||
if (val >= 0) {
|
if (val >= 0) {
|
||||||
snd_ctl_elem_value_set_enumerated(ctl, idx, val);
|
snd_ctl_elem_value_set_enumerated(ctl, idx, val);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1091,7 +1094,7 @@ static int restore_config_value(snd_ctl_t *handle, snd_ctl_elem_info_t *info,
|
||||||
case SND_CTL_ELEM_TYPE_IEC958:
|
case SND_CTL_ELEM_TYPE_IEC958:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error("Unknow control type: %d", type);
|
cerror(doit, "Unknow control type: %d", type);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1101,9 +1104,9 @@ static int restore_config_value2(snd_ctl_t *handle, snd_ctl_elem_info_t *info,
|
||||||
snd_ctl_elem_iface_t type,
|
snd_ctl_elem_iface_t type,
|
||||||
snd_config_t *value,
|
snd_config_t *value,
|
||||||
snd_ctl_elem_value_t *ctl, int idx,
|
snd_ctl_elem_value_t *ctl, int idx,
|
||||||
unsigned int numid)
|
unsigned int numid, int doit)
|
||||||
{
|
{
|
||||||
int err = restore_config_value(handle, info, type, value, ctl, idx);
|
int err = restore_config_value(handle, info, type, value, ctl, idx, doit);
|
||||||
long val;
|
long val;
|
||||||
|
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
|
@ -1113,8 +1116,8 @@ static int restore_config_value2(snd_ctl_t *handle, snd_ctl_elem_info_t *info,
|
||||||
case SND_CTL_ELEM_TYPE_IEC958:
|
case SND_CTL_ELEM_TYPE_IEC958:
|
||||||
err = snd_config_get_integer(value, &val);
|
err = snd_config_get_integer(value, &val);
|
||||||
if (err < 0 || val < 0 || val > 255) {
|
if (err < 0 || val < 0 || val > 255) {
|
||||||
error("bad control.%d.value.%d content", numid, idx);
|
cerror(doit, "bad control.%d.value.%d content", numid, idx);
|
||||||
return force_restore ? 0 : -EINVAL;
|
return force_restore && doit ? 0 : -EINVAL;
|
||||||
}
|
}
|
||||||
snd_ctl_elem_value_set_byte(ctl, idx, val);
|
snd_ctl_elem_value_set_byte(ctl, idx, val);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1125,7 +1128,8 @@ static int restore_config_value2(snd_ctl_t *handle, snd_ctl_elem_info_t *info,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int set_control(snd_ctl_t *handle, snd_config_t *control)
|
static int set_control(snd_ctl_t *handle, snd_config_t *control,
|
||||||
|
int *maxnumid, int doit)
|
||||||
{
|
{
|
||||||
snd_ctl_elem_value_t *ctl;
|
snd_ctl_elem_value_t *ctl;
|
||||||
snd_ctl_elem_info_t *info;
|
snd_ctl_elem_info_t *info;
|
||||||
|
@ -1153,15 +1157,17 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
|
||||||
snd_ctl_elem_value_alloca(&ctl);
|
snd_ctl_elem_value_alloca(&ctl);
|
||||||
snd_ctl_elem_info_alloca(&info);
|
snd_ctl_elem_info_alloca(&info);
|
||||||
if (snd_config_get_type(control) != SND_CONFIG_TYPE_COMPOUND) {
|
if (snd_config_get_type(control) != SND_CONFIG_TYPE_COMPOUND) {
|
||||||
error("control is not a compound");
|
cerror(doit, "control is not a compound");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
err = snd_config_get_id(control, &id);
|
err = snd_config_get_id(control, &id);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
error("unable to get id");
|
cerror(doit, "unable to get id");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
numid = atoi(id);
|
numid = atoi(id);
|
||||||
|
if (numid > *maxnumid)
|
||||||
|
*maxnumid = numid;
|
||||||
snd_config_for_each(i, next, control) {
|
snd_config_for_each(i, next, control) {
|
||||||
snd_config_t *n = snd_config_iterator_entry(i);
|
snd_config_t *n = snd_config_iterator_entry(i);
|
||||||
const char *fld;
|
const char *fld;
|
||||||
|
@ -1169,7 +1175,7 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
|
||||||
continue;
|
continue;
|
||||||
if (strcmp(fld, "comment") == 0) {
|
if (strcmp(fld, "comment") == 0) {
|
||||||
if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
|
if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
|
||||||
error("control.%d.%s is invalid", numid, fld);
|
cerror(doit, "control.%d.%s is invalid", numid, fld);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
comment = n;
|
comment = n;
|
||||||
|
@ -1178,14 +1184,14 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
|
||||||
if (strcmp(fld, "iface") == 0) {
|
if (strcmp(fld, "iface") == 0) {
|
||||||
iface = (snd_ctl_elem_iface_t)config_iface(n);
|
iface = (snd_ctl_elem_iface_t)config_iface(n);
|
||||||
if (iface < 0) {
|
if (iface < 0) {
|
||||||
error("control.%d.%s is invalid", numid, fld);
|
cerror(doit, "control.%d.%s is invalid", numid, fld);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (strcmp(fld, "device") == 0) {
|
if (strcmp(fld, "device") == 0) {
|
||||||
if (snd_config_get_type(n) != SND_CONFIG_TYPE_INTEGER) {
|
if (snd_config_get_type(n) != SND_CONFIG_TYPE_INTEGER) {
|
||||||
error("control.%d.%s is invalid", numid, fld);
|
cerror(doit, "control.%d.%s is invalid", numid, fld);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
snd_config_get_integer(n, &device);
|
snd_config_get_integer(n, &device);
|
||||||
|
@ -1193,7 +1199,7 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
|
||||||
}
|
}
|
||||||
if (strcmp(fld, "subdevice") == 0) {
|
if (strcmp(fld, "subdevice") == 0) {
|
||||||
if (snd_config_get_type(n) != SND_CONFIG_TYPE_INTEGER) {
|
if (snd_config_get_type(n) != SND_CONFIG_TYPE_INTEGER) {
|
||||||
error("control.%d.%s is invalid", numid, fld);
|
cerror(doit, "control.%d.%s is invalid", numid, fld);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
snd_config_get_integer(n, &subdevice);
|
snd_config_get_integer(n, &subdevice);
|
||||||
|
@ -1201,7 +1207,7 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
|
||||||
}
|
}
|
||||||
if (strcmp(fld, "name") == 0) {
|
if (strcmp(fld, "name") == 0) {
|
||||||
if (snd_config_get_type(n) != SND_CONFIG_TYPE_STRING) {
|
if (snd_config_get_type(n) != SND_CONFIG_TYPE_STRING) {
|
||||||
error("control.%d.%s is invalid", numid, fld);
|
cerror(doit, "control.%d.%s is invalid", numid, fld);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
snd_config_get_string(n, &name);
|
snd_config_get_string(n, &name);
|
||||||
|
@ -1209,7 +1215,7 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
|
||||||
}
|
}
|
||||||
if (strcmp(fld, "index") == 0) {
|
if (strcmp(fld, "index") == 0) {
|
||||||
if (snd_config_get_type(n) != SND_CONFIG_TYPE_INTEGER) {
|
if (snd_config_get_type(n) != SND_CONFIG_TYPE_INTEGER) {
|
||||||
error("control.%d.%s is invalid", numid, fld);
|
cerror(doit, "control.%d.%s is invalid", numid, fld);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
snd_config_get_integer(n, &index);
|
snd_config_get_integer(n, &index);
|
||||||
|
@ -1219,10 +1225,10 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
|
||||||
value = n;
|
value = n;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
error("unknown control.%d.%s field", numid, fld);
|
cerror(doit, "unknown control.%d.%s field", numid, fld);
|
||||||
}
|
}
|
||||||
if (!value) {
|
if (!value) {
|
||||||
error("missing control.%d.value", numid);
|
cerror(doit, "missing control.%d.value", numid);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (device < 0)
|
if (device < 0)
|
||||||
|
@ -1233,7 +1239,7 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
|
||||||
index = 0;
|
index = 0;
|
||||||
|
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
if (! force_restore) {
|
if (!force_restore) {
|
||||||
snd_ctl_elem_info_set_numid(info, numid);
|
snd_ctl_elem_info_set_numid(info, numid);
|
||||||
err = snd_ctl_elem_info(handle, info);
|
err = snd_ctl_elem_info(handle, info);
|
||||||
}
|
}
|
||||||
|
@ -1249,7 +1255,7 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
|
||||||
if (err < 0 && comment && is_user_control(comment)) {
|
if (err < 0 && comment && is_user_control(comment)) {
|
||||||
err = add_user_control(handle, info, comment);
|
err = add_user_control(handle, info, comment);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
error("failed to add user control #%d (%s)",
|
cerror(doit, "failed to add user control #%d (%s)",
|
||||||
numid, snd_strerror(err));
|
numid, snd_strerror(err));
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -1257,7 +1263,7 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
error("failed to obtain info for control #%d (%s)", numid, snd_strerror(err));
|
cerror(doit, "failed to obtain info for control #%d (%s)", numid, snd_strerror(err));
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
numid1 = snd_ctl_elem_info_get_numid(info);
|
numid1 = snd_ctl_elem_info_get_numid(info);
|
||||||
|
@ -1268,30 +1274,30 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
|
||||||
index1 = snd_ctl_elem_info_get_index(info);
|
index1 = snd_ctl_elem_info_get_index(info);
|
||||||
count = snd_ctl_elem_info_get_count(info);
|
count = snd_ctl_elem_info_get_count(info);
|
||||||
type = snd_ctl_elem_info_get_type(info);
|
type = snd_ctl_elem_info_get_type(info);
|
||||||
if (err |= numid != numid1 && ! force_restore)
|
if (err |= numid != numid1 && !force_restore)
|
||||||
error("warning: numid mismatch (%d/%d) for control #%d",
|
cerror(doit, "warning: numid mismatch (%d/%d) for control #%d",
|
||||||
numid, numid1, numid);
|
numid, numid1, numid);
|
||||||
if (err |= iface != iface1)
|
if (err |= iface != iface1)
|
||||||
error("warning: iface mismatch (%d/%d) for control #%d", iface, iface1, numid);
|
cerror(doit, "warning: iface mismatch (%d/%d) for control #%d", iface, iface1, numid);
|
||||||
if (err |= device != device1)
|
if (err |= device != device1)
|
||||||
error("warning: device mismatch (%ld/%ld) for control #%d", device, device1, numid);
|
cerror(doit, "warning: device mismatch (%ld/%ld) for control #%d", device, device1, numid);
|
||||||
if (err |= subdevice != subdevice1)
|
if (err |= subdevice != subdevice1)
|
||||||
error("warning: subdevice mismatch (%ld/%ld) for control #%d", subdevice, subdevice1, numid);
|
cerror(doit, "warning: subdevice mismatch (%ld/%ld) for control #%d", subdevice, subdevice1, numid);
|
||||||
if (err |= strcmp(name, name1))
|
if (err |= strcmp(name, name1))
|
||||||
error("warning: name mismatch (%s/%s) for control #%d", name, name1, numid);
|
cerror(doit, "warning: name mismatch (%s/%s) for control #%d", name, name1, numid);
|
||||||
if (err |= index != index1)
|
if (err |= index != index1)
|
||||||
error("warning: index mismatch (%ld/%ld) for control #%d", index, index1, numid);
|
cerror(doit, "warning: index mismatch (%ld/%ld) for control #%d", index, index1, numid);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
error("failed to obtain info for control #%d (%s)", numid, snd_strerror(err));
|
cerror(doit, "failed to obtain info for control #%d (%s)", numid, snd_strerror(err));
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comment) {
|
if (comment) {
|
||||||
if (check_comment_type(comment, type) < 0)
|
if (check_comment_type(comment, type) < 0)
|
||||||
error("incompatible field type for control #%d", numid);
|
cerror(doit, "incompatible field type for control #%d", numid);
|
||||||
if (type == SND_CTL_ELEM_TYPE_INTEGER) {
|
if (type == SND_CTL_ELEM_TYPE_INTEGER) {
|
||||||
if (check_comment_range(handle, comment, info, value) < 0) {
|
if (check_comment_range(handle, comment, info, value, doit) < 0) {
|
||||||
error("value range mismatch for control #%d",
|
cerror(doit, "value range mismatch for control #%d",
|
||||||
numid);
|
numid);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -1304,7 +1310,7 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
|
||||||
snd_ctl_elem_value_set_numid(ctl, numid1);
|
snd_ctl_elem_value_set_numid(ctl, numid1);
|
||||||
|
|
||||||
if (count == 1) {
|
if (count == 1) {
|
||||||
err = restore_config_value(handle, info, type, value, ctl, 0);
|
err = restore_config_value(handle, info, type, value, ctl, 0, doit);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
if (err > 0)
|
if (err > 0)
|
||||||
|
@ -1323,13 +1329,13 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
|
||||||
int size = type == SND_CTL_ELEM_TYPE_BYTES ?
|
int size = type == SND_CTL_ELEM_TYPE_BYTES ?
|
||||||
count : sizeof(snd_aes_iec958_t);
|
count : sizeof(snd_aes_iec958_t);
|
||||||
if (size * 2 != len) {
|
if (size * 2 != len) {
|
||||||
error("bad control.%d.value contents\n", numid);
|
cerror(doit, "bad control.%d.value contents\n", numid);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
while (*buf) {
|
while (*buf) {
|
||||||
int c = *buf++;
|
int c = *buf++;
|
||||||
if ((c = hextodigit(c)) < 0) {
|
if ((c = hextodigit(c)) < 0) {
|
||||||
error("bad control.%d.value contents\n", numid);
|
cerror(doit, "bad control.%d.value contents\n", numid);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (idx % 2 == 1)
|
if (idx % 2 == 1)
|
||||||
|
@ -1345,13 +1351,13 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (snd_config_get_type(value) != SND_CONFIG_TYPE_COMPOUND) {
|
if (snd_config_get_type(value) != SND_CONFIG_TYPE_COMPOUND) {
|
||||||
if (!force_restore) {
|
if (!force_restore || !doit) {
|
||||||
error("bad control.%d.value type", numid);
|
cerror(doit, "bad control.%d.value type", numid);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
for (idx = 0; idx < count; ++idx) {
|
for (idx = 0; idx < count; ++idx) {
|
||||||
err = restore_config_value2(handle, info, type, value,
|
err = restore_config_value2(handle, info, type, value,
|
||||||
ctl, idx, numid);
|
ctl, idx, numid, doit);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -1368,13 +1374,13 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
|
||||||
idx = atoi(id);
|
idx = atoi(id);
|
||||||
if (idx < 0 || idx >= count ||
|
if (idx < 0 || idx >= count ||
|
||||||
set[idx]) {
|
set[idx]) {
|
||||||
error("bad control.%d.value index", numid);
|
cerror(doit, "bad control.%d.value index", numid);
|
||||||
if (!force_restore)
|
if (!force_restore || !doit)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
err = restore_config_value2(handle, info, type, n,
|
err = restore_config_value2(handle, info, type, n,
|
||||||
ctl, idx, numid);
|
ctl, idx, numid, doit);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
if (err > 0)
|
if (err > 0)
|
||||||
|
@ -1382,14 +1388,14 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
|
||||||
}
|
}
|
||||||
for (idx = 0; idx < count; ++idx) {
|
for (idx = 0; idx < count; ++idx) {
|
||||||
if (!set[idx]) {
|
if (!set[idx]) {
|
||||||
error("control.%d.value.%d is not specified", numid, idx);
|
cerror(doit, "control.%d.value.%d is not specified", numid, idx);
|
||||||
if (!force_restore)
|
if (!force_restore || !doit)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_ok:
|
_ok:
|
||||||
err = snd_ctl_elem_write(handle, ctl);
|
err = doit ? snd_ctl_elem_write(handle, ctl) : 0;
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
error("Cannot write control '%d:%ld:%ld:%s:%ld' : %s", (int)iface, device, subdevice, name, index, snd_strerror(err));
|
error("Cannot write control '%d:%ld:%ld:%s:%ld' : %s", (int)iface, device, subdevice, name, index, snd_strerror(err));
|
||||||
return err;
|
return err;
|
||||||
|
@ -1397,13 +1403,13 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int set_controls(int card, snd_config_t *top)
|
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_config_t *control;
|
snd_config_t *control;
|
||||||
snd_config_iterator_t i, next;
|
snd_config_iterator_t i, next;
|
||||||
int err;
|
int err, maxnumid;
|
||||||
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);
|
||||||
|
@ -1435,16 +1441,32 @@ static int set_controls(int card, snd_config_t *top)
|
||||||
id = tmpid;
|
id = tmpid;
|
||||||
}
|
}
|
||||||
if (snd_config_get_type(control) != SND_CONFIG_TYPE_COMPOUND) {
|
if (snd_config_get_type(control) != SND_CONFIG_TYPE_COMPOUND) {
|
||||||
error("state.%s.control is not a compound\n", id);
|
cerror(doit, "state.%s.control is not a compound\n", id);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
snd_config_for_each(i, next, control) {
|
snd_config_for_each(i, next, control) {
|
||||||
snd_config_t *n = snd_config_iterator_entry(i);
|
snd_config_t *n = snd_config_iterator_entry(i);
|
||||||
err = set_control(handle, n);
|
err = set_control(handle, n, &maxnumid, doit);
|
||||||
if (err < 0 && ! force_restore)
|
if (err < 0 && (!force_restore || !doit))
|
||||||
goto _close;
|
goto _close;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check if we have additional controls in driver */
|
||||||
|
/* in this case we should go through init procedure */
|
||||||
|
if (!doit) {
|
||||||
|
snd_ctl_elem_id_t *id;
|
||||||
|
snd_ctl_elem_info_t *info;
|
||||||
|
snd_ctl_elem_id_alloca(&id);
|
||||||
|
snd_ctl_elem_info_alloca(&info);
|
||||||
|
snd_ctl_elem_info_set_numid(info, maxnumid+1);
|
||||||
|
if (snd_ctl_elem_info(handle, info) == 0) {
|
||||||
|
/* not very informative */
|
||||||
|
/* but value is used for check only */
|
||||||
|
err = -EAGAIN;
|
||||||
|
goto _close;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_close:
|
_close:
|
||||||
snd_ctl_close(handle);
|
snd_ctl_close(handle);
|
||||||
return err;
|
return err;
|
||||||
|
@ -1522,9 +1544,9 @@ int save_state(const char *file, const char *cardname)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int load_state(const char *file, const char *cardname)
|
int load_state(const char *file, const char *initfile, const char *cardname)
|
||||||
{
|
{
|
||||||
int err;
|
int err, finalerr = 0;
|
||||||
snd_config_t *config;
|
snd_config_t *config;
|
||||||
snd_input_t *in;
|
snd_input_t *in;
|
||||||
int stdio;
|
int stdio;
|
||||||
|
@ -1547,12 +1569,35 @@ int load_state(const char *file, const char *cardname)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
int card, first = 1;
|
||||||
|
char cardname1[16];
|
||||||
|
|
||||||
error("Cannot open %s for reading: %s", file, snd_strerror(err));
|
error("Cannot open %s for reading: %s", file, snd_strerror(err));
|
||||||
return err;
|
finalerr = err;
|
||||||
|
card = -1;
|
||||||
|
/* find each installed soundcards */
|
||||||
|
while (1) {
|
||||||
|
if (snd_card_next(&card) < 0)
|
||||||
|
break;
|
||||||
|
if (card < 0)
|
||||||
|
break;
|
||||||
|
first = 0;
|
||||||
|
sprintf(cardname1, "%i", card);
|
||||||
|
err = init(initfile, cardname1);
|
||||||
|
if (err < 0) {
|
||||||
|
finalerr = err;
|
||||||
|
initfailed(card, "init");
|
||||||
|
}
|
||||||
|
initfailed(card, "restore");
|
||||||
|
}
|
||||||
|
if (!first)
|
||||||
|
finalerr = 0; /* no cards, no error code */
|
||||||
|
return finalerr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cardname) {
|
if (!cardname) {
|
||||||
int card, first = 1;
|
int card, first = 1;
|
||||||
|
char cardname1[16];
|
||||||
|
|
||||||
card = -1;
|
card = -1;
|
||||||
/* find each installed soundcards */
|
/* find each installed soundcards */
|
||||||
|
@ -1567,8 +1612,20 @@ int load_state(const char *file, const char *cardname)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
first = 0;
|
first = 0;
|
||||||
if ((err = set_controls(card, config)) && ! force_restore)
|
/* do a check if controls matches state file */
|
||||||
return err;
|
if (set_controls(card, config, 0)) {
|
||||||
|
sprintf(cardname1, "%i", card);
|
||||||
|
err = init(initfile, cardname1);
|
||||||
|
if (err < 0) {
|
||||||
|
initfailed(card, "init");
|
||||||
|
finalerr = err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((err = set_controls(card, config, 1))) {
|
||||||
|
if (!force_restore)
|
||||||
|
finalerr = err;
|
||||||
|
initfailed(card, "restore");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int cardno;
|
int cardno;
|
||||||
|
@ -1578,9 +1635,19 @@ int load_state(const char *file, const char *cardname)
|
||||||
error("Cannot find soundcard '%s'...", cardname);
|
error("Cannot find soundcard '%s'...", cardname);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
if ((err = set_controls(cardno, config)) && ! force_restore) {
|
/* do a check if controls matches state file */
|
||||||
return err;
|
if (set_controls(cardno, config, 0)) {
|
||||||
|
err = init(initfile, cardname);
|
||||||
|
if (err < 0) {
|
||||||
|
initfailed(cardno, "init");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((err = set_controls(cardno, config, 1))) {
|
||||||
|
initfailed(cardno, "restore");
|
||||||
|
if (!force_restore)
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return finalerr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#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)
|
||||||
|
@ -77,3 +78,21 @@ size_t line_width(const char *buf, size_t bufsize, size_t pos)
|
||||||
|
|
||||||
return count - pos;
|
return count - pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void initfailed(int cardnumber, const char *reason)
|
||||||
|
{
|
||||||
|
int fp;
|
||||||
|
char *str;
|
||||||
|
|
||||||
|
if (statefile == NULL)
|
||||||
|
return;
|
||||||
|
if (snd_card_get_name(cardnumber, &str) < 0)
|
||||||
|
return;
|
||||||
|
fp = open(statefile, O_WRONLY|O_CREAT|O_APPEND, 0644);
|
||||||
|
write(fp, str, strlen(str));
|
||||||
|
write(fp, ":", 1);
|
||||||
|
write(fp, reason, strlen(reason));
|
||||||
|
write(fp, "\n", 1);
|
||||||
|
close(fp);
|
||||||
|
free(str);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue