]> kaliko git repositories - python-musicpdaio.git/commitdiff
Initial import
authorkaliko <kaliko@azylum.org>
Wed, 22 Apr 2015 13:31:08 +0000 (15:31 +0200)
committerkaliko <kaliko@azylum.org>
Wed, 22 Apr 2015 13:31:08 +0000 (15:31 +0200)
musicpdasio.py [new file with mode: 0644]

diff --git a/musicpdasio.py b/musicpdasio.py
new file mode 100644 (file)
index 0000000..3848ecd
--- /dev/null
@@ -0,0 +1,122 @@
+# -*- coding: utf-8 -*-
+#
+# python-musicpd: Python MPD client library
+# Copyright (C) 2014-2015  Kaliko Jack <kaliko@azylum.org>
+#
+# python-musicpdasio is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# python-musicpd is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with python-musicpd.  If not, see <http://www.gnu.org/licenses/>.
+
+try:
+    import asyncio
+except ImportError:
+    print('Failed to import asyncio, need python >= 3.4')
+
+import sys
+
+HELLO_PREFIX = "OK MPD "
+ERROR_PREFIX = "ACK "
+SUCCESS = "OK"
+NEXT = "list_OK"
+
+
+class MPDError(Exception):
+    pass
+
+class ConnectionError(MPDError):
+    pass
+
+class ProtocolError(MPDError):
+    pass
+
+class CommandError(MPDError):
+    pass
+
+class CommandListError(MPDError):
+    pass
+
+class PendingCommandError(MPDError):
+    pass
+
+class IteratingError(MPDError):
+    pass
+
+loop = asyncio.get_event_loop()
+
+class Response:
+    def __init__(self):
+        self.version = None
+        self.resp = ''
+        self.err = None
+
+    def __repr__(self):
+        return '{0}, {1}… ({2})'.format(self.err, self.resp[:15], self.version)
+
+class MPDProto(asyncio.Protocol):
+    def __init__(self, future, payload):
+        self.future = future
+        self.payload = payload
+        self.sess = Response()
+
+    def connection_made(self, transport):
+        self.transport = transport
+        self.transport.write(bytes('{}\n'.format(self.payload), 'utf-8'))
+
+    def data_received(self, data):
+        rcv = data.decode('utf-8')
+        if '\n' not in rcv:
+            self.sess.err = 'Connection lost while reading line'
+            self.future.set_result(self.sess)
+            raise ConnectionError("Connection lost while reading line")
+
+        rcv = rcv.strip('\n')
+
+        if rcv.startswith(HELLO_PREFIX):
+            self.sess.version = rcv[len(HELLO_PREFIX):]
+            return
+        self.transport.close()
+
+        # set the result on the Future so that the main() coroutine can
+        # resume
+        if rcv.startswith(ERROR_PREFIX):
+            self.sess.err = rcv[len(ERROR_PREFIX):].strip()
+            self.future.set_result(self.sess)
+            return
+        else:
+            self.sess.resp = rcv
+            self.future.set_result(self.sess)
+
+def command(payload):
+    future = asyncio.Future()
+    if payload:
+        cli = MPDProto(future, payload)
+        # kick off a task to create the connection to MPD.
+        asyncio.async(loop.create_connection(lambda: cli, host='192.168.0.20', port=6600))
+    else:
+        future.set_result((None, None, None))
+
+    # return the future for the main() coroutine to wait on.
+    return future
+
+
+def main():
+    """main"""
+    import logging
+    logging.basicConfig(level=logging.DEBUG)
+    res = yield from command('currentsongt')
+    if res.err:
+        raise CommandError(res.err)
+    print(res)
+    print(res.resp)
+
+if __name__ == '__main__':
+    loop.run_until_complete(main())