#!/usr/bin/perl # Filename: vol # Author: David Ljung Madison # See License: http://MarginalHacks.com/License # Description: Set main soundcard volume # Requires: aumix (to get/set volume settings) # http://freshmeat.net/projects/aumix/ # Optional: osd_cat (for cool on-screen settings!) # http://www.ignavus.net/software.html use strict; ################################################## # Setup the variables ################################################## my $PROGNAME = $0; $PROGNAME =~ s|.*/||; my $AUMIX = "aumix"; my $SAVE_VOL = "/tmp/$PROGNAME.saved"; # osd (on-screen display) if available (otherwise undef) my $OSD = "osd_cat"; my $OSD_ARGS = "-d 2 -f '-*-courier-*-r-*-*-50-*-*-*-*-*-*-*' -c red -t -o 400"; my $DAY_VOL = 90; my $NIGHT_VOL = 55; my $MUTE_VOL = 35; my $DAY_STARTS = 700; # 7am my $DAY_ENDS = 2230; # 10:30pm my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); my $miltime = sprintf("%0.2d%0.2d",$hour,$min); my $NOW_VOL = ($miltime<$DAY_STARTS || $miltime>=$DAY_ENDS) ? $NIGHT_VOL : $DAY_VOL; ################################################## # Usage ################################################## sub show_time { my ($miltime) = @_; $miltime = sprintf("%0.4d",$miltime); my $h = substr($miltime,0,2); my $m = substr($miltime,2,2); return "$h:${m}am" if ($h<=12); $h-=12; "$h:${m}pm"; } sub usage { my $msg; foreach $msg (@_) { print "ERROR: $msg\n"; } print "\n"; print "Usage:\t$PROGNAME [-d] [[+-]|day|night|mute|unmute]\n"; print "\tSet soundcard volume levels\n"; print "\n"; print "\t Specify a numeric volume setting\n"; print "\t[+-] Increase/decrease volume\n"; print "\tday Daytime volume, full level [$DAY_VOL]\n"; print "\tnight Nighttime volume, quieter [$NIGHT_VOL]\n"; print "\tmute Save volume and mute (for phone calls, ..) [$MUTE_VOL]\n"; print "\tunmute Restore volume from last mute\n"; print "\n"; print "\tIf no option, $PROGNAME will toggle between normal vol and mute:\n"; print "\t Between ",show_time($DAY_STARTS)," and ",show_time($DAY_ENDS), ", uses daytime volume [$DAY_VOL]\n"; print "\t Otherwise uses night volume [$NIGHT_VOL]\n"; print "\n"; exit -1; } sub parse_args { my $action; while ($#ARGV>=0) { my $arg=shift(@ARGV); if ($arg =~ /^-h$/) { usage(); } if ($arg =~ /^-d$/) { $MAIN::DEBUG=1; next; } usage("Too many actions specified [$arg and $action]") if (defined($action)); $action=$arg; usage("Unknown action: $action") unless $action =~ /^[-+]?\d+$/ || grep($action eq $_,qw(day night mute unmute)); } $action = $action || "now"; $action="mute" if ($action eq "now" && get_vol()==$NOW_VOL); $action; } ################################################## # Vol code ################################################## sub get_vol { open(GET,"$AUMIX -v query|") || usage("Couldn't run aumix! [$AUMIX]"); my ($l,$r); while () { ($l,$r) = ($1,$2) if (/vol (\d+),\s*(\d+),/); } close(GET); usage("Error running aumix! [$AUMIX: $?]") if $?; usage("Didn't get volume settings from [$AUMIX]??") unless defined $l && defined $r; ($l,$r); } sub set_vol { my ($vol) = @_; system("$AUMIX -v $vol"); usage("Error running aumix! [$AUMIX: $?]") if $?; my $x = int($vol/4); my $o = 25-$x; my $str = "Volume=$vol [".(">"x$x).(" "x$o)."]\n"; $ENV{DISPLAY} = ":0.0" unless ($ENV{DISPLAY}); # cron doesn't set if ($OSD && open(OSD,"|$OSD $OSD_ARGS")) { print OSD " "x5,$str; close(OSD); return unless $?; } print $str; } sub set_restored_vol { my ($l,$r) = @_; print STDERR "Volume levels are unbalanced - saving average of $l,$r\n" if ($l != $r); $l = ($l+$r)/2; open(SAVE,">$SAVE_VOL") || usage("Can't write [$SAVE_VOL]"); print SAVE "$l\n"; close(SAVE); } sub get_restored_vol { open(SAVE,"<$SAVE_VOL") || usage("Can't read [$SAVE_VOL]"); $_ = ; close(SAVE); usage("save_vol file corrupted [$SAVE_VOL]") unless /^(\d+)$/; $1; } ################################################## # Main code ################################################## sub main { my $action = parse_args(); if ($action =~ /^(\d+)$/) { set_vol($1); } elsif ($action =~ /^([+-]\d+)$/) { my $add = $1; set_vol(get_vol()+$add); } elsif ($action eq "day") { set_vol($DAY_VOL); } elsif ($action eq "night") { set_vol($NIGHT_VOL); } elsif ($action eq "mute") { my ($l,$r) = get_vol(); if ($l != $MUTE_VOL || $r != $MUTE_VOL) { set_restored_vol($l,$r); set_vol($MUTE_VOL); } } elsif ($action eq "unmute") { set_vol(get_restored_vol()); } elsif ($action eq "now") { set_vol($NOW_VOL); } } main();