--- /dev/null
+# -*- 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())