ALSA Volume Script

From Superk

Jump to: navigation, search
#! /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*)\");
Personal tools