#!/usr/bin/python
# -*- coding: UTF-8 -*-
"""
Copyright 2008 Sebastian Kügler, Canonical Ltd, Luka Renko

Authors: 
    Andreas Wenning <awen@awen.dk>

This program is free software; you can redistribute it and/or modify 
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

"""

"""
A frontend to HAL's power features for KDE - Helper application
This application listens for HAL signals and issues dcop-calls to the
kde-power-manager that originally started it. To avoid the need for
kde-power-manager to shut it's helper down, this application
will automatically shut down if it's kde-power-manager isn't running.
"""

import dbus, sys, time
from dbus.mainloop.glib import DBusGMainLoop
import gobject
from dcopext import DCOPClient, DCOPObj, DCOPApp

class GPMHelper():
    def mother_alive(self):
        """Check that our mother is still alive"""
        found = False
        for name in self.dcop.registeredApplications():
            name = str(name)
            if name == self.motherName:
                found = True
        if not found:
            """No mother; commit suicide"""
            print "guidance-power-manager not alive; exiting"
            loop.quit()

    """Called when signal is received"""
    def signal_recv(self, *args):
        if args[0] == "ButtonPressed":
            if args[1] == "brightness-up":
                if time.time()-0.02 <= self.last_brightness_up <= time.time():
                    """Most likely an extra brightness-up call, discarding"""
                    print "Extra brightness-up call discarded"
                    return
                try:
                    ok, foo = self.mother.brightnessUp()
                    if not ok:
                        print "brightnessUp-call failed"
                        return self.mother_alive()
                    self.last_brightness_up = time.time()
                except:
                    print "brightnessUp-call failed"
                    return self.mother_alive()
            elif args[1] == "brightness-down":
                if time.time()-0.02 <= self.last_brightness_down <= time.time():
                    """Most likely an extra brightness-down call, discarding"""
                    print "Extra brightness-down call discarded"
                    return
                try:
                    ok, foo = self.mother.brightnessDown()
                    if not ok:
                        print "brightnessDown-call failed"
                        return self.mother_alive()
                    self.last_brightness_down = time.time()
                except:
                    print "brightnessDown-call failed"
                    return self.mother_alive()
            elif args[1] == "sleep":
                if time.time()-1 <= self.last_sleep <= time.time():
                    """Most likely an extra sleep-call, discarding"""
                    print "Extra sleep-call discarded"
                    return
                try:
                    ok, foo = self.mother.suspend()
                    if not ok:
                        print "suspend-call failed"
                        return self.mother_alive()
                    self.last_sleep = time.time()
                except:
                    print "suspend-call failed"
                    return self.mother_alive()
            elif args[1] == "hibernate":
                if time.time()-1 <= self.last_hibernate <= time.time():
                    """Most likely an extra hibernate-call, discarding"""
                    print "Extra hibernate-call discarded"
                    return
                try:
                    ok, foo = self.mother.hibernate()
                    if not ok:
                        print "hibernate-call failed"
                        return self.mother_alive()
                    self.last_hibernate = time.time()
                except:
                    print "hibernate failed"
                    return self.mother_alive()

    def __init__(self):
        """Connect to HAL"""
        self.dbus_loop = DBusGMainLoop(set_as_default=True)
        self.bus = dbus.SystemBus(mainloop=self.dbus_loop)
        hal_manager_obj = self.bus.get_object("org.freedesktop.Hal",u'/org/freedesktop/Hal/Manager')
        self.hal_manager = dbus.Interface(hal_manager_obj, "org.freedesktop.Hal.Manager")

        """Find button-devices and to connect to"""
        button_devices = self.hal_manager.FindDeviceByCapability("button")
        for device in button_devices:
            self.bus.add_signal_receiver(self.signal_recv,
                                        "Condition",
                                        "org.freedesktop.Hal.Device",
                                        "org.freedesktop.Hal",
                                        device)
        """Let's find our mother"""
        self.dcop = DCOPClient()
        self.dcop.attach()
        found = False
        for name in self.dcop.registeredApplications():
            name = str(name)
            if name.startswith('guidance-'):
                self.motherName = name
                try:
                    self.mother = DCOPObj(name, self.dcop, 'power-manager')
                    found = True
                except:
                    """Do nothing, catched by found=False"""
                break
        if not found:
            """No mother; commit suicide"""
            print "No guidance-power-manager is running"
            sys.exit()

        """Some laptops issue double sleep/hibernate-calls, we need to discard one in that case"""
        self.last_sleep = 0
        self.last_hibernate = 0

        """And multiple brightness calls is also possible"""
        self.last_brightness_up = 0
        self.last_brightness_down = 0

if __name__ == "__main__":
    gpmh = GPMHelper()
    loop = gobject.MainLoop()
    loop.run()
