]> git.alsa-project.org Git - alsa-utils.git/commitdiff
alsactl init configuration syntax changes
authorJaroslav Kysela <perex@perex.cz>
Wed, 13 Aug 2008 18:49:07 +0000 (20:49 +0200)
committerJaroslav Kysela <perex@perex.cz>
Wed, 13 Aug 2008 18:49:07 +0000 (20:49 +0200)
- change SYSFS_DEVICE to CONFIG{sysfs_device}
- INCLUDE key now handles also directories
- RESULT key can assign value now
- EXIT="return" operation returns from included file immediately

Default 00main and hda configuration files changes:

- handle preinit and postinit directories

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
alsactl/alsactl_init.xml
alsactl/init/00main
alsactl/init/hda
alsactl/init_parse.c

index d4b65fd37b749f82abe45c21abb794a9f76a04df..f0ed9a4914ae128fcd9ec420f9edf347ccc210cf 100644 (file)
             </varlistentry>
 
             <varlistentry>
-              <term><option>SYSFS_DEVICE</option></term>
+              <term><option>CONFIG{sysfs_device}</option></term>
               <listitem>
                 <para>The relative path to sysfs subsystem specifying
                 the root directory of a soundcard device. Usually,
               <listitem>
                 <para>Match sysfs attribute values of the soundcard device.
                 The relative path to sysfs tree must be defined by
-               SYSFS_DEVICE key. Trailing whitespace in the attribute
+               CONFIG{sysfs_device} key. Trailing whitespace in the attribute
                values is ignored, if the specified match value does
                not contain trailing whitespace itself. Depending on
                the type of operator, this key is also used to set
               </listitem>
             </varlistentry>
 
+            <varlistentry>
+              <term><option>RESULT</option></term>
+              <listitem>
+                <para>Set RESULT variable. Note that PROGRAM also sets
+                this variable, but setting this variable manually
+                might be useful to change code execution order (included
+                files).</para>
+              </listitem>
+            </varlistentry>
+
             <varlistentry>
               <term><option>LABEL</option></term>
               <listitem>
             </varlistentry>
 
             <varlistentry>
-              <term><option>SYSFS_DEVICE</option></term>
+              <term><option>INCLUDE</option></term>
+              <listitem>
+                <para>Include specified filename or all files in specified directory</para>
+              </listitem>
+            </varlistentry>
+
+            <varlistentry>
+              <term><option>ACCESS</option></term>
+              <listitem>
+                <para>Check if specified file or directory exists</para>
+              </listitem>
+            </varlistentry>
+
+            <varlistentry>
+              <term><option>CONFIG{sysfs_device}</option></term>
               <listitem>
                 <para>The relative path to sysfs subsystem specifying
                 the root directory of a soundcard device. Usually,
             <varlistentry>
               <term><option>EXIT</option></term>
               <listitem>
-                <para>Exit immediately and set program exit code to value (should be integer).</para>
+                <para>Exit immediately and set program exit code to value
+                (should be integer). If value is "return" string,
+                parser leaves current included file and returns to parent
+                configuration file.</para>
               </listitem>
             </varlistentry>
 
           </variablelist>
 
-          <para>The <option>PROGRAM</option>, <option>CTL{value}</option>,
+          <para>The <option>PROGRAM</option>, <option>RESULT</option>,
+          <option>CTL{value}</option>,
          <option>PRINT</option>, <option>ERROR</option>,
-         <option>EXIT</option>, <option>SYSFS_DEVICE</option>
+         <option>EXIT</option>, <option>CONFIG{}</option>
          fields support simple printf-like string substitutions.
           It allows the use of the complete environment set by earlier matching
           rules. For all other fields, substitutions are applied while the individual rule is
index daac95255d3b87a1c440d0f577c0f2910824fcad..3d289cbf33e2d5f94c93f86a20472c8c6b268d3d 100644 (file)
@@ -2,7 +2,7 @@
 # See 'man alsactl_init' for syntax.
 
 # set root device directory in sysfs for soundcard for ATTR{} command
