diff --git a/alsactl/alsactl_init.xml b/alsactl/alsactl_init.xml index dd4239c..eefe9ef 100644 --- a/alsactl/alsactl_init.xml +++ b/alsactl/alsactl_init.xml @@ -270,6 +270,24 @@ comma (,). + + + + Search for a control. Value "1" is returned + if a control was found. The CTL{name} key might + contain match characters * and ?. An control index + might be specified as first argument starting from + zero (e.g. CTL{do_search 2}="1"). + + + + + + Search for a controls and return total count + of matched ones. The CTL{name} key might contain match + characters * and ?. + + @@ -410,6 +428,15 @@ next key on line). + + + + Value is set (written) also to soundcard's control + device (all control values are set to specified value). + The result of set operation is true when operation + succeed (it means continue with next key on line). + + @@ -439,7 +466,8 @@ - Jumps to the next LABEL with a matching name + Jumps to the next LABEL with a matching name. + The goto cannot jump backward. diff --git a/alsactl/init/default b/alsactl/init/default index dbe30ac..55fb48f 100644 --- a/alsactl/init/default +++ b/alsactl/init/default @@ -17,22 +17,22 @@ ENV{cvolume}:="12dB" ENV{has_pmaster_vol}:="false" CTL{reset}="mixer" -CTL{name}="Playback Volume",PROGRAM=="__ctl_search", \ +CTL{name}="Playback Volume",CTL{do_search}=="1", \ CTL{write}!="$env{pvolume}",CTL{values}="$env{ppercent}" -CTL{name}="Playback Switch",PROGRAM=="__ctl_search", \ +CTL{name}="Playback Switch",CTL{do_search}=="1", \ CTL{values}="on" CTL{reset}="mixer" -CTL{name}="Master Playback Volume",PROGRAM=="__ctl_search", \ +CTL{name}="Master Playback Volume",CTL{do_search}=="1", \ ENV{has_pmaster_vol}:="true", \ CTL{write}!="$env{pvolume}",CTL{values}="$env{ppercent}" -CTL{name}="Master Playback Switch",PROGRAM=="__ctl_search", \ +CTL{name}="Master Playback Switch",CTL{do_search}=="1", \ CTL{values}="on" CTL{reset}="mixer" -CTL{name}="Master Digital Playback Volume",PROGRAM=="__ctl_search", \ +CTL{name}="Master Digital Playback Volume",CTL{do_search}=="1", \ CTL{write}!="$env{pvolume}",CTL{values}="$env{ppercent}" -CTL{name}="Master Digital Playback Switch",PROGRAM=="__ctl_search", \ +CTL{name}="Master Digital Playback Switch",CTL{do_search}=="1", \ CTL{values}="on" CTL{reset}="mixer" @@ -42,7 +42,7 @@ ENV{has_pmaster_vol}=="true",CTL{write}=="0dB",GOTO="" ENV{has_pmaster_vol}=="true",CTL{write}=="100%",GOTO="" CTL{write}!="$env{pvolume}",CTL{values}="$env{ppercent}" LABEL="" -CTL{name}="Front Playback Switch",PROGRAM=="__ctl_search", \ +CTL{name}="Front Playback Switch",CTL{do_search}=="1", \ CTL{values}="on" CTL{reset}="mixer" @@ -52,7 +52,7 @@ ENV{has_pmaster_vol}=="true",CTL{write}=="0dB",GOTO="" ENV{has_pmaster_vol}=="true",CTL{write}=="100%",GOTO="" CTL{write}!="$env{pvolume}",CTL{values}="$env{ppercent}" LABEL="" -CTL{name}="Headphone Playback Switch",PROGRAM=="__ctl_search", \ +CTL{name}="Headphone Playback Switch",CTL{do_search}=="1", \ CTL{values}="on" CTL{reset}="mixer" @@ -63,7 +63,7 @@ ENV{has_pmaster_vol}=="true",CTL{write}=="0dB",GOTO="" ENV{has_pmaster_vol}=="true",CTL{write}=="100%",GOTO="" CTL{write}!="$env{pvolume}",CTL{values}="$env{ppercent}" LABEL="" -CTL{name}="Headphone Playback Switch",CTL{index}="1",PROGRAM=="__ctl_search", \ +CTL{name}="Headphone Playback Switch",CTL{index}="1",CTL{do_search}=="1", \ CTL{values}="on" CTL{reset}="mixer" @@ -73,13 +73,13 @@ ENV{has_pmaster_vol}=="true",CTL{write}=="0dB",GOTO="" ENV{has_pmaster_vol}=="true",CTL{write}=="100%",GOTO="" CTL{write}!="$env{pvolume}",CTL{values}="$env{ppercent}" LABEL="" -CTL{name}="Speaker Playback Switch",PROGRAM=="__ctl_search", \ +CTL{name}="Speaker Playback Switch",CTL{do_search}=="1", \ CTL{values}="on" CTL{reset}="mixer" -CTL{name}="PC Speaker Playback Volume",PROGRAM=="__ctl_search", \ +CTL{name}="PC Speaker Playback Volume",CTL{do_search}=="1", \ CTL{values}="$env{pvolume}",RESULT!="0",CTL{values}="$env{ppercent}" -CTL{name}="PC Speaker Playback Switch",PROGRAM=="__ctl_search", \ +CTL{name}="PC Speaker Playback Switch",CTL{do_search}=="1", \ CTL{values}="on" CTL{reset}="mixer" @@ -93,8 +93,8 @@ CTL{dBmin}=="-34.50dB",CTL{dBmax}=="12.00dB",CTL{write}=="0dB",GOTO="" CTL{dBmin}=="-30.00dB",CTL{dBmax}=="0dB",CTL{write}=="0dB",GOTO="" CTL{write}!="$env{pvolume}",CTL{values}="75%" LABEL="" -CTL{name}="PCM Playback Switch",PROGRAM=="__ctl_search", CTL{values}="on" -CTL{name}="PCM Switch",PROGRAM=="__ctl_search",CTL{values}="on" +CTL{name}="PCM Playback Switch",CTL{do_search}=="1", CTL{values}="on" +CTL{name}="PCM Switch",CTL{do_search}=="1",CTL{values}="on" CTL{reset}="mixer" CTL{name}="PCM Playback Volume",CTL{index}="1",PROGRAM!="__ctl_search", \ @@ -107,33 +107,33 @@ CTL{dBmin}=="-34.50dB",CTL{dBmax}=="12.00dB",CTL{write}=="0dB",GOTO="" CTL{dBmin}=="-30.00dB",CTL{dBmax}=="0dB",CTL{write}=="0dB",GOTO="" CTL{write}!="$env{pvolume}",CTL{values}="75%" LABEL="" -CTL{name}="PCM Playback Switch",CTL{index}="1",PROGRAM=="__ctl_search", \ +CTL{name}="PCM Playback Switch",CTL{index}="1",CTL{do_search}=="1", \ CTL{values}="on" -CTL{name}="PCM Switch",CTL{index}="1",PROGRAM=="__ctl_search", \ +CTL{name}="PCM Switch",CTL{index}="1",CTL{do_search}=="1", \ CTL{values}="on" CTL{reset}="mixer" -CTL{name}="DAC Playback Volume",PROGRAM=="__ctl_search", \ +CTL{name}="DAC Playback Volume",CTL{do_search}=="1", \ CTL{values}="$env{pvolume}",RESULT!="0",CTL{values}="$env{ppercent}" -CTL{name}="DAC Playback Switch",PROGRAM=="__ctl_search", \ +CTL{name}="DAC Playback Switch",CTL{do_search}=="1", \ CTL{values}="on" CTL{reset}="mixer" -CTL{name}="Synth Playback Volume",PROGRAM=="__ctl_search", \ +CTL{name}="Synth Playback Volume",CTL{do_search}=="1", \ CTL{values}="$env{pvolume}",RESULT!="0",CTL{values}="$env{ppercent}" -CTL{name}="Synth Playback Switch",PROGRAM=="__ctl_search", \ +CTL{name}="Synth Playback Switch",CTL{do_search}=="1", \ CTL{values}="on" CTL{reset}="mixer" -CTL{name}="Wave Playback Volume",PROGRAM=="__ctl_search", \ +CTL{name}="Wave Playback Volume",CTL{do_search}=="1", \ CTL{values}="100%" -CTL{name}="Wave Playback Switch",PROGRAM=="__ctl_search", \ +CTL{name}="Wave Playback Switch",CTL{do_search}=="1", \ CTL{values}="on" CTL{reset}="mixer" -CTL{name}="Music Playback Volume",PROGRAM=="__ctl_search", \ +CTL{name}="Music Playback Volume",CTL{do_search}=="1", \ CTL{values}="100%" -CTL{name}="Music Playback Switch",PROGRAM=="__ctl_search", \ +CTL{name}="Music Playback Switch",CTL{do_search}=="1", \ CTL{values}="on" CTL{reset}="mixer" @@ -146,25 +146,25 @@ CTL{dBmin}=="-34.50dB",CTL{dBmax}=="12.00dB",CTL{write}=="0dB",GOTO="" CTL{dBmin}=="-30.00dB",CTL{dBmax}=="0dB",CTL{write}=="0dB",GOTO="" CTL{write}!="$env{pvolume}",CTL{values}="$env{ppercent}" LABEL="" -CTL{name}="CD Playback Switch",PROGRAM=="__ctl_search", \ +CTL{name}="CD Playback Switch",CTL{do_search}=="1", \ CTL{values}="on" CTL{reset}="mixer" -CTL{name}="Mono Playback Volume",PROGRAM=="__ctl_search", \ +CTL{name}="Mono Playback Volume",CTL{do_search}=="1", \ CTL{values}="$env{pvolume}",RESULT!="0",CTL{values}="$env{ppercent}" -CTL{name}="Mono Playback Switch",PROGRAM=="__ctl_search", \ +CTL{name}="Mono Playback Switch",CTL{do_search}=="1", \ CTL{values}="on" CTL{reset}="mixer" -CTL{name}="Master Mono Playback Volume",PROGRAM=="__ctl_search", \ +CTL{name}="Master Mono Playback Volume",CTL{do_search}=="1", \ CTL{values}="$env{pvolume}",RESULT!="0",CTL{values}="$env{ppercent}" -CTL{name}="Master Mono Playback Switch",PROGRAM=="__ctl_search", \ +CTL{name}="Master Mono Playback Switch",CTL{do_search}=="1", \ CTL{values}="on" CTL{reset}="mixer" -CTL{name}="AC97 Playback Volume",PROGRAM=="__ctl_search", \ +CTL{name}="AC97 Playback Volume",CTL{do_search}=="1", \ CTL{values}="100%" -CTL{name}="AC97 Playback Switch",PROGRAM=="__ctl_search", \ +CTL{name}="AC97 Playback Switch",CTL{do_search}=="1", \ CTL{values}="on" # @@ -172,7 +172,7 @@ CTL{name}="AC97 Playback Switch",PROGRAM=="__ctl_search", \ # CTL{reset}="mixer" -CTL{name}="DRC Range",PROGRAM=="__ctl_search", \ +CTL{name}="DRC Range",CTL{do_search}=="1", \ CTL{write}!="$env{pvolume}",CTL{values}="$env{ppercent}" # ************************************************************************** @@ -180,9 +180,9 @@ CTL{name}="DRC Range",PROGRAM=="__ctl_search", \ # ************************************************************************** CTL{reset}="mixer" -CTL{name}="Capture Volume",PROGRAM=="__ctl_search", \ +CTL{name}="Capture Volume",CTL{do_search}=="1", \ CTL{write}!="$env{cvolume}",CTL{values}="$env{cpercent}" -CTL{name}="Capture Switch",PROGRAM=="__ctl_search", \ +CTL{name}="Capture Switch",CTL{do_search}=="1", \ CTL{values}="on" CTL{name}="Input Source",PROGRAM!="__ctl_search", GOTO="" @@ -191,5 +191,5 @@ CTL{enums}=="*|Internal Mic|*",CTL{values}="Internal Mic", \ CTL{enums}=="*|Mic|*",CTL{values}="Mic" LABEL="" -CTL{name}="Internal Mic Boost",PROGRAM=="__ctl_search", \ +CTL{name}="Internal Mic Boost",CTL{do_search}=="1", \ CTL{values}="on" diff --git a/alsactl/init/test b/alsactl/init/test index 26db2a3..56659f8 100644 --- a/alsactl/init/test +++ b/alsactl/init/test @@ -37,9 +37,9 @@ PRINT=" CTL{index}=\"$ctl{index}\"\n" ERROR="Ignore following error:\n " PROGRAM="__just_test" -PRINT="__ctl_count test:\n" -CTL{search}="mixer", CTL{name}="*Switch*", PROGRAM="__ctl_count", \ - PRINT=" *Switch* count result: $result\n" +PRINT="CTL{do_count} test:\n" +CTL{search}="mixer", CTL{name}="*Switch*", \ + PRINT=" *Switch* count result: $ctl{do_count}\n" PRINT="__ctl_search test:\n" CTL{search}="mixer", CTL{name}="*Switch*", PROGRAM!="__ctl_search", GOTO="skip_switch_search" @@ -60,7 +60,7 @@ PRINT=" CTL{name}=\"$ctl{name}\"\n" PRINT=" CTL{index}=\"$ctl{index}\"\n" PRINT="First ten elements:\n" -CTL{search}="mixer", CTL{name}="*", PROGRAM!="__ctl_search 0", GOTO="skip_first_ten_search" +CTL{search}="mixer", CTL{name}="*", CTL{do_search 0}!="1", GOTO="skip_first_ten_search" PRINT=" Element #0:\n" PRINT=" CTL{numid}=\"$ctl{numid}\"\n" PRINT=" CTL{iface}=\"$ctl{iface}\"\n" @@ -79,7 +79,7 @@ PRINT=" CTL{dBmin}=\"$ctl{dBmin}\"\n" PRINT=" CTL{dBmax}=\"$ctl{dBmax}\"\n" PRINT=" CTL{items}=\"$ctl{items}\"\n" PRINT=" CTL{value}=\"$ctl{value}\"\n" -CTL{search}="mixer", CTL{name}="*", PROGRAM!="__ctl_search 1", GOTO="skip_first_ten_search" +CTL{search}="mixer", CTL{name}="*", CTL{do_search 1}!="1", GOTO="skip_first_ten_search" PRINT=" Element #1:\n" PRINT=" CTL{numid}=\"$ctl{numid}\"\n" PRINT=" CTL{iface}=\"$ctl{iface}\"\n" @@ -98,7 +98,7 @@ PRINT=" CTL{dBmin}=\"$ctl{dBmin}\"\n" PRINT=" CTL{dBmax}=\"$ctl{dBmax}\"\n" PRINT=" CTL{items}=\"$ctl{items}\"\n" PRINT=" CTL{value}=\"$ctl{value}\"\n" -CTL{search}="mixer", CTL{name}="*", PROGRAM!="__ctl_search 2", GOTO="skip_first_ten_search" +CTL{search}="mixer", CTL{name}="*", CTL{do_search 2}!="1", GOTO="skip_first_ten_search" PRINT=" Element #2:\n" PRINT=" CTL{numid}=\"$ctl{numid}\"\n" PRINT=" CTL{iface}=\"$ctl{iface}\"\n" @@ -117,7 +117,7 @@ PRINT=" CTL{dBmin}=\"$ctl{dBmin}\"\n" PRINT=" CTL{dBmax}=\"$ctl{dBmax}\"\n" PRINT=" CTL{items}=\"$ctl{items}\"\n" PRINT=" CTL{value}=\"$ctl{value}\"\n" -CTL{search}="mixer", CTL{name}="*", PROGRAM!="__ctl_search 3", GOTO="skip_first_ten_search" +CTL{search}="mixer", CTL{name}="*", CTL{do_search 3}!="3", GOTO="skip_first_ten_search" PRINT=" Element #3:\n" PRINT=" CTL{numid}=\"$ctl{numid}\"\n" PRINT=" CTL{iface}=\"$ctl{iface}\"\n" @@ -136,7 +136,7 @@ PRINT=" CTL{dBmax}=\"$ctl{dBmax}\"\n" PRINT=" CTL{step}=\"$ctl{step}\"\n" PRINT=" CTL{items}=\"$ctl{items}\"\n" PRINT=" CTL{value}=\"$ctl{value}\"\n" -CTL{search}="mixer", CTL{name}="*", PROGRAM!="__ctl_search 4", GOTO="skip_first_ten_search" +CTL{search}="mixer", CTL{name}="*", CTL{do_search 4}!="1", GOTO="skip_first_ten_search" PRINT=" Element #4:\n" PRINT=" CTL{numid}=\"$ctl{numid}\"\n" PRINT=" CTL{iface}=\"$ctl{iface}\"\n" @@ -155,7 +155,7 @@ PRINT=" CTL{dBmin}=\"$ctl{dBmin}\"\n" PRINT=" CTL{dBmax}=\"$ctl{dBmax}\"\n" PRINT=" CTL{items}=\"$ctl{items}\"\n" PRINT=" CTL{value}=\"$ctl{value}\"\n" -CTL{search}="mixer", CTL{name}="*", PROGRAM!="__ctl_search 5", GOTO="skip_first_ten_search" +CTL{search}="mixer", CTL{name}="*", CTL{do_search 5}!="1", GOTO="skip_first_ten_search" PRINT=" Element #5:\n" PRINT=" CTL{numid}=\"$ctl{numid}\"\n" PRINT=" CTL{iface}=\"$ctl{iface}\"\n" @@ -174,7 +174,7 @@ PRINT=" CTL{dBmin}=\"$ctl{dBmin}\"\n" PRINT=" CTL{dBmax}=\"$ctl{dBmax}\"\n" PRINT=" CTL{items}=\"$ctl{items}\"\n" PRINT=" CTL{value}=\"$ctl{value}\"\n" -CTL{search}="mixer", CTL{name}="*", PROGRAM!="__ctl_search 6", GOTO="skip_first_ten_search" +CTL{search}="mixer", CTL{name}="*", CTL{do_search 6}!="1", GOTO="skip_first_ten_search" PRINT=" Element #6:\n" PRINT=" CTL{numid}=\"$ctl{numid}\"\n" PRINT=" CTL{iface}=\"$ctl{iface}\"\n" @@ -193,7 +193,7 @@ PRINT=" CTL{dBmin}=\"$ctl{dBmin}\"\n" PRINT=" CTL{dBmax}=\"$ctl{dBmax}\"\n" PRINT=" CTL{items}=\"$ctl{items}\"\n" PRINT=" CTL{value}=\"$ctl{value}\"\n" -CTL{search}="mixer", CTL{name}="*", PROGRAM!="__ctl_search 7", GOTO="skip_first_ten_search" +CTL{search}="mixer", CTL{name}="*", CTL{do_search 7}!="1", GOTO="skip_first_ten_search" PRINT=" Element #7:\n" PRINT=" CTL{numid}=\"$ctl{numid}\"\n" PRINT=" CTL{iface}=\"$ctl{iface}\"\n" @@ -212,7 +212,7 @@ PRINT=" CTL{dBmin}=\"$ctl{dBmin}\"\n" PRINT=" CTL{dBmax}=\"$ctl{dBmax}\"\n" PRINT=" CTL{items}=\"$ctl{items}\"\n" PRINT=" CTL{value}=\"$ctl{value}\"\n" -CTL{search}="mixer", CTL{name}="*", PROGRAM!="__ctl_search 8", GOTO="skip_first_ten_search" +CTL{search}="mixer", CTL{name}="*", CTL{do_search 8}!="1", GOTO="skip_first_ten_search" PRINT=" Element #8:\n" PRINT=" CTL{numid}=\"$ctl{numid}\"\n" PRINT=" CTL{iface}=\"$ctl{iface}\"\n" @@ -231,7 +231,7 @@ PRINT=" CTL{dBmin}=\"$ctl{dBmin}\"\n" PRINT=" CTL{dBmax}=\"$ctl{dBmax}\"\n" PRINT=" CTL{items}=\"$ctl{items}\"\n" PRINT=" CTL{value}=\"$ctl{value}\"\n" -CTL{search}="mixer", CTL{name}="*", PROGRAM!="__ctl_search 9", GOTO="skip_first_ten_search" +CTL{search}="mixer", CTL{name}="*", CTL{do_search 9}!="1", GOTO="skip_first_ten_search" PRINT=" Element #9:\n" PRINT=" CTL{numid}=\"$ctl{numid}\"\n" PRINT=" CTL{iface}=\"$ctl{iface}\"\n" @@ -254,15 +254,15 @@ LABEL="skip_first_ten_search" PRINT="Elements write test #1:\n", \ CTL{search}="mixer", CTL{name}="Front Playback Switch", \ - PROGRAM="__ctl_search", CTL{value}="on,on", \ + CTL{do_search}=="1", CTL{value}="on,on", \ PRINT=" result=$result\n" PRINT="Elements write test #2:\n", \ CTL{search}="mixer", CTL{name}="Front Playback Volume", \ - PROGRAM="__ctl_search", CTL{value}="32,32", \ + CTL{do_search}=="1", CTL{value}="32,32", \ PRINT=" result=$result\n" PRINT="Elements write test #3:\n", \ CTL{search}="mixer", CTL{name}="Front Playback Volume Error", \ - PROGRAM="__ctl_search" + CTL{do_search}=="1", \ PRINT=" result=$result\n" #CTL{reset}="mixer", CTL{name}="Input Source", PRINT="***$ctl{enums}\n" diff --git a/alsactl/init_parse.c b/alsactl/init_parse.c index 83857a2..8d9c7ae 100644 --- a/alsactl/init_parse.c +++ b/alsactl/init_parse.c @@ -485,6 +485,46 @@ static int set_ctl_value(struct space *space, const char *value, int all) return -EINVAL; } +static int do_match(const char *key, enum key_op op, + const char *key_value, const char *value) +{ + int match; + + if (value == NULL) + return 0; + dbg("match %s '%s' <-> '%s'", key, key_value, value); + match = fnmatch(key_value, value, 0) == 0; + if (match && op == KEY_OP_MATCH) { + dbg("%s is true (matching value)", key); + return 1; + } + if (!match && op == KEY_OP_NOMATCH) { + dbg("%s is true (non-matching value)", key); + return 1; + } + dbg("%s is false", key); + return 0; +} + +static int ctl_match(snd_ctl_elem_id_t *pattern, snd_ctl_elem_id_t *id) +{ + if (snd_ctl_elem_id_get_interface(pattern) != -1 && + snd_ctl_elem_id_get_interface(pattern) != snd_ctl_elem_id_get_interface(id)) + return 0; + if (snd_ctl_elem_id_get_device(pattern) != -1 && + snd_ctl_elem_id_get_device(pattern) != snd_ctl_elem_id_get_device(id)) + return 0; + if (snd_ctl_elem_id_get_subdevice(pattern) != -1 && + snd_ctl_elem_id_get_subdevice(pattern) != snd_ctl_elem_id_get_subdevice(id)) + return 0; + if (snd_ctl_elem_id_get_index(pattern) != -1 && + snd_ctl_elem_id_get_index(pattern) != snd_ctl_elem_id_get_index(id)) + return 0; + if (fnmatch(snd_ctl_elem_id_get_name(pattern), snd_ctl_elem_id_get_name(id), 0) != 0) + return 0; + return 1; +} + static const char *elemid_get(struct space *space, const char *attr) { long long val; @@ -649,6 +689,56 @@ dbvalue: } return res; } + if (strncasecmp(attr, "do_search", 9) == 0) { + int err, index = 0; + snd_hctl_elem_t *elem; + snd_ctl_elem_id_t *id; + char *pos = strchr(attr, ' '); + if (pos) + index = strtol(pos, NULL, 0); + err = snd_ctl_elem_id_malloc(&id); + if (err < 0) + return NULL; + elem = snd_hctl_first_elem(space->ctl_handle); + while (elem) { + snd_hctl_elem_get_id(elem, id); + if (!ctl_match(space->ctl_id, id)) + goto next_search; + if (index > 0) { + index--; + goto next_search; + } + strcpy(res, "1"); + snd_ctl_elem_id_copy(space->ctl_id, id); + snd_ctl_elem_id_free(id); + dbg("do_ctl_search found a control"); + return res; + next_search: + elem = snd_hctl_elem_next(elem); + } + snd_ctl_elem_id_free(id); + strcpy(res, "0"); + return res; + } + if (strncasecmp(attr, "do_count", 8) == 0) { + int err, index = 0; + snd_hctl_elem_t *elem; + snd_ctl_elem_id_t *id; + err = snd_ctl_elem_id_malloc(&id); + if (err < 0) + return NULL; + elem = snd_hctl_first_elem(space->ctl_handle); + while (elem) { + snd_hctl_elem_get_id(elem, id); + if (ctl_match(space->ctl_id, id)) + index++; + elem = snd_hctl_elem_next(elem); + } + snd_ctl_elem_id_free(id); + sprintf(res, "%u", index); + dbg("do_ctl_count found %s controls", res); + return res; + } Perror(space, "unknown ctl{} attribute '%s'", attr); return NULL; value: @@ -1150,108 +1240,23 @@ found: *tail = 0; } -static int do_match(const char *key, enum key_op op, - const char *key_value, const char *value) -{ - int match; - - if (value == NULL) - return 0; - dbg("match %s '%s' <-> '%s'", key, key_value, value); - match = fnmatch(key_value, value, 0) == 0; - if (match && op == KEY_OP_MATCH) { - dbg("%s is true (matching value)", key); - return 1; - } - if (!match && op == KEY_OP_NOMATCH) { - dbg("%s is true (non-matching value)", key); - return 1; - } - dbg("%s is false", key); - return 0; -} - -static int ctl_match(snd_ctl_elem_id_t *pattern, snd_ctl_elem_id_t *id) -{ - if (snd_ctl_elem_id_get_interface(pattern) != -1 && - snd_ctl_elem_id_get_interface(pattern) != snd_ctl_elem_id_get_interface(id)) - return 0; - if (snd_ctl_elem_id_get_device(pattern) != -1 && - snd_ctl_elem_id_get_device(pattern) != snd_ctl_elem_id_get_device(id)) - return 0; - if (snd_ctl_elem_id_get_subdevice(pattern) != -1 && - snd_ctl_elem_id_get_subdevice(pattern) != snd_ctl_elem_id_get_subdevice(id)) - return 0; - if (snd_ctl_elem_id_get_index(pattern) != -1 && - snd_ctl_elem_id_get_index(pattern) != snd_ctl_elem_id_get_index(id)) - return 0; - if (fnmatch(snd_ctl_elem_id_get_name(pattern), snd_ctl_elem_id_get_name(id), 0) != 0) - return 0; - return 1; -} - static int run_program1(struct space *space, const char *command0, char *result, size_t ressize, size_t *reslen, int log) { - char *pos = strchr(command0, ' '); - int cmdlen = pos ? pos - command0 : strlen(command0); - int err, index; - snd_hctl_elem_t *elem; - snd_ctl_elem_id_t *id; - - if (cmdlen == 12 && strncmp(command0, "__ctl_search", 12) == 0) { - index = 0; - if (pos) - index = strtol(pos, NULL, 0); - err = snd_ctl_elem_id_malloc(&id); - if (err < 0) + if (strncmp(command0, "__ctl_search", 12) == 0) { + const char *res = elemid_get(space, "do_search"); + if (res == NULL || strcmp(res, "1") != 0) return EXIT_FAILURE; - elem = snd_hctl_first_elem(space->ctl_handle); - while (elem) { - snd_hctl_elem_get_id(elem, id); - if (!ctl_match(space->ctl_id, id)) - goto next_search; - if (index > 0) { - index--; - goto next_search; - } - strlcpy(result, "0", ressize); - snd_ctl_elem_id_copy(space->ctl_id, id); - snd_ctl_elem_id_free(id); - dbg("__ctl_search found a control"); - return EXIT_SUCCESS; - next_search: - elem = snd_hctl_elem_next(elem); - } - snd_ctl_elem_id_free(id); - return EXIT_FAILURE; + return EXIT_SUCCESS; } - if (cmdlen == 11 && strncmp(command0, "__ctl_count", 11) == 0) { - index = 0; - err = snd_ctl_elem_id_malloc(&id); - if (err < 0) + if (strncmp(command0, "__ctl_count", 11) == 0) { + const char *res = elemid_get(space, "do_count"); + if (res == NULL || strcmp(res, "0") == 0) return EXIT_FAILURE; - elem = snd_hctl_first_elem(space->ctl_handle); - while (elem) { - snd_hctl_elem_get_id(elem, id); - if (!ctl_match(space->ctl_id, id)) - goto next_count; - index++; - next_count: - elem = snd_hctl_elem_next(elem); - } - snd_ctl_elem_id_free(id); - if (index > 0) { - snprintf(result, ressize, "%u", index); - dbg("__ctl_count found %s controls", result); - return EXIT_SUCCESS; - } - dbg("__ctl_count no match"); - return EXIT_FAILURE; - } - if (cmdlen == 11 && strncmp(command0, "__ctl_write", 11) == 0) { + strlcpy(result, res, ressize); + return EXIT_SUCCESS; } Perror(space, "unknown buildin command '%s'", command0); return EXIT_FAILURE;