#!/usr/bin/python

"""
    hotvolume - a simple script that uses alsa to
    adjust the volume and mute/unmute a card. Uses aosd_cat
    for OSD output on screen, making it useful for lightweight
    windowmanagers.

    The hardware volume key codes seem to be standardised across
    manufacturers (at least, they're the same for my hp530 and
    my wife's eeepc), and this script can generate an xbindkeysrc

    You need the following packages installed to use this
    script:

    aosd-cat
    alsa-utils

    Written by R. Rawson-Tetley, Apr 2009
"""

CARD_NUMBER = 0
MIXER = "Master"
VOLUME_UP_INCR = "2dB+"
VOLUME_DOWN_DECR = "2dB-"
MUTE_LOCK = "/tmp/is_muted"
AOSD_FLAGS = "--font=\"bitstream vera sans bold 36\" -f 200 -u 1000 -o 200 &"
OSD_PCT = 1
OSD_COLS = 2
OSD_MODE = OSD_COLS

import os, sys

def usage():
    print """Usage: hotvolume <action>

Where <action> is one of:

up                  Turn up the volume of the first sound card
down                Turn down the volume of the first sound card
mute                Mute or unmute the first sound card

genbindings         Generates the .xbindkeysrc file. 
                    Also includes www support for firefox and
                    xscreensaver locking if hardware lock and
                    www buttons are present.
"""

def checkdeps():
    bins = [ "amixer", "aosd_cat" ]
    for b in bins:
        if not os.path.exists("/usr/bin/%s" % b):
            print "Could not find %s, you need to install it." % b
            sys.exit(1)

def showosd(msg):
    """ Shows the OSD (killing any existing one first) """
    os.system("pkill aosd_cat")
    os.system("echo '%s' | aosd_cat %s" % (msg, AOSD_FLAGS))

def getvolpct():
    """ Returns the volume of the card/mixer as a percentage """
    p = os.popen("amixer -c %d get %s" % (CARD_NUMBER, MIXER), "r")
    lines = p.readlines()
    p.close()
    for i in lines:
        if i.find("%") != -1:
            pos = i.find("%")
            spos = i.find("[", pos - 4) + 1
            print "Pos: %d - %d" % (spos, pos)
            return i[spos:pos]
    return "0"

def getmsg():
    """ Gets the message to show on screen when volume changes up or down """
    if OSD_MODE == OSD_PCT:
        return "%s: %s%%" % (MIXER, getvolpct())
    elif OSD_MODE == OSD_COLS:
        cols = "||||||||||||||||||||||||||||||||||||||||||||||||||||"
        nocols = int(getvolpct()) / 2
        return "%s: %s" % (MIXER, cols[0:nocols])

def doaction(action):
    if action == "up":
        os.system("amixer -c %d set %s %s" % (CARD_NUMBER, MIXER, VOLUME_UP_INCR))
        showosd(getmsg())

    elif action == "down":
        os.system("amixer -c %d set %s %s" % (CARD_NUMBER, MIXER, VOLUME_DOWN_DECR))
        showosd(getmsg())

    elif action == "mute":
        if os.path.exists(MUTE_LOCK):
            muteaction = "unmute"
            os.system("rm %s" % MUTE_LOCK)
        else:
            muteaction="mute"
            os.system("touch %s" % MUTE_LOCK)
        os.system("amixer -c %d set %s %s" % (CARD_NUMBER, MIXER, muteaction))
        showosd(muteaction)

    elif action == "genbindings":
        print """
# Volume buttons
"hotvolume up"
    m:0x0 + c:176
    NoSymbol

"hotvolume down"
    m:0x0 + c:174
    NoSymbol

"hotvolume mute"
    m:0x0 + c:160
    NoSymbol

# Lock button
"xscreensaver-command -lock"
    m:0x0 + c:146
    NoSymbol

# WWW button
"firefox"
    m:0x0 + c:178
    NoSymbol"""



# ENTRY POINT ==================================
checkdeps()
if len(sys.argv) == 1:
    usage()
    sys.exit(1)

doaction(sys.argv[1])

