diff --git a/alsa-utils-1.0.20.tar.bz2 b/alsa-utils-1.0.20.tar.bz2 new file mode 100644 index 0000000..eacafd7 --- /dev/null +++ b/alsa-utils-1.0.20.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:07f08286b3860f60d1794cc0de4407a53adcd4b6f065531d6dcef02b0c56a0cf +size 1044483 diff --git a/alsa-utils-1.0.21.tar.bz2 b/alsa-utils-1.0.21.tar.bz2 deleted file mode 100644 index 8fbaada..0000000 --- a/alsa-utils-1.0.21.tar.bz2 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6df349518b930714ca4664d8aaaf3ea949de1e33bcfd3df8ee7e0446b3c357a6 -size 1074700 diff --git a/alsa-utils-git-fixes.diff b/alsa-utils-git-fixes.diff new file mode 100644 index 0000000..6ab0956 --- /dev/null +++ b/alsa-utils-git-fixes.diff @@ -0,0 +1,10297 @@ +diff --git a/alsactl/init/default b/alsactl/init/default +index c9aa7cc..2ac187f 100644 +--- a/alsactl/init/default ++++ b/alsactl/init/default +@@ -46,7 +46,7 @@ CTL{name}="Front Playback Switch",PROGRAM=="__ctl_search", \ + CTL{values}="on" + + CTL{reset}="mixer" +-CTL{name}="Headphone Playback Volume",PROGRAM=="__ctl_search",GOTO="headphone0_end" ++CTL{name}="Headphone Playback Volume",PROGRAM!="__ctl_search",GOTO="headphone0_end" + # if master volume control is present, turn headphone volume to max + ENV{has_pmaster_vol}=="true",CTL{values}="0dB",RESULT=="0",GOTO="headphone0_end" + ENV{has_pmaster_vol}=="true",CTL{values)="100%",GOTO="headphone0_end" +@@ -56,8 +56,23 @@ CTL{name}="Headphone Playback Switch",PROGRAM=="__ctl_search", \ + CTL{values}="on" + + CTL{reset}="mixer" +-CTL{name}="Speaker Playback Volume",PROGRAM=="__ctl_search", \ +- CTL{values}="$env{pvolume}",RESULT!="0",CTL{values}="$env{ppercent}" ++CTL{name}="Headphone Playback Volume",CTL{index}="1",PROGRAM!="__ctl_search",\ ++ GOTO="headphone1_end" ++# if master volume control is present, turn headphone volume to max ++ENV{has_pmaster_vol}=="true",CTL{values}="0dB",RESULT=="0",GOTO="headphone1_end" ++ENV{has_pmaster_vol}=="true",CTL{values)="100%",GOTO="headphone1_end" ++CTL{values}="$env{pvolume}",RESULT!="0",CTL{values}="$env{ppercent}" ++LABEL="headphone1_end" ++CTL{name}="Headphone Playback Switch",CTL{index}="1",PROGRAM=="__ctl_search", \ ++ CTL{values}="on" ++ ++CTL{reset}="mixer" ++CTL{name}="Sepaker Playback Volume",PROGRAM!="__ctl_search",GOTO="speaker0_end" ++# if master volume control is present, turn speaker volume to max ++ENV{has_pmaster_vol}=="true",CTL{values}="0dB",RESULT=="0",GOTO="speaker0_end" ++ENV{has_pmaster_vol}=="true",CTL{values)="100%",GOTO="speaker0_end" ++CTL{values}="$env{pvolume}",RESULT!="0",CTL{values}="$env{ppercent}" ++LABEL="speaker0_end" + CTL{name}="Speaker Playback Switch",PROGRAM=="__ctl_search", \ + CTL{values}="on" + +@@ -68,7 +83,8 @@ CTL{name}="PC Speaker Playback Switch",PROGRAM=="__ctl_search", \ + CTL{values}="on" + + CTL{reset}="mixer" +-CTL{name}="PCM Playback Volume",PROGRAM!="__ctl_search",GOTO="pcm0_end" ++CTL{name}="PCM Playback Volume",PROGRAM!="__ctl_search", \ ++ CTL{name}="PCM Volume",PROGRAM!="__ctl_search", GOTO="pcm0_end" + # if master volume control is present, turn PCM volume to max + ENV{has_pmaster_vol}=="true",CTL{values}="0dB",RESULT=="0",GOTO="pcm0_end" + ENV{has_pmaster_vol}=="true",CTL{values)="100%",GOTO="pcm0_end" +@@ -77,12 +93,12 @@ CTL{dBmin}=="-34.50dB",CTL{dBmax}=="12.00dB",CTL{values}="0dB",GOTO="pcm0_end" + CTL{dBmin}=="-30.00dB",CTL{dBmax}=="0dB",CTL{values}="0dB",GOTO="pcm0_end" + CTL{values}="$env{pvolume}",RESULT!="0",CTL{values}="75%" + LABEL="pcm0_end" +-CTL{name}="PCM Playback Switch",PROGRAM=="__ctl_search", \ +- CTL{values}="on" ++CTL{name}="PCM Playback Switch",PROGRAM=="__ctl_search", CTL{values}="on" ++CTL{name}="PCM Switch",PROGRAM=="__ctl_search",CTL{values}="on" + + CTL{reset}="mixer" + CTL{name}="PCM Playback Volume",CTL{index}="1",PROGRAM!="__ctl_search", \ +- GOTO="pcm1_end" ++ CTL{name}="PCM Volume",PROGRAM!="__ctl_search",GOTO="pcm1_end" + # if master volume control is present, turn PCM volume to max + ENV{has_pmaster_vol}=="true",CTL{values}="0dB",RESULT=="0",GOTO="pcm1_end" + ENV{has_pmaster_vol}=="true",CTL{values)="100%",GOTO="pcm1_end" +@@ -93,6 +109,8 @@ CTL{values}="$env{pvolume}",RESULT!="0",CTL{values}="75%" + LABEL="pcm1_end" + CTL{name}="PCM Playback Switch",CTL{index}="1",PROGRAM=="__ctl_search", \ + CTL{values}="on" ++CTL{name}="PCM Switch",CTL{index}="1",PROGRAM=="__ctl_search", \ ++ CTL{values}="on" + + CTL{reset}="mixer" + CTL{name}="DAC Playback Volume",PROGRAM=="__ctl_search", \ +@@ -101,7 +119,7 @@ CTL{name}="DAC Playback Switch",PROGRAM=="__ctl_search", \ + CTL{values}="on" + + CTL{reset}="mixer" +-CTL{name}="Synth Playback Volume",,PROGRAM=="__ctl_search", \ ++CTL{name}="Synth Playback Volume",PROGRAM=="__ctl_search", \ + CTL{values}="$env{pvolume}",RESULT!="0",CTL{values}="$env{ppercent}" + CTL{name}="Synth Playback Switch",PROGRAM=="__ctl_search", \ + CTL{values}="on" +diff --git a/alsactl/init/hda b/alsactl/init/hda +index f457ca4..a6919f1 100644 +--- a/alsactl/init/hda ++++ b/alsactl/init/hda +@@ -29,6 +29,7 @@ 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}="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" +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/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 and +-been furtherly improved by Jaroslav Kysela . +-This document was provided by Paul Winkler . +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 ++\fI\-c, \-\-card\fP + Select the soundcard to use, if you have more than one. Cards are + numbered from 0 (the default). + + .TP +-\fI\-D\fP ++\fI\-D, \-\-device\fP + 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 ++Select the starting view mode, either \fIplayback\fP, \fIcapture\fP or \fIall\fP. + + .TP +-\fI\-V\fP +-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 and +-been further improved by Jaroslav Kysela . ++been further improved by Jaroslav Kysela ++and Clemens Ladisch . + + This manual page was provided by Paul Winkler . +diff --git a/alsamixer/alsamixer.c b/alsamixer/alsamixer.c +deleted file mode 100644 +index c65c22d..0000000 +--- a/alsamixer/alsamixer.c ++++ /dev/null +@@ -1,2412 +0,0 @@ +-/* AlsaMixer - Commandline mixer for the ALSA project Copyright (C) 1998, +- * 1999 Tim Janik and Jaroslav Kysela +- * +- * 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 +- * +- * * ported to the latest mixer 0.9.x API (function based) +- * +- * Fri Jun 23 14:10:00 MEST 2000 Jaroslav Kysela +- * +- * * 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 +- * +- * * a group is split into front, rear, center and woofer elements. +- * +- * Mon Jan 3 23:33:42 MET 2000 Jaroslav Kysela +- * +- * * version 1.00 +- * +- * * ported to new mixer API (scontrol control) +- * +- * Sun Feb 21 19:55:01 1999 Tim Janik +- * +- * * 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 +- * +- * * 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 . +- * +- * 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 +-#include +-#include +-#include +- +-#include +- +-#include +-#include +-#include +-#include +-#include +- +-#include +- +-#ifndef CURSESINC +-#include +-#else +-#include CURSESINC +-#endif +-#include +- +-#include +-#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 and Jaroslav Kysela .\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 'k': +- case 'w': +- case 'W': +- mixer_vscroll_delta -= 1; +- break; +- case KEY_DOWN: +- case 'j': +- 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: +- case 'k': +- mixer_set_delta(1); +- case 'W': +- mixer_add_delta(1); +- break; +- case 'x': +- case KEY_DOWN: +- case 'j': +- 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 ] [-D ] [-g] [-s] [-V ] [-a ]\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 ++ * ++ * 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 . ++ */ ++ ++#include "aconfig.h" ++#include ++#include ++#include ++#include ++#include ++#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 ++ * Jaroslav Kysela ++ * Copyright (c) 2009 Clemens Ladisch ++ * ++ * 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 . ++ */ ++ ++#include "aconfig.h" ++#include ++#include ++#include ++#include ++#include ++#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 ++ * Jaroslav Kysela ++ * Copyright (c) 2009 Clemens Ladisch ++ * ++ * 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 . ++ */ ++ ++#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 ++ * ++ * 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 . ++ */ ++ ++#include "aconfig.h" ++#include ++#include ++#include CURSESINC ++#include ++#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 ++ * ++ * 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 . ++ */ ++ ++#include "aconfig.h" ++#include ++#include ++#include ++#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..7a5ffdc +--- /dev/null ++++ b/alsamixer/mainloop.c +@@ -0,0 +1,135 @@ ++/* ++ * mainloop.c - main loop ++ * Copyright (c) Clemens Ladisch ++ * ++ * 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 . ++ */ ++ ++#include "aconfig.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#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 NCURSES_VERSION ++ 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 ++ * ++ * 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 . ++ */ ++ ++#define _GNU_SOURCE ++#include "aconfig.h" ++#include ++#include ++#include ++#include ++#include ++#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 ++ ++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 ++ * Jaroslav Kysela ++ * Copyright (c) 2009 Clemens Ladisch ++ * ++ * 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 . ++ */ ++ ++#include "aconfig.h" ++#include ++#include ++#include ++#include CURSESINC ++#include ++#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 ++ ++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..9eadcc9 +--- /dev/null ++++ b/alsamixer/mixer_display.c +@@ -0,0 +1,751 @@ ++/* ++ * mixer_display.c - handles displaying of mixer widget and controls ++ * Copyright (c) 1874 Lewis Carroll ++ * Copyright (c) 2009 Clemens Ladisch ++ * ++ * 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 . ++ */ ++ ++#include "aconfig.h" ++#include ++#include ++#include ++#include CURSESINC ++#include ++#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 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 (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 ++ * Jaroslav Kysela ++ * Copyright (c) 2009 Clemens Ladisch ++ * ++ * 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 . ++ */ ++ ++#include "aconfig.h" ++#include ++#include ++#include ++#include ++#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(¤t_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 "), ++ _(" Jaroslav Kysela "), ++ _(" Clemens Ladisch "), ++ }; ++ 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 ++#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 ++ * ++ * 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 . ++ */ ++ ++#include "aconfig.h" ++#include ++#include ++#include ++#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 ++ * Jaroslav Kysela ++ * Copyright (c) 2009 Clemens Ladisch ++ * ++ * 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 . ++ */ ++ ++#include "aconfig.h" ++#include ++#include ++#include ++#include ++#include CURSESINC ++#include ++#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 ++ * ++ * 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 . ++ */ ++ ++#define _XOPEN_SOURCE ++#include "aconfig.h" ++#include ++#include ++#include ++#include ++#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 ++ * ++ * 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 . ++ */ ++ ++#include "aconfig.h" ++#include ++#include ++#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 ++ ++#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/configure.in b/configure.in +index 5cb22a9..1349ff3 100644 +--- a/configure.in ++++ b/configure.in +@@ -1,6 +1,6 @@ + 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.20) + +@@ -105,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="" + CURSESLIB=`ncursesw5-config --libs` ++ CURSESLIBDIR=`ncursesw5-config --libdir` + CURSES_CFLAGS=`ncursesw5-config --cflags` + curseslib="ncursesw" + else + AC_CHECK_LIB(ncursesw, initscr, + [ CURSESINC=''; 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="" + CURSESLIB=`ncurses5-config --libs` ++ CURSESLIBDIR=`ncurses5-config --libdir` + CURSES_CFLAGS=`ncurses5-config --cflags` + curseslib="ncurses" + else +@@ -136,6 +145,78 @@ 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" ++ ++ 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 ++ ], [ ++ 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) +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/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 + #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/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/de.po b/po/de.po +new file mode 100644 +index 0000000..7cae06e +--- /dev/null ++++ b/po/de.po +@@ -0,0 +1,1532 @@ ++# 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 , 2009. ++# ++msgid "" ++msgstr "" ++"Project-Id-Version: alsa-utils 1.0.20\n" ++"Report-Msgid-Bugs-To: \n" ++"POT-Creation-Date: 2009-05-24 19:56+0200\n" ++"PO-Revision-Date: 2009-05-24 12:34+0200\n" ++"Last-Translator: Clemens Ladisch \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:512 alsamixer/mixer_display.c:517 ++msgid "O" ++msgstr "O" ++ ++#. TRANSLATORS: playback muted; one character ++#: alsamixer/mixer_display.c:514 alsamixer/mixer_display.c:518 ++msgid "M" ++msgstr "M" ++ ++#. TRANSLATORS: "left"; no more than two characters ++#: alsamixer/mixer_display.c:532 ++msgid "L" ++msgstr "L" ++ ++#. TRANSLATORS: "right"; no more than two characters ++#: alsamixer/mixer_display.c:536 ++msgid "R" ++msgstr "R" ++ ++#. TRANSLATORS: no more than eight characters ++#: alsamixer/mixer_display.c:538 ++msgid "CAPTURE" ++msgstr "AUFNAHME" ++ ++#: alsamixer/mixer_display.c:588 ++msgid "Front" ++msgstr "Vorne" ++ ++#: alsamixer/mixer_display.c:591 ++msgid "Rear" ++msgstr "Hinten" ++ ++#: alsamixer/mixer_display.c:594 speaker-test/speaker-test.c:106 ++msgid "Center" ++msgstr "Mitte" ++ ++#: alsamixer/mixer_display.c:597 ++msgid "Woofer" ++msgstr "Bass" ++ ++#: alsamixer/mixer_display.c:600 ++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 " ++msgstr " Tim Janik " ++ ++#: alsamixer/mixer_widget.c:215 ++msgid " Jaroslav Kysela " ++msgstr " Jaroslav Kysela " ++ ++#: alsamixer/mixer_widget.c:216 ++msgid " Clemens Ladisch " ++msgstr " Clemens Ladisch " ++ ++#: 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:139 ++msgid "raw data" ++msgstr "Rohdaten" ++ ++#: aplay/aplay.c:140 ++msgid "VOC" ++msgstr "VOC" ++ ++#: aplay/aplay.c:142 ++msgid "WAVE" ++msgstr "WAVE" ++ ++#: aplay/aplay.c:143 ++msgid "Sparc Audio" ++msgstr "Sparc-Audio" ++ ++#: aplay/aplay.c:164 ++#, 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" ++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:199 speaker-test/speaker-test.c:740 ++#, c-format ++msgid "Recognized sample formats are:" ++msgstr "Unterstützte Sample-Formate:" ++ ++#: aplay/aplay.c:205 ++#, 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:206 ++#, c-format ++msgid "The availabled format shortcuts are:\n" ++msgstr "Unterstütze Format-Abkürzungen:\n" ++ ++#: aplay/aplay.c:207 ++#, 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:208 ++#, 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:209 ++#, 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:223 ++msgid "no soundcards found..." ++msgstr "keine Soundkarten gefunden ..." ++ ++#: aplay/aplay.c:226 ++#, c-format ++msgid "**** List of %s Hardware Devices ****\n" ++msgstr "**** Liste der Hardware-Geräte (%s) ****\n" ++ ++#: aplay/aplay.c:255 ++#, 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:261 ++#, c-format ++msgid " Subdevices: %i/%i\n" ++msgstr " Sub-Geräte: %i/%i\n" ++ ++#: aplay/aplay.c:268 ++#, c-format ++msgid " Subdevice #%i: %s\n" ++msgstr " Sub-Gerät #%i: %s\n" ++ ++#: aplay/aplay.c:332 ++#, c-format ++msgid "Aborted by signal %s...\n" ++msgstr "Abbruch durch Signal %s ...\n" ++ ++#: aplay/aplay.c:430 ++msgid "command should be named either arecord or aplay" ++msgstr "Befehl sollte arecord oder aplay sein" ++ ++#: aplay/aplay.c:469 ++#, c-format ++msgid "unrecognized file format %s" ++msgstr "unbekanntes Dateiformat %s" ++ ++#: aplay/aplay.c:476 ++#, c-format ++msgid "value %i for channels is invalid" ++msgstr "Kanalanzahl %i ist ungültig" ++ ++#: aplay/aplay.c:495 ++#, c-format ++msgid "wrong extended format '%s'" ++msgstr "erweitertes Format '%s' ist ungültig" ++ ++#: aplay/aplay.c:506 ++#, c-format ++msgid "bad speed value %i" ++msgstr "ungültige Rate %i" ++ ++#: aplay/aplay.c:592 ++#, c-format ++msgid "Try `%s --help' for more information.\n" ++msgstr "Siehe `%s --help' für mehr Informationen.\n" ++ ++#: aplay/aplay.c:608 ++#, c-format ++msgid "audio open error: %s" ++msgstr "Fehler beim Öffnen des Gerätes: %s" ++ ++#: aplay/aplay.c:613 ++#, c-format ++msgid "info error: %s" ++msgstr "Fehler beim Lesen der Geräteinformationen: %s" ++ ++#: aplay/aplay.c:620 ++#, c-format ++msgid "nonblock setting error: %s" ++msgstr "Fehler beim Setzen des nonblock-Modus: %s" ++ ++#: aplay/aplay.c:630 aplay/aplay.c:737 aplay/aplay.c:1092 ++msgid "not enough memory" ++msgstr "nicht genug Speicher" ++ ++#: aplay/aplay.c:727 ++#, c-format ++msgid "read error (called from line %i)" ++msgstr "Lesefehler (aufgerufen von Zeile %i)" ++ ++#: aplay/aplay.c:785 ++#, 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:795 ++#, 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:800 ++msgid "wrong format tag in extensible 'fmt ' chunk" ++msgstr "ungültiger Format-Wert im erweiterten 'fmt '-Block" ++ ++#: aplay/aplay.c:807 ++#, 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:811 ++#, c-format ++msgid "can't play WAVE-files with %d tracks" ++msgstr "kann WAVE-Datei mit %d Kanälen nicht abspielen" ++ ++#: aplay/aplay.c:819 aplay/aplay.c:919 ++#, c-format ++msgid "Warning: format is changed to U8\n" ++msgstr "Warnung: benutztes Format ist U8\n" ++ ++#: aplay/aplay.c:825 ++#, c-format ++msgid "Warning: format is changed to S16_LE\n" ++msgstr "Warnung: benutztes Format ist S16_LE\n" ++ ++#: aplay/aplay.c:833 ++#, c-format ++msgid "Warning: format is changed to S24_3LE\n" ++msgstr "Warnung: benutztes Format ist S24_3LE\n" ++ ++#: aplay/aplay.c:839 ++#, c-format ++msgid "Warning: format is changed to S24_LE\n" ++msgstr "Warnung: benutztes Format ist S24_LE\n" ++ ++#: aplay/aplay.c:843 ++#, 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:855 ++#, 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:913 ++#, c-format ++msgid "Warning: format is changed to MU_LAW\n" ++msgstr "Warnung: benutztes Format ist MU_LAW\n" ++ ++#: aplay/aplay.c:925 ++#, c-format ++msgid "Warning: format is changed to S16_BE\n" ++msgstr "Warnung: benutztes Format ist S16_BE\n" ++ ++#: aplay/aplay.c:938 aplay/aplay.c:1768 aplay/aplay.c:1775 aplay/aplay.c:2297 ++#: aplay/aplay.c:2309 ++msgid "read error" ++msgstr "Lesefehler" ++ ++#: aplay/aplay.c:957 ++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:974 ++msgid "Access type not available" ++msgstr "Zugriffs-Modus nicht unterstützt" ++ ++#: aplay/aplay.c:979 ++msgid "Sample format non available" ++msgstr "Sample-Format nicht unterstützt" ++ ++#: aplay/aplay.c:984 ++msgid "Channels count non available" ++msgstr "Kanalanzahl nicht unterstützt" ++ ++#: aplay/aplay.c:999 ++#, 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:1005 ++#, c-format ++msgid " please, try the plug plugin %s\n" ++msgstr " probieren Sie bitte das plug-Plugin: %s\n" ++ ++#: aplay/aplay.c:1041 ++msgid "Unable to install hw params:" ++msgstr "Fehler beim Setzen der Hardware-Parameter:" ++ ++#: aplay/aplay.c:1048 ++#, 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:1079 ++msgid "unable to install sw params:" ++msgstr "Fehler beim Setzen der Software-Parameter:" ++ ++#: aplay/aplay.c:1154 ++#, c-format ++msgid "status error: %s" ++msgstr "Status-Fehler: %s" ++ ++#: aplay/aplay.c:1164 aplay/aplay.c:1175 ++#, c-format ++msgid "%s!!! (at least %.3f ms long)\n" ++msgstr "%s!!! (mindestens %.3f ms)\n" ++ ++#: aplay/aplay.c:1165 aplay/aplay.c:1168 aplay/aplay.c:1176 ++msgid "underrun" ++msgstr "Unterlauf" ++ ++#: aplay/aplay.c:1165 aplay/aplay.c:1176 ++msgid "overrun" ++msgstr "Überlauf" ++ ++#: aplay/aplay.c:1180 ++#, c-format ++msgid "Status:\n" ++msgstr "Status:\n" ++ ++#: aplay/aplay.c:1184 ++#, c-format ++msgid "xrun: prepare error: %s" ++msgstr "Unter-/Überlauf: Fehler beim Re-Initialisieren des Gerätes: %s" ++ ++#: aplay/aplay.c:1190 ++#, c-format ++msgid "Status(DRAINING):\n" ++msgstr "Status (DRAINING):\n" ++ ++#: aplay/aplay.c:1194 ++#, c-format ++msgid "capture stream format change? attempting recover...\n" ++msgstr "Format-Wechsel der Aufnahme-Daten? Versuche Wiederherstellung ...\n" ++ ++#: aplay/aplay.c:1196 ++#, c-format ++msgid "xrun(DRAINING): prepare error: %s" ++msgstr "XRUN (DRAINING): Fehler beim Re-Initialisieren des Gerätes: %s" ++ ++#: aplay/aplay.c:1203 ++#, c-format ++msgid "Status(R/W):\n" ++msgstr "Status (R/W):\n" ++ ++#: aplay/aplay.c:1206 ++#, c-format ++msgid "read/write error, state = %s" ++msgstr "Lese-/Schreibfehler, Status = %s" ++ ++#: aplay/aplay.c:1216 ++#, c-format ++msgid "Suspended. Trying resume. " ++msgstr "Ruhezustand. Versuche, aufzuwecken. " ++ ++#: aplay/aplay.c:1221 ++#, c-format ++msgid "Failed. Restarting stream. " ++msgstr "Fehlgeschlagen. Re-Initialisierung. " ++ ++#: aplay/aplay.c:1223 ++#, c-format ++msgid "suspend: prepare error: %s" ++msgstr "Ruhezustand: Fehler beim Re-Initialisieren: %s" ++ ++#: aplay/aplay.c:1228 ++#, c-format ++msgid "Done.\n" ++msgstr "Fertig.\n" ++ ++#: aplay/aplay.c:1250 ++#, c-format ++msgid " !clip " ++msgstr " !clip " ++ ++#: aplay/aplay.c:1397 ++#, c-format ++msgid "Unsupported bit size %d.\n" ++msgstr "%d-Bit-Samples werden nicht unterstützt.\n" ++ ++#: aplay/aplay.c:1431 ++#, c-format ++msgid "Max peak (%li samples): 0x%08x " ++msgstr "Höchstwert (%li Samples): 0x%08x " ++ ++#: aplay/aplay.c:1465 ++#, 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:1528 ++#, c-format ++msgid "write error: %s" ++msgstr "Schreibfehler: %s" ++ ++#: aplay/aplay.c:1574 ++#, c-format ++msgid "writev error: %s" ++msgstr "Vektor-Schreib-Fehler: %s" ++ ++#: aplay/aplay.c:1617 ++#, c-format ++msgid "read error: %s" ++msgstr "Lesefehler: %s" ++ ++#: aplay/aplay.c:1660 ++#, c-format ++msgid "readv error: %s" ++msgstr "Vektor-Lese-Fehler: %s" ++ ++#: aplay/aplay.c:1708 ++msgid "can't allocate buffer for silence" ++msgstr "nicht genug Speicher für Stille-Block" ++ ++#: aplay/aplay.c:1717 aplay/aplay.c:1943 aplay/aplay.c:1948 aplay/aplay.c:1995 ++#: aplay/aplay.c:2004 aplay/aplay.c:2011 aplay/aplay.c:2021 aplay/aplay.c:2027 ++#: aplay/aplay.c:2099 aplay/aplay.c:2129 aplay/aplay.c:2143 ++msgid "write error" ++msgstr "Schreibfehler" ++ ++#: aplay/aplay.c:1730 ++#, c-format ++msgid "voc_pcm_flush - silence error" ++msgstr "voc_pcm_flush - Fehler in set_silence" ++ ++#: aplay/aplay.c:1733 ++msgid "voc_pcm_flush error" ++msgstr "Schreibfehler" ++ ++#: aplay/aplay.c:1759 ++msgid "malloc error" ++msgstr "nicht genug Speicher" ++ ++#: aplay/aplay.c:1763 ++#, c-format ++msgid "Playing Creative Labs Channel file '%s'...\n" ++msgstr "Spiele Creative Labs Channel-Datei '%s'...\n" ++ ++#: aplay/aplay.c:1831 aplay/aplay.c:1923 ++msgid "can't play packed .voc files" ++msgstr "kann komprimierte .voc-Dateien nicht abspielen" ++ ++#: aplay/aplay.c:1883 ++#, 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:1932 ++#, c-format ++msgid "unknown blocktype %d. terminate." ++msgstr "Unbekannter Block-Typ %d. Abbruch." ++ ++#: aplay/aplay.c:2063 ++#, c-format ++msgid "Wave doesn't support %s format..." ++msgstr "Format %s wird in WAVE nicht unterstützt ..." ++ ++#: aplay/aplay.c:2123 ++#, c-format ++msgid "Sparc Audio doesn't support %s format..." ++msgstr "Format %s wird in Sparc-Audio nicht unterstützt ..." ++ ++#: aplay/aplay.c:2204 ++msgid "Playing" ++msgstr "Wiedergabe:" ++ ++#: aplay/aplay.c:2204 ++msgid "Recording" ++msgstr "Aufnahme:" ++ ++#: aplay/aplay.c:2208 ++#, c-format ++msgid "Rate %d Hz, " ++msgstr "Rate: %d Hz, " ++ ++#: aplay/aplay.c:2210 ++#, c-format ++msgid "Mono" ++msgstr "mono" ++ ++#: aplay/aplay.c:2212 ++#, c-format ++msgid "Stereo" ++msgstr "stereo" ++ ++#: aplay/aplay.c:2214 ++#, c-format ++msgid "Channels %i" ++msgstr "%i Kanäle" ++ ++#: aplay/aplay.c:2573 aplay/aplay.c:2626 ++#, 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:326 ++#, c-format ++msgid "can't open sequencer\n" ++msgstr "Fehler beim Öffnen des Sequenzers\n" ++ ++#: seq/aconnect/aconnect.c:354 ++#, c-format ++msgid "can't get client id\n" ++msgstr "Fehler beim Lesen der Client-ID\n" ++ ++#: seq/aconnect/aconnect.c:361 ++#, c-format ++msgid "can't set client info\n" ++msgstr "Fehler beim Setzen des Client-Namens\n" ++ ++#: seq/aconnect/aconnect.c:368 ++#, c-format ++msgid "invalid sender address %s\n" ++msgstr "ungültige Sender-Adresse %s\n" ++ ++#: seq/aconnect/aconnect.c:373 seq/aseqnet/aseqnet.c:290 ++#, c-format ++msgid "invalid destination address %s\n" ++msgstr "ungültige Ziel-Adresse %s\n" ++ ++#: seq/aconnect/aconnect.c:387 ++#, c-format ++msgid "No subscription is found\n" ++msgstr "keine Verbindung gefunden\n" ++ ++#: seq/aconnect/aconnect.c:392 ++#, c-format ++msgid "Disconnection failed (%s)\n" ++msgstr "Verbindungs-Trennung fehlgeschlagen (%s)\n" ++ ++#: seq/aconnect/aconnect.c:398 ++#, c-format ++msgid "Connection is already subscribed\n" ++msgstr "Verbindung ist bereits vorhanden\n" ++ ++#: seq/aconnect/aconnect.c:403 ++#, 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:102 ++msgid "Front Left" ++msgstr "Vorne links" ++ ++#: speaker-test/speaker-test.c:103 ++msgid "Front Right" ++msgstr "Vorne rechts" ++ ++#: speaker-test/speaker-test.c:104 ++msgid "Rear Left" ++msgstr "Hinten links" ++ ++#: speaker-test/speaker-test.c:105 ++msgid "Rear Right" ++msgstr "Hinten rechts" ++ ++#: speaker-test/speaker-test.c:107 ++msgid "LFE" ++msgstr "Bass" ++ ++#: speaker-test/speaker-test.c:108 ++msgid "Side Left" ++msgstr "Seitlich links" ++ ++#: speaker-test/speaker-test.c:109 ++msgid "Side Right" ++msgstr "Seitlich rechts" ++ ++#: speaker-test/speaker-test.c:110 ++msgid "Channel 9" ++msgstr "Kanal 9" ++ ++#: speaker-test/speaker-test.c:111 ++msgid "Channel 10" ++msgstr "Kanal 10" ++ ++#: speaker-test/speaker-test.c:112 ++msgid "Channel 11" ++msgstr "Kanal 11" ++ ++#: speaker-test/speaker-test.c:113 ++msgid "Channel 12" ++msgstr "Kanal 12" ++ ++#: speaker-test/speaker-test.c:114 ++msgid "Channel 13" ++msgstr "Kanal 13" ++ ++#: speaker-test/speaker-test.c:115 ++msgid "Channel 14" ++msgstr "Kanal 14" ++ ++#: speaker-test/speaker-test.c:116 ++msgid "Channel 15" ++msgstr "Kanal 15" ++ ++#: speaker-test/speaker-test.c:117 ++msgid "Channel 16" ++msgstr "Kanal 16" ++ ++#: speaker-test/speaker-test.c:307 ++#, 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:314 ++#, c-format ++msgid "Access type not available for playback: %s\n" ++msgstr "Zugriffsmodus nicht unterstützt: %s\n" ++ ++#: speaker-test/speaker-test.c:321 ++#, c-format ++msgid "Sample format not available for playback: %s\n" ++msgstr "Sample-Format nicht unterstützt: %s\n" ++ ++#: speaker-test/speaker-test.c:328 ++#, 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:336 ++#, 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:341 ++#, 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:345 ++#, c-format ++msgid "Rate set to %iHz (requested %iHz)\n" ++msgstr "Rate ist %i Hz (angefordert: %i Hz)\n" ++ ++#: speaker-test/speaker-test.c:351 ++#, c-format ++msgid "Buffer size range from %lu to %lu\n" ++msgstr "Puffergröße von %lu bis %lu\n" ++ ++#: speaker-test/speaker-test.c:352 ++#, c-format ++msgid "Period size range from %lu to %lu\n" ++msgstr "Periodengröße von %lu bis %lu\n" ++ ++#: speaker-test/speaker-test.c:354 ++#, c-format ++msgid "Requested period time %u us\n" ++msgstr "Angeforderte Periodenzeit %u µs\n" ++ ++#: speaker-test/speaker-test.c:357 ++#, 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:363 ++#, c-format ++msgid "Requested buffer time %u us\n" ++msgstr "Angeforderte Pufferlänge %u µs\n" ++ ++#: speaker-test/speaker-test.c:366 ++#, 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:375 ++#, c-format ++msgid "Using max buffer size %lu\n" ++msgstr "Verwende maximale Puffergröße %lu\n" ++ ++#: speaker-test/speaker-test.c:378 ++#, 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:384 ++#, c-format ++msgid "Periods = %u\n" ++msgstr "Perioden = %u\n" ++ ++#: speaker-test/speaker-test.c:387 ++#, 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:396 ++#, 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:402 ++#, c-format ++msgid "was set period_size = %lu\n" ++msgstr "gesetzt: period_size = %lu\n" ++ ++#: speaker-test/speaker-test.c:403 ++#, c-format ++msgid "was set buffer_size = %lu\n" ++msgstr "gesetzt: buffer_size = %lu\n" ++ ++#: speaker-test/speaker-test.c:405 ++#, c-format ++msgid "buffer to small, could not use\n" ++msgstr "Puffer zu klein, kann nicht benutzt werden\n" ++ ++#: speaker-test/speaker-test.c:418 ++#, 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:425 ++#, 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:432 ++#, 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:439 ++#, 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:454 ++#, 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:465 ++#, 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:529 speaker-test/speaker-test.c:926 ++#, c-format ++msgid "No enough memory\n" ++msgstr "Nicht genug Speicher\n" ++ ++#: speaker-test/speaker-test.c:534 ++#, c-format ++msgid "Cannot open WAV file %s\n" ++msgstr "Kann WAV-Datei %s nicht öffnen\n" ++ ++#: speaker-test/speaker-test.c:538 speaker-test/speaker-test.c:567 ++#, c-format ++msgid "Invalid WAV file %s\n" ++msgstr "Ungültige WAV-Datei %s\n" ++ ++#: speaker-test/speaker-test.c:543 ++#, c-format ++msgid "Not a WAV file: %s\n" ++msgstr "Keine WAV-Datei: %s\n" ++ ++#: speaker-test/speaker-test.c:547 ++#, 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:552 ++#, 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:557 ++#, 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:562 ++#, 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:612 ++#, c-format ++msgid "Undefined channel %d\n" ++msgstr "Kanal %d nicht definiert\n" ++ ++#: speaker-test/speaker-test.c:663 ++#, c-format ++msgid "Write error: %d,%s\n" ++msgstr "Schreibfehler: %d, %s\n" ++ ++#: speaker-test/speaker-test.c:665 ++#, c-format ++msgid "xrun_recovery failed: %d,%s\n" ++msgstr "xrun_recovery fehlgeschlagen: %d, %s\n" ++ ++#: speaker-test/speaker-test.c:723 ++#, 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:835 ++#, c-format ++msgid "Invalid number of periods %d\n" ++msgstr "Ungültige Periodenanzahl %d\n" ++ ++#: speaker-test/speaker-test.c:849 speaker-test/speaker-test.c:853 ++#, c-format ++msgid "Invalid test type %s\n" ++msgstr "Ungültiger Test-Typ %s\n" ++ ++#: speaker-test/speaker-test.c:865 ++#, c-format ++msgid "Invalid parameter for -s option.\n" ++msgstr "Ungültiger Wert für Option -s\n" ++ ++#: speaker-test/speaker-test.c:876 ++#, c-format ++msgid "Unknown option '%c'\n" ++msgstr "Unbekannte Options '%c'\n" ++ ++#: speaker-test/speaker-test.c:890 ++#, c-format ++msgid "Playback device is %s\n" ++msgstr "Wiedergabe-Gerät ist %s\n" ++ ++#: speaker-test/speaker-test.c:891 ++#, 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:894 ++#, c-format ++msgid "Using 16 octaves of pink noise\n" ++msgstr "Verwende 16 Oktaven rosa Rauschen\n" ++ ++#: speaker-test/speaker-test.c:897 ++#, c-format ++msgid "Sine wave rate is %.4fHz\n" ++msgstr "Sinuswelle mit Frequenz %.4f Hz\n" ++ ++#: speaker-test/speaker-test.c:900 ++#, c-format ++msgid "WAV file(s)\n" ++msgstr "WAV-Datei(en)\n" ++ ++#: speaker-test/speaker-test.c:906 ++#, c-format ++msgid "Playback open error: %d,%s\n" ++msgstr "Fehler beim Öffnen des Gerätes: %d, %s\n" ++ ++#: speaker-test/speaker-test.c:911 ++#, c-format ++msgid "Setting of hwparams failed: %s\n" ++msgstr "Fehler beim Setzen der Hardware-Parameter: %s\n" ++ ++#: speaker-test/speaker-test.c:916 ++#, c-format ++msgid "Setting of swparams failed: %s\n" ++msgstr "Fehler beim Setzen der Software-Parameter: %s\n" ++ ++#: speaker-test/speaker-test.c:957 speaker-test/speaker-test.c:979 ++#, c-format ++msgid "Transfer failed: %s\n" ++msgstr "Schreibfehler: %s\n" ++ ++#: speaker-test/speaker-test.c:967 ++#, c-format ++msgid "Time per period = %lf\n" ++msgstr "Zeit pro Periode = %lf\n" +diff --git a/po/ja.po b/po/ja.po +index 3b2e319..2c234f4 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: 2006-11-11 10:45+0000\n" +-"PO-Revision-Date: 2006-04-18 15:51+0200\n" ++"POT-Creation-Date: 2009-05-24 19:56+0200\n" ++"PO-Revision-Date: 2009-05-27 15:08+0200\n" + "Last-Translator: Takashi Iwai \n" + "Language-Team: Japanese\n" + "MIME-Version: 1.0\n" +@@ -17,24 +17,373 @@ msgstr "" + "Content-Transfer-Encoding: 8bit\n" + "Plural-Forms: nplurals=1; plural=0;\n" + +-#: aplay/aplay.c:128 ++#: 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:512 alsamixer/mixer_display.c:517 ++msgid "O" ++msgstr "" ++ ++#. TRANSLATORS: playback muted; one character ++#: alsamixer/mixer_display.c:514 alsamixer/mixer_display.c:518 ++msgid "M" ++msgstr "" ++ ++#. TRANSLATORS: "left"; no more than two characters ++#: alsamixer/mixer_display.c:532 ++msgid "L" ++msgstr "" ++ ++#. TRANSLATORS: "right"; no more than two characters ++#: alsamixer/mixer_display.c:536 ++msgid "R" ++msgstr "" ++ ++#. TRANSLATORS: no more than eight characters ++#: alsamixer/mixer_display.c:538 ++msgid "CAPTURE" ++msgstr "録音" ++ ++#: alsamixer/mixer_display.c:588 ++msgid "Front" ++msgstr "フロント" ++ ++#: alsamixer/mixer_display.c:591 ++msgid "Rear" ++msgstr "リア" ++ ++#: alsamixer/mixer_display.c:594 speaker-test/speaker-test.c:106 ++msgid "Center" ++msgstr "センター" ++ ++#: alsamixer/mixer_display.c:597 ++msgid "Woofer" ++msgstr "低音" ++ ++#: alsamixer/mixer_display.c:600 ++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 " ++msgstr "" ++ ++#: alsamixer/mixer_widget.c:215 ++msgid " Jaroslav Kysela " ++msgstr "" ++ ++#: alsamixer/mixer_widget.c:216 ++msgid " Clemens Ladisch " ++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:139 + msgid "raw data" + msgstr "raw データ" + +-#: aplay/aplay.c:129 ++#: aplay/aplay.c:140 + msgid "VOC" + msgstr "VOC" + +-#: aplay/aplay.c:131 ++#: aplay/aplay.c:142 + msgid "WAVE" + msgstr "WAVE" + +-#: aplay/aplay.c:132 ++#: aplay/aplay.c:143 + msgid "Sparc Audio" + msgstr "Sparc オーディオ" + +-#: aplay/aplay.c:153 +-#, fuzzy, c-format ++#: aplay/aplay.c:164 ++#, c-format + msgid "" + "Usage: %s [OPTION]... [FILE]...\n" + "\n" +@@ -49,7 +398,6 @@ msgid "" + "-f, --format=FORMAT sample format (case insensitive)\n" + "-r, --rate=# sample rate\n" + "-d, --duration=# interrupt after # seconds\n" +-"-s, --sleep-min=# min ticks to sleep\n" + "-M, --mmap mmap stream\n" + "-N, --nonblock nonblocking mode\n" + "-F, --period-time=# distance between interrupts is # microseconds\n" +@@ -62,7 +410,17 @@ msgid "" + "-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" + msgstr "" + "使用法: %s [オプション]... [ファイル]...\n" + "\n" +@@ -77,7 +435,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" +@@ -89,14 +446,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:180 speaker-test/speaker-test.c:725 ++#: aplay/aplay.c:199 speaker-test/speaker-test.c:740 + #, c-format + msgid "Recognized sample formats are:" + msgstr "認識されるサンプルフォーマット:" + +-#: aplay/aplay.c:186 ++#: aplay/aplay.c:205 + #, c-format + msgid "" + "\n" +@@ -105,143 +471,154 @@ msgstr "" + "\n" + "これらのいくつかは指定のハードウェアで使用不可能な場合があります\n" + +-#: aplay/aplay.c:187 ++#: aplay/aplay.c:206 + #, c-format + msgid "The availabled format shortcuts are:\n" + msgstr "可能なフォーマットの省略形:\n" + +-#: aplay/aplay.c:188 ++#: aplay/aplay.c:207 + #, c-format + msgid "-f cd (16 bit little endian, 44100, stereo)\n" + msgstr "-f cd (16 ビット、リトルエンディアン、44100、ステレオ)\n" + +-#: aplay/aplay.c:189 ++#: aplay/aplay.c:208 + #, c-format + msgid "-f cdr (16 bit big endian, 44100, stereo)\n" + msgstr "-f cdr (16 ビット、ビッグエンディアン、44100、ステレオ)\n" + +-#: aplay/aplay.c:190 ++#: aplay/aplay.c:209 + #, c-format + msgid "-f dat (16 bit little endian, 48000, stereo)\n" + msgstr "-f dat (16 ビット、リトルエンディアン、48000、ステレオ)\n" + +-#: aplay/aplay.c:204 ++#: aplay/aplay.c:223 + msgid "no soundcards found..." + msgstr "サウンドカードが見つかりません..." + +-#: aplay/aplay.c:207 ++#: aplay/aplay.c:226 + #, c-format + msgid "**** List of %s Hardware Devices ****\n" + msgstr "**** ハードウェアデバイス %s のリスト ****\n" + +-#: aplay/aplay.c:236 ++#: aplay/aplay.c:255 + #, c-format + msgid "card %i: %s [%s], device %i: %s [%s]\n" + msgstr "カード %i: %s [%s], デバイス %i: %s [%s]\n" + +-#: aplay/aplay.c:242 ++#: aplay/aplay.c:261 + #, c-format + msgid " Subdevices: %i/%i\n" + msgstr " サブデバイス: %i/%i\n" + +-#: aplay/aplay.c:249 ++#: aplay/aplay.c:268 + #, c-format + msgid " Subdevice #%i: %s\n" + msgstr " サブデバイス #%i: %s\n" + +-#: aplay/aplay.c:306 ++#: aplay/aplay.c:332 + #, c-format + msgid "Aborted by signal %s...\n" + msgstr "シグナル %s で中断...\n" + +-#: aplay/aplay.c:390 ++#: aplay/aplay.c:430 + msgid "command should be named either arecord or aplay" + msgstr "arecord または aplay コマンドのみ可能" + +-#: aplay/aplay.c:429 ++#: aplay/aplay.c:469 + #, c-format + msgid "unrecognized file format %s" + msgstr "不正なファイルフォーマット %s" + +-#: aplay/aplay.c:436 ++#: aplay/aplay.c:476 + #, c-format + msgid "value %i for channels is invalid" + msgstr "不正なチャネル数 %i" + +-#: aplay/aplay.c:455 ++#: aplay/aplay.c:495 + #, c-format + msgid "wrong extended format '%s'" + msgstr "不正な拡張フォーマット '%s'" + +-#: aplay/aplay.c:466 ++#: aplay/aplay.c:506 + #, c-format + msgid "bad speed value %i" + msgstr "不正なレート値 %i" + +-#: aplay/aplay.c:522 ++#: aplay/aplay.c:592 + #, c-format + msgid "Try `%s --help' for more information.\n" + msgstr "より詳しい情報は「%s --help」を実行してください\n" + +-#: aplay/aplay.c:538 ++#: aplay/aplay.c:608 + #, c-format + msgid "audio open error: %s" + msgstr "" + +-#: aplay/aplay.c:543 ++#: aplay/aplay.c:613 + #, c-format + msgid "info error: %s" + msgstr "" + +-#: aplay/aplay.c:550 ++#: aplay/aplay.c:620 + #, c-format + msgid "nonblock setting error: %s" + msgstr "" + +-#: aplay/aplay.c:560 aplay/aplay.c:667 aplay/aplay.c:1018 ++#: aplay/aplay.c:630 aplay/aplay.c:737 aplay/aplay.c:1092 + msgid "not enough memory" + msgstr "メモリが足りません" + +-#: aplay/aplay.c:657 ++#: aplay/aplay.c:727 + #, c-format + msgid "read error (called from line %i)" + msgstr "リードエラー (%i 行)" + +-#: aplay/aplay.c:715 ++#: aplay/aplay.c:785 + #, c-format + msgid "unknown length of 'fmt ' chunk (read %u, should be %u at least)" + msgstr "" + +-#: aplay/aplay.c:723 +-msgid "can't play not PCM-coded WAVE-files" +-msgstr "PCM 以外の WAVE ファイルは再生できません" ++#: aplay/aplay.c:795 ++#, c-format ++msgid "" ++"unknown length of extensible 'fmt ' chunk (read %u, should be %u at least)" ++msgstr "" + +-#: aplay/aplay.c:727 ++#: aplay/aplay.c:800 ++msgid "wrong format tag in extensible 'fmt ' chunk" ++msgstr "" ++ ++#: aplay/aplay.c:807 ++#, c-format ++msgid "can't play WAVE-file format 0x%04x which is not PCM or FLOAT encoded" ++msgstr "" ++ ++#: aplay/aplay.c:811 + #, c-format + msgid "can't play WAVE-files with %d tracks" + msgstr "%d トラックを含む WAVE ファイルは再生できません" + +-#: aplay/aplay.c:735 aplay/aplay.c:832 ++#: aplay/aplay.c:819 aplay/aplay.c:919 + #, c-format + msgid "Warning: format is changed to U8\n" + msgstr "警告: フォーマットは U8 に変更されます\n" + +-#: aplay/aplay.c:741 ++#: aplay/aplay.c:825 + #, c-format + msgid "Warning: format is changed to S16_LE\n" + msgstr "警告: フォーマットは S16_LE に変更されます\n" + +-#: aplay/aplay.c:749 ++#: aplay/aplay.c:833 + #, c-format + msgid "Warning: format is changed to S24_3LE\n" + msgstr "警告: フォーマットは S24_3LE に変更されます\n" + +-#: aplay/aplay.c:755 ++#: aplay/aplay.c:839 + #, c-format + msgid "Warning: format is changed to S24_LE\n" + msgstr "警告: フォーマットは S24_LE に変更されます\n" + +-#: aplay/aplay.c:759 ++#: aplay/aplay.c:843 + #, c-format + msgid "" + " can't play WAVE-files with sample %d bits in %d bytes wide (%d channels)" +@@ -249,258 +626,261 @@ msgstr "" + "%2$d バイト長 %1$d サンプルビット (%3$d チャネル) の WAVE ファイルは再生でき" + "ません" + +-#: aplay/aplay.c:768 ++#: aplay/aplay.c:855 + #, c-format + msgid " can't play WAVE-files with sample %d bits wide" + msgstr "%d ビット長のサンプルの WAVE ファイルは再生できません" + +-#: aplay/aplay.c:826 ++#: aplay/aplay.c:913 + #, c-format + msgid "Warning: format is changed to MU_LAW\n" + msgstr "警告: フォーマットは MU_LAW に変更されます\n" + +-#: aplay/aplay.c:838 ++#: aplay/aplay.c:925 + #, c-format + msgid "Warning: format is changed to S16_BE\n" + msgstr "警告: フォーマットは S16_BE に変更されます\n" + +-#: aplay/aplay.c:851 aplay/aplay.c:1488 aplay/aplay.c:1495 aplay/aplay.c:2011 +-#: aplay/aplay.c:2023 ++#: aplay/aplay.c:938 aplay/aplay.c:1768 aplay/aplay.c:1775 aplay/aplay.c:2297 ++#: aplay/aplay.c:2309 + msgid "read error" + msgstr "リードエラー" + +-#: aplay/aplay.c:871 ++#: aplay/aplay.c:957 + msgid "Broken configuration for this PCM: no configurations available" + msgstr "指定の PCM を使用できません: 設定がありません" + +-#: aplay/aplay.c:888 ++#: aplay/aplay.c:974 + msgid "Access type not available" + msgstr "アクセスタイプが使用不可能" + +-#: aplay/aplay.c:893 ++#: aplay/aplay.c:979 + msgid "Sample format non available" + msgstr "サンプルフォーマットが使用不可能" + +-#: aplay/aplay.c:898 ++#: aplay/aplay.c:984 + msgid "Channels count non available" + msgstr "チャネル数が使用不可能" + +-#: aplay/aplay.c:913 ++#: aplay/aplay.c:999 + #, c-format + msgid "Warning: rate is not accurate (requested = %iHz, got = %iHz)\n" + msgstr "警告: レートが不正確です (要求値 = %iHz, 使用値 = %iHz)\n" + +-#: aplay/aplay.c:919 ++#: aplay/aplay.c:1005 + #, c-format + msgid " please, try the plug plugin %s\n" + msgstr " plug プラグイン%s を使用してください\n" + +-#: aplay/aplay.c:954 ++#: aplay/aplay.c:1041 + msgid "Unable to install hw params:" + msgstr "hw params のインストールに失敗しました:" + +-#: aplay/aplay.c:961 ++#: aplay/aplay.c:1048 + #, c-format + msgid "Can't use period equal to buffer size (%lu == %lu)" + msgstr "period と buffer サイズには同じ値を使用できません (%lu == %lu)" + +-#: aplay/aplay.c:968 +-msgid "Unable to obtain xfer align\n" +-msgstr "xfer align 値を得ることができません\n" +- +-#: aplay/aplay.c:1005 ++#: aplay/aplay.c:1079 + msgid "unable to install sw params:" + msgstr "sw params のインストールに失敗しました:" + +-#: aplay/aplay.c:1044 ++#: aplay/aplay.c:1154 + #, c-format + msgid "status error: %s" + msgstr "ステータスエラー: %s" + +-#: aplay/aplay.c:1052 ++#: aplay/aplay.c:1164 aplay/aplay.c:1175 + #, c-format + msgid "%s!!! (at least %.3f ms long)\n" + msgstr "%s!!! (少なくとも %.3f ms)\n" + +-#: aplay/aplay.c:1053 ++#: aplay/aplay.c:1165 aplay/aplay.c:1168 aplay/aplay.c:1176 + msgid "underrun" + msgstr "アンダーラン" + +-#: aplay/aplay.c:1053 ++#: aplay/aplay.c:1165 aplay/aplay.c:1176 + msgid "overrun" + msgstr "オーバーラン" + +-#: aplay/aplay.c:1056 ++#: aplay/aplay.c:1180 + #, c-format + msgid "Status:\n" + msgstr "ステータス:\n" + +-#: aplay/aplay.c:1060 ++#: aplay/aplay.c:1184 + #, c-format + msgid "xrun: prepare error: %s" + msgstr "" + +-#: aplay/aplay.c:1066 ++#: aplay/aplay.c:1190 + #, c-format + msgid "Status(DRAINING):\n" + msgstr "ステータス(DRAINING):\n" + +-#: aplay/aplay.c:1070 ++#: aplay/aplay.c:1194 + #, c-format + msgid "capture stream format change? attempting recover...\n" + msgstr "録音ストリームのフォーマットが変更? 修復を試みます...\n" + +-#: aplay/aplay.c:1072 ++#: aplay/aplay.c:1196 + #, c-format + msgid "xrun(DRAINING): prepare error: %s" + msgstr "" + +-#: aplay/aplay.c:1079 ++#: aplay/aplay.c:1203 + #, c-format + msgid "Status(R/W):\n" + msgstr "ステータス(R/W):\n" + +-#: aplay/aplay.c:1082 ++#: aplay/aplay.c:1206 + #, c-format + msgid "read/write error, state = %s" + msgstr "読み書きエラー, ステータス = %s" + +-#: aplay/aplay.c:1092 ++#: aplay/aplay.c:1216 + #, c-format + msgid "Suspended. Trying resume. " + msgstr "サスペンド中です。レジュームします。" + +-#: aplay/aplay.c:1097 ++#: aplay/aplay.c:1221 + #, c-format + msgid "Failed. Restarting stream. " + msgstr "失敗しました。ストリームを再スタートします。" + +-#: aplay/aplay.c:1099 ++#: aplay/aplay.c:1223 + #, c-format + msgid "suspend: prepare error: %s" + msgstr "サスペンド: prepare エラー: %s" + +-#: aplay/aplay.c:1104 ++#: aplay/aplay.c:1228 + #, c-format + msgid "Done.\n" + msgstr "終了\n" + +-#: aplay/aplay.c:1183 ++#: aplay/aplay.c:1250 + #, c-format +-msgid "Unsupported bit size %d.\n" ++msgid " !clip " + msgstr "" + +-#: aplay/aplay.c:1219 ++#: aplay/aplay.c:1397 + #, c-format +-msgid " !clip " ++msgid "Unsupported bit size %d.\n" + msgstr "" + +-#: aplay/aplay.c:1224 ++#: aplay/aplay.c:1431 + #, c-format + msgid "Max peak (%li samples): 0x%08x " + msgstr "最大ピーク (%li サンプル): 0x%08x " + +-#: aplay/aplay.c:1258 ++#: aplay/aplay.c:1465 ++#, c-format ++msgid "" ++"Suspicious buffer position (%li total): avail = %li, delay = %li, buffer = %" ++"li\n" ++msgstr "" ++ ++#: aplay/aplay.c:1528 + #, c-format + msgid "write error: %s" + msgstr "書込エラー: %s" + +-#: aplay/aplay.c:1300 ++#: aplay/aplay.c:1574 + #, c-format + msgid "writev error: %s" + msgstr "書込(writev)エラー: %s" + +-#: aplay/aplay.c:1339 ++#: aplay/aplay.c:1617 + #, c-format + msgid "read error: %s" + msgstr "読込エラー: %s" + +-#: aplay/aplay.c:1378 ++#: aplay/aplay.c:1660 + #, c-format + msgid "readv error: %s" + msgstr "読込(readv)エラー: %s" + +-#: aplay/aplay.c:1426 ++#: aplay/aplay.c:1708 + msgid "can't allocate buffer for silence" + msgstr "サイレンス用のバッファの取得に失敗しました" + +-#: aplay/aplay.c:1435 aplay/aplay.c:1663 aplay/aplay.c:1668 aplay/aplay.c:1715 +-#: aplay/aplay.c:1724 aplay/aplay.c:1731 aplay/aplay.c:1741 aplay/aplay.c:1747 +-#: aplay/aplay.c:1815 aplay/aplay.c:1845 aplay/aplay.c:1859 ++#: aplay/aplay.c:1717 aplay/aplay.c:1943 aplay/aplay.c:1948 aplay/aplay.c:1995 ++#: aplay/aplay.c:2004 aplay/aplay.c:2011 aplay/aplay.c:2021 aplay/aplay.c:2027 ++#: aplay/aplay.c:2099 aplay/aplay.c:2129 aplay/aplay.c:2143 + msgid "write error" + msgstr "書込エラー" + +-#: aplay/aplay.c:1449 ++#: aplay/aplay.c:1730 + #, c-format + msgid "voc_pcm_flush - silence error" + msgstr "" + +-#: aplay/aplay.c:1455 ++#: aplay/aplay.c:1733 + msgid "voc_pcm_flush error" + msgstr "" + +-#: aplay/aplay.c:1479 ++#: aplay/aplay.c:1759 + msgid "malloc error" + msgstr "malloc エラー" + +-#: aplay/aplay.c:1483 ++#: aplay/aplay.c:1763 + #, c-format + msgid "Playing Creative Labs Channel file '%s'...\n" + msgstr "Creative Labs Channel ファイル '%s' を演奏中...\n" + +-#: aplay/aplay.c:1551 aplay/aplay.c:1643 ++#: aplay/aplay.c:1831 aplay/aplay.c:1923 + msgid "can't play packed .voc files" + msgstr "packed .voc ファイルは演奏できません" + +-#: aplay/aplay.c:1603 ++#: aplay/aplay.c:1883 + #, c-format + msgid "can't play loops; %s isn't seekable\n" + msgstr "ループ演奏できません。%s はシーク不可能です\n" + +-#: aplay/aplay.c:1652 ++#: aplay/aplay.c:1932 + #, c-format + msgid "unknown blocktype %d. terminate." + msgstr "未知のブロックタイプ %d: 終了します。" + +-#: aplay/aplay.c:1782 ++#: aplay/aplay.c:2063 + #, c-format + msgid "Wave doesn't support %s format..." + msgstr "WAVE は %s フォーマットをサポートしません..." + +-#: aplay/aplay.c:1839 ++#: aplay/aplay.c:2123 + #, c-format + msgid "Sparc Audio doesn't support %s format..." + msgstr "Sparc オーディオは %s フォーマットをサポートしません..." + +-#: aplay/aplay.c:1920 ++#: aplay/aplay.c:2204 + msgid "Playing" + msgstr "再生中" + +-#: aplay/aplay.c:1920 ++#: aplay/aplay.c:2204 + msgid "Recording" + msgstr "録音中" + +-#: aplay/aplay.c:1924 ++#: aplay/aplay.c:2208 + #, c-format + msgid "Rate %d Hz, " + msgstr "レート %d Hz, " + +-#: aplay/aplay.c:1926 ++#: aplay/aplay.c:2210 + #, c-format + msgid "Mono" + msgstr "モノラル" + +-#: aplay/aplay.c:1928 ++#: aplay/aplay.c:2212 + #, c-format + msgid "Stereo" + msgstr "ステレオ" + +-#: aplay/aplay.c:1930 ++#: aplay/aplay.c:2214 + #, c-format + msgid "Channels %i" + msgstr "チャネル数 %i" + +-#: aplay/aplay.c:2285 aplay/aplay.c:2338 ++#: aplay/aplay.c:2573 aplay/aplay.c:2626 + #, c-format + msgid "You need to specify %d files" + msgstr "%d 個のファイルを指定してください" +@@ -631,7 +1011,7 @@ msgstr "クライアント情報を取得できません\n" + msgid "invalid sender address %s\n" + msgstr "送信アドレスが不正です: %s\n" + +-#: seq/aconnect/aconnect.c:373 seq/aseqnet/aseqnet.c:289 ++#: seq/aconnect/aconnect.c:373 seq/aseqnet/aseqnet.c:290 + #, c-format + msgid "invalid destination address %s\n" + msgstr "受信アドレスが不正です: %s\n" +@@ -656,391 +1036,382 @@ msgstr "既に接続されています\n" + msgid "Connection failed (%s)\n" + msgstr "接続に失敗 (%s)\n" + +-#: seq/aseqnet/aseqnet.c:163 ++#: seq/aseqnet/aseqnet.c:164 + #, c-format + msgid "aseqnet - network client/server on ALSA sequencer\n" + msgstr "aseqnet - ALSA sequencer 上のネットワーククライアント/サーバ\n" + +-#: seq/aseqnet/aseqnet.c:164 ++#: seq/aseqnet/aseqnet.c:165 + #, c-format + msgid " Copyright (C) 1999 Takashi Iwai\n" + msgstr "" + +-#: seq/aseqnet/aseqnet.c:165 ++#: seq/aseqnet/aseqnet.c:166 + #, c-format + msgid "usage:\n" + msgstr "使用法:\n" + +-#: seq/aseqnet/aseqnet.c:166 ++#: seq/aseqnet/aseqnet.c:167 + #, c-format + msgid " server mode: aseqnet [-options]\n" + msgstr " サーバモード: aseqnet [-オプション]\n" + +-#: seq/aseqnet/aseqnet.c:167 ++#: seq/aseqnet/aseqnet.c:168 + #, c-format + msgid " client mode: aseqnet [-options] server_host\n" + msgstr " クライアントモード: aseqnet [-オプション] サーバホスト\n" + +-#: seq/aseqnet/aseqnet.c:168 ++#: seq/aseqnet/aseqnet.c:169 + #, c-format + msgid "options:\n" + msgstr "オプション:\n" + +-#: seq/aseqnet/aseqnet.c:169 ++#: seq/aseqnet/aseqnet.c:170 + #, c-format + msgid " -p,--port # : sepcify TCP port (digit or service name)\n" + msgstr " -p,--port # : TCP ポートの指定 (数字またはサービス名)\n" + +-#: seq/aseqnet/aseqnet.c:170 ++#: seq/aseqnet/aseqnet.c:171 + #, c-format + msgid " -s,--source addr : read from given addr (client:port)\n" + msgstr " -s,--source addr : 指定のアドレス(クライアント:ポート)から読み込む\n" + +-#: seq/aseqnet/aseqnet.c:171 ++#: seq/aseqnet/aseqnet.c:172 + #, c-format + msgid " -d,--dest addr : write to given addr (client:port)\n" + msgstr " -d,--dest addr : 指定のアドレス(クライアント:ポート)に書き込む\n" + +-#: seq/aseqnet/aseqnet.c:172 ++#: seq/aseqnet/aseqnet.c:173 + #, c-format + msgid " -v, --verbose : print verbose messages\n" + msgstr " -v,--verbose : 冗長メッセージ表示\n" + +-#: seq/aseqnet/aseqnet.c:173 ++#: seq/aseqnet/aseqnet.c:174 + #, c-format + msgid " -i, --info : print certain received events\n" + msgstr " -i,--info : 受信イベントを表示する\n" + +-#: seq/aseqnet/aseqnet.c:187 ++#: seq/aseqnet/aseqnet.c:188 + #, c-format + msgid "can't malloc\n" + msgstr "malloc できません\n" + +-#: seq/aseqnet/aseqnet.c:212 ++#: seq/aseqnet/aseqnet.c:213 + #, c-format + msgid "closing files..\n" + msgstr "ファイルを閉じます..\n" + +-#: seq/aseqnet/aseqnet.c:271 ++#: seq/aseqnet/aseqnet.c:272 + #, c-format + msgid "sequencer opened: %d:%d\n" + msgstr "" + +-#: seq/aseqnet/aseqnet.c:278 ++#: seq/aseqnet/aseqnet.c:279 + #, c-format + msgid "invalid source address %s\n" + msgstr "不正な送信アドレス %s\n" + +-#: seq/aseqnet/aseqnet.c:308 ++#: seq/aseqnet/aseqnet.c:309 + #, c-format + msgid "service '%s' is not found in /etc/services\n" + msgstr "サービス '%s' が /etc/services に見つかりません\n" + +-#: seq/aseqnet/aseqnet.c:376 ++#: seq/aseqnet/aseqnet.c:377 + #, c-format + msgid "too many connections!\n" + msgstr "接続が多すぎます!\n" + +-#: seq/aseqnet/aseqnet.c:387 ++#: seq/aseqnet/aseqnet.c:388 + #, c-format + msgid "accepted[%d]\n" + msgstr "了解[%d]\n" + +-#: seq/aseqnet/aseqnet.c:410 ++#: seq/aseqnet/aseqnet.c:411 + #, c-format + msgid "can't get address %s\n" + msgstr "アドレス %s を取得できません\n" + +-#: seq/aseqnet/aseqnet.c:421 ++#: seq/aseqnet/aseqnet.c:422 + #, c-format + msgid "ok.. connected\n" + msgstr "ok.. 接続\n" + +-#: seq/aseqnet/aseqnet.c:517 ++#: seq/aseqnet/aseqnet.c:518 + #, c-format + msgid "Channel %2d: Control event : %5d\n" + msgstr "チャネル %2d: コントロール : %5d\n" + +-#: seq/aseqnet/aseqnet.c:521 ++#: seq/aseqnet/aseqnet.c:522 + #, c-format + msgid "Channel %2d: Pitchbender : %5d\n" + msgstr "チャネル %2d: ピッチベンド : %5d\n" + +-#: seq/aseqnet/aseqnet.c:525 ++#: seq/aseqnet/aseqnet.c:526 + #, c-format + msgid "Channel %2d: Note On event : %5d\n" + msgstr "チャネル %2d: ノートオン : %5d\n" + +-#: seq/aseqnet/aseqnet.c:529 ++#: seq/aseqnet/aseqnet.c:530 + #, c-format + msgid "Channel %2d: Note Off event: %5d\n" + msgstr "チャネル %2d: ノートオフ : %5d\n" + +-#: seq/aseqnet/aseqnet.c:584 ++#: seq/aseqnet/aseqnet.c:585 + #, c-format + msgid "disconnected\n" + msgstr "切り離し\n" + +-#: speaker-test/speaker-test.c:87 ++#: speaker-test/speaker-test.c:102 + msgid "Front Left" + msgstr "" + +-#: speaker-test/speaker-test.c:88 ++#: speaker-test/speaker-test.c:103 + msgid "Front Right" + msgstr "" + +-#: speaker-test/speaker-test.c:89 ++#: speaker-test/speaker-test.c:104 + msgid "Rear Left" + msgstr "" + +-#: speaker-test/speaker-test.c:90 ++#: speaker-test/speaker-test.c:105 + msgid "Rear Right" + msgstr "" + +-#: speaker-test/speaker-test.c:91 +-msgid "Center" +-msgstr "" +- +-#: speaker-test/speaker-test.c:92 ++#: speaker-test/speaker-test.c:107 + msgid "LFE" + msgstr "" + +-#: speaker-test/speaker-test.c:93 ++#: speaker-test/speaker-test.c:108 + msgid "Side Left" + msgstr "" + +-#: speaker-test/speaker-test.c:94 ++#: speaker-test/speaker-test.c:109 + msgid "Side Right" + msgstr "" + +-#: speaker-test/speaker-test.c:95 ++#: speaker-test/speaker-test.c:110 + msgid "Channel 9" + msgstr "" + +-#: speaker-test/speaker-test.c:96 ++#: speaker-test/speaker-test.c:111 + msgid "Channel 10" + msgstr "" + +-#: speaker-test/speaker-test.c:97 ++#: speaker-test/speaker-test.c:112 + msgid "Channel 11" + msgstr "" + +-#: speaker-test/speaker-test.c:98 ++#: speaker-test/speaker-test.c:113 + msgid "Channel 12" + msgstr "" + +-#: speaker-test/speaker-test.c:99 ++#: speaker-test/speaker-test.c:114 + msgid "Channel 13" + msgstr "" + +-#: speaker-test/speaker-test.c:100 ++#: speaker-test/speaker-test.c:115 + msgid "Channel 14" + msgstr "" + +-#: speaker-test/speaker-test.c:101 ++#: speaker-test/speaker-test.c:116 + msgid "Channel 15" + msgstr "" + +-#: speaker-test/speaker-test.c:102 ++#: speaker-test/speaker-test.c:117 + msgid "Channel 16" + msgstr "" + +-#: speaker-test/speaker-test.c:279 ++#: speaker-test/speaker-test.c:307 + #, c-format + msgid "Broken configuration for playback: no configurations available: %s\n" + msgstr "再生用に設定できません: 設定がみつかりません: %s\n" + +-#: speaker-test/speaker-test.c:286 ++#: speaker-test/speaker-test.c:314 + #, c-format + msgid "Access type not available for playback: %s\n" + msgstr "アクセスタイプが不正です: %s\n" + +-#: speaker-test/speaker-test.c:293 ++#: speaker-test/speaker-test.c:321 + #, c-format + msgid "Sample format not available for playback: %s\n" + msgstr "指定のサンプルフォーマットを使用できません: %s\n" + +-#: speaker-test/speaker-test.c:300 ++#: speaker-test/speaker-test.c:328 + #, c-format + msgid "Channels count (%i) not available for playbacks: %s\n" + msgstr "チャネル数 (%i) を使用できません: %s\n" + +-#: speaker-test/speaker-test.c:308 ++#: speaker-test/speaker-test.c:336 + #, c-format + msgid "Rate %iHz not available for playback: %s\n" + msgstr "レート %iHz を使用できません: %s\n" + +-#: speaker-test/speaker-test.c:313 ++#: speaker-test/speaker-test.c:341 + #, c-format + msgid "Rate doesn't match (requested %iHz, get %iHz, err %d)\n" + msgstr "設定レートが一致しません< (要求値 %iHz, 取得値 %iHz, エラー %d)\n" + +-#: speaker-test/speaker-test.c:317 ++#: speaker-test/speaker-test.c:345 + #, c-format + msgid "Rate set to %iHz (requested %iHz)\n" + msgstr "レート %iHz (要求値 %iHz)\n" + +-#: speaker-test/speaker-test.c:323 ++#: speaker-test/speaker-test.c:351 + #, c-format + msgid "Buffer size range from %lu to %lu\n" + msgstr "バッファサイズ範囲 %lu 〜 %lu\n" + +-#: speaker-test/speaker-test.c:324 ++#: speaker-test/speaker-test.c:352 + #, c-format + msgid "Period size range from %lu to %lu\n" + msgstr "ピリオドサイズ範囲 %lu 〜 %lu\n" + +-#: speaker-test/speaker-test.c:326 ++#: speaker-test/speaker-test.c:354 + #, c-format + msgid "Requested period time %u us\n" + msgstr "要求されたピリオド長 %u us\n" + +-#: speaker-test/speaker-test.c:329 ++#: speaker-test/speaker-test.c:357 + #, c-format + msgid "Unable to set period time %u us for playback: %s\n" + msgstr "ピリオド長 %u us を設定できません: %s\n" + +-#: speaker-test/speaker-test.c:335 ++#: speaker-test/speaker-test.c:363 + #, c-format + msgid "Requested buffer time %u us\n" + msgstr "要求されたバッファ長 %u us\n" + +-#: speaker-test/speaker-test.c:338 ++#: speaker-test/speaker-test.c:366 + #, c-format + msgid "Unable to set buffer time %u us for playback: %s\n" + msgstr "バッファ長 %u us を設定できません: %s\n" + +-#: speaker-test/speaker-test.c:347 ++#: speaker-test/speaker-test.c:375 + #, c-format + msgid "Using max buffer size %lu\n" + msgstr "最大バッファサイズ %lu を使用\n" + +-#: speaker-test/speaker-test.c:350 ++#: speaker-test/speaker-test.c:378 + #, c-format + msgid "Unable to set buffer size %lu for playback: %s\n" + msgstr "バッファサイズ %lu を設定できません: %s\n" + +-#: speaker-test/speaker-test.c:356 ++#: speaker-test/speaker-test.c:384 + #, c-format + msgid "Periods = %u\n" + msgstr "ピリオド数 = %u\n" + +-#: speaker-test/speaker-test.c:359 ++#: speaker-test/speaker-test.c:387 + #, c-format + msgid "Unable to set nperiods %u for playback: %s\n" + msgstr "ピリオド数 %u を設定できません: %s\n" + +-#: speaker-test/speaker-test.c:366 ++#: speaker-test/speaker-test.c:396 ++#, c-format ++msgid "Unable to set hw params for playback: %s\n" ++msgstr "hw params を設定できません: %s\n" ++ ++#: speaker-test/speaker-test.c:402 + #, c-format + msgid "was set period_size = %lu\n" + msgstr "period_size = %lu で設定\n" + +-#: speaker-test/speaker-test.c:367 ++#: speaker-test/speaker-test.c:403 + #, c-format + msgid "was set buffer_size = %lu\n" + msgstr "buffer_size = %lu で設定\n" + +-#: speaker-test/speaker-test.c:369 ++#: speaker-test/speaker-test.c:405 + #, c-format + msgid "buffer to small, could not use\n" + msgstr "バッファが小さすぎます\n" + +-#: speaker-test/speaker-test.c:376 +-#, c-format +-msgid "Unable to set hw params for playback: %s\n" +-msgstr "hw params を設定できません: %s\n" +- +-#: speaker-test/speaker-test.c:389 ++#: speaker-test/speaker-test.c:418 + #, c-format + msgid "Unable to determine current swparams for playback: %s\n" + msgstr "現在の swparams を取得できません: %s\n" + +-#: speaker-test/speaker-test.c:396 ++#: speaker-test/speaker-test.c:425 + #, c-format + msgid "Unable to set start threshold mode for playback: %s\n" + msgstr "start_threshold モードを設定できません: %s\n" + +-#: speaker-test/speaker-test.c:403 ++#: speaker-test/speaker-test.c:432 + #, c-format + msgid "Unable to set avail min for playback: %s\n" + msgstr "avail_min を設定できません: %s\n" + +-#: speaker-test/speaker-test.c:410 +-#, c-format +-msgid "Unable to set transfer align for playback: %s\n" +-msgstr "転送 align を設定できません: %s\n" +- +-#: speaker-test/speaker-test.c:417 ++#: speaker-test/speaker-test.c:439 + #, c-format + msgid "Unable to set sw params for playback: %s\n" + msgstr "再生用の sw params を設定できません: %s\n" + +-#: speaker-test/speaker-test.c:432 ++#: speaker-test/speaker-test.c:454 + #, c-format + msgid "Can't recovery from underrun, prepare failed: %s\n" + msgstr "アンダーランから復帰失敗: %s\n" + +-#: speaker-test/speaker-test.c:443 ++#: speaker-test/speaker-test.c:465 + #, c-format + msgid "Can't recovery from suspend, prepare failed: %s\n" + msgstr "サスペンドから復帰失敗: %s\n" + +-#: speaker-test/speaker-test.c:517 speaker-test/speaker-test.c:911 ++#: speaker-test/speaker-test.c:529 speaker-test/speaker-test.c:926 + #, c-format + msgid "No enough memory\n" + msgstr "メモリが足りません\n" + +-#: speaker-test/speaker-test.c:522 ++#: speaker-test/speaker-test.c:534 + #, c-format + msgid "Cannot open WAV file %s\n" + msgstr "WAVファイルがオープンできません: %s\n" + +-#: speaker-test/speaker-test.c:526 speaker-test/speaker-test.c:555 ++#: speaker-test/speaker-test.c:538 speaker-test/speaker-test.c:567 + #, c-format + msgid "Invalid WAV file %s\n" + msgstr "不正なWAVファイルです: %s\n" + +-#: speaker-test/speaker-test.c:531 ++#: speaker-test/speaker-test.c:543 + #, c-format + msgid "Not a WAV file: %s\n" + msgstr "WAVファイルではありません: %s\n" + +-#: speaker-test/speaker-test.c:535 ++#: speaker-test/speaker-test.c:547 + #, c-format + msgid "Unsupported WAV format %d for %s\n" + msgstr "未サポートのWAVフォーマット %d: %s\n" + +-#: speaker-test/speaker-test.c:540 ++#: speaker-test/speaker-test.c:552 + #, c-format + msgid "%s is not a mono stream (%d channels)\n" + msgstr "%s はモノストリームではありません (%d チャネル)\n" + +-#: speaker-test/speaker-test.c:545 ++#: speaker-test/speaker-test.c:557 + #, c-format + msgid "Sample rate doesn't match (%d) for %s\n" + msgstr "サンプルレートが不一致です(%d): %s\n" + +-#: speaker-test/speaker-test.c:550 ++#: speaker-test/speaker-test.c:562 + #, c-format + msgid "Unsupported sample format bits %d for %s\n" + msgstr "未サポートのサンプルフォーマットビット %d: %s\n" + +-#: speaker-test/speaker-test.c:600 ++#: speaker-test/speaker-test.c:612 + #, c-format + msgid "Undefined channel %d\n" + msgstr "未定義のチャネル %d\n" + +-#: speaker-test/speaker-test.c:651 ++#: speaker-test/speaker-test.c:663 + #, c-format + msgid "Write error: %d,%s\n" + msgstr "書込エラー: %d,%s\n" + +-#: speaker-test/speaker-test.c:653 ++#: speaker-test/speaker-test.c:665 + #, c-format + msgid "xrun_recovery failed: %d,%s\n" + msgstr "xrun_recovery 失敗: %d,%s\n" + +-#: speaker-test/speaker-test.c:708 ++#: speaker-test/speaker-test.c:723 + #, c-format + msgid "" + "Usage: speaker-test [OPTION]... \n" +@@ -1078,84 +1449,72 @@ msgstr "" + "-W,--wavdir WAVファイルのあるディレクトリを指定\n" + "\n" + +-#: speaker-test/speaker-test.c:820 ++#: speaker-test/speaker-test.c:835 + #, c-format + msgid "Invalid number of periods %d\n" + msgstr "不正なピリオド数 %d\n" + +-#: speaker-test/speaker-test.c:834 speaker-test/speaker-test.c:838 ++#: speaker-test/speaker-test.c:849 speaker-test/speaker-test.c:853 + #, c-format + msgid "Invalid test type %s\n" + msgstr "不正なテストタイプ %s\n" + +-#: speaker-test/speaker-test.c:850 ++#: speaker-test/speaker-test.c:865 + #, c-format + msgid "Invalid parameter for -s option.\n" + msgstr "-s オプションの値が不正です\n" + +-#: speaker-test/speaker-test.c:861 ++#: speaker-test/speaker-test.c:876 + #, c-format + msgid "Unknown option '%c'\n" + msgstr "未知のオプション '%c'\n" + +-#: speaker-test/speaker-test.c:875 ++#: speaker-test/speaker-test.c:890 + #, c-format + msgid "Playback device is %s\n" + msgstr "再生デバイス: %s\n" + +-#: speaker-test/speaker-test.c:876 ++#: speaker-test/speaker-test.c:891 + #, c-format + msgid "Stream parameters are %iHz, %s, %i channels\n" + msgstr "ストリームパラメータ: %iHz, %s, %i チャネル\n" + +-#: speaker-test/speaker-test.c:879 ++#: speaker-test/speaker-test.c:894 + #, c-format + msgid "Using 16 octaves of pink noise\n" + msgstr "16 オクターブのピンクノイズを使用\n" + +-#: speaker-test/speaker-test.c:882 ++#: speaker-test/speaker-test.c:897 + #, c-format + msgid "Sine wave rate is %.4fHz\n" + msgstr "正弦波レート: %.4fHz\n" + +-#: speaker-test/speaker-test.c:885 ++#: speaker-test/speaker-test.c:900 + #, c-format + msgid "WAV file(s)\n" + msgstr "WAV ファイル\n" + +-#: speaker-test/speaker-test.c:891 ++#: speaker-test/speaker-test.c:906 + #, c-format + msgid "Playback open error: %d,%s\n" + msgstr "再生オープンエラー: %d,%s\n" + +-#: speaker-test/speaker-test.c:896 ++#: speaker-test/speaker-test.c:911 + #, c-format + msgid "Setting of hwparams failed: %s\n" + msgstr "hwparams の設定に失敗: %s\n" + +-#: speaker-test/speaker-test.c:901 ++#: speaker-test/speaker-test.c:916 + #, c-format + msgid "Setting of swparams failed: %s\n" + msgstr "swparams の設定に失敗: %s\n" + +-#: speaker-test/speaker-test.c:942 speaker-test/speaker-test.c:964 ++#: speaker-test/speaker-test.c:957 speaker-test/speaker-test.c:979 + #, c-format + msgid "Transfer failed: %s\n" + msgstr "転送に失敗しました: %s\n" + +-#: speaker-test/speaker-test.c:952 ++#: speaker-test/speaker-test.c:967 + #, c-format + msgid "Time per period = %lf\n" + msgstr "ピリオド時間 = %lf\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/speaker-test/speaker-test.c b/speaker-test/speaker-test.c +index 63a7151..e22c937 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,7 +90,7 @@ 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; +@@ -142,17 +156,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> 16; +-#elif __BYTE_ORDER == __BIG_ENDIAN +- *samp16++ = bswap_16(ires >> 16); +-#endif ++ *samp16++ = LE_SHORT(ires >> 16); + } else { + *samp16++ = 0; + } +@@ -181,11 +180,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 +190,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 +198,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 +207,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 +254,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 +263,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 +272,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 +281,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 +502,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',' ') +@@ -860,9 +817,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); diff --git a/alsa-utils-po-pre-patch.diff b/alsa-utils-po-pre-patch.diff new file mode 100644 index 0000000..6fc63dd --- /dev/null +++ b/alsa-utils-po-pre-patch.diff @@ -0,0 +1,1180 @@ +--- + po/ja.po | 439 +++++++++++++++++++++++++++++---------------------------------- + 1 file changed, 206 insertions(+), 233 deletions(-) + +--- a/po/ja.po ++++ b/po/ja.po +@@ -8,7 +8,7 @@ + msgstr "" + "Project-Id-Version: alsa-utils 1.0.9a\n" + "Report-Msgid-Bugs-To: \n" +-"POT-Creation-Date: 2009-05-06 09:17+0200\n" ++"POT-Creation-Date: 2006-11-11 10:45+0000\n" + "PO-Revision-Date: 2006-04-18 15:51+0200\n" + "Last-Translator: Takashi Iwai \n" + "Language-Team: Japanese\n" +@@ -17,23 +17,23 @@ + "Content-Transfer-Encoding: 8bit\n" + "Plural-Forms: nplurals=1; plural=0;\n" + +-#: aplay/aplay.c:139 ++#: aplay/aplay.c:128 + msgid "raw data" + msgstr "raw データ" + +-#: aplay/aplay.c:140 ++#: aplay/aplay.c:129 + msgid "VOC" + msgstr "VOC" + +-#: aplay/aplay.c:142 ++#: aplay/aplay.c:131 + msgid "WAVE" + msgstr "WAVE" + +-#: aplay/aplay.c:143 ++#: aplay/aplay.c:132 + msgid "Sparc Audio" + msgstr "Sparc オーディオ" + +-#: aplay/aplay.c:164 ++#: aplay/aplay.c:153 + #, fuzzy, c-format + msgid "" + "Usage: %s [OPTION]... [FILE]...\n" +@@ -49,6 +49,7 @@ + "-f, --format=FORMAT sample format (case insensitive)\n" + "-r, --rate=# sample rate\n" + "-d, --duration=# interrupt after # seconds\n" ++"-s, --sleep-min=# min ticks to sleep\n" + "-M, --mmap mmap stream\n" + "-N, --nonblock nonblocking mode\n" + "-F, --period-time=# distance between interrupts is # microseconds\n" +@@ -61,17 +62,7 @@ + "-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" + msgstr "" + "使用法: %s [オプション]... [ファイル]...\n" + "\n" +@@ -100,12 +91,12 @@ + "-v, --verbose PCM の設定を表示 (複数指定可能)\n" + "-I, --separate-channels 各チャネルに一つのファイルを用いる\n" + +-#: aplay/aplay.c:199 speaker-test/speaker-test.c:783 ++#: aplay/aplay.c:180 speaker-test/speaker-test.c:725 + #, c-format + msgid "Recognized sample formats are:" + msgstr "認識されるサンプルフォーマット:" + +-#: aplay/aplay.c:205 ++#: aplay/aplay.c:186 + #, c-format + msgid "" + "\n" +@@ -114,154 +105,143 @@ + "\n" + "これらのいくつかは指定のハードウェアで使用不可能な場合があります\n" + +-#: aplay/aplay.c:206 ++#: aplay/aplay.c:187 + #, c-format + msgid "The availabled format shortcuts are:\n" + msgstr "可能なフォーマットの省略形:\n" + +-#: aplay/aplay.c:207 ++#: aplay/aplay.c:188 + #, c-format + msgid "-f cd (16 bit little endian, 44100, stereo)\n" + msgstr "-f cd (16 ビット、リトルエンディアン、44100、ステレオ)\n" + +-#: aplay/aplay.c:208 ++#: aplay/aplay.c:189 + #, c-format + msgid "-f cdr (16 bit big endian, 44100, stereo)\n" + msgstr "-f cdr (16 ビット、ビッグエンディアン、44100、ステレオ)\n" + +-#: aplay/aplay.c:209 ++#: aplay/aplay.c:190 + #, c-format + msgid "-f dat (16 bit little endian, 48000, stereo)\n" + msgstr "-f dat (16 ビット、リトルエンディアン、48000、ステレオ)\n" + +-#: aplay/aplay.c:223 ++#: aplay/aplay.c:204 + msgid "no soundcards found..." + msgstr "サウンドカードが見つかりません..." + +-#: aplay/aplay.c:226 ++#: aplay/aplay.c:207 + #, c-format + msgid "**** List of %s Hardware Devices ****\n" + msgstr "**** ハードウェアデバイス %s のリスト ****\n" + +-#: aplay/aplay.c:255 ++#: aplay/aplay.c:236 + #, c-format + msgid "card %i: %s [%s], device %i: %s [%s]\n" + msgstr "カード %i: %s [%s], デバイス %i: %s [%s]\n" + +-#: aplay/aplay.c:261 ++#: aplay/aplay.c:242 + #, c-format + msgid " Subdevices: %i/%i\n" + msgstr " サブデバイス: %i/%i\n" + +-#: aplay/aplay.c:268 ++#: aplay/aplay.c:249 + #, c-format + msgid " Subdevice #%i: %s\n" + msgstr " サブデバイス #%i: %s\n" + +-#: aplay/aplay.c:332 ++#: aplay/aplay.c:306 + #, c-format + msgid "Aborted by signal %s...\n" + msgstr "シグナル %s で中断...\n" + +-#: aplay/aplay.c:430 ++#: aplay/aplay.c:390 + msgid "command should be named either arecord or aplay" + msgstr "arecord または aplay コマンドのみ可能" + +-#: aplay/aplay.c:469 ++#: aplay/aplay.c:429 + #, c-format + msgid "unrecognized file format %s" + msgstr "不正なファイルフォーマット %s" + +-#: aplay/aplay.c:476 ++#: aplay/aplay.c:436 + #, c-format + msgid "value %i for channels is invalid" + msgstr "不正なチャネル数 %i" + +-#: aplay/aplay.c:495 ++#: aplay/aplay.c:455 + #, c-format + msgid "wrong extended format '%s'" + msgstr "不正な拡張フォーマット '%s'" + +-#: aplay/aplay.c:506 ++#: aplay/aplay.c:466 + #, c-format + msgid "bad speed value %i" + msgstr "不正なレート値 %i" + +-#: aplay/aplay.c:592 ++#: aplay/aplay.c:522 + #, c-format + msgid "Try `%s --help' for more information.\n" + msgstr "より詳しい情報は「%s --help」を実行してください\n" + +-#: aplay/aplay.c:608 ++#: aplay/aplay.c:538 + #, c-format + msgid "audio open error: %s" + msgstr "" + +-#: aplay/aplay.c:613 ++#: aplay/aplay.c:543 + #, c-format + msgid "info error: %s" + msgstr "" + +-#: aplay/aplay.c:620 ++#: aplay/aplay.c:550 + #, c-format + msgid "nonblock setting error: %s" + msgstr "" + +-#: aplay/aplay.c:630 aplay/aplay.c:737 aplay/aplay.c:1092 ++#: aplay/aplay.c:560 aplay/aplay.c:667 aplay/aplay.c:1018 + msgid "not enough memory" + msgstr "メモリが足りません" + +-#: aplay/aplay.c:727 ++#: aplay/aplay.c:657 + #, c-format + msgid "read error (called from line %i)" + msgstr "リードエラー (%i 行)" + +-#: aplay/aplay.c:785 ++#: aplay/aplay.c:715 + #, c-format + msgid "unknown length of 'fmt ' chunk (read %u, should be %u at least)" + msgstr "" + +-#: aplay/aplay.c:795 +-#, c-format +-msgid "" +-"unknown length of extensible 'fmt ' chunk (read %u, should be %u at least)" +-msgstr "" ++#: aplay/aplay.c:723 ++msgid "can't play not PCM-coded WAVE-files" ++msgstr "PCM 以外の WAVE ファイルは再生できません" + +-#: aplay/aplay.c:800 +-msgid "wrong format tag in extensible 'fmt ' chunk" +-msgstr "" +- +-#: aplay/aplay.c:807 +-#, c-format +-msgid "can't play WAVE-file format 0x%04x which is not PCM or FLOAT encoded" +-msgstr "" +- +-#: aplay/aplay.c:811 ++#: aplay/aplay.c:727 + #, c-format + msgid "can't play WAVE-files with %d tracks" + msgstr "%d トラックを含む WAVE ファイルは再生できません" + +-#: aplay/aplay.c:819 aplay/aplay.c:919 ++#: aplay/aplay.c:735 aplay/aplay.c:832 + #, c-format + msgid "Warning: format is changed to U8\n" + msgstr "警告: フォーマットは U8 に変更されます\n" + +-#: aplay/aplay.c:825 ++#: aplay/aplay.c:741 + #, c-format + msgid "Warning: format is changed to S16_LE\n" + msgstr "警告: フォーマットは S16_LE に変更されます\n" + +-#: aplay/aplay.c:833 ++#: aplay/aplay.c:749 + #, c-format + msgid "Warning: format is changed to S24_3LE\n" + msgstr "警告: フォーマットは S24_3LE に変更されます\n" + +-#: aplay/aplay.c:839 ++#: aplay/aplay.c:755 + #, c-format + msgid "Warning: format is changed to S24_LE\n" + msgstr "警告: フォーマットは S24_LE に変更されます\n" + +-#: aplay/aplay.c:843 ++#: aplay/aplay.c:759 + #, c-format + msgid "" + " can't play WAVE-files with sample %d bits in %d bytes wide (%d channels)" +@@ -269,261 +249,258 @@ + "%2$d バイト長 %1$d サンプルビット (%3$d チャネル) の WAVE ファイルは再生でき" + "ません" + +-#: aplay/aplay.c:855 ++#: aplay/aplay.c:768 + #, c-format + msgid " can't play WAVE-files with sample %d bits wide" + msgstr "%d ビット長のサンプルの WAVE ファイルは再生できません" + +-#: aplay/aplay.c:913 ++#: aplay/aplay.c:826 + #, c-format + msgid "Warning: format is changed to MU_LAW\n" + msgstr "警告: フォーマットは MU_LAW に変更されます\n" + +-#: aplay/aplay.c:925 ++#: aplay/aplay.c:838 + #, c-format + msgid "Warning: format is changed to S16_BE\n" + msgstr "警告: フォーマットは S16_BE に変更されます\n" + +-#: aplay/aplay.c:938 aplay/aplay.c:1768 aplay/aplay.c:1775 aplay/aplay.c:2297 +-#: aplay/aplay.c:2309 ++#: aplay/aplay.c:851 aplay/aplay.c:1488 aplay/aplay.c:1495 aplay/aplay.c:2011 ++#: aplay/aplay.c:2023 + msgid "read error" + msgstr "リードエラー" + +-#: aplay/aplay.c:957 ++#: aplay/aplay.c:871 + msgid "Broken configuration for this PCM: no configurations available" + msgstr "指定の PCM を使用できません: 設定がありません" + +-#: aplay/aplay.c:974 ++#: aplay/aplay.c:888 + msgid "Access type not available" + msgstr "アクセスタイプが使用不可能" + +-#: aplay/aplay.c:979 ++#: aplay/aplay.c:893 + msgid "Sample format non available" + msgstr "サンプルフォーマットが使用不可能" + +-#: aplay/aplay.c:984 ++#: aplay/aplay.c:898 + msgid "Channels count non available" + msgstr "チャネル数が使用不可能" + +-#: aplay/aplay.c:999 ++#: aplay/aplay.c:913 + #, c-format + msgid "Warning: rate is not accurate (requested = %iHz, got = %iHz)\n" + msgstr "警告: レートが不正確です (要求値 = %iHz, 使用値 = %iHz)\n" + +-#: aplay/aplay.c:1005 ++#: aplay/aplay.c:919 + #, c-format + msgid " please, try the plug plugin %s\n" + msgstr " plug プラグイン%s を使用してください\n" + +-#: aplay/aplay.c:1041 ++#: aplay/aplay.c:954 + msgid "Unable to install hw params:" + msgstr "hw params のインストールに失敗しました:" + +-#: aplay/aplay.c:1048 ++#: aplay/aplay.c:961 + #, c-format + msgid "Can't use period equal to buffer size (%lu == %lu)" + msgstr "period と buffer サイズには同じ値を使用できません (%lu == %lu)" + +-#: aplay/aplay.c:1079 ++#: aplay/aplay.c:968 ++msgid "Unable to obtain xfer align\n" ++msgstr "xfer align 値を得ることができません\n" ++ ++#: aplay/aplay.c:1005 + msgid "unable to install sw params:" + msgstr "sw params のインストールに失敗しました:" + +-#: aplay/aplay.c:1154 ++#: aplay/aplay.c:1044 + #, c-format + msgid "status error: %s" + msgstr "ステータスエラー: %s" + +-#: aplay/aplay.c:1164 aplay/aplay.c:1175 ++#: aplay/aplay.c:1052 + #, c-format + msgid "%s!!! (at least %.3f ms long)\n" + msgstr "%s!!! (少なくとも %.3f ms)\n" + +-#: aplay/aplay.c:1165 aplay/aplay.c:1168 aplay/aplay.c:1176 ++#: aplay/aplay.c:1053 + msgid "underrun" + msgstr "アンダーラン" + +-#: aplay/aplay.c:1165 aplay/aplay.c:1176 ++#: aplay/aplay.c:1053 + msgid "overrun" + msgstr "オーバーラン" + +-#: aplay/aplay.c:1180 ++#: aplay/aplay.c:1056 + #, c-format + msgid "Status:\n" + msgstr "ステータス:\n" + +-#: aplay/aplay.c:1184 ++#: aplay/aplay.c:1060 + #, c-format + msgid "xrun: prepare error: %s" + msgstr "" + +-#: aplay/aplay.c:1190 ++#: aplay/aplay.c:1066 + #, c-format + msgid "Status(DRAINING):\n" + msgstr "ステータス(DRAINING):\n" + +-#: aplay/aplay.c:1194 ++#: aplay/aplay.c:1070 + #, c-format + msgid "capture stream format change? attempting recover...\n" + msgstr "録音ストリームのフォーマットが変更? 修復を試みます...\n" + +-#: aplay/aplay.c:1196 ++#: aplay/aplay.c:1072 + #, c-format + msgid "xrun(DRAINING): prepare error: %s" + msgstr "" + +-#: aplay/aplay.c:1203 ++#: aplay/aplay.c:1079 + #, c-format + msgid "Status(R/W):\n" + msgstr "ステータス(R/W):\n" + +-#: aplay/aplay.c:1206 ++#: aplay/aplay.c:1082 + #, c-format + msgid "read/write error, state = %s" + msgstr "読み書きエラー, ステータス = %s" + +-#: aplay/aplay.c:1216 ++#: aplay/aplay.c:1092 + #, c-format + msgid "Suspended. Trying resume. " + msgstr "サスペンド中です。レジュームします。" + +-#: aplay/aplay.c:1221 ++#: aplay/aplay.c:1097 + #, c-format + msgid "Failed. Restarting stream. " + msgstr "失敗しました。ストリームを再スタートします。" + +-#: aplay/aplay.c:1223 ++#: aplay/aplay.c:1099 + #, c-format + msgid "suspend: prepare error: %s" + msgstr "サスペンド: prepare エラー: %s" + +-#: aplay/aplay.c:1228 ++#: aplay/aplay.c:1104 + #, c-format + msgid "Done.\n" + msgstr "終了\n" + +-#: aplay/aplay.c:1250 ++#: aplay/aplay.c:1183 + #, c-format +-msgid " !clip " ++msgid "Unsupported bit size %d.\n" + msgstr "" + +-#: aplay/aplay.c:1397 ++#: aplay/aplay.c:1219 + #, c-format +-msgid "Unsupported bit size %d.\n" ++msgid " !clip " + msgstr "" + +-#: aplay/aplay.c:1431 ++#: aplay/aplay.c:1224 + #, c-format + msgid "Max peak (%li samples): 0x%08x " + msgstr "最大ピーク (%li サンプル): 0x%08x " + +-#: aplay/aplay.c:1465 +-#, c-format +-msgid "" +-"Suspicious buffer position (%li total): avail = %li, delay = %li, buffer = %" +-"li\n" +-msgstr "" +- +-#: aplay/aplay.c:1528 ++#: aplay/aplay.c:1258 + #, c-format + msgid "write error: %s" + msgstr "書込エラー: %s" + +-#: aplay/aplay.c:1574 ++#: aplay/aplay.c:1300 + #, c-format + msgid "writev error: %s" + msgstr "書込(writev)エラー: %s" + +-#: aplay/aplay.c:1617 ++#: aplay/aplay.c:1339 + #, c-format + msgid "read error: %s" + msgstr "読込エラー: %s" + +-#: aplay/aplay.c:1660 ++#: aplay/aplay.c:1378 + #, c-format + msgid "readv error: %s" + msgstr "読込(readv)エラー: %s" + +-#: aplay/aplay.c:1708 ++#: aplay/aplay.c:1426 + msgid "can't allocate buffer for silence" + msgstr "サイレンス用のバッファの取得に失敗しました" + +-#: aplay/aplay.c:1717 aplay/aplay.c:1943 aplay/aplay.c:1948 aplay/aplay.c:1995 +-#: aplay/aplay.c:2004 aplay/aplay.c:2011 aplay/aplay.c:2021 aplay/aplay.c:2027 +-#: aplay/aplay.c:2099 aplay/aplay.c:2129 aplay/aplay.c:2143 ++#: aplay/aplay.c:1435 aplay/aplay.c:1663 aplay/aplay.c:1668 aplay/aplay.c:1715 ++#: aplay/aplay.c:1724 aplay/aplay.c:1731 aplay/aplay.c:1741 aplay/aplay.c:1747 ++#: aplay/aplay.c:1815 aplay/aplay.c:1845 aplay/aplay.c:1859 + msgid "write error" + msgstr "書込エラー" + +-#: aplay/aplay.c:1730 ++#: aplay/aplay.c:1449 + #, c-format + msgid "voc_pcm_flush - silence error" + msgstr "" + +-#: aplay/aplay.c:1733 ++#: aplay/aplay.c:1455 + msgid "voc_pcm_flush error" + msgstr "" + +-#: aplay/aplay.c:1759 ++#: aplay/aplay.c:1479 + msgid "malloc error" + msgstr "malloc エラー" + +-#: aplay/aplay.c:1763 ++#: aplay/aplay.c:1483 + #, c-format + msgid "Playing Creative Labs Channel file '%s'...\n" + msgstr "Creative Labs Channel ファイル '%s' を演奏中...\n" + +-#: aplay/aplay.c:1831 aplay/aplay.c:1923 ++#: aplay/aplay.c:1551 aplay/aplay.c:1643 + msgid "can't play packed .voc files" + msgstr "packed .voc ファイルは演奏できません" + +-#: aplay/aplay.c:1883 ++#: aplay/aplay.c:1603 + #, c-format + msgid "can't play loops; %s isn't seekable\n" + msgstr "ループ演奏できません。%s はシーク不可能です\n" + +-#: aplay/aplay.c:1932 ++#: aplay/aplay.c:1652 + #, c-format + msgid "unknown blocktype %d. terminate." + msgstr "未知のブロックタイプ %d: 終了します。" + +-#: aplay/aplay.c:2063 ++#: aplay/aplay.c:1782 + #, c-format + msgid "Wave doesn't support %s format..." + msgstr "WAVE は %s フォーマットをサポートしません..." + +-#: aplay/aplay.c:2123 ++#: aplay/aplay.c:1839 + #, c-format + msgid "Sparc Audio doesn't support %s format..." + msgstr "Sparc オーディオは %s フォーマットをサポートしません..." + +-#: aplay/aplay.c:2204 ++#: aplay/aplay.c:1920 + msgid "Playing" + msgstr "再生中" + +-#: aplay/aplay.c:2204 ++#: aplay/aplay.c:1920 + msgid "Recording" + msgstr "録音中" + +-#: aplay/aplay.c:2208 ++#: aplay/aplay.c:1924 + #, c-format + msgid "Rate %d Hz, " + msgstr "レート %d Hz, " + +-#: aplay/aplay.c:2210 ++#: aplay/aplay.c:1926 + #, c-format + msgid "Mono" + msgstr "モノラル" + +-#: aplay/aplay.c:2212 ++#: aplay/aplay.c:1928 + #, c-format + msgid "Stereo" + msgstr "ステレオ" + +-#: aplay/aplay.c:2214 ++#: aplay/aplay.c:1930 + #, c-format + msgid "Channels %i" + msgstr "チャネル数 %i" + +-#: aplay/aplay.c:2573 aplay/aplay.c:2626 ++#: aplay/aplay.c:2285 aplay/aplay.c:2338 + #, c-format + msgid "You need to specify %d files" + msgstr "%d 個のファイルを指定してください" +@@ -654,7 +631,7 @@ + msgid "invalid sender address %s\n" + msgstr "送信アドレスが不正です: %s\n" + +-#: seq/aconnect/aconnect.c:373 seq/aseqnet/aseqnet.c:290 ++#: seq/aconnect/aconnect.c:373 seq/aseqnet/aseqnet.c:289 + #, c-format + msgid "invalid destination address %s\n" + msgstr "受信アドレスが不正です: %s\n" +@@ -679,386 +656,391 @@ + msgid "Connection failed (%s)\n" + msgstr "接続に失敗 (%s)\n" + +-#: seq/aseqnet/aseqnet.c:164 ++#: seq/aseqnet/aseqnet.c:163 + #, c-format + msgid "aseqnet - network client/server on ALSA sequencer\n" + msgstr "aseqnet - ALSA sequencer 上のネットワーククライアント/サーバ\n" + +-#: seq/aseqnet/aseqnet.c:165 ++#: seq/aseqnet/aseqnet.c:164 + #, c-format + msgid " Copyright (C) 1999 Takashi Iwai\n" + msgstr "" + +-#: seq/aseqnet/aseqnet.c:166 ++#: seq/aseqnet/aseqnet.c:165 + #, c-format + msgid "usage:\n" + msgstr "使用法:\n" + +-#: seq/aseqnet/aseqnet.c:167 ++#: seq/aseqnet/aseqnet.c:166 + #, c-format + msgid " server mode: aseqnet [-options]\n" + msgstr " サーバモード: aseqnet [-オプション]\n" + +-#: seq/aseqnet/aseqnet.c:168 ++#: seq/aseqnet/aseqnet.c:167 + #, c-format + msgid " client mode: aseqnet [-options] server_host\n" + msgstr " クライアントモード: aseqnet [-オプション] サーバホスト\n" + +-#: seq/aseqnet/aseqnet.c:169 ++#: seq/aseqnet/aseqnet.c:168 + #, c-format + msgid "options:\n" + msgstr "オプション:\n" + +-#: seq/aseqnet/aseqnet.c:170 ++#: seq/aseqnet/aseqnet.c:169 + #, c-format + msgid " -p,--port # : sepcify TCP port (digit or service name)\n" + msgstr " -p,--port # : TCP ポートの指定 (数字またはサービス名)\n" + +-#: seq/aseqnet/aseqnet.c:171 ++#: seq/aseqnet/aseqnet.c:170 + #, c-format + msgid " -s,--source addr : read from given addr (client:port)\n" + msgstr " -s,--source addr : 指定のアドレス(クライアント:ポート)から読み込む\n" + +-#: seq/aseqnet/aseqnet.c:172 ++#: seq/aseqnet/aseqnet.c:171 + #, c-format + msgid " -d,--dest addr : write to given addr (client:port)\n" + msgstr " -d,--dest addr : 指定のアドレス(クライアント:ポート)に書き込む\n" + +-#: seq/aseqnet/aseqnet.c:173 ++#: seq/aseqnet/aseqnet.c:172 + #, c-format + msgid " -v, --verbose : print verbose messages\n" + msgstr " -v,--verbose : 冗長メッセージ表示\n" + +-#: seq/aseqnet/aseqnet.c:174 ++#: seq/aseqnet/aseqnet.c:173 + #, c-format + msgid " -i, --info : print certain received events\n" + msgstr " -i,--info : 受信イベントを表示する\n" + +-#: seq/aseqnet/aseqnet.c:188 ++#: seq/aseqnet/aseqnet.c:187 + #, c-format + msgid "can't malloc\n" + msgstr "malloc できません\n" + +-#: seq/aseqnet/aseqnet.c:213 ++#: seq/aseqnet/aseqnet.c:212 + #, c-format + msgid "closing files..\n" + msgstr "ファイルを閉じます..\n" + +-#: seq/aseqnet/aseqnet.c:272 ++#: seq/aseqnet/aseqnet.c:271 + #, c-format + msgid "sequencer opened: %d:%d\n" + msgstr "" + +-#: seq/aseqnet/aseqnet.c:279 ++#: seq/aseqnet/aseqnet.c:278 + #, c-format + msgid "invalid source address %s\n" + msgstr "不正な送信アドレス %s\n" + +-#: seq/aseqnet/aseqnet.c:309 ++#: seq/aseqnet/aseqnet.c:308 + #, c-format + msgid "service '%s' is not found in /etc/services\n" + msgstr "サービス '%s' が /etc/services に見つかりません\n" + +-#: seq/aseqnet/aseqnet.c:377 ++#: seq/aseqnet/aseqnet.c:376 + #, c-format + msgid "too many connections!\n" + msgstr "接続が多すぎます!\n" + +-#: seq/aseqnet/aseqnet.c:388 ++#: seq/aseqnet/aseqnet.c:387 + #, c-format + msgid "accepted[%d]\n" + msgstr "了解[%d]\n" + +-#: seq/aseqnet/aseqnet.c:411 ++#: seq/aseqnet/aseqnet.c:410 + #, c-format + msgid "can't get address %s\n" + msgstr "アドレス %s を取得できません\n" + +-#: seq/aseqnet/aseqnet.c:422 ++#: seq/aseqnet/aseqnet.c:421 + #, c-format + msgid "ok.. connected\n" + msgstr "ok.. 接続\n" + +-#: seq/aseqnet/aseqnet.c:518 ++#: seq/aseqnet/aseqnet.c:517 + #, c-format + msgid "Channel %2d: Control event : %5d\n" + msgstr "チャネル %2d: コントロール : %5d\n" + +-#: seq/aseqnet/aseqnet.c:522 ++#: seq/aseqnet/aseqnet.c:521 + #, c-format + msgid "Channel %2d: Pitchbender : %5d\n" + msgstr "チャネル %2d: ピッチベンド : %5d\n" + +-#: seq/aseqnet/aseqnet.c:526 ++#: seq/aseqnet/aseqnet.c:525 + #, c-format + msgid "Channel %2d: Note On event : %5d\n" + msgstr "チャネル %2d: ノートオン : %5d\n" + +-#: seq/aseqnet/aseqnet.c:530 ++#: seq/aseqnet/aseqnet.c:529 + #, c-format + msgid "Channel %2d: Note Off event: %5d\n" + msgstr "チャネル %2d: ノートオフ : %5d\n" + +-#: seq/aseqnet/aseqnet.c:585 ++#: seq/aseqnet/aseqnet.c:584 + #, c-format + msgid "disconnected\n" + msgstr "切り離し\n" + +-#: speaker-test/speaker-test.c:88 ++#: speaker-test/speaker-test.c:87 + msgid "Front Left" + msgstr "" + +-#: speaker-test/speaker-test.c:89 ++#: speaker-test/speaker-test.c:88 + msgid "Front Right" + msgstr "" + +-#: speaker-test/speaker-test.c:90 ++#: speaker-test/speaker-test.c:89 + msgid "Rear Left" + msgstr "" + +-#: speaker-test/speaker-test.c:91 ++#: speaker-test/speaker-test.c:90 + msgid "Rear Right" + msgstr "" + +-#: speaker-test/speaker-test.c:92 ++#: speaker-test/speaker-test.c:91 + msgid "Center" + msgstr "" + +-#: speaker-test/speaker-test.c:93 ++#: speaker-test/speaker-test.c:92 + msgid "LFE" + msgstr "" + +-#: speaker-test/speaker-test.c:94 ++#: speaker-test/speaker-test.c:93 + msgid "Side Left" + msgstr "" + +-#: speaker-test/speaker-test.c:95 ++#: speaker-test/speaker-test.c:94 + msgid "Side Right" + msgstr "" + +-#: speaker-test/speaker-test.c:96 ++#: speaker-test/speaker-test.c:95 + msgid "Channel 9" + msgstr "" + +-#: speaker-test/speaker-test.c:97 ++#: speaker-test/speaker-test.c:96 + msgid "Channel 10" + msgstr "" + +-#: speaker-test/speaker-test.c:98 ++#: speaker-test/speaker-test.c:97 + msgid "Channel 11" + msgstr "" + +-#: speaker-test/speaker-test.c:99 ++#: speaker-test/speaker-test.c:98 + msgid "Channel 12" + msgstr "" + +-#: speaker-test/speaker-test.c:100 ++#: speaker-test/speaker-test.c:99 + msgid "Channel 13" + msgstr "" + +-#: speaker-test/speaker-test.c:101 ++#: speaker-test/speaker-test.c:100 + msgid "Channel 14" + msgstr "" + +-#: speaker-test/speaker-test.c:102 ++#: speaker-test/speaker-test.c:101 + msgid "Channel 15" + msgstr "" + +-#: speaker-test/speaker-test.c:103 ++#: speaker-test/speaker-test.c:102 + msgid "Channel 16" + msgstr "" + +-#: speaker-test/speaker-test.c:340 ++#: speaker-test/speaker-test.c:279 + #, 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:286 + #, 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:293 + #, 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:300 + #, 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:308 + #, 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:313 + #, 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:317 + #, 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:323 + #, 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:324 + #, 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:326 + #, c-format + msgid "Requested period time %u us\n" + msgstr "要求されたピリオド長 %u us\n" + +-#: speaker-test/speaker-test.c:390 ++#: speaker-test/speaker-test.c:329 + #, 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:335 + #, c-format + msgid "Requested buffer time %u us\n" + msgstr "要求されたバッファ長 %u us\n" + +-#: speaker-test/speaker-test.c:399 ++#: speaker-test/speaker-test.c:338 + #, 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:347 + #, c-format + msgid "Using max buffer size %lu\n" + msgstr "最大バッファサイズ %lu を使用\n" + +-#: speaker-test/speaker-test.c:411 ++#: speaker-test/speaker-test.c:350 + #, 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:356 + #, c-format + msgid "Periods = %u\n" + msgstr "ピリオド数 = %u\n" + +-#: speaker-test/speaker-test.c:420 ++#: speaker-test/speaker-test.c:359 + #, c-format + msgid "Unable to set nperiods %u for playback: %s\n" + msgstr "ピリオド数 %u を設定できません: %s\n" + +-#: speaker-test/speaker-test.c:429 +-#, 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:366 + #, 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:367 + #, 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:369 + #, c-format + msgid "buffer to small, could not use\n" + msgstr "バッファが小さすぎます\n" + +-#: speaker-test/speaker-test.c:451 ++#: speaker-test/speaker-test.c:376 ++#, c-format ++msgid "Unable to set hw params for playback: %s\n" ++msgstr "hw params を設定できません: %s\n" ++ ++#: speaker-test/speaker-test.c:389 + #, 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:396 + #, 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:403 + #, 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:410 ++#, c-format ++msgid "Unable to set transfer align for playback: %s\n" ++msgstr "転送 align を設定できません: %s\n" ++ ++#: speaker-test/speaker-test.c:417 + #, 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:432 + #, 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:443 + #, 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:517 speaker-test/speaker-test.c:911 + #, c-format + msgid "No enough memory\n" + msgstr "メモリが足りません\n" + +-#: speaker-test/speaker-test.c:577 ++#: speaker-test/speaker-test.c:522 + #, 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:526 speaker-test/speaker-test.c:555 + #, c-format + msgid "Invalid WAV file %s\n" + msgstr "不正なWAVファイルです: %s\n" + +-#: speaker-test/speaker-test.c:586 ++#: speaker-test/speaker-test.c:531 + #, c-format + msgid "Not a WAV file: %s\n" + msgstr "WAVファイルではありません: %s\n" + +-#: speaker-test/speaker-test.c:590 ++#: speaker-test/speaker-test.c:535 + #, 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:540 + #, 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:545 + #, 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:550 + #, 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:600 + #, c-format + msgid "Undefined channel %d\n" + msgstr "未定義のチャネル %d\n" + +-#: speaker-test/speaker-test.c:706 ++#: speaker-test/speaker-test.c:651 + #, c-format + msgid "Write error: %d,%s\n" + msgstr "書込エラー: %d,%s\n" + +-#: speaker-test/speaker-test.c:708 ++#: speaker-test/speaker-test.c:653 + #, 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:708 + #, c-format + msgid "" + "Usage: speaker-test [OPTION]... \n" +@@ -1096,85 +1078,76 @@ + "-W,--wavdir WAVファイルのあるディレクトリを指定\n" + "\n" + +-#: speaker-test/speaker-test.c:878 ++#: speaker-test/speaker-test.c:820 + #, 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:834 speaker-test/speaker-test.c:838 + #, c-format + msgid "Invalid test type %s\n" + msgstr "不正なテストタイプ %s\n" + +-#: speaker-test/speaker-test.c:908 ++#: speaker-test/speaker-test.c:850 + #, c-format + msgid "Invalid parameter for -s option.\n" + msgstr "-s オプションの値が不正です\n" + +-#: speaker-test/speaker-test.c:919 ++#: speaker-test/speaker-test.c:861 + #, c-format + msgid "Unknown option '%c'\n" + msgstr "未知のオプション '%c'\n" + +-#: speaker-test/speaker-test.c:933 ++#: speaker-test/speaker-test.c:875 + #, c-format + msgid "Playback device is %s\n" + msgstr "再生デバイス: %s\n" + +-#: speaker-test/speaker-test.c:934 ++#: speaker-test/speaker-test.c:876 + #, 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:879 + #, c-format + msgid "Using 16 octaves of pink noise\n" + msgstr "16 オクターブのピンクノイズを使用\n" + +-#: speaker-test/speaker-test.c:940 ++#: speaker-test/speaker-test.c:882 + #, c-format + msgid "Sine wave rate is %.4fHz\n" + msgstr "正弦波レート: %.4fHz\n" + +-#: speaker-test/speaker-test.c:943 ++#: speaker-test/speaker-test.c:885 + #, c-format + msgid "WAV file(s)\n" + msgstr "WAV ファイル\n" + +-#: speaker-test/speaker-test.c:949 ++#: speaker-test/speaker-test.c:891 + #, c-format + msgid "Playback open error: %d,%s\n" + msgstr "再生オープンエラー: %d,%s\n" + +-#: speaker-test/speaker-test.c:954 ++#: speaker-test/speaker-test.c:896 + #, c-format + msgid "Setting of hwparams failed: %s\n" + msgstr "hwparams の設定に失敗: %s\n" + +-#: speaker-test/speaker-test.c:959 ++#: speaker-test/speaker-test.c:901 + #, 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:942 speaker-test/speaker-test.c:964 + #, c-format + msgid "Transfer failed: %s\n" + msgstr "転送に失敗しました: %s\n" + +-#: speaker-test/speaker-test.c:1010 ++#: speaker-test/speaker-test.c:952 + #, 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" + diff --git a/alsa-utils.changes b/alsa-utils.changes index 99c3940..6b46116 100644 --- a/alsa-utils.changes +++ b/alsa-utils.changes @@ -1,9 +1,3 @@ -------------------------------------------------------------------- -Mon Aug 31 17:27:36 CEST 2009 - tiwai@suse.de - -- updated to version 1.0.21: - just a version bump including previous fixes - ------------------------------------------------------------------- Wed Aug 12 12:52:16 CEST 2009 - tiwai@suse.de diff --git a/alsa-utils.spec b/alsa-utils.spec index 9a0b3a2..b168df2 100644 --- a/alsa-utils.spec +++ b/alsa-utils.spec @@ -1,5 +1,5 @@ # -# spec file for package alsa-utils (Version 1.0.21) +# spec file for package alsa-utils (Version 1.0.20) # # Copyright (c) 2009 SUSE LINUX Products GmbH, Nuernberg, Germany. # @@ -20,19 +20,19 @@ Name: alsa-utils BuildRequires: alsa-devel ncurses-devel xmlto -%define package_version 1.0.21 +%define package_version 1.0.20 License: GPL v2 or later Group: Productivity/Multimedia/Sound/Players Provides: alsa-conf Requires: dialog pciutils AutoReqProv: on Summary: Advanced Linux Sound Architecture Utilities -Version: 1.0.21 -Release: 1 +Version: 1.0.20 +Release: 4 Source: ftp://ftp.alsa-project.org/pub/util/alsa-utils-%{package_version}.tar.bz2 -# Patch: alsa-utils-git-fixes.diff +Patch: alsa-utils-git-fixes.diff Patch1: alsa-utils-gettext-version-removal.diff -# Patch2: alsa-utils-po-pre-patch.diff +Patch2: alsa-utils-po-pre-patch.diff Patch3: alsa-utils-alsamixer-old-ncurses-fix.diff Url: http://www.alsa-project.org/ BuildRoot: %{_tmppath}/%{name}-%{version}-build @@ -53,9 +53,9 @@ Authors: # fix stupid automake's automatic action sed -i -e's/EXTRA_DIST= config.rpath /EXTRA_DIST=/' Makefile.am # fix po changes in tarball first -# %patch2 -p1 -# rm -f po/Makefile* po/*.gmo po/*.pot po/*.header po/stamp-* -# %patch -p1 +%patch2 -p1 +rm -f po/Makefile* po/*.gmo po/*.pot po/*.header po/stamp-* +%patch -p1 %if %suse_version < 1020 %patch1 -p1 %endif