mpd_watcher: automatically reconnect
authorHelmut Grohne <helmut@subdivi.de>
Wed, 12 Mar 2014 08:36:45 +0000 (09:36 +0100)
committerHelmut Grohne <helmut@subdivi.de>
Wed, 12 Mar 2014 08:36:45 +0000 (09:36 +0100)
mpd_watcher.py

index 6cccabe..ce3f8a3 100755 (executable)
@@ -6,6 +6,7 @@ local mpd plays music.
 
 import argparse
 import os
+import socket
 
 from dbus.mainloop.glib import DBusGMainLoop
 from gi.repository import GObject
@@ -14,12 +15,13 @@ import mpd
 import onoff.dbusutils
 
 class MpdWatcher(object):
-    def __init__(self, mpdclient, onoffproxy):
-        self.mpdclient = mpdclient
+    def __init__(self, onoffproxy, mpdaddress=("localhost", 6600)):
+        self.mpdaddress = mpdaddress
+        self.mpdclient = mpd.MPDClient()
         self.onoffproxy = onoffproxy
         self.activatefd = None
         self.statechanged = True
-        GObject.io_add_watch(self.mpdclient, GObject.IO_OUT, self.handle_write)
+        self.do_connect()
 
     def handle_write(self, source, condition):
         if self.statechanged:
@@ -30,32 +32,51 @@ class MpdWatcher(object):
         return False
 
     def handle_read(self, source, condition):
-        if self.statechanged:
-            state = self.mpdclient.fetch_status()["state"]
-            self.statechanged = False
-            if state == "play":
-                if self.activatefd is None:
-                    st, fd = self.onoffproxy.activatefd()
-                    self.activatefd = fd.take()
+        try:
+            if self.statechanged:
+                state = self.mpdclient.fetch_status()["state"]
+                self.statechanged = False
+                if state == "play":
+                    if self.activatefd is None:
+                        st, fd = self.onoffproxy.activatefd()
+                        self.activatefd = fd.take()
+                else:
+                    if self.activatefd is not None:
+                        os.close(self.activatefd)
+                        self.activatefd = None
             else:
-                if self.activatefd is not None:
-                    os.close(self.activatefd)
-                    self.activatefd = None
+                changes = self.mpdclient.fetch_idle()
+                if "player" in changes:
+                    self.statechanged = True
+        except mpd.ConnectionError:
+            self.reconnect()
         else:
-            changes = self.mpdclient.fetch_idle()
-            if "player" in changes:
-                self.statechanged = True
-        GObject.io_add_watch(self.mpdclient, GObject.IO_OUT, self.handle_write)
+            GObject.io_add_watch(self.mpdclient, GObject.IO_OUT, self.handle_write)
         return False
 
+    def reconnect(self):
+        try:
+            self.mpdclient.disconnect()
+        except mpd.ConnectionError:
+            pass
+        GObject.timeout_add(1000, self.do_connect)
+
+    def do_connect(self):
+        try:
+            self.mpdclient.connect(*self.mpdaddress)
+        except socket.error:
+            self.reconnect()
+        else:
+            self.statechanged = True
+            GObject.io_add_watch(self.mpdclient, GObject.IO_OUT, self.handle_write)
+
+
 def main():
     parser = argparse.ArgumentParser(parents=[onoff.dbusutils.dbus_options])
     args = parser.parse_args()
     DBusGMainLoop(set_as_default=True)
     proxy = onoff.dbusutils.get_dbus_proxy(args)
-    client = mpd.MPDClient()
-    client.connect("localhost", 6600)
-    watcher = MpdWatcher(client, proxy)
+    watcher = MpdWatcher(proxy)
     GObject.MainLoop().run()
 
 if __name__ == "__main__":