From 9a748178d1c9e783242f0cc794ab3efb27092f34 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 18 Aug 2008 15:01:44 +0200 Subject: [PATCH] alsactl init - CTL{values}, CTL{enums} and default "guess method" initialization Implemented CTL{values)=value to set all values at once. Implemented CTL{enums} to match against strings in enum list. Added 'default' (guess method) initialization configuration. Signed-off-by: Jaroslav Kysela --- alsactl/alsactl_init.xml | 16 +++++ alsactl/init/00main | 7 +- alsactl/init/default | 145 +++++++++++++++++++++++++++++++++++++++ alsactl/init/test | 14 ++-- alsactl/init_parse.c | 47 +++++++++++-- 5 files changed, 212 insertions(+), 17 deletions(-) create mode 100644 alsactl/init/default 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;