improve dbus api
[~helmut/onoff.git] / dbus_service.py
1 #!/usr/bin/env python
2
3 import os
4
5 import dbus
6 import dbus.service
7 from dbus.mainloop.glib import DBusGMainLoop
8 from gi.repository import GObject
9
10 from onoff.common import ST_ACTIVE, ST_TRANSITION
11
12 class OnoffControl(dbus.service.Object):
13     domain = "de.subdivi.onoff"
14     path = "/de/subdivi/onoff"
15
16     def __init__(self, bus, num):
17         busname = dbus.service.BusName(self.domain, bus=bus)
18         dbus.service.Object.__init__(self, busname, "%s/%d" % (self.path, num))
19         self.usecount = 0
20         self.curstate = 0 # empty bitmask
21
22     @dbus.service.signal(domain, signature="q")
23     def changestate(self, st):
24         print("emitting state %d" % st)
25         self.curstate = st
26
27     @dbus.service.method(domain, out_signature="q")
28     def state(self):
29         return self.curstate
30
31     @dbus.service.method(domain, in_signature="q", out_signature="q")
32     def activatetime(self, duration):
33         print("called with duration %d" % duration)
34         self.usecount += 1
35         GObject.timeout_add(duration * 1000, self.unuse)
36         if self.usecount > 1:
37             return self.curstate
38         self.changestate(ST_ACTIVE|ST_TRANSITION)
39         def finish():
40             self.changestate(ST_ACTIVE)
41         GObject.timeout_add(200, finish)
42         return self.curstate
43
44     @dbus.service.method(domain, in_signature="hq", out_signature="q")
45     def activatefd(self, fd, duration):
46         self.usecount += 1
47         fd = fd.take()
48         print("called with fd %d and duration %d" % (fd, duration))
49         def callback(fd, _):
50             print("fd %d completed" % fd)
51             os.close(fd)
52             GObject.timeout_add(duration * 1000, self.unuse)
53             return False
54         GObject.io_add_watch(fd, GObject.IO_HUP|GObject.IO_ERR, callback)
55         self.changestate(ST_ACTIVE)
56         return self.curstate
57
58     def unuse(self):
59         self.usecount -= 1
60         if not self.usecount:
61             self.changestate(0)
62         else:
63             print("%d users left" % self.usecount)
64         return False
65
66
67 def main():
68     DBusGMainLoop(set_as_default=True)
69     bus = dbus.SessionBus()
70     OnoffControl(bus, 5)
71     GObject.MainLoop().run()
72
73 if __name__ == "__main__":
74     main()