* morituri/image/table.py:
* morituri/image/toc.py: Add parsing of ISRC codes. Add first part of CDTEXT stuff. * morituri/test/test_image_toc.py: Add test for converting .toc to .cue * morituri/test/cure.cue Add reference for converted cure.toc
This commit is contained in:
11
ChangeLog
11
ChangeLog
@@ -1,3 +1,14 @@
|
||||
2009-05-14 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||
|
||||
* morituri/image/table.py:
|
||||
* morituri/image/toc.py:
|
||||
Add parsing of ISRC codes.
|
||||
Add first part of CDTEXT stuff.
|
||||
* morituri/test/test_image_toc.py:
|
||||
Add test for converting .toc to .cue
|
||||
* morituri/test/cure.cue
|
||||
Add reference for converted cure.toc
|
||||
|
||||
2009-05-10 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||
|
||||
* examples/readhtoa.py:
|
||||
|
||||
@@ -31,20 +31,41 @@ import gst
|
||||
|
||||
from morituri.common import task, checksum, common, log
|
||||
|
||||
CDTEXT_FIELDS = [
|
||||
'ARRANGER',
|
||||
'COMPOSER',
|
||||
'DISCID',
|
||||
'GENRE',
|
||||
'MESSAGE',
|
||||
'ISRC',
|
||||
'PERFORMER',
|
||||
'SIZE_INFO',
|
||||
'SONGWRITER',
|
||||
'TITLE',
|
||||
'TOC_INFO',
|
||||
'TOC_INFO2',
|
||||
'UPC_EAN',
|
||||
]
|
||||
|
||||
|
||||
class ITTrack:
|
||||
"""
|
||||
I represent a track entry in an IndexTable.
|
||||
|
||||
@ivar number: track number (1-based)
|
||||
@type number: int
|
||||
@ivar audio: whether the track is audio
|
||||
@type audio: bool
|
||||
@ivar number: track number (1-based)
|
||||
@type number: int
|
||||
@ivar audio: whether the track is audio
|
||||
@type audio: bool
|
||||
@type indexes: dict of number -> L{Index}
|
||||
@ivar isrc: ISRC code (12 alphanumeric characters)
|
||||
@type isrc: str
|
||||
"""
|
||||
|
||||
number = None
|
||||
audio = None
|
||||
indexes = None
|
||||
isrc = None
|
||||
cdtext = None
|
||||
|
||||
def __repr__(self):
|
||||
return '<Track %02d>' % self.number
|
||||
@@ -53,6 +74,7 @@ class ITTrack:
|
||||
self.number = number
|
||||
self.audio = audio
|
||||
self.indexes = {}
|
||||
self.cdtext = {}
|
||||
|
||||
def index(self, number, absolute=None, path=None, relative=None, counter=None):
|
||||
i = Index(number, absolute, path, relative, counter)
|
||||
@@ -94,10 +116,13 @@ class IndexTable(object, log.Loggable):
|
||||
|
||||
@ivar tracks: tracks on this CD
|
||||
@type tracks: list of L{ITTrack}
|
||||
@ivar catalog: catalog number
|
||||
@type catalog: str
|
||||
"""
|
||||
|
||||
tracks = None # list of ITTrack
|
||||
leadout = None # offset where the leadout starts
|
||||
catalog = None # catalog number; FIXME: is this UPC ?
|
||||
|
||||
def __init__(self, tracks=None):
|
||||
if not tracks:
|
||||
@@ -298,6 +323,11 @@ class IndexTable(object, log.Loggable):
|
||||
"""
|
||||
lines = []
|
||||
|
||||
# header
|
||||
lines.append('REM COMMENT "Morituri"')
|
||||
if self.catalog:
|
||||
lines.append("CATALOG %s" % self.catalog)
|
||||
|
||||
# add the first FILE line
|
||||
path = self.tracks[0].getFirstIndex().path
|
||||
currentPath = path
|
||||
@@ -305,6 +335,8 @@ class IndexTable(object, log.Loggable):
|
||||
|
||||
for i, track in enumerate(self.tracks):
|
||||
lines.append(" TRACK %02d %s" % (i + 1, 'AUDIO'))
|
||||
if track.isrc is not None:
|
||||
lines.append(" ISRC %s" % track.isrc)
|
||||
|
||||
indexes = track.indexes.keys()
|
||||
indexes.sort()
|
||||
|
||||
@@ -30,6 +30,9 @@ import re
|
||||
from morituri.common import common, log
|
||||
from morituri.image import table
|
||||
|
||||
# shared
|
||||
_CDTEXT_CANDIDATE_RE = re.compile(r'(?P<key>s+) "(?P<value>.+")')
|
||||
|
||||
# header
|
||||
_CATALOG_RE = re.compile(r'^CATALOG "(?P<catalog>\d+)"$')
|
||||
|
||||
@@ -39,6 +42,8 @@ _TRACK_RE = re.compile(r"""
|
||||
\s(?P<mode>.+)$ # mode (AUDIO, MODEx/2xxx, ...)
|
||||
""", re.VERBOSE)
|
||||
|
||||
_ISRC_RE = re.compile(r'^ISRC "(?P<isrc>\w+)"$')
|
||||
|
||||
# a HTOA is marked in the cdrdao's TOC as SILENCE
|
||||
_SILENCE_RE = re.compile(r"""
|
||||
^SILENCE # SILENCE
|
||||
@@ -91,9 +96,18 @@ class TocFile(object, log.Loggable):
|
||||
for number, line in enumerate(handle.readlines()):
|
||||
line = line.rstrip()
|
||||
|
||||
# look for CDTEXT stuff in either header or tracks
|
||||
m = _CDTEXT_CANDIDATE_RE.search(line)
|
||||
if m:
|
||||
key = m.group('key')
|
||||
value = m.group('value')
|
||||
# print key, value
|
||||
|
||||
# look for header elements
|
||||
m = _CATALOG_RE.search(line)
|
||||
if m:
|
||||
catalog = m.group('catalog')
|
||||
self.table.catalog = m.group('catalog')
|
||||
self.debug("Found catalog number %s", self.table.catalog)
|
||||
|
||||
# look for TRACK lines
|
||||
m = _TRACK_RE.search(line)
|
||||
@@ -120,6 +134,13 @@ class TocFile(object, log.Loggable):
|
||||
self.table.tracks.append(currentTrack)
|
||||
continue
|
||||
|
||||
# look for ISRC lines
|
||||
m = _ISRC_RE.search(line)
|
||||
if m:
|
||||
isrc = m.group('isrc')
|
||||
currentTrack.isrc = isrc
|
||||
self.debug('Found ISRC code %s', isrc)
|
||||
|
||||
# look for SILENCE lines
|
||||
m = _SILENCE_RE.search(line)
|
||||
if m:
|
||||
|
||||
54
morituri/test/cure.cue
Normal file
54
morituri/test/cure.cue
Normal file
@@ -0,0 +1,54 @@
|
||||
REM COMMENT "Morituri"
|
||||
CATALOG 0602517642256
|
||||
FILE "data.wav" WAVE
|
||||
TRACK 01 AUDIO
|
||||
ISRC USUM70839873
|
||||
INDEX 01 00:00:00
|
||||
TRACK 02 AUDIO
|
||||
ISRC USUM70839874
|
||||
INDEX 00 06:16:45
|
||||
INDEX 01 06:17:49
|
||||
TRACK 03 AUDIO
|
||||
ISRC USUM70839875
|
||||
INDEX 00 10:13:02
|
||||
INDEX 01 10:14:60
|
||||
TRACK 04 AUDIO
|
||||
ISRC USUM70839876
|
||||
INDEX 00 14:50:07
|
||||
INDEX 01 14:50:17
|
||||
TRACK 05 AUDIO
|
||||
ISRC USUM70839877
|
||||
INDEX 00 17:18:42
|
||||
INDEX 01 17:20:47
|
||||
TRACK 06 AUDIO
|
||||
ISRC USUM70839878
|
||||
INDEX 00 19:43:06
|
||||
INDEX 01 19:43:10
|
||||
TRACK 07 AUDIO
|
||||
ISRC USUM70839879
|
||||
INDEX 00 24:25:07
|
||||
INDEX 01 24:26:41
|
||||
TRACK 08 AUDIO
|
||||
ISRC USUM70839880
|
||||
INDEX 00 28:56:00
|
||||
INDEX 01 28:56:09
|
||||
TRACK 09 AUDIO
|
||||
ISRC USUM70839881
|
||||
INDEX 00 32:38:11
|
||||
INDEX 01 32:40:45
|
||||
TRACK 10 AUDIO
|
||||
ISRC USUM70839882
|
||||
INDEX 00 36:01:58
|
||||
INDEX 01 36:02:04
|
||||
TRACK 11 AUDIO
|
||||
ISRC USUM70839883
|
||||
INDEX 00 40:08:30
|
||||
INDEX 01 40:08:53
|
||||
TRACK 12 AUDIO
|
||||
ISRC USUM70839884
|
||||
INDEX 00 43:59:51
|
||||
INDEX 01 44:00:27
|
||||
TRACK 13 AUDIO
|
||||
ISRC USUM70839885
|
||||
INDEX 00 48:35:63
|
||||
INDEX 01 48:36:71
|
||||
@@ -78,6 +78,11 @@ class CureTestCase(unittest.TestCase):
|
||||
self._assertPath(2, 1, None)
|
||||
self._assertRelative(2, 1, None)
|
||||
|
||||
def testConvertCue(self):
|
||||
cue = self.toc.table.cue()
|
||||
ref = open(os.path.join(os.path.dirname(__file__), 'cure.cue')).read()
|
||||
self.assertEquals(cue, ref)
|
||||
|
||||
# Bloc Party - Silent Alarm has a Hidden Track One Audio
|
||||
class BlocTestCase(unittest.TestCase):
|
||||
def setUp(self):
|
||||
|
||||
Reference in New Issue
Block a user