diff --git a/alsactl/alsactl_init.xml b/alsactl/alsactl_init.xml
index c902fc8..0e0d46b 100644
--- a/alsactl/alsactl_init.xml
+++ b/alsactl/alsactl_init.xml
@@ -257,6 +257,12 @@
Enumerated value - number of text items
+
+
+
+ Enumerated value - list of text names stored between '|' character
+
+
@@ -394,6 +400,16 @@
next key on line).
+
+
+
+ Value is set (written) also to soundcard's control
+ device (all control values are set to specified value) and
+ RESULT key is set to errno code. The result of
+ set operation is always true (it means continue with
+ next key on line).
+
+
diff --git a/alsactl/init/00main b/alsactl/init/00main
index 3d289cb..942f386 100644
--- a/alsactl/init/00main
+++ b/alsactl/init/00main
@@ -7,6 +7,7 @@ CONFIG{sysfs_device}="/class/sound/controlC$cardinfo{card}/device"
# test for extra commands
ENV{CMD}=="help", INCLUDE="help", GOTO="00main_end"
ENV{CMD}=="info", INCLUDE="info", GOTO="00main_end"
+ENV{CMD}=="default", INCLUDE="default", GOTO="00main_end"
ENV{CMD}=="test", INCLUDE="test", GOTO="00main_end"
ENV{CMD}=="*", ERROR="Unknown command '$env{CMD}'\n", GOTO="00main_end"
@@ -17,7 +18,8 @@ ENV{CMD}=="*", ERROR="Unknown command '$env{CMD}'\n", GOTO="00main_end"
# 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
+# 5) if RESULT!="true", initialize hardware using a guess method,
+# print an error message and return with exit code 99
# 6) return with exit code 0 (success)
#
@@ -33,7 +35,8 @@ 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"
+ERROR="Hardware is initialized using a guess method\n"
+INCLUDE="default"
EXIT="99"
#
diff --git a/alsactl/init/default b/alsactl/init/default
new file mode 100644
index 0000000..66692b3
--- /dev/null
+++ b/alsactl/init/default
@@ -0,0 +1,145 @@
+#
+# Default ALSA volume levels and setting when initialization database fails.
+#
+# Basic rules are:
+# - keep volumes at minimal level, but sound should be hearable
+# - enable just main speakers for playback and main microphone for recording
+#
+
+# **************************************************************************
+# playback
+# **************************************************************************
+
+ENV{volume}:="-20dB"
+
+CTL{reset}="mixer"
+CTL{name}="Playback Volume",PROGRAM=="__ctl_search", \
+ CTL{values}="$env{volume}",RESULT!="0",CTL{values}="75%"
+CTL{name}="Playback Switch",PROGRAM=="__ctl_search", \
+ CTL{values}="on"
+
+CTL{reset}="mixer"
+CTL{name}="Master Playback Volume",PROGRAM=="__ctl_search", \
+ CTL{values}="$env{volume}",RESULT!="0",CTL{values}="75%"
+CTL{name}="Master Playback Switch",PROGRAM=="__ctl_search", \
+ CTL{values}="on"
+
+CTL{reset}="mixer"
+CTL{name}="Master Digital Playback Volume",PROGRAM=="__ctl_search", \
+ CTL{values}="$env{volume}",RESULT!="0",CTL{values}="75%"
+CTL{name}="Master Digital Playback Switch",PROGRAM=="__ctl_search", \
+ CTL{values}="on"
+
+CTL{reset}="mixer"
+CTL{name}="Front Playback Volume",PROGRAM=="__ctl_search", \
+ CTL{values}="$env{volume}",RESULT!="0",CTL{values}="75%"
+CTL{name}="Front Playback Switch",PROGRAM=="__ctl_search", \
+ CTL{values}="on"
+
+CTL{reset}="mixer"
+CTL{name}="Headphone Playback Volume",PROGRAM=="__ctl_search", \
+ CTL{values}="$env{volume}",RESULT!="0",CTL{values}="75%"
+CTL{name}="Headphone Playback Switch",PROGRAM=="__ctl_search", \
+ CTL{values}="on"
+
+CTL{reset}="mixer"
+CTL{name}="Speaker Playback Volume",PROGRAM=="__ctl_search", \
+ CTL{values}="$env{volume}",RESULT!="0",CTL{values}="75%"
+CTL{name}="Speaker Playback Switch",PROGRAM=="__ctl_search", \
+ CTL{values}="on"
+
+CTL{reset}="mixer"
+CTL{name}="PC Speaker Playback Volume",PROGRAM=="__ctl_search", \
+ CTL{values}="$env{volume}",RESULT!="0",CTL{values}="75%"
+CTL{name}="PC Speaker Playback Switch",PROGRAM=="__ctl_search", \
+ CTL{values}="on"
+
+CTL{reset}="mixer"
+CTL{name}="PCM Playback Volume",PROGRAM=="__ctl_search", \
+ CTL{values}="$env{volume}",RESULT!="0",CTL{values}="75%"
+CTL{name}="PCM Playback Switch",PROGRAM=="__ctl_search", \
+ CTL{values}="on"
+
+CTL{reset}="mixer"
+CTL{name}="PCM Playback Volume",CTL{index}="1",PROGRAM=="__ctl_search", \
+ CTL{values}="$env{volume}",RESULT!="0",CTL{values}="75%"
+CTL{name}="PCM Playback Switch",CTL{index}="1",PROGRAM=="__ctl_search", \
+ CTL{values}="on"
+
+CTL{reset}="mixer"
+CTL{name}="DAC Playback Volume",PROGRAM=="__ctl_search", \
+ CTL{values}="$env{volume}",RESULT!="0",CTL{values}="75%"
+CTL{name}="DAC Playback Switch",PROGRAM=="__ctl_search", \
+ CTL{values}="on"
+
+CTL{reset}="mixer"
+CTL{name}="Synth Playback Volume",,PROGRAM=="__ctl_search", \
+ CTL{values}="$env{volume}",RESULT!="0",CTL{values}="75%"
+CTL{name}="Synth Playback Switch",PROGRAM=="__ctl_search", \
+ CTL{values}="on"
+
+CTL{reset}="mixer"
+CTL{name}="Wave Playback Volume",PROGRAM=="__ctl_search", \
+ CTL{values}="100%"
+CTL{name}="Wave Playback Switch",PROGRAM=="__ctl_search", \
+ CTL{values}="on"
+
+CTL{reset}="mixer"
+CTL{name}="Music Playback Volume",PROGRAM=="__ctl_search", \
+ CTL{values}="100%"
+CTL{name}="Music Playback Switch",PROGRAM=="__ctl_search", \
+ CTL{values}="on"
+
+CTL{reset}="mixer"
+CTL{name}="CD Playback Volume",PROGRAM=="__ctl_search", \
+ CTL{values}="$env{volume}",RESULT!="0",CTL{values}="75%"
+CTL{name}="CD Playback Switch",PROGRAM=="__ctl_search", \
+ CTL{values}="on"
+
+CTL{reset}="mixer"
+CTL{name}="Mono Playback Volume",PROGRAM=="__ctl_search", \
+ CTL{values}="$env{volume}",RESULT!="0",CTL{values}="75%"
+CTL{name}="Mono Playback Switch",PROGRAM=="__ctl_search", \
+ CTL{values}="on"
+
+CTL{reset}="mixer"
+CTL{name}="Master Mono Playback Volume",PROGRAM=="__ctl_search", \
+ CTL{values}="$env{volume}",RESULT!="0",CTL{values}="75%"
+CTL{name}="Master Mono Playback Switch",PROGRAM=="__ctl_search", \
+ CTL{values}="on"
+
+CTL{reset}="mixer"
+CTL{name}="AC97 Playback Volume",PROGRAM=="__ctl_search", \
+ CTL{values}="100%"
+CTL{name}="AC97 Playback Switch",PROGRAM=="__ctl_search", \
+ CTL{values}="on"
+
+#
+# Powermacs
+#
+
+CTL{reset}="mixer"
+CTL{name}="DRC Range",PROGRAM=="__ctl_search", \
+ CTL{values}="$env{volume}",RESULT!="0",CTL{values}="75%"
+
+# **************************************************************************
+# capture
+# **************************************************************************
+
+ENV{volume}:="20dB"
+
+CTL{reset}="mixer"
+CTL{name}="Capture Volume",PROGRAM=="__ctl_search", \
+ CTL{values}="$env{volume}",RESULT!="0",CTL{values}="75%"
+CTL{name}="Capture Switch",PROGRAM=="__ctl_search", \
+ CTL{values}="on"
+
+CTL{name}="Input Source",PROGRAM=="__ctl_search", \
+ CTL{enums}=="*|Internal Mic|*",CTL{values}="Internal Mic", \
+ GOTO="end_input_source"
+CTL{name}="Input Source",PROGRAM=="__ctl_search", \
+ CTL{enums}=="*|Mic|*",CTL{values}="Mic"
+LABEL="end_input_source"
+
+CTL{name}="Internal Mic Boost",PROGRAM=="__ctl_search", \
+ CTL{values}="on"
diff --git a/alsactl/init/test b/alsactl/init/test
index 024787d..26db2a3 100644
--- a/alsactl/init/test
+++ b/alsactl/init/test
@@ -58,7 +58,6 @@ PRINT=" CTL{device}=\"$ctl{device}\"\n"
PRINT=" CTL{subdevice}=\"$ctl{subdevice}\"\n"
PRINT=" CTL{name}=\"$ctl{name}\"\n"
PRINT=" CTL{index}=\"$ctl{index}\"\n"
-LABEL="skip_switch_search"
PRINT="First ten elements:\n"
CTL{search}="mixer", CTL{name}="*", PROGRAM!="__ctl_search 0", GOTO="skip_first_ten_search"
@@ -118,7 +117,6 @@ PRINT=" CTL{dBmin}=\"$ctl{dBmin}\"\n"
PRINT=" CTL{dBmax}=\"$ctl{dBmax}\"\n"
PRINT=" CTL{items}=\"$ctl{items}\"\n"
PRINT=" CTL{value}=\"$ctl{value}\"\n"
-LABEL="skip_first_ten_search"
CTL{search}="mixer", CTL{name}="*", PROGRAM!="__ctl_search 3", GOTO="skip_first_ten_search"
PRINT=" Element #3:\n"
PRINT=" CTL{numid}=\"$ctl{numid}\"\n"
@@ -138,7 +136,6 @@ PRINT=" CTL{dBmax}=\"$ctl{dBmax}\"\n"
PRINT=" CTL{step}=\"$ctl{step}\"\n"
PRINT=" CTL{items}=\"$ctl{items}\"\n"
PRINT=" CTL{value}=\"$ctl{value}\"\n"
-LABEL="skip_first_ten_search"
CTL{search}="mixer", CTL{name}="*", PROGRAM!="__ctl_search 4", GOTO="skip_first_ten_search"
PRINT=" Element #4:\n"
PRINT=" CTL{numid}=\"$ctl{numid}\"\n"
@@ -158,7 +155,6 @@ PRINT=" CTL{dBmin}=\"$ctl{dBmin}\"\n"
PRINT=" CTL{dBmax}=\"$ctl{dBmax}\"\n"
PRINT=" CTL{items}=\"$ctl{items}\"\n"
PRINT=" CTL{value}=\"$ctl{value}\"\n"
-LABEL="skip_first_ten_search"
CTL{search}="mixer", CTL{name}="*", PROGRAM!="__ctl_search 5", GOTO="skip_first_ten_search"
PRINT=" Element #5:\n"
PRINT=" CTL{numid}=\"$ctl{numid}\"\n"
@@ -178,7 +174,6 @@ PRINT=" CTL{dBmin}=\"$ctl{dBmin}\"\n"
PRINT=" CTL{dBmax}=\"$ctl{dBmax}\"\n"
PRINT=" CTL{items}=\"$ctl{items}\"\n"
PRINT=" CTL{value}=\"$ctl{value}\"\n"
-LABEL="skip_first_ten_search"
CTL{search}="mixer", CTL{name}="*", PROGRAM!="__ctl_search 6", GOTO="skip_first_ten_search"
PRINT=" Element #6:\n"
PRINT=" CTL{numid}=\"$ctl{numid}\"\n"
@@ -198,7 +193,6 @@ PRINT=" CTL{dBmin}=\"$ctl{dBmin}\"\n"
PRINT=" CTL{dBmax}=\"$ctl{dBmax}\"\n"
PRINT=" CTL{items}=\"$ctl{items}\"\n"
PRINT=" CTL{value}=\"$ctl{value}\"\n"
-LABEL="skip_first_ten_search"
CTL{search}="mixer", CTL{name}="*", PROGRAM!="__ctl_search 7", GOTO="skip_first_ten_search"
PRINT=" Element #7:\n"
PRINT=" CTL{numid}=\"$ctl{numid}\"\n"
@@ -218,7 +212,6 @@ PRINT=" CTL{dBmin}=\"$ctl{dBmin}\"\n"
PRINT=" CTL{dBmax}=\"$ctl{dBmax}\"\n"
PRINT=" CTL{items}=\"$ctl{items}\"\n"
PRINT=" CTL{value}=\"$ctl{value}\"\n"
-LABEL="skip_first_ten_search"
CTL{search}="mixer", CTL{name}="*", PROGRAM!="__ctl_search 8", GOTO="skip_first_ten_search"
PRINT=" Element #8:\n"
PRINT=" CTL{numid}=\"$ctl{numid}\"\n"
@@ -238,7 +231,6 @@ PRINT=" CTL{dBmin}=\"$ctl{dBmin}\"\n"
PRINT=" CTL{dBmax}=\"$ctl{dBmax}\"\n"
PRINT=" CTL{items}=\"$ctl{items}\"\n"
PRINT=" CTL{value}=\"$ctl{value}\"\n"
-LABEL="skip_first_ten_search"
CTL{search}="mixer", CTL{name}="*", PROGRAM!="__ctl_search 9", GOTO="skip_first_ten_search"
PRINT=" Element #9:\n"
PRINT=" CTL{numid}=\"$ctl{numid}\"\n"
@@ -270,7 +262,9 @@ PRINT="Elements write test #2:\n", \
PRINT=" result=$result\n"
PRINT="Elements write test #3:\n", \
CTL{search}="mixer", CTL{name}="Front Playback Volume Error", \
- PROGRAM="__ctl_search", CTL{value}="32,32", \
- PRINT=" result=$result\n"
+ PROGRAM="__ctl_search"
+PRINT=" result=$result\n"
+
+#CTL{reset}="mixer", CTL{name}="Input Source", PRINT="***$ctl{enums}\n"
PRINT="\nAll tests done..\n"
diff --git a/alsactl/init_parse.c b/alsactl/init_parse.c
index b93cf78..57f9a92 100644
--- a/alsactl/init_parse.c
+++ b/alsactl/init_parse.c
@@ -335,7 +335,7 @@ static const char *get_ctl_value(struct space *space)
#define convert_prange1(val, min, max) \
ceil((val) * ((max) - (min)) * 0.01 + (min))
-static int set_ctl_value(struct space *space, const char *value)
+static int set_ctl_value(struct space *space, const char *value, int all)
{
snd_ctl_elem_type_t type;
unsigned int idx, idx2, count, items;
@@ -358,6 +358,8 @@ static int set_ctl_value(struct space *space, const char *value)
strncasecmp(value, "on", 2) == 0 ||
strncasecmp(value, "1", 1) == 0;
snd_ctl_elem_value_set_boolean(space->ctl_value, idx, val);
+ if (all)
+ continue;
pos = strchr(value, ',');
value = pos ? pos + 1 : value + strlen(value) - 1;
}
@@ -398,6 +400,8 @@ static int set_ctl_value(struct space *space, const char *value)
} else {
snd_ctl_elem_value_set_integer(space->ctl_value, idx, strtol(value, NULL, 0));
}
+ if (all)
+ continue;
value = pos ? pos + 1 : value + strlen(value) - 1;
}
break;
@@ -406,6 +410,8 @@ static int set_ctl_value(struct space *space, const char *value)
while (*value == ' ')
value++;
snd_ctl_elem_value_set_integer64(space->ctl_value, idx, strtoll(value, NULL, 0));
+ if (all)
+ continue;
pos = strchr(value, ',');
value = pos ? pos + 1 : value + strlen(value) - 1;
}
@@ -440,6 +446,8 @@ static int set_ctl_value(struct space *space, const char *value)
return -EINVAL;
}
}
+ if (all)
+ continue;
value = pos ? pos + 1 : value + strlen(value) - 1;
}
break;
@@ -478,7 +486,7 @@ static const char *elemid_get(struct space *space, const char *attr)
{
long long val;
snd_ctl_elem_type_t type;
- static char res[32];
+ static char res[256];
if (strncasecmp(attr, "numid", 5) == 0) {
val = snd_ctl_elem_id_get_numid(space->ctl_id);
@@ -617,6 +625,27 @@ dbvalue:
val = max;
goto dbvalue;
}
+ if (strncasecmp(attr, "enums", 5) == 0) {
+ unsigned int idx, items;
+ snd_hctl_elem_t *elem;
+ if (check_id_changed(space, 1))
+ return NULL;
+ if (snd_ctl_elem_info_get_type(space->ctl_info) != SND_CTL_ELEM_TYPE_ENUMERATED)
+ goto empty;
+ items = snd_ctl_elem_info_get_items(space->ctl_info);
+ strcpy(res, "|");
+ for (idx = 0; idx < items; idx++) {
+ snd_ctl_elem_info_set_item(space->ctl_info, idx);
+ elem = snd_hctl_find_elem(space->ctl_handle, space->ctl_id);
+ if (elem == NULL)
+ break;
+ if (snd_hctl_elem_info(elem, space->ctl_info) < 0)
+ break;
+ strlcat(res, snd_ctl_elem_info_get_item_name(space->ctl_info), sizeof(res));
+ strlcat(res, "|", sizeof(res));
+ }
+ return res;
+ }
Perror(space, "unknown ctl{} attribute '%s'", attr);
return NULL;
value:
@@ -684,13 +713,14 @@ static int elemid_set(struct space *space, const char *attr, const char *value)
fcn = snd_ctl_elem_id_set_index;
goto value;
}
- if (strncasecmp(attr, "value", 5) == 0) {
+ if (strncasecmp(attr, "values", 6) == 0 ||
+ strncasecmp(attr, "value", 5) == 0) {
err = check_id_changed(space, 1);
if (err < 0) {
Perror(space, "control element not found");
return err;
}
- err = set_ctl_value(space, value);
+ err = set_ctl_value(space, value, strncasecmp(attr, "values", 6) == 0);
if (err < 0) {
space->ctl_id_changed |= 2;
} else {
@@ -1244,7 +1274,7 @@ static int parse_line(struct space *space, char *line, size_t linesize)
err = get_key(&linepos, &key, &op, &value);
if (err < 0)
- break;
+ goto invalid;
if (strncasecmp(key, "LABEL", 5) == 0) {
if (op != KEY_OP_ASSIGN) {
@@ -1392,6 +1422,13 @@ static int parse_line(struct space *space, char *line, size_t linesize)
dbg("env: '%s' '%s'", attr, temp);
if (!do_match(key, op, value, temp))
break;
+ } else if (op == KEY_OP_ASSIGN ||
+ op == KEY_OP_ASSIGN_FINAL) {
+ strlcpy(result, value, sizeof(result));
+ apply_format(space, result, sizeof(result));
+ dbg("env set: '%s' '%s'", attr, result);
+ if (setenv(attr, result, op == KEY_OP_ASSIGN_FINAL))
+ break;
} else {
Perror(space, "invalid ENV{} operation");
goto invalid;