diff --git a/ChangeLog b/ChangeLog index 20557f5..cc539a4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2009-05-01 Thomas Vander Stichele + + * morituri/image/toc.py: + * morituri/test/test_image_toc.py: + * morituri/test/bloc.toc (added): + Fix up .toc parsing to correct index 0 behaviour. + Add Bloc Party's Silent Alarm .toc file to test HTOA. + 2009-05-01 Thomas Vander Stichele * examples/readtoc.py: diff --git a/morituri/image/toc.py b/morituri/image/toc.py index ca57705..0d68f43 100644 --- a/morituri/image/toc.py +++ b/morituri/image/toc.py @@ -36,6 +36,13 @@ _TRACK_RE = re.compile(r""" \s(?P.+)$ # mode (AUDIO, MODEx/2xxx, ...) """, re.VERBOSE) +# a HTOA is marked in the cdrdao's TOC as SILENCE +_SILENCE_RE = re.compile(r""" + ^SILENCE # SILENCE + \s(?P.*)$ # pre-gap length +""", re.VERBOSE) + + _FILE_RE = re.compile(r""" ^FILE # FILE \s+"(?P.*)" # 'file name' in quotes @@ -67,8 +74,14 @@ class TOC: currentTrack = None trackNumber = 0 indexNumber = 0 - offset = 0 # running count of where each track starts + currentOffset = 0 # running absolute offset of where each track starts + currentLength = 0 # accrued during TRACK record parsing, current track + pregapLength = 0 # length of the pre-gap, current track + + # the first track's INDEX 1 can only be gotten from the .toc + # file once the first pregap is calculated; so we add INDEX 1 + # at the end of each parsed TRACK record handle = open(self._path, 'r') for number, line in enumerate(handle.readlines()): @@ -82,13 +95,28 @@ class TOC: m = _TRACK_RE.search(line) if m: state = 'TRACK' + + # handle index 1 of previous track, if any + if currentTrack: + currentTrack.index(1, currentOffset + pregapLength, + currentFile) + trackNumber += 1 + currentOffset += currentLength + currentLength = 0 + indexNumber = 1 trackMode = m.group('mode') currentTrack = Track(trackNumber) self.tracks.append(currentTrack) continue + # look for SILENCE lines + m = _SILENCE_RE.search(line) + if m: + length = m.group('length') + currentLength += self._parseMSF(length) + # look for FILE lines m = _FILE_RE.search(line) if m: @@ -96,9 +124,8 @@ class TOC: start = m.group('start') length = m.group('length') currentFile = File(filePath, start, length) - offset = self._parseMSF(start) - indexNumber = 1 - currentTrack.index(1, offset, currentFile) + #currentOffset += self._parseMSF(start) + currentLength += self._parseMSF(length) # look for START lines m = _START_RE.search(line) @@ -109,7 +136,9 @@ class TOC: continue length = self._parseMSF(m.group('length')) - currentTrack.index(0, offset - length, currentFile) + currentTrack.index(0, currentOffset, currentFile) + currentLength += length + pregapLength = length # look for INDEX lines m = _INDEX_RE.search(line) @@ -120,6 +149,10 @@ class TOC: offset = self._parseMSF(m.group('offset')) currentTrack.index(indexNumber, offset, currentFile) + # handle index 1 of final track, if any + if currentTrack: + currentTrack.index(1, currentOffset + pregapLength, currentFile) + def message(self, number, message): """ Add a message about a given line in the cue file. diff --git a/morituri/test/bloc.toc b/morituri/test/bloc.toc new file mode 100644 index 0000000..65e2a96 --- /dev/null +++ b/morituri/test/bloc.toc @@ -0,0 +1,116 @@ +CD_DA + + +// Track 1 +TRACK AUDIO +NO COPY +NO PRE_EMPHASIS +TWO_CHANNEL_AUDIO +SILENCE 03:22:70 +FILE "data.wav" 0 04:21:74 +START 03:22:70 + + +// Track 2 +TRACK AUDIO +NO COPY +NO PRE_EMPHASIS +TWO_CHANNEL_AUDIO +FILE "data.wav" 04:21:74 03:40:13 + + +// Track 3 +TRACK AUDIO +NO COPY +NO PRE_EMPHASIS +TWO_CHANNEL_AUDIO +FILE "data.wav" 08:02:12 03:55:33 + + +// Track 4 +TRACK AUDIO +NO COPY +NO PRE_EMPHASIS +TWO_CHANNEL_AUDIO +FILE "data.wav" 11:57:45 03:20:30 + + +// Track 5 +TRACK AUDIO +NO COPY +NO PRE_EMPHASIS +TWO_CHANNEL_AUDIO +FILE "data.wav" 15:18:00 02:47:40 +START 00:00:72 + + +// Track 6 +TRACK AUDIO +NO COPY +NO PRE_EMPHASIS +TWO_CHANNEL_AUDIO +FILE "data.wav" 18:05:40 03:29:50 +START 00:00:41 + + +// Track 7 +TRACK AUDIO +NO COPY +NO PRE_EMPHASIS +TWO_CHANNEL_AUDIO +FILE "data.wav" 21:35:15 04:25:59 +START 00:00:17 + + +// Track 8 +TRACK AUDIO +NO COPY +NO PRE_EMPHASIS +TWO_CHANNEL_AUDIO +FILE "data.wav" 26:00:74 03:35:15 +START 00:00:04 + + +// Track 9 +TRACK AUDIO +NO COPY +NO PRE_EMPHASIS +TWO_CHANNEL_AUDIO +FILE "data.wav" 29:36:14 04:19:63 +START 00:00:11 + + +// Track 10 +TRACK AUDIO +NO COPY +NO PRE_EMPHASIS +TWO_CHANNEL_AUDIO +FILE "data.wav" 33:56:02 03:52:24 + + +// Track 11 +TRACK AUDIO +NO COPY +NO PRE_EMPHASIS +TWO_CHANNEL_AUDIO +FILE "data.wav" 37:48:26 03:56:19 +START 00:00:43 + + +// Track 12 +TRACK AUDIO +NO COPY +NO PRE_EMPHASIS +TWO_CHANNEL_AUDIO +FILE "data.wav" 41:44:45 04:11:41 +START 00:01:41 + + +// Track 13 +TRACK AUDIO +NO COPY +NO PRE_EMPHASIS +TWO_CHANNEL_AUDIO +FILE "data.wav" 45:56:11 04:43:60 +START 00:00:22 + diff --git a/morituri/test/test_image_toc.py b/morituri/test/test_image_toc.py index ab1c8f0..f06503e 100644 --- a/morituri/test/test_image_toc.py +++ b/morituri/test/test_image_toc.py @@ -21,8 +21,33 @@ class CureTestCase(unittest.TestCase): 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, 28166) - (offset, file) = t.getIndex(1) self.assertEquals(offset, 28245) + (offset, file) = t.getIndex(1) + self.assertEquals(offset, 28324) + +# Bloc Party - Silent Alarm has a Hidden Track One Audio +class BlocTestCase(unittest.TestCase): + def setUp(self): + self.toc = toc.TOC(os.path.join(os.path.dirname(__file__), + 'bloc.toc')) + self.toc.parse() + self.assertEquals(len(self.toc.tracks), 13) + + def testGetTrackLength(self): + t = self.toc.tracks[0] + self.assertEquals(self.toc.getTrackLength(t), -1) + # last track has unknown length + t = self.toc.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)