mpd_watcher: properly schedule all IO via gobject
authorHelmut Grohne <helmut@subdivi.de>
Sun, 21 Jul 2013 16:50:05 +0000 (18:50 +0200)
committerHelmut Grohne <helmut@subdivi.de>
Sun, 21 Jul 2013 16:50:05 +0000 (18:50 +0200)
Otherwise it might block, which would make it impossible to run it in an
existing mainloop that also services different needs.

mpd_watcher.py

index f72ca51..6cccabe 100755 (executable)
@@ -18,27 +18,35 @@ class MpdWatcher(object):
         self.mpdclient = mpdclient
         self.onoffproxy = onoffproxy
         self.activatefd = None
-        self.update_state()
-        self.mpdclient.send_idle()
-        GObject.io_add_watch(self.mpdclient, GObject.IO_IN, self.on_idle)
-
-    def on_idle(self, source, condition):
-        changes = self.mpdclient.fetch_idle()
-        if "player" in changes:
-            self.update_state()
-        self.mpdclient.send_idle()
-        return True # want to be called again
-
-    def update_state(self):
-        state = self.mpdclient.status()["state"]
-        if state == "play":
-            if self.activatefd is None:
-                st, fd = self.onoffproxy.activatefd()
-                self.activatefd = fd.take()
+        self.statechanged = True
+        GObject.io_add_watch(self.mpdclient, GObject.IO_OUT, self.handle_write)
+
+    def handle_write(self, source, condition):
+        if self.statechanged:
+            self.mpdclient.send_status()
+        else:
+            self.mpdclient.send_idle()
+        GObject.io_add_watch(self.mpdclient, GObject.IO_IN, self.handle_read)
+        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()
+            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
+        GObject.io_add_watch(self.mpdclient, GObject.IO_OUT, self.handle_write)
+        return False
 
 def main():
     parser = argparse.ArgumentParser(parents=[onoff.dbusutils.dbus_options])