#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (c) Thomas Perl <thpinfo.com>.
# All rights reserved.
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
# 
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#

import sys
import os
import gobject
import dbus
import dbus.mainloop.glib
import urlparse

from BaseHTTPServer import HTTPServer
from BaseHTTPServer import BaseHTTPRequestHandler
from threading import Thread

vagalume_commands = [
    'play',
    'skip',
    'stop',
    'love',
    'ban',
    'start',
    'close',
#    'globaltag <TAG>',
#    'artist <ARTIST>',
#    'group <GROUP>',
#    'loved <USER>',
#    'neighbours <USER>',
#    'library <USER>',
#    'playlist <USER>',
#    'playurl <URL>',
    'volumeup',
    'volumedown',
#    'volume <VALUE>',
#    'help',
]

class VagalumeListener(object):
    SERVICE = 'com.igalia.vagalume'
    DEVINTERFACE = 'com.igalia.vagalume'
    PATH = '/com/igalia/vagalume'

    def __init__(self, current_track=None):
        self.current_track = current_track

        dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
        self.__bus = dbus.Bus.get_session()
        self.__bus.add_signal_receiver(self.vagalume_status_changed, 'notify', self.SERVICE, self.SERVICE, self.PATH)

    def vagalume_status_changed(self, status, artist=None, title=None, album=None):
        if self.current_track is not None:
            self.current_track.status = status
            self.current_track.artist = artist
            self.current_track.title = title
            self.current_track.album = album
            self.current_track.notify()

class CurrentTrack(object):
    def __init__(self):
        self.status = None
        self.artist = None
        self.title = None
        self.album = None

    def notify(self):
        pass

def object_string_formatter(s, **kwargs):
    import re
    result = s
    for (key, o) in kwargs.items():
        matches = re.findall(r'\{%s\.([^\}]+)\}' % key, s)
        for attr in matches:
            if hasattr(o, attr):
                from_s = '{%s.%s}' % (key, attr)
                to_s = getattr(o, attr)
                if to_s is None:
                    to_s = '...'
                elif isinstance(to_s, unicode):
                    to_s = to_s.encode('utf-8')
                result = result.replace(from_s, to_s)
    return result

current_track = CurrentTrack()

def vagalumectl(command):
    if command in vagalume_commands:
        args = ['vagalumectl', command]
        if command.startswith('volume'):
            # volumeup/volumedown gets "10" as argument
            args.append('10')
        Thread(target=os.system,args=[' '.join(args)]).start()
    else:
        print >>sys.stderr, 'IGNORING: %s' % command

class RequestHandler(BaseHTTPRequestHandler):
    TEMPLATE = """
<htmL><head><title>&lt;{ct.status}&gt; {ct.artist} - {ct.title} (Vagalume)</title></head>
<body>
<h2>Vagalume Server</h2>
<p>Current status: <b>{ct.status}</b></p>
<h3>Current track</h3>
<ul>
<li>Artist: <b>{ct.artist}</b></li>
<li>Title: <b>{ct.title}</b></li>
<li>Album: <b>{ct.album}</b></li>
</ul>
<hr>
<p><a href="?play">PLAY</a> | <a href="?skip">SKIP</a> | <a href="?stop">STOP</a> | <a href="?volumeup">VOL++</a> | <a href="?volumedown">VOL--</a></p>
<p><a href="?love">LOVE</a> | <a href="?ban">BAN</a> | <a href="?start">START VAGALUME</a> | <a href="?close">CLOSE VAGALUME</a></p>
<hr><address>powered by <a href="http://thpinfo.com/2008/maemo/#vagalumisierung">vagalumisierung.py</a>, &copy; 2008 <a href="http://thpinfo.com/">thp</a></address></body></html>"""
    def do_GET(self):
        global current_track
        command = urlparse.urlparse(self.path)[4]
        if command != '':
            vagalumectl(command)
            refreshtime = 2
        else:
            refreshtime = 5
        self.send_response(200)
        self.send_header('Content-type', 'text/html; encoding=utf-8')
        self.send_header('Refresh', '%d; URL=/'%refreshtime)
        self.end_headers()
        self.wfile.write(object_string_formatter(self.TEMPLATE, ct=current_track))

if __name__ == '__main__':
    gobject.threads_init()
    server = HTTPServer(('', 8242), RequestHandler) # 8242 = "vaga"
    Thread(target=server.serve_forever).start()
    listener = VagalumeListener(current_track)
    loop = gobject.MainLoop()
    loop.run()

