summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormikeos <mike.osipov@gmail.com>2013-07-11 22:55:38 +0400
committermikeos <mike.osipov@gmail.com>2013-07-11 22:55:38 +0400
commit961637d2c6921b4aec45d46014808abe7b1ac02f (patch)
tree33195c51142a00979c6a89ed5d77f6b51a3fcc83
parent5cabe429103800eb920dec8313451b80ded9111c (diff)
draft
-rw-r--r--.gitignore4
-rw-r--r--cue.py210
2 files changed, 214 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index d2d6f36..0057231 100644
--- a/.gitignore
+++ b/.gitignore
@@ -33,3 +33,7 @@ nosetests.xml
.mr.developer.cfg
.project
.pydevproject
+
+# after vim
+*.swp
+*~
diff --git a/cue.py b/cue.py
new file mode 100644
index 0000000..c8d13a2
--- /dev/null
+++ b/cue.py
@@ -0,0 +1,210 @@
+import sys
+
+def printf(fmt, *args):
+ sys.stdout.write(fmt % args)
+
+class Track:
+ def __init__(self, number, datatype):
+ try:
+ self.number = int(number)
+ except ValueError:
+ raise InvalidCommand("invalid number \"%s\"" % number)
+
+ self.datatype = datatype
+ self.indexes = []
+
+ self.performer = ""
+ self.title = ""
+
+ def get_number():
+ return self.number
+
+class File:
+ def __init__(self, name, filetype):
+ self.name = name
+ self.filetype = filetype
+ self.tracks = []
+
+ def __repr__(self):
+ return self.name
+
+ def get_type(self):
+ return self.filetype
+
+class Cue:
+ def __init__(self):
+ self.performer = ""
+ self.title = ""
+
+ self.tracks = []
+ self.files = []
+
+ def get_tracks(self):
+ return self.tracks
+
+class CueParserError(Exception):
+ pass
+
+class UnknownCommand(CueParserError):
+ pass
+
+class InvalidCommand(CueParserError):
+ pass
+
+class InvalidContext(CueParserError):
+ pass
+
+def check_argc(count):
+ def deco(func):
+ def method(cls, *lst):
+ n = len(lst)
+ if n != count:
+ raise InvalidCommand("%d args expected, got %d" % (count, n))
+ func(cls, *lst)
+ return method
+ return deco
+
+class CueParser:
+ (
+ GENERAL,
+ TRACK
+ FILE,
+ ) = range(3)
+
+ def __init__(self, msg):
+ self.cue = Cue()
+ self.context = self.GENERAL
+ self.commands = {
+ "file": self.parse_file,
+ "track": self.parse_track,
+ "index": self.parse_index,
+ "title": self.parse_title,
+ "performer": self.parse_performer,
+ "flags": self.parse_flags
+ }
+
+ self.msg = msg
+
+ @staticmethod
+ def split_args(args):
+ lst = []
+ quote = None
+ cur = []
+
+ def push():
+ lst.append("".join(cur))
+ cur[:] = []
+
+ for ch in args:
+ if quote:
+ if ch != quote:
+ cur.append(ch)
+ else:
+ quote = None
+ elif ch.isspace():
+ if cur:
+ push()
+ elif ch in ("\"", "'"):
+ quote = ch
+ else:
+ cur.append(ch)
+
+ if quote:
+ raise CueParserError("unclosed quote '%s'" % quote)
+
+ if cur:
+ push()
+
+ return lst
+
+ def get_cue():
+ return cue
+
+ @check_argc(2)
+ def parse_file(self, *args):
+ self.last_file = File(*args)
+ self.cue.files.append(self.last_file)
+ self.context = self.FILE
+
+ @check_argc(2)
+ def parse_track(self, *args):
+ if self.context != self.FILE:
+ raise InvalidContext
+
+ self.last_track = Track(*args)
+ self.cue.tracks.append(self.last_track)
+ self.last_file.tracks.append(self.last_track)
+ self.context = self.TRACK
+
+ def set_prop(self, attr, value, opt):
+ obj = opt.get(self.context)
+ if obj is None:
+ raise InvalidContext
+
+ if getattr(obj, attr):
+ raise InvalidCommand("duplicate")
+
+ setattr(obj, attr, value)
+
+ @check_argc(1):
+ def parse_title(self, title):
+ self.set_prop("title", title, {
+ self.GENERAL: self.cue,
+ self.TRACK: self.last_track
+ })
+
+ @check_argc(1)
+ def parse_performer(self, performer):
+ self.set_prop("performer", performer, {
+ self.GENERAL: self.cue,
+ self.TRACK: self.last_track
+ })
+
+ def parse_flags(self, *flags):
+ if self.context != self.TRACK:
+ raise InvalidContext
+ if self.last_track.indexes:
+ raise InvalidCommand("must appear before any INDEX commands")
+
+ def parse_default(self, args):
+ raise UnknownCommand
+
+ def parse(self, cmd, arg):
+ self.commands.get(cmd.lower(), parse_default)(*self.split_args(arg))
+
+def read_cuesheet(filename):
+ def msg(fmt, args):
+ printf("read_cuesheet %s:%d: ", filename, nline)
+ printf(fmt, args)
+
+ if not fmt.endswith("\n"):
+ printf("\n")
+
+ fp = open(filename)
+ parser = CueParser(msg)
+ nline = 0
+
+ for line in fp.readlines():
+ nline = nline + 1
+ s = line.strip()
+ if not len(s):
+ continue
+
+ data = s.split(None, 1)
+ if len(data) is 1:
+ msg("arg missed")
+ continue
+
+ try:
+ parser.parse(*data)
+ except UnknownCommand:
+ msg("unknown command \"%s\"", data[0])
+ except InvalidContext:
+ msg("invalid context for command \"%s\"", data[0])
+ except InvalidCommand as err:
+ msg("invalid command \"%s\": %s", data[0], err)
+ except CueParserError as err:
+ msg("%s", err)
+
+ fp.close()
+ return parser.get_cue()