From Superk
#! /usr/bin/perl -w
#
# Adjust ALSA master volume up/down or report current volume. Can also
# mute or unmute the volume.
#
# Written by Ewen McNeill <ewen@naos.co.nz>, 2003/10/11
#---------------------------------------------------------------------------
use strict;
my $MIXER=\'/usr/bin/amixer\';
my $UNMUTE=\"numid=1,iface=MIXER,name=\'Master Playback Switch\'\";
my $VOLUME=\"numid=2,iface=MIXER,name=\'Master Playback Volume\'\";
my %ACTION_DECODE =
(
\'up\' => \'up\',
\'+1\' => \'up\',
\'+\' => \'up\',
\'down\' => \'down\',
\'-1\' => \'down\',
\'-\' => \'down\',
\'mute\' => \'mute\',
\'0\' => \'mute\',
\'unmute\' => \'unmute\',
\'1\' => \'unmute\',
\'toggle\' => \'toggle\',
\'show\' => \'show\'
);
my $USAGE=\"$0 {up|down|mute|unmute|toggle|show}\";
#---------------------------------------------------------------------------
# Get existing mixer settings
#
# Input: path to a (complex) mixer setting
#
# Returns: minimum value, maximum value, current value (left then right,
# or one value for mono)
#
# NOTE: Boolean values are cooerced into 0 or 1 (true/false)
#
# Example output from mixer command:
#
# $ amixer cget numid=1,iface=MIXER,name=\'Master Playback Switch\'
# numid=1,iface=MIXER,name=\'Master Playback Switch\'
# ; type=BOOLEAN,access=rw---,values=1
# : values=on
#
# $ amixer cget numid=2,iface=MIXER,name=\'Master Playback Volume\'
# numid=2,iface=MIXER,name=\'Master Playback Volume\'
# ; type=INTEGER,access=rw---,values=2,min=0,max=31,step=0
# : values=24,23
#
sub get_mixer_value
{
my ($control)=@_;
return undef unless defined($control);
open(MIXER, \"$MIXER cget $control|\") or
do { warn \"Cannot run $MIXER!\\n\"; return undef; };
my ($min, $max, $left, $right);
while(<MIXER>)
{
# Boolean
if (/^\\s*:.*values=on/) { $left=1; $min=0; $max=1; }
if (/^\\s*:.*values=off/) { $left=0; $min=0; $max=1; }
# Integer
if (/^\\s*;.*min=(\\d+)/) { $min=$1; }
if (/^\\s*;.*max=(\\d+)/) { $max=$1; }
if (/^\\s*:.*values=(\\d+),(\\d+)/) { ($left,$right)=($1,$2); next; }
if (/^\\s*:.*values=(\\d+)/) { ($left)=($1); next; }
}
close(MIXER);
return ($min, $max, $left, $right);
}
#---------------------------------------------------------------------------
# Set a mixer value
#
# Input: name of (complex) mixer control, value(s) to set
#
sub set_mixer_value
{
my ($control,@values) = @_;
return undef unless (defined($control) && defined($values[0]));
# warn (\"$MIXER cset $control \" . join(\",\", @values) . \">/dev/null\\n\");
system(\"$MIXER cset $control \" . join(\",\", @values) . \" >/dev/null\");
return 1;
}
#---------------------------------------------------------------------------
# Mainline
#
my ($mmin, $mmax, $mleft, $mright) = get_mixer_value($UNMUTE);
my ($vmin, $vmax, $vleft, $vright) = get_mixer_value($VOLUME);
#
my $action=$ARGV[0];
$action=$ACTION_DECODE{$action} if (defined($action));
if (defined($action))
{
if ($action eq \'up\')
{
set_mixer_value($VOLUME, $vleft+1, $vright+1);
set_mixer_value($UNMUTE, 1);
}
if ($action eq \'down\')
{
set_mixer_value($VOLUME, (($vleft-1 > 0) ? ($vleft-1) : 0),
(($vright-1 > 0) ? ($vright-1) : 0));
set_mixer_value($UNMUTE, 1);
}
if ($action eq \'mute\')
{
set_mixer_value($UNMUTE, 0);
}
if ($action eq \'unmute\')
{
set_mixer_value($UNMUTE, 1);
}
if ($action eq \'toggle\')
{
set_mixer_value($UNMUTE, (! $mleft));
}
# Reload mixer values after changes
($mmin, $mmax, $mleft, $mright) = get_mixer_value($UNMUTE);
($vmin, $vmax, $vleft, $vright) = get_mixer_value($VOLUME);
}
elsif (defined($ARGV[0]))
{
warn \"Unrecognised option: $ARGV[0]\\n$USAGE\\n\";
}
#
printf \"Master Volume: left: %d (%d%%); right: %d (%d%%)%s\\n\",
$vleft, int(($vleft-$vmin)*100/($vmax-$vmin)),
$vright, int(($vright-$vmin)*100/($vmax-$vmin)),
($mleft ? \"\" : \" (*MUTED*)\");