mirror of
https://github.com/alsa-project/alsa-utils
synced 2024-12-22 17:26:31 +01:00
* 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 record volume changes since they broke ExactMode display. * * * composed ChangeLog entries.
This commit is contained in:
parent
4775b46362
commit
d47938eab3
3 changed files with 953 additions and 823 deletions
|
@ -79,5 +79,6 @@ You can exit with ALT + Q, or by hitting ESC.
|
|||
|
||||
-----------------------------------------------------------------
|
||||
|
||||
alsamixer is by Jaroslav Kysela <perex@jcu.cz>
|
||||
This document is by Paul Winkler <zarmzarm@erols.com>
|
||||
Alsamixer has been written by Tim Janik <timj@gtk.org> and
|
||||
been furtherly improved by Jaroslav Kysela <perex@jcu.cz>.
|
||||
This document was provided by Paul Winkler <zarmzarm@erols.com>.
|
||||
|
|
|
@ -107,15 +107,14 @@ arecord(1)
|
|||
\fP
|
||||
|
||||
.SH BUGS
|
||||
None known. Some terminal emulators (e.g. \fBnxterm\fP) may not
|
||||
There is no help screen implemented yet. Some terminal emulators
|
||||
(e.g. \fBnxterm\fP) may not
|
||||
work quite right with ncurses, but that's their own damn
|
||||
fault. Plain old \fBxterm\fP seems to be fine.
|
||||
|
||||
.SH AUTHOR
|
||||
\fBalsamixer\fP is by Jaroslav Kysela <perex@jcu.cz>
|
||||
This document is by Paul Winkler <zarmzarm@erols.com>.
|
||||
|
||||
|
||||
|
||||
|
||||
.B alsamixer
|
||||
has been written by Tim Janik <timj@gtk.org> and
|
||||
been furtherly improved by Jaroslav Kysela <perex@jcu.cz>.
|
||||
|
||||
This manual page was provided by Paul Winkler <zarmzarm@erols.com>.
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
/* AlsaMixer - Commandline mixer for the ALSA project
|
||||
* Copyright (C) 1998 Jaroslav Kysela <perex@jcu.cz>,
|
||||
* Tim Janik <timj@gtk.org>,
|
||||
* Carl van Schaik <carl@dreamcoat.che.uct.ac.za>
|
||||
* Copyright (C) 1998, 1999 Tim Janik <timj@gtk.org> and Jaroslav Kysela <perex@jcu.cz>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -16,6 +14,49 @@
|
|||
* 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:
|
||||
*
|
||||
* 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 record volume changes since they broke ExactMode display.
|
||||
*
|
||||
* * composed ChangeLog entries.
|
||||
*
|
||||
* 1998/11/04 19:43:45 perex
|
||||
*
|
||||
* * Stereo record 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!).
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
@ -40,13 +81,15 @@
|
|||
#include <sys/asoundlib.h>
|
||||
|
||||
/* example compilation commandline:
|
||||
* clear; gcc -Wall -pipe -O2 alsamixer.c -o alsamixer -lncurses
|
||||
* clear; gcc -Wall -pipe -O2 alsamixer.c -o alsamixer -lasound -lncurses
|
||||
*/
|
||||
|
||||
/* --- defines --- */
|
||||
#define PRGNAME "alsamixer"
|
||||
#define PRGNAME_UPPER "AlsaMixer"
|
||||
#define VERSION "v0.9"
|
||||
#define REFRESH() ({ if (!mixer_needs_resize) refresh (); })
|
||||
#define CHECK_ABORT(e,s) ({ if (errno != EINTR) mixer_abort ((e), (s)); })
|
||||
|
||||
#undef MAX
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
|
@ -57,8 +100,9 @@
|
|||
#undef CLAMP
|
||||
#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
|
||||
|
||||
#define MIXER_MIN_X (23) /* minimum: 23 */
|
||||
#define MIXER_MIN_Y (19) /* minimum: 19 */
|
||||
#define MIXER_MIN_X (18) /* abs minimum: 18 */
|
||||
#define MIXER_TEXT_Y (10)
|
||||
#define MIXER_MIN_Y (MIXER_TEXT_Y + 3) /* abs minimum: 11 */
|
||||
|
||||
#define MIXER_BLACK (COLOR_BLACK)
|
||||
#define MIXER_DARK_RED (COLOR_RED)
|
||||
|
@ -78,11 +122,11 @@
|
|||
|
||||
/* --- variables --- */
|
||||
static WINDOW *mixer_window = NULL;
|
||||
static int mixer_needs_resize = 0;
|
||||
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_ofs_y = 0;
|
||||
static int mixer_cbar_height = 0;
|
||||
|
||||
static int card_id = 0;
|
||||
|
@ -95,10 +139,9 @@ static int mixer_n_channels = 0;
|
|||
static int mixer_n_vis_channels = 0;
|
||||
static int mixer_first_vis_channel = 0;
|
||||
static int mixer_focus_channel = 0;
|
||||
static int mixer_have_old_focus = 0;
|
||||
static int mixer_exact = 0;
|
||||
|
||||
static int mixer_record_volumes = 0;
|
||||
|
||||
static int mixer_lvolume_delta = 0;
|
||||
static int mixer_rvolume_delta = 0;
|
||||
static int mixer_balance_volumes = 0;
|
||||
|
@ -137,15 +180,13 @@ enum {
|
|||
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 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,
|
||||
static void
|
||||
mixer_init_dc (int c,
|
||||
int n,
|
||||
int f,
|
||||
int b,
|
||||
|
@ -158,7 +199,8 @@ static void mixer_init_dc(int c,
|
|||
init_pair (n, dc_fg[n] & 0xf, b & 0x0f);
|
||||
}
|
||||
|
||||
static int mixer_dc(int n)
|
||||
static int
|
||||
mixer_dc (int n)
|
||||
{
|
||||
if (mixer_do_color)
|
||||
attrset (COLOR_PAIR (n) | (dc_fg[n] & 0xfffffff0));
|
||||
|
@ -168,7 +210,8 @@ static int mixer_dc(int n)
|
|||
return dc_char[n];
|
||||
}
|
||||
|
||||
static void mixer_init_draw_contexts(void)
|
||||
static void
|
||||
mixer_init_draw_contexts (void)
|
||||
{
|
||||
start_color ();
|
||||
|
||||
|
@ -193,7 +236,8 @@ static void mixer_init_draw_contexts(void)
|
|||
|
||||
|
||||
/* --- error types --- */
|
||||
typedef enum {
|
||||
typedef enum
|
||||
{
|
||||
ERR_NONE,
|
||||
ERR_OPEN,
|
||||
ERR_FCN,
|
||||
|
@ -203,18 +247,21 @@ typedef enum {
|
|||
|
||||
|
||||
/* --- prototypes --- */
|
||||
static void mixer_abort(ErrType error,
|
||||
static void
|
||||
mixer_abort (ErrType error,
|
||||
const char *err_string)
|
||||
__attribute__
|
||||
((noreturn));
|
||||
|
||||
|
||||
/* --- functions --- */
|
||||
static void mixer_clear(void)
|
||||
static void
|
||||
mixer_clear (void)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
mixer_dc (DC_BACK);
|
||||
clearok (mixer_window, TRUE);
|
||||
clear ();
|
||||
|
||||
/* buggy ncurses doesn't really write spaces with the specified
|
||||
|
@ -223,20 +270,25 @@ static void mixer_clear(void)
|
|||
for (x = 0; x < mixer_max_x; x++)
|
||||
for (y = 0; y < mixer_max_y; y++)
|
||||
mvaddch (y, x, ' ');
|
||||
refresh();
|
||||
}
|
||||
|
||||
static void mixer_abort(ErrType error,
|
||||
static void
|
||||
mixer_abort (ErrType error,
|
||||
const char *err_string)
|
||||
{
|
||||
if (mixer_window) {
|
||||
if (mixer_window)
|
||||
{
|
||||
mixer_clear ();
|
||||
refresh ();
|
||||
keypad (mixer_window, FALSE);
|
||||
leaveok (mixer_window, FALSE);
|
||||
endwin ();
|
||||
mixer_window = NULL;
|
||||
}
|
||||
printf ("\n");
|
||||
|
||||
switch (error) {
|
||||
switch (error)
|
||||
{
|
||||
case ERR_OPEN:
|
||||
fprintf (stderr,
|
||||
PRGNAME ": failed to open mixer #%i/#%i: %s\n",
|
||||
|
@ -268,7 +320,8 @@ static void mixer_abort(ErrType error,
|
|||
exit (error);
|
||||
}
|
||||
|
||||
static int mixer_cbar_get_pos(int channel_index,
|
||||
static int
|
||||
mixer_cbar_get_pos (int channel_index,
|
||||
int *x_p,
|
||||
int *y_p)
|
||||
{
|
||||
|
@ -281,11 +334,14 @@ static int mixer_cbar_get_pos(int channel_index,
|
|||
|
||||
channel_index -= mixer_first_vis_channel;
|
||||
|
||||
x = mixer_ofs_x + 1;
|
||||
y = mixer_ofs_y;
|
||||
x += channel_index * (3 + 2 + 3 + 1 + mixer_extra_space);
|
||||
y += mixer_max_y / 2;
|
||||
y += mixer_cbar_height / 2 + 1;
|
||||
x = mixer_ofs_x;
|
||||
x += (3 + 2 + 3 + 1) * channel_index + mixer_extra_space * (channel_index + 1);
|
||||
|
||||
if (MIXER_TEXT_Y + 10 < mixer_max_y)
|
||||
y = mixer_max_y / 2 + 3;
|
||||
else
|
||||
y = (mixer_max_y + 1) / 2 + 3;
|
||||
y += mixer_cbar_height / 2;
|
||||
|
||||
if (x_p)
|
||||
*x_p = x;
|
||||
|
@ -295,31 +351,26 @@ static int mixer_cbar_get_pos(int channel_index,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void mixer_update_cbar(int channel_index)
|
||||
static void
|
||||
mixer_update_cbar (int channel_index)
|
||||
{
|
||||
char string[64];
|
||||
char c;
|
||||
snd_mixer_channel_info_t cinfo =
|
||||
{0};
|
||||
snd_mixer_channel_t cdata =
|
||||
{0};
|
||||
snd_mixer_channel_t crdata =
|
||||
{0};
|
||||
snd_mixer_channel_info_t cinfo = { 0, };
|
||||
snd_mixer_channel_t cdata = { 0, };
|
||||
int vleft, vright;
|
||||
int x, y, i;
|
||||
|
||||
int channel_record_volume;
|
||||
|
||||
/* set specified EXACT mode
|
||||
*/
|
||||
if (snd_mixer_exact_mode (mixer_handle, mixer_exact) < 0)
|
||||
mixer_abort(ERR_FCN, "snd_mixer_exact");
|
||||
CHECK_ABORT (ERR_FCN, "snd_mixer_exact_mode()");
|
||||
|
||||
/* set new channel indices and read info
|
||||
*/
|
||||
if (snd_mixer_channel_info (mixer_handle, channel_index, &cinfo) < 0)
|
||||
mixer_abort(ERR_FCN, "snd_mixer_channel_info");
|
||||
channel_record_volume = (cinfo.caps & SND_MIXER_CINFO_CAP_RECORDVOLUME);
|
||||
CHECK_ABORT (ERR_FCN, "snd_mixer_channel_info()");
|
||||
|
||||
/* set new channel values
|
||||
*/
|
||||
|
@ -329,59 +380,38 @@ static void mixer_update_cbar(int channel_index)
|
|||
mixer_balance_volumes ||
|
||||
mixer_toggle_record || mixer_toggle_rec_left ||
|
||||
mixer_toggle_rec_right ||
|
||||
mixer_route_rtol_in || mixer_route_ltor_in)) {
|
||||
mixer_route_rtol_in || mixer_route_ltor_in))
|
||||
{
|
||||
if (snd_mixer_channel_read (mixer_handle, channel_index, &cdata) < 0)
|
||||
mixer_abort(ERR_FCN, "snd_mixer_channel_read");
|
||||
if (mixer_record_volumes && channel_record_volume &&
|
||||
snd_mixer_channel_record_read(mixer_handle, channel_index, &crdata) < 0)
|
||||
mixer_abort(ERR_FCN, "snd_mixer_channel_record_read");
|
||||
CHECK_ABORT (ERR_FCN, "snd_mixer_channel_read()");
|
||||
|
||||
cdata.flags &= ~SND_MIXER_FLG_DECIBEL;
|
||||
if (mixer_lvolume_delta) {
|
||||
if (mixer_record_volumes) {
|
||||
if (channel_record_volume)
|
||||
crdata.left = CLAMP(crdata.left + mixer_lvolume_delta, cinfo.min, cinfo.max);
|
||||
}
|
||||
else
|
||||
cdata.left = CLAMP (cdata.left + mixer_lvolume_delta, cinfo.min, cinfo.max);
|
||||
mixer_lvolume_delta = 0;
|
||||
}
|
||||
if (mixer_rvolume_delta) {
|
||||
if (mixer_record_volumes) {
|
||||
if (channel_record_volume)
|
||||
crdata.right = CLAMP(crdata.right + mixer_rvolume_delta, cinfo.min, cinfo.max);
|
||||
}
|
||||
else
|
||||
cdata.right = CLAMP (cdata.right + mixer_rvolume_delta, cinfo.min, cinfo.max);
|
||||
mixer_rvolume_delta = 0;
|
||||
}
|
||||
if (mixer_balance_volumes) {
|
||||
if (mixer_record_volumes) {
|
||||
if (channel_record_volume) {
|
||||
crdata.left = (crdata.left + crdata.right) / 2;
|
||||
crdata.right = crdata.left;
|
||||
}
|
||||
}
|
||||
else {
|
||||
mixer_lvolume_delta = mixer_rvolume_delta = 0;
|
||||
if (mixer_balance_volumes)
|
||||
{
|
||||
cdata.left = (cdata.left + cdata.right) / 2;
|
||||
cdata.right = cdata.left;
|
||||
}
|
||||
mixer_balance_volumes = 0;
|
||||
}
|
||||
if (mixer_toggle_mute_left) {
|
||||
if (mixer_toggle_mute_left)
|
||||
{
|
||||
if (cdata.flags & SND_MIXER_FLG_MUTE_LEFT)
|
||||
cdata.flags &= ~SND_MIXER_FLG_MUTE_LEFT;
|
||||
else
|
||||
cdata.flags |= SND_MIXER_FLG_MUTE_LEFT;
|
||||
}
|
||||
if (mixer_toggle_mute_right) {
|
||||
if (mixer_toggle_mute_right)
|
||||
{
|
||||
if (cdata.flags & SND_MIXER_FLG_MUTE_RIGHT)
|
||||
cdata.flags &= ~SND_MIXER_FLG_MUTE_RIGHT;
|
||||
else
|
||||
cdata.flags |= SND_MIXER_FLG_MUTE_RIGHT;
|
||||
}
|
||||
mixer_toggle_mute_left = mixer_toggle_mute_right = 0;
|
||||
if (mixer_toggle_record) {
|
||||
if (mixer_toggle_record)
|
||||
{
|
||||
if (cdata.flags & SND_MIXER_FLG_RECORD)
|
||||
cdata.flags &= ~SND_MIXER_FLG_RECORD;
|
||||
else
|
||||
|
@ -389,7 +419,8 @@ static void mixer_update_cbar(int channel_index)
|
|||
}
|
||||
mixer_toggle_record = 0;
|
||||
|
||||
if (mixer_toggle_rec_left) {
|
||||
if (mixer_toggle_rec_left)
|
||||
{
|
||||
if (cdata.flags & SND_MIXER_FLG_RECORD_LEFT)
|
||||
cdata.flags &= ~SND_MIXER_FLG_RECORD_LEFT;
|
||||
else
|
||||
|
@ -397,7 +428,8 @@ static void mixer_update_cbar(int channel_index)
|
|||
}
|
||||
mixer_toggle_rec_left = 0;
|
||||
|
||||
if (mixer_toggle_rec_right) {
|
||||
if (mixer_toggle_rec_right)
|
||||
{
|
||||
if (cdata.flags & SND_MIXER_FLG_RECORD_RIGHT)
|
||||
cdata.flags &= ~SND_MIXER_FLG_RECORD_RIGHT;
|
||||
else
|
||||
|
@ -405,7 +437,8 @@ static void mixer_update_cbar(int channel_index)
|
|||
}
|
||||
mixer_toggle_rec_right = 0;
|
||||
|
||||
if (mixer_route_ltor_in) {
|
||||
if (mixer_route_ltor_in)
|
||||
{
|
||||
if (cdata.flags & SND_MIXER_FLG_LTOR_IN)
|
||||
cdata.flags &= ~SND_MIXER_FLG_LTOR_IN;
|
||||
else
|
||||
|
@ -415,7 +448,8 @@ static void mixer_update_cbar(int channel_index)
|
|||
}
|
||||
mixer_route_ltor_in = 0;
|
||||
|
||||
if (mixer_route_rtol_in) {
|
||||
if (mixer_route_rtol_in)
|
||||
{
|
||||
if (cdata.flags & SND_MIXER_FLG_RTOL_IN)
|
||||
cdata.flags &= ~SND_MIXER_FLG_RTOL_IN;
|
||||
else
|
||||
|
@ -424,45 +458,28 @@ static void mixer_update_cbar(int channel_index)
|
|||
mixer_route_rtol_in = 0;
|
||||
|
||||
if (snd_mixer_channel_write (mixer_handle, channel_index, &cdata) < 0)
|
||||
mixer_abort(ERR_FCN, "snd_mixer_channel_write");
|
||||
if (mixer_record_volumes && channel_record_volume &&
|
||||
snd_mixer_channel_record_write(mixer_handle, channel_index, &crdata) < 0)
|
||||
mixer_abort(ERR_FCN, "snd_mixer_channel_record_write");
|
||||
CHECK_ABORT (ERR_FCN, "snd_mixer_channel_write()");
|
||||
}
|
||||
/* first, read values for the numbers to be displayed in
|
||||
* specified EXACT mode
|
||||
*/
|
||||
if (snd_mixer_channel_read (mixer_handle, channel_index, &cdata) < 0)
|
||||
mixer_abort(ERR_FCN, "snd_mixer_ioctl_channel_read");
|
||||
if (mixer_record_volumes) {
|
||||
if (channel_record_volume) {
|
||||
if (snd_mixer_channel_record_read(mixer_handle, channel_index, &crdata) < 0)
|
||||
mixer_abort(ERR_FCN, "snd_mixer_channel_record_read");
|
||||
vleft = crdata.left;
|
||||
vright = crdata.right;
|
||||
}
|
||||
else
|
||||
vleft = vright = 0;
|
||||
}
|
||||
else {
|
||||
CHECK_ABORT (ERR_FCN, "snd_mixer_channel_read()");
|
||||
vleft = cdata.left;
|
||||
vright = cdata.right;
|
||||
}
|
||||
|
||||
/* then, always use percentage values for the bars. if we don't do
|
||||
* this, we will see aliasing effects on specific circumstances.
|
||||
* (actually they don't really dissapear, but they are transfered
|
||||
* to bar<->smaller-scale ambiguities).
|
||||
*/
|
||||
if (mixer_exact) {
|
||||
if (mixer_exact)
|
||||
{
|
||||
i = 0;
|
||||
if (snd_mixer_exact_mode (mixer_handle, 0) < 0)
|
||||
mixer_abort(ERR_FCN, "snd_mixer_exact");
|
||||
CHECK_ABORT (ERR_FCN, "snd_mixer_exact_mode()");
|
||||
if (snd_mixer_channel_read (mixer_handle, channel_index, &cdata) < 0)
|
||||
mixer_abort(ERR_FCN, "snd_mixer_channel_read");
|
||||
if (mixer_record_volumes && channel_record_volume &&
|
||||
snd_mixer_channel_record_read(mixer_handle, channel_index, &crdata) < 0)
|
||||
mixer_abort(ERR_FCN, "snd_mixer_channel_record_read");
|
||||
CHECK_ABORT (ERR_FCN, "snd_mixer_channel_read()");
|
||||
}
|
||||
/* get channel bar position
|
||||
*/
|
||||
|
@ -473,7 +490,8 @@ static void mixer_update_cbar(int channel_index)
|
|||
*/
|
||||
mixer_dc (channel_index == mixer_focus_channel ? DC_CBAR_FOCUS_LABEL : DC_CBAR_LABEL);
|
||||
cinfo.name[8] = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
string[i] = ' ';
|
||||
}
|
||||
sprintf (string + (8 - strlen (cinfo.name)) / 2, "%s ", cinfo.name);
|
||||
|
@ -505,13 +523,15 @@ static void mixer_update_cbar(int channel_index)
|
|||
mvaddch (y, x + 4, ACS_HLINE);
|
||||
mvaddch (y, x + 5, ACS_LRCORNER);
|
||||
y--;
|
||||
for (i = 0; i < mixer_cbar_height; i++) {
|
||||
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);
|
||||
}
|
||||
string[2] = 0;
|
||||
for (i = 0; i < mixer_cbar_height; i++) {
|
||||
for (i = 0; i < mixer_cbar_height; i++)
|
||||
{
|
||||
int dc;
|
||||
|
||||
if (i + 1 >= 0.8 * mixer_cbar_height)
|
||||
|
@ -520,8 +540,8 @@ static void mixer_update_cbar(int channel_index)
|
|||
dc = DC_CBAR_FULL_2;
|
||||
else
|
||||
dc = DC_CBAR_FULL_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));
|
||||
mvaddch (y, x + 3, mixer_dc (cdata.left > i * 100 / mixer_cbar_height ? dc : DC_CBAR_EMPTY));
|
||||
mvaddch (y, x + 4, mixer_dc (cdata.right > i * 100 / mixer_cbar_height ? dc : DC_CBAR_EMPTY));
|
||||
y--;
|
||||
}
|
||||
|
||||
|
@ -542,38 +562,45 @@ static void mixer_update_cbar(int channel_index)
|
|||
|
||||
/* record input?
|
||||
*/
|
||||
if (cdata.flags & SND_MIXER_FLG_RECORD) {
|
||||
if (cdata.flags & SND_MIXER_FLG_RECORD)
|
||||
{
|
||||
mixer_dc (DC_CBAR_RECORD);
|
||||
mvaddstr (y, x + 1, "RECORD");
|
||||
if (cdata.flags & SND_MIXER_FLG_RECORD_LEFT) {
|
||||
if (cdata.flags & SND_MIXER_FLG_RECORD_LEFT)
|
||||
{
|
||||
if (cdata.flags & SND_MIXER_FLG_LTOR_IN)
|
||||
mvaddstr (y + 2, x + 6, "L");
|
||||
else
|
||||
mvaddstr (y + 1, x + 1, "L");
|
||||
}
|
||||
if (cdata.flags & SND_MIXER_FLG_RECORD_RIGHT) {
|
||||
if (cdata.flags & SND_MIXER_FLG_RECORD_RIGHT)
|
||||
{
|
||||
if (cdata.flags & SND_MIXER_FLG_RTOL_IN)
|
||||
mvaddstr (y + 2, x + 1, "R");
|
||||
else
|
||||
mvaddstr (y + 1, x + 6, "R");
|
||||
}
|
||||
} else if (cinfo.caps & SND_MIXER_CINFO_CAP_RECORD)
|
||||
}
|
||||
else if (cinfo.caps & SND_MIXER_CINFO_CAP_RECORD)
|
||||
for (i = 0; i < 6; i++)
|
||||
mvaddch (y, x + 1 + i, mixer_dc (DC_CBAR_NORECORD));
|
||||
else {
|
||||
else
|
||||
{
|
||||
mixer_dc (DC_BACK);
|
||||
mvaddstr (y, x, " ");
|
||||
}
|
||||
y--;
|
||||
}
|
||||
|
||||
static void mixer_update_cbars(void)
|
||||
static void
|
||||
mixer_update_cbars (void)
|
||||
{
|
||||
static int o_x = 0;
|
||||
static int o_y = 0;
|
||||
int i, x, y;
|
||||
|
||||
if (!mixer_cbar_get_pos(mixer_focus_channel, &x, &y)) {
|
||||
if (!mixer_cbar_get_pos (mixer_focus_channel, &x, &y))
|
||||
{
|
||||
if (mixer_focus_channel < mixer_first_vis_channel)
|
||||
mixer_first_vis_channel = mixer_focus_channel;
|
||||
else if (mixer_focus_channel >= mixer_first_vis_channel + mixer_n_vis_channels)
|
||||
|
@ -585,17 +612,22 @@ static void mixer_update_cbars(void)
|
|||
|
||||
/* 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)
|
||||
static void
|
||||
mixer_draw_frame (void)
|
||||
{
|
||||
char string[128];
|
||||
int i;
|
||||
|
@ -603,33 +635,6 @@ static void mixer_draw_frame(void)
|
|||
|
||||
mixer_dc (DC_FRAME);
|
||||
|
||||
/* corners
|
||||
*/
|
||||
mvaddch(0, 0, ACS_ULCORNER);
|
||||
mvaddch(mixer_max_y - 1, 0, ACS_LLCORNER);
|
||||
mvaddch(mixer_max_y - 1, mixer_max_x - 1, ACS_LRCORNER);
|
||||
mvaddch(0, mixer_max_x - 1, ACS_URCORNER);
|
||||
|
||||
/* lines
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/* program title
|
||||
*/
|
||||
sprintf(string, "%s %s", PRGNAME_UPPER, VERSION);
|
||||
max_len = strlen(string);
|
||||
mvaddch(0, mixer_max_x / 2 - max_len / 2 - 1, '[');
|
||||
mvaddch(0, mixer_max_x / 2 - max_len / 2 + max_len, ']');
|
||||
mixer_dc(DC_TEXT);
|
||||
mvaddstr(0, mixer_max_x / 2 - max_len / 2, string);
|
||||
|
||||
/* card name
|
||||
*/
|
||||
mixer_dc (DC_PROMPT);
|
||||
|
@ -639,7 +644,7 @@ static void mixer_draw_frame(void)
|
|||
max_len = mixer_max_x - 2 - 6 - 2;
|
||||
if (strlen (string) > max_len)
|
||||
string[max_len] = 0;
|
||||
mvaddstr(1, 2 + 6, string);
|
||||
addstr (string);
|
||||
|
||||
/* device name
|
||||
*/
|
||||
|
@ -650,17 +655,65 @@ static void mixer_draw_frame(void)
|
|||
max_len = mixer_max_x - 2 - 6 - 2;
|
||||
if (strlen (string) > max_len)
|
||||
string[max_len] = 0;
|
||||
mvaddstr(2, 2 + 6, string);
|
||||
if (mixer_record_volumes)
|
||||
mvaddstr(3, 2, "Record mixer");
|
||||
addstr (string);
|
||||
|
||||
/* indicate exact mode
|
||||
*/
|
||||
if (mixer_exact)
|
||||
{
|
||||
mixer_dc (DC_PROMPT);
|
||||
mvaddstr (3, 2, "[");
|
||||
mixer_dc (DC_TEXT);
|
||||
addstr ("ExactMode");
|
||||
mixer_dc (DC_PROMPT);
|
||||
addstr ("]");
|
||||
}
|
||||
else
|
||||
mvaddstr (3, 2, " ");
|
||||
|
||||
/* lines
|
||||
*/
|
||||
mixer_dc (DC_PROMPT);
|
||||
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);
|
||||
}
|
||||
|
||||
static void mixer_init(void)
|
||||
/* corners
|
||||
*/
|
||||
mixer_dc (DC_PROMPT);
|
||||
mvaddch (mixer_max_y - 1, mixer_max_x - 1, ACS_LRCORNER);
|
||||
mvaddch (mixer_max_y - 1, 0, ACS_LLCORNER);
|
||||
mvaddch (0, 0, ACS_ULCORNER);
|
||||
mvaddch (0, mixer_max_x - 1, ACS_URCORNER);
|
||||
|
||||
/* program title
|
||||
*/
|
||||
sprintf (string, "%s %s", PRGNAME_UPPER, VERSION);
|
||||
max_len = strlen (string);
|
||||
if (mixer_max_x >= max_len + 4)
|
||||
{
|
||||
static snd_mixer_info_t mixer_info =
|
||||
{0};
|
||||
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 void
|
||||
mixer_init (void)
|
||||
{
|
||||
static snd_mixer_info_t mixer_info = { 0, };
|
||||
static struct snd_ctl_hw_info hw_info;
|
||||
void *ctl_handle;
|
||||
|
||||
|
@ -683,39 +736,133 @@ static void mixer_init(void)
|
|||
mixer_device_name = mixer_info.name;
|
||||
}
|
||||
|
||||
static void mixer_iteration_update(void *dummy, int channel)
|
||||
static void
|
||||
mixer_init_window (void)
|
||||
{
|
||||
/* initialize ncurses
|
||||
*/
|
||||
mixer_window = initscr ();
|
||||
|
||||
if (mixer_do_color)
|
||||
mixer_do_color = has_colors ();
|
||||
mixer_init_draw_contexts ();
|
||||
|
||||
/* react on key presses
|
||||
* and draw window
|
||||
*/
|
||||
keypad (mixer_window, TRUE);
|
||||
leaveok (mixer_window, TRUE);
|
||||
cbreak ();
|
||||
noecho ();
|
||||
|
||||
/* init mixer screen
|
||||
*/
|
||||
getmaxyx (mixer_window, mixer_max_y, mixer_max_x);
|
||||
mixer_ofs_x = 2 /* extra begin padding: */ + 1;
|
||||
|
||||
/* required allocations */
|
||||
mixer_n_vis_channels = (mixer_max_x - mixer_ofs_x * 2 + 1) / 9;
|
||||
mixer_n_vis_channels = CLAMP (mixer_n_vis_channels, 1, mixer_n_channels);
|
||||
mixer_extra_space = mixer_max_x - mixer_ofs_x * 2 + 1 - mixer_n_vis_channels * 9;
|
||||
mixer_extra_space = MAX (0, mixer_extra_space / (mixer_n_vis_channels + 1));
|
||||
if (MIXER_TEXT_Y + 10 < mixer_max_y)
|
||||
mixer_cbar_height = 10 + MAX (0, mixer_max_y - MIXER_TEXT_Y - 10 ) / 2;
|
||||
else
|
||||
mixer_cbar_height = MAX (1, mixer_max_y - MIXER_TEXT_Y);
|
||||
|
||||
mixer_clear ();
|
||||
}
|
||||
|
||||
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,
|
||||
* clear() segfaults (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_channel_changed_cb (void *private_data,
|
||||
int channel)
|
||||
{
|
||||
/* we don't actually need to update the individual channels because
|
||||
* we redraw the whole screen upon every main iteration anyways.
|
||||
*/
|
||||
#if 0
|
||||
fprintf (stderr, "*** channel = %i\n", channel);
|
||||
#endif
|
||||
mixer_update_cbar (channel);
|
||||
refresh();
|
||||
#endif
|
||||
}
|
||||
|
||||
static int mixer_iteration(void)
|
||||
static int
|
||||
mixer_iteration (void)
|
||||
{
|
||||
snd_mixer_callbacks_t callbacks;
|
||||
int key;
|
||||
int finished = 0;
|
||||
struct timeval delay = { 0, };
|
||||
snd_mixer_callbacks_t callbacks = { 0, };
|
||||
int mixer_fd;
|
||||
fd_set in;
|
||||
fd_set rfds;
|
||||
int finished = 0;
|
||||
int key = 0;
|
||||
|
||||
bzero(&callbacks, sizeof(callbacks));
|
||||
callbacks.channel_was_changed = mixer_iteration_update;
|
||||
callbacks.channel_was_changed = mixer_channel_changed_cb;
|
||||
|
||||
/* setup for select on stdin and the mixer fd */
|
||||
mixer_fd = snd_mixer_file_descriptor (mixer_handle);
|
||||
while (1) {
|
||||
FD_ZERO(&in);
|
||||
FD_SET(fileno(stdin), &in);
|
||||
FD_SET(mixer_fd, &in);
|
||||
if (select(mixer_fd + 1, &in, NULL, NULL, NULL) <= 0)
|
||||
return 1;
|
||||
if (FD_ISSET(mixer_fd, &in))
|
||||
snd_mixer_read(mixer_handle, &callbacks);
|
||||
if (FD_ISSET(fileno(stdin), &in))
|
||||
break;
|
||||
FD_ZERO (&rfds);
|
||||
FD_SET (fileno (stdin), &rfds);
|
||||
FD_SET (mixer_fd, &rfds);
|
||||
|
||||
delay.tv_sec = 0;
|
||||
delay.tv_usec = 0 * 100 * 1000;
|
||||
|
||||
finished = select (mixer_fd + 1, &rfds, NULL, NULL, mixer_needs_resize ? &delay : NULL) < 0;
|
||||
|
||||
/* don't abort on handled signals */
|
||||
if (finished && errno == EINTR)
|
||||
{
|
||||
FD_ZERO (&rfds);
|
||||
finished = 0;
|
||||
}
|
||||
else if (mixer_needs_resize)
|
||||
mixer_resize ();
|
||||
|
||||
if (FD_ISSET (mixer_fd, &rfds))
|
||||
snd_mixer_read (mixer_handle, &callbacks);
|
||||
|
||||
if (FD_ISSET (fileno (stdin), &rfds))
|
||||
key = getch ();
|
||||
switch (key) {
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case 0:
|
||||
/* ignore */
|
||||
break;
|
||||
case 27: /* Escape */
|
||||
finished = 1;
|
||||
break;
|
||||
|
@ -731,19 +878,25 @@ static int mixer_iteration(void)
|
|||
mixer_focus_channel -= 1;
|
||||
break;
|
||||
case KEY_PPAGE:
|
||||
if (mixer_exact) {
|
||||
if (mixer_exact)
|
||||
{
|
||||
mixer_lvolume_delta = 8;
|
||||
mixer_rvolume_delta = 8;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
mixer_lvolume_delta = 10;
|
||||
mixer_rvolume_delta = 10;
|
||||
}
|
||||
break;
|
||||
case KEY_NPAGE:
|
||||
if (mixer_exact) {
|
||||
if (mixer_exact)
|
||||
{
|
||||
mixer_lvolume_delta = -8;
|
||||
mixer_rvolume_delta = -8;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
mixer_lvolume_delta = -10;
|
||||
mixer_rvolume_delta = -10;
|
||||
}
|
||||
|
@ -806,7 +959,6 @@ static int mixer_iteration(void)
|
|||
break;
|
||||
case 'm':
|
||||
case 'M':
|
||||
mixer_record_volumes = 0;
|
||||
mixer_toggle_mute_left = 1;
|
||||
mixer_toggle_mute_right = 1;
|
||||
break;
|
||||
|
@ -817,18 +969,14 @@ static int mixer_iteration(void)
|
|||
break;
|
||||
case '<':
|
||||
case ',':
|
||||
mixer_record_volumes = 0;
|
||||
mixer_toggle_mute_left = 1;
|
||||
break;
|
||||
case '>':
|
||||
case '.':
|
||||
mixer_record_volumes = 0;
|
||||
mixer_toggle_mute_right = 1;
|
||||
break;
|
||||
case 'R':
|
||||
case 'r':
|
||||
mixer_record_volumes = !mixer_record_volumes;
|
||||
break;
|
||||
case 'L':
|
||||
case 'l':
|
||||
mixer_clear ();
|
||||
|
@ -845,11 +993,9 @@ static int mixer_iteration(void)
|
|||
mixer_toggle_rec_right = 1;
|
||||
break;
|
||||
case '1':
|
||||
mixer_record_volumes = 0;
|
||||
mixer_route_rtol_in = 1;
|
||||
break;
|
||||
case '2':
|
||||
mixer_record_volumes = 0;
|
||||
mixer_route_ltor_in = 1;
|
||||
break;
|
||||
}
|
||||
|
@ -858,50 +1004,39 @@ static int mixer_iteration(void)
|
|||
return finished;
|
||||
}
|
||||
|
||||
static void mixer_init_screen(void)
|
||||
static void
|
||||
mixer_winch (void)
|
||||
{
|
||||
signal(SIGWINCH, (void *) mixer_init_screen);
|
||||
signal (SIGWINCH, (void*) mixer_winch);
|
||||
|
||||
getmaxyx(mixer_window, mixer_max_y, mixer_max_x);
|
||||
mixer_clear();
|
||||
mixer_max_x = MAX(MIXER_MIN_X, mixer_max_x);
|
||||
mixer_max_y = MAX(MIXER_MIN_Y, mixer_max_y);
|
||||
mixer_clear();
|
||||
mixer_ofs_x = 2;
|
||||
mixer_ofs_y = 2;
|
||||
mixer_extra_space = 0;
|
||||
mixer_n_vis_channels = MIN((mixer_max_x - 2 * mixer_ofs_x + 1) / (9 + mixer_extra_space),
|
||||
mixer_n_channels);
|
||||
mixer_extra_space = ((mixer_max_x - 2 * mixer_ofs_x - 1 - mixer_n_vis_channels * 9.0) /
|
||||
(mixer_n_vis_channels - 1));
|
||||
if (mixer_n_vis_channels < mixer_n_channels) {
|
||||
/* recalc
|
||||
*/
|
||||
mixer_extra_space = MAX(mixer_extra_space, 1);
|
||||
mixer_n_vis_channels = MIN((mixer_max_x - 2 * mixer_ofs_x + 1) / (9 + mixer_extra_space),
|
||||
mixer_n_channels);
|
||||
mixer_extra_space = ((mixer_max_x - 2 * mixer_ofs_x - 1 - mixer_n_vis_channels * 9.0) /
|
||||
(mixer_n_vis_channels - 1));
|
||||
}
|
||||
mixer_first_vis_channel = 0;
|
||||
mixer_cbar_height = 10 + MAX(0, (mixer_max_y - MIXER_MIN_Y - 1)) / 2;
|
||||
mixer_needs_resize++;
|
||||
}
|
||||
|
||||
static void mixer_signal_handler(int signal)
|
||||
static void
|
||||
mixer_signal_handler (int signal)
|
||||
{
|
||||
if (signal != SIGSEGV)
|
||||
mixer_abort (ERR_SIGNAL, sys_siglist[signal]);
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "\nSegmentation fault.\n");
|
||||
_exit (11);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc,
|
||||
int
|
||||
main (int argc,
|
||||
char **argv)
|
||||
{
|
||||
int opt;
|
||||
|
||||
/* parse args
|
||||
*/
|
||||
do {
|
||||
do
|
||||
{
|
||||
opt = getopt (argc, argv, "c:m:ehg");
|
||||
switch (opt) {
|
||||
switch (opt)
|
||||
{
|
||||
case '?':
|
||||
case 'h':
|
||||
fprintf (stderr, "%s %s\n", PRGNAME_UPPER, VERSION);
|
||||
|
@ -940,26 +1075,21 @@ int main(int argc,
|
|||
|
||||
/* initialize ncurses
|
||||
*/
|
||||
mixer_window = initscr();
|
||||
if (mixer_do_color)
|
||||
mixer_do_color = has_colors();
|
||||
mixer_init_draw_contexts();
|
||||
mixer_init_screen();
|
||||
mixer_init_window ();
|
||||
if (mixer_max_x < MIXER_MIN_X ||
|
||||
mixer_max_y < MIXER_MIN_Y)
|
||||
mixer_abort(ERR_WINSIZE, "");
|
||||
beep (); // mixer_abort (ERR_WINSIZE, "");
|
||||
|
||||
signal (SIGWINCH, (void*) mixer_winch);
|
||||
|
||||
/* react on key presses
|
||||
* and draw window
|
||||
*/
|
||||
keypad(mixer_window, TRUE);
|
||||
leaveok(mixer_window, TRUE);
|
||||
cbreak();
|
||||
noecho();
|
||||
do {
|
||||
do
|
||||
{
|
||||
mixer_update_cbars ();
|
||||
mixer_draw_frame ();
|
||||
refresh();
|
||||
REFRESH ();
|
||||
}
|
||||
while (!mixer_iteration ());
|
||||
|
||||
|
|
Loading…
Reference in a new issue