OSDN Git Service

UCM: get: Implement 'exact' value retrieval
authorStephen Warren <swarren@nvidia.com>
Mon, 6 Jun 2011 20:16:57 +0000 (14:16 -0600)
committerTakashi Iwai <tiwai@suse.de>
Wed, 8 Jun 2011 16:22:15 +0000 (18:22 +0200)
[=]<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>
include/use-case.h
src/ucm/main.c

index b346877..c37c842 100644 (file)
@@ -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
index 13ea1ed..8e9a85d 100644 (file)
@@ -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);