From e60dbd8f3a9f838baf500154390eeb52a8cbcc40 Mon Sep 17 00:00:00 2001 From: "adrian.sampson" Date: Tue, 24 Mar 2009 01:08:04 +0000 Subject: [PATCH] added path-handling functions; documentation --HG-- extra : convert_revision : svn%3A41726ec3-264d-0410-9c23-a9f1637257cc/trunk%40144 --- beets/player/bpd.py | 54 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/beets/player/bpd.py b/beets/player/bpd.py index 7874d4b63..c0db305e6 100755 --- a/beets/player/bpd.py +++ b/beets/player/bpd.py @@ -50,6 +50,8 @@ log.setLevel(logging.DEBUG) log.addHandler(logging.StreamHandler()) +# Error-handling, exceptions, parameter parsing. + class BPDError(Exception): """An error that should be exposed to the client to the BPD server. @@ -98,6 +100,51 @@ class BPDClose(Exception): """ +# Path-like encoding of string sequences. We use this to simulate the +# directory structure required by the MPD protocol to browse music in +# the library. + +def seq_to_path(seq): + """Encodes a sequence of strings as a path-like string. The + sequence can be recovered exactly using path_to_list. + """ + + out = [] + for s in seq: + out.append(s.replace('\\', '\\\\').replace('/', '\\/')) + return '/'.join(out) + +path_to_list_pattern = re.compile(r'(?:\\/|[^/])*') +def path_to_list(path): + """Takes a path-like string (probably encoded by seq_to_path) and + returns the list of strings it represents. + """ + + # To simplify parsing, ensure that everything is terminated by a + # slash. Note that seq_to_path never added a trailing slash, so + # they are "disallowed" by this encoding. + path += '/' + + out = [] + while path: + + # Search for one path component. + m = path_to_list_pattern.match(s) + if not m: break # Should never happen. + component = m.group(0) + + # Chop off this component and the / that follows it. + path = path[len(component):] + if len(s) >= 1 and s[0] == '/': # Should always be true. + s = s[1:] # chop it off, too + + out.append(component.replace('\\/', '/').replace('\\\\', '\\')) + + return out + + +# Generic server infrastructure, implementing the basic protocol. + class Server(object): """A MPD-compatible music player server. @@ -621,6 +668,10 @@ class SuccessResponse(Response): return RESP_OK + +# A subclass of the basic, protocol-handling server that actually plays +# music. + class BGServer(Server): """A `Server` using GStreamer to play audio and beets to store its library. @@ -750,6 +801,9 @@ class BGServer(Server): super(BGServer, self).cmd_stop() self.player.stop() + +# When run as a script, just start the server. + if __name__ == '__main__': BGServer(beets.Library('library.blb')).run()