use the enum module to represent states
[~helmut/onoff.git] / mpd_watcher.py
1 #!/usr/bin/python3
2 """
3 A client to a device given on the commnd line, that is activated whenever the
4 local mpd plays music.
5 """
6
7 import argparse
8 import os
9 import socket
10
11 from dbus.mainloop.glib import DBusGMainLoop
12 from gi.repository import GObject
13 import mpd
14
15 import onoff.dbusutils
16
17 class MpdWatcher(object):
18     def __init__(self, onoffproxy, mpdaddress=("localhost", 6600)):
19         self.mpdaddress = mpdaddress
20         self.mpdclient = mpd.MPDClient()
21         self.onoffproxy = onoffproxy
22         self.activatefd = None
23         self.statechanged = True
24         self.do_connect()
25
26     def handle_write(self, source, condition):
27         if self.statechanged:
28             self.mpdclient.send_status()
29         else:
30             self.mpdclient.send_idle()
31         GObject.io_add_watch(self.mpdclient, GObject.IO_IN, self.handle_read)
32         return False
33
34     def handle_read(self, source, condition):
35         try:
36             if self.statechanged:
37                 state = self.mpdclient.fetch_status()["state"]
38                 self.statechanged = False
39                 if state == "play":
40                     if self.activatefd is None:
41                         st, fd = self.onoffproxy.activatefd()
42                         self.activatefd = fd.take()
43                 else:
44                     if self.activatefd is not None:
45                         os.close(self.activatefd)
46                         self.activatefd = None
47             else:
48                 changes = self.mpdclient.fetch_idle()
49                 if "player" in changes:
50                     self.statechanged = True
51         except mpd.ConnectionError:
52             self.reconnect()
53         else:
54             GObject.io_add_watch(self.mpdclient, GObject.IO_OUT, self.handle_write)
55         return False
56
57     def reconnect(self):
58         try:
59             self.mpdclient.disconnect()
60         except mpd.ConnectionError:
61             pass
62         GObject.timeout_add(1000, self.do_connect)
63
64     def do_connect(self):
65         try:
66             self.mpdclient.connect(*self.mpdaddress)
67         except socket.error:
68             self.reconnect()
69         else:
70             self.statechanged = True
71             GObject.io_add_watch(self.mpdclient, GObject.IO_OUT, self.handle_write)
72
73
74 def main():
75     parser = argparse.ArgumentParser(parents=[onoff.dbusutils.dbus_options])
76     args = parser.parse_args()
77     DBusGMainLoop(set_as_default=True)
78     proxy = onoff.dbusutils.get_dbus_proxy(args)
79     watcher = MpdWatcher(proxy)
80     GObject.MainLoop().run()
81
82 if __name__ == "__main__":
83     main()