diff mbox series

[alsa-lib,RFC] ucm: reset config id of condition items

Message ID 1587607135-20106-1-git-send-email-libin.yang@linux.intel.com
State New
Headers show
Series [alsa-lib,RFC] ucm: reset config id of condition items | expand

Commit Message

libin.yang@linux.intel.com April 23, 2020, 1:58 a.m. UTC
From: Libin Yang <libin.yang@intel.com>

UCMv2 supports "If" statement and will merge the same items with
compound_merge(). If the items have the same id, it will fail to
add the config items. And the id of the item in an array is
automatically generated with the increased number. It is probably
that some items to be merged have the same id. Let's add prefix
in the id to avoid such situation.

For example:

If.seq1 {
	Condition {
		Type ControlExists
		Control "name='PGA1.0 1 Master Playback Volume'"
	}
	True {
		EnableSequence [
			cset "name='PGA1.0 1 Master Playback Volume' 50"
		]
	}
}

If.seq2 {
	Condition {
		Type ControlExists
		Control "name='PGA2.0 2 Master Playback Volume'"
	}
	True {
		EnableSequence [
			cset "name='PGA2.0 2 Master Playback Volume' 50"
		]
	}
}

If.seq3 {
	Condition {
		Type ControlExists
		Control "name='PGA3.0 3 Master Playback Volume'"
	}
	True {
		EnableSequence [
			cset "name='PGA3.0 3 Master Playback Volume' 50"
		]
	}
}

If seq1, seq2 and seq3 conditions are true, UCM will fail to initialize.

This patch rename the config id to avoid the same id conflict.

Signed-off-by: Libin Yang <libin.yang@intel.com>
---
 include/conf.h     |  2 +-
 src/conf.c         | 21 +++++++++++++++++++++
 src/ucm/ucm_cond.c | 28 ++++++++++++++++++++++++----
 3 files changed, 46 insertions(+), 5 deletions(-)
diff mbox series

Patch

diff --git a/include/conf.h b/include/conf.h
index 456b272..adb3d84 100644
--- a/include/conf.h
+++ b/include/conf.h
@@ -139,7 +139,7 @@  int snd_config_imake_safe_string(snd_config_t **config, const char *key, const c
 int snd_config_imake_pointer(snd_config_t **config, const char *key, const void *ptr);
 
 snd_config_type_t snd_config_get_type(const snd_config_t *config);
-
+int snd_config_of_array(const snd_config_t *config);
 int snd_config_set_id(snd_config_t *config, const char *id);
 int snd_config_set_integer(snd_config_t *config, long value);
 int snd_config_set_integer64(snd_config_t *config, long long value);
diff --git a/src/conf.c b/src/conf.c
index 50d0403..43d565b 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -435,6 +435,8 @@  struct _snd_config {
 	char *id;
 	snd_config_type_t type;
 	int refcount; /* default = 0 */
+	/* member of an array */
+	int of_array;
 	union {
 		long integer;
 		long long integer64;
@@ -1123,6 +1125,7 @@  static int _snd_config_make(snd_config_t **config, char **id, snd_config_type_t
 		*id = NULL;
 	}
 	n->type = type;
+	n->of_array = 0;
 	if (type == SND_CONFIG_TYPE_COMPOUND)
 		INIT_LIST_HEAD(&n->u.compound.fields);
 	*config = n;
@@ -1316,6 +1319,8 @@  static int parse_array_def(snd_config_t *parent, input_t *input, int *idx, int s
 	default:
 		unget_char(c, input);
 		err = parse_value(&n, parent, input, &id, skip);
+		/* this is a member of an array */
+		n->of_array = 1;
 		if (err < 0)
 			goto __end;
 		break;
@@ -1784,6 +1789,22 @@  snd_config_type_t snd_config_get_type(const snd_config_t *config)
 }
 
 /**
+ * \brief Returns the of_array of a configuration node.
+ * \param config Handle to the configuration node.
+ * \return of_array of the node
+ *
+ * The returned value indicates whether the node is a member of an array.
+ *
+ * \par Conforming to:
+ * LSB 3.2
+ */
+int snd_config_of_array(const snd_config_t *config)
+{
+	assert(config);
+	return config->of_array;
+}
+
+/**
  * \brief Returns the id of a configuration node.
  * \param[in] config Handle to the configuration node.
  * \param[out] id The function puts the pointer to the id string at the
diff --git a/src/ucm/ucm_cond.c b/src/ucm/ucm_cond.c
index 22b418d..725a69e 100644
--- a/src/ucm/ucm_cond.c
+++ b/src/ucm/ucm_cond.c
@@ -347,14 +347,15 @@  static void config_dump(snd_config_t *cfg)
 }
 #endif
 
-static int compound_merge(const char *id,
+static int compound_merge(const char *id, const char *cname,
 			  snd_config_t *dst, snd_config_t *src,
 			  snd_config_t *before, snd_config_t *after)
 {
 	snd_config_iterator_t i, next;
 	snd_config_t *n, *_before = NULL, *_after = NULL;
 	const char *s;
-	int err;
+	char s1[32];
+	int err, cnt;
 
 	if (snd_config_get_type(src) != SND_CONFIG_TYPE_COMPOUND) {
 		uc_error("compound type expected for If True/False block");
@@ -387,8 +388,22 @@  static int compound_merge(const char *id,
 		return -EINVAL;
 	}
 
+	cnt = 0;
 	snd_config_for_each(i, next, src) {
 		n = snd_config_iterator_entry(i);
+		/*
+		 * If n is an array member, n->id is automatically generated.
+		 * It is prossible that n->id is used by other array member,
+		 * which will be merged with this one. So let's add prefix
+		 * to the id to avoid the conflict.
+		 */
+		if (snd_config_of_array(n)) {
+			err = snd_config_get_id(n, &s);
+			if (err < 0)
+				return err; /* FIXME: this will never happen */
+			snprintf(s1, sizeof(s1), "%s-%d-%s", cname, cnt++, s);
+			snd_config_set_id(n, (const char *)s1);
+		}
 		err = snd_config_remove(n);
 		if (err < 0)
 			return err;
@@ -422,7 +437,7 @@  int uc_mgr_evaluate_condition(snd_use_case_mgr_t *uc_mgr,
 {
 	snd_config_iterator_t i, i2, next, next2;
 	snd_config_t *a, *n, *n2, *parent2, *before, *after;
-	const char *id;
+	const char *id, *cname;
 	int err;
 
 	if (uc_mgr->conf_format < 2) {
@@ -437,6 +452,10 @@  int uc_mgr_evaluate_condition(snd_use_case_mgr_t *uc_mgr,
 
 	snd_config_for_each(i, next, cond) {
 		n = snd_config_iterator_entry(i);
+		err = snd_config_get_id(n, &cname);
+		if (err < 0)
+			return err; /* FIXME: this will never happen */
+
 		before = after = NULL;
 		err = if_eval_one(uc_mgr, n, &a, &before, &after);
 		if (err < 0)
@@ -469,7 +488,8 @@  __add:
 				err = snd_config_search(parent, id, &parent2);
 				if (err == -ENOENT)
 					goto __add;
-				err = compound_merge(id, parent2, n2, before, after);
+				err = compound_merge(id, cname, parent2, n2,
+						     before, after);
 				if (err < 0)
 					return err;
 			}