diff --git a/ChangeLog b/ChangeLog index 4260b29..a5a77c5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2009-05-14 Thomas Vander Stichele + + * morituri/image/table.py: + Add CDText writing to .cue() method. + * morituri/image/toc.py: + Add CDText parsing. + * morituri/test/test_image_toc.py: + * morituri/test/breeders.cue (added): + Add a test for cue'ing the breeders' toc. + 2009-05-14 Thomas Vander Stichele * morituri/image/table.py: diff --git a/morituri/image/table.py b/morituri/image/table.py index 8a33165..0b97f71 100644 --- a/morituri/image/table.py +++ b/morituri/image/table.py @@ -31,6 +31,8 @@ import gst from morituri.common import task, checksum, common, log +# FIXME: taken from libcdio, but no reference found for these + CDTEXT_FIELDS = [ 'ARRANGER', 'COMPOSER', @@ -123,12 +125,14 @@ class IndexTable(object, log.Loggable): tracks = None # list of ITTrack leadout = None # offset where the leadout starts catalog = None # catalog number; FIXME: is this UPC ? + cdtext = None def __init__(self, tracks=None): if not tracks: tracks = [] self.tracks = tracks + self.cdtext = {} def getTrackStart(self, number): """ @@ -324,10 +328,21 @@ class IndexTable(object, log.Loggable): lines = [] # header + main = ['PERFORMER', 'TITLE'] + + for key in CDTEXT_FIELDS: + if key not in main and self.cdtext.has_key(key): + lines.append(" %s %s" % (key, track.cdtext[key])) + lines.append('REM COMMENT "Morituri"') + if self.catalog: lines.append("CATALOG %s" % self.catalog) + for key in main: + if self.cdtext.has_key(key): + lines.append('%s "%s"' % (key, self.cdtext[key])) + # add the first FILE line path = self.tracks[0].getFirstIndex().path currentPath = path @@ -335,6 +350,10 @@ class IndexTable(object, log.Loggable): for i, track in enumerate(self.tracks): lines.append(" TRACK %02d %s" % (i + 1, 'AUDIO')) + for key in CDTEXT_FIELDS: + if track.cdtext.has_key(key): + lines.append(' %s "%s"' % (key, track.cdtext[key])) + if track.isrc is not None: lines.append(" ISRC %s" % track.isrc) diff --git a/morituri/image/toc.py b/morituri/image/toc.py index 1571205..df7a9db 100644 --- a/morituri/image/toc.py +++ b/morituri/image/toc.py @@ -31,7 +31,7 @@ from morituri.common import common, log from morituri.image import table # shared -_CDTEXT_CANDIDATE_RE = re.compile(r'(?Ps+) "(?P.+")') +_CDTEXT_CANDIDATE_RE = re.compile(r'(?P\w+) "(?P.+)"') # header _CATALOG_RE = re.compile(r'^CATALOG "(?P\d+)"$') @@ -101,7 +101,15 @@ class TocFile(object, log.Loggable): if m: key = m.group('key') value = m.group('value') - # print key, value + if key in table.CDTEXT_FIELDS: + # FIXME: consider ISRC separate for now, but this + # is a limitation of our parser approach + if state == 'HEADER': + self.table.cdtext[key] = value + elif state == 'TRACK': + if key != 'ISRC' or not currentTrack \ + or currentTrack.isrc is not None: + currentTrack.cdtext[key] = value # look for header elements m = _CATALOG_RE.search(line) diff --git a/morituri/test/breeders.cue b/morituri/test/breeders.cue new file mode 100644 index 0000000..2db081b --- /dev/null +++ b/morituri/test/breeders.cue @@ -0,0 +1,63 @@ +REM COMMENT "Morituri" +CATALOG 0652637280326 +PERFORMER "THE BREEDERS" +TITLE "MOUNTAIN BATTLES" +FILE "data.wav" WAVE + TRACK 01 AUDIO + TITLE "OVERGLAZED" + ISRC GBAFL0700213 + INDEX 01 00:00:00 + TRACK 02 AUDIO + TITLE "BANG ON" + ISRC GBAFL0700214 + INDEX 00 02:14:51 + INDEX 01 02:15:26 + TRACK 03 AUDIO + TITLE "NIGHT OF JOY" + ISRC GBAFL0700215 + INDEX 00 04:17:74 + INDEX 01 04:18:34 + TRACK 04 AUDIO + TITLE "WE'RE GONNA RISE" + ISRC GBAFL0700216 + INDEX 01 07:44:22 + TRACK 05 AUDIO + TITLE "GERMAN STUDIES" + ISRC GBAFL0700217 + INDEX 01 11:37:39 + TRACK 06 AUDIO + TITLE "SPARK" + ISRC GBAFL0700218 + INDEX 00 13:51:54 + INDEX 01 13:53:38 + TRACK 07 AUDIO + TITLE "INSTANBUL" + ISRC GBAFL0700219 + INDEX 00 16:31:20 + INDEX 01 16:32:49 + TRACK 08 AUDIO + TITLE "WALK IT OFF" + ISRC GBAFL0700220 + INDEX 01 19:30:19 + TRACK 09 AUDIO + TITLE "REGLAME ESTA NOCHE" + ISRC GBAFL0700221 + INDEX 00 22:14:69 + INDEX 01 22:16:27 + TRACK 10 AUDIO + TITLE "HERE NO MORE" + ISRC GBAFL0700222 + INDEX 00 25:06:18 + INDEX 01 25:08:01 + TRACK 11 AUDIO + TITLE "NO WAY" + ISRC GBAFL0700223 + INDEX 01 27:46:64 + TRACK 12 AUDIO + TITLE "IT'S THE LOVE" + ISRC GBAFL0700224 + INDEX 01 30:19:39 + TRACK 13 AUDIO + TITLE "MOUNTAIN BATTLES" + ISRC GBAFL0700225 + INDEX 01 32:47:56 diff --git a/morituri/test/test_image_toc.py b/morituri/test/test_image_toc.py index 4697f2f..a3e6007 100644 --- a/morituri/test/test_image_toc.py +++ b/morituri/test/test_image_toc.py @@ -105,3 +105,27 @@ class BlocTestCase(unittest.TestCase): t = self.toc.table.tracks[0] self.assertEquals(t.getIndex(0).relative, 0) self.assertEquals(t.getIndex(1).relative, 15220) + +# The Breeders - Mountain Battles has CDText +class BreedersTestCase(unittest.TestCase): + def setUp(self): + self.toc = toc.TocFile(os.path.join(os.path.dirname(__file__), + 'breeders.toc')) + self.toc.parse() + self.assertEquals(len(self.toc.table.tracks), 13) + + def testCDText(self): + cdt = self.toc.table.cdtext + self.assertEquals(cdt['PERFORMER'], 'THE BREEDERS') + self.assertEquals(cdt['TITLE'], 'MOUNTAIN BATTLES') + + t = self.toc.table.tracks[0] + cdt = t.cdtext + self.assertRaises(AttributeError, getattr, cdt, 'PERFORMER') + self.assertEquals(cdt['TITLE'], 'OVERGLAZED') + + def testConvertCue(self): + cue = self.toc.table.cue() + ref = open(os.path.join(os.path.dirname(__file__), + 'breeders.cue')).read() + self.assertEquals(cue, ref)