forked from pool/alsa-utils
10272 lines
283 KiB
Diff
10272 lines
283 KiB
Diff
diff --git a/alsactl/init/default b/alsactl/init/default
|
|
index c9aa7cc..8653ec6 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"
|
|
@@ -68,7 +68,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 +78,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 +94,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 +104,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 <timj@gtk.org> and
|
|
-been furtherly improved by Jaroslav Kysela <perex@perex.cz>.
|
|
-This document was provided by Paul Winkler <zarmzarm@erols.com>.
|
|
diff --git a/alsamixer/alsamixer.1 b/alsamixer/alsamixer.1
|
|
index 47d8aed..ba05aca 100644
|
|
--- a/alsamixer/alsamixer.1
|
|
+++ b/alsamixer/alsamixer.1
|
|
@@ -1,4 +1,4 @@
|
|
-.TH ALSAMIXER 1 "15 May 2001"
|
|
+.TH ALSAMIXER 1 "22 May 2009"
|
|
.SH NAME
|
|
alsamixer \- soundcard mixer for ALSA soundcard driver, with ncurses interface
|
|
.SH SYNOPSIS
|
|
@@ -12,29 +12,25 @@ soundcard drivers. It supports multiple soundcards with multiple devices.
|
|
.SH OPTIONS
|
|
|
|
.TP
|
|
-\fI\-h, \-help\fP
|
|
+\fI\-h, \-\-help\fP
|
|
Help: show available flags.
|
|
|
|
.TP
|
|
-\fI\-c\fP <card number or identification>
|
|
+\fI\-c, \-\-card\fP <card number or identification>
|
|
Select the soundcard to use, if you have more than one. Cards are
|
|
numbered from 0 (the default).
|
|
|
|
.TP
|
|
-\fI\-D\fP <device identification>
|
|
+\fI\-D, \-\-device\fP <device identification>
|
|
Select the mixer device to control.
|
|
|
|
.TP
|
|
-\fI\-g\fP
|
|
-Toggle the using of colors.
|
|
-
|
|
-.TP
|
|
-\fI\-s\fP
|
|
-Minimize the mixer window.
|
|
+\fI\-V, \-\-view\fP <mode>
|
|
+Select the starting view mode, either \fIplayback\fP, \fIcapture\fP or \fIall\fP.
|
|
|
|
.TP
|
|
-\fI\-V\fP <view mode>
|
|
-Select the starting view mode, either \fIplayback\fP, \fIcapture\fP or \fIall\fP.
|
|
+\fI\-g, \-\-no\-color\fP
|
|
+Toggle the using of colors.
|
|
|
|
.SH MIXER VIEWS
|
|
|
|
@@ -60,7 +56,7 @@ You can toggle the switch via \fIm\fP key.
|
|
|
|
When a mixer control has capture capability, the capture flag appears
|
|
below the volume bar, too. When the capture is turned off,
|
|
-\-\-\-\-\-\- is shown. \fICAPTUR\fP in red appears when the
|
|
+\-\-\-\-\-\-\- is shown. \fICAPTURE\fP in red appears when the
|
|
capture switch is turned on. In addition, \fIL\fP and \fIR\fP letters
|
|
appear in left and right side to indicate that left and the right
|
|
channels are turned on.
|
|
@@ -148,6 +144,13 @@ The number keys from \fI0\fP to \fI9\fP are to change the absolute volume
|
|
quickly. They correspond to 0 to 90% volume.
|
|
|
|
.SS
|
|
+Selecting the Sound Card
|
|
+
|
|
+You can select another sound card by pressing the \fIF6\fP or \fIS\fP keys.
|
|
+This will show a list of available sound cards to choose from,
|
|
+and an entry to enter the mixer device name by hand.
|
|
+
|
|
+.SS
|
|
Exiting
|
|
|
|
Quit the program with \fIALT Q\fP, or by hitting \fIESC\fP.
|
|
@@ -169,6 +172,7 @@ fault. Plain old \fBxterm\fP seems to be fine.
|
|
.SH AUTHOR
|
|
.B alsamixer
|
|
has been written by Tim Janik <timj@gtk.org> and
|
|
-been further improved by Jaroslav Kysela <perex@perex.cz>.
|
|
+been further improved by Jaroslav Kysela <perex@perex.cz>
|
|
+and Clemens Ladisch <clemens@ladisch.de>.
|
|
|
|
This manual page was provided by Paul Winkler <zarmzarm@erols.com>.
|
|
diff --git a/alsamixer/alsamixer.c b/alsamixer/alsamixer.c
|
|
deleted file mode 100644
|
|
index 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 <timj@gtk.org> and Jaroslav Kysela <perex@perex.cz>
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * as published by the Free Software Foundation; either version 2
|
|
- * of the License, or (at your option) any later version.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- *
|
|
- * You should have received a copy of the GNU Library General Public
|
|
- * License along with this library; if not, write to the Free Software
|
|
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
|
- *
|
|
- *
|
|
- * ChangeLog:
|
|
- *
|
|
- * Wed Feb 14 13:08:17 CET 2001 Jaroslav Kysela <perex@perex.cz>
|
|
- *
|
|
- * * ported to the latest mixer 0.9.x API (function based)
|
|
- *
|
|
- * Fri Jun 23 14:10:00 MEST 2000 Jaroslav Kysela <perex@perex.cz>
|
|
- *
|
|
- * * ported to new mixer 0.9.x API (simple control)
|
|
- * * improved error handling (mixer_abort)
|
|
- *
|
|
- * Thu Mar 9 22:54:16 MET 2000 Takashi iwai <iwai@ww.uni-erlangen.de>
|
|
- *
|
|
- * * a group is split into front, rear, center and woofer elements.
|
|
- *
|
|
- * Mon Jan 3 23:33:42 MET 2000 Jaroslav Kysela <perex@perex.cz>
|
|
- *
|
|
- * * version 1.00
|
|
- *
|
|
- * * ported to new mixer API (scontrol control)
|
|
- *
|
|
- * Sun Feb 21 19:55:01 1999 Tim Janik <timj@gtk.org>
|
|
- *
|
|
- * * bumped version to 0.10.
|
|
- *
|
|
- * * added scrollable text views.
|
|
- * we now feature an F1 Help screen and an F2 /proc info screen.
|
|
- * the help screen does still require lots of work though.
|
|
- *
|
|
- * * keys are evaluated view specific now.
|
|
- *
|
|
- * * we feature meta-keys now, e.g. M-Tab as back-tab.
|
|
- *
|
|
- * * if we are already in channel view and the user still hits Return,
|
|
- * we do a refresh nonetheless, since 'r'/'R' got removed as a redraw
|
|
- * key (reserved for capture volumes). 'l'/'L' is still preserved though,
|
|
- * and actually needs to be to e.g. get around the xterm bold-artefacts.
|
|
- *
|
|
- * * support terminals that can't write into lower right corner.
|
|
- *
|
|
- * * undocumented '-s' option that will keep the screen to its
|
|
- * minimum size, usefull for debugging only.
|
|
- *
|
|
- * Sun Feb 21 02:23:52 1999 Tim Janik <timj@gtk.org>
|
|
- *
|
|
- * * don't abort if snd_mixer_* functions failed due to EINTR,
|
|
- * we simply retry on the next cycle. hopefully asoundlib preserves
|
|
- * errno states correctly (Jaroslav can you asure that?).
|
|
- *
|
|
- * * feature WINCH correctly, so we make a complete relayout on
|
|
- * screen resizes. don't abort on too-small screen sizes anymore,
|
|
- * but simply beep.
|
|
- *
|
|
- * * redid the layout algorithm to fix some bugs and to preserve
|
|
- * space for a flag indication line. the channels are
|
|
- * nicer spread horizontally now (i.e. we also pad on the left and
|
|
- * right screen bounds now).
|
|
- *
|
|
- * * various other minor fixes.
|
|
- *
|
|
- * * indicate whether ExactMode is active or not.
|
|
- *
|
|
- * * fixed coding style to follow the GNU coding conventions.
|
|
- *
|
|
- * * reverted capture volume changes since they broke ExactMode display.
|
|
- *
|
|
- * * composed ChangeLog entries.
|
|
- *
|
|
- * 1998/11/04 19:43:45 perex
|
|
- *
|
|
- * * Stereo capture source and route selection...
|
|
- * provided by Carl van Schaik <carl@dreamcoat.che.uct.ac.za>.
|
|
- *
|
|
- * 1998/09/20 08:05:24 perex
|
|
- *
|
|
- * * Fixed -m option...
|
|
- *
|
|
- * 1998/10/29 22:50:10
|
|
- *
|
|
- * * initial checkin of alsamixer.c, written by Tim Janik, modified by
|
|
- * Jaroslav Kysela to feature asoundlib.h instead of plain ioctl()s and
|
|
- * automated updates after select() (i always missed that with OSS!).
|
|
- */
|
|
-
|
|
-#define _GNU_SOURCE
|
|
-#include <stdio.h>
|
|
-#include <unistd.h>
|
|
-#include <fcntl.h>
|
|
-#include <sys/ioctl.h>
|
|
-
|
|
-#include <errno.h>
|
|
-
|
|
-#include <string.h>
|
|
-#include <stdlib.h>
|
|
-#include <unistd.h>
|
|
-#include <sys/signal.h>
|
|
-#include <sys/time.h>
|
|
-
|
|
-#include <locale.h>
|
|
-
|
|
-#ifndef CURSESINC
|
|
-#include <ncurses.h>
|
|
-#else
|
|
-#include CURSESINC
|
|
-#endif
|
|
-#include <time.h>
|
|
-
|
|
-#include <alsa/asoundlib.h>
|
|
-#include "aconfig.h"
|
|
-
|
|
-/* example compilation commandline:
|
|
- * clear; gcc -Wall -pipe -O2 alsamixer.c -o alsamixer -lasound -lncurses
|
|
- */
|
|
-
|
|
-/* --- defines --- */
|
|
-#define PRGNAME "alsamixer"
|
|
-#define PRGNAME_UPPER "AlsaMixer"
|
|
-#define CHECK_ABORT(e,s,n) ({ if ((n) != -EINTR) mixer_abort ((e), (s), (n)); })
|
|
-#define GETCH_BLOCK(w) ({ timeout ((w) ? -1 : 0); })
|
|
-
|
|
-#undef MAX
|
|
-#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
|
-#undef MIN
|
|
-#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
|
-#undef ABS
|
|
-#define ABS(a) (((a) < 0) ? -(a) : (a))
|
|
-#undef CLAMP
|
|
-#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
|
|
-
|
|
-#define MIXER_MIN_X (18) /* abs minimum: 18 */
|
|
-#define MIXER_TEXT_Y (10)
|
|
-#define MIXER_CBAR_STD_HGT (10)
|
|
-#define MIXER_MIN_Y (MIXER_TEXT_Y + 6) /* abs minimum: 16 */
|
|
-
|
|
-#define MIXER_BLACK (COLOR_BLACK)
|
|
-#define MIXER_DARK_RED (COLOR_RED)
|
|
-#define MIXER_RED (COLOR_RED | A_BOLD)
|
|
-#define MIXER_GREEN (COLOR_GREEN | A_BOLD)
|
|
-#define MIXER_ORANGE (COLOR_YELLOW)
|
|
-#define MIXER_YELLOW (COLOR_YELLOW | A_BOLD)
|
|
-#define MIXER_MARIN (COLOR_BLUE)
|
|
-#define MIXER_BLUE (COLOR_BLUE | A_BOLD)
|
|
-#define MIXER_MAGENTA (COLOR_MAGENTA)
|
|
-#define MIXER_DARK_CYAN (COLOR_CYAN)
|
|
-#define MIXER_CYAN (COLOR_CYAN | A_BOLD)
|
|
-#define MIXER_GREY (COLOR_WHITE)
|
|
-#define MIXER_GRAY (MIXER_GREY)
|
|
-#define MIXER_WHITE (COLOR_WHITE | A_BOLD)
|
|
-
|
|
-
|
|
-/* --- views --- */
|
|
-enum {
|
|
- VIEW_CHANNELS,
|
|
- VIEW_PLAYBACK,
|
|
- VIEW_CAPTURE,
|
|
- VIEW_HELP,
|
|
- VIEW_PROCINFO
|
|
-};
|
|
-
|
|
-
|
|
-/* --- variables --- */
|
|
-static WINDOW *mixer_window = NULL;
|
|
-static int mixer_needs_resize = 0;
|
|
-static int mixer_minimize = 0;
|
|
-static int mixer_no_lrcorner = 0;
|
|
-static int mixer_view = VIEW_PLAYBACK;
|
|
-static int mixer_view_saved = VIEW_PLAYBACK;
|
|
-static int mixer_max_x = 0;
|
|
-static int mixer_max_y = 0;
|
|
-static int mixer_ofs_x = 0;
|
|
-static float mixer_extra_space = 0;
|
|
-static int mixer_cbar_height = 0;
|
|
-static int mixer_text_y = MIXER_TEXT_Y;
|
|
-
|
|
-static char card_id[64] = "default";
|
|
-static snd_mixer_t *mixer_handle;
|
|
-static char mixer_card_name[128];
|
|
-static char mixer_device_name[128];
|
|
-static int mixer_level = 0;
|
|
-static struct snd_mixer_selem_regopt mixer_options;
|
|
-
|
|
-/* mixer bar channel : left or right */
|
|
-#define MIXER_CHN_LEFT 0
|
|
-#define MIXER_CHN_RIGHT 1
|
|
-/* mask for toggle mute and capture */
|
|
-#define MIXER_MASK_LEFT (1 << 0)
|
|
-#define MIXER_MASK_RIGHT (1 << 1)
|
|
-#define MIXER_MASK_STEREO (MIXER_MASK_LEFT|MIXER_MASK_RIGHT)
|
|
-
|
|
-/* mixer split types */
|
|
-enum {
|
|
- MIXER_ELEM_FRONT, MIXER_ELEM_REAR,
|
|
- MIXER_ELEM_CENTER, MIXER_ELEM_WOOFER,
|
|
- MIXER_ELEM_SIDE,
|
|
- MIXER_ELEM_CAPTURE,
|
|
- MIXER_ELEM_ENUM, MIXER_ELEM_CAPTURE_ENUM,
|
|
- MIXER_ELEM_END
|
|
-};
|
|
-
|
|
-#define MIXER_ELEM_TYPE_MASK 0xff
|
|
-#define MIXER_ELEM_CAPTURE_SWITCH 0x100 /* bit */
|
|
-#define MIXER_ELEM_MUTE_SWITCH 0x200 /* bit */
|
|
-#define MIXER_ELEM_CAPTURE_SUFFIX 0x400
|
|
-#define MIXER_ELEM_HAS_VOLUME 0x800
|
|
-
|
|
-/* left and right channels for each type */
|
|
-static const snd_mixer_selem_channel_id_t mixer_elem_chn[][2] = {
|
|
- { SND_MIXER_SCHN_FRONT_LEFT, SND_MIXER_SCHN_FRONT_RIGHT },
|
|
- { SND_MIXER_SCHN_REAR_LEFT, SND_MIXER_SCHN_REAR_RIGHT },
|
|
- { SND_MIXER_SCHN_FRONT_CENTER, SND_MIXER_SCHN_UNKNOWN },
|
|
- { SND_MIXER_SCHN_WOOFER, SND_MIXER_SCHN_UNKNOWN },
|
|
- { SND_MIXER_SCHN_SIDE_LEFT, SND_MIXER_SCHN_SIDE_RIGHT },
|
|
- { SND_MIXER_SCHN_FRONT_LEFT, SND_MIXER_SCHN_FRONT_RIGHT },
|
|
-};
|
|
-
|
|
-static void *mixer_sid = NULL;
|
|
-static int mixer_n_selems = 0;
|
|
-static int mixer_changed_state = 1;
|
|
-
|
|
-/* split scontrols */
|
|
-static int mixer_n_elems = 0;
|
|
-static int mixer_n_view_elems = 0;
|
|
-static int mixer_n_vis_elems = 0;
|
|
-static int mixer_first_vis_elem = 0;
|
|
-static int mixer_focus_elem = 0;
|
|
-static int mixer_have_old_focus = 0;
|
|
-static int *mixer_grpidx;
|
|
-static int *mixer_type;
|
|
-
|
|
-static int mixer_volume_delta[2]; /* left/right volume delta in % */
|
|
-static int mixer_volume_absolute = -1; /* absolute volume settings in % */
|
|
-static int mixer_balance_volumes = 0; /* boolean */
|
|
-static unsigned mixer_toggle_mute = 0; /* left/right mask */
|
|
-static unsigned mixer_toggle_capture = 0; /* left/right mask */
|
|
-
|
|
-static int mixer_hscroll_delta = 0;
|
|
-static int mixer_vscroll_delta = 0;
|
|
-
|
|
-
|
|
-/* --- text --- */
|
|
-static int mixer_procinfo_xoffs = 0;
|
|
-static int mixer_procinfo_yoffs = 0;
|
|
-static int mixer_help_xoffs = 0;
|
|
-static int mixer_help_yoffs = 0;
|
|
-static char *mixer_help_text =
|
|
-(
|
|
- " Esc exit alsamixer\n"
|
|
- " F1 ? show Help screen\n"
|
|
- " F2 / show /proc info screen\n"
|
|
- " F3 show Playback controls only\n"
|
|
- " F4 show Capture controls only\n"
|
|
- " F5 show all controls\n"
|
|
- " Tab toggle view mode\n"
|
|
- " Return return to main screen\n"
|
|
- " Space toggle Capture facility\n"
|
|
- " m M toggle mute on both channels\n"
|
|
- " < > toggle mute on left/right channel\n"
|
|
- " Up increase left and right volume\n"
|
|
- " Down decrease left and right volume\n"
|
|
- " Right move (scroll) to the right next channel\n"
|
|
- " Left move (scroll) to the left next channel\n"
|
|
- "\n"
|
|
- "Alsamixer has been written and is Copyrighted in 1998, 1999 by\n"
|
|
- "Tim Janik <timj@gtk.org> and Jaroslav Kysela <perex@perex.cz>.\n"
|
|
- );
|
|
-
|
|
-
|
|
-/* --- draw contexts --- */
|
|
-enum {
|
|
- DC_DEFAULT,
|
|
- DC_BACK,
|
|
- DC_TEXT,
|
|
- DC_PROMPT,
|
|
- DC_CBAR_FRAME,
|
|
- DC_CBAR_MUTE,
|
|
- DC_CBAR_NOMUTE,
|
|
- DC_CBAR_CAPTURE,
|
|
- DC_CBAR_NOCAPTURE,
|
|
- DC_CBAR_EMPTY,
|
|
- DC_CBAR_LABEL,
|
|
- DC_CBAR_FOCUS_LABEL,
|
|
- DC_FOCUS,
|
|
- DC_ANY_1,
|
|
- DC_ANY_2,
|
|
- DC_ANY_3,
|
|
- DC_ANY_4,
|
|
- DC_LAST
|
|
-};
|
|
-
|
|
-static int dc_fg[DC_LAST] = { 0 };
|
|
-static int dc_attrib[DC_LAST] = { 0 };
|
|
-static int dc_char[DC_LAST] = { 0 };
|
|
-static int mixer_do_color = 1;
|
|
-
|
|
-static void
|
|
-mixer_init_dc (int c,
|
|
- int n,
|
|
- int f,
|
|
- int b,
|
|
- int a)
|
|
-{
|
|
- dc_fg[n] = f;
|
|
- dc_attrib[n] = a;
|
|
- dc_char[n] = c;
|
|
- if (n > 0)
|
|
- init_pair (n, dc_fg[n] & 0xf, b & 0x0f);
|
|
-}
|
|
-
|
|
-static int
|
|
-mixer_dc (int n)
|
|
-{
|
|
- if (mixer_do_color)
|
|
- attrset (COLOR_PAIR (n) | (dc_fg[n] & 0xfffffff0));
|
|
- else
|
|
- attrset (dc_attrib[n]);
|
|
-
|
|
- return dc_char[n];
|
|
-}
|
|
-
|
|
-static void
|
|
-mixer_init_draw_contexts (void)
|
|
-{
|
|
- start_color ();
|
|
-
|
|
- mixer_init_dc ('.', DC_BACK, MIXER_WHITE, MIXER_BLACK, A_NORMAL);
|
|
- mixer_init_dc ('.', DC_TEXT, MIXER_YELLOW, MIXER_BLACK, A_BOLD);
|
|
- mixer_init_dc ('.', DC_PROMPT, MIXER_DARK_CYAN, MIXER_BLACK, A_NORMAL);
|
|
- mixer_init_dc ('.', DC_CBAR_FRAME, MIXER_CYAN, MIXER_BLACK, A_BOLD);
|
|
- mixer_init_dc ('M', DC_CBAR_MUTE, MIXER_DARK_CYAN, MIXER_BLACK, A_NORMAL);
|
|
- mixer_init_dc ('O', DC_CBAR_NOMUTE, MIXER_WHITE, MIXER_GREEN, A_BOLD);
|
|
- mixer_init_dc ('x', DC_CBAR_CAPTURE, MIXER_DARK_RED, MIXER_BLACK, A_BOLD);
|
|
- mixer_init_dc ('-', DC_CBAR_NOCAPTURE, MIXER_GRAY, MIXER_BLACK, A_NORMAL);
|
|
- mixer_init_dc (' ', DC_CBAR_EMPTY, MIXER_GRAY, MIXER_BLACK, A_DIM);
|
|
- mixer_init_dc ('.', DC_CBAR_LABEL, MIXER_WHITE, MIXER_BLUE, A_REVERSE | A_BOLD);
|
|
- mixer_init_dc ('.', DC_CBAR_FOCUS_LABEL, MIXER_RED, MIXER_BLUE, A_REVERSE | A_BOLD);
|
|
- mixer_init_dc ('.', DC_FOCUS, MIXER_RED, MIXER_BLACK, A_BOLD);
|
|
- mixer_init_dc (ACS_CKBOARD, DC_ANY_1, MIXER_WHITE, MIXER_WHITE, A_BOLD);
|
|
- mixer_init_dc (ACS_CKBOARD, DC_ANY_2, MIXER_GREEN, MIXER_GREEN, A_BOLD);
|
|
- mixer_init_dc (ACS_CKBOARD, DC_ANY_3, MIXER_RED, MIXER_RED, A_BOLD);
|
|
- mixer_init_dc ('.', DC_ANY_4, MIXER_WHITE, MIXER_BLUE, A_BOLD);
|
|
-}
|
|
-
|
|
-#define DC_FRAME (DC_PROMPT)
|
|
-
|
|
-
|
|
-/* --- error types --- */
|
|
-typedef enum
|
|
-{
|
|
- ERR_NONE,
|
|
- ERR_OPEN,
|
|
- ERR_FCN,
|
|
- ERR_SIGNAL,
|
|
- ERR_WINSIZE,
|
|
-} ErrType;
|
|
-
|
|
-
|
|
-/* --- prototypes --- */
|
|
-static void
|
|
-mixer_abort (ErrType error,
|
|
- const char *err_string,
|
|
- int xerrno)
|
|
- __attribute__
|
|
-((noreturn));
|
|
-
|
|
-
|
|
-/* --- functions --- */
|
|
-static void
|
|
-mixer_clear (int full_redraw)
|
|
-{
|
|
- int x, y;
|
|
- int f = full_redraw ? 0 : 1;
|
|
-
|
|
- mixer_dc (DC_BACK);
|
|
-
|
|
- if (full_redraw)
|
|
- clearok (mixer_window, TRUE);
|
|
-
|
|
- /* buggy ncurses doesn't really write spaces with the specified
|
|
- * color into the screen on clear () or erase ()
|
|
- */
|
|
- for (x = f; x < mixer_max_x - f; x++)
|
|
- for (y = f; y < mixer_max_y - f; y++)
|
|
- mvaddch (y, x, ' ');
|
|
-}
|
|
-
|
|
-static void
|
|
-mixer_abort (ErrType error,
|
|
- const char *err_string,
|
|
- int xerrno)
|
|
-{
|
|
- if (mixer_window)
|
|
- {
|
|
- mixer_clear (TRUE);
|
|
- refresh ();
|
|
- keypad (mixer_window, FALSE);
|
|
- leaveok (mixer_window, FALSE);
|
|
- endwin ();
|
|
- mixer_window = NULL;
|
|
- }
|
|
- printf ("\n");
|
|
-
|
|
- switch (error)
|
|
- {
|
|
- case ERR_OPEN:
|
|
- fprintf (stderr,
|
|
- PRGNAME ": function %s failed for %s: %s\n",
|
|
- err_string,
|
|
- card_id,
|
|
- snd_strerror (xerrno));
|
|
- break;
|
|
- case ERR_FCN:
|
|
- fprintf (stderr,
|
|
- PRGNAME ": function %s failed: %s\n",
|
|
- err_string,
|
|
- snd_strerror (xerrno));
|
|
- break;
|
|
- case ERR_SIGNAL:
|
|
- fprintf (stderr,
|
|
- PRGNAME ": aborting due to signal `%s'\n",
|
|
- err_string);
|
|
- break;
|
|
- case ERR_WINSIZE:
|
|
- fprintf (stderr,
|
|
- PRGNAME ": screen size too small (%dx%d)\n",
|
|
- mixer_max_x,
|
|
- mixer_max_y);
|
|
- break;
|
|
- default:
|
|
- break;
|
|
- }
|
|
-
|
|
- exit (error);
|
|
-}
|
|
-
|
|
-static int
|
|
-mixer_cbar_get_pos (int elem_index,
|
|
- int *x_p,
|
|
- int *y_p)
|
|
-{
|
|
- int x;
|
|
- int y;
|
|
-
|
|
- if (elem_index < mixer_first_vis_elem ||
|
|
- elem_index - mixer_first_vis_elem >= mixer_n_vis_elems)
|
|
- return FALSE;
|
|
-
|
|
- elem_index -= mixer_first_vis_elem;
|
|
-
|
|
- x = mixer_ofs_x;
|
|
- x += (3 + 2 + 3 + 1) * elem_index + mixer_extra_space * (elem_index + 1);
|
|
-
|
|
- if (mixer_text_y + MIXER_CBAR_STD_HGT < mixer_max_y)
|
|
- y = (mixer_text_y + mixer_cbar_height) / 2 - 1 + mixer_max_y / 2;
|
|
- else
|
|
- y = mixer_text_y - 1 + mixer_cbar_height;
|
|
- if (y >= mixer_max_y - 1)
|
|
- y = mixer_max_y - 2;
|
|
- if (x_p)
|
|
- *x_p = x;
|
|
- if (y_p)
|
|
- *y_p = y;
|
|
-
|
|
- return TRUE;
|
|
-}
|
|
-
|
|
-static int
|
|
-mixer_conv(int val, int omin, int omax, int nmin, int nmax)
|
|
-{
|
|
- float orange = omax - omin, nrange = nmax - nmin;
|
|
-
|
|
- if (orange == 0)
|
|
- return 0;
|
|
- return ((nrange * (val - omin)) + (orange / 2)) / orange + nmin;
|
|
-}
|
|
-
|
|
-static int
|
|
-mixer_calc_volume(snd_mixer_elem_t *elem,
|
|
- int vol, int type,
|
|
- snd_mixer_selem_channel_id_t chn)
|
|
-{
|
|
- int vol1;
|
|
- long v;
|
|
- long min, max;
|
|
- if (type != MIXER_ELEM_CAPTURE)
|
|
- snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
|
|
- else
|
|
- snd_mixer_selem_get_capture_volume_range(elem, &min, &max);
|
|
- vol1 = (vol < 0) ? -vol : vol;
|
|
- if (vol1 > 0) {
|
|
- if (vol1 > 100)
|
|
- vol1 = max;
|
|
- else
|
|
- vol1 = mixer_conv(vol1, 0, 100, min, max);
|
|
- /* Note: we have delta in vol1 and we need to map our */
|
|
- /* delta value to hardware range */
|
|
- vol1 -= min;
|
|
- if (vol1 <= 0)
|
|
- vol1 = 1;
|
|
- if (vol < 0)
|
|
- vol1 = -vol1;
|
|
- }
|
|
- if (type != MIXER_ELEM_CAPTURE)
|
|
- snd_mixer_selem_get_playback_volume(elem, chn, &v);
|
|
- else
|
|
- snd_mixer_selem_get_capture_volume(elem, chn, &v);
|
|
- vol1 += v;
|
|
- return CLAMP(vol1, min, max);
|
|
-}
|
|
-
|
|
-static int
|
|
-mixer_convert_volume(snd_mixer_elem_t *elem,
|
|
- int vol, int type)
|
|
-{
|
|
- long min, max;
|
|
- if (type != MIXER_ELEM_CAPTURE)
|
|
- snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
|
|
- else
|
|
- snd_mixer_selem_get_capture_volume_range(elem, &min, &max);
|
|
- return mixer_conv(vol, 0, 100, min, max);
|
|
-}
|
|
-
|
|
-/* update enum list */
|
|
-static void update_enum_list(snd_mixer_elem_t *elem, int chn, int delta)
|
|
-{
|
|
- unsigned int eidx;
|
|
- if (snd_mixer_selem_get_enum_item(elem, chn, &eidx) < 0)
|
|
- return;
|
|
- if (delta < 0) {
|
|
- if (eidx == 0)
|
|
- return;
|
|
- eidx--;
|
|
- } else {
|
|
- int items = snd_mixer_selem_get_enum_items(elem);
|
|
- if (items < 0)
|
|
- return;
|
|
- eidx++;
|
|
- if (eidx >= items)
|
|
- return;
|
|
- }
|
|
- snd_mixer_selem_set_enum_item(elem, chn, eidx);
|
|
-}
|
|
-
|
|
-/* set new channel values
|
|
- */
|
|
-static void
|
|
-mixer_write_cbar (int elem_index)
|
|
-{
|
|
- snd_mixer_elem_t *elem;
|
|
- int vleft, vright, vbalance;
|
|
- int type;
|
|
- snd_mixer_selem_id_t *sid;
|
|
- snd_mixer_selem_channel_id_t chn_left, chn_right, chn;
|
|
- int sw;
|
|
-
|
|
- if (mixer_sid == NULL)
|
|
- return;
|
|
-
|
|
- sid = (snd_mixer_selem_id_t *)(((char *)mixer_sid) + snd_mixer_selem_id_sizeof() * mixer_grpidx[elem_index]);
|
|
- elem = snd_mixer_find_selem(mixer_handle, sid);
|
|
- if (elem == NULL)
|
|
- CHECK_ABORT (ERR_FCN, "snd_mixer_find_selem()", -EINVAL);
|
|
- type = mixer_type[elem_index] & MIXER_ELEM_TYPE_MASK;
|
|
- chn_left = mixer_elem_chn[type][MIXER_CHN_LEFT];
|
|
- chn_right = mixer_elem_chn[type][MIXER_CHN_RIGHT];
|
|
- if (chn_right != SND_MIXER_SCHN_UNKNOWN) {
|
|
- if (type != MIXER_ELEM_CAPTURE) {
|
|
- if (!snd_mixer_selem_has_playback_channel(elem, chn_right))
|
|
- chn_right = SND_MIXER_SCHN_UNKNOWN;
|
|
- } else {
|
|
- if (!snd_mixer_selem_has_capture_channel(elem, chn_right))
|
|
- chn_right = SND_MIXER_SCHN_UNKNOWN;
|
|
- }
|
|
- }
|
|
-
|
|
- /* volume
|
|
- */
|
|
- if ((mixer_volume_delta[MIXER_CHN_LEFT] ||
|
|
- mixer_volume_delta[MIXER_CHN_RIGHT] ||
|
|
- mixer_volume_absolute != -1 ||
|
|
- mixer_balance_volumes) &&
|
|
- (mixer_type[elem_index] & MIXER_ELEM_HAS_VOLUME)) {
|
|
- int mono;
|
|
- int joined;
|
|
- mono = (chn_right == SND_MIXER_SCHN_UNKNOWN);
|
|
- if (type != MIXER_ELEM_CAPTURE)
|
|
- joined = snd_mixer_selem_has_playback_volume_joined(elem);
|
|
- else
|
|
- joined = snd_mixer_selem_has_capture_volume_joined(elem);
|
|
- mono |= joined;
|
|
- if (mixer_volume_absolute != -1) {
|
|
- vbalance = vright = vleft = mixer_convert_volume(elem, mixer_volume_absolute, type);
|
|
- } else {
|
|
- if (mono && !mixer_volume_delta[MIXER_CHN_LEFT])
|
|
- mixer_volume_delta[MIXER_CHN_LEFT] = mixer_volume_delta[MIXER_CHN_RIGHT];
|
|
- vleft = mixer_calc_volume(elem, mixer_volume_delta[MIXER_CHN_LEFT], type, chn_left);
|
|
- vbalance = vleft;
|
|
- if (! mono) {
|
|
- vright = mixer_calc_volume(elem, mixer_volume_delta[MIXER_CHN_RIGHT], type, chn_right);
|
|
- vbalance += vright;
|
|
- vbalance /= 2;
|
|
- } else {
|
|
- vright = vleft;
|
|
- }
|
|
- }
|
|
-
|
|
- if (joined) {
|
|
- for (chn = 0; chn < SND_MIXER_SCHN_LAST; chn++)
|
|
- if (type != MIXER_ELEM_CAPTURE) {
|
|
- if (snd_mixer_selem_has_playback_channel(elem, chn))
|
|
- snd_mixer_selem_set_playback_volume(elem, chn, vleft);
|
|
- } else {
|
|
- if (snd_mixer_selem_has_capture_channel(elem, chn))
|
|
- snd_mixer_selem_set_capture_volume(elem, chn, vleft);
|
|
- }
|
|
- } else {
|
|
- if (mixer_balance_volumes)
|
|
- vleft = vright = vbalance;
|
|
- if (type != MIXER_ELEM_CAPTURE) {
|
|
- if (snd_mixer_selem_has_playback_volume(elem) &&
|
|
- snd_mixer_selem_has_playback_channel(elem, chn_left))
|
|
- snd_mixer_selem_set_playback_volume(elem, chn_left, vleft);
|
|
- } else {
|
|
- if (snd_mixer_selem_has_capture_volume(elem) &&
|
|
- snd_mixer_selem_has_capture_channel(elem, chn_left))
|
|
- snd_mixer_selem_set_capture_volume(elem, chn_left, vleft);
|
|
- }
|
|
- if (! mono) {
|
|
- if (type != MIXER_ELEM_CAPTURE) {
|
|
- if (snd_mixer_selem_has_playback_volume(elem) &&
|
|
- snd_mixer_selem_has_playback_channel(elem, chn_right))
|
|
- snd_mixer_selem_set_playback_volume(elem, chn_right, vright);
|
|
- } else {
|
|
- if (snd_mixer_selem_has_capture_volume(elem) &&
|
|
- snd_mixer_selem_has_capture_channel(elem, chn_right))
|
|
- snd_mixer_selem_set_capture_volume(elem, chn_right, vright);
|
|
- }
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- /* mute
|
|
- */
|
|
- if (mixer_type[elem_index] & MIXER_ELEM_MUTE_SWITCH) {
|
|
- if (mixer_toggle_mute) {
|
|
- if (snd_mixer_selem_has_playback_switch_joined(elem)) {
|
|
- snd_mixer_selem_get_playback_switch(elem, chn_left, &sw);
|
|
- snd_mixer_selem_set_playback_switch_all(elem, !sw);
|
|
- } else {
|
|
- if (mixer_toggle_mute & MIXER_MASK_LEFT) {
|
|
- snd_mixer_selem_get_playback_switch(elem, chn_left, &sw);
|
|
- snd_mixer_selem_set_playback_switch(elem, chn_left, !sw);
|
|
- }
|
|
- if (chn_right != SND_MIXER_SCHN_UNKNOWN &&
|
|
- (mixer_toggle_mute & MIXER_MASK_RIGHT)) {
|
|
- snd_mixer_selem_get_playback_switch(elem, chn_right, &sw);
|
|
- snd_mixer_selem_set_playback_switch(elem, chn_right, !sw);
|
|
- }
|
|
- }
|
|
- }
|
|
- }
|
|
- mixer_toggle_mute = 0;
|
|
-
|
|
- /* capture
|
|
- */
|
|
- if (mixer_type[elem_index] & MIXER_ELEM_CAPTURE_SWITCH) {
|
|
- if (mixer_toggle_capture && snd_mixer_selem_has_capture_switch(elem)) {
|
|
- if (snd_mixer_selem_has_capture_switch_joined(elem)) {
|
|
- snd_mixer_selem_get_capture_switch(elem, chn_left, &sw);
|
|
- snd_mixer_selem_set_capture_switch_all(elem, !sw);
|
|
- } else {
|
|
- if ((mixer_toggle_capture & MIXER_MASK_LEFT) &&
|
|
- snd_mixer_selem_has_capture_channel(elem, chn_left)) {
|
|
- snd_mixer_selem_get_capture_switch(elem, chn_left, &sw);
|
|
- snd_mixer_selem_set_capture_switch(elem, chn_left, !sw);
|
|
- }
|
|
- if (chn_right != SND_MIXER_SCHN_UNKNOWN &&
|
|
- snd_mixer_selem_has_capture_channel(elem, chn_right) &&
|
|
- (mixer_toggle_capture & MIXER_MASK_RIGHT)) {
|
|
- snd_mixer_selem_get_capture_switch(elem, chn_right, &sw);
|
|
- snd_mixer_selem_set_capture_switch(elem, chn_right, !sw);
|
|
- }
|
|
- }
|
|
- }
|
|
- }
|
|
- mixer_toggle_capture = 0;
|
|
-
|
|
- /* enum list
|
|
- */
|
|
- if (type == MIXER_ELEM_ENUM || type == MIXER_ELEM_CAPTURE_ENUM) {
|
|
- if (mixer_volume_delta[MIXER_CHN_LEFT])
|
|
- update_enum_list(elem, MIXER_CHN_LEFT, mixer_volume_delta[MIXER_CHN_LEFT]);
|
|
- if (mixer_volume_delta[MIXER_CHN_RIGHT])
|
|
- update_enum_list(elem, MIXER_CHN_RIGHT, mixer_volume_delta[MIXER_CHN_RIGHT]);
|
|
- }
|
|
-
|
|
- mixer_volume_delta[MIXER_CHN_LEFT] = mixer_volume_delta[MIXER_CHN_RIGHT] = 0;
|
|
- mixer_volume_absolute = -1;
|
|
- mixer_balance_volumes = 0;
|
|
-}
|
|
-
|
|
-
|
|
-static void draw_blank(int x, int y, int lines)
|
|
-{
|
|
- int i;
|
|
-
|
|
- mixer_dc (DC_TEXT);
|
|
- for (i = 0; i < lines; i++)
|
|
- mvaddstr (y - i, x, " ");
|
|
-}
|
|
-
|
|
-/* show the current view mode */
|
|
-static void display_view_info(void)
|
|
-{
|
|
- mixer_dc (DC_PROMPT);
|
|
- mvaddstr (3, 2, "View: Playback Capture All ");
|
|
- mixer_dc (DC_TEXT);
|
|
- switch (mixer_view) {
|
|
- case VIEW_PLAYBACK:
|
|
- mvaddstr (3, 8, "[Playback]");
|
|
- break;
|
|
- case VIEW_CAPTURE:
|
|
- mvaddstr (3, 18, "[Capture]");
|
|
- break;
|
|
- default:
|
|
- mvaddstr (3, 27, "[All]");
|
|
- break;
|
|
- }
|
|
-}
|
|
-
|
|
-/* show the information of the focused item */
|
|
-static void display_item_info(int elem_index, snd_mixer_selem_id_t *sid, char *extra_info)
|
|
-{
|
|
- char string[64], idxstr[10];
|
|
- int idx;
|
|
- int i, xlen = mixer_max_x - 8;
|
|
- if (xlen > sizeof(string) - 1)
|
|
- xlen = sizeof(string) - 1;
|
|
- mixer_dc (DC_PROMPT);
|
|
- mvaddstr (4, 2, "Item: ");
|
|
- mixer_dc (DC_TEXT);
|
|
- idx = snd_mixer_selem_id_get_index(sid);
|
|
- if (idx > 0)
|
|
- snprintf(idxstr, sizeof(idxstr), " %i", snd_mixer_selem_id_get_index(sid));
|
|
- snprintf(string, sizeof(string), "%s%s%s%s",
|
|
- snd_mixer_selem_id_get_name(sid),
|
|
- (mixer_type[elem_index] & MIXER_ELEM_CAPTURE_SUFFIX) ? " Capture" : "",
|
|
- idx > 0 ? idxstr : "",
|
|
- extra_info);
|
|
- for (i = strlen(string); i < sizeof(string) - 1; i++)
|
|
- string[i] = ' ';
|
|
- string[xlen] = '\0';
|
|
- addstr(string);
|
|
-}
|
|
-
|
|
-/* show the bar item name */
|
|
-static void display_item_name(int x, int y, int elem_index, snd_mixer_selem_id_t *sid)
|
|
-{
|
|
- const char *suffix;
|
|
- char string1[9], string[9];
|
|
- int i;
|
|
-
|
|
- mixer_dc (elem_index == mixer_focus_elem ? DC_CBAR_FOCUS_LABEL : DC_CBAR_LABEL);
|
|
- if (mixer_type[elem_index] & MIXER_ELEM_CAPTURE_SUFFIX)
|
|
- suffix = " Capture";
|
|
- else
|
|
- suffix = "";
|
|
- if (snd_mixer_selem_id_get_index(sid) > 0)
|
|
- snprintf(string1, sizeof(string1), "%s%s %d", snd_mixer_selem_id_get_name(sid),
|
|
- suffix, snd_mixer_selem_id_get_index(sid));
|
|
- else
|
|
- snprintf(string1, sizeof(string1), "%s%s", snd_mixer_selem_id_get_name(sid), suffix);
|
|
- string[8] = 0;
|
|
- for (i = 0; i < 8; i++)
|
|
- string[i] = ' ';
|
|
- memcpy(string + (8 - strlen (string1)) / 2, string1, strlen(string1));
|
|
- mvaddstr (y, x, string);
|
|
-}
|
|
-
|
|
-static void display_enum_list(snd_mixer_elem_t *elem, int y, int x)
|
|
-{
|
|
- int cury, ch, err;
|
|
-
|
|
- draw_blank(x, y, mixer_cbar_height + (mixer_view == VIEW_PLAYBACK ? 5 : 6));
|
|
-
|
|
- cury = y - 4;
|
|
- for (ch = 0; ch < 2; ch++) {
|
|
- unsigned int eidx, ofs;
|
|
- char tmp[9];
|
|
- err = snd_mixer_selem_get_enum_item(elem, ch, &eidx);
|
|
- if (err < 0)
|
|
- break;
|
|
- if (snd_mixer_selem_get_enum_item_name(elem, eidx, sizeof(tmp) - 1, tmp) < 0)
|
|
- break;
|
|
- tmp[8] = 0;
|
|
- ofs = (8 - strlen(tmp)) / 2;
|
|
- mvaddstr(cury, x + ofs, tmp);
|
|
- cury += 2;
|
|
- }
|
|
-}
|
|
-
|
|
-static void draw_volume_bar(int x, int y, int elem_index, long vleft, long vright)
|
|
-{
|
|
- int i, dc;
|
|
-
|
|
- mixer_dc (DC_CBAR_FRAME);
|
|
- if (mixer_type[elem_index] & MIXER_ELEM_MUTE_SWITCH) {
|
|
- mvaddch (y, x + 2, ACS_LTEE);
|
|
- mvaddch (y, x + 5, ACS_RTEE);
|
|
- } else {
|
|
- mvaddch (y, x + 2, ACS_LLCORNER);
|
|
- mvaddch (y, x + 3, ACS_HLINE);
|
|
- mvaddch (y, x + 4, ACS_HLINE);
|
|
- mvaddch (y, x + 5, ACS_LRCORNER);
|
|
- }
|
|
- y--;
|
|
- for (i = 0; i < mixer_cbar_height; i++)
|
|
- {
|
|
- mvaddstr (y - i, x, " ");
|
|
- mvaddch (y - i, x + 2, ACS_VLINE);
|
|
- mvaddch (y - i, x + 5, ACS_VLINE);
|
|
- }
|
|
- for (i = 0; i < mixer_cbar_height; i++)
|
|
- {
|
|
- if (i + 1 >= 0.8 * mixer_cbar_height)
|
|
- dc = DC_ANY_3;
|
|
- else if (i + 1 >= 0.4 * mixer_cbar_height)
|
|
- dc = DC_ANY_2;
|
|
- else
|
|
- dc = DC_ANY_1;
|
|
- mvaddch (y, x + 3, mixer_dc (vleft > i * 100 / mixer_cbar_height ? dc : DC_CBAR_EMPTY));
|
|
- mvaddch (y, x + 4, mixer_dc (vright > i * 100 / mixer_cbar_height ? dc : DC_CBAR_EMPTY));
|
|
- y--;
|
|
- }
|
|
-
|
|
- mixer_dc (DC_CBAR_FRAME);
|
|
- mvaddstr (y, x, " ");
|
|
- mvaddch (y, x + 2, ACS_ULCORNER);
|
|
- mvaddch (y, x + 3, ACS_HLINE);
|
|
- mvaddch (y, x + 4, ACS_HLINE);
|
|
- mvaddch (y, x + 5, ACS_URCORNER);
|
|
-}
|
|
-
|
|
-static void draw_playback_switch(int x, int y, int elem_index, int swl, int swr)
|
|
-{
|
|
- int dc;
|
|
-
|
|
- mixer_dc (DC_CBAR_FRAME);
|
|
- mvaddch (y, x + 2, ACS_LLCORNER);
|
|
- mvaddch (y, x + 3, ACS_HLINE);
|
|
- mvaddch (y, x + 4, ACS_HLINE);
|
|
- mvaddch (y, x + 5, ACS_LRCORNER);
|
|
- mvaddstr (y - 1, x, " ");
|
|
- mvaddch (y - 1, x + 2, ACS_VLINE);
|
|
- mvaddch (y - 1, x + 5, ACS_VLINE);
|
|
- mvaddstr (y - 2, x, " ");
|
|
- mvaddch (y - 2, x + 2, ACS_ULCORNER);
|
|
- mvaddch (y - 2, x + 3, ACS_HLINE);
|
|
- mvaddch (y - 2, x + 4, ACS_HLINE);
|
|
- mvaddch (y - 2, x + 5, ACS_URCORNER);
|
|
- dc = swl ? DC_CBAR_NOMUTE : DC_CBAR_MUTE;
|
|
- mvaddch (y - 1, x + 3, mixer_dc (dc));
|
|
- dc = swr ? DC_CBAR_NOMUTE : DC_CBAR_MUTE;
|
|
- mvaddch (y - 1, x + 4, mixer_dc (dc));
|
|
-}
|
|
-
|
|
-static void draw_capture_switch(int x, int y, int elem_index, int swl, int swr)
|
|
-{
|
|
- int i;
|
|
-
|
|
- if (swl || swr) {
|
|
- mixer_dc (DC_CBAR_CAPTURE);
|
|
- mvaddstr (y, x + 1, "CAPTUR");
|
|
- } else {
|
|
- for (i = 0; i < 6; i++)
|
|
- mvaddch(y, x + i + 1, mixer_dc(DC_CBAR_NOCAPTURE));
|
|
- }
|
|
- mixer_dc (DC_CBAR_CAPTURE);
|
|
- mvaddch (y - 1, x + 1, swl ? 'L' : ' ');
|
|
- mvaddch (y - 1, x + 6, swr ? 'R' : ' ');
|
|
-}
|
|
-
|
|
-#ifndef SND_CTL_TLV_DB_GAIN_MUTE
|
|
-#define SND_CTL_TLV_DB_GAIN_MUTE -9999999
|
|
-#endif
|
|
-
|
|
-static void dB_value(char *s, long val)
|
|
-{
|
|
- if (val <= SND_CTL_TLV_DB_GAIN_MUTE)
|
|
- strcpy(s, "mute");
|
|
- else
|
|
- snprintf(s, 10, "%3.2f", (float)val / 100);
|
|
-}
|
|
-
|
|
-static void
|
|
-mixer_update_cbar (int elem_index)
|
|
-{
|
|
- snd_mixer_elem_t *elem;
|
|
- long vleft, vright;
|
|
- int type;
|
|
- snd_mixer_selem_id_t *sid;
|
|
- snd_mixer_selem_channel_id_t chn_left, chn_right;
|
|
- int x, y;
|
|
- int swl, swr;
|
|
- char * extra_info;
|
|
-
|
|
- /* set new scontrol indices and read info
|
|
- */
|
|
- if (mixer_sid == NULL)
|
|
- return;
|
|
-
|
|
- sid = (snd_mixer_selem_id_t *)(((char *)mixer_sid) + snd_mixer_selem_id_sizeof() * mixer_grpidx[elem_index]);
|
|
- elem = snd_mixer_find_selem(mixer_handle, sid);
|
|
- if (elem == NULL)
|
|
- CHECK_ABORT (ERR_FCN, "snd_mixer_find_selem()", -EINVAL);
|
|
-
|
|
- type = mixer_type[elem_index] & MIXER_ELEM_TYPE_MASK;
|
|
- chn_left = mixer_elem_chn[type][MIXER_CHN_LEFT];
|
|
- chn_right = mixer_elem_chn[type][MIXER_CHN_RIGHT];
|
|
- if (chn_right != SND_MIXER_SCHN_UNKNOWN) {
|
|
- if (type != MIXER_ELEM_CAPTURE) {
|
|
- if (!snd_mixer_selem_has_playback_channel(elem, chn_right))
|
|
- chn_right = SND_MIXER_SCHN_UNKNOWN;
|
|
- } else {
|
|
- if (!snd_mixer_selem_has_capture_channel(elem, chn_right))
|
|
- chn_right = SND_MIXER_SCHN_UNKNOWN;
|
|
- }
|
|
- }
|
|
-
|
|
- vleft = vright = 0;
|
|
- if (type != MIXER_ELEM_CAPTURE && snd_mixer_selem_has_playback_volume(elem)) {
|
|
- long vmin, vmax;
|
|
- snd_mixer_selem_get_playback_volume_range(elem, &vmin, &vmax);
|
|
- snd_mixer_selem_get_playback_volume(elem, chn_left, &vleft);
|
|
- vleft = mixer_conv(vleft, vmin, vmax, 0, 100);
|
|
- if (chn_right != SND_MIXER_SCHN_UNKNOWN) {
|
|
- snd_mixer_selem_get_playback_volume(elem, chn_right, &vright);
|
|
- vright = mixer_conv(vright, vmin, vmax, 0, 100);
|
|
- } else {
|
|
- vright = vleft;
|
|
- }
|
|
- }
|
|
-
|
|
- if (type == MIXER_ELEM_CAPTURE && snd_mixer_selem_has_capture_volume(elem)) {
|
|
- long vmin, vmax;
|
|
- snd_mixer_selem_get_capture_volume_range(elem, &vmin, &vmax);
|
|
- snd_mixer_selem_get_capture_volume(elem, chn_left, &vleft);
|
|
- vleft = mixer_conv(vleft, vmin, vmax, 0, 100);
|
|
- if (chn_right != SND_MIXER_SCHN_UNKNOWN) {
|
|
- snd_mixer_selem_get_capture_volume(elem, chn_right, &vright);
|
|
- vright = mixer_conv(vright, vmin, vmax, 0, 100);
|
|
- } else {
|
|
- vright = vleft;
|
|
- }
|
|
- }
|
|
-
|
|
- /* update the focused full bar name
|
|
- */
|
|
- if (elem_index == mixer_focus_elem) {
|
|
- char tmp[50];
|
|
- /* control muted? */
|
|
- swl = swr = 1;
|
|
- extra_info = "";
|
|
- if (mixer_type[elem_index] & MIXER_ELEM_MUTE_SWITCH) {
|
|
- snd_mixer_selem_get_playback_switch(elem, chn_left, &swl);
|
|
- swr = swl;
|
|
- if (chn_right != SND_MIXER_SCHN_UNKNOWN)
|
|
- snd_mixer_selem_get_playback_switch(elem, chn_right, &swr);
|
|
- extra_info = !swl && !swr ? " [Off]" : "";
|
|
- }
|
|
- if (type == MIXER_ELEM_ENUM || type == MIXER_ELEM_CAPTURE_ENUM) {
|
|
- /* FIXME: should show the item names of secondary and later channels... */
|
|
- unsigned int eidx, length;
|
|
- tmp[0]=' ';
|
|
- tmp[1]='[';
|
|
- if (! snd_mixer_selem_get_enum_item(elem, 0, &eidx) &&
|
|
- ! snd_mixer_selem_get_enum_item_name(elem, eidx, sizeof(tmp) - 3, tmp+2)) {
|
|
- tmp[sizeof(tmp)-2] = 0;
|
|
- length=strlen(tmp);
|
|
- tmp[length]=']';
|
|
- tmp[length+1]=0;
|
|
- extra_info = tmp;
|
|
- }
|
|
- }
|
|
- if (type != MIXER_ELEM_CAPTURE && snd_mixer_selem_has_playback_volume(elem)) {
|
|
- long vdbleft, vdbright;
|
|
- unsigned int length;
|
|
- if (!snd_mixer_selem_get_playback_dB(elem, chn_left, &vdbleft)) {
|
|
- char tmpl[10], tmpr[10];
|
|
- dB_value(tmpl, vdbleft);
|
|
- if ((chn_right != SND_MIXER_SCHN_UNKNOWN) &&
|
|
- (!snd_mixer_selem_get_playback_dB(elem, chn_right, &vdbright))) {
|
|
- dB_value(tmpr, vdbright);
|
|
- snprintf(tmp, 48, " [dB gain=%s, %s]", tmpl, tmpr);
|
|
- } else {
|
|
- snprintf(tmp, 48, " [dB gain=%s]", tmpl);
|
|
- }
|
|
- tmp[sizeof(tmp)-2] = 0;
|
|
- length=strlen(tmp);
|
|
- tmp[length+1]=0;
|
|
- extra_info = tmp;
|
|
- }
|
|
- }
|
|
- if (type == MIXER_ELEM_CAPTURE && snd_mixer_selem_has_capture_volume(elem)) {
|
|
- long vdbleft, vdbright;
|
|
- unsigned int length;
|
|
- if (!snd_mixer_selem_get_capture_dB(elem, chn_left, &vdbleft)) {
|
|
- char tmpl[10], tmpr[10];
|
|
- dB_value(tmpl, vdbleft);
|
|
- if ((chn_right != SND_MIXER_SCHN_UNKNOWN) &&
|
|
- (!snd_mixer_selem_get_capture_dB(elem, chn_right, &vdbright))) {
|
|
- dB_value(tmpr, vdbright);
|
|
- snprintf(tmp, 48, " [dB gain=%s, %s]", tmpl, tmpr);
|
|
- } else {
|
|
- snprintf(tmp, 48, " [dB gain=%s]", tmpl);
|
|
- }
|
|
- tmp[sizeof(tmp)-2] = 0;
|
|
- length=strlen(tmp);
|
|
- tmp[length+1]=0;
|
|
- extra_info = tmp;
|
|
- }
|
|
- }
|
|
- display_item_info(elem_index, sid, extra_info);
|
|
- }
|
|
-
|
|
- /* get channel bar position
|
|
- */
|
|
- if (!mixer_cbar_get_pos (elem_index, &x, &y))
|
|
- return;
|
|
-
|
|
- /* channel bar name
|
|
- */
|
|
- display_item_name(x, y, elem_index, sid);
|
|
- y--;
|
|
-
|
|
- /* enum list? */
|
|
- if (type == MIXER_ELEM_ENUM || type == MIXER_ELEM_CAPTURE_ENUM) {
|
|
- display_enum_list(elem, y, x);
|
|
- return; /* no more to display */
|
|
- }
|
|
-
|
|
- /* current channel values
|
|
- */
|
|
- mixer_dc (DC_BACK);
|
|
- mvaddstr (y, x, " ");
|
|
- if (mixer_type[elem_index] & MIXER_ELEM_HAS_VOLUME) {
|
|
- char string[4];
|
|
- mixer_dc (DC_TEXT);
|
|
- if (chn_right == SND_MIXER_SCHN_UNKNOWN) {
|
|
- /* mono */
|
|
- snprintf (string, sizeof(string), "%ld", vleft);
|
|
- mvaddstr (y, x + 4 - strlen (string) / 2, string);
|
|
- } else {
|
|
- /* stereo */
|
|
- snprintf (string, sizeof(string), "%ld", vleft);
|
|
- mvaddstr (y, x + 3 - strlen (string), string);
|
|
- mixer_dc (DC_CBAR_FRAME);
|
|
- mvaddch (y, x + 3, '<');
|
|
- mvaddch (y, x + 4, '>');
|
|
- mixer_dc (DC_TEXT);
|
|
- snprintf (string, sizeof(string), "%ld", vright);
|
|
- mvaddstr (y, x + 5, string);
|
|
- }
|
|
- }
|
|
- y--;
|
|
-
|
|
- /* capture input?
|
|
- */
|
|
- if (mixer_view == VIEW_CAPTURE || mixer_view == VIEW_CHANNELS) {
|
|
- if ((mixer_type[elem_index] & MIXER_ELEM_CAPTURE_SWITCH) &&
|
|
- snd_mixer_selem_has_capture_switch(elem)) {
|
|
- int has_r_sw = chn_right != SND_MIXER_SCHN_UNKNOWN &&
|
|
- snd_mixer_selem_has_capture_channel(elem, chn_right);
|
|
- snd_mixer_selem_get_capture_switch(elem, chn_left, &swl);
|
|
- if (has_r_sw)
|
|
- snd_mixer_selem_get_capture_switch(elem, chn_right, &swr);
|
|
- else
|
|
- swr = swl;
|
|
- draw_capture_switch(x, y, elem_index, swl, swr);
|
|
- } else
|
|
- draw_blank(x, y, 2);
|
|
- y--;
|
|
- }
|
|
-
|
|
- /* mute switch */
|
|
- if (mixer_view == VIEW_PLAYBACK || mixer_view == VIEW_CHANNELS) {
|
|
- if (mixer_type[elem_index] & MIXER_ELEM_MUTE_SWITCH) {
|
|
- snd_mixer_selem_get_playback_switch(elem, chn_left, &swl);
|
|
- if (chn_right != SND_MIXER_SCHN_UNKNOWN)
|
|
- snd_mixer_selem_get_playback_switch(elem, chn_right, &swr);
|
|
- else
|
|
- swr = swl;
|
|
- draw_playback_switch(x, y, elem_index, swl, swr);
|
|
- } else {
|
|
- mixer_dc (DC_CBAR_FRAME);
|
|
- mvaddstr (y, x + 2, " ");
|
|
- draw_blank(x, y - 1, 2);
|
|
- }
|
|
- y -= 2;
|
|
- }
|
|
-
|
|
- /* left/right volume bar
|
|
- */
|
|
- if (mixer_type[elem_index] & MIXER_ELEM_HAS_VOLUME)
|
|
- draw_volume_bar(x, y, elem_index, vleft, vright);
|
|
- else {
|
|
- if (mixer_view == VIEW_CAPTURE)
|
|
- mvaddstr (y, x + 2, " ");
|
|
- draw_blank(x, y - 1, mixer_cbar_height + 1);
|
|
- }
|
|
-}
|
|
-
|
|
-static void
|
|
-mixer_update_cbars (void)
|
|
-{
|
|
- static int o_x = 0;
|
|
- static int o_y = 0;
|
|
- int i, x, y;
|
|
-
|
|
- display_view_info();
|
|
- if (!mixer_cbar_get_pos (mixer_focus_elem, &x, &y))
|
|
- {
|
|
- if (mixer_focus_elem < mixer_first_vis_elem)
|
|
- mixer_first_vis_elem = mixer_focus_elem;
|
|
- else if (mixer_focus_elem >= mixer_first_vis_elem + mixer_n_vis_elems)
|
|
- mixer_first_vis_elem = mixer_focus_elem - mixer_n_vis_elems + 1;
|
|
- mixer_cbar_get_pos (mixer_focus_elem, &x, &y);
|
|
- }
|
|
- if (mixer_first_vis_elem + mixer_n_vis_elems >= mixer_n_view_elems) {
|
|
- mixer_first_vis_elem = mixer_n_view_elems - mixer_n_vis_elems;
|
|
- if (mixer_first_vis_elem < 0)
|
|
- mixer_first_vis_elem = 0;
|
|
- mixer_cbar_get_pos (mixer_focus_elem, &x, &y);
|
|
- }
|
|
- mixer_write_cbar(mixer_focus_elem);
|
|
- for (i = 0; i < mixer_n_vis_elems; i++) {
|
|
- if (i + mixer_first_vis_elem >= mixer_n_view_elems)
|
|
- continue;
|
|
- mixer_update_cbar (i + mixer_first_vis_elem);
|
|
- }
|
|
-
|
|
- /* draw focused cbar
|
|
- */
|
|
- if (mixer_have_old_focus)
|
|
- {
|
|
- mixer_dc (DC_BACK);
|
|
- mvaddstr (o_y, o_x, " ");
|
|
- mvaddstr (o_y, o_x + 9, " ");
|
|
- }
|
|
- o_x = x - 1;
|
|
- o_y = y;
|
|
- mixer_dc (DC_FOCUS);
|
|
- mvaddstr (o_y, o_x, "<");
|
|
- mvaddstr (o_y, o_x + 9, ">");
|
|
- mixer_have_old_focus = 1;
|
|
-}
|
|
-
|
|
-static void
|
|
-mixer_draw_frame (void)
|
|
-{
|
|
- char string[128];
|
|
- int i;
|
|
- int max_len;
|
|
-
|
|
- /* card name
|
|
- */
|
|
- mixer_dc (DC_PROMPT);
|
|
- mvaddstr (1, 2, "Card: ");
|
|
- mixer_dc (DC_TEXT);
|
|
- sprintf (string, "%s", mixer_card_name);
|
|
- max_len = mixer_max_x - 2 - 6 - 2;
|
|
- if ((int)strlen (string) > max_len)
|
|
- string[max_len] = 0;
|
|
- addstr (string);
|
|
-
|
|
- /* device name
|
|
- */
|
|
- mixer_dc (DC_PROMPT);
|
|
- mvaddstr (2, 2, "Chip: ");
|
|
- mixer_dc (DC_TEXT);
|
|
- sprintf (string, "%s", mixer_device_name);
|
|
- max_len = mixer_max_x - 2 - 6 - 2;
|
|
- if ((int)strlen (string) > max_len)
|
|
- string[max_len] = 0;
|
|
- addstr (string);
|
|
-
|
|
- /* lines
|
|
- */
|
|
- mixer_dc (DC_FRAME);
|
|
- for (i = 1; i < mixer_max_y - 1; i++)
|
|
- {
|
|
- mvaddch (i, 0, ACS_VLINE);
|
|
- mvaddch (i, mixer_max_x - 1, ACS_VLINE);
|
|
- }
|
|
- for (i = 1; i < mixer_max_x - 1; i++)
|
|
- {
|
|
- mvaddch (0, i, ACS_HLINE);
|
|
- mvaddch (mixer_max_y - 1, i, ACS_HLINE);
|
|
- }
|
|
-
|
|
- /* corners
|
|
- */
|
|
- mvaddch (0, 0, ACS_ULCORNER);
|
|
- mvaddch (0, mixer_max_x - 1, ACS_URCORNER);
|
|
- mvaddch (mixer_max_y - 1, 0, ACS_LLCORNER);
|
|
- if (!mixer_no_lrcorner)
|
|
- mvaddch (mixer_max_y - 1, mixer_max_x - 1, ACS_LRCORNER);
|
|
- else
|
|
- {
|
|
- mvaddch (mixer_max_y - 2, mixer_max_x - 1, ACS_LRCORNER);
|
|
- mvaddch (mixer_max_y - 2, mixer_max_x - 2, ACS_ULCORNER);
|
|
- mvaddch (mixer_max_y - 1, mixer_max_x - 2, ACS_LRCORNER);
|
|
- }
|
|
-
|
|
- /* left/right scroll indicators */
|
|
- switch (mixer_view) {
|
|
- case VIEW_PLAYBACK:
|
|
- case VIEW_CAPTURE:
|
|
- case VIEW_CHANNELS:
|
|
- if (mixer_cbar_height > 0) {
|
|
- int ind_hgt = (mixer_cbar_height + 1) / 2;
|
|
- int ind_ofs = mixer_max_y / 2 - ind_hgt/2;
|
|
- /* left scroll possible? */
|
|
- if (mixer_first_vis_elem > 0) {
|
|
- for (i = 0; i < ind_hgt; i++)
|
|
- mvaddch (i + ind_ofs, 0, '<');
|
|
- }
|
|
- /* right scroll possible? */
|
|
- if (mixer_first_vis_elem + mixer_n_vis_elems < mixer_n_view_elems) {
|
|
- for (i = 0; i < ind_hgt; i++)
|
|
- mvaddch (i + ind_ofs, mixer_max_x - 1, '>');
|
|
- }
|
|
- }
|
|
- break;
|
|
- default:
|
|
- break;
|
|
- }
|
|
-
|
|
- /* program title
|
|
- */
|
|
- sprintf (string, "%s v%s (Press Escape to quit)", PRGNAME_UPPER, VERSION);
|
|
- max_len = strlen (string);
|
|
- if (mixer_max_x >= max_len + 4)
|
|
- {
|
|
- mixer_dc (DC_PROMPT);
|
|
- mvaddch (0, mixer_max_x / 2 - max_len / 2 - 1, '[');
|
|
- mvaddch (0, mixer_max_x / 2 - max_len / 2 + max_len, ']');
|
|
- }
|
|
- if (mixer_max_x >= max_len + 2)
|
|
- {
|
|
- mixer_dc (DC_TEXT);
|
|
- mvaddstr (0, mixer_max_x / 2 - max_len / 2, string);
|
|
- }
|
|
-}
|
|
-
|
|
-static char*
|
|
-mixer_offset_text (char **t,
|
|
- int col,
|
|
- int *length)
|
|
-{
|
|
- char *p = *t;
|
|
- char *r;
|
|
-
|
|
- while (*p && *p != '\n' && col--)
|
|
- p++;
|
|
- if (*p == '\n' || !*p)
|
|
- {
|
|
- if (*p == '\n')
|
|
- p++;
|
|
- *length = 0;
|
|
- *t = p;
|
|
- return p;
|
|
- }
|
|
-
|
|
- r = p;
|
|
- while (*r && *r != '\n' && (*length)--)
|
|
- r++;
|
|
-
|
|
- *length = r - p;
|
|
- while (*r && *r != '\n')
|
|
- r++;
|
|
- if (*r == '\n')
|
|
- r++;
|
|
- *t = r;
|
|
-
|
|
- return p;
|
|
-}
|
|
-
|
|
-static void
|
|
-mixer_show_text (char *title,
|
|
- char *text,
|
|
- int *xoffs,
|
|
- int *yoffs)
|
|
-{
|
|
- int tlines = 0, tcols = 0;
|
|
- float hscroll, vscroll;
|
|
- float hoffs, voffs;
|
|
- char *p, *text_offs = text;
|
|
- int x1, x2, y1, y2;
|
|
- int i, n, l, r;
|
|
- unsigned long block, stipple;
|
|
-
|
|
- /* coords
|
|
- */
|
|
- x1 = 2;
|
|
- x2 = mixer_max_x - 3;
|
|
- y1 = 4;
|
|
- y2 = mixer_max_y - 2;
|
|
-
|
|
- if ((y2 - y1) < 3 || (x2 - x1) < 3)
|
|
- return;
|
|
-
|
|
- /* text dimensions
|
|
- */
|
|
- l = 0;
|
|
- for (p = text; *p; p++)
|
|
- if (*p == '\n')
|
|
- {
|
|
- tlines++;
|
|
- tcols = MAX (l, tcols);
|
|
- l = 0;
|
|
- }
|
|
- else
|
|
- l++;
|
|
- tcols = MAX (l, tcols);
|
|
- if (p > text && *(p - 1) != '\n')
|
|
- tlines++;
|
|
-
|
|
- /* scroll areas / offsets
|
|
- */
|
|
- l = x2 - x1 - 2;
|
|
- if (l > tcols)
|
|
- {
|
|
- x1 += (l - tcols) / 2;
|
|
- x2 = x1 + tcols + 1;
|
|
- }
|
|
- if (mixer_hscroll_delta)
|
|
- {
|
|
- *xoffs += mixer_hscroll_delta;
|
|
- mixer_hscroll_delta = 0;
|
|
- if (*xoffs < 0)
|
|
- {
|
|
- *xoffs = 0;
|
|
- beep ();
|
|
- }
|
|
- else if (*xoffs > tcols - l - 1)
|
|
- {
|
|
- *xoffs = MAX (0, tcols - l - 1);
|
|
- beep ();
|
|
- }
|
|
- }
|
|
- if (tcols - l - 1 <= 0)
|
|
- {
|
|
- hscroll = 1;
|
|
- hoffs = 0;
|
|
- }
|
|
- else
|
|
- {
|
|
- hscroll = ((float) l) / tcols;
|
|
- hoffs = ((float) *xoffs) / (tcols - l - 1);
|
|
- }
|
|
-
|
|
- l = y2 - y1 - 2;
|
|
- if (l > tlines)
|
|
- {
|
|
- y1 += (l - tlines) / 2;
|
|
- y2 = y1 + tlines + 1;
|
|
- }
|
|
- if (mixer_vscroll_delta)
|
|
- {
|
|
- *yoffs += mixer_vscroll_delta;
|
|
- mixer_vscroll_delta = 0;
|
|
- if (*yoffs < 0)
|
|
- {
|
|
- *yoffs = 0;
|
|
- beep ();
|
|
- }
|
|
- else if (*yoffs > tlines - l - 1)
|
|
- {
|
|
- *yoffs = MAX (0, tlines - l - 1);
|
|
- beep ();
|
|
- }
|
|
- }
|
|
- if (tlines - l - 1 <= 0)
|
|
- {
|
|
- voffs = 0;
|
|
- vscroll = 1;
|
|
- }
|
|
- else
|
|
- {
|
|
- vscroll = ((float) l) / tlines;
|
|
- voffs = ((float) *yoffs) / (tlines - l - 1);
|
|
- }
|
|
-
|
|
- /* colors
|
|
- */
|
|
- mixer_dc (DC_ANY_4);
|
|
-
|
|
- /* corners
|
|
- */
|
|
- mvaddch (y2, x2, ACS_LRCORNER);
|
|
- mvaddch (y2, x1, ACS_LLCORNER);
|
|
- mvaddch (y1, x1, ACS_ULCORNER);
|
|
- mvaddch (y1, x2, ACS_URCORNER);
|
|
-
|
|
- /* left + upper border
|
|
- */
|
|
- for (i = y1 + 1; i < y2; i++)
|
|
- mvaddch (i, x1, ACS_VLINE);
|
|
- for (i = x1 + 1; i < x2; i++)
|
|
- mvaddch (y1, i, ACS_HLINE);
|
|
- if (title)
|
|
- {
|
|
- l = strlen (title);
|
|
- if (l <= x2 - x1 - 3)
|
|
- {
|
|
- mvaddch (y1, x1 + 1 + (x2 - x1 - l) / 2 - 1, '[');
|
|
- mvaddch (y1, x1 + 1 + (x2 - x1 - l) / 2 + l, ']');
|
|
- }
|
|
- if (l <= x2 - x1 - 1)
|
|
- {
|
|
- mixer_dc (DC_CBAR_LABEL);
|
|
- mvaddstr (y1, x1 + 1 + (x2 - x1 - l) / 2, title);
|
|
- }
|
|
- mixer_dc (DC_ANY_4);
|
|
- }
|
|
-
|
|
- stipple = ACS_CKBOARD;
|
|
- block = ACS_BLOCK;
|
|
- if (block == '#' && ACS_BOARD == '#')
|
|
- {
|
|
- block = stipple;
|
|
- stipple = ACS_BLOCK;
|
|
- }
|
|
-
|
|
- /* lower scroll border
|
|
- */
|
|
- l = x2 - x1 - 1;
|
|
- n = hscroll * l;
|
|
- r = (hoffs + 1.0 / (2 * (l - n - 1))) * (l - n - 1);
|
|
- for (i = 0; i < l; i++)
|
|
- mvaddch (y2, i + x1 + 1, hscroll >= 1 ? ACS_HLINE :
|
|
- i >= r && i <= r + n ? block : stipple);
|
|
-
|
|
- /* right scroll border
|
|
- */
|
|
- l = y2 - y1 - 1;
|
|
- n = vscroll * l;
|
|
- r = (voffs + 1.0 / (2 * (l - n - 1))) * (l - n - 1);
|
|
- for (i = 0; i < l; i++)
|
|
- mvaddch (i + y1 + 1, x2, vscroll >= 1 ? ACS_VLINE :
|
|
- i >= r && i <= r + n ? block : stipple);
|
|
-
|
|
- /* show text
|
|
- */
|
|
- x1++; y1++;
|
|
- for (i = 0; i < *yoffs; i++)
|
|
- {
|
|
- l = 0;
|
|
- mixer_offset_text (&text_offs, 0, &l);
|
|
- }
|
|
- for (i = y1; i < y2; i++)
|
|
- {
|
|
- l = x2 - x1;
|
|
- p = mixer_offset_text (&text_offs, *xoffs, &l);
|
|
- n = x1;
|
|
- while (l--)
|
|
- mvaddch (i, n++, *p++);
|
|
- while (n < x2)
|
|
- mvaddch (i, n++, ' ');
|
|
- }
|
|
-}
|
|
-
|
|
-struct vbuffer
|
|
-{
|
|
- char *buffer;
|
|
- int size;
|
|
- int len;
|
|
-};
|
|
-
|
|
-static void
|
|
-vbuffer_kill (struct vbuffer *vbuf)
|
|
-{
|
|
- if (vbuf->size)
|
|
- free (vbuf->buffer);
|
|
- vbuf->buffer = NULL;
|
|
- vbuf->size = 0;
|
|
- vbuf->len = 0;
|
|
-}
|
|
-
|
|
-#define vbuffer_append_string(vb,str) vbuffer_append (vb, str, strlen (str))
|
|
-static void
|
|
-vbuffer_append (struct vbuffer *vbuf,
|
|
- char *text,
|
|
- int len)
|
|
-{
|
|
- if (vbuf->size - vbuf->len <= len)
|
|
- {
|
|
- vbuf->size += len + 1;
|
|
- vbuf->buffer = realloc (vbuf->buffer, vbuf->size);
|
|
- }
|
|
- memcpy (vbuf->buffer + vbuf->len, text, len);
|
|
- vbuf->len += len;
|
|
- vbuf->buffer[vbuf->len] = 0;
|
|
-}
|
|
-
|
|
-static int
|
|
-vbuffer_append_file (struct vbuffer *vbuf,
|
|
- char *name)
|
|
-{
|
|
- int fd;
|
|
-
|
|
- fd = open (name, O_RDONLY);
|
|
- if (fd >= 0)
|
|
- {
|
|
- char buffer[1025];
|
|
- int l;
|
|
-
|
|
- do
|
|
- {
|
|
- l = read (fd, buffer, 1024);
|
|
-
|
|
- vbuffer_append (vbuf, buffer, MAX (0, l));
|
|
- }
|
|
- while (l > 0 || (l < 0 && (errno == EAGAIN || errno == EINTR)));
|
|
-
|
|
- close (fd);
|
|
-
|
|
- return 0;
|
|
- }
|
|
- else
|
|
- return 1;
|
|
-}
|
|
-
|
|
-static void
|
|
-mixer_show_procinfo (void)
|
|
-{
|
|
- struct vbuffer vbuf = { NULL, 0, 0 };
|
|
-
|
|
- vbuffer_append_string (&vbuf, "\n");
|
|
- vbuffer_append_string (&vbuf, "/proc/asound/version:\n");
|
|
- vbuffer_append_string (&vbuf, "====================\n");
|
|
- if (vbuffer_append_file (&vbuf, "/proc/asound/version"))
|
|
- {
|
|
- vbuffer_kill (&vbuf);
|
|
- mixer_procinfo_xoffs = mixer_procinfo_yoffs = 0;
|
|
- mixer_show_text ("/proc",
|
|
- " No /proc information available. ",
|
|
- &mixer_procinfo_xoffs, &mixer_procinfo_yoffs);
|
|
- return;
|
|
- }
|
|
- else
|
|
- vbuffer_append_file (&vbuf, "/proc/asound/meminfo");
|
|
-
|
|
- vbuffer_append_string (&vbuf, "\n");
|
|
- vbuffer_append_string (&vbuf, "/proc/asound/cards:\n");
|
|
- vbuffer_append_string (&vbuf, "===================\n");
|
|
- if (vbuffer_append_file (&vbuf, "/proc/asound/cards"))
|
|
- vbuffer_append_string (&vbuf, "No information available.\n");
|
|
-
|
|
- vbuffer_append_string (&vbuf, "\n");
|
|
- vbuffer_append_string (&vbuf, "/proc/asound/devices:\n");
|
|
- vbuffer_append_string (&vbuf, "=====================\n");
|
|
- if (vbuffer_append_file (&vbuf, "/proc/asound/devices"))
|
|
- vbuffer_append_string (&vbuf, "No information available.\n");
|
|
-
|
|
- vbuffer_append_string (&vbuf, "\n");
|
|
- vbuffer_append_string (&vbuf, "/proc/asound/oss/devices:\n");
|
|
- vbuffer_append_string (&vbuf, "=========================\n");
|
|
- if (vbuffer_append_file (&vbuf, "/proc/asound/oss/devices"))
|
|
- vbuffer_append_string (&vbuf, "No information available.\n");
|
|
-
|
|
- vbuffer_append_string (&vbuf, "\n");
|
|
- vbuffer_append_string (&vbuf, "/proc/asound/timers:\n");
|
|
- vbuffer_append_string (&vbuf, "====================\n");
|
|
- if (vbuffer_append_file (&vbuf, "/proc/asound/timers"))
|
|
- vbuffer_append_string (&vbuf, "No information available.\n");
|
|
-
|
|
- vbuffer_append_string (&vbuf, "\n");
|
|
- vbuffer_append_string (&vbuf, "/proc/asound/pcm:\n");
|
|
- vbuffer_append_string (&vbuf, "=================\n");
|
|
- if (vbuffer_append_file (&vbuf, "/proc/asound/pcm"))
|
|
- vbuffer_append_string (&vbuf, "No information available.\n");
|
|
-
|
|
- mixer_show_text ("/proc", vbuf.buffer,
|
|
- &mixer_procinfo_xoffs, &mixer_procinfo_yoffs);
|
|
- vbuffer_kill (&vbuf);
|
|
-}
|
|
-
|
|
-static int
|
|
-mixer_event (snd_mixer_t *mixer, unsigned int mask, snd_mixer_elem_t *elem)
|
|
-{
|
|
- mixer_changed_state = 1;
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static void
|
|
-mixer_init (void)
|
|
-{
|
|
- snd_ctl_card_info_t *hw_info;
|
|
- snd_ctl_t *ctl_handle;
|
|
- int err;
|
|
- snd_ctl_card_info_alloca(&hw_info);
|
|
-
|
|
- if ((err = snd_ctl_open (&ctl_handle, card_id, 0)) < 0)
|
|
- mixer_abort (ERR_OPEN, "snd_ctl_open", err);
|
|
- if ((err = snd_ctl_card_info (ctl_handle, hw_info)) < 0)
|
|
- mixer_abort (ERR_FCN, "snd_ctl_card_info", err);
|
|
- snd_ctl_close (ctl_handle);
|
|
- /* open mixer device
|
|
- */
|
|
- if ((err = snd_mixer_open (&mixer_handle, 0)) < 0)
|
|
- mixer_abort (ERR_FCN, "snd_mixer_open", err);
|
|
- if (mixer_level == 0 && (err = snd_mixer_attach (mixer_handle, card_id)) < 0)
|
|
- mixer_abort (ERR_FCN, "snd_mixer_attach", err);
|
|
- if ((err = snd_mixer_selem_register (mixer_handle, mixer_level > 0 ? &mixer_options : NULL, NULL)) < 0)
|
|
- mixer_abort (ERR_FCN, "snd_mixer_selem_register", err);
|
|
- snd_mixer_set_callback (mixer_handle, mixer_event);
|
|
- if ((err = snd_mixer_load (mixer_handle)) < 0)
|
|
- mixer_abort (ERR_FCN, "snd_mixer_load", err);
|
|
-
|
|
- /* setup global variables
|
|
- */
|
|
- strcpy(mixer_card_name, snd_ctl_card_info_get_name(hw_info));
|
|
- strcpy(mixer_device_name, snd_ctl_card_info_get_mixername(hw_info));
|
|
-}
|
|
-
|
|
-/* init mixer screen
|
|
- */
|
|
-static void
|
|
-recalc_screen_size (void)
|
|
-{
|
|
- getmaxyx (mixer_window, mixer_max_y, mixer_max_x);
|
|
- if (mixer_minimize)
|
|
- {
|
|
- mixer_max_x = MIXER_MIN_X;
|
|
- mixer_max_y = MIXER_MIN_Y;
|
|
- }
|
|
- mixer_ofs_x = 2 /* extra begin padding: */ + 1;
|
|
-
|
|
- /* required allocations */
|
|
- mixer_n_vis_elems = (mixer_max_x - mixer_ofs_x * 2 + 1) / 9;
|
|
- mixer_n_vis_elems = CLAMP (mixer_n_vis_elems, 1, mixer_n_view_elems);
|
|
- mixer_extra_space = mixer_max_x - mixer_ofs_x * 2 + 1 - mixer_n_vis_elems * 9;
|
|
- mixer_extra_space = MAX (0, mixer_extra_space / (mixer_n_vis_elems + 1));
|
|
- mixer_text_y = MIXER_TEXT_Y;
|
|
- if (mixer_view == VIEW_PLAYBACK || mixer_view == VIEW_CHANNELS)
|
|
- mixer_text_y += 2; /* row for mute switch */
|
|
- if (mixer_view == VIEW_CAPTURE || mixer_view == VIEW_CHANNELS)
|
|
- mixer_text_y++; /* row for capture switch */
|
|
- if (mixer_text_y + MIXER_CBAR_STD_HGT < mixer_max_y)
|
|
- mixer_cbar_height = MIXER_CBAR_STD_HGT + MAX (1, mixer_max_y - mixer_text_y - MIXER_CBAR_STD_HGT + 1) / 2;
|
|
- else
|
|
- mixer_cbar_height = MAX (1, mixer_max_y - mixer_text_y);
|
|
-}
|
|
-
|
|
-static void
|
|
-mixer_reinit (void)
|
|
-{
|
|
- snd_mixer_elem_t *elem;
|
|
- int idx, elem_index, i, j, selem_count;
|
|
- snd_mixer_selem_id_t *sid;
|
|
- snd_mixer_selem_id_t *focus_gid;
|
|
- int focus_type = -1;
|
|
- snd_mixer_selem_id_alloca(&focus_gid);
|
|
-
|
|
- if (!mixer_changed_state)
|
|
- return;
|
|
- if (mixer_sid) {
|
|
- snd_mixer_selem_id_copy(focus_gid, (snd_mixer_selem_id_t *)(((char *)mixer_sid) + snd_mixer_selem_id_sizeof() * mixer_grpidx[mixer_focus_elem]));
|
|
- focus_type = mixer_type[mixer_focus_elem] & MIXER_ELEM_TYPE_MASK;
|
|
- }
|
|
-__again:
|
|
- mixer_changed_state = 0;
|
|
- if (mixer_sid != NULL)
|
|
- free(mixer_sid);
|
|
- selem_count = snd_mixer_get_count(mixer_handle);
|
|
- mixer_sid = malloc(snd_mixer_selem_id_sizeof() * selem_count);
|
|
- if (mixer_sid == NULL)
|
|
- mixer_abort (ERR_FCN, "malloc", 0);
|
|
-
|
|
- mixer_n_selems = 0;
|
|
- for (elem = snd_mixer_first_elem(mixer_handle); elem; elem = snd_mixer_elem_next(elem)) {
|
|
- sid = (snd_mixer_selem_id_t *)(((char *)mixer_sid) + snd_mixer_selem_id_sizeof() * mixer_n_selems);
|
|
- if (mixer_changed_state)
|
|
- goto __again;
|
|
- if (!snd_mixer_selem_is_active(elem))
|
|
- continue;
|
|
- snd_mixer_selem_get_id(elem, sid);
|
|
- mixer_n_selems++;
|
|
- }
|
|
-
|
|
- mixer_n_elems = 0;
|
|
- for (idx = 0; idx < mixer_n_selems; idx++) {
|
|
- int nelems_added = 0;
|
|
- sid = (snd_mixer_selem_id_t *)(((char *)mixer_sid) + snd_mixer_selem_id_sizeof() * idx);
|
|
- if (mixer_changed_state)
|
|
- goto __again;
|
|
- elem = snd_mixer_find_selem(mixer_handle, sid);
|
|
- if (elem == NULL)
|
|
- CHECK_ABORT (ERR_FCN, "snd_mixer_find_selem()", -EINVAL);
|
|
- for (i = 0; i < MIXER_ELEM_CAPTURE; i++) {
|
|
- int ok;
|
|
- for (j = ok = 0; j < 2; j++) {
|
|
- if (mixer_changed_state)
|
|
- goto __again;
|
|
- if (snd_mixer_selem_has_playback_channel(elem, mixer_elem_chn[i][j]))
|
|
- ok++;
|
|
- }
|
|
- if (ok) {
|
|
- nelems_added++;
|
|
- mixer_n_elems++;
|
|
- }
|
|
- }
|
|
- if (snd_mixer_selem_has_capture_volume(elem) ||
|
|
- (nelems_added == 0 && snd_mixer_selem_has_capture_switch(elem)))
|
|
- mixer_n_elems++;
|
|
- }
|
|
-
|
|
- if (mixer_type)
|
|
- free(mixer_type);
|
|
- mixer_type = (int *)calloc(mixer_n_elems, sizeof(int));
|
|
- if (mixer_type == NULL)
|
|
- mixer_abort(ERR_FCN, "malloc", 0);
|
|
- if (mixer_grpidx)
|
|
- free(mixer_grpidx);
|
|
- mixer_grpidx = (int *)calloc(mixer_n_elems, sizeof(int));
|
|
- if (mixer_grpidx == NULL)
|
|
- mixer_abort(ERR_FCN, "malloc", 0);
|
|
- elem_index = 0;
|
|
- for (idx = 0; idx < mixer_n_selems; idx++) {
|
|
- int nelems_added = 0;
|
|
- sid = (snd_mixer_selem_id_t *)(((char *)mixer_sid) + snd_mixer_selem_id_sizeof() * idx);
|
|
- if (mixer_changed_state)
|
|
- goto __again;
|
|
- elem = snd_mixer_find_selem(mixer_handle, sid);
|
|
- if (elem == NULL)
|
|
- CHECK_ABORT (ERR_FCN, "snd_mixer_find_selem()", -EINVAL);
|
|
- if ( (mixer_view == VIEW_PLAYBACK) || (mixer_view == VIEW_CHANNELS) ) {
|
|
- for (i = MIXER_ELEM_FRONT; i <= MIXER_ELEM_SIDE; i++) {
|
|
- int ok;
|
|
- for (j = ok = 0; j < 2; j++) {
|
|
- if (mixer_changed_state)
|
|
- goto __again;
|
|
- if (snd_mixer_selem_has_playback_channel(elem, mixer_elem_chn[i][j]))
|
|
- ok++;
|
|
- }
|
|
- if (ok) {
|
|
- sid = (snd_mixer_selem_id_t *)(((char *)mixer_sid) + snd_mixer_selem_id_sizeof() * idx);
|
|
- mixer_grpidx[elem_index] = idx;
|
|
- if (snd_mixer_selem_is_enumerated(elem)) {
|
|
- if (mixer_view == VIEW_PLAYBACK &&
|
|
- snd_mixer_selem_is_enum_capture(elem))
|
|
- continue;
|
|
- mixer_type[elem_index] = MIXER_ELEM_ENUM;
|
|
- } else {
|
|
- mixer_type[elem_index] = i;
|
|
- if (i == 0 && snd_mixer_selem_has_playback_switch(elem))
|
|
- mixer_type[elem_index] |= MIXER_ELEM_MUTE_SWITCH;
|
|
- if (snd_mixer_selem_has_playback_volume(elem))
|
|
- mixer_type[elem_index] |= MIXER_ELEM_HAS_VOLUME;
|
|
- }
|
|
- if (mixer_view == VIEW_CHANNELS) {
|
|
- if (nelems_added == 0 &&
|
|
- ! snd_mixer_selem_has_capture_volume(elem) &&
|
|
- snd_mixer_selem_has_capture_switch(elem))
|
|
- mixer_type[elem_index] |= MIXER_ELEM_CAPTURE_SWITCH;
|
|
- }
|
|
- elem_index++;
|
|
- nelems_added++;
|
|
- if (elem_index >= mixer_n_elems)
|
|
- break;
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- if ( (mixer_view == VIEW_CAPTURE) || (mixer_view == VIEW_CHANNELS) ) {
|
|
- int do_add = 0;
|
|
- if (snd_mixer_selem_has_capture_volume(elem) &&
|
|
- (mixer_view == VIEW_CAPTURE || !snd_mixer_selem_has_common_volume(elem)))
|
|
- do_add = 1;
|
|
- if (!do_add &&
|
|
- (nelems_added == 0 && snd_mixer_selem_has_capture_switch(elem)) &&
|
|
- (mixer_view == VIEW_CAPTURE || !snd_mixer_selem_has_common_switch(elem)))
|
|
- do_add = 1;
|
|
- if (!do_add &&
|
|
- mixer_view == VIEW_CAPTURE && snd_mixer_selem_is_enum_capture(elem))
|
|
- do_add = 1;
|
|
-
|
|
- if (do_add) {
|
|
- mixer_grpidx[elem_index] = idx;
|
|
- if (snd_mixer_selem_is_enum_capture(elem))
|
|
- mixer_type[elem_index] = MIXER_ELEM_CAPTURE_ENUM;
|
|
- else {
|
|
- mixer_type[elem_index] = MIXER_ELEM_CAPTURE;
|
|
- if (nelems_added == 0 && snd_mixer_selem_has_capture_switch(elem))
|
|
- mixer_type[elem_index] |= MIXER_ELEM_CAPTURE_SWITCH;
|
|
- if (nelems_added)
|
|
- mixer_type[elem_index] |= MIXER_ELEM_CAPTURE_SUFFIX;
|
|
- if (snd_mixer_selem_has_capture_volume(elem))
|
|
- mixer_type[elem_index] |= MIXER_ELEM_HAS_VOLUME;
|
|
- }
|
|
- elem_index++;
|
|
- if (elem_index >= mixer_n_elems)
|
|
- break;
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- mixer_n_view_elems = elem_index;
|
|
- recalc_screen_size();
|
|
- mixer_focus_elem = 0;
|
|
- if (focus_type >= 0) {
|
|
- for (elem_index = 0; elem_index < mixer_n_view_elems; elem_index++) {
|
|
- sid = (snd_mixer_selem_id_t *)(((char *)mixer_sid) + snd_mixer_selem_id_sizeof() * mixer_grpidx[elem_index]);
|
|
- if (!strcmp(snd_mixer_selem_id_get_name(focus_gid),
|
|
- snd_mixer_selem_id_get_name(sid)) &&
|
|
- snd_mixer_selem_id_get_index(focus_gid) ==
|
|
- snd_mixer_selem_id_get_index(sid) &&
|
|
- (mixer_type[elem_index] & MIXER_ELEM_TYPE_MASK) == focus_type) {
|
|
- mixer_focus_elem = elem_index;
|
|
- break;
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- if (mixer_changed_state)
|
|
- goto __again;
|
|
-}
|
|
-
|
|
-static void
|
|
-mixer_init_window (void)
|
|
-{
|
|
- /* initialize ncurses
|
|
- */
|
|
- setlocale(LC_CTYPE, "");
|
|
- mixer_window = initscr ();
|
|
- curs_set (0); /* hide the cursor */
|
|
-
|
|
- mixer_no_lrcorner = tigetflag ("xenl") != 1 && tigetflag ("am") != 1;
|
|
-
|
|
- if (mixer_do_color)
|
|
- mixer_do_color = has_colors ();
|
|
- mixer_init_draw_contexts ();
|
|
-
|
|
- /* react on key presses
|
|
- */
|
|
- cbreak ();
|
|
- noecho ();
|
|
- leaveok (mixer_window, TRUE);
|
|
- keypad (mixer_window, TRUE);
|
|
- GETCH_BLOCK (1);
|
|
-
|
|
- recalc_screen_size();
|
|
-
|
|
- mixer_clear (TRUE);
|
|
-}
|
|
-
|
|
-static void
|
|
-mixer_resize (void)
|
|
-{
|
|
- struct winsize winsz = { 0, };
|
|
-
|
|
- mixer_needs_resize = 0;
|
|
-
|
|
- if (ioctl (fileno (stdout), TIOCGWINSZ, &winsz) >= 0 &&
|
|
- winsz.ws_row && winsz.ws_col)
|
|
- {
|
|
- keypad (mixer_window, FALSE);
|
|
- leaveok (mixer_window, FALSE);
|
|
-
|
|
- endwin ();
|
|
-
|
|
- mixer_max_x = MAX (2, winsz.ws_col);
|
|
- mixer_max_y = MAX (2, winsz.ws_row);
|
|
-
|
|
- /* humpf, i don't get it, if only the number of rows change,
|
|
- * ncurses will segfault shortly after (could trigger that with mc as well).
|
|
- */
|
|
- resizeterm (mixer_max_y + 1, mixer_max_x + 1);
|
|
- resizeterm (mixer_max_y, mixer_max_x);
|
|
-
|
|
- mixer_init_window ();
|
|
-
|
|
- if (mixer_max_x < MIXER_MIN_X ||
|
|
- mixer_max_y < MIXER_MIN_Y)
|
|
- beep (); // mixer_abort (ERR_WINSIZE, "");
|
|
-
|
|
- mixer_have_old_focus = 0;
|
|
- }
|
|
-}
|
|
-
|
|
-static void
|
|
-mixer_set_delta(int delta)
|
|
-{
|
|
- int grp;
|
|
-
|
|
- for (grp = 0; grp < 2; grp++)
|
|
- mixer_volume_delta[grp] = delta;
|
|
-}
|
|
-
|
|
-static void
|
|
-mixer_add_delta(int delta)
|
|
-{
|
|
- int grp;
|
|
-
|
|
- for (grp = 0; grp < 2; grp++)
|
|
- mixer_volume_delta[grp] += delta;
|
|
-}
|
|
-
|
|
-static int
|
|
-mixer_iteration (void)
|
|
-{
|
|
- int count, err;
|
|
- struct pollfd *fds;
|
|
- int finished = 0;
|
|
- int key = 0;
|
|
- int old_view;
|
|
- unsigned short revents;
|
|
-
|
|
- /* setup for select on stdin and the mixer fd */
|
|
- if ((count = snd_mixer_poll_descriptors_count(mixer_handle)) < 0)
|
|
- mixer_abort (ERR_FCN, "snd_mixer_poll_descriptors_count", count);
|
|
- fds = calloc(count + 1, sizeof(struct pollfd));
|
|
- if (fds == NULL)
|
|
- mixer_abort (ERR_FCN, "malloc", 0);
|
|
- fds->fd = fileno(stdin);
|
|
- fds->events = POLLIN;
|
|
- if ((err = snd_mixer_poll_descriptors(mixer_handle, fds + 1, count)) < 0)
|
|
- mixer_abort (ERR_FCN, "snd_mixer_poll_descriptors", err);
|
|
- if (err != count)
|
|
- mixer_abort (ERR_FCN, "snd_mixer_poll_descriptors (err != count)", 0);
|
|
-
|
|
- finished = poll(fds, count + 1, -1);
|
|
-
|
|
- /* don't abort on handled signals */
|
|
- if (finished < 0 && errno == EINTR)
|
|
- finished = 0;
|
|
- if (mixer_needs_resize)
|
|
- mixer_resize ();
|
|
-
|
|
- if (finished > 0) {
|
|
- if (fds->revents & POLLIN) {
|
|
- key = getch ();
|
|
- finished--;
|
|
- }
|
|
- } else {
|
|
- key = 0;
|
|
- }
|
|
-
|
|
- if (finished > 0) {
|
|
- if (snd_mixer_poll_descriptors_revents(mixer_handle, fds + 1, count, &revents) >= 0) {
|
|
- if (revents & POLLNVAL)
|
|
- mixer_abort (ERR_FCN, "snd_mixer_poll_descriptors (POLLNVAL)", 0);
|
|
- if (revents & POLLERR)
|
|
- mixer_abort (ERR_FCN, "snd_mixer_poll_descriptors (POLLERR)", 0);
|
|
- if (revents & POLLIN)
|
|
- snd_mixer_handle_events(mixer_handle);
|
|
- }
|
|
- }
|
|
-
|
|
- finished = 0;
|
|
- free(fds);
|
|
-
|
|
- old_view = mixer_view;
|
|
-
|
|
-#if 0 /* DISABLED: it's not so usefull rather annoying... */
|
|
- /* feature Escape prefixing for some keys */
|
|
- if (key == 27)
|
|
- {
|
|
- GETCH_BLOCK (0);
|
|
- key = getch ();
|
|
- GETCH_BLOCK (1);
|
|
- switch (key)
|
|
- {
|
|
- case 9: /* Tab */
|
|
- key = KEY_BTAB;
|
|
- break;
|
|
- default:
|
|
- key = 27;
|
|
- break;
|
|
- }
|
|
- }
|
|
-#endif /* DISABLED */
|
|
-
|
|
- /* general keys */
|
|
- switch (key)
|
|
- {
|
|
- case 0:
|
|
- /* ignore */
|
|
- break;
|
|
- case 27: /* Escape */
|
|
- case KEY_F (10):
|
|
- finished = 1;
|
|
- key = 0;
|
|
- break;
|
|
- case 13: /* Return */
|
|
- case 10: /* NewLine */
|
|
- if (mixer_view != mixer_view_saved) {
|
|
- mixer_view = mixer_view_saved;
|
|
- mixer_changed_state=1;
|
|
- mixer_reinit ();
|
|
- }
|
|
- key = 0;
|
|
- break;
|
|
- case 'h':
|
|
- case 'H':
|
|
- case '?':
|
|
- case KEY_F (1):
|
|
- mixer_view = VIEW_HELP;
|
|
- key = 0;
|
|
- break;
|
|
- case '/':
|
|
- case KEY_F (2):
|
|
- mixer_view = VIEW_PROCINFO;
|
|
- key = 0;
|
|
- break;
|
|
- case KEY_F (3):
|
|
- if (mixer_view == VIEW_PLAYBACK) {
|
|
- mixer_clear (FALSE);
|
|
- } else {
|
|
- mixer_view = mixer_view_saved = VIEW_PLAYBACK;
|
|
- mixer_changed_state=1;
|
|
- mixer_reinit ();
|
|
- }
|
|
- key = 0;
|
|
- break;
|
|
- case KEY_F (4):
|
|
- if (mixer_view == VIEW_CAPTURE) {
|
|
- mixer_clear (FALSE);
|
|
- } else {
|
|
- mixer_view = mixer_view_saved = VIEW_CAPTURE;
|
|
- mixer_changed_state=1;
|
|
- mixer_reinit ();
|
|
- }
|
|
- key = 0;
|
|
- break;
|
|
- case KEY_F (5):
|
|
- if (mixer_view == VIEW_CHANNELS) {
|
|
- mixer_clear (FALSE);
|
|
- } else {
|
|
- mixer_view = mixer_view_saved = VIEW_CHANNELS;
|
|
- mixer_changed_state=1;
|
|
- mixer_reinit ();
|
|
- }
|
|
- key = 0;
|
|
- break;
|
|
- case 9: /* Tab */
|
|
- if (mixer_view >= VIEW_CHANNELS && mixer_view <= VIEW_CAPTURE) {
|
|
- mixer_view = (mixer_view + 1) % 3 + VIEW_CHANNELS;
|
|
- mixer_view_saved = mixer_view;
|
|
- mixer_changed_state = 1;
|
|
- mixer_reinit ();
|
|
- key = 0;
|
|
- }
|
|
- break;
|
|
- case '\014':
|
|
- case 'L':
|
|
- case 'l':
|
|
- mixer_clear (TRUE);
|
|
- break;
|
|
- }
|
|
-
|
|
- if (key && (mixer_view == VIEW_HELP ||
|
|
- mixer_view == VIEW_PROCINFO))
|
|
- switch (key)
|
|
- {
|
|
- case 9: /* Tab */
|
|
- mixer_hscroll_delta += 8;
|
|
- break;
|
|
- case KEY_BTAB:
|
|
- mixer_hscroll_delta -= 8;
|
|
- break;
|
|
- case KEY_A1:
|
|
- mixer_hscroll_delta -= 1;
|
|
- mixer_vscroll_delta -= 1;
|
|
- break;
|
|
- case KEY_A3:
|
|
- mixer_hscroll_delta += 1;
|
|
- mixer_vscroll_delta -= 1;
|
|
- break;
|
|
- case KEY_C1:
|
|
- mixer_hscroll_delta -= 1;
|
|
- mixer_vscroll_delta += 1;
|
|
- break;
|
|
- case KEY_C3:
|
|
- mixer_hscroll_delta += 1;
|
|
- mixer_vscroll_delta += 1;
|
|
- break;
|
|
- case KEY_RIGHT:
|
|
- case 'n':
|
|
- mixer_hscroll_delta += 1;
|
|
- break;
|
|
- case KEY_LEFT:
|
|
- case 'p':
|
|
- mixer_hscroll_delta -= 1;
|
|
- break;
|
|
- case KEY_UP:
|
|
- case '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 <card: 0...7>] [-D <mixer device>] [-g] [-s] [-V <view>] [-a <abst>]\n", PRGNAME);
|
|
- return 1;
|
|
- case 'c':
|
|
- {
|
|
- int i = snd_card_get_index(optarg);
|
|
- if (i < 0 || i > 31) {
|
|
- fprintf (stderr, "wrong -c argument '%s'\n", optarg);
|
|
- mixer_abort (ERR_NONE, "", 0);
|
|
- }
|
|
- sprintf(card_id, "hw:%i", i);
|
|
- }
|
|
- break;
|
|
- case 'D':
|
|
- strncpy(card_id, optarg, sizeof(card_id));
|
|
- card_id[sizeof(card_id)-1] = '\0';
|
|
- break;
|
|
- case 'g':
|
|
- mixer_do_color = !mixer_do_color;
|
|
- break;
|
|
- case 's':
|
|
- mixer_minimize = 1;
|
|
- break;
|
|
- case 'V':
|
|
- if (*optarg == 'p' || *optarg == 'P')
|
|
- mixer_view = VIEW_PLAYBACK;
|
|
- else if (*optarg == 'c' || *optarg == 'C')
|
|
- mixer_view = VIEW_CAPTURE;
|
|
- else
|
|
- mixer_view = VIEW_CHANNELS;
|
|
- break;
|
|
- case 'a':
|
|
- mixer_level = 1;
|
|
- memset(&mixer_options, 0, sizeof(mixer_options));
|
|
- mixer_options.ver = 1;
|
|
- if (!strcmp(optarg, "none"))
|
|
- mixer_options.abstract = SND_MIXER_SABSTRACT_NONE;
|
|
- else if (!strcmp(optarg, "basic"))
|
|
- mixer_options.abstract = SND_MIXER_SABSTRACT_BASIC;
|
|
- else {
|
|
- fprintf(stderr, "Select correct abstraction level (none or basic)...\n");
|
|
- mixer_abort (ERR_NONE, "", 0);
|
|
- }
|
|
- break;
|
|
- }
|
|
- }
|
|
- while (opt > 0);
|
|
-
|
|
- mixer_options.device = card_id;
|
|
-
|
|
- /* initialize mixer
|
|
- */
|
|
- mixer_init ();
|
|
- mixer_reinit ();
|
|
-
|
|
- if (mixer_n_elems == 0) {
|
|
- fprintf(stderr, "No mixer elems found\n");
|
|
- mixer_abort (ERR_NONE, "", 0);
|
|
- }
|
|
-
|
|
- /* setup signal handlers
|
|
- */
|
|
- signal (SIGINT, mixer_signal_handler);
|
|
- signal (SIGTRAP, mixer_signal_handler);
|
|
- // signal (SIGABRT, mixer_signal_handler);
|
|
- signal (SIGQUIT, mixer_signal_handler);
|
|
- signal (SIGBUS, mixer_signal_handler);
|
|
- signal (SIGSEGV, mixer_signal_handler);
|
|
- signal (SIGPIPE, mixer_signal_handler);
|
|
- signal (SIGTERM, mixer_signal_handler);
|
|
-
|
|
- /* initialize ncurses
|
|
- */
|
|
- mixer_init_window ();
|
|
- if (mixer_max_x < MIXER_MIN_X ||
|
|
- mixer_max_y < MIXER_MIN_Y)
|
|
- beep (); // mixer_abort (ERR_WINSIZE, "");
|
|
-
|
|
- signal (SIGWINCH, (void*) mixer_winch);
|
|
-
|
|
- do
|
|
- {
|
|
- /* draw window upon every iteration */
|
|
- if (!mixer_needs_resize)
|
|
- {
|
|
- switch (mixer_view)
|
|
- {
|
|
- case VIEW_CHANNELS:
|
|
- case VIEW_PLAYBACK:
|
|
- case VIEW_CAPTURE:
|
|
- mixer_update_cbars ();
|
|
- break;
|
|
- case VIEW_HELP:
|
|
- mixer_show_text ("Help", mixer_help_text, &mixer_help_xoffs, &mixer_help_yoffs);
|
|
- break;
|
|
- case VIEW_PROCINFO:
|
|
- mixer_show_procinfo ();
|
|
- break;
|
|
- }
|
|
- mixer_draw_frame ();
|
|
- refresh ();
|
|
- }
|
|
- }
|
|
- while (!mixer_iteration ());
|
|
-
|
|
- mixer_abort (ERR_NONE, "", 0);
|
|
-}
|
|
diff --git a/alsamixer/card_select.c b/alsamixer/card_select.c
|
|
new file mode 100644
|
|
index 0000000..b473dcf
|
|
--- /dev/null
|
|
+++ b/alsamixer/card_select.c
|
|
@@ -0,0 +1,268 @@
|
|
+/*
|
|
+ * card_select.c - select a card by list or device name
|
|
+ * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
|
|
+ *
|
|
+ * This program is free software: you can redistribute it and/or modify
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
+ * the Free Software Foundation, either version 2 of the License, or
|
|
+ * (at your option) any later version.
|
|
+ *
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License
|
|
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
+ */
|
|
+
|
|
+#include "aconfig.h"
|
|
+#include <stdio.h>
|
|
+#include <stdlib.h>
|
|
+#include <assert.h>
|
|
+#include <alsa/asoundlib.h>
|
|
+#include <menu.h>
|
|
+#include "gettext_curses.h"
|
|
+#include "die.h"
|
|
+#include "mem.h"
|
|
+#include "utils.h"
|
|
+#include "colors.h"
|
|
+#include "widget.h"
|
|
+#include "mixer_widget.h"
|
|
+#include "device_name.h"
|
|
+#include "card_select.h"
|
|
+
|
|
+struct card {
|
|
+ struct card *next;
|
|
+ char *indexstr;
|
|
+ char *name;
|
|
+ char *device_name;
|
|
+};
|
|
+
|
|
+static struct widget list_widget;
|
|
+static struct card first_card;
|
|
+static ITEM **items;
|
|
+static MENU *menu;
|
|
+static ITEM *initial_item;
|
|
+
|
|
+static void on_key_enter(void)
|
|
+{
|
|
+ ITEM *item = current_item(menu);
|
|
+ if (item) {
|
|
+ struct card *card = item_userptr(item);
|
|
+ if (card->device_name) {
|
|
+ if (select_card_by_name(card->device_name))
|
|
+ list_widget.close();
|
|
+ } else {
|
|
+ create_device_name_form();
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+static void on_menu_key(int key)
|
|
+{
|
|
+ static const struct {
|
|
+ int key;
|
|
+ int request;
|
|
+ } key_map[] = {
|
|
+ { KEY_DOWN, REQ_DOWN_ITEM },
|
|
+ { KEY_UP, REQ_UP_ITEM },
|
|
+ { KEY_HOME, REQ_FIRST_ITEM },
|
|
+ { KEY_NPAGE, REQ_SCR_DPAGE },
|
|
+ { KEY_PPAGE, REQ_SCR_UPAGE },
|
|
+ { KEY_BEG, REQ_FIRST_ITEM },
|
|
+ { KEY_END, REQ_LAST_ITEM },
|
|
+ };
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(key_map); ++i)
|
|
+ if (key_map[i].key == key) {
|
|
+ menu_driver(menu, key_map[i].request);
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+
|
|
+static void on_handle_key(int key)
|
|
+{
|
|
+ switch (key) {
|
|
+ case 27:
|
|
+ case KEY_CANCEL:
|
|
+ case 'q':
|
|
+ case 'Q':
|
|
+ list_widget.close();
|
|
+ break;
|
|
+ case 10:
|
|
+ case 13:
|
|
+ case KEY_ENTER:
|
|
+ on_key_enter();
|
|
+ break;
|
|
+ default:
|
|
+ on_menu_key(key);
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+
|
|
+static bool create(void)
|
|
+{
|
|
+ int rows, columns;
|
|
+ const char *title;
|
|
+
|
|
+ if (screen_lines < 3 || screen_cols < 10) {
|
|
+ beep();
|
|
+ list_widget.close();
|
|
+ return FALSE;
|
|
+ }
|
|
+ scale_menu(menu, &rows, &columns);
|
|
+ rows += 2;
|
|
+ columns += 2;
|
|
+ if (rows > screen_lines)
|
|
+ rows = screen_lines;
|
|
+ if (columns > screen_cols)
|
|
+ columns = screen_cols;
|
|
+
|
|
+ widget_init(&list_widget, rows, columns, SCREEN_CENTER, SCREEN_CENTER,
|
|
+ attr_menu, WIDGET_BORDER | WIDGET_SUBWINDOW);
|
|
+
|
|
+ title = _("Sound Card");
|
|
+ mvwprintw(list_widget.window, 0, (columns - 2 - get_mbs_width(title)) / 2, " %s ", title);
|
|
+ set_menu_win(menu, list_widget.window);
|
|
+ set_menu_sub(menu, list_widget.subwindow);
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+static void on_window_size_changed(void)
|
|
+{
|
|
+ unpost_menu(menu);
|
|
+ if (!create())
|
|
+ return;
|
|
+ post_menu(menu);
|
|
+}
|
|
+
|
|
+static void on_close(void)
|
|
+{
|
|
+ unsigned int i;
|
|
+ struct card *card, *next_card;
|
|
+
|
|
+ unpost_menu(menu);
|
|
+ free_menu(menu);
|
|
+ for (i = 0; items[i]; ++i)
|
|
+ free_item(items[i]);
|
|
+ free(items);
|
|
+ for (card = first_card.next; card; card = next_card) {
|
|
+ next_card = card->next;
|
|
+ free(card->indexstr);
|
|
+ free(card->name);
|
|
+ free(card->device_name);
|
|
+ free(card);
|
|
+ }
|
|
+ widget_free(&list_widget);
|
|
+}
|
|
+
|
|
+void close_card_select_list(void)
|
|
+{
|
|
+ on_close();
|
|
+}
|
|
+
|
|
+static struct widget list_widget = {
|
|
+ .handle_key = on_handle_key,
|
|
+ .window_size_changed = on_window_size_changed,
|
|
+ .close = on_close,
|
|
+};
|
|
+
|
|
+static int get_cards(void)
|
|
+{
|
|
+ int count, number, err;
|
|
+ snd_ctl_t *ctl;
|
|
+ snd_ctl_card_info_t *info;
|
|
+ char buf[16];
|
|
+ struct card *card, *prev_card;
|
|
+
|
|
+ first_card.indexstr = "-";
|
|
+ first_card.name = _("(default)");
|
|
+ first_card.device_name = "default";
|
|
+ count = 1;
|
|
+
|
|
+ snd_ctl_card_info_alloca(&info);
|
|
+ prev_card = &first_card;
|
|
+ number = -1;
|
|
+ for (;;) {
|
|
+ err = snd_card_next(&number);
|
|
+ if (err < 0)
|
|
+ fatal_alsa_error(_("cannot enumerate sound cards"), err);
|
|
+ if (number < 0)
|
|
+ break;
|
|
+ sprintf(buf, "hw:%d", number);
|
|
+ err = snd_ctl_open(&ctl, buf, 0);
|
|
+ if (err < 0)
|
|
+ continue;
|
|
+ err = snd_ctl_card_info(ctl, info);
|
|
+ snd_ctl_close(ctl);
|
|
+ if (err < 0)
|
|
+ continue;
|
|
+ card = ccalloc(1, sizeof *card);
|
|
+ sprintf(buf, "%d", number);
|
|
+ card->indexstr = cstrdup(buf);
|
|
+ card->name = cstrdup(snd_ctl_card_info_get_name(info));
|
|
+ sprintf(buf, "hw:%d", number);
|
|
+ card->device_name = cstrdup(buf);
|
|
+ prev_card->next = card;
|
|
+ prev_card = card;
|
|
+ ++count;
|
|
+ }
|
|
+
|
|
+ card = ccalloc(1, sizeof *card);
|
|
+ card->indexstr = cstrdup(" ");
|
|
+ card->name = cstrdup(_("enter device name..."));
|
|
+ prev_card->next = card;
|
|
+ ++count;
|
|
+
|
|
+ return count;
|
|
+}
|
|
+
|
|
+static void create_list_items(int cards)
|
|
+{
|
|
+ int i;
|
|
+ struct card *card;
|
|
+ ITEM *item;
|
|
+
|
|
+ initial_item = NULL;
|
|
+ items = ccalloc(cards + 1, sizeof(ITEM*));
|
|
+ i = 0;
|
|
+ for (card = &first_card; card; card = card->next) {
|
|
+ item = new_item(card->indexstr, card->name);
|
|
+ if (!item)
|
|
+ fatal_error("cannot create menu item");
|
|
+ set_item_userptr(item, card);
|
|
+ items[i++] = item;
|
|
+ if (!initial_item &&
|
|
+ mixer_device_name &&
|
|
+ (!card->device_name ||
|
|
+ !strcmp(card->device_name, mixer_device_name)))
|
|
+ initial_item = item;
|
|
+ }
|
|
+ assert(i == cards);
|
|
+}
|
|
+
|
|
+void create_card_select_list(void)
|
|
+{
|
|
+ int cards;
|
|
+
|
|
+ cards = get_cards();
|
|
+ create_list_items(cards);
|
|
+
|
|
+ menu = new_menu(items);
|
|
+ if (!menu)
|
|
+ fatal_error("cannot create menu");
|
|
+ set_menu_fore(menu, attr_menu_selected);
|
|
+ set_menu_back(menu, attr_menu);
|
|
+ set_menu_mark(menu, NULL);
|
|
+ if (initial_item)
|
|
+ set_current_item(menu, initial_item);
|
|
+ set_menu_spacing(menu, 2, 1, 1);
|
|
+ menu_opts_on(menu, O_SHOWDESC);
|
|
+
|
|
+ if (!create())
|
|
+ return;
|
|
+
|
|
+ post_menu(menu);
|
|
+}
|
|
diff --git a/alsamixer/card_select.h b/alsamixer/card_select.h
|
|
new file mode 100644
|
|
index 0000000..4ba15fc
|
|
--- /dev/null
|
|
+++ b/alsamixer/card_select.h
|
|
@@ -0,0 +1,7 @@
|
|
+#ifndef CARD_SELECT_H_INCLUDED
|
|
+#define CARD_SELECT_H_INCLUDED
|
|
+
|
|
+void create_card_select_list(void);
|
|
+void close_card_select_list(void);
|
|
+
|
|
+#endif
|
|
diff --git a/alsamixer/cli.c b/alsamixer/cli.c
|
|
new file mode 100644
|
|
index 0000000..ab6255f
|
|
--- /dev/null
|
|
+++ b/alsamixer/cli.c
|
|
@@ -0,0 +1,135 @@
|
|
+/*
|
|
+ * alsamixer - curses mixer for the ALSA project
|
|
+ * Copyright (c) 1998,1999 Tim Janik <timj@gtk.org>
|
|
+ * Jaroslav Kysela <perex@perex.cz>
|
|
+ * Copyright (c) 2009 Clemens Ladisch <clemens@ladisch.de>
|
|
+ *
|
|
+ * This program is free software: you can redistribute it and/or modify
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
+ * the Free Software Foundation, either version 2 of the License, or
|
|
+ * (at your option) any later version.
|
|
+ *
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License
|
|
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
+ */
|
|
+
|
|
+#include "aconfig.h"
|
|
+#include <stdio.h>
|
|
+#include <stdlib.h>
|
|
+#include <locale.h>
|
|
+#include <getopt.h>
|
|
+#include <alsa/asoundlib.h>
|
|
+#include "gettext_curses.h"
|
|
+#include "mixer_widget.h"
|
|
+#include "mainloop.h"
|
|
+
|
|
+static int use_color = 1;
|
|
+static struct snd_mixer_selem_regopt selem_regopt = {
|
|
+ .ver = 1,
|
|
+ .abstract = SND_MIXER_SABSTRACT_NONE,
|
|
+ .device = "default",
|
|
+};
|
|
+
|
|
+static void show_help(void)
|
|
+{
|
|
+ puts(_("Usage: alsamixer [options]"));
|
|
+ puts(_("Useful options:\n"
|
|
+ " -h, --help this help\n"
|
|
+ " -c, --card=NUMBER sound card number or id\n"
|
|
+ " -D, --device=NAME mixer device name\n"
|
|
+ " -V, --view=MODE starting view mode: playback/capture/all"));
|
|
+ puts(_("Debugging options:\n"
|
|
+ " -g, --no-color toggle using of colors\n"
|
|
+ " -a, --abstraction=NAME mixer abstraction level: none/basic"));
|
|
+}
|
|
+
|
|
+static void parse_options(int argc, char *argv[])
|
|
+{
|
|
+ static const char short_options[] = "hc:D:V:gsa:";
|
|
+ static const struct option long_options[] = {
|
|
+ { .name = "help", .val = 'h' },
|
|
+ { .name = "card", .has_arg = 1, .val = 'c' },
|
|
+ { .name = "device", .has_arg = 1, .val = 'D' },
|
|
+ { .name = "view", .has_arg = 1, .val = 'V' },
|
|
+ { .name = "no-color", .val = 'g' },
|
|
+ { .name = "abstraction", .has_arg = 1, .val = 'a' },
|
|
+ { }
|
|
+ };
|
|
+ int option;
|
|
+ int card_index;
|
|
+ static char name_buf[16];
|
|
+
|
|
+ while ((option = getopt_long(argc, argv, short_options,
|
|
+ long_options, NULL)) != -1) {
|
|
+ switch (option) {
|
|
+ case '?':
|
|
+ case 'h':
|
|
+ show_help();
|
|
+ exit(EXIT_SUCCESS);
|
|
+ case 'c':
|
|
+ card_index = snd_card_get_index(optarg);
|
|
+ if (card_index < 0) {
|
|
+ fprintf(stderr, _("invalid card index: %s\n"), optarg);
|
|
+ goto fail;
|
|
+ }
|
|
+ sprintf(name_buf, "hw:%d", card_index);
|
|
+ selem_regopt.device = name_buf;
|
|
+ break;
|
|
+ case 'D':
|
|
+ selem_regopt.device = optarg;
|
|
+ break;
|
|
+ case 'V':
|
|
+ if (*optarg == 'p' || *optarg == 'P')
|
|
+ view_mode = VIEW_MODE_PLAYBACK;
|
|
+ else if (*optarg == 'c' || *optarg == 'C')
|
|
+ view_mode = VIEW_MODE_CAPTURE;
|
|
+ else
|
|
+ view_mode = VIEW_MODE_ALL;
|
|
+ break;
|
|
+ case 'g':
|
|
+ use_color = !use_color;
|
|
+ break;
|
|
+ case 'a':
|
|
+ if (!strcmp(optarg, "none"))
|
|
+ selem_regopt.abstract = SND_MIXER_SABSTRACT_NONE;
|
|
+ else if (!strcmp(optarg, "basic"))
|
|
+ selem_regopt.abstract = SND_MIXER_SABSTRACT_BASIC;
|
|
+ else {
|
|
+ fprintf(stderr, _("unknown abstraction level: %s\n"), optarg);
|
|
+ goto fail;
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ fprintf(stderr, _("unknown option: %c\n"), option);
|
|
+fail:
|
|
+ fputs(_("try `alsamixer --help' for more information\n"), stderr);
|
|
+ exit(EXIT_FAILURE);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+int main(int argc, char *argv[])
|
|
+{
|
|
+ setlocale(LC_ALL, "");
|
|
+#ifdef ENABLE_NLS_IN_CURSES
|
|
+ textdomain(PACKAGE);
|
|
+#endif
|
|
+
|
|
+ parse_options(argc, argv);
|
|
+
|
|
+ create_mixer_object(&selem_regopt);
|
|
+
|
|
+ initialize_curses(use_color);
|
|
+
|
|
+ create_mixer_widget();
|
|
+
|
|
+ mainloop();
|
|
+
|
|
+ shutdown();
|
|
+ return 0;
|
|
+}
|
|
diff --git a/alsamixer/colors.c b/alsamixer/colors.c
|
|
new file mode 100644
|
|
index 0000000..fcceb16
|
|
--- /dev/null
|
|
+++ b/alsamixer/colors.c
|
|
@@ -0,0 +1,119 @@
|
|
+/*
|
|
+ * colors.c - color and attribute definitions
|
|
+ * Copyright (c) 1998,1999 Tim Janik <timj@gtk.org>
|
|
+ * Jaroslav Kysela <perex@perex.cz>
|
|
+ * Copyright (c) 2009 Clemens Ladisch <clemens@ladisch.de>
|
|
+ *
|
|
+ * This program is free software: you can redistribute it and/or modify
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
+ * the Free Software Foundation, either version 2 of the License, or
|
|
+ * (at your option) any later version.
|
|
+ *
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License
|
|
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
+ */
|
|
+
|
|
+#include "aconfig.h"
|
|
+#include CURSESINC
|
|
+#include "colors.h"
|
|
+
|
|
+int attr_mixer_frame;
|
|
+int attr_mixer_text;
|
|
+int attr_mixer_active;
|
|
+int attr_ctl_frame;
|
|
+int attr_ctl_mute;
|
|
+int attr_ctl_nomute;
|
|
+int attr_ctl_capture;
|
|
+int attr_ctl_nocapture;
|
|
+int attr_ctl_label;
|
|
+int attr_ctl_label_focus;
|
|
+int attr_ctl_mark_focus;
|
|
+int attr_ctl_bar_lo;
|
|
+#ifdef TRICOLOR_VOLUME_BAR
|
|
+int attr_ctl_bar_mi;
|
|
+int attr_ctl_bar_hi;
|
|
+#endif
|
|
+int attr_ctl_inactive;
|
|
+int attr_ctl_label_inactive;
|
|
+int attr_errormsg;
|
|
+int attr_infomsg;
|
|
+int attr_textbox;
|
|
+int attr_textfield;
|
|
+int attr_menu;
|
|
+int attr_menu_selected;
|
|
+
|
|
+void init_colors(int use_color)
|
|
+{
|
|
+ if (!!has_colors() == !!use_color) {
|
|
+ start_color();
|
|
+
|
|
+ init_pair(1, COLOR_CYAN, COLOR_BLACK);
|
|
+ init_pair(2, COLOR_YELLOW, COLOR_BLACK);
|
|
+ init_pair(3, COLOR_WHITE, COLOR_GREEN);
|
|
+ init_pair(4, COLOR_RED, COLOR_BLACK);
|
|
+ init_pair(5, COLOR_WHITE, COLOR_BLACK);
|
|
+ init_pair(6, COLOR_WHITE, COLOR_BLUE);
|
|
+ init_pair(7, COLOR_RED, COLOR_BLUE);
|
|
+ init_pair(8, COLOR_GREEN, COLOR_GREEN);
|
|
+ init_pair(9, COLOR_WHITE, COLOR_RED);
|
|
+#ifdef TRICOLOR_VOLUME_BAR
|
|
+ init_pair(10, COLOR_WHITE, COLOR_WHITE);
|
|
+ init_pair(11, COLOR_RED, COLOR_RED);
|
|
+#endif
|
|
+
|
|
+ attr_mixer_frame = COLOR_PAIR(1);
|
|
+ attr_mixer_text = COLOR_PAIR(1);
|
|
+ attr_mixer_active = A_BOLD | COLOR_PAIR(2);
|
|
+ attr_ctl_frame = A_BOLD | COLOR_PAIR(1);
|
|
+ attr_ctl_mute = COLOR_PAIR(1);
|
|
+ attr_ctl_nomute = A_BOLD | COLOR_PAIR(3);
|
|
+ attr_ctl_capture = A_BOLD | COLOR_PAIR(4);
|
|
+ attr_ctl_nocapture = COLOR_PAIR(5);
|
|
+ attr_ctl_label = A_BOLD | COLOR_PAIR(6);
|
|
+ attr_ctl_label_focus = A_BOLD | COLOR_PAIR(7);
|
|
+ attr_ctl_mark_focus = A_BOLD | COLOR_PAIR(4);
|
|
+ attr_ctl_bar_lo = A_BOLD | COLOR_PAIR(8);
|
|
+#ifdef TRICOLOR_VOLUME_BAR
|
|
+ attr_ctl_bar_mi = A_BOLD | COLOR_PAIR(10);
|
|
+ attr_ctl_bar_hi = A_BOLD | COLOR_PAIR(11);
|
|
+#endif
|
|
+ attr_ctl_inactive = COLOR_PAIR(5);
|
|
+ attr_ctl_label_inactive = A_REVERSE | COLOR_PAIR(5);
|
|
+ attr_errormsg = A_BOLD | COLOR_PAIR(9);
|
|
+ attr_infomsg = A_BOLD | COLOR_PAIR(6);
|
|
+ attr_textbox = A_BOLD | COLOR_PAIR(6);
|
|
+ attr_textfield = A_REVERSE | COLOR_PAIR(5);
|
|
+ attr_menu = A_BOLD | COLOR_PAIR(6);
|
|
+ attr_menu_selected = A_REVERSE | COLOR_PAIR(6);
|
|
+ } else {
|
|
+ attr_mixer_frame = A_NORMAL;
|
|
+ attr_mixer_text = A_NORMAL;
|
|
+ attr_mixer_active = A_BOLD;
|
|
+ attr_ctl_frame = A_BOLD;
|
|
+ attr_ctl_mute = A_NORMAL;
|
|
+ attr_ctl_nomute = A_BOLD;
|
|
+ attr_ctl_capture = A_BOLD;
|
|
+ attr_ctl_nocapture = A_NORMAL;
|
|
+ attr_ctl_label = A_REVERSE;
|
|
+ attr_ctl_label_focus = A_REVERSE | A_BOLD;
|
|
+ attr_ctl_mark_focus = A_BOLD;
|
|
+ attr_ctl_bar_lo = A_BOLD;
|
|
+#ifdef TRICOLOR_VOLUME_BAR
|
|
+ attr_ctl_bar_mi = A_BOLD;
|
|
+ attr_ctl_bar_hi = A_BOLD;
|
|
+#endif
|
|
+ attr_ctl_inactive = A_NORMAL;
|
|
+ attr_ctl_label_inactive = A_REVERSE;
|
|
+ attr_errormsg = A_STANDOUT;
|
|
+ attr_infomsg = A_NORMAL;
|
|
+ attr_textbox = A_NORMAL;
|
|
+ attr_textfield = A_REVERSE;
|
|
+ attr_menu = A_NORMAL;
|
|
+ attr_menu_selected = A_REVERSE;
|
|
+ }
|
|
+}
|
|
diff --git a/alsamixer/colors.h b/alsamixer/colors.h
|
|
new file mode 100644
|
|
index 0000000..9396004
|
|
--- /dev/null
|
|
+++ b/alsamixer/colors.h
|
|
@@ -0,0 +1,33 @@
|
|
+#ifndef COLORS_H_INCLUDED
|
|
+#define COLORS_H_INCLUDED
|
|
+
|
|
+#define TRICOLOR_VOLUME_BAR
|
|
+
|
|
+extern int attr_mixer_frame;
|
|
+extern int attr_mixer_text;
|
|
+extern int attr_mixer_active;
|
|
+extern int attr_ctl_frame;
|
|
+extern int attr_ctl_mute;
|
|
+extern int attr_ctl_nomute;
|
|
+extern int attr_ctl_capture;
|
|
+extern int attr_ctl_nocapture;
|
|
+extern int attr_ctl_label;
|
|
+extern int attr_ctl_label_focus;
|
|
+extern int attr_ctl_mark_focus;
|
|
+extern int attr_ctl_bar_lo;
|
|
+#ifdef TRICOLOR_VOLUME_BAR
|
|
+extern int attr_ctl_bar_mi;
|
|
+extern int attr_ctl_bar_hi;
|
|
+#endif
|
|
+extern int attr_ctl_inactive;
|
|
+extern int attr_ctl_label_inactive;
|
|
+extern int attr_errormsg;
|
|
+extern int attr_infomsg;
|
|
+extern int attr_textbox;
|
|
+extern int attr_textfield;
|
|
+extern int attr_menu;
|
|
+extern int attr_menu_selected;
|
|
+
|
|
+void init_colors(int use_color);
|
|
+
|
|
+#endif
|
|
diff --git a/alsamixer/device_name.c b/alsamixer/device_name.c
|
|
new file mode 100644
|
|
index 0000000..c58e652
|
|
--- /dev/null
|
|
+++ b/alsamixer/device_name.c
|
|
@@ -0,0 +1,197 @@
|
|
+/*
|
|
+ * device_name_form.c - ask for sound control device name
|
|
+ * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
|
|
+ *
|
|
+ * This program is free software: you can redistribute it and/or modify
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
+ * the Free Software Foundation, either version 2 of the License, or
|
|
+ * (at your option) any later version.
|
|
+ *
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License
|
|
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
+ */
|
|
+
|
|
+#include "aconfig.h"
|
|
+#include <stdlib.h>
|
|
+#include <string.h>
|
|
+#include CURSESINC
|
|
+#include <form.h>
|
|
+#include "gettext_curses.h"
|
|
+#include "die.h"
|
|
+#include "mem.h"
|
|
+#include "utils.h"
|
|
+#include "colors.h"
|
|
+#include "widget.h"
|
|
+#include "mixer_widget.h"
|
|
+#include "card_select.h"
|
|
+#include "device_name.h"
|
|
+
|
|
+static struct widget form_widget;
|
|
+static FIELD *fields[3];
|
|
+static FORM *form;
|
|
+
|
|
+static char *dup_current_name(void)
|
|
+{
|
|
+ int rows, cols, max, i;
|
|
+ char *s;
|
|
+
|
|
+ if (form_driver(form, REQ_VALIDATION) == E_OK) {
|
|
+ dynamic_field_info(fields[1], &rows, &cols, &max);
|
|
+ s = ccalloc(1, cols + 1);
|
|
+ memcpy(s, field_buffer(fields[1], 0), cols);
|
|
+ for (i = strlen(s) - 1; i >= 0 && s[i] == ' '; --i)
|
|
+ s[i] = '\0';
|
|
+ return s;
|
|
+ } else {
|
|
+ return cstrdup("");
|
|
+ }
|
|
+}
|
|
+
|
|
+static void on_key_enter(void)
|
|
+{
|
|
+ char *s;
|
|
+ bool ok;
|
|
+
|
|
+ s = dup_current_name();
|
|
+ ok = select_card_by_name(s);
|
|
+ free(s);
|
|
+ if (ok) {
|
|
+ form_widget.close();
|
|
+ close_card_select_list();
|
|
+ }
|
|
+}
|
|
+
|
|
+static void on_form_key(int key)
|
|
+{
|
|
+ static const struct {
|
|
+ int key;
|
|
+ int request;
|
|
+ } key_map[] = {
|
|
+ { KEY_LEFT, REQ_PREV_CHAR },
|
|
+ { KEY_RIGHT, REQ_NEXT_CHAR },
|
|
+ { KEY_HOME, REQ_BEG_FIELD },
|
|
+ { KEY_BACKSPACE, REQ_DEL_PREV },
|
|
+ { KEY_DC, REQ_DEL_CHAR },
|
|
+ { KEY_BEG, REQ_BEG_FIELD },
|
|
+ { KEY_END, REQ_END_FIELD },
|
|
+ };
|
|
+ unsigned int i;
|
|
+
|
|
+ if (key >= 32 && key < 256) {
|
|
+ form_driver(form, key);
|
|
+ return;
|
|
+ }
|
|
+ for (i = 0; i < ARRAY_SIZE(key_map); ++i)
|
|
+ if (key_map[i].key == key) {
|
|
+ form_driver(form, key_map[i].request);
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+
|
|
+static void on_handle_key(int key)
|
|
+{
|
|
+ switch (key) {
|
|
+ case 27:
|
|
+ case KEY_CANCEL:
|
|
+ form_widget.close();
|
|
+ break;
|
|
+ case 10:
|
|
+ case 13:
|
|
+ case KEY_ENTER:
|
|
+ on_key_enter();
|
|
+ break;
|
|
+ default:
|
|
+ on_form_key(key);
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+
|
|
+static bool create(void)
|
|
+{
|
|
+ const char *title;
|
|
+
|
|
+ if (screen_lines < 6 || screen_cols < 36) {
|
|
+ form_widget.close();
|
|
+ beep();
|
|
+ return FALSE;
|
|
+ }
|
|
+ widget_init(&form_widget,
|
|
+ 6, 36, SCREEN_CENTER, SCREEN_CENTER,
|
|
+ attr_textbox, WIDGET_BORDER | WIDGET_SUBWINDOW | WIDGET_CURSOR_VISIBLE);
|
|
+ title = _("Sound Card");
|
|
+ mvwprintw(form_widget.window, 0, (36 - 2 - get_mbs_width(title)) / 2, " %s ", title);
|
|
+
|
|
+ set_form_win(form, form_widget.window);
|
|
+ set_form_sub(form, form_widget.subwindow);
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+static void on_window_size_changed(void)
|
|
+{
|
|
+ form_driver(form, REQ_VALIDATION); /* save field value */
|
|
+ unpost_form(form);
|
|
+
|
|
+ if (!create())
|
|
+ return;
|
|
+
|
|
+ /*
|
|
+ * This call fails because ncurses does not allow changing options of
|
|
+ * the current field, and we cannot change the current field because
|
|
+ * there is only one. The only way to make this work would be to throw
|
|
+ * away and recreate all fields.
|
|
+ */
|
|
+ field_opts_off(fields[1], O_BLANK);
|
|
+
|
|
+ post_form(form);
|
|
+}
|
|
+
|
|
+static void on_close(void)
|
|
+{
|
|
+ unpost_form(form);
|
|
+ free_form(form);
|
|
+ free_field(fields[0]);
|
|
+ free_field(fields[1]);
|
|
+ widget_free(&form_widget);
|
|
+}
|
|
+
|
|
+static struct widget form_widget = {
|
|
+ .handle_key = on_handle_key,
|
|
+ .window_size_changed = on_window_size_changed,
|
|
+ .close = on_close,
|
|
+};
|
|
+
|
|
+void create_device_name_form(void)
|
|
+{
|
|
+ fields[0] = new_field(1, 32, 1, 1, 0, 0);
|
|
+ if (!fields[0])
|
|
+ fatal_error("cannot create field");
|
|
+ field_opts_off(fields[0], O_ACTIVE);
|
|
+ field_opts_off(fields[0], O_EDIT);
|
|
+ set_field_fore(fields[0], attr_textbox);
|
|
+ set_field_back(fields[0], attr_textbox);
|
|
+ set_field_buffer(fields[0], 0, _("Device name:"));
|
|
+
|
|
+ fields[1] = new_field(1, 32, 2, 1, 0, 0);
|
|
+ if (!fields[1])
|
|
+ fatal_error("cannot create field");
|
|
+ field_opts_off(fields[1], O_AUTOSKIP);
|
|
+ field_opts_off(fields[1], O_NULLOK);
|
|
+ field_opts_off(fields[1], O_STATIC);
|
|
+ set_field_fore(fields[1], attr_textfield);
|
|
+ set_field_back(fields[1], attr_textfield);
|
|
+ set_field_buffer(fields[1], 0, mixer_device_name);
|
|
+
|
|
+ form = new_form(fields);
|
|
+ if (!form)
|
|
+ fatal_error("cannot create form");
|
|
+
|
|
+ if (!create())
|
|
+ return;
|
|
+
|
|
+ post_form(form);
|
|
+}
|
|
diff --git a/alsamixer/device_name.h b/alsamixer/device_name.h
|
|
new file mode 100644
|
|
index 0000000..f4a1f3f
|
|
--- /dev/null
|
|
+++ b/alsamixer/device_name.h
|
|
@@ -0,0 +1,6 @@
|
|
+#ifndef DEVICE_NAME_FORM_H_INCLUDED
|
|
+#define DEVICE_NAME_FORM_H_INCLUDED
|
|
+
|
|
+void create_device_name_form(void);
|
|
+
|
|
+#endif
|
|
diff --git a/alsamixer/die.c b/alsamixer/die.c
|
|
new file mode 100644
|
|
index 0000000..dcd8536
|
|
--- /dev/null
|
|
+++ b/alsamixer/die.c
|
|
@@ -0,0 +1,39 @@
|
|
+/*
|
|
+ * die.c - error handlers
|
|
+ * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
|
|
+ *
|
|
+ * This program is free software: you can redistribute it and/or modify
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
+ * the Free Software Foundation, either version 2 of the License, or
|
|
+ * (at your option) any later version.
|
|
+ *
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License
|
|
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
+ */
|
|
+
|
|
+#include "aconfig.h"
|
|
+#include <stdio.h>
|
|
+#include <stdlib.h>
|
|
+#include <alsa/asoundlib.h>
|
|
+#include "gettext_curses.h"
|
|
+#include "mainloop.h"
|
|
+#include "die.h"
|
|
+
|
|
+void fatal_error(const char *msg)
|
|
+{
|
|
+ shutdown();
|
|
+ fprintf(stderr, "%s\n", msg);
|
|
+ exit(EXIT_FAILURE);
|
|
+}
|
|
+
|
|
+void fatal_alsa_error(const char *msg, int err)
|
|
+{
|
|
+ shutdown();
|
|
+ fprintf(stderr, _("%s: %s\n"), msg, snd_strerror(err));
|
|
+ exit(EXIT_FAILURE);
|
|
+}
|
|
diff --git a/alsamixer/die.h b/alsamixer/die.h
|
|
new file mode 100644
|
|
index 0000000..39ef1c0
|
|
--- /dev/null
|
|
+++ b/alsamixer/die.h
|
|
@@ -0,0 +1,7 @@
|
|
+#ifndef DIE_H_INCLUDED
|
|
+#define DIE_H_INCLUDED
|
|
+
|
|
+void fatal_error(const char *msg) __attribute__((__noreturn__));
|
|
+void fatal_alsa_error(const char *msg, int err) __attribute__((__noreturn__));
|
|
+
|
|
+#endif
|
|
diff --git a/alsamixer/mainloop.c b/alsamixer/mainloop.c
|
|
new file mode 100644
|
|
index 0000000..7a5ffdc
|
|
--- /dev/null
|
|
+++ b/alsamixer/mainloop.c
|
|
@@ -0,0 +1,135 @@
|
|
+/*
|
|
+ * mainloop.c - main loop
|
|
+ * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
|
|
+ *
|
|
+ * This program is free software: you can redistribute it and/or modify
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
+ * the Free Software Foundation, either version 2 of the License, or
|
|
+ * (at your option) any later version.
|
|
+ *
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License
|
|
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
+ */
|
|
+
|
|
+#include "aconfig.h"
|
|
+#include <stdio.h>
|
|
+#include <stdlib.h>
|
|
+#include <errno.h>
|
|
+#include <poll.h>
|
|
+#include <panel.h>
|
|
+#include <alsa/asoundlib.h>
|
|
+#include "mem.h"
|
|
+#include "die.h"
|
|
+#include "colors.h"
|
|
+#include "widget.h"
|
|
+#include "mixer_widget.h"
|
|
+#include "mixer_display.h"
|
|
+#include "mainloop.h"
|
|
+
|
|
+static WINDOW *curses_initialized;
|
|
+
|
|
+static void black_hole_error_handler(const char *file, int line,
|
|
+ const char *function, int err,
|
|
+ const char *fmt, ...)
|
|
+{
|
|
+}
|
|
+
|
|
+void initialize_curses(bool use_color)
|
|
+{
|
|
+ curses_initialized = initscr();
|
|
+ cbreak();
|
|
+ noecho();
|
|
+#ifdef 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 <clemens@ladisch.de>
|
|
+ *
|
|
+ * This program is free software: you can redistribute it and/or modify
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
+ * the Free Software Foundation, either version 2 of the License, or
|
|
+ * (at your option) any later version.
|
|
+ *
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License
|
|
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
+ */
|
|
+
|
|
+#define _GNU_SOURCE
|
|
+#include "aconfig.h"
|
|
+#include <stdio.h>
|
|
+#include <stdlib.h>
|
|
+#include <stdarg.h>
|
|
+#include <string.h>
|
|
+#include <errno.h>
|
|
+#include "die.h"
|
|
+#include "mem.h"
|
|
+
|
|
+static void check(void *p)
|
|
+{
|
|
+ if (!p)
|
|
+ fatal_error("out of memory");
|
|
+}
|
|
+
|
|
+void *ccalloc(size_t n, size_t size)
|
|
+{
|
|
+ void *mem = calloc(n, size);
|
|
+ if (n && size)
|
|
+ check(mem);
|
|
+ return mem;
|
|
+}
|
|
+
|
|
+void *crealloc(void *ptr, size_t new_size)
|
|
+{
|
|
+ ptr = realloc(ptr, new_size);
|
|
+ if (new_size)
|
|
+ check(ptr);
|
|
+ return ptr;
|
|
+}
|
|
+
|
|
+char *cstrdup(const char *s)
|
|
+{
|
|
+ char *str = strdup(s);
|
|
+ check(str);
|
|
+ return str;
|
|
+}
|
|
+
|
|
+char *casprintf(const char *fmt, ...)
|
|
+{
|
|
+ va_list ap;
|
|
+ char *str;
|
|
+
|
|
+ va_start(ap, fmt);
|
|
+ if (vasprintf(&str, fmt, ap) < 0)
|
|
+ check(NULL);
|
|
+ va_end(ap);
|
|
+ return str;
|
|
+}
|
|
diff --git a/alsamixer/mem.h b/alsamixer/mem.h
|
|
new file mode 100644
|
|
index 0000000..d0e5f54
|
|
--- /dev/null
|
|
+++ b/alsamixer/mem.h
|
|
@@ -0,0 +1,11 @@
|
|
+#ifndef MEM_H_INCLUDED
|
|
+#define MEM_H_INCLUDED
|
|
+
|
|
+#include <stddef.h>
|
|
+
|
|
+void *ccalloc(size_t n, size_t size);
|
|
+void *crealloc(void *ptr, size_t new_size);
|
|
+char *cstrdup(const char *s);
|
|
+char *casprintf(const char *fmt, ...) __attribute__((__format__(printf, 1, 2)));
|
|
+
|
|
+#endif
|
|
diff --git a/alsamixer/mixer_controls.c b/alsamixer/mixer_controls.c
|
|
new file mode 100644
|
|
index 0000000..796df7b
|
|
--- /dev/null
|
|
+++ b/alsamixer/mixer_controls.c
|
|
@@ -0,0 +1,521 @@
|
|
+/*
|
|
+ * mixer_controls.c - handles mixer controls and mapping from selems
|
|
+ * Copyright (c) 1998,1999 Tim Janik <timj@gtk.org>
|
|
+ * Jaroslav Kysela <perex@perex.cz>
|
|
+ * Copyright (c) 2009 Clemens Ladisch <clemens@ladisch.de>
|
|
+ *
|
|
+ * This program is free software: you can redistribute it and/or modify
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
+ * the Free Software Foundation, either version 2 of the License, or
|
|
+ * (at your option) any later version.
|
|
+ *
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License
|
|
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
+ */
|
|
+
|
|
+#include "aconfig.h"
|
|
+#include <stdlib.h>
|
|
+#include <string.h>
|
|
+#include <assert.h>
|
|
+#include CURSESINC
|
|
+#include <alsa/asoundlib.h>
|
|
+#include "utils.h"
|
|
+#include "mem.h"
|
|
+#include "mixer_display.h"
|
|
+#include "mixer_widget.h"
|
|
+#include "mixer_controls.h"
|
|
+
|
|
+struct control *controls;
|
|
+unsigned int controls_count;
|
|
+
|
|
+static const snd_mixer_selem_channel_id_t supported_channels[] = {
|
|
+ SND_MIXER_SCHN_FRONT_LEFT,
|
|
+ SND_MIXER_SCHN_FRONT_RIGHT,
|
|
+ SND_MIXER_SCHN_REAR_LEFT,
|
|
+ SND_MIXER_SCHN_REAR_RIGHT,
|
|
+ SND_MIXER_SCHN_FRONT_CENTER,
|
|
+ SND_MIXER_SCHN_WOOFER,
|
|
+ SND_MIXER_SCHN_SIDE_LEFT,
|
|
+ SND_MIXER_SCHN_SIDE_RIGHT,
|
|
+};
|
|
+#define LAST_SUPPORTED_CHANNEL SND_MIXER_SCHN_SIDE_RIGHT
|
|
+
|
|
+static const snd_mixer_selem_channel_id_t control_channels[][2] = {
|
|
+ { SND_MIXER_SCHN_FRONT_LEFT, SND_MIXER_SCHN_FRONT_RIGHT },
|
|
+ { SND_MIXER_SCHN_REAR_LEFT, SND_MIXER_SCHN_REAR_RIGHT },
|
|
+ { SND_MIXER_SCHN_FRONT_CENTER, SND_MIXER_SCHN_UNKNOWN },
|
|
+ { SND_MIXER_SCHN_WOOFER, SND_MIXER_SCHN_UNKNOWN },
|
|
+ { SND_MIXER_SCHN_SIDE_LEFT, SND_MIXER_SCHN_SIDE_RIGHT },
|
|
+};
|
|
+
|
|
+bool are_there_any_controls(void)
|
|
+{
|
|
+ snd_mixer_elem_t *elem;
|
|
+ unsigned int i;
|
|
+
|
|
+ for (elem = snd_mixer_first_elem(mixer);
|
|
+ elem;
|
|
+ elem = snd_mixer_elem_next(elem)) {
|
|
+ if (snd_mixer_elem_get_type(elem) != SND_MIXER_ELEM_SIMPLE)
|
|
+ continue;
|
|
+ if (snd_mixer_selem_is_enumerated(elem))
|
|
+ return TRUE;
|
|
+ if (snd_mixer_selem_has_playback_volume_joined(elem) ||
|
|
+ snd_mixer_selem_has_capture_volume_joined(elem) ||
|
|
+ snd_mixer_selem_has_playback_switch_joined(elem) ||
|
|
+ snd_mixer_selem_has_capture_switch_joined(elem))
|
|
+ return TRUE;
|
|
+ for (i = 0; i < ARRAY_SIZE(supported_channels); ++i)
|
|
+ if (snd_mixer_selem_has_playback_channel(elem, supported_channels[i]) ||
|
|
+ snd_mixer_selem_has_capture_channel(elem, supported_channels[i]))
|
|
+ return TRUE;
|
|
+ }
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
+static bool has_more_than_front_capture_channels(snd_mixer_elem_t *elem)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 2; i < ARRAY_SIZE(supported_channels); ++i)
|
|
+ if (snd_mixer_selem_has_capture_channel(elem, supported_channels[i]))
|
|
+ return TRUE;
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
+static bool has_any_control_channel(snd_mixer_elem_t *elem,
|
|
+ const snd_mixer_selem_channel_id_t channels[2],
|
|
+ int (*has_channel)(snd_mixer_elem_t *, snd_mixer_selem_channel_id_t))
|
|
+{
|
|
+ return has_channel(elem, channels[0]) ||
|
|
+ (channels[1] != SND_MIXER_SCHN_UNKNOWN && has_channel(elem, channels[1]));
|
|
+}
|
|
+
|
|
+static bool has_merged_cswitch(snd_mixer_elem_t *elem)
|
|
+{
|
|
+ bool pvol, psw;
|
|
+ unsigned int i;
|
|
+
|
|
+ pvol = snd_mixer_selem_has_playback_volume(elem);
|
|
+ psw = snd_mixer_selem_has_playback_switch(elem);
|
|
+ if ((pvol || psw) &&
|
|
+ snd_mixer_selem_has_capture_switch(elem) &&
|
|
+ !snd_mixer_selem_has_capture_volume(elem)) {
|
|
+ if (snd_mixer_selem_has_capture_switch_joined(elem))
|
|
+ return TRUE;
|
|
+ else if (((pvol && snd_mixer_selem_has_playback_volume_joined(elem)) ||
|
|
+ (psw && snd_mixer_selem_has_playback_switch_joined(elem))) &&
|
|
+ has_more_than_front_capture_channels(elem))
|
|
+ return FALSE;
|
|
+ for (i = 0; i < ARRAY_SIZE(control_channels); ++i) {
|
|
+ if (has_any_control_channel(elem, control_channels[i], snd_mixer_selem_has_capture_channel) &&
|
|
+ !has_any_control_channel(elem, control_channels[i], snd_mixer_selem_has_playback_channel))
|
|
+ return FALSE;
|
|
+ }
|
|
+ return TRUE;
|
|
+ }
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
+static unsigned int get_playback_controls_count(snd_mixer_elem_t *elem)
|
|
+{
|
|
+ unsigned int count = 0;
|
|
+ unsigned int i;
|
|
+ int has_vol, has_sw;
|
|
+
|
|
+ has_vol = snd_mixer_selem_has_playback_volume(elem);
|
|
+ has_sw = snd_mixer_selem_has_playback_switch(elem);
|
|
+ if (!has_vol && !has_sw)
|
|
+ return 0;
|
|
+ if ((!has_vol || snd_mixer_selem_has_playback_volume_joined(elem)) &&
|
|
+ (!has_sw || snd_mixer_selem_has_playback_switch_joined(elem)))
|
|
+ return 1;
|
|
+ for (i = 0; i < ARRAY_SIZE(control_channels); ++i) {
|
|
+ if (snd_mixer_selem_has_playback_channel(elem, control_channels[i][0]) ||
|
|
+ (control_channels[i][1] != SND_MIXER_SCHN_UNKNOWN &&
|
|
+ snd_mixer_selem_has_playback_channel(elem, control_channels[i][1])))
|
|
+ ++count;
|
|
+ }
|
|
+ return count;
|
|
+}
|
|
+
|
|
+static unsigned int get_capture_controls_count(snd_mixer_elem_t *elem)
|
|
+{
|
|
+ unsigned int count = 0;
|
|
+ unsigned int i;
|
|
+ int has_vol, has_sw;
|
|
+
|
|
+ has_vol = snd_mixer_selem_has_capture_volume(elem);
|
|
+ has_sw = snd_mixer_selem_has_capture_switch(elem);
|
|
+ if ((!has_vol && !has_sw) ||
|
|
+ (view_mode == VIEW_MODE_ALL && has_merged_cswitch(elem)))
|
|
+ return 0;
|
|
+ if ((!has_vol || snd_mixer_selem_has_capture_volume_joined(elem)) &&
|
|
+ (!has_sw || snd_mixer_selem_has_capture_switch_joined(elem)))
|
|
+ return 1;
|
|
+ for (i = 0; i < ARRAY_SIZE(control_channels); ++i) {
|
|
+ if (snd_mixer_selem_has_capture_channel(elem, control_channels[i][0]) ||
|
|
+ (control_channels[i][1] != SND_MIXER_SCHN_UNKNOWN &&
|
|
+ snd_mixer_selem_has_capture_channel(elem, control_channels[i][1])))
|
|
+ ++count;
|
|
+ }
|
|
+ return count;
|
|
+}
|
|
+
|
|
+static unsigned int get_controls_count_for_elem(snd_mixer_elem_t *elem)
|
|
+{
|
|
+ unsigned int p, c;
|
|
+
|
|
+ if (snd_mixer_elem_get_type(elem) != SND_MIXER_ELEM_SIMPLE)
|
|
+ return 0;
|
|
+ if (snd_mixer_selem_is_enumerated(elem)) {
|
|
+ switch (view_mode) {
|
|
+ case VIEW_MODE_PLAYBACK:
|
|
+ return snd_mixer_selem_is_enum_capture(elem) ? 0 : 1;
|
|
+ case VIEW_MODE_CAPTURE:
|
|
+ return snd_mixer_selem_is_enum_capture(elem) ? 1 : 0;
|
|
+ case VIEW_MODE_ALL:
|
|
+ default:
|
|
+ return 1;
|
|
+ }
|
|
+ }
|
|
+ switch (view_mode) {
|
|
+ case VIEW_MODE_PLAYBACK:
|
|
+ return get_playback_controls_count(elem);
|
|
+ case VIEW_MODE_CAPTURE:
|
|
+ return get_capture_controls_count(elem);
|
|
+ case VIEW_MODE_ALL:
|
|
+ default:
|
|
+ p = get_playback_controls_count(elem);
|
|
+ c = get_capture_controls_count(elem);
|
|
+ return has_merged_cswitch(elem) ? p : p + c;
|
|
+ }
|
|
+}
|
|
+
|
|
+static void create_name(struct control *control)
|
|
+{
|
|
+ unsigned int index;
|
|
+ char *s;
|
|
+
|
|
+ index = snd_mixer_selem_get_index(control->elem);
|
|
+ if (index > 0)
|
|
+ control->name = casprintf("%s %u", snd_mixer_selem_get_name(control->elem), index);
|
|
+ else
|
|
+ control->name = cstrdup(snd_mixer_selem_get_name(control->elem));
|
|
+
|
|
+ while ((s = strstr(control->name, "IEC958")) != NULL)
|
|
+ memcpy(s, "S/PDIF", 6);
|
|
+}
|
|
+
|
|
+static unsigned int create_controls_for_elem(snd_mixer_elem_t *elem, struct control *control)
|
|
+{
|
|
+ unsigned int count = 0;
|
|
+ unsigned int i;
|
|
+ unsigned int multich_flag;
|
|
+ unsigned int enum_index;
|
|
+ struct control *front_control = NULL;
|
|
+ bool has_pvol, has_psw;
|
|
+ bool has_cvol, has_csw;
|
|
+ bool has_channel[LAST_SUPPORTED_CHANNEL + 1];
|
|
+ bool merged_cswitch;
|
|
+ bool has_ch0, has_ch1;
|
|
+
|
|
+ if (snd_mixer_elem_get_type(elem) != SND_MIXER_ELEM_SIMPLE)
|
|
+ return 0;
|
|
+ if (snd_mixer_selem_is_enumerated(elem)) {
|
|
+ if ((view_mode == VIEW_MODE_PLAYBACK && snd_mixer_selem_is_enum_capture(elem)) ||
|
|
+ (view_mode == VIEW_MODE_CAPTURE && !snd_mixer_selem_is_enum_capture(elem)))
|
|
+ return 0;
|
|
+ control->elem = elem;
|
|
+ control->flags = TYPE_ENUM;
|
|
+ control->enum_channel_bits = 0;
|
|
+ for (i = 0; i <= SND_MIXER_SCHN_LAST; ++i)
|
|
+ if (snd_mixer_selem_get_enum_item(control->elem, (snd_mixer_selem_channel_id_t)i, &enum_index) >= 0)
|
|
+ control->enum_channel_bits |= 1 << i;
|
|
+ if (snd_mixer_selem_is_active(control->elem))
|
|
+ control->flags |= IS_ACTIVE;
|
|
+ create_name(control);
|
|
+ return 1;
|
|
+ }
|
|
+ has_pvol = snd_mixer_selem_has_playback_volume(elem);
|
|
+ has_psw = snd_mixer_selem_has_playback_switch(elem);
|
|
+ has_cvol = snd_mixer_selem_has_capture_volume(elem);
|
|
+ has_csw = snd_mixer_selem_has_capture_switch(elem);
|
|
+ merged_cswitch = view_mode == VIEW_MODE_ALL && has_merged_cswitch(elem);
|
|
+ if (view_mode != VIEW_MODE_CAPTURE && (has_pvol || has_psw)) {
|
|
+ if ((!has_pvol || snd_mixer_selem_has_playback_volume_joined(elem)) &&
|
|
+ (!has_psw || snd_mixer_selem_has_playback_switch_joined(elem))) {
|
|
+ control->elem = elem;
|
|
+ if (has_pvol) {
|
|
+ control->flags |= TYPE_PVOLUME | HAS_VOLUME_0;
|
|
+ control->volume_channels[0] = 0;
|
|
+ }
|
|
+ if (has_psw) {
|
|
+ control->flags |= TYPE_PSWITCH | HAS_PSWITCH_0;
|
|
+ control->pswitch_channels[0] = 0;
|
|
+ }
|
|
+ if (merged_cswitch) {
|
|
+ control->flags |= TYPE_CSWITCH;
|
|
+ if (snd_mixer_selem_has_capture_switch_joined(elem)) {
|
|
+ control->flags |= HAS_CSWITCH_0;
|
|
+ control->cswitch_channels[0] = 0;
|
|
+ } else {
|
|
+ if (snd_mixer_selem_has_capture_channel(elem, control_channels[0][0])) {
|
|
+ control->flags |= HAS_CSWITCH_0;
|
|
+ control->cswitch_channels[0] = control_channels[0][0];
|
|
+ }
|
|
+ if (control_channels[0][1] != SND_MIXER_SCHN_UNKNOWN &&
|
|
+ snd_mixer_selem_has_capture_channel(elem, control_channels[0][1])) {
|
|
+ control->flags |= HAS_CSWITCH_1;
|
|
+ control->cswitch_channels[1] = control_channels[0][1];
|
|
+ }
|
|
+ }
|
|
+ if ((control->flags & (HAS_CSWITCH_0 | HAS_CSWITCH_1)) == HAS_CSWITCH_1) {
|
|
+ control->flags ^= HAS_CSWITCH_0 | HAS_CSWITCH_1;
|
|
+ control->cswitch_channels[0] = control->cswitch_channels[1];
|
|
+ }
|
|
+ }
|
|
+ if (snd_mixer_selem_is_active(control->elem))
|
|
+ control->flags |= IS_ACTIVE;
|
|
+ create_name(control);
|
|
+ ++control;
|
|
+ ++count;
|
|
+ } else {
|
|
+ multich_flag = 0;
|
|
+ for (i = 0; i < ARRAY_SIZE(supported_channels); ++i)
|
|
+ has_channel[supported_channels[i]] =
|
|
+ snd_mixer_selem_has_playback_channel(elem, supported_channels[i]);
|
|
+ for (i = 0; i < ARRAY_SIZE(control_channels); ++i) {
|
|
+ has_ch0 = has_channel[control_channels[i][0]];
|
|
+ has_ch1 = control_channels[i][1] != SND_MIXER_SCHN_UNKNOWN &&
|
|
+ has_channel[control_channels[i][1]];
|
|
+ if (!has_ch0 && !has_ch1)
|
|
+ continue;
|
|
+ control->elem = elem;
|
|
+ if (has_pvol) {
|
|
+ control->flags |= TYPE_PVOLUME;
|
|
+ if (snd_mixer_selem_has_playback_volume_joined(elem)) {
|
|
+ control->flags |= HAS_VOLUME_0;
|
|
+ control->volume_channels[0] = 0;
|
|
+ } else {
|
|
+ if (has_ch0) {
|
|
+ control->flags |= HAS_VOLUME_0;
|
|
+ control->volume_channels[0] = control_channels[i][0];
|
|
+ }
|
|
+ if (has_ch1) {
|
|
+ control->flags |= HAS_VOLUME_1;
|
|
+ control->volume_channels[1] = control_channels[i][1];
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ if (has_psw) {
|
|
+ control->flags |= TYPE_PSWITCH;
|
|
+ if (snd_mixer_selem_has_playback_switch_joined(elem)) {
|
|
+ control->flags |= HAS_PSWITCH_0;
|
|
+ control->pswitch_channels[0] = 0;
|
|
+ } else {
|
|
+ if (has_ch0) {
|
|
+ control->flags |= HAS_PSWITCH_0;
|
|
+ control->pswitch_channels[0] = control_channels[i][0];
|
|
+ }
|
|
+ if (has_ch1) {
|
|
+ control->flags |= HAS_PSWITCH_1;
|
|
+ control->pswitch_channels[1] = control_channels[i][1];
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ if (merged_cswitch) {
|
|
+ control->flags |= TYPE_CSWITCH;
|
|
+ if (snd_mixer_selem_has_capture_switch_joined(elem)) {
|
|
+ control->flags |= HAS_CSWITCH_0;
|
|
+ control->cswitch_channels[0] = 0;
|
|
+ } else {
|
|
+ if (snd_mixer_selem_has_capture_channel(elem, control_channels[i][0])) {
|
|
+ control->flags |= HAS_CSWITCH_0;
|
|
+ control->cswitch_channels[0] = control_channels[i][0];
|
|
+ }
|
|
+ if (control_channels[i][1] != SND_MIXER_SCHN_UNKNOWN &&
|
|
+ snd_mixer_selem_has_capture_channel(elem, control_channels[i][1])) {
|
|
+ control->flags |= HAS_CSWITCH_1;
|
|
+ control->cswitch_channels[1] = control_channels[i][1];
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ if ((control->flags & (HAS_VOLUME_0 | HAS_VOLUME_1)) == HAS_VOLUME_1) {
|
|
+ control->flags ^= HAS_VOLUME_0 | HAS_VOLUME_1;
|
|
+ control->volume_channels[0] = control->volume_channels[1];
|
|
+ }
|
|
+ if ((control->flags & (HAS_PSWITCH_0 | HAS_PSWITCH_1)) == HAS_PSWITCH_1) {
|
|
+ control->flags ^= HAS_PSWITCH_0 | HAS_PSWITCH_1;
|
|
+ control->pswitch_channels[0] = control->pswitch_channels[1];
|
|
+ }
|
|
+ if ((control->flags & (HAS_CSWITCH_0 | HAS_CSWITCH_1)) == HAS_CSWITCH_1) {
|
|
+ control->flags ^= HAS_CSWITCH_0 | HAS_CSWITCH_1;
|
|
+ control->cswitch_channels[0] = control->cswitch_channels[1];
|
|
+ }
|
|
+ if (snd_mixer_selem_is_active(control->elem))
|
|
+ control->flags |= IS_ACTIVE;
|
|
+ create_name(control);
|
|
+ if (i == 0)
|
|
+ front_control = control;
|
|
+ else {
|
|
+ front_control->flags |= IS_MULTICH | 0;
|
|
+ control->flags |= IS_MULTICH | i;
|
|
+ }
|
|
+ ++control;
|
|
+ ++count;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ if (view_mode != VIEW_MODE_PLAYBACK && (has_cvol || has_csw) && !merged_cswitch) {
|
|
+ if ((!has_cvol || snd_mixer_selem_has_capture_volume_joined(elem)) &&
|
|
+ (!has_csw || snd_mixer_selem_has_capture_switch_joined(elem))) {
|
|
+ control->elem = elem;
|
|
+ if (has_cvol) {
|
|
+ control->flags |= TYPE_CVOLUME | HAS_VOLUME_0;
|
|
+ control->volume_channels[0] = 0;
|
|
+ }
|
|
+ if (has_csw) {
|
|
+ control->flags |= TYPE_CSWITCH | HAS_CSWITCH_0;
|
|
+ control->cswitch_channels[0] = 0;
|
|
+ }
|
|
+ if (snd_mixer_selem_is_active(control->elem))
|
|
+ control->flags |= IS_ACTIVE;
|
|
+ create_name(control);
|
|
+ ++control;
|
|
+ ++count;
|
|
+ } else {
|
|
+ for (i = 0; i < ARRAY_SIZE(supported_channels); ++i)
|
|
+ has_channel[supported_channels[i]] =
|
|
+ snd_mixer_selem_has_capture_channel(elem, supported_channels[i]);
|
|
+ for (i = 0; i < ARRAY_SIZE(control_channels); ++i) {
|
|
+ has_ch0 = has_channel[control_channels[i][0]];
|
|
+ has_ch1 = control_channels[i][1] != SND_MIXER_SCHN_UNKNOWN &&
|
|
+ has_channel[control_channels[i][1]];
|
|
+ if (!has_ch0 && !has_ch1)
|
|
+ continue;
|
|
+ control->elem = elem;
|
|
+ if (has_cvol) {
|
|
+ control->flags |= TYPE_CVOLUME;
|
|
+ if (snd_mixer_selem_has_capture_volume_joined(elem)) {
|
|
+ control->flags |= HAS_VOLUME_0;
|
|
+ control->volume_channels[0] = 0;
|
|
+ } else {
|
|
+ if (has_ch0) {
|
|
+ control->flags |= HAS_VOLUME_0;
|
|
+ control->volume_channels[0] = control_channels[i][0];
|
|
+ }
|
|
+ if (has_ch1) {
|
|
+ control->flags |= HAS_VOLUME_1;
|
|
+ control->volume_channels[1] = control_channels[i][1];
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ if (has_csw) {
|
|
+ control->flags |= TYPE_CSWITCH;
|
|
+ if (snd_mixer_selem_has_capture_switch_joined(elem)) {
|
|
+ control->flags |= HAS_CSWITCH_0;
|
|
+ control->cswitch_channels[0] = 0;
|
|
+ } else {
|
|
+ if (has_ch0) {
|
|
+ control->flags |= HAS_CSWITCH_0;
|
|
+ control->cswitch_channels[0] = control_channels[i][0];
|
|
+ }
|
|
+ if (has_ch1) {
|
|
+ control->flags |= HAS_CSWITCH_1;
|
|
+ control->cswitch_channels[1] = control_channels[i][1];
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ if ((control->flags & (HAS_VOLUME_0 | HAS_VOLUME_1)) == HAS_VOLUME_1) {
|
|
+ control->flags ^= HAS_VOLUME_0 | HAS_VOLUME_1;
|
|
+ control->volume_channels[0] = control->volume_channels[1];
|
|
+ }
|
|
+ if ((control->flags & (HAS_CSWITCH_0 | HAS_CSWITCH_1)) == HAS_CSWITCH_1) {
|
|
+ control->flags ^= HAS_CSWITCH_0 | HAS_CSWITCH_1;
|
|
+ control->cswitch_channels[0] = control->cswitch_channels[1];
|
|
+ }
|
|
+ if (snd_mixer_selem_is_active(control->elem))
|
|
+ control->flags |= IS_ACTIVE;
|
|
+ create_name(control);
|
|
+ if (i == 0)
|
|
+ front_control = control;
|
|
+ else {
|
|
+ front_control->flags |= IS_MULTICH | 0;
|
|
+ control->flags |= IS_MULTICH | i;
|
|
+ }
|
|
+ ++control;
|
|
+ ++count;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return count;
|
|
+}
|
|
+
|
|
+static void search_for_focus_control(void)
|
|
+{
|
|
+ snd_mixer_elem_t *elem;
|
|
+ unsigned int i;
|
|
+
|
|
+ elem = snd_mixer_find_selem(mixer, current_selem_id);
|
|
+ if (elem)
|
|
+ for (i = 0; i < controls_count; ++i)
|
|
+ if (controls[i].elem == elem) {
|
|
+ focus_control_index = i;
|
|
+ for (;;) {
|
|
+ ++i;
|
|
+ if (i >= controls_count || controls[i].elem != elem)
|
|
+ return;
|
|
+ if (controls[i].flags == current_control_flags) {
|
|
+ focus_control_index = i;
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ focus_control_index = 0;
|
|
+}
|
|
+
|
|
+void free_controls(void)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < controls_count; ++i)
|
|
+ free(controls[i].name);
|
|
+ free(controls);
|
|
+ controls = NULL;
|
|
+ controls_count = 0;
|
|
+}
|
|
+
|
|
+void create_controls(void)
|
|
+{
|
|
+ snd_mixer_elem_t *elem;
|
|
+ struct control *control;
|
|
+
|
|
+ free_controls();
|
|
+
|
|
+ for (elem = snd_mixer_first_elem(mixer);
|
|
+ elem;
|
|
+ elem = snd_mixer_elem_next(elem))
|
|
+ controls_count += get_controls_count_for_elem(elem);
|
|
+
|
|
+ if (controls_count > 0) {
|
|
+ controls = ccalloc(controls_count, sizeof *controls);
|
|
+ control = controls;
|
|
+ for (elem = snd_mixer_first_elem(mixer);
|
|
+ elem;
|
|
+ elem = snd_mixer_elem_next(elem))
|
|
+ control += create_controls_for_elem(elem, control);
|
|
+ assert(control == controls + controls_count);
|
|
+ }
|
|
+
|
|
+ compute_controls_layout();
|
|
+ display_view_mode();
|
|
+
|
|
+ search_for_focus_control();
|
|
+ refocus_control();
|
|
+}
|
|
diff --git a/alsamixer/mixer_controls.h b/alsamixer/mixer_controls.h
|
|
new file mode 100644
|
|
index 0000000..dbb3a9d
|
|
--- /dev/null
|
|
+++ b/alsamixer/mixer_controls.h
|
|
@@ -0,0 +1,37 @@
|
|
+#ifndef MIXER_CONTROLS_H_INCLUDED
|
|
+#define MIXER_CONTROLS_H_INCLUDED
|
|
+
|
|
+#include <alsa/asoundlib.h>
|
|
+
|
|
+struct control {
|
|
+ snd_mixer_elem_t *elem;
|
|
+ char *name;
|
|
+ unsigned int flags;
|
|
+#define TYPE_PVOLUME (1u << 4)
|
|
+#define TYPE_CVOLUME (1u << 5)
|
|
+#define TYPE_PSWITCH (1u << 6)
|
|
+#define TYPE_CSWITCH (1u << 7)
|
|
+#define TYPE_ENUM (1u << 8)
|
|
+#define HAS_VOLUME_0 (1u << 9)
|
|
+#define HAS_VOLUME_1 (1u << 10)
|
|
+#define HAS_PSWITCH_0 (1u << 11)
|
|
+#define HAS_PSWITCH_1 (1u << 12)
|
|
+#define HAS_CSWITCH_0 (1u << 13)
|
|
+#define HAS_CSWITCH_1 (1u << 14)
|
|
+#define IS_MULTICH (1u << 15)
|
|
+#define IS_ACTIVE (1u << 16)
|
|
+#define MULTICH_MASK (0x0000f)
|
|
+ snd_mixer_selem_channel_id_t volume_channels[2];
|
|
+ snd_mixer_selem_channel_id_t pswitch_channels[2];
|
|
+ snd_mixer_selem_channel_id_t cswitch_channels[2];
|
|
+ unsigned int enum_channel_bits;
|
|
+};
|
|
+
|
|
+extern struct control *controls;
|
|
+extern unsigned int controls_count;
|
|
+
|
|
+bool are_there_any_controls(void);
|
|
+void create_controls(void);
|
|
+void free_controls(void);
|
|
+
|
|
+#endif
|
|
diff --git a/alsamixer/mixer_display.c b/alsamixer/mixer_display.c
|
|
new file mode 100644
|
|
index 0000000..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 <clemens@ladisch.de>
|
|
+ *
|
|
+ * This program is free software: you can redistribute it and/or modify
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
+ * the Free Software Foundation, either version 2 of the License, or
|
|
+ * (at your option) any later version.
|
|
+ *
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License
|
|
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
+ */
|
|
+
|
|
+#include "aconfig.h"
|
|
+#include <stdlib.h>
|
|
+#include <string.h>
|
|
+#include <strings.h>
|
|
+#include CURSESINC
|
|
+#include <alsa/asoundlib.h>
|
|
+#include "gettext_curses.h"
|
|
+#include "utils.h"
|
|
+#include "mem.h"
|
|
+#include "colors.h"
|
|
+#include "widget.h"
|
|
+#include "mixer_widget.h"
|
|
+#include "mixer_controls.h"
|
|
+#include "mixer_display.h"
|
|
+
|
|
+enum align {
|
|
+ ALIGN_LEFT,
|
|
+ ALIGN_RIGHT,
|
|
+ ALIGN_CENTER,
|
|
+};
|
|
+
|
|
+static bool screen_too_small;
|
|
+static bool has_info_items;
|
|
+
|
|
+static int info_items_left;
|
|
+static int info_items_width;
|
|
+
|
|
+static int visible_controls;
|
|
+static int first_visible_control_index;
|
|
+static int first_control_x;
|
|
+static int control_width;
|
|
+static int control_name_width;
|
|
+
|
|
+static int base_y;
|
|
+static int volume_height;
|
|
+static int cswitch_y;
|
|
+static int values_y;
|
|
+static int name_y;
|
|
+static int channel_name_y;
|
|
+
|
|
+static void display_string_in_field(int y, int x, const char *s, int width, enum align align)
|
|
+{
|
|
+ int string_width;
|
|
+ const char *s_end;
|
|
+ int spaces;
|
|
+ int cur_y, cur_x;
|
|
+
|
|
+ wmove(mixer_widget.window, y, x);
|
|
+ string_width = width;
|
|
+ s_end = mbs_at_width(s, &string_width, -1);
|
|
+ if (string_width >= width) {
|
|
+ waddnstr(mixer_widget.window, s, s_end - s);
|
|
+ } else {
|
|
+ if (align != ALIGN_LEFT) {
|
|
+ spaces = width - string_width;
|
|
+ if (align == ALIGN_CENTER)
|
|
+ spaces /= 2;
|
|
+ if (spaces > 0)
|
|
+ wprintw(mixer_widget.window, "%*s", spaces, "");
|
|
+ }
|
|
+ waddstr(mixer_widget.window, s);
|
|
+ if (align != ALIGN_RIGHT) {
|
|
+ getyx(mixer_widget.window, cur_y, cur_x);
|
|
+ if (cur_y == y) {
|
|
+ spaces = x + width - cur_x;
|
|
+ if (spaces > 0)
|
|
+ wprintw(mixer_widget.window, "%*s", spaces, "");
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+void init_mixer_layout(void)
|
|
+{
|
|
+ const char *labels_left[4] = {
|
|
+ _("Card:"),
|
|
+ _("Chip:"),
|
|
+ _("View:"),
|
|
+ _("Item:"),
|
|
+ };
|
|
+ const char *labels_right[4] = {
|
|
+ _("F1: Help"),
|
|
+ _("F2: System information"),
|
|
+ _("F6: Select sound card"),
|
|
+ _("Esc: Exit"),
|
|
+ };
|
|
+ unsigned int label_width_left, label_width_right;
|
|
+ unsigned int right_x, i;
|
|
+
|
|
+ screen_too_small = screen_lines < 14 || screen_cols < 12;
|
|
+ has_info_items = screen_lines >= 6;
|
|
+ if (!has_info_items)
|
|
+ return;
|
|
+
|
|
+ label_width_left = get_max_mbs_width(labels_left, 4);
|
|
+ label_width_right = get_max_mbs_width(labels_right, 4);
|
|
+ if (2 + label_width_left + 1 + 28 + label_width_right + 2 > screen_cols)
|
|
+ label_width_right = 0;
|
|
+ if (2 + label_width_left + 1 + 28 + label_width_right + 2 > screen_cols)
|
|
+ label_width_left = 0;
|
|
+
|
|
+ info_items_left = label_width_left ? 3 + label_width_left : 2;
|
|
+ right_x = screen_cols - label_width_right - 2;
|
|
+ info_items_width = right_x - info_items_left;
|
|
+ if (info_items_width < 1) {
|
|
+ has_info_items = FALSE;
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ wattrset(mixer_widget.window, attr_mixer_text);
|
|
+ if (label_width_left)
|
|
+ for (i = 0; i < 4; ++i)
|
|
+ display_string_in_field(1 + i, 2, labels_left[i],
|
|
+ label_width_left, ALIGN_RIGHT);
|
|
+ if (label_width_right)
|
|
+ for (i = 0; i < 4; ++i)
|
|
+ display_string_in_field(1 + i, right_x, labels_right[i],
|
|
+ label_width_right, ALIGN_LEFT);
|
|
+}
|
|
+
|
|
+void display_card_info(void)
|
|
+{
|
|
+ snd_hctl_t *hctl;
|
|
+ snd_ctl_t *ctl;
|
|
+ snd_ctl_card_info_t *card_info;
|
|
+ const char *card_name = NULL;
|
|
+ const char *mixer_name = NULL;
|
|
+ int err;
|
|
+
|
|
+ if (!has_info_items)
|
|
+ return;
|
|
+
|
|
+ snd_ctl_card_info_alloca(&card_info);
|
|
+ if (mixer_device_name)
|
|
+ err = snd_mixer_get_hctl(mixer, mixer_device_name, &hctl);
|
|
+ else
|
|
+ err = -1;
|
|
+ if (err >= 0) {
|
|
+ ctl = snd_hctl_ctl(hctl);
|
|
+ err = snd_ctl_card_info(ctl, card_info);
|
|
+ if (err >= 0) {
|
|
+ card_name = snd_ctl_card_info_get_name(card_info);
|
|
+ mixer_name = snd_ctl_card_info_get_mixername(card_info);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (card_name)
|
|
+ wattrset(mixer_widget.window, attr_mixer_active);
|
|
+ else {
|
|
+ wattrset(mixer_widget.window, attr_mixer_text);
|
|
+ if (unplugged)
|
|
+ card_name = _("(unplugged)");
|
|
+ else
|
|
+ card_name = "-";
|
|
+ }
|
|
+ display_string_in_field(1, info_items_left, card_name, info_items_width, ALIGN_LEFT);
|
|
+
|
|
+ if (mixer_name)
|
|
+ wattrset(mixer_widget.window, attr_mixer_active);
|
|
+ else {
|
|
+ wattrset(mixer_widget.window, attr_mixer_text);
|
|
+ mixer_name = "-";
|
|
+ }
|
|
+ display_string_in_field(2, info_items_left, mixer_name, info_items_width, ALIGN_LEFT);
|
|
+}
|
|
+
|
|
+void display_view_mode(void)
|
|
+{
|
|
+ const char *modes[3] = {
|
|
+ _("Playback"),
|
|
+ _("Capture"),
|
|
+ _("All"),
|
|
+ };
|
|
+ unsigned int widths[3];
|
|
+ bool has_view_mode;
|
|
+ int i;
|
|
+
|
|
+ if (!has_info_items)
|
|
+ return;
|
|
+
|
|
+ has_view_mode = controls_count > 0 || are_there_any_controls();
|
|
+ for (i = 0; i < 3; ++i)
|
|
+ widths[i] = get_mbs_width(modes[i]);
|
|
+ if (4 + widths[0] + 6 + widths[1] + 6 + widths[2] + 1 <= info_items_width) {
|
|
+ wmove(mixer_widget.window, 3, info_items_left);
|
|
+ wattrset(mixer_widget.window, attr_mixer_text);
|
|
+ for (i = 0; i < 3; ++i) {
|
|
+ wprintw(mixer_widget.window, "F%c:", '3' + i);
|
|
+ if (has_view_mode && (int)view_mode == i) {
|
|
+ wattrset(mixer_widget.window, attr_mixer_active);
|
|
+ wprintw(mixer_widget.window, "[%s]", modes[i]);
|
|
+ wattrset(mixer_widget.window, attr_mixer_text);
|
|
+ } else {
|
|
+ wprintw(mixer_widget.window, " %s ", modes[i]);
|
|
+ }
|
|
+ if (i < 2)
|
|
+ waddch(mixer_widget.window, ' ');
|
|
+ }
|
|
+ } else {
|
|
+ wattrset(mixer_widget.window, attr_mixer_active);
|
|
+ display_string_in_field(3, info_items_left,
|
|
+ has_view_mode ? modes[view_mode] : "",
|
|
+ info_items_width, ALIGN_LEFT);
|
|
+ }
|
|
+}
|
|
+
|
|
+static char *format_gain(long db)
|
|
+{
|
|
+ if (db != SND_CTL_TLV_DB_GAIN_MUTE)
|
|
+ return casprintf("%.2f", db / 100.0);
|
|
+ else
|
|
+ return cstrdup(_("mute"));
|
|
+}
|
|
+
|
|
+static void display_focus_item_info(void)
|
|
+{
|
|
+ struct control *control;
|
|
+ unsigned int index;
|
|
+ char buf[64];
|
|
+ long db, db2;
|
|
+ int sw, sw2;
|
|
+ char *dbs, *dbs2;
|
|
+ char *value_info;
|
|
+ char *item_info;
|
|
+ int err;
|
|
+
|
|
+ if (!has_info_items)
|
|
+ return;
|
|
+ wattrset(mixer_widget.window, attr_mixer_active);
|
|
+ if (!controls_count || screen_too_small) {
|
|
+ display_string_in_field(4, info_items_left, "", info_items_width, ALIGN_LEFT);
|
|
+ return;
|
|
+ }
|
|
+ control = &controls[focus_control_index];
|
|
+ value_info = NULL;
|
|
+ if (control->flags & TYPE_ENUM) {
|
|
+ err = snd_mixer_selem_get_enum_item(control->elem, ffs(control->enum_channel_bits) - 1, &index);
|
|
+ if (err >= 0)
|
|
+ err = snd_mixer_selem_get_enum_item_name(control->elem, index, sizeof buf - 1, buf);
|
|
+ if (err >= 0)
|
|
+ value_info = casprintf(" [%s]", buf);
|
|
+ } else if (control->flags & (TYPE_PVOLUME | TYPE_CVOLUME)) {
|
|
+ int (*get_vol_func)(snd_mixer_elem_t *, snd_mixer_selem_channel_id_t, long *);
|
|
+
|
|
+ if (control->flags & TYPE_PVOLUME)
|
|
+ get_vol_func = snd_mixer_selem_get_playback_dB;
|
|
+ else
|
|
+ get_vol_func = snd_mixer_selem_get_capture_dB;
|
|
+ if (!(control->flags & HAS_VOLUME_1)) {
|
|
+ err = get_vol_func(control->elem, control->volume_channels[0], &db);
|
|
+ if (err >= 0) {
|
|
+ dbs = format_gain(db);
|
|
+ value_info = casprintf(" [%s %s]", _("dB gain:"), dbs);
|
|
+ free(dbs);
|
|
+ }
|
|
+ } else {
|
|
+ err = get_vol_func(control->elem, control->volume_channels[0], &db);
|
|
+ if (err >= 0)
|
|
+ err = get_vol_func(control->elem, control->volume_channels[1], &db2);
|
|
+ if (err >= 0) {
|
|
+ dbs = format_gain(db);
|
|
+ dbs2 = format_gain(db2);
|
|
+ value_info = casprintf(_(" [%s %s, %s]"), _("dB gain:"), dbs, dbs2);
|
|
+ free(dbs);
|
|
+ free(dbs2);
|
|
+ }
|
|
+ }
|
|
+ } else if (control->flags & TYPE_PSWITCH) {
|
|
+ if (!(control->flags & HAS_PSWITCH_1)) {
|
|
+ err = snd_mixer_selem_get_playback_switch(control->elem, control->pswitch_channels[0], &sw);
|
|
+ if (err >= 0 && !sw)
|
|
+ value_info = casprintf(" [%s]", _("Off"));
|
|
+ } else {
|
|
+ err = snd_mixer_selem_get_playback_switch(control->elem, control->pswitch_channels[0], &sw);
|
|
+ if (err >= 0)
|
|
+ err = snd_mixer_selem_get_playback_switch(control->elem, control->pswitch_channels[1], &sw2);
|
|
+ if (err >= 0 && (!sw || !sw2))
|
|
+ value_info = casprintf(" [%s, %s]", sw ? _("On") : _("Off"), sw2 ? _("On") : _("Off"));
|
|
+ }
|
|
+ } else if (control->flags & TYPE_CSWITCH) {
|
|
+ if (!(control->flags & HAS_CSWITCH_1)) {
|
|
+ err = snd_mixer_selem_get_capture_switch(control->elem, control->cswitch_channels[0], &sw);
|
|
+ if (err >= 0 && !sw)
|
|
+ value_info = casprintf(" [%s]", _("Off"));
|
|
+ } else {
|
|
+ err = snd_mixer_selem_get_capture_switch(control->elem, control->cswitch_channels[0], &sw);
|
|
+ if (err >= 0)
|
|
+ err = snd_mixer_selem_get_capture_switch(control->elem, control->cswitch_channels[1], &sw2);
|
|
+ if (err >= 0 && (!sw || !sw2))
|
|
+ value_info = casprintf(" [%s, %s]", sw ? _("On") : _("Off"), sw2 ? _("On") : _("Off"));
|
|
+ }
|
|
+ }
|
|
+ item_info = casprintf("%s%s", control->name, value_info ? value_info : "");
|
|
+ free(value_info);
|
|
+ display_string_in_field(4, info_items_left, item_info, info_items_width, ALIGN_LEFT);
|
|
+ free(item_info);
|
|
+}
|
|
+
|
|
+static void clear_controls_display(void)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ wattrset(mixer_widget.window, attr_mixer_frame);
|
|
+ for (i = 5; i < screen_lines - 1; ++i)
|
|
+ mvwprintw(mixer_widget.window, i, 1, "%*s", screen_cols - 2, "");
|
|
+}
|
|
+
|
|
+static void center_string(int line, const char *s)
|
|
+{
|
|
+ int width = get_mbs_width(s);
|
|
+ if (width <= screen_cols - 2)
|
|
+ mvwaddstr(mixer_widget.window, line, (screen_cols - width) / 2, s);
|
|
+}
|
|
+
|
|
+static void display_unplugged(void)
|
|
+{
|
|
+ int lines, top, left;
|
|
+ bool boojum;
|
|
+
|
|
+ lines = screen_lines - 6;
|
|
+ if (lines < 2)
|
|
+ return;
|
|
+ top = lines / 2;
|
|
+ boojum = lines >= 10 && screen_cols >= 48;
|
|
+ top -= boojum ? 5 : 1;
|
|
+ if (top < 5)
|
|
+ top = 5;
|
|
+ if (boojum) {
|
|
+ left = (screen_cols - 46) / 2;
|
|
+ wattrset(mixer_widget.window, attr_mixer_text);
|
|
+ mvwaddstr(mixer_widget.window, top + 0, left, "In the midst of the word he was trying to say,");
|
|
+ mvwaddstr(mixer_widget.window, top + 1, left + 2, "In the midst of his laughter and glee,");
|
|
+ mvwaddstr(mixer_widget.window, top + 2, left, "He had softly and suddenly vanished away---");
|
|
+ mvwaddstr(mixer_widget.window, top + 3, left + 2, "For the Snark was a Boojum, you see.");
|
|
+ mvwchgat(mixer_widget.window, top + 3, left + 16, 3, /* ^^^ */
|
|
+ attr_mixer_text | A_BOLD, PAIR_NUMBER(attr_mixer_text), NULL);
|
|
+ mvwaddstr(mixer_widget.window, top + 5, left, "(Lewis Carroll, \"The Hunting of the Snark\")");
|
|
+ top += 8;
|
|
+ }
|
|
+ wattrset(mixer_widget.window, attr_errormsg);
|
|
+ center_string(top, _("The sound device was unplugged."));
|
|
+ center_string(top + 1, _("Press F6 to select another sound card."));
|
|
+}
|
|
+
|
|
+static void display_no_controls(void)
|
|
+{
|
|
+ int y;
|
|
+ const char *msg;
|
|
+
|
|
+ y = (screen_lines - 6) / 2 - 1;
|
|
+ if (y < 5)
|
|
+ y = 5;
|
|
+ if (y >= screen_lines - 1)
|
|
+ return;
|
|
+ wattrset(mixer_widget.window, attr_infomsg);
|
|
+ if (view_mode == VIEW_MODE_PLAYBACK && are_there_any_controls())
|
|
+ msg = _("This sound device does not have any playback controls.");
|
|
+ else if (view_mode == VIEW_MODE_CAPTURE && are_there_any_controls())
|
|
+ msg = _("This sound device does not have any capture controls.");
|
|
+ else
|
|
+ msg = _("This sound device does not have any controls.");
|
|
+ center_string(y, msg);
|
|
+}
|
|
+
|
|
+static void display_string_centered_in_control(int y, int col, const char *s, int width)
|
|
+{
|
|
+ int left, x;
|
|
+
|
|
+ left = first_control_x + col * (control_width + 1);
|
|
+ x = left + (control_width - width) / 2;
|
|
+ display_string_in_field(y, x, s, width, ALIGN_CENTER);
|
|
+}
|
|
+
|
|
+static 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 <timj@gtk.org>
|
|
+ * Jaroslav Kysela <perex@perex.cz>
|
|
+ * Copyright (c) 2009 Clemens Ladisch <clemens@ladisch.de>
|
|
+ *
|
|
+ * This program is free software: you can redistribute it and/or modify
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
+ * the Free Software Foundation, either version 2 of the License, or
|
|
+ * (at your option) any later version.
|
|
+ *
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License
|
|
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
+ */
|
|
+
|
|
+#include "aconfig.h"
|
|
+#include <stdlib.h>
|
|
+#include <string.h>
|
|
+#include <errno.h>
|
|
+#include <alsa/asoundlib.h>
|
|
+#include "gettext_curses.h"
|
|
+#include "version.h"
|
|
+#include "utils.h"
|
|
+#include "die.h"
|
|
+#include "mem.h"
|
|
+#include "colors.h"
|
|
+#include "widget.h"
|
|
+#include "textbox.h"
|
|
+#include "proc_files.h"
|
|
+#include "card_select.h"
|
|
+#include "mixer_controls.h"
|
|
+#include "mixer_display.h"
|
|
+#include "mixer_widget.h"
|
|
+
|
|
+snd_mixer_t *mixer;
|
|
+char *mixer_device_name;
|
|
+bool unplugged;
|
|
+
|
|
+struct widget mixer_widget;
|
|
+
|
|
+enum view_mode view_mode;
|
|
+
|
|
+int focus_control_index;
|
|
+snd_mixer_selem_id_t *current_selem_id;
|
|
+unsigned int current_control_flags;
|
|
+
|
|
+bool controls_changed;
|
|
+
|
|
+enum channel_mask {
|
|
+ LEFT = 1,
|
|
+ RIGHT = 2,
|
|
+};
|
|
+
|
|
+static int elem_callback(snd_mixer_elem_t *elem, unsigned int mask)
|
|
+{
|
|
+ if (mask & (SND_CTL_EVENT_MASK_REMOVE |
|
|
+ SND_CTL_EVENT_MASK_INFO |
|
|
+ SND_CTL_EVENT_MASK_VALUE))
|
|
+ controls_changed = TRUE;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int mixer_callback(snd_mixer_t *mixer, unsigned int mask, snd_mixer_elem_t *elem)
|
|
+{
|
|
+ if (mask & SND_CTL_EVENT_MASK_ADD) {
|
|
+ snd_mixer_elem_set_callback(elem, elem_callback);
|
|
+ controls_changed = TRUE;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+void create_mixer_object(struct snd_mixer_selem_regopt *selem_regopt)
|
|
+{
|
|
+ int err;
|
|
+
|
|
+ err = snd_mixer_open(&mixer, 0);
|
|
+ if (err < 0)
|
|
+ fatal_alsa_error(_("cannot open mixer"), err);
|
|
+
|
|
+ mixer_device_name = cstrdup(selem_regopt->device);
|
|
+ err = snd_mixer_selem_register(mixer, selem_regopt, NULL);
|
|
+ if (err < 0)
|
|
+ fatal_alsa_error(_("cannot open mixer"), err);
|
|
+
|
|
+ snd_mixer_set_callback(mixer, mixer_callback);
|
|
+
|
|
+ err = snd_mixer_load(mixer);
|
|
+ if (err < 0)
|
|
+ fatal_alsa_error(_("cannot load mixer controls"), err);
|
|
+
|
|
+ err = snd_mixer_selem_id_malloc(¤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 <timj@gtk.org>"),
|
|
+ _(" Jaroslav Kysela <perex@perex.cz>"),
|
|
+ _(" Clemens Ladisch <clemens@ladisch.de>"),
|
|
+ };
|
|
+ show_text(help, ARRAY_SIZE(help), _("Help"));
|
|
+}
|
|
+
|
|
+void refocus_control(void)
|
|
+{
|
|
+ if (focus_control_index < controls_count) {
|
|
+ snd_mixer_selem_get_id(controls[focus_control_index].elem, current_selem_id);
|
|
+ current_control_flags = controls[focus_control_index].flags;
|
|
+ }
|
|
+
|
|
+ display_controls();
|
|
+}
|
|
+
|
|
+static struct control *get_focus_control(unsigned int type)
|
|
+{
|
|
+ if (focus_control_index >= 0 &&
|
|
+ focus_control_index < controls_count &&
|
|
+ (controls[focus_control_index].flags & IS_ACTIVE) &&
|
|
+ (controls[focus_control_index].flags & type))
|
|
+ return &controls[focus_control_index];
|
|
+ else
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+static void change_enum_to_percent(struct control *control, int value)
|
|
+{
|
|
+ unsigned int i;
|
|
+ unsigned int index;
|
|
+ unsigned int new_index;
|
|
+ int items;
|
|
+ int err;
|
|
+
|
|
+ i = ffs(control->enum_channel_bits) - 1;
|
|
+ err = snd_mixer_selem_get_enum_item(control->elem, i, &index);
|
|
+ if (err < 0)
|
|
+ return;
|
|
+ new_index = index;
|
|
+ if (value == 0) {
|
|
+ new_index = 0;
|
|
+ } else if (value == 100) {
|
|
+ items = snd_mixer_selem_get_enum_items(control->elem);
|
|
+ if (items < 1)
|
|
+ return;
|
|
+ new_index = items - 1;
|
|
+ }
|
|
+ if (new_index == index)
|
|
+ return;
|
|
+ for (i = 0; i <= SND_MIXER_SCHN_LAST; ++i)
|
|
+ if (control->enum_channel_bits & (1 << i))
|
|
+ snd_mixer_selem_set_enum_item(control->elem, i, new_index);
|
|
+}
|
|
+
|
|
+static void change_enum_relative(struct control *control, int delta)
|
|
+{
|
|
+ int items;
|
|
+ unsigned int i;
|
|
+ unsigned int index;
|
|
+ int new_index;
|
|
+ int err;
|
|
+
|
|
+ items = snd_mixer_selem_get_enum_items(control->elem);
|
|
+ if (items < 1)
|
|
+ return;
|
|
+ err = snd_mixer_selem_get_enum_item(control->elem, 0, &index);
|
|
+ if (err < 0)
|
|
+ return;
|
|
+ new_index = (int)index + delta;
|
|
+ if (new_index < 0)
|
|
+ new_index = 0;
|
|
+ else if (new_index >= items)
|
|
+ new_index = items - 1;
|
|
+ if (new_index == index)
|
|
+ return;
|
|
+ for (i = 0; i <= SND_MIXER_SCHN_LAST; ++i)
|
|
+ if (control->enum_channel_bits & (1 << i))
|
|
+ snd_mixer_selem_set_enum_item(control->elem, i, new_index);
|
|
+}
|
|
+
|
|
+static void change_volume_to_percent(struct control *control, int value, unsigned int channels)
|
|
+{
|
|
+ int (*get_range_func)(snd_mixer_elem_t *, long *, long *);
|
|
+ int (*set_func)(snd_mixer_elem_t *, snd_mixer_selem_channel_id_t, long);
|
|
+ long min, max;
|
|
+ int err;
|
|
+
|
|
+ if (!(control->flags & HAS_VOLUME_1))
|
|
+ channels = LEFT;
|
|
+ if (control->flags & TYPE_PVOLUME) {
|
|
+ get_range_func = snd_mixer_selem_get_playback_volume_range;
|
|
+ set_func = snd_mixer_selem_set_playback_volume;
|
|
+ } else {
|
|
+ get_range_func = snd_mixer_selem_get_capture_volume_range;
|
|
+ set_func = snd_mixer_selem_set_capture_volume;
|
|
+ }
|
|
+ err = get_range_func(control->elem, &min, &max);
|
|
+ if (err < 0)
|
|
+ return;
|
|
+ if (channels & LEFT)
|
|
+ set_func(control->elem, control->volume_channels[0], min + (max - min) * value / 100);
|
|
+ if (channels & RIGHT)
|
|
+ set_func(control->elem, control->volume_channels[1], min + (max - min) * value / 100);
|
|
+}
|
|
+
|
|
+static void change_volume_relative(struct control *control, int delta, unsigned int channels)
|
|
+{
|
|
+ int (*get_range_func)(snd_mixer_elem_t *, long *, long *);
|
|
+ int (*get_func)(snd_mixer_elem_t *, snd_mixer_selem_channel_id_t, long *);
|
|
+ int (*set_func)(snd_mixer_elem_t *, snd_mixer_selem_channel_id_t, long);
|
|
+ long min, max;
|
|
+ long left, right;
|
|
+ long value;
|
|
+ int err;
|
|
+
|
|
+ if (!(control->flags & HAS_VOLUME_1))
|
|
+ channels = LEFT;
|
|
+ if (control->flags & TYPE_PVOLUME) {
|
|
+ get_range_func = snd_mixer_selem_get_playback_volume_range;
|
|
+ get_func = snd_mixer_selem_get_playback_volume;
|
|
+ set_func = snd_mixer_selem_set_playback_volume;
|
|
+ } else {
|
|
+ get_range_func = snd_mixer_selem_get_capture_volume_range;
|
|
+ get_func = snd_mixer_selem_get_capture_volume;
|
|
+ set_func = snd_mixer_selem_set_capture_volume;
|
|
+ }
|
|
+ err = get_range_func(control->elem, &min, &max);
|
|
+ if (err < 0)
|
|
+ return;
|
|
+ if (channels & LEFT) {
|
|
+ err = get_func(control->elem, control->volume_channels[0], &left);
|
|
+ if (err < 0)
|
|
+ return;
|
|
+ }
|
|
+ if (channels & RIGHT) {
|
|
+ err = get_func(control->elem, control->volume_channels[1], &right);
|
|
+ if (err < 0)
|
|
+ return;
|
|
+ }
|
|
+ if (channels & LEFT) {
|
|
+ value = left + delta;
|
|
+ if (value < min)
|
|
+ value = min;
|
|
+ else if (value > max)
|
|
+ value = max;
|
|
+ if (value != left)
|
|
+ set_func(control->elem, control->volume_channels[0], value);
|
|
+ }
|
|
+ if (channels & RIGHT) {
|
|
+ value = right + delta;
|
|
+ if (value < min)
|
|
+ value = min;
|
|
+ else if (value > max)
|
|
+ value = max;
|
|
+ if (value != right)
|
|
+ set_func(control->elem, control->volume_channels[1], value);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void change_control_to_percent(int value, unsigned int channels)
|
|
+{
|
|
+ struct control *control;
|
|
+
|
|
+ control = get_focus_control(TYPE_PVOLUME | TYPE_CVOLUME | TYPE_ENUM);
|
|
+ if (!control)
|
|
+ return;
|
|
+ if (control->flags & TYPE_ENUM)
|
|
+ change_enum_to_percent(control, value);
|
|
+ else
|
|
+ change_volume_to_percent(control, value, channels);
|
|
+ display_controls();
|
|
+}
|
|
+
|
|
+static void change_control_relative(int delta, unsigned int channels)
|
|
+{
|
|
+ struct control *control;
|
|
+
|
|
+ control = get_focus_control(TYPE_PVOLUME | TYPE_CVOLUME | TYPE_ENUM);
|
|
+ if (!control)
|
|
+ return;
|
|
+ if (control->flags & TYPE_ENUM)
|
|
+ change_enum_relative(control, delta);
|
|
+ else
|
|
+ change_volume_relative(control, delta, channels);
|
|
+ display_controls();
|
|
+}
|
|
+
|
|
+static void toggle_switches(unsigned int type, unsigned int channels)
|
|
+{
|
|
+ struct control *control;
|
|
+ unsigned int switch_1_mask;
|
|
+ int (*get_func)(snd_mixer_elem_t *, snd_mixer_selem_channel_id_t, int *);
|
|
+ int (*set_func)(snd_mixer_elem_t *, snd_mixer_selem_channel_id_t, int);
|
|
+ snd_mixer_selem_channel_id_t channel_ids[2];
|
|
+ int left, right;
|
|
+ int err;
|
|
+
|
|
+ control = get_focus_control(type);
|
|
+ if (!control)
|
|
+ return;
|
|
+ if (type == TYPE_PSWITCH) {
|
|
+ switch_1_mask = HAS_PSWITCH_1;
|
|
+ get_func = snd_mixer_selem_get_playback_switch;
|
|
+ set_func = snd_mixer_selem_set_playback_switch;
|
|
+ channel_ids[0] = control->pswitch_channels[0];
|
|
+ channel_ids[1] = control->pswitch_channels[1];
|
|
+ } else {
|
|
+ switch_1_mask = HAS_CSWITCH_1;
|
|
+ get_func = snd_mixer_selem_get_capture_switch;
|
|
+ set_func = snd_mixer_selem_set_capture_switch;
|
|
+ channel_ids[0] = control->cswitch_channels[0];
|
|
+ channel_ids[1] = control->cswitch_channels[1];
|
|
+ }
|
|
+ if (!(control->flags & switch_1_mask))
|
|
+ channels = LEFT;
|
|
+ if (channels & LEFT) {
|
|
+ err = get_func(control->elem, channel_ids[0], &left);
|
|
+ if (err < 0)
|
|
+ return;
|
|
+ }
|
|
+ if (channels & RIGHT) {
|
|
+ err = get_func(control->elem, channel_ids[1], &right);
|
|
+ if (err < 0)
|
|
+ return;
|
|
+ }
|
|
+ if (channels & LEFT)
|
|
+ set_func(control->elem, channel_ids[0], !left);
|
|
+ if (channels & RIGHT)
|
|
+ set_func(control->elem, channel_ids[1], !right);
|
|
+ display_controls();
|
|
+}
|
|
+
|
|
+static void toggle_mute(unsigned int channels)
|
|
+{
|
|
+ toggle_switches(TYPE_PSWITCH, channels);
|
|
+}
|
|
+
|
|
+static void toggle_capture(unsigned int channels)
|
|
+{
|
|
+ toggle_switches(TYPE_CSWITCH, channels);
|
|
+}
|
|
+
|
|
+static void balance_volumes(void)
|
|
+{
|
|
+ struct control *control;
|
|
+ long left, right;
|
|
+ int err;
|
|
+
|
|
+ control = get_focus_control(TYPE_PVOLUME | TYPE_CVOLUME);
|
|
+ if (!control || !(control->flags & HAS_VOLUME_1))
|
|
+ return;
|
|
+ if (control->flags & TYPE_PVOLUME) {
|
|
+ err = snd_mixer_selem_get_playback_volume(control->elem, control->volume_channels[0], &left);
|
|
+ if (err < 0)
|
|
+ return;
|
|
+ err = snd_mixer_selem_get_playback_volume(control->elem, control->volume_channels[1], &right);
|
|
+ if (err < 0)
|
|
+ return;
|
|
+ } else {
|
|
+ err = snd_mixer_selem_get_capture_volume(control->elem, control->volume_channels[0], &left);
|
|
+ if (err < 0)
|
|
+ return;
|
|
+ err = snd_mixer_selem_get_capture_volume(control->elem, control->volume_channels[1], &right);
|
|
+ if (err < 0)
|
|
+ return;
|
|
+ }
|
|
+ left = (left + right) / 2;
|
|
+ if (control->flags & TYPE_PVOLUME) {
|
|
+ snd_mixer_selem_set_playback_volume(control->elem, control->volume_channels[0], left);
|
|
+ snd_mixer_selem_set_playback_volume(control->elem, control->volume_channels[1], left);
|
|
+ } else {
|
|
+ snd_mixer_selem_set_capture_volume(control->elem, control->volume_channels[0], left);
|
|
+ snd_mixer_selem_set_capture_volume(control->elem, control->volume_channels[1], left);
|
|
+ }
|
|
+ display_controls();
|
|
+}
|
|
+
|
|
+static void on_handle_key(int key)
|
|
+{
|
|
+ switch (key) {
|
|
+ case 27:
|
|
+ case KEY_CANCEL:
|
|
+ case KEY_F(10):
|
|
+ mixer_widget.close();
|
|
+ break;
|
|
+ case KEY_F(1):
|
|
+ case KEY_HELP:
|
|
+ case 'H':
|
|
+ case 'h':
|
|
+ case '?':
|
|
+ show_help();
|
|
+ break;
|
|
+ case KEY_F(2):
|
|
+ case '/':
|
|
+ create_proc_files_list();
|
|
+ break;
|
|
+ case KEY_F(3):
|
|
+ set_view_mode(VIEW_MODE_PLAYBACK);
|
|
+ break;
|
|
+ case KEY_F(4):
|
|
+ set_view_mode(VIEW_MODE_CAPTURE);
|
|
+ break;
|
|
+ case KEY_F(5):
|
|
+ set_view_mode(VIEW_MODE_ALL);
|
|
+ break;
|
|
+ case '\t':
|
|
+ set_view_mode((enum view_mode)((view_mode + 1) % VIEW_MODE_COUNT));
|
|
+ break;
|
|
+ case KEY_F(6):
|
|
+ case 'S':
|
|
+ case 's':
|
|
+ create_card_select_list();
|
|
+ break;
|
|
+ case KEY_REFRESH:
|
|
+ case 12:
|
|
+ case 'L':
|
|
+ case 'l':
|
|
+ clearok(mixer_widget.window, TRUE);
|
|
+ display_controls();
|
|
+ break;
|
|
+ case KEY_LEFT:
|
|
+ case 'P':
|
|
+ case 'p':
|
|
+ if (focus_control_index > 0) {
|
|
+ --focus_control_index;
|
|
+ refocus_control();
|
|
+ }
|
|
+ break;
|
|
+ case KEY_RIGHT:
|
|
+ case 'N':
|
|
+ case 'n':
|
|
+ if (focus_control_index < controls_count - 1) {
|
|
+ ++focus_control_index;
|
|
+ refocus_control();
|
|
+ }
|
|
+ break;
|
|
+ case KEY_PPAGE:
|
|
+ change_control_relative(5, LEFT | RIGHT);
|
|
+ break;
|
|
+ case KEY_NPAGE:
|
|
+ change_control_relative(-5, LEFT | RIGHT);
|
|
+ break;
|
|
+#if 0
|
|
+ case KEY_BEG:
|
|
+ case KEY_HOME:
|
|
+ change_control_to_percent(100, LEFT | RIGHT);
|
|
+ break;
|
|
+#endif
|
|
+ case KEY_LL:
|
|
+ case KEY_END:
|
|
+ change_control_to_percent(0, LEFT | RIGHT);
|
|
+ break;
|
|
+ case KEY_UP:
|
|
+ case '+':
|
|
+ case 'K':
|
|
+ case 'k':
|
|
+ case 'W':
|
|
+ case 'w':
|
|
+ change_control_relative(1, LEFT | RIGHT);
|
|
+ break;
|
|
+ case KEY_DOWN:
|
|
+ case '-':
|
|
+ case 'J':
|
|
+ case 'j':
|
|
+ case 'X':
|
|
+ case 'x':
|
|
+ change_control_relative(-1, LEFT | RIGHT);
|
|
+ break;
|
|
+ case '0': case '1': case '2': case '3': case '4':
|
|
+ case '5': case '6': case '7': case '8': case '9':
|
|
+ change_control_to_percent((key - '0') * 10, LEFT | RIGHT);
|
|
+ break;
|
|
+ case 'Q':
|
|
+ case 'q':
|
|
+ change_control_relative(1, LEFT);
|
|
+ break;
|
|
+ case 'Y':
|
|
+ case 'y':
|
|
+ case 'Z':
|
|
+ case 'z':
|
|
+ change_control_relative(-1, LEFT);
|
|
+ break;
|
|
+ case 'E':
|
|
+ case 'e':
|
|
+ change_control_relative(1, RIGHT);
|
|
+ break;
|
|
+ case 'C':
|
|
+ case 'c':
|
|
+ change_control_relative(-1, RIGHT);
|
|
+ break;
|
|
+ case 'M':
|
|
+ case 'm':
|
|
+ toggle_mute(LEFT | RIGHT);
|
|
+ break;
|
|
+ case 'B':
|
|
+ case 'b':
|
|
+ case '=':
|
|
+ balance_volumes();
|
|
+ break;
|
|
+ case '<':
|
|
+ case ',':
|
|
+ toggle_mute(LEFT);
|
|
+ break;
|
|
+ case '>':
|
|
+ case '.':
|
|
+ toggle_mute(RIGHT);
|
|
+ break;
|
|
+ case ' ':
|
|
+ toggle_capture(LEFT | RIGHT);
|
|
+ break;
|
|
+ case KEY_IC:
|
|
+ case ';':
|
|
+ toggle_capture(LEFT);
|
|
+ break;
|
|
+ case KEY_DC:
|
|
+ case '\'':
|
|
+ toggle_capture(RIGHT);
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+
|
|
+static void create(void)
|
|
+{
|
|
+ static const char title[] = " AlsaMixer v" SND_UTIL_VERSION_STR " ";
|
|
+
|
|
+ widget_init(&mixer_widget, screen_lines, screen_cols, 0, 0,
|
|
+ attr_mixer_frame, WIDGET_BORDER);
|
|
+ if (screen_cols >= (sizeof(title) - 1) + 2) {
|
|
+ wattrset(mixer_widget.window, attr_mixer_active);
|
|
+ mvwaddstr(mixer_widget.window, 0, (screen_cols - (sizeof(title) - 1)) / 2, title);
|
|
+ }
|
|
+ init_mixer_layout();
|
|
+ display_card_info();
|
|
+ set_view_mode(view_mode);
|
|
+}
|
|
+
|
|
+static void on_window_size_changed(void)
|
|
+{
|
|
+ create();
|
|
+}
|
|
+
|
|
+static void on_close(void)
|
|
+{
|
|
+ widget_free(&mixer_widget);
|
|
+}
|
|
+
|
|
+void mixer_shutdown(void)
|
|
+{
|
|
+ free_controls();
|
|
+ if (mixer)
|
|
+ snd_mixer_close(mixer);
|
|
+ if (current_selem_id)
|
|
+ snd_mixer_selem_id_free(current_selem_id);
|
|
+}
|
|
+
|
|
+struct widget mixer_widget = {
|
|
+ .handle_key = on_handle_key,
|
|
+ .window_size_changed = on_window_size_changed,
|
|
+ .close = on_close,
|
|
+};
|
|
+
|
|
+void create_mixer_widget(void)
|
|
+{
|
|
+ create();
|
|
+}
|
|
diff --git a/alsamixer/mixer_widget.h b/alsamixer/mixer_widget.h
|
|
new file mode 100644
|
|
index 0000000..da8628e
|
|
--- /dev/null
|
|
+++ b/alsamixer/mixer_widget.h
|
|
@@ -0,0 +1,36 @@
|
|
+#ifndef MIXER_WIDGET_H_INCLUDED
|
|
+#define MIXER_WIDGET_H_INCLUDED
|
|
+
|
|
+#include CURSESINC
|
|
+#include <alsa/asoundlib.h>
|
|
+#include "widget.h"
|
|
+
|
|
+enum view_mode {
|
|
+ VIEW_MODE_PLAYBACK,
|
|
+ VIEW_MODE_CAPTURE,
|
|
+ VIEW_MODE_ALL,
|
|
+ VIEW_MODE_COUNT,
|
|
+};
|
|
+
|
|
+extern snd_mixer_t *mixer;
|
|
+extern char *mixer_device_name;
|
|
+extern bool unplugged;
|
|
+
|
|
+extern struct widget mixer_widget;
|
|
+
|
|
+extern enum view_mode view_mode;
|
|
+
|
|
+extern int focus_control_index;
|
|
+extern snd_mixer_selem_id_t *current_selem_id;
|
|
+extern unsigned int current_control_flags;
|
|
+
|
|
+extern bool controls_changed;
|
|
+
|
|
+void create_mixer_object(struct snd_mixer_selem_regopt *selem_regopt);
|
|
+void create_mixer_widget(void);
|
|
+void mixer_shutdown(void);
|
|
+void close_mixer_device(void);
|
|
+bool select_card_by_name(const char *device_name);
|
|
+void refocus_control(void);
|
|
+
|
|
+#endif
|
|
diff --git a/alsamixer/proc_files.c b/alsamixer/proc_files.c
|
|
new file mode 100644
|
|
index 0000000..b2f5f21
|
|
--- /dev/null
|
|
+++ b/alsamixer/proc_files.c
|
|
@@ -0,0 +1,169 @@
|
|
+/*
|
|
+ * proc_files.c - shows ALSA system information files
|
|
+ * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
|
|
+ *
|
|
+ * This program is free software: you can redistribute it and/or modify
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
+ * the Free Software Foundation, either version 2 of the License, or
|
|
+ * (at your option) any later version.
|
|
+ *
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License
|
|
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
+ */
|
|
+
|
|
+#include "aconfig.h"
|
|
+#include <assert.h>
|
|
+#include <menu.h>
|
|
+#include <unistd.h>
|
|
+#include "gettext_curses.h"
|
|
+#include "utils.h"
|
|
+#include "die.h"
|
|
+#include "mem.h"
|
|
+#include "colors.h"
|
|
+#include "widget.h"
|
|
+#include "textbox.h"
|
|
+#include "proc_files.h"
|
|
+
|
|
+static struct widget proc_widget;
|
|
+static ITEM *items[7];
|
|
+static unsigned int items_count;
|
|
+static MENU *menu;
|
|
+
|
|
+static void on_menu_key(int key)
|
|
+{
|
|
+ static const struct {
|
|
+ int key;
|
|
+ int request;
|
|
+ } key_map[] = {
|
|
+ { KEY_DOWN, REQ_DOWN_ITEM },
|
|
+ { KEY_UP, REQ_UP_ITEM },
|
|
+ { KEY_HOME, REQ_FIRST_ITEM },
|
|
+ { KEY_NPAGE, REQ_SCR_DPAGE },
|
|
+ { KEY_PPAGE, REQ_SCR_UPAGE },
|
|
+ { KEY_BEG, REQ_FIRST_ITEM },
|
|
+ { KEY_END, REQ_LAST_ITEM },
|
|
+ };
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(key_map); ++i)
|
|
+ if (key_map[i].key == key) {
|
|
+ menu_driver(menu, key_map[i].request);
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+
|
|
+static void on_handle_key(int key)
|
|
+{
|
|
+ ITEM *item;
|
|
+
|
|
+ switch (key) {
|
|
+ case 27:
|
|
+ case KEY_CANCEL:
|
|
+ proc_widget.close();
|
|
+ break;
|
|
+ case 10:
|
|
+ case 13:
|
|
+ case KEY_ENTER:
|
|
+ item = current_item(menu);
|
|
+ if (item)
|
|
+ show_textfile(item_name(item));
|
|
+ break;
|
|
+ default:
|
|
+ on_menu_key(key);
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+
|
|
+static bool create(void)
|
|
+{
|
|
+ int rows, columns;
|
|
+ const char *title;
|
|
+
|
|
+ if (screen_lines < 3 || screen_cols < 20) {
|
|
+ proc_widget.close();
|
|
+ beep();
|
|
+ return FALSE;
|
|
+ }
|
|
+ scale_menu(menu, &rows, &columns);
|
|
+ rows += 2;
|
|
+ columns += 2;
|
|
+ if (rows > screen_lines)
|
|
+ rows = screen_lines;
|
|
+ if (columns > screen_cols)
|
|
+ columns = screen_cols;
|
|
+
|
|
+ widget_init(&proc_widget, rows, columns, SCREEN_CENTER, SCREEN_CENTER,
|
|
+ attr_menu, WIDGET_BORDER | WIDGET_SUBWINDOW);
|
|
+
|
|
+ title = _("Select File");
|
|
+ mvwprintw(proc_widget.window, 0, (columns - 2 - get_mbs_width(title)) / 2, " %s ", title);
|
|
+ set_menu_win(menu, proc_widget.window);
|
|
+ set_menu_sub(menu, proc_widget.subwindow);
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+static void on_window_size_changed(void)
|
|
+{
|
|
+ unpost_menu(menu);
|
|
+ if (!create())
|
|
+ return;
|
|
+ post_menu(menu);
|
|
+}
|
|
+
|
|
+static void on_close(void)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ unpost_menu(menu);
|
|
+ free_menu(menu);
|
|
+ for (i = 0; i < items_count; ++i)
|
|
+ free_item(items[i]);
|
|
+ widget_free(&proc_widget);
|
|
+}
|
|
+
|
|
+static void add_item(const char *file_name)
|
|
+{
|
|
+ if (access(file_name, F_OK) == 0) {
|
|
+ items[items_count] = new_item(file_name, NULL);
|
|
+ if (!items[items_count])
|
|
+ fatal_error("cannot create menu item");
|
|
+ ++items_count;
|
|
+ assert(items_count < ARRAY_SIZE(items));
|
|
+ }
|
|
+}
|
|
+
|
|
+static struct widget proc_widget = {
|
|
+ .handle_key = on_handle_key,
|
|
+ .window_size_changed = on_window_size_changed,
|
|
+ .close = on_close,
|
|
+};
|
|
+
|
|
+void create_proc_files_list(void)
|
|
+{
|
|
+ items_count = 0;
|
|
+ add_item("/proc/asound/version");
|
|
+ add_item("/proc/asound/cards");
|
|
+ add_item("/proc/asound/devices");
|
|
+ add_item("/proc/asound/oss/devices");
|
|
+ add_item("/proc/asound/timers");
|
|
+ add_item("/proc/asound/pcm");
|
|
+ items[items_count] = NULL;
|
|
+
|
|
+ menu = new_menu(items);
|
|
+ if (!menu)
|
|
+ fatal_error("cannot create menu");
|
|
+ set_menu_fore(menu, attr_menu_selected);
|
|
+ set_menu_back(menu, attr_menu);
|
|
+ set_menu_mark(menu, NULL);
|
|
+ menu_opts_off(menu, O_SHOWDESC);
|
|
+
|
|
+ if (!create())
|
|
+ return;
|
|
+
|
|
+ post_menu(menu);
|
|
+}
|
|
diff --git a/alsamixer/proc_files.h b/alsamixer/proc_files.h
|
|
new file mode 100644
|
|
index 0000000..8862c71
|
|
--- /dev/null
|
|
+++ b/alsamixer/proc_files.h
|
|
@@ -0,0 +1,6 @@
|
|
+#ifndef PROC_FILES_H_INCLUDED
|
|
+#define PROC_FILES_H_INCLUDED
|
|
+
|
|
+void create_proc_files_list(void);
|
|
+
|
|
+#endif
|
|
diff --git a/alsamixer/textbox.c b/alsamixer/textbox.c
|
|
new file mode 100644
|
|
index 0000000..d743a14
|
|
--- /dev/null
|
|
+++ b/alsamixer/textbox.c
|
|
@@ -0,0 +1,397 @@
|
|
+/*
|
|
+ * textbox.c - show a text box for messages, files or help
|
|
+ * Copyright (c) 1998,1999 Tim Janik <timj@gtk.org>
|
|
+ * Jaroslav Kysela <perex@perex.cz>
|
|
+ * Copyright (c) 2009 Clemens Ladisch <clemens@ladisch.de>
|
|
+ *
|
|
+ * This program is free software: you can redistribute it and/or modify
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
+ * the Free Software Foundation, either version 2 of the License, or
|
|
+ * (at your option) any later version.
|
|
+ *
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License
|
|
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
+ */
|
|
+
|
|
+#include "aconfig.h"
|
|
+#include <stdio.h>
|
|
+#include <stdlib.h>
|
|
+#include <string.h>
|
|
+#include <errno.h>
|
|
+#include CURSESINC
|
|
+#include <alsa/asoundlib.h>
|
|
+#include "gettext_curses.h"
|
|
+#include "utils.h"
|
|
+#include "die.h"
|
|
+#include "mem.h"
|
|
+#include "colors.h"
|
|
+#include "widget.h"
|
|
+#include "textbox.h"
|
|
+
|
|
+#define MAX_FILE_SIZE 1048576
|
|
+
|
|
+static void create_text_box(const char *const *lines, unsigned int count,
|
|
+ const char *title, int attrs);
|
|
+
|
|
+void show_error(const char *msg, int err)
|
|
+{
|
|
+ const char *lines[2];
|
|
+ unsigned int count;
|
|
+
|
|
+ lines[0] = msg;
|
|
+ count = 1;
|
|
+ if (err) {
|
|
+ lines[1] = strerror(err);
|
|
+ count = 2;
|
|
+ }
|
|
+ create_text_box(lines, count, _("Error"), attr_errormsg);
|
|
+}
|
|
+
|
|
+void show_alsa_error(const char *msg, int err)
|
|
+{
|
|
+ const char *lines[2];
|
|
+ unsigned int count;
|
|
+
|
|
+ lines[0] = msg;
|
|
+ count = 1;
|
|
+ if (err < 0) {
|
|
+ lines[1] = snd_strerror(err);
|
|
+ count = 2;
|
|
+ }
|
|
+ create_text_box(lines, count, _("Error"), attr_errormsg);
|
|
+}
|
|
+
|
|
+static char *read_file(const char *file_name, unsigned int *file_size)
|
|
+{
|
|
+ FILE *f;
|
|
+ int err;
|
|
+ char *buf;
|
|
+ unsigned int allocated = 2048;
|
|
+ unsigned int bytes_read;
|
|
+
|
|
+ f = fopen(file_name, "r");
|
|
+ if (!f) {
|
|
+ err = errno;
|
|
+ buf = casprintf(_("Cannot open file \"%s\"."), file_name);
|
|
+ show_error(buf, err);
|
|
+ free(buf);
|
|
+ return NULL;
|
|
+ }
|
|
+ *file_size = 0;
|
|
+ buf = NULL;
|
|
+ do {
|
|
+ allocated *= 2;
|
|
+ buf = crealloc(buf, allocated);
|
|
+ bytes_read = fread(buf + *file_size, 1, allocated - *file_size, f);
|
|
+ *file_size += bytes_read;
|
|
+ } while (*file_size == allocated && allocated < MAX_FILE_SIZE);
|
|
+ fclose(f);
|
|
+ if (*file_size > 0 && buf[*file_size - 1] != '\n' && *file_size < allocated) {
|
|
+ buf[*file_size] = '\n';
|
|
+ ++*file_size;
|
|
+ }
|
|
+ return buf;
|
|
+}
|
|
+
|
|
+void show_textfile(const char *file_name)
|
|
+{
|
|
+ char *buf;
|
|
+ unsigned int file_size;
|
|
+ unsigned int line_count;
|
|
+ unsigned int i;
|
|
+ const char **lines;
|
|
+ const char *start_line;
|
|
+
|
|
+ buf = read_file(file_name, &file_size);
|
|
+ if (!buf)
|
|
+ return;
|
|
+ line_count = 0;
|
|
+ for (i = 0; i < file_size; ++i)
|
|
+ line_count += buf[i] == '\n';
|
|
+ lines = ccalloc(line_count, sizeof *lines);
|
|
+ line_count = 0;
|
|
+ start_line = buf;
|
|
+ for (i = 0; i < file_size; ++i) {
|
|
+ if (buf[i] == '\n') {
|
|
+ lines[line_count++] = start_line;
|
|
+ buf[i] = '\0';
|
|
+ start_line = &buf[i + 1];
|
|
+ }
|
|
+ if (buf[i] == '\t')
|
|
+ buf[i] = ' ';
|
|
+ }
|
|
+ create_text_box(lines, line_count, file_name, attr_textbox);
|
|
+ free(lines);
|
|
+ free(buf);
|
|
+}
|
|
+
|
|
+void show_text(const char *const *lines, unsigned int count, const char *title)
|
|
+{
|
|
+ create_text_box(lines, count, title, attr_textbox);
|
|
+}
|
|
+
|
|
+/**********************************************************************/
|
|
+
|
|
+static struct widget text_widget;
|
|
+static char *title;
|
|
+static int widget_attrs;
|
|
+static char **text_lines;
|
|
+static unsigned int text_lines_count;
|
|
+static int max_line_width;
|
|
+static int text_box_y;
|
|
+static int text_box_x;
|
|
+static int max_scroll_y;
|
|
+static int max_scroll_x;
|
|
+static int current_top;
|
|
+static int current_left;
|
|
+
|
|
+static void update_text_lines(void)
|
|
+{
|
|
+ int i;
|
|
+ int width;
|
|
+ const char *line_begin;
|
|
+ const char *line_end;
|
|
+ int cur_y, cur_x;
|
|
+ int rest_of_line;
|
|
+
|
|
+ for (i = 0; i < text_box_y; ++i) {
|
|
+ width = current_left;
|
|
+ line_begin = mbs_at_width(text_lines[current_top + i], &width, 1);
|
|
+ wmove(text_widget.window, i + 1, 1);
|
|
+ if (width > current_left)
|
|
+ waddch(text_widget.window, ' ');
|
|
+ if (*line_begin != '\0') {
|
|
+ width = text_box_x - (width > current_left);
|
|
+ line_end = mbs_at_width(line_begin, &width, -1);
|
|
+ if (width)
|
|
+ waddnstr(text_widget.window, line_begin,
|
|
+ line_end - line_begin);
|
|
+ }
|
|
+ getyx(text_widget.window, cur_y, cur_x);
|
|
+ if (cur_y == i + 1) {
|
|
+ rest_of_line = text_box_x + 1 - cur_x;
|
|
+ if (rest_of_line > 0)
|
|
+ wprintw(text_widget.window, "%*s", rest_of_line, "");
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+static void update_y_scroll_bar(void)
|
|
+{
|
|
+ int length;
|
|
+ int begin, end;
|
|
+ int i;
|
|
+
|
|
+ if (max_scroll_y <= 0 || text_lines_count == 0)
|
|
+ return;
|
|
+ length = text_box_y * text_box_y / text_lines_count;
|
|
+ if (length >= text_box_y)
|
|
+ return;
|
|
+ begin = current_top * (text_box_y - length) / max_scroll_y;
|
|
+ end = begin + length;
|
|
+ for (i = 0; i < text_box_y; ++i)
|
|
+ mvwaddch(text_widget.window, i + 1, text_box_x + 1,
|
|
+ i >= begin && i < end ? ACS_BOARD : ' ');
|
|
+}
|
|
+
|
|
+static void update_x_scroll_bar(void)
|
|
+{
|
|
+ int length;
|
|
+ int begin, end;
|
|
+ int i;
|
|
+
|
|
+ if (max_scroll_x <= 0 || max_line_width <= 0)
|
|
+ return;
|
|
+ length = text_box_x * text_box_x / max_line_width;
|
|
+ if (length >= text_box_x)
|
|
+ return;
|
|
+ begin = current_left * (text_box_x - length) / max_scroll_x;
|
|
+ end = begin + length;
|
|
+ wmove(text_widget.window, text_box_y + 1, 1);
|
|
+ for (i = 0; i < text_box_x; ++i)
|
|
+ waddch(text_widget.window, i >= begin && i < end ? ACS_BOARD : ' ');
|
|
+}
|
|
+
|
|
+static void move_x(int delta)
|
|
+{
|
|
+ int left;
|
|
+
|
|
+ left = current_left + delta;
|
|
+ if (left < 0)
|
|
+ left = 0;
|
|
+ else if (left > max_scroll_x)
|
|
+ left = max_scroll_x;
|
|
+ if (left != current_left) {
|
|
+ current_left = left;
|
|
+ update_text_lines();
|
|
+ update_x_scroll_bar();
|
|
+ }
|
|
+}
|
|
+
|
|
+static void move_y(int delta)
|
|
+{
|
|
+ int top;
|
|
+
|
|
+ top = current_top + delta;
|
|
+ if (top < 0)
|
|
+ top = 0;
|
|
+ else if (top > max_scroll_y)
|
|
+ top = max_scroll_y;
|
|
+ if (top != current_top) {
|
|
+ current_top = top;
|
|
+ update_text_lines();
|
|
+ update_y_scroll_bar();
|
|
+ }
|
|
+}
|
|
+
|
|
+static void on_handle_key(int key)
|
|
+{
|
|
+ switch (key) {
|
|
+ case 10:
|
|
+ case 13:
|
|
+ case 27:
|
|
+ case KEY_CANCEL:
|
|
+ case KEY_ENTER:
|
|
+ case KEY_CLOSE:
|
|
+ case KEY_EXIT:
|
|
+ text_widget.close();
|
|
+ break;
|
|
+ case KEY_DOWN:
|
|
+ case KEY_SF:
|
|
+ case 'J':
|
|
+ case 'j':
|
|
+ case 'X':
|
|
+ case 'x':
|
|
+ move_y(1);
|
|
+ break;
|
|
+ case KEY_UP:
|
|
+ case KEY_SR:
|
|
+ case 'K':
|
|
+ case 'k':
|
|
+ case 'W':
|
|
+ case 'w':
|
|
+ move_y(-1);
|
|
+ break;
|
|
+ case KEY_LEFT:
|
|
+ case 'H':
|
|
+ case 'h':
|
|
+ case 'P':
|
|
+ case 'p':
|
|
+ move_x(-1);
|
|
+ break;
|
|
+ case KEY_RIGHT:
|
|
+ case 'L':
|
|
+ case 'l':
|
|
+ case 'N':
|
|
+ case 'n':
|
|
+ move_x(1);
|
|
+ break;
|
|
+ case KEY_NPAGE:
|
|
+ case ' ':
|
|
+ move_y(text_box_y);
|
|
+ break;
|
|
+ case KEY_PPAGE:
|
|
+ case KEY_BACKSPACE:
|
|
+ case 'B':
|
|
+ case 'b':
|
|
+ move_y(-text_box_y);
|
|
+ break;
|
|
+ case KEY_HOME:
|
|
+ case KEY_BEG:
|
|
+ move_x(-max_scroll_x);
|
|
+ break;
|
|
+ case KEY_LL:
|
|
+ case KEY_END:
|
|
+ move_x(max_scroll_x);
|
|
+ break;
|
|
+ case '\t':
|
|
+ move_x(8);
|
|
+ break;
|
|
+ case KEY_BTAB:
|
|
+ move_x(-8);
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+
|
|
+static bool create(void)
|
|
+{
|
|
+ int len, width;
|
|
+
|
|
+ if (screen_lines < 3 || screen_cols < 8) {
|
|
+ text_widget.close();
|
|
+ beep();
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ width = max_line_width;
|
|
+ len = get_mbs_width(title) + 2;
|
|
+ if (width < len)
|
|
+ width = len;
|
|
+
|
|
+ text_box_y = text_lines_count;
|
|
+ if (text_box_y > screen_lines - 2)
|
|
+ text_box_y = screen_lines - 2;
|
|
+ max_scroll_y = text_lines_count - text_box_y;
|
|
+ text_box_x = width;
|
|
+ if (text_box_x > screen_cols - 2)
|
|
+ text_box_x = screen_cols - 2;
|
|
+ max_scroll_x = max_line_width - text_box_x;
|
|
+
|
|
+ widget_init(&text_widget, text_box_y + 2, text_box_x + 2,
|
|
+ SCREEN_CENTER, SCREEN_CENTER, widget_attrs, WIDGET_BORDER);
|
|
+ mvwprintw(text_widget.window, 0, (text_box_x + 2 - get_mbs_width(title) - 2) / 2, " %s ", title);
|
|
+
|
|
+ if (current_top > max_scroll_y)
|
|
+ current_top = max_scroll_y;
|
|
+ if (current_left > max_scroll_x)
|
|
+ current_left = max_scroll_x;
|
|
+ update_text_lines();
|
|
+ update_y_scroll_bar();
|
|
+ update_x_scroll_bar();
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+static void on_window_size_changed(void)
|
|
+{
|
|
+ create();
|
|
+}
|
|
+
|
|
+static void on_close(void)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < text_lines_count; ++i)
|
|
+ free(text_lines[i]);
|
|
+ free(text_lines);
|
|
+ widget_free(&text_widget);
|
|
+}
|
|
+
|
|
+static struct widget text_widget = {
|
|
+ .handle_key = on_handle_key,
|
|
+ .window_size_changed = on_window_size_changed,
|
|
+ .close = on_close,
|
|
+};
|
|
+
|
|
+static void create_text_box(const char *const *lines, unsigned int count,
|
|
+ const char *title_, int attrs)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ text_lines = ccalloc(count, sizeof *text_lines);
|
|
+ for (i = 0; i < count; ++i)
|
|
+ text_lines[i] = cstrdup(lines[i]);
|
|
+ text_lines_count = count;
|
|
+ max_line_width = get_max_mbs_width(lines, count);
|
|
+ title = cstrdup(title_);
|
|
+ widget_attrs = attrs;
|
|
+
|
|
+ current_top = 0;
|
|
+ current_left = 0;
|
|
+
|
|
+ create();
|
|
+}
|
|
diff --git a/alsamixer/textbox.h b/alsamixer/textbox.h
|
|
new file mode 100644
|
|
index 0000000..7dc290b
|
|
--- /dev/null
|
|
+++ b/alsamixer/textbox.h
|
|
@@ -0,0 +1,10 @@
|
|
+#ifndef TEXTBOX_H_INCLUDED
|
|
+#define TEXTBOX_H_INCLUDED
|
|
+
|
|
+void show_error(const char *msg, int err);
|
|
+void show_alsa_error(const char *msg, int err);
|
|
+void show_text(const char *const *text_lines, unsigned int count,
|
|
+ const char *title);
|
|
+void show_textfile(const char *file_name);
|
|
+
|
|
+#endif
|
|
diff --git a/alsamixer/utils.c b/alsamixer/utils.c
|
|
new file mode 100644
|
|
index 0000000..3602bef
|
|
--- /dev/null
|
|
+++ b/alsamixer/utils.c
|
|
@@ -0,0 +1,111 @@
|
|
+/*
|
|
+ * utils.c - multibyte-string helpers
|
|
+ * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
|
|
+ *
|
|
+ * This program is free software: you can redistribute it and/or modify
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
+ * the Free Software Foundation, either version 2 of the License, or
|
|
+ * (at your option) any later version.
|
|
+ *
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License
|
|
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
+ */
|
|
+
|
|
+#define _XOPEN_SOURCE
|
|
+#include "aconfig.h"
|
|
+#include <limits.h>
|
|
+#include <stdlib.h>
|
|
+#include <string.h>
|
|
+#include <wchar.h>
|
|
+#include "utils.h"
|
|
+
|
|
+/*
|
|
+ * mbs_at_width - compute screen position in a string
|
|
+ *
|
|
+ * For displaying strings on the screen, we have to know how many character
|
|
+ * cells are occupied. This function calculates the position in a multibyte
|
|
+ * string that is at a desired position.
|
|
+ *
|
|
+ * Parameters:
|
|
+ * s: the string
|
|
+ * width: on input, the desired number of character cells; on output, the actual
|
|
+ * position, in character cells, of the return value
|
|
+ * dir: -1 or 1; in which direction to round if a multi-column character goes
|
|
+ * over the desired width
|
|
+ *
|
|
+ * Return value:
|
|
+ * Pointer to the place in the string that is as near the desired width as
|
|
+ * possible. If the string is too short, the return value points to the
|
|
+ * terminating zero. If the last character is a multi-column character that
|
|
+ * goes over the desired width, the return value may be one character cell
|
|
+ * earlier or later than desired, depending on the dir parameter.
|
|
+ * In any case, the return value points after any zero-width characters that
|
|
+ * follow the last character.
|
|
+ */
|
|
+const char *mbs_at_width(const char *s, int *width, int dir)
|
|
+{
|
|
+ size_t len;
|
|
+ wchar_t wc;
|
|
+ int bytes;
|
|
+ int width_so_far, w;
|
|
+
|
|
+ if (*width <= 0)
|
|
+ return s;
|
|
+ mbtowc(NULL, NULL, 0); /* reset shift state */
|
|
+ len = strlen(s);
|
|
+ width_so_far = 0;
|
|
+ while (len && (bytes = mbtowc(&wc, s, len)) > 0) {
|
|
+ w = wcwidth(wc);
|
|
+ if (width_so_far + w > *width && dir < 0)
|
|
+ break;
|
|
+ if (w >= 0)
|
|
+ width_so_far += w;
|
|
+ s += bytes;
|
|
+ len -= bytes;
|
|
+ if (width_so_far >= *width) {
|
|
+ while (len && (bytes = mbtowc(&wc, s, len)) > 0) {
|
|
+ w = wcwidth(wc);
|
|
+ if (w != 0)
|
|
+ break;
|
|
+ s += bytes;
|
|
+ len -= bytes;
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ *width = width_so_far;
|
|
+ return s;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * get_mbs_width - compute screen width of a string
|
|
+ */
|
|
+unsigned int get_mbs_width(const char *s)
|
|
+{
|
|
+ int width;
|
|
+
|
|
+ width = INT_MAX;
|
|
+ mbs_at_width(s, &width, 1);
|
|
+ return width;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * get_max_mbs_width - get width of longest string in an array
|
|
+ */
|
|
+unsigned int get_max_mbs_width(const char *const *s, unsigned int count)
|
|
+{
|
|
+ unsigned int max_width, i, len;
|
|
+
|
|
+ max_width = 0;
|
|
+ for (i = 0; i < count; ++i) {
|
|
+ len = get_mbs_width(s[i]);
|
|
+ if (len > max_width)
|
|
+ max_width = len;
|
|
+ }
|
|
+ return max_width;
|
|
+}
|
|
diff --git a/alsamixer/utils.h b/alsamixer/utils.h
|
|
new file mode 100644
|
|
index 0000000..00a52dd
|
|
--- /dev/null
|
|
+++ b/alsamixer/utils.h
|
|
@@ -0,0 +1,10 @@
|
|
+#ifndef UTILS_H_INCLUDED
|
|
+#define UTILS_H_INCLUDED
|
|
+
|
|
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof *(a))
|
|
+
|
|
+unsigned int get_mbs_width(const char *s);
|
|
+unsigned int get_max_mbs_width(const char *const *s, unsigned int count);
|
|
+const char *mbs_at_width(const char *s, int *width, int dir);
|
|
+
|
|
+#endif
|
|
diff --git a/alsamixer/widget.c b/alsamixer/widget.c
|
|
new file mode 100644
|
|
index 0000000..75da4c2
|
|
--- /dev/null
|
|
+++ b/alsamixer/widget.c
|
|
@@ -0,0 +1,140 @@
|
|
+/*
|
|
+ * widget.c - handles widget objects and the widget stack
|
|
+ * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
|
|
+ *
|
|
+ * This program is free software: you can redistribute it and/or modify
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
+ * the Free Software Foundation, either version 2 of the License, or
|
|
+ * (at your option) any later version.
|
|
+ *
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License
|
|
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
+ */
|
|
+
|
|
+#include "aconfig.h"
|
|
+#include <stdlib.h>
|
|
+#include <term.h>
|
|
+#include "die.h"
|
|
+#include "widget.h"
|
|
+
|
|
+int screen_lines;
|
|
+int screen_cols;
|
|
+
|
|
+static int cursor_visibility = -1;
|
|
+
|
|
+static void widget_handle_key(int key)
|
|
+{
|
|
+}
|
|
+
|
|
+static void update_cursor_visibility(void)
|
|
+{
|
|
+ struct widget *active_widget;
|
|
+
|
|
+ active_widget = get_active_widget();
|
|
+ if (active_widget &&
|
|
+ active_widget->cursor_visibility != cursor_visibility) {
|
|
+ cursor_visibility = active_widget->cursor_visibility;
|
|
+ curs_set(cursor_visibility);
|
|
+ }
|
|
+}
|
|
+
|
|
+void widget_init(struct widget *widget, int lines_, int cols, int y, int x,
|
|
+ chtype bkgd, unsigned int flags)
|
|
+{
|
|
+ WINDOW *old_window;
|
|
+
|
|
+ if (y == SCREEN_CENTER)
|
|
+ y = (screen_lines - lines_) / 2;
|
|
+ if (x == SCREEN_CENTER)
|
|
+ x = (screen_cols - cols) / 2;
|
|
+
|
|
+ old_window = widget->window;
|
|
+ widget->window = newwin(lines_, cols, y, x);
|
|
+ if (!widget->window)
|
|
+ fatal_error("cannot create window");
|
|
+ keypad(widget->window, TRUE);
|
|
+ nodelay(widget->window, TRUE);
|
|
+ leaveok(widget->window, !(flags & WIDGET_CURSOR_VISIBLE));
|
|
+ wbkgdset(widget->window, bkgd);
|
|
+ werase(widget->window);
|
|
+
|
|
+ if (flags & WIDGET_BORDER)
|
|
+ box(widget->window, 0, 0);
|
|
+ if (flags & WIDGET_SUBWINDOW) {
|
|
+ if (widget->subwindow)
|
|
+ delwin(widget->subwindow);
|
|
+ widget->subwindow = derwin(widget->window,
|
|
+ lines_ - 2, cols - 2, 1, 1);
|
|
+ if (!widget->subwindow)
|
|
+ fatal_error("cannot create subwindow");
|
|
+ wbkgdset(widget->subwindow, bkgd);
|
|
+ }
|
|
+ widget->cursor_visibility = !!(flags & WIDGET_CURSOR_VISIBLE);
|
|
+
|
|
+ if (widget->panel) {
|
|
+ replace_panel(widget->panel, widget->window);
|
|
+ } else {
|
|
+ widget->panel = new_panel(widget->window);
|
|
+ if (!widget->panel)
|
|
+ fatal_error("cannot create panel");
|
|
+ set_panel_userptr(widget->panel, widget);
|
|
+ }
|
|
+
|
|
+ if (!widget->handle_key)
|
|
+ widget->handle_key = widget_handle_key;
|
|
+
|
|
+ if (old_window)
|
|
+ delwin(old_window);
|
|
+
|
|
+ update_cursor_visibility();
|
|
+}
|
|
+
|
|
+void widget_free(struct widget *widget)
|
|
+{
|
|
+ if (widget->panel) {
|
|
+ del_panel(widget->panel);
|
|
+ widget->panel = NULL;
|
|
+ }
|
|
+ if (widget->subwindow) {
|
|
+ delwin(widget->subwindow);
|
|
+ widget->subwindow = NULL;
|
|
+ }
|
|
+ if (widget->window) {
|
|
+ delwin(widget->window);
|
|
+ widget->window = NULL;
|
|
+ }
|
|
+
|
|
+ update_cursor_visibility();
|
|
+}
|
|
+
|
|
+struct widget *get_active_widget(void)
|
|
+{
|
|
+ PANEL *active_panel;
|
|
+
|
|
+ active_panel = panel_below(NULL);
|
|
+ if (active_panel)
|
|
+ return panel_userptr(active_panel);
|
|
+ else
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+void window_size_changed(void)
|
|
+{
|
|
+ PANEL *panel, *below;
|
|
+ struct widget *widget;
|
|
+
|
|
+ getmaxyx(stdscr, screen_lines, screen_cols);
|
|
+ if (tigetflag("xenl") != 1 && tigetflag("am") != 1)
|
|
+ --screen_lines;
|
|
+
|
|
+ for (panel = panel_below(NULL); panel; panel = below) {
|
|
+ below = panel_below(panel);
|
|
+ widget = panel_userptr(panel);
|
|
+ widget->window_size_changed();
|
|
+ }
|
|
+}
|
|
diff --git a/alsamixer/widget.h b/alsamixer/widget.h
|
|
new file mode 100644
|
|
index 0000000..6adb526
|
|
--- /dev/null
|
|
+++ b/alsamixer/widget.h
|
|
@@ -0,0 +1,33 @@
|
|
+#ifndef WIDGET_H_INCLUDED
|
|
+#define WIDGET_H_INCLUDED
|
|
+
|
|
+#include <panel.h>
|
|
+
|
|
+#define WIDGET_BORDER 0x1
|
|
+#define WIDGET_SUBWINDOW 0x2
|
|
+#define WIDGET_CURSOR_VISIBLE 0x4
|
|
+
|
|
+#define SCREEN_CENTER -1
|
|
+
|
|
+struct widget {
|
|
+ WINDOW *window;
|
|
+ WINDOW *subwindow; /* optional: contents without border */
|
|
+ PANEL *panel;
|
|
+ int cursor_visibility;
|
|
+
|
|
+ void (*handle_key)(int key);
|
|
+ void (*window_size_changed)(void);
|
|
+ void (*close)(void);
|
|
+};
|
|
+
|
|
+extern int screen_lines;
|
|
+extern int screen_cols;
|
|
+
|
|
+void widget_init(struct widget *widget,
|
|
+ int lines_, int cols, int y, int x,
|
|
+ chtype bkgd, unsigned int flags);
|
|
+void widget_free(struct widget *widget);
|
|
+struct widget *get_active_widget(void);
|
|
+void window_size_changed(void);
|
|
+
|
|
+#endif
|
|
diff --git a/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="<ncurses.h>"
|
|
CURSESLIB=`ncursesw5-config --libs`
|
|
+ CURSESLIBDIR=`ncursesw5-config --libdir`
|
|
CURSES_CFLAGS=`ncursesw5-config --cflags`
|
|
curseslib="ncursesw"
|
|
else
|
|
AC_CHECK_LIB(ncursesw, initscr,
|
|
[ CURSESINC='<ncurses.h>'; CURSESLIB='-lncursesw'; curseslib="ncursesw"])
|
|
fi
|
|
+ if test -n "$CURSESINC"; then
|
|
+ NCURSESLIBSUFFIX="w"
|
|
+ CURSES_NLS="yes"
|
|
+ fi
|
|
fi
|
|
if test "$curseslib" = "ncurses" -o "$curseslib" = "auto"; then
|
|
AC_CHECK_PROG([ncurses5_config], [ncurses5-config], [yes])
|
|
if test "$ncurses5_config" = "yes"; then
|
|
CURSESINC="<ncurses.h>"
|
|
CURSESLIB=`ncurses5-config --libs`
|
|
+ CURSESLIBDIR=`ncurses5-config --libdir`
|
|
CURSES_CFLAGS=`ncurses5-config --cflags`
|
|
curseslib="ncurses"
|
|
else
|
|
@@ -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 <curses.h>
|
|
+ ], [
|
|
+ cchar_t wc;
|
|
+ setcchar(&wc, L"x", A_NORMAL, 0, 0);
|
|
+ ],
|
|
+ [CURSES_NLS="yes"])
|
|
+ fi
|
|
+ AC_MSG_RESULT([$CURSES_NLS])
|
|
+ if test "$CURSES_NLS" = "yes"; then
|
|
+ AC_DEFINE([ENABLE_NLS_IN_CURSES], [1],
|
|
+ [Define if curses-based programs can show translated messages.])
|
|
+ fi
|
|
+ fi
|
|
+
|
|
+ AC_CHECK_HEADERS([panel.h menu.h form.h], [],
|
|
+ [AC_MSG_ERROR([required curses helper header not found])])
|
|
+ AC_CHECK_LIB([panel$NCURSESLIBSUFFIX], [new_panel],
|
|
+ [CURSESLIB="-lpanel$NCURSESLIBSUFFIX $CURSESLIB"],
|
|
+ [AC_MSG_ERROR([panel$NCURSESLIBSUFFIX library not found])])
|
|
+ AC_CHECK_LIB([menu$NCURSESLIBSUFFIX], [new_menu],
|
|
+ [CURSESLIB="-lmenu$NCURSESLIBSUFFIX $CURSESLIB"],
|
|
+ [AC_MSG_ERROR([menu$NCURSESLIBSUFFIX library not found])])
|
|
+ AC_CHECK_LIB([form$NCURSESLIBSUFFIX], [new_form],
|
|
+ [CURSESLIB="-lform$NCURSESLIBSUFFIX $CURSESLIB"],
|
|
+ [AC_MSG_ERROR([form$NCURSESLIBSUFFIX library not found])])
|
|
+
|
|
+ CFLAGS="$saved_CFLAGS"
|
|
+ LDFLAGS="$saved_LDFLAGS"
|
|
+ LIBS="$saved_LIBS"
|
|
+
|
|
+ if test -n "$CURSESLIBDIR"; then
|
|
+ CURSESLIB="-L$CURSESLIBDIR $CURSESLIB"
|
|
+ fi
|
|
+
|
|
+ AC_MSG_CHECKING([for curses linker flags])
|
|
+ AC_MSG_RESULT([$CURSESLIB])
|
|
fi
|
|
|
|
AC_SUBST(CURSESINC)
|
|
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 <libintl.h>
|
|
#else
|
|
# define gettext(msgid) (msgid)
|
|
diff --git a/include/gettext_curses.h b/include/gettext_curses.h
|
|
new file mode 100644
|
|
index 0000000..f1c4041
|
|
--- /dev/null
|
|
+++ b/include/gettext_curses.h
|
|
@@ -0,0 +1,2 @@
|
|
+#define USES_CURSES
|
|
+#include "gettext.h"
|
|
diff --git a/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 <clemens@ladisch.de>, 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 <clemens@ladisch.de>\n"
|
|
+"Language-Team: German\n"
|
|
+"MIME-Version: 1.0\n"
|
|
+"Content-Type: text/plain; charset=UTF-8\n"
|
|
+"Content-Transfer-Encoding: 8bit\n"
|
|
+
|
|
+#: alsamixer/card_select.c:126 alsamixer/device_name.c:126
|
|
+msgid "Sound Card"
|
|
+msgstr "Soundkarte"
|
|
+
|
|
+#: alsamixer/card_select.c:181
|
|
+msgid "(default)"
|
|
+msgstr "(Standard)"
|
|
+
|
|
+#: alsamixer/card_select.c:191
|
|
+msgid "cannot enumerate sound cards"
|
|
+msgstr "Fehler beim Aufzählen der Soundkarten"
|
|
+
|
|
+#: alsamixer/card_select.c:215
|
|
+msgid "enter device name..."
|
|
+msgstr "Gerätenamen eingeben..."
|
|
+
|
|
+#: alsamixer/cli.c:40
|
|
+msgid "Usage: alsamixer [options]"
|
|
+msgstr "Verwendung: alsamixer [Optionen]"
|
|
+
|
|
+#: alsamixer/cli.c:41
|
|
+msgid ""
|
|
+"Useful options:\n"
|
|
+" -h, --help this help\n"
|
|
+" -c, --card=NUMBER sound card number or id\n"
|
|
+" -D, --device=NAME mixer device name\n"
|
|
+" -V, --view=MODE starting view mode: playback/capture/all"
|
|
+msgstr ""
|
|
+"Optionen:\n"
|
|
+" -h, --help Hilfe\n"
|
|
+" -c, --card=NUMMER Soundkarten-Nummer oder -ID\n"
|
|
+" -D, --device=NAME Mixer-Gerätename\n"
|
|
+" -V, --view=MODUS Ansicht beim Starten: playback=Wiedergabe, "
|
|
+"capture=Aufnahme, all=alle"
|
|
+
|
|
+#: alsamixer/cli.c:46
|
|
+msgid ""
|
|
+"Debugging options:\n"
|
|
+" -g, --no-color toggle using of colors\n"
|
|
+" -a, --abstraction=NAME mixer abstraction level: none/basic"
|
|
+msgstr ""
|
|
+"Debugging-Optionen:\n"
|
|
+" -g, --no-color keine Farben\n"
|
|
+" -a, --abstraction=NAME Mixer-Abstraktion: none/basic"
|
|
+
|
|
+#: alsamixer/cli.c:77
|
|
+#, c-format
|
|
+msgid "invalid card index: %s\n"
|
|
+msgstr "ungültige Karten-Nummer: %s\n"
|
|
+
|
|
+#: alsamixer/cli.c:103
|
|
+#, c-format
|
|
+msgid "unknown abstraction level: %s\n"
|
|
+msgstr "unbekannte Abstraktion: %s\n"
|
|
+
|
|
+#: alsamixer/cli.c:108
|
|
+#, c-format
|
|
+msgid "unknown option: %c\n"
|
|
+msgstr "unbekannte Option: %c\n"
|
|
+
|
|
+#: alsamixer/cli.c:110
|
|
+msgid "try `alsamixer --help' for more information\n"
|
|
+msgstr "siehe `alsamixer --help' für mehr Informationen\n"
|
|
+
|
|
+#: alsamixer/device_name.c:177
|
|
+msgid "Device name:"
|
|
+msgstr "Gerätename:"
|
|
+
|
|
+#: alsamixer/die.c:37
|
|
+#, c-format
|
|
+msgid "%s: %s\n"
|
|
+msgstr "%s: %s\n"
|
|
+
|
|
+#: alsamixer/mixer_display.c:95
|
|
+msgid "Card:"
|
|
+msgstr "Gerät:"
|
|
+
|
|
+#: alsamixer/mixer_display.c:96
|
|
+msgid "Chip:"
|
|
+msgstr "Chip:"
|
|
+
|
|
+#: alsamixer/mixer_display.c:97
|
|
+msgid "View:"
|
|
+msgstr "Ansicht:"
|
|
+
|
|
+#: alsamixer/mixer_display.c:98
|
|
+msgid "Item:"
|
|
+msgstr "Element:"
|
|
+
|
|
+#: alsamixer/mixer_display.c:101
|
|
+msgid "F1: Help"
|
|
+msgstr "F1: Hilfe"
|
|
+
|
|
+#: alsamixer/mixer_display.c:102
|
|
+msgid "F2: System information"
|
|
+msgstr "F2: System-Informationen"
|
|
+
|
|
+#: alsamixer/mixer_display.c:103
|
|
+msgid "F6: Select sound card"
|
|
+msgstr "F6: Soundkarte auswählen"
|
|
+
|
|
+#: alsamixer/mixer_display.c:104
|
|
+msgid "Esc: Exit"
|
|
+msgstr "Esc: Beenden"
|
|
+
|
|
+#: alsamixer/mixer_display.c:171
|
|
+msgid "(unplugged)"
|
|
+msgstr "(entfernt)"
|
|
+
|
|
+#: alsamixer/mixer_display.c:189
|
|
+msgid "Playback"
|
|
+msgstr "Wiedergabe"
|
|
+
|
|
+#: alsamixer/mixer_display.c:190
|
|
+msgid "Capture"
|
|
+msgstr "Aufnahme"
|
|
+
|
|
+#: alsamixer/mixer_display.c:191
|
|
+msgid "All"
|
|
+msgstr "Alle"
|
|
+
|
|
+#: alsamixer/mixer_display.c:231
|
|
+msgid "mute"
|
|
+msgstr "stumm"
|
|
+
|
|
+#: alsamixer/mixer_display.c:272 alsamixer/mixer_display.c:282
|
|
+msgid "dB gain:"
|
|
+msgstr "dB-Änderung:"
|
|
+
|
|
+#: alsamixer/mixer_display.c:282
|
|
+#, c-format
|
|
+msgid " [%s %s, %s]"
|
|
+msgstr " [%s %s; %s]"
|
|
+
|
|
+#: alsamixer/mixer_display.c:291 alsamixer/mixer_display.c:297
|
|
+#: alsamixer/mixer_display.c:303 alsamixer/mixer_display.c:309
|
|
+msgid "Off"
|
|
+msgstr "Aus"
|
|
+
|
|
+#: alsamixer/mixer_display.c:297 alsamixer/mixer_display.c:309
|
|
+msgid "On"
|
|
+msgstr "An"
|
|
+
|
|
+#: alsamixer/mixer_display.c:360
|
|
+msgid "The sound device was unplugged."
|
|
+msgstr "Das Gerät wurde entfernt."
|
|
+
|
|
+#: alsamixer/mixer_display.c:361
|
|
+msgid "Press F6 to select another sound card."
|
|
+msgstr "Drücken Sie F6, um eine andere Soundkarte auszuwählen."
|
|
+
|
|
+#: alsamixer/mixer_display.c:376
|
|
+msgid "This sound device does not have any playback controls."
|
|
+msgstr "Dieses Gerät hat keine Wiedergabe-Regler."
|
|
+
|
|
+#: alsamixer/mixer_display.c:378
|
|
+msgid "This sound device does not have any capture controls."
|
|
+msgstr "Dieses Gerät hat keine Aufnahme-Regler."
|
|
+
|
|
+#: alsamixer/mixer_display.c:380
|
|
+msgid "This sound device does not have any controls."
|
|
+msgstr "Dieses Gerät hat keine Regler."
|
|
+
|
|
+#. TRANSLATORS: playback on; one character
|
|
+#: alsamixer/mixer_display.c: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 <timj@gtk.org>"
|
|
+msgstr " Tim Janik <tim@gtk.org>"
|
|
+
|
|
+#: alsamixer/mixer_widget.c:215
|
|
+msgid " Jaroslav Kysela <perex@perex.cz>"
|
|
+msgstr " Jaroslav Kysela <perex@perex.cz>"
|
|
+
|
|
+#: alsamixer/mixer_widget.c:216
|
|
+msgid " Clemens Ladisch <clemens@ladisch.de>"
|
|
+msgstr " Clemens Ladisch <clemens@ladisch.de>"
|
|
+
|
|
+#: alsamixer/mixer_widget.c:218
|
|
+msgid "Help"
|
|
+msgstr "Hilfe"
|
|
+
|
|
+#: alsamixer/proc_files.c:103
|
|
+msgid "Select File"
|
|
+msgstr "Datei wählen"
|
|
+
|
|
+#: alsamixer/textbox.c:52 alsamixer/textbox.c:66
|
|
+msgid "Error"
|
|
+msgstr "Fehler"
|
|
+
|
|
+#: alsamixer/textbox.c:80
|
|
+#, c-format
|
|
+msgid "Cannot open file \"%s\"."
|
|
+msgstr "Fehler beim Öffnen der Datei \"%s\"."
|
|
+
|
|
+#: aplay/aplay.c: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 <tiwai@suse.de>\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 <timj@gtk.org>"
|
|
+msgstr ""
|
|
+
|
|
+#: alsamixer/mixer_widget.c:215
|
|
+msgid " Jaroslav Kysela <perex@perex.cz>"
|
|
+msgstr ""
|
|
+
|
|
+#: alsamixer/mixer_widget.c:216
|
|
+msgid " Clemens Ladisch <clemens@ladisch.de>"
|
|
+msgstr ""
|
|
+
|
|
+#: alsamixer/mixer_widget.c:218
|
|
+msgid "Help"
|
|
+msgstr "ヘルプ"
|
|
+
|
|
+#: alsamixer/proc_files.c:103
|
|
+msgid "Select File"
|
|
+msgstr "ファイル選択"
|
|
+
|
|
+#: alsamixer/textbox.c:52 alsamixer/textbox.c:66
|
|
+msgid "Error"
|
|
+msgstr "エラー"
|
|
+
|
|
+#: alsamixer/textbox.c:80
|
|
+#, c-format
|
|
+msgid "Cannot open file \"%s\"."
|
|
+msgstr "\"%s\"をオープンできません"
|
|
+
|
|
+#: aplay/aplay.c: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<channels;chn++) {
|
|
switch (format) {
|
|
case SND_PCM_FORMAT_S8:
|
|
@@ -168,11 +171,7 @@ static void generate_sine(uint8_t *frames, int channel, int count, double *_phas
|
|
if (chn==channel) {
|
|
res = (sin((phase * 2 * M_PI) / max_phase - M_PI)) * 0x03fffffff; /* Don't use MAX volume */
|
|
ires = res;
|
|
-#if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
- *samp16++ = ires >> 16;
|
|
-#elif __BYTE_ORDER == __BIG_ENDIAN
|
|
- *samp16++ = bswap_16(ires >> 16);
|
|
-#endif
|
|
+ *samp16++ = LE_SHORT(ires >> 16);
|
|
} else {
|
|
*samp16++ = 0;
|
|
}
|
|
@@ -181,11 +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);
|