aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean McNeil <sean.mcneil@windriver.com>2010-07-02 16:53:26 +0700
committerSean McNeil <sean.mcneil@windriver.com>2010-07-02 16:53:26 +0700
commit99c51181a747d47bb3d9daae822d07d66f1f0467 (patch)
tree48e33a53bf94b8f30758a69d957df088d1fca568
parentb8cab81b331395e706d9e4a9333538a07f9d7dc5 (diff)
downloadalsa-utils-99c51181a747d47bb3d9daae822d07d66f1f0467.tar.gz
Update alsa-utils to version 1.0.23.
Change-Id: I71d4636823c3ca585c2c8d3362ec9d227bda9e21
-rw-r--r--Makefile.am25
-rw-r--r--Makefile.in29
-rw-r--r--alsaconf/Makefile.in9
-rw-r--r--alsaconf/alsaconf.in21
-rw-r--r--alsactl/Makefile.in9
-rw-r--r--alsactl/alsactl.c7
-rw-r--r--alsactl/alsactl.h10
-rw-r--r--alsactl/alsactl_init.xml41
-rw-r--r--alsactl/init/00main5
-rw-r--r--alsactl/init/Makefile.in9
-rw-r--r--alsactl/init/default181
-rw-r--r--alsactl/init/hda9
-rw-r--r--alsactl/init/test32
-rw-r--r--alsactl/init_parse.c267
-rw-r--r--alsactl/init_utils_string.c11
-rw-r--r--alsactl/state.c22
-rw-r--r--alsactl/utils.c6
-rw-r--r--alsamixer/Makefile.am14
-rw-r--r--alsamixer/Makefile.in54
-rw-r--r--alsamixer/README84
-rw-r--r--alsamixer/alsamixer.132
-rw-r--r--alsamixer/alsamixer.c2408
-rw-r--r--alsamixer/card_select.c268
-rw-r--r--alsamixer/card_select.h7
-rw-r--r--alsamixer/cli.c135
-rw-r--r--alsamixer/colors.c119
-rw-r--r--alsamixer/colors.h33
-rw-r--r--alsamixer/device_name.c197
-rw-r--r--alsamixer/device_name.h6
-rw-r--r--alsamixer/die.c39
-rw-r--r--alsamixer/die.h7
-rw-r--r--alsamixer/mainloop.c135
-rw-r--r--alsamixer/mainloop.h10
-rw-r--r--alsamixer/mem.c68
-rw-r--r--alsamixer/mem.h11
-rw-r--r--alsamixer/mixer_controls.c521
-rw-r--r--alsamixer/mixer_controls.h37
-rw-r--r--alsamixer/mixer_display.c764
-rw-r--r--alsamixer/mixer_display.h10
-rw-r--r--alsamixer/mixer_widget.c680
-rw-r--r--alsamixer/mixer_widget.h36
-rw-r--r--alsamixer/proc_files.c169
-rw-r--r--alsamixer/proc_files.h6
-rw-r--r--alsamixer/textbox.c397
-rw-r--r--alsamixer/textbox.h10
-rw-r--r--alsamixer/utils.c111
-rw-r--r--alsamixer/utils.h10
-rw-r--r--alsamixer/widget.c140
-rw-r--r--alsamixer/widget.h33
-rw-r--r--amidi/Makefile.in9
-rw-r--r--amidi/amidi.c131
-rw-r--r--amixer/Makefile.in9
-rw-r--r--amixer/amixer.c23
-rw-r--r--aplay/Makefile.am4
-rw-r--r--aplay/Makefile.in13
-rw-r--r--aplay/aplay.191
-rw-r--r--aplay/aplay.c487
-rw-r--r--aplay/arecord.191
-rwxr-xr-xconfigure1274
-rw-r--r--configure.in129
-rw-r--r--iecset/Makefile.in9
-rw-r--r--include/Makefile.am2
-rw-r--r--include/Makefile.in11
-rw-r--r--include/aconfig.h.in60
-rw-r--r--include/gettext.h8
-rw-r--r--include/gettext_curses.h2
-rw-r--r--include/version.h4
-rw-r--r--m4/Makefile.in9
-rw-r--r--po/LINGUAS2
-rw-r--r--po/Makevars2
-rw-r--r--po/POTFILES.in8
-rw-r--r--po/alsa-utils.pot711
-rw-r--r--po/de.gmobin0 -> 25968 bytes
-rw-r--r--po/de.po1542
-rw-r--r--po/ja.gmobin19263 -> 24675 bytes
-rw-r--r--po/ja.po751
-rw-r--r--seq/Makefile.in9
-rw-r--r--seq/aconnect/Makefile.in9
-rw-r--r--seq/aconnect/aconnect.c49
-rw-r--r--seq/aplaymidi/Makefile.in9
-rw-r--r--seq/aplaymidi/aplaymidi.c7
-rw-r--r--seq/aseqdump/Makefile.in9
-rw-r--r--seq/aseqnet/Makefile.in9
-rw-r--r--speaker-test/Makefile.in9
-rw-r--r--speaker-test/samples/Makefile.in9
-rw-r--r--speaker-test/speaker-test.c209
-rw-r--r--utils/Makefile.in9
87 files changed, 9466 insertions, 3497 deletions
diff --git a/Makefile.am b/Makefile.am
index d28422a..69ce92c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -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
diff --git a/Makefile.in b/Makefile.in
index c8ec583..9d40dc8 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -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
diff --git a/alsaconf/Makefile.in b/alsaconf/Makefile.in
index 7d0b63c..11dcd36 100644
--- a/alsaconf/Makefile.in
+++ b/alsaconf/Makefile.in
@@ -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@
diff --git a/alsaconf/alsaconf.in b/alsaconf/alsaconf.in
index 6e9ff75..ccc1b37 100644
--- a/alsaconf/alsaconf.in
+++ b/alsaconf/alsaconf.in
@@ -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
diff --git a/alsactl/Makefile.in b/alsactl/Makefile.in
index 2d8fe45..7ba7c4a 100644
--- a/alsactl/Makefile.in
+++ b/alsactl/Makefile.in
@@ -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@
diff --git a/alsactl/alsactl.c b/alsactl/alsactl.c
index e0bc276..3b5dfda 100644
--- a/alsactl/alsactl.c
+++ b/alsactl/alsactl.c
@@ -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;
}
diff --git a/alsactl/alsactl.h b/alsactl/alsactl.h
index 89ad295..be90efb 100644
--- a/alsactl/alsactl.h
+++ b/alsactl/alsactl.h
@@ -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)
{
diff --git a/alsactl/alsactl_init.xml b/alsactl/alsactl_init.xml
index 0e0d46b..eefe9ef 100644
--- a/alsactl/alsactl_init.xml
+++ b/alsactl/alsactl_init.xml
@@ -270,6 +270,24 @@
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>
@@ -279,7 +297,7 @@
<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>
@@ -410,6 +428,15 @@
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>
@@ -439,7 +466,8 @@
<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>
@@ -462,7 +490,7 @@
<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>
@@ -553,6 +581,13 @@
</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>
diff --git a/alsactl/init/00main b/alsactl/init/00main
index 942f386..2d26bbf 100644
--- a/alsactl/init/00main
+++ b/alsactl/init/00main
@@ -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"
diff --git a/alsactl/init/Makefile.in b/alsactl/init/Makefile.in
index 1cabfb4..26e6f86 100644
--- a/alsactl/init/Makefile.in
+++ b/alsactl/init/Makefile.in
@@ -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@
diff --git a/alsactl/init/default b/alsactl/init/default
index 66692b3..35acfc3 100644
--- a/alsactl/init/default
+++ b/alsactl/init/default
@@ -10,108 +10,161 @@
# 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"
diff --git a/alsactl/init/hda b/alsactl/init/hda
index 43dfec2..a6919f1 100644
--- a/alsactl/init/hda
+++ b/alsactl/init/hda
@@ -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"
diff --git a/alsactl/init/test b/alsactl/init/test
index 26db2a3..56659f8 100644
--- a/alsactl/init/test
+++ b/alsactl/init/test
@@ -37,9 +37,9 @@ PRINT=" CTL{index}=\"$ctl{index}\"\n"
ERROR="Ignore following error:\n "
PROGRAM="__just_test"
-PRINT="__ctl_count test:\n"
-CTL{search}="mixer", CTL{name}="*Switch*", PROGRAM="__ctl_count", \
- PRINT=" *Switch* count result: $result\n"
+PRINT="CTL{do_count} test:\n"
+CTL{search}="mixer", CTL{name}="*Switch*", \
+ PRINT=" *Switch* count result: $ctl{do_count}\n"
PRINT="__ctl_search test:\n"
CTL{search}="mixer", CTL{name}="*Switch*", PROGRAM!="__ctl_search", GOTO="skip_switch_search"
@@ -60,7 +60,7 @@ PRINT=" CTL{name}=\"$ctl{name}\"\n"
PRINT=" CTL{index}=\"$ctl{index}\"\n"
PRINT="First ten elements:\n"
-CTL{search}="mixer", CTL{name}="*", PROGRAM!="__ctl_search 0", GOTO="skip_first_ten_search"
+CTL{search}="mixer", CTL{name}="*", CTL{do_search 0}!="1", GOTO="skip_first_ten_search"
PRINT=" Element #0:\n"
PRINT=" CTL{numid}=\"$ctl{numid}\"\n"
PRINT=" CTL{iface}=\"$ctl{iface}\"\n"
@@ -79,7 +79,7 @@ PRINT=" CTL{dBmin}=\"$ctl{dBmin}\"\n"
PRINT=" CTL{dBmax}=\"$ctl{dBmax}\"\n"
PRINT=" CTL{items}=\"$ctl{items}\"\n"
PRINT=" CTL{value}=\"$ctl{value}\"\n"
-CTL{search}="mixer", CTL{name}="*", PROGRAM!="__ctl_search 1", GOTO="skip_first_ten_search"
+CTL{search}="mixer", CTL{name}="*", CTL{do_search 1}!="1", GOTO="skip_first_ten_search"
PRINT=" Element #1:\n"
PRINT=" CTL{numid}=\"$ctl{numid}\"\n"
PRINT=" CTL{iface}=\"$ctl{iface}\"\n"
@@ -98,7 +98,7 @@ PRINT=" CTL{dBmin}=\"$ctl{dBmin}\"\n"
PRINT=" CTL{dBmax}=\"$ctl{dBmax}\"\n"
PRINT=" CTL{items}=\"$ctl{items}\"\n"
PRINT=" CTL{value}=\"$ctl{value}\"\n"
-CTL{search}="mixer", CTL{name}="*", PROGRAM!="__ctl_search 2", GOTO="skip_first_ten_search"
+CTL{search}="mixer", CTL{name}="*", CTL{do_search 2}!="1", GOTO="skip_first_ten_search"
PRINT=" Element #2:\n"
PRINT=" CTL{numid}=\"$ctl{numid}\"\n"
PRINT=" CTL{iface}=\"$ctl{iface}\"\n"
@@ -117,7 +117,7 @@ PRINT=" CTL{dBmin}=\"$ctl{dBmin}\"\n"
PRINT=" CTL{dBmax}=\"$ctl{dBmax}\"\n"
PRINT=" CTL{items}=\"$ctl{items}\"\n"
PRINT=" CTL{value}=\"$ctl{value}\"\n"
-CTL{search}="mixer", CTL{name}="*", PROGRAM!="__ctl_search 3", GOTO="skip_first_ten_search"
+CTL{search}="mixer", CTL{name}="*", CTL{do_search 3}!="3", GOTO="skip_first_ten_search"
PRINT=" Element #3:\n"
PRINT=" CTL{numid}=\"$ctl{numid}\"\n"
PRINT=" CTL{iface}=\"$ctl{iface}\"\n"
@@ -136,7 +136,7 @@ PRINT=" CTL{dBmax}=\"$ctl{dBmax}\"\n"
PRINT=" CTL{step}=\"$ctl{step}\"\n"
PRINT=" CTL{items}=\"$ctl{items}\"\n"
PRINT=" CTL{value}=\"$ctl{value}\"\n"
-CTL{search}="mixer", CTL{name}="*", PROGRAM!="__ctl_search 4", GOTO="skip_first_ten_search"
+CTL{search}="mixer", CTL{name}="*", CTL{do_search 4}!="1", GOTO="skip_first_ten_search"
PRINT=" Element #4:\n"
PRINT=" CTL{numid}=\"$ctl{numid}\"\n"
PRINT=" CTL{iface}=\"$ctl{iface}\"\n"
@@ -155,7 +155,7 @@ PRINT=" CTL{dBmin}=\"$ctl{dBmin}\"\n"
PRINT=" CTL{dBmax}=\"$ctl{dBmax}\"\n"
PRINT=" CTL{items}=\"$ctl{items}\"\n"
PRINT=" CTL{value}=\"$ctl{value}\"\n"
-CTL{search}="mixer", CTL{name}="*", PROGRAM!="__ctl_search 5", GOTO="skip_first_ten_search"
+CTL{search}="mixer", CTL{name}="*", CTL{do_search 5}!="1", GOTO="skip_first_ten_search"
PRINT=" Element #5:\n"
PRINT=" CTL{numid}=\"$ctl{numid}\"\n"
PRINT=" CTL{iface}=\"$ctl{iface}\"\n"
@@ -174,7 +174,7 @@ PRINT=" CTL{dBmin}=\"$ctl{dBmin}\"\n"
PRINT=" CTL{dBmax}=\"$ctl{dBmax}\"\n"
PRINT=" CTL{items}=\"$ctl{items}\"\n"
PRINT=" CTL{value}=\"$ctl{value}\"\n"
-CTL{search}="mixer", CTL{name}="*", PROGRAM!="__ctl_search 6", GOTO="skip_first_ten_search"
+CTL{search}="mixer", CTL{name}="*", CTL{do_search 6}!="1", GOTO="skip_first_ten_search"
PRINT=" Element #6:\n"
PRINT=" CTL{numid}=\"$ctl{numid}\"\n"
PRINT=" CTL{iface}=\"$ctl{iface}\"\n"
@@ -193,7 +193,7 @@ PRINT=" CTL{dBmin}=\"$ctl{dBmin}\"\n"
PRINT=" CTL{dBmax}=\"$ctl{dBmax}\"\n"
PRINT=" CTL{items}=\"$ctl{items}\"\n"
PRINT=" CTL{value}=\"$ctl{value}\"\n"
-CTL{search}="mixer", CTL{name}="*", PROGRAM!="__ctl_search 7", GOTO="skip_first_ten_search"
+CTL{search}="mixer", CTL{name}="*", CTL{do_search 7}!="1", GOTO="skip_first_ten_search"
PRINT=" Element #7:\n"
PRINT=" CTL{numid}=\"$ctl{numid}\"\n"
PRINT=" CTL{iface}=\"$ctl{iface}\"\n"
@@ -212,7 +212,7 @@ PRINT=" CTL{dBmin}=\"$ctl{dBmin}\"\n"
PRINT=" CTL{dBmax}=\"$ctl{dBmax}\"\n"
PRINT=" CTL{items}=\"$ctl{items}\"\n"
PRINT=" CTL{value}=\"$ctl{value}\"\n"
-CTL{search}="mixer", CTL{name}="*", PROGRAM!="__ctl_search 8", GOTO="skip_first_ten_search"
+CTL{search}="mixer", CTL{name}="*", CTL{do_search 8}!="1", GOTO="skip_first_ten_search"
PRINT=" Element #8:\n"
PRINT=" CTL{numid}=\"$ctl{numid}\"\n"
PRINT=" CTL{iface}=\"$ctl{iface}\"\n"
@@ -231,7 +231,7 @@ PRINT=" CTL{dBmin}=\"$ctl{dBmin}\"\n"
PRINT=" CTL{dBmax}=\"$ctl{dBmax}\"\n"
PRINT=" CTL{items}=\"$ctl{items}\"\n"
PRINT=" CTL{value}=\"$ctl{value}\"\n"
-CTL{search}="mixer", CTL{name}="*", PROGRAM!="__ctl_search 9", GOTO="skip_first_ten_search"
+CTL{search}="mixer", CTL{name}="*", CTL{do_search 9}!="1", GOTO="skip_first_ten_search"
PRINT=" Element #9:\n"
PRINT=" CTL{numid}=\"$ctl{numid}\"\n"
PRINT=" CTL{iface}=\"$ctl{iface}\"\n"
@@ -254,15 +254,15 @@ LABEL="skip_first_ten_search"
PRINT="Elements write test #1:\n", \
CTL{search}="mixer", CTL{name}="Front Playback Switch", \
- PROGRAM="__ctl_search", CTL{value}="on,on", \
+ CTL{do_search}=="1", CTL{value}="on,on", \
PRINT=" result=$result\n"
PRINT="Elements write test #2:\n", \
CTL{search}="mixer", CTL{name}="Front Playback Volume", \
- PROGRAM="__ctl_search", CTL{value}="32,32", \
+ CTL{do_search}=="1", CTL{value}="32,32", \
PRINT=" result=$result\n"
PRINT="Elements write test #3:\n", \
CTL{search}="mixer", CTL{name}="Front Playback Volume Error", \
- PROGRAM="__ctl_search"
+ CTL{do_search}=="1", \
PRINT=" result=$result\n"
#CTL{reset}="mixer", CTL{name}="Input Source", PRINT="***$ctl{enums}\n"
diff --git a/alsactl/init_parse.c b/alsactl/init_parse.c
index c82797e..f243406 100644
--- a/alsactl/init_parse.c
+++ b/alsactl/init_parse.c
@@ -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();
diff --git a/alsactl/init_utils_string.c b/alsactl/init_utils_string.c
index 2598e9f..01ea800 100644
--- a/alsactl/init_utils_string.c
+++ b/alsactl/init_utils_string.c
@@ -17,17 +17,6 @@
*/
-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;
diff --git a/alsactl/state.c b/alsactl/state.c
index 635a999..e70c6f9 100644
--- a/alsactl/state.c
+++ b/alsactl/state.c
@@ -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;
}
diff --git a/alsactl/utils.c b/alsactl/utils.c
index ab4dbd4..a27eb6e 100644
--- a/alsactl/utils.c
+++ b/alsactl/utils.c
@@ -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);
diff --git a/alsamixer/Makefile.am b/alsamixer/Makefile.am
index 6426193..1de47c6 100644
--- a/alsamixer/Makefile.am
+++ b/alsamixer/Makefile.am
@@ -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
diff --git a/alsamixer/Makefile.in b/alsamixer/Makefile.in
index 1332bff..8455506 100644
--- a/alsamixer/Makefile.in
+++ b/alsamixer/Makefile.in
@@ -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
index 05c6615..0000000
--- a/alsamixer/README
+++ /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>.
diff --git a/alsamixer/alsamixer.1 b/alsamixer/alsamixer.1
index 47d8aed..ba05aca 100644
--- a/alsamixer/alsamixer.1
+++ b/alsamixer/alsamixer.1
@@ -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
index 414033e..0000000
--- a/alsamixer/alsamixer.c
+++ /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
index 0000000..b473dcf
--- /dev/null
+++ b/alsamixer/card_select.c
@@ -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
index 0000000..4ba15fc
--- /dev/null
+++ b/alsamixer/card_select.h
@@ -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
index 0000000..ab6255f
--- /dev/null
+++ b/alsamixer/cli.c
@@ -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
index 0000000..fcceb16
--- /dev/null
+++ b/alsamixer/colors.c
@@ -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
index 0000000..9396004
--- /dev/null
+++ b/alsamixer/colors.h
@@ -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
index 0000000..c58e652
--- /dev/null
+++ b/alsamixer/device_name.c
@@ -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
index 0000000..f4a1f3f
--- /dev/null
+++ b/alsamixer/device_name.h
@@ -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
index 0000000..dcd8536
--- /dev/null
+++ b/alsamixer/die.c
@@ -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
index 0000000..39ef1c0
--- /dev/null
+++ b/alsamixer/die.h
@@ -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
index 0000000..eddaf3b
--- /dev/null
+++ b/alsamixer/mainloop.c
@@ -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
index 0000000..0cfc989
--- /dev/null
+++ b/alsamixer/mainloop.h
@@ -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
index 0000000..fa03a89
--- /dev/null
+++ b/alsamixer/mem.c
@@ -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
index 0000000..d0e5f54
--- /dev/null
+++ b/alsamixer/mem.h
@@ -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
index 0000000..796df7b
--- /dev/null
+++ b/alsamixer/mixer_controls.c
@@ -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
index 0000000..dbb3a9d
--- /dev/null
+++ b/alsamixer/mixer_controls.h
@@ -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
index 0000000..20d6d6a
--- /dev/null
+++ b/alsamixer/mixer_display.c
@@ -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
index 0000000..3d65670
--- /dev/null
+++ b/alsamixer/mixer_display.h
@@ -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
index 0000000..796ea1d
--- /dev/null
+++ b/alsamixer/mixer_widget.c
@@ -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
index 0000000..da8628e
--- /dev/null
+++ b/alsamixer/mixer_widget.h
@@ -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
index 0000000..b2f5f21
--- /dev/null
+++ b/alsamixer/proc_files.c
@@ -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
index 0000000..8862c71
--- /dev/null
+++ b/alsamixer/proc_files.h
@@ -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
index 0000000..d743a14
--- /dev/null
+++ b/alsamixer/textbox.c
@@ -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
index 0000000..7dc290b
--- /dev/null
+++ b/alsamixer/textbox.h
@@ -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
index 0000000..3602bef
--- /dev/null
+++ b/alsamixer/utils.c
@@ -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
index 0000000..00a52dd
--- /dev/null
+++ b/alsamixer/utils.h
@@ -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
index 0000000..75da4c2
--- /dev/null
+++ b/alsamixer/widget.c
@@ -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
index 0000000..6adb526
--- /dev/null
+++ b/alsamixer/widget.h
@@ -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
diff --git a/amidi/Makefile.in b/amidi/Makefile.in
index ea7361b..e4ef66e 100644
--- a/amidi/Makefile.in
+++ b/amidi/Makefile.in
@@ -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@
diff --git a/amidi/amidi.c b/amidi/amidi.c
index 2e970ae..cedf18c 100644
--- a/amidi/amidi.c
+++ b/amidi/amidi.c
@@ -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);
}
}
}
diff --git a/amixer/Makefile.in b/amixer/Makefile.in
index 7ed5a12..06fda51 100644
--- a/amixer/Makefile.in
+++ b/amixer/Makefile.in
@@ -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@
diff --git a/amixer/amixer.c b/amixer/amixer.c
index 9620721..c9ea572 100644
--- a/amixer/amixer.c
+++ b/amixer/amixer.c
@@ -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);
diff --git a/aplay/Makefile.am b/aplay/Makefile.am
index 60811de..92323d1 100644
--- a/aplay/Makefile.am
+++ b/aplay/Makefile.am
@@ -1,5 +1,7 @@
+LIBRT = @LIBRT@
+
INCLUDES = -I$(top_srcdir)/include
-LDADD = $(LIBINTL)
+LDADD = $(LIBINTL) $(LIBRT)
# debug flags
#LDFLAGS = -static
diff --git a/aplay/Makefile.in b/aplay/Makefile.in
index 6a35153..bde9feb 100644
--- a/aplay/Makefile.in
+++ b/aplay/Makefile.in
@@ -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
diff --git a/aplay/aplay.1 b/aplay/aplay.1
index 7759347..b6caf0b 100644
--- a/aplay/aplay.1
+++ b/aplay/aplay.1
@@ -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),
diff --git a/aplay/aplay.c b/aplay/aplay.c
index 837e46a..8d084d6 100644
--- a/aplay/aplay.c
+++ b/aplay/aplay.c
@@ -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);
}
diff --git a/aplay/arecord.1 b/aplay/arecord.1
index 7759347..b6caf0b 100644
--- a/aplay/arecord.1
+++ b/aplay/arecord.1
@@ -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),
diff --git a/configure b/configure
index 10b429c..fc77bca 100755
--- 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
@@ -6678,9 +6724,472 @@ fi
+
+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
+ 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>
+
+#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
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_Header=no"
+fi
+
+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_pcm="yes"
+else
+ have_pcm="no"
+fi
+
+done
+
+
+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
+ 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>
+
+#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
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_Header=no"
+fi
+
+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
+
+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 <alsa/asoundlib.h>
+
+#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
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_Header=no"
+fi
+
+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
+
+
+for ac_header in alsa/seq.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 <alsa/asoundlib.h>
+
+#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
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_Header=no"
+fi
+
+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
+ have_seq="no"
+fi
+
+done
+
+
+
+
+if test "$have_pcm" = "yes"; then
+ HAVE_PCM_TRUE=
+ HAVE_PCM_FALSE='#'
+else
+ HAVE_PCM_TRUE='#'
+ HAVE_PCM_FALSE=
+fi
+
+
+
+if test "$have_mixer" = "yes"; then
+ HAVE_MIXER_TRUE=
+ HAVE_MIXER_FALSE='#'
+else
+ HAVE_MIXER_TRUE='#'
+ HAVE_MIXER_FALSE=
+fi
+
+
+
+if test "$have_rawmidi" = "yes"; then
+ HAVE_RAWMIDI_TRUE=
+ HAVE_RAWMIDI_FALSE='#'
+else
+ 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
+
+
+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
+ 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_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
@@ -6694,6 +7203,7 @@ else
alsamixer=true
fi
+fi
if test x$alsamixer = xtrue; then
@@ -7410,7 +7920,10 @@ else
curseslib="auto"
fi
- if test "$curseslib" = "ncursesw"; then
+ 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
@@ -7451,6 +7964,7 @@ 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
@@ -7536,6 +8050,10 @@ if test $ac_cv_lib_ncursesw_initscr = yes; then
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.
@@ -7578,6 +8096,7 @@ 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
@@ -7752,6 +8271,714 @@ fi
echo "$as_me: error: this packages requires a curses library" >&2;}
{ (exit 1); exit 1; }; }
fi
+
+ { 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"
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <panel.h>
+int
+main ()
+{
+set_escdelay(100);
+ ;
+ 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
+ HAVE_CURSES_ESCDELAY="yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ if test "$HAVE_CURSES_ESCDELAY" = "yes"; then
+
+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. */
+
+ #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
+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
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+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. */
+$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_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
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_Header=no"
+fi
+
+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
+
+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
+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_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_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ 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; }
+
+# 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 -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+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
+ 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
+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: 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
+
+ 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="-lpanel$NCURSESLIBSUFFIX $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 new_panel ();
+int
+main ()
+{
+return new_panel ();
+ ;
+ 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
+ eval "$as_ac_Lib=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ 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
+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: error: panel$NCURSESLIBSUFFIX library not found" >&5
+echo "$as_me: error: panel$NCURSESLIBSUFFIX library not found" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ 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="-lmenu$NCURSESLIBSUFFIX $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 new_menu ();
+int
+main ()
+{
+return new_menu ();
+ ;
+ 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
+ eval "$as_ac_Lib=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ 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
+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
+
+ 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="-lform$NCURSESLIBSUFFIX $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 new_form ();
+int
+main ()
+{
+return new_form ();
+ ;
+ 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
+ eval "$as_ac_Lib=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ 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
+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
+
+ { 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
diff --git a/configure.in b/configure.in
index 59247ed..8bae007 100644
--- a/configure.in
+++ b/configure.in
@@ -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 \
diff --git a/iecset/Makefile.in b/iecset/Makefile.in
index 82c31cc..f27887a 100644
--- a/iecset/Makefile.in
+++ b/iecset/Makefile.in
@@ -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@
diff --git a/include/Makefile.am b/include/Makefile.am
index 112e5ce..7a3968d 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -1,4 +1,4 @@
-noinst_HEADERS=version.h gettext.h
+noinst_HEADERS=version.h gettext.h gettext_curses.h
version.h: stamp-vh
@:
diff --git a/include/Makefile.in b/include/Makefile.in
index e835006..ef532d2 100644
--- a/include/Makefile.in
+++ b/include/Makefile.in
@@ -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
diff --git a/include/aconfig.h.in b/include/aconfig.h.in
index 600c887..033a345 100644
--- a/include/aconfig.h.in
+++ b/include/aconfig.h.in
@@ -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
@@ -15,19 +30,64 @@
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
diff --git a/include/gettext.h b/include/gettext.h
index c2bfe96..d8a1467 100644
--- a/include/gettext.h
+++ b/include/gettext.h
@@ -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
index 0000000..f1c4041
--- /dev/null
+++ b/include/gettext_curses.h
@@ -0,0 +1,2 @@
+#define USES_CURSES
+#include "gettext.h"
diff --git a/include/version.h b/include/version.h
index 36a48c1..dbdcc82 100644
--- a/include/version.h
+++ b/include/version.h
@@ -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"
diff --git a/m4/Makefile.in b/m4/Makefile.in
index 06e33ad..9d68382 100644
--- a/m4/Makefile.in
+++ b/m4/Makefile.in
@@ -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@
diff --git a/po/LINGUAS b/po/LINGUAS
index bef7f4a..081e105 100644
--- a/po/LINGUAS
+++ b/po/LINGUAS
@@ -1 +1 @@
-ja
+ja de
diff --git a/po/Makevars b/po/Makevars
index 32692ab..779d8ac 100644
--- a/po/Makevars
+++ b/po/Makevars
@@ -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:
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 11a6a96..3d1b8ea 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -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
diff --git a/po/alsa-utils.pot b/po/alsa-utils.pot
index 93bf58e..5011590 100644
--- a/po/alsa-utils.pot
+++ b/po/alsa-utils.pot
@@ -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
index 0000000..4c731f5
--- /dev/null
+++ b/po/de.gmo
Binary files differ
diff --git a/po/de.po b/po/de.po
new file mode 100644
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"
diff --git a/po/ja.gmo b/po/ja.gmo
index 6e8a5e4..a9af3c0 100644
--- a/po/ja.gmo
+++ b/po/ja.gmo
Binary files differ
diff --git a/po/ja.po b/po/ja.po
index 4607a4c..b65b8b0 100644
--- 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"
diff --git a/seq/Makefile.in b/seq/Makefile.in
index 8c7c0ba..f43af5a 100644
--- a/seq/Makefile.in
+++ b/seq/Makefile.in
@@ -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@
diff --git a/seq/aconnect/Makefile.in b/seq/aconnect/Makefile.in
index ccf0aeb..d754476 100644
--- a/seq/aconnect/Makefile.in
+++ b/seq/aconnect/Makefile.in
@@ -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@
diff --git a/seq/aconnect/aconnect.c b/seq/aconnect/aconnect.c
index 1a50666..8c66cfd 100644
--- a/seq/aconnect/aconnect.c
+++ b/seq/aconnect/aconnect.c
@@ -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);
+ }
}
}
diff --git a/seq/aplaymidi/Makefile.in b/seq/aplaymidi/Makefile.in
index 4e623db..aedeaa8 100644
--- a/seq/aplaymidi/Makefile.in
+++ b/seq/aplaymidi/Makefile.in
@@ -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@
diff --git a/seq/aplaymidi/aplaymidi.c b/seq/aplaymidi/aplaymidi.c
index 5ed7bab..ad508b3 100644
--- a/seq/aplaymidi/aplaymidi.c
+++ b/seq/aplaymidi/aplaymidi.c
@@ -31,7 +31,12 @@
#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.
diff --git a/seq/aseqdump/Makefile.in b/seq/aseqdump/Makefile.in
index f2971a5..e827601 100644
--- a/seq/aseqdump/Makefile.in
+++ b/seq/aseqdump/Makefile.in
@@ -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@
diff --git a/seq/aseqnet/Makefile.in b/seq/aseqnet/Makefile.in
index 9169d65..42fdc74 100644
--- a/seq/aseqnet/Makefile.in
+++ b/seq/aseqnet/Makefile.in
@@ -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@
diff --git a/speaker-test/Makefile.in b/speaker-test/Makefile.in
index 2ad0c75..2718abe 100644
--- a/speaker-test/Makefile.in
+++ b/speaker-test/Makefile.in
@@ -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@
diff --git a/speaker-test/samples/Makefile.in b/speaker-test/samples/Makefile.in
index 2240d2e..44109d5 100644
--- a/speaker-test/samples/Makefile.in
+++ b/speaker-test/samples/Makefile.in
@@ -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@
diff --git a/speaker-test/speaker-test.c b/speaker-test/speaker-test.c
index 75a4bed..d8d68e2 100644
--- a/speaker-test/speaker-test.c
+++ b/speaker-test/speaker-test.c
@@ -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)
diff --git a/utils/Makefile.in b/utils/Makefile.in
index f337a26..ed2acd3 100644
--- a/utils/Makefile.in
+++ b/utils/Makefile.in
@@ -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@