summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaroslav Kysela <perex@perex.cz>2021-05-14 12:20:18 +0200
committerJaroslav Kysela <perex@perex.cz>2021-05-17 16:49:46 +0200
commit5e7c507152f71ea1323c6583849528b370441cfc (patch)
treee954acca5458f114d18947e904ca10881b435a81
parentf821f097271b9b31a706e606dca33e7dca51ad5c (diff)
downloadalsa-lib-5e7c507152f71ea1323c6583849528b370441cfc.tar.gz
ucm: add cfg-save command
Allow to save whole (or partial) local UCM alsa library configuration to a file. Syntax (saves key1.key2 sub-tree): Sequence [ cfg-save "/tmp/my-file.conf:key1.key2" ] Signed-off-by: Jaroslav Kysela <perex@perex.cz>
-rw-r--r--src/ucm/main.c41
-rw-r--r--src/ucm/parser.c10
-rw-r--r--src/ucm/ucm_local.h2
-rw-r--r--src/ucm/utils.c3
4 files changed, 56 insertions, 0 deletions
diff --git a/src/ucm/main.c b/src/ucm/main.c
index f50ccff5..b1536ac3 100644
--- a/src/ucm/main.c
+++ b/src/ucm/main.c
@@ -573,6 +573,42 @@ static int execute_sysw(const char *sysw)
return 0;
}
+static int execute_cfgsave(snd_use_case_mgr_t *uc_mgr, const char *filename)
+{
+ snd_config_t *config = uc_mgr->local_config;
+ char *file, *root;
+ snd_output_t *out;
+ int err = 0;
+
+ file = strdup(filename);
+ if (!file)
+ return -ENOMEM;
+ root = strchr(file, ':');
+ if (root) {
+ *root = '\0';
+ err = snd_config_search(config, root + 1, &config);
+ if (err < 0) {
+ uc_error("Unable to find subtree '%s'", root);
+ goto _err;
+ }
+ }
+
+ err = snd_output_stdio_open(&out, file, "w+");
+ if (err < 0) {
+ uc_error("unable to open file '%s': %s", file, snd_strerror(err));
+ goto _err;
+ }
+ err = snd_config_save(config, out);
+ snd_output_close(out);
+ if (err < 0) {
+ uc_error("unable to save configuration: %s", snd_strerror(err));
+ goto _err;
+ }
+_err:
+ free(file);
+ return err;
+}
+
static int rewrite_device_value(snd_use_case_mgr_t *uc_mgr, const char *name, char **value)
{
char *sval;
@@ -754,6 +790,11 @@ shell_retry:
if (err < 0)
goto __fail;
break;
+ case SEQUENCE_ELEMENT_TYPE_CFGSAVE:
+ err = execute_cfgsave(uc_mgr, s->data.cfgsave);
+ if (err < 0)
+ goto __fail;
+ break;
default:
uc_error("unknown sequence command %i", s->type);
break;
diff --git a/src/ucm/parser.c b/src/ucm/parser.c
index 2a425da6..68b0ee62 100644
--- a/src/ucm/parser.c
+++ b/src/ucm/parser.c
@@ -924,6 +924,16 @@ exec:
goto exec;
}
+ if (strcmp(cmd, "cfg-save") == 0) {
+ curr->type = SEQUENCE_ELEMENT_TYPE_CFGSAVE;
+ err = parse_string_substitute3(uc_mgr, n, &curr->data.cfgsave);
+ if (err < 0) {
+ uc_error("error: sysw requires a string!");
+ return err;
+ }
+ continue;
+ }
+
if (strcmp(cmd, "comment") == 0)
goto skip;
diff --git a/src/ucm/ucm_local.h b/src/ucm/ucm_local.h
index c0374148..8eb1fc7a 100644
--- a/src/ucm/ucm_local.h
+++ b/src/ucm/ucm_local.h
@@ -56,6 +56,7 @@
#define SEQUENCE_ELEMENT_TYPE_CTL_REMOVE 9
#define SEQUENCE_ELEMENT_TYPE_CMPT_SEQ 10
#define SEQUENCE_ELEMENT_TYPE_SYSSET 11
+#define SEQUENCE_ELEMENT_TYPE_CFGSAVE 12
struct ucm_value {
struct list_head list;
@@ -78,6 +79,7 @@ struct sequence_element {
char *cset;
char *exec;
char *sysw;
+ char *cfgsave;
struct component_sequence cmpt_seq; /* component sequence */
} data;
};
diff --git a/src/ucm/utils.c b/src/ucm/utils.c
index 0eaf6c3c..f3a8c9ba 100644
--- a/src/ucm/utils.c
+++ b/src/ucm/utils.c
@@ -512,6 +512,9 @@ void uc_mgr_free_sequence_element(struct sequence_element *seq)
case SEQUENCE_ELEMENT_TYPE_SHELL:
free(seq->data.exec);
break;
+ case SEQUENCE_ELEMENT_TYPE_CFGSAVE:
+ free(seq->data.cfgsave);
+ break;
default:
break;
}