OSDN Git Service

Update alsa-utils to version 1.0.23.
authorSean McNeil <sean.mcneil@windriver.com>
Fri, 2 Jul 2010 09:53:26 +0000 (16:53 +0700)
committerSean McNeil <sean.mcneil@windriver.com>
Fri, 2 Jul 2010 09:53:26 +0000 (16:53 +0700)
Change-Id: I71d4636823c3ca585c2c8d3362ec9d227bda9e21

87 files changed:
Makefile.am
Makefile.in
alsaconf/Makefile.in
alsaconf/alsaconf.in
alsactl/Makefile.in
alsactl/alsactl.c
alsactl/alsactl.h
alsactl/alsactl_init.xml
alsactl/init/00main
alsactl/init/Makefile.in
alsactl/init/default
alsactl/init/hda
alsactl/init/test
alsactl/init_parse.c
alsactl/init_utils_string.c
alsactl/state.c
alsactl/utils.c
alsamixer/Makefile.am
alsamixer/Makefile.in
alsamixer/README [deleted file]
alsamixer/alsamixer.1
alsamixer/alsamixer.c [deleted file]
alsamixer/card_select.c [new file with mode: 0644]
alsamixer/card_select.h [new file with mode: 0644]
alsamixer/cli.c [new file with mode: 0644]
alsamixer/colors.c [new file with mode: 0644]
alsamixer/colors.h [new file with mode: 0644]
alsamixer/device_name.c [new file with mode: 0644]
alsamixer/device_name.h [new file with mode: 0644]
alsamixer/die.c [new file with mode: 0644]
alsamixer/die.h [new file with mode: 0644]
alsamixer/mainloop.c [new file with mode: 0644]
alsamixer/mainloop.h [new file with mode: 0644]
alsamixer/mem.c [new file with mode: 0644]
alsamixer/mem.h [new file with mode: 0644]
alsamixer/mixer_controls.c [new file with mode: 0644]
alsamixer/mixer_controls.h [new file with mode: 0644]
alsamixer/mixer_display.c [new file with mode: 0644]
alsamixer/mixer_display.h [new file with mode: 0644]
alsamixer/mixer_widget.c [new file with mode: 0644]
alsamixer/mixer_widget.h [new file with mode: 0644]
alsamixer/proc_files.c [new file with mode: 0644]
alsamixer/proc_files.h [new file with mode: 0644]
alsamixer/textbox.c [new file with mode: 0644]
alsamixer/textbox.h [new file with mode: 0644]
alsamixer/utils.c [new file with mode: 0644]
alsamixer/utils.h [new file with mode: 0644]
alsamixer/widget.c [new file with mode: 0644]
alsamixer/widget.h [new file with mode: 0644]
amidi/Makefile.in
amidi/amidi.c
amixer/Makefile.in
amixer/amixer.c
aplay/Makefile.am
aplay/Makefile.in
aplay/aplay.1
aplay/aplay.c
aplay/arecord.1
configure
configure.in
iecset/Makefile.in
include/Makefile.am
include/Makefile.in
include/aconfig.h.in
include/gettext.h
include/gettext_curses.h [new file with mode: 0644]
include/version.h
m4/Makefile.in
po/LINGUAS
po/Makevars
po/POTFILES.in
po/alsa-utils.pot
po/de.gmo [new file with mode: 0644]
po/de.po [new file with mode: 0644]
po/ja.gmo
po/ja.po
seq/Makefile.in
seq/aconnect/Makefile.in
seq/aconnect/aconnect.c
seq/aplaymidi/Makefile.in
seq/aplaymidi/aplaymidi.c
seq/aseqdump/Makefile.in
seq/aseqnet/Makefile.in
speaker-test/Makefile.in
speaker-test/samples/Makefile.in
speaker-test/speaker-test.c
utils/Makefile.in

index d28422a..69ce92c 100644 (file)
@@ -1,16 +1,25 @@
 INCLUDES=-I$(top_srcdir)/include
+
+SUBDIRS = include alsactl utils m4 po
 if ALSAMIXER
-ALSAMIXER_DIR=alsamixer
-else
-ALSAMIXER_DIR=
+SUBDIRS += alsamixer
+endif
+if HAVE_MIXER
+SUBDIRS += amixer
+endif
+if HAVE_RAWMIDI
+SUBDIRS += amidi
 endif
 if ALSACONF
-ALSACONF_DIR=alsaconf
-else
-ALSACONF_DIR=
+SUBDIRS += alsaconf
 endif
-SUBDIRS= include alsactl $(ALSACONF_DIR) $(ALSAMIXER_DIR) amidi amixer \
-        aplay iecset seq speaker-test utils m4 po
+if HAVE_PCM
+SUBDIRS += aplay iecset speaker-test
+endif
+if HAVE_SEQ
+SUBDIRS += seq
+endif
+
 EXTRA_DIST= config.rpath  TODO gitcompile
 AUTOMAKE_OPTIONS=foreign
 ACLOCAL_AMFLAGS = -I m4
index c8ec583..9d40dc8 100644 (file)
@@ -35,6 +35,12 @@ PRE_UNINSTALL = :
 POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
+@ALSAMIXER_TRUE@am__append_1 = alsamixer
+@HAVE_MIXER_TRUE@am__append_2 = amixer
+@HAVE_RAWMIDI_TRUE@am__append_3 = amidi
+@ALSACONF_TRUE@am__append_4 = alsaconf
+@HAVE_PCM_TRUE@am__append_5 = aplay iecset speaker-test
+@HAVE_SEQ_TRUE@am__append_6 = seq
 DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
        $(srcdir)/Makefile.in $(top_srcdir)/alsaconf/po/Makefile.in \
        $(top_srcdir)/configure ABOUT-NLS COPYING ChangeLog INSTALL \
@@ -65,8 +71,8 @@ RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
        uninstall-recursive
 ETAGS = etags
 CTAGS = ctags
-DIST_SUBDIRS = include alsactl alsaconf alsamixer amidi amixer aplay \
-       iecset seq speaker-test utils m4 po
+DIST_SUBDIRS = include alsactl utils m4 po alsamixer amixer amidi \
+       alsaconf aplay iecset speaker-test seq
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
 distdir = $(PACKAGE)-$(VERSION)
 top_distdir = $(distdir)
@@ -111,6 +117,14 @@ EXEEXT = @EXEEXT@
 GMSGFMT = @GMSGFMT@
 GMSGFMT_015 = @GMSGFMT_015@
 GREP = @GREP@
+HAVE_MIXER_FALSE = @HAVE_MIXER_FALSE@
+HAVE_MIXER_TRUE = @HAVE_MIXER_TRUE@
+HAVE_PCM_FALSE = @HAVE_PCM_FALSE@
+HAVE_PCM_TRUE = @HAVE_PCM_TRUE@
+HAVE_RAWMIDI_FALSE = @HAVE_RAWMIDI_FALSE@
+HAVE_RAWMIDI_TRUE = @HAVE_RAWMIDI_TRUE@
+HAVE_SEQ_FALSE = @HAVE_SEQ_FALSE@
+HAVE_SEQ_TRUE = @HAVE_SEQ_TRUE@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -121,6 +135,7 @@ LDFLAGS = @LDFLAGS@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
 LIBOBJS = @LIBOBJS@
+LIBRT = @LIBRT@
 LIBS = @LIBS@
 LN_S = @LN_S@
 LTLIBICONV = @LTLIBICONV@
@@ -200,13 +215,9 @@ sysconfdir = @sysconfdir@
 target_alias = @target_alias@
 xmlto = @xmlto@
 INCLUDES = -I$(top_srcdir)/include
-@ALSAMIXER_FALSE@ALSAMIXER_DIR = 
-@ALSAMIXER_TRUE@ALSAMIXER_DIR = alsamixer
-@ALSACONF_FALSE@ALSACONF_DIR = 
-@ALSACONF_TRUE@ALSACONF_DIR = alsaconf
-SUBDIRS = include alsactl $(ALSACONF_DIR) $(ALSAMIXER_DIR) amidi amixer \
-        aplay iecset seq speaker-test utils m4 po
-
+SUBDIRS = include alsactl utils m4 po $(am__append_1) $(am__append_2) \
+       $(am__append_3) $(am__append_4) $(am__append_5) \
+       $(am__append_6)
 EXTRA_DIST = config.rpath  TODO gitcompile
 AUTOMAKE_OPTIONS = foreign
 ACLOCAL_AMFLAGS = -I m4
index 7d0b63c..11dcd36 100644 (file)
@@ -102,6 +102,14 @@ EXEEXT = @EXEEXT@
 GMSGFMT = @GMSGFMT@
 GMSGFMT_015 = @GMSGFMT_015@
 GREP = @GREP@
+HAVE_MIXER_FALSE = @HAVE_MIXER_FALSE@
+HAVE_MIXER_TRUE = @HAVE_MIXER_TRUE@
+HAVE_PCM_FALSE = @HAVE_PCM_FALSE@
+HAVE_PCM_TRUE = @HAVE_PCM_TRUE@
+HAVE_RAWMIDI_FALSE = @HAVE_RAWMIDI_FALSE@
+HAVE_RAWMIDI_TRUE = @HAVE_RAWMIDI_TRUE@
+HAVE_SEQ_FALSE = @HAVE_SEQ_FALSE@
+HAVE_SEQ_TRUE = @HAVE_SEQ_TRUE@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -112,6 +120,7 @@ LDFLAGS = @LDFLAGS@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
 LIBOBJS = @LIBOBJS@
+LIBRT = @LIBRT@
 LIBS = @LIBS@
 LN_S = @LN_S@
 LTLIBICONV = @LTLIBICONV@
index 6e9ff75..ccc1b37 100644 (file)
@@ -291,6 +291,8 @@ esac
 
 # cfgfile = base config file to remove/update the sound setting
 # cfgout = new config file to write the sound setting (if different from $cfgfile)
+cfgout=""
+cfgoldout=""
 if [ -n "$cfgfile" ]; then
   if [ ! -r "$cfgfile" ]; then
     xecho "ERROR: The config file doesn't exist: "
@@ -301,10 +303,22 @@ else
 if [ "$distribution" = "gentoo" ]; then
   cfgfile="/etc/modules.d/alsa"
 elif [ "$kernel" = "new" ]; then
+  cfgfile="/etc/modprobe.conf"
   if [ -d /etc/modprobe.d ]; then
-    cfgout="/etc/modprobe.d/sound"
+    cfgout="/etc/modprobe.d/50-sound.conf"
+    cfgoldout="/etc/modprobe.d/sound"
+    if [ ! -f $cfgout ]; then
+       modver=$(modprobe -V | sed -e's/^module-init-tools version //')
+       case "$modver" in
+       3.[789]*)
+         ;;
+       *)
+         cfgout="/etc/modprobe.d/sound"
+         cfgoldout=""
+         ;;
+       esac
+    fi
   fi
-  cfgfile="/etc/modprobe.conf"
 elif [ "$distribution" = "debian" ]; then
   cfgfile="/etc/modutils/sound"
 elif [ -e /etc/modules.conf ]; then
@@ -818,7 +832,7 @@ ac_config_card () {
        msg=$(xmsg "
 Configuring %s
 Do you want to modify %s (and %s if present)?" $CARD_DRIVER $cfgout $cfgfile)
-        $DIALOG --yesno "$msg" 8 50 || acex 0
+        $DIALOG --yesno "$msg" 10 50 || acex 0
     else
        msg=$(xmsg "
 Configuring %s
@@ -875,6 +889,7 @@ alias sound-slot-0 $CARD_DRIVER" >> $addcfg
     if [ -n "$cfgout" ]; then
        [ ! -r "$cfgfile" ] || cmp -s "$TMP" "$cfgfile" || cat "$TMP" > "$cfgfile"
        cmp -s "$addcfg" "$cfgout" || cat "$addcfg" > "$cfgout"
+       test -n "$cfgoldout" && rm -f "$cfgoldout"
     else
        echo "$ACB
 # --- ALSACONF version $version ---" >> $TMP
index 2d8fe45..7ba7c4a 100644 (file)
@@ -119,6 +119,14 @@ EXEEXT = @EXEEXT@
 GMSGFMT = @GMSGFMT@
 GMSGFMT_015 = @GMSGFMT_015@
 GREP = @GREP@
+HAVE_MIXER_FALSE = @HAVE_MIXER_FALSE@
+HAVE_MIXER_TRUE = @HAVE_MIXER_TRUE@
+HAVE_PCM_FALSE = @HAVE_PCM_FALSE@
+HAVE_PCM_TRUE = @HAVE_PCM_TRUE@
+HAVE_RAWMIDI_FALSE = @HAVE_RAWMIDI_FALSE@
+HAVE_RAWMIDI_TRUE = @HAVE_RAWMIDI_TRUE@
+HAVE_SEQ_FALSE = @HAVE_SEQ_FALSE@
+HAVE_SEQ_TRUE = @HAVE_SEQ_TRUE@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -129,6 +137,7 @@ LDFLAGS = @LDFLAGS@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
 LIBOBJS = @LIBOBJS@
+LIBRT = @LIBRT@
 LIBS = @LIBS@
 LN_S = @LN_S@
 LTLIBICONV = @LTLIBICONV@
index e0bc276..3b5dfda 100644 (file)
@@ -97,7 +97,8 @@ int main(int argc, char *argv[])
        };
        char *cfgfile = SYS_ASOUNDRC;
        char *initfile = DATADIR "/init/00main";
-       char *cardname, **tmp, ncardname[16];
+       char *cardname, ncardname[16];
+       const char *const *tmp;
        int removestate = 0;
        int init_fallback = 1; /* new default behavior */
        int res;
@@ -106,7 +107,7 @@ int main(int argc, char *argv[])
        while (1) {
                int c;
 
-               if ((c = getopt_long(argc, argv, "hdvf:FgE:i:Pr:R", long_option, NULL)) < 0)
+               if ((c = getopt_long(argc, argv, "hdvf:FgE:i:IPr:R", long_option, NULL)) < 0)
                        break;
                switch (c) {
                case 'h':
@@ -188,5 +189,5 @@ int main(int argc, char *argv[])
        }
 
        snd_config_update_free_global();
-       return res < 0 ? res : 0;
+       return res < 0 ? -res : 0;
 }
index 89ad295..be90efb 100644 (file)
@@ -34,16 +34,16 @@ extern char *statefile;
 
 #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
 #define cerror(cond, ...) do {\
-       if (cond) { \
-               fprintf(stderr, "%s: %s:%d: ", command, __FUNCTION__, __LINE__); \
+       if (cond || debugflag) { \
+               fprintf(stderr, "%s%s: %s:%d: ", debugflag ? "WARNING: " : "", command, __FUNCTION__, __LINE__); \
                fprintf(stderr, __VA_ARGS__); \
                putc('\n', stderr); \
        } \
 } while (0)
 #else
 #define cerror(cond, args...) do {\
-       if (cond) { \
-               fprintf(stderr, "%s: %s:%d: ", command, __FUNCTION__, __LINE__); \
+       if (cond || debugflag) { \
+               fprintf(stderr, "%s%s: %s:%d: ", debugflag ? "WARNING: " : "", command, __FUNCTION__, __LINE__); \
                fprintf(stderr, ##args); \
                putc('\n', stderr); \
        } \
@@ -78,7 +78,7 @@ int generate_names(const char *cfgfile);
 int file_map(const char *filename, char **buf, size_t *bufsize);
 void file_unmap(void *buf, size_t bufsize);
 size_t line_width(const char *buf, size_t bufsize, size_t pos);
-void initfailed(int cardnumber, const char *reason);
+void initfailed(int cardnumber, const char *reason, int exitcode);
 
 static inline int hextodigit(int c)
 {
index 0e0d46b..eefe9ef 100644 (file)
                       comma (,).</para>
                     </listitem>
                   </varlistentry>
+                  <varlistentry>
+                    <term><option>do_search</option></term>
+                    <listitem>
+                      <para>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").</para>
+                     </listitem>
+                  </varlistentry>
+                  <varlistentry>
+                    <term><option>do_count</option></term>
+                    <listitem>
+                      <para>Search for a controls and return total count
+                      of matched ones. The CTL{name} key might contain match
+                      characters * and ?.</para>
+                     </listitem>
+                  </varlistentry>
                 </variablelist>
               </listitem>
             </varlistentry>
               <listitem>
                 <para>The relative path to sysfs subsystem specifying
                 the root directory of a soundcard device. Usually,
-                it should be set to "/class/sound/controlC$cardinfo{card}/device".
+                it should be set to "/class/sound/card$cardinfo{card}/device".
                 </para>
               </listitem>
             </varlistentry>
                  next key on line).</para>
               </listitem>
             </varlistentry>
+            <varlistentry>
+              <term><option>CTL{write}</option></term>
+              <listitem>
+                <para>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).</para>
+              </listitem>
+            </varlistentry>
 
             <varlistentry>
               <term><option>ENV{<replaceable>key</replaceable>}</option></term>
             <varlistentry>
               <term><option>GOTO</option></term>
               <listitem>
-                <para>Jumps to the next LABEL with a matching name</para>
+                <para>Jumps to the next LABEL with a matching name.
+                      The goto cannot jump backward.</para>
               </listitem>
             </varlistentry>
 
               <listitem>
                 <para>The relative path to sysfs subsystem specifying
                 the root directory of a soundcard device. Usually,
-                it should be set to "/class/sound/controlC$cardinfo{card}/device".
+                it should be set to "/class/sound/card$cardinfo{card}/device".
                 </para>
               </listitem>
             </varlistentry>
             </varlistentry>
 
             <varlistentry>
+              <term><option>$config{<replaceable>key</replaceable>}</option>, <option>%g{<replaceable>key</replaceable>}</option></term>
+              <listitem>
+                <para>The value of a configuration variable. See CONFIG{} for more details.</para>
+              </listitem>
+            </varlistentry>
+
+            <varlistentry>
               <term><option>%%</option></term>
               <listitem>
               <para>The '%' character itself.</para>
index 942f386..2d26bbf 100644 (file)
@@ -2,7 +2,9 @@
 # See 'man alsactl_init' for syntax.
 
 # set root device directory in sysfs for soundcard for ATTR{} command
-CONFIG{sysfs_device}="/class/sound/controlC$cardinfo{card}/device"
+CONFIG{sysfs_device}="/class/sound/card$cardinfo{card}/device"
+ACCESS!="$sysfsroot$config{sysfs_device}", \
+       CONFIG{sysfs_device}="/class/sound/controlC$cardinfo{card}/device"
 
 # test for extra commands
 ENV{CMD}=="help", INCLUDE="help", GOTO="00main_end"
@@ -29,6 +31,7 @@ RESULT=="skip", GOTO="init_end"
 
 # real ALSA configuration database
 CARDINFO{driver}=="HDA-Intel", INCLUDE="hda", GOTO="init_end"
+CARDINFO{driver}=="CA0106", INCLUDE="ca0106", GOTO="init_end"
 CARDINFO{driver}=="Test", INCLUDE="test", GOTO="init_end"
 
 LABEL="init_end"
index 1cabfb4..26e6f86 100644 (file)
@@ -95,6 +95,14 @@ EXEEXT = @EXEEXT@
 GMSGFMT = @GMSGFMT@
 GMSGFMT_015 = @GMSGFMT_015@
 GREP = @GREP@
+HAVE_MIXER_FALSE = @HAVE_MIXER_FALSE@
+HAVE_MIXER_TRUE = @HAVE_MIXER_TRUE@
+HAVE_PCM_FALSE = @HAVE_PCM_FALSE@
+HAVE_PCM_TRUE = @HAVE_PCM_TRUE@
+HAVE_RAWMIDI_FALSE = @HAVE_RAWMIDI_FALSE@
+HAVE_RAWMIDI_TRUE = @HAVE_RAWMIDI_TRUE@
+HAVE_SEQ_FALSE = @HAVE_SEQ_FALSE@
+HAVE_SEQ_TRUE = @HAVE_SEQ_TRUE@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -105,6 +113,7 @@ LDFLAGS = @LDFLAGS@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
 LIBOBJS = @LIBOBJS@
+LIBRT = @LIBRT@
 LIBS = @LIBS@
 LN_S = @LN_S@
 LTLIBICONV = @LTLIBICONV@
index 66692b3..35acfc3 100644 (file)
 # playback
 # **************************************************************************
 
-ENV{volume}:="-20dB"
+ENV{ppercent}:="75%"
+ENV{cpercent}:="75%"
+ENV{pvolume}:="-20dB"
+ENV{cvolume}:="12dB"
+ENV{has_pmaster_vol}:="false"
 
 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{name}="Playback Volume",CTL{do_search}=="1", \
+  CTL{write}!="$env{pvolume}",CTL{values}="$env{ppercent}"
+CTL{name}="Playback Switch",CTL{do_search}=="1", \
   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{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",CTL{do_search}=="1", \
   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{name}="Master Digital Playback Volume",CTL{do_search}=="1", \
+  CTL{write}!="$env{pvolume}",CTL{values}="$env{ppercent}"
+CTL{name}="Master Digital Playback Switch",CTL{do_search}=="1", \
   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{name}="Front Playback Volume",PROGRAM!="__ctl_search",GOTO=""
+# if master volume control is present, turn front volume to max
+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",CTL{do_search}=="1", \
   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{name}="Headphone Playback Volume",PROGRAM!="__ctl_search",GOTO=""
+# if master volume control is present, turn headphone volume to max
+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{do_search}=="1", \
   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{name}="Headphone Playback Volume",CTL{index}="1",PROGRAM!="__ctl_search",\
+  GOTO=""
+# if master volume control is present, turn headphone volume to max
+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",CTL{do_search}=="1", \
   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{name}="Speaker Playback Volume",PROGRAM!="__ctl_search",GOTO=""
+# if master volume control is present, turn speaker volume to max
+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",CTL{do_search}=="1", \
   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{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",CTL{do_search}=="1", \
   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{name}="PCM Playback Volume",PROGRAM!="__ctl_search", \
+ CTL{name}="PCM Volume",PROGRAM!="__ctl_search", GOTO=""
+# if master volume control is present, turn PCM volume to max
+ENV{has_pmaster_vol}=="true",CTL{write}=="0dB",GOTO=""
+ENV{has_pmaster_vol}=="true",CTL{write}=="100%",GOTO=""
+# exception - some HDA codecs have shifted dB range
+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{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", \
+  CTL{name}="PCM Volume",PROGRAM!="__ctl_search",GOTO=""
+# if master volume control is present, turn PCM volume to max
+ENV{has_pmaster_vol}=="true",CTL{write}=="0dB",GOTO=""
+ENV{has_pmaster_vol}=="true",CTL{write}=="100%",GOTO=""
+# exception - some HDA codecs have shifted dB range
+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",CTL{do_search}=="1", \
+  CTL{values}="on"
+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{values}="$env{volume}",RESULT!="0",CTL{values}="75%"
-CTL{name}="DAC Playback Switch",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",CTL{do_search}=="1", \
   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{name}="Synth Playback Volume",CTL{do_search}=="1", \
+  CTL{values}="$env{pvolume}",RESULT!="0",CTL{values}="$env{ppercent}"
+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"
-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{name}="CD Playback Volume",PROGRAM!="__ctl_search", GOTO=""
+# if master volume control is present, turn CD volume to max
+ENV{has_pmaster_vol}=="true",CTL{write}=="0dB",GOTO=""
+ENV{has_pmaster_vol}=="true",CTL{write}=="100%",GOTO=""
+# exception - some HDA codecs have shifted dB range
+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",CTL{do_search}=="1", \
   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{name}="Mono Playback Volume",CTL{do_search}=="1", \
+  CTL{values}="$env{pvolume}",RESULT!="0",CTL{values}="$env{ppercent}"
+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{values}="$env{volume}",RESULT!="0",CTL{values}="75%"
-CTL{name}="Master Mono Playback Switch",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",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"
 
 #
@@ -119,27 +172,27 @@ CTL{name}="AC97 Playback Switch",PROGRAM=="__ctl_search", \
 #
 
 CTL{reset}="mixer"
-CTL{name}="DRC Range",PROGRAM=="__ctl_search", \
-  CTL{values}="$env{volume}",RESULT!="0",CTL{values}="75%"
+CTL{name}="DRC Range",CTL{do_search}=="1", \
+  CTL{write}!="$env{pvolume}",CTL{values}="$env{ppercent}"
 
 # **************************************************************************
 # 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{name}="Capture Volume",CTL{do_search}=="1", \
+  CTL{write}!="$env{cvolume}",CTL{values}="$env{cpercent}"
+CTL{name}="Capture Switch",CTL{do_search}=="1", \
   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}="Input Source",PROGRAM!="__ctl_search", GOTO=""
+CTL{enums}=="*|Internal Mic|*",CTL{values}="Internal Mic", GOTO=""
+CTL{enums}=="*|Mic|*",CTL{values}="Mic"
+LABEL=""
 
-CTL{name}="Internal Mic Boost",PROGRAM=="__ctl_search", \
-  CTL{values}="on"
+CTL{name}="Digital Input Source",PROGRAM!="__ctl_search", GOTO=""
+CTL{enums}=="*|Digital Mic 1|*",CTL{values}="Digital Mic 1", GOTO=""
+CTL{enums}=="*|Mic|*",CTL{values}="Mic"
+LABEL=""
+
+CTL{name}="Internal Mic Boost",CTL{do_search}=="1", CTL{values}="on"
index 43dfec2..a6919f1 100644 (file)
@@ -11,10 +11,12 @@ RESULT="false", EXIT="return"
 LABEL="Acer Travelmate 8100"
 # playback
 CTL{reset}="mixer"
+CTL{name}="Master Playback Volume", CTL{value}="-21dB"
+CTL{name}="Master Playback Switch", CTL{value}="on"
 CTL{name}="Headphone Playback Switch", CTL{value}="on,on"
 CTL{name}="Front Playback Volume", CTL{value}="-29dB,-29dB"
 CTL{name}="Front Playback Switch", CTL{value}="on,on"
-CTL{name}="PCM Playback Volume", CTL{value}="-21dB,-21dB"
+CTL{name}="PCM Playback Volume", CTL{value}="0dB,0dB"
 # capture
 CTL{name}="Input Source", CTL{value}="Mic"
 CTL{name}="Capture Volume", CTL{value}="20dB,20dB"
@@ -24,8 +26,11 @@ RESULT="true", EXIT="return"
 LABEL="Lenovo T61"
 # playback
 CTL{reset}="mixer"
+CTL{name}="Master Playback Volume", CTL{value}="-13.5dB"
+CTL{name}="Master Playback Switch", CTL{value}="on"
 CTL{name}="Headphone Playback Switch", CTL{value}="on,on"
-CTL{name}="PCM Playback Volume", CTL{value}="-13.5dB,-13.5dB"
+CTL{name}="Speaker Playback Switch", CTL{value}="on,on"
+CTL{name}="PCM Playback Volume", CTL{value}="0dB,0dB"
 # capture
 CTL{name}="Input Source", CTL{value}="Internal Mic"
 CTL{name}="Internal Mic Boost", CTL{value}="1"
index 26db2a3..56659f8 100644 (file)
@@ -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"
index c82797e..f243406 100644 (file)
@@ -382,7 +382,7 @@ static int set_ctl_value(struct space *space, const char *value, int all)
                                snd_ctl_elem_value_set_integer(space->ctl_value, idx, val);
                        } else if (items > 2 && value[items-2] == 'd' && value[items-1] == 'B') {
                                val = strtol(value, NULL, 0) * 100;
-                               if ((pos2 = index(value, '.')) != NULL) {
+                               if ((pos2 = strchr(value, '.')) != NULL) {
                                        if (isdigit(*(pos2-1)) && isdigit(*(pos2-2))) {
                                                if (val < 0)
                                                        val -= strtol(pos2 + 1, NULL, 0);
@@ -397,7 +397,7 @@ static int set_ctl_value(struct space *space, const char *value, int all)
                                }
                                val = snd_ctl_convert_from_dB(snd_hctl_ctl(space->ctl_handle), space->ctl_id, val, &lval, -1);
                                if (val < 0) {
-                                       Perror(space, "unable to convert dB value '%s' to internal integer range", value);
+                                       dbg("unable to convert dB value '%s' to internal integer range", value);
                                        return val;
                                }
                                snd_ctl_elem_value_set_integer(space->ctl_value, idx, lval);
@@ -486,6 +486,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;
@@ -650,6 +690,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:
@@ -930,6 +1020,7 @@ static void apply_format(struct space *space, char *string, size_t maxsize)
                SUBST_ATTR,
                SUBST_SYSFSROOT,
                SUBST_ENV,
+               SUBST_CONFIG,
        };
        static const struct subst_map {
                char *name;
@@ -942,6 +1033,7 @@ static void apply_format(struct space *space, char *string, size_t maxsize)
                { .name = "attr",       .fmt = 's',     .type = SUBST_ATTR },
                { .name = "sysfsroot",  .fmt = 'r',     .type = SUBST_SYSFSROOT },
                { .name = "env",        .fmt = 'E',     .type = SUBST_ENV },
+               { .name = "config",     .fmt = 'g',     .type = SUBST_CONFIG },
                { NULL, '\0', 0 }
        };
        enum subst_type type;
@@ -1102,6 +1194,16 @@ found:
                        dbg("substitute env '%s=%s'", attr, pos);
                        strlcat(string, pos, maxsize);
                        break;
+               case SUBST_CONFIG:
+                       if (attr == NULL) {
+                               dbg("missing attribute");
+                               break;
+                       }
+                       pair = value_find(space, attr);
+                       if (pair == NULL)
+                               break;
+                       strlcat(string, pair->value, maxsize);
+                       break;
                default:
                        Perror(space, "unknown substitution type=%i", type);
                        break;
@@ -1139,108 +1241,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;
@@ -1254,7 +1271,7 @@ static char *new_root_dir(const char *filename)
 
        res = strdup(filename);
        if (res) {
-               tmp = rindex(res, '/');
+               tmp = strrchr(res, '/');
                if (tmp)
                        *tmp = '\0';
        }
@@ -1314,15 +1331,25 @@ static int parse_line(struct space *space, char *line, size_t linesize)
                                }
                                snprintf(string, sizeof(string), "%i", err);
                                space->program_result = strdup(string);
-                               if (err < 0 || space->program_result == NULL) {
-                                       err = 0;
+                               err = 0;
+                               if (space->program_result == NULL)
                                        break;
-                               }
                        } else if (op == KEY_OP_MATCH || op == KEY_OP_NOMATCH) {
-                               dbg("ctl match: '%s' '%s'", value, attr);
-                               temp = (char *)elemid_get(space, attr);
-                               if (!do_match(key, op, value, temp))
-                                       break;
+                               if (strncmp(attr, "write", 5) == 0) {
+                                       strlcpy(result, value, sizeof(result));
+                                       apply_format(space, result, sizeof(result));
+                                       dbg("ctl write: '%s' '%s'", value, attr);
+                                       err = elemid_set(space, "values", result);
+                                       if (err == 0 && op == KEY_OP_NOMATCH)
+                                               break;
+                                       if (err != 0 && op == KEY_OP_MATCH)
+                                               break;
+                               } else {
+                                       temp = (char *)elemid_get(space, attr);
+                                       dbg("ctl match: '%s' '%s' '%s'", attr, value, temp);
+                                       if (!do_match(key, op, value, temp))
+                                               break;
+                               }
                        } else {
                                Perror(space, "invalid CTL{} operation");
                                goto invalid;
@@ -1522,15 +1549,23 @@ static int parse_line(struct space *space, char *line, size_t linesize)
                }
                if (strncasecmp(key, "ACCESS", 6) == 0) {
                        if (op == KEY_OP_MATCH || op == KEY_OP_NOMATCH) {
+                               if (value[0] == '$') {
+                                       strlcpy(string, value, sizeof(string));
+                                       apply_format(space, string, sizeof(string));
+                                       if (string[0] == '/')
+                                               goto __access1;
+                               }
                                if (value[0] != '/') {
                                        strlcpy(string, space->rootdir, sizeof(string));
                                        strlcat(string, "/", sizeof(string));
                                        strlcat(string, value, sizeof(string));
                                } else {
-                                       strlcat(string, value, sizeof(string));
+                                       strlcpy(string, value, sizeof(string));
                                }
+                               apply_format(space, string, sizeof(string));
+                             __access1:
                                count = access(string, F_OK);
-                               dbg("access(%s) = %i", value, count);
+                               dbg("access(%s) = %i (%s)", string, count, value);
                                if (op == KEY_OP_MATCH && count != 0)
                                        break;
                                if (op == KEY_OP_NOMATCH && count == 0)
@@ -1713,10 +1748,12 @@ int init(const char *filename, const char *cardname)
                        }
                        first = 0;
                        err = init_space(&space, card);
-                       if (err == 0 &&
-                           (space->rootdir = new_root_dir(filename)) != NULL)
-                               err = parse(space, filename);
-                       free_space(space);
+                       if (err == 0) {
+                               space->rootdir = new_root_dir(filename);
+                               if (space->rootdir != NULL)
+                                       err = parse(space, filename);
+                               free_space(space);
+                       }
                        if (err < 0)
                                break;
                }
@@ -1728,10 +1765,12 @@ int init(const char *filename, const char *cardname)
                }
                memset(&space, 0, sizeof(space));
                err = init_space(&space, card);
-               if (err == 0 &&
-                   (space->rootdir = new_root_dir(filename)) != NULL)
-                       err = parse(space, filename);
-               free_space(space);
+               if (err == 0) {
+                       space->rootdir = new_root_dir(filename);
+                       if (space->rootdir  != NULL)
+                               err = parse(space, filename);
+                       free_space(space);
+               }
        }
   error:
        sysfs_cleanup();
index 2598e9f..01ea800 100644 (file)
  */
 
 
-static int string_is_true(const char *str)
-{
-       if (strcasecmp(str, "true") == 0)
-               return 1;
-       if (strcasecmp(str, "yes") == 0)
-               return 1;
-       if (strcasecmp(str, "1") == 0)
-               return 1;
-       return 0;
-}
-
 static void remove_trailing_chars(char *path, char c)
 {
        size_t len;
index 635a999..e70c6f9 100644 (file)
@@ -1117,7 +1117,6 @@ static int restore_config_value2(snd_ctl_t *handle, snd_ctl_elem_info_t *info,
                }
                snd_ctl_elem_value_set_byte(ctl, idx, val);
                return 1;
-               break;
        default:
                break;
        }
@@ -1404,6 +1403,7 @@ static int set_controls(int card, snd_config_t *top, int doit)
        snd_ctl_card_info_alloca(&info);
 
        sprintf(name, "hw:%d", card);
+       dbg("device='%s', doit=%i", name, doit);
        err = snd_ctl_open(&handle, name, 0);
        if (err < 0) {
                error("snd_ctl_open error: %s", snd_strerror(err));
@@ -1415,6 +1415,7 @@ static int set_controls(int card, snd_config_t *top, int doit)
                goto _close;
        }
        id = snd_ctl_card_info_get_id(info);
+       dbg("card-info-id: '%s'", id);
        err = snd_config_searchv(top, &control, "state", id, "control", 0);
        if (err < 0) {
                if (force_restore) {
@@ -1440,24 +1441,25 @@ static int set_controls(int card, snd_config_t *top, int doit)
                        goto _close;
        }
 
+       dbg("maxnumid=%i", maxnumid);
        /* check if we have additional controls in driver */
        /* in this case we should go through init procedure */
        if (!doit && maxnumid >= 0) {
-               snd_ctl_elem_id_t *id;
                snd_ctl_elem_info_t *info;
-               snd_ctl_elem_id_alloca(&id);
                snd_ctl_elem_info_alloca(&info);
                snd_ctl_elem_info_set_numid(info, maxnumid+1);
                if (snd_ctl_elem_info(handle, info) == 0) {
                        /* not very informative */
                        /* but value is used for check only */
                        err = -EAGAIN;
+                       dbg("more controls than maxnumid?");
                        goto _close;
                }
        }
 
  _close:
        snd_ctl_close(handle);
+       dbg("result code: %i", err);
        return err;
 }
 
@@ -1582,9 +1584,9 @@ int load_state(const char *file, const char *initfile, const char *cardname,
                        err = init(initfile, cardname1);
                        if (err < 0) {
                                finalerr = err;
-                               initfailed(card, "init");
+                               initfailed(card, "init", err);
                        }
-                       initfailed(card, "restore");
+                       initfailed(card, "restore", -ENOENT);
                }
                if (first)
                        finalerr = 0;   /* no cards, no error code */
@@ -1617,14 +1619,14 @@ int load_state(const char *file, const char *initfile, const char *cardname,
                                sprintf(cardname1, "%i", card);
                                err = init(initfile, cardname1);
                                if (err < 0) {
-                                       initfailed(card, "init");
+                                       initfailed(card, "init", err);
                                        finalerr = err;
                                }
                        }
                        if ((err = set_controls(card, config, 1))) {
                                if (!force_restore)
                                        finalerr = err;
-                               initfailed(card, "restore");
+                               initfailed(card, "restore", err);
                        }
                }
        } else {
@@ -1639,12 +1641,12 @@ int load_state(const char *file, const char *initfile, const char *cardname,
                if (do_init && set_controls(cardno, config, 0)) {
                        err = init(initfile, cardname);
                        if (err < 0) {
-                               initfailed(cardno, "init");
-                               return err;
+                               initfailed(cardno, "init", err);
+                               finalerr = err;
                        }
                }
                if ((err = set_controls(cardno, config, 1))) {
-                       initfailed(cardno, "restore");
+                       initfailed(cardno, "restore", err);
                        if (!force_restore)
                                return err;
                }
index ab4dbd4..a27eb6e 100644 (file)
@@ -79,19 +79,23 @@ size_t line_width(const char *buf, size_t bufsize, size_t pos)
        return count - pos;
 }
 
-void initfailed(int cardnumber, const char *reason)
+void initfailed(int cardnumber, const char *reason, int exitcode)
 {
        int fp;
        char *str;
+       char sexitcode[16];
 
        if (statefile == NULL)
                return;
        if (snd_card_get_name(cardnumber, &str) < 0)
                return;
+       sprintf(sexitcode, "%i", exitcode);
        fp = open(statefile, O_WRONLY|O_CREAT|O_APPEND, 0644);
        write(fp, str, strlen(str));
        write(fp, ":", 1);
        write(fp, reason, strlen(reason));
+       write(fp, ":", 1);
+       write(fp, sexitcode, strlen(sexitcode));
        write(fp, "\n", 1);
        close(fp);
        free(str);
index 6426193..1de47c6 100644 (file)
@@ -2,6 +2,20 @@ AM_CFLAGS = @CURSES_CFLAGS@ -DCURSESINC="@CURSESINC@"
 LDADD = @CURSESLIB@
 
 bin_PROGRAMS = alsamixer
+alsamixer_SOURCES = card_select.c card_select.h \
+               cli.c \
+               colors.c colors.h \
+               device_name.c device_name.h \
+               die.c die.h \
+               mainloop.c mainloop.h \
+               mem.c mem.h \
+               mixer_controls.c mixer_controls.h \
+               mixer_display.c mixer_display.h \
+               mixer_widget.c mixer_widget.h \
+               proc_files.c proc_files.h \
+               textbox.c textbox.h \
+               utils.c utils.h \
+               widget.c widget.h
 man_MANS = alsamixer.1
 EXTRA_DIST = alsamixer.1
 alsamixer_INCLUDES = -I$(top_srcdir)/include
index 1332bff..8455506 100644 (file)
@@ -38,7 +38,7 @@ build_triplet = @build@
 host_triplet = @host@
 bin_PROGRAMS = alsamixer$(EXEEXT)
 subdir = alsamixer
-DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \
        $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \
@@ -54,8 +54,13 @@ CONFIG_CLEAN_FILES =
 am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"
 binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
 PROGRAMS = $(bin_PROGRAMS)
-alsamixer_SOURCES = alsamixer.c
-alsamixer_OBJECTS = alsamixer.$(OBJEXT)
+am_alsamixer_OBJECTS = card_select.$(OBJEXT) cli.$(OBJEXT) \
+       colors.$(OBJEXT) device_name.$(OBJEXT) die.$(OBJEXT) \
+       mainloop.$(OBJEXT) mem.$(OBJEXT) mixer_controls.$(OBJEXT) \
+       mixer_display.$(OBJEXT) mixer_widget.$(OBJEXT) \
+       proc_files.$(OBJEXT) textbox.$(OBJEXT) utils.$(OBJEXT) \
+       widget.$(OBJEXT)
+alsamixer_OBJECTS = $(am_alsamixer_OBJECTS)
 alsamixer_LDADD = $(LDADD)
 alsamixer_DEPENDENCIES =
 DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/include
@@ -65,8 +70,8 @@ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
        $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
 CCLD = $(CC)
 LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
-SOURCES = alsamixer.c
-DIST_SOURCES = alsamixer.c
+SOURCES = $(alsamixer_SOURCES)
+DIST_SOURCES = $(alsamixer_SOURCES)
 man1dir = $(mandir)/man1
 NROFF = nroff
 MANS = $(man_MANS)
@@ -106,6 +111,14 @@ EXEEXT = @EXEEXT@
 GMSGFMT = @GMSGFMT@
 GMSGFMT_015 = @GMSGFMT_015@
 GREP = @GREP@
+HAVE_MIXER_FALSE = @HAVE_MIXER_FALSE@
+HAVE_MIXER_TRUE = @HAVE_MIXER_TRUE@
+HAVE_PCM_FALSE = @HAVE_PCM_FALSE@
+HAVE_PCM_TRUE = @HAVE_PCM_TRUE@
+HAVE_RAWMIDI_FALSE = @HAVE_RAWMIDI_FALSE@
+HAVE_RAWMIDI_TRUE = @HAVE_RAWMIDI_TRUE@
+HAVE_SEQ_FALSE = @HAVE_SEQ_FALSE@
+HAVE_SEQ_TRUE = @HAVE_SEQ_TRUE@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -116,6 +129,7 @@ LDFLAGS = @LDFLAGS@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
 LIBOBJS = @LIBOBJS@
+LIBRT = @LIBRT@
 LIBS = @LIBS@
 LN_S = @LN_S@
 LTLIBICONV = @LTLIBICONV@
@@ -196,6 +210,21 @@ target_alias = @target_alias@
 xmlto = @xmlto@
 AM_CFLAGS = @CURSES_CFLAGS@ -DCURSESINC="@CURSESINC@"
 LDADD = @CURSESLIB@
+alsamixer_SOURCES = card_select.c card_select.h \
+               cli.c \
+               colors.c colors.h \
+               device_name.c device_name.h \
+               die.c die.h \
+               mainloop.c mainloop.h \
+               mem.c mem.h \
+               mixer_controls.c mixer_controls.h \
+               mixer_display.c mixer_display.h \
+               mixer_widget.c mixer_widget.h \
+               proc_files.c proc_files.h \
+               textbox.c textbox.h \
+               utils.c utils.h \
+               widget.c widget.h
+
 man_MANS = alsamixer.1
 EXTRA_DIST = alsamixer.1
 alsamixer_INCLUDES = -I$(top_srcdir)/include
@@ -265,7 +294,20 @@ mostlyclean-compile:
 distclean-compile:
        -rm -f *.tab.c
 
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alsamixer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/card_select.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cli.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/colors.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/device_name.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/die.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mainloop.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mem.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mixer_controls.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mixer_display.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mixer_widget.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_files.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/textbox.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/widget.Po@am__quote@
 
 .c.o:
 @am__fastdepCC_TRUE@   if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
diff --git a/alsamixer/README b/alsamixer/README
deleted file mode 100644 (file)
index 05c6615..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-Using Alsamixer
-===============
-
-Alsamixer uses an ncurses interface, which may not display properly in
-an xterm.
-
-Start it by typing "alsamixer".
-
-Optional flags:
-alsamixer -h displays the available flags.
-alsamixer -e starts in "exact" mode. See below...
-alsamixer -c N selects the soundcard to control, where N is the number of
-the card, counting from 1.
-alsamixer -m selects which mixer device to control, counting from 0. This
-is only applicable to soundcards that have more than one mixer to 
-control. It is the same as the amixer -d flag.
-
-
-Keyboard commands:
-==================
-
-Left & right arrow keys are used to select the channel (or device,
-depending on your preferred terminology). You can also use n (next) 
-and p (previous).
-
-Up/down arrows control the volume for the currently selected device.
-Both the left & right signals are controlled.
-You can also use "+" or "-" to turn volumes up or down.
-
-"M" toggles muting for the current channel (both left and right). You can
-mute left and right independently by using , and . respectively.
-
-SPACE toggles recording: the current channel will be added or removed from
-the sources used for recording. This only works on valid input channels,
-of course.
-
-"L" re-draws the screen.
-
-TAB does something interesting: it toggles the mode for volume display.
-This affects the numbers you see, but not the operation of the level
-controls. There seem to be two modes: one is percentages from 0-100, the
-other is called "exact mode" and varies from channel to channel. This
-shows you the settings as the soundcard understands them. All the channel
-level ranges are from 0 to a power of 2 minus one (e.g. 0-31 or 0-63).
-
-Quick Volume Changes
---------------------
-
-PageUp increases volume by 10.
-PageDown decreases volume by 10.
-Home sets volume to 100.
-End sets volume to 0.
-
-You can also control left & right levels for the current channel
-independently,
-according to this chart:
-
-Q  |  W  |  E    <-- UP
--------------
-Z  |  X  |  C    <---DOWN
-
-^     ^     ^
-|     |     +-- Right
-|     |
-|     +--- Both
-|
-Left
-
-
-If the current mixer channel is not a stereo channel, then all UP keys
-will work like W, and all DOWN keys will work like X.
-
-
-Exiting
-=======
-
-You can exit with ALT + Q, or by hitting ESC.
-
-
------------------------------------------------------------------
-
-Alsamixer has been written by Tim Janik <timj@gtk.org> and
-been furtherly improved by Jaroslav Kysela <perex@perex.cz>.
-This document was provided by Paul Winkler <zarmzarm@erols.com>.
index 47d8aed..ba05aca 100644 (file)
@@ -1,4 +1,4 @@
-.TH ALSAMIXER 1 "15 May 2001"
+.TH ALSAMIXER 1 "22 May 2009"
 .SH NAME
 alsamixer \- soundcard mixer for ALSA soundcard driver, with ncurses interface
 .SH SYNOPSIS
@@ -12,29 +12,25 @@ soundcard drivers. It supports multiple soundcards with multiple devices.
 .SH OPTIONS
 
 .TP
-\fI\-h, \-help\fP 
+\fI\-h, \-\-help\fP
 Help: show available flags.
 
 .TP
-\fI\-c\fP <card number or identification>
+\fI\-c, \-\-card\fP <card number or identification>
 Select the soundcard to use, if you have more than one. Cards are
 numbered from 0 (the default).
 
 .TP
-\fI\-D\fP <device identification>
+\fI\-D, \-\-device\fP <device identification>
 Select the mixer device to control.
 
 .TP
-\fI\-g\fP
-Toggle the using of colors.
-
-.TP
-\fI\-s\fP
-Minimize the mixer window.
+\fI\-V, \-\-view\fP <mode>
+Select the starting view mode, either \fIplayback\fP, \fIcapture\fP or \fIall\fP.
 
 .TP
-\fI\-V\fP <view mode>
-Select the starting view mode, either \fIplayback\fP, \fIcapture\fP or \fIall\fP.
+\fI\-g, \-\-no\-color\fP
+Toggle the using of colors.
 
 .SH MIXER VIEWS
 
@@ -60,7 +56,7 @@ You can toggle the switch via \fIm\fP key.
 
 When a mixer control has capture capability, the capture flag appears
 below the volume bar, too.  When the capture is turned off,
-\-\-\-\-\-\- is shown.  \fICAPTUR\fP in red appears when the
+\-\-\-\-\-\-\- is shown.  \fICAPTURE\fP in red appears when the
 capture switch is turned on.  In addition, \fIL\fP and \fIR\fP letters
 appear in left and right side to indicate that left and the right
 channels are turned on.
@@ -148,6 +144,13 @@ The number keys from \fI0\fP to \fI9\fP are to change the absolute volume
 quickly.  They correspond to 0 to 90% volume.
 
 .SS
+Selecting the Sound Card
+
+You can select another sound card by pressing the \fIF6\fP or \fIS\fP keys.
+This will show a list of available sound cards to choose from,
+and an entry to enter the mixer device name by hand.
+
+.SS
 Exiting
 
 Quit the program with \fIALT Q\fP, or by hitting \fIESC\fP.
@@ -169,6 +172,7 @@ fault. Plain old \fBxterm\fP seems to be fine.
 .SH AUTHOR
 .B alsamixer
 has been written by Tim Janik <timj@gtk.org> and
-been further improved by Jaroslav Kysela <perex@perex.cz>.
+been further improved by Jaroslav Kysela <perex@perex.cz>
+and Clemens Ladisch <clemens@ladisch.de>.
 
 This manual page was provided by Paul Winkler <zarmzarm@erols.com>.
diff --git a/alsamixer/alsamixer.c b/alsamixer/alsamixer.c
deleted file mode 100644 (file)
index 414033e..0000000
+++ /dev/null
@@ -1,2408 +0,0 @@
-/* AlsaMixer - Commandline mixer for the ALSA project Copyright (C) 1998,
- * 1999 Tim Janik <timj@gtk.org> and Jaroslav Kysela <perex@perex.cz>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
- *
- *
- * ChangeLog:
- *
- * Wed Feb 14 13:08:17 CET 2001   Jaroslav Kysela <perex@perex.cz>
- *
- *      * ported to the latest mixer 0.9.x API (function based)
- *
- * Fri Jun 23 14:10:00 MEST 2000  Jaroslav Kysela <perex@perex.cz>
- *
- *      * ported to new mixer 0.9.x API (simple control)
- *      * improved error handling (mixer_abort)
- *
- * Thu Mar  9 22:54:16 MET 2000  Takashi iwai <iwai@ww.uni-erlangen.de>
- *
- *     * a group is split into front, rear, center and woofer elements.
- *
- * Mon Jan  3 23:33:42 MET 2000  Jaroslav Kysela <perex@perex.cz>
- *
- *      * version 1.00
- *
- *      * ported to new mixer API (scontrol control)
- *
- * Sun Feb 21 19:55:01 1999  Tim Janik  <timj@gtk.org>
- *
- *     * bumped version to 0.10.
- *
- *     * added scrollable text views.
- *     we now feature an F1 Help screen and an F2 /proc info screen.
- *     the help screen does still require lots of work though.
- *
- *     * keys are evaluated view specific now.
- *
- *     * we feature meta-keys now, e.g. M-Tab as back-tab.
- *
- *     * if we are already in channel view and the user still hits Return,
- *     we do a refresh nonetheless, since 'r'/'R' got removed as a redraw
- *     key (reserved for capture volumes). 'l'/'L' is still preserved though,
- *     and actually needs to be to e.g. get around the xterm bold-artefacts.
- *
- *     * support terminals that can't write into lower right corner.
- *
- *     * undocumented '-s' option that will keep the screen to its
- *     minimum size, usefull for debugging only.
- *
- * Sun Feb 21 02:23:52 1999  Tim Janik  <timj@gtk.org>
- *
- *     * don't abort if snd_mixer_* functions failed due to EINTR,
- *     we simply retry on the next cycle. hopefully asoundlib preserves
- *     errno states correctly (Jaroslav can you asure that?).
- *
- *     * feature WINCH correctly, so we make a complete relayout on
- *     screen resizes. don't abort on too-small screen sizes anymore,
- *     but simply beep.
- *
- *     * redid the layout algorithm to fix some bugs and to preserve
- *     space for a flag indication line. the channels are
- *     nicer spread horizontally now (i.e. we also pad on the left and
- *     right screen bounds now).
- *
- *     * various other minor fixes.
- *
- *     * indicate whether ExactMode is active or not.
- *
- *     * fixed coding style to follow the GNU coding conventions.
- *
- *     * reverted capture volume changes since they broke ExactMode display.
- *
- *     * composed ChangeLog entries.
- *
- * 1998/11/04 19:43:45  perex
- *
- *     * Stereo capture source and route selection...
- *     provided by Carl van Schaik <carl@dreamcoat.che.uct.ac.za>.
- *
- * 1998/09/20 08:05:24  perex
- *
- *     * Fixed -m option...
- *
- * 1998/10/29 22:50:10
- *
- *     * initial checkin of alsamixer.c, written by Tim Janik, modified by
- *     Jaroslav Kysela to feature asoundlib.h instead of plain ioctl()s and
- *     automated updates after select() (i always missed that with OSS!).
- */
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-
-#include <errno.h>
-
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/signal.h>
-#include <sys/time.h>
-
-#include <locale.h>
-
-#ifndef CURSESINC
-#include <ncurses.h>
-#else
-#include CURSESINC
-#endif
-#include <time.h>
-
-#include <alsa/asoundlib.h>
-#include "aconfig.h"
-
-/* example compilation commandline:
- * clear; gcc -Wall -pipe -O2 alsamixer.c -o alsamixer -lasound -lncurses
- */
-
-/* --- defines --- */
-#define        PRGNAME          "alsamixer"
-#define        PRGNAME_UPPER    "AlsaMixer"
-#define        CHECK_ABORT(e,s,n) ({ if ((n) != -EINTR) mixer_abort ((e), (s), (n)); })
-#define GETCH_BLOCK(w)  ({ timeout ((w) ? -1 : 0); })
-
-#undef MAX
-#define MAX(a, b)  (((a) > (b)) ? (a) : (b))
-#undef MIN
-#define MIN(a, b)  (((a) < (b)) ? (a) : (b))
-#undef ABS
-#define ABS(a)     (((a) < 0) ? -(a) : (a))
-#undef CLAMP
-#define CLAMP(x, low, high)  (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
-
-#define MIXER_MIN_X    (18)                    /* abs minimum: 18 */
-#define        MIXER_TEXT_Y    (10)
-#define MIXER_CBAR_STD_HGT (10)
-#define        MIXER_MIN_Y     (MIXER_TEXT_Y + 6)      /* abs minimum: 16 */
-
-#define MIXER_BLACK    (COLOR_BLACK)
-#define MIXER_DARK_RED  (COLOR_RED)
-#define MIXER_RED       (COLOR_RED | A_BOLD)
-#define MIXER_GREEN     (COLOR_GREEN | A_BOLD)
-#define MIXER_ORANGE    (COLOR_YELLOW)
-#define MIXER_YELLOW    (COLOR_YELLOW | A_BOLD)
-#define MIXER_MARIN     (COLOR_BLUE)
-#define MIXER_BLUE      (COLOR_BLUE | A_BOLD)
-#define MIXER_MAGENTA   (COLOR_MAGENTA)
-#define MIXER_DARK_CYAN (COLOR_CYAN)
-#define MIXER_CYAN      (COLOR_CYAN | A_BOLD)
-#define MIXER_GREY      (COLOR_WHITE)
-#define MIXER_GRAY      (MIXER_GREY)
-#define MIXER_WHITE     (COLOR_WHITE | A_BOLD)
-
-
-/* --- views --- */
-enum {
-  VIEW_CHANNELS,
-  VIEW_PLAYBACK,
-  VIEW_CAPTURE,
-  VIEW_HELP,
-  VIEW_PROCINFO
-};
-
-
-/* --- variables --- */
-static WINDOW  *mixer_window = NULL;
-static int      mixer_needs_resize = 0;
-static int      mixer_minimize = 0;
-static int      mixer_no_lrcorner = 0;
-static int      mixer_view = VIEW_PLAYBACK;
-static int      mixer_view_saved = VIEW_PLAYBACK;
-static int      mixer_max_x = 0;
-static int      mixer_max_y = 0;
-static int      mixer_ofs_x = 0;
-static float    mixer_extra_space = 0;
-static int      mixer_cbar_height = 0;
-static int       mixer_text_y = MIXER_TEXT_Y;
-
-static char     card_id[64] = "default";
-static snd_mixer_t *mixer_handle;
-static char     mixer_card_name[128];
-static char     mixer_device_name[128];
-static int      mixer_level = 0;
-static struct snd_mixer_selem_regopt mixer_options;
-
-/* mixer bar channel : left or right */
-#define MIXER_CHN_LEFT         0
-#define MIXER_CHN_RIGHT                1
-/* mask for toggle mute and capture */
-#define MIXER_MASK_LEFT                (1 << 0)
-#define MIXER_MASK_RIGHT       (1 << 1)
-#define MIXER_MASK_STEREO      (MIXER_MASK_LEFT|MIXER_MASK_RIGHT)
-
-/* mixer split types */
-enum {
-  MIXER_ELEM_FRONT, MIXER_ELEM_REAR,
-  MIXER_ELEM_CENTER, MIXER_ELEM_WOOFER,
-  MIXER_ELEM_SIDE,
-  MIXER_ELEM_CAPTURE,
-  MIXER_ELEM_ENUM, MIXER_ELEM_CAPTURE_ENUM,
-  MIXER_ELEM_END
-};
-
-#define MIXER_ELEM_TYPE_MASK           0xff
-#define MIXER_ELEM_CAPTURE_SWITCH      0x100 /* bit */
-#define MIXER_ELEM_MUTE_SWITCH         0x200 /* bit */
-#define MIXER_ELEM_CAPTURE_SUFFIX      0x400
-#define MIXER_ELEM_HAS_VOLUME          0x800
-
-/* left and right channels for each type */
-static const snd_mixer_selem_channel_id_t mixer_elem_chn[][2] = {
-  { SND_MIXER_SCHN_FRONT_LEFT, SND_MIXER_SCHN_FRONT_RIGHT },
-  { SND_MIXER_SCHN_REAR_LEFT, SND_MIXER_SCHN_REAR_RIGHT },
-  { SND_MIXER_SCHN_FRONT_CENTER, SND_MIXER_SCHN_UNKNOWN },
-  { SND_MIXER_SCHN_WOOFER, SND_MIXER_SCHN_UNKNOWN },
-  { SND_MIXER_SCHN_SIDE_LEFT, SND_MIXER_SCHN_SIDE_RIGHT },
-  { SND_MIXER_SCHN_FRONT_LEFT, SND_MIXER_SCHN_FRONT_RIGHT },
-};
-
-static void    *mixer_sid = NULL;
-static int      mixer_n_selems = 0;
-static int       mixer_changed_state = 1;
-
-/* split scontrols */
-static int      mixer_n_elems = 0;
-static int      mixer_n_view_elems = 0;
-static int      mixer_n_vis_elems = 0;
-static int      mixer_first_vis_elem = 0;
-static int      mixer_focus_elem = 0;
-static int      mixer_have_old_focus = 0;
-static int *mixer_grpidx;
-static int *mixer_type;
-
-static int      mixer_volume_delta[2];         /* left/right volume delta in % */
-static int      mixer_volume_absolute = -1;    /* absolute volume settings in % */
-static int      mixer_balance_volumes = 0;     /* boolean */
-static unsigned         mixer_toggle_mute = 0;         /* left/right mask */
-static unsigned         mixer_toggle_capture = 0;      /* left/right mask */
-
-static int      mixer_hscroll_delta = 0;
-static int      mixer_vscroll_delta = 0;
-
-
-/* --- text --- */
-static int      mixer_procinfo_xoffs = 0;
-static int      mixer_procinfo_yoffs = 0;
-static int      mixer_help_xoffs = 0;
-static int      mixer_help_yoffs = 0;
-static char     *mixer_help_text =
-(
- " Esc     exit alsamixer\n"
- " F1 ?    show Help screen\n"
- " F2 /    show /proc info screen\n"
- " F3      show Playback controls only\n"
- " F4      show Capture controls only\n"
- " F5      show all controls\n"
- " Tab     toggle view mode\n"
- " Return  return to main screen\n"
- " Space   toggle Capture facility\n"
- " m M     toggle mute on both channels\n"
- " < >     toggle mute on left/right channel\n"
- " Up      increase left and right volume\n"
- " Down    decrease left and right volume\n"
- " Right   move (scroll) to the right next channel\n"
- " Left    move (scroll) to the left next channel\n"
- "\n"
- "Alsamixer has been written and is Copyrighted in 1998, 1999 by\n"
- "Tim Janik <timj@gtk.org> and Jaroslav Kysela <perex@perex.cz>.\n"
- );
-
-
-/* --- draw contexts --- */
-enum {
-  DC_DEFAULT,
-  DC_BACK,
-  DC_TEXT,
-  DC_PROMPT,
-  DC_CBAR_FRAME,
-  DC_CBAR_MUTE,
-  DC_CBAR_NOMUTE,
-  DC_CBAR_CAPTURE,
-  DC_CBAR_NOCAPTURE,
-  DC_CBAR_EMPTY,
-  DC_CBAR_LABEL,
-  DC_CBAR_FOCUS_LABEL,
-  DC_FOCUS,
-  DC_ANY_1,
-  DC_ANY_2,
-  DC_ANY_3,
-  DC_ANY_4,
-  DC_LAST
-};
-
-static int dc_fg[DC_LAST] = { 0 };
-static int dc_attrib[DC_LAST] = { 0 };
-static int dc_char[DC_LAST] = { 0 };
-static int mixer_do_color = 1;
-
-static void
-mixer_init_dc (int c,
-              int n,
-              int f,
-              int b,
-              int a)
-{
-  dc_fg[n] = f;
-  dc_attrib[n] = a;
-  dc_char[n] = c;
-  if (n > 0)
-    init_pair (n, dc_fg[n] & 0xf, b & 0x0f);
-}
-
-static int
-mixer_dc (int n)
-{
-  if (mixer_do_color)
-    attrset (COLOR_PAIR (n) | (dc_fg[n] & 0xfffffff0));
-  else
-    attrset (dc_attrib[n]);
-  
-  return dc_char[n];
-}
-
-static void
-mixer_init_draw_contexts (void)
-{
-  start_color ();
-  
-  mixer_init_dc ('.', DC_BACK, MIXER_WHITE, MIXER_BLACK, A_NORMAL);
-  mixer_init_dc ('.', DC_TEXT, MIXER_YELLOW, MIXER_BLACK, A_BOLD);
-  mixer_init_dc ('.', DC_PROMPT, MIXER_DARK_CYAN, MIXER_BLACK, A_NORMAL);
-  mixer_init_dc ('.', DC_CBAR_FRAME, MIXER_CYAN, MIXER_BLACK, A_BOLD);
-  mixer_init_dc ('M', DC_CBAR_MUTE, MIXER_DARK_CYAN, MIXER_BLACK, A_NORMAL);
-  mixer_init_dc ('O', DC_CBAR_NOMUTE, MIXER_WHITE, MIXER_GREEN, A_BOLD);
-  mixer_init_dc ('x', DC_CBAR_CAPTURE, MIXER_DARK_RED, MIXER_BLACK, A_BOLD);
-  mixer_init_dc ('-', DC_CBAR_NOCAPTURE, MIXER_GRAY, MIXER_BLACK, A_NORMAL);
-  mixer_init_dc (' ', DC_CBAR_EMPTY, MIXER_GRAY, MIXER_BLACK, A_DIM);
-  mixer_init_dc ('.', DC_CBAR_LABEL, MIXER_WHITE, MIXER_BLUE, A_REVERSE | A_BOLD);
-  mixer_init_dc ('.', DC_CBAR_FOCUS_LABEL, MIXER_RED, MIXER_BLUE, A_REVERSE | A_BOLD);
-  mixer_init_dc ('.', DC_FOCUS, MIXER_RED, MIXER_BLACK, A_BOLD);
-  mixer_init_dc (ACS_CKBOARD, DC_ANY_1, MIXER_WHITE, MIXER_WHITE, A_BOLD);
-  mixer_init_dc (ACS_CKBOARD, DC_ANY_2, MIXER_GREEN, MIXER_GREEN, A_BOLD);
-  mixer_init_dc (ACS_CKBOARD, DC_ANY_3, MIXER_RED, MIXER_RED, A_BOLD);
-  mixer_init_dc ('.', DC_ANY_4, MIXER_WHITE, MIXER_BLUE, A_BOLD);
-}
-
-#define        DC_FRAME        (DC_PROMPT)
-
-
-/* --- error types --- */
-typedef enum
-{
-  ERR_NONE,
-  ERR_OPEN,
-  ERR_FCN,
-  ERR_SIGNAL,
-  ERR_WINSIZE,
-} ErrType;
-
-
-/* --- prototypes --- */
-static void
-mixer_abort (ErrType error,
-            const char *err_string,
-            int xerrno)
-     __attribute__
-((noreturn));
-
-
-/* --- functions --- */
-static void
-mixer_clear (int full_redraw)
-{
-  int x, y;
-  int f = full_redraw ? 0 : 1;
-
-  mixer_dc (DC_BACK);
-
-  if (full_redraw)
-    clearok (mixer_window, TRUE);
-
-  /* buggy ncurses doesn't really write spaces with the specified
-   * color into the screen on clear () or erase ()
-   */
-  for (x = f; x < mixer_max_x - f; x++)
-    for (y = f; y < mixer_max_y - f; y++)
-      mvaddch (y, x, ' ');
-}
-
-static void
-mixer_abort (ErrType     error,
-            const char *err_string,
-            int         xerrno)
-{
-  if (mixer_window)
-    {
-      mixer_clear (TRUE);
-      refresh ();
-      keypad (mixer_window, FALSE);
-      leaveok (mixer_window, FALSE);
-      endwin ();
-      mixer_window = NULL;
-    }
-  printf ("\n");
-  
-  switch (error)
-    {
-    case ERR_OPEN:
-      fprintf (stderr,
-              PRGNAME ": function %s failed for %s: %s\n",
-              err_string,
-              card_id,
-              snd_strerror (xerrno));
-      break;
-    case ERR_FCN:
-      fprintf (stderr,
-              PRGNAME ": function %s failed: %s\n",
-              err_string,
-              snd_strerror (xerrno));
-      break;
-    case ERR_SIGNAL:
-      fprintf (stderr,
-              PRGNAME ": aborting due to signal `%s'\n",
-              err_string);
-      break;
-    case ERR_WINSIZE:
-      fprintf (stderr,
-              PRGNAME ": screen size too small (%dx%d)\n",
-              mixer_max_x,
-              mixer_max_y);
-      break;
-    default:
-      break;
-    }
-  
-  exit (error);
-}
-
-static int
-mixer_cbar_get_pos (int  elem_index,
-                   int *x_p,
-                   int *y_p)
-{
-  int x;
-  int y;
-  
-  if (elem_index < mixer_first_vis_elem ||
-      elem_index - mixer_first_vis_elem >= mixer_n_vis_elems)
-    return FALSE;
-  
-  elem_index -= mixer_first_vis_elem;
-  
-  x = mixer_ofs_x;
-  x += (3 + 2 + 3 + 1) * elem_index + mixer_extra_space * (elem_index + 1);
-
-  if (mixer_text_y + MIXER_CBAR_STD_HGT < mixer_max_y)
-    y = (mixer_text_y + mixer_cbar_height) / 2 - 1 + mixer_max_y / 2;
-  else
-    y = mixer_text_y - 1 + mixer_cbar_height;
-  if (y >= mixer_max_y - 1)
-    y = mixer_max_y - 2;
-  if (x_p)
-    *x_p = x;
-  if (y_p)
-    *y_p = y;
-  
-  return TRUE;
-}
-
-static int
-mixer_conv(int val, int omin, int omax, int nmin, int nmax)
-{
-       float orange = omax - omin, nrange = nmax - nmin;
-       
-       if (orange == 0)
-               return 0;
-       return ((nrange * (val - omin)) + (orange / 2)) / orange + nmin;
-}
-
-static int
-mixer_calc_volume(snd_mixer_elem_t *elem,
-                 int vol, int type,
-                 snd_mixer_selem_channel_id_t chn)
-{
-  int vol1;
-  long v;
-  long min, max;
-  if (type != MIXER_ELEM_CAPTURE)
-    snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
-  else
-    snd_mixer_selem_get_capture_volume_range(elem, &min, &max);
-  vol1 = (vol < 0) ? -vol : vol;
-  if (vol1 > 0) {
-    if (vol1 > 100)
-      vol1 = max;
-    else
-      vol1 = mixer_conv(vol1, 0, 100, min, max);
-    /* Note: we have delta in vol1 and we need to map our */
-    /*       delta value to hardware range */
-    vol1 -= min;
-    if (vol1 <= 0)
-      vol1 = 1;
-    if (vol < 0)
-      vol1 = -vol1;
-  }
-  if (type != MIXER_ELEM_CAPTURE)
-    snd_mixer_selem_get_playback_volume(elem, chn, &v);
-  else
-    snd_mixer_selem_get_capture_volume(elem, chn, &v);
-  vol1 += v;
-  return CLAMP(vol1, min, max);
-}
-
-static int
-mixer_convert_volume(snd_mixer_elem_t *elem,
-                 int vol, int type)
-{
-  long min, max;
-  if (type != MIXER_ELEM_CAPTURE)
-    snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
-  else
-    snd_mixer_selem_get_capture_volume_range(elem, &min, &max);
-  return  mixer_conv(vol, 0, 100, min, max);
-}
-
-/* update enum list */
-static void update_enum_list(snd_mixer_elem_t *elem, int chn, int delta)
-{
-  unsigned int eidx;
-  if (snd_mixer_selem_get_enum_item(elem, chn, &eidx) < 0)
-    return;
-  if (delta < 0) {
-    if (eidx == 0)
-      return;
-    eidx--;
-  } else {
-    int items = snd_mixer_selem_get_enum_items(elem);
-    if (items < 0)
-      return;
-    eidx++;
-    if (eidx >= items)
-      return;
-  }
-  snd_mixer_selem_set_enum_item(elem, chn, eidx);
-}
-
-/* set new channel values
- */
-static void
-mixer_write_cbar (int elem_index)
-{
-  snd_mixer_elem_t *elem;
-  int vleft, vright, vbalance;
-  int type;
-  snd_mixer_selem_id_t *sid;
-  snd_mixer_selem_channel_id_t chn_left, chn_right, chn;
-  int sw;
-
-  if (mixer_sid == NULL)
-    return;
-
-  sid = (snd_mixer_selem_id_t *)(((char *)mixer_sid) + snd_mixer_selem_id_sizeof() * mixer_grpidx[elem_index]);
-  elem = snd_mixer_find_selem(mixer_handle, sid);
-  if (elem == NULL)
-    CHECK_ABORT (ERR_FCN, "snd_mixer_find_selem()", -EINVAL);
-  type = mixer_type[elem_index] & MIXER_ELEM_TYPE_MASK;
-  chn_left = mixer_elem_chn[type][MIXER_CHN_LEFT];
-  chn_right = mixer_elem_chn[type][MIXER_CHN_RIGHT];
-  if (chn_right != SND_MIXER_SCHN_UNKNOWN) {
-    if (type != MIXER_ELEM_CAPTURE) {
-      if (!snd_mixer_selem_has_playback_channel(elem, chn_right))
-       chn_right = SND_MIXER_SCHN_UNKNOWN;
-    } else {
-      if (!snd_mixer_selem_has_capture_channel(elem, chn_right))
-       chn_right = SND_MIXER_SCHN_UNKNOWN;
-    }
-  }
-
-  /* volume
-   */
-  if ((mixer_volume_delta[MIXER_CHN_LEFT] ||
-       mixer_volume_delta[MIXER_CHN_RIGHT] ||
-       mixer_volume_absolute != -1 ||
-       mixer_balance_volumes) &&
-      (mixer_type[elem_index] & MIXER_ELEM_HAS_VOLUME)) {
-    int mono;
-    int joined;
-    mono = (chn_right == SND_MIXER_SCHN_UNKNOWN);
-    if (type != MIXER_ELEM_CAPTURE)
-      joined = snd_mixer_selem_has_playback_volume_joined(elem);
-    else
-      joined = snd_mixer_selem_has_capture_volume_joined(elem);
-    mono |= joined;
-    if (mixer_volume_absolute != -1) {
-      vbalance = vright = vleft = mixer_convert_volume(elem, mixer_volume_absolute, type);
-    } else {
-      if (mono && !mixer_volume_delta[MIXER_CHN_LEFT])
-        mixer_volume_delta[MIXER_CHN_LEFT] = mixer_volume_delta[MIXER_CHN_RIGHT];
-      vleft = mixer_calc_volume(elem, mixer_volume_delta[MIXER_CHN_LEFT], type, chn_left);
-      vbalance = vleft;
-      if (! mono) {
-        vright = mixer_calc_volume(elem, mixer_volume_delta[MIXER_CHN_RIGHT], type, chn_right);
-        vbalance += vright;
-        vbalance /= 2;
-      } else {
-        vright = vleft;
-      }
-    }
-
-      if (joined) {
-       for (chn = 0; chn < SND_MIXER_SCHN_LAST; chn++)
-         if (type != MIXER_ELEM_CAPTURE) {
-           if (snd_mixer_selem_has_playback_channel(elem, chn))
-             snd_mixer_selem_set_playback_volume(elem, chn, vleft);
-         } else {
-           if (snd_mixer_selem_has_capture_channel(elem, chn))
-             snd_mixer_selem_set_capture_volume(elem, chn, vleft);
-         }
-      } else {
-       if (mixer_balance_volumes)
-         vleft = vright = vbalance;
-       if (type != MIXER_ELEM_CAPTURE) {
-         if (snd_mixer_selem_has_playback_volume(elem) &&
-             snd_mixer_selem_has_playback_channel(elem, chn_left))
-           snd_mixer_selem_set_playback_volume(elem, chn_left, vleft);
-       } else {
-         if (snd_mixer_selem_has_capture_volume(elem) &&
-             snd_mixer_selem_has_capture_channel(elem, chn_left))
-           snd_mixer_selem_set_capture_volume(elem, chn_left, vleft);
-       }
-       if (! mono) {
-         if (type != MIXER_ELEM_CAPTURE) {
-           if (snd_mixer_selem_has_playback_volume(elem) &&
-               snd_mixer_selem_has_playback_channel(elem, chn_right))
-             snd_mixer_selem_set_playback_volume(elem, chn_right, vright);
-         } else {
-           if (snd_mixer_selem_has_capture_volume(elem) &&
-               snd_mixer_selem_has_capture_channel(elem, chn_right))
-             snd_mixer_selem_set_capture_volume(elem, chn_right, vright);
-         }
-       }
-      }
-  }
-
-  /* mute
-   */
-  if (mixer_type[elem_index] & MIXER_ELEM_MUTE_SWITCH) {
-    if (mixer_toggle_mute) {
-      if (snd_mixer_selem_has_playback_switch_joined(elem)) {
-       snd_mixer_selem_get_playback_switch(elem, chn_left, &sw);
-       snd_mixer_selem_set_playback_switch_all(elem, !sw);
-      } else {
-       if (mixer_toggle_mute & MIXER_MASK_LEFT) {
-         snd_mixer_selem_get_playback_switch(elem, chn_left, &sw);
-         snd_mixer_selem_set_playback_switch(elem, chn_left, !sw);
-       }
-       if (chn_right != SND_MIXER_SCHN_UNKNOWN && 
-           (mixer_toggle_mute & MIXER_MASK_RIGHT)) {
-         snd_mixer_selem_get_playback_switch(elem, chn_right, &sw);
-         snd_mixer_selem_set_playback_switch(elem, chn_right, !sw);
-       }
-      }
-    }
-  }
-  mixer_toggle_mute = 0;
-
-  /* capture
-   */
-  if (mixer_type[elem_index] & MIXER_ELEM_CAPTURE_SWITCH) {
-    if (mixer_toggle_capture && snd_mixer_selem_has_capture_switch(elem)) {
-      if (snd_mixer_selem_has_capture_switch_joined(elem)) {
-       snd_mixer_selem_get_capture_switch(elem, chn_left, &sw);
-       snd_mixer_selem_set_capture_switch_all(elem, !sw);
-      } else {
-       if ((mixer_toggle_capture & MIXER_MASK_LEFT) &&
-           snd_mixer_selem_has_capture_channel(elem, chn_left)) {
-         snd_mixer_selem_get_capture_switch(elem, chn_left, &sw);
-         snd_mixer_selem_set_capture_switch(elem, chn_left, !sw);
-       }
-       if (chn_right != SND_MIXER_SCHN_UNKNOWN && 
-           snd_mixer_selem_has_capture_channel(elem, chn_right) &&
-           (mixer_toggle_capture & MIXER_MASK_RIGHT)) {
-         snd_mixer_selem_get_capture_switch(elem, chn_right, &sw);
-         snd_mixer_selem_set_capture_switch(elem, chn_right, !sw);
-       }
-      }
-    }
-  }
-  mixer_toggle_capture = 0;
-
-  /* enum list
-   */
-  if (type == MIXER_ELEM_ENUM || type == MIXER_ELEM_CAPTURE_ENUM) {
-    if (mixer_volume_delta[MIXER_CHN_LEFT])
-      update_enum_list(elem, MIXER_CHN_LEFT, mixer_volume_delta[MIXER_CHN_LEFT]);
-    if (mixer_volume_delta[MIXER_CHN_RIGHT])
-      update_enum_list(elem, MIXER_CHN_RIGHT, mixer_volume_delta[MIXER_CHN_RIGHT]);
-  }
-
-  mixer_volume_delta[MIXER_CHN_LEFT] = mixer_volume_delta[MIXER_CHN_RIGHT] = 0;
-  mixer_volume_absolute = -1;
-  mixer_balance_volumes = 0;
-}
-
-
-static void draw_blank(int x, int y, int lines)
-{
-  int i;
-
-  mixer_dc (DC_TEXT);
-  for (i = 0; i < lines; i++)
-    mvaddstr (y - i, x, "         ");
-}
-
-/* show the current view mode */
-static void display_view_info(void)
-{
-  mixer_dc (DC_PROMPT);
-  mvaddstr (3, 2, "View:  Playback  Capture  All ");
-  mixer_dc (DC_TEXT);
-  switch (mixer_view) {
-  case VIEW_PLAYBACK:
-    mvaddstr (3, 8, "[Playback]");
-    break;
-  case VIEW_CAPTURE:
-    mvaddstr (3, 18, "[Capture]");
-    break;
-  default:
-    mvaddstr (3, 27, "[All]");
-    break;
-  }
-}
-
-/* show the information of the focused item */
-static void display_item_info(int elem_index, snd_mixer_selem_id_t *sid, char *extra_info)
-{
-  char string[64], idxstr[10];
-  int idx;
-  int i, xlen = mixer_max_x - 8;
-  if (xlen > sizeof(string) - 1)
-    xlen = sizeof(string) - 1;
-  mixer_dc (DC_PROMPT);
-  mvaddstr (4, 2, "Item: ");
-  mixer_dc (DC_TEXT);
-  idx = snd_mixer_selem_id_get_index(sid);
-  if (idx > 0)
-    snprintf(idxstr, sizeof(idxstr), " %i", snd_mixer_selem_id_get_index(sid));
-  snprintf(string, sizeof(string), "%s%s%s%s",
-          snd_mixer_selem_id_get_name(sid),
-          (mixer_type[elem_index] & MIXER_ELEM_CAPTURE_SUFFIX) ? " Capture" : "",
-          idx > 0 ? idxstr : "",
-          extra_info);
-  for (i = strlen(string); i < sizeof(string) - 1; i++)
-    string[i] = ' ';
-  string[xlen] = '\0';
-  addstr(string);
-}
-
-/* show the bar item name */
-static void display_item_name(int x, int y, int elem_index, snd_mixer_selem_id_t *sid)
-{
-  const char *suffix;
-  char string1[9], string[9];
-  int i;
-
-  mixer_dc (elem_index == mixer_focus_elem ? DC_CBAR_FOCUS_LABEL : DC_CBAR_LABEL);
-  if (mixer_type[elem_index] & MIXER_ELEM_CAPTURE_SUFFIX)
-    suffix = " Capture";
-  else
-    suffix = "";
-  if (snd_mixer_selem_id_get_index(sid) > 0)
-    snprintf(string1, sizeof(string1), "%s%s %d", snd_mixer_selem_id_get_name(sid),
-            suffix, snd_mixer_selem_id_get_index(sid));
-  else
-    snprintf(string1, sizeof(string1), "%s%s", snd_mixer_selem_id_get_name(sid), suffix);
-  string[8] = 0;
-  for (i = 0; i < 8; i++)
-    string[i] = ' ';
-  memcpy(string + (8 - strlen (string1)) / 2, string1, strlen(string1));
-  mvaddstr (y, x, string);
-}
-
-static void display_enum_list(snd_mixer_elem_t *elem, int y, int x)
-{
-  int cury, ch, err;
-
-  draw_blank(x, y, mixer_cbar_height + (mixer_view == VIEW_PLAYBACK ? 5 : 6));
-  
-  cury = y - 4;
-  for (ch = 0; ch < 2; ch++) {
-    unsigned int eidx, ofs;
-    char tmp[9];
-    err = snd_mixer_selem_get_enum_item(elem, ch, &eidx);
-    if (err < 0)
-      break;
-    if (snd_mixer_selem_get_enum_item_name(elem, eidx, sizeof(tmp) - 1, tmp) < 0)
-      break;
-    tmp[8] = 0;
-    ofs = (8 - strlen(tmp)) / 2;
-    mvaddstr(cury, x + ofs, tmp);
-    cury += 2;
-  }
-}
-
-static void draw_volume_bar(int x, int y, int elem_index, long vleft, long vright)
-{
-  int i, dc;
-
-  mixer_dc (DC_CBAR_FRAME);
-  if (mixer_type[elem_index] & MIXER_ELEM_MUTE_SWITCH) {
-    mvaddch (y, x + 2, ACS_LTEE);
-    mvaddch (y, x + 5, ACS_RTEE);
-  } else {
-    mvaddch (y, x + 2, ACS_LLCORNER);
-    mvaddch (y, x + 3, ACS_HLINE);
-    mvaddch (y, x + 4, ACS_HLINE);
-    mvaddch (y, x + 5, ACS_LRCORNER);
-  }
-  y--;
-  for (i = 0; i < mixer_cbar_height; i++)
-    {
-      mvaddstr (y - i, x, "         ");
-      mvaddch (y - i, x + 2, ACS_VLINE);
-      mvaddch (y - i, x + 5, ACS_VLINE);
-    }
-  for (i = 0; i < mixer_cbar_height; i++)
-    {
-      if (i + 1 >= 0.8 * mixer_cbar_height)
-       dc = DC_ANY_3;
-      else if (i + 1 >= 0.4 * mixer_cbar_height)
-       dc = DC_ANY_2;
-      else
-       dc = DC_ANY_1;
-      mvaddch (y, x + 3, mixer_dc (vleft > i * 100 / mixer_cbar_height ? dc : DC_CBAR_EMPTY));
-       mvaddch (y, x + 4, mixer_dc (vright > i * 100 / mixer_cbar_height ? dc : DC_CBAR_EMPTY));
-       y--;
-      }
-  
-  mixer_dc (DC_CBAR_FRAME);
-  mvaddstr (y, x, "         ");
-  mvaddch (y, x + 2, ACS_ULCORNER);
-  mvaddch (y, x + 3, ACS_HLINE);
-  mvaddch (y, x + 4, ACS_HLINE);
-  mvaddch (y, x + 5, ACS_URCORNER);
-}
-
-static void draw_playback_switch(int x, int y, int elem_index, int swl, int swr)
-{
-  int dc;
-
-  mixer_dc (DC_CBAR_FRAME);
-  mvaddch (y, x + 2, ACS_LLCORNER);
-  mvaddch (y, x + 3, ACS_HLINE);
-  mvaddch (y, x + 4, ACS_HLINE);
-  mvaddch (y, x + 5, ACS_LRCORNER);
-  mvaddstr (y - 1, x, "         ");
-  mvaddch (y - 1, x + 2, ACS_VLINE);
-  mvaddch (y - 1, x + 5, ACS_VLINE);
-  mvaddstr (y - 2, x, "         ");
-  mvaddch (y - 2, x + 2, ACS_ULCORNER);
-  mvaddch (y - 2, x + 3, ACS_HLINE);
-  mvaddch (y - 2, x + 4, ACS_HLINE);
-  mvaddch (y - 2, x + 5, ACS_URCORNER);
-  dc = swl ? DC_CBAR_NOMUTE : DC_CBAR_MUTE;
-  mvaddch (y - 1, x + 3, mixer_dc (dc));
-  dc = swr ? DC_CBAR_NOMUTE : DC_CBAR_MUTE;
-  mvaddch (y - 1, x + 4, mixer_dc (dc));
-}
-
-static void draw_capture_switch(int x, int y, int elem_index, int swl, int swr)
-{
-  int i;
-
-  if (swl || swr) {
-    mixer_dc (DC_CBAR_CAPTURE);
-    mvaddstr (y, x + 1, "CAPTUR");
-  } else {
-    for (i = 0; i < 6; i++)
-      mvaddch(y, x + i + 1, mixer_dc(DC_CBAR_NOCAPTURE));
-  }
-  mixer_dc (DC_CBAR_CAPTURE);
-  mvaddch (y - 1, x + 1, swl ? 'L' : ' ');
-  mvaddch (y - 1, x + 6, swr ? 'R' : ' ');
-}
-
-#ifndef SND_CTL_TLV_DB_GAIN_MUTE
-#define SND_CTL_TLV_DB_GAIN_MUTE       -9999999
-#endif
-
-static void dB_value(char *s, long val)
-{
-       if (val <= SND_CTL_TLV_DB_GAIN_MUTE)
-               strcpy(s, "mute");
-       else
-               snprintf(s, 10, "%3.2f", (float)val / 100);
-}
-                       
-static void
-mixer_update_cbar (int elem_index)
-{
-  snd_mixer_elem_t *elem;
-  long vleft, vright;
-  int type;
-  snd_mixer_selem_id_t *sid;
-  snd_mixer_selem_channel_id_t chn_left, chn_right;
-  int x, y;
-  int swl, swr;
-  char * extra_info;
-
-  /* set new scontrol indices and read info
-   */
-  if (mixer_sid == NULL)
-    return;
-
-  sid = (snd_mixer_selem_id_t *)(((char *)mixer_sid) + snd_mixer_selem_id_sizeof() * mixer_grpidx[elem_index]);
-  elem = snd_mixer_find_selem(mixer_handle, sid);
-  if (elem == NULL)
-    CHECK_ABORT (ERR_FCN, "snd_mixer_find_selem()", -EINVAL);
-
-  type = mixer_type[elem_index] & MIXER_ELEM_TYPE_MASK;
-  chn_left = mixer_elem_chn[type][MIXER_CHN_LEFT];
-  chn_right = mixer_elem_chn[type][MIXER_CHN_RIGHT];
-  if (chn_right != SND_MIXER_SCHN_UNKNOWN) {
-    if (type != MIXER_ELEM_CAPTURE) {
-      if (!snd_mixer_selem_has_playback_channel(elem, chn_right))
-       chn_right = SND_MIXER_SCHN_UNKNOWN;
-    } else {
-      if (!snd_mixer_selem_has_capture_channel(elem, chn_right))
-       chn_right = SND_MIXER_SCHN_UNKNOWN;
-    }
-  }
-
-  vleft = vright = 0;
-  if (type != MIXER_ELEM_CAPTURE && snd_mixer_selem_has_playback_volume(elem)) {
-    long vmin, vmax;
-    snd_mixer_selem_get_playback_volume_range(elem, &vmin, &vmax);
-    snd_mixer_selem_get_playback_volume(elem, chn_left, &vleft);
-    vleft = mixer_conv(vleft, vmin, vmax, 0, 100);
-    if (chn_right != SND_MIXER_SCHN_UNKNOWN) {
-      snd_mixer_selem_get_playback_volume(elem, chn_right, &vright);
-      vright = mixer_conv(vright, vmin, vmax, 0, 100);
-    } else {
-      vright = vleft;
-    }
-  }
-
-  if (type == MIXER_ELEM_CAPTURE && snd_mixer_selem_has_capture_volume(elem)) {
-    long vmin, vmax;
-    snd_mixer_selem_get_capture_volume_range(elem, &vmin, &vmax);
-    snd_mixer_selem_get_capture_volume(elem, chn_left, &vleft);
-    vleft = mixer_conv(vleft, vmin, vmax, 0, 100);
-    if (chn_right != SND_MIXER_SCHN_UNKNOWN) {
-      snd_mixer_selem_get_capture_volume(elem, chn_right, &vright);
-      vright = mixer_conv(vright, vmin, vmax, 0, 100);
-    } else {
-      vright = vleft;
-    }
-  }
-  
-  /* update the focused full bar name
-   */
-  if (elem_index == mixer_focus_elem) {
-    char tmp[50];
-    /* control muted? */
-    swl = swr = 1;
-    extra_info = "";
-    if (mixer_type[elem_index] & MIXER_ELEM_MUTE_SWITCH) {
-      snd_mixer_selem_get_playback_switch(elem, chn_left, &swl);
-      swr = swl;
-      if (chn_right != SND_MIXER_SCHN_UNKNOWN)
-       snd_mixer_selem_get_playback_switch(elem, chn_right, &swr);
-      extra_info = !swl && !swr ? " [Off]" : "";
-    }
-    if (type == MIXER_ELEM_ENUM || type == MIXER_ELEM_CAPTURE_ENUM) {
-      /* FIXME: should show the item names of secondary and later channels... */
-      unsigned int eidx, length;
-      tmp[0]=' ';
-      tmp[1]='[';
-      if (! snd_mixer_selem_get_enum_item(elem, 0, &eidx) &&
-         ! snd_mixer_selem_get_enum_item_name(elem, eidx, sizeof(tmp) - 3, tmp+2)) {
-       tmp[sizeof(tmp)-2] = 0;
-       length=strlen(tmp);
-       tmp[length]=']';
-       tmp[length+1]=0;
-       extra_info = tmp;
-      }
-    }
-    if (type != MIXER_ELEM_CAPTURE && snd_mixer_selem_has_playback_volume(elem)) {
-       long vdbleft, vdbright;
-       unsigned int length;
-       if (!snd_mixer_selem_get_playback_dB(elem, chn_left, &vdbleft)) {
-               char tmpl[10], tmpr[10];
-               dB_value(tmpl, vdbleft);
-               if ((chn_right != SND_MIXER_SCHN_UNKNOWN) &&
-                    (!snd_mixer_selem_get_playback_dB(elem, chn_right, &vdbright))) {
-                       dB_value(tmpr, vdbright);
-                       snprintf(tmp, 48, " [dB gain=%s, %s]", tmpl, tmpr);
-               } else {
-                       snprintf(tmp, 48, " [dB gain=%s]", tmpl);
-               }
-               tmp[sizeof(tmp)-2] = 0;
-               length=strlen(tmp);
-               tmp[length+1]=0;
-               extra_info = tmp;
-       }
-    }
-    if (type == MIXER_ELEM_CAPTURE && snd_mixer_selem_has_capture_volume(elem)) {
-       long vdbleft, vdbright;
-       unsigned int length;
-       if (!snd_mixer_selem_get_capture_dB(elem, chn_left, &vdbleft)) {
-               char tmpl[10], tmpr[10];
-               dB_value(tmpl, vdbleft);
-               if ((chn_right != SND_MIXER_SCHN_UNKNOWN) &&
-                    (!snd_mixer_selem_get_capture_dB(elem, chn_right, &vdbright))) {
-                       dB_value(tmpr, vdbright);
-                       snprintf(tmp, 48, " [dB gain=%s, %s]", tmpl, tmpr);
-               } else {
-                       snprintf(tmp, 48, " [dB gain=%s]", tmpl);
-               }
-               tmp[sizeof(tmp)-2] = 0;
-               length=strlen(tmp);
-               tmp[length+1]=0;
-               extra_info = tmp;
-       }
-    }
-    display_item_info(elem_index, sid, extra_info);
-  }
-
-  /* get channel bar position
-   */
-  if (!mixer_cbar_get_pos (elem_index, &x, &y))
-    return;
-
-  /* channel bar name
-   */
-  display_item_name(x, y, elem_index, sid);
-  y--;
-  
-  /* enum list? */
-  if (type == MIXER_ELEM_ENUM || type == MIXER_ELEM_CAPTURE_ENUM) {
-    display_enum_list(elem, y, x);
-    return; /* no more to display */
-  } 
-
-  /* current channel values
-   */
-  mixer_dc (DC_BACK);
-  mvaddstr (y, x, "         ");
-  if (mixer_type[elem_index] & MIXER_ELEM_HAS_VOLUME) {
-    char string[4];
-    mixer_dc (DC_TEXT);
-    if (chn_right == SND_MIXER_SCHN_UNKNOWN) {
-      /* mono */
-      snprintf (string, sizeof(string), "%ld", vleft);
-      mvaddstr (y, x + 4 - strlen (string) / 2, string);
-    } else {
-      /* stereo */
-      snprintf (string, sizeof(string), "%ld", vleft);
-      mvaddstr (y, x + 3 - strlen (string), string);
-      mixer_dc (DC_CBAR_FRAME);
-      mvaddch (y, x + 3, '<');
-      mvaddch (y, x + 4, '>');
-      mixer_dc (DC_TEXT);
-      snprintf (string, sizeof(string), "%ld", vright);
-      mvaddstr (y, x + 5, string);
-    }
-  }
-  y--;
-  
-  /* capture input?
-   */
-  if (mixer_view == VIEW_CAPTURE || mixer_view == VIEW_CHANNELS) {
-    if ((mixer_type[elem_index] & MIXER_ELEM_CAPTURE_SWITCH) &&
-       snd_mixer_selem_has_capture_switch(elem)) {
-      int has_r_sw = chn_right != SND_MIXER_SCHN_UNKNOWN &&
-       snd_mixer_selem_has_capture_channel(elem, chn_right);
-      snd_mixer_selem_get_capture_switch(elem, chn_left, &swl);
-      if (has_r_sw)
-       snd_mixer_selem_get_capture_switch(elem, chn_right, &swr);
-      else
-       swr = swl;
-      draw_capture_switch(x, y, elem_index, swl, swr);
-    } else
-      draw_blank(x, y, 2);
-    y--;
-  }
-
-  /* mute switch */
-  if (mixer_view == VIEW_PLAYBACK || mixer_view == VIEW_CHANNELS) {
-    if (mixer_type[elem_index] & MIXER_ELEM_MUTE_SWITCH) {
-      snd_mixer_selem_get_playback_switch(elem, chn_left, &swl);
-      if (chn_right != SND_MIXER_SCHN_UNKNOWN)
-       snd_mixer_selem_get_playback_switch(elem, chn_right, &swr);
-      else
-       swr = swl;
-      draw_playback_switch(x, y, elem_index, swl, swr);
-    } else {
-      mixer_dc (DC_CBAR_FRAME);
-      mvaddstr (y, x + 2, "    ");
-      draw_blank(x, y - 1, 2);
-    }
-    y -= 2;
-  }
-
-  /* left/right volume bar
-   */
-  if (mixer_type[elem_index] & MIXER_ELEM_HAS_VOLUME)
-    draw_volume_bar(x, y, elem_index, vleft, vright);
-  else {
-    if (mixer_view == VIEW_CAPTURE)
-      mvaddstr (y, x + 2, "    ");
-    draw_blank(x, y - 1, mixer_cbar_height + 1);
-  }
-}
-
-static void
-mixer_update_cbars (void)
-{
-  static int o_x = 0;
-  static int o_y = 0;
-  int i, x, y;
-  
-  display_view_info();
-  if (!mixer_cbar_get_pos (mixer_focus_elem, &x, &y))
-    {
-      if (mixer_focus_elem < mixer_first_vis_elem)
-       mixer_first_vis_elem = mixer_focus_elem;
-      else if (mixer_focus_elem >= mixer_first_vis_elem + mixer_n_vis_elems)
-       mixer_first_vis_elem = mixer_focus_elem - mixer_n_vis_elems + 1;
-      mixer_cbar_get_pos (mixer_focus_elem, &x, &y);
-    }
-  if (mixer_first_vis_elem + mixer_n_vis_elems >= mixer_n_view_elems) {
-     mixer_first_vis_elem = mixer_n_view_elems - mixer_n_vis_elems;
-     if (mixer_first_vis_elem < 0)
-       mixer_first_vis_elem = 0;
-     mixer_cbar_get_pos (mixer_focus_elem, &x, &y);
-  }
-  mixer_write_cbar(mixer_focus_elem);
-  for (i = 0; i < mixer_n_vis_elems; i++) {
-    if (i + mixer_first_vis_elem >= mixer_n_view_elems)
-      continue;
-    mixer_update_cbar (i + mixer_first_vis_elem);
-  }
-  
-  /* draw focused cbar
-   */
-  if (mixer_have_old_focus)
-    {
-      mixer_dc (DC_BACK);
-      mvaddstr (o_y, o_x, " ");
-      mvaddstr (o_y, o_x + 9, " ");
-    }
-  o_x = x - 1;
-  o_y = y;
-  mixer_dc (DC_FOCUS);
-  mvaddstr (o_y, o_x, "<");
-  mvaddstr (o_y, o_x + 9, ">");
-  mixer_have_old_focus = 1;
-}
-
-static void
-mixer_draw_frame (void)
-{
-  char string[128];
-  int i;
-  int max_len;
-  
-  /* card name
-   */
-  mixer_dc (DC_PROMPT);
-  mvaddstr (1, 2, "Card: ");
-  mixer_dc (DC_TEXT);
-  sprintf (string, "%s", mixer_card_name);
-  max_len = mixer_max_x - 2 - 6 - 2;
-  if ((int)strlen (string) > max_len)
-    string[max_len] = 0;
-  addstr (string);
-  
-  /* device name
-   */
-  mixer_dc (DC_PROMPT);
-  mvaddstr (2, 2, "Chip: ");
-  mixer_dc (DC_TEXT);
-  sprintf (string, "%s", mixer_device_name);
-  max_len = mixer_max_x - 2 - 6 - 2;
-  if ((int)strlen (string) > max_len)
-    string[max_len] = 0;
-  addstr (string);
-
-  /* lines
-   */
-  mixer_dc (DC_FRAME);
-  for (i = 1; i < mixer_max_y - 1; i++)
-    {
-      mvaddch (i, 0, ACS_VLINE);
-      mvaddch (i, mixer_max_x - 1, ACS_VLINE);
-    }
-  for (i = 1; i < mixer_max_x - 1; i++)
-    {
-      mvaddch (0, i, ACS_HLINE);
-      mvaddch (mixer_max_y - 1, i, ACS_HLINE);
-    }
-  
-  /* corners
-   */
-  mvaddch (0, 0, ACS_ULCORNER);
-  mvaddch (0, mixer_max_x - 1, ACS_URCORNER);
-  mvaddch (mixer_max_y - 1, 0, ACS_LLCORNER);
-  if (!mixer_no_lrcorner)
-    mvaddch (mixer_max_y - 1, mixer_max_x - 1, ACS_LRCORNER);
-  else
-    {
-      mvaddch (mixer_max_y - 2, mixer_max_x - 1, ACS_LRCORNER);
-      mvaddch (mixer_max_y - 2, mixer_max_x - 2, ACS_ULCORNER);
-      mvaddch (mixer_max_y - 1, mixer_max_x - 2, ACS_LRCORNER);
-    }
-
-  /* left/right scroll indicators */
-  switch (mixer_view) {
-  case VIEW_PLAYBACK:
-  case VIEW_CAPTURE:
-  case VIEW_CHANNELS:
-    if (mixer_cbar_height > 0) {
-      int ind_hgt = (mixer_cbar_height + 1) / 2;
-      int ind_ofs = mixer_max_y / 2 - ind_hgt/2;
-      /* left scroll possible? */
-      if (mixer_first_vis_elem > 0) {
-       for (i = 0; i < ind_hgt; i++)
-         mvaddch (i + ind_ofs, 0, '<');
-      }
-      /* right scroll possible? */
-      if (mixer_first_vis_elem + mixer_n_vis_elems < mixer_n_view_elems) {
-       for (i = 0; i < ind_hgt; i++)
-         mvaddch (i + ind_ofs, mixer_max_x - 1, '>');
-      }
-    }
-    break;
-  default:
-    break;
-  }
-
-  /* program title
-   */
-  sprintf (string, "%s v%s (Press Escape to quit)", PRGNAME_UPPER, VERSION);
-  max_len = strlen (string);
-  if (mixer_max_x >= max_len + 4)
-    {
-      mixer_dc (DC_PROMPT);
-      mvaddch (0, mixer_max_x / 2 - max_len / 2 - 1, '[');
-      mvaddch (0, mixer_max_x / 2 - max_len / 2 + max_len, ']');
-    }
-  if (mixer_max_x >= max_len + 2)
-    {
-      mixer_dc (DC_TEXT);
-      mvaddstr (0, mixer_max_x / 2 - max_len / 2, string);
-    }
-}
-
-static char*
-mixer_offset_text (char **t,
-                  int    col,
-                  int   *length)
-{
-  char *p = *t;
-  char *r;
-
-  while (*p && *p != '\n' && col--)
-    p++;
-  if (*p == '\n' || !*p)
-    {
-      if (*p == '\n')
-       p++;
-      *length = 0;
-      *t = p;
-      return p;
-    }
-
-  r = p;
-  while (*r && *r != '\n' && (*length)--)
-    r++;
-
-  *length = r - p;
-  while (*r && *r != '\n')
-    r++;
-  if (*r == '\n')
-    r++;
-  *t = r;
-
-  return p;
-}
-
-static void
-mixer_show_text (char *title,
-                char *text,
-                int  *xoffs,
-                int  *yoffs)
-{
-  int tlines = 0, tcols = 0;
-  float hscroll, vscroll;
-  float hoffs, voffs;
-  char *p, *text_offs = text;
-  int x1, x2, y1, y2;
-  int i, n, l, r;
-  unsigned long block, stipple;
-
-  /* coords
-   */
-  x1 = 2;
-  x2 = mixer_max_x - 3;
-  y1 = 4;
-  y2 = mixer_max_y - 2;
-
-  if ((y2 - y1) < 3 || (x2 - x1) < 3)
-    return;
-
-  /* text dimensions
-   */
-  l = 0;
-  for (p = text; *p; p++)
-    if (*p == '\n')
-      {
-       tlines++;
-       tcols = MAX (l, tcols);
-       l = 0;
-      }
-    else
-      l++;
-  tcols = MAX (l, tcols);
-  if (p > text && *(p - 1) != '\n')
-    tlines++;
-
-  /* scroll areas / offsets
-   */
-  l = x2 - x1 - 2;
-  if (l > tcols)
-    {
-      x1 += (l - tcols) / 2;
-      x2 = x1 + tcols + 1;
-    }
-  if (mixer_hscroll_delta)
-    {
-      *xoffs += mixer_hscroll_delta;
-      mixer_hscroll_delta = 0;
-      if (*xoffs < 0)
-       {
-         *xoffs = 0;
-         beep ();
-       }
-      else if (*xoffs > tcols - l - 1)
-       {
-         *xoffs = MAX (0, tcols - l - 1);
-         beep ();
-       }
-    }
-  if (tcols - l - 1 <= 0)
-    {
-      hscroll = 1;
-      hoffs = 0;
-    }
-  else
-    {
-      hscroll = ((float) l) / tcols;
-      hoffs = ((float) *xoffs) / (tcols - l - 1);
-    }
-
-  l = y2 - y1 - 2;
-  if (l > tlines)
-    {
-      y1 += (l - tlines) / 2;
-      y2 = y1 + tlines + 1;
-    }
-  if (mixer_vscroll_delta)
-    {
-      *yoffs += mixer_vscroll_delta;
-      mixer_vscroll_delta = 0;
-      if (*yoffs < 0)
-       {
-         *yoffs = 0;
-         beep ();
-       }
-      else if (*yoffs > tlines - l - 1)
-       {
-         *yoffs = MAX (0, tlines - l - 1);
-         beep ();
-       }
-    }
-  if (tlines - l - 1 <= 0)
-    {
-      voffs = 0;
-      vscroll = 1;
-    }
-  else
-    {
-      vscroll = ((float) l) / tlines;
-      voffs = ((float) *yoffs) / (tlines - l - 1);
-    }
-
-  /* colors
-   */
-  mixer_dc (DC_ANY_4);
-
-  /* corners
-   */
-  mvaddch (y2, x2, ACS_LRCORNER);
-  mvaddch (y2, x1, ACS_LLCORNER);
-  mvaddch (y1, x1, ACS_ULCORNER);
-  mvaddch (y1, x2, ACS_URCORNER);
-
-  /* left + upper border
-   */
-  for (i = y1 + 1; i < y2; i++)
-    mvaddch (i, x1, ACS_VLINE);
-  for (i = x1 + 1; i < x2; i++)
-    mvaddch (y1, i, ACS_HLINE);
-  if (title)
-    {
-      l = strlen (title);
-      if (l <= x2 - x1 - 3)
-       {
-         mvaddch (y1, x1 + 1 + (x2 - x1 - l) / 2 - 1, '[');
-         mvaddch (y1, x1 + 1 + (x2 - x1 - l) / 2 + l, ']');
-       }
-      if (l <= x2 - x1 - 1)
-       {
-         mixer_dc (DC_CBAR_LABEL);
-         mvaddstr (y1, x1 + 1 + (x2 - x1 - l) / 2, title);
-       }
-      mixer_dc (DC_ANY_4);
-    }
-
-  stipple = ACS_CKBOARD;
-  block = ACS_BLOCK;
-  if (block == '#' && ACS_BOARD == '#')
-    {
-      block = stipple;
-      stipple = ACS_BLOCK;
-    }
-
-  /* lower scroll border
-   */
-  l = x2 - x1 - 1;
-  n = hscroll * l;
-  r = (hoffs + 1.0 / (2 * (l - n - 1))) * (l - n - 1);
-  for (i = 0; i < l; i++)
-    mvaddch (y2, i + x1 + 1, hscroll >= 1 ? ACS_HLINE :
-            i >= r && i <= r + n ? block : stipple);
-
-  /* right scroll border
-   */
-  l = y2 - y1 - 1;
-  n = vscroll * l;
-  r = (voffs + 1.0 / (2 * (l - n - 1))) * (l - n - 1);
-  for (i = 0; i < l; i++)
-    mvaddch (i + y1 + 1, x2, vscroll >= 1 ? ACS_VLINE :
-            i >= r && i <= r + n ? block : stipple);
-
-  /* show text
-   */
-  x1++; y1++;
-  for (i = 0; i < *yoffs; i++)
-    {
-      l = 0;
-      mixer_offset_text (&text_offs, 0, &l);
-    }
-  for (i = y1; i < y2; i++)
-    {
-      l = x2 - x1;
-      p = mixer_offset_text (&text_offs, *xoffs, &l);
-      n = x1;
-      while (l--)
-       mvaddch (i, n++, *p++);
-      while (n < x2)
-       mvaddch (i, n++, ' ');
-    }
-}
-
-struct vbuffer
-{
-  char *buffer;
-  int size;
-  int len;
-};
-
-static void
-vbuffer_kill (struct vbuffer *vbuf)
-{
-  if (vbuf->size)
-    free (vbuf->buffer);
-  vbuf->buffer = NULL;
-  vbuf->size = 0;
-  vbuf->len = 0;
-}
-
-#define vbuffer_append_string(vb,str)  vbuffer_append (vb, str, strlen (str))
-static void
-vbuffer_append (struct vbuffer *vbuf,
-               char           *text,
-               int             len)
-{
-  if (vbuf->size - vbuf->len <= len)
-    {
-      vbuf->size += len + 1;
-      vbuf->buffer = realloc (vbuf->buffer, vbuf->size);
-    }
-  memcpy (vbuf->buffer + vbuf->len, text, len);
-  vbuf->len += len;
-  vbuf->buffer[vbuf->len] = 0;
-}
-
-static int
-vbuffer_append_file (struct vbuffer *vbuf,
-                    char           *name)
-{
-  int fd;
-
-  fd = open (name, O_RDONLY);
-  if (fd >= 0)
-    {
-      char buffer[1025];
-      int l;
-
-      do
-       {
-         l = read (fd, buffer, 1024);
-         
-         vbuffer_append (vbuf, buffer, MAX (0, l));
-       }
-      while (l > 0 || (l < 0 && (errno == EAGAIN || errno == EINTR)));
-
-      close (fd);
-
-      return 0;
-    }
-  else
-    return 1;
-}
-
-static void
-mixer_show_procinfo (void)
-{
-  struct vbuffer vbuf = { NULL, 0, 0 };
-
-  vbuffer_append_string (&vbuf, "\n");
-  vbuffer_append_string (&vbuf, "/proc/asound/version:\n");
-  vbuffer_append_string (&vbuf, "====================\n");
-  if (vbuffer_append_file (&vbuf, "/proc/asound/version"))
-    {
-      vbuffer_kill (&vbuf);
-      mixer_procinfo_xoffs = mixer_procinfo_yoffs = 0;
-      mixer_show_text ("/proc",
-                      " No /proc information available. ",
-                      &mixer_procinfo_xoffs, &mixer_procinfo_yoffs);
-      return;
-    }
-  else
-    vbuffer_append_file (&vbuf, "/proc/asound/meminfo");
-
-  vbuffer_append_string (&vbuf, "\n");
-  vbuffer_append_string (&vbuf, "/proc/asound/cards:\n");
-  vbuffer_append_string (&vbuf, "===================\n");
-  if (vbuffer_append_file (&vbuf, "/proc/asound/cards"))
-    vbuffer_append_string (&vbuf, "No information available.\n");
-
-  vbuffer_append_string (&vbuf, "\n");
-  vbuffer_append_string (&vbuf, "/proc/asound/devices:\n");
-  vbuffer_append_string (&vbuf, "=====================\n");
-  if (vbuffer_append_file (&vbuf, "/proc/asound/devices"))
-    vbuffer_append_string (&vbuf, "No information available.\n");
-
-  vbuffer_append_string (&vbuf, "\n");
-  vbuffer_append_string (&vbuf, "/proc/asound/oss/devices:\n");
-  vbuffer_append_string (&vbuf, "=========================\n");
-  if (vbuffer_append_file (&vbuf, "/proc/asound/oss/devices"))
-    vbuffer_append_string (&vbuf, "No information available.\n");
-
-  vbuffer_append_string (&vbuf, "\n");
-  vbuffer_append_string (&vbuf, "/proc/asound/timers:\n");
-  vbuffer_append_string (&vbuf, "====================\n");
-  if (vbuffer_append_file (&vbuf, "/proc/asound/timers"))
-    vbuffer_append_string (&vbuf, "No information available.\n");
-
-  vbuffer_append_string (&vbuf, "\n");
-  vbuffer_append_string (&vbuf, "/proc/asound/pcm:\n");
-  vbuffer_append_string (&vbuf, "=================\n");
-  if (vbuffer_append_file (&vbuf, "/proc/asound/pcm"))
-    vbuffer_append_string (&vbuf, "No information available.\n");
-
-  mixer_show_text ("/proc", vbuf.buffer,
-                  &mixer_procinfo_xoffs, &mixer_procinfo_yoffs);
-  vbuffer_kill (&vbuf);
-}
-
-static int
-mixer_event (snd_mixer_t *mixer, unsigned int mask, snd_mixer_elem_t *elem)
-{
-  mixer_changed_state = 1;
-  return 0;
-}
-
-static void
-mixer_init (void)
-{
-  snd_ctl_card_info_t *hw_info;
-  snd_ctl_t *ctl_handle;
-  int err;
-  snd_ctl_card_info_alloca(&hw_info);
-  
-  if ((err = snd_ctl_open (&ctl_handle, card_id, 0)) < 0)
-    mixer_abort (ERR_OPEN, "snd_ctl_open", err);
-  if ((err = snd_ctl_card_info (ctl_handle, hw_info)) < 0)
-    mixer_abort (ERR_FCN, "snd_ctl_card_info", err);
-  snd_ctl_close (ctl_handle);
-  /* open mixer device
-   */
-  if ((err = snd_mixer_open (&mixer_handle, 0)) < 0)
-    mixer_abort (ERR_FCN, "snd_mixer_open", err);
-  if (mixer_level == 0 && (err = snd_mixer_attach (mixer_handle, card_id)) < 0)
-    mixer_abort (ERR_FCN, "snd_mixer_attach", err);
-  if ((err = snd_mixer_selem_register (mixer_handle, mixer_level > 0 ? &mixer_options : NULL, NULL)) < 0)
-    mixer_abort (ERR_FCN, "snd_mixer_selem_register", err);
-  snd_mixer_set_callback (mixer_handle, mixer_event);
-  if ((err = snd_mixer_load (mixer_handle)) < 0)
-    mixer_abort (ERR_FCN, "snd_mixer_load", err);
-  
-  /* setup global variables
-   */
-  strcpy(mixer_card_name, snd_ctl_card_info_get_name(hw_info));
-  strcpy(mixer_device_name, snd_ctl_card_info_get_mixername(hw_info));
-}
-
-/* init mixer screen
- */
-static void
-recalc_screen_size (void)
-{
-  getmaxyx (mixer_window, mixer_max_y, mixer_max_x);
-  if (mixer_minimize)
-    {
-      mixer_max_x = MIXER_MIN_X;
-      mixer_max_y = MIXER_MIN_Y;
-    }
-  mixer_ofs_x = 2 /* extra begin padding: */ + 1;
-
-  /* required allocations */
-  mixer_n_vis_elems = (mixer_max_x - mixer_ofs_x * 2 + 1) / 9;
-  mixer_n_vis_elems = CLAMP (mixer_n_vis_elems, 1, mixer_n_view_elems);
-  mixer_extra_space = mixer_max_x - mixer_ofs_x * 2 + 1 - mixer_n_vis_elems * 9;
-  mixer_extra_space = MAX (0, mixer_extra_space / (mixer_n_vis_elems + 1));
-  mixer_text_y = MIXER_TEXT_Y;
-  if (mixer_view == VIEW_PLAYBACK || mixer_view == VIEW_CHANNELS)
-    mixer_text_y += 2; /* row for mute switch */
-  if (mixer_view == VIEW_CAPTURE || mixer_view == VIEW_CHANNELS)
-    mixer_text_y++; /* row for capture switch */
-  if (mixer_text_y + MIXER_CBAR_STD_HGT < mixer_max_y)
-    mixer_cbar_height = MIXER_CBAR_STD_HGT + MAX (1, mixer_max_y - mixer_text_y - MIXER_CBAR_STD_HGT + 1) / 2;
-  else
-    mixer_cbar_height = MAX (1, mixer_max_y - mixer_text_y);
-}
-
-static void
-mixer_reinit (void)
-{
-  snd_mixer_elem_t *elem;
-  int idx, elem_index, i, j, selem_count;
-  snd_mixer_selem_id_t *sid;
-  snd_mixer_selem_id_t *focus_gid;
-  int focus_type = -1;
-  snd_mixer_selem_id_alloca(&focus_gid);
-  
-  if (!mixer_changed_state)
-    return;
-  if (mixer_sid) {
-    snd_mixer_selem_id_copy(focus_gid, (snd_mixer_selem_id_t *)(((char *)mixer_sid) + snd_mixer_selem_id_sizeof() * mixer_grpidx[mixer_focus_elem]));
-    focus_type = mixer_type[mixer_focus_elem] & MIXER_ELEM_TYPE_MASK;
-  }
-__again:
-  mixer_changed_state = 0;
-  if (mixer_sid != NULL)
-    free(mixer_sid);
-  selem_count = snd_mixer_get_count(mixer_handle);
-  mixer_sid = malloc(snd_mixer_selem_id_sizeof() * selem_count);
-  if (mixer_sid == NULL)
-    mixer_abort (ERR_FCN, "malloc", 0);
-  
-  mixer_n_selems = 0;
-  for (elem = snd_mixer_first_elem(mixer_handle); elem; elem = snd_mixer_elem_next(elem)) {
-    sid = (snd_mixer_selem_id_t *)(((char *)mixer_sid) + snd_mixer_selem_id_sizeof() * mixer_n_selems);
-    if (mixer_changed_state)
-      goto __again;
-    if (!snd_mixer_selem_is_active(elem))
-      continue;
-    snd_mixer_selem_get_id(elem, sid);
-    mixer_n_selems++;
-  }
-
-  mixer_n_elems = 0;
-  for (idx = 0; idx < mixer_n_selems; idx++) {
-    int nelems_added = 0;
-    sid = (snd_mixer_selem_id_t *)(((char *)mixer_sid) + snd_mixer_selem_id_sizeof() * idx);
-    if (mixer_changed_state)
-      goto __again;
-    elem = snd_mixer_find_selem(mixer_handle, sid);
-    if (elem == NULL)
-      CHECK_ABORT (ERR_FCN, "snd_mixer_find_selem()", -EINVAL);
-    for (i = 0; i < MIXER_ELEM_CAPTURE; i++) {
-      int ok;
-      for (j = ok = 0; j < 2; j++) {
-       if (mixer_changed_state)
-         goto __again;
-       if (snd_mixer_selem_has_playback_channel(elem, mixer_elem_chn[i][j]))
-         ok++;
-      }
-      if (ok) {
-       nelems_added++;
-       mixer_n_elems++;
-      }
-    }
-    if (snd_mixer_selem_has_capture_volume(elem) ||
-       (nelems_added == 0 && snd_mixer_selem_has_capture_switch(elem)))
-      mixer_n_elems++;
-  }
-
-  if (mixer_type)
-    free(mixer_type);
-  mixer_type = (int *)calloc(mixer_n_elems, sizeof(int));
-  if (mixer_type == NULL)
-    mixer_abort(ERR_FCN, "malloc", 0);
-  if (mixer_grpidx)
-    free(mixer_grpidx);
-  mixer_grpidx = (int *)calloc(mixer_n_elems, sizeof(int));
-  if (mixer_grpidx == NULL)
-    mixer_abort(ERR_FCN, "malloc", 0);
-  elem_index = 0;
-  for (idx = 0; idx < mixer_n_selems; idx++) {
-    int nelems_added = 0;
-    sid = (snd_mixer_selem_id_t *)(((char *)mixer_sid) + snd_mixer_selem_id_sizeof() * idx);
-    if (mixer_changed_state)
-      goto __again;
-    elem = snd_mixer_find_selem(mixer_handle, sid);
-    if (elem == NULL)
-      CHECK_ABORT (ERR_FCN, "snd_mixer_find_selem()", -EINVAL);
-    if ( (mixer_view == VIEW_PLAYBACK) || (mixer_view == VIEW_CHANNELS) ) {
-      for (i = MIXER_ELEM_FRONT; i <= MIXER_ELEM_SIDE; i++) {
-        int ok;
-        for (j = ok = 0; j < 2; j++) {
-         if (mixer_changed_state)
-           goto __again;
-         if (snd_mixer_selem_has_playback_channel(elem, mixer_elem_chn[i][j]))
-           ok++;
-        }
-        if (ok) {
-         sid = (snd_mixer_selem_id_t *)(((char *)mixer_sid) + snd_mixer_selem_id_sizeof() * idx);
-         mixer_grpidx[elem_index] = idx;
-         if (snd_mixer_selem_is_enumerated(elem)) {
-           if (mixer_view == VIEW_PLAYBACK &&
-               snd_mixer_selem_is_enum_capture(elem))
-             continue;
-           mixer_type[elem_index] = MIXER_ELEM_ENUM;
-         } else {
-           mixer_type[elem_index] = i;
-           if (i == 0 && snd_mixer_selem_has_playback_switch(elem))
-             mixer_type[elem_index] |= MIXER_ELEM_MUTE_SWITCH;
-           if (snd_mixer_selem_has_playback_volume(elem))
-             mixer_type[elem_index] |= MIXER_ELEM_HAS_VOLUME;
-         }
-         if (mixer_view == VIEW_CHANNELS) {
-           if (nelems_added == 0 &&
-               ! snd_mixer_selem_has_capture_volume(elem) &&
-               snd_mixer_selem_has_capture_switch(elem))
-             mixer_type[elem_index] |= MIXER_ELEM_CAPTURE_SWITCH;
-         }
-         elem_index++;
-         nelems_added++;
-         if (elem_index >= mixer_n_elems)
-           break;
-        }
-      }
-    }
-
-    if ( (mixer_view == VIEW_CAPTURE) || (mixer_view == VIEW_CHANNELS) ) {
-      int do_add = 0;
-      if (snd_mixer_selem_has_capture_volume(elem) &&
-         (mixer_view == VIEW_CAPTURE || !snd_mixer_selem_has_common_volume(elem)))
-       do_add = 1;
-      if (!do_add &&
-         (nelems_added == 0 && snd_mixer_selem_has_capture_switch(elem)) &&
-         (mixer_view == VIEW_CAPTURE || !snd_mixer_selem_has_common_switch(elem)))
-       do_add = 1;
-      if (!do_add &&
-         mixer_view == VIEW_CAPTURE && snd_mixer_selem_is_enum_capture(elem))
-       do_add = 1;
-
-      if (do_add) {
-        mixer_grpidx[elem_index] = idx;
-       if (snd_mixer_selem_is_enum_capture(elem))
-         mixer_type[elem_index] = MIXER_ELEM_CAPTURE_ENUM;
-       else {
-         mixer_type[elem_index] = MIXER_ELEM_CAPTURE;
-         if (nelems_added == 0 && snd_mixer_selem_has_capture_switch(elem))
-           mixer_type[elem_index] |= MIXER_ELEM_CAPTURE_SWITCH;
-         if (nelems_added)
-           mixer_type[elem_index] |= MIXER_ELEM_CAPTURE_SUFFIX;
-         if (snd_mixer_selem_has_capture_volume(elem))
-           mixer_type[elem_index] |= MIXER_ELEM_HAS_VOLUME;
-       }
-        elem_index++;
-        if (elem_index >= mixer_n_elems)
-         break;
-      }
-    }
-  }
-
-  mixer_n_view_elems = elem_index;
-  recalc_screen_size();
-  mixer_focus_elem = 0;
-  if (focus_type >= 0) {
-    for (elem_index = 0; elem_index < mixer_n_view_elems; elem_index++) {
-      sid = (snd_mixer_selem_id_t *)(((char *)mixer_sid) + snd_mixer_selem_id_sizeof() * mixer_grpidx[elem_index]);
-      if (!strcmp(snd_mixer_selem_id_get_name(focus_gid),
-                  snd_mixer_selem_id_get_name(sid)) &&
-          snd_mixer_selem_id_get_index(focus_gid) ==
-          snd_mixer_selem_id_get_index(sid) &&
-         (mixer_type[elem_index] & MIXER_ELEM_TYPE_MASK) == focus_type) {
-        mixer_focus_elem = elem_index;
-        break;
-      }
-    }
-  }
-
-  if (mixer_changed_state)
-    goto __again;
-}
-
-static void
-mixer_init_window (void)
-{
-  /* initialize ncurses
-   */
-  setlocale(LC_CTYPE, "");
-  mixer_window = initscr ();
-  curs_set (0); /* hide the cursor */
-
-  mixer_no_lrcorner = tigetflag ("xenl") != 1 && tigetflag ("am") != 1;
-
-  if (mixer_do_color)
-    mixer_do_color = has_colors ();
-  mixer_init_draw_contexts ();
-
-  /* react on key presses
-   */
-  cbreak ();
-  noecho ();
-  leaveok (mixer_window, TRUE);
-  keypad (mixer_window, TRUE);
-  GETCH_BLOCK (1);
-
-  recalc_screen_size();
-
-  mixer_clear (TRUE);
-}
-
-static void
-mixer_resize (void)
-{
-  struct winsize winsz = { 0, };
-
-  mixer_needs_resize = 0;
-  
-  if (ioctl (fileno (stdout), TIOCGWINSZ, &winsz) >= 0 &&
-      winsz.ws_row && winsz.ws_col)
-    {
-      keypad (mixer_window, FALSE);
-      leaveok (mixer_window, FALSE);
-
-      endwin ();
-      
-      mixer_max_x = MAX (2, winsz.ws_col);
-      mixer_max_y = MAX (2, winsz.ws_row);
-      
-      /* humpf, i don't get it, if only the number of rows change,
-       * ncurses will segfault shortly after (could trigger that with mc as well).
-       */
-      resizeterm (mixer_max_y + 1, mixer_max_x + 1);
-      resizeterm (mixer_max_y, mixer_max_x);
-      
-      mixer_init_window ();
-      
-      if (mixer_max_x < MIXER_MIN_X ||
-         mixer_max_y < MIXER_MIN_Y)
-       beep (); // mixer_abort (ERR_WINSIZE, "");
-
-      mixer_have_old_focus = 0;
-    }
-}
-
-static void
-mixer_set_delta(int delta)
-{
-  int grp;
-  
-  for (grp = 0; grp < 2; grp++)
-    mixer_volume_delta[grp] = delta;
-}
-
-static void
-mixer_add_delta(int delta)
-{
-  int grp;
-  
-  for (grp = 0; grp < 2; grp++)
-    mixer_volume_delta[grp] += delta;
-}
-
-static int
-mixer_iteration (void)
-{
-  int count, err;
-  struct pollfd *fds;
-  int finished = 0;
-  int key = 0;
-  int old_view;
-  unsigned short revents;
-  
-  /* setup for select on stdin and the mixer fd */
-  if ((count = snd_mixer_poll_descriptors_count(mixer_handle)) < 0)
-    mixer_abort (ERR_FCN, "snd_mixer_poll_descriptors_count", count);
-  fds = calloc(count + 1, sizeof(struct pollfd));
-  if (fds == NULL)
-    mixer_abort (ERR_FCN, "malloc", 0);
-  fds->fd = fileno(stdin);
-  fds->events = POLLIN;
-  if ((err = snd_mixer_poll_descriptors(mixer_handle, fds + 1, count)) < 0)
-    mixer_abort (ERR_FCN, "snd_mixer_poll_descriptors", err);
-  if (err != count)
-    mixer_abort (ERR_FCN, "snd_mixer_poll_descriptors (err != count)", 0);
-  
-  finished = poll(fds, count + 1, -1);
-
-  /* don't abort on handled signals */
-  if (finished < 0 && errno == EINTR)
-    finished = 0;
-  if (mixer_needs_resize)
-    mixer_resize ();
-
-  if (finished > 0) {
-    if (fds->revents & POLLIN) {
-      key = getch ();
-      finished--;
-    }
-  } else {
-    key = 0;
-  }
-  
-  if (finished > 0) {
-    if (snd_mixer_poll_descriptors_revents(mixer_handle, fds + 1, count, &revents) >= 0) {
-      if (revents & POLLNVAL)
-        mixer_abort (ERR_FCN, "snd_mixer_poll_descriptors (POLLNVAL)", 0);
-      if (revents & POLLERR)
-        mixer_abort (ERR_FCN, "snd_mixer_poll_descriptors (POLLERR)", 0);
-      if (revents & POLLIN)
-        snd_mixer_handle_events(mixer_handle);
-    }
-  }
-
-  finished = 0;
-  free(fds);
-
-  old_view = mixer_view;
-  
-#if 0 /* DISABLED: it's not so usefull rather annoying... */
-  /* feature Escape prefixing for some keys */
-  if (key == 27)
-    {
-      GETCH_BLOCK (0);
-      key = getch ();
-      GETCH_BLOCK (1);
-      switch (key)
-       {
-       case 9: /* Tab */
-         key = KEY_BTAB;
-         break;
-       default:
-         key = 27;
-         break;
-       }
-    }
-#endif /* DISABLED */
-  
-  /* general keys */
-  switch (key)
-    {
-    case 0:
-      /* ignore */
-      break;
-    case 27:   /* Escape */
-    case KEY_F (10):
-      finished = 1;
-      key = 0;
-      break;
-    case 13:   /* Return */
-    case 10:   /* NewLine */
-      if (mixer_view != mixer_view_saved) {
-        mixer_view = mixer_view_saved;
-        mixer_changed_state=1;
-        mixer_reinit ();
-      }
-      key = 0;
-      break;
-    case 'h':
-    case 'H':
-    case '?':
-    case KEY_F (1):
-      mixer_view = VIEW_HELP;
-      key = 0;
-      break;
-    case '/':
-    case KEY_F (2):
-      mixer_view = VIEW_PROCINFO;
-      key = 0;
-      break;
-    case KEY_F (3):
-      if (mixer_view == VIEW_PLAYBACK) {
-       mixer_clear (FALSE);
-      } else {
-        mixer_view = mixer_view_saved = VIEW_PLAYBACK;
-        mixer_changed_state=1;
-        mixer_reinit ();
-      } 
-      key = 0;
-      break;
-    case KEY_F (4):
-      if (mixer_view == VIEW_CAPTURE) {
-       mixer_clear (FALSE);
-      } else {
-        mixer_view = mixer_view_saved = VIEW_CAPTURE;
-        mixer_changed_state=1;
-        mixer_reinit ();
-      } 
-      key = 0;
-      break;
-    case KEY_F (5):
-      if (mixer_view == VIEW_CHANNELS) {
-       mixer_clear (FALSE);
-      } else {
-        mixer_view = mixer_view_saved = VIEW_CHANNELS;
-        mixer_changed_state=1;
-        mixer_reinit ();
-      } 
-      key = 0;
-      break;
-    case 9: /* Tab */
-      if (mixer_view >= VIEW_CHANNELS && mixer_view <= VIEW_CAPTURE) {
-       mixer_view = (mixer_view + 1) % 3 + VIEW_CHANNELS;
-       mixer_view_saved = mixer_view;
-       mixer_changed_state = 1;
-       mixer_reinit ();
-       key = 0;
-      }
-      break;
-    case '\014':
-    case 'L':
-    case 'l':
-      mixer_clear (TRUE);
-      break;
-    }
-  
-  if (key && (mixer_view == VIEW_HELP ||
-             mixer_view == VIEW_PROCINFO))
-    switch (key)
-      {
-      case 9:          /* Tab */
-       mixer_hscroll_delta += 8;
-       break;
-      case KEY_BTAB:
-       mixer_hscroll_delta -= 8;
-       break;
-      case KEY_A1:
-       mixer_hscroll_delta -= 1;
-       mixer_vscroll_delta -= 1;
-       break;
-      case KEY_A3:
-       mixer_hscroll_delta += 1;
-       mixer_vscroll_delta -= 1;
-       break;
-      case KEY_C1:
-       mixer_hscroll_delta -= 1;
-       mixer_vscroll_delta += 1;
-       break;
-      case KEY_C3:
-       mixer_hscroll_delta += 1;
-       mixer_vscroll_delta += 1;
-       break;
-      case KEY_RIGHT:
-      case 'n':
-       mixer_hscroll_delta += 1;
-       break;
-      case KEY_LEFT:
-      case 'p':
-       mixer_hscroll_delta -= 1;
-       break;
-      case KEY_UP:
-      case 'w':
-      case 'W':
-       mixer_vscroll_delta -= 1;
-       break;
-      case KEY_DOWN:
-      case 'x':
-      case 'X':
-       mixer_vscroll_delta += 1;
-       break;
-      case KEY_PPAGE:
-      case 'B':
-      case 'b':
-       mixer_vscroll_delta -= (mixer_max_y - 5) / 2;
-       break;
-      case KEY_NPAGE:
-      case ' ':
-       mixer_vscroll_delta += (mixer_max_y - 5) / 2;
-       break;
-      case KEY_BEG:
-      case KEY_HOME:
-       mixer_hscroll_delta -= 0xffffff;
-       break;
-      case KEY_LL:
-      case KEY_END:
-       mixer_hscroll_delta += 0xffffff;
-       break;
-      }
-  
-  if (key && 
-    ((mixer_view == VIEW_CHANNELS) ||
-    (mixer_view == VIEW_PLAYBACK) ||
-    (mixer_view == VIEW_CAPTURE)) )
-    switch (key)
-      {
-      case KEY_RIGHT:
-      case 'n':
-       mixer_focus_elem += 1;
-       break;
-      case KEY_LEFT:
-      case 'p':
-       mixer_focus_elem -= 1;
-       break;
-      case KEY_PPAGE:
-        mixer_set_delta(5);
-       break;
-      case KEY_NPAGE:
-        mixer_set_delta(-5);
-       break;
-#if 0
-      case KEY_BEG:
-      case KEY_HOME:
-        mixer_set_delta(100);
-       break;
-#endif
-      case KEY_LL:
-      case KEY_END:
-        mixer_set_delta(-100);
-       break;
-      case '+':
-        mixer_set_delta(1);
-       break;
-      case '-':
-        mixer_set_delta(-1);
-       break;
-      case 'w':
-      case KEY_UP:
-        mixer_set_delta(1);
-      case 'W':
-        mixer_add_delta(1);
-       break;
-      case 'x':
-      case KEY_DOWN:
-        mixer_set_delta(-1);
-      case 'X':
-        mixer_add_delta(-1);
-       break;
-      case '0':
-      case '1':
-      case '2':
-      case '3':
-      case '4':
-      case '5':
-      case '6':
-      case '7':
-      case '8':
-      case '9':
-       mixer_volume_absolute = 10 * (key - '0');
-       break;
-      case 'q':
-       mixer_volume_delta[MIXER_CHN_LEFT] = 1;
-      case 'Q':
-       mixer_volume_delta[MIXER_CHN_LEFT] += 1;
-       break;
-      case 'y':
-      case 'z':
-       mixer_volume_delta[MIXER_CHN_LEFT] = -1;
-      case 'Y':
-      case 'Z':
-       mixer_volume_delta[MIXER_CHN_LEFT] += -1;
-       break;
-      case 'e':
-       mixer_volume_delta[MIXER_CHN_RIGHT] = 1;
-      case 'E':
-       mixer_volume_delta[MIXER_CHN_RIGHT] += 1;
-       break;
-      case 'c':
-       mixer_volume_delta[MIXER_CHN_RIGHT] = -1;
-      case 'C':
-       mixer_volume_delta[MIXER_CHN_RIGHT] += -1;
-       break;
-      case 'm':
-      case 'M':
-       mixer_toggle_mute |= MIXER_MASK_STEREO;
-       break;
-      case 'b':
-      case 'B':
-      case '=':
-       mixer_balance_volumes = 1;
-       break;
-      case '<':
-      case ',':
-       mixer_toggle_mute |= MIXER_MASK_LEFT;
-       break;
-      case '>':
-      case '.':
-       mixer_toggle_mute |= MIXER_MASK_RIGHT;
-       break;
-      case ' ':
-       mixer_toggle_capture |= MIXER_MASK_STEREO;
-       break;
-      case KEY_IC:
-      case ';':
-       mixer_toggle_capture |= MIXER_MASK_LEFT;
-       break;
-      case '\'':
-      case KEY_DC:
-       mixer_toggle_capture |= MIXER_MASK_RIGHT;
-       break;
-      }
-  
-  if (old_view != mixer_view)
-    mixer_clear (FALSE);
-  
-  if (! mixer_n_view_elems)
-    mixer_focus_elem = 0;
-  else
-    mixer_focus_elem = CLAMP (mixer_focus_elem, 0, mixer_n_view_elems - 1);
-  
-  return finished;
-}
-
-static void
-mixer_winch (void)
-{
-  signal (SIGWINCH, (void*) mixer_winch);
-
-  mixer_needs_resize++;
-}
-
-static void
-mixer_signal_handler (int signal)
-{
-  if (signal != SIGSEGV)
-    mixer_abort (ERR_SIGNAL, strsignal(signal), 0);
-  else
-    {
-      fprintf (stderr, "\nSegmentation fault.\n");
-      _exit (11);
-    }
-}
-
-int
-main (int    argc,
-      char **argv)
-{
-  int opt;
-  
-  /* parse args
-   */
-  do
-    {
-      opt = getopt (argc, argv, "c:D:shgV:a:");
-      switch (opt)
-       {
-       case '?':
-       case 'h':
-         printf ("%s v%s\n", PRGNAME_UPPER, VERSION);
-         printf ("Usage: %s [-h] [-c <card: 0...7>] [-D <mixer device>] [-g] [-s] [-V <view>] [-a <abst>]\n", PRGNAME);
-         return 1;
-       case 'c':
-         {
-           int i = snd_card_get_index(optarg);
-           if (i < 0 || i > 31) {
-             fprintf (stderr, "wrong -c argument '%s'\n", optarg);
-             mixer_abort (ERR_NONE, "", 0);
-           }
-           sprintf(card_id, "hw:%i", i);
-         }
-         break;
-       case 'D':
-         strncpy(card_id, optarg, sizeof(card_id));
-         card_id[sizeof(card_id)-1] = '\0';
-         break;
-       case 'g':
-         mixer_do_color = !mixer_do_color;
-         break;
-       case 's':
-         mixer_minimize = 1;
-         break;
-       case 'V':
-         if (*optarg == 'p' || *optarg == 'P')
-           mixer_view = VIEW_PLAYBACK;
-         else if (*optarg == 'c' || *optarg == 'C')
-           mixer_view = VIEW_CAPTURE;
-         else
-           mixer_view = VIEW_CHANNELS;
-         break;
-       case 'a':
-         mixer_level = 1;
-         memset(&mixer_options, 0, sizeof(mixer_options));
-         mixer_options.ver = 1;
-         if (!strcmp(optarg, "none"))
-           mixer_options.abstract = SND_MIXER_SABSTRACT_NONE;
-         else if (!strcmp(optarg, "basic"))
-           mixer_options.abstract = SND_MIXER_SABSTRACT_BASIC;
-         else {
-           fprintf(stderr, "Select correct abstraction level (none or basic)...\n");
-           mixer_abort (ERR_NONE, "", 0);
-         }
-         break;
-       }
-    }
-  while (opt > 0);
-  
-  mixer_options.device = card_id;
-  
-  /* initialize mixer
-   */
-  mixer_init ();
-  mixer_reinit ();
-  
-  if (mixer_n_elems == 0) {
-    fprintf(stderr, "No mixer elems found\n");
-    mixer_abort (ERR_NONE, "", 0);
-  }
-
-  /* setup signal handlers
-   */
-  signal (SIGINT, mixer_signal_handler);
-  signal (SIGTRAP, mixer_signal_handler);
-  // signal (SIGABRT, mixer_signal_handler);
-  signal (SIGQUIT, mixer_signal_handler);
-  signal (SIGBUS, mixer_signal_handler);
-  signal (SIGSEGV, mixer_signal_handler);
-  signal (SIGPIPE, mixer_signal_handler);
-  signal (SIGTERM, mixer_signal_handler);
-  
-  /* initialize ncurses
-   */
-  mixer_init_window ();
-  if (mixer_max_x < MIXER_MIN_X ||
-      mixer_max_y < MIXER_MIN_Y)
-    beep (); // mixer_abort (ERR_WINSIZE, "");
-  
-  signal (SIGWINCH, (void*) mixer_winch);
-
-  do
-    {
-      /* draw window upon every iteration */
-      if (!mixer_needs_resize)
-       {
-         switch (mixer_view)
-           {
-           case VIEW_CHANNELS:
-           case VIEW_PLAYBACK:
-           case VIEW_CAPTURE:
-             mixer_update_cbars ();
-             break;
-           case VIEW_HELP:
-             mixer_show_text ("Help", mixer_help_text, &mixer_help_xoffs, &mixer_help_yoffs);
-             break;
-           case VIEW_PROCINFO:
-             mixer_show_procinfo ();
-             break;
-           }
-         mixer_draw_frame ();
-         refresh ();
-       }
-    }
-  while (!mixer_iteration ());
-  
-  mixer_abort (ERR_NONE, "", 0);
-}
diff --git a/alsamixer/card_select.c b/alsamixer/card_select.c
new file mode 100644 (file)
index 0000000..b473dcf
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+ * card_select.c - select a card by list or device name
+ * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "aconfig.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <alsa/asoundlib.h>
+#include <menu.h>
+#include "gettext_curses.h"
+#include "die.h"
+#include "mem.h"
+#include "utils.h"
+#include "colors.h"
+#include "widget.h"
+#include "mixer_widget.h"
+#include "device_name.h"
+#include "card_select.h"
+
+struct card {
+       struct card *next;
+       char *indexstr;
+       char *name;
+       char *device_name;
+};
+
+static struct widget list_widget;
+static struct card first_card;
+static ITEM **items;
+static MENU *menu;
+static ITEM *initial_item;
+
+static void on_key_enter(void)
+{
+       ITEM *item = current_item(menu);
+       if (item) {
+               struct card *card = item_userptr(item);
+               if (card->device_name) {
+                       if (select_card_by_name(card->device_name))
+                               list_widget.close();
+               } else {
+                       create_device_name_form();
+               }
+       }
+}
+
+static void on_menu_key(int key)
+{
+       static const struct {
+               int key;
+               int request;
+       } key_map[] = {
+               { KEY_DOWN, REQ_DOWN_ITEM },
+               { KEY_UP, REQ_UP_ITEM },
+               { KEY_HOME, REQ_FIRST_ITEM },
+               { KEY_NPAGE, REQ_SCR_DPAGE },
+               { KEY_PPAGE, REQ_SCR_UPAGE },
+               { KEY_BEG, REQ_FIRST_ITEM },
+               { KEY_END, REQ_LAST_ITEM },
+       };
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(key_map); ++i)
+               if (key_map[i].key == key) {
+                       menu_driver(menu, key_map[i].request);
+                       break;
+               }
+}
+
+static void on_handle_key(int key)
+{
+       switch (key) {
+       case 27:
+       case KEY_CANCEL:
+       case 'q':
+       case 'Q':
+               list_widget.close();
+               break;
+       case 10:
+       case 13:
+       case KEY_ENTER:
+               on_key_enter();
+               break;
+       default:
+               on_menu_key(key);
+               break;
+       }
+}
+
+static bool create(void)
+{
+       int rows, columns;
+       const char *title;
+
+       if (screen_lines < 3 || screen_cols < 10) {
+               beep();
+               list_widget.close();
+               return FALSE;
+       }
+       scale_menu(menu, &rows, &columns);
+       rows += 2;
+       columns += 2;
+       if (rows > screen_lines)
+               rows = screen_lines;
+       if (columns > screen_cols)
+               columns = screen_cols;
+
+       widget_init(&list_widget, rows, columns, SCREEN_CENTER, SCREEN_CENTER,
+                   attr_menu, WIDGET_BORDER | WIDGET_SUBWINDOW);
+
+       title = _("Sound Card");
+       mvwprintw(list_widget.window, 0, (columns - 2 - get_mbs_width(title)) / 2, " %s ", title);
+       set_menu_win(menu, list_widget.window);
+       set_menu_sub(menu, list_widget.subwindow);
+       return TRUE;
+}
+
+static void on_window_size_changed(void)
+{
+       unpost_menu(menu);
+       if (!create())
+               return;
+       post_menu(menu);
+}
+
+static void on_close(void)
+{
+       unsigned int i;
+       struct card *card, *next_card;
+
+       unpost_menu(menu);
+       free_menu(menu);
+       for (i = 0; items[i]; ++i)
+               free_item(items[i]);
+       free(items);
+       for (card = first_card.next; card; card = next_card) {
+               next_card = card->next;
+               free(card->indexstr);
+               free(card->name);
+               free(card->device_name);
+               free(card);
+       }
+       widget_free(&list_widget);
+}
+
+void close_card_select_list(void)
+{
+       on_close();
+}
+
+static struct widget list_widget = {
+       .handle_key = on_handle_key,
+       .window_size_changed = on_window_size_changed,
+       .close = on_close,
+};
+
+static int get_cards(void)
+{
+       int count, number, err;
+       snd_ctl_t *ctl;
+       snd_ctl_card_info_t *info;
+       char buf[16];
+       struct card *card, *prev_card;
+
+       first_card.indexstr = "-";
+       first_card.name = _("(default)");
+       first_card.device_name = "default";
+       count = 1;
+
+       snd_ctl_card_info_alloca(&info);
+       prev_card = &first_card;
+       number = -1;
+       for (;;) {
+               err = snd_card_next(&number);
+               if (err < 0)
+                       fatal_alsa_error(_("cannot enumerate sound cards"), err);
+               if (number < 0)
+                       break;
+               sprintf(buf, "hw:%d", number);
+               err = snd_ctl_open(&ctl, buf, 0);
+               if (err < 0)
+                       continue;
+               err = snd_ctl_card_info(ctl, info);
+               snd_ctl_close(ctl);
+               if (err < 0)
+                       continue;
+               card = ccalloc(1, sizeof *card);
+               sprintf(buf, "%d", number);
+               card->indexstr = cstrdup(buf);
+               card->name = cstrdup(snd_ctl_card_info_get_name(info));
+               sprintf(buf, "hw:%d", number);
+               card->device_name = cstrdup(buf);
+               prev_card->next = card;
+               prev_card = card;
+               ++count;
+       }
+
+       card = ccalloc(1, sizeof *card);
+       card->indexstr = cstrdup(" ");
+       card->name = cstrdup(_("enter device name..."));
+       prev_card->next = card;
+       ++count;
+
+       return count;
+}
+
+static void create_list_items(int cards)
+{
+       int i;
+       struct card *card;
+       ITEM *item;
+
+       initial_item = NULL;
+       items = ccalloc(cards + 1, sizeof(ITEM*));
+       i = 0;
+       for (card = &first_card; card; card = card->next) {
+               item = new_item(card->indexstr, card->name);
+               if (!item)
+                       fatal_error("cannot create menu item");
+               set_item_userptr(item, card);
+               items[i++] = item;
+               if (!initial_item &&
+                   mixer_device_name &&
+                   (!card->device_name ||
+                    !strcmp(card->device_name, mixer_device_name)))
+                       initial_item = item;
+       }
+       assert(i == cards);
+}
+
+void create_card_select_list(void)
+{
+       int cards;
+
+       cards = get_cards();
+       create_list_items(cards);
+
+       menu = new_menu(items);
+       if (!menu)
+               fatal_error("cannot create menu");
+       set_menu_fore(menu, attr_menu_selected);
+       set_menu_back(menu, attr_menu);
+       set_menu_mark(menu, NULL);
+       if (initial_item)
+               set_current_item(menu, initial_item);
+       set_menu_spacing(menu, 2, 1, 1);
+       menu_opts_on(menu, O_SHOWDESC);
+
+       if (!create())
+               return;
+
+       post_menu(menu);
+}
diff --git a/alsamixer/card_select.h b/alsamixer/card_select.h
new file mode 100644 (file)
index 0000000..4ba15fc
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef CARD_SELECT_H_INCLUDED
+#define CARD_SELECT_H_INCLUDED
+
+void create_card_select_list(void);
+void close_card_select_list(void);
+
+#endif
diff --git a/alsamixer/cli.c b/alsamixer/cli.c
new file mode 100644 (file)
index 0000000..ab6255f
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * alsamixer - curses mixer for the ALSA project
+ * Copyright (c) 1998,1999 Tim Janik <timj@gtk.org>
+ *                         Jaroslav Kysela <perex@perex.cz>
+ * Copyright (c) 2009      Clemens Ladisch <clemens@ladisch.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "aconfig.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <locale.h>
+#include <getopt.h>
+#include <alsa/asoundlib.h>
+#include "gettext_curses.h"
+#include "mixer_widget.h"
+#include "mainloop.h"
+
+static int use_color = 1;
+static struct snd_mixer_selem_regopt selem_regopt = {
+       .ver = 1,
+       .abstract = SND_MIXER_SABSTRACT_NONE,
+       .device = "default",
+};
+
+static void show_help(void)
+{
+       puts(_("Usage: alsamixer [options]"));
+       puts(_("Useful options:\n"
+              "  -h, --help              this help\n"
+              "  -c, --card=NUMBER       sound card number or id\n"
+              "  -D, --device=NAME       mixer device name\n"
+              "  -V, --view=MODE         starting view mode: playback/capture/all"));
+       puts(_("Debugging options:\n"
+              "  -g, --no-color          toggle using of colors\n"
+              "  -a, --abstraction=NAME  mixer abstraction level: none/basic"));
+}
+
+static void parse_options(int argc, char *argv[])
+{
+       static const char short_options[] = "hc:D:V:gsa:";
+       static const struct option long_options[] = {
+               { .name = "help", .val = 'h' },
+               { .name = "card", .has_arg = 1, .val = 'c' },
+               { .name = "device", .has_arg = 1, .val = 'D' },
+               { .name = "view", .has_arg = 1, .val = 'V' },
+               { .name = "no-color", .val = 'g' },
+               { .name = "abstraction", .has_arg = 1, .val = 'a' },
+               { }
+       };
+       int option;
+       int card_index;
+       static char name_buf[16];
+
+       while ((option = getopt_long(argc, argv, short_options,
+                                    long_options, NULL)) != -1) {
+               switch (option) {
+               case '?':
+               case 'h':
+                       show_help();
+                       exit(EXIT_SUCCESS);
+               case 'c':
+                       card_index = snd_card_get_index(optarg);
+                       if (card_index < 0) {
+                               fprintf(stderr, _("invalid card index: %s\n"), optarg);
+                               goto fail;
+                       }
+                       sprintf(name_buf, "hw:%d", card_index);
+                       selem_regopt.device = name_buf;
+                       break;
+               case 'D':
+                       selem_regopt.device = optarg;
+                       break;
+               case 'V':
+                       if (*optarg == 'p' || *optarg == 'P')
+                               view_mode = VIEW_MODE_PLAYBACK;
+                       else if (*optarg == 'c' || *optarg == 'C')
+                               view_mode = VIEW_MODE_CAPTURE;
+                       else
+                               view_mode = VIEW_MODE_ALL;
+                       break;
+               case 'g':
+                       use_color = !use_color;
+                       break;
+               case 'a':
+                       if (!strcmp(optarg, "none"))
+                               selem_regopt.abstract = SND_MIXER_SABSTRACT_NONE;
+                       else if (!strcmp(optarg, "basic"))
+                               selem_regopt.abstract = SND_MIXER_SABSTRACT_BASIC;
+                       else {
+                               fprintf(stderr, _("unknown abstraction level: %s\n"), optarg);
+                               goto fail;
+                       }
+                       break;
+               default:
+                       fprintf(stderr, _("unknown option: %c\n"), option);
+fail:
+                       fputs(_("try `alsamixer --help' for more information\n"), stderr);
+                       exit(EXIT_FAILURE);
+               }
+       }
+}
+
+int main(int argc, char *argv[])
+{
+       setlocale(LC_ALL, "");
+#ifdef ENABLE_NLS_IN_CURSES
+       textdomain(PACKAGE);
+#endif
+
+       parse_options(argc, argv);
+
+       create_mixer_object(&selem_regopt);
+
+       initialize_curses(use_color);
+
+       create_mixer_widget();
+
+       mainloop();
+
+       shutdown();
+       return 0;
+}
diff --git a/alsamixer/colors.c b/alsamixer/colors.c
new file mode 100644 (file)
index 0000000..fcceb16
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * colors.c - color and attribute definitions
+ * Copyright (c) 1998,1999 Tim Janik <timj@gtk.org>
+ *                         Jaroslav Kysela <perex@perex.cz>
+ * Copyright (c) 2009      Clemens Ladisch <clemens@ladisch.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "aconfig.h"
+#include CURSESINC
+#include "colors.h"
+
+int attr_mixer_frame;
+int attr_mixer_text;
+int attr_mixer_active;
+int attr_ctl_frame;
+int attr_ctl_mute;
+int attr_ctl_nomute;
+int attr_ctl_capture;
+int attr_ctl_nocapture;
+int attr_ctl_label;
+int attr_ctl_label_focus;
+int attr_ctl_mark_focus;
+int attr_ctl_bar_lo;
+#ifdef TRICOLOR_VOLUME_BAR
+int attr_ctl_bar_mi;
+int attr_ctl_bar_hi;
+#endif
+int attr_ctl_inactive;
+int attr_ctl_label_inactive;
+int attr_errormsg;
+int attr_infomsg;
+int attr_textbox;
+int attr_textfield;
+int attr_menu;
+int attr_menu_selected;
+
+void init_colors(int use_color)
+{
+       if (!!has_colors() == !!use_color) {
+               start_color();
+
+               init_pair(1, COLOR_CYAN, COLOR_BLACK);
+               init_pair(2, COLOR_YELLOW, COLOR_BLACK);
+               init_pair(3, COLOR_WHITE, COLOR_GREEN);
+               init_pair(4, COLOR_RED, COLOR_BLACK);
+               init_pair(5, COLOR_WHITE, COLOR_BLACK);
+               init_pair(6, COLOR_WHITE, COLOR_BLUE);
+               init_pair(7, COLOR_RED, COLOR_BLUE);
+               init_pair(8, COLOR_GREEN, COLOR_GREEN);
+               init_pair(9, COLOR_WHITE, COLOR_RED);
+#ifdef TRICOLOR_VOLUME_BAR
+               init_pair(10, COLOR_WHITE, COLOR_WHITE);
+               init_pair(11, COLOR_RED, COLOR_RED);
+#endif
+
+               attr_mixer_frame = COLOR_PAIR(1);
+               attr_mixer_text = COLOR_PAIR(1);
+               attr_mixer_active = A_BOLD | COLOR_PAIR(2);
+               attr_ctl_frame = A_BOLD | COLOR_PAIR(1);
+               attr_ctl_mute = COLOR_PAIR(1);
+               attr_ctl_nomute = A_BOLD | COLOR_PAIR(3);
+               attr_ctl_capture = A_BOLD | COLOR_PAIR(4);
+               attr_ctl_nocapture = COLOR_PAIR(5);
+               attr_ctl_label = A_BOLD | COLOR_PAIR(6);
+               attr_ctl_label_focus = A_BOLD | COLOR_PAIR(7);
+               attr_ctl_mark_focus = A_BOLD | COLOR_PAIR(4);
+               attr_ctl_bar_lo = A_BOLD | COLOR_PAIR(8);
+#ifdef TRICOLOR_VOLUME_BAR
+               attr_ctl_bar_mi = A_BOLD | COLOR_PAIR(10);
+               attr_ctl_bar_hi = A_BOLD | COLOR_PAIR(11);
+#endif
+               attr_ctl_inactive = COLOR_PAIR(5);
+               attr_ctl_label_inactive = A_REVERSE | COLOR_PAIR(5);
+               attr_errormsg = A_BOLD | COLOR_PAIR(9);
+               attr_infomsg = A_BOLD | COLOR_PAIR(6);
+               attr_textbox = A_BOLD | COLOR_PAIR(6);
+               attr_textfield = A_REVERSE | COLOR_PAIR(5);
+               attr_menu = A_BOLD | COLOR_PAIR(6);
+               attr_menu_selected = A_REVERSE | COLOR_PAIR(6);
+       } else {
+               attr_mixer_frame = A_NORMAL;
+               attr_mixer_text = A_NORMAL;
+               attr_mixer_active = A_BOLD;
+               attr_ctl_frame = A_BOLD;
+               attr_ctl_mute = A_NORMAL;
+               attr_ctl_nomute = A_BOLD;
+               attr_ctl_capture = A_BOLD;
+               attr_ctl_nocapture = A_NORMAL;
+               attr_ctl_label = A_REVERSE;
+               attr_ctl_label_focus = A_REVERSE | A_BOLD;
+               attr_ctl_mark_focus = A_BOLD;
+               attr_ctl_bar_lo = A_BOLD;
+#ifdef TRICOLOR_VOLUME_BAR
+               attr_ctl_bar_mi = A_BOLD;
+               attr_ctl_bar_hi = A_BOLD;
+#endif
+               attr_ctl_inactive = A_NORMAL;
+               attr_ctl_label_inactive = A_REVERSE;
+               attr_errormsg = A_STANDOUT;
+               attr_infomsg = A_NORMAL;
+               attr_textbox = A_NORMAL;
+               attr_textfield = A_REVERSE;
+               attr_menu = A_NORMAL;
+               attr_menu_selected = A_REVERSE;
+       }
+}
diff --git a/alsamixer/colors.h b/alsamixer/colors.h
new file mode 100644 (file)
index 0000000..9396004
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef COLORS_H_INCLUDED
+#define COLORS_H_INCLUDED
+
+#define TRICOLOR_VOLUME_BAR
+
+extern int attr_mixer_frame;
+extern int attr_mixer_text;
+extern int attr_mixer_active;
+extern int attr_ctl_frame;
+extern int attr_ctl_mute;
+extern int attr_ctl_nomute;
+extern int attr_ctl_capture;
+extern int attr_ctl_nocapture;
+extern int attr_ctl_label;
+extern int attr_ctl_label_focus;
+extern int attr_ctl_mark_focus;
+extern int attr_ctl_bar_lo;
+#ifdef TRICOLOR_VOLUME_BAR
+extern int attr_ctl_bar_mi;
+extern int attr_ctl_bar_hi;
+#endif
+extern int attr_ctl_inactive;
+extern int attr_ctl_label_inactive;
+extern int attr_errormsg;
+extern int attr_infomsg;
+extern int attr_textbox;
+extern int attr_textfield;
+extern int attr_menu;
+extern int attr_menu_selected;
+
+void init_colors(int use_color);
+
+#endif
diff --git a/alsamixer/device_name.c b/alsamixer/device_name.c
new file mode 100644 (file)
index 0000000..c58e652
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * device_name_form.c - ask for sound control device name
+ * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "aconfig.h"
+#include <stdlib.h>
+#include <string.h>
+#include CURSESINC
+#include <form.h>
+#include "gettext_curses.h"
+#include "die.h"
+#include "mem.h"
+#include "utils.h"
+#include "colors.h"
+#include "widget.h"
+#include "mixer_widget.h"
+#include "card_select.h"
+#include "device_name.h"
+
+static struct widget form_widget;
+static FIELD *fields[3];
+static FORM *form;
+
+static char *dup_current_name(void)
+{
+       int rows, cols, max, i;
+       char *s;
+
+       if (form_driver(form, REQ_VALIDATION) == E_OK) {
+               dynamic_field_info(fields[1], &rows, &cols, &max);
+               s = ccalloc(1, cols + 1);
+               memcpy(s, field_buffer(fields[1], 0), cols);
+               for (i = strlen(s) - 1; i >= 0 && s[i] == ' '; --i)
+                       s[i] = '\0';
+               return s;
+       } else {
+               return cstrdup("");
+       }
+}
+
+static void on_key_enter(void)
+{
+       char *s;
+       bool ok;
+
+       s = dup_current_name();
+       ok = select_card_by_name(s);
+       free(s);
+       if (ok) {
+               form_widget.close();
+               close_card_select_list();
+       }
+}
+
+static void on_form_key(int key)
+{
+       static const struct {
+               int key;
+               int request;
+       } key_map[] = {
+               { KEY_LEFT, REQ_PREV_CHAR },
+               { KEY_RIGHT, REQ_NEXT_CHAR },
+               { KEY_HOME, REQ_BEG_FIELD },
+               { KEY_BACKSPACE, REQ_DEL_PREV },
+               { KEY_DC, REQ_DEL_CHAR },
+               { KEY_BEG, REQ_BEG_FIELD },
+               { KEY_END, REQ_END_FIELD },
+       };
+       unsigned int i;
+
+       if (key >= 32 && key < 256) {
+               form_driver(form, key);
+               return;
+       }
+       for (i = 0; i < ARRAY_SIZE(key_map); ++i)
+               if (key_map[i].key == key) {
+                       form_driver(form, key_map[i].request);
+                       break;
+               }
+}
+
+static void on_handle_key(int key)
+{
+       switch (key) {
+       case 27:
+       case KEY_CANCEL:
+               form_widget.close();
+               break;
+       case 10:
+       case 13:
+       case KEY_ENTER:
+               on_key_enter();
+               break;
+       default:
+               on_form_key(key);
+               break;
+       }
+}
+
+static bool create(void)
+{
+       const char *title;
+
+       if (screen_lines < 6 || screen_cols < 36) {
+               form_widget.close();
+               beep();
+               return FALSE;
+       }
+       widget_init(&form_widget,
+                   6, 36, SCREEN_CENTER, SCREEN_CENTER,
+                   attr_textbox, WIDGET_BORDER | WIDGET_SUBWINDOW | WIDGET_CURSOR_VISIBLE);
+       title = _("Sound Card");
+       mvwprintw(form_widget.window, 0, (36 - 2 - get_mbs_width(title)) / 2, " %s ", title);
+
+       set_form_win(form, form_widget.window);
+       set_form_sub(form, form_widget.subwindow);
+       return TRUE;
+}
+
+static void on_window_size_changed(void)
+{
+       form_driver(form, REQ_VALIDATION); /* save field value */
+       unpost_form(form);
+
+       if (!create())
+               return;
+
+       /*
+        * This call fails because ncurses does not allow changing options of
+        * the current field, and we cannot change the current field because
+        * there is only one.  The only way to make this work would be to throw
+        * away and recreate all fields.
+        */
+       field_opts_off(fields[1], O_BLANK);
+
+       post_form(form);
+}
+
+static void on_close(void)
+{
+       unpost_form(form);
+       free_form(form);
+       free_field(fields[0]);
+       free_field(fields[1]);
+       widget_free(&form_widget);
+}
+
+static struct widget form_widget = {
+       .handle_key = on_handle_key,
+       .window_size_changed = on_window_size_changed,
+       .close = on_close,
+};
+
+void create_device_name_form(void)
+{
+       fields[0] = new_field(1, 32, 1, 1, 0, 0);
+       if (!fields[0])
+               fatal_error("cannot create field");
+       field_opts_off(fields[0], O_ACTIVE);
+       field_opts_off(fields[0], O_EDIT);
+       set_field_fore(fields[0], attr_textbox);
+       set_field_back(fields[0], attr_textbox);
+       set_field_buffer(fields[0], 0, _("Device name:"));
+
+       fields[1] = new_field(1, 32, 2, 1, 0, 0);
+       if (!fields[1])
+               fatal_error("cannot create field");
+       field_opts_off(fields[1], O_AUTOSKIP);
+       field_opts_off(fields[1], O_NULLOK);
+       field_opts_off(fields[1], O_STATIC);
+       set_field_fore(fields[1], attr_textfield);
+       set_field_back(fields[1], attr_textfield);
+       set_field_buffer(fields[1], 0, mixer_device_name);
+
+       form = new_form(fields);
+       if (!form)
+               fatal_error("cannot create form");
+
+       if (!create())
+               return;
+
+       post_form(form);
+}
diff --git a/alsamixer/device_name.h b/alsamixer/device_name.h
new file mode 100644 (file)
index 0000000..f4a1f3f
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef DEVICE_NAME_FORM_H_INCLUDED
+#define DEVICE_NAME_FORM_H_INCLUDED
+
+void create_device_name_form(void);
+
+#endif
diff --git a/alsamixer/die.c b/alsamixer/die.c
new file mode 100644 (file)
index 0000000..dcd8536
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * die.c - error handlers
+ * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "aconfig.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <alsa/asoundlib.h>
+#include "gettext_curses.h"
+#include "mainloop.h"
+#include "die.h"
+
+void fatal_error(const char *msg)
+{
+       shutdown();
+       fprintf(stderr, "%s\n", msg);
+       exit(EXIT_FAILURE);
+}
+
+void fatal_alsa_error(const char *msg, int err)
+{
+       shutdown();
+       fprintf(stderr, _("%s: %s\n"), msg, snd_strerror(err));
+       exit(EXIT_FAILURE);
+}
diff --git a/alsamixer/die.h b/alsamixer/die.h
new file mode 100644 (file)
index 0000000..39ef1c0
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef DIE_H_INCLUDED
+#define DIE_H_INCLUDED
+
+void fatal_error(const char *msg) __attribute__((__noreturn__));
+void fatal_alsa_error(const char *msg, int err) __attribute__((__noreturn__));
+
+#endif
diff --git a/alsamixer/mainloop.c b/alsamixer/mainloop.c
new file mode 100644 (file)
index 0000000..eddaf3b
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * mainloop.c - main loop
+ * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "aconfig.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <poll.h>
+#include <panel.h>
+#include <alsa/asoundlib.h>
+#include "mem.h"
+#include "die.h"
+#include "colors.h"
+#include "widget.h"
+#include "mixer_widget.h"
+#include "mixer_display.h"
+#include "mainloop.h"
+
+static WINDOW *curses_initialized;
+
+static void black_hole_error_handler(const char *file, int line,
+                                    const char *function, int err,
+                                    const char *fmt, ...)
+{
+}
+
+void initialize_curses(bool use_color)
+{
+       curses_initialized = initscr();
+       cbreak();
+       noecho();
+#ifdef HAVE_CURSES_ESCDELAY
+       set_escdelay(100);
+#endif
+       window_size_changed(); /* update screen_lines/cols */
+       init_colors(use_color);
+       snd_lib_error_set_handler(black_hole_error_handler);
+}
+
+void shutdown(void)
+{
+       if (curses_initialized) {
+               clear();
+               refresh();
+               curs_set(1);
+               endwin();
+       }
+       mixer_shutdown();
+}
+
+void mainloop(void)
+{
+       struct pollfd *pollfds = NULL;
+       int nfds = 0, n;
+       struct widget *active_widget;
+       unsigned short revents;
+       int key;
+       int err;
+
+       for (;;) {
+               update_panels();
+               doupdate();
+
+               active_widget = get_active_widget();
+               if (!active_widget)
+                       break;
+
+               n = 1 + snd_mixer_poll_descriptors_count(mixer);
+               if (n != nfds) {
+                       free(pollfds);
+                       nfds = n;
+                       pollfds = ccalloc(nfds, sizeof *pollfds);
+                       pollfds[0].fd = fileno(stdin);
+                       pollfds[0].events = POLLIN;
+               }
+               err = snd_mixer_poll_descriptors(mixer, &pollfds[1], nfds - 1);
+               if (err < 0)
+                       fatal_alsa_error("cannot get poll descriptors", err);
+               n = poll(pollfds, nfds, -1);
+               if (n < 0) {
+                       if (errno == EINTR) {
+                               pollfds[0].revents = 0;
+                               doupdate(); /* handle SIGWINCH */
+                       } else {
+                               fatal_error("poll error");
+                       }
+               }
+               if (pollfds[0].revents & (POLLERR | POLLHUP | POLLNVAL))
+                       break;
+               if (pollfds[0].revents & POLLIN)
+                       --n;
+               if (n > 0) {
+                       err = snd_mixer_poll_descriptors_revents(mixer, &pollfds[1], nfds - 1, &revents);
+                       if (err < 0)
+                               fatal_alsa_error("cannot get poll events", err);
+                       if (revents & (POLLERR | POLLNVAL))
+                               close_mixer_device();
+                       else if (revents & POLLIN)
+                               snd_mixer_handle_events(mixer);
+               }
+               key = wgetch(active_widget->window);
+               while (key != ERR) {
+#ifdef KEY_RESIZE
+                       if (key == KEY_RESIZE)
+                               window_size_changed();
+                       else
+#endif
+                               active_widget->handle_key(key);
+                       active_widget = get_active_widget();
+                       if (!active_widget)
+                               break;
+                       key = wgetch(active_widget->window);
+               }
+               if (!active_widget)
+                       break;
+               if (controls_changed)
+                       display_controls();
+       }
+       free(pollfds);
+}
diff --git a/alsamixer/mainloop.h b/alsamixer/mainloop.h
new file mode 100644 (file)
index 0000000..0cfc989
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef MAINLOOP_H_INCLUDED
+#define MAINLOOP_H_INCLUDED
+
+#include CURSESINC
+
+void initialize_curses(bool use_color);
+void mainloop(void);
+void shutdown(void);
+
+#endif
diff --git a/alsamixer/mem.c b/alsamixer/mem.c
new file mode 100644 (file)
index 0000000..fa03a89
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * mem.c - memory allocation checkers
+ * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define _GNU_SOURCE
+#include "aconfig.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include "die.h"
+#include "mem.h"
+
+static void check(void *p)
+{
+       if (!p)
+               fatal_error("out of memory");
+}
+
+void *ccalloc(size_t n, size_t size)
+{
+       void *mem = calloc(n, size);
+       if (n && size)
+               check(mem);
+       return mem;
+}
+
+void *crealloc(void *ptr, size_t new_size)
+{
+       ptr = realloc(ptr, new_size);
+       if (new_size)
+               check(ptr);
+       return ptr;
+}
+
+char *cstrdup(const char *s)
+{
+       char *str = strdup(s);
+       check(str);
+       return str;
+}
+
+char *casprintf(const char *fmt, ...)
+{
+       va_list ap;
+       char *str;
+
+       va_start(ap, fmt);
+       if (vasprintf(&str, fmt, ap) < 0)
+               check(NULL);
+       va_end(ap);
+       return str;
+}
diff --git a/alsamixer/mem.h b/alsamixer/mem.h
new file mode 100644 (file)
index 0000000..d0e5f54
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef MEM_H_INCLUDED
+#define MEM_H_INCLUDED
+
+#include <stddef.h>
+
+void *ccalloc(size_t n, size_t size);
+void *crealloc(void *ptr, size_t new_size);
+char *cstrdup(const char *s);
+char *casprintf(const char *fmt, ...) __attribute__((__format__(printf, 1, 2)));
+
+#endif
diff --git a/alsamixer/mixer_controls.c b/alsamixer/mixer_controls.c
new file mode 100644 (file)
index 0000000..796df7b
--- /dev/null
@@ -0,0 +1,521 @@
+/*
+ * mixer_controls.c - handles mixer controls and mapping from selems
+ * Copyright (c) 1998,1999 Tim Janik <timj@gtk.org>
+ *                         Jaroslav Kysela <perex@perex.cz>
+ * Copyright (c) 2009      Clemens Ladisch <clemens@ladisch.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "aconfig.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include CURSESINC
+#include <alsa/asoundlib.h>
+#include "utils.h"
+#include "mem.h"
+#include "mixer_display.h"
+#include "mixer_widget.h"
+#include "mixer_controls.h"
+
+struct control *controls;
+unsigned int controls_count;
+
+static const snd_mixer_selem_channel_id_t supported_channels[] = {
+       SND_MIXER_SCHN_FRONT_LEFT,
+       SND_MIXER_SCHN_FRONT_RIGHT,
+       SND_MIXER_SCHN_REAR_LEFT,
+       SND_MIXER_SCHN_REAR_RIGHT,
+       SND_MIXER_SCHN_FRONT_CENTER,
+       SND_MIXER_SCHN_WOOFER,
+       SND_MIXER_SCHN_SIDE_LEFT,
+       SND_MIXER_SCHN_SIDE_RIGHT,
+};
+#define LAST_SUPPORTED_CHANNEL SND_MIXER_SCHN_SIDE_RIGHT
+
+static const snd_mixer_selem_channel_id_t control_channels[][2] = {
+       { SND_MIXER_SCHN_FRONT_LEFT, SND_MIXER_SCHN_FRONT_RIGHT },
+       { SND_MIXER_SCHN_REAR_LEFT, SND_MIXER_SCHN_REAR_RIGHT },
+       { SND_MIXER_SCHN_FRONT_CENTER, SND_MIXER_SCHN_UNKNOWN },
+       { SND_MIXER_SCHN_WOOFER, SND_MIXER_SCHN_UNKNOWN },
+       { SND_MIXER_SCHN_SIDE_LEFT, SND_MIXER_SCHN_SIDE_RIGHT },
+};
+
+bool are_there_any_controls(void)
+{
+       snd_mixer_elem_t *elem;
+       unsigned int i;
+
+       for (elem = snd_mixer_first_elem(mixer);
+            elem;
+            elem = snd_mixer_elem_next(elem)) {
+               if (snd_mixer_elem_get_type(elem) != SND_MIXER_ELEM_SIMPLE)
+                       continue;
+               if (snd_mixer_selem_is_enumerated(elem))
+                       return TRUE;
+               if (snd_mixer_selem_has_playback_volume_joined(elem) ||
+                   snd_mixer_selem_has_capture_volume_joined(elem) ||
+                   snd_mixer_selem_has_playback_switch_joined(elem) ||
+                   snd_mixer_selem_has_capture_switch_joined(elem))
+                       return TRUE;
+               for (i = 0; i < ARRAY_SIZE(supported_channels); ++i)
+                       if (snd_mixer_selem_has_playback_channel(elem, supported_channels[i]) ||
+                           snd_mixer_selem_has_capture_channel(elem, supported_channels[i]))
+                               return TRUE;
+       }
+       return FALSE;
+}
+
+static bool has_more_than_front_capture_channels(snd_mixer_elem_t *elem)
+{
+       unsigned int i;
+
+       for (i = 2; i < ARRAY_SIZE(supported_channels); ++i)
+               if (snd_mixer_selem_has_capture_channel(elem, supported_channels[i]))
+                       return TRUE;
+       return FALSE;
+}
+
+static bool has_any_control_channel(snd_mixer_elem_t *elem,
+                                   const snd_mixer_selem_channel_id_t channels[2],
+                                   int (*has_channel)(snd_mixer_elem_t *, snd_mixer_selem_channel_id_t))
+{
+       return has_channel(elem, channels[0]) ||
+              (channels[1] != SND_MIXER_SCHN_UNKNOWN && has_channel(elem, channels[1]));
+}
+
+static bool has_merged_cswitch(snd_mixer_elem_t *elem)
+{
+       bool pvol, psw;
+       unsigned int i;
+
+       pvol = snd_mixer_selem_has_playback_volume(elem);
+       psw = snd_mixer_selem_has_playback_switch(elem);
+       if ((pvol || psw) &&
+           snd_mixer_selem_has_capture_switch(elem) &&
+           !snd_mixer_selem_has_capture_volume(elem)) {
+               if (snd_mixer_selem_has_capture_switch_joined(elem))
+                       return TRUE;
+               else if (((pvol && snd_mixer_selem_has_playback_volume_joined(elem)) ||
+                         (psw && snd_mixer_selem_has_playback_switch_joined(elem))) &&
+                        has_more_than_front_capture_channels(elem))
+                       return FALSE;
+               for (i = 0; i < ARRAY_SIZE(control_channels); ++i) {
+                       if (has_any_control_channel(elem, control_channels[i], snd_mixer_selem_has_capture_channel) &&
+                           !has_any_control_channel(elem, control_channels[i], snd_mixer_selem_has_playback_channel))
+                               return FALSE;
+               }
+               return TRUE;
+       }
+       return FALSE;
+}
+
+static unsigned int get_playback_controls_count(snd_mixer_elem_t *elem)
+{
+       unsigned int count = 0;
+       unsigned int i;
+       int has_vol, has_sw;
+
+       has_vol = snd_mixer_selem_has_playback_volume(elem);
+       has_sw = snd_mixer_selem_has_playback_switch(elem);
+       if (!has_vol && !has_sw)
+               return 0;
+       if ((!has_vol || snd_mixer_selem_has_playback_volume_joined(elem)) &&
+           (!has_sw || snd_mixer_selem_has_playback_switch_joined(elem)))
+               return 1;
+       for (i = 0; i < ARRAY_SIZE(control_channels); ++i) {
+               if (snd_mixer_selem_has_playback_channel(elem, control_channels[i][0]) ||
+                   (control_channels[i][1] != SND_MIXER_SCHN_UNKNOWN &&
+                    snd_mixer_selem_has_playback_channel(elem, control_channels[i][1])))
+                       ++count;
+       }
+       return count;
+}
+
+static unsigned int get_capture_controls_count(snd_mixer_elem_t *elem)
+{
+       unsigned int count = 0;
+       unsigned int i;
+       int has_vol, has_sw;
+
+       has_vol = snd_mixer_selem_has_capture_volume(elem);
+       has_sw = snd_mixer_selem_has_capture_switch(elem);
+       if ((!has_vol && !has_sw) ||
+           (view_mode == VIEW_MODE_ALL && has_merged_cswitch(elem)))
+               return 0;
+       if ((!has_vol || snd_mixer_selem_has_capture_volume_joined(elem)) &&
+           (!has_sw || snd_mixer_selem_has_capture_switch_joined(elem)))
+               return 1;
+       for (i = 0; i < ARRAY_SIZE(control_channels); ++i) {
+               if (snd_mixer_selem_has_capture_channel(elem, control_channels[i][0]) ||
+                   (control_channels[i][1] != SND_MIXER_SCHN_UNKNOWN &&
+                    snd_mixer_selem_has_capture_channel(elem, control_channels[i][1])))
+                       ++count;
+       }
+       return count;
+}
+
+static unsigned int get_controls_count_for_elem(snd_mixer_elem_t *elem)
+{
+       unsigned int p, c;
+
+       if (snd_mixer_elem_get_type(elem) != SND_MIXER_ELEM_SIMPLE)
+               return 0;
+       if (snd_mixer_selem_is_enumerated(elem)) {
+               switch (view_mode) {
+               case VIEW_MODE_PLAYBACK:
+                       return snd_mixer_selem_is_enum_capture(elem) ? 0 : 1;
+               case VIEW_MODE_CAPTURE:
+                       return snd_mixer_selem_is_enum_capture(elem) ? 1 : 0;
+               case VIEW_MODE_ALL:
+               default:
+                       return 1;
+               }
+       }
+       switch (view_mode) {
+       case VIEW_MODE_PLAYBACK:
+               return get_playback_controls_count(elem);
+       case VIEW_MODE_CAPTURE:
+               return get_capture_controls_count(elem);
+       case VIEW_MODE_ALL:
+       default:
+               p = get_playback_controls_count(elem);
+               c = get_capture_controls_count(elem);
+               return has_merged_cswitch(elem) ? p : p + c;
+       }
+}
+
+static void create_name(struct control *control)
+{
+       unsigned int index;
+       char *s;
+
+       index = snd_mixer_selem_get_index(control->elem);
+       if (index > 0)
+               control->name = casprintf("%s %u", snd_mixer_selem_get_name(control->elem), index);
+       else
+               control->name = cstrdup(snd_mixer_selem_get_name(control->elem));
+
+       while ((s = strstr(control->name, "IEC958")) != NULL)
+               memcpy(s, "S/PDIF", 6);
+}
+
+static unsigned int create_controls_for_elem(snd_mixer_elem_t *elem, struct control *control)
+{
+       unsigned int count = 0;
+       unsigned int i;
+       unsigned int multich_flag;
+       unsigned int enum_index;
+       struct control *front_control = NULL;
+       bool has_pvol, has_psw;
+       bool has_cvol, has_csw;
+       bool has_channel[LAST_SUPPORTED_CHANNEL + 1];
+       bool merged_cswitch;
+       bool has_ch0, has_ch1;
+
+       if (snd_mixer_elem_get_type(elem) != SND_MIXER_ELEM_SIMPLE)
+               return 0;
+       if (snd_mixer_selem_is_enumerated(elem)) {
+               if ((view_mode == VIEW_MODE_PLAYBACK && snd_mixer_selem_is_enum_capture(elem)) ||
+                   (view_mode == VIEW_MODE_CAPTURE && !snd_mixer_selem_is_enum_capture(elem)))
+                       return 0;
+               control->elem = elem;
+               control->flags = TYPE_ENUM;
+               control->enum_channel_bits = 0;
+               for (i = 0; i <= SND_MIXER_SCHN_LAST; ++i)
+                       if (snd_mixer_selem_get_enum_item(control->elem, (snd_mixer_selem_channel_id_t)i, &enum_index) >= 0)
+                               control->enum_channel_bits |= 1 << i;
+               if (snd_mixer_selem_is_active(control->elem))
+                       control->flags |= IS_ACTIVE;
+               create_name(control);
+               return 1;
+       }
+       has_pvol = snd_mixer_selem_has_playback_volume(elem);
+       has_psw = snd_mixer_selem_has_playback_switch(elem);
+       has_cvol = snd_mixer_selem_has_capture_volume(elem);
+       has_csw = snd_mixer_selem_has_capture_switch(elem);
+       merged_cswitch = view_mode == VIEW_MODE_ALL && has_merged_cswitch(elem);
+       if (view_mode != VIEW_MODE_CAPTURE && (has_pvol || has_psw)) {
+               if ((!has_pvol || snd_mixer_selem_has_playback_volume_joined(elem)) &&
+                   (!has_psw || snd_mixer_selem_has_playback_switch_joined(elem))) {
+                       control->elem = elem;
+                       if (has_pvol) {
+                               control->flags |= TYPE_PVOLUME | HAS_VOLUME_0;
+                               control->volume_channels[0] = 0;
+                       }
+                       if (has_psw) {
+                               control->flags |= TYPE_PSWITCH | HAS_PSWITCH_0;
+                               control->pswitch_channels[0] = 0;
+                       }
+                       if (merged_cswitch) {
+                               control->flags |= TYPE_CSWITCH;
+                               if (snd_mixer_selem_has_capture_switch_joined(elem)) {
+                                       control->flags |= HAS_CSWITCH_0;
+                                       control->cswitch_channels[0] = 0;
+                               } else {
+                                       if (snd_mixer_selem_has_capture_channel(elem, control_channels[0][0])) {
+                                               control->flags |= HAS_CSWITCH_0;
+                                               control->cswitch_channels[0] = control_channels[0][0];
+                                       }
+                                       if (control_channels[0][1] != SND_MIXER_SCHN_UNKNOWN &&
+                                           snd_mixer_selem_has_capture_channel(elem, control_channels[0][1])) {
+                                               control->flags |= HAS_CSWITCH_1;
+                                               control->cswitch_channels[1] = control_channels[0][1];
+                                       }
+                               }
+                               if ((control->flags & (HAS_CSWITCH_0 | HAS_CSWITCH_1)) == HAS_CSWITCH_1) {
+                                       control->flags ^= HAS_CSWITCH_0 | HAS_CSWITCH_1;
+                                       control->cswitch_channels[0] = control->cswitch_channels[1];
+                               }
+                       }
+                       if (snd_mixer_selem_is_active(control->elem))
+                               control->flags |= IS_ACTIVE;
+                       create_name(control);
+                       ++control;
+                       ++count;
+               } else {
+                       multich_flag = 0;
+                       for (i = 0; i < ARRAY_SIZE(supported_channels); ++i)
+                               has_channel[supported_channels[i]] =
+                                       snd_mixer_selem_has_playback_channel(elem, supported_channels[i]);
+                       for (i = 0; i < ARRAY_SIZE(control_channels); ++i) {
+                               has_ch0 = has_channel[control_channels[i][0]];
+                               has_ch1 = control_channels[i][1] != SND_MIXER_SCHN_UNKNOWN &&
+                                       has_channel[control_channels[i][1]];
+                               if (!has_ch0 && !has_ch1)
+                                       continue;
+                               control->elem = elem;
+                               if (has_pvol) {
+                                       control->flags |= TYPE_PVOLUME;
+                                       if (snd_mixer_selem_has_playback_volume_joined(elem)) {
+                                               control->flags |= HAS_VOLUME_0;
+                                               control->volume_channels[0] = 0;
+                                       } else {
+                                               if (has_ch0) {
+                                                       control->flags |= HAS_VOLUME_0;
+                                                       control->volume_channels[0] = control_channels[i][0];
+                                               }
+                                               if (has_ch1) {
+                                                       control->flags |= HAS_VOLUME_1;
+                                                       control->volume_channels[1] = control_channels[i][1];
+                                               }
+                                       }
+                               }
+                               if (has_psw) {
+                                       control->flags |= TYPE_PSWITCH;
+                                       if (snd_mixer_selem_has_playback_switch_joined(elem)) {
+                                               control->flags |= HAS_PSWITCH_0;
+                                               control->pswitch_channels[0] = 0;
+                                       } else {
+                                               if (has_ch0) {
+                                                       control->flags |= HAS_PSWITCH_0;
+                                                       control->pswitch_channels[0] = control_channels[i][0];
+                                               }
+                                               if (has_ch1) {
+                                                       control->flags |= HAS_PSWITCH_1;
+                                                       control->pswitch_channels[1] = control_channels[i][1];
+                                               }
+                                       }
+                               }
+                               if (merged_cswitch) {
+                                       control->flags |= TYPE_CSWITCH;
+                                       if (snd_mixer_selem_has_capture_switch_joined(elem)) {
+                                               control->flags |= HAS_CSWITCH_0;
+                                               control->cswitch_channels[0] = 0;
+                                       } else {
+                                               if (snd_mixer_selem_has_capture_channel(elem, control_channels[i][0])) {
+                                                       control->flags |= HAS_CSWITCH_0;
+                                                       control->cswitch_channels[0] = control_channels[i][0];
+                                               }
+                                               if (control_channels[i][1] != SND_MIXER_SCHN_UNKNOWN &&
+                                                   snd_mixer_selem_has_capture_channel(elem, control_channels[i][1])) {
+                                                       control->flags |= HAS_CSWITCH_1;
+                                                       control->cswitch_channels[1] = control_channels[i][1];
+                                               }
+                                       }
+                               }
+                               if ((control->flags & (HAS_VOLUME_0 | HAS_VOLUME_1)) == HAS_VOLUME_1) {
+                                       control->flags ^= HAS_VOLUME_0 | HAS_VOLUME_1;
+                                       control->volume_channels[0] = control->volume_channels[1];
+                               }
+                               if ((control->flags & (HAS_PSWITCH_0 | HAS_PSWITCH_1)) == HAS_PSWITCH_1) {
+                                       control->flags ^= HAS_PSWITCH_0 | HAS_PSWITCH_1;
+                                       control->pswitch_channels[0] = control->pswitch_channels[1];
+                               }
+                               if ((control->flags & (HAS_CSWITCH_0 | HAS_CSWITCH_1)) == HAS_CSWITCH_1) {
+                                       control->flags ^= HAS_CSWITCH_0 | HAS_CSWITCH_1;
+                                       control->cswitch_channels[0] = control->cswitch_channels[1];
+                               }
+                               if (snd_mixer_selem_is_active(control->elem))
+                                       control->flags |= IS_ACTIVE;
+                               create_name(control);
+                               if (i == 0)
+                                       front_control = control;
+                               else {
+                                       front_control->flags |= IS_MULTICH | 0;
+                                       control->flags |= IS_MULTICH | i;
+                               }
+                               ++control;
+                               ++count;
+                       }
+               }
+       }
+       if (view_mode != VIEW_MODE_PLAYBACK && (has_cvol || has_csw) && !merged_cswitch) {
+               if ((!has_cvol || snd_mixer_selem_has_capture_volume_joined(elem)) &&
+                   (!has_csw || snd_mixer_selem_has_capture_switch_joined(elem))) {
+                       control->elem = elem;
+                       if (has_cvol) {
+                               control->flags |= TYPE_CVOLUME | HAS_VOLUME_0;
+                               control->volume_channels[0] = 0;
+                       }
+                       if (has_csw) {
+                               control->flags |= TYPE_CSWITCH | HAS_CSWITCH_0;
+                               control->cswitch_channels[0] = 0;
+                       }
+                       if (snd_mixer_selem_is_active(control->elem))
+                               control->flags |= IS_ACTIVE;
+                       create_name(control);
+                       ++control;
+                       ++count;
+               } else {
+                       for (i = 0; i < ARRAY_SIZE(supported_channels); ++i)
+                               has_channel[supported_channels[i]] =
+                                       snd_mixer_selem_has_capture_channel(elem, supported_channels[i]);
+                       for (i = 0; i < ARRAY_SIZE(control_channels); ++i) {
+                               has_ch0 = has_channel[control_channels[i][0]];
+                               has_ch1 = control_channels[i][1] != SND_MIXER_SCHN_UNKNOWN &&
+                                       has_channel[control_channels[i][1]];
+                               if (!has_ch0 && !has_ch1)
+                                       continue;
+                               control->elem = elem;
+                               if (has_cvol) {
+                                       control->flags |= TYPE_CVOLUME;
+                                       if (snd_mixer_selem_has_capture_volume_joined(elem)) {
+                                               control->flags |= HAS_VOLUME_0;
+                                               control->volume_channels[0] = 0;
+                                       } else {
+                                               if (has_ch0) {
+                                                       control->flags |= HAS_VOLUME_0;
+                                                       control->volume_channels[0] = control_channels[i][0];
+                                               }
+                                               if (has_ch1) {
+                                                       control->flags |= HAS_VOLUME_1;
+                                                       control->volume_channels[1] = control_channels[i][1];
+                                               }
+                                       }
+                               }
+                               if (has_csw) {
+                                       control->flags |= TYPE_CSWITCH;
+                                       if (snd_mixer_selem_has_capture_switch_joined(elem)) {
+                                               control->flags |= HAS_CSWITCH_0;
+                                               control->cswitch_channels[0] = 0;
+                                       } else {
+                                               if (has_ch0) {
+                                                       control->flags |= HAS_CSWITCH_0;
+                                                       control->cswitch_channels[0] = control_channels[i][0];
+                                               }
+                                               if (has_ch1) {
+                                                       control->flags |= HAS_CSWITCH_1;
+                                                       control->cswitch_channels[1] = control_channels[i][1];
+                                               }
+                                       }
+                               }
+                               if ((control->flags & (HAS_VOLUME_0 | HAS_VOLUME_1)) == HAS_VOLUME_1) {
+                                       control->flags ^= HAS_VOLUME_0 | HAS_VOLUME_1;
+                                       control->volume_channels[0] = control->volume_channels[1];
+                               }
+                               if ((control->flags & (HAS_CSWITCH_0 | HAS_CSWITCH_1)) == HAS_CSWITCH_1) {
+                                       control->flags ^= HAS_CSWITCH_0 | HAS_CSWITCH_1;
+                                       control->cswitch_channels[0] = control->cswitch_channels[1];
+                               }
+                               if (snd_mixer_selem_is_active(control->elem))
+                                       control->flags |= IS_ACTIVE;
+                               create_name(control);
+                               if (i == 0)
+                                       front_control = control;
+                               else {
+                                       front_control->flags |= IS_MULTICH | 0;
+                                       control->flags |= IS_MULTICH | i;
+                               }
+                               ++control;
+                               ++count;
+                       }
+               }
+       }
+       return count;
+}
+
+static void search_for_focus_control(void)
+{
+       snd_mixer_elem_t *elem;
+       unsigned int i;
+
+       elem = snd_mixer_find_selem(mixer, current_selem_id);
+       if (elem)
+               for (i = 0; i < controls_count; ++i)
+                       if (controls[i].elem == elem) {
+                               focus_control_index = i;
+                               for (;;) {
+                                       ++i;
+                                       if (i >= controls_count || controls[i].elem != elem)
+                                               return;
+                                       if (controls[i].flags == current_control_flags) {
+                                               focus_control_index = i;
+                                               return;
+                                       }
+                               }
+                       }
+       focus_control_index = 0;
+}
+
+void free_controls(void)
+{
+       unsigned int i;
+
+       for (i = 0; i < controls_count; ++i)
+               free(controls[i].name);
+       free(controls);
+       controls = NULL;
+       controls_count = 0;
+}
+
+void create_controls(void)
+{
+       snd_mixer_elem_t *elem;
+       struct control *control;
+
+       free_controls();
+
+       for (elem = snd_mixer_first_elem(mixer);
+            elem;
+            elem = snd_mixer_elem_next(elem))
+               controls_count += get_controls_count_for_elem(elem);
+
+       if (controls_count > 0) {
+               controls = ccalloc(controls_count, sizeof *controls);
+               control = controls;
+               for (elem = snd_mixer_first_elem(mixer);
+                    elem;
+                    elem = snd_mixer_elem_next(elem))
+                       control += create_controls_for_elem(elem, control);
+               assert(control == controls + controls_count);
+       }
+
+       compute_controls_layout();
+       display_view_mode();
+
+       search_for_focus_control();
+       refocus_control();
+}
diff --git a/alsamixer/mixer_controls.h b/alsamixer/mixer_controls.h
new file mode 100644 (file)
index 0000000..dbb3a9d
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef MIXER_CONTROLS_H_INCLUDED
+#define MIXER_CONTROLS_H_INCLUDED
+
+#include <alsa/asoundlib.h>
+
+struct control {
+       snd_mixer_elem_t *elem;
+       char *name;
+       unsigned int flags;
+#define TYPE_PVOLUME   (1u << 4)
+#define TYPE_CVOLUME   (1u << 5)
+#define TYPE_PSWITCH   (1u << 6)
+#define TYPE_CSWITCH   (1u << 7)
+#define TYPE_ENUM      (1u << 8)
+#define HAS_VOLUME_0   (1u << 9)
+#define HAS_VOLUME_1   (1u << 10)
+#define HAS_PSWITCH_0  (1u << 11)
+#define HAS_PSWITCH_1  (1u << 12)
+#define HAS_CSWITCH_0  (1u << 13)
+#define HAS_CSWITCH_1  (1u << 14)
+#define IS_MULTICH     (1u << 15)
+#define IS_ACTIVE      (1u << 16)
+#define MULTICH_MASK   (0x0000f)
+       snd_mixer_selem_channel_id_t volume_channels[2];
+       snd_mixer_selem_channel_id_t pswitch_channels[2];
+       snd_mixer_selem_channel_id_t cswitch_channels[2];
+       unsigned int enum_channel_bits;
+};
+
+extern struct control *controls;
+extern unsigned int controls_count;
+
+bool are_there_any_controls(void);
+void create_controls(void);
+void free_controls(void);
+
+#endif
diff --git a/alsamixer/mixer_display.c b/alsamixer/mixer_display.c
new file mode 100644 (file)
index 0000000..20d6d6a
--- /dev/null
@@ -0,0 +1,764 @@
+/*
+ * mixer_display.c - handles displaying of mixer widget and controls
+ * Copyright (c) 1874 Lewis Carroll
+ * Copyright (c) 2009 Clemens Ladisch <clemens@ladisch.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "aconfig.h"
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include CURSESINC
+#include <alsa/asoundlib.h>
+#include "gettext_curses.h"
+#include "utils.h"
+#include "mem.h"
+#include "colors.h"
+#include "widget.h"
+#include "mixer_widget.h"
+#include "mixer_controls.h"
+#include "mixer_display.h"
+
+enum align {
+       ALIGN_LEFT,
+       ALIGN_RIGHT,
+       ALIGN_CENTER,
+};
+
+static bool screen_too_small;
+static bool has_info_items;
+
+static int info_items_left;
+static int info_items_width;
+
+static int visible_controls;
+static int first_visible_control_index;
+static int first_control_x;
+static int control_width;
+static int control_name_width;
+
+static int base_y;
+static int volume_height;
+static int cswitch_y;
+static int values_y;
+static int name_y;
+static int channel_name_y;
+
+static void display_string_in_field(int y, int x, const char *s, int width, enum align align)
+{
+       int string_width;
+       const char *s_end;
+       int spaces;
+       int cur_y, cur_x;
+
+       wmove(mixer_widget.window, y, x);
+       string_width = width;
+       s_end = mbs_at_width(s, &string_width, -1);
+       if (string_width >= width) {
+               waddnstr(mixer_widget.window, s, s_end - s);
+       } else {
+               if (align != ALIGN_LEFT) {
+                       spaces = width - string_width;
+                       if (align == ALIGN_CENTER)
+                               spaces /= 2;
+                       if (spaces > 0)
+                               wprintw(mixer_widget.window, "%*s", spaces, "");
+               }
+               waddstr(mixer_widget.window, s);
+               if (align != ALIGN_RIGHT) {
+                       getyx(mixer_widget.window, cur_y, cur_x);
+                       if (cur_y == y) {
+                               spaces = x + width - cur_x;
+                               if (spaces > 0)
+                                       wprintw(mixer_widget.window, "%*s", spaces, "");
+                       }
+               }
+       }
+}
+
+void init_mixer_layout(void)
+{
+       const char *labels_left[4] = {
+               _("Card:"),
+               _("Chip:"),
+               _("View:"),
+               _("Item:"),
+       };
+       const char *labels_right[4] = {
+               _("F1:  Help"),
+               _("F2:  System information"),
+               _("F6:  Select sound card"),
+               _("Esc: Exit"),
+       };
+       unsigned int label_width_left, label_width_right;
+       unsigned int right_x, i;
+
+       screen_too_small = screen_lines < 14 || screen_cols < 12;
+       has_info_items = screen_lines >= 6;
+       if (!has_info_items)
+               return;
+
+       label_width_left = get_max_mbs_width(labels_left, 4);
+       label_width_right = get_max_mbs_width(labels_right, 4);
+       if (2 + label_width_left + 1 + 28 + label_width_right + 2 > screen_cols)
+               label_width_right = 0;
+       if (2 + label_width_left + 1 + 28 + label_width_right + 2 > screen_cols)
+               label_width_left = 0;
+
+       info_items_left = label_width_left ? 3 + label_width_left : 2;
+       right_x = screen_cols - label_width_right - 2;
+       info_items_width = right_x - info_items_left;
+       if (info_items_width < 1) {
+               has_info_items = FALSE;
+               return;
+       }
+
+       wattrset(mixer_widget.window, attr_mixer_text);
+       if (label_width_left)
+               for (i = 0; i < 4; ++i)
+                       display_string_in_field(1 + i, 2, labels_left[i],
+                                               label_width_left, ALIGN_RIGHT);
+       if (label_width_right)
+               for (i = 0; i < 4; ++i)
+                       display_string_in_field(1 + i, right_x, labels_right[i],
+                                               label_width_right, ALIGN_LEFT);
+}
+
+void display_card_info(void)
+{
+       snd_hctl_t *hctl;
+       snd_ctl_t *ctl;
+       snd_ctl_card_info_t *card_info;
+       const char *card_name = NULL;
+       const char *mixer_name = NULL;
+       int err;
+
+       if (!has_info_items)
+               return;
+
+       snd_ctl_card_info_alloca(&card_info);
+       if (mixer_device_name)
+               err = snd_mixer_get_hctl(mixer, mixer_device_name, &hctl);
+       else
+               err = -1;
+       if (err >= 0) {
+               ctl = snd_hctl_ctl(hctl);
+               err = snd_ctl_card_info(ctl, card_info);
+               if (err >= 0) {
+                       card_name = snd_ctl_card_info_get_name(card_info);
+                       mixer_name = snd_ctl_card_info_get_mixername(card_info);
+               }
+       }
+
+       if (card_name)
+               wattrset(mixer_widget.window, attr_mixer_active);
+       else {
+               wattrset(mixer_widget.window, attr_mixer_text);
+               if (unplugged)
+                       card_name = _("(unplugged)");
+               else
+                       card_name = "-";
+       }
+       display_string_in_field(1, info_items_left, card_name, info_items_width, ALIGN_LEFT);
+
+       if (mixer_name)
+               wattrset(mixer_widget.window, attr_mixer_active);
+       else {
+               wattrset(mixer_widget.window, attr_mixer_text);
+               mixer_name = "-";
+       }
+       display_string_in_field(2, info_items_left, mixer_name, info_items_width, ALIGN_LEFT);
+}
+
+void display_view_mode(void)
+{
+       const char *modes[3] = {
+               _("Playback"),
+               _("Capture"),
+               _("All"),
+       };
+       unsigned int widths[3];
+       bool has_view_mode;
+       int i;
+
+       if (!has_info_items)
+               return;
+
+       has_view_mode = controls_count > 0 || are_there_any_controls();
+       for (i = 0; i < 3; ++i)
+               widths[i] = get_mbs_width(modes[i]);
+       if (4 + widths[0] + 6 + widths[1] + 6 + widths[2] + 1 <= info_items_width) {
+               wmove(mixer_widget.window, 3, info_items_left);
+               wattrset(mixer_widget.window, attr_mixer_text);
+               for (i = 0; i < 3; ++i) {
+                       wprintw(mixer_widget.window, "F%c:", '3' + i);
+                       if (has_view_mode && (int)view_mode == i) {
+                               wattrset(mixer_widget.window, attr_mixer_active);
+                               wprintw(mixer_widget.window, "[%s]", modes[i]);
+                               wattrset(mixer_widget.window, attr_mixer_text);
+                       } else {
+                               wprintw(mixer_widget.window, " %s ", modes[i]);
+                       }
+                       if (i < 2)
+                               waddch(mixer_widget.window, ' ');
+               }
+       } else {
+               wattrset(mixer_widget.window, attr_mixer_active);
+               display_string_in_field(3, info_items_left,
+                                       has_view_mode ? modes[view_mode] : "",
+                                       info_items_width, ALIGN_LEFT);
+       }
+}
+
+static char *format_gain(long db)
+{
+       if (db != SND_CTL_TLV_DB_GAIN_MUTE)
+               return casprintf("%.2f", db / 100.0);
+       else
+               return cstrdup(_("mute"));
+}
+
+static void display_focus_item_info(void)
+{
+       struct control *control;
+       unsigned int index;
+       char buf[64];
+       long db, db2;
+       int sw, sw2;
+       char *dbs, *dbs2;
+       char *value_info;
+       char *item_info;
+       int err;
+
+       if (!has_info_items)
+               return;
+       wattrset(mixer_widget.window, attr_mixer_active);
+       if (!controls_count || screen_too_small) {
+               display_string_in_field(4, info_items_left, "", info_items_width, ALIGN_LEFT);
+               return;
+       }
+       control = &controls[focus_control_index];
+       value_info = NULL;
+       if (control->flags & TYPE_ENUM) {
+               err = snd_mixer_selem_get_enum_item(control->elem, ffs(control->enum_channel_bits) - 1, &index);
+               if (err >= 0)
+                       err = snd_mixer_selem_get_enum_item_name(control->elem, index, sizeof buf - 1, buf);
+               if (err >= 0)
+                       value_info = casprintf(" [%s]", buf);
+       } else if (control->flags & (TYPE_PVOLUME | TYPE_CVOLUME)) {
+               int (*get_vol_func)(snd_mixer_elem_t *, snd_mixer_selem_channel_id_t, long *);
+
+               if (control->flags & TYPE_PVOLUME)
+                       get_vol_func = snd_mixer_selem_get_playback_dB;
+               else
+                       get_vol_func = snd_mixer_selem_get_capture_dB;
+               if (!(control->flags & HAS_VOLUME_1)) {
+                       err = get_vol_func(control->elem, control->volume_channels[0], &db);
+                       if (err >= 0) {
+                               dbs = format_gain(db);
+                               value_info = casprintf(" [%s %s]", _("dB gain:"), dbs);
+                               free(dbs);
+                       }
+               } else {
+                       err = get_vol_func(control->elem, control->volume_channels[0], &db);
+                       if (err >= 0)
+                               err = get_vol_func(control->elem, control->volume_channels[1], &db2);
+                       if (err >= 0) {
+                               dbs = format_gain(db);
+                               dbs2 = format_gain(db2);
+                               value_info = casprintf(_(" [%s %s, %s]"), _("dB gain:"), dbs, dbs2);
+                               free(dbs);
+                               free(dbs2);
+                       }
+               }
+       } else if (control->flags & TYPE_PSWITCH) {
+               if (!(control->flags & HAS_PSWITCH_1)) {
+                       err = snd_mixer_selem_get_playback_switch(control->elem, control->pswitch_channels[0], &sw);
+                       if (err >= 0 && !sw)
+                               value_info = casprintf(" [%s]", _("Off"));
+               } else {
+                       err = snd_mixer_selem_get_playback_switch(control->elem, control->pswitch_channels[0], &sw);
+                       if (err >= 0)
+                               err = snd_mixer_selem_get_playback_switch(control->elem, control->pswitch_channels[1], &sw2);
+                       if (err >= 0 && (!sw || !sw2))
+                               value_info = casprintf(" [%s, %s]", sw ? _("On") : _("Off"), sw2 ? _("On") : _("Off"));
+               }
+       } else if (control->flags & TYPE_CSWITCH) {
+               if (!(control->flags & HAS_CSWITCH_1)) {
+                       err = snd_mixer_selem_get_capture_switch(control->elem, control->cswitch_channels[0], &sw);
+                       if (err >= 0 && !sw)
+                               value_info = casprintf(" [%s]", _("Off"));
+               } else {
+                       err = snd_mixer_selem_get_capture_switch(control->elem, control->cswitch_channels[0], &sw);
+                       if (err >= 0)
+                               err = snd_mixer_selem_get_capture_switch(control->elem, control->cswitch_channels[1], &sw2);
+                       if (err >= 0 && (!sw || !sw2))
+                               value_info = casprintf(" [%s, %s]", sw ? _("On") : _("Off"), sw2 ? _("On") : _("Off"));
+               }
+       }
+       item_info = casprintf("%s%s", control->name, value_info ? value_info : "");
+       free(value_info);
+       display_string_in_field(4, info_items_left, item_info, info_items_width, ALIGN_LEFT);
+       free(item_info);
+}
+
+static void clear_controls_display(void)
+{
+       int i;
+
+       wattrset(mixer_widget.window, attr_mixer_frame);
+       for (i = 5; i < screen_lines - 1; ++i)
+               mvwprintw(mixer_widget.window, i, 1, "%*s", screen_cols - 2, "");
+}
+
+static void center_string(int line, const char *s)
+{
+       int width = get_mbs_width(s);
+       if (width <= screen_cols - 2)
+               mvwaddstr(mixer_widget.window, line, (screen_cols - width) / 2, s);
+}
+
+static void display_unplugged(void)
+{
+       int lines, top, left;
+       bool boojum;
+
+       lines = screen_lines - 6;
+       if (lines < 2)
+               return;
+       top = lines / 2;
+       boojum = lines >= 10 && screen_cols >= 48;
+       top -= boojum ? 5 : 1;
+       if (top < 5)
+               top = 5;
+       if (boojum) {
+               left = (screen_cols - 46) / 2;
+               wattrset(mixer_widget.window, attr_mixer_text);
+               mvwaddstr(mixer_widget.window, top + 0, left,    "In the midst of the word he was trying to say,");
+               mvwaddstr(mixer_widget.window, top + 1, left + 2,  "In the midst of his laughter and glee,");
+               mvwaddstr(mixer_widget.window, top + 2, left,    "He had softly and suddenly vanished away---");
+               mvwaddstr(mixer_widget.window, top + 3, left + 2,  "For the Snark was a Boojum, you see.");
+               mvwchgat(mixer_widget.window,  top + 3, left + 16, 3,          /* ^^^ */
+                        attr_mixer_text | A_BOLD, PAIR_NUMBER(attr_mixer_text), NULL);
+               mvwaddstr(mixer_widget.window, top + 5, left,    "(Lewis Carroll, \"The Hunting of the Snark\")");
+               top += 8;
+       }
+       wattrset(mixer_widget.window, attr_errormsg);
+       center_string(top, _("The sound device was unplugged."));
+       center_string(top + 1, _("Press F6 to select another sound card."));
+}
+
+static void display_no_controls(void)
+{
+       int y;
+       const char *msg;
+
+       y = (screen_lines - 6) / 2 - 1;
+       if (y < 5)
+               y = 5;
+       if (y >= screen_lines - 1)
+               return;
+       wattrset(mixer_widget.window, attr_infomsg);
+       if (view_mode == VIEW_MODE_PLAYBACK && are_there_any_controls())
+               msg = _("This sound device does not have any playback controls.");
+       else if (view_mode == VIEW_MODE_CAPTURE && are_there_any_controls())
+               msg = _("This sound device does not have any capture controls.");
+       else
+               msg = _("This sound device does not have any controls.");
+       center_string(y, msg);
+}
+
+static void display_string_centered_in_control(int y, int col, const char *s, int width)
+{
+       int left, x;
+
+       left = first_control_x + col * (control_width + 1);
+       x = left + (control_width - width) / 2;
+       display_string_in_field(y, x, s, width, ALIGN_CENTER);
+}
+
+static long clamp(long value, long min, long max)
+{
+       if (value < min)
+               return min;
+       if (value > max)
+               return max;
+       return value;
+}
+
+static void display_control(unsigned int control_index)
+{
+       struct control *control;
+       int col;
+       int i, c;
+       int left, frame_left;
+       int bar_height, value;
+       long volumes[2];
+       long min, max;
+       int switches[2];
+       unsigned int index;
+       const char *s;
+       char buf[64];
+       int err;
+
+       control = &controls[control_index];
+       col = control_index - first_visible_control_index;
+       left = first_control_x + col * (control_width + 1);
+       frame_left = left + (control_width - 4) / 2;
+       if (control->flags & IS_ACTIVE)
+               wattrset(mixer_widget.window, attr_ctl_frame);
+       else
+               wattrset(mixer_widget.window, attr_ctl_inactive);
+       if (control->flags & (TYPE_PVOLUME | TYPE_CVOLUME)) {
+               mvwaddch(mixer_widget.window, base_y - volume_height - 1, frame_left, ACS_ULCORNER);
+               waddch(mixer_widget.window, ACS_HLINE);
+               waddch(mixer_widget.window, ACS_HLINE);
+               waddch(mixer_widget.window, ACS_URCORNER);
+               for (i = 0; i < volume_height; ++i) {
+                       mvwaddch(mixer_widget.window, base_y - i - 1, frame_left, ACS_VLINE);
+                       mvwaddch(mixer_widget.window, base_y - i - 1, frame_left + 3, ACS_VLINE);
+               }
+               mvwaddch(mixer_widget.window, base_y, frame_left,
+                        control->flags & TYPE_PSWITCH ? ACS_LTEE : ACS_LLCORNER);
+               waddch(mixer_widget.window, ACS_HLINE);
+               waddch(mixer_widget.window, ACS_HLINE);
+               waddch(mixer_widget.window,
+                      control->flags & TYPE_PSWITCH ? ACS_RTEE : ACS_LRCORNER);
+       } else if (control->flags & TYPE_PSWITCH) {
+               mvwaddch(mixer_widget.window, base_y, frame_left, ACS_ULCORNER);
+               waddch(mixer_widget.window, ACS_HLINE);
+               waddch(mixer_widget.window, ACS_HLINE);
+               waddch(mixer_widget.window, ACS_URCORNER);
+       }
+       if (control->flags & TYPE_PSWITCH) {
+               mvwaddch(mixer_widget.window, base_y + 1, frame_left, ACS_VLINE);
+               mvwaddch(mixer_widget.window, base_y + 1, frame_left + 3, ACS_VLINE);
+               mvwaddch(mixer_widget.window, base_y + 2, frame_left, ACS_LLCORNER);
+               waddch(mixer_widget.window, ACS_HLINE);
+               waddch(mixer_widget.window, ACS_HLINE);
+               waddch(mixer_widget.window, ACS_LRCORNER);
+       }
+       if (control->flags & (TYPE_PVOLUME | TYPE_CVOLUME)) {
+               int (*get_vol_func)(snd_mixer_elem_t *, snd_mixer_selem_channel_id_t, long *);
+
+               if (control->flags & TYPE_PVOLUME)
+                       get_vol_func = snd_mixer_selem_get_playback_volume;
+               else
+                       get_vol_func = snd_mixer_selem_get_capture_volume;
+               err = get_vol_func(control->elem, control->volume_channels[0], &volumes[0]);
+               if (err >= 0 && (control->flags & HAS_VOLUME_1))
+                       err = get_vol_func(control->elem, control->volume_channels[1], &volumes[1]);
+               else
+                       volumes[1] = volumes[0];
+               if (err < 0)
+                       return;
+               if (control->flags & TYPE_PVOLUME)
+                       err = snd_mixer_selem_get_playback_volume_range(control->elem, &min, &max);
+               else
+                       err = snd_mixer_selem_get_capture_volume_range(control->elem, &min, &max);
+               if (err < 0)
+                       return;
+               if (min >= max)
+                       max = min + 1;
+               volumes[0] = clamp(volumes[0], min, max);
+               volumes[1] = clamp(volumes[1], min, max);
+
+               if (control->flags & IS_ACTIVE)
+                       wattrset(mixer_widget.window, 0);
+               for (c = 0; c < 2; c++) {
+                       bar_height = ((volumes[c] - min) * volume_height +
+                                     max - min - 1) / (max - min);
+                       for (i = 0; i < volume_height; ++i) {
+                               chtype ch;
+                               if (i + 1 > bar_height)
+                                       ch = ' ' | (control->flags & IS_ACTIVE ?
+                                                   attr_ctl_frame : 0);
+                               else {
+                                       ch = ACS_CKBOARD;
+                                       if (!(control->flags & IS_ACTIVE))
+                                               ;
+#ifdef TRICOLOR_VOLUME_BAR
+                                       else if (i > volume_height * 8 / 10)
+                                               ch |= attr_ctl_bar_hi;
+                                       else if (i > volume_height * 4 / 10)
+                                               ch |= attr_ctl_bar_mi;
+#endif
+                                       else
+                                               ch |= attr_ctl_bar_lo;
+                               }
+                               mvwaddch(mixer_widget.window, base_y - i - 1,
+                                        frame_left + c + 1, ch);
+                       }
+               }
+               if (control->flags & IS_ACTIVE)
+                       wattrset(mixer_widget.window, attr_mixer_active);
+               value = ((volumes[0] - min) * 100 + (max - min) / 2) / (max - min);
+               if (!(control->flags & HAS_VOLUME_1)) {
+                       sprintf(buf, "%d", value);
+                       display_string_in_field(values_y, frame_left - 2, buf, 8, ALIGN_CENTER);
+               } else {
+                       mvwprintw(mixer_widget.window, values_y, frame_left - 2, "%3d", value);
+                       if (control->flags & IS_ACTIVE)
+                               wattrset(mixer_widget.window, attr_ctl_frame);
+                       waddstr(mixer_widget.window, "<>");
+                       if (control->flags & IS_ACTIVE)
+                               wattrset(mixer_widget.window, attr_mixer_active);
+                       value = ((volumes[1] - min) * 100 + (max - min) / 2) / (max - min);
+                       wprintw(mixer_widget.window, "%-3d", value);
+               }
+       }
+
+       if (control->flags & TYPE_PSWITCH) {
+               err = snd_mixer_selem_get_playback_switch(control->elem, control->pswitch_channels[0], &switches[0]);
+               if (err >= 0 && (control->flags & HAS_PSWITCH_1))
+                       err = snd_mixer_selem_get_playback_switch(control->elem, control->pswitch_channels[1], &switches[1]);
+               else
+                       switches[1] = switches[0];
+               if (err < 0)
+                       return;
+               if (control->flags & IS_ACTIVE)
+                       wattrset(mixer_widget.window, 0);
+               mvwaddch(mixer_widget.window, base_y + 1, frame_left + 1,
+                        switches[0]
+                        /* TRANSLATORS: playback on; one character */
+                        ? _("O")[0] | (control->flags & IS_ACTIVE ? attr_ctl_nomute : 0)
+                        /* TRANSLATORS: playback muted; one character */
+                        : _("M")[0] | (control->flags & IS_ACTIVE ? attr_ctl_mute : 0));
+               waddch(mixer_widget.window,
+                      switches[1]
+                      ? _("O")[0] | (control->flags & IS_ACTIVE ? attr_ctl_nomute : 0)
+                      : _("M")[0] | (control->flags & IS_ACTIVE ? attr_ctl_mute : 0));
+       }
+
+       if (control->flags & TYPE_CSWITCH) {
+               err = snd_mixer_selem_get_capture_switch(control->elem, control->cswitch_channels[0], &switches[0]);
+               if (err >= 0 && (control->flags & HAS_CSWITCH_1))
+                       err = snd_mixer_selem_get_capture_switch(control->elem, control->cswitch_channels[1], &switches[1]);
+               else
+                       switches[1] = switches[0];
+               if (err < 0)
+                       return;
+               if (control->flags & IS_ACTIVE)
+                       wattrset(mixer_widget.window, switches[0] ? attr_ctl_capture : attr_ctl_nocapture);
+               /* TRANSLATORS: "left"; no more than two characters */
+               display_string_in_field(cswitch_y - 1, frame_left - 2, switches[0] ? _("L") : "", 2, ALIGN_RIGHT);
+               if (control->flags & IS_ACTIVE)
+                       wattrset(mixer_widget.window, switches[1] ? attr_ctl_capture : attr_ctl_nocapture);
+               /* TRANSLATORS: "right"; no more than two characters */
+               display_string_in_field(cswitch_y - 1, frame_left + 4, switches[1] ? _("R") : "", 2, ALIGN_LEFT);
+               /* TRANSLATORS: no more than eight characters */
+               s = _("CAPTURE");
+               if (switches[0] || switches[1]) {
+                       if (control->flags & IS_ACTIVE)
+                               wattrset(mixer_widget.window, attr_ctl_capture);
+                       display_string_in_field(cswitch_y, frame_left - 2, s, 8, ALIGN_CENTER);
+               } else {
+                       i = get_mbs_width(s);
+                       if (i > 8)
+                               i = 8;
+                       memset(buf, '-', i);
+                       buf[i] = '\0';
+                       if (control->flags & IS_ACTIVE)
+                               wattrset(mixer_widget.window, attr_ctl_nocapture);
+                       display_string_in_field(cswitch_y, frame_left - 2, buf, 8, ALIGN_CENTER);
+               }
+       }
+
+       if (control->flags & TYPE_ENUM) {
+               err = snd_mixer_selem_get_enum_item(control->elem, ffs(control->enum_channel_bits) - 1, &index);
+               if (err < 0)
+                       return;
+               err = snd_mixer_selem_get_enum_item_name(control->elem, index, sizeof buf - 1, buf);
+               if (err < 0)
+                       return;
+               if (control->flags & IS_ACTIVE)
+                       wattrset(mixer_widget.window, attr_mixer_active);
+               display_string_centered_in_control(base_y, col, buf, control_width);
+       }
+
+       if (control_index == focus_control_index) {
+               i = first_control_x + col * (control_width + 1) + (control_width - control_name_width) / 2;
+               wattrset(mixer_widget.window, attr_ctl_mark_focus);
+               mvwaddch(mixer_widget.window, name_y, i - 1, '<');
+               mvwaddch(mixer_widget.window, name_y, i + control_name_width, '>');
+               if (control->flags & IS_ACTIVE)
+                       wattrset(mixer_widget.window, attr_ctl_label_focus);
+               else
+                       wattrset(mixer_widget.window, attr_ctl_label_inactive);
+       } else {
+               if (control->flags & IS_ACTIVE)
+                       wattrset(mixer_widget.window, attr_ctl_label);
+               else
+                       wattrset(mixer_widget.window, attr_ctl_label_inactive);
+       }
+       display_string_centered_in_control(name_y, col, control->name, control_name_width);
+       if (channel_name_y > name_y) {
+               if (control->flags & IS_MULTICH) {
+                       switch (control->flags & MULTICH_MASK) {
+                       case 0:
+                       default:
+                               s = _("Front");
+                               break;
+                       case 1:
+                               s = _("Rear");
+                               break;
+                       case 2:
+                               s = _("Center");
+                               break;
+                       case 3:
+                               s = _("Woofer");
+                               break;
+                       case 4:
+                               s = _("Side");
+                               break;
+                       }
+               } else {
+                       s = "";
+                       wattrset(mixer_widget.window, attr_mixer_frame);
+               }
+               display_string_centered_in_control(channel_name_y, col, s,
+                                                  control_name_width);
+       }
+}
+
+static void display_scroll_indicators(void)
+{
+       int y0, y1, y;
+       chtype left, right;
+
+       if (screen_too_small)
+               return;
+       y0 = screen_lines * 3 / 8;
+       y1 = screen_lines * 5 / 8;
+       left = first_visible_control_index > 0 ? ACS_LARROW : ACS_VLINE;
+       right = first_visible_control_index + visible_controls < controls_count
+               ? ACS_RARROW : ACS_VLINE;
+       wattrset(mixer_widget.window, attr_mixer_frame);
+       for (y = y0; y <= y1; ++y) {
+               mvwaddch(mixer_widget.window, y, 0, left);
+               mvwaddch(mixer_widget.window, y, screen_cols - 1, right);
+       }
+}
+
+void display_controls(void)
+{
+       unsigned int i;
+
+       if (first_visible_control_index > controls_count - visible_controls)
+               first_visible_control_index = controls_count - visible_controls;
+       if (first_visible_control_index > focus_control_index)
+               first_visible_control_index = focus_control_index;
+       else if (first_visible_control_index < focus_control_index - visible_controls + 1 && visible_controls)
+               first_visible_control_index = focus_control_index - visible_controls + 1;
+
+       clear_controls_display();
+
+       display_focus_item_info();
+
+       if (controls_count > 0) {
+               if (!screen_too_small)
+                       for (i = 0; i < visible_controls; ++i)
+                               display_control(first_visible_control_index + i);
+       } else if (unplugged) {
+               display_unplugged();
+       } else if (mixer_device_name) {
+               display_no_controls();
+       }
+       display_scroll_indicators();
+       controls_changed = FALSE;
+}
+
+void compute_controls_layout(void)
+{
+       bool any_volume, any_pswitch, any_cswitch, any_multich;
+       int max_width, name_len;
+       int height, space;
+       unsigned int i;
+
+       if (controls_count == 0 || screen_too_small) {
+               visible_controls = 0;
+               return;
+       }
+
+       any_volume = FALSE;
+       any_pswitch = FALSE;
+       any_cswitch = FALSE;
+       any_multich = FALSE;
+       for (i = 0; i < controls_count; ++i) {
+               if (controls[i].flags & (TYPE_PVOLUME | TYPE_CVOLUME))
+                       any_volume = 1;
+               if (controls[i].flags & TYPE_PSWITCH)
+                       any_pswitch = 1;
+               if (controls[i].flags & TYPE_CSWITCH)
+                       any_cswitch = 1;
+               if (controls[i].flags & IS_MULTICH)
+                       any_multich = 1;
+       }
+
+       max_width = 8;
+       for (i = 0; i < controls_count; ++i) {
+               name_len = strlen(controls[i].name);
+               if (name_len > max_width)
+                       max_width = name_len;
+       }
+       max_width = (max_width + 1) & ~1;
+
+       control_width = (screen_cols - 3 - (int)controls_count) / controls_count;
+       if (control_width < 8)
+               control_width = 8;
+       if (control_width > max_width)
+               control_width = max_width;
+       if (control_width > screen_cols - 4)
+               control_width = screen_cols - 4;
+
+       visible_controls = (screen_cols - 3) / (control_width + 1);
+       if (visible_controls > controls_count)
+               visible_controls = controls_count;
+
+       first_control_x = 2 + (screen_cols - 3 - visible_controls * (control_width + 1)) / 2;
+
+       if (control_width < max_width)
+               control_name_width = control_width;
+       else
+               control_name_width = max_width;
+
+       height = 2;
+       if (any_volume)
+               height += 2;
+       if (any_pswitch)
+               height += 2;
+       if (any_cswitch)
+               height += 1;
+       if (any_multich)
+               height += 1;
+       if (any_volume) {
+               space = screen_lines - 6 - height;
+               if (space <= 1)
+                       volume_height = 1;
+               else if (space <= 10)
+                       volume_height = space;
+               else
+                       volume_height = 10 + (space - 10) / 2;
+               height += volume_height;
+       }
+
+       space = screen_lines - 6 - height;
+       channel_name_y = screen_lines - 2 - space / 2;
+       name_y = channel_name_y - any_multich;
+       values_y = name_y - any_volume;
+       cswitch_y = values_y - any_cswitch;
+       base_y = cswitch_y - 1 - 2 * any_pswitch;
+}
diff --git a/alsamixer/mixer_display.h b/alsamixer/mixer_display.h
new file mode 100644 (file)
index 0000000..3d65670
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef MIXER_DISPLAY_H_INCLUDED
+#define MIXER_DISPLAY_H_INCLUDED
+
+void init_mixer_layout(void);
+void display_card_info(void);
+void display_view_mode(void);
+void display_controls(void);
+void compute_controls_layout(void);
+
+#endif
diff --git a/alsamixer/mixer_widget.c b/alsamixer/mixer_widget.c
new file mode 100644 (file)
index 0000000..796ea1d
--- /dev/null
@@ -0,0 +1,680 @@
+/*
+ * mixer_widget.c - mixer widget and keys handling
+ * Copyright (c) 1998,1999 Tim Janik <timj@gtk.org>
+ *                         Jaroslav Kysela <perex@perex.cz>
+ * Copyright (c) 2009      Clemens Ladisch <clemens@ladisch.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "aconfig.h"
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <alsa/asoundlib.h>
+#include "gettext_curses.h"
+#include "version.h"
+#include "utils.h"
+#include "die.h"
+#include "mem.h"
+#include "colors.h"
+#include "widget.h"
+#include "textbox.h"
+#include "proc_files.h"
+#include "card_select.h"
+#include "mixer_controls.h"
+#include "mixer_display.h"
+#include "mixer_widget.h"
+
+snd_mixer_t *mixer;
+char *mixer_device_name;
+bool unplugged;
+
+struct widget mixer_widget;
+
+enum view_mode view_mode;
+
+int focus_control_index;
+snd_mixer_selem_id_t *current_selem_id;
+unsigned int current_control_flags;
+
+bool controls_changed;
+
+enum channel_mask {
+       LEFT = 1,
+       RIGHT = 2,
+};
+
+static int elem_callback(snd_mixer_elem_t *elem, unsigned int mask)
+{
+       if (mask & (SND_CTL_EVENT_MASK_REMOVE |
+                   SND_CTL_EVENT_MASK_INFO |
+                   SND_CTL_EVENT_MASK_VALUE))
+               controls_changed = TRUE;
+       return 0;
+}
+
+static int mixer_callback(snd_mixer_t *mixer, unsigned int mask, snd_mixer_elem_t *elem)
+{
+       if (mask & SND_CTL_EVENT_MASK_ADD) {
+               snd_mixer_elem_set_callback(elem, elem_callback);
+               controls_changed = TRUE;
+       }
+       return 0;
+}
+
+void create_mixer_object(struct snd_mixer_selem_regopt *selem_regopt)
+{
+       int err;
+
+       err = snd_mixer_open(&mixer, 0);
+       if (err < 0)
+               fatal_alsa_error(_("cannot open mixer"), err);
+
+       mixer_device_name = cstrdup(selem_regopt->device);
+       err = snd_mixer_selem_register(mixer, selem_regopt, NULL);
+       if (err < 0)
+               fatal_alsa_error(_("cannot open mixer"), err);
+
+       snd_mixer_set_callback(mixer, mixer_callback);
+
+       err = snd_mixer_load(mixer);
+       if (err < 0)
+               fatal_alsa_error(_("cannot load mixer controls"), err);
+
+       err = snd_mixer_selem_id_malloc(&current_selem_id);
+       if (err < 0)
+               fatal_error("out of memory");
+}
+
+static void set_view_mode(enum view_mode m)
+{
+       view_mode = m;
+       create_controls();
+}
+
+static void close_hctl(void)
+{
+       free_controls();
+       if (mixer_device_name) {
+               snd_mixer_detach(mixer, mixer_device_name);
+               free(mixer_device_name);
+               mixer_device_name = NULL;
+       }
+}
+
+static void check_unplugged(void)
+{
+       snd_hctl_t *hctl;
+       snd_ctl_t *ctl;
+       unsigned int state;
+       int err;
+
+       unplugged = FALSE;
+       if (mixer_device_name) {
+               err = snd_mixer_get_hctl(mixer, mixer_device_name, &hctl);
+               if (err >= 0) {
+                       ctl = snd_hctl_ctl(hctl);
+                       /* just any random function that does an ioctl() */
+                       err = snd_ctl_get_power_state(ctl, &state);
+                       if (err == -ENODEV)
+                               unplugged = TRUE;
+               }
+       }
+}
+
+void close_mixer_device(void)
+{
+       check_unplugged();
+       close_hctl();
+
+       display_card_info();
+       set_view_mode(view_mode);
+}
+
+bool select_card_by_name(const char *device_name)
+{
+       int err;
+       bool opened;
+       char *msg;
+
+       close_hctl();
+       unplugged = FALSE;
+
+       opened = FALSE;
+       if (device_name) {
+               err = snd_mixer_attach(mixer, device_name);
+               if (err >= 0)
+                       opened = TRUE;
+               else {
+                       msg = casprintf(_("Cannot open mixer device '%s'."), device_name);
+                       show_alsa_error(msg, err);
+                       free(msg);
+               }
+       }
+       if (opened) {
+               mixer_device_name = cstrdup(device_name);
+
+               err = snd_mixer_load(mixer);
+               if (err < 0)
+                       fatal_alsa_error(_("cannot load mixer controls"), err);
+       }
+
+       display_card_info();
+       set_view_mode(view_mode);
+       return opened;
+}
+
+static void show_help(void)
+{
+       const char *help[] = {
+               _("Esc     Exit"),
+               _("F1 ? H  Help"),
+               _("F2 /    System information"),
+               _("F3      Show playback controls"),
+               _("F4      Show capture controls"),
+               _("F5      Show all controls"),
+               _("Tab     Toggle view mode (F3/F4/F5)"),
+               _("F6 S    Select sound card"),
+               _("L       Redraw screen"),
+               "",
+               _("Left    Move to the previous control"),
+               _("Right   Move to the next control"),
+               "",
+               _("Up/Down    Change volume"),
+               _("+ -        Change volume"),
+               _("Page Up/Dn Change volume in big steps"),
+               _("End        Set volume to 0%"),
+               _("0-9        Set volume to 0%-90%"),
+               _("Q W E      Increase left/both/right volumes"),
+               /* TRANSLATORS: or Y instead of Z */
+               _("Z X C      Decrease left/both/right volumes"),
+               _("B          Balance left and right volumes"),
+               "",
+               _("M          Toggle mute"),
+               /* TRANSLATORS: or , . */
+               _("< >        Toggle left/right mute"),
+               "",
+               _("Space      Toggle capture"),
+               /* TRANSLATORS: or Insert Delete */
+               _("; '        Toggle left/right capture"),
+               "",
+               _("Authors:"),
+               _("  Tim Janik <timj@gtk.org>"),
+               _("  Jaroslav Kysela <perex@perex.cz>"),
+               _("  Clemens Ladisch <clemens@ladisch.de>"),
+       };
+       show_text(help, ARRAY_SIZE(help), _("Help"));
+}
+
+void refocus_control(void)
+{
+       if (focus_control_index < controls_count) {
+               snd_mixer_selem_get_id(controls[focus_control_index].elem, current_selem_id);
+               current_control_flags = controls[focus_control_index].flags;
+       }
+
+       display_controls();
+}
+
+static struct control *get_focus_control(unsigned int type)
+{
+       if (focus_control_index >= 0 &&
+           focus_control_index < controls_count &&
+           (controls[focus_control_index].flags & IS_ACTIVE) &&
+           (controls[focus_control_index].flags & type))
+               return &controls[focus_control_index];
+       else
+               return NULL;
+}
+
+static void change_enum_to_percent(struct control *control, int value)
+{
+       unsigned int i;
+       unsigned int index;
+       unsigned int new_index;
+       int items;
+       int err;
+
+       i = ffs(control->enum_channel_bits) - 1;
+       err = snd_mixer_selem_get_enum_item(control->elem, i, &index);
+       if (err < 0)
+               return;
+       new_index = index;
+       if (value == 0) {
+               new_index = 0;
+       } else if (value == 100) {
+               items = snd_mixer_selem_get_enum_items(control->elem);
+               if (items < 1)
+                       return;
+               new_index = items - 1;
+       }
+       if (new_index == index)
+               return;
+       for (i = 0; i <= SND_MIXER_SCHN_LAST; ++i)
+               if (control->enum_channel_bits & (1 << i))
+                       snd_mixer_selem_set_enum_item(control->elem, i, new_index);
+}
+
+static void change_enum_relative(struct control *control, int delta)
+{
+       int items;
+       unsigned int i;
+       unsigned int index;
+       int new_index;
+       int err;
+
+       items = snd_mixer_selem_get_enum_items(control->elem);
+       if (items < 1)
+               return;
+       err = snd_mixer_selem_get_enum_item(control->elem, 0, &index);
+       if (err < 0)
+               return;
+       new_index = (int)index + delta;
+       if (new_index < 0)
+               new_index = 0;
+       else if (new_index >= items)
+               new_index = items - 1;
+       if (new_index == index)
+               return;
+       for (i = 0; i <= SND_MIXER_SCHN_LAST; ++i)
+               if (control->enum_channel_bits & (1 << i))
+                       snd_mixer_selem_set_enum_item(control->elem, i, new_index);
+}
+
+static void change_volume_to_percent(struct control *control, int value, unsigned int channels)
+{
+       int (*get_range_func)(snd_mixer_elem_t *, long *, long *);
+       int (*set_func)(snd_mixer_elem_t *, snd_mixer_selem_channel_id_t, long);
+       long min, max;
+       int err;
+
+       if (!(control->flags & HAS_VOLUME_1))
+               channels = LEFT;
+       if (control->flags & TYPE_PVOLUME) {
+               get_range_func = snd_mixer_selem_get_playback_volume_range;
+               set_func = snd_mixer_selem_set_playback_volume;
+       } else {
+               get_range_func = snd_mixer_selem_get_capture_volume_range;
+               set_func = snd_mixer_selem_set_capture_volume;
+       }
+       err = get_range_func(control->elem, &min, &max);
+       if (err < 0)
+               return;
+       if (channels & LEFT)
+               set_func(control->elem, control->volume_channels[0], min + (max - min) * value / 100);
+       if (channels & RIGHT)
+               set_func(control->elem, control->volume_channels[1], min + (max - min) * value / 100);
+}
+
+static void change_volume_relative(struct control *control, int delta, unsigned int channels)
+{
+       int (*get_range_func)(snd_mixer_elem_t *, long *, long *);
+       int (*get_func)(snd_mixer_elem_t *, snd_mixer_selem_channel_id_t, long *);
+       int (*set_func)(snd_mixer_elem_t *, snd_mixer_selem_channel_id_t, long);
+       long min, max;
+       long left, right;
+       long value;
+       int err;
+
+       if (!(control->flags & HAS_VOLUME_1))
+               channels = LEFT;
+       if (control->flags & TYPE_PVOLUME) {
+               get_range_func = snd_mixer_selem_get_playback_volume_range;
+               get_func = snd_mixer_selem_get_playback_volume;
+               set_func = snd_mixer_selem_set_playback_volume;
+       } else {
+               get_range_func = snd_mixer_selem_get_capture_volume_range;
+               get_func = snd_mixer_selem_get_capture_volume;
+               set_func = snd_mixer_selem_set_capture_volume;
+       }
+       err = get_range_func(control->elem, &min, &max);
+       if (err < 0)
+               return;
+       if (channels & LEFT) {
+               err = get_func(control->elem, control->volume_channels[0], &left);
+               if (err < 0)
+                       return;
+       }
+       if (channels & RIGHT) {
+               err = get_func(control->elem, control->volume_channels[1], &right);
+               if (err < 0)
+                       return;
+       }
+       if (channels & LEFT) {
+               value = left + delta;
+               if (value < min)
+                       value = min;
+               else if (value > max)
+                       value = max;
+               if (value != left)
+                       set_func(control->elem, control->volume_channels[0], value);
+       }
+       if (channels & RIGHT) {
+               value = right + delta;
+               if (value < min)
+                       value = min;
+               else if (value > max)
+                       value = max;
+               if (value != right)
+                       set_func(control->elem, control->volume_channels[1], value);
+       }
+}
+
+static void change_control_to_percent(int value, unsigned int channels)
+{
+       struct control *control;
+
+       control = get_focus_control(TYPE_PVOLUME | TYPE_CVOLUME | TYPE_ENUM);
+       if (!control)
+               return;
+       if (control->flags & TYPE_ENUM)
+               change_enum_to_percent(control, value);
+       else
+               change_volume_to_percent(control, value, channels);
+       display_controls();
+}
+
+static void change_control_relative(int delta, unsigned int channels)
+{
+       struct control *control;
+
+       control = get_focus_control(TYPE_PVOLUME | TYPE_CVOLUME | TYPE_ENUM);
+       if (!control)
+               return;
+       if (control->flags & TYPE_ENUM)
+               change_enum_relative(control, delta);
+       else
+               change_volume_relative(control, delta, channels);
+       display_controls();
+}
+
+static void toggle_switches(unsigned int type, unsigned int channels)
+{
+       struct control *control;
+       unsigned int switch_1_mask;
+       int (*get_func)(snd_mixer_elem_t *, snd_mixer_selem_channel_id_t, int *);
+       int (*set_func)(snd_mixer_elem_t *, snd_mixer_selem_channel_id_t, int);
+       snd_mixer_selem_channel_id_t channel_ids[2];
+       int left, right;
+       int err;
+
+       control = get_focus_control(type);
+       if (!control)
+               return;
+       if (type == TYPE_PSWITCH) {
+               switch_1_mask = HAS_PSWITCH_1;
+               get_func = snd_mixer_selem_get_playback_switch;
+               set_func = snd_mixer_selem_set_playback_switch;
+               channel_ids[0] = control->pswitch_channels[0];
+               channel_ids[1] = control->pswitch_channels[1];
+       } else {
+               switch_1_mask = HAS_CSWITCH_1;
+               get_func = snd_mixer_selem_get_capture_switch;
+               set_func = snd_mixer_selem_set_capture_switch;
+               channel_ids[0] = control->cswitch_channels[0];
+               channel_ids[1] = control->cswitch_channels[1];
+       }
+       if (!(control->flags & switch_1_mask))
+               channels = LEFT;
+       if (channels & LEFT) {
+               err = get_func(control->elem, channel_ids[0], &left);
+               if (err < 0)
+                       return;
+       }
+       if (channels & RIGHT) {
+               err = get_func(control->elem, channel_ids[1], &right);
+               if (err < 0)
+                       return;
+       }
+       if (channels & LEFT)
+               set_func(control->elem, channel_ids[0], !left);
+       if (channels & RIGHT)
+               set_func(control->elem, channel_ids[1], !right);
+       display_controls();
+}
+
+static void toggle_mute(unsigned int channels)
+{
+       toggle_switches(TYPE_PSWITCH, channels);
+}
+
+static void toggle_capture(unsigned int channels)
+{
+       toggle_switches(TYPE_CSWITCH, channels);
+}
+
+static void balance_volumes(void)
+{
+       struct control *control;
+       long left, right;
+       int err;
+
+       control = get_focus_control(TYPE_PVOLUME | TYPE_CVOLUME);
+       if (!control || !(control->flags & HAS_VOLUME_1))
+               return;
+       if (control->flags & TYPE_PVOLUME) {
+               err = snd_mixer_selem_get_playback_volume(control->elem, control->volume_channels[0], &left);
+               if (err < 0)
+                       return;
+               err = snd_mixer_selem_get_playback_volume(control->elem, control->volume_channels[1], &right);
+               if (err < 0)
+                       return;
+       } else {
+               err = snd_mixer_selem_get_capture_volume(control->elem, control->volume_channels[0], &left);
+               if (err < 0)
+                       return;
+               err = snd_mixer_selem_get_capture_volume(control->elem, control->volume_channels[1], &right);
+               if (err < 0)
+                       return;
+       }
+       left = (left + right) / 2;
+       if (control->flags & TYPE_PVOLUME) {
+               snd_mixer_selem_set_playback_volume(control->elem, control->volume_channels[0], left);
+               snd_mixer_selem_set_playback_volume(control->elem, control->volume_channels[1], left);
+       } else {
+               snd_mixer_selem_set_capture_volume(control->elem, control->volume_channels[0], left);
+               snd_mixer_selem_set_capture_volume(control->elem, control->volume_channels[1], left);
+       }
+       display_controls();
+}
+
+static void on_handle_key(int key)
+{
+       switch (key) {
+       case 27:
+       case KEY_CANCEL:
+       case KEY_F(10):
+               mixer_widget.close();
+               break;
+       case KEY_F(1):
+       case KEY_HELP:
+       case 'H':
+       case 'h':
+       case '?':
+               show_help();
+               break;
+       case KEY_F(2):
+       case '/':
+               create_proc_files_list();
+               break;
+       case KEY_F(3):
+               set_view_mode(VIEW_MODE_PLAYBACK);
+               break;
+       case KEY_F(4):
+               set_view_mode(VIEW_MODE_CAPTURE);
+               break;
+       case KEY_F(5):
+               set_view_mode(VIEW_MODE_ALL);
+               break;
+       case '\t':
+               set_view_mode((enum view_mode)((view_mode + 1) % VIEW_MODE_COUNT));
+               break;
+       case KEY_F(6):
+       case 'S':
+       case 's':
+               create_card_select_list();
+               break;
+       case KEY_REFRESH:
+       case 12:
+       case 'L':
+       case 'l':
+               clearok(mixer_widget.window, TRUE);
+               display_controls();
+               break;
+       case KEY_LEFT:
+       case 'P':
+       case 'p':
+               if (focus_control_index > 0) {
+                       --focus_control_index;
+                       refocus_control();
+               }
+               break;
+       case KEY_RIGHT:
+       case 'N':
+       case 'n':
+               if (focus_control_index < controls_count - 1) {
+                       ++focus_control_index;
+                       refocus_control();
+               }
+               break;
+       case KEY_PPAGE:
+               change_control_relative(5, LEFT | RIGHT);
+               break;
+       case KEY_NPAGE:
+               change_control_relative(-5, LEFT | RIGHT);
+               break;
+#if 0
+       case KEY_BEG:
+       case KEY_HOME:
+               change_control_to_percent(100, LEFT | RIGHT);
+               break;
+#endif
+       case KEY_LL:
+       case KEY_END:
+               change_control_to_percent(0, LEFT | RIGHT);
+               break;
+       case KEY_UP:
+       case '+':
+       case 'K':
+       case 'k':
+       case 'W':
+       case 'w':
+               change_control_relative(1, LEFT | RIGHT);
+               break;
+       case KEY_DOWN:
+       case '-':
+       case 'J':
+       case 'j':
+       case 'X':
+       case 'x':
+               change_control_relative(-1, LEFT | RIGHT);
+               break;
+       case '0': case '1': case '2': case '3': case '4':
+       case '5': case '6': case '7': case '8': case '9':
+               change_control_to_percent((key - '0') * 10, LEFT | RIGHT);
+               break;
+       case 'Q':
+       case 'q':
+               change_control_relative(1, LEFT);
+               break;
+       case 'Y':
+       case 'y':
+       case 'Z':
+       case 'z':
+               change_control_relative(-1, LEFT);
+               break;
+       case 'E':
+       case 'e':
+               change_control_relative(1, RIGHT);
+               break;
+       case 'C':
+       case 'c':
+               change_control_relative(-1, RIGHT);
+               break;
+       case 'M':
+       case 'm':
+               toggle_mute(LEFT | RIGHT);
+               break;
+       case 'B':
+       case 'b':
+       case '=':
+               balance_volumes();
+               break;
+       case '<':
+       case ',':
+               toggle_mute(LEFT);
+               break;
+       case '>':
+       case '.':
+               toggle_mute(RIGHT);
+               break;
+       case ' ':
+               toggle_capture(LEFT | RIGHT);
+               break;
+       case KEY_IC:
+       case ';':
+               toggle_capture(LEFT);
+               break;
+       case KEY_DC:
+       case '\'':
+               toggle_capture(RIGHT);
+               break;
+       }
+}
+
+static void create(void)
+{
+       static const char title[] = " AlsaMixer v" SND_UTIL_VERSION_STR " ";
+
+       widget_init(&mixer_widget, screen_lines, screen_cols, 0, 0,
+                   attr_mixer_frame, WIDGET_BORDER);
+       if (screen_cols >= (sizeof(title) - 1) + 2) {
+               wattrset(mixer_widget.window, attr_mixer_active);
+               mvwaddstr(mixer_widget.window, 0, (screen_cols - (sizeof(title) - 1)) / 2, title);
+       }
+       init_mixer_layout();
+       display_card_info();
+       set_view_mode(view_mode);
+}
+
+static void on_window_size_changed(void)
+{
+       create();
+}
+
+static void on_close(void)
+{
+       widget_free(&mixer_widget);
+}
+
+void mixer_shutdown(void)
+{
+       free_controls();
+       if (mixer)
+               snd_mixer_close(mixer);
+       if (current_selem_id)
+               snd_mixer_selem_id_free(current_selem_id);
+}
+
+struct widget mixer_widget = {
+       .handle_key = on_handle_key,
+       .window_size_changed = on_window_size_changed,
+       .close = on_close,
+};
+
+void create_mixer_widget(void)
+{
+       create();
+}
diff --git a/alsamixer/mixer_widget.h b/alsamixer/mixer_widget.h
new file mode 100644 (file)
index 0000000..da8628e
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef MIXER_WIDGET_H_INCLUDED
+#define MIXER_WIDGET_H_INCLUDED
+
+#include CURSESINC
+#include <alsa/asoundlib.h>
+#include "widget.h"
+
+enum view_mode {
+       VIEW_MODE_PLAYBACK,
+       VIEW_MODE_CAPTURE,
+       VIEW_MODE_ALL,
+       VIEW_MODE_COUNT,
+};
+
+extern snd_mixer_t *mixer;
+extern char *mixer_device_name;
+extern bool unplugged;
+
+extern struct widget mixer_widget;
+
+extern enum view_mode view_mode;
+
+extern int focus_control_index;
+extern snd_mixer_selem_id_t *current_selem_id;
+extern unsigned int current_control_flags;
+
+extern bool controls_changed;
+
+void create_mixer_object(struct snd_mixer_selem_regopt *selem_regopt);
+void create_mixer_widget(void);
+void mixer_shutdown(void);
+void close_mixer_device(void);
+bool select_card_by_name(const char *device_name);
+void refocus_control(void);
+
+#endif
diff --git a/alsamixer/proc_files.c b/alsamixer/proc_files.c
new file mode 100644 (file)
index 0000000..b2f5f21
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * proc_files.c - shows ALSA system information files
+ * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "aconfig.h"
+#include <assert.h>
+#include <menu.h>
+#include <unistd.h>
+#include "gettext_curses.h"
+#include "utils.h"
+#include "die.h"
+#include "mem.h"
+#include "colors.h"
+#include "widget.h"
+#include "textbox.h"
+#include "proc_files.h"
+
+static struct widget proc_widget;
+static ITEM *items[7];
+static unsigned int items_count;
+static MENU *menu;
+
+static void on_menu_key(int key)
+{
+       static const struct {
+               int key;
+               int request;
+       } key_map[] = {
+               { KEY_DOWN, REQ_DOWN_ITEM },
+               { KEY_UP, REQ_UP_ITEM },
+               { KEY_HOME, REQ_FIRST_ITEM },
+               { KEY_NPAGE, REQ_SCR_DPAGE },
+               { KEY_PPAGE, REQ_SCR_UPAGE },
+               { KEY_BEG, REQ_FIRST_ITEM },
+               { KEY_END, REQ_LAST_ITEM },
+       };
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(key_map); ++i)
+               if (key_map[i].key == key) {
+                       menu_driver(menu, key_map[i].request);
+                       break;
+               }
+}
+
+static void on_handle_key(int key)
+{
+       ITEM *item;
+
+       switch (key) {
+       case 27:
+       case KEY_CANCEL:
+               proc_widget.close();
+               break;
+       case 10:
+       case 13:
+       case KEY_ENTER:
+               item = current_item(menu);
+               if (item)
+                       show_textfile(item_name(item));
+               break;
+       default:
+               on_menu_key(key);
+               break;
+       }
+}
+
+static bool create(void)
+{
+       int rows, columns;
+       const char *title;
+
+       if (screen_lines < 3 || screen_cols < 20) {
+               proc_widget.close();
+               beep();
+               return FALSE;
+       }
+       scale_menu(menu, &rows, &columns);
+       rows += 2;
+       columns += 2;
+       if (rows > screen_lines)
+               rows = screen_lines;
+       if (columns > screen_cols)
+               columns = screen_cols;
+
+       widget_init(&proc_widget, rows, columns, SCREEN_CENTER, SCREEN_CENTER,
+                   attr_menu, WIDGET_BORDER | WIDGET_SUBWINDOW);
+
+       title = _("Select File");
+       mvwprintw(proc_widget.window, 0, (columns - 2 - get_mbs_width(title)) / 2, " %s ", title);
+       set_menu_win(menu, proc_widget.window);
+       set_menu_sub(menu, proc_widget.subwindow);
+       return TRUE;
+}
+
+static void on_window_size_changed(void)
+{
+       unpost_menu(menu);
+       if (!create())
+               return;
+       post_menu(menu);
+}
+
+static void on_close(void)
+{
+       unsigned int i;
+
+       unpost_menu(menu);
+       free_menu(menu);
+       for (i = 0; i < items_count; ++i)
+               free_item(items[i]);
+       widget_free(&proc_widget);
+}
+
+static void add_item(const char *file_name)
+{
+       if (access(file_name, F_OK) == 0) {
+               items[items_count] = new_item(file_name, NULL);
+               if (!items[items_count])
+                       fatal_error("cannot create menu item");
+               ++items_count;
+               assert(items_count < ARRAY_SIZE(items));
+       }
+}
+
+static struct widget proc_widget = {
+       .handle_key = on_handle_key,
+       .window_size_changed = on_window_size_changed,
+       .close = on_close,
+};
+
+void create_proc_files_list(void)
+{
+       items_count = 0;
+       add_item("/proc/asound/version");
+       add_item("/proc/asound/cards");
+       add_item("/proc/asound/devices");
+       add_item("/proc/asound/oss/devices");
+       add_item("/proc/asound/timers");
+       add_item("/proc/asound/pcm");
+       items[items_count] = NULL;
+
+       menu = new_menu(items);
+       if (!menu)
+               fatal_error("cannot create menu");
+       set_menu_fore(menu, attr_menu_selected);
+       set_menu_back(menu, attr_menu);
+       set_menu_mark(menu, NULL);
+       menu_opts_off(menu, O_SHOWDESC);
+
+       if (!create())
+               return;
+
+       post_menu(menu);
+}
diff --git a/alsamixer/proc_files.h b/alsamixer/proc_files.h
new file mode 100644 (file)
index 0000000..8862c71
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef PROC_FILES_H_INCLUDED
+#define PROC_FILES_H_INCLUDED
+
+void create_proc_files_list(void);
+
+#endif
diff --git a/alsamixer/textbox.c b/alsamixer/textbox.c
new file mode 100644 (file)
index 0000000..d743a14
--- /dev/null
@@ -0,0 +1,397 @@
+/*
+ * textbox.c - show a text box for messages, files or help
+ * Copyright (c) 1998,1999 Tim Janik <timj@gtk.org>
+ *                         Jaroslav Kysela <perex@perex.cz>
+ * Copyright (c) 2009      Clemens Ladisch <clemens@ladisch.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "aconfig.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include CURSESINC
+#include <alsa/asoundlib.h>
+#include "gettext_curses.h"
+#include "utils.h"
+#include "die.h"
+#include "mem.h"
+#include "colors.h"
+#include "widget.h"
+#include "textbox.h"
+
+#define MAX_FILE_SIZE 1048576
+
+static void create_text_box(const char *const *lines, unsigned int count,
+                           const char *title, int attrs);
+
+void show_error(const char *msg, int err)
+{
+       const char *lines[2];
+       unsigned int count;
+
+       lines[0] = msg;
+       count = 1;
+       if (err) {
+               lines[1] = strerror(err);
+               count = 2;
+       }
+       create_text_box(lines, count, _("Error"), attr_errormsg);
+}
+
+void show_alsa_error(const char *msg, int err)
+{
+       const char *lines[2];
+       unsigned int count;
+
+       lines[0] = msg;
+       count = 1;
+       if (err < 0) {
+               lines[1] = snd_strerror(err);
+               count = 2;
+       }
+       create_text_box(lines, count, _("Error"), attr_errormsg);
+}
+
+static char *read_file(const char *file_name, unsigned int *file_size)
+{
+       FILE *f;
+       int err;
+       char *buf;
+       unsigned int allocated = 2048;
+       unsigned int bytes_read;
+
+       f = fopen(file_name, "r");
+       if (!f) {
+               err = errno;
+               buf = casprintf(_("Cannot open file \"%s\"."), file_name);
+               show_error(buf, err);
+               free(buf);
+               return NULL;
+       }
+       *file_size = 0;
+       buf = NULL;
+       do {
+               allocated *= 2;
+               buf = crealloc(buf, allocated);
+               bytes_read = fread(buf + *file_size, 1, allocated - *file_size, f);
+               *file_size += bytes_read;
+       } while (*file_size == allocated && allocated < MAX_FILE_SIZE);
+       fclose(f);
+       if (*file_size > 0 && buf[*file_size - 1] != '\n' && *file_size < allocated) {
+               buf[*file_size] = '\n';
+               ++*file_size;
+       }
+       return buf;
+}
+
+void show_textfile(const char *file_name)
+{
+       char *buf;
+       unsigned int file_size;
+       unsigned int line_count;
+       unsigned int i;
+       const char **lines;
+       const char *start_line;
+
+       buf = read_file(file_name, &file_size);
+       if (!buf)
+               return;
+       line_count = 0;
+       for (i = 0; i < file_size; ++i)
+               line_count += buf[i] == '\n';
+       lines = ccalloc(line_count, sizeof *lines);
+       line_count = 0;
+       start_line = buf;
+       for (i = 0; i < file_size; ++i) {
+               if (buf[i] == '\n') {
+                       lines[line_count++] = start_line;
+                       buf[i] = '\0';
+                       start_line = &buf[i + 1];
+               }
+               if (buf[i] == '\t')
+                       buf[i] = ' ';
+       }
+       create_text_box(lines, line_count, file_name, attr_textbox);
+       free(lines);
+       free(buf);
+}
+
+void show_text(const char *const *lines, unsigned int count, const char *title)
+{
+       create_text_box(lines, count, title, attr_textbox);
+}
+
+/**********************************************************************/
+
+static struct widget text_widget;
+static char *title;
+static int widget_attrs;
+static char **text_lines;
+static unsigned int text_lines_count;
+static int max_line_width;
+static int text_box_y;
+static int text_box_x;
+static int max_scroll_y;
+static int max_scroll_x;
+static int current_top;
+static int current_left;
+
+static void update_text_lines(void)
+{
+       int i;
+       int width;
+       const char *line_begin;
+       const char *line_end;
+       int cur_y, cur_x;
+       int rest_of_line;
+
+       for (i = 0; i < text_box_y; ++i) {
+               width = current_left;
+               line_begin = mbs_at_width(text_lines[current_top + i], &width, 1);
+               wmove(text_widget.window, i + 1, 1);
+               if (width > current_left)
+                       waddch(text_widget.window, ' ');
+               if (*line_begin != '\0') {
+                       width = text_box_x - (width > current_left);
+                       line_end = mbs_at_width(line_begin, &width, -1);
+                       if (width)
+                               waddnstr(text_widget.window, line_begin,
+                                        line_end - line_begin);
+               }
+               getyx(text_widget.window, cur_y, cur_x);
+               if (cur_y == i + 1) {
+                       rest_of_line = text_box_x + 1 - cur_x;
+                       if (rest_of_line > 0)
+                               wprintw(text_widget.window, "%*s", rest_of_line, "");
+               }
+       }
+}
+
+static void update_y_scroll_bar(void)
+{
+       int length;
+       int begin, end;
+       int i;
+
+       if (max_scroll_y <= 0 || text_lines_count == 0)
+               return;
+       length = text_box_y * text_box_y / text_lines_count;
+       if (length >= text_box_y)
+               return;
+       begin = current_top * (text_box_y - length) / max_scroll_y;
+       end = begin + length;
+       for (i = 0; i < text_box_y; ++i)
+               mvwaddch(text_widget.window, i + 1, text_box_x + 1,
+                        i >= begin && i < end ? ACS_BOARD : ' ');
+}
+
+static void update_x_scroll_bar(void)
+{
+       int length;
+       int begin, end;
+       int i;
+
+       if (max_scroll_x <= 0 || max_line_width <= 0)
+               return;
+       length = text_box_x * text_box_x / max_line_width;
+       if (length >= text_box_x)
+               return;
+       begin = current_left * (text_box_x - length) / max_scroll_x;
+       end = begin + length;
+       wmove(text_widget.window, text_box_y + 1, 1);
+       for (i = 0; i < text_box_x; ++i)
+               waddch(text_widget.window, i >= begin && i < end ? ACS_BOARD : ' ');
+}
+
+static void move_x(int delta)
+{
+       int left;
+
+       left = current_left + delta;
+       if (left < 0)
+               left = 0;
+       else if (left > max_scroll_x)
+               left = max_scroll_x;
+       if (left != current_left) {
+               current_left = left;
+               update_text_lines();
+               update_x_scroll_bar();
+       }
+}
+
+static void move_y(int delta)
+{
+       int top;
+
+       top = current_top + delta;
+       if (top < 0)
+               top = 0;
+       else if (top > max_scroll_y)
+               top = max_scroll_y;
+       if (top != current_top) {
+               current_top = top;
+               update_text_lines();
+               update_y_scroll_bar();
+       }
+}
+
+static void on_handle_key(int key)
+{
+       switch (key) {
+       case 10:
+       case 13:
+       case 27:
+       case KEY_CANCEL:
+       case KEY_ENTER:
+       case KEY_CLOSE:
+       case KEY_EXIT:
+               text_widget.close();
+               break;
+       case KEY_DOWN:
+       case KEY_SF:
+       case 'J':
+       case 'j':
+       case 'X':
+       case 'x':
+               move_y(1);
+               break;
+       case KEY_UP:
+       case KEY_SR:
+       case 'K':
+       case 'k':
+       case 'W':
+       case 'w':
+               move_y(-1);
+               break;
+       case KEY_LEFT:
+       case 'H':
+       case 'h':
+       case 'P':
+       case 'p':
+               move_x(-1);
+               break;
+       case KEY_RIGHT:
+       case 'L':
+       case 'l':
+       case 'N':
+       case 'n':
+               move_x(1);
+               break;
+       case KEY_NPAGE:
+       case ' ':
+               move_y(text_box_y);
+               break;
+       case KEY_PPAGE:
+       case KEY_BACKSPACE:
+       case 'B':
+       case 'b':
+               move_y(-text_box_y);
+               break;
+       case KEY_HOME:
+       case KEY_BEG:
+               move_x(-max_scroll_x);
+               break;
+       case KEY_LL:
+       case KEY_END:
+               move_x(max_scroll_x);
+               break;
+       case '\t':
+               move_x(8);
+               break;
+       case KEY_BTAB:
+               move_x(-8);
+               break;
+       }
+}
+
+static bool create(void)
+{
+       int len, width;
+
+       if (screen_lines < 3 || screen_cols < 8) {
+               text_widget.close();
+               beep();
+               return FALSE;
+       }
+
+       width = max_line_width;
+       len = get_mbs_width(title) + 2;
+       if (width < len)
+               width = len;
+
+       text_box_y = text_lines_count;
+       if (text_box_y > screen_lines - 2)
+               text_box_y = screen_lines - 2;
+       max_scroll_y = text_lines_count - text_box_y;
+       text_box_x = width;
+       if (text_box_x > screen_cols - 2)
+               text_box_x = screen_cols - 2;
+       max_scroll_x = max_line_width - text_box_x;
+
+       widget_init(&text_widget, text_box_y + 2, text_box_x + 2,
+                   SCREEN_CENTER, SCREEN_CENTER, widget_attrs, WIDGET_BORDER);
+       mvwprintw(text_widget.window, 0, (text_box_x + 2 - get_mbs_width(title) - 2) / 2, " %s ", title);
+
+       if (current_top > max_scroll_y)
+               current_top = max_scroll_y;
+       if (current_left > max_scroll_x)
+               current_left = max_scroll_x;
+       update_text_lines();
+       update_y_scroll_bar();
+       update_x_scroll_bar();
+       return TRUE;
+}
+
+static void on_window_size_changed(void)
+{
+       create();
+}
+
+static void on_close(void)
+{
+       unsigned int i;
+
+       for (i = 0; i < text_lines_count; ++i)
+               free(text_lines[i]);
+       free(text_lines);
+       widget_free(&text_widget);
+}
+
+static struct widget text_widget = {
+       .handle_key = on_handle_key,
+       .window_size_changed = on_window_size_changed,
+       .close = on_close,
+};
+
+static void create_text_box(const char *const *lines, unsigned int count,
+                           const char *title_, int attrs)
+{
+       unsigned int i;
+
+       text_lines = ccalloc(count, sizeof *text_lines);
+       for (i = 0; i < count; ++i)
+               text_lines[i] = cstrdup(lines[i]);
+       text_lines_count = count;
+       max_line_width = get_max_mbs_width(lines, count);
+       title = cstrdup(title_);
+       widget_attrs = attrs;
+
+       current_top = 0;
+       current_left = 0;
+
+       create();
+}
diff --git a/alsamixer/textbox.h b/alsamixer/textbox.h
new file mode 100644 (file)
index 0000000..7dc290b
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef TEXTBOX_H_INCLUDED
+#define TEXTBOX_H_INCLUDED
+
+void show_error(const char *msg, int err);
+void show_alsa_error(const char *msg, int err);
+void show_text(const char *const *text_lines, unsigned int count,
+              const char *title);
+void show_textfile(const char *file_name);
+
+#endif
diff --git a/alsamixer/utils.c b/alsamixer/utils.c
new file mode 100644 (file)
index 0000000..3602bef
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * utils.c - multibyte-string helpers
+ * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define _XOPEN_SOURCE
+#include "aconfig.h"
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include "utils.h"
+
+/*
+ * mbs_at_width - compute screen position in a string
+ *
+ * For displaying strings on the screen, we have to know how many character
+ * cells are occupied.  This function calculates the position in a multibyte
+ * string that is at a desired position.
+ *
+ * Parameters:
+ * s:     the string
+ * width: on input, the desired number of character cells; on output, the actual
+ *        position, in character cells, of the return value
+ * dir:   -1 or 1; in which direction to round if a multi-column character goes
+ *        over the desired width
+ *
+ * Return value:
+ * Pointer to the place in the string that is as near the desired width as
+ * possible.  If the string is too short, the return value points to the
+ * terminating zero.  If the last character is a multi-column character that
+ * goes over the desired width, the return value may be one character cell
+ * earlier or later than desired, depending on the dir parameter.
+ * In any case, the return value points after any zero-width characters that
+ * follow the last character.
+ */
+const char *mbs_at_width(const char *s, int *width, int dir)
+{
+       size_t len;
+       wchar_t wc;
+       int bytes;
+       int width_so_far, w;
+
+       if (*width <= 0)
+               return s;
+       mbtowc(NULL, NULL, 0); /* reset shift state */
+       len = strlen(s);
+       width_so_far = 0;
+       while (len && (bytes = mbtowc(&wc, s, len)) > 0) {
+               w = wcwidth(wc);
+               if (width_so_far + w > *width && dir < 0)
+                       break;
+               if (w >= 0)
+                       width_so_far += w;
+               s += bytes;
+               len -= bytes;
+               if (width_so_far >= *width) {
+                       while (len && (bytes = mbtowc(&wc, s, len)) > 0) {
+                               w = wcwidth(wc);
+                               if (w != 0)
+                                       break;
+                               s += bytes;
+                               len -= bytes;
+                       }
+                       break;
+               }
+       }
+       *width = width_so_far;
+       return s;
+}
+
+/*
+ * get_mbs_width - compute screen width of a string
+ */
+unsigned int get_mbs_width(const char *s)
+{
+       int width;
+
+       width = INT_MAX;
+       mbs_at_width(s, &width, 1);
+       return width;
+}
+
+/*
+ * get_max_mbs_width - get width of longest string in an array
+ */
+unsigned int get_max_mbs_width(const char *const *s, unsigned int count)
+{
+       unsigned int max_width, i, len;
+
+       max_width = 0;
+       for (i = 0; i < count; ++i) {
+               len = get_mbs_width(s[i]);
+               if (len > max_width)
+                       max_width = len;
+       }
+       return max_width;
+}
diff --git a/alsamixer/utils.h b/alsamixer/utils.h
new file mode 100644 (file)
index 0000000..00a52dd
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef UTILS_H_INCLUDED
+#define UTILS_H_INCLUDED
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof *(a))
+
+unsigned int get_mbs_width(const char *s);
+unsigned int get_max_mbs_width(const char *const *s, unsigned int count);
+const char *mbs_at_width(const char *s, int *width, int dir);
+
+#endif
diff --git a/alsamixer/widget.c b/alsamixer/widget.c
new file mode 100644 (file)
index 0000000..75da4c2
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * widget.c - handles widget objects and the widget stack
+ * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "aconfig.h"
+#include <stdlib.h>
+#include <term.h>
+#include "die.h"
+#include "widget.h"
+
+int screen_lines;
+int screen_cols;
+
+static int cursor_visibility = -1;
+
+static void widget_handle_key(int key)
+{
+}
+
+static void update_cursor_visibility(void)
+{
+       struct widget *active_widget;
+
+       active_widget = get_active_widget();
+       if (active_widget &&
+           active_widget->cursor_visibility != cursor_visibility) {
+               cursor_visibility = active_widget->cursor_visibility;
+               curs_set(cursor_visibility);
+       }
+}
+
+void widget_init(struct widget *widget, int lines_, int cols, int y, int x,
+                chtype bkgd, unsigned int flags)
+{
+       WINDOW *old_window;
+
+       if (y == SCREEN_CENTER)
+               y = (screen_lines - lines_) / 2;
+       if (x == SCREEN_CENTER)
+               x = (screen_cols - cols) / 2;
+
+       old_window = widget->window;
+       widget->window = newwin(lines_, cols, y, x);
+       if (!widget->window)
+               fatal_error("cannot create window");
+       keypad(widget->window, TRUE);
+       nodelay(widget->window, TRUE);
+       leaveok(widget->window, !(flags & WIDGET_CURSOR_VISIBLE));
+       wbkgdset(widget->window, bkgd);
+       werase(widget->window);
+
+       if (flags & WIDGET_BORDER)
+               box(widget->window, 0, 0);
+       if (flags & WIDGET_SUBWINDOW) {
+               if (widget->subwindow)
+                       delwin(widget->subwindow);
+               widget->subwindow = derwin(widget->window,
+                                          lines_ - 2, cols - 2, 1, 1);
+               if (!widget->subwindow)
+                       fatal_error("cannot create subwindow");
+               wbkgdset(widget->subwindow, bkgd);
+       }
+       widget->cursor_visibility = !!(flags & WIDGET_CURSOR_VISIBLE);
+
+       if (widget->panel) {
+               replace_panel(widget->panel, widget->window);
+       } else {
+               widget->panel = new_panel(widget->window);
+               if (!widget->panel)
+                       fatal_error("cannot create panel");
+               set_panel_userptr(widget->panel, widget);
+       }
+
+       if (!widget->handle_key)
+               widget->handle_key = widget_handle_key;
+
+       if (old_window)
+               delwin(old_window);
+
+       update_cursor_visibility();
+}
+
+void widget_free(struct widget *widget)
+{
+       if (widget->panel) {
+               del_panel(widget->panel);
+               widget->panel = NULL;
+       }
+       if (widget->subwindow) {
+               delwin(widget->subwindow);
+               widget->subwindow = NULL;
+       }
+       if (widget->window) {
+               delwin(widget->window);
+               widget->window = NULL;
+       }
+
+       update_cursor_visibility();
+}
+
+struct widget *get_active_widget(void)
+{
+       PANEL *active_panel;
+
+       active_panel = panel_below(NULL);
+       if (active_panel)
+               return panel_userptr(active_panel);
+       else
+               return NULL;
+}
+
+void window_size_changed(void)
+{
+       PANEL *panel, *below;
+       struct widget *widget;
+
+       getmaxyx(stdscr, screen_lines, screen_cols);
+       if (tigetflag("xenl") != 1 && tigetflag("am") != 1)
+               --screen_lines;
+
+       for (panel = panel_below(NULL); panel; panel = below) {
+               below = panel_below(panel);
+               widget = panel_userptr(panel);
+               widget->window_size_changed();
+       }
+}
diff --git a/alsamixer/widget.h b/alsamixer/widget.h
new file mode 100644 (file)
index 0000000..6adb526
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef WIDGET_H_INCLUDED
+#define WIDGET_H_INCLUDED
+
+#include <panel.h>
+
+#define WIDGET_BORDER          0x1
+#define WIDGET_SUBWINDOW       0x2
+#define WIDGET_CURSOR_VISIBLE  0x4
+
+#define SCREEN_CENTER  -1
+
+struct widget {
+       WINDOW *window;
+       WINDOW *subwindow; /* optional: contents without border */
+       PANEL *panel;
+       int cursor_visibility;
+
+       void (*handle_key)(int key);
+       void (*window_size_changed)(void);
+       void (*close)(void);
+};
+
+extern int screen_lines;
+extern int screen_cols;
+
+void widget_init(struct widget *widget,
+                int lines_, int cols, int y, int x,
+                chtype bkgd, unsigned int flags);
+void widget_free(struct widget *widget);
+struct widget *get_active_widget(void);
+void window_size_changed(void);
+
+#endif
index ea7361b..e4ef66e 100644 (file)
@@ -105,6 +105,14 @@ EXEEXT = @EXEEXT@
 GMSGFMT = @GMSGFMT@
 GMSGFMT_015 = @GMSGFMT_015@
 GREP = @GREP@
+HAVE_MIXER_FALSE = @HAVE_MIXER_FALSE@
+HAVE_MIXER_TRUE = @HAVE_MIXER_TRUE@
+HAVE_PCM_FALSE = @HAVE_PCM_FALSE@
+HAVE_PCM_TRUE = @HAVE_PCM_TRUE@
+HAVE_RAWMIDI_FALSE = @HAVE_RAWMIDI_FALSE@
+HAVE_RAWMIDI_TRUE = @HAVE_RAWMIDI_TRUE@
+HAVE_SEQ_FALSE = @HAVE_SEQ_FALSE@
+HAVE_SEQ_TRUE = @HAVE_SEQ_TRUE@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -115,6 +123,7 @@ LDFLAGS = @LDFLAGS@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
 LIBOBJS = @LIBOBJS@
+LIBRT = @LIBRT@
 LIBS = @LIBS@
 LN_S = @LN_S@
 LTLIBICONV = @LTLIBICONV@
index 2e970ae..cedf18c 100644 (file)
@@ -95,122 +95,63 @@ static void *my_malloc(size_t size)
        return p;
 }
 
-static int is_input(snd_ctl_t *ctl, int card, int device, int sub)
-{
-       snd_rawmidi_info_t *info;
-       int err;
-
-       snd_rawmidi_info_alloca(&info);
-       snd_rawmidi_info_set_device(info, device);
-       snd_rawmidi_info_set_subdevice(info, sub);
-       snd_rawmidi_info_set_stream(info, SND_RAWMIDI_STREAM_INPUT);
-       
-       if ((err = snd_ctl_rawmidi_info(ctl, info)) < 0 && err != -ENXIO)
-               return err;
-       else if (err == 0)
-               return 1;
-
-       return 0;
-}
-
-static int is_output(snd_ctl_t *ctl, int card, int device, int sub)
-{
-       snd_rawmidi_info_t *info;
-       int err;
-
-       snd_rawmidi_info_alloca(&info);
-       snd_rawmidi_info_set_device(info, device);
-       snd_rawmidi_info_set_subdevice(info, sub);
-       snd_rawmidi_info_set_stream(info, SND_RAWMIDI_STREAM_OUTPUT);
-       
-       if ((err = snd_ctl_rawmidi_info(ctl, info)) < 0 && err != -ENXIO)
-               return err;
-       else if (err == 0)
-               return 1;
-
-       return 0;
-}
-
 static void list_device(snd_ctl_t *ctl, int card, int device)
 {
        snd_rawmidi_info_t *info;
        const char *name;
        const char *sub_name;
        int subs, subs_in, subs_out;
-       int sub, in, out;
+       int sub;
        int err;
 
        snd_rawmidi_info_alloca(&info);
        snd_rawmidi_info_set_device(info, device);
 
        snd_rawmidi_info_set_stream(info, SND_RAWMIDI_STREAM_INPUT);
-       snd_ctl_rawmidi_info(ctl, info);
-       subs_in = snd_rawmidi_info_get_subdevices_count(info);
+       err = snd_ctl_rawmidi_info(ctl, info);
+       if (err >= 0)
+               subs_in = snd_rawmidi_info_get_subdevices_count(info);
+       else
+               subs_in = 0;
+
        snd_rawmidi_info_set_stream(info, SND_RAWMIDI_STREAM_OUTPUT);
-       snd_ctl_rawmidi_info(ctl, info);
-       subs_out = snd_rawmidi_info_get_subdevices_count(info);
-       subs = subs_in > subs_out ? subs_in : subs_out;
+       err = snd_ctl_rawmidi_info(ctl, info);
+       if (err >= 0)
+               subs_out = snd_rawmidi_info_get_subdevices_count(info);
+       else
+               subs_out = 0;
 
-       sub = 0;
-       in = out = 0;
-       if ((err = is_output(ctl, card, device, sub)) < 0) {
-               error("cannot get rawmidi information %d:%d: %s",
-                     card, device, snd_strerror(err));
+       subs = subs_in > subs_out ? subs_in : subs_out;
+       if (!subs)
                return;
-       } else if (err)
-               out = 1;
 
-       if (err == 0) {
-               if ((err = is_input(ctl, card, device, sub)) < 0) {
-                       error("cannot get rawmidi information %d:%d: %s",
-                             card, device, snd_strerror(err));
+       for (sub = 0; sub < subs; ++sub) {
+               snd_rawmidi_info_set_stream(info, sub < subs_in ?
+                                           SND_RAWMIDI_STREAM_INPUT :
+                                           SND_RAWMIDI_STREAM_OUTPUT);
+               snd_rawmidi_info_set_subdevice(info, sub);
+               err = snd_ctl_rawmidi_info(ctl, info);
+               if (err < 0) {
+                       error("cannot get rawmidi information %d:%d:%d: %s\n",
+                             card, device, sub, snd_strerror(err));
                        return;
                }
-       } else if (err) 
-               in = 1;
-
-       if (err == 0)
-               return;
-
-       name = snd_rawmidi_info_get_name(info);
-       sub_name = snd_rawmidi_info_get_subdevice_name(info);
-       if (sub_name[0] == '\0') {
-               if (subs == 1) {
-                       printf("%c%c  hw:%d,%d    %s\n", 
-                              in ? 'I' : ' ', out ? 'O' : ' ',
+               name = snd_rawmidi_info_get_name(info);
+               sub_name = snd_rawmidi_info_get_subdevice_name(info);
+               if (sub == 0 && sub_name[0] == '\0') {
+                       printf("%c%c  hw:%d,%d    %s",
+                              sub < subs_in ? 'I' : ' ',
+                              sub < subs_out ? 'O' : ' ',
                               card, device, name);
-               } else
-                       printf("%c%c  hw:%d,%d    %s (%d subdevices)\n",
-                              in ? 'I' : ' ', out ? 'O' : ' ',
-                              card, device, name, subs);
-       } else {
-               sub = 0;
-               for (;;) {
+                       if (subs > 1)
+                               printf(" (%d subdevices)", subs);
+                       putchar('\n');
+                       break;
+               } else {
                        printf("%c%c  hw:%d,%d,%d  %s\n",
-                              in ? 'I' : ' ', out ? 'O' : ' ',
+                              sub < subs_in ? 'I' : ' ',
+                              sub < subs_out ? 'O' : ' ',
                               card, device, sub, sub_name);
-                       if (++sub >= subs)
-                               break;
-
-                       in = is_input(ctl, card, device, sub);
-                       out = is_output(ctl, card, device, sub);
-                       snd_rawmidi_info_set_subdevice(info, sub);
-                       if (out) {
-                               snd_rawmidi_info_set_stream(info, SND_RAWMIDI_STREAM_OUTPUT);
-                               if ((err = snd_ctl_rawmidi_info(ctl, info)) < 0) {
-                                       error("cannot get rawmidi information %d:%d:%d: %s",
-                                             card, device, sub, snd_strerror(err));
-                                       break;
-                               } 
-                       } else {
-                               snd_rawmidi_info_set_stream(info, SND_RAWMIDI_STREAM_INPUT);
-                               if ((err = snd_ctl_rawmidi_info(ctl, info)) < 0) {
-                                       error("cannot get rawmidi information %d:%d:%d: %s",
-                                             card, device, sub, snd_strerror(err));
-                                       break;
-                               }
-                       }
-                       sub_name = snd_rawmidi_info_get_subdevice_name(info);
                }
        }
 }
index 7ed5a12..06fda51 100644 (file)
@@ -109,6 +109,14 @@ EXEEXT = @EXEEXT@
 GMSGFMT = @GMSGFMT@
 GMSGFMT_015 = @GMSGFMT_015@
 GREP = @GREP@
+HAVE_MIXER_FALSE = @HAVE_MIXER_FALSE@
+HAVE_MIXER_TRUE = @HAVE_MIXER_TRUE@
+HAVE_PCM_FALSE = @HAVE_PCM_FALSE@
+HAVE_PCM_TRUE = @HAVE_PCM_TRUE@
+HAVE_RAWMIDI_FALSE = @HAVE_RAWMIDI_FALSE@
+HAVE_RAWMIDI_TRUE = @HAVE_RAWMIDI_TRUE@
+HAVE_SEQ_FALSE = @HAVE_SEQ_FALSE@
+HAVE_SEQ_TRUE = @HAVE_SEQ_TRUE@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -119,6 +127,7 @@ LDFLAGS = @LDFLAGS@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
 LIBOBJS = @LIBOBJS@
+LIBRT = @LIBRT@
 LIBS = @LIBS@
 LN_S = @LN_S@
 LTLIBICONV = @LTLIBICONV@
index 9620721..c9ea572 100644 (file)
@@ -534,6 +534,26 @@ static void decode_tlv(unsigned int spaces, unsigned int *tlv, unsigned int tlv_
                }
                break;
 #endif
+#ifdef SND_CTL_TLVT_DB_MINMAX
+       case SND_CTL_TLVT_DB_MINMAX:
+       case SND_CTL_TLVT_DB_MINMAX_MUTE:
+               if (type == SND_CTL_TLVT_DB_MINMAX_MUTE)
+                       printf("dBminmaxmute-");
+               else
+                       printf("dBminmax-");
+               if (size != 2 * sizeof(unsigned int)) {
+                       while (size > 0) {
+                               printf("0x%08x,", tlv[idx++]);
+                               size -= sizeof(unsigned int);
+                       }
+               } else {
+                       printf("min=");
+                       print_dB(tlv[2]);
+                       printf(",max=");
+                       print_dB(tlv[3]);
+               }
+               break;
+#endif
        default:
                printf("unk-%i-", type);
                while (size > 0) {
@@ -602,6 +622,8 @@ static int show_control(const char *space, snd_hctl_elem_t *elem,
                break;
        }
        if (level & LEVEL_BASIC) {
+               if (!snd_ctl_elem_info_is_readable(info))
+                       goto __skip_read;
                if ((err = snd_hctl_elem_read(elem, control)) < 0) {
                        error("Control %s element read error: %s\n", card, snd_strerror(err));
                        return err;
@@ -638,6 +660,7 @@ static int show_control(const char *space, snd_hctl_elem_t *elem,
                        }
                }
                printf("\n");
+             __skip_read:
                if (!snd_ctl_elem_info_is_tlv_readable(info))
                        goto __skip_tlv;
                tlv = malloc(4096);
index 60811de..92323d1 100644 (file)
@@ -1,5 +1,7 @@
+LIBRT = @LIBRT@
+
 INCLUDES = -I$(top_srcdir)/include
-LDADD = $(LIBINTL)
+LDADD = $(LIBINTL) $(LIBRT)
 
 # debug flags
 #LDFLAGS = -static
index 6a35153..bde9feb 100644 (file)
@@ -60,7 +60,7 @@ aplay_SOURCES = aplay.c
 aplay_OBJECTS = aplay.$(OBJEXT)
 aplay_LDADD = $(LDADD)
 am__DEPENDENCIES_1 =
-aplay_DEPENDENCIES = $(am__DEPENDENCIES_1)
+aplay_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
 DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/include
 depcomp = $(SHELL) $(top_srcdir)/depcomp
 am__depfiles_maybe = depfiles
@@ -110,6 +110,14 @@ EXEEXT = @EXEEXT@
 GMSGFMT = @GMSGFMT@
 GMSGFMT_015 = @GMSGFMT_015@
 GREP = @GREP@
+HAVE_MIXER_FALSE = @HAVE_MIXER_FALSE@
+HAVE_MIXER_TRUE = @HAVE_MIXER_TRUE@
+HAVE_PCM_FALSE = @HAVE_PCM_FALSE@
+HAVE_PCM_TRUE = @HAVE_PCM_TRUE@
+HAVE_RAWMIDI_FALSE = @HAVE_RAWMIDI_FALSE@
+HAVE_RAWMIDI_TRUE = @HAVE_RAWMIDI_TRUE@
+HAVE_SEQ_FALSE = @HAVE_SEQ_FALSE@
+HAVE_SEQ_TRUE = @HAVE_SEQ_TRUE@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -120,6 +128,7 @@ LDFLAGS = @LDFLAGS@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
 LIBOBJS = @LIBOBJS@
+LIBRT = @LIBRT@
 LIBS = @LIBS@
 LN_S = @LN_S@
 LTLIBICONV = @LTLIBICONV@
@@ -199,7 +208,7 @@ sysconfdir = @sysconfdir@
 target_alias = @target_alias@
 xmlto = @xmlto@
 INCLUDES = -I$(top_srcdir)/include
-LDADD = $(LIBINTL)
+LDADD = $(LIBINTL) $(LIBRT)
 man_MANS = aplay.1 arecord.1
 noinst_HEADERS = formats.h
 EXTRA_DIST = aplay.1 arecord.1
index 7759347..b6caf0b 100644 (file)
@@ -1,4 +1,4 @@
-.TH APLAY 1 "2 August 2001"
+.TH APLAY 1 "1 January 2010"
 .SH NAME
 arecord, aplay \- command-line sound recorder and player for ALSA 
 soundcard driver
@@ -46,6 +46,7 @@ If this parameter is omitted the WAVE format is used.
 \fI\-c, \-\-channels=#\fP
 The number of channels.
 The default is one channel.
+Valid values are 1 through 32.
 .TP
 \fI\-f \-\-format=FORMAT\fP
 Sample format
@@ -53,19 +54,23 @@ Sample format
 Recognized sample formats are: S8 U8 S16_LE S16_BE U16_LE U16_BE S24_LE
 S24_BE U24_LE U24_BE S32_LE S32_BE U32_LE U32_BE FLOAT_LE FLOAT_BE
 FLOAT64_LE FLOAT64_BE IEC958_SUBFRAME_LE IEC958_SUBFRAME_BE MU_LAW
-A_LAW IMA_ADPCM MPEG GSM
+A_LAW IMA_ADPCM MPEG GSM SPECIAL S24_3LE S24_3BE U24_3LE U24_3BE S20_3LE
+S20_3BE U20_3LE U20_3BE S18_3LE S18_3BE U18_3LE
 .br
 Some of these may not be available on selected hardware
 .br
-There are also two format shortcuts available:
+The available format shortcuts are:
 .nf
-\-f cd (16 bit little endian, 44100, stereo [\-f S16_LE \-c2 \-r44100]
+\-f cd (16 bit little endian, 44100, stereo) [\-f S16_LE \-c2 \-r44100]
+\-f cdr (16 bit big endian, 44100, stereo) [\-f S16_BE \-c2 \-f44100]
 \-f dat (16 bit little endian, 48000, stereo) [\-f S16_LE \-c2 \-r48000]
 .fi
 If no format is given U8 is used.
 .TP
 \fI\-r, \-\-rate=#<Hz>\fP
 Sampling rate in Hertz. The default rate is 8000 Hertz.
+If the value specified is less than 300, it is taken as the rate in kilohertz.
+Valid values are 2000 through 192000 Hertz.
 .TP
 \fI\-d, \-\-duration=#\fP
 Interrupt after # seconds.
@@ -120,10 +125,69 @@ The stereo VU-meter is available only for 2-channel stereo samples
 with interleaved format.
 .TP
 \fI\-I, \-\-separate\-channels\fP 
-One file for each channel
+One file for each channel.  This option disables max\-file\-time
+and use\-strftime, and ignores SIGUSR1.  The stereo VU meter is
+not available with separate channels.
+.TP
+\fI\-P\fP
+Playback.  This is the default if the program is invoked
+by typing aplay.
+.TP
+\fI\-C\fP
+Record.  This is the default if the program is invoked
+by typing arecord.
+.TP
+\fI\-\-disable\-resample\fP
+Disable automatic rate resample.
+.TP
+\fI\-\-disable\-channels\fP
+Disable automatic channel conversions.
+.TP
+\fI\-\-disable\-format\fP
+Disable automatic format conversions.
+.TP
+\fI\-\-disable\-softvol\fP
+Disable software volume control (softvol).
+.TP
+\fI\-\-test\-position\fP
+Test ring buffer position.
+.TP
+\fI\-\-test\-coef=<coef>\fP
+Test coefficient for ring buffer position; default is 8.
+Expression for validation is: coef * (buffer_size / 2).
+Minimum value is 1.
+.TP
+\fI\-\-test\-nowait\fP
+Do not wait for the ring buffer--eats the whole CPU.
+.TP
+\fI\-\-max\-file\-time\fP
+While recording, when the output file has been accumulating
+sound for this long,
+close it and open a new output file.  Default is the maximum
+size supported by the file format: 2 GiB for WAV files.
+This option has no effect if  \-\-separate\-channels is
+specified.
+.TP
+\fI\-\-process\-id\-file <file name>\fP
+aplay writes its process ID here, so other programs can
+send signals to it.
+.TP
+\fI\-\-use\-strftime\fP
+When recording, interpret %-codes in the file name parameter using
+the strftime facility whenever the output file is opened.  The
+important strftime codes are: %Y is the year, %m month, %d day of
+the month, %H hour, %M minute and %S second.  In addition, %v is
+the file number, starting at 1.  When this option is specified,
+intermediate directories for the output file are created automatically.
+This option has no effect if \-\-separate\-channels is specified.
 
-.SS
-Example:
+.SH SIGNALS
+When recording, SIGINT, SIGTERM and SIGABRT will close the output 
+file and exit.  SIGUSR1 will close the output file, open a new one,
+and continue recording.  However, SIGUSR1 does not work with
+\-\-separate\-channels.
+
+.SH EXAMPLES
 
 .TP
 \fBaplay \-c 1 \-t raw \-r 22050 \-f mu_law foobar\fR
@@ -144,6 +208,19 @@ pcm.copy {
 }
 .fi
 
+.TP
+\fBarecord \-t wav \-max-file_time 30 mon.wav\fP
+Record from the default audio source in monaural, 8,000 samples
+per second, 8 bits per sample.  Start a new file every
+30 seconds.  File names are mon-nn.wav, where nn increases
+from 01.  The file after mon-99.wav is mon-100.wav.
+
+.TP
+\fBarecord \-f cd \-t wav \-max-file-time 3600 --use-strftime %Y/%m/%d/listen-%H-%M-%v.wav\fP
+Record in stereo from the default audio source.  Create a new file
+every hour.  The files are placed in directories based on their start dates
+and have names which include their start times and file numbers.
+
 .SH SEE ALSO
 \fB
 alsamixer(1),
index 837e46a..8d084d6 100644 (file)
@@ -45,6 +45,7 @@
 #include <sys/uio.h>
 #include <sys/time.h>
 #include <sys/signal.h>
+#include <sys/stat.h>
 #include <asm/byteorder.h>
 #include "aconfig.h"
 #include "gettext.h"
@@ -101,18 +102,29 @@ static snd_pcm_uframes_t buffer_frames = 0;
 static int avail_min = -1;
 static int start_delay = 0;
 static int stop_delay = 0;
+static int monotonic = 0;
 static int verbose = 0;
 static int vumeter = VUMETER_NONE;
 static int buffer_pos = 0;
 static size_t bits_per_sample, bits_per_frame;
 static size_t chunk_bytes;
 static int test_position = 0;
+static int test_coef = 8;
+static int test_nowait = 0;
 static snd_output_t *log;
+static long long max_file_size = 0;
+static int max_file_time = 0;
+static int use_strftime = 0;
+volatile static int recycle_capture_file = 0;
 
 static int fd = -1;
 static off64_t pbrec_count = LLONG_MAX, fdcount;
 static int vocmajor, vocminor;
 
+static char *pidfile_name = NULL;
+FILE *pidf = NULL;
+static int pidfile_written = 0;
+
 /* needed prototypes */
 
 static void playback(char *filename);
@@ -188,7 +200,14 @@ _("Usage: %s [OPTION]... [FILE]...\n"
 "    --disable-channels  disable automatic channel conversions\n"
 "    --disable-format    disable automatic format conversions\n"
 "    --disable-softvol   disable software volume control (softvol)\n"
-"    --test-position     test ring buffer position\n")
+"    --test-position     test ring buffer position\n"
+"    --test-coef=#      test coeficient for ring buffer position (default 8)\n"
+"                        expression for validation is: coef * (buffer_size / 2)\n"
+"    --test-nowait       do not wait for ring buffer - eats whole CPU\n"
+"    --max-file-time=#   start another output file when the old file has recorded\n"
+"                        for this many seconds\n"
+"    --process-id-file   write the process ID here\n"
+"    --use-strftime      apply the strftime facility to the output file name\n")
                , command);
        printf(_("Recognized sample formats are:"));
        for (k = 0; k < SND_PCM_FORMAT_LAST; ++k) {
@@ -318,6 +337,18 @@ static void version(void)
        printf("%s: version " SND_UTIL_VERSION_STR " by Jaroslav Kysela <perex@perex.cz>\n", command);
 }
 
+/*
+ *     Subroutine to clean up before exit.
+ */
+static void prg_exit(int code) 
+{
+       if (handle)
+               snd_pcm_close(handle);
+       if (pidfile_written)
+               remove (pidfile_name);
+       exit(code);
+}
+
 static void signal_handler(int sig)
 {
        if (verbose==2)
@@ -339,7 +370,14 @@ static void signal_handler(int sig)
                snd_pcm_close(handle);
                handle = NULL;
        }
-       exit(EXIT_FAILURE);
+       prg_exit(EXIT_FAILURE);
+}
+
+/* call on SIGUSR1 signal. */
+static void signal_handler_recycle (int sig)
+{
+       /* flag the capture loop to start a new output file */
+       recycle_capture_file = 1;
 }
 
 enum {
@@ -350,7 +388,12 @@ enum {
        OPT_DISABLE_CHANNELS,
        OPT_DISABLE_FORMAT,
        OPT_DISABLE_SOFTVOL,
-       OPT_TEST_POSITION
+       OPT_TEST_POSITION,
+       OPT_TEST_COEF,
+       OPT_TEST_NOWAIT,
+       OPT_MAX_FILE_TIME,
+       OPT_PROCESS_ID_FILE,
+       OPT_USE_STRFTIME
 };
 
 int main(int argc, char *argv[])
@@ -389,6 +432,11 @@ int main(int argc, char *argv[])
                {"disable-format", 0, 0, OPT_DISABLE_FORMAT},
                {"disable-softvol", 0, 0, OPT_DISABLE_SOFTVOL},
                {"test-position", 0, 0, OPT_TEST_POSITION},
+               {"test-coef", 1, 0, OPT_TEST_COEF},
+               {"test-nowait", 0, 0, OPT_TEST_NOWAIT},
+               {"max-file-time", 1, 0, OPT_MAX_FILE_TIME},
+               {"process-id-file", 1, 0, OPT_PROCESS_ID_FILE},
+               {"use-strftime", 0, 0, OPT_USE_STRFTIME},
                {0, 0, 0, 0}
        };
        char *pcm_name = "default";
@@ -483,7 +531,7 @@ int main(int argc, char *argv[])
                                rhwparams.format = snd_pcm_format_value(optarg);
                                if (rhwparams.format == SND_PCM_FORMAT_UNKNOWN) {
                                        error(_("wrong extended format '%s'"), optarg);
-                                       exit(EXIT_FAILURE);
+                                       prg_exit(EXIT_FAILURE);
                                }
                        }
                        break;
@@ -570,6 +618,23 @@ int main(int argc, char *argv[])
                case OPT_TEST_POSITION:
                        test_position = 1;
                        break;
+               case OPT_TEST_COEF:
+                       test_coef = strtol(optarg, NULL, 0);
+                       if (test_coef < 1)
+                               test_coef = 1;
+                       break;
+               case OPT_TEST_NOWAIT:
+                       test_nowait = 1;
+                       break;
+               case OPT_MAX_FILE_TIME:
+                       max_file_time = strtol(optarg, NULL, 0);
+                       break;
+               case OPT_PROCESS_ID_FILE:
+                       pidfile_name = optarg;
+                       break;
+               case OPT_USE_STRFTIME:
+                       use_strftime = 1;
+                       break;
                default:
                        fprintf(stderr, _("Try `%s --help' for more information.\n"), command);
                        return 1;
@@ -625,10 +690,24 @@ int main(int argc, char *argv[])
                readn_func = snd_pcm_readn;
        }
 
+       if (pidfile_name) {
+               errno = 0;
+               pidf = fopen (pidfile_name, "w");
+               if (pidf) {
+                       (void)fprintf (pidf, "%d\n", getpid());
+                       fclose(pidf);
+                       pidfile_written = 1;
+               } else {
+                       error(_("Cannot create process ID file %s: %s"), 
+                               pidfile_name, strerror (errno));
+                       return 1;
+               }
+       }
 
        signal(SIGINT, signal_handler);
        signal(SIGTERM, signal_handler);
        signal(SIGABRT, signal_handler);
+       signal(SIGUSR1, signal_handler_recycle);
        if (interleaved) {
                if (optind > argc - 1) {
                        if (stream == SND_PCM_STREAM_PLAYBACK)
@@ -652,10 +731,13 @@ int main(int argc, char *argv[])
        if (verbose==2)
                putchar('\n');
        snd_pcm_close(handle);
+       handle = NULL;
        free(audiobuf);
       __end:
        snd_output_close(log);
        snd_config_update_free_global();
+       prg_exit(EXIT_SUCCESS);
+       /* avoid warning */
        return EXIT_SUCCESS;
 }
 
@@ -707,7 +789,7 @@ static size_t test_wavefile_read(int fd, u_char *buffer, size_t *size, size_t re
                return *size;
        if ((size_t)safe_read(fd, buffer + *size, reqsize - *size) != reqsize - *size) {
                error(_("read error (called from line %i)"), line);
-               exit(EXIT_FAILURE);
+               prg_exit(EXIT_FAILURE);
        }
        return *size = reqsize;
 }
@@ -717,7 +799,7 @@ static size_t test_wavefile_read(int fd, u_char *buffer, size_t *size, size_t re
                blimit = len; \
                if ((buffer = realloc(buffer, blimit)) == NULL) { \
                        error(_("not enough memory"));            \
-                       exit(EXIT_FAILURE); \
+                       prg_exit(EXIT_FAILURE);  \
                } \
        }
 
@@ -766,7 +848,7 @@ static ssize_t test_wavefile(int fd, u_char *_buffer, size_t size)
        if (len < sizeof(WaveFmtBody)) {
                error(_("unknown length of 'fmt ' chunk (read %u, should be %u at least)"),
                      len, (u_int)sizeof(WaveFmtBody));
-               exit(EXIT_FAILURE);
+               prg_exit(EXIT_FAILURE);
        }
        check_wavefile_space(buffer, len, blimit);
        test_wavefile_read(fd, buffer, &size, len, __LINE__);
@@ -776,22 +858,22 @@ static ssize_t test_wavefile(int fd, u_char *_buffer, size_t size)
                if (len < sizeof(WaveFmtExtensibleBody)) {
                        error(_("unknown length of extensible 'fmt ' chunk (read %u, should be %u at least)"),
                                        len, (u_int)sizeof(WaveFmtExtensibleBody));
-                       exit(EXIT_FAILURE);
+                       prg_exit(EXIT_FAILURE);
                }
                if (memcmp(fe->guid_tag, WAV_GUID_TAG, 14) != 0) {
                        error(_("wrong format tag in extensible 'fmt ' chunk"));
-                       exit(EXIT_FAILURE);
+                       prg_exit(EXIT_FAILURE);
                }
                f->format = fe->guid_format;
        }
         if (LE_SHORT(f->format) != WAV_FMT_PCM &&
             LE_SHORT(f->format) != WAV_FMT_IEEE_FLOAT) {
                 error(_("can't play WAVE-file format 0x%04x which is not PCM or FLOAT encoded"), LE_SHORT(f->format));
-               exit(EXIT_FAILURE);
+               prg_exit(EXIT_FAILURE);
        }
        if (LE_SHORT(f->channels) < 1) {
                error(_("can't play WAVE-files with %d tracks"), LE_SHORT(f->channels));
-               exit(EXIT_FAILURE);
+               prg_exit(EXIT_FAILURE);
        }
        hwparams.channels = LE_SHORT(f->channels);
        switch (LE_SHORT(f->bit_p_spl)) {
@@ -824,7 +906,7 @@ static ssize_t test_wavefile(int fd, u_char *_buffer, size_t size)
                default:
                        error(_(" can't play WAVE-files with sample %d bits in %d bytes wide (%d channels)"),
                              LE_SHORT(f->bit_p_spl), LE_SHORT(f->byte_p_spl), hwparams.channels);
-                       exit(EXIT_FAILURE);
+                       prg_exit(EXIT_FAILURE);
                }
                break;
        case 32:
@@ -836,7 +918,7 @@ static ssize_t test_wavefile(int fd, u_char *_buffer, size_t size)
        default:
                error(_(" can't play WAVE-files with sample %d bits wide"),
                      LE_SHORT(f->bit_p_spl));
-               exit(EXIT_FAILURE);
+               prg_exit(EXIT_FAILURE);
        }
        hwparams.rate = LE_INT(f->sample_fq);
        
@@ -918,11 +1000,22 @@ static int test_au(int fd, void *buffer)
                return -1;
        if ((size_t)safe_read(fd, buffer + sizeof(AuHeader), BE_INT(ap->hdr_size) - sizeof(AuHeader)) != BE_INT(ap->hdr_size) - sizeof(AuHeader)) {
                error(_("read error"));
-               exit(EXIT_FAILURE);
+               prg_exit(EXIT_FAILURE);
        }
        return 0;
 }
 
+static void show_available_sample_formats(snd_pcm_hw_params_t* params)
+{
+       snd_pcm_format_t format;
+
+       fprintf(stderr, "Available formats:\n");
+       for (format = 0; format < SND_PCM_FORMAT_LAST; format++) {
+               if (snd_pcm_hw_params_test_format(handle, params, format) == 0)
+                       fprintf(stderr, "- %s\n", snd_pcm_format_name(format));
+       }
+}
+
 static void set_params(void)
 {
        snd_pcm_hw_params_t *params;
@@ -937,7 +1030,7 @@ static void set_params(void)
        err = snd_pcm_hw_params_any(handle, params);
        if (err < 0) {
                error(_("Broken configuration for this PCM: no configurations available"));
-               exit(EXIT_FAILURE);
+               prg_exit(EXIT_FAILURE);
        }
        if (mmap_flag) {
                snd_pcm_access_mask_t *mask = alloca(snd_pcm_access_mask_sizeof());
@@ -954,17 +1047,18 @@ static void set_params(void)
                                                   SND_PCM_ACCESS_RW_NONINTERLEAVED);
        if (err < 0) {
                error(_("Access type not available"));
-               exit(EXIT_FAILURE);
+               prg_exit(EXIT_FAILURE);
        }
        err = snd_pcm_hw_params_set_format(handle, params, hwparams.format);
        if (err < 0) {
                error(_("Sample format non available"));
-               exit(EXIT_FAILURE);
+               show_available_sample_formats(params);
+               prg_exit(EXIT_FAILURE);
        }
        err = snd_pcm_hw_params_set_channels(handle, params, hwparams.channels);
        if (err < 0) {
                error(_("Channels count non available"));
-               exit(EXIT_FAILURE);
+               prg_exit(EXIT_FAILURE);
        }
 
 #if 0
@@ -1017,18 +1111,19 @@ static void set_params(void)
                                                             &buffer_frames);
        }
        assert(err >= 0);
+       monotonic = snd_pcm_hw_params_is_monotonic(params);
        err = snd_pcm_hw_params(handle, params);
        if (err < 0) {
                error(_("Unable to install hw params:"));
                snd_pcm_hw_params_dump(params, log);
-               exit(EXIT_FAILURE);
+               prg_exit(EXIT_FAILURE);
        }
        snd_pcm_hw_params_get_period_size(params, &chunk_size, 0);
        snd_pcm_hw_params_get_buffer_size(params, &buffer_size);
        if (chunk_size == buffer_size) {
                error(_("Can't use period equal to buffer size (%lu == %lu)"),
                      chunk_size, buffer_size);
-               exit(EXIT_FAILURE);
+               prg_exit(EXIT_FAILURE);
        }
        snd_pcm_sw_params_current(handle, swparams);
        if (avail_min < 0)
@@ -1059,7 +1154,7 @@ static void set_params(void)
        if (snd_pcm_sw_params(handle, swparams) < 0) {
                error(_("unable to install sw params:"));
                snd_pcm_sw_params_dump(swparams, log);
-               exit(EXIT_FAILURE);
+               prg_exit(EXIT_FAILURE);
        }
 
        if (verbose)
@@ -1071,7 +1166,7 @@ static void set_params(void)
        audiobuf = realloc(audiobuf, chunk_bytes);
        if (audiobuf == NULL) {
                error(_("not enough memory"));
-               exit(EXIT_FAILURE);
+               prg_exit(EXIT_FAILURE);
        }
        // fprintf(stderr, "real chunk_size = %i, frags = %i, total = %i\n", chunk_size, setup.buf.block.frags, setup.buf.block.frags * chunk_size);
 
@@ -1084,12 +1179,12 @@ static void set_params(void)
        /* show mmap buffer arragment */
        if (mmap_flag && verbose) {
                const snd_pcm_channel_area_t *areas;
-               snd_pcm_uframes_t offset;
+               snd_pcm_uframes_t offset, size = chunk_size;
                int i;
-               err = snd_pcm_mmap_begin(handle, &areas, &offset, &chunk_size);
+               err = snd_pcm_mmap_begin(handle, &areas, &offset, &size);
                if (err < 0) {
                        error("snd_pcm_mmap_begin problem: %s", snd_strerror(err));
-                       exit(EXIT_FAILURE);
+                       prg_exit(EXIT_FAILURE);
                }
                for (i = 0; i < hwparams.channels; i++)
                        fprintf(stderr, "mmap_area[%i] = %p,%u,%u (%u)\n", i, areas[i].addr, areas[i].first, areas[i].step, snd_pcm_format_physical_width(hwparams.format));
@@ -1112,6 +1207,18 @@ do { \
 } while (0)
 #endif
 
+#ifndef timermsub
+#define        timermsub(a, b, result) \
+do { \
+       (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
+       (result)->tv_nsec = (a)->tv_nsec - (b)->tv_nsec; \
+       if ((result)->tv_nsec < 0) { \
+               --(result)->tv_sec; \
+               (result)->tv_nsec += 1000000000L; \
+       } \
+} while (0)
+#endif
+
 /* I/O error handler */
 static void xrun(void)
 {
@@ -1121,23 +1228,37 @@ static void xrun(void)
        snd_pcm_status_alloca(&status);
        if ((res = snd_pcm_status(handle, status))<0) {
                error(_("status error: %s"), snd_strerror(res));
-               exit(EXIT_FAILURE);
+               prg_exit(EXIT_FAILURE);
        }
        if (snd_pcm_status_get_state(status) == SND_PCM_STATE_XRUN) {
-               struct timeval now, diff, tstamp;
-               gettimeofday(&now, 0);
-               snd_pcm_status_get_trigger_tstamp(status, &tstamp);
-               timersub(&now, &tstamp, &diff);
-               fprintf(stderr, _("%s!!! (at least %.3f ms long)\n"),
-                       stream == SND_PCM_STREAM_PLAYBACK ? _("underrun") : _("overrun"),
-                       diff.tv_sec * 1000 + diff.tv_usec / 1000.0);
+               if (monotonic) {
+#ifdef HAVE_CLOCK_GETTIME
+                       struct timespec now, diff, tstamp;
+                       clock_gettime(CLOCK_MONOTONIC, &now);
+                       snd_pcm_status_get_trigger_htstamp(status, &tstamp);
+                       timermsub(&now, &tstamp, &diff);
+                       fprintf(stderr, _("%s!!! (at least %.3f ms long)\n"),
+                               stream == SND_PCM_STREAM_PLAYBACK ? _("underrun") : _("overrun"),
+                               diff.tv_sec * 1000 + diff.tv_nsec / 10000000.0);
+#else
+                       fprintf(stderr, "%s !!!\n", _("underrun"));
+#endif
+               } else {
+                       struct timeval now, diff, tstamp;
+                       gettimeofday(&now, 0);
+                       snd_pcm_status_get_trigger_tstamp(status, &tstamp);
+                       timersub(&now, &tstamp, &diff);
+                       fprintf(stderr, _("%s!!! (at least %.3f ms long)\n"),
+                               stream == SND_PCM_STREAM_PLAYBACK ? _("underrun") : _("overrun"),
+                               diff.tv_sec * 1000 + diff.tv_usec / 1000.0);
+               }
                if (verbose) {
                        fprintf(stderr, _("Status:\n"));
                        snd_pcm_status_dump(status, log);
                }
                if ((res = snd_pcm_prepare(handle))<0) {
                        error(_("xrun: prepare error: %s"), snd_strerror(res));
-                       exit(EXIT_FAILURE);
+                       prg_exit(EXIT_FAILURE);
                }
                return;         /* ok, data should be accepted again */
        } if (snd_pcm_status_get_state(status) == SND_PCM_STATE_DRAINING) {
@@ -1149,7 +1270,7 @@ static void xrun(void)
                        fprintf(stderr, _("capture stream format change? attempting recover...\n"));
                        if ((res = snd_pcm_prepare(handle))<0) {
                                error(_("xrun(DRAINING): prepare error: %s"), snd_strerror(res));
-                               exit(EXIT_FAILURE);
+                               prg_exit(EXIT_FAILURE);
                        }
                        return;
                }
@@ -1159,7 +1280,7 @@ static void xrun(void)
                snd_pcm_status_dump(status, log);
        }
        error(_("read/write error, state = %s"), snd_pcm_state_name(snd_pcm_status_get_state(status)));
-       exit(EXIT_FAILURE);
+       prg_exit(EXIT_FAILURE);
 }
 
 /* I/O suspend handler */
@@ -1176,7 +1297,7 @@ static void suspend(void)
                        fprintf(stderr, _("Failed. Restarting stream. ")); fflush(stderr);
                if ((res = snd_pcm_prepare(handle)) < 0) {
                        error(_("suspend: prepare error: %s"), snd_strerror(res));
-                       exit(EXIT_FAILURE);
+                       prg_exit(EXIT_FAILURE);
                }
        }
        if (!quiet_mode)
@@ -1396,20 +1517,60 @@ static void compute_max_peak(u_char *data, size_t count)
 
 static void do_test_position(void)
 {
-       static int counter = 0;
+       static long counter = 0;
+       static time_t tmr = -1;
+       time_t now;
+       static float availsum, delaysum, samples;
+       static snd_pcm_sframes_t maxavail, maxdelay;
+       static snd_pcm_sframes_t minavail, mindelay;
+       static snd_pcm_sframes_t badavail = 0, baddelay = 0;
+       snd_pcm_sframes_t outofrange;
        snd_pcm_sframes_t avail, delay;
        int err;
 
        err = snd_pcm_avail_delay(handle, &avail, &delay);
        if (err < 0)
                return;
-       if (avail > 4 * (snd_pcm_sframes_t)buffer_frames ||
-           avail < -4 * (snd_pcm_sframes_t)buffer_frames ||
-           delay > 4 * (snd_pcm_sframes_t)buffer_frames ||
-           delay < -4 * (snd_pcm_sframes_t)buffer_frames) {
-         fprintf(stderr, "Suspicious buffer position (%i total): avail = %li, delay = %li, buffer = %li\n", ++counter, (long)avail, (long)delay, (long)buffer_frames);
+       outofrange = (test_coef * (snd_pcm_sframes_t)buffer_frames) / 2;
+       if (avail > outofrange || avail < -outofrange ||
+           delay > outofrange || delay < -outofrange) {
+         badavail = avail; baddelay = delay;
+         availsum = delaysum = samples = 0;
+         maxavail = maxdelay = 0;
+         minavail = mindelay = buffer_frames * 16;
+         fprintf(stderr, _("Suspicious buffer position (%li total): "
+               "avail = %li, delay = %li, buffer = %li\n"),
+               ++counter, (long)avail, (long)delay, (long)buffer_frames);
        } else if (verbose) {
-         fprintf(stderr, "Buffer position: %li/%li (%li)\n", (long)avail, (long)delay, (long)buffer_frames);
+               time(&now);
+               if (tmr == (time_t) -1) {
+                       tmr = now;
+                       availsum = delaysum = samples = 0;
+                       maxavail = maxdelay = 0;
+                       minavail = mindelay = buffer_frames * 16;
+               }
+               if (avail > maxavail)
+                       maxavail = avail;
+               if (delay > maxdelay)
+                       maxdelay = delay;
+               if (avail < minavail)
+                       minavail = avail;
+               if (delay < mindelay)
+                       mindelay = delay;
+               availsum += avail;
+               delaysum += delay;
+               samples++;
+               if (avail != 0 && now != tmr) {
+                       fprintf(stderr, "BUFPOS: avg%li/%li "
+                               "min%li/%li max%li/%li (%li) (%li:%li/%li)\n",
+                               (long)(availsum / samples),
+                               (long)(delaysum / samples),
+                               (long)minavail, (long)mindelay,
+                               (long)maxavail, (long)maxdelay,
+                               (long)buffer_frames,
+                               counter, badavail, baddelay);
+                       tmr = now;
+               }
        }
 }
 
@@ -1433,14 +1594,15 @@ static ssize_t pcm_write(u_char *data, size_t count)
                if (test_position)
                        do_test_position();
                if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) {
-                       snd_pcm_wait(handle, 1000);
+                       if (!test_nowait)
+                               snd_pcm_wait(handle, 1000);
                } else if (r == -EPIPE) {
                        xrun();
                } else if (r == -ESTRPIPE) {
                        suspend();
                } else if (r < 0) {
                        error(_("write error: %s"), snd_strerror(r));
-                       exit(EXIT_FAILURE);
+                       prg_exit(EXIT_FAILURE);
                }
                if (r > 0) {
                        if (vumeter)
@@ -1478,14 +1640,15 @@ static ssize_t pcm_writev(u_char **data, unsigned int channels, size_t count)
                if (test_position)
                        do_test_position();
                if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) {
-                       snd_pcm_wait(handle, 1000);
+                       if (!test_nowait)
+                               snd_pcm_wait(handle, 1000);
                } else if (r == -EPIPE) {
                        xrun();
                } else if (r == -ESTRPIPE) {
                        suspend();
                } else if (r < 0) {
                        error(_("writev error: %s"), snd_strerror(r));
-                       exit(EXIT_FAILURE);
+                       prg_exit(EXIT_FAILURE);
                }
                if (r > 0) {
                        if (vumeter) {
@@ -1520,14 +1683,15 @@ static ssize_t pcm_read(u_char *data, size_t rcount)
                if (test_position)
                        do_test_position();
                if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) {
-                       snd_pcm_wait(handle, 1000);
+                       if (!test_nowait)
+                               snd_pcm_wait(handle, 1000);
                } else if (r == -EPIPE) {
                        xrun();
                } else if (r == -ESTRPIPE) {
                        suspend();
                } else if (r < 0) {
                        error(_("read error: %s"), snd_strerror(r));
-                       exit(EXIT_FAILURE);
+                       prg_exit(EXIT_FAILURE);
                }
                if (r > 0) {
                        if (vumeter)
@@ -1562,14 +1726,15 @@ static ssize_t pcm_readv(u_char **data, unsigned int channels, size_t rcount)
                if (test_position)
                        do_test_position();
                if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) {
-                       snd_pcm_wait(handle, 1000);
+                       if (!test_nowait)
+                               snd_pcm_wait(handle, 1000);
                } else if (r == -EPIPE) {
                        xrun();
                } else if (r == -ESTRPIPE) {
                        suspend();
                } else if (r < 0) {
                        error(_("readv error: %s"), snd_strerror(r));
-                       exit(EXIT_FAILURE);
+                       prg_exit(EXIT_FAILURE);
                }
                if (r > 0) {
                        if (vumeter) {
@@ -1626,7 +1791,7 @@ static void voc_write_silence(unsigned x)
                        l = chunk_size;
                if (voc_pcm_write(buf, l) != (ssize_t)l) {
                        error(_("write error"));
-                       exit(EXIT_FAILURE);
+                       prg_exit(EXIT_FAILURE);
                }
                x -= l;
        }
@@ -1668,7 +1833,7 @@ static void voc_play(int fd, int ofs, char *name)
        buffer_pos = 0;
        if (data == NULL) {
                error(_("malloc error"));
-               exit(EXIT_FAILURE);
+               prg_exit(EXIT_FAILURE);
        }
        if (!quiet_mode) {
                fprintf(stderr, _("Playing Creative Labs Channel file '%s'...\n"), name);
@@ -1677,14 +1842,14 @@ static void voc_play(int fd, int ofs, char *name)
        while (ofs > (ssize_t)chunk_bytes) {
                if ((size_t)safe_read(fd, buf, chunk_bytes) != chunk_bytes) {
                        error(_("read error"));
-                       exit(EXIT_FAILURE);
+                       prg_exit(EXIT_FAILURE);
                }
                ofs -= chunk_bytes;
        }
        if (ofs) {
                if (safe_read(fd, buf, ofs) != ofs) {
                        error(_("read error"));
-                       exit(EXIT_FAILURE);
+                       prg_exit(EXIT_FAILURE);
                }
        }
        hwparams.format = DEFAULT_FORMAT;
@@ -1708,7 +1873,7 @@ static void voc_play(int fd, int ofs, char *name)
                                nextblock = buf[0] = 0;
                                if (l == -1) {
                                        perror(name);
-                                       exit(EXIT_FAILURE);
+                                       prg_exit(EXIT_FAILURE);
                                }
                        }
                }
@@ -1852,12 +2017,12 @@ static void voc_play(int fd, int ofs, char *name)
                        if (output && !quiet_mode) {
                                if (write(2, data, l) != l) {   /* to stderr */
                                        error(_("write error"));
-                                       exit(EXIT_FAILURE);
+                                       prg_exit(EXIT_FAILURE);
                                }
                        } else {
                                if (voc_pcm_write(data, l) != l) {
                                        error(_("write error"));
-                                       exit(EXIT_FAILURE);
+                                       prg_exit(EXIT_FAILURE);
                                }
                        }
                        COUNT(l);
@@ -1904,7 +2069,7 @@ static void begin_voc(int fd, size_t cnt)
 
        if (write(fd, &vh, sizeof(VocHeader)) != sizeof(VocHeader)) {
                error(_("write error"));
-               exit(EXIT_FAILURE);
+               prg_exit(EXIT_FAILURE);
        }
        if (hwparams.channels > 1) {
                /* write an extended block */
@@ -1913,14 +2078,14 @@ static void begin_voc(int fd, size_t cnt)
                bt.datalen_m = bt.datalen_h = 0;
                if (write(fd, &bt, sizeof(VocBlockType)) != sizeof(VocBlockType)) {
                        error(_("write error"));
-                       exit(EXIT_FAILURE);
+                       prg_exit(EXIT_FAILURE);
                }
                eb.tc = LE_SHORT(65536 - 256000000L / (hwparams.rate << 1));
                eb.pack = 0;
                eb.mode = 1;
                if (write(fd, &eb, sizeof(VocExtBlock)) != sizeof(VocExtBlock)) {
                        error(_("write error"));
-                       exit(EXIT_FAILURE);
+                       prg_exit(EXIT_FAILURE);
                }
        }
        bt.type = 1;
@@ -1930,13 +2095,13 @@ static void begin_voc(int fd, size_t cnt)
        bt.datalen_h = (u_char) ((cnt & 0xFF0000) >> 16);
        if (write(fd, &bt, sizeof(VocBlockType)) != sizeof(VocBlockType)) {
                error(_("write error"));
-               exit(EXIT_FAILURE);
+               prg_exit(EXIT_FAILURE);
        }
        vd.tc = (u_char) (256 - (1000000 / hwparams.rate));
        vd.pack = 0;
        if (write(fd, &vd, sizeof(VocVoiceData)) != sizeof(VocVoiceData)) {
                error(_("write error"));
-               exit(EXIT_FAILURE);
+               prg_exit(EXIT_FAILURE);
        }
 }
 
@@ -1972,7 +2137,7 @@ static void begin_wave(int fd, size_t cnt)
                break;
        default:
                error(_("Wave doesn't support %s format..."), snd_pcm_format_name(hwparams.format));
-               exit(EXIT_FAILURE);
+               prg_exit(EXIT_FAILURE);
        }
        h.magic = WAV_RIFF;
        tmp = cnt + sizeof(WaveHeader) + sizeof(WaveChunkHeader) + sizeof(WaveFmtBody) + sizeof(WaveChunkHeader) - 8;
@@ -2008,7 +2173,7 @@ static void begin_wave(int fd, size_t cnt)
            write(fd, &f, sizeof(WaveFmtBody)) != sizeof(WaveFmtBody) ||
            write(fd, &cd, sizeof(WaveChunkHeader)) != sizeof(WaveChunkHeader)) {
                error(_("write error"));
-               exit(EXIT_FAILURE);
+               prg_exit(EXIT_FAILURE);
        }
 }
 
@@ -2032,13 +2197,13 @@ static void begin_au(int fd, size_t cnt)
                break;
        default:
                error(_("Sparc Audio doesn't support %s format..."), snd_pcm_format_name(hwparams.format));
-               exit(EXIT_FAILURE);
+               prg_exit(EXIT_FAILURE);
        }
        ah.sample_rate = BE_INT(hwparams.rate);
        ah.channels = BE_INT(hwparams.channels);
        if (write(fd, &ah, sizeof(AuHeader)) != sizeof(AuHeader)) {
                error(_("write error"));
-               exit(EXIT_FAILURE);
+               prg_exit(EXIT_FAILURE);
        }
 }
 
@@ -2052,7 +2217,7 @@ static void end_voc(int fd)
 
        if (write(fd, &dummy, 1) != 1) {
                error(_("write error"));
-               exit(EXIT_FAILURE);
+               prg_exit(EXIT_FAILURE);
        }
        length_seek = sizeof(VocHeader);
        if (hwparams.channels > 1)
@@ -2160,7 +2325,7 @@ static void playback_go(int fd, size_t loaded, off64_t count, int rtype, char *n
                        r = safe_read(fd, audiobuf + l, c);
                        if (r < 0) {
                                perror(name);
-                               exit(EXIT_FAILURE);
+                               prg_exit(EXIT_FAILURE);
                        }
                        fdcount += r;
                        if (r == 0)
@@ -2199,14 +2364,14 @@ static void playback(char *name)
        } else {
                if ((fd = open64(name, O_RDONLY, 0)) == -1) {
                        perror(name);
-                       exit(EXIT_FAILURE);
+                       prg_exit(EXIT_FAILURE);
                }
        }
        /* read the file header */
        dta = sizeof(AuHeader);
        if ((size_t)safe_read(fd, audiobuf, dta) != dta) {
                error(_("read error"));
-               exit(EXIT_FAILURE);
+               prg_exit(EXIT_FAILURE);
        }
        if (test_au(fd, audiobuf) >= 0) {
                rhwparams.format = hwparams.format;
@@ -2218,7 +2383,7 @@ static void playback(char *name)
        if ((size_t)safe_read(fd, audiobuf + sizeof(AuHeader),
                 dta - sizeof(AuHeader)) != dta - sizeof(AuHeader)) {
                error(_("read error"));
-               exit(EXIT_FAILURE);
+               prg_exit(EXIT_FAILURE);;
        }
        if ((ofs = test_vocfile(audiobuf)) >= 0) {
                pbrec_count = calc_count();
@@ -2240,13 +2405,98 @@ static void playback(char *name)
                close(fd);
 }
 
+/**
+ * mystrftime
+ *
+ *   Variant of strftime(3) that supports additional format
+ *   specifiers in the format string.
+ *
+ * Parameters:
+ *
+ *   s   - destination string
+ *   max       - max number of bytes to write
+ *   userformat - format string
+ *   tm         - time information
+ *   filenumber - the number of the file, starting at 1
+ *
+ * Returns: number of bytes written to the string s
+ */
+size_t mystrftime(char *s, size_t max, const char *userformat,
+                 const struct tm *tm, const int filenumber)
+{
+       char formatstring[PATH_MAX] = "";
+       char tempstring[PATH_MAX] = "";
+       char *format, *tempstr;
+       const char *pos_userformat;
+
+       format = formatstring;
+
+       /* if mystrftime is called with userformat = NULL we return a zero length string */
+       if (userformat == NULL) {
+               *s = '\0';
+               return 0;
+       }
+
+       for (pos_userformat = userformat; *pos_userformat; ++pos_userformat) {
+               if (*pos_userformat == '%') {
+                       tempstr = tempstring;
+                       tempstr[0] = '\0';
+                       switch (*++pos_userformat) {
+
+                               case '\0': // end of string
+                                       --pos_userformat;
+                                       break;
+
+                               case 'v': // file number 
+                                       sprintf(tempstr, "%02d", filenumber);
+                                       break;
+
+                               default: // All other codes will be handled by strftime
+                                       *format++ = '%';
+                                       *format++ = *pos_userformat;
+                                       continue;
+                       }
+
+                       /* If a format specifier was found and used, copy the result. */
+                       if (tempstr[0]) {
+                               while ((*format = *tempstr++) != '\0')
+                                       ++format;
+                               continue;
+                       }
+               }
+
+               /* For any other character than % we simply copy the character */
+               *format++ = *pos_userformat;
+       }
+
+       *format = '\0';
+       format = formatstring;
+       return strftime(s, max, format, tm);
+}
+
 static int new_capture_file(char *name, char *namebuf, size_t namelen,
                            int filecount)
 {
-       /* get a copy of the original filename */
        char *s;
        char buf[PATH_MAX+1];
+       time_t t;
+       struct tm *tmp;
+
+       if (use_strftime) {
+               t = time(NULL);
+               tmp = localtime(&t);
+               if (tmp == NULL) {
+                       perror("localtime");
+                       prg_exit(EXIT_FAILURE);
+               }
+               if (mystrftime(namebuf, namelen, name, tmp, filecount+1) == 0) {
+                       fprintf(stderr, "mystrftime returned 0");
+                       prg_exit(EXIT_FAILURE);
+               }
+               return filecount;
+       }
 
+       /* get a copy of the original filename */
        strncpy(buf, name, sizeof(buf));
 
        /* separate extension from filename */
@@ -2278,6 +2528,58 @@ static int new_capture_file(char *name, char *namebuf, size_t namelen,
        return filecount;
 }
 
+/**
+ * create_path
+ *
+ *   This function creates a file path, like mkdir -p. 
+ *
+ * Parameters:
+ *
+ *   path - the path to create
+ *
+ * Returns: 0 on success, -1 on failure
+ * On failure, a message has been printed to stderr.
+ */
+int create_path(const char *path)
+{
+       char *start;
+       mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
+
+       if (path[0] == '/')
+               start = strchr(path + 1, '/');
+       else
+               start = strchr(path, '/');
+
+       while (start) {
+               char *buffer = strdup(path);
+               buffer[start-path] = 0x00;
+
+               if (mkdir(buffer, mode) == -1 && errno != EEXIST) {
+                       fprintf(stderr, "Problem creating directory %s", buffer);
+                       perror(" ");
+                       free(buffer);
+                       return -1;
+               }
+               free(buffer);
+               start = strchr(start + 1, '/');
+       }
+       return 0;
+}
+
+static int safe_open(const char *name)
+{
+       int fd;
+
+       fd = open64(name, O_WRONLY | O_CREAT, 0644);
+       if (fd == -1) {
+               if (errno != ENOENT || !use_strftime)
+                       return -1;
+               if (create_path(name) == 0)
+                       fd = open64(name, O_WRONLY | O_CREAT, 0644);
+       }
+       return fd;
+}
+
 static void capture(char *orig_name)
 {
        int tostdout=0;         /* boolean which describes output stream */
@@ -2290,6 +2592,10 @@ static void capture(char *orig_name)
        count = calc_count();
        if (count == 0)
                count = LLONG_MAX;
+       /* compute the number of bytes per file */
+       max_file_size = max_file_time *
+               snd_pcm_format_size(hwparams.format,
+                                   hwparams.rate * hwparams.channels);
        /* WAVE-file should be even (I'm not sure), but wasting one byte
           isn't a problem (this can only be in 8 bit mono) */
        if (count < LLONG_MAX)
@@ -2316,7 +2622,7 @@ static void capture(char *orig_name)
                /* open a file to write */
                if(!tostdout) {
                        /* upon the second file we start the numbering scheme */
-                       if (filecount) {
+                       if (filecount || use_strftime) {
                                filecount = new_capture_file(orig_name, namebuf,
                                                             sizeof(namebuf),
                                                             filecount);
@@ -2325,9 +2631,10 @@ static void capture(char *orig_name)
                        
                        /* open a new file */
                        remove(name);
-                       if ((fd = open64(name, O_WRONLY | O_CREAT, 0644)) == -1) {
+                       fd = safe_open(name);
+                       if (fd < 0) {
                                perror(name);
-                               exit(EXIT_FAILURE);
+                               prg_exit(EXIT_FAILURE);
                        }
                        filecount++;
                }
@@ -2335,6 +2642,8 @@ static void capture(char *orig_name)
                rest = count;
                if (rest > fmt_rec_table[file_type].max_filesize)
                        rest = fmt_rec_table[file_type].max_filesize;
+               if (max_file_size && (rest > max_file_size)) 
+                       rest = max_file_size;
 
                /* setup sample header */
                if (fmt_rec_table[file_type].start)
@@ -2342,7 +2651,7 @@ static void capture(char *orig_name)
 
                /* capture */
                fdcount = 0;
-               while (rest > 0) {
+               while (rest > 0 && recycle_capture_file == 0) {
                        size_t c = (rest <= (off64_t)chunk_bytes) ?
                                (size_t)rest : chunk_bytes;
                        size_t f = c * 8 / bits_per_frame;
@@ -2350,13 +2659,19 @@ static void capture(char *orig_name)
                                break;
                        if (write(fd, audiobuf, c) != c) {
                                perror(name);
-                               exit(EXIT_FAILURE);
+                               prg_exit(EXIT_FAILURE);
                        }
                        count -= c;
                        rest -= c;
                        fdcount += c;
                }
 
+               /* re-enable SIGUSR1 signal */
+               if (recycle_capture_file) {
+                       recycle_capture_file = 0;
+                       signal(SIGUSR1, signal_handler_recycle);
+               }
+
                /* finish sample container */
                if (fmt_rec_table[file_type].end && !tostdout) {
                        fmt_rec_table[file_type].end(fd);
@@ -2397,12 +2712,12 @@ static void playbackv_go(int* fds, unsigned int channels, size_t loaded, off64_t
                        r = safe_read(fds[0], bufs[0], expected);
                        if (r < 0) {
                                perror(names[channel]);
-                               exit(EXIT_FAILURE);
+                               prg_exit(EXIT_FAILURE);
                        }
                        for (channel = 1; channel < channels; ++channel) {
                                if (safe_read(fds[channel], bufs[channel], r) != r) {
                                        perror(names[channel]);
-                                       exit(EXIT_FAILURE);
+                                       prg_exit(EXIT_FAILURE);
                                }
                        }
                        if (r == 0)
@@ -2449,7 +2764,7 @@ static void capturev_go(int* fds, unsigned int channels, off64_t count, int rtyp
                for (channel = 0; channel < channels; ++channel) {
                        if ((size_t)write(fds[channel], bufs[channel], rv) != rv) {
                                perror(names[channel]);
-                               exit(EXIT_FAILURE);
+                               prg_exit(EXIT_FAILURE);
                        }
                }
                r = r * bits_per_frame / 8;
@@ -2482,7 +2797,7 @@ static void playbackv(char **names, unsigned int count)
                alloced = 1;
        } else if (count != channels) {
                error(_("You need to specify %d files"), channels);
-               exit(EXIT_FAILURE);
+               prg_exit(EXIT_FAILURE);
        }
 
        for (channel = 0; channel < channels; ++channel) {
@@ -2508,7 +2823,7 @@ static void playbackv(char **names, unsigned int count)
        if (alloced)
                free(names);
        if (ret)
-               exit(ret);
+               prg_exit(ret);
 }
 
 static void capturev(char **names, unsigned int count)
@@ -2535,7 +2850,7 @@ static void capturev(char **names, unsigned int count)
                alloced = 1;
        } else if (count != channels) {
                error(_("You need to specify %d files"), channels);
-               exit(EXIT_FAILURE);
+               prg_exit(EXIT_FAILURE);
        }
 
        for (channel = 0; channel < channels; ++channel) {
@@ -2561,5 +2876,5 @@ static void capturev(char **names, unsigned int count)
        if (alloced)
                free(names);
        if (ret)
-               exit(ret);
+               prg_exit(ret);
 }
index 7759347..b6caf0b 100644 (file)
@@ -1,4 +1,4 @@
-.TH APLAY 1 "2 August 2001"
+.TH APLAY 1 "1 January 2010"
 .SH NAME
 arecord, aplay \- command-line sound recorder and player for ALSA 
 soundcard driver
@@ -46,6 +46,7 @@ If this parameter is omitted the WAVE format is used.
 \fI\-c, \-\-channels=#\fP
 The number of channels.
 The default is one channel.
+Valid values are 1 through 32.
 .TP
 \fI\-f \-\-format=FORMAT\fP
 Sample format
@@ -53,19 +54,23 @@ Sample format
 Recognized sample formats are: S8 U8 S16_LE S16_BE U16_LE U16_BE S24_LE
 S24_BE U24_LE U24_BE S32_LE S32_BE U32_LE U32_BE FLOAT_LE FLOAT_BE
 FLOAT64_LE FLOAT64_BE IEC958_SUBFRAME_LE IEC958_SUBFRAME_BE MU_LAW
-A_LAW IMA_ADPCM MPEG GSM
+A_LAW IMA_ADPCM MPEG GSM SPECIAL S24_3LE S24_3BE U24_3LE U24_3BE S20_3LE
+S20_3BE U20_3LE U20_3BE S18_3LE S18_3BE U18_3LE
 .br
 Some of these may not be available on selected hardware
 .br
-There are also two format shortcuts available:
+The available format shortcuts are:
 .nf
-\-f cd (16 bit little endian, 44100, stereo [\-f S16_LE \-c2 \-r44100]
+\-f cd (16 bit little endian, 44100, stereo) [\-f S16_LE \-c2 \-r44100]
+\-f cdr (16 bit big endian, 44100, stereo) [\-f S16_BE \-c2 \-f44100]
 \-f dat (16 bit little endian, 48000, stereo) [\-f S16_LE \-c2 \-r48000]
 .fi
 If no format is given U8 is used.
 .TP
 \fI\-r, \-\-rate=#<Hz>\fP
 Sampling rate in Hertz. The default rate is 8000 Hertz.
+If the value specified is less than 300, it is taken as the rate in kilohertz.
+Valid values are 2000 through 192000 Hertz.
 .TP
 \fI\-d, \-\-duration=#\fP
 Interrupt after # seconds.
@@ -120,10 +125,69 @@ The stereo VU-meter is available only for 2-channel stereo samples
 with interleaved format.
 .TP
 \fI\-I, \-\-separate\-channels\fP 
-One file for each channel
+One file for each channel.  This option disables max\-file\-time
+and use\-strftime, and ignores SIGUSR1.  The stereo VU meter is
+not available with separate channels.
+.TP
+\fI\-P\fP
+Playback.  This is the default if the program is invoked
+by typing aplay.
+.TP
+\fI\-C\fP
+Record.  This is the default if the program is invoked
+by typing arecord.
+.TP
+\fI\-\-disable\-resample\fP
+Disable automatic rate resample.
+.TP
+\fI\-\-disable\-channels\fP
+Disable automatic channel conversions.
+.TP
+\fI\-\-disable\-format\fP
+Disable automatic format conversions.
+.TP
+\fI\-\-disable\-softvol\fP
+Disable software volume control (softvol).
+.TP
+\fI\-\-test\-position\fP
+Test ring buffer position.
+.TP
+\fI\-\-test\-coef=<coef>\fP
+Test coefficient for ring buffer position; default is 8.
+Expression for validation is: coef * (buffer_size / 2).
+Minimum value is 1.
+.TP
+\fI\-\-test\-nowait\fP
+Do not wait for the ring buffer--eats the whole CPU.
+.TP
+\fI\-\-max\-file\-time\fP
+While recording, when the output file has been accumulating
+sound for this long,
+close it and open a new output file.  Default is the maximum
+size supported by the file format: 2 GiB for WAV files.
+This option has no effect if  \-\-separate\-channels is
+specified.
+.TP
+\fI\-\-process\-id\-file <file name>\fP
+aplay writes its process ID here, so other programs can
+send signals to it.
+.TP
+\fI\-\-use\-strftime\fP
+When recording, interpret %-codes in the file name parameter using
+the strftime facility whenever the output file is opened.  The
+important strftime codes are: %Y is the year, %m month, %d day of
+the month, %H hour, %M minute and %S second.  In addition, %v is
+the file number, starting at 1.  When this option is specified,
+intermediate directories for the output file are created automatically.
+This option has no effect if \-\-separate\-channels is specified.
 
-.SS
-Example:
+.SH SIGNALS
+When recording, SIGINT, SIGTERM and SIGABRT will close the output 
+file and exit.  SIGUSR1 will close the output file, open a new one,
+and continue recording.  However, SIGUSR1 does not work with
+\-\-separate\-channels.
+
+.SH EXAMPLES
 
 .TP
 \fBaplay \-c 1 \-t raw \-r 22050 \-f mu_law foobar\fR
@@ -144,6 +208,19 @@ pcm.copy {
 }
 .fi
 
+.TP
+\fBarecord \-t wav \-max-file_time 30 mon.wav\fP
+Record from the default audio source in monaural, 8,000 samples
+per second, 8 bits per sample.  Start a new file every
+30 seconds.  File names are mon-nn.wav, where nn increases
+from 01.  The file after mon-99.wav is mon-100.wav.
+
+.TP
+\fBarecord \-f cd \-t wav \-max-file-time 3600 --use-strftime %Y/%m/%d/listen-%H-%M-%v.wav\fP
+Record in stereo from the default audio source.  Create a new file
+every hour.  The files are placed in directories based on their start dates
+and have names which include their start times and file numbers.
+
 .SH SEE ALSO
 \fB
 alsamixer(1),
index 10b429c..fc77bca 100755 (executable)
--- a/configure
+++ b/configure
@@ -561,8 +561,44 @@ PACKAGE_VERSION=
 PACKAGE_STRING=
 PACKAGE_BUGREPORT=
 
-ac_unique_file="alsamixer/alsamixer.c"
+ac_unique_file="aplay/aplay.c"
 ac_default_prefix=/usr
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# if HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
 ac_subst_vars='SHELL
 PATH_SEPARATOR
 PACKAGE_NAME
@@ -663,6 +699,14 @@ POSUB
 LN_S
 ALSA_CFLAGS
 ALSA_LIBS
+HAVE_PCM_TRUE
+HAVE_PCM_FALSE
+HAVE_MIXER_TRUE
+HAVE_MIXER_FALSE
+HAVE_RAWMIDI_TRUE
+HAVE_RAWMIDI_FALSE
+HAVE_SEQ_TRUE
+HAVE_SEQ_FALSE
 ALSAMIXER_TRUE
 ALSAMIXER_FALSE
 ALSACONF_TRUE
@@ -683,6 +727,7 @@ SND_UTIL_VERSION
 SND_UTIL_MAJOR
 SND_UTIL_MINOR
 SND_UTIL_SUBMINOR
+LIBRT
 LIBOBJS
 LTLIBOBJS'
 ac_subst_files=''
@@ -1291,6 +1336,7 @@ Optional Packages:
   --without-libintl-prefix     don't search for libintl in includedir and libdir
   --with-alsa-prefix=PFX  Prefix where Alsa library is installed(optional)
   --with-alsa-inc-prefix=PFX  Prefix where include libraries are (optional)
+  --with-librt            Use librt for monotonic clock (default = yes)
   --with-curses libname   Specify the curses library to use (default=auto)
   --with-testsound=file        give the path of test sound file for alsaconf
 
@@ -2043,7 +2089,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE=alsa-utils
- VERSION=1.0.19
+ VERSION=1.0.23
 
 
 cat >>confdefs.h <<_ACEOF
 
 
 
-CURSESINC=""
-CURSESLIB=""
-CURSES_CFLAGS=""
-# Check whether --enable-alsamixer was given.
-if test "${enable_alsamixer+set}" = set; then
-  enableval=$enable_alsamixer; case "${enableval}" in
-       yes) alsamixer=true ;;
-       no)  alsamixer=false ;;
-       *) { { echo "$as_me:$LINENO: error: bad value ${enableval} for --enable-alsamixer" >&5
-echo "$as_me: error: bad value ${enableval} for --enable-alsamixer" >&2;}
-   { (exit 1); exit 1; }; } ;;
-     esac
-else
-  alsamixer=true
-fi
-
-
-
-if test x$alsamixer = xtrue; then
-  ALSAMIXER_TRUE=
-  ALSAMIXER_FALSE='#'
-else
-  ALSAMIXER_TRUE='#'
-  ALSAMIXER_FALSE=
-fi
-
 
-# Check whether --enable-alsaconf was given.
-if test "${enable_alsaconf+set}" = set; then
-  enableval=$enable_alsaconf; case "${enableval}" in
-       yes) alsaconf=true ;;
-       no)  alsaconf=false ;;
-       *) { { echo "$as_me:$LINENO: error: bad value ${enableval} for --enable-alsaconf" >&5
-echo "$as_me: error: bad value ${enableval} for --enable-alsaconf" >&2;}
-   { (exit 1); exit 1; }; } ;;
-     esac
+for ac_header in alsa/pcm.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  alsaconf=true
-fi
-
-
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <alsa/asoundlib.h>
 
-if test x$alsaconf = xtrue; then
-  ALSACONF_TRUE=
-  ALSACONF_FALSE='#'
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_Header=yes"
 else
-  ALSACONF_TRUE='#'
-  ALSACONF_FALSE=
-fi
-
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
 
-xmlto=""
-if test x"$alsaconf" = xtrue; then
-   # Check whether --enable-xmlto was given.
-if test "${enable_xmlto+set}" = set; then
-  enableval=$enable_xmlto; xmlto="$enableval"
-else
-  xmlto="yes"
+       eval "$as_ac_Header=no"
 fi
 
-   if test "$xmlto" = "yes"; then
-      # Extract the first word of "xmlto", so it can be a program name with args.
-set dummy xmlto; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_xmlto+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$xmlto"; then
-  ac_cv_prog_xmlto="$xmlto" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
-    ac_cv_prog_xmlto="yes"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-IFS=$as_save_IFS
-
-fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
-xmlto=$ac_cv_prog_xmlto
-if test -n "$xmlto"; then
-  { echo "$as_me:$LINENO: result: $xmlto" >&5
-echo "${ECHO_T}$xmlto" >&6; }
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+ have_pcm="yes"
 else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
-   fi
+  have_pcm="no"
 fi
 
-
-if test x"$xmlto" = xyes; then
-  USE_XMLTO_TRUE=
-  USE_XMLTO_FALSE='#'
-else
-  USE_XMLTO_TRUE='#'
-  USE_XMLTO_FALSE=
-fi
+done
 
 
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
-echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; }
-# On Suns, sometimes $CPP names a directory.
-if test -n "$CPP" && test -d "$CPP"; then
-  CPP=
-fi
-if test -z "$CPP"; then
-  if test "${ac_cv_prog_CPP+set}" = set; then
+for ac_header in alsa/mixer.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-      # Double quotes because CPP needs to be expanded
-    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
-    do
-      ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
-  # Use a header file that comes with gcc, so configuring glibc
-  # with a fresh cross-compiler works.
-  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
-  # <limits.h> exists even on freestanding compilers.
-  # On the NeXT, cc -E runs the code through the compiler's parser,
-  # not just through cpp. "Syntax error" is here to catch this case.
   cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-                    Syntax error
+#include <alsa/asoundlib.h>
+
+#include <$ac_header>
 _ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
 case "(($ac_try" in
   *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
   *) ac_try_echo=$ac_try;;
 esac
 eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  (eval "$ac_compile") 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null; then
-  if test -s conftest.err; then
-    ac_cpp_err=$ac_c_preproc_warn_flag
-    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
-  else
-    ac_cpp_err=
-  fi
-else
-  ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
-  :
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_Header=yes"
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-  # Broken: fails on valid input.
-continue
+       eval "$as_ac_Header=no"
 fi
 
-rm -f conftest.err conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+ have_mixer="yes"
+else
+  have_mixer="no"
+fi
 
-  # OK, works on sane cases.  Now check whether nonexistent headers
-  # can be detected and how.
+done
+
+
+for ac_header in alsa/rawmidi.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
   cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-#include <ac_nonexistent.h>
+#include <alsa/asoundlib.h>
+
+#include <$ac_header>
 _ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
 case "(($ac_try" in
   *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
   *) ac_try_echo=$ac_try;;
 esac
 eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  (eval "$ac_compile") 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null; then
-  if test -s conftest.err; then
-    ac_cpp_err=$ac_c_preproc_warn_flag
-    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
-  else
-    ac_cpp_err=
-  fi
-else
-  ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
-  # Broken: success on invalid input.
-continue
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_Header=yes"
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-  # Passes both tests.
-ac_preproc_ok=:
-break
+       eval "$as_ac_Header=no"
 fi
 
-rm -f conftest.err conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+ have_rawmidi="yes"
+else
+  have_rawmidi="no"
+fi
 
 done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then
-  break
-fi
 
-    done
-    ac_cv_prog_CPP=$CPP
 
-fi
-  CPP=$ac_cv_prog_CPP
-else
-  ac_cv_prog_CPP=$CPP
-fi
-{ echo "$as_me:$LINENO: result: $CPP" >&5
-echo "${ECHO_T}$CPP" >&6; }
-ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
+for ac_header in alsa/seq.h
 do
-  # Use a header file that comes with gcc, so configuring glibc
-  # with a fresh cross-compiler works.
-  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
-  # <limits.h> exists even on freestanding compilers.
-  # On the NeXT, cc -E runs the code through the compiler's parser,
-  # not just through cpp. "Syntax error" is here to catch this case.
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
   cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-                    Syntax error
+#include <alsa/asoundlib.h>
+
+#include <$ac_header>
 _ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
 case "(($ac_try" in
   *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
   *) ac_try_echo=$ac_try;;
 esac
 eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  (eval "$ac_compile") 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null; then
-  if test -s conftest.err; then
-    ac_cpp_err=$ac_c_preproc_warn_flag
-    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
-  else
-    ac_cpp_err=
-  fi
-else
-  ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
-  :
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-  # Broken: fails on valid input.
-continue
-fi
-
-rm -f conftest.err conftest.$ac_ext
-
-  # OK, works on sane cases.  Now check whether nonexistent headers
-  # can be detected and how.
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <ac_nonexistent.h>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
   *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
   *) ac_try_echo=$ac_try;;
 esac
 eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  (eval "$ac_try") 2>&5
   ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null; then
-  if test -s conftest.err; then
-    ac_cpp_err=$ac_c_preproc_warn_flag
-    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
-  else
-    ac_cpp_err=
-  fi
-else
-  ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
-  # Broken: success on invalid input.
-continue
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_Header=yes"
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-  # Passes both tests.
-ac_preproc_ok=:
-break
+       eval "$as_ac_Header=no"
 fi
 
-rm -f conftest.err conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then
-  :
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+ have_seq="yes"
 else
-  { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details." >&5
-echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }
+  have_seq="no"
 fi
 
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
+done
 
 
-{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5
-echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; }
-if test "${ac_cv_path_GREP+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  # Extract the first word of "grep ggrep" to use in msg output
-if test -z "$GREP"; then
-set dummy grep ggrep; ac_prog_name=$2
-if test "${ac_cv_path_GREP+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_path_GREP_found=false
-# Loop through the user's path and test for each of PROGNAME-LIST
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_prog in grep ggrep; do
-  for ac_exec_ext in '' $ac_executable_extensions; do
-    ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
-    { test -f "$ac_path_GREP" && $as_executable_p "$ac_path_GREP"; } || continue
-    # Check for GNU ac_path_GREP and select it if it is found.
-  # Check for GNU $ac_path_GREP
-case `"$ac_path_GREP" --version 2>&1` in
-*GNU*)
-  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
-*)
-  ac_count=0
-  echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
-  while :
-  do
-    cat "conftest.in" "conftest.in" >"conftest.tmp"
-    mv "conftest.tmp" "conftest.in"
-    cp "conftest.in" "conftest.nl"
-    echo 'GREP' >> "conftest.nl"
-    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
-    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
-    ac_count=`expr $ac_count + 1`
-    if test $ac_count -gt ${ac_path_GREP_max-0}; then
-      # Best one so far, save it but keep looking for a better one
-      ac_cv_path_GREP="$ac_path_GREP"
-      ac_path_GREP_max=$ac_count
-    fi
-    # 10*(2^10) chars as input seems more than enough
-    test $ac_count -gt 10 && break
-  done
-  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
 
 
-    $ac_path_GREP_found && break 3
-  done
-done
+if test "$have_pcm" = "yes"; then
+  HAVE_PCM_TRUE=
+  HAVE_PCM_FALSE='#'
+else
+  HAVE_PCM_TRUE='#'
+  HAVE_PCM_FALSE=
+fi
 
-done
-IFS=$as_save_IFS
 
 
+if test "$have_mixer" = "yes"; then
+  HAVE_MIXER_TRUE=
+  HAVE_MIXER_FALSE='#'
+else
+  HAVE_MIXER_TRUE='#'
+  HAVE_MIXER_FALSE=
 fi
 
-GREP="$ac_cv_path_GREP"
-if test -z "$GREP"; then
-  { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
-echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
-   { (exit 1); exit 1; }; }
-fi
 
+
+if test "$have_rawmidi" = "yes"; then
+  HAVE_RAWMIDI_TRUE=
+  HAVE_RAWMIDI_FALSE='#'
 else
-  ac_cv_path_GREP=$GREP
+  HAVE_RAWMIDI_TRUE='#'
+  HAVE_RAWMIDI_FALSE=
 fi
 
 
+
+if test "$have_seq" = "yes"; then
+  HAVE_SEQ_TRUE=
+  HAVE_SEQ_FALSE='#'
+else
+  HAVE_SEQ_TRUE='#'
+  HAVE_SEQ_FALSE=
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5
-echo "${ECHO_T}$ac_cv_path_GREP" >&6; }
- GREP="$ac_cv_path_GREP"
 
 
-{ echo "$as_me:$LINENO: checking for egrep" >&5
-echo $ECHO_N "checking for egrep... $ECHO_C" >&6; }
-if test "${ac_cv_path_EGREP+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
+LIBRT=""
+{ echo "$as_me:$LINENO: checking for librt" >&5
+echo $ECHO_N "checking for librt... $ECHO_C" >&6; }
+
+# Check whether --with-librt was given.
+if test "${with_librt+set}" = set; then
+  withval=$with_librt;  have_librt="$withval"
 else
-  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
-   then ac_cv_path_EGREP="$GREP -E"
-   else
-     # Extract the first word of "egrep" to use in msg output
-if test -z "$EGREP"; then
-set dummy egrep; ac_prog_name=$2
-if test "${ac_cv_path_EGREP+set}" = set; then
+   have_librt="yes"
+fi
+
+if test "$have_librt" = "yes"; then
+  { echo "$as_me:$LINENO: checking for clock_gettime in -lrt" >&5
+echo $ECHO_N "checking for clock_gettime in -lrt... $ECHO_C" >&6; }
+if test "${ac_cv_lib_rt_clock_gettime+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  ac_path_EGREP_found=false
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lrt  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char clock_gettime ();
+int
+main ()
+{
+return clock_gettime ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_rt_clock_gettime=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_rt_clock_gettime=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_rt_clock_gettime" >&5
+echo "${ECHO_T}$ac_cv_lib_rt_clock_gettime" >&6; }
+if test $ac_cv_lib_rt_clock_gettime = yes; then
+  HAVE_LIBRT="yes"
+fi
+
+  if test "$HAVE_LIBRT" = "yes" ; then
+    LIBRT="-lrt"
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_LIBRT 1
+_ACEOF
+
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_CLOCK_GETTIME 1
+_ACEOF
+
+  fi
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+CURSESINC=""
+CURSESLIB=""
+CURSES_CFLAGS=""
+alsamixer=
+if test "$have_mixer" = "yes"; then
+# Check whether --enable-alsamixer was given.
+if test "${enable_alsamixer+set}" = set; then
+  enableval=$enable_alsamixer; case "${enableval}" in
+       yes) alsamixer=true ;;
+       no)  alsamixer=false ;;
+       *) { { echo "$as_me:$LINENO: error: bad value ${enableval} for --enable-alsamixer" >&5
+echo "$as_me: error: bad value ${enableval} for --enable-alsamixer" >&2;}
+   { (exit 1); exit 1; }; } ;;
+     esac
+else
+  alsamixer=true
+fi
+
+fi
+
+
+if test x$alsamixer = xtrue; then
+  ALSAMIXER_TRUE=
+  ALSAMIXER_FALSE='#'
+else
+  ALSAMIXER_TRUE='#'
+  ALSAMIXER_FALSE=
+fi
+
+
+# Check whether --enable-alsaconf was given.
+if test "${enable_alsaconf+set}" = set; then
+  enableval=$enable_alsaconf; case "${enableval}" in
+       yes) alsaconf=true ;;
+       no)  alsaconf=false ;;
+       *) { { echo "$as_me:$LINENO: error: bad value ${enableval} for --enable-alsaconf" >&5
+echo "$as_me: error: bad value ${enableval} for --enable-alsaconf" >&2;}
+   { (exit 1); exit 1; }; } ;;
+     esac
+else
+  alsaconf=true
+fi
+
+
+
+if test x$alsaconf = xtrue; then
+  ALSACONF_TRUE=
+  ALSACONF_FALSE='#'
+else
+  ALSACONF_TRUE='#'
+  ALSACONF_FALSE=
+fi
+
+
+xmlto=""
+if test x"$alsaconf" = xtrue; then
+   # Check whether --enable-xmlto was given.
+if test "${enable_xmlto+set}" = set; then
+  enableval=$enable_xmlto; xmlto="$enableval"
+else
+  xmlto="yes"
+fi
+
+   if test "$xmlto" = "yes"; then
+      # Extract the first word of "xmlto", so it can be a program name with args.
+set dummy xmlto; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_xmlto+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$xmlto"; then
+  ac_cv_prog_xmlto="$xmlto" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_xmlto="yes"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+xmlto=$ac_cv_prog_xmlto
+if test -n "$xmlto"; then
+  { echo "$as_me:$LINENO: result: $xmlto" >&5
+echo "${ECHO_T}$xmlto" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+   fi
+fi
+
+
+if test x"$xmlto" = xyes; then
+  USE_XMLTO_TRUE=
+  USE_XMLTO_FALSE='#'
+else
+  USE_XMLTO_TRUE='#'
+  USE_XMLTO_FALSE=
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if test "${ac_cv_prog_CPP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+{ echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  :
+else
+  { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5
+echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; }
+if test "${ac_cv_path_GREP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # Extract the first word of "grep ggrep" to use in msg output
+if test -z "$GREP"; then
+set dummy grep ggrep; ac_prog_name=$2
+if test "${ac_cv_path_GREP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_path_GREP_found=false
+# Loop through the user's path and test for each of PROGNAME-LIST
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in grep ggrep; do
+  for ac_exec_ext in '' $ac_executable_extensions; do
+    ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+    { test -f "$ac_path_GREP" && $as_executable_p "$ac_path_GREP"; } || continue
+    # Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    ac_count=`expr $ac_count + 1`
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+    $ac_path_GREP_found && break 3
+  done
+done
+
+done
+IFS=$as_save_IFS
+
+
+fi
+
+GREP="$ac_cv_path_GREP"
+if test -z "$GREP"; then
+  { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5
+echo "${ECHO_T}$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6; }
+if test "${ac_cv_path_EGREP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     # Extract the first word of "egrep" to use in msg output
+if test -z "$EGREP"; then
+set dummy egrep; ac_prog_name=$2
+if test "${ac_cv_path_EGREP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_path_EGREP_found=false
 # Loop through the user's path and test for each of PROGNAME-LIST
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in egrep; do
+  for ac_exec_ext in '' $ac_executable_extensions; do
+    ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+    { test -f "$ac_path_EGREP" && $as_executable_p "$ac_path_EGREP"; } || continue
+    # Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+  ac_count=0
+  echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    echo 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    ac_count=`expr $ac_count + 1`
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+    $ac_path_EGREP_found && break 3
+  done
+done
+
+done
+IFS=$as_save_IFS
+
+
+fi
+
+EGREP="$ac_cv_path_EGREP"
+if test -z "$EGREP"; then
+  { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+
+   fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5
+echo "${ECHO_T}$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; }
+if test "${ac_cv_header_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_header_stdc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_header_stdc=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then
+  :
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+                  (('a' <= (c) && (c) <= 'i') \
+                    || ('j' <= (c) && (c) <= 'r') \
+                    || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+       || toupper (i) != TOUPPER (i))
+      return 2;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+if test x$alsamixer = xtrue; then
+
+# Check whether --with-curses was given.
+if test "${with_curses+set}" = set; then
+  withval=$with_curses; curseslib="$withval"
+else
+  curseslib="auto"
+fi
+
+  CURSESLIBDIR=""
+  NCURSESLIBSUFFIX=""
+  CURSES_NLS="no"
+  if test "$curseslib" = "ncursesw" -o \( "$curseslib" = "auto" -a "$USE_NLS" = "yes" \); then
+    # Extract the first word of "ncursesw5-config", so it can be a program name with args.
+set dummy ncursesw5-config; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ncursesw5_config+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ncursesw5_config"; then
+  ac_cv_prog_ncursesw5_config="$ncursesw5_config" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ncursesw5_config="yes"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ncursesw5_config=$ac_cv_prog_ncursesw5_config
+if test -n "$ncursesw5_config"; then
+  { echo "$as_me:$LINENO: result: $ncursesw5_config" >&5
+echo "${ECHO_T}$ncursesw5_config" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+    if test "$ncursesw5_config" = "yes"; then
+      CURSESINC="<ncurses.h>"
+      CURSESLIB=`ncursesw5-config --libs`
+      CURSESLIBDIR=`ncursesw5-config --libdir`
+      CURSES_CFLAGS=`ncursesw5-config --cflags`
+      curseslib="ncursesw"
+    else
+      { echo "$as_me:$LINENO: checking for initscr in -lncursesw" >&5
+echo $ECHO_N "checking for initscr in -lncursesw... $ECHO_C" >&6; }
+if test "${ac_cv_lib_ncursesw_initscr+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lncursesw  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char initscr ();
+int
+main ()
+{
+return initscr ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_ncursesw_initscr=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_ncursesw_initscr=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_ncursesw_initscr" >&5
+echo "${ECHO_T}$ac_cv_lib_ncursesw_initscr" >&6; }
+if test $ac_cv_lib_ncursesw_initscr = yes; then
+   CURSESINC='<ncurses.h>'; CURSESLIB='-lncursesw'; curseslib="ncursesw"
+fi
+
+    fi
+    if test -n "$CURSESINC"; then
+      NCURSESLIBSUFFIX="w"
+      CURSES_NLS="yes"
+    fi
+  fi
+  if test "$curseslib" = "ncurses" -o "$curseslib" = "auto"; then
+    # Extract the first word of "ncurses5-config", so it can be a program name with args.
+set dummy ncurses5-config; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ncurses5_config+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ncurses5_config"; then
+  ac_cv_prog_ncurses5_config="$ncurses5_config" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
-  for ac_prog in egrep; do
   for ac_exec_ext in '' $ac_executable_extensions; do
-    ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
-    { test -f "$ac_path_EGREP" && $as_executable_p "$ac_path_EGREP"; } || continue
-    # Check for GNU ac_path_EGREP and select it if it is found.
-  # Check for GNU $ac_path_EGREP
-case `"$ac_path_EGREP" --version 2>&1` in
-*GNU*)
-  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
-*)
-  ac_count=0
-  echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
-  while :
-  do
-    cat "conftest.in" "conftest.in" >"conftest.tmp"
-    mv "conftest.tmp" "conftest.in"
-    cp "conftest.in" "conftest.nl"
-    echo 'EGREP' >> "conftest.nl"
-    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
-    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
-    ac_count=`expr $ac_count + 1`
-    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
-      # Best one so far, save it but keep looking for a better one
-      ac_cv_path_EGREP="$ac_path_EGREP"
-      ac_path_EGREP_max=$ac_count
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ncurses5_config="yes"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ncurses5_config=$ac_cv_prog_ncurses5_config
+if test -n "$ncurses5_config"; then
+  { echo "$as_me:$LINENO: result: $ncurses5_config" >&5
+echo "${ECHO_T}$ncurses5_config" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+    if test "$ncurses5_config" = "yes"; then
+      CURSESINC="<ncurses.h>"
+      CURSESLIB=`ncurses5-config --libs`
+      CURSESLIBDIR=`ncurses5-config --libdir`
+      CURSES_CFLAGS=`ncurses5-config --cflags`
+      curseslib="ncurses"
+    else
+      { echo "$as_me:$LINENO: checking for initscr in -lncurses" >&5
+echo $ECHO_N "checking for initscr in -lncurses... $ECHO_C" >&6; }
+if test "${ac_cv_lib_ncurses_initscr+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lncurses  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char initscr ();
+int
+main ()
+{
+return initscr ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_ncurses_initscr=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_ncurses_initscr=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_ncurses_initscr" >&5
+echo "${ECHO_T}$ac_cv_lib_ncurses_initscr" >&6; }
+if test $ac_cv_lib_ncurses_initscr = yes; then
+   CURSESINC='<ncurses.h>'; CURSESLIB='-lncurses'; curseslib="ncurses"
+fi
+
     fi
-    # 10*(2^10) chars as input seems more than enough
-    test $ac_count -gt 10 && break
-  done
-  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+  fi
+  if test "$curseslib" = "curses" -o "$curseslib" = "auto"; then
+    { echo "$as_me:$LINENO: checking for initscr in -lcurses" >&5
+echo $ECHO_N "checking for initscr in -lcurses... $ECHO_C" >&6; }
+if test "${ac_cv_lib_curses_initscr+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcurses  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char initscr ();
+int
+main ()
+{
+return initscr ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
 esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_curses_initscr=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
 
-
-    $ac_path_EGREP_found && break 3
-  done
-done
-
-done
-IFS=$as_save_IFS
-
-
+       ac_cv_lib_curses_initscr=no
 fi
 
-EGREP="$ac_cv_path_EGREP"
-if test -z "$EGREP"; then
-  { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
-echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
-   { (exit 1); exit 1; }; }
+rm -f core conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
 fi
-
-else
-  ac_cv_path_EGREP=$EGREP
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_curses_initscr" >&5
+echo "${ECHO_T}$ac_cv_lib_curses_initscr" >&6; }
+if test $ac_cv_lib_curses_initscr = yes; then
+   CURSESINC='<curses.h>'; CURSESLIB='-lcurses'; curseslib="curses"
 fi
 
+  fi
+  if test -z "$CURSESINC"; then
+     { { echo "$as_me:$LINENO: error: this packages requires a curses library" >&5
+echo "$as_me: error: this packages requires a curses library" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
 
-   fi
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5
-echo "${ECHO_T}$ac_cv_path_EGREP" >&6; }
- EGREP="$ac_cv_path_EGREP"
+  { echo "$as_me:$LINENO: checking for curses library" >&5
+echo $ECHO_N "checking for curses library... $ECHO_C" >&6; }
+  { echo "$as_me:$LINENO: result: $curseslib" >&5
+echo "${ECHO_T}$curseslib" >&6; }
+  { echo "$as_me:$LINENO: checking for curses header name" >&5
+echo $ECHO_N "checking for curses header name... $ECHO_C" >&6; }
+  { echo "$as_me:$LINENO: result: $CURSESINC" >&5
+echo "${ECHO_T}$CURSESINC" >&6; }
+  { echo "$as_me:$LINENO: checking for curses compiler flags" >&5
+echo $ECHO_N "checking for curses compiler flags... $ECHO_C" >&6; }
+  { echo "$as_me:$LINENO: result: $CURSES_CFLAGS" >&5
+echo "${ECHO_T}$CURSES_CFLAGS" >&6; }
+
+        if test -n "$CURSESLIBDIR"; then
+    if test "-L$CURSESLIBDIR " = "$(echo $CURSESLIB | cut -c-$((${#CURSESLIBDIR}+3)) )"; then
+      CURSESLIB="$(echo $CURSESLIB | cut -c$((${#CURSESLIBDIR}+4))-)"
+    fi
+  fi
 
+  saved_CFLAGS="$CFLAGS"
+  saved_LDFLAGS="$LDFLAGS"
+  saved_LIBS="$LIBS"
+  CFLAGS="$CFLAGS $CURSES_CFLAGS"
+  if test -n "$CURSESLIBDIR"; then
+    LDFLAGS="$LDFLAGS -L$CURSESLIBDIR"
+  fi
+  LIBS="$CURSESLIB $LIBS"
 
-{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5
-echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; }
-if test "${ac_cv_header_stdc+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
   cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <float.h>
-
+#include <panel.h>
 int
 main ()
 {
-
+set_escdelay(100);
   ;
   return 0;
 }
 _ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
 case "(($ac_try" in
   *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
   *) ac_try_echo=$ac_try;;
 esac
 eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+  (eval "$ac_link") 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
@@ -7258,7 +8339,7 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
+        { ac_try='test -s conftest$ac_exeext'
   { (case "(($ac_try" in
   *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
   *) ac_try_echo=$ac_try;;
@@ -7268,105 +8349,245 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_header_stdc=yes
+  HAVE_CURSES_ESCDELAY="yes"
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_header_stdc=no
+
 fi
 
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+  if test "$HAVE_CURSES_ESCDELAY" = "yes"; then
 
-if test $ac_cv_header_stdc = yes; then
-  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
-  cat >conftest.$ac_ext <<_ACEOF
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_CURSES_ESCDELAY 1
+_ACEOF
+
+  fi
+
+  if test "$USE_NLS" = "yes"; then
+    { echo "$as_me:$LINENO: checking for curses NLS support" >&5
+echo $ECHO_N "checking for curses NLS support... $ECHO_C" >&6; }
+                    if test "$curseslib" = "curses"; then
+      cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-#include <string.h>
 
+          #define _XOPEN_SOURCE 1
+          #define _XOPEN_SOURCE_EXTENDED 1
+          #include <curses.h>
+
+int
+main ()
+{
+
+          cchar_t wc;
+          setcchar(&wc, L"x", A_NORMAL, 0, 0);
+
+  ;
+  return 0;
+}
 _ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  $EGREP "memchr" >/dev/null 2>&1; then
-  :
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  CURSES_NLS="yes"
 else
-  ac_cv_header_stdc=no
-fi
-rm -f conftest*
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
 
 fi
 
-if test $ac_cv_header_stdc = yes; then
-  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+rm -f core conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+    fi
+    { echo "$as_me:$LINENO: result: $CURSES_NLS" >&5
+echo "${ECHO_T}$CURSES_NLS" >&6; }
+    if test "$CURSES_NLS" = "yes"; then
+
+cat >>confdefs.h <<\_ACEOF
+#define ENABLE_NLS_IN_CURSES 1
+_ACEOF
+
+    fi
+  fi
+
+  # On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+                 inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
   cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-#include <stdlib.h>
+$ac_includes_default
 
+#include <$ac_header>
 _ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  $EGREP "free" >/dev/null 2>&1; then
-  :
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_Header=yes"
 else
-  ac_cv_header_stdc=no
-fi
-rm -f conftest*
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
 
+       eval "$as_ac_Header=no"
 fi
 
-if test $ac_cv_header_stdc = yes; then
-  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
-  if test "$cross_compiling" = yes; then
-  :
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
 _ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <ctype.h>
-#include <stdlib.h>
-#if ((' ' & 0x0FF) == 0x020)
-# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
-# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
-#else
-# define ISLOWER(c) \
-                  (('a' <= (c) && (c) <= 'i') \
-                    || ('j' <= (c) && (c) <= 'r') \
-                    || ('s' <= (c) && (c) <= 'z'))
-# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
-#endif
 
-#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
-int
-main ()
-{
-  int i;
-  for (i = 0; i < 256; i++)
-    if (XOR (islower (i), ISLOWER (i))
-       || toupper (i) != TOUPPER (i))
-      return 2;
-  return 0;
-}
+fi
+
+done
+
+
+
+
+
+for ac_header in panel.h menu.h form.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
 _ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
 case "(($ac_try" in
   *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
   *) ac_try_echo=$ac_try;;
 esac
 eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>&5
+  (eval "$ac_compile") 2>conftest.er1
   ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
   { (case "(($ac_try" in
   *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
   *) ac_try_echo=$ac_try;;
@@ -7376,91 +8597,122 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  :
+  ac_header_compiler=yes
 else
-  echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
+  echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-( exit $ac_status )
-ac_cv_header_stdc=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+       ac_header_compiler=no
 fi
 
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
 
-fi
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
-echo "${ECHO_T}$ac_cv_header_stdc" >&6; }
-if test $ac_cv_header_stdc = yes; then
-
-cat >>confdefs.h <<\_ACEOF
-#define STDC_HEADERS 1
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
 _ACEOF
-
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
 fi
-
-if test x$alsamixer = xtrue; then
-
-# Check whether --with-curses was given.
-if test "${with_curses+set}" = set; then
-  withval=$with_curses; curseslib="$withval"
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
 else
-  curseslib="auto"
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
 fi
 
-  if test "$curseslib" = "ncursesw"; then
-    # Extract the first word of "ncursesw5-config", so it can be a program name with args.
-set dummy ncursesw5-config; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_ncursesw5_config+set}" = set; then
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  if test -n "$ncursesw5_config"; then
-  ac_cv_prog_ncursesw5_config="$ncursesw5_config" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
-    ac_cv_prog_ncursesw5_config="yes"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-IFS=$as_save_IFS
-
+  eval "$as_ac_Header=\$ac_header_preproc"
 fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
 fi
-ncursesw5_config=$ac_cv_prog_ncursesw5_config
-if test -n "$ncursesw5_config"; then
-  { echo "$as_me:$LINENO: result: $ncursesw5_config" >&5
-echo "${ECHO_T}$ncursesw5_config" >&6; }
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
 else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  { { echo "$as_me:$LINENO: error: required curses helper header not found" >&5
+echo "$as_me: error: required curses helper header not found" >&2;}
+   { (exit 1); exit 1; }; }
 fi
 
+done
 
-    if test "$ncursesw5_config" = "yes"; then
-      CURSESINC="<ncurses.h>"
-      CURSESLIB=`ncursesw5-config --libs`
-      CURSES_CFLAGS=`ncursesw5-config --cflags`
-      curseslib="ncursesw"
-    else
-      { echo "$as_me:$LINENO: checking for initscr in -lncursesw" >&5
-echo $ECHO_N "checking for initscr in -lncursesw... $ECHO_C" >&6; }
-if test "${ac_cv_lib_ncursesw_initscr+set}" = set; then
+  as_ac_Lib=`echo "ac_cv_lib_panel$NCURSESLIBSUFFIX''_new_panel" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for new_panel in -lpanel$NCURSESLIBSUFFIX" >&5
+echo $ECHO_N "checking for new_panel in -lpanel$NCURSESLIBSUFFIX... $ECHO_C" >&6; }
+if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   ac_check_lib_save_LIBS=$LIBS
-LIBS="-lncursesw  $LIBS"
+LIBS="-lpanel$NCURSESLIBSUFFIX  $LIBS"
 cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
@@ -7474,11 +8726,11 @@ cat >>conftest.$ac_ext <<_ACEOF
 #ifdef __cplusplus
 extern "C"
 #endif
-char initscr ();
+char new_panel ();
 int
 main ()
 {
-return initscr ();
+return new_panel ();
   ;
   return 0;
 }
@@ -7517,77 +8769,37 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_lib_ncursesw_initscr=yes
+  eval "$as_ac_Lib=yes"
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_lib_ncursesw_initscr=no
+       eval "$as_ac_Lib=no"
 fi
 
 rm -f core conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_ncursesw_initscr" >&5
-echo "${ECHO_T}$ac_cv_lib_ncursesw_initscr" >&6; }
-if test $ac_cv_lib_ncursesw_initscr = yes; then
-   CURSESINC='<ncurses.h>'; CURSESLIB='-lncursesw'; curseslib="ncursesw"
-fi
-
-    fi
-  fi
-  if test "$curseslib" = "ncurses" -o "$curseslib" = "auto"; then
-    # Extract the first word of "ncurses5-config", so it can be a program name with args.
-set dummy ncurses5-config; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_ncurses5_config+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$ncurses5_config"; then
-  ac_cv_prog_ncurses5_config="$ncurses5_config" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
-    ac_cv_prog_ncurses5_config="yes"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-IFS=$as_save_IFS
-
-fi
-fi
-ncurses5_config=$ac_cv_prog_ncurses5_config
-if test -n "$ncurses5_config"; then
-  { echo "$as_me:$LINENO: result: $ncurses5_config" >&5
-echo "${ECHO_T}$ncurses5_config" >&6; }
+ac_res=`eval echo '${'$as_ac_Lib'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Lib'}'` = yes; then
+  CURSESLIB="-lpanel$NCURSESLIBSUFFIX $CURSESLIB"
 else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  { { echo "$as_me:$LINENO: error: panel$NCURSESLIBSUFFIX library not found" >&5
+echo "$as_me: error: panel$NCURSESLIBSUFFIX library not found" >&2;}
+   { (exit 1); exit 1; }; }
 fi
 
-
-    if test "$ncurses5_config" = "yes"; then
-      CURSESINC="<ncurses.h>"
-      CURSESLIB=`ncurses5-config --libs`
-      CURSES_CFLAGS=`ncurses5-config --cflags`
-      curseslib="ncurses"
-    else
-      { echo "$as_me:$LINENO: checking for initscr in -lncurses" >&5
-echo $ECHO_N "checking for initscr in -lncurses... $ECHO_C" >&6; }
-if test "${ac_cv_lib_ncurses_initscr+set}" = set; then
+  as_ac_Lib=`echo "ac_cv_lib_menu$NCURSESLIBSUFFIX''_new_menu" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for new_menu in -lmenu$NCURSESLIBSUFFIX" >&5
+echo $ECHO_N "checking for new_menu in -lmenu$NCURSESLIBSUFFIX... $ECHO_C" >&6; }
+if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   ac_check_lib_save_LIBS=$LIBS
-LIBS="-lncurses  $LIBS"
+LIBS="-lmenu$NCURSESLIBSUFFIX  $LIBS"
 cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
@@ -7601,11 +8813,11 @@ cat >>conftest.$ac_ext <<_ACEOF
 #ifdef __cplusplus
 extern "C"
 #endif
-char initscr ();
+char new_menu ();
 int
 main ()
 {
-return initscr ();
+return new_menu ();
   ;
   return 0;
 }
@@ -7644,34 +8856,37 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_lib_ncurses_initscr=yes
+  eval "$as_ac_Lib=yes"
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_lib_ncurses_initscr=no
+       eval "$as_ac_Lib=no"
 fi
 
 rm -f core conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_ncurses_initscr" >&5
-echo "${ECHO_T}$ac_cv_lib_ncurses_initscr" >&6; }
-if test $ac_cv_lib_ncurses_initscr = yes; then
-   CURSESINC='<ncurses.h>'; CURSESLIB='-lncurses'; curseslib="ncurses"
+ac_res=`eval echo '${'$as_ac_Lib'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Lib'}'` = yes; then
+  CURSESLIB="-lmenu$NCURSESLIBSUFFIX $CURSESLIB"
+else
+  { { echo "$as_me:$LINENO: error: menu$NCURSESLIBSUFFIX library not found" >&5
+echo "$as_me: error: menu$NCURSESLIBSUFFIX library not found" >&2;}
+   { (exit 1); exit 1; }; }
 fi
 
-    fi
-  fi
-  if test "$curseslib" = "curses" -o "$curseslib" = "auto"; then
-    { echo "$as_me:$LINENO: checking for initscr in -lcurses" >&5
-echo $ECHO_N "checking for initscr in -lcurses... $ECHO_C" >&6; }
-if test "${ac_cv_lib_curses_initscr+set}" = set; then
+  as_ac_Lib=`echo "ac_cv_lib_form$NCURSESLIBSUFFIX''_new_form" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for new_form in -lform$NCURSESLIBSUFFIX" >&5
+echo $ECHO_N "checking for new_form in -lform$NCURSESLIBSUFFIX... $ECHO_C" >&6; }
+if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   ac_check_lib_save_LIBS=$LIBS
-LIBS="-lcurses  $LIBS"
+LIBS="-lform$NCURSESLIBSUFFIX  $LIBS"
 cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
@@ -7685,11 +8900,11 @@ cat >>conftest.$ac_ext <<_ACEOF
 #ifdef __cplusplus
 extern "C"
 #endif
-char initscr ();
+char new_form ();
 int
 main ()
 {
-return initscr ();
+return new_form ();
   ;
   return 0;
 }
@@ -7728,30 +8943,42 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_lib_curses_initscr=yes
+  eval "$as_ac_Lib=yes"
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_lib_curses_initscr=no
+       eval "$as_ac_Lib=no"
 fi
 
 rm -f core conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_curses_initscr" >&5
-echo "${ECHO_T}$ac_cv_lib_curses_initscr" >&6; }
-if test $ac_cv_lib_curses_initscr = yes; then
-   CURSESINC='<curses.h>'; CURSESLIB='-lcurses'; curseslib="curses"
+ac_res=`eval echo '${'$as_ac_Lib'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Lib'}'` = yes; then
+  CURSESLIB="-lform$NCURSESLIBSUFFIX $CURSESLIB"
+else
+  { { echo "$as_me:$LINENO: error: form$NCURSESLIBSUFFIX library not found" >&5
+echo "$as_me: error: form$NCURSESLIBSUFFIX library not found" >&2;}
+   { (exit 1); exit 1; }; }
 fi
 
+
+  CFLAGS="$saved_CFLAGS"
+  LDFLAGS="$saved_LDFLAGS"
+  LIBS="$saved_LIBS"
+
+  if test -n "$CURSESLIBDIR"; then
+    CURSESLIB="-L$CURSESLIBDIR $CURSESLIB"
   fi
-  if test -z "$CURSESINC"; then
-     { { echo "$as_me:$LINENO: error: this packages requires a curses library" >&5
-echo "$as_me: error: this packages requires a curses library" >&2;}
-   { (exit 1); exit 1; }; }
-  fi
+
+  { echo "$as_me:$LINENO: checking for curses linker flags" >&5
+echo $ECHO_N "checking for curses linker flags... $ECHO_C" >&6; }
+  { echo "$as_me:$LINENO: result: $CURSESLIB" >&5
+echo "${ECHO_T}$CURSESLIB" >&6; }
 fi
 
 
@@ -8598,6 +9825,8 @@ SND_UTIL_SUBMINOR=`echo $VERSION | cut -d . -f 3 | sed -e 's/pre[0-9]*//g'`
 
 
 
+
+
 ac_config_files="$ac_config_files Makefile alsactl/Makefile alsactl/init/Makefile alsamixer/Makefile amidi/Makefile amixer/Makefile m4/Makefile po/Makefile.in alsaconf/alsaconf alsaconf/Makefile alsaconf/po/Makefile aplay/Makefile include/Makefile iecset/Makefile utils/Makefile utils/alsa-utils.spec seq/Makefile seq/aconnect/Makefile seq/aplaymidi/Makefile seq/aseqdump/Makefile seq/aseqnet/Makefile speaker-test/Makefile speaker-test/samples/Makefile"
 
 cat >confcache <<\_ACEOF
@@ -8717,6 +9946,34 @@ echo "$as_me: error: conditional \"am__fastdepCC\" was never defined.
 Usually this means the macro was only invoked conditionally." >&2;}
    { (exit 1); exit 1; }; }
 fi
+if test -z "${HAVE_PCM_TRUE}" && test -z "${HAVE_PCM_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"HAVE_PCM\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"HAVE_PCM\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${HAVE_MIXER_TRUE}" && test -z "${HAVE_MIXER_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"HAVE_MIXER\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"HAVE_MIXER\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${HAVE_RAWMIDI_TRUE}" && test -z "${HAVE_RAWMIDI_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"HAVE_RAWMIDI\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"HAVE_RAWMIDI\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${HAVE_SEQ_TRUE}" && test -z "${HAVE_SEQ_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"HAVE_SEQ\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"HAVE_SEQ\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
 if test -z "${ALSAMIXER_TRUE}" && test -z "${ALSAMIXER_FALSE}"; then
   { { echo "$as_me:$LINENO: error: conditional \"ALSAMIXER\" was never defined.
 Usually this means the macro was only invoked conditionally." >&5
@@ -9427,6 +10684,14 @@ for ac_last_try in false false false false false :; do
 LN_S!$LN_S$ac_delim
 ALSA_CFLAGS!$ALSA_CFLAGS$ac_delim
 ALSA_LIBS!$ALSA_LIBS$ac_delim
+HAVE_PCM_TRUE!$HAVE_PCM_TRUE$ac_delim
+HAVE_PCM_FALSE!$HAVE_PCM_FALSE$ac_delim
+HAVE_MIXER_TRUE!$HAVE_MIXER_TRUE$ac_delim
+HAVE_MIXER_FALSE!$HAVE_MIXER_FALSE$ac_delim
+HAVE_RAWMIDI_TRUE!$HAVE_RAWMIDI_TRUE$ac_delim
+HAVE_RAWMIDI_FALSE!$HAVE_RAWMIDI_FALSE$ac_delim
+HAVE_SEQ_TRUE!$HAVE_SEQ_TRUE$ac_delim
+HAVE_SEQ_FALSE!$HAVE_SEQ_FALSE$ac_delim
 ALSAMIXER_TRUE!$ALSAMIXER_TRUE$ac_delim
 ALSAMIXER_FALSE!$ALSAMIXER_FALSE$ac_delim
 ALSACONF_TRUE!$ALSACONF_TRUE$ac_delim
@@ -9447,11 +10712,12 @@ SND_UTIL_VERSION!$SND_UTIL_VERSION$ac_delim
 SND_UTIL_MAJOR!$SND_UTIL_MAJOR$ac_delim
 SND_UTIL_MINOR!$SND_UTIL_MINOR$ac_delim
 SND_UTIL_SUBMINOR!$SND_UTIL_SUBMINOR$ac_delim
+LIBRT!$LIBRT$ac_delim
 LIBOBJS!$LIBOBJS$ac_delim
 LTLIBOBJS!$LTLIBOBJS$ac_delim
 _ACEOF
 
-  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 25; then
+  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 34; then
     break
   elif $ac_last_try; then
     { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
index 59247ed..8bae007 100644 (file)
@@ -1,8 +1,8 @@
 dnl Process this file with autoconf to produce a configure script.
 AC_PREREQ(2.59)
-AC_INIT(alsamixer/alsamixer.c)
+AC_INIT(aplay/aplay.c)
 AC_PREFIX_DEFAULT(/usr)
-AM_INIT_AUTOMAKE(alsa-utils, 1.0.19)
+AM_INIT_AUTOMAKE(alsa-utils, 1.0.23)
 
 AM_GNU_GETTEXT([external])
 AM_GNU_GETTEXT_VERSION([0.15])
@@ -29,10 +29,44 @@ AC_PROG_INSTALL
 AC_PROG_LN_S
 AM_PATH_ALSA(1.0.16)
 
+dnl Check components
+AC_CHECK_HEADERS([alsa/pcm.h], [have_pcm="yes"], [have_pcm="no"],
+  [#include <alsa/asoundlib.h>])
+AC_CHECK_HEADERS([alsa/mixer.h], [have_mixer="yes"], [have_mixer="no"],
+  [#include <alsa/asoundlib.h>])
+AC_CHECK_HEADERS([alsa/rawmidi.h], [have_rawmidi="yes"], [have_rawmidi="no"],
+  [#include <alsa/asoundlib.h>])
+AC_CHECK_HEADERS([alsa/seq.h], [have_seq="yes"], [have_seq="no"],
+  [#include <alsa/asoundlib.h>])
+
+AM_CONDITIONAL(HAVE_PCM, test "$have_pcm" = "yes")
+AM_CONDITIONAL(HAVE_MIXER, test "$have_mixer" = "yes")
+AM_CONDITIONAL(HAVE_RAWMIDI, test "$have_rawmidi" = "yes")
+AM_CONDITIONAL(HAVE_SEQ, test "$have_seq" = "yes")
+
+dnl Check for librt
+LIBRT=""
+AC_MSG_CHECKING(for librt)
+AC_ARG_WITH(librt,
+  AS_HELP_STRING([--with-librt], [Use librt for monotonic clock (default = yes)]),
+  [ have_librt="$withval" ], [ have_librt="yes" ])
+if test "$have_librt" = "yes"; then
+  AC_CHECK_LIB([rt], [clock_gettime], [HAVE_LIBRT="yes"])
+  if test "$HAVE_LIBRT" = "yes" ; then
+    LIBRT="-lrt"
+    AC_DEFINE([HAVE_LIBRT], 1, [Have librt])
+    AC_DEFINE([HAVE_CLOCK_GETTIME], 1, [Have clock gettime])
+  fi
+else
+  AC_MSG_RESULT(no)
+fi
+
 dnl Disable alsamixer
 CURSESINC=""
 CURSESLIB=""
 CURSES_CFLAGS=""
+alsamixer=
+if test "$have_mixer" = "yes"; then
 AC_ARG_ENABLE(alsamixer,
      [  --disable-alsamixer     Disable alsamixer compilation],
      [case "${enableval}" in
@@ -40,6 +74,7 @@ AC_ARG_ENABLE(alsamixer,
        no)  alsamixer=false ;;
        *) AC_MSG_ERROR(bad value ${enableval} for --enable-alsamixer) ;;
      esac],[alsamixer=true])
+fi
 AM_CONDITIONAL(ALSAMIXER, test x$alsamixer = xtrue)
 
 dnl Disable alsaconf
@@ -70,23 +105,32 @@ if test x$alsamixer = xtrue; then
     [  --with-curses libname   Specify the curses library to use (default=auto)],
     curseslib="$withval",
     curseslib="auto")
-  if test "$curseslib" = "ncursesw"; then
+  CURSESLIBDIR=""
+  NCURSESLIBSUFFIX=""
+  CURSES_NLS="no"
+  if test "$curseslib" = "ncursesw" -o \( "$curseslib" = "auto" -a "$USE_NLS" = "yes" \); then
     AC_CHECK_PROG([ncursesw5_config], [ncursesw5-config], [yes])
     if test "$ncursesw5_config" = "yes"; then
       CURSESINC="<ncurses.h>"
       CURSESLIB=`ncursesw5-config --libs`
+      CURSESLIBDIR=`ncursesw5-config --libdir`
       CURSES_CFLAGS=`ncursesw5-config --cflags`
       curseslib="ncursesw"
     else
       AC_CHECK_LIB(ncursesw, initscr, 
                  [ CURSESINC='<ncurses.h>'; CURSESLIB='-lncursesw'; curseslib="ncursesw"])
     fi
+    if test -n "$CURSESINC"; then
+      NCURSESLIBSUFFIX="w"
+      CURSES_NLS="yes"
+    fi
   fi
   if test "$curseslib" = "ncurses" -o "$curseslib" = "auto"; then
     AC_CHECK_PROG([ncurses5_config], [ncurses5-config], [yes])
     if test "$ncurses5_config" = "yes"; then
       CURSESINC="<ncurses.h>"
       CURSESLIB=`ncurses5-config --libs`
+      CURSESLIBDIR=`ncurses5-config --libdir`
       CURSES_CFLAGS=`ncurses5-config --cflags`
       curseslib="ncurses"
     else
@@ -101,6 +145,83 @@ if test x$alsamixer = xtrue; then
   if test -z "$CURSESINC"; then
      AC_MSG_ERROR(this packages requires a curses library)
   fi
+
+  AC_MSG_CHECKING([for curses library])
+  AC_MSG_RESULT([$curseslib])
+  AC_MSG_CHECKING([for curses header name])
+  AC_MSG_RESULT([$CURSESINC])
+  AC_MSG_CHECKING([for curses compiler flags])
+  AC_MSG_RESULT([$CURSES_CFLAGS])
+
+  dnl CURSESLIBS might have the library path at the beginning.  If so, we cut it
+  dnl off so that we can insert the other curses libraries before the ncurses
+  dnl library but after the library path (which is later again prepended below).
+  if test -n "$CURSESLIBDIR"; then
+    if test "-L$CURSESLIBDIR " = "$(echo $CURSESLIB | cut -c-$((${#CURSESLIBDIR}+3)) )"; then
+      CURSESLIB="$(echo $CURSESLIB | cut -c$((${#CURSESLIBDIR}+4))-)"
+    fi
+  fi
+
+  saved_CFLAGS="$CFLAGS"
+  saved_LDFLAGS="$LDFLAGS"
+  saved_LIBS="$LIBS"
+  CFLAGS="$CFLAGS $CURSES_CFLAGS"
+  if test -n "$CURSESLIBDIR"; then
+    LDFLAGS="$LDFLAGS -L$CURSESLIBDIR"
+  fi
+  LIBS="$CURSESLIB $LIBS"
+
+  AC_TRY_LINK([#include <panel.h>], [set_escdelay(100);],[HAVE_CURSES_ESCDELAY="yes"])
+  if test "$HAVE_CURSES_ESCDELAY" = "yes"; then
+    AC_DEFINE([HAVE_CURSES_ESCDELAY], 1, [Have curses set_escdelay])
+  fi
+
+  if test "$USE_NLS" = "yes"; then
+    AC_MSG_CHECKING([for curses NLS support])
+    dnl In theory, a single-byte curses works just fine in ISO 8859-* locales.
+    dnl In practice, however, everybody uses UTF-8 nowadays, so we'd better
+    dnl check for wide-character support.
+    dnl For ncurses/ncursesw, CURSES_NLS was already set above.
+    if test "$curseslib" = "curses"; then
+      AC_TRY_LINK([
+          #define _XOPEN_SOURCE 1
+          #define _XOPEN_SOURCE_EXTENDED 1
+          #include <curses.h>
+        ], [
+          cchar_t wc;
+          setcchar(&wc, L"x", A_NORMAL, 0, 0);
+        ],
+        [CURSES_NLS="yes"])
+    fi
+    AC_MSG_RESULT([$CURSES_NLS])
+    if test "$CURSES_NLS" = "yes"; then
+      AC_DEFINE([ENABLE_NLS_IN_CURSES], [1],
+                [Define if curses-based programs can show translated messages.])
+    fi
+  fi
+
+  AC_CHECK_HEADERS([panel.h menu.h form.h], [],
+                   [AC_MSG_ERROR([required curses helper header not found])])
+  AC_CHECK_LIB([panel$NCURSESLIBSUFFIX], [new_panel],
+               [CURSESLIB="-lpanel$NCURSESLIBSUFFIX $CURSESLIB"],
+               [AC_MSG_ERROR([panel$NCURSESLIBSUFFIX library not found])])
+  AC_CHECK_LIB([menu$NCURSESLIBSUFFIX], [new_menu],
+               [CURSESLIB="-lmenu$NCURSESLIBSUFFIX $CURSESLIB"],
+               [AC_MSG_ERROR([menu$NCURSESLIBSUFFIX library not found])])
+  AC_CHECK_LIB([form$NCURSESLIBSUFFIX], [new_form],
+               [CURSESLIB="-lform$NCURSESLIBSUFFIX $CURSESLIB"],
+               [AC_MSG_ERROR([form$NCURSESLIBSUFFIX library not found])])
+
+  CFLAGS="$saved_CFLAGS"
+  LDFLAGS="$saved_LDFLAGS"
+  LIBS="$saved_LIBS"
+
+  if test -n "$CURSESLIBDIR"; then
+    CURSESLIB="-L$CURSESLIBDIR $CURSESLIB"
+  fi
+
+  AC_MSG_CHECKING([for curses linker flags])
+  AC_MSG_RESULT([$CURSESLIB])
 fi
 
 AC_SUBST(CURSESINC)
@@ -142,6 +263,8 @@ AC_SYS_LARGEFILE
 
 SAVE_UTIL_VERSION
 
+AC_SUBST(LIBRT)
+
 AC_OUTPUT(Makefile alsactl/Makefile alsactl/init/Makefile \
          alsamixer/Makefile amidi/Makefile amixer/Makefile \
          m4/Makefile po/Makefile.in \
index 82c31cc..f27887a 100644 (file)
@@ -106,6 +106,14 @@ EXEEXT = @EXEEXT@
 GMSGFMT = @GMSGFMT@
 GMSGFMT_015 = @GMSGFMT_015@
 GREP = @GREP@
+HAVE_MIXER_FALSE = @HAVE_MIXER_FALSE@
+HAVE_MIXER_TRUE = @HAVE_MIXER_TRUE@
+HAVE_PCM_FALSE = @HAVE_PCM_FALSE@
+HAVE_PCM_TRUE = @HAVE_PCM_TRUE@
+HAVE_RAWMIDI_FALSE = @HAVE_RAWMIDI_FALSE@
+HAVE_RAWMIDI_TRUE = @HAVE_RAWMIDI_TRUE@
+HAVE_SEQ_FALSE = @HAVE_SEQ_FALSE@
+HAVE_SEQ_TRUE = @HAVE_SEQ_TRUE@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -116,6 +124,7 @@ LDFLAGS = @LDFLAGS@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
 LIBOBJS = @LIBOBJS@
+LIBRT = @LIBRT@
 LIBS = @LIBS@
 LN_S = @LN_S@
 LTLIBICONV = @LTLIBICONV@
index 112e5ce..7a3968d 100644 (file)
@@ -1,4 +1,4 @@
-noinst_HEADERS=version.h gettext.h
+noinst_HEADERS=version.h gettext.h gettext_curses.h
 
 version.h: stamp-vh
        @:
index e835006..ef532d2 100644 (file)
@@ -90,6 +90,14 @@ EXEEXT = @EXEEXT@
 GMSGFMT = @GMSGFMT@
 GMSGFMT_015 = @GMSGFMT_015@
 GREP = @GREP@
+HAVE_MIXER_FALSE = @HAVE_MIXER_FALSE@
+HAVE_MIXER_TRUE = @HAVE_MIXER_TRUE@
+HAVE_PCM_FALSE = @HAVE_PCM_FALSE@
+HAVE_PCM_TRUE = @HAVE_PCM_TRUE@
+HAVE_RAWMIDI_FALSE = @HAVE_RAWMIDI_FALSE@
+HAVE_RAWMIDI_TRUE = @HAVE_RAWMIDI_TRUE@
+HAVE_SEQ_FALSE = @HAVE_SEQ_FALSE@
+HAVE_SEQ_TRUE = @HAVE_SEQ_TRUE@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -100,6 +108,7 @@ LDFLAGS = @LDFLAGS@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
 LIBOBJS = @LIBOBJS@
+LIBRT = @LIBRT@
 LIBS = @LIBS@
 LN_S = @LN_S@
 LTLIBICONV = @LTLIBICONV@
@@ -178,7 +187,7 @@ sharedstatedir = @sharedstatedir@
 sysconfdir = @sysconfdir@
 target_alias = @target_alias@
 xmlto = @xmlto@
-noinst_HEADERS = version.h gettext.h
+noinst_HEADERS = version.h gettext.h gettext_curses.h
 INCLUDES = -I$(top_srcdir)/include
 all: aconfig.h
        $(MAKE) $(AM_MAKEFLAGS) all-am
index 600c887..033a345 100644 (file)
@@ -7,6 +7,21 @@
    language is requested. */
 #undef ENABLE_NLS
 
+/* Define if curses-based programs can show translated messages. */
+#undef ENABLE_NLS_IN_CURSES
+
+/* Define to 1 if you have the <alsa/mixer.h> header file. */
+#undef HAVE_ALSA_MIXER_H
+
+/* Define to 1 if you have the <alsa/pcm.h> header file. */
+#undef HAVE_ALSA_PCM_H
+
+/* Define to 1 if you have the <alsa/rawmidi.h> header file. */
+#undef HAVE_ALSA_RAWMIDI_H
+
+/* Define to 1 if you have the <alsa/seq.h> header file. */
+#undef HAVE_ALSA_SEQ_H
+
 /* Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the
    CoreFoundation framework. */
 #undef HAVE_CFLOCALECOPYCURRENT
    the CoreFoundation framework. */
 #undef HAVE_CFPREFERENCESCOPYAPPVALUE
 
+/* Have clock gettime */
+#undef HAVE_CLOCK_GETTIME
+
+/* Have curses set_escdelay */
+#undef HAVE_CURSES_ESCDELAY
+
 /* Define if the GNU dcgettext() function is already present or preinstalled.
    */
 #undef HAVE_DCGETTEXT
 
+/* Define to 1 if you have the <form.h> header file. */
+#undef HAVE_FORM_H
+
 /* Define if the GNU gettext() function is already present or preinstalled. */
 #undef HAVE_GETTEXT
 
 /* Define if you have the iconv() function. */
 #undef HAVE_ICONV
 
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
 /* Define to 1 if you have the `asound' library (-lasound). */
 #undef HAVE_LIBASOUND
 
+/* Have librt */
+#undef HAVE_LIBRT
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <menu.h> header file. */
+#undef HAVE_MENU_H
+
+/* Define to 1 if you have the <panel.h> header file. */
+#undef HAVE_PANEL_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
 /* Name of package */
 #undef PACKAGE
 
index c2bfe96..d8a1467 100644 (file)
@@ -1,7 +1,13 @@
 #ifndef __MY_GETTEXT_H
 #define __MY_GETTEXT_H
 
-#if ENABLE_NLS
+#ifdef USES_CURSES
+#define ENABLE_NLS_TEST ENABLE_NLS_IN_CURSES
+#else
+#define ENABLE_NLS_TEST ENABLE_NLS
+#endif
+
+#if ENABLE_NLS_TEST
 # include <libintl.h>
 #else
 # define gettext(msgid) (msgid)
diff --git a/include/gettext_curses.h b/include/gettext_curses.h
new file mode 100644 (file)
index 0000000..f1c4041
--- /dev/null
@@ -0,0 +1,2 @@
+#define USES_CURSES
+#include "gettext.h"
index 36a48c1..dbdcc82 100644 (file)
@@ -4,9 +4,9 @@
 
 #define SND_UTIL_MAJOR         1
 #define SND_UTIL_MINOR         0
-#define SND_UTIL_SUBMINOR      19
+#define SND_UTIL_SUBMINOR      23
 #define SND_UTIL_VERSION               ((SND_UTIL_MAJOR<<16)|\
                                 (SND_UTIL_MINOR<<8)|\
                                  SND_UTIL_SUBMINOR)
-#define SND_UTIL_VERSION_STR   "1.0.19"
+#define SND_UTIL_VERSION_STR   "1.0.23"
 
index 06e33ad..9d68382 100644 (file)
@@ -85,6 +85,14 @@ EXEEXT = @EXEEXT@
 GMSGFMT = @GMSGFMT@
 GMSGFMT_015 = @GMSGFMT_015@
 GREP = @GREP@
+HAVE_MIXER_FALSE = @HAVE_MIXER_FALSE@
+HAVE_MIXER_TRUE = @HAVE_MIXER_TRUE@
+HAVE_PCM_FALSE = @HAVE_PCM_FALSE@
+HAVE_PCM_TRUE = @HAVE_PCM_TRUE@
+HAVE_RAWMIDI_FALSE = @HAVE_RAWMIDI_FALSE@
+HAVE_RAWMIDI_TRUE = @HAVE_RAWMIDI_TRUE@
+HAVE_SEQ_FALSE = @HAVE_SEQ_FALSE@
+HAVE_SEQ_TRUE = @HAVE_SEQ_TRUE@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -95,6 +103,7 @@ LDFLAGS = @LDFLAGS@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
 LIBOBJS = @LIBOBJS@
+LIBRT = @LIBRT@
 LIBS = @LIBS@
 LN_S = @LN_S@
 LTLIBICONV = @LTLIBICONV@
index bef7f4a..081e105 100644 (file)
@@ -1 +1 @@
-ja
+ja de
index 32692ab..779d8ac 100644 (file)
@@ -18,7 +18,7 @@ XGETTEXT_OPTIONS = --keyword=_ --keyword=N_
 # or entity, or to disclaim their copyright.  The empty string stands for
 # the public domain; in this case the translators are expected to disclaim
 # their copyright.
-COPYRIGHT_HOLDER = Free Software Foundation, Inc.
+COPYRIGHT_HOLDER = The ALSA Team
 
 # This is the email address or URL to which the translators shall report
 # bugs in the untranslated strings:
index 11a6a96..3d1b8ea 100644 (file)
@@ -1,3 +1,11 @@
+alsamixer/card_select.c
+alsamixer/cli.c
+alsamixer/device_name.c
+alsamixer/die.c
+alsamixer/mixer_display.c
+alsamixer/mixer_widget.c
+alsamixer/proc_files.c
+alsamixer/textbox.c
 aplay/aplay.c
 seq/aconnect/aconnect.c
 seq/aseqnet/aseqnet.c
index 93bf58e..5011590 100644 (file)
@@ -1,5 +1,5 @@
 # SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR Free Software Foundation, Inc.
+# Copyright (C) YEAR The ALSA Team
 # This file is distributed under the same license as the PACKAGE package.
 # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
 #
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2009-01-19 12:24+0100\n"
+"POT-Creation-Date: 2010-04-16 13:19+0200\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -16,23 +16,363 @@ msgstr ""
 "Content-Type: text/plain; charset=CHARSET\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: aplay/aplay.c:136
+#: alsamixer/card_select.c:126 alsamixer/device_name.c:126
+msgid "Sound Card"
+msgstr ""
+
+#: alsamixer/card_select.c:181
+msgid "(default)"
+msgstr ""
+
+#: alsamixer/card_select.c:191
+msgid "cannot enumerate sound cards"
+msgstr ""
+
+#: alsamixer/card_select.c:215
+msgid "enter device name..."
+msgstr ""
+
+#: alsamixer/cli.c:40
+msgid "Usage: alsamixer [options]"
+msgstr ""
+
+#: alsamixer/cli.c:41
+msgid ""
+"Useful options:\n"
+"  -h, --help              this help\n"
+"  -c, --card=NUMBER       sound card number or id\n"
+"  -D, --device=NAME       mixer device name\n"
+"  -V, --view=MODE         starting view mode: playback/capture/all"
+msgstr ""
+
+#: alsamixer/cli.c:46
+msgid ""
+"Debugging options:\n"
+"  -g, --no-color          toggle using of colors\n"
+"  -a, --abstraction=NAME  mixer abstraction level: none/basic"
+msgstr ""
+
+#: alsamixer/cli.c:77
+#, c-format
+msgid "invalid card index: %s\n"
+msgstr ""
+
+#: alsamixer/cli.c:103
+#, c-format
+msgid "unknown abstraction level: %s\n"
+msgstr ""
+
+#: alsamixer/cli.c:108
+#, c-format
+msgid "unknown option: %c\n"
+msgstr ""
+
+#: alsamixer/cli.c:110
+msgid "try `alsamixer --help' for more information\n"
+msgstr ""
+
+#: alsamixer/device_name.c:177
+msgid "Device name:"
+msgstr ""
+
+#: alsamixer/die.c:37
+#, c-format
+msgid "%s: %s\n"
+msgstr ""
+
+#: alsamixer/mixer_display.c:95
+msgid "Card:"
+msgstr ""
+
+#: alsamixer/mixer_display.c:96
+msgid "Chip:"
+msgstr ""
+
+#: alsamixer/mixer_display.c:97
+msgid "View:"
+msgstr ""
+
+#: alsamixer/mixer_display.c:98
+msgid "Item:"
+msgstr ""
+
+#: alsamixer/mixer_display.c:101
+msgid "F1:  Help"
+msgstr ""
+
+#: alsamixer/mixer_display.c:102
+msgid "F2:  System information"
+msgstr ""
+
+#: alsamixer/mixer_display.c:103
+msgid "F6:  Select sound card"
+msgstr ""
+
+#: alsamixer/mixer_display.c:104
+msgid "Esc: Exit"
+msgstr ""
+
+#: alsamixer/mixer_display.c:171
+msgid "(unplugged)"
+msgstr ""
+
+#: alsamixer/mixer_display.c:189
+msgid "Playback"
+msgstr ""
+
+#: alsamixer/mixer_display.c:190
+msgid "Capture"
+msgstr ""
+
+#: alsamixer/mixer_display.c:191
+msgid "All"
+msgstr ""
+
+#: alsamixer/mixer_display.c:231
+msgid "mute"
+msgstr ""
+
+#: alsamixer/mixer_display.c:272 alsamixer/mixer_display.c:282
+msgid "dB gain:"
+msgstr ""
+
+#: alsamixer/mixer_display.c:282
+#, c-format
+msgid " [%s %s, %s]"
+msgstr ""
+
+#: alsamixer/mixer_display.c:291 alsamixer/mixer_display.c:297
+#: alsamixer/mixer_display.c:303 alsamixer/mixer_display.c:309
+msgid "Off"
+msgstr ""
+
+#: alsamixer/mixer_display.c:297 alsamixer/mixer_display.c:309
+msgid "On"
+msgstr ""
+
+#: alsamixer/mixer_display.c:360
+msgid "The sound device was unplugged."
+msgstr ""
+
+#: alsamixer/mixer_display.c:361
+msgid "Press F6 to select another sound card."
+msgstr ""
+
+#: alsamixer/mixer_display.c:376
+msgid "This sound device does not have any playback controls."
+msgstr ""
+
+#: alsamixer/mixer_display.c:378
+msgid "This sound device does not have any capture controls."
+msgstr ""
+
+#: alsamixer/mixer_display.c:380
+msgid "This sound device does not have any controls."
+msgstr ""
+
+#. TRANSLATORS: playback on; one character
+#: alsamixer/mixer_display.c:537 alsamixer/mixer_display.c:542
+msgid "O"
+msgstr ""
+
+#. TRANSLATORS: playback muted; one character
+#: alsamixer/mixer_display.c:539 alsamixer/mixer_display.c:543
+msgid "M"
+msgstr ""
+
+#. TRANSLATORS: "left"; no more than two characters
+#: alsamixer/mixer_display.c:557
+msgid "L"
+msgstr ""
+
+#. TRANSLATORS: "right"; no more than two characters
+#: alsamixer/mixer_display.c:561
+msgid "R"
+msgstr ""
+
+#. TRANSLATORS: no more than eight characters
+#: alsamixer/mixer_display.c:563
+msgid "CAPTURE"
+msgstr ""
+
+#: alsamixer/mixer_display.c:613
+msgid "Front"
+msgstr ""
+
+#: alsamixer/mixer_display.c:616
+msgid "Rear"
+msgstr ""
+
+#: alsamixer/mixer_display.c:619 speaker-test/speaker-test.c:107
+msgid "Center"
+msgstr ""
+
+#: alsamixer/mixer_display.c:622
+msgid "Woofer"
+msgstr ""
+
+#: alsamixer/mixer_display.c:625
+msgid "Side"
+msgstr ""
+
+#: alsamixer/mixer_widget.c:83 alsamixer/mixer_widget.c:88
+msgid "cannot open mixer"
+msgstr ""
+
+#: alsamixer/mixer_widget.c:94 alsamixer/mixer_widget.c:171
+msgid "cannot load mixer controls"
+msgstr ""
+
+#: alsamixer/mixer_widget.c:161
+#, c-format
+msgid "Cannot open mixer device '%s'."
+msgstr ""
+
+#: alsamixer/mixer_widget.c:182
+msgid "Esc     Exit"
+msgstr ""
+
+#: alsamixer/mixer_widget.c:183
+msgid "F1 ? H  Help"
+msgstr ""
+
+#: alsamixer/mixer_widget.c:184
+msgid "F2 /    System information"
+msgstr ""
+
+#: alsamixer/mixer_widget.c:185
+msgid "F3      Show playback controls"
+msgstr ""
+
+#: alsamixer/mixer_widget.c:186
+msgid "F4      Show capture controls"
+msgstr ""
+
+#: alsamixer/mixer_widget.c:187
+msgid "F5      Show all controls"
+msgstr ""
+
+#: alsamixer/mixer_widget.c:188
+msgid "Tab     Toggle view mode (F3/F4/F5)"
+msgstr ""
+
+#: alsamixer/mixer_widget.c:189
+msgid "F6 S    Select sound card"
+msgstr ""
+
+#: alsamixer/mixer_widget.c:190
+msgid "L       Redraw screen"
+msgstr ""
+
+#: alsamixer/mixer_widget.c:192
+msgid "Left    Move to the previous control"
+msgstr ""
+
+#: alsamixer/mixer_widget.c:193
+msgid "Right   Move to the next control"
+msgstr ""
+
+#: alsamixer/mixer_widget.c:195
+msgid "Up/Down    Change volume"
+msgstr ""
+
+#: alsamixer/mixer_widget.c:196
+msgid "+ -        Change volume"
+msgstr ""
+
+#: alsamixer/mixer_widget.c:197
+msgid "Page Up/Dn Change volume in big steps"
+msgstr ""
+
+#: alsamixer/mixer_widget.c:198
+msgid "End        Set volume to 0%"
+msgstr ""
+
+#: alsamixer/mixer_widget.c:199
+msgid "0-9        Set volume to 0%-90%"
+msgstr ""
+
+#: alsamixer/mixer_widget.c:200
+msgid "Q W E      Increase left/both/right volumes"
+msgstr ""
+
+#. TRANSLATORS: or Y instead of Z
+#: alsamixer/mixer_widget.c:202
+msgid "Z X C      Decrease left/both/right volumes"
+msgstr ""
+
+#: alsamixer/mixer_widget.c:203
+msgid "B          Balance left and right volumes"
+msgstr ""
+
+#: alsamixer/mixer_widget.c:205
+msgid "M          Toggle mute"
+msgstr ""
+
+#. TRANSLATORS: or , .
+#: alsamixer/mixer_widget.c:207
+msgid "< >        Toggle left/right mute"
+msgstr ""
+
+#: alsamixer/mixer_widget.c:209
+msgid "Space      Toggle capture"
+msgstr ""
+
+#. TRANSLATORS: or Insert Delete
+#: alsamixer/mixer_widget.c:211
+msgid "; '        Toggle left/right capture"
+msgstr ""
+
+#: alsamixer/mixer_widget.c:213
+msgid "Authors:"
+msgstr ""
+
+#: alsamixer/mixer_widget.c:214
+msgid "  Tim Janik <timj@gtk.org>"
+msgstr ""
+
+#: alsamixer/mixer_widget.c:215
+msgid "  Jaroslav Kysela <perex@perex.cz>"
+msgstr ""
+
+#: alsamixer/mixer_widget.c:216
+msgid "  Clemens Ladisch <clemens@ladisch.de>"
+msgstr ""
+
+#: alsamixer/mixer_widget.c:218
+msgid "Help"
+msgstr ""
+
+#: alsamixer/proc_files.c:103
+msgid "Select File"
+msgstr ""
+
+#: alsamixer/textbox.c:52 alsamixer/textbox.c:66
+msgid "Error"
+msgstr ""
+
+#: alsamixer/textbox.c:80
+#, c-format
+msgid "Cannot open file \"%s\"."
+msgstr ""
+
+#: aplay/aplay.c:147
 msgid "raw data"
 msgstr ""
 
-#: aplay/aplay.c:137
+#: aplay/aplay.c:148
 msgid "VOC"
 msgstr ""
 
-#: aplay/aplay.c:139
+#: aplay/aplay.c:150
 msgid "WAVE"
 msgstr ""
 
-#: aplay/aplay.c:140
+#: aplay/aplay.c:151
 msgid "Sparc Audio"
 msgstr ""
 
-#: aplay/aplay.c:161
+#: aplay/aplay.c:172
 #, c-format
 msgid ""
 "Usage: %s [OPTION]... [FILE]...\n"
@@ -67,421 +407,442 @@ msgid ""
 "    --disable-format    disable automatic format conversions\n"
 "    --disable-softvol   disable software volume control (softvol)\n"
 "    --test-position     test ring buffer position\n"
+"    --test-coef=#\t test coeficient for ring buffer position (default 8)\n"
+"                        expression for validation is: coef * (buffer_size / "
+"2)\n"
+"    --test-nowait       do not wait for ring buffer - eats whole CPU\n"
+"    --max-file-time=#   start another output file when the old file has "
+"recorded\n"
+"                        for this many seconds\n"
+"    --process-id-file   write the process ID here\n"
+"    --use-strftime      apply the strftime facility to the output file name\n"
 msgstr ""
 
-#: aplay/aplay.c:193 speaker-test/speaker-test.c:783
+#: aplay/aplay.c:211 speaker-test/speaker-test.c:750
 #, c-format
 msgid "Recognized sample formats are:"
 msgstr ""
 
-#: aplay/aplay.c:199
+#: aplay/aplay.c:217
 #, c-format
 msgid ""
 "\n"
 "Some of these may not be available on selected hardware\n"
 msgstr ""
 
-#: aplay/aplay.c:200
+#: aplay/aplay.c:218
 #, c-format
 msgid "The availabled format shortcuts are:\n"
 msgstr ""
 
-#: aplay/aplay.c:201
+#: aplay/aplay.c:219
 #, c-format
 msgid "-f cd (16 bit little endian, 44100, stereo)\n"
 msgstr ""
 
-#: aplay/aplay.c:202
+#: aplay/aplay.c:220
 #, c-format
 msgid "-f cdr (16 bit big endian, 44100, stereo)\n"
 msgstr ""
 
-#: aplay/aplay.c:203
+#: aplay/aplay.c:221
 #, c-format
 msgid "-f dat (16 bit little endian, 48000, stereo)\n"
 msgstr ""
 
-#: aplay/aplay.c:217
+#: aplay/aplay.c:235
 msgid "no soundcards found..."
 msgstr ""
 
-#: aplay/aplay.c:220
+#: aplay/aplay.c:238
 #, c-format
 msgid "**** List of %s Hardware Devices ****\n"
 msgstr ""
 
-#: aplay/aplay.c:249
+#: aplay/aplay.c:267
 #, c-format
 msgid "card %i: %s [%s], device %i: %s [%s]\n"
 msgstr ""
 
-#: aplay/aplay.c:255
+#: aplay/aplay.c:273
 #, c-format
 msgid "  Subdevices: %i/%i\n"
 msgstr ""
 
-#: aplay/aplay.c:262
+#: aplay/aplay.c:280
 #, c-format
 msgid "  Subdevice #%i: %s\n"
 msgstr ""
 
-#: aplay/aplay.c:326
+#: aplay/aplay.c:356
 #, c-format
 msgid "Aborted by signal %s...\n"
 msgstr ""
 
-#: aplay/aplay.c:420
+#: aplay/aplay.c:467
 msgid "command should be named either arecord or aplay"
 msgstr ""
 
-#: aplay/aplay.c:459
+#: aplay/aplay.c:506
 #, c-format
 msgid "unrecognized file format %s"
 msgstr ""
 
-#: aplay/aplay.c:466
+#: aplay/aplay.c:513
 #, c-format
 msgid "value %i for channels is invalid"
 msgstr ""
 
-#: aplay/aplay.c:485
+#: aplay/aplay.c:532
 #, c-format
 msgid "wrong extended format '%s'"
 msgstr ""
 
-#: aplay/aplay.c:496
+#: aplay/aplay.c:543
 #, c-format
 msgid "bad speed value %i"
 msgstr ""
 
-#: aplay/aplay.c:574
+#: aplay/aplay.c:638
 #, c-format
 msgid "Try `%s --help' for more information.\n"
 msgstr ""
 
-#: aplay/aplay.c:590
+#: aplay/aplay.c:654
 #, c-format
 msgid "audio open error: %s"
 msgstr ""
 
-#: aplay/aplay.c:595
+#: aplay/aplay.c:659
 #, c-format
 msgid "info error: %s"
 msgstr ""
 
-#: aplay/aplay.c:602
+#: aplay/aplay.c:666
 #, c-format
 msgid "nonblock setting error: %s"
 msgstr ""
 
-#: aplay/aplay.c:612 aplay/aplay.c:719 aplay/aplay.c:1073
+#: aplay/aplay.c:676 aplay/aplay.c:800 aplay/aplay.c:1167
 msgid "not enough memory"
 msgstr ""
 
-#: aplay/aplay.c:709
+#: aplay/aplay.c:700
+#, c-format
+msgid "Cannot create process ID file %s: %s"
+msgstr ""
+
+#: aplay/aplay.c:790
 #, c-format
 msgid "read error (called from line %i)"
 msgstr ""
 
-#: aplay/aplay.c:767
+#: aplay/aplay.c:848
 #, c-format
 msgid "unknown length of 'fmt ' chunk (read %u, should be %u at least)"
 msgstr ""
 
-#: aplay/aplay.c:777
+#: aplay/aplay.c:858
 #, c-format
 msgid ""
 "unknown length of extensible 'fmt ' chunk (read %u, should be %u at least)"
 msgstr ""
 
-#: aplay/aplay.c:782
+#: aplay/aplay.c:863
 msgid "wrong format tag in extensible 'fmt ' chunk"
 msgstr ""
 
-#: aplay/aplay.c:789
+#: aplay/aplay.c:870
 #, c-format
 msgid "can't play WAVE-file format 0x%04x which is not PCM or FLOAT encoded"
 msgstr ""
 
-#: aplay/aplay.c:793
+#: aplay/aplay.c:874
 #, c-format
 msgid "can't play WAVE-files with %d tracks"
 msgstr ""
 
-#: aplay/aplay.c:801 aplay/aplay.c:901
+#: aplay/aplay.c:882 aplay/aplay.c:982
 #, c-format
 msgid "Warning: format is changed to U8\n"
 msgstr ""
 
-#: aplay/aplay.c:807
+#: aplay/aplay.c:888
 #, c-format
 msgid "Warning: format is changed to S16_LE\n"
 msgstr ""
 
-#: aplay/aplay.c:815
+#: aplay/aplay.c:896
 #, c-format
 msgid "Warning: format is changed to S24_3LE\n"
 msgstr ""
 
-#: aplay/aplay.c:821
+#: aplay/aplay.c:902
 #, c-format
 msgid "Warning: format is changed to S24_LE\n"
 msgstr ""
 
-#: aplay/aplay.c:825
+#: aplay/aplay.c:906
 #, c-format
 msgid ""
 " can't play WAVE-files with sample %d bits in %d bytes wide (%d channels)"
 msgstr ""
 
-#: aplay/aplay.c:837
+#: aplay/aplay.c:918
 #, c-format
 msgid " can't play WAVE-files with sample %d bits wide"
 msgstr ""
 
-#: aplay/aplay.c:895
+#: aplay/aplay.c:976
 #, c-format
 msgid "Warning: format is changed to MU_LAW\n"
 msgstr ""
 
-#: aplay/aplay.c:907
+#: aplay/aplay.c:988
 #, c-format
 msgid "Warning: format is changed to S16_BE\n"
 msgstr ""
 
-#: aplay/aplay.c:920 aplay/aplay.c:1679 aplay/aplay.c:1686 aplay/aplay.c:2208
-#: aplay/aplay.c:2220
+#: aplay/aplay.c:1001 aplay/aplay.c:1843 aplay/aplay.c:1850 aplay/aplay.c:2372
+#: aplay/aplay.c:2384
 msgid "read error"
 msgstr ""
 
-#: aplay/aplay.c:939
+#: aplay/aplay.c:1031
 msgid "Broken configuration for this PCM: no configurations available"
 msgstr ""
 
-#: aplay/aplay.c:956
+#: aplay/aplay.c:1048
 msgid "Access type not available"
 msgstr ""
 
-#: aplay/aplay.c:961
+#: aplay/aplay.c:1053
 msgid "Sample format non available"
 msgstr ""
 
-#: aplay/aplay.c:966
+#: aplay/aplay.c:1059
 msgid "Channels count non available"
 msgstr ""
 
-#: aplay/aplay.c:981
+#: aplay/aplay.c:1074
 #, c-format
 msgid "Warning: rate is not accurate (requested = %iHz, got = %iHz)\n"
 msgstr ""
 
-#: aplay/aplay.c:987
+#: aplay/aplay.c:1080
 #, c-format
 msgid "         please, try the plug plugin %s\n"
 msgstr ""
 
-#: aplay/aplay.c:1022
+#: aplay/aplay.c:1116
 msgid "Unable to install hw params:"
 msgstr ""
 
-#: aplay/aplay.c:1029
+#: aplay/aplay.c:1123
 #, c-format
 msgid "Can't use period equal to buffer size (%lu == %lu)"
 msgstr ""
 
-#: aplay/aplay.c:1060
+#: aplay/aplay.c:1154
 msgid "unable to install sw params:"
 msgstr ""
 
-#: aplay/aplay.c:1123
+#: aplay/aplay.c:1229
 #, c-format
 msgid "status error: %s"
 msgstr ""
 
-#: aplay/aplay.c:1131
+#: aplay/aplay.c:1239 aplay/aplay.c:1250
 #, c-format
 msgid "%s!!! (at least %.3f ms long)\n"
 msgstr ""
 
-#: aplay/aplay.c:1132
+#: aplay/aplay.c:1240 aplay/aplay.c:1243 aplay/aplay.c:1251
 msgid "underrun"
 msgstr ""
 
-#: aplay/aplay.c:1132
+#: aplay/aplay.c:1240 aplay/aplay.c:1251
 msgid "overrun"
 msgstr ""
 
-#: aplay/aplay.c:1135
+#: aplay/aplay.c:1255
 #, c-format
 msgid "Status:\n"
 msgstr ""
 
-#: aplay/aplay.c:1139
+#: aplay/aplay.c:1259
 #, c-format
 msgid "xrun: prepare error: %s"
 msgstr ""
 
-#: aplay/aplay.c:1145
+#: aplay/aplay.c:1265
 #, c-format
 msgid "Status(DRAINING):\n"
 msgstr ""
 
-#: aplay/aplay.c:1149
+#: aplay/aplay.c:1269
 #, c-format
 msgid "capture stream format change? attempting recover...\n"
 msgstr ""
 
-#: aplay/aplay.c:1151
+#: aplay/aplay.c:1271
 #, c-format
 msgid "xrun(DRAINING): prepare error: %s"
 msgstr ""
 
-#: aplay/aplay.c:1158
+#: aplay/aplay.c:1278
 #, c-format
 msgid "Status(R/W):\n"
 msgstr ""
 
-#: aplay/aplay.c:1161
+#: aplay/aplay.c:1281
 #, c-format
 msgid "read/write error, state = %s"
 msgstr ""
 
-#: aplay/aplay.c:1171
+#: aplay/aplay.c:1291
 #, c-format
 msgid "Suspended. Trying resume. "
 msgstr ""
 
-#: aplay/aplay.c:1176
+#: aplay/aplay.c:1296
 #, c-format
 msgid "Failed. Restarting stream. "
 msgstr ""
 
-#: aplay/aplay.c:1178
+#: aplay/aplay.c:1298
 #, c-format
 msgid "suspend: prepare error: %s"
 msgstr ""
 
-#: aplay/aplay.c:1183
+#: aplay/aplay.c:1303
 #, c-format
 msgid "Done.\n"
 msgstr ""
 
-#: aplay/aplay.c:1205
+#: aplay/aplay.c:1325
 #, c-format
 msgid " !clip  "
 msgstr ""
 
-#: aplay/aplay.c:1352
+#: aplay/aplay.c:1472
 #, c-format
 msgid "Unsupported bit size %d.\n"
 msgstr ""
 
-#: aplay/aplay.c:1386
+#: aplay/aplay.c:1506
 #, c-format
 msgid "Max peak (%li samples): 0x%08x "
 msgstr ""
 
-#: aplay/aplay.c:1442
+#: aplay/aplay.c:1540
+#, c-format
+msgid ""
+"Suspicious buffer position (%li total): avail = %li, delay = %li, buffer = %"
+"li\n"
+msgstr ""
+
+#: aplay/aplay.c:1603
 #, c-format
 msgid "write error: %s"
 msgstr ""
 
-#: aplay/aplay.c:1487
+#: aplay/aplay.c:1649
 #, c-format
 msgid "writev error: %s"
 msgstr ""
 
-#: aplay/aplay.c:1529
+#: aplay/aplay.c:1692
 #, c-format
 msgid "read error: %s"
 msgstr ""
 
-#: aplay/aplay.c:1571
+#: aplay/aplay.c:1735
 #, c-format
 msgid "readv error: %s"
 msgstr ""
 
-#: aplay/aplay.c:1619
+#: aplay/aplay.c:1783
 msgid "can't allocate buffer for silence"
 msgstr ""
 
-#: aplay/aplay.c:1628 aplay/aplay.c:1854 aplay/aplay.c:1859 aplay/aplay.c:1906
-#: aplay/aplay.c:1915 aplay/aplay.c:1922 aplay/aplay.c:1932 aplay/aplay.c:1938
-#: aplay/aplay.c:2010 aplay/aplay.c:2040 aplay/aplay.c:2054
+#: aplay/aplay.c:1792 aplay/aplay.c:2018 aplay/aplay.c:2023 aplay/aplay.c:2070
+#: aplay/aplay.c:2079 aplay/aplay.c:2086 aplay/aplay.c:2096 aplay/aplay.c:2102
+#: aplay/aplay.c:2174 aplay/aplay.c:2204 aplay/aplay.c:2218
 msgid "write error"
 msgstr ""
 
-#: aplay/aplay.c:1641
+#: aplay/aplay.c:1805
 #, c-format
 msgid "voc_pcm_flush - silence error"
 msgstr ""
 
-#: aplay/aplay.c:1644
+#: aplay/aplay.c:1808
 msgid "voc_pcm_flush error"
 msgstr ""
 
-#: aplay/aplay.c:1670
+#: aplay/aplay.c:1834
 msgid "malloc error"
 msgstr ""
 
-#: aplay/aplay.c:1674
+#: aplay/aplay.c:1838
 #, c-format
 msgid "Playing Creative Labs Channel file '%s'...\n"
 msgstr ""
 
-#: aplay/aplay.c:1742 aplay/aplay.c:1834
+#: aplay/aplay.c:1906 aplay/aplay.c:1998
 msgid "can't play packed .voc files"
 msgstr ""
 
-#: aplay/aplay.c:1794
+#: aplay/aplay.c:1958
 #, c-format
 msgid "can't play loops; %s isn't seekable\n"
 msgstr ""
 
-#: aplay/aplay.c:1843
+#: aplay/aplay.c:2007
 #, c-format
 msgid "unknown blocktype %d. terminate."
 msgstr ""
 
-#: aplay/aplay.c:1974
+#: aplay/aplay.c:2138
 #, c-format
 msgid "Wave doesn't support %s format..."
 msgstr ""
 
-#: aplay/aplay.c:2034
+#: aplay/aplay.c:2198
 #, c-format
 msgid "Sparc Audio doesn't support %s format..."
 msgstr ""
 
-#: aplay/aplay.c:2115
+#: aplay/aplay.c:2279
 msgid "Playing"
 msgstr ""
 
-#: aplay/aplay.c:2115
+#: aplay/aplay.c:2279
 msgid "Recording"
 msgstr ""
 
-#: aplay/aplay.c:2119
+#: aplay/aplay.c:2283
 #, c-format
 msgid "Rate %d Hz, "
 msgstr ""
 
-#: aplay/aplay.c:2121
+#: aplay/aplay.c:2285
 #, c-format
 msgid "Mono"
 msgstr ""
 
-#: aplay/aplay.c:2123
+#: aplay/aplay.c:2287
 #, c-format
 msgid "Stereo"
 msgstr ""
 
-#: aplay/aplay.c:2125
+#: aplay/aplay.c:2289
 #, c-format
 msgid "Channels %i"
 msgstr ""
 
-#: aplay/aplay.c:2484 aplay/aplay.c:2537
+#: aplay/aplay.c:2798 aplay/aplay.c:2851
 #, c-format
 msgid "You need to specify %d files"
 msgstr ""
@@ -592,47 +953,47 @@ msgstr ""
 msgid "kernel"
 msgstr ""
 
-#: seq/aconnect/aconnect.c:326
+#: seq/aconnect/aconnect.c:307
 #, c-format
 msgid "can't open sequencer\n"
 msgstr ""
 
-#: seq/aconnect/aconnect.c:354
+#: seq/aconnect/aconnect.c:335
 #, c-format
 msgid "can't get client id\n"
 msgstr ""
 
-#: seq/aconnect/aconnect.c:361
+#: seq/aconnect/aconnect.c:342
 #, c-format
 msgid "can't set client info\n"
 msgstr ""
 
-#: seq/aconnect/aconnect.c:368
+#: seq/aconnect/aconnect.c:349
 #, c-format
 msgid "invalid sender address %s\n"
 msgstr ""
 
-#: seq/aconnect/aconnect.c:373 seq/aseqnet/aseqnet.c:290
+#: seq/aconnect/aconnect.c:354 seq/aseqnet/aseqnet.c:290
 #, c-format
 msgid "invalid destination address %s\n"
 msgstr ""
 
-#: seq/aconnect/aconnect.c:387
+#: seq/aconnect/aconnect.c:368
 #, c-format
 msgid "No subscription is found\n"
 msgstr ""
 
-#: seq/aconnect/aconnect.c:392
+#: seq/aconnect/aconnect.c:373
 #, c-format
 msgid "Disconnection failed (%s)\n"
 msgstr ""
 
-#: seq/aconnect/aconnect.c:398
+#: seq/aconnect/aconnect.c:379
 #, c-format
 msgid "Connection is already subscribed\n"
 msgstr ""
 
-#: seq/aconnect/aconnect.c:403
+#: seq/aconnect/aconnect.c:384
 #, c-format
 msgid "Connection failed (%s)\n"
 msgstr ""
@@ -762,261 +1123,257 @@ msgstr ""
 msgid "disconnected\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:88
+#: speaker-test/speaker-test.c:103
 msgid "Front Left"
 msgstr ""
 
-#: speaker-test/speaker-test.c:89
+#: speaker-test/speaker-test.c:104
 msgid "Front Right"
 msgstr ""
 
-#: speaker-test/speaker-test.c:90
+#: speaker-test/speaker-test.c:105
 msgid "Rear Left"
 msgstr ""
 
-#: speaker-test/speaker-test.c:91
+#: speaker-test/speaker-test.c:106
 msgid "Rear Right"
 msgstr ""
 
-#: speaker-test/speaker-test.c:92
-msgid "Center"
-msgstr ""
-
-#: speaker-test/speaker-test.c:93
+#: speaker-test/speaker-test.c:108
 msgid "LFE"
 msgstr ""
 
-#: speaker-test/speaker-test.c:94
+#: speaker-test/speaker-test.c:109
 msgid "Side Left"
 msgstr ""
 
-#: speaker-test/speaker-test.c:95
+#: speaker-test/speaker-test.c:110
 msgid "Side Right"
 msgstr ""
 
-#: speaker-test/speaker-test.c:96
+#: speaker-test/speaker-test.c:111
 msgid "Channel 9"
 msgstr ""
 
-#: speaker-test/speaker-test.c:97
+#: speaker-test/speaker-test.c:112
 msgid "Channel 10"
 msgstr ""
 
-#: speaker-test/speaker-test.c:98
+#: speaker-test/speaker-test.c:113
 msgid "Channel 11"
 msgstr ""
 
-#: speaker-test/speaker-test.c:99
+#: speaker-test/speaker-test.c:114
 msgid "Channel 12"
 msgstr ""
 
-#: speaker-test/speaker-test.c:100
+#: speaker-test/speaker-test.c:115
 msgid "Channel 13"
 msgstr ""
 
-#: speaker-test/speaker-test.c:101
+#: speaker-test/speaker-test.c:116
 msgid "Channel 14"
 msgstr ""
 
-#: speaker-test/speaker-test.c:102
+#: speaker-test/speaker-test.c:117
 msgid "Channel 15"
 msgstr ""
 
-#: speaker-test/speaker-test.c:103
+#: speaker-test/speaker-test.c:118
 msgid "Channel 16"
 msgstr ""
 
-#: speaker-test/speaker-test.c:340
+#: speaker-test/speaker-test.c:317
 #, c-format
 msgid "Broken configuration for playback: no configurations available: %s\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:347
+#: speaker-test/speaker-test.c:324
 #, c-format
 msgid "Access type not available for playback: %s\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:354
+#: speaker-test/speaker-test.c:331
 #, c-format
 msgid "Sample format not available for playback: %s\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:361
+#: speaker-test/speaker-test.c:338
 #, c-format
 msgid "Channels count (%i) not available for playbacks: %s\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:369
+#: speaker-test/speaker-test.c:346
 #, c-format
 msgid "Rate %iHz not available for playback: %s\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:374
+#: speaker-test/speaker-test.c:351
 #, c-format
 msgid "Rate doesn't match (requested %iHz, get %iHz, err %d)\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:378
+#: speaker-test/speaker-test.c:355
 #, c-format
 msgid "Rate set to %iHz (requested %iHz)\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:384
+#: speaker-test/speaker-test.c:361
 #, c-format
 msgid "Buffer size range from %lu to %lu\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:385
+#: speaker-test/speaker-test.c:362
 #, c-format
 msgid "Period size range from %lu to %lu\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:387
+#: speaker-test/speaker-test.c:364
 #, c-format
 msgid "Requested period time %u us\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:390
+#: speaker-test/speaker-test.c:367
 #, c-format
 msgid "Unable to set period time %u us for playback: %s\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:396
+#: speaker-test/speaker-test.c:373
 #, c-format
 msgid "Requested buffer time %u us\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:399
+#: speaker-test/speaker-test.c:376
 #, c-format
 msgid "Unable to set buffer time %u us for playback: %s\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:408
+#: speaker-test/speaker-test.c:385
 #, c-format
 msgid "Using max buffer size %lu\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:411
+#: speaker-test/speaker-test.c:388
 #, c-format
 msgid "Unable to set buffer size %lu for playback: %s\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:417
+#: speaker-test/speaker-test.c:394
 #, c-format
 msgid "Periods = %u\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:420
+#: speaker-test/speaker-test.c:397
 #, c-format
 msgid "Unable to set nperiods %u for playback: %s\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:429
+#: speaker-test/speaker-test.c:406
 #, c-format
 msgid "Unable to set hw params for playback: %s\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:435
+#: speaker-test/speaker-test.c:412
 #, c-format
 msgid "was set period_size = %lu\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:436
+#: speaker-test/speaker-test.c:413
 #, c-format
 msgid "was set buffer_size = %lu\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:438
+#: speaker-test/speaker-test.c:415
 #, c-format
 msgid "buffer to small, could not use\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:451
+#: speaker-test/speaker-test.c:428
 #, c-format
 msgid "Unable to determine current swparams for playback: %s\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:458
+#: speaker-test/speaker-test.c:435
 #, c-format
 msgid "Unable to set start threshold mode for playback: %s\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:465
+#: speaker-test/speaker-test.c:442
 #, c-format
 msgid "Unable to set avail min for playback: %s\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:472
+#: speaker-test/speaker-test.c:449
 #, c-format
 msgid "Unable to set sw params for playback: %s\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:487
+#: speaker-test/speaker-test.c:464
 #, c-format
 msgid "Can't recovery from underrun, prepare failed: %s\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:498
+#: speaker-test/speaker-test.c:475
 #, c-format
 msgid "Can't recovery from suspend, prepare failed: %s\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:572 speaker-test/speaker-test.c:969
+#: speaker-test/speaker-test.c:539 speaker-test/speaker-test.c:954
 #, c-format
 msgid "No enough memory\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:577
+#: speaker-test/speaker-test.c:544
 #, c-format
 msgid "Cannot open WAV file %s\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:581 speaker-test/speaker-test.c:610
+#: speaker-test/speaker-test.c:548 speaker-test/speaker-test.c:577
 #, c-format
 msgid "Invalid WAV file %s\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:586
+#: speaker-test/speaker-test.c:553
 #, c-format
 msgid "Not a WAV file: %s\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:590
+#: speaker-test/speaker-test.c:557
 #, c-format
 msgid "Unsupported WAV format %d for %s\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:595
+#: speaker-test/speaker-test.c:562
 #, c-format
 msgid "%s is not a mono stream (%d channels)\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:600
+#: speaker-test/speaker-test.c:567
 #, c-format
 msgid "Sample rate doesn't match (%d) for %s\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:605
+#: speaker-test/speaker-test.c:572
 #, c-format
 msgid "Unsupported sample format bits %d for %s\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:655
+#: speaker-test/speaker-test.c:622
 #, c-format
 msgid "Undefined channel %d\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:706
+#: speaker-test/speaker-test.c:673
 #, c-format
 msgid "Write error: %d,%s\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:708
+#: speaker-test/speaker-test.c:675
 #, c-format
 msgid "xrun_recovery failed: %d,%s\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:766
+#: speaker-test/speaker-test.c:734
 #, c-format
 msgid ""
 "Usage: speaker-test [OPTION]... \n"
@@ -1037,72 +1394,72 @@ msgid ""
 "\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:878
+#: speaker-test/speaker-test.c:852
 #, c-format
 msgid "Invalid number of periods %d\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:892 speaker-test/speaker-test.c:896
+#: speaker-test/speaker-test.c:866 speaker-test/speaker-test.c:870
 #, c-format
 msgid "Invalid test type %s\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:908
+#: speaker-test/speaker-test.c:882
 #, c-format
 msgid "Invalid parameter for -s option.\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:919
+#: speaker-test/speaker-test.c:896
 #, c-format
 msgid "Unknown option '%c'\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:933
+#: speaker-test/speaker-test.c:910
 #, c-format
 msgid "Playback device is %s\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:934
+#: speaker-test/speaker-test.c:911
 #, c-format
 msgid "Stream parameters are %iHz, %s, %i channels\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:937
+#: speaker-test/speaker-test.c:914
 #, c-format
 msgid "Using 16 octaves of pink noise\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:940
+#: speaker-test/speaker-test.c:917
 #, c-format
 msgid "Sine wave rate is %.4fHz\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:943
+#: speaker-test/speaker-test.c:920
 #, c-format
 msgid "WAV file(s)\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:949
+#: speaker-test/speaker-test.c:926
 #, c-format
 msgid "Playback open error: %d,%s\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:954
+#: speaker-test/speaker-test.c:931
 #, c-format
 msgid "Setting of hwparams failed: %s\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:959
+#: speaker-test/speaker-test.c:936
 #, c-format
 msgid "Setting of swparams failed: %s\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:1000 speaker-test/speaker-test.c:1022
+#: speaker-test/speaker-test.c:985 speaker-test/speaker-test.c:1007
 #, c-format
 msgid "Transfer failed: %s\n"
 msgstr ""
 
-#: speaker-test/speaker-test.c:1010
+#: speaker-test/speaker-test.c:995
 #, c-format
 msgid "Time per period = %lf\n"
 msgstr ""
diff --git a/po/de.gmo b/po/de.gmo
new file mode 100644 (file)
index 0000000..4c731f5
Binary files /dev/null and b/po/de.gmo differ
diff --git a/po/de.po b/po/de.po
new file mode 100644 (file)
index 0000000..b34a50a
--- /dev/null
+++ b/po/de.po
@@ -0,0 +1,1542 @@
+# German translations for the alsa-utils package.
+# Copyright (C) 2009 The ALSA Team
+# This file is distributed under the same license as the alsa-utils package.
+# Clemens Ladisch <clemens@ladisch.de>, 2009.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: alsa-utils 1.0.20\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-04-16 13:19+0200\n"
+"PO-Revision-Date: 2009-05-24 12:34+0200\n"
+"Last-Translator: Clemens Ladisch <clemens@ladisch.de>\n"
+"Language-Team: German\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: alsamixer/card_select.c:126 alsamixer/device_name.c:126
+msgid "Sound Card"
+msgstr "Soundkarte"
+
+#: alsamixer/card_select.c:181
+msgid "(default)"
+msgstr "(Standard)"
+
+#: alsamixer/card_select.c:191
+msgid "cannot enumerate sound cards"
+msgstr "Fehler beim Aufzählen der Soundkarten"
+
+#: alsamixer/card_select.c:215
+msgid "enter device name..."
+msgstr "Gerätenamen eingeben..."
+
+#: alsamixer/cli.c:40
+msgid "Usage: alsamixer [options]"
+msgstr "Verwendung: alsamixer [Optionen]"
+
+#: alsamixer/cli.c:41
+msgid ""
+"Useful options:\n"
+"  -h, --help              this help\n"
+"  -c, --card=NUMBER       sound card number or id\n"
+"  -D, --device=NAME       mixer device name\n"
+"  -V, --view=MODE         starting view mode: playback/capture/all"
+msgstr ""
+"Optionen:\n"
+"  -h, --help              Hilfe\n"
+"  -c, --card=NUMMER       Soundkarten-Nummer oder -ID\n"
+"  -D, --device=NAME       Mixer-Gerätename\n"
+"  -V, --view=MODUS        Ansicht beim Starten: playback=Wiedergabe, "
+"capture=Aufnahme, all=alle"
+
+#: alsamixer/cli.c:46
+msgid ""
+"Debugging options:\n"
+"  -g, --no-color          toggle using of colors\n"
+"  -a, --abstraction=NAME  mixer abstraction level: none/basic"
+msgstr ""
+"Debugging-Optionen:\n"
+"  -g, --no-color          keine Farben\n"
+"  -a, --abstraction=NAME  Mixer-Abstraktion: none/basic"
+
+#: alsamixer/cli.c:77
+#, c-format
+msgid "invalid card index: %s\n"
+msgstr "ungültige Karten-Nummer: %s\n"
+
+#: alsamixer/cli.c:103
+#, c-format
+msgid "unknown abstraction level: %s\n"
+msgstr "unbekannte Abstraktion: %s\n"
+
+#: alsamixer/cli.c:108
+#, c-format
+msgid "unknown option: %c\n"
+msgstr "unbekannte Option: %c\n"
+
+#: alsamixer/cli.c:110
+msgid "try `alsamixer --help' for more information\n"
+msgstr "siehe `alsamixer --help' für mehr Informationen\n"
+
+#: alsamixer/device_name.c:177
+msgid "Device name:"
+msgstr "Gerätename:"
+
+#: alsamixer/die.c:37
+#, c-format
+msgid "%s: %s\n"
+msgstr "%s: %s\n"
+
+#: alsamixer/mixer_display.c:95
+msgid "Card:"
+msgstr "Gerät:"
+
+#: alsamixer/mixer_display.c:96
+msgid "Chip:"
+msgstr "Chip:"
+
+#: alsamixer/mixer_display.c:97
+msgid "View:"
+msgstr "Ansicht:"
+
+#: alsamixer/mixer_display.c:98
+msgid "Item:"
+msgstr "Element:"
+
+#: alsamixer/mixer_display.c:101
+msgid "F1:  Help"
+msgstr "F1:  Hilfe"
+
+#: alsamixer/mixer_display.c:102
+msgid "F2:  System information"
+msgstr "F2:  System-Informationen"
+
+#: alsamixer/mixer_display.c:103
+msgid "F6:  Select sound card"
+msgstr "F6:  Soundkarte auswählen"
+
+#: alsamixer/mixer_display.c:104
+msgid "Esc: Exit"
+msgstr "Esc: Beenden"
+
+#: alsamixer/mixer_display.c:171
+msgid "(unplugged)"
+msgstr "(entfernt)"
+
+#: alsamixer/mixer_display.c:189
+msgid "Playback"
+msgstr "Wiedergabe"
+
+#: alsamixer/mixer_display.c:190
+msgid "Capture"
+msgstr "Aufnahme"
+
+#: alsamixer/mixer_display.c:191
+msgid "All"
+msgstr "Alle"
+
+#: alsamixer/mixer_display.c:231
+msgid "mute"
+msgstr "stumm"
+
+#: alsamixer/mixer_display.c:272 alsamixer/mixer_display.c:282
+msgid "dB gain:"
+msgstr "dB-Änderung:"
+
+#: alsamixer/mixer_display.c:282
+#, c-format
+msgid " [%s %s, %s]"
+msgstr " [%s %s; %s]"
+
+#: alsamixer/mixer_display.c:291 alsamixer/mixer_display.c:297
+#: alsamixer/mixer_display.c:303 alsamixer/mixer_display.c:309
+msgid "Off"
+msgstr "Aus"
+
+#: alsamixer/mixer_display.c:297 alsamixer/mixer_display.c:309
+msgid "On"
+msgstr "An"
+
+#: alsamixer/mixer_display.c:360
+msgid "The sound device was unplugged."
+msgstr "Das Gerät wurde entfernt."
+
+#: alsamixer/mixer_display.c:361
+msgid "Press F6 to select another sound card."
+msgstr "Drücken Sie F6, um eine andere Soundkarte auszuwählen."
+
+#: alsamixer/mixer_display.c:376
+msgid "This sound device does not have any playback controls."
+msgstr "Dieses Gerät hat keine Wiedergabe-Regler."
+
+#: alsamixer/mixer_display.c:378
+msgid "This sound device does not have any capture controls."
+msgstr "Dieses Gerät hat keine Aufnahme-Regler."
+
+#: alsamixer/mixer_display.c:380
+msgid "This sound device does not have any controls."
+msgstr "Dieses Gerät hat keine Regler."
+
+#. TRANSLATORS: playback on; one character
+#: alsamixer/mixer_display.c:537 alsamixer/mixer_display.c:542
+msgid "O"
+msgstr "O"
+
+#. TRANSLATORS: playback muted; one character
+#: alsamixer/mixer_display.c:539 alsamixer/mixer_display.c:543
+msgid "M"
+msgstr "M"
+
+#. TRANSLATORS: "left"; no more than two characters
+#: alsamixer/mixer_display.c:557
+msgid "L"
+msgstr "L"
+
+#. TRANSLATORS: "right"; no more than two characters
+#: alsamixer/mixer_display.c:561
+msgid "R"
+msgstr "R"
+
+#. TRANSLATORS: no more than eight characters
+#: alsamixer/mixer_display.c:563
+msgid "CAPTURE"
+msgstr "AUFNAHME"
+
+#: alsamixer/mixer_display.c:613
+msgid "Front"
+msgstr "Vorne"
+
+#: alsamixer/mixer_display.c:616
+msgid "Rear"
+msgstr "Hinten"
+
+#: alsamixer/mixer_display.c:619 speaker-test/speaker-test.c:107
+msgid "Center"
+msgstr "Mitte"
+
+#: alsamixer/mixer_display.c:622
+msgid "Woofer"
+msgstr "Bass"
+
+#: alsamixer/mixer_display.c:625
+msgid "Side"
+msgstr "Seiten"
+
+#: alsamixer/mixer_widget.c:83 alsamixer/mixer_widget.c:88
+msgid "cannot open mixer"
+msgstr "Fehler beim Öffen des Mixer-Gerätes"
+
+#: alsamixer/mixer_widget.c:94 alsamixer/mixer_widget.c:171
+msgid "cannot load mixer controls"
+msgstr "Fehler beim Laden der Mixer-Regler"
+
+#: alsamixer/mixer_widget.c:161
+#, c-format
+msgid "Cannot open mixer device '%s'."
+msgstr "Fehler beim Öffnen des Mixer-Gerätes '%s'."
+
+#: alsamixer/mixer_widget.c:182
+msgid "Esc     Exit"
+msgstr "Esc     Beenden"
+
+#: alsamixer/mixer_widget.c:183
+msgid "F1 ? H  Help"
+msgstr "F1 ? H  Hilfe"
+
+#: alsamixer/mixer_widget.c:184
+msgid "F2 /    System information"
+msgstr "F2 /    System-Informationen"
+
+#: alsamixer/mixer_widget.c:185
+msgid "F3      Show playback controls"
+msgstr "F3      Ansicht Wiedergabe-Regler"
+
+#: alsamixer/mixer_widget.c:186
+msgid "F4      Show capture controls"
+msgstr "F4      Ansicht Aufnahme-Regler"
+
+#: alsamixer/mixer_widget.c:187
+msgid "F5      Show all controls"
+msgstr "F5      Ansicht alle Regler"
+
+#: alsamixer/mixer_widget.c:188
+msgid "Tab     Toggle view mode (F3/F4/F5)"
+msgstr "Tab     Ansichts-Modus umschalten (F3/F4/F5)"
+
+#: alsamixer/mixer_widget.c:189
+msgid "F6 S    Select sound card"
+msgstr "F6 S    Soundkarte auswählen"
+
+#: alsamixer/mixer_widget.c:190
+msgid "L       Redraw screen"
+msgstr "L       Bildschirm neu darstellen"
+
+#: alsamixer/mixer_widget.c:192
+msgid "Left    Move to the previous control"
+msgstr "Links   gehe zum vorherigen Regler"
+
+#: alsamixer/mixer_widget.c:193
+msgid "Right   Move to the next control"
+msgstr "Rechts  gehe zum nächsten Regler"
+
+#: alsamixer/mixer_widget.c:195
+msgid "Up/Down    Change volume"
+msgstr "Oben/Unten  Lautstärke ändern"
+
+#: alsamixer/mixer_widget.c:196
+msgid "+ -        Change volume"
+msgstr "+ -         Lautstärke ändern"
+
+#: alsamixer/mixer_widget.c:197
+msgid "Page Up/Dn Change volume in big steps"
+msgstr "Bild ^/v    Lautstärke in großen Schritten ändern"
+
+#: alsamixer/mixer_widget.c:198
+msgid "End        Set volume to 0%"
+msgstr "Ende        Lautstärke auf 0% setzen"
+
+#: alsamixer/mixer_widget.c:199
+msgid "0-9        Set volume to 0%-90%"
+msgstr "0-9         Lautstärke auf 0%-90% setzen"
+
+#: alsamixer/mixer_widget.c:200
+msgid "Q W E      Increase left/both/right volumes"
+msgstr "Q W E       linke/beide/rechte Lautstärke erhöhen"
+
+#. TRANSLATORS: or Y instead of Z
+#: alsamixer/mixer_widget.c:202
+msgid "Z X C      Decrease left/both/right volumes"
+msgstr "Y X C       linke/beide/rechte Lautstärke verringern"
+
+#: alsamixer/mixer_widget.c:203
+msgid "B          Balance left and right volumes"
+msgstr "B           linke und rechte Lautstärke angleichen"
+
+#: alsamixer/mixer_widget.c:205
+msgid "M          Toggle mute"
+msgstr "M           stumm umschalten"
+
+#. TRANSLATORS: or , .
+#: alsamixer/mixer_widget.c:207
+msgid "< >        Toggle left/right mute"
+msgstr ", .         stumm links/rechts umschalten"
+
+#: alsamixer/mixer_widget.c:209
+msgid "Space      Toggle capture"
+msgstr "Leertaste   Aufnahme umschalten"
+
+#. TRANSLATORS: or Insert Delete
+#: alsamixer/mixer_widget.c:211
+msgid "; '        Toggle left/right capture"
+msgstr "Einfg Entf  Aufnahme links/rechts umschalten"
+
+#: alsamixer/mixer_widget.c:213
+msgid "Authors:"
+msgstr "Autoren:"
+
+#: alsamixer/mixer_widget.c:214
+msgid "  Tim Janik <timj@gtk.org>"
+msgstr "  Tim Janik <tim@gtk.org>"
+
+#: alsamixer/mixer_widget.c:215
+msgid "  Jaroslav Kysela <perex@perex.cz>"
+msgstr "  Jaroslav Kysela <perex@perex.cz>"
+
+#: alsamixer/mixer_widget.c:216
+msgid "  Clemens Ladisch <clemens@ladisch.de>"
+msgstr "  Clemens Ladisch <clemens@ladisch.de>"
+
+#: alsamixer/mixer_widget.c:218
+msgid "Help"
+msgstr "Hilfe"
+
+#: alsamixer/proc_files.c:103
+msgid "Select File"
+msgstr "Datei wählen"
+
+#: alsamixer/textbox.c:52 alsamixer/textbox.c:66
+msgid "Error"
+msgstr "Fehler"
+
+#: alsamixer/textbox.c:80
+#, c-format
+msgid "Cannot open file \"%s\"."
+msgstr "Fehler beim Öffnen der Datei \"%s\"."
+
+#: aplay/aplay.c:147
+msgid "raw data"
+msgstr "Rohdaten"
+
+#: aplay/aplay.c:148
+msgid "VOC"
+msgstr "VOC"
+
+#: aplay/aplay.c:150
+msgid "WAVE"
+msgstr "WAVE"
+
+#: aplay/aplay.c:151
+msgid "Sparc Audio"
+msgstr "Sparc-Audio"
+
+#: aplay/aplay.c:172
+#, fuzzy, c-format
+msgid ""
+"Usage: %s [OPTION]... [FILE]...\n"
+"\n"
+"-h, --help              help\n"
+"    --version           print current version\n"
+"-l, --list-devices      list all soundcards and digital audio devices\n"
+"-L, --list-pcms         list device names\n"
+"-D, --device=NAME       select PCM by name\n"
+"-q, --quiet             quiet mode\n"
+"-t, --file-type TYPE    file type (voc, wav, raw or au)\n"
+"-c, --channels=#        channels\n"
+"-f, --format=FORMAT     sample format (case insensitive)\n"
+"-r, --rate=#            sample rate\n"
+"-d, --duration=#        interrupt after # seconds\n"
+"-M, --mmap              mmap stream\n"
+"-N, --nonblock          nonblocking mode\n"
+"-F, --period-time=#     distance between interrupts is # microseconds\n"
+"-B, --buffer-time=#     buffer duration is # microseconds\n"
+"    --period-size=#     distance between interrupts is # frames\n"
+"    --buffer-size=#     buffer duration is # frames\n"
+"-A, --avail-min=#       min available space for wakeup is # microseconds\n"
+"-R, --start-delay=#     delay for automatic PCM start is # microseconds \n"
+"                        (relative to buffer size if <= 0)\n"
+"-T, --stop-delay=#      delay for automatic PCM stop is # microseconds from "
+"xrun\n"
+"-v, --verbose           show PCM structure and setup (accumulative)\n"
+"-V, --vumeter=TYPE      enable VU meter (TYPE: mono or stereo)\n"
+"-I, --separate-channels one file for each channel\n"
+"    --disable-resample  disable automatic rate resample\n"
+"    --disable-channels  disable automatic channel conversions\n"
+"    --disable-format    disable automatic format conversions\n"
+"    --disable-softvol   disable software volume control (softvol)\n"
+"    --test-position     test ring buffer position\n"
+"    --test-coef=#\t test coeficient for ring buffer position (default 8)\n"
+"                        expression for validation is: coef * (buffer_size / "
+"2)\n"
+"    --test-nowait       do not wait for ring buffer - eats whole CPU\n"
+"    --max-file-time=#   start another output file when the old file has "
+"recorded\n"
+"                        for this many seconds\n"
+"    --process-id-file   write the process ID here\n"
+"    --use-strftime      apply the strftime facility to the output file name\n"
+msgstr ""
+"Verwendung: %s [Option]... [Datei]...\n"
+"\n"
+"-h, --help              Hilfe\n"
+"    --version           Version anzeigen\n"
+"-l, --list-devices      alle Soundkarten und -Geräte auflisten\n"
+"-L, --list-pcms         ALSA-Gerätenamen auflisten\n"
+"-D, --device=NAME       PCM-Gerät wählen\n"
+"-q, --quiet             weniger Programmausgaben\n"
+"-t, --file-type TYP     Dateityp (voc, wav, raw oder au)\n"
+"-c, --channels=#        Kanäle\n"
+"-f, --format=FORMAT     Sample-Format\n"
+"-r, --rate=#            Sample-Rate\n"
+"-d, --duration=#        Beenden nach # Sekunden\n"
+"-M, --mmap              mmap-Modus\n"
+"-N, --nonblock          nonblocking-Modus\n"
+"-F, --period-time=#     Abstand zwischen Interrupts ist # µs\n"
+"-B, --buffer-time=#     Puffer-Länge ist # µs\n"
+"    --period-size=#     Abstand zwischen Interrupts ist # Frames\n"
+"    --buffer-size=#     Puffer-Länge ist # Frames\n"
+"-A, --avail-min=#       freier Pufferspeicher für Wakeup ist # µs\n"
+"-R, --start-delay=#     Puffer-Füllgrad zum automatischen PCM-Start, in µs\n"
+"                        (wenn <= 0, freier Puffer-Speicher)\n"
+"-T, --stop-delay=#      Zeit vor xrun zum automatischen PCM-Stop, in µs\n"
+"-v, --verbose           zeige PCM-Struktur und -Konfiguration (akkumulativ)\n"
+"-V, --vumeter=TYP       VU-Anzeige (TYP: mono oder stereo)\n"
+"-I, --separate-channels eine Datei pro Kanal\n"
+"    --disable-resample  keine automatische Sample-Rate-Anpassung\n"
+"    --disable-channels  keine automatische Kanal-Anzahl-Anpassung\n"
+"    --disable-format    keine automatische Format-Anpassung\n"
+"    --disable-softvol   kein Software-Lautstärke-Regler (softvol)\n"
+"    --test-position     überprüfe Position im Ring-Puffer\n"
+"    --test-coef=#       Test-Koeffizient für Positionsprüfung (Standard 8)\n"
+"                        Formel für Prüfung ist: Koeffizient * (Puffergröße / "
+"2)\n"
+"    --test-nowait       kein Warten auf Ringpuffer; beansprucht volle CPU-"
+"Leistung\n"
+
+#: aplay/aplay.c:211 speaker-test/speaker-test.c:750
+#, c-format
+msgid "Recognized sample formats are:"
+msgstr "Unterstützte Sample-Formate:"
+
+#: aplay/aplay.c:217
+#, c-format
+msgid ""
+"\n"
+"Some of these may not be available on selected hardware\n"
+msgstr ""
+"\n"
+"Nicht alle davon sind auf jeder Hardware verfügbar.\n"
+
+#: aplay/aplay.c:218
+#, c-format
+msgid "The availabled format shortcuts are:\n"
+msgstr "Unterstütze Format-Abkürzungen:\n"
+
+#: aplay/aplay.c:219
+#, c-format
+msgid "-f cd (16 bit little endian, 44100, stereo)\n"
+msgstr "-f cd (16 Bits, Little Endian, 44100 Hz, stereo)\n"
+
+#: aplay/aplay.c:220
+#, c-format
+msgid "-f cdr (16 bit big endian, 44100, stereo)\n"
+msgstr "-f cdr (16 Bits, Big Endian, 44100 Hz, stereo)\n"
+
+#: aplay/aplay.c:221
+#, c-format
+msgid "-f dat (16 bit little endian, 48000, stereo)\n"
+msgstr "-f dat (16 Bits, Little Endian, 48000 Hz, stereo)\n"
+
+#: aplay/aplay.c:235
+msgid "no soundcards found..."
+msgstr "keine Soundkarten gefunden ..."
+
+#: aplay/aplay.c:238
+#, c-format
+msgid "**** List of %s Hardware Devices ****\n"
+msgstr "**** Liste der Hardware-Geräte (%s) ****\n"
+
+#: aplay/aplay.c:267
+#, c-format
+msgid "card %i: %s [%s], device %i: %s [%s]\n"
+msgstr "Karte %i: %s [%s], Gerät %i: %s [%s]\n"
+
+#: aplay/aplay.c:273
+#, c-format
+msgid "  Subdevices: %i/%i\n"
+msgstr "  Sub-Geräte: %i/%i\n"
+
+#: aplay/aplay.c:280
+#, c-format
+msgid "  Subdevice #%i: %s\n"
+msgstr "  Sub-Gerät #%i: %s\n"
+
+#: aplay/aplay.c:356
+#, c-format
+msgid "Aborted by signal %s...\n"
+msgstr "Abbruch durch Signal %s ...\n"
+
+#: aplay/aplay.c:467
+msgid "command should be named either arecord or aplay"
+msgstr "Befehl sollte arecord oder aplay sein"
+
+#: aplay/aplay.c:506
+#, c-format
+msgid "unrecognized file format %s"
+msgstr "unbekanntes Dateiformat %s"
+
+#: aplay/aplay.c:513
+#, c-format
+msgid "value %i for channels is invalid"
+msgstr "Kanalanzahl %i ist ungültig"
+
+#: aplay/aplay.c:532
+#, c-format
+msgid "wrong extended format '%s'"
+msgstr "erweitertes Format '%s' ist ungültig"
+
+#: aplay/aplay.c:543
+#, c-format
+msgid "bad speed value %i"
+msgstr "ungültige Rate %i"
+
+#: aplay/aplay.c:638
+#, c-format
+msgid "Try `%s --help' for more information.\n"
+msgstr "Siehe `%s --help' für mehr Informationen.\n"
+
+#: aplay/aplay.c:654
+#, c-format
+msgid "audio open error: %s"
+msgstr "Fehler beim Öffnen des Gerätes: %s"
+
+#: aplay/aplay.c:659
+#, c-format
+msgid "info error: %s"
+msgstr "Fehler beim Lesen der Geräteinformationen: %s"
+
+#: aplay/aplay.c:666
+#, c-format
+msgid "nonblock setting error: %s"
+msgstr "Fehler beim Setzen des nonblock-Modus: %s"
+
+#: aplay/aplay.c:676 aplay/aplay.c:800 aplay/aplay.c:1167
+msgid "not enough memory"
+msgstr "nicht genug Speicher"
+
+#: aplay/aplay.c:700
+#, fuzzy, c-format
+msgid "Cannot create process ID file %s: %s"
+msgstr "Kann WAV-Datei %s nicht öffnen\n"
+
+#: aplay/aplay.c:790
+#, c-format
+msgid "read error (called from line %i)"
+msgstr "Lesefehler (aufgerufen von Zeile %i)"
+
+#: aplay/aplay.c:848
+#, c-format
+msgid "unknown length of 'fmt ' chunk (read %u, should be %u at least)"
+msgstr ""
+"unbekannte Länge des 'fmt '-Blocks (gelesen: %u, sollte mindestens %u sein)"
+
+#: aplay/aplay.c:858
+#, c-format
+msgid ""
+"unknown length of extensible 'fmt ' chunk (read %u, should be %u at least)"
+msgstr ""
+"unbekannte Länge des erweiterten 'fmt '-Blocks (gelesen: %u, sollte "
+"mindestens %u sein)"
+
+#: aplay/aplay.c:863
+msgid "wrong format tag in extensible 'fmt ' chunk"
+msgstr "ungültiger Format-Wert im erweiterten 'fmt '-Block"
+
+#: aplay/aplay.c:870
+#, c-format
+msgid "can't play WAVE-file format 0x%04x which is not PCM or FLOAT encoded"
+msgstr ""
+"kann WAVE-Datei-Format 0x%04x nicht abspielen; ist weder PCM noch FLOAT"
+
+#: aplay/aplay.c:874
+#, c-format
+msgid "can't play WAVE-files with %d tracks"
+msgstr "kann WAVE-Datei mit %d Kanälen nicht abspielen"
+
+#: aplay/aplay.c:882 aplay/aplay.c:982
+#, c-format
+msgid "Warning: format is changed to U8\n"
+msgstr "Warnung: benutztes Format ist U8\n"
+
+#: aplay/aplay.c:888
+#, c-format
+msgid "Warning: format is changed to S16_LE\n"
+msgstr "Warnung: benutztes Format ist S16_LE\n"
+
+#: aplay/aplay.c:896
+#, c-format
+msgid "Warning: format is changed to S24_3LE\n"
+msgstr "Warnung: benutztes Format ist S24_3LE\n"
+
+#: aplay/aplay.c:902
+#, c-format
+msgid "Warning: format is changed to S24_LE\n"
+msgstr "Warnung: benutztes Format ist S24_LE\n"
+
+#: aplay/aplay.c:906
+#, c-format
+msgid ""
+" can't play WAVE-files with sample %d bits in %d bytes wide (%d channels)"
+msgstr ""
+"kann WAVE-Datei mit %d-Bit-Samples in %d Bytes (%d Kanäle) nicht abspielen"
+
+#: aplay/aplay.c:918
+#, c-format
+msgid " can't play WAVE-files with sample %d bits wide"
+msgstr "kann WAVE-Datei mit %d-Bit-Samples nicht abspielen"
+
+#: aplay/aplay.c:976
+#, c-format
+msgid "Warning: format is changed to MU_LAW\n"
+msgstr "Warnung: benutztes Format ist MU_LAW\n"
+
+#: aplay/aplay.c:988
+#, c-format
+msgid "Warning: format is changed to S16_BE\n"
+msgstr "Warnung: benutztes Format ist S16_BE\n"
+
+#: aplay/aplay.c:1001 aplay/aplay.c:1843 aplay/aplay.c:1850 aplay/aplay.c:2372
+#: aplay/aplay.c:2384
+msgid "read error"
+msgstr "Lesefehler"
+
+#: aplay/aplay.c:1031
+msgid "Broken configuration for this PCM: no configurations available"
+msgstr ""
+"ungültige Konfiguration für dieses Gerät: keine unterstützte Konfiguration"
+
+#: aplay/aplay.c:1048
+msgid "Access type not available"
+msgstr "Zugriffs-Modus nicht unterstützt"
+
+#: aplay/aplay.c:1053
+msgid "Sample format non available"
+msgstr "Sample-Format nicht unterstützt"
+
+#: aplay/aplay.c:1059
+msgid "Channels count non available"
+msgstr "Kanalanzahl nicht unterstützt"
+
+#: aplay/aplay.c:1074
+#, c-format
+msgid "Warning: rate is not accurate (requested = %iHz, got = %iHz)\n"
+msgstr ""
+"Warnung: Rate ist nicht exakt (angefordert: %i Hz, unterstützt: %i Hz)\n"
+
+#: aplay/aplay.c:1080
+#, c-format
+msgid "         please, try the plug plugin %s\n"
+msgstr "         probieren Sie bitte das plug-Plugin: %s\n"
+
+#: aplay/aplay.c:1116
+msgid "Unable to install hw params:"
+msgstr "Fehler beim Setzen der Hardware-Parameter:"
+
+#: aplay/aplay.c:1123
+#, c-format
+msgid "Can't use period equal to buffer size (%lu == %lu)"
+msgstr "Periode gleich der Puffer-Größe wird nicht unterstützt (%lu == %lu)"
+
+#: aplay/aplay.c:1154
+msgid "unable to install sw params:"
+msgstr "Fehler beim Setzen der Software-Parameter:"
+
+#: aplay/aplay.c:1229
+#, c-format
+msgid "status error: %s"
+msgstr "Status-Fehler: %s"
+
+#: aplay/aplay.c:1239 aplay/aplay.c:1250
+#, c-format
+msgid "%s!!! (at least %.3f ms long)\n"
+msgstr "%s!!! (mindestens %.3f ms)\n"
+
+#: aplay/aplay.c:1240 aplay/aplay.c:1243 aplay/aplay.c:1251
+msgid "underrun"
+msgstr "Unterlauf"
+
+#: aplay/aplay.c:1240 aplay/aplay.c:1251
+msgid "overrun"
+msgstr "Überlauf"
+
+#: aplay/aplay.c:1255
+#, c-format
+msgid "Status:\n"
+msgstr "Status:\n"
+
+#: aplay/aplay.c:1259
+#, c-format
+msgid "xrun: prepare error: %s"
+msgstr "Unter-/Überlauf: Fehler beim Re-Initialisieren des Gerätes: %s"
+
+#: aplay/aplay.c:1265
+#, c-format
+msgid "Status(DRAINING):\n"
+msgstr "Status (DRAINING):\n"
+
+#: aplay/aplay.c:1269
+#, c-format
+msgid "capture stream format change? attempting recover...\n"
+msgstr "Format-Wechsel der Aufnahme-Daten? Versuche Wiederherstellung ...\n"
+
+#: aplay/aplay.c:1271
+#, c-format
+msgid "xrun(DRAINING): prepare error: %s"
+msgstr "XRUN (DRAINING): Fehler beim Re-Initialisieren des Gerätes: %s"
+
+#: aplay/aplay.c:1278
+#, c-format
+msgid "Status(R/W):\n"
+msgstr "Status (R/W):\n"
+
+#: aplay/aplay.c:1281
+#, c-format
+msgid "read/write error, state = %s"
+msgstr "Lese-/Schreibfehler, Status = %s"
+
+#: aplay/aplay.c:1291
+#, c-format
+msgid "Suspended. Trying resume. "
+msgstr "Ruhezustand. Versuche, aufzuwecken. "
+
+#: aplay/aplay.c:1296
+#, c-format
+msgid "Failed. Restarting stream. "
+msgstr "Fehlgeschlagen. Re-Initialisierung. "
+
+#: aplay/aplay.c:1298
+#, c-format
+msgid "suspend: prepare error: %s"
+msgstr "Ruhezustand: Fehler beim Re-Initialisieren: %s"
+
+#: aplay/aplay.c:1303
+#, c-format
+msgid "Done.\n"
+msgstr "Fertig.\n"
+
+#: aplay/aplay.c:1325
+#, c-format
+msgid " !clip  "
+msgstr " !clip  "
+
+#: aplay/aplay.c:1472
+#, c-format
+msgid "Unsupported bit size %d.\n"
+msgstr "%d-Bit-Samples werden nicht unterstützt.\n"
+
+#: aplay/aplay.c:1506
+#, c-format
+msgid "Max peak (%li samples): 0x%08x "
+msgstr "Höchstwert (%li Samples): 0x%08x "
+
+#: aplay/aplay.c:1540
+#, c-format
+msgid ""
+"Suspicious buffer position (%li total): avail = %li, delay = %li, buffer = %"
+"li\n"
+msgstr ""
+"verdächtige Puffer-Position (total %li): avail = %li, delay = %li, buffer = %"
+"li\n"
+
+#: aplay/aplay.c:1603
+#, c-format
+msgid "write error: %s"
+msgstr "Schreibfehler: %s"
+
+#: aplay/aplay.c:1649
+#, c-format
+msgid "writev error: %s"
+msgstr "Vektor-Schreib-Fehler: %s"
+
+#: aplay/aplay.c:1692
+#, c-format
+msgid "read error: %s"
+msgstr "Lesefehler: %s"
+
+#: aplay/aplay.c:1735
+#, c-format
+msgid "readv error: %s"
+msgstr "Vektor-Lese-Fehler: %s"
+
+#: aplay/aplay.c:1783
+msgid "can't allocate buffer for silence"
+msgstr "nicht genug Speicher für Stille-Block"
+
+#: aplay/aplay.c:1792 aplay/aplay.c:2018 aplay/aplay.c:2023 aplay/aplay.c:2070
+#: aplay/aplay.c:2079 aplay/aplay.c:2086 aplay/aplay.c:2096 aplay/aplay.c:2102
+#: aplay/aplay.c:2174 aplay/aplay.c:2204 aplay/aplay.c:2218
+msgid "write error"
+msgstr "Schreibfehler"
+
+#: aplay/aplay.c:1805
+#, c-format
+msgid "voc_pcm_flush - silence error"
+msgstr "voc_pcm_flush - Fehler in set_silence"
+
+#: aplay/aplay.c:1808
+msgid "voc_pcm_flush error"
+msgstr "Schreibfehler"
+
+#: aplay/aplay.c:1834
+msgid "malloc error"
+msgstr "nicht genug Speicher"
+
+#: aplay/aplay.c:1838
+#, c-format
+msgid "Playing Creative Labs Channel file '%s'...\n"
+msgstr "Spiele Creative Labs Channel-Datei '%s'...\n"
+
+#: aplay/aplay.c:1906 aplay/aplay.c:1998
+msgid "can't play packed .voc files"
+msgstr "kann komprimierte .voc-Dateien nicht abspielen"
+
+#: aplay/aplay.c:1958
+#, c-format
+msgid "can't play loops; %s isn't seekable\n"
+msgstr ""
+"kann Schleife nicht abspielen; Dateiposition in %s ist nicht änderbar\n"
+
+#: aplay/aplay.c:2007
+#, c-format
+msgid "unknown blocktype %d. terminate."
+msgstr "Unbekannter Block-Typ %d. Abbruch."
+
+#: aplay/aplay.c:2138
+#, c-format
+msgid "Wave doesn't support %s format..."
+msgstr "Format %s wird in WAVE nicht unterstützt ..."
+
+#: aplay/aplay.c:2198
+#, c-format
+msgid "Sparc Audio doesn't support %s format..."
+msgstr "Format %s wird in Sparc-Audio nicht unterstützt ..."
+
+#: aplay/aplay.c:2279
+msgid "Playing"
+msgstr "Wiedergabe:"
+
+#: aplay/aplay.c:2279
+msgid "Recording"
+msgstr "Aufnahme:"
+
+#: aplay/aplay.c:2283
+#, c-format
+msgid "Rate %d Hz, "
+msgstr "Rate: %d Hz, "
+
+#: aplay/aplay.c:2285
+#, c-format
+msgid "Mono"
+msgstr "mono"
+
+#: aplay/aplay.c:2287
+#, c-format
+msgid "Stereo"
+msgstr "stereo"
+
+#: aplay/aplay.c:2289
+#, c-format
+msgid "Channels %i"
+msgstr "%i Kanäle"
+
+#: aplay/aplay.c:2798 aplay/aplay.c:2851
+#, c-format
+msgid "You need to specify %d files"
+msgstr "Es werden %d Dateien benötigt."
+
+#: seq/aconnect/aconnect.c:49
+#, c-format
+msgid "aconnect - ALSA sequencer connection manager\n"
+msgstr "aconnect - ALSA Sequenzer Verbindungs-Manager\n"
+
+#: seq/aconnect/aconnect.c:50
+#, c-format
+msgid "Copyright (C) 1999-2000 Takashi Iwai\n"
+msgstr "Copyright © 1999-2000 Takashi Iwai\n"
+
+#: seq/aconnect/aconnect.c:51
+#, c-format
+msgid "Usage:\n"
+msgstr "Verwendung:\n"
+
+#: seq/aconnect/aconnect.c:52
+#, c-format
+msgid " * Connection/disconnection between two ports\n"
+msgstr " * Verbindung zwischen zwei Ports herstellen/trennen\n"
+
+#: seq/aconnect/aconnect.c:53
+#, c-format
+msgid "   aconnect [-options] sender receiver\n"
+msgstr "   aconnect [Optionen] Sender Empfänger\n"
+
+#: seq/aconnect/aconnect.c:54
+#, c-format
+msgid "     sender, receiver = client:port pair\n"
+msgstr "     Sender, Empfänger = Client:Port\n"
+
+#: seq/aconnect/aconnect.c:55
+#, c-format
+msgid "     -d,--disconnect     disconnect\n"
+msgstr "     -d,--disconnect     Verbindung trennen\n"
+
+#: seq/aconnect/aconnect.c:56
+#, c-format
+msgid "     -e,--exclusive      exclusive connection\n"
+msgstr "     -e,--exclusive      exklusive Verbindung\n"
+
+#: seq/aconnect/aconnect.c:57
+#, c-format
+msgid "     -r,--real #         convert real-time-stamp on queue\n"
+msgstr "     -r,--real #         benutze Zeitstempel der Queue #\n"
+
+#: seq/aconnect/aconnect.c:58
+#, c-format
+msgid "     -t,--tick #         convert tick-time-stamp on queue\n"
+msgstr "     -t,--tick #         benutze Tick-Zeitstempel der Queue #\n"
+
+#: seq/aconnect/aconnect.c:59
+#, c-format
+msgid " * List connected ports (no subscription action)\n"
+msgstr " * Ports und Verbindungen auflisten\n"
+
+#: seq/aconnect/aconnect.c:60
+#, c-format
+msgid "   aconnect -i|-o [-options]\n"
+msgstr "   aconnect -i|-o [Optionen]\n"
+
+#: seq/aconnect/aconnect.c:61
+#, c-format
+msgid "     -i,--input          list input (readable) ports\n"
+msgstr "     -i,--input          Eingabe-Ports (lesbar) auflisten\n"
+
+#: seq/aconnect/aconnect.c:62
+#, c-format
+msgid "     -o,--output         list output (writable) ports\n"
+msgstr "     -o,--output         Ausgabe-Ports (schreibbar) auflisten\n"
+
+#: seq/aconnect/aconnect.c:63
+#, c-format
+msgid "     -l,--list           list current connections of each port\n"
+msgstr "     -l,--list           Verbindungen der Ports auflisten\n"
+
+#: seq/aconnect/aconnect.c:64
+#, c-format
+msgid " * Remove all exported connections\n"
+msgstr " * alle Verbindungen trennen\n"
+
+#: seq/aconnect/aconnect.c:65
+#, c-format
+msgid "     -x, --removeall\n"
+msgstr "     -x,--removeall\n"
+
+#: seq/aconnect/aconnect.c:132
+msgid "Connecting To"
+msgstr "verbunden zu"
+
+#: seq/aconnect/aconnect.c:133
+msgid "Connected From"
+msgstr "verbunden von"
+
+#: seq/aconnect/aconnect.c:169
+#, c-format
+msgid "client %d: '%s' [type=%s]\n"
+msgstr "Client %d: '%s' [Typ=%s]\n"
+
+#: seq/aconnect/aconnect.c:173
+msgid "user"
+msgstr "User"
+
+#: seq/aconnect/aconnect.c:173
+msgid "kernel"
+msgstr "Kernel"
+
+#: seq/aconnect/aconnect.c:307
+#, c-format
+msgid "can't open sequencer\n"
+msgstr "Fehler beim Öffnen des Sequenzers\n"
+
+#: seq/aconnect/aconnect.c:335
+#, c-format
+msgid "can't get client id\n"
+msgstr "Fehler beim Lesen der Client-ID\n"
+
+#: seq/aconnect/aconnect.c:342
+#, c-format
+msgid "can't set client info\n"
+msgstr "Fehler beim Setzen des Client-Namens\n"
+
+#: seq/aconnect/aconnect.c:349
+#, c-format
+msgid "invalid sender address %s\n"
+msgstr "ungültige Sender-Adresse %s\n"
+
+#: seq/aconnect/aconnect.c:354 seq/aseqnet/aseqnet.c:290
+#, c-format
+msgid "invalid destination address %s\n"
+msgstr "ungültige Ziel-Adresse %s\n"
+
+#: seq/aconnect/aconnect.c:368
+#, c-format
+msgid "No subscription is found\n"
+msgstr "keine Verbindung gefunden\n"
+
+#: seq/aconnect/aconnect.c:373
+#, c-format
+msgid "Disconnection failed (%s)\n"
+msgstr "Verbindungs-Trennung fehlgeschlagen (%s)\n"
+
+#: seq/aconnect/aconnect.c:379
+#, c-format
+msgid "Connection is already subscribed\n"
+msgstr "Verbindung ist bereits vorhanden\n"
+
+#: seq/aconnect/aconnect.c:384
+#, c-format
+msgid "Connection failed (%s)\n"
+msgstr "Verbindung fehlgeschlagen (%s)\n"
+
+#: seq/aseqnet/aseqnet.c:164
+#, c-format
+msgid "aseqnet - network client/server on ALSA sequencer\n"
+msgstr "aseqnet - Netzwerk-Client/Server für ALSA Sequenzer\n"
+
+#: seq/aseqnet/aseqnet.c:165
+#, c-format
+msgid "  Copyright (C) 1999 Takashi Iwai\n"
+msgstr "  Copyright © 1999 Takashi Iwai\n"
+
+#: seq/aseqnet/aseqnet.c:166
+#, c-format
+msgid "usage:\n"
+msgstr "Verwendung:\n"
+
+#: seq/aseqnet/aseqnet.c:167
+#, c-format
+msgid "  server mode: aseqnet [-options]\n"
+msgstr "  Server-Modus: aseqnet [Optionen]\n"
+
+#: seq/aseqnet/aseqnet.c:168
+#, c-format
+msgid "  client mode: aseqnet [-options] server_host\n"
+msgstr "  Client-Modus: aseqnet [Optionen] ServerHost\n"
+
+#: seq/aseqnet/aseqnet.c:169
+#, c-format
+msgid "options:\n"
+msgstr "Optionen:\n"
+
+#: seq/aseqnet/aseqnet.c:170
+#, c-format
+msgid "  -p,--port # : sepcify TCP port (digit or service name)\n"
+msgstr "  -p,--port # : TCP-Port (Zahl oder Service-Name)\n"
+
+#: seq/aseqnet/aseqnet.c:171
+#, c-format
+msgid "  -s,--source addr : read from given addr (client:port)\n"
+msgstr "  -s,--source # : lese von Sequenzer-Port (Client:Port)\n"
+
+#: seq/aseqnet/aseqnet.c:172
+#, c-format
+msgid "  -d,--dest addr : write to given addr (client:port)\n"
+msgstr "  -d,--dest # : schreibe auf Sequenzer-Port (Client:Port)\n"
+
+#: seq/aseqnet/aseqnet.c:173
+#, c-format
+msgid "  -v, --verbose : print verbose messages\n"
+msgstr "  -v,--verbose : ausführliche Meldungen\n"
+
+#: seq/aseqnet/aseqnet.c:174
+#, c-format
+msgid "  -i, --info : print certain received events\n"
+msgstr "  -i,--info : Ausgabe bestimmter empfangener Ereignisse\n"
+
+#: seq/aseqnet/aseqnet.c:188
+#, c-format
+msgid "can't malloc\n"
+msgstr "nicht genug Speicher\n"
+
+#: seq/aseqnet/aseqnet.c:213
+#, c-format
+msgid "closing files..\n"
+msgstr "schließe Dateien ...\n"
+
+#: seq/aseqnet/aseqnet.c:272
+#, c-format
+msgid "sequencer opened: %d:%d\n"
+msgstr "Sequenzer geöffnet: %d:%d\n"
+
+#: seq/aseqnet/aseqnet.c:279
+#, c-format
+msgid "invalid source address %s\n"
+msgstr "ungültige Quell-Adresse %s\n"
+
+#: seq/aseqnet/aseqnet.c:309
+#, c-format
+msgid "service '%s' is not found in /etc/services\n"
+msgstr "Service '%s' in /etc/services nicht gefunden\n"
+
+#: seq/aseqnet/aseqnet.c:377
+#, c-format
+msgid "too many connections!\n"
+msgstr "zu viele Verbindungen\n"
+
+#: seq/aseqnet/aseqnet.c:388
+#, c-format
+msgid "accepted[%d]\n"
+msgstr "angenommen[%d]\n"
+
+#: seq/aseqnet/aseqnet.c:411
+#, c-format
+msgid "can't get address %s\n"
+msgstr "kann Adresse für %s nicht bestimmen\n"
+
+#: seq/aseqnet/aseqnet.c:422
+#, c-format
+msgid "ok.. connected\n"
+msgstr "OK ... verbunden\n"
+
+#: seq/aseqnet/aseqnet.c:518
+#, c-format
+msgid "Channel %2d: Control event : %5d\n"
+msgstr "Channel %2d: Control event : %5d\n"
+
+#: seq/aseqnet/aseqnet.c:522
+#, c-format
+msgid "Channel %2d: Pitchbender   : %5d\n"
+msgstr "Channel %2d: Pitchbender   : %5d\n"
+
+#: seq/aseqnet/aseqnet.c:526
+#, c-format
+msgid "Channel %2d: Note On event : %5d\n"
+msgstr "Channel %2d: Note On evenet : %5d\n"
+
+#: seq/aseqnet/aseqnet.c:530
+#, c-format
+msgid "Channel %2d: Note Off event: %5d\n"
+msgstr "Channel %2d: Note Off event: %5d\n"
+
+#: seq/aseqnet/aseqnet.c:585
+#, c-format
+msgid "disconnected\n"
+msgstr "Verbindung getrennt\n"
+
+#: speaker-test/speaker-test.c:103
+msgid "Front Left"
+msgstr "Vorne links"
+
+#: speaker-test/speaker-test.c:104
+msgid "Front Right"
+msgstr "Vorne rechts"
+
+#: speaker-test/speaker-test.c:105
+msgid "Rear Left"
+msgstr "Hinten links"
+
+#: speaker-test/speaker-test.c:106
+msgid "Rear Right"
+msgstr "Hinten rechts"
+
+#: speaker-test/speaker-test.c:108
+msgid "LFE"
+msgstr "Bass"
+
+#: speaker-test/speaker-test.c:109
+msgid "Side Left"
+msgstr "Seitlich links"
+
+#: speaker-test/speaker-test.c:110
+msgid "Side Right"
+msgstr "Seitlich rechts"
+
+#: speaker-test/speaker-test.c:111
+msgid "Channel 9"
+msgstr "Kanal 9"
+
+#: speaker-test/speaker-test.c:112
+msgid "Channel 10"
+msgstr "Kanal 10"
+
+#: speaker-test/speaker-test.c:113
+msgid "Channel 11"
+msgstr "Kanal 11"
+
+#: speaker-test/speaker-test.c:114
+msgid "Channel 12"
+msgstr "Kanal 12"
+
+#: speaker-test/speaker-test.c:115
+msgid "Channel 13"
+msgstr "Kanal 13"
+
+#: speaker-test/speaker-test.c:116
+msgid "Channel 14"
+msgstr "Kanal 14"
+
+#: speaker-test/speaker-test.c:117
+msgid "Channel 15"
+msgstr "Kanal 15"
+
+#: speaker-test/speaker-test.c:118
+msgid "Channel 16"
+msgstr "Kanal 16"
+
+#: speaker-test/speaker-test.c:317
+#, c-format
+msgid "Broken configuration for playback: no configurations available: %s\n"
+msgstr "Ungültige Konfiguration: keine unterstützte Konfiguration: %s\n"
+
+#: speaker-test/speaker-test.c:324
+#, c-format
+msgid "Access type not available for playback: %s\n"
+msgstr "Zugriffsmodus nicht unterstützt: %s\n"
+
+#: speaker-test/speaker-test.c:331
+#, c-format
+msgid "Sample format not available for playback: %s\n"
+msgstr "Sample-Format nicht unterstützt: %s\n"
+
+#: speaker-test/speaker-test.c:338
+#, c-format
+msgid "Channels count (%i) not available for playbacks: %s\n"
+msgstr "Kanal-Anzahl %i nicht unterstützt: %s\n"
+
+#: speaker-test/speaker-test.c:346
+#, c-format
+msgid "Rate %iHz not available for playback: %s\n"
+msgstr "Rate %i Hz nicht unterstützt: %s\n"
+
+#: speaker-test/speaker-test.c:351
+#, c-format
+msgid "Rate doesn't match (requested %iHz, get %iHz, err %d)\n"
+msgstr ""
+"Rate ist nicht exakt (angefordert: %i Hz, unterstützt: %i Hz, Fehlercode %"
+"d)\n"
+
+#: speaker-test/speaker-test.c:355
+#, c-format
+msgid "Rate set to %iHz (requested %iHz)\n"
+msgstr "Rate ist %i Hz (angefordert: %i Hz)\n"
+
+#: speaker-test/speaker-test.c:361
+#, c-format
+msgid "Buffer size range from %lu to %lu\n"
+msgstr "Puffergröße von %lu bis %lu\n"
+
+#: speaker-test/speaker-test.c:362
+#, c-format
+msgid "Period size range from %lu to %lu\n"
+msgstr "Periodengröße von %lu bis %lu\n"
+
+#: speaker-test/speaker-test.c:364
+#, c-format
+msgid "Requested period time %u us\n"
+msgstr "Angeforderte Periodenzeit %u µs\n"
+
+#: speaker-test/speaker-test.c:367
+#, c-format
+msgid "Unable to set period time %u us for playback: %s\n"
+msgstr "Fehler beim Setzen der Periodenzeit %u µs: %s\n"
+
+#: speaker-test/speaker-test.c:373
+#, c-format
+msgid "Requested buffer time %u us\n"
+msgstr "Angeforderte Pufferlänge %u µs\n"
+
+#: speaker-test/speaker-test.c:376
+#, c-format
+msgid "Unable to set buffer time %u us for playback: %s\n"
+msgstr "Fehler beim Setzen der Pufferlänge %u µs: %s\n"
+
+#: speaker-test/speaker-test.c:385
+#, c-format
+msgid "Using max buffer size %lu\n"
+msgstr "Verwende maximale Puffergröße %lu\n"
+
+#: speaker-test/speaker-test.c:388
+#, c-format
+msgid "Unable to set buffer size %lu for playback: %s\n"
+msgstr "Fehler beim Setzen der Puffergröße %lu: %s\n"
+
+#: speaker-test/speaker-test.c:394
+#, c-format
+msgid "Periods = %u\n"
+msgstr "Perioden = %u\n"
+
+#: speaker-test/speaker-test.c:397
+#, c-format
+msgid "Unable to set nperiods %u for playback: %s\n"
+msgstr "Fehler beim Setzen der Periodenanzahl %u: %s\n"
+
+#: speaker-test/speaker-test.c:406
+#, c-format
+msgid "Unable to set hw params for playback: %s\n"
+msgstr "Fehler beim Setzen der Hardware-Parameter: %s\n"
+
+#: speaker-test/speaker-test.c:412
+#, c-format
+msgid "was set period_size = %lu\n"
+msgstr "gesetzt: period_size = %lu\n"
+
+#: speaker-test/speaker-test.c:413
+#, c-format
+msgid "was set buffer_size = %lu\n"
+msgstr "gesetzt: buffer_size = %lu\n"
+
+#: speaker-test/speaker-test.c:415
+#, c-format
+msgid "buffer to small, could not use\n"
+msgstr "Puffer zu klein, kann nicht benutzt werden\n"
+
+#: speaker-test/speaker-test.c:428
+#, c-format
+msgid "Unable to determine current swparams for playback: %s\n"
+msgstr "Fehler beim Lesen der Software-Parameter: %s\n"
+
+#: speaker-test/speaker-test.c:435
+#, c-format
+msgid "Unable to set start threshold mode for playback: %s\n"
+msgstr "Fehler beim Setzen des Start-Schwellenwertes: %s\n"
+
+#: speaker-test/speaker-test.c:442
+#, c-format
+msgid "Unable to set avail min for playback: %s\n"
+msgstr "Fehler beim Setzen des Mindest-verfügbar-Wertes: %s\n"
+
+#: speaker-test/speaker-test.c:449
+#, c-format
+msgid "Unable to set sw params for playback: %s\n"
+msgstr "Fehler beim Setzen der Software-Parameter: %s\n"
+
+#: speaker-test/speaker-test.c:464
+#, c-format
+msgid "Can't recovery from underrun, prepare failed: %s\n"
+msgstr ""
+"Fehler bei Unterlauf-Behandlung, Re-Initialisierung fehlgeschlagen: %s\n"
+
+#: speaker-test/speaker-test.c:475
+#, c-format
+msgid "Can't recovery from suspend, prepare failed: %s\n"
+msgstr ""
+"Fehler beim Aufwachen aus dem Ruhezustand, Re-Initialisierung "
+"fehlgeschlagen: %s\n"
+
+#: speaker-test/speaker-test.c:539 speaker-test/speaker-test.c:954
+#, c-format
+msgid "No enough memory\n"
+msgstr "Nicht genug Speicher\n"
+
+#: speaker-test/speaker-test.c:544
+#, c-format
+msgid "Cannot open WAV file %s\n"
+msgstr "Kann WAV-Datei %s nicht öffnen\n"
+
+#: speaker-test/speaker-test.c:548 speaker-test/speaker-test.c:577
+#, c-format
+msgid "Invalid WAV file %s\n"
+msgstr "Ungültige WAV-Datei %s\n"
+
+#: speaker-test/speaker-test.c:553
+#, c-format
+msgid "Not a WAV file: %s\n"
+msgstr "Keine WAV-Datei: %s\n"
+
+#: speaker-test/speaker-test.c:557
+#, c-format
+msgid "Unsupported WAV format %d for %s\n"
+msgstr "Nicht unterstütztes WAV-Format %d in %s\n"
+
+#: speaker-test/speaker-test.c:562
+#, c-format
+msgid "%s is not a mono stream (%d channels)\n"
+msgstr "%s ist keine Mono-Datei (%d Kanäle)\n"
+
+#: speaker-test/speaker-test.c:567
+#, c-format
+msgid "Sample rate doesn't match (%d) for %s\n"
+msgstr "Sample-Rate (%d) stimmt nicht überein in %s\n"
+
+#: speaker-test/speaker-test.c:572
+#, c-format
+msgid "Unsupported sample format bits %d for %s\n"
+msgstr "Nicht unterstütztes Sample-Format mit %d Bits in %s\n"
+
+#: speaker-test/speaker-test.c:622
+#, c-format
+msgid "Undefined channel %d\n"
+msgstr "Kanal %d nicht definiert\n"
+
+#: speaker-test/speaker-test.c:673
+#, c-format
+msgid "Write error: %d,%s\n"
+msgstr "Schreibfehler: %d, %s\n"
+
+#: speaker-test/speaker-test.c:675
+#, c-format
+msgid "xrun_recovery failed: %d,%s\n"
+msgstr "xrun_recovery fehlgeschlagen: %d, %s\n"
+
+#: speaker-test/speaker-test.c:734
+#, c-format
+msgid ""
+"Usage: speaker-test [OPTION]... \n"
+"-h,--help\thelp\n"
+"-D,--device\tplayback device\n"
+"-r,--rate\tstream rate in Hz\n"
+"-c,--channels\tcount of channels in stream\n"
+"-f,--frequency\tsine wave frequency in Hz\n"
+"-F,--format\tsample format\n"
+"-b,--buffer\tring buffer size in us\n"
+"-p,--period\tperiod size in us\n"
+"-P,--nperiods\tnumber of periods\n"
+"-t,--test\tpink=use pink noise, sine=use sine wave, wav=WAV file\n"
+"-l,--nloops\tspecify number of loops to test, 0 = infinite\n"
+"-s,--speaker\tsingle speaker test. Values 1=Left, 2=right, etc\n"
+"-w,--wavfile\tUse the given WAV file as a test sound\n"
+"-W,--wavdir\tSpecify the directory containing WAV files\n"
+"\n"
+msgstr ""
+"Verwendung: speaker-test [Option]...\n"
+"-h,--help       Hilfe\n"
+"-D,--device     Wiedergabe-Gerät\n"
+"-r,--rate       Sample-Rate in Hz\n"
+"-c,--channels   Anzahl der Kanäle\n"
+"-f,--frequency  Frequenz der Sinuswelle in Hz\n"
+"-F,--format     Sample-Format\n"
+"-b,--buffer     Ringpufferlänge in µs\n"
+"-p,--period     Periodenlänge in µs\n"
+"-P,--nperiods   Anzahl der Perioden\n"
+"-t,--test       pink=rosa Rauschen, sine=Sinuswelle, wav=WAV-Datei\n"
+"-l,--nloops     Anzahl der Wiederholungen, 0 = unendlich\n"
+"-s,--speaker    teste einen einzelnen Lautsprecher; 1=links, 2=rechts, usw.\n"
+"-w,--wavfile    benutze WAV-Datei als Testton\n"
+"-W,--wavdir     benutze Verzeichnis mit darin enthaltenen WAV-Dateien\n"
+"\n"
+
+#: speaker-test/speaker-test.c:852
+#, c-format
+msgid "Invalid number of periods %d\n"
+msgstr "Ungültige Periodenanzahl %d\n"
+
+#: speaker-test/speaker-test.c:866 speaker-test/speaker-test.c:870
+#, c-format
+msgid "Invalid test type %s\n"
+msgstr "Ungültiger Test-Typ %s\n"
+
+#: speaker-test/speaker-test.c:882
+#, c-format
+msgid "Invalid parameter for -s option.\n"
+msgstr "Ungültiger Wert für Option -s\n"
+
+#: speaker-test/speaker-test.c:896
+#, c-format
+msgid "Unknown option '%c'\n"
+msgstr "Unbekannte Options '%c'\n"
+
+#: speaker-test/speaker-test.c:910
+#, c-format
+msgid "Playback device is %s\n"
+msgstr "Wiedergabe-Gerät ist %s\n"
+
+#: speaker-test/speaker-test.c:911
+#, c-format
+msgid "Stream parameters are %iHz, %s, %i channels\n"
+msgstr "Stream-Parameter sind %i Hz, %s, %i Kanäle\n"
+
+#: speaker-test/speaker-test.c:914
+#, c-format
+msgid "Using 16 octaves of pink noise\n"
+msgstr "Verwende 16 Oktaven rosa Rauschen\n"
+
+#: speaker-test/speaker-test.c:917
+#, c-format
+msgid "Sine wave rate is %.4fHz\n"
+msgstr "Sinuswelle mit Frequenz %.4f Hz\n"
+
+#: speaker-test/speaker-test.c:920
+#, c-format
+msgid "WAV file(s)\n"
+msgstr "WAV-Datei(en)\n"
+
+#: speaker-test/speaker-test.c:926
+#, c-format
+msgid "Playback open error: %d,%s\n"
+msgstr "Fehler beim Öffnen des Gerätes: %d, %s\n"
+
+#: speaker-test/speaker-test.c:931
+#, c-format
+msgid "Setting of hwparams failed: %s\n"
+msgstr "Fehler beim Setzen der Hardware-Parameter: %s\n"
+
+#: speaker-test/speaker-test.c:936
+#, c-format
+msgid "Setting of swparams failed: %s\n"
+msgstr "Fehler beim Setzen der Software-Parameter: %s\n"
+
+#: speaker-test/speaker-test.c:985 speaker-test/speaker-test.c:1007
+#, c-format
+msgid "Transfer failed: %s\n"
+msgstr "Schreibfehler: %s\n"
+
+#: speaker-test/speaker-test.c:995
+#, c-format
+msgid "Time per period = %lf\n"
+msgstr "Zeit pro Periode = %lf\n"
index 6e8a5e4..a9af3c0 100644 (file)
Binary files a/po/ja.gmo and b/po/ja.gmo differ
index 4607a4c..b65b8b0 100644 (file)
--- a/po/ja.po
+++ b/po/ja.po
@@ -8,8 +8,8 @@ msgid ""
 msgstr ""
 "Project-Id-Version: alsa-utils 1.0.9a\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2009-01-19 12:24+0100\n"
-"PO-Revision-Date: 2006-04-18 15:51+0200\n"
+"POT-Creation-Date: 2010-04-16 13:19+0200\n"
+"PO-Revision-Date: 2009-05-27 15:08+0200\n"
 "Last-Translator: Takashi Iwai <tiwai@suse.de>\n"
 "Language-Team: Japanese\n"
 "MIME-Version: 1.0\n"
@@ -17,23 +17,372 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=1; plural=0;\n"
 
-#: aplay/aplay.c:136
+#: alsamixer/card_select.c:126 alsamixer/device_name.c:126
+msgid "Sound Card"
+msgstr "サウンドカード"
+
+#: alsamixer/card_select.c:181
+msgid "(default)"
+msgstr "(デフォルト)"
+
+#: alsamixer/card_select.c:191
+msgid "cannot enumerate sound cards"
+msgstr "サウンドカードを検出できません"
+
+#: alsamixer/card_select.c:215
+msgid "enter device name..."
+msgstr "デバイス名入力..."
+
+#: alsamixer/cli.c:40
+msgid "Usage: alsamixer [options]"
+msgstr "使用法: alsamixer [オプション]"
+
+#: alsamixer/cli.c:41
+msgid ""
+"Useful options:\n"
+"  -h, --help              this help\n"
+"  -c, --card=NUMBER       sound card number or id\n"
+"  -D, --device=NAME       mixer device name\n"
+"  -V, --view=MODE         starting view mode: playback/capture/all"
+msgstr ""
+"主なオプション:\n"
+"  -h, --help               このヘルプ画面\n"
+"  -c, --card=番号          サウンドカード番号またはID\n"
+"  -D, --device=名前        ミキサーデバイス名\n"
+"  -V, --view=表示モード    開始時の表示モード: playback/capture/all"
+
+#: alsamixer/cli.c:46
+msgid ""
+"Debugging options:\n"
+"  -g, --no-color          toggle using of colors\n"
+"  -a, --abstraction=NAME  mixer abstraction level: none/basic"
+msgstr ""
+"デバッグオプション:\n"
+"  -g, --no-color           カラー/モノクロ表示\n"
+"  -a, --abstraction=名前   ミキサー抽象レベル: none/basic"
+
+#: alsamixer/cli.c:77
+#, c-format
+msgid "invalid card index: %s\n"
+msgstr "不正なカード番号: %s\n"
+
+#: alsamixer/cli.c:103
+#, c-format
+msgid "unknown abstraction level: %s\n"
+msgstr "未知の抽象レベル: %s\n"
+
+#: alsamixer/cli.c:108
+#, c-format
+msgid "unknown option: %c\n"
+msgstr "未知のオプション '%c'\n"
+
+#: alsamixer/cli.c:110
+msgid "try `alsamixer --help' for more information\n"
+msgstr "より詳しい情報は「alsamixer --help」を実行してください\n"
+
+#: alsamixer/device_name.c:177
+msgid "Device name:"
+msgstr "デバイス名:"
+
+#: alsamixer/die.c:37
+#, c-format
+msgid "%s: %s\n"
+msgstr ""
+
+#: alsamixer/mixer_display.c:95
+msgid "Card:"
+msgstr "カード:"
+
+#: alsamixer/mixer_display.c:96
+msgid "Chip:"
+msgstr "チップ:"
+
+#: alsamixer/mixer_display.c:97
+msgid "View:"
+msgstr "表示:"
+
+#: alsamixer/mixer_display.c:98
+msgid "Item:"
+msgstr "項目:"
+
+#: alsamixer/mixer_display.c:101
+msgid "F1:  Help"
+msgstr "F1:  ヘルプ"
+
+#: alsamixer/mixer_display.c:102
+msgid "F2:  System information"
+msgstr "F2:  システム情報"
+
+#: alsamixer/mixer_display.c:103
+msgid "F6:  Select sound card"
+msgstr "F6:  サウンドカード選択"
+
+#: alsamixer/mixer_display.c:104
+msgid "Esc: Exit"
+msgstr "Esc: 終了"
+
+#: alsamixer/mixer_display.c:171
+msgid "(unplugged)"
+msgstr ""
+
+#: alsamixer/mixer_display.c:189
+msgid "Playback"
+msgstr "再生"
+
+#: alsamixer/mixer_display.c:190
+msgid "Capture"
+msgstr "録音"
+
+#: alsamixer/mixer_display.c:191
+msgid "All"
+msgstr "全て"
+
+#: alsamixer/mixer_display.c:231
+msgid "mute"
+msgstr "ミュート"
+
+#: alsamixer/mixer_display.c:272 alsamixer/mixer_display.c:282
+msgid "dB gain:"
+msgstr "dBゲイン:"
+
+#: alsamixer/mixer_display.c:282
+#, c-format
+msgid " [%s %s, %s]"
+msgstr ""
+
+#: alsamixer/mixer_display.c:291 alsamixer/mixer_display.c:297
+#: alsamixer/mixer_display.c:303 alsamixer/mixer_display.c:309
+msgid "Off"
+msgstr "オフ"
+
+#: alsamixer/mixer_display.c:297 alsamixer/mixer_display.c:309
+msgid "On"
+msgstr "オン"
+
+#: alsamixer/mixer_display.c:360
+msgid "The sound device was unplugged."
+msgstr "デバイスが接続されていません"
+
+#: alsamixer/mixer_display.c:361
+msgid "Press F6 to select another sound card."
+msgstr "他のカードを選択するにはF6を押して下さい"
+
+#: alsamixer/mixer_display.c:376
+msgid "This sound device does not have any playback controls."
+msgstr "このカードには再生ミキサーがありません"
+
+#: alsamixer/mixer_display.c:378
+msgid "This sound device does not have any capture controls."
+msgstr "このカードには録音ミキサーがありません"
+
+#: alsamixer/mixer_display.c:380
+msgid "This sound device does not have any controls."
+msgstr "このカードには制御可能なミキサーがありません"
+
+#. TRANSLATORS: playback on; one character
+#: alsamixer/mixer_display.c:537 alsamixer/mixer_display.c:542
+msgid "O"
+msgstr ""
+
+#. TRANSLATORS: playback muted; one character
+#: alsamixer/mixer_display.c:539 alsamixer/mixer_display.c:543
+msgid "M"
+msgstr ""
+
+#. TRANSLATORS: "left"; no more than two characters
+#: alsamixer/mixer_display.c:557
+msgid "L"
+msgstr ""
+
+#. TRANSLATORS: "right"; no more than two characters
+#: alsamixer/mixer_display.c:561
+msgid "R"
+msgstr ""
+
+#. TRANSLATORS: no more than eight characters
+#: alsamixer/mixer_display.c:563
+msgid "CAPTURE"
+msgstr "録音"
+
+#: alsamixer/mixer_display.c:613
+msgid "Front"
+msgstr "フロント"
+
+#: alsamixer/mixer_display.c:616
+msgid "Rear"
+msgstr "リア"
+
+#: alsamixer/mixer_display.c:619 speaker-test/speaker-test.c:107
+msgid "Center"
+msgstr "センター"
+
+#: alsamixer/mixer_display.c:622
+msgid "Woofer"
+msgstr "低音"
+
+#: alsamixer/mixer_display.c:625
+msgid "Side"
+msgstr "サイド"
+
+#: alsamixer/mixer_widget.c:83 alsamixer/mixer_widget.c:88
+msgid "cannot open mixer"
+msgstr "ミキサーを開けません"
+
+#: alsamixer/mixer_widget.c:94 alsamixer/mixer_widget.c:171
+msgid "cannot load mixer controls"
+msgstr "ミキサーをロードできません"
+
+#: alsamixer/mixer_widget.c:161
+#, c-format
+msgid "Cannot open mixer device '%s'."
+msgstr "ミキサーデバイス'%s'を開けません"
+
+#: alsamixer/mixer_widget.c:182
+msgid "Esc     Exit"
+msgstr "Esc    終了"
+
+#: alsamixer/mixer_widget.c:183
+msgid "F1 ? H  Help"
+msgstr "F1 ?   H ヘルプ"
+
+#: alsamixer/mixer_widget.c:184
+msgid "F2 /    System information"
+msgstr "F2 /   システム情報"
+
+#: alsamixer/mixer_widget.c:185
+msgid "F3      Show playback controls"
+msgstr "F3     再生ミキサー表示"
+
+#: alsamixer/mixer_widget.c:186
+msgid "F4      Show capture controls"
+msgstr "F4     録音ミキサー表示"
+
+#: alsamixer/mixer_widget.c:187
+msgid "F5      Show all controls"
+msgstr "F5     全て表示"
+
+#: alsamixer/mixer_widget.c:188
+msgid "Tab     Toggle view mode (F3/F4/F5)"
+msgstr "Tab    表示モード変更 (F3/F4/F5)"
+
+#: alsamixer/mixer_widget.c:189
+msgid "F6 S    Select sound card"
+msgstr "F5 S   サウンドカード選択"
+
+#: alsamixer/mixer_widget.c:190
+msgid "L       Redraw screen"
+msgstr "L      画面再描画"
+
+#: alsamixer/mixer_widget.c:192
+msgid "Left    Move to the previous control"
+msgstr "←     前の項目に移る"
+
+#: alsamixer/mixer_widget.c:193
+msgid "Right   Move to the next control"
+msgstr "→     次の項目に移る"
+
+# ↑
+#: alsamixer/mixer_widget.c:195
+msgid "Up/Down    Change volume"
+msgstr "↑/↓     音量変更"
+
+#: alsamixer/mixer_widget.c:196
+msgid "+ -        Change volume"
+msgstr "+ -       音量変更"
+
+#: alsamixer/mixer_widget.c:197
+msgid "Page Up/Dn Change volume in big steps"
+msgstr "Page Up/dn 音量変更"
+
+#: alsamixer/mixer_widget.c:198
+msgid "End        Set volume to 0%"
+msgstr "End       音量 0%"
+
+#: alsamixer/mixer_widget.c:199
+msgid "0-9        Set volume to 0%-90%"
+msgstr "0-9       音量 0%-90%"
+
+#: alsamixer/mixer_widget.c:200
+msgid "Q W E      Increase left/both/right volumes"
+msgstr "Q W E     左/両/右音量アップ"
+
+#. TRANSLATORS: or Y instead of Z
+#: alsamixer/mixer_widget.c:202
+msgid "Z X C      Decrease left/both/right volumes"
+msgstr "Z X C     左/両/右音量ダウン"
+
+#: alsamixer/mixer_widget.c:203
+msgid "B          Balance left and right volumes"
+msgstr "B         左右音量を平均化する"
+
+#: alsamixer/mixer_widget.c:205
+msgid "M          Toggle mute"
+msgstr "M         ミュートをトグル"
+
+#. TRANSLATORS: or , .
+#: alsamixer/mixer_widget.c:207
+msgid "< >        Toggle left/right mute"
+msgstr "< >       左/右ミュートをトグル"
+
+#: alsamixer/mixer_widget.c:209
+msgid "Space      Toggle capture"
+msgstr "スペース  録音をトグル"
+
+#. TRANSLATORS: or Insert Delete
+#: alsamixer/mixer_widget.c:211
+msgid "; '        Toggle left/right capture"
+msgstr "; '       左/右録音をトグル"
+
+#: alsamixer/mixer_widget.c:213
+msgid "Authors:"
+msgstr "作者:"
+
+#: alsamixer/mixer_widget.c:214
+msgid "  Tim Janik <timj@gtk.org>"
+msgstr ""
+
+#: alsamixer/mixer_widget.c:215
+msgid "  Jaroslav Kysela <perex@perex.cz>"
+msgstr ""
+
+#: alsamixer/mixer_widget.c:216
+msgid "  Clemens Ladisch <clemens@ladisch.de>"
+msgstr ""
+
+#: alsamixer/mixer_widget.c:218
+msgid "Help"
+msgstr "ヘルプ"
+
+#: alsamixer/proc_files.c:103
+msgid "Select File"
+msgstr "ファイル選択"
+
+#: alsamixer/textbox.c:52 alsamixer/textbox.c:66
+msgid "Error"
+msgstr "エラー"
+
+#: alsamixer/textbox.c:80
+#, c-format
+msgid "Cannot open file \"%s\"."
+msgstr "\"%s\"をオープンできません"
+
+#: aplay/aplay.c:147
 msgid "raw data"
 msgstr "raw データ"
 
-#: aplay/aplay.c:137
+#: aplay/aplay.c:148
 msgid "VOC"
 msgstr "VOC"
 
-#: aplay/aplay.c:139
+#: aplay/aplay.c:150
 msgid "WAVE"
 msgstr "WAVE"
 
-#: aplay/aplay.c:140
+#: aplay/aplay.c:151
 msgid "Sparc Audio"
 msgstr "Sparc オーディオ"
 
-#: aplay/aplay.c:161
+#: aplay/aplay.c:172
 #, fuzzy, c-format
 msgid ""
 "Usage: %s [OPTION]... [FILE]...\n"
@@ -68,6 +417,15 @@ msgid ""
 "    --disable-format    disable automatic format conversions\n"
 "    --disable-softvol   disable software volume control (softvol)\n"
 "    --test-position     test ring buffer position\n"
+"    --test-coef=#\t test coeficient for ring buffer position (default 8)\n"
+"                        expression for validation is: coef * (buffer_size / "
+"2)\n"
+"    --test-nowait       do not wait for ring buffer - eats whole CPU\n"
+"    --max-file-time=#   start another output file when the old file has "
+"recorded\n"
+"                        for this many seconds\n"
+"    --process-id-file   write the process ID here\n"
+"    --use-strftime      apply the strftime facility to the output file name\n"
 msgstr ""
 "使用法: %s [オプション]... [ファイル]...\n"
 "\n"
@@ -82,7 +440,6 @@ msgstr ""
 "-f, --format=FORMAT     サンプルフォーマット (大/小文字区別)\n"
 "-r, --rate=#            サンプルレート\n"
 "-d, --duration=#        指定の秒数後に終了\n"
-"-s, --sleep-min=#       sleep する最少 tick 数\n"
 "-M, --mmap              mmap ストリーム\n"
 "-N, --nonblock          非ブロックモード\n"
 "-F, --period-time=#     割り込み間隔をμ秒で指定\n"
@@ -94,14 +451,23 @@ msgstr ""
 "                        (0 以下の場合はバッファサイズより)\n"
 "-T, --stop-delay=#      XRUN から指定のμ秒後に PCM の自動停止\n"
 "-v, --verbose           PCM の設定を表示 (複数指定可能)\n"
+"-V, --vumeter=TYPE      enable VU meter (TYPE: mono or stereo)\n"
 "-I, --separate-channels 各チャネルに一つのファイルを用いる\n"
+"    --disable-resample  自動レート変換を禁止する\n"
+"    --disable-channels  自動チャネル変換を禁止する\n"
+"    --disable-format    自動フォーマット変換を禁止する\n"
+"    --disable-softvol   ソフト音量制御(softvol)を禁止する\n"
+"    --test-position     リングバッファ位置をテストする\n"
+"    --test-coef=#       リングバッファ位置テストの係数 (デフォルト 8)\n"
+"                        テスト範囲: coef * (buffer_size / 2)\n"
+"    --test-nowait       リングバッファのウエイトを禁止 - 注意:高CPU負荷\n"
 
-#: aplay/aplay.c:193 speaker-test/speaker-test.c:783
+#: aplay/aplay.c:211 speaker-test/speaker-test.c:750
 #, c-format
 msgid "Recognized sample formats are:"
 msgstr "認識されるサンプルフォーマット:"
 
-#: aplay/aplay.c:199
+#: aplay/aplay.c:217
 #, c-format
 msgid ""
 "\n"
@@ -110,154 +476,159 @@ msgstr ""
 "\n"
 "これらのいくつかは指定のハードウェアで使用不可能な場合があります\n"
 
-#: aplay/aplay.c:200
+#: aplay/aplay.c:218
 #, c-format
 msgid "The availabled format shortcuts are:\n"
 msgstr "可能なフォーマットの省略形:\n"
 
-#: aplay/aplay.c:201
+#: aplay/aplay.c:219
 #, c-format
 msgid "-f cd (16 bit little endian, 44100, stereo)\n"
 msgstr "-f cd (16 ビット、リトルエンディアン、44100、ステレオ)\n"
 
-#: aplay/aplay.c:202
+#: aplay/aplay.c:220
 #, c-format
 msgid "-f cdr (16 bit big endian, 44100, stereo)\n"
 msgstr "-f cdr (16 ビット、ビッグエンディアン、44100、ステレオ)\n"
 
-#: aplay/aplay.c:203
+#: aplay/aplay.c:221
 #, c-format
 msgid "-f dat (16 bit little endian, 48000, stereo)\n"
 msgstr "-f dat (16 ビット、リトルエンディアン、48000、ステレオ)\n"
 
-#: aplay/aplay.c:217
+#: aplay/aplay.c:235
 msgid "no soundcards found..."
 msgstr "サウンドカードが見つかりません..."
 
-#: aplay/aplay.c:220
+#: aplay/aplay.c:238
 #, c-format
 msgid "**** List of %s Hardware Devices ****\n"
 msgstr "**** ハードウェアデバイス %s のリスト ****\n"
 
-#: aplay/aplay.c:249
+#: aplay/aplay.c:267
 #, c-format
 msgid "card %i: %s [%s], device %i: %s [%s]\n"
 msgstr "カード %i: %s [%s], デバイス %i: %s [%s]\n"
 
-#: aplay/aplay.c:255
+#: aplay/aplay.c:273
 #, c-format
 msgid "  Subdevices: %i/%i\n"
 msgstr "  サブデバイス: %i/%i\n"
 
-#: aplay/aplay.c:262
+#: aplay/aplay.c:280
 #, c-format
 msgid "  Subdevice #%i: %s\n"
 msgstr "  サブデバイス #%i: %s\n"
 
-#: aplay/aplay.c:326
+#: aplay/aplay.c:356
 #, c-format
 msgid "Aborted by signal %s...\n"
 msgstr "シグナル %s で中断...\n"
 
-#: aplay/aplay.c:420
+#: aplay/aplay.c:467
 msgid "command should be named either arecord or aplay"
 msgstr "arecord または aplay コマンドのみ可能"
 
-#: aplay/aplay.c:459
+#: aplay/aplay.c:506
 #, c-format
 msgid "unrecognized file format %s"
 msgstr "不正なファイルフォーマット %s"
 
-#: aplay/aplay.c:466
+#: aplay/aplay.c:513
 #, c-format
 msgid "value %i for channels is invalid"
 msgstr "不正なチャネル数 %i"
 
-#: aplay/aplay.c:485
+#: aplay/aplay.c:532
 #, c-format
 msgid "wrong extended format '%s'"
 msgstr "不正な拡張フォーマット '%s'"
 
-#: aplay/aplay.c:496
+#: aplay/aplay.c:543
 #, c-format
 msgid "bad speed value %i"
 msgstr "不正なレート値 %i"
 
-#: aplay/aplay.c:574
+#: aplay/aplay.c:638
 #, c-format
 msgid "Try `%s --help' for more information.\n"
 msgstr "より詳しい情報は「%s --help」を実行してください\n"
 
-#: aplay/aplay.c:590
+#: aplay/aplay.c:654
 #, c-format
 msgid "audio open error: %s"
 msgstr ""
 
-#: aplay/aplay.c:595
+#: aplay/aplay.c:659
 #, c-format
 msgid "info error: %s"
 msgstr ""
 
-#: aplay/aplay.c:602
+#: aplay/aplay.c:666
 #, c-format
 msgid "nonblock setting error: %s"
 msgstr ""
 
-#: aplay/aplay.c:612 aplay/aplay.c:719 aplay/aplay.c:1073
+#: aplay/aplay.c:676 aplay/aplay.c:800 aplay/aplay.c:1167
 msgid "not enough memory"
 msgstr "メモリが足りません"
 
-#: aplay/aplay.c:709
+#: aplay/aplay.c:700
+#, fuzzy, c-format
+msgid "Cannot create process ID file %s: %s"
+msgstr "WAVファイルがオープンできません: %s\n"
+
+#: aplay/aplay.c:790
 #, c-format
 msgid "read error (called from line %i)"
 msgstr "リードエラー (%i 行)"
 
-#: aplay/aplay.c:767
+#: aplay/aplay.c:848
 #, c-format
 msgid "unknown length of 'fmt ' chunk (read %u, should be %u at least)"
 msgstr ""
 
-#: aplay/aplay.c:777
+#: aplay/aplay.c:858
 #, c-format
 msgid ""
 "unknown length of extensible 'fmt ' chunk (read %u, should be %u at least)"
 msgstr ""
 
-#: aplay/aplay.c:782
+#: aplay/aplay.c:863
 msgid "wrong format tag in extensible 'fmt ' chunk"
 msgstr ""
 
-#: aplay/aplay.c:789
+#: aplay/aplay.c:870
 #, c-format
 msgid "can't play WAVE-file format 0x%04x which is not PCM or FLOAT encoded"
 msgstr ""
 
-#: aplay/aplay.c:793
+#: aplay/aplay.c:874
 #, c-format
 msgid "can't play WAVE-files with %d tracks"
 msgstr "%d トラックを含む WAVE ファイルは再生できません"
 
-#: aplay/aplay.c:801 aplay/aplay.c:901
+#: aplay/aplay.c:882 aplay/aplay.c:982
 #, c-format
 msgid "Warning: format is changed to U8\n"
 msgstr "警告: フォーマットは U8 に変更されます\n"
 
-#: aplay/aplay.c:807
+#: aplay/aplay.c:888
 #, c-format
 msgid "Warning: format is changed to S16_LE\n"
 msgstr "警告: フォーマットは S16_LE に変更されます\n"
 
-#: aplay/aplay.c:815
+#: aplay/aplay.c:896
 #, c-format
 msgid "Warning: format is changed to S24_3LE\n"
 msgstr "警告: フォーマットは S24_3LE に変更されます\n"
 
-#: aplay/aplay.c:821
+#: aplay/aplay.c:902
 #, c-format
 msgid "Warning: format is changed to S24_LE\n"
 msgstr "警告: フォーマットは S24_LE に変更されます\n"
 
-#: aplay/aplay.c:825
+#: aplay/aplay.c:906
 #, c-format
 msgid ""
 " can't play WAVE-files with sample %d bits in %d bytes wide (%d channels)"
@@ -265,254 +636,261 @@ msgstr ""
 "%2$d バイト長 %1$d サンプルビット (%3$d チャネル) の WAVE ファイルは再生でき"
 "ません"
 
-#: aplay/aplay.c:837
+#: aplay/aplay.c:918
 #, c-format
 msgid " can't play WAVE-files with sample %d bits wide"
 msgstr "%d ビット長のサンプルの WAVE ファイルは再生できません"
 
-#: aplay/aplay.c:895
+#: aplay/aplay.c:976
 #, c-format
 msgid "Warning: format is changed to MU_LAW\n"
 msgstr "警告: フォーマットは MU_LAW に変更されます\n"
 
-#: aplay/aplay.c:907
+#: aplay/aplay.c:988
 #, c-format
 msgid "Warning: format is changed to S16_BE\n"
 msgstr "警告: フォーマットは S16_BE に変更されます\n"
 
-#: aplay/aplay.c:920 aplay/aplay.c:1679 aplay/aplay.c:1686 aplay/aplay.c:2208
-#: aplay/aplay.c:2220
+#: aplay/aplay.c:1001 aplay/aplay.c:1843 aplay/aplay.c:1850 aplay/aplay.c:2372
+#: aplay/aplay.c:2384
 msgid "read error"
 msgstr "リードエラー"
 
-#: aplay/aplay.c:939
+#: aplay/aplay.c:1031
 msgid "Broken configuration for this PCM: no configurations available"
 msgstr "指定の PCM を使用できません: 設定がありません"
 
-#: aplay/aplay.c:956
+#: aplay/aplay.c:1048
 msgid "Access type not available"
 msgstr "アクセスタイプが使用不可能"
 
-#: aplay/aplay.c:961
+#: aplay/aplay.c:1053
 msgid "Sample format non available"
 msgstr "サンプルフォーマットが使用不可能"
 
-#: aplay/aplay.c:966
+#: aplay/aplay.c:1059
 msgid "Channels count non available"
 msgstr "チャネル数が使用不可能"
 
-#: aplay/aplay.c:981
+#: aplay/aplay.c:1074
 #, c-format
 msgid "Warning: rate is not accurate (requested = %iHz, got = %iHz)\n"
 msgstr "警告: レートが不正確です (要求値 = %iHz, 使用値 = %iHz)\n"
 
-#: aplay/aplay.c:987
+#: aplay/aplay.c:1080
 #, c-format
 msgid "         please, try the plug plugin %s\n"
 msgstr "        plug プラグイン%s を使用してください\n"
 
-#: aplay/aplay.c:1022
+#: aplay/aplay.c:1116
 msgid "Unable to install hw params:"
 msgstr "hw params のインストールに失敗しました:"
 
-#: aplay/aplay.c:1029
+#: aplay/aplay.c:1123
 #, c-format
 msgid "Can't use period equal to buffer size (%lu == %lu)"
 msgstr "period と buffer サイズには同じ値を使用できません (%lu == %lu)"
 
-#: aplay/aplay.c:1060
+#: aplay/aplay.c:1154
 msgid "unable to install sw params:"
 msgstr "sw params のインストールに失敗しました:"
 
-#: aplay/aplay.c:1123
+#: aplay/aplay.c:1229
 #, c-format
 msgid "status error: %s"
 msgstr "ステータスエラー: %s"
 
-#: aplay/aplay.c:1131
+#: aplay/aplay.c:1239 aplay/aplay.c:1250
 #, c-format
 msgid "%s!!! (at least %.3f ms long)\n"
 msgstr "%s!!! (少なくとも %.3f ms)\n"
 
-#: aplay/aplay.c:1132
+#: aplay/aplay.c:1240 aplay/aplay.c:1243 aplay/aplay.c:1251
 msgid "underrun"
 msgstr "アンダーラン"
 
-#: aplay/aplay.c:1132
+#: aplay/aplay.c:1240 aplay/aplay.c:1251
 msgid "overrun"
 msgstr "オーバーラン"
 
-#: aplay/aplay.c:1135
+#: aplay/aplay.c:1255
 #, c-format
 msgid "Status:\n"
 msgstr "ステータス:\n"
 
-#: aplay/aplay.c:1139
+#: aplay/aplay.c:1259
 #, c-format
 msgid "xrun: prepare error: %s"
 msgstr ""
 
-#: aplay/aplay.c:1145
+#: aplay/aplay.c:1265
 #, c-format
 msgid "Status(DRAINING):\n"
 msgstr "ステータス(DRAINING):\n"
 
-#: aplay/aplay.c:1149
+#: aplay/aplay.c:1269
 #, c-format
 msgid "capture stream format change? attempting recover...\n"
 msgstr "録音ストリームのフォーマットが変更? 修復を試みます...\n"
 
-#: aplay/aplay.c:1151
+#: aplay/aplay.c:1271
 #, c-format
 msgid "xrun(DRAINING): prepare error: %s"
 msgstr ""
 
-#: aplay/aplay.c:1158
+#: aplay/aplay.c:1278
 #, c-format
 msgid "Status(R/W):\n"
 msgstr "ステータス(R/W):\n"
 
-#: aplay/aplay.c:1161
+#: aplay/aplay.c:1281
 #, c-format
 msgid "read/write error, state = %s"
 msgstr "読み書きエラー, ステータス = %s"
 
-#: aplay/aplay.c:1171
+#: aplay/aplay.c:1291
 #, c-format
 msgid "Suspended. Trying resume. "
 msgstr "サスペンド中です。レジュームします。"
 
-#: aplay/aplay.c:1176
+#: aplay/aplay.c:1296
 #, c-format
 msgid "Failed. Restarting stream. "
 msgstr "失敗しました。ストリームを再スタートします。"
 
-#: aplay/aplay.c:1178
+#: aplay/aplay.c:1298
 #, c-format
 msgid "suspend: prepare error: %s"
 msgstr "サスペンド: prepare エラー: %s"
 
-#: aplay/aplay.c:1183
+#: aplay/aplay.c:1303
 #, c-format
 msgid "Done.\n"
 msgstr "終了\n"
 
-#: aplay/aplay.c:1205
+#: aplay/aplay.c:1325
 #, c-format
 msgid " !clip  "
 msgstr ""
 
-#: aplay/aplay.c:1352
+#: aplay/aplay.c:1472
 #, c-format
 msgid "Unsupported bit size %d.\n"
 msgstr ""
 
-#: aplay/aplay.c:1386
+#: aplay/aplay.c:1506
 #, c-format
 msgid "Max peak (%li samples): 0x%08x "
 msgstr "最大ピーク (%li サンプル): 0x%08x "
 
-#: aplay/aplay.c:1442
+#: aplay/aplay.c:1540
+#, c-format
+msgid ""
+"Suspicious buffer position (%li total): avail = %li, delay = %li, buffer = %"
+"li\n"
+msgstr ""
+
+#: aplay/aplay.c:1603
 #, c-format
 msgid "write error: %s"
 msgstr "書込エラー: %s"
 
-#: aplay/aplay.c:1487
+#: aplay/aplay.c:1649
 #, c-format
 msgid "writev error: %s"
 msgstr "書込(writev)エラー: %s"
 
-#: aplay/aplay.c:1529
+#: aplay/aplay.c:1692
 #, c-format
 msgid "read error: %s"
 msgstr "読込エラー: %s"
 
-#: aplay/aplay.c:1571
+#: aplay/aplay.c:1735
 #, c-format
 msgid "readv error: %s"
 msgstr "読込(readv)エラー: %s"
 
-#: aplay/aplay.c:1619
+#: aplay/aplay.c:1783
 msgid "can't allocate buffer for silence"
 msgstr "サイレンス用のバッファの取得に失敗しました"
 
-#: aplay/aplay.c:1628 aplay/aplay.c:1854 aplay/aplay.c:1859 aplay/aplay.c:1906
-#: aplay/aplay.c:1915 aplay/aplay.c:1922 aplay/aplay.c:1932 aplay/aplay.c:1938
-#: aplay/aplay.c:2010 aplay/aplay.c:2040 aplay/aplay.c:2054
+#: aplay/aplay.c:1792 aplay/aplay.c:2018 aplay/aplay.c:2023 aplay/aplay.c:2070
+#: aplay/aplay.c:2079 aplay/aplay.c:2086 aplay/aplay.c:2096 aplay/aplay.c:2102
+#: aplay/aplay.c:2174 aplay/aplay.c:2204 aplay/aplay.c:2218
 msgid "write error"
 msgstr "書込エラー"
 
-#: aplay/aplay.c:1641
+#: aplay/aplay.c:1805
 #, c-format
 msgid "voc_pcm_flush - silence error"
 msgstr ""
 
-#: aplay/aplay.c:1644
+#: aplay/aplay.c:1808
 msgid "voc_pcm_flush error"
 msgstr ""
 
-#: aplay/aplay.c:1670
+#: aplay/aplay.c:1834
 msgid "malloc error"
 msgstr "malloc エラー"
 
-#: aplay/aplay.c:1674
+#: aplay/aplay.c:1838
 #, c-format
 msgid "Playing Creative Labs Channel file '%s'...\n"
 msgstr "Creative Labs Channel ファイル '%s' を演奏中...\n"
 
-#: aplay/aplay.c:1742 aplay/aplay.c:1834
+#: aplay/aplay.c:1906 aplay/aplay.c:1998
 msgid "can't play packed .voc files"
 msgstr "packed .voc ファイルは演奏できません"
 
-#: aplay/aplay.c:1794
+#: aplay/aplay.c:1958
 #, c-format
 msgid "can't play loops; %s isn't seekable\n"
 msgstr "ループ演奏できません。%s はシーク不可能です\n"
 
-#: aplay/aplay.c:1843
+#: aplay/aplay.c:2007
 #, c-format
 msgid "unknown blocktype %d. terminate."
 msgstr "未知のブロックタイプ %d: 終了します。"
 
-#: aplay/aplay.c:1974
+#: aplay/aplay.c:2138
 #, c-format
 msgid "Wave doesn't support %s format..."
 msgstr "WAVE は %s フォーマットをサポートしません..."
 
-#: aplay/aplay.c:2034
+#: aplay/aplay.c:2198
 #, c-format
 msgid "Sparc Audio doesn't support %s format..."
 msgstr "Sparc オーディオは %s フォーマットをサポートしません..."
 
-#: aplay/aplay.c:2115
+#: aplay/aplay.c:2279
 msgid "Playing"
 msgstr "再生中"
 
-#: aplay/aplay.c:2115
+#: aplay/aplay.c:2279
 msgid "Recording"
 msgstr "録音中"
 
-#: aplay/aplay.c:2119
+#: aplay/aplay.c:2283
 #, c-format
 msgid "Rate %d Hz, "
 msgstr "レート %d Hz, "
 
-#: aplay/aplay.c:2121
+#: aplay/aplay.c:2285
 #, c-format
 msgid "Mono"
 msgstr "モノラル"
 
-#: aplay/aplay.c:2123
+#: aplay/aplay.c:2287
 #, c-format
 msgid "Stereo"
 msgstr "ステレオ"
 
-#: aplay/aplay.c:2125
+#: aplay/aplay.c:2289
 #, c-format
 msgid "Channels %i"
 msgstr "チャネル数 %i"
 
-#: aplay/aplay.c:2484 aplay/aplay.c:2537
+#: aplay/aplay.c:2798 aplay/aplay.c:2851
 #, c-format
 msgid "You need to specify %d files"
 msgstr "%d 個のファイルを指定してください"
@@ -623,47 +1001,47 @@ msgstr "ユーザ"
 msgid "kernel"
 msgstr "カーネル"
 
-#: seq/aconnect/aconnect.c:326
+#: seq/aconnect/aconnect.c:307
 #, c-format
 msgid "can't open sequencer\n"
 msgstr "sequencer をオープンできません\n"
 
-#: seq/aconnect/aconnect.c:354
+#: seq/aconnect/aconnect.c:335
 #, c-format
 msgid "can't get client id\n"
 msgstr "クライアント ID を取得できません\n"
 
-#: seq/aconnect/aconnect.c:361
+#: seq/aconnect/aconnect.c:342
 #, c-format
 msgid "can't set client info\n"
 msgstr "クライアント情報を取得できません\n"
 
-#: seq/aconnect/aconnect.c:368
+#: seq/aconnect/aconnect.c:349
 #, c-format
 msgid "invalid sender address %s\n"
 msgstr "送信アドレスが不正です: %s\n"
 
-#: seq/aconnect/aconnect.c:373 seq/aseqnet/aseqnet.c:290
+#: seq/aconnect/aconnect.c:354 seq/aseqnet/aseqnet.c:290
 #, c-format
 msgid "invalid destination address %s\n"
 msgstr "受信アドレスが不正です: %s\n"
 
-#: seq/aconnect/aconnect.c:387
+#: seq/aconnect/aconnect.c:368
 #, c-format
 msgid "No subscription is found\n"
 msgstr "接続が見つかりません\n"
 
-#: seq/aconnect/aconnect.c:392
+#: seq/aconnect/aconnect.c:373
 #, c-format
 msgid "Disconnection failed (%s)\n"
 msgstr "切り離しに失敗 (%s)\n"
 
-#: seq/aconnect/aconnect.c:398
+#: seq/aconnect/aconnect.c:379
 #, c-format
 msgid "Connection is already subscribed\n"
 msgstr "既に接続されています\n"
 
-#: seq/aconnect/aconnect.c:403
+#: seq/aconnect/aconnect.c:384
 #, c-format
 msgid "Connection failed (%s)\n"
 msgstr "接続に失敗 (%s)\n"
@@ -793,261 +1171,257 @@ msgstr "チャネル %2d: ノートオフ   : %5d\n"
 msgid "disconnected\n"
 msgstr "切り離し\n"
 
-#: speaker-test/speaker-test.c:88
+#: speaker-test/speaker-test.c:103
 msgid "Front Left"
 msgstr ""
 
-#: speaker-test/speaker-test.c:89
+#: speaker-test/speaker-test.c:104
 msgid "Front Right"
 msgstr ""
 
-#: speaker-test/speaker-test.c:90
+#: speaker-test/speaker-test.c:105
 msgid "Rear Left"
 msgstr ""
 
-#: speaker-test/speaker-test.c:91
+#: speaker-test/speaker-test.c:106
 msgid "Rear Right"
 msgstr ""
 
-#: speaker-test/speaker-test.c:92
-msgid "Center"
-msgstr ""
-
-#: speaker-test/speaker-test.c:93
+#: speaker-test/speaker-test.c:108
 msgid "LFE"
 msgstr ""
 
-#: speaker-test/speaker-test.c:94
+#: speaker-test/speaker-test.c:109
 msgid "Side Left"
 msgstr ""
 
-#: speaker-test/speaker-test.c:95
+#: speaker-test/speaker-test.c:110
 msgid "Side Right"
 msgstr ""
 
-#: speaker-test/speaker-test.c:96
+#: speaker-test/speaker-test.c:111
 msgid "Channel 9"
 msgstr ""
 
-#: speaker-test/speaker-test.c:97
+#: speaker-test/speaker-test.c:112
 msgid "Channel 10"
 msgstr ""
 
-#: speaker-test/speaker-test.c:98
+#: speaker-test/speaker-test.c:113
 msgid "Channel 11"
 msgstr ""
 
-#: speaker-test/speaker-test.c:99
+#: speaker-test/speaker-test.c:114
 msgid "Channel 12"
 msgstr ""
 
-#: speaker-test/speaker-test.c:100
+#: speaker-test/speaker-test.c:115
 msgid "Channel 13"
 msgstr ""
 
-#: speaker-test/speaker-test.c:101
+#: speaker-test/speaker-test.c:116
 msgid "Channel 14"
 msgstr ""
 
-#: speaker-test/speaker-test.c:102
+#: speaker-test/speaker-test.c:117
 msgid "Channel 15"
 msgstr ""
 
-#: speaker-test/speaker-test.c:103
+#: speaker-test/speaker-test.c:118
 msgid "Channel 16"
 msgstr ""
 
-#: speaker-test/speaker-test.c:340
+#: speaker-test/speaker-test.c:317
 #, c-format
 msgid "Broken configuration for playback: no configurations available: %s\n"
 msgstr "再生用に設定できません: 設定がみつかりません: %s\n"
 
-#: speaker-test/speaker-test.c:347
+#: speaker-test/speaker-test.c:324
 #, c-format
 msgid "Access type not available for playback: %s\n"
 msgstr "アクセスタイプが不正です: %s\n"
 
-#: speaker-test/speaker-test.c:354
+#: speaker-test/speaker-test.c:331
 #, c-format
 msgid "Sample format not available for playback: %s\n"
 msgstr "指定のサンプルフォーマットを使用できません: %s\n"
 
-#: speaker-test/speaker-test.c:361
+#: speaker-test/speaker-test.c:338
 #, c-format
 msgid "Channels count (%i) not available for playbacks: %s\n"
 msgstr "チャネル数 (%i) を使用できません: %s\n"
 
-#: speaker-test/speaker-test.c:369
+#: speaker-test/speaker-test.c:346
 #, c-format
 msgid "Rate %iHz not available for playback: %s\n"
 msgstr "レート %iHz を使用できません: %s\n"
 
-#: speaker-test/speaker-test.c:374
+#: speaker-test/speaker-test.c:351
 #, c-format
 msgid "Rate doesn't match (requested %iHz, get %iHz, err %d)\n"
 msgstr "設定レートが一致しません< (要求値 %iHz, 取得値 %iHz, エラー %d)\n"
 
-#: speaker-test/speaker-test.c:378
+#: speaker-test/speaker-test.c:355
 #, c-format
 msgid "Rate set to %iHz (requested %iHz)\n"
 msgstr "レート %iHz (要求値 %iHz)\n"
 
-#: speaker-test/speaker-test.c:384
+#: speaker-test/speaker-test.c:361
 #, c-format
 msgid "Buffer size range from %lu to %lu\n"
 msgstr "バッファサイズ範囲 %lu 〜 %lu\n"
 
-#: speaker-test/speaker-test.c:385
+#: speaker-test/speaker-test.c:362
 #, c-format
 msgid "Period size range from %lu to %lu\n"
 msgstr "ピリオドサイズ範囲 %lu 〜 %lu\n"
 
-#: speaker-test/speaker-test.c:387
+#: speaker-test/speaker-test.c:364
 #, c-format
 msgid "Requested period time %u us\n"
 msgstr "要求されたピリオド長 %u us\n"
 
-#: speaker-test/speaker-test.c:390
+#: speaker-test/speaker-test.c:367
 #, c-format
 msgid "Unable to set period time %u us for playback: %s\n"
 msgstr "ピリオド長 %u us を設定できません: %s\n"
 
-#: speaker-test/speaker-test.c:396
+#: speaker-test/speaker-test.c:373
 #, c-format
 msgid "Requested buffer time %u us\n"
 msgstr "要求されたバッファ長 %u us\n"
 
-#: speaker-test/speaker-test.c:399
+#: speaker-test/speaker-test.c:376
 #, c-format
 msgid "Unable to set buffer time %u us for playback: %s\n"
 msgstr "バッファ長 %u us を設定できません: %s\n"
 
-#: speaker-test/speaker-test.c:408
+#: speaker-test/speaker-test.c:385
 #, c-format
 msgid "Using max buffer size %lu\n"
 msgstr "最大バッファサイズ %lu を使用\n"
 
-#: speaker-test/speaker-test.c:411
+#: speaker-test/speaker-test.c:388
 #, c-format
 msgid "Unable to set buffer size %lu for playback: %s\n"
 msgstr "バッファサイズ %lu を設定できません: %s\n"
 
-#: speaker-test/speaker-test.c:417
+#: speaker-test/speaker-test.c:394
 #, c-format
 msgid "Periods = %u\n"
 msgstr "ピリオド数 = %u\n"
 
-#: speaker-test/speaker-test.c:420
+#: speaker-test/speaker-test.c:397
 #, c-format
 msgid "Unable to set nperiods %u for playback: %s\n"
 msgstr "ピリオド数 %u を設定できません: %s\n"
 
-#: speaker-test/speaker-test.c:429
+#: speaker-test/speaker-test.c:406
 #, c-format
 msgid "Unable to set hw params for playback: %s\n"
 msgstr "hw params を設定できません: %s\n"
 
-#: speaker-test/speaker-test.c:435
+#: speaker-test/speaker-test.c:412
 #, c-format
 msgid "was set period_size = %lu\n"
 msgstr "period_size = %lu で設定\n"
 
-#: speaker-test/speaker-test.c:436
+#: speaker-test/speaker-test.c:413
 #, c-format
 msgid "was set buffer_size = %lu\n"
 msgstr "buffer_size = %lu で設定\n"
 
-#: speaker-test/speaker-test.c:438
+#: speaker-test/speaker-test.c:415
 #, c-format
 msgid "buffer to small, could not use\n"
 msgstr "バッファが小さすぎます\n"
 
-#: speaker-test/speaker-test.c:451
+#: speaker-test/speaker-test.c:428
 #, c-format
 msgid "Unable to determine current swparams for playback: %s\n"
 msgstr "現在の swparams を取得できません: %s\n"
 
-#: speaker-test/speaker-test.c:458
+#: speaker-test/speaker-test.c:435
 #, c-format
 msgid "Unable to set start threshold mode for playback: %s\n"
 msgstr "start_threshold モードを設定できません: %s\n"
 
-#: speaker-test/speaker-test.c:465
+#: speaker-test/speaker-test.c:442
 #, c-format
 msgid "Unable to set avail min for playback: %s\n"
 msgstr "avail_min を設定できません: %s\n"
 
-#: speaker-test/speaker-test.c:472
+#: speaker-test/speaker-test.c:449
 #, c-format
 msgid "Unable to set sw params for playback: %s\n"
 msgstr "再生用の sw params を設定できません: %s\n"
 
-#: speaker-test/speaker-test.c:487
+#: speaker-test/speaker-test.c:464
 #, c-format
 msgid "Can't recovery from underrun, prepare failed: %s\n"
 msgstr "アンダーランから復帰失敗: %s\n"
 
-#: speaker-test/speaker-test.c:498
+#: speaker-test/speaker-test.c:475
 #, c-format
 msgid "Can't recovery from suspend, prepare failed: %s\n"
 msgstr "サスペンドから復帰失敗: %s\n"
 
-#: speaker-test/speaker-test.c:572 speaker-test/speaker-test.c:969
+#: speaker-test/speaker-test.c:539 speaker-test/speaker-test.c:954
 #, c-format
 msgid "No enough memory\n"
 msgstr "メモリが足りません\n"
 
-#: speaker-test/speaker-test.c:577
+#: speaker-test/speaker-test.c:544
 #, c-format
 msgid "Cannot open WAV file %s\n"
 msgstr "WAVファイルがオープンできません: %s\n"
 
-#: speaker-test/speaker-test.c:581 speaker-test/speaker-test.c:610
+#: speaker-test/speaker-test.c:548 speaker-test/speaker-test.c:577
 #, c-format
 msgid "Invalid WAV file %s\n"
 msgstr "不正なWAVファイルです: %s\n"
 
-#: speaker-test/speaker-test.c:586
+#: speaker-test/speaker-test.c:553
 #, c-format
 msgid "Not a WAV file: %s\n"
 msgstr "WAVファイルではありません: %s\n"
 
-#: speaker-test/speaker-test.c:590
+#: speaker-test/speaker-test.c:557
 #, c-format
 msgid "Unsupported WAV format %d for %s\n"
 msgstr "未サポートのWAVフォーマット %d: %s\n"
 
-#: speaker-test/speaker-test.c:595
+#: speaker-test/speaker-test.c:562
 #, c-format
 msgid "%s is not a mono stream (%d channels)\n"
 msgstr "%s はモノストリームではありません (%d チャネル)\n"
 
-#: speaker-test/speaker-test.c:600
+#: speaker-test/speaker-test.c:567
 #, c-format
 msgid "Sample rate doesn't match (%d) for %s\n"
 msgstr "サンプルレートが不一致です(%d): %s\n"
 
-#: speaker-test/speaker-test.c:605
+#: speaker-test/speaker-test.c:572
 #, c-format
 msgid "Unsupported sample format bits %d for %s\n"
 msgstr "未サポートのサンプルフォーマットビット %d: %s\n"
 
-#: speaker-test/speaker-test.c:655
+#: speaker-test/speaker-test.c:622
 #, c-format
 msgid "Undefined channel %d\n"
 msgstr "未定義のチャネル %d\n"
 
-#: speaker-test/speaker-test.c:706
+#: speaker-test/speaker-test.c:673
 #, c-format
 msgid "Write error: %d,%s\n"
 msgstr "書込エラー: %d,%s\n"
 
-#: speaker-test/speaker-test.c:708
+#: speaker-test/speaker-test.c:675
 #, c-format
 msgid "xrun_recovery failed: %d,%s\n"
 msgstr "xrun_recovery 失敗: %d,%s\n"
 
-#: speaker-test/speaker-test.c:766
+#: speaker-test/speaker-test.c:734
 #, c-format
 msgid ""
 "Usage: speaker-test [OPTION]... \n"
@@ -1085,93 +1459,72 @@ msgstr ""
 "-W,--wavdir          WAVファイルのあるディレクトリを指定\n"
 "\n"
 
-#: speaker-test/speaker-test.c:878
+#: speaker-test/speaker-test.c:852
 #, c-format
 msgid "Invalid number of periods %d\n"
 msgstr "不正なピリオド数 %d\n"
 
-#: speaker-test/speaker-test.c:892 speaker-test/speaker-test.c:896
+#: speaker-test/speaker-test.c:866 speaker-test/speaker-test.c:870
 #, c-format
 msgid "Invalid test type %s\n"
 msgstr "不正なテストタイプ %s\n"
 
-#: speaker-test/speaker-test.c:908
+#: speaker-test/speaker-test.c:882
 #, c-format
 msgid "Invalid parameter for -s option.\n"
 msgstr "-s オプションの値が不正です\n"
 
-#: speaker-test/speaker-test.c:919
+#: speaker-test/speaker-test.c:896
 #, c-format
 msgid "Unknown option '%c'\n"
 msgstr "未知のオプション '%c'\n"
 
-#: speaker-test/speaker-test.c:933
+#: speaker-test/speaker-test.c:910
 #, c-format
 msgid "Playback device is %s\n"
 msgstr "再生デバイス: %s\n"
 
-#: speaker-test/speaker-test.c:934
+#: speaker-test/speaker-test.c:911
 #, c-format
 msgid "Stream parameters are %iHz, %s, %i channels\n"
 msgstr "ストリームパラメータ: %iHz, %s, %i チャネル\n"
 
-#: speaker-test/speaker-test.c:937
+#: speaker-test/speaker-test.c:914
 #, c-format
 msgid "Using 16 octaves of pink noise\n"
 msgstr "16 オクターブのピンクノイズを使用\n"
 
-#: speaker-test/speaker-test.c:940
+#: speaker-test/speaker-test.c:917
 #, c-format
 msgid "Sine wave rate is %.4fHz\n"
 msgstr "正弦波レート: %.4fHz\n"
 
-#: speaker-test/speaker-test.c:943
+#: speaker-test/speaker-test.c:920
 #, c-format
 msgid "WAV file(s)\n"
 msgstr "WAV ファイル\n"
 
-#: speaker-test/speaker-test.c:949
+#: speaker-test/speaker-test.c:926
 #, c-format
 msgid "Playback open error: %d,%s\n"
 msgstr "再生オープンエラー: %d,%s\n"
 
-#: speaker-test/speaker-test.c:954
+#: speaker-test/speaker-test.c:931
 #, c-format
 msgid "Setting of hwparams failed: %s\n"
 msgstr "hwparams の設定に失敗: %s\n"
 
-#: speaker-test/speaker-test.c:959
+#: speaker-test/speaker-test.c:936
 #, c-format
 msgid "Setting of swparams failed: %s\n"
 msgstr "swparams の設定に失敗: %s\n"
 
-#: speaker-test/speaker-test.c:1000 speaker-test/speaker-test.c:1022
+#: speaker-test/speaker-test.c:985 speaker-test/speaker-test.c:1007
 #, c-format
 msgid "Transfer failed: %s\n"
 msgstr "転送に失敗しました: %s\n"
 
-#: speaker-test/speaker-test.c:1010
+#: speaker-test/speaker-test.c:995
 #, c-format
 msgid "Time per period = %lf\n"
 msgstr "ピリオド時間 = %lf\n"
-
-#~ msgid "can't play not PCM-coded WAVE-files"
-#~ msgstr "PCM 以外の WAVE ファイルは再生できません"
-
-#~ msgid "Unable to obtain xfer align\n"
-#~ msgstr "xfer align 値を得ることができません\n"
-
-#~ msgid "Unable to set transfer align for playback: %s\n"
-#~ msgstr "転送 align を設定できません: %s\n"
-
-#~ msgid "snd_names_list error: %s"
-#~ msgstr "snd_names_list エラー: %s"
-
-#~ msgid "PCM list:\n"
-#~ msgstr "PCM リスト:\n"
-
-#~ msgid "Output failed: %s\n"
-#~ msgstr "出力失敗: %s\n"
-
-#~ msgid "Pausing\n"
-#~ msgstr "停止中\n"
index 8c7c0ba..f43af5a 100644 (file)
@@ -94,6 +94,14 @@ EXEEXT = @EXEEXT@
 GMSGFMT = @GMSGFMT@
 GMSGFMT_015 = @GMSGFMT_015@
 GREP = @GREP@
+HAVE_MIXER_FALSE = @HAVE_MIXER_FALSE@
+HAVE_MIXER_TRUE = @HAVE_MIXER_TRUE@
+HAVE_PCM_FALSE = @HAVE_PCM_FALSE@
+HAVE_PCM_TRUE = @HAVE_PCM_TRUE@
+HAVE_RAWMIDI_FALSE = @HAVE_RAWMIDI_FALSE@
+HAVE_RAWMIDI_TRUE = @HAVE_RAWMIDI_TRUE@
+HAVE_SEQ_FALSE = @HAVE_SEQ_FALSE@
+HAVE_SEQ_TRUE = @HAVE_SEQ_TRUE@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -104,6 +112,7 @@ LDFLAGS = @LDFLAGS@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
 LIBOBJS = @LIBOBJS@
+LIBRT = @LIBRT@
 LIBS = @LIBS@
 LN_S = @LN_S@
 LTLIBICONV = @LTLIBICONV@
index ccf0aeb..d754476 100644 (file)
@@ -107,6 +107,14 @@ EXEEXT = @EXEEXT@
 GMSGFMT = @GMSGFMT@
 GMSGFMT_015 = @GMSGFMT_015@
 GREP = @GREP@
+HAVE_MIXER_FALSE = @HAVE_MIXER_FALSE@
+HAVE_MIXER_TRUE = @HAVE_MIXER_TRUE@
+HAVE_PCM_FALSE = @HAVE_PCM_FALSE@
+HAVE_PCM_TRUE = @HAVE_PCM_TRUE@
+HAVE_RAWMIDI_FALSE = @HAVE_RAWMIDI_FALSE@
+HAVE_RAWMIDI_TRUE = @HAVE_RAWMIDI_TRUE@
+HAVE_SEQ_FALSE = @HAVE_SEQ_FALSE@
+HAVE_SEQ_TRUE = @HAVE_SEQ_TRUE@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -117,6 +125,7 @@ LDFLAGS = @LDFLAGS@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
 LIBOBJS = @LIBOBJS@
+LIBRT = @LIBRT@
 LIBS = @LIBS@
 LN_S = @LN_S@
 LTLIBICONV = @LTLIBICONV@
index 1a50666..8c66cfd 100644 (file)
@@ -192,52 +192,33 @@ static void remove_connection(snd_seq_t *seq, snd_seq_client_info_t *cinfo,
                              snd_seq_port_info_t *pinfo, int count)
 {
        snd_seq_query_subscribe_t *query;
+       snd_seq_port_info_t *port;
+       snd_seq_port_subscribe_t *subs;
 
        snd_seq_query_subscribe_alloca(&query);
        snd_seq_query_subscribe_set_root(query, snd_seq_port_info_get_addr(pinfo));
-
        snd_seq_query_subscribe_set_type(query, SND_SEQ_QUERY_SUBS_READ);
        snd_seq_query_subscribe_set_index(query, 0);
-       for (; snd_seq_query_port_subscribers(seq, query) >= 0;
-            snd_seq_query_subscribe_set_index(query, snd_seq_query_subscribe_get_index(query) + 1)) {
-               snd_seq_port_info_t *port;
-               snd_seq_port_subscribe_t *subs;
+
+       snd_seq_port_info_alloca(&port);
+       snd_seq_port_subscribe_alloca(&subs);
+
+       while (snd_seq_query_port_subscribers(seq, query) >= 0) {
                const snd_seq_addr_t *sender = snd_seq_query_subscribe_get_root(query);
                const snd_seq_addr_t *dest = snd_seq_query_subscribe_get_addr(query);
-               snd_seq_port_info_alloca(&port);
-               if (snd_seq_get_any_port_info(seq, dest->client, dest->port, port) < 0)
-                       continue;
-               if (!(snd_seq_port_info_get_capability(port) & SND_SEQ_PORT_CAP_SUBS_WRITE))
-                       continue;
-               if (snd_seq_port_info_get_capability(port) & SND_SEQ_PORT_CAP_NO_EXPORT)
-                       continue;
-               snd_seq_port_subscribe_alloca(&subs);
-               snd_seq_port_subscribe_set_queue(subs, snd_seq_query_subscribe_get_queue(query));
-               snd_seq_port_subscribe_set_sender(subs, sender);
-               snd_seq_port_subscribe_set_dest(subs, dest);
-               snd_seq_unsubscribe_port(seq, subs);
-       }
 
-       snd_seq_query_subscribe_set_type(query, SND_SEQ_QUERY_SUBS_WRITE);
-       snd_seq_query_subscribe_set_index(query, 0);
-       for (; snd_seq_query_port_subscribers(seq, query) >= 0;
-            snd_seq_query_subscribe_set_index(query, snd_seq_query_subscribe_get_index(query) + 1)) {
-               snd_seq_port_info_t *port;
-               snd_seq_port_subscribe_t *subs;
-               const snd_seq_addr_t *dest = snd_seq_query_subscribe_get_root(query);
-               const snd_seq_addr_t *sender = snd_seq_query_subscribe_get_addr(query);
-               snd_seq_port_info_alloca(&port);
-               if (snd_seq_get_any_port_info(seq, sender->client, sender->port, port) < 0)
-                       continue;
-               if (!(snd_seq_port_info_get_capability(port) & SND_SEQ_PORT_CAP_SUBS_READ))
+               if (snd_seq_get_any_port_info(seq, dest->client, dest->port, port) < 0 ||
+                   !(snd_seq_port_info_get_capability(port) & SND_SEQ_PORT_CAP_SUBS_WRITE) ||
+                   (snd_seq_port_info_get_capability(port) & SND_SEQ_PORT_CAP_NO_EXPORT)) {
+                       snd_seq_query_subscribe_set_index(query, snd_seq_query_subscribe_get_index(query) + 1);
                        continue;
-               if (snd_seq_port_info_get_capability(port) & SND_SEQ_PORT_CAP_NO_EXPORT)
-                       continue;
-               snd_seq_port_subscribe_alloca(&subs);
+               }
                snd_seq_port_subscribe_set_queue(subs, snd_seq_query_subscribe_get_queue(query));
                snd_seq_port_subscribe_set_sender(subs, sender);
                snd_seq_port_subscribe_set_dest(subs, dest);
-               snd_seq_unsubscribe_port(seq, subs);
+               if (snd_seq_unsubscribe_port(seq, subs) < 0) {
+                       snd_seq_query_subscribe_set_index(query, snd_seq_query_subscribe_get_index(query) + 1);
+               }
        }
 }
 
index 4e623db..aedeaa8 100644 (file)
@@ -108,6 +108,14 @@ EXEEXT = @EXEEXT@
 GMSGFMT = @GMSGFMT@
 GMSGFMT_015 = @GMSGFMT_015@
 GREP = @GREP@
+HAVE_MIXER_FALSE = @HAVE_MIXER_FALSE@
+HAVE_MIXER_TRUE = @HAVE_MIXER_TRUE@
+HAVE_PCM_FALSE = @HAVE_PCM_FALSE@
+HAVE_PCM_TRUE = @HAVE_PCM_TRUE@
+HAVE_RAWMIDI_FALSE = @HAVE_RAWMIDI_FALSE@
+HAVE_RAWMIDI_TRUE = @HAVE_RAWMIDI_TRUE@
+HAVE_SEQ_FALSE = @HAVE_SEQ_FALSE@
+HAVE_SEQ_TRUE = @HAVE_SEQ_TRUE@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -118,6 +126,7 @@ LDFLAGS = @LDFLAGS@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
 LIBOBJS = @LIBOBJS@
+LIBRT = @LIBRT@
 LIBS = @LIBS@
 LN_S = @LN_S@
 LTLIBICONV = @LTLIBICONV@
index 5ed7bab..ad508b3 100644 (file)
 #include "aconfig.h"
 #include "version.h"
 
-#define MIDI_BYTES_PER_SEC 3125
+/*
+ * 31.25 kbaud, one start bit, eight data bits, two stop bits.
+ * (The MIDI spec says one stop bit, but every transmitter uses two, just to be
+ * sure, so we better not exceed that to avoid overflowing the output buffer.)
+ */
+#define MIDI_BYTES_PER_SEC (31250 / (1 + 8 + 2))
 
 /*
  * A MIDI event after being parsed/loaded from the file.
index f2971a5..e827601 100644 (file)
@@ -105,6 +105,14 @@ EXEEXT = @EXEEXT@
 GMSGFMT = @GMSGFMT@
 GMSGFMT_015 = @GMSGFMT_015@
 GREP = @GREP@
+HAVE_MIXER_FALSE = @HAVE_MIXER_FALSE@
+HAVE_MIXER_TRUE = @HAVE_MIXER_TRUE@
+HAVE_PCM_FALSE = @HAVE_PCM_FALSE@
+HAVE_PCM_TRUE = @HAVE_PCM_TRUE@
+HAVE_RAWMIDI_FALSE = @HAVE_RAWMIDI_FALSE@
+HAVE_RAWMIDI_TRUE = @HAVE_RAWMIDI_TRUE@
+HAVE_SEQ_FALSE = @HAVE_SEQ_FALSE@
+HAVE_SEQ_TRUE = @HAVE_SEQ_TRUE@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -115,6 +123,7 @@ LDFLAGS = @LDFLAGS@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
 LIBOBJS = @LIBOBJS@
+LIBRT = @LIBRT@
 LIBS = @LIBS@
 LN_S = @LN_S@
 LTLIBICONV = @LTLIBICONV@
index 9169d65..42fdc74 100644 (file)
@@ -106,6 +106,14 @@ EXEEXT = @EXEEXT@
 GMSGFMT = @GMSGFMT@
 GMSGFMT_015 = @GMSGFMT_015@
 GREP = @GREP@
+HAVE_MIXER_FALSE = @HAVE_MIXER_FALSE@
+HAVE_MIXER_TRUE = @HAVE_MIXER_TRUE@
+HAVE_PCM_FALSE = @HAVE_PCM_FALSE@
+HAVE_PCM_TRUE = @HAVE_PCM_TRUE@
+HAVE_RAWMIDI_FALSE = @HAVE_RAWMIDI_FALSE@
+HAVE_RAWMIDI_TRUE = @HAVE_RAWMIDI_TRUE@
+HAVE_SEQ_FALSE = @HAVE_SEQ_FALSE@
+HAVE_SEQ_TRUE = @HAVE_SEQ_TRUE@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -116,6 +124,7 @@ LDFLAGS = @LDFLAGS@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
 LIBOBJS = @LIBOBJS@
+LIBRT = @LIBRT@
 LIBS = @LIBS@
 LN_S = @LN_S@
 LTLIBICONV = @LTLIBICONV@
index 2ad0c75..2718abe 100644 (file)
@@ -114,6 +114,14 @@ EXEEXT = @EXEEXT@
 GMSGFMT = @GMSGFMT@
 GMSGFMT_015 = @GMSGFMT_015@
 GREP = @GREP@
+HAVE_MIXER_FALSE = @HAVE_MIXER_FALSE@
+HAVE_MIXER_TRUE = @HAVE_MIXER_TRUE@
+HAVE_PCM_FALSE = @HAVE_PCM_FALSE@
+HAVE_PCM_TRUE = @HAVE_PCM_TRUE@
+HAVE_RAWMIDI_FALSE = @HAVE_RAWMIDI_FALSE@
+HAVE_RAWMIDI_TRUE = @HAVE_RAWMIDI_TRUE@
+HAVE_SEQ_FALSE = @HAVE_SEQ_FALSE@
+HAVE_SEQ_TRUE = @HAVE_SEQ_TRUE@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -124,6 +132,7 @@ LDFLAGS = @LDFLAGS@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
 LIBOBJS = @LIBOBJS@
+LIBRT = @LIBRT@
 LIBS = @LIBS@
 LN_S = @LN_S@
 LTLIBICONV = @LTLIBICONV@
index 2240d2e..44109d5 100644 (file)
@@ -96,6 +96,14 @@ EXEEXT = @EXEEXT@
 GMSGFMT = @GMSGFMT@
 GMSGFMT_015 = @GMSGFMT_015@
 GREP = @GREP@
+HAVE_MIXER_FALSE = @HAVE_MIXER_FALSE@
+HAVE_MIXER_TRUE = @HAVE_MIXER_TRUE@
+HAVE_PCM_FALSE = @HAVE_PCM_FALSE@
+HAVE_PCM_TRUE = @HAVE_PCM_TRUE@
+HAVE_RAWMIDI_FALSE = @HAVE_RAWMIDI_FALSE@
+HAVE_RAWMIDI_TRUE = @HAVE_RAWMIDI_TRUE@
+HAVE_SEQ_FALSE = @HAVE_SEQ_FALSE@
+HAVE_SEQ_TRUE = @HAVE_SEQ_TRUE@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -106,6 +114,7 @@ LDFLAGS = @LDFLAGS@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
 LIBOBJS = @LIBOBJS@
+LIBRT = @LIBRT@
 LIBS = @LIBS@
 LN_S = @LN_S@
 LTLIBICONV = @LTLIBICONV@
index 75a4bed..d8d68e2 100644 (file)
@@ -68,6 +68,20 @@ enum {
 
 #define MAX_CHANNELS   16
 
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define COMPOSE_ID(a,b,c,d)    ((a) | ((b)<<8) | ((c)<<16) | ((d)<<24))
+#define LE_SHORT(v)            (v)
+#define LE_INT(v)              (v)
+#define BE_SHORT(v)            bswap_16(v)
+#define BE_INT(v)              bswap_32(v)
+#else /* __BIG_ENDIAN */
+#define COMPOSE_ID(a,b,c,d)    ((d) | ((c)<<8) | ((b)<<16) | ((a)<<24))
+#define LE_SHORT(v)            bswap_16(v)
+#define LE_INT(v)              bswap_32(v)
+#define BE_SHORT(v)            (v)
+#define BE_INT(v)              (v)
+#endif
+
 static char              *device      = "default";       /* playback device */
 static snd_pcm_format_t   format      = SND_PCM_FORMAT_S16; /* sample format */
 static unsigned int       rate        = 48000;             /* stream rate */
@@ -76,57 +90,67 @@ static unsigned int       speaker     = 0;              /* count of channels */
 static unsigned int       buffer_time = 0;                 /* ring buffer length in us */
 static unsigned int       period_time = 0;                 /* period time in us */
 static unsigned int       nperiods    = 4;                  /* number of periods */
-static double             freq        = 440;                /* sinusoidal wave frequency in Hz */
+static double             freq        = 440.0;              /* sinusoidal wave frequency in Hz */
 static int                test_type   = TEST_PINK_NOISE;    /* Test type. 1 = noise, 2 = sine wave */
 static pink_noise_t pink;
 static snd_pcm_uframes_t  buffer_size;
 static snd_pcm_uframes_t  period_size;
 static const char *given_test_wav_file = NULL;
 static char *wav_file_dir = SOUNDSDIR;
+static int debug = 0;
 
 static const char *const channel_name[MAX_CHANNELS] = {
-  N_("Front Left"),
-  N_("Front Right"),
-  N_("Rear Left"),
-  N_("Rear Right"),
-  N_("Center"),
-  N_("LFE"),
-  N_("Side Left"),
-  N_("Side Right"),
-  N_("Channel 9"),
-  N_("Channel 10"),
-  N_("Channel 11"),
-  N_("Channel 12"),
-  N_("Channel 13"),
-  N_("Channel 14"),
-  N_("Channel 15"),
-  N_("Channel 16")
+  /*  0 */ N_("Front Left"),
+  /*  1 */ N_("Front Right"),
+  /*  2 */ N_("Rear Left"),
+  /*  3 */ N_("Rear Right"),
+  /*  4 */ N_("Center"),
+  /*  5 */ N_("LFE"),
+  /*  6 */ N_("Side Left"),
+  /*  7 */ N_("Side Right"),
+  /*  8 */ N_("Channel 9"),
+  /*  9 */ N_("Channel 10"),
+  /* 10 */ N_("Channel 11"),
+  /* 11 */ N_("Channel 12"),
+  /* 12 */ N_("Channel 13"),
+  /* 13 */ N_("Channel 14"),
+  /* 14 */ N_("Channel 15"),
+  /* 15 */ N_("Channel 16")
 };
 
 static const int       channels4[] = {
-  0,
-  1,
-  3,
-  2
+  0, /* Front Left  */
+  1, /* Front Right */
+  3, /* Rear Right  */
+  2, /* Rear Left   */
 };
 static const int       channels6[] = {
-  0,
-  4,
-  1,
-  3,
-  2,
-  5
-}; 
+  0, /* Front Left  */
+  4, /* Center      */
+  1, /* Front Right */
+  3, /* Rear Right  */
+  2, /* Rear Left   */
+  5, /* LFE         */
+};
 static const int       channels8[] = {
-  0,
-  4,
-  1,
-  7,
-  3,
-  2,
-  6,
-  5
-}; 
+  0, /* Front Left  */
+  4, /* Center      */
+  1, /* Front Right */
+  7, /* Side Right  */
+  3, /* Rear Right  */
+  2, /* Rear Left   */
+  6, /* Side Left   */
+  5, /* LFE         */
+};
+static const int       supported_formats[] = {
+  SND_PCM_FORMAT_S8,
+  SND_PCM_FORMAT_S16_LE,
+  SND_PCM_FORMAT_S16_BE,
+  SND_PCM_FORMAT_FLOAT_LE,
+  SND_PCM_FORMAT_S32_LE,
+  SND_PCM_FORMAT_S32_BE,
+  -1
+};
 
 static void generate_sine(uint8_t *frames, int channel, int count, double *_phase) {
   double phase = *_phase;
@@ -142,17 +166,6 @@ static void generate_sine(uint8_t *frames, int channel, int count, double *_phas
   float   *samp_f = (float*) frames;
 
   while (count-- > 0) {
-    //res = sin((phase * 2 * M_PI) / max_phase - M_PI) * 32767;
-    //res = sin((phase * 2 * M_PI) / max_phase - M_PI) * 32767;
-    //res = (sin((phase * 2 * M_PI) / max_phase - M_PI)) * 0x03fffffff; /* Don't use MAX volume */
-    //if (res > 0) res = 10000;
-    //if (res < 0) res = -10000;
-
-    /* printf("%e\n",res); */
-    //ires = res;
-    //ires = ((16 - (count & 0xf)) <<24);
-    //ires = 0;
-
     for(chn=0;chn<channels;chn++) {
       switch (format) {
       case SND_PCM_FORMAT_S8:
@@ -168,11 +181,7 @@ static void generate_sine(uint8_t *frames, int channel, int count, double *_phas
         if (chn==channel) {
           res = (sin((phase * 2 * M_PI) / max_phase - M_PI)) * 0x03fffffff; /* Don't use MAX volume */
           ires = res;
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-          *samp16++ = ires >> 16;
-#elif __BYTE_ORDER == __BIG_ENDIAN
-          *samp16++ = bswap_16(ires >> 16);
-#endif
+          *samp16++ = LE_SHORT(ires >> 16);
         } else {
           *samp16++ = 0;
         }
@@ -181,11 +190,7 @@ static void generate_sine(uint8_t *frames, int channel, int count, double *_phas
         if (chn==channel) {
           res = (sin((phase * 2 * M_PI) / max_phase - M_PI)) * 0x03fffffff; /* Don't use MAX volume */
           ires = res;
-#if __BYTE_ORDER == __BIG_ENDIAN
-          *samp16++ = ires >> 16;
-#elif __BYTE_ORDER == __LITTLE_ENDIAN
-          *samp16++ = bswap_16(ires >> 16);
-#endif
+          *samp16++ = BE_SHORT(ires >> 16);
         } else {
           *samp16++ = 0;
         }
@@ -195,11 +200,7 @@ static void generate_sine(uint8_t *frames, int channel, int count, double *_phas
           res = (sin((phase * 2 * M_PI) / max_phase - M_PI)) * 0.75 ; /* Don't use MAX volume */
           fres = res;
          *samp_f++ = fres;
-         //*samp32++ = 0xF2345678;
-       //printf("res=%lf, ires=%d 0x%x, samp32=0x%x\n",res,ires, ires, samp32[-1]);
         } else {
-         //*samp32++ = ires+0x10000;
-         //*samp32++ = ires;
          *samp_f++ = 0.0;
         }
         break;
@@ -207,11 +208,7 @@ static void generate_sine(uint8_t *frames, int channel, int count, double *_phas
         if (chn==channel) {
           res = (sin((phase * 2 * M_PI) / max_phase - M_PI)) * 0x03fffffff; /* Don't use MAX volume */
           ires = res;
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-          *samp32++ = ires;
-#elif __BYTE_ORDER == __BIG_ENDIAN
-          *samp32++ = bswap_32(ires);
-#endif
+          *samp32++ = LE_INT(ires);
         } else {
           *samp32++ = 0;
         }
@@ -220,11 +217,7 @@ static void generate_sine(uint8_t *frames, int channel, int count, double *_phas
         if (chn==channel) {
           res = (sin((phase * 2 * M_PI) / max_phase - M_PI)) * 0x03fffffff; /* Don't use MAX volume */
           ires = res;
-#if __BYTE_ORDER == __BIG_ENDIAN
-          *samp32++ = ires;
-#elif __BYTE_ORDER == __LITTLE_ENDIAN
-          *samp32++ = bswap_32(ires);
-#endif
+          *samp32++ = BE_INT(ires);
         } else {
           *samp32++ = 0;
         }
@@ -271,11 +264,7 @@ static void generate_pink_noise( uint8_t *frames, int channel, int count) {
         if (chn==channel) {
          res = generate_pink_noise_sample(&pink) * 0x03fffffff; /* Don't use MAX volume */
          ires = res;
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-          *samp16++ = ires >> 16;
-#elif __BYTE_ORDER == __BIG_ENDIAN
-          *samp16++ = bswap_16(ires >> 16);
-#endif
+          *samp16++ = LE_SHORT(ires >> 16);
         } else {
          *samp16++ = 0;
         }
@@ -284,11 +273,7 @@ static void generate_pink_noise( uint8_t *frames, int channel, int count) {
         if (chn==channel) {
           res = generate_pink_noise_sample(&pink) * 0x03fffffff; /* Don't use MAX volume */
           ires = res;
-#if __BYTE_ORDER == __BIG_ENDIAN
-          *samp16++ = ires >> 16;
-#elif __BYTE_ORDER == __LITTLE_ENDIAN
-          *samp16++ = bswap_16(ires >> 16);
-#endif
+          *samp16++ = BE_SHORT(ires >> 16);
         } else {
           *samp16++ = 0;
         }
@@ -297,11 +282,7 @@ static void generate_pink_noise( uint8_t *frames, int channel, int count) {
         if (chn==channel) {
           res = generate_pink_noise_sample(&pink) * 0x03fffffff; /* Don't use MAX volume */
           ires = res;
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-          *samp32++ = ires;
-#elif __BYTE_ORDER == __BIG_ENDIAN
-          *samp32++ = bswap_32(ires);
-#endif
+          *samp32++ = LE_INT(ires);
         } else {
           *samp32++ = 0;
         }
@@ -310,11 +291,7 @@ static void generate_pink_noise( uint8_t *frames, int channel, int count) {
         if (chn==channel) {
          res = generate_pink_noise_sample(&pink) * 0x03fffffff; /* Don't use MAX volume */
          ires = res;
-#if __BYTE_ORDER == __BIG_ENDIAN
-         *samp32++ = ires;
-#elif __BYTE_ORDER == __LITTLE_ENDIAN
-          *samp32++ = bswap_32(ires);
-#endif
+         *samp32++ = BE_INT(ires);
         } else {
          *samp32++ = 0;
         }
@@ -535,16 +512,6 @@ struct wave_header {
   } chunk;
 };
 
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-#define COMPOSE_ID(a,b,c,d)    ((a) | ((b)<<8) | ((c)<<16) | ((d)<<24))
-#define LE_SHORT(v)            (v)
-#define LE_INT(v)              (v)
-#else
-#define COMPOSE_ID(a,b,c,d)    ((d) | ((c)<<8) | ((b)<<16) | ((a)<<24))
-#define LE_SHORT(v)            bswap_16(v)
-#define LE_INT(v)              bswap_32(v)
-#endif
-
 #define WAV_RIFF               COMPOSE_ID('R','I','F','F')
 #define WAV_WAVE               COMPOSE_ID('W','A','V','E')
 #define WAV_FMT                        COMPOSE_ID('f','m','t',' ')
@@ -722,6 +689,7 @@ static int write_loop(snd_pcm_t *handle, int channel, int periods, uint8_t *fram
   double phase = 0;
   int    err, n;
 
+  fflush(stdout);
   if (test_type == TEST_WAV) {
     int bufsize = snd_pcm_frames_to_bytes(handle, period_size);
     n = 0;
@@ -760,7 +728,7 @@ static int write_loop(snd_pcm_t *handle, int channel, int periods, uint8_t *fram
 
 static void help(void)
 {
-  int k;
+  const int *fmt;
 
   printf(
         _("Usage: speaker-test [OPTION]... \n"
@@ -779,17 +747,14 @@ static void help(void)
           "-w,--wavfile        Use the given WAV file as a test sound\n"
           "-W,--wavdir Specify the directory containing WAV files\n"
           "\n"));
-#if 1
   printf(_("Recognized sample formats are:"));
-  for (k = 0; k < SND_PCM_FORMAT_LAST; ++k) {
-    const char *s = snd_pcm_format_name(k);
+  for (fmt = supported_formats; *fmt >= 0; fmt++) {
+    const char *s = snd_pcm_format_name(*fmt);
     if (s)
       printf(" %s", s);
   }
 
   printf("\n\n");
-#endif
-
 }
 
 int main(int argc, char *argv[]) {
@@ -799,6 +764,7 @@ int main(int argc, char *argv[]) {
   snd_pcm_sw_params_t  *swparams;
   uint8_t              *frames;
   int                   chn;
+  const int           *fmt;
   double               time1,time2,time3;
   unsigned int         n, nloops;
   struct   timeval     tv1,tv2;
@@ -818,6 +784,7 @@ int main(int argc, char *argv[]) {
     {"speaker",   1, NULL, 's'},
     {"wavfile",   1, NULL, 'w'},
     {"wavdir",    1, NULL, 'W'},
+    {"debug",    0, NULL, 'd'},
     {NULL,        0, NULL, 0  },
   };
 
@@ -836,7 +803,7 @@ int main(int argc, char *argv[]) {
   while (1) {
     int c;
     
-    if ((c = getopt_long(argc, argv, "hD:r:c:f:F:b:p:P:t:l:s:w:W:", long_option, NULL)) < 0)
+    if ((c = getopt_long(argc, argv, "hD:r:c:f:F:b:p:P:t:l:s:w:W:d", long_option, NULL)) < 0)
       break;
     
     switch (c) {
@@ -848,6 +815,13 @@ int main(int argc, char *argv[]) {
       break;
     case 'F':
       format = snd_pcm_format_value(optarg);
+      for (fmt = supported_formats; *fmt >= 0; fmt++)
+        if (*fmt == format)
+          break;
+      if (*fmt < 0) {
+        fprintf(stderr, "Format %s is not supported...\n", snd_pcm_format_name(format));
+        exit(EXIT_FAILURE);
+      }
       break;
     case 'r':
       rate = atoi(optarg);
@@ -860,9 +834,9 @@ int main(int argc, char *argv[]) {
       channels = channels > 1024 ? 1024 : channels;
       break;
     case 'f':
-      freq = atoi(optarg);
-      freq = freq < 50 ? 50 : freq;
-      freq = freq > 5000 ? 5000 : freq;
+      freq = atof(optarg);
+      freq = freq < 30.0 ? 30.0 : freq;
+      freq = freq > 5000.0 ? 5000.0 : freq;
       break;
     case 'b':
       buffer_time = atoi(optarg);
@@ -915,6 +889,9 @@ int main(int argc, char *argv[]) {
     case 'W':
       wav_file_dir = optarg;
       break;
+    case 'd':
+      debug = 1;
+      break;
     default:
       fprintf(stderr, _("Unknown option '%c'\n"), c);
       exit(EXIT_FAILURE);
@@ -960,6 +937,14 @@ int main(int argc, char *argv[]) {
     snd_pcm_close(handle);
     exit(EXIT_FAILURE);
   }
+  if (debug) {
+    snd_output_t *log;
+    err = snd_output_stdio_attach(&log, stderr, 0);
+    if (err >= 0) {
+      snd_pcm_dump(handle, log);
+      snd_output_close(log);
+    }
+  }
 
   frames = malloc(snd_pcm_frames_to_bytes(handle, period_size));
   if (test_type == TEST_PINK_NOISE)
index f337a26..ed2acd3 100644 (file)
@@ -86,6 +86,14 @@ EXEEXT = @EXEEXT@
 GMSGFMT = @GMSGFMT@
 GMSGFMT_015 = @GMSGFMT_015@
 GREP = @GREP@
+HAVE_MIXER_FALSE = @HAVE_MIXER_FALSE@
+HAVE_MIXER_TRUE = @HAVE_MIXER_TRUE@
+HAVE_PCM_FALSE = @HAVE_PCM_FALSE@
+HAVE_PCM_TRUE = @HAVE_PCM_TRUE@
+HAVE_RAWMIDI_FALSE = @HAVE_RAWMIDI_FALSE@
+HAVE_RAWMIDI_TRUE = @HAVE_RAWMIDI_TRUE@
+HAVE_SEQ_FALSE = @HAVE_SEQ_FALSE@
+HAVE_SEQ_TRUE = @HAVE_SEQ_TRUE@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -96,6 +104,7 @@ LDFLAGS = @LDFLAGS@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
 LIBOBJS = @LIBOBJS@
+LIBRT = @LIBRT@
 LIBS = @LIBS@
 LN_S = @LN_S@
 LTLIBICONV = @LTLIBICONV@