-SYSFS_DEVICE="/class/sound/controlC$cardinfo{card}/device"
+CONFIG{sysfs_device}="/class/sound/controlC$cardinfo{card}/device"
 
 # test for extra commands
 ENV{CMD}=="help", INCLUDE="help", GOTO="00main_end"
@@ -11,6 +11,33 @@ ENV{CMD}=="test", INCLUDE="test", GOTO="00main_end"
 ENV{CMD}=="*", ERROR="Unknown command '$env{CMD}'\n", GOTO="00main_end"
 
 # include files with real configuration
-CARDINFO{driver}=="HDA-Intel", INCLUDE="hda", GOTO="00main_end"
-CARDINFO{driver}=="Test", INCLUDE="test", GOTO="00main_end"
+#
+# steps are:
+#   1) look for preinit subdirectory and parse all files in it
+#   2) if RESULT=="skip", skip ALSA standard configuration files
+#   3) do ALSA standard configuration
+#   4) look for postinit subdirectory and parse all files in it
+#   5) if RESULT!="true", print an error message and return with exit code 99
+#   6) return with exit code 0 (success)
+#
+
+RESULT="unknown"
+ACCESS=="preinit", INCLUDE="preinit"
+RESULT=="skip", GOTO="init_end"
+
+# real ALSA configuration database
+CARDINFO{driver}=="HDA-Intel", INCLUDE="hda", GOTO="init_end"
+CARDINFO{driver}=="Test", INCLUDE="test", GOTO="init_end"
+
+LABEL="init_end"
+ACCESS=="postinit", INCLUDE="postinit"
+RESULT=="true", GOTO="00_mainend"
+ERROR="Unknown hardware: \"$cardinfo{driver}\" \"$cardinfo{mixername}\" \"$cardinfo{components}\" \"$attr{subsystem_vendor}\" \"$attr{subsystem_device}\"\n"
+ERROR="Hardware is left uninitialized\n"
+EXIT="99"
+
+#
+# label identifying end of main file
+#
+
 LABEL="00main_end"
index 939641826203429a33fb8b650976cb855868c79d..9c33123f6d030b8585e37397e4912c22178998d6 100644 (file)
@@ -6,11 +6,8 @@ CARDINFO{mixername}=="Realtek ALC880", \
 CARDINFO{mixername}=="Analog Devices AD1984", \
   ATTR{subsystem_vendor}=="0x17aa", ATTR{subsystem_device}=="0x20ac", \
   GOTO="Lenovo T61"
-
-ERROR="Unknown hardware: \"$cardinfo{mixername}\" \"$cardinfo{components}\" \"$attr{subsystem_vendor}" \"$attr{subsystem_device}\"\n"
-ERROR="Hardware is left uninitialized\n"
-EXIT="99"
-
+RESULT="false", EXIT="return"
 LABEL="Acer Travelmate 8100"
 # playback
 CTL{reset}="mixer"
@@ -22,7 +19,7 @@ CTL{name}="PCM Playback Volume", CTL{value}="150,150"
 CTL{name}="Input Source", CTL{value}="0"
 CTL{name}="Capture Volume", CTL{value}="65,65"
 CTL{name}="Capture Switch", CTL{value}="on,on"
-EXIT="0"
+RESULT="true", EXIT="return"
 
 LABEL="Lenovo T61"
 # playback
@@ -34,4 +31,4 @@ CTL{name}="Input Source", CTL{value}="1"
 CTL{name}="Internal Mic Boost", CTL{value}="1"
 CTL{name}="Capture Volume", CTL{value}="45,45"
 CTL{name}="Capture Switch", CTL{value}="on,on"
-EXIT="0"
+RESULT="true", EXIT="return"
index a99362dbf688e440189e5e6099356231374ae160..96caf46bc5c93cd07fcacc4d88f4e4e697ef2857 100644 (file)
@@ -34,6 +34,8 @@
 #include <sys/un.h>
 #include <sys/wait.h>
 #include <sys/select.h>
+#include <sys/types.h>
+#include <dirent.h>
 #include <alsa/asoundlib.h>
 #include "aconfig.h"
 #include "alsactl.h"
