X-Git-Url: http://git.kaliko.me/?p=python-musicpd.git;a=blobdiff_plain;f=mpd.py;h=d40b5fab8791291db4e48b174fc97b29989533a8;hp=8810face31f19cc2147815d71f286fca0c0f9c14;hb=a299df609a97947e767e721e0623442b64705ac9;hpb=535e659098997d301a7176e45bfc806bbc5cedb4 diff --git a/mpd.py b/mpd.py index 8810fac..d40b5fa 100644 --- a/mpd.py +++ b/mpd.py @@ -1,18 +1,18 @@ -# Python MPD client library +# python-mpd: Python MPD client library # Copyright (C) 2008-2010 J. Alexander Treuman # -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# python-mpd 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. # -# This program is distributed in the hope that it will be useful, +# python-mpd 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 General Public License for more details. +# GNU Lesser General Public License for more details. # -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# You should have received a copy of the GNU Lesser General Public License +# along with python-mpd. If not, see . import socket @@ -67,6 +67,8 @@ class MPDClient(object): # Playback Option Commands "consume": self._fetch_nothing, "crossfade": self._fetch_nothing, + "mixrampdb": self._fetch_nothing, + "mixrampdelay": self._fetch_nothing, "random": self._fetch_nothing, "repeat": self._fetch_nothing, "setvol": self._fetch_nothing, @@ -114,12 +116,20 @@ class MPDClient(object): # Database Commands "count": self._fetch_object, "find": self._fetch_songs, + "findadd": self._fetch_nothing, "list": self._fetch_list, "listall": self._fetch_database, "listallinfo": self._fetch_database, "lsinfo": self._fetch_database, "search": self._fetch_songs, "update": self._fetch_item, + "rescan": self._fetch_item, + # Sticker Commands + "sticker get": self._fetch_item, + "sticker set": self._fetch_nothing, + "sticker delete": self._fetch_nothing, + "sticker list": self._fetch_list, + "sticker find": self._fetch_songs, # Connection Commands "close": None, "kill": None, @@ -134,6 +144,7 @@ class MPDClient(object): "notcommands": self._fetch_list, "tagtypes": self._fetch_list, "urlhandlers": self._fetch_list, + "decoders": self._fetch_plugins, } def __getattr__(self, attr): @@ -146,6 +157,7 @@ class MPDClient(object): else: command = attr wrapper = self._execute + command = command.replace("_", " ") if command not in self._commands: raise AttributeError("'%s' object has no attribute '%s'" % (self.__class__.__name__, attr)) @@ -154,21 +166,21 @@ class MPDClient(object): def _send(self, command, args): if self._command_list is not None: raise CommandListError("Cannot use send_%s in a command list" % - command) + command.replace(" ", "_")) self._write_command(command, args) self._pending.append(command) def _fetch(self, command, args=None): if self._command_list is not None: raise CommandListError("Cannot use fetch_%s in a command list" % - command) + command.replace(" ", "_")) if self._iterating: raise IteratingError("Cannot use fetch_%s while iterating" % - command) + command.replace(" ", "_")) if not self._pending: raise PendingCommandError("No pending commands to fetch") if self._pending[0] != command: - raise PendingCommandError("%s is not the currently " + raise PendingCommandError("'%s' is not the currently " "pending command" % command) del self._pending[0] retval = self._commands[command] @@ -177,14 +189,15 @@ class MPDClient(object): def _execute(self, command, args): if self._iterating: - raise IteratingError("Cannot execute %s while iterating" % command) + raise IteratingError("Cannot execute '%s' while iterating" % + command) if self._pending: - raise PendingCommandError("Cannot execute %s with " + raise PendingCommandError("Cannot execute '%s' with " "pending commands" % command) retval = self._commands[command] if self._command_list is not None: if not callable(retval): - raise CommandListError("%s not allowed in command list" % + raise CommandListError("'%s' not allowed in command list" % command) self._write_command(command, args) self._command_list.append(retval) @@ -269,20 +282,24 @@ class MPDClient(object): yield obj def _read_command_list(self): - for retval in self._command_list: - yield retval() - self._command_list = None + try: + for retval in self._command_list: + yield retval() + finally: + self._command_list = None self._fetch_nothing() def _iterator_wrapper(self, iterator): - self._iterating = True - for item in iterator: - yield item - self._iterating = False + try: + for item in iterator: + yield item + finally: + self._iterating = False def _wrap_iterator(self, iterator): if not self.iterate: return list(iterator) + self._iterating = True return self._iterator_wrapper(iterator) def _fetch_nothing(self): @@ -311,6 +328,9 @@ class MPDClient(object): def _fetch_objects(self, delimiters): return self._wrap_iterator(self._read_objects(delimiters)) + def _fetch_changes(self): + return self._fetch_objects(["cpos"]) + def _fetch_songs(self): return self._fetch_objects(["file"]) @@ -323,8 +343,8 @@ class MPDClient(object): def _fetch_outputs(self): return self._fetch_objects(["outputid"]) - def _fetch_changes(self): - return self._fetch_objects(["cpos"]) + def _fetch_plugins(self): + return self._fetch_objects(["plugin"]) def _fetch_command_list(self): return self._wrap_iterator(self._read_command_list()) @@ -360,26 +380,26 @@ class MPDClient(object): flags = socket.AI_ADDRCONFIG except AttributeError: flags = 0 - msg = "getaddrinfo returns an empty list" + err = None for res in socket.getaddrinfo(host, port, socket.AF_UNSPEC, socket.SOCK_STREAM, socket.IPPROTO_TCP, flags): af, socktype, proto, canonname, sa = res + sock = None try: sock = socket.socket(af, socktype, proto) sock.connect(sa) - except socket.error, msg: - if sock: + return sock + except socket.error, err: + if sock is not None: sock.close() - sock = None - continue - break - if not sock: - raise socket.error(msg) - return sock + if err is not None: + raise err + else: + raise ConnectionError("getaddrinfo returns an empty list") def connect(self, host, port): - if self._sock: + if self._sock is not None: raise ConnectionError("Already connected") if host.startswith("/"): self._sock = self._connect_unix(host) @@ -400,7 +420,7 @@ class MPDClient(object): self._reset() def fileno(self): - if not self._sock: + if self._sock is None: raise ConnectionError("Not connected") return self._sock.fileno() @@ -418,6 +438,8 @@ class MPDClient(object): def command_list_end(self): if self._command_list is None: raise CommandListError("Not in command list") + if self._iterating: + raise IteratingError("Already iterating over a command list") self._write_command("command_list_end") return self._fetch_command_list()