#! /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 , 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() { # 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*)");