- (ep.label(), ch.title, ch.url))
-
-UNSET = ["UNSET"]
-
-def parse_list(fn):
- playlist = Playlist()
- season, episode, chapter, ep_i = None, None, None, 1
- vds = {}
- ads = iso = None
- with location(FileLocation(fn, 0)) as floc:
- with open(fn, "r") as f:
- for line in f:
- floc.stepline()
- sline = line.lstrip()
- if sline == "" or sline.startswith(";"): continue
-
- if line.startswith("!"):
- ww = Words(line[1:])
- cmd = ww.nextword()
- check(cmd is not None, "missing command")
-
- if cmd == "season":
- v = ww.nextword();
- check(v is not None, "missing season number")
- if v == "-":
- check(v.rest() is None, "trailing junk")
- season = playlist.add_movies()
- else:
- i = getint(v)
- title = ww.rest()
- season = playlist.add_season(title, i, implicitp = False)
- episode = chapter = None
- ep_i = 1
-
- elif cmd == "movie":
- check(ww.rest() is None, "trailing junk")
- season = playlist.add_movies()
- episode = chapter = None
- ep_i = 1
-
- elif cmd == "epname":
- name = ww.rest()
- check(name is not None, "missing episode name")
- try: sep = name.index(":")
- except ValueError: names = name + "s"
- else: name, names = name[:sep], name[sep + 1:]
- playlist.epname, playlist.epnames = name, names
-
- elif cmd == "epno":
- i = ww.rest()
- check(i is not None, "missing episode number")
- ep_i = getint(i)
-
- elif cmd == "iso":
- fn = ww.rest(); check(fn is not None, "missing filename")
- if fn == "-": iso = None
- else:
- check(OS.path.exists(OS.path.join(ROOT, fn)),
- "iso file `%s' not found" % fn)
- iso = VideoDisc(fn)
-
- elif cmd == "vdir":
- name = ww.nextword(); check(name is not None, "missing name")
- fn = ww.rest(); check(fn is not None, "missing directory")
- if fn == "-":
- try: del vds[name]
- except KeyError: pass
- else:
- vds[name] = VideoDir(fn)
-
- elif cmd == "adir":
- fn = ww.rest(); check(fn is not None, "missing directory")
- if fn == "-": ads = None
- else: ads = AudioDir(fn)
-
- elif cmd == "end":
- break
-
- else:
- raise ExpectedError("unknown command `%s'" % cmd)
+ (label, ch.title, ch.url))
+
+MODE_UNSET = 0
+MODE_SINGLE = 1
+MODE_MULTI = 2
+
+class EpisodeListParser (object):
+
+ def __init__(me, series_wanted = None, chapters_wanted_p = False):
+ me._pl = Playlist()
+ me._cur_episode = me._cur_chapter = None
+ me._series = {}; me._vdirs = {}; me._audirs = {}; me._isos = {}
+ me._series_wanted = series_wanted
+ me._chaptersp = chapters_wanted_p
+ if series_wanted is None: me._mode = MODE_UNSET
+ else: me._mode = MODE_MULTI
+
+ def _bad_keyval(me, cmd, k, v):
+ raise ExpectedError("invalid `!%s' option `%s'" %
+ (cmd, v if k is None else k))
+
+ def _keyvals(me, opts):
+ if opts is not None:
+ for kv in opts.split(","):
+ try: sep = kv.index("=")
+ except ValueError: yield None, kv
+ else: yield kv[:sep], kv[sep + 1:]
+
+ def _set_mode(me, mode):
+ if me._mode == MODE_UNSET:
+ me._mode = mode
+ elif me._mode != mode:
+ raise ExpectedError("inconsistent single-/multi-series usage")
+
+ def _get_series(me, name):
+ if name is None:
+ me._set_mode(MODE_SINGLE)
+ try: series = me._series[None]
+ except KeyError:
+ series = me._series[None] = Series(me._pl)
+ me._pl.nseries += 1
+ else:
+ me._set_mode(MODE_MULTI)
+ series = lookup(me._series, name, "unknown series `%s'" % name)
+ return series
+
+ def _opts_series(me, cmd, opts):
+ name = None
+ for k, v in me._keyvals(opts):
+ if k is None: name = v
+ else: me._bad_keyval(cmd, k, v)
+ return me._get_series(name), name
+
+ def _wantedp(me, name):
+ return me._series_wanted is None or name in me._series_wanted
+
+ def _process_cmd(me, ww):
+
+ cmd = ww.nextword(); check(cmd is not None, "missing command")
+ try: sep = cmd.index(":")
+ except ValueError: opts = None
+ else: cmd, opts = cmd[:sep], cmd[sep + 1:]
+
+ if cmd == "series":
+ name = None
+ for k, v in me._keyvals(opts):
+ if k is None: name = v
+ else: me._bad_keyval(cmd, k, v)
+ check(name is not None, "missing series name")
+ check(name not in me._series, "series `%s' already defined" % name)
+ title = ww.rest(); check(title is not None, "missing title")
+ me._set_mode(MODE_MULTI)
+ me._series[name] = Series(me._pl, title)
+ if me._wantedp(name): me._pl.nseries += 1
+
+ elif cmd == "season":
+ series, sname = me._opts_series(cmd, opts)
+ w = ww.nextword();
+ check(w is not None, "missing season number")
+ if w == "-":
+ check(ww.rest() is None, "trailing junk")
+ if not me._wantedp(sname): return
+ series.add_movies()
+ else:
+ title = ww.rest(); i = getint(w)
+ if not me._wantedp(sname): return
+ series.add_season(ww.rest(), getint(w), implicitp = False)
+ me._cur_episode = me._cur_chapter = None
+ me._pl.done_season()
+
+ elif cmd == "epname":
+ for k, v in me._keyvals(opts): me._bad_keyval("epname", k, v)
+ name = ww.rest(); check(name is not None, "missing episode name")
+ try: sep = name.index(",")
+ except ValueError: names = name + "s"
+ else: name, names = name[:sep], name[sep + 1:]
+ me._pl.epname, me._pl.epnames = name, names
+
+ elif cmd == "epno":
+ series, sname = me._opts_series(cmd, opts)
+ w = ww.rest(); check(w is not None, "missing episode number")
+ epi = getint(w)
+ if not me._wantedp(sname): return
+ series.ensure_season().ep_i = epi
+
+ elif cmd == "iso":
+ _, name = me._opts_series(cmd, opts)
+ fn = ww.rest(); check(fn is not None, "missing filename")
+ if not me._wantedp(name): return
+ if fn == "-": forget(me._isos, name)
+ else:
+ check(OS.path.exists(OS.path.join(ROOT, fn)),
+ "iso file `%s' not found" % fn)
+ me._isos[name] = VideoDisc(fn)
+
+ elif cmd == "vdir":
+ _, name = me._opts_series(cmd, opts)
+ dir = ww.rest(); check(dir is not None, "missing directory")
+ if not me._wantedp(name): return
+ if dir == "-": forget(me._vdirs, name)
+ else: me._vdirs[name] = VideoDir(dir)
+
+ elif cmd == "adir":
+ _, name = me._opts_series(cmd, opts)
+ dir = ww.rest(); check(dir is not None, "missing directory")
+ if not me._wantedp(name): return
+ if dir == "-": forget(me._audirs, name)
+ else: me._audirs[name] = AudioDir(dir)