[SCM] morituri/master: * morituri/image/table.py: Add logging. Add methods to clear a table of files, and to absolutize indexes as long as the source is the same file, and to set a File on a given index, adjusting all following indexes that match the duration, and check if the IndexTable has all information for a TOC. * morituri/image/toc.py: Add logging. Use a counter for the source. Fix up index offset calculation. * morituri/program/cdrdao.py: Use a real IndexTable as the result, instead of a TocFile. * morituri/image/cue.py: Use a real IndexTable to store tracks. * morituri/test/test_image_toc.py: The toc file now has a table which has the tracks. Fix the tests to adjust for wrong index calculations. * morituri/test/test_image_cue.py: * morituri/test/test_image_image.py: * morituri/image/image.py: The cue file now has a table which has the tracks. * morituri/test/test_image_table.py: Add assertions to make sure when the table can serve as a TOC. * examples/readdisc.py: Adjust for changes. Fix up to include AccurateRip results. First time we can do a complete normal rip including verifying against AccurateRip results!
js at users.alioth.debian.org
js at users.alioth.debian.org
Sun Oct 19 20:08:57 UTC 2014
The following commit has been merged in the master branch:
commit 2f464207dbe50f3179f207ae318e4147e950f327
Author: Thomas Vander Stichele <thomas (at) apestaart (dot) org>
Date: Tue May 5 10:01:41 2009 +0000
* morituri/image/table.py:
Add logging.
Add methods to clear a table of files, and to absolutize indexes
as long as the source is the same file, and to set a File on a
given index, adjusting all following indexes that match the
duration, and check if the IndexTable has all information for a TOC.
* morituri/image/toc.py:
Add logging.
Use a counter for the source.
Fix up index offset calculation.
* morituri/program/cdrdao.py:
Use a real IndexTable as the result, instead of a TocFile.
* morituri/image/cue.py:
Use a real IndexTable to store tracks.
* morituri/test/test_image_toc.py:
The toc file now has a table which has the tracks.
Fix the tests to adjust for wrong index calculations.
* morituri/test/test_image_cue.py:
* morituri/test/test_image_image.py:
* morituri/image/image.py:
The cue file now has a table which has the tracks.
* morituri/test/test_image_table.py:
Add assertions to make sure when the table can serve as a TOC.
* examples/readdisc.py:
Adjust for changes. Fix up to include AccurateRip results.
First time we can do a complete normal rip including verifying
against AccurateRip results!
diff --git a/ChangeLog b/ChangeLog
index 2b20081..f3ef80b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,35 @@
2009-05-05 Thomas Vander Stichele <thomas at apestaart dot org>
+ * morituri/image/table.py:
+ Add logging.
+ Add methods to clear a table of files, and to absolutize indexes
+ as long as the source is the same file, and to set a File on a
+ given index, adjusting all following indexes that match the
+ duration, and check if the IndexTable has all information for a TOC.
+ * morituri/image/toc.py:
+ Add logging.
+ Use a counter for the source.
+ Fix up index offset calculation.
+ * morituri/program/cdrdao.py:
+ Use a real IndexTable as the result, instead of a TocFile.
+ * morituri/image/cue.py:
+ Use a real IndexTable to store tracks.
+ * morituri/test/test_image_toc.py:
+ The toc file now has a table which has the tracks.
+ Fix the tests to adjust for wrong index calculations.
+ * morituri/test/test_image_cue.py:
+ * morituri/test/test_image_image.py:
+ * morituri/image/image.py:
+ The cue file now has a table which has the tracks.
+ * morituri/test/test_image_table.py:
+ Add assertions to make sure when the table can serve as a TOC.
+ * examples/readdisc.py:
+ Adjust for changes. Fix up to include AccurateRip results.
+ First time we can do a complete normal rip including verifying
+ against AccurateRip results!
+
+2009-05-05 Thomas Vander Stichele <thomas at apestaart dot org>
+
* examples/readdisc.py:
* morituri/image/table.py:
* morituri/test/test_image_table.py:
diff --git a/examples/readdisc.py b/examples/readdisc.py
index 8a7c679..40b52da 100644
--- a/examples/readdisc.py
+++ b/examples/readdisc.py
@@ -121,9 +121,11 @@ def main(argv):
if not ptable.object:
t = cdrdao.ReadIndexTableTask()
function(runner, t)
- ptable.persist(t.toc)
+ ptable.persist(t.table)
itable = ptable.object
+ assert itable.hasTOC()
+
lastTrackStart = 0
for i, track in enumerate(itable.tracks):
@@ -139,36 +141,16 @@ def main(argv):
if t.checksum:
print 'Checksums match for track %d' % (i + 1)
- ittrack = table.ITTrack(i + 1)
- # we know the .toc file represents a single wav rip, so all offsets
- # are absolute since beginning of disc
-
- # copy over indexes, adjusting the offset
- tocTrack = itable.tracks[i]
-
- # first copy over index 0 if there is any
- try:
- sector, _ = tocTrack.getIndex(0)
- ittrack.index(0, path=path, relative=sector - lastTrackStart)
- except KeyError:
- pass
- lastTrackStart, _ = tocTrack.getIndex(1)
-
- indexes = itable.tracks[i]._indexes
- numbers = indexes.keys()
- numbers.sort()
- if 0 in numbers:
- del numbers[0]
- for number in numbers:
- sector, _ = tocTrack.getIndex(number)
- ittrack.index(number, path=path, relative=sector - lastTrackStart)
- #itable.tracks.append(ittrack)
-
-
-
- # FIXME: this is the part where our IndexTable reader should convert
- # a .toc file to a IndexTable we can dump .cue from
- print ittoc.cue()
+ # overlay this rip onto the IndexTable
+ itable.setFile(i + 1, 1, path, ittoc.getTrackLength(i + 1))
+
+ print itable.tracks
+ for t in itable.tracks:
+ print t, t.indexes.values()
+
+ handle = open('morituri.cue', 'w')
+ handle.write(itable.cue())
+ handle.close()
# verify using accuraterip
print "CDDB disc id", itable.getCDDBDiscId()
@@ -196,7 +178,55 @@ def main(argv):
responses[0].cddbDiscId
-
+ # FIXME: put accuraterip verification into a separate task/function
+ # and apply here
+ cueImage = image.Image('morituri.cue')
+ verifytask = image.ImageVerifyTask(cueImage)
+ cuetask = image.AccurateRipChecksumTask(cueImage)
+ function(runner, verifytask)
+ function(runner, cuetask)
+
+ response = None # track which response matches, for all tracks
+
+ # loop over tracks
+ for i, checksum in enumerate(cuetask.checksums):
+ status = 'rip NOT accurate'
+
+ confidence = None
+ archecksum = None
+
+ # match against each response's checksum
+ for j, r in enumerate(responses):
+ if "%08x" % checksum == r.checksums[i]:
+ if not response:
+ response = r
+ else:
+ assert r == response, \
+ "checksum %s for %d matches wrong response %d, "\
+ "checksum %s" % (
+ checksum, i + 1, j + 1, response.checksums[i])
+ status = 'rip accurate '
+ archecksum = checksum
+ confidence = response.confidences[i]
+
+ c = "(not found)"
+ ar = "(not in database)"
+ if responses:
+ if not response:
+ print 'ERROR: none of the responses matched.'
+ else:
+ maxConfidence = max(r.confidences[i] for r in responses)
+
+ c = "(confidence %3d)" % maxConfidence
+ if confidence is not None:
+ if confidence < maxConfidence:
+ c = "(confidence %3d of %3d)" % (confidence, maxConfidence)
+
+ ar = ", AR [%s]" % response.checksums[i]
+ print "Track %2d: %s %s [%08x]%s" % (
+ i + 1, status, c, checksum, ar)
+
+
main(sys.argv)
diff --git a/morituri/image/cue.py b/morituri/image/cue.py
index 53fea20..11307d3 100644
--- a/morituri/image/cue.py
+++ b/morituri/image/cue.py
@@ -58,12 +58,18 @@ _INDEX_RE = re.compile(r"""
class CueFile(object, log.Loggable):
+ """
+ I represent a .cue file as an object.
+
+ @type table: L{table.IndexTable}
+ @ivar table: the index table.
+ """
def __init__(self, path):
self._path = path
self._rems = {}
self._messages = []
- self.tracks = []
self.leadout = None
+ self.table = table.IndexTable()
def parse(self):
state = 'HEADER'
@@ -109,7 +115,7 @@ class CueFile(object, log.Loggable):
self.debug('found track %d', trackNumber)
currentTrack = table.ITTrack(trackNumber)
- self.tracks.append(currentTrack)
+ self.table.tracks.append(currentTrack)
continue
# look for INDEX lines
@@ -145,13 +151,13 @@ class CueFile(object, log.Loggable):
# returns track length in frames, or -1 if can't be determined and
# complete file should be assumed
# FIXME: this assumes a track can only be in one file; is this true ?
- i = self.tracks.index(track)
- if i == len(self.tracks) - 1:
+ i = self.table.tracks.index(track)
+ if i == len(self.table.tracks) - 1:
# last track, so no length known
return -1
thisIndex = track.indexes[1] # FIXME: could be more
- nextIndex = self.tracks[i + 1].indexes[1] # FIXME: could be 0
+ nextIndex = self.table.tracks[i + 1].indexes[1] # FIXME: could be 0
c = thisIndex.counter
if c is not None and c == nextIndex.counter:
diff --git a/morituri/image/image.py b/morituri/image/image.py
index 50f0080..34afc0a 100644
--- a/morituri/image/image.py
+++ b/morituri/image/image.py
@@ -73,19 +73,19 @@ class Image(object, log.Loggable):
# CD's have a standard lead-in time of 2 seconds;
# checksums that use it should add it there
- offset = self.cue.tracks[0].getIndex(1).relative
+ offset = self.cue.table.tracks[0].getIndex(1).relative
tracks = []
- for i in range(len(self.cue.tracks)):
- length = self.cue.getTrackLength(self.cue.tracks[i])
+ for i in range(len(self.cue.table.tracks)):
+ length = self.cue.getTrackLength(self.cue.table.tracks[i])
if length == -1:
length = verify.lengths[i + 1]
t = table.ITTrack(i + 1, audio=True)
tracks.append(t)
# FIXME: this probably only works for non-compliant .CUE files
# where pregap is put at end of previous file
- t.index(1, absolute=offset, path=self.cue.tracks[i].getIndex(1).path,
+ t.index(1, absolute=offset, path=self.cue.table.tracks[i].getIndex(1).path,
relative=0)
offset += length
@@ -107,15 +107,15 @@ class AccurateRipChecksumTask(task.MultiSeparateTask):
cue = image.cue
self.checksums = []
- self.debug('Checksumming %d tracks' % len(cue.tracks))
- for trackIndex, track in enumerate(cue.tracks):
+ self.debug('Checksumming %d tracks' % len(cue.table.tracks))
+ for trackIndex, track in enumerate(cue.table.tracks):
index = track.indexes[1]
length = cue.getTrackLength(track)
self.debug('track %d has length %d' % (trackIndex + 1, length))
path = image.getRealPath(index.path)
checksumTask = checksum.AccurateRipChecksumTask(path,
- trackNumber=trackIndex + 1, trackCount=len(cue.tracks),
+ trackNumber=trackIndex + 1, trackCount=len(cue.table.tracks),
frameStart=index.relative * checksum.SAMPLES_PER_FRAME,
frameLength=length * checksum.SAMPLES_PER_FRAME)
self.addTask(checksumTask)
@@ -176,7 +176,7 @@ class ImageVerifyTask(task.MultiSeparateTask):
self._tasks = []
self.lengths = {}
- for trackIndex, track in enumerate(cue.tracks):
+ for trackIndex, track in enumerate(cue.table.tracks):
self.debug('verifying track %d', trackIndex + 1)
index = track.indexes[1]
length = cue.getTrackLength(track)
diff --git a/morituri/image/table.py b/morituri/image/table.py
index 7775d0e..924fb08 100644
--- a/morituri/image/table.py
+++ b/morituri/image/table.py
@@ -29,7 +29,9 @@ import struct
import gst
-from morituri.common import task, checksum, common
+from morituri.common import task, checksum, common, log
+
+from morituri.test import common as tcommon
class DeleteMeTrack:
"""
@@ -249,12 +251,12 @@ class Index:
self.counter = counter
def __repr__(self):
- return '<Index %02d, absolute %r, path %r, relative %r>' % (
- self.number, self.absolute, self.path, self.relative)
+ return '<Index %02d, absolute %r, path %r, relative %r, counter %r>' % (
+ self.number, self.absolute, self.path, self.relative, self.counter)
-class IndexTable:
+class IndexTable(object, log.Loggable):
"""
- I represent the Table of Contents of a CD.
+ I represent a table of indexes on a CD.
@ivar tracks: tracks on this CD
@type tracks: list of L{ITTrack}
@@ -417,6 +419,140 @@ class IndexTable:
common.framesToMSF(index.relative)))
lines.append("")
+
return "\n".join(lines)
+ ### methods that modify the table
+ def clearFiles(self):
+ """
+ Clear all file backings.
+ Resets indexes paths and relative offsets.
+ """
+ # FIXME: do a loop over track indexes better, with a pythonic
+ # construct that allows you to do for t, i in ...
+ t = self.tracks[0].number
+ index = self.tracks[0].getFirstIndex()
+ i = index.number
+ # the first cut is the deepest
+ counter = index.counter
+
+ self.debug('clearing path')
+ while True:
+ track = self.tracks[t - 1]
+ index = track.getIndex(i)
+ self.debug('Clearing path on track %d, index %d', t, i)
+ index.path = None
+ index.relative = None
+ try:
+ t, i = self.getNextTrackIndex(t, i)
+ except IndexError:
+ break
+
+
+ def setFile(self, track, index, path, length):
+ """
+ Sets the given file as the source from the given index on.
+ Will loop over all indexes that fall within the given length,
+ to adjust the path.
+
+ Assumes all indexes have an absolute offset and will raise if not.
+ """
+ t = self.tracks[track - 1]
+ i = t.indexes[index]
+ start = i.absolute
+ assert start is not None, "index %r is missing absolute offset" % i
+ end = start + length
+
+ # FIXME: check border conditions here, esp. wrt. toc's off-by-one bug
+ while i.absolute <= end:
+ self.debug('Setting path and relative on track %d, index %d',
+ track, index)
+ i.path = path
+ i.relative = i.absolute - start
+ try:
+ track, index = self.getNextTrackIndex(track, index)
+ t = self.tracks[track - 1]
+ i = t.indexes[index]
+ except IndexError:
+ break
+
+ def absolutize(self):
+ """
+ Calculate absolute offsets on indexes as much as possible.
+ Only possible for as long as tracks draw from the same file.
+ """
+ t = self.tracks[0].number
+ index = self.tracks[0].getFirstIndex()
+ i = index.number
+ # the first cut is the deepest
+ counter = index.counter
+
+ self.debug('absolutizing')
+ while True:
+ if index.counter is None:
+ self.debug('Track %d, index %d has no counter', t, i)
+ break
+ if index.counter != counter:
+ self.debug('Track %d, index %d has a different counter', t, i)
+ break
+ track = self.tracks[t - 1]
+ index = track.getIndex(i)
+ assert track.number == t
+ assert index.number == i
+ self.debug('Setting absolute offset %d on track %d, index %d',
+ index.relative, t, i)
+ index.absolute = index.relative
+ try:
+ t, i = self.getNextTrackIndex(t, i)
+ except IndexError:
+ break
+
+ ### lookups
+ def getNextTrackIndex(self, track, index):
+ """
+ Return the next track and index.
+
+ @param track: track number, 1-based
+ @raises IndexError: on last index
+
+ @rtype: tuple of (int, int)
+ """
+ t = self.tracks[track - 1]
+ indexes = t.indexes.keys()
+ position = indexes.index(index)
+
+ if position + 1 < len(indexes):
+ return track, indexes[position + 1]
+
+ track += 1
+ if track > len(self.tracks):
+ raise IndexError, "No index beyond track %d, index %d" % (
+ track - 1, index)
+
+ t = self.tracks[track - 1]
+ indexes = t.indexes.keys()
+
+ return track, indexes[0]
+
+
+ # various tests for types of IndexTable
+ def hasTOC(self):
+ """
+ Check if the Index Table has a complete TOC.
+ a TOC is a list of all tracks and their Index 01, with absolute
+ offsets, as well as the leadout.
+ """
+ if not self.leadout:
+ self.debug('no leadout, no TOC')
+ return False
+
+ for t in self.tracks:
+ if 1 not in t.indexes.keys():
+ self.debug('no index 1, no TOC')
+ return False
+ if t.indexes[1].absolute is None:
+ self.debug('no absolute index 1, no TOC')
+ return False
+
+ return True
diff --git a/morituri/image/toc.py b/morituri/image/toc.py
index 754e13e..879e5d3 100644
--- a/morituri/image/toc.py
+++ b/morituri/image/toc.py
@@ -27,7 +27,8 @@ Reading .toc files
import os
import re
-from morituri.common import common
+from morituri.common import common, log
+from morituri.image import table
# header
_CATALOG_RE = re.compile(r'^CATALOG "(?P<catalog>\d+)"$')
@@ -64,16 +65,17 @@ _INDEX_RE = re.compile(r"""
\s(?P<offset>.+)$ # start offset
""", re.VERBOSE)
-class TocFile(object):
+class TocFile(object, log.Loggable):
def __init__(self, path):
self._path = path
self._messages = []
- self.tracks = []
+ self.table = table.IndexTable()
def parse(self):
state = 'HEADER'
currentFile = None
currentTrack = None
+ counter = 0
trackNumber = 0
indexNumber = 0
currentOffset = 0 # running absolute offset of where each track starts
@@ -100,8 +102,8 @@ class TocFile(object):
# handle index 1 of previous track, if any
if currentTrack:
- currentTrack.index(1, currentOffset + pregapLength,
- currentFile)
+ currentTrack.index(1, path=currentFile.path,
+ relative=currentOffset + pregapLength, counter=counter)
trackNumber += 1
currentOffset += currentLength
@@ -109,13 +111,18 @@ class TocFile(object):
indexNumber = 1
trackMode = m.group('mode')
- currentTrack = Track(trackNumber)
- self.tracks.append(currentTrack)
+ # FIXME: track mode
+ currentTrack = table.ITTrack(trackNumber)
+ self.table.tracks.append(currentTrack)
continue
# look for SILENCE lines
m = _SILENCE_RE.search(line)
if m:
+ if currentFile is not None:
+ self.debug('SILENCE after FILE, increasing counter')
+ counter += 1
+ currentFile = None
length = m.group('length')
currentLength += common.msfToFrames(length)
@@ -125,6 +132,13 @@ class TocFile(object):
filePath = m.group('name')
start = m.group('start')
length = m.group('length')
+ self.debug('FILE %s, start %r, length %r',
+ filePath, common.msfToFrames(start),
+ common.msfToFrames(length))
+ if not currentFile or filePath != currentFile.path:
+ counter += 1
+ self.debug('track %d, switched to new FILE, increased counter to %d',
+ trackNumber, counter)
currentFile = File(filePath, start, length)
#currentOffset += common.msfToFrames(start)
currentLength += common.msfToFrames(length)
@@ -138,8 +152,9 @@ class TocFile(object):
continue
length = common.msfToFrames(m.group('length'))
- currentTrack.index(0, currentOffset, currentFile)
- currentLength += length
+ currentTrack.index(0, path=currentFile.path,
+ relative=currentOffset - length, counter=counter)
+ #currentLength += length
pregapLength = length
# look for INDEX lines
@@ -149,11 +164,13 @@ class TocFile(object):
self.message(number, 'INDEX without preceding TRACK')
indexNumber += 1
offset = common.msfToFrames(m.group('offset'))
- currentTrack.index(indexNumber, offset, currentFile)
+ currentTrack.index(indexNumber, path=currentFile.path,
+ relative=offset, counter=counter)
# handle index 1 of final track, if any
if currentTrack:
- currentTrack.index(1, currentOffset + pregapLength, currentFile)
+ currentTrack.index(1, path=currentFile.path,
+ relative=currentOffset + pregapLength, counter=counter)
def message(self, number, message):
"""
@@ -167,16 +184,18 @@ class TocFile(object):
# returns track length in frames, or -1 if can't be determined and
# complete file should be assumed
# FIXME: this assumes a track can only be in one file; is this true ?
- i = self.tracks.index(track)
- if i == len(self.tracks) - 1:
+ i = self.table.tracks.index(track)
+ if i == len(self.table.tracks) - 1:
# last track, so no length known
return -1
- thisIndex = track._indexes[1] # FIXME: could be more
- nextIndex = self.tracks[i + 1]._indexes[1] # FIXME: could be 0
+ thisIndex = track.indexes[1] # FIXME: could be more
+ nextIndex = self.table.tracks[i + 1].indexes[1] # FIXME: could be 0
- if thisIndex[1] == nextIndex[1]: # same file
- return nextIndex[0] - thisIndex[0]
+ c = thisIndex.counter
+ if c is not None and c == nextIndex.counter:
+ # they belong to the same source, so their relative delta is length
+ return nextIndex.relative - thisIndex.relative
# FIXME: more logic
return -1
@@ -218,15 +237,15 @@ class File:
"""
def __init__(self, path, start, length):
self.path = path
- self.start = start
- self.length = length
+ #self.start = start
+ #self.length = length
def __repr__(self):
return '<File "%s">' % (self.path, )
# FIXME: add type ? separate AUDIO from others
-class Track:
+class DeleteMeTrack:
"""
I represent a track in a cue file.
I have index points.
diff --git a/morituri/program/cdrdao.py b/morituri/program/cdrdao.py
index f940040..ac33d39 100644
--- a/morituri/program/cdrdao.py
+++ b/morituri/program/cdrdao.py
@@ -69,7 +69,7 @@ class OutputParser(object, log.Loggable):
self._track = None # which track are we analyzing?
self._task = taskk
- self.toc = table.IndexTable() # the index table for the TOC
+ self.table = table.IndexTable() # the index table for the TOC
def read(self, bytes):
self.log('received %d bytes in state %s', len(bytes), self._state)
@@ -95,7 +95,7 @@ class OutputParser(object, log.Loggable):
# we need both a position reported and an Analyzing line
# to have been parsed to report progress
if m and self._track is not None:
- track = self.toc.tracks[self._track - 1]
+ track = self.table.tracks[self._track - 1]
frame = (track.getIndex(1).absolute or 0) \
+ int(m.group('hh')) * 60 * 75 \
+ int(m.group('mm')) * 75 \
@@ -146,7 +146,7 @@ class OutputParser(object, log.Loggable):
self._tracks = int(m.group('track'))
track = table.ITTrack(self._tracks)
track.index(1, absolute=int(m.group('start')))
- self.toc.tracks.append(track)
+ self.table.tracks.append(track)
self.debug('Found track %d', self._tracks)
m = _LEADOUT_RE.search(line)
@@ -155,7 +155,7 @@ class OutputParser(object, log.Loggable):
self._state = 'LEADOUT'
self._frames = int(m.group('start'))
self.debug('Found leadout at offset %r', self._frames)
- self.toc.leadout = self._frames
+ self.table.leadout = self._frames
self.info('%d tracks found', self._tracks)
return
@@ -238,21 +238,21 @@ class ReadIndexTableTask(CDRDAOTask):
"""
I am a task that reads all indexes of a CD.
- @ivar toc: the .toc file object
- @type toc: L{toc.TOC}
+ @ivar table: the index table
+ @type table: L{table.IndexTable}
"""
description = "Scanning indexes..."
+ table = None
def __init__(self):
CDRDAOTask.__init__(self)
self.parser = OutputParser(self)
- self.toc = None # result
- (fd, self._toc) = tempfile.mkstemp(suffix='.morituri')
+ (fd, self._tocfilepath) = tempfile.mkstemp(suffix='.morituri')
os.close(fd)
- os.unlink(self._toc)
+ os.unlink(self._tocfilepath)
- self.options = ['read-toc', self._toc]
+ self.options = ['read-toc', self._tocfilepath]
def readbytes(self, bytes):
self.parser.read(bytes)
@@ -260,13 +260,34 @@ class ReadIndexTableTask(CDRDAOTask):
def done(self):
# FIXME: instead of reading only a TOC, output a complete IndexTable
# by merging the TOC info.
- self.toc = toc.TocFile(self._toc)
- self.toc.parse()
- os.unlink(self._toc)
+ self._tocfile = toc.TocFile(self._tocfilepath)
+ self._tocfile.parse()
+ os.unlink(self._tocfilepath)
+ self.table = self._tocfile.table
+
+ # we know the .toc file represents a single wav rip, so all offsets
+ # are absolute since beginning of disc
+ self.table.absolutize()
+ # we unset relative since there is no real file backing this toc
+ for t in self.table.tracks:
+ for i in t.indexes.values():
+ #i.absolute = i.relative
+ i.relative = None
+
+ # copy the leadout from the parser's table
+ # FIXME: how do we get the length of the last audio track in the case
+ # of a data track ?
+ self.table.leadout = self.parser.table.leadout
+
+ # we should have parsed it from the initial output
+ assert self.table.leadout is not None
class ReadTOCTask(CDRDAOTask):
"""
I am a task that reads the TOC of a CD, without pregaps.
+
+ @ivar table: the index table that matches the TOC.
+ @type table: L{table.IndexTable}
"""
description = "Reading TOC..."
@@ -287,4 +308,6 @@ class ReadTOCTask(CDRDAOTask):
def done(self):
os.unlink(self._toc)
- self.table = self.parser.toc
+ self.table = self.parser.table
+
+ assert self.table.hasTOC(), "This Table Index should be a TOC"
diff --git a/morituri/test/test_image_cue.py b/morituri/test/test_image_cue.py
index bcd4ae5..3a8c06c 100644
--- a/morituri/test/test_image_cue.py
+++ b/morituri/test/test_image_cue.py
@@ -14,13 +14,13 @@ class KingsSingleTestCase(unittest.TestCase):
self.cue = cue.CueFile(os.path.join(os.path.dirname(__file__),
'kings-single.cue'))
self.cue.parse()
- self.assertEquals(len(self.cue.tracks), 11)
+ self.assertEquals(len(self.cue.table.tracks), 11)
def testGetTrackLength(self):
- t = self.cue.tracks[0]
+ t = self.cue.table.tracks[0]
self.assertEquals(self.cue.getTrackLength(t), 17811)
# last track has unknown length
- t = self.cue.tracks[-1]
+ t = self.cue.table.tracks[-1]
self.assertEquals(self.cue.getTrackLength(t), -1)
class KingsSeparateTestCase(unittest.TestCase):
@@ -28,13 +28,13 @@ class KingsSeparateTestCase(unittest.TestCase):
self.cue = cue.CueFile(os.path.join(os.path.dirname(__file__),
'kings-separate.cue'))
self.cue.parse()
- self.assertEquals(len(self.cue.tracks), 11)
+ self.assertEquals(len(self.cue.table.tracks), 11)
def testGetTrackLength(self):
# all tracks have unknown length
- t = self.cue.tracks[0]
+ t = self.cue.table.tracks[0]
self.assertEquals(self.cue.getTrackLength(t), -1)
- t = self.cue.tracks[-1]
+ t = self.cue.table.tracks[-1]
self.assertEquals(self.cue.getTrackLength(t), -1)
class KanyeMixedTestCase(unittest.TestCase):
@@ -42,10 +42,10 @@ class KanyeMixedTestCase(unittest.TestCase):
self.cue = cue.CueFile(os.path.join(os.path.dirname(__file__),
'kanye.cue'))
self.cue.parse()
- self.assertEquals(len(self.cue.tracks), 13)
+ self.assertEquals(len(self.cue.table.tracks), 13)
def testGetTrackLength(self):
- t = self.cue.tracks[0]
+ t = self.cue.table.tracks[0]
self.assertEquals(self.cue.getTrackLength(t), -1)
diff --git a/morituri/test/test_image_image.py b/morituri/test/test_image_image.py
index 01695c5..86db997 100644
--- a/morituri/test/test_image_image.py
+++ b/morituri/test/test_image_image.py
@@ -61,7 +61,7 @@ class TrackSeparateTestCase(unittest.TestCase):
self.assertEquals(h(checksumtask.checksums[3]), '0x7271db39')
def testLength(self):
- tracks = self.image.cue.tracks
+ tracks = self.image.cue.table.tracks
self.assertEquals(self.image.table.getTrackLength(1), 10)
self.assertEquals(self.image.table.getTrackLength(2), 10)
self.assertEquals(self.image.table.getTrackLength(3), 10)
diff --git a/morituri/test/test_image_table.py b/morituri/test/test_image_table.py
index 13db8ba..ea13199 100644
--- a/morituri/test/test_image_table.py
+++ b/morituri/test/test_image_table.py
@@ -30,8 +30,12 @@ class LadyhawkeTestCase(unittest.TestCase):
for i, offset in enumerate(offsets):
t[i].index(1, absolute=offset)
+ self.failIf(self.table.hasTOC())
+
self.table.leadout = 210385
+ self.failUnless(self.table.hasTOC())
+
def testCDDB(self):
self.assertEquals(self.table.getCDDBDiscId(), "c60af50d")
diff --git a/morituri/test/test_image_toc.py b/morituri/test/test_image_toc.py
index 08a5b9d..1c9971a 100644
--- a/morituri/test/test_image_toc.py
+++ b/morituri/test/test_image_toc.py
@@ -11,24 +11,71 @@ class CureTestCase(unittest.TestCase):
self.toc = toc.TocFile(os.path.join(os.path.dirname(__file__),
'cure.toc'))
self.toc.parse()
- self.assertEquals(len(self.toc.tracks), 13)
+ self.assertEquals(len(self.toc.table.tracks), 13)
def testGetTrackLength(self):
- t = self.toc.tracks[0]
- self.assertEquals(self.toc.getTrackLength(t), -1)
+ t = self.toc.table.tracks[0]
+ # first track has known length because the .toc is a single file
+ self.assertEquals(self.toc.getTrackLength(t), 28324)
# last track has unknown length
- t = self.toc.tracks[-1]
+ t = self.toc.table.tracks[-1]
self.assertEquals(self.toc.getTrackLength(t), -1)
def testIndexes(self):
# track 2, index 0 is at 06:16:45
# FIXME: cdrdao seems to get length of FILE 1 frame too many,
# and START value one frame less
- t = self.toc.tracks[1]
- (offset, file) = t.getIndex(0)
- self.assertEquals(offset, 28245)
- (offset, file) = t.getIndex(1)
- self.assertEquals(offset, 28324)
+ t = self.toc.table.tracks[1]
+ self.assertEquals(t.getIndex(0).relative, 28245)
+ self.assertEquals(t.getIndex(1).relative, 28324)
+
+ def _getIndex(self, t, i):
+ track = self.toc.table.tracks[t - 1]
+ return track.getIndex(i)
+
+ def _assertAbsolute(self, t, i, value):
+ index = self._getIndex(t, i)
+ self.assertEquals(index.absolute, value)
+
+ def _assertPath(self, t, i, value):
+ index = self._getIndex(t, i)
+ self.assertEquals(index.path, value)
+
+ def _assertRelative(self, t, i, value):
+ index = self._getIndex(t, i)
+ self.assertEquals(index.relative, value)
+
+ def testSetFile(self):
+ self._assertAbsolute(1, 1, None)
+ self._assertAbsolute(2, 0, None)
+ self._assertAbsolute(2, 1, None)
+ self._assertPath(1, 1, "data.wav")
+
+ def dump():
+ for t in self.toc.table.tracks:
+ print t
+ print t.indexes.values()
+
+ self.toc.table.absolutize()
+ self.toc.table.clearFiles()
+
+ self._assertAbsolute(1, 1, 0)
+ self._assertAbsolute(2, 0, 28166)
+ self._assertAbsolute(2, 1, 28324)
+ self._assertAbsolute(3, 1, 46110)
+ self._assertAbsolute(4, 1, 66767)
+ self._assertPath(1, 1, None)
+ self._assertRelative(1, 1, None)
+
+ # adding a file to the table should fix up to including 2, 0
+ self.toc.table.setFile(1, 1, 'track01.wav', 28245)
+ self._assertPath(1, 1, 'track01.wav')
+ self._assertRelative(1, 1, 0)
+ self._assertPath(2, 0, 'track01.wav')
+ self._assertAbsolute(2, 0, 28166)
+
+ self._assertPath(2, 1, None)
+ self._assertRelative(2, 1, None)
# Bloc Party - Silent Alarm has a Hidden Track One Audio
class BlocTestCase(unittest.TestCase):
@@ -36,18 +83,17 @@ class BlocTestCase(unittest.TestCase):
self.toc = toc.TocFile(os.path.join(os.path.dirname(__file__),
'bloc.toc'))
self.toc.parse()
- self.assertEquals(len(self.toc.tracks), 13)
+ self.assertEquals(len(self.toc.table.tracks), 13)
def testGetTrackLength(self):
- t = self.toc.tracks[0]
- self.assertEquals(self.toc.getTrackLength(t), -1)
+ t = self.toc.table.tracks[0]
+ # first track has known length because the .toc is a single file
+ self.assertEquals(self.toc.getTrackLength(t), 50089)
# last track has unknown length
- t = self.toc.tracks[-1]
+ t = self.toc.table.tracks[-1]
self.assertEquals(self.toc.getTrackLength(t), -1)
def testIndexes(self):
- t = self.toc.tracks[0]
- (offset, file) = t.getIndex(0)
- self.assertEquals(offset, 0)
- (offset, file) = t.getIndex(1)
- self.assertEquals(offset, 15220)
+ t = self.toc.table.tracks[0]
+ self.assertEquals(t.getIndex(0).relative, 0)
+ self.assertEquals(t.getIndex(1).relative, 15220)
--
morituri packaging
More information about the pkg-multimedia-commits
mailing list