@@ -41,6 +43,7 @@
 
 #define PATH_SIZE      512
 #define NAME_SIZE      128
+#define EJUSTRETURN    0x7fffffff
 
 enum key_op {
        KEY_OP_UNSET,
@@ -946,7 +949,7 @@ found:
                                const char *value = NULL;
                                size_t size;
 
-                               pair = value_find(space, "SYSFS_DEVICE");
+                               pair = value_find(space, "sysfs_device");
                                if (pair == NULL)
                                        break;
                                value = sysfs_attr_get_value(pair->value, attr);
@@ -1215,7 +1218,17 @@ static int parse_line(struct space *space, char *line, size_t linesize)
                        if (op == KEY_OP_MATCH || op == KEY_OP_NOMATCH) {
                                if (!do_match(key, op, value, space->program_result))
                                        break;
-                       } else {
+                       } else if (op == KEY_OP_ASSIGN) {
+                               if (space->program_result) {
+                                       free(space->program_result);
+                                       space->program_result = NULL;
+                               }
+                               strlcpy(string, value, sizeof(string));
+                               apply_format(space, string, sizeof(string));
+                               space->program_result = strdup(string);
+                               if (space->program_result == NULL)
+                                       break;
+                       } else {
                                Perror(space, "invalid RESULT operation");
                                goto invalid;
                        }
@@ -1274,7 +1287,7 @@ static int parse_line(struct space *space, char *line, size_t linesize)
                                goto invalid;
                        }
                        if (op == KEY_OP_MATCH || op == KEY_OP_NOMATCH) {
-                               pair = value_find(space, "SYSFS_DEVICE");
+                               pair = value_find(space, "sysfs_device");
                                if (pair == NULL)
                                        break;
                                dbg("sysfs_attr: '%s' '%s'", pair->value, attr);
@@ -1319,6 +1332,8 @@ static int parse_line(struct space *space, char *line, size_t linesize)
                if (strcasecmp(key, "INCLUDE") == 0) {
                        char *rootdir, *go_to;
                        const char *filename;
+                       struct dirent *dirent;
+                       DIR *dir;
                        int linenum;
                        if (op != KEY_OP_ASSIGN) {
                                Perror(space, "invalid INCLUDE operation");
@@ -1335,16 +1350,41 @@ static int parse_line(struct space *space, char *line, size_t linesize)
                        go_to = space->go_to;
                        filename = space->filename;
                        linenum = space->linenum;
-                       space->go_to = NULL;
-                       space->rootdir = new_root_dir(string);
-                       if (space->rootdir) {
-                               err = parse(space, string);
-                               free(space->rootdir);
-                       } else
-                               err = -ENOMEM;
-                       if (space->go_to) {
-                               Perror(space, "unterminated GOTO '%s'", space->go_to);
-                               free(space->go_to);
+                       dir = opendir(string);
+                       if (dir) {
+                               count = strlen(string);
+                               while ((dirent = readdir(dir)) != NULL) {
+                                       if (strcmp(dirent->d_name, ".") == 0 ||
+                                           strcmp(dirent->d_name, "..") == 0)
+                                               continue;
+                                       string[count] = '\0';
+                                       strlcat(string, "/", sizeof(string));
+                                       strlcat(string, dirent->d_name, sizeof(string));
+                                       space->go_to = NULL;
+                                       space->rootdir = new_root_dir(string);
+                                       if (space->rootdir) {
+                                               err = parse(space, string);
+                                               free(space->rootdir);
+                                       } else
+                                               err = -ENOMEM;
+                                       if (space->go_to) {
+                                               Perror(space, "unterminated GOTO '%s'", space->go_to);
+                                               free(space->go_to);
+                                       }
+                               }
+                               closedir(dir);
+                       } else {
+                               space->go_to = NULL;
+                               space->rootdir = new_root_dir(string);
+                               if (space->rootdir) {
+                                       err = parse(space, string);
+                                       free(space->rootdir);
+                               } else
+                                       err = -ENOMEM;
+                               if (space->go_to) {
+                                       Perror(space, "unterminated GOTO '%s'", space->go_to);
+                                       free(space->go_to);
+                               }
                        }
                        space->go_to = go_to;
                        space->rootdir = rootdir;
@@ -1354,31 +1394,82 @@ static int parse_line(struct space *space, char *line, size_t linesize)
                                break;
                        continue;
                }
+               if (strncasecmp(key, "ACCESS", 6) == 0) {
+                       if (op == KEY_OP_MATCH || op == KEY_OP_NOMATCH) {
+                               if (value[0] != '/') {
+                                       strlcpy(string, space->rootdir, sizeof(string));
+                                       strlcat(string, "/", sizeof(string));
+                                       strlcat(string, value, sizeof(string));
+                               } else {
+                                       strlcat(string, value, sizeof(string));
+                               }
+                               count = access(string, F_OK);
+                               dbg("access(%s) = %i", value, count);
+                               if (op == KEY_OP_MATCH && count != 0)
+                                       break;
+                               if (op == KEY_OP_NOMATCH && count == 0)
+                                       break;
+                       } else {
+                               Perror(space, "invalid ACCESS operation");
+                               goto invalid;
+                       }
+                       continue;
+               }
                if (strncasecmp(key, "PRINT", 5) == 0) {
+                       if (op != KEY_OP_ASSIGN) {
+                               Perror(space, "invalid PRINT operation");
+                               goto invalid;
+                       }
                        strlcpy(string, value, sizeof(string));
                        apply_format(space, string, sizeof(string));
                        fwrite(string, strlen(string), 1, stdout);
                        continue;
                }
                if (strncasecmp(key, "ERROR", 5) == 0) {
+                       if (op != KEY_OP_ASSIGN) {
+                               Perror(space, "invalid ERROR operation");
+                               goto invalid;
+                       }
                        strlcpy(string, value, sizeof(string));
                        apply_format(space, string, sizeof(string));
                        fwrite(string, strlen(string), 1, stderr);
                        continue;
                }
                if (strncasecmp(key, "EXIT", 4) == 0) {
+                       if (op != KEY_OP_ASSIGN) {
+                               Perror(space, "invalid EXIT operation");
+                               goto invalid;
+                       }
                        strlcpy(string, value, sizeof(string));
                        apply_format(space, string, sizeof(string));
+                       if (strcmp(string, "return") == 0)
+                               return -EJUSTRETURN;
                        space->exit_code = strtol(string, NULL, 0);
                        space->quit = 1;
                        break;
                }
-               if (strncasecmp(key, "SYSFS_DEVICE", 12) == 0) {
-                       strlcpy(string, value, sizeof(string));
-                       apply_format(space, string, sizeof(string));
-                       err = value_set(space, key, string);
-                       dbg("SYSFS_DEVICE='%s'", string);
-                       break;
+               if (strncasecmp(key, "CONFIG{", 7) == 0) {
+                       attr = get_key_attribute(space, key + 6, string, sizeof(string));
+                       if (attr == NULL) {
+                               Perror(space, "error parsing CONFIG attribute");
+                               goto invalid;
+                       }
+                       strlcpy(result, value, sizeof(result));
+                       apply_format(space, result, sizeof(result));
+                       if (op == KEY_OP_ASSIGN) {
+                               err = value_set(space, attr, result);
+                               dbg("CONFIG{%s}='%s'", attr, result);
+                               break;
+                       } else if (op == KEY_OP_MATCH || op == KEY_OP_NOMATCH) {
+                               pair = value_find(space, attr);
+                               if (pair == NULL)
+                                       break;
+                               if (!do_match(key, op, result, pair->value))
+                                       break;
+                       } else {
+                               Perror(space, "invalid CONFIG{} operation");
+                               goto invalid;
+                       }
                }
 
                Perror(space, "unknown key '%s'", key);
@@ -1460,6 +1551,10 @@ static int parse(struct space *space, const char *filename)
                dbg("read (%i) '%s'", linenum, line);
                space->linenum = linenum;
                err = parse_line(space, line, linesize);
+               if (err == -EJUSTRETURN) {
+                       err = 0;
+                       break;
+               }
                linenum += linenum_adj;
        }