diff options
author | Stephen Warren <swarren@nvidia.com> | 2011-06-06 14:16:57 -0600 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-06-08 18:22:15 +0200 |
commit | e2c2262403c5639c7ff96f47a43682ff16b7ae4f (patch) | |
tree | c302f2a45f4486cee6cf9b3c012f06310a28c1a2 | |
parent | a48f67c0ed7485e10dcbf08f9006a6282ef8ab7d (diff) | |
download | alsa-lib-e2c2262403c5639c7ff96f47a43682ff16b7ae4f.tar.gz |
UCM: get: Implement 'exact' value retrieval
[=]<NAME>[/[<modifier>|</device>][/<verb>]]
- value identifier <NAME>
- Search starts at given modifier or device if any,
else at a verb
- Search starts at given verb if any,
else current verb
- Searches modifier/device, then verb, then defaults
- Specify a leading "=" to search only the exact
device/modifier/verb specified, and not search
through each object in turn.
- Examples:
"PlaybackPCM/Play Music"
"CapturePCM/SPDIF"
From ValueDefaults only:
"=Variable"
From current active verb:
"=Variable//"
From verb "Verb":
"=Variable//Verb"
From "Modifier" in current active verb:
"=Variable/Modifier/"
From "Modifier" in "Verb":
"=Variable/Modifier/Verb"
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Acked-by: Liam Girdwood <lrg@ti.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r-- | include/use-case.h | 30 | ||||
-rw-r--r-- | src/ucm/main.c | 110 |
2 files changed, 104 insertions, 36 deletions
diff --git a/include/use-case.h b/include/use-case.h index b346877b..c37c842a 100644 --- a/include/use-case.h +++ b/include/use-case.h @@ -230,12 +230,30 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr, * NULL - return current card * _verb - return current verb * - * <NAME>[/<modifier>|</device>] - * - value identifier <NAME> for - * given modifier or device - * - Examples: "PlaybackPCM/Play Music", - * "CapturePCM/SPDIF" - * + * [=]<NAME>[/[<modifier>|</device>][/<verb>]] + * - value identifier <NAME> + * - Search starts at given modifier or device if any, + * else at a verb + * - Search starts at given verb if any, + * else current verb + * - Searches modifier/device, then verb, then defaults + * - Specify a leading "=" to search only the exact + * device/modifier/verb specified, and not search + * through each object in turn. + * - Examples: + * "PlaybackPCM/Play Music" + * "CapturePCM/SPDIF" + * From ValueDefaults only: + * "=Variable" + * From current active verb: + * "=Variable//" + * From verb "Verb": + * "=Variable//Verb" + * From "Modifier" in current active verb: + * "=Variable/Modifier/" + * From "Modifier" in "Verb": + * "=Variable/Modifier/Verb" + * * Recommended names for values: * TQ - Tone Quality * PlaybackPCM - full PCM playback device name diff --git a/src/ucm/main.c b/src/ucm/main.c index 13ea1ed0..8e9a85d2 100644 --- a/src/ucm/main.c +++ b/src/ucm/main.c @@ -1174,35 +1174,60 @@ static int get_value3(const char **value, static int get_value(snd_use_case_mgr_t *uc_mgr, const char *identifier, const char **value, - const char *item) + const char *mod_dev_name, + const char *verb_name, + int exact) { + struct use_case_verb *verb; struct use_case_modifier *mod; struct use_case_device *dev; int err; - if (!uc_mgr->active_verb) - return -ENOENT; - - if (item != NULL) { - mod = find_modifier(uc_mgr, uc_mgr->active_verb, item, 0); - if (mod != NULL) { - err = get_value1(value, &mod->value_list, identifier); - if (err >= 0 || err != -ENOENT) - return err; + if (mod_dev_name || verb_name || !exact) { + if (verb_name && strlen(verb_name)) { + verb = find_verb(uc_mgr, verb_name); + } else { + verb = uc_mgr->active_verb; } - dev = find_device(uc_mgr, uc_mgr->active_verb, item, 0); - if (dev != NULL) { - err = get_value1(value, &dev->value_list, identifier); + if (verb) { + if (mod_dev_name) { + mod = find_modifier(uc_mgr, verb, + mod_dev_name, 0); + if (mod) { + err = get_value1(value, + &mod->value_list, + identifier); + if (err >= 0 || err != -ENOENT) + return err; + } + + dev = find_device(uc_mgr, verb, + mod_dev_name, 0); + if (dev) { + err = get_value1(value, + &dev->value_list, + identifier); + if (err >= 0 || err != -ENOENT) + return err; + } + + if (exact) + return -ENOENT; + } + + err = get_value1(value, &verb->value_list, identifier); if (err >= 0 || err != -ENOENT) return err; } + + if (exact) + return -ENOENT; } - err = get_value1(value, &uc_mgr->active_verb->value_list, identifier); - if (err >= 0 || err != -ENOENT) - return err; + err = get_value1(value, &uc_mgr->value_list, identifier); if (err >= 0 || err != -ENOENT) return err; + return -ENOENT; } @@ -1220,7 +1245,9 @@ int snd_use_case_get(snd_use_case_mgr_t *uc_mgr, const char *identifier, const char **value) { - char *str, *str1; + const char *slash1, *slash2, *mod_dev_after; + const char *ident, *mod_dev, *verb; + int exact = 0; int err; pthread_mutex_lock(&uc_mgr->mutex); @@ -1246,19 +1273,42 @@ int snd_use_case_get(snd_use_case_mgr_t *uc_mgr, err = -ENOENT; goto __end; } else { - str1 = strchr(identifier, '/'); - if (str1) { - str = strdup(str1 + 1); - if (str == NULL) { - err = -ENOMEM; - goto __end; - } - } else { - str = NULL; - } - err = get_value(uc_mgr, identifier, value, str); - if (str) - free(str); + if (identifier[0] == '=') { + exact = 1; + identifier++; + } + + slash1 = strchr(identifier, '/'); + if (slash1) { + ident = strndup(identifier, slash1 - identifier); + + slash2 = strchr(slash1 + 1, '/'); + if (slash2) { + mod_dev_after = slash2; + verb = slash2 + 1; + } + else { + mod_dev_after = slash1 + strlen(slash1); + verb = NULL; + } + + if (mod_dev_after == slash1 + 1) + mod_dev = NULL; + else + mod_dev = strndup(slash1 + 1, + mod_dev_after - (slash1 + 1)); + } + else { + ident = identifier; + mod_dev = NULL; + verb = NULL; + } + + err = get_value(uc_mgr, ident, value, mod_dev, verb, exact); + if (ident != identifier) + free((void *)ident); + if (mod_dev) + free((void *)mod_dev); } __end: pthread_mutex_unlock(&uc_mgr->mutex); |