⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 alsamixer.c

📁 ALSA驱动的一些调试测试工具
💻 C
📖 第 1 页 / 共 5 页
字号:
/* 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 voidmixer_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 intmixer_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 voidmixer_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 voidmixer_abort (ErrType error,	     const char *err_string,	     int xerrno)     __attribute__((noreturn));/* --- functions --- */static voidmixer_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 voidmixer_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 intmixer_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;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -