X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/disorder/blobdiff_plain/f383b2f1d06591099d3b353098bb8b18a973e1ed..79cbb91d611df73fbb24ccae5f858f2dae7d7d18:/python/disorder.py.in diff --git a/python/disorder.py.in b/python/disorder.py.in index 95465c0..0f16c1a 100644 --- a/python/disorder.py.in +++ b/python/disorder.py.in @@ -1,5 +1,5 @@ # -# Copyright (C) 2004, 2005 Richard Kettlewell +# Copyright (C) 2004, 2005, 2007 Richard Kettlewell # # 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 @@ -39,6 +39,11 @@ Example 2: for path in sys.argv[1:]: d.play(path) +See disorder_protocol(5) for details of the communication protocol. + +NB that this code only supports servers configured to use SHA1-based +authentication. If the server demands another hash then it will not be +possible to use this module. """ import re @@ -231,7 +236,7 @@ def _list2dict(l): while True: k = i.next() v = i.next() - d[k] = v + d[str(k)] = v except StopIteration: pass return d @@ -294,7 +299,8 @@ class client: home = pw.pw_dir privconf = _configfile + "." + pw.pw_name passfile = home + os.sep + ".disorder" + os.sep + "passwd" - self._readfile(_configfile) + if os.path.exists(_configfile): + self._readfile(_configfile) if os.path.exists(privconf): self._readfile(privconf) if os.path.exists(passfile) and _userconf: @@ -402,8 +408,14 @@ class client: Arguments: track -- the path of the track to play. + + Returns the ID of the new queue entry. + + Note that queue IDs are unicode strings (because all track information + values are unicode strings). """ - self._simple("play", track) + res, details = self._simple("play", track) + return unicode(details) # because it's unicode in queue() output def remove(self, track): """Remove a track from the queue. @@ -471,7 +483,10 @@ class client: def playing(self): """Return the currently playing track. - If a track is playing then it is returned as a dictionary. + If a track is playing then it is returned as a dictionary. See + disorder_protocol(5) for the meanings of the keys. All keys are + plain strings but the values will be unicode strings. + If no track is playing then None is returned.""" res, details = self._simple("playing") if res % 10 != 9: @@ -493,14 +508,20 @@ class client: """Return a list of recently played tracks. The return value is a list of dictionaries corresponding to - recently played tracks. The oldest track comes first.""" + recently played tracks. The oldest track comes first. + + See disorder_protocol(5) for the meanings of the keys. All keys are + plain strings but the values will be unicode strings.""" return self._somequeue("recent") def queue(self): """Return the current queue. The return value is a list of dictionaries corresponding to - recently played tracks. The next track to be played comes first.""" + recently played tracks. The next track to be played comes first. + + See disorder_protocol(5) for the meanings of the keys. All keys are + plain strings but the values will be unicode strings.""" return self._somequeue("queue") def _somedir(self, command, dir, re): @@ -582,10 +603,13 @@ class client: track -- the track to query key -- the preference to remove - The return value is the preference + The return value is the preference. """ ret, details = self._simple("get", track, key) - return details + if ret == 555: + return None + else: + return details def prefs(self, track): """Get all the preferences for a track. @@ -656,6 +680,14 @@ class client: self._simple("search", _quote(words)) return self._body() + def tags(self): + """List all tags + + The return value is a list of all tags which apply to at least one + track.""" + self._simple("tags") + return self._body() + def stats(self): """Get server statistics. @@ -699,6 +731,21 @@ class client: ret, details = self._simple("move", track, str(delta)) return int(details) + def moveafter(self, target, tracks): + """Move a track in the queue + + Arguments: + target -- target ID or None + tracks -- a list of IDs to move + + If target is '' or is not in the queue then the tracks are moved to + the head of the queue. + + Otherwise the tracks are moved to just after the target.""" + if target is None: + target = '' + self._simple("moveafter", target, *tracks) + def log(self, callback): """Read event log entries as they happen. @@ -755,6 +802,37 @@ class client: ret, details = self._simple("part", track, context, part) return details + def setglobal(self, key, value): + """Set a global preference value. + + Arguments: + key -- the preference name + value -- the new preference value + """ + self._simple("set-global", key, value) + + def unsetglobal(self, key): + """Unset a global preference value. + + Arguments: + key -- the preference to remove + """ + self._simple("set-global", key, value) + + def getglobal(self, key): + """Get a global preference value. + + Arguments: + key -- the preference to look up + + The return value is the preference + """ + ret, details = self._simple("get-global", key) + if ret == 555: + return None + else: + return details + ######################################################################## # I/O infrastructure @@ -809,7 +887,7 @@ class client: # # If an I/O error occurs, disconnect from the server. # - # On success returns response as a (code, details) tuple + # On success or 'normal' errors returns response as a (code, details) tuple # # On error raise operationError if self.state == 'disconnected': @@ -819,7 +897,7 @@ class client: else: cmd = None res, details = self._response() - if res / 100 == 2: + if res / 100 == 2 or res == 555: return res, details raise operationError(res, details, cmd)