#!/usr/bin/python
# -*- coding: latin-1 -*-

"""
(c) 2007 Jérôme Sautret <jerome @ sautret.org>
Licensed under the GNU General Public License, version 3.
See the file http://www.gnu.org/licenses/gpl-3.0.txt

Tux warns you when your favorite TV show begins.

Prerequisites:

* python XML library

* xmltv (http://xmltv.org/) installed and configured.
To configure xmltv, run
tv_grab_fr --configure --gui
to select your TV channels (change fr by your country code, see
http://www2.holmlund.se/xmltv-nightly/test_grabbers.html for a list of
tv_grab_* commands)

* the 'at' command must be allowed for current user (see /etc/at.allow
and /etc/at.deny)

Usage:

Edit the CONFIG SECTION below before using, make it executable, then
run this script once a day, without any argument (you can put it into
the crontab). It will then program the announces for the next day.

"""

import sys, os, shutil
from xml.dom.ext.reader import Sax2
from xml import xpath

########################################################
# CONFIG SECTION

# List of TV show titles
TITLES=["Heroes", "Dr House", "Desperate Housewives"]

# xmltv program to use
# (see http://www2.holmlund.se/xmltv-nightly/test_grabbers.html)
TV_GRAB="tv_grab_uk_rt"

# Voice settings
VOICE="SPK_US_FEMALE"
PITCH=120

# What to say to announce a programme
ANNOUNCE="It's time of %(title)s on %(channel)s."

# Path to the xmltv DTD
XMLTV_DTD = "/usr/share/xmltv/xmltv.dtd"


# Config example for France:
#TV_GRAB="tv_grab_fr"
#VOICE="SPK_FR_FEMALE"
#PITCH=120
#ANNOUNCE="C'est l'heure de %(title)s sur %(channel)s."

# END OF CONFIG SECTION
########################################################





########################################################
# ADVANCED CONFIG SECTION

AT_COMMAND="at %(hour)s:%(minute)s %(month)s%(day)s%(year)s"
TMP_DIR="/tmp"
PROG_FILE=TMP_DIR+"/tv.xml"

TV_GRAB_COMMAND = "%(tv_grab)s --offset 1 -days 1 --output %(file)s"

PROGNAME = os.path.abspath(sys.argv[0])

# END OF ADVANCED CONFIG SECTION
########################################################


# Use Unix at command to add an alert
def set_alert(year, month, day, hour, minute, channel, title):
    pipe = os.popen(AT_COMMAND % {'year': year, 'month': month, 'day': day,
                                  'hour': hour, 'minute': minute}
                    , "w")
    pipe.write("%s announce '%s' '%s'" % (PROGNAME, channel.encode('latin-1'), title.encode('latin-1')))
    pipe.close()

# Announce a TV show
def announce(channel, title):
    sys.path.append('/opt/tuxdroid/api/python')
    import tux

    os.system("tuxttsd -d &")
    tux.tux.tts.on_sound_on=tux.tux.cmd.mouth_open
    tux.tux.tts.on_sound_off=tux.tux.cmd.mouth_close
    tux.tux.tts.select_voice(eval("tux."+VOICE), PITCH)
    tux.tux.cmd.wings_off()
    tux.tux.cmd.wings_on(4)
    tux.tux.cmd.mouth_close()
    tux.tux.tts.speak(ANNOUNCE % {"channel": channel, "title": title})
    tux.tux.cmd.mouth_close()
    tux.tux.tts.kill_daemon()

# get a DOM tree from the xlmtv XML file
def getDom(File):
    print "Parsing TV programmes file..."
    reader = Sax2.Reader()
    shutil.copy(XMLTV_DTD, TMP_DIR)
    os.chdir(TMP_DIR)
    return reader.fromStream(File)

# look for title in programmes DOM tree and set an alert for each one found
def set_alerts_for_title(programmes, title):
    print "Looking for "+title+"..."
    nodes = xpath.Evaluate(u'/tv/programme[title="%s"]' % title, programmes.documentElement)
    for node in nodes:
        time = node.getAttribute("start")
        channel_id = node.getAttribute("channel")
        channel_name = xpath.Evaluate('/tv/channel[@id="%s"]/display-name' % channel_id,
                                      programmes.documentElement)[0].firstChild.data
        title = xpath.Evaluate('./title', node)[0].firstChild.data
        print "   Setting alert at " + time + " on channel " + channel_name
        set_alert(time[:4], time[4:6], time[6:8], time[8:10], time[10:12], channel_name, title)

# get programmes withy xmltv and set alerts
def set_alerts():
    os.system(TV_GRAB_COMMAND % {'tv_grab': TV_GRAB, 'file': PROG_FILE})
    programmes = getDom(PROG_FILE)
    for title in TITLES:
        set_alerts_for_title(programmes, title)

#------------------------------------------------------------------------------
# Main
#------------------------------------------------------------------------------
def main():
    if (len(sys.argv) == 1):
        set_alerts()
    elif (len(sys.argv) == 4):
        cmd = sys.argv[1]
        channel = sys.argv[2]
        title = sys.argv[3]
        if (cmd == "announce"):
            announce(channel, title)


if __name__ == "__main__":
    main()
