diff --git a/ChangeLog b/ChangeLog index 47ca9b8..dfd1a01 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2009-04-20 Thomas Vander Stichele + + * examples/readtoc.py: + Read the toc using cdrdao. Now sets progress based on which + frame it is on. + 2009-04-20 Thomas Vander Stichele * morituri/common/task.py: diff --git a/examples/readtoc.py b/examples/readtoc.py index 115fc71..d9f775c 100644 --- a/examples/readtoc.py +++ b/examples/readtoc.py @@ -1,12 +1,35 @@ # -*- Mode: Python -*- # vi:si:et:sw=4:sts=4:ts=4 +import re import os import subprocess from morituri.common import task from morituri.extern import asyncsub +states = ['START', 'TRACK', 'LEADOUT', 'DONE'] + +_ANALYZING_RE = re.compile(r'^Analyzing track (\d+).*') +_TRACK_RE = re.compile(r""" + ^(?P[\d\s]{2})\s+ # Track + \w+\s+ # Mode + \d\s+ # Flags + \d\d:\d\d:\d\d # Start in HH:MM:FF + \((?P.+)\)\s+ # Start in frames + \d\d:\d\d:\d\d # Length in HH:MM:FF + \(.+\) # Length in frames +""", re.VERBOSE) +_LEADOUT_RE = re.compile(r""" + ^Leadout\s + \w+\s+ # Mode + \d\s+ # Flags + \d\d:\d\d:\d\d # Start in HH:MM:FF + \((?P.+)\) # Start in frames +""", re.VERBOSE) + +# FIXME: handle errors + class ReadTOCTask(task.Task): """ I am a task that reads the TOC of a CD, including pregaps. @@ -14,9 +37,20 @@ class ReadTOCTask(task.Task): description = "Reading TOC..." + + def __init__(self): + self._buffer = "" # accumulate characters + self._lines = [] # accumulate lines + self._lineIndex = 0 # where we are + self._state = 'START' + self._frames = None # number of frames + self._starts = [] # start of each track, in frames + self._track = None # which track are we analyzing? + def start(self, runner): task.Task.start(self, runner) + # FIXME: create a temporary file instead if os.path.exists('/tmp/toc'): os.unlink('/tmp/toc') @@ -29,9 +63,81 @@ class ReadTOCTask(task.Task): self.runner.schedule(1.0, self._read, runner) def _read(self, runner): - print self._popen.recv_err() + ret = self._popen.recv_err() + if not ret: + # FIXME: handle done + self.setProgress(1.0) + print + print 'done' + self.stop() + return + + self._buffer += ret + + # find counter in LEADOUT state + if self._buffer and self._state == 'LEADOUT': + times = self._buffer.split('\r') + position = "" + while len(position) != 8: + position = times.pop() + + frame = self._starts[self._track - 1] \ + + int(position[0:2]) * 60 * 75 \ + + int(position[3:5]) * 75 \ + + int(position[6:8]) + self.setProgress(float(frame) / self._frames) + + if "\n" in self._buffer: + lines = self._buffer.split('\n') + if lines[-1] != "\n": + # last line didn't end yet + self._buffer = lines[-1] + del lines[-1] + else: + self._buffer = "" + self._parse(lines) + self._lines.extend(lines) + self.runner.schedule(1.0, self._read, runner) + def _parse(self, lines): + for line in lines: + #print 'parsing', len(line), line + methodName = "_parse_" + self._state + getattr(self, methodName)(line) + + def _parse_START(self, line): + if line == "Track Mode Flags Start Length": + #print 'Found track line' + self._state = 'TRACK' + + def _parse_TRACK(self, line): + if line.startswith('---'): + return + + m = _TRACK_RE.search(line) + if m: + self._tracks = int(m.group('track')) + self._starts.append(int(m.group('start'))) + + m = _LEADOUT_RE.search(line) + if m: + self._state = 'LEADOUT' + self._frames = int(m.group('start')) + return + + self._tracks = int(line[:2]) + #print '%d tracks found' % self._tracks + + def _parse_LEADOUT(self, line): + m = _ANALYZING_RE.search(line) + if m: + track = int(m.expand('\\1')) + self.description = 'Analyzing track %d...' % track + self._track = track + #self.setProgress(float(track - 1) / self._tracks) + #print 'analyzing', track + def main(): runner = task.SyncRunner()