[SCM] morituri/master: * morituri/test/test_image_toc.py (added): * morituri/image/toc.py (added): Add first stab at .toc parsing.
js at users.alioth.debian.org
js at users.alioth.debian.org
Sun Oct 19 20:08:49 UTC 2014
The following commit has been merged in the master branch:
commit f2b6991dbe2c72b34a4c925e3e0fe93c4339eafb
Author: Thomas Vander Stichele <thomas (at) apestaart (dot) org>
Date: Mon Apr 27 22:18:03 2009 +0000
* morituri/test/test_image_toc.py (added):
* morituri/image/toc.py (added):
Add first stab at .toc parsing.
diff --git a/ChangeLog b/ChangeLog
index 28af6b1..78e0206 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
2009-04-28 Thomas Vander Stichele <thomas at apestaart dot org>
+ * morituri/test/test_image_toc.py (added):
+ * morituri/image/toc.py (added):
+ Add first stab at .toc parsing.
+
+2009-04-28 Thomas Vander Stichele <thomas at apestaart dot org>
+
* examples/readtoc.py:
get errors from output too.
diff --git a/morituri/image/cue.py b/morituri/image/toc.py
similarity index 72%
copy from morituri/image/cue.py
copy to morituri/image/toc.py
index c4162d8..ca57705 100644
--- a/morituri/image/cue.py
+++ b/morituri/image/toc.py
@@ -1,4 +1,4 @@
-# -*- Mode: Python; test-case-name: morituri.test.test_image_cue -*-
+# -*- Mode: Python; test-case-name: morituri.test.test_image_toc -*-
# vi:si:et:sw=4:sts=4:ts=4
# Morituri - for those about to RIP
@@ -21,43 +21,43 @@
# along with morituri. If not, see <http://www.gnu.org/licenses/>.
"""
-Reading .cue files
-
-See http://digitalx.org/cuesheetsyntax.php
+Reading .toc files
"""
import os
import re
-_REM_RE = re.compile("^REM\s(\w+)\s(.*)$")
-_PERFORMER_RE = re.compile("^PERFORMER\s(.*)$")
-_TITLE_RE = re.compile("^TITLE\s(.*)$")
+# header
+_CATALOG_RE = re.compile(r'^CATALOG "(?P<catalog>\d+)"$')
+
+# records
+_TRACK_RE = re.compile(r"""
+ ^TRACK # TRACK
+ \s(?P<mode>.+)$ # mode (AUDIO, MODEx/2xxx, ...)
+""", re.VERBOSE)
_FILE_RE = re.compile(r"""
^FILE # FILE
\s+"(?P<name>.*)" # 'file name' in quotes
- \s+(?P<format>\w+)$ # format (WAVE/MP3/AIFF/...)
+ \s+(?P<start>.+) # start offset
+ \s(?P<length>.+)$ # stop offset
""", re.VERBOSE)
-_TRACK_RE = re.compile(r"""
- ^\s+TRACK # TRACK
- \s+(?P<track>\d\d) # two-digit track number
- \s+(?P<mode>.+)$ # mode (AUDIO, MODEx/2xxx, ...)
+# FIXME: start can be 0
+_START_RE = re.compile(r"""
+ ^START # START
+ \s(?P<length>.*)$ # pre-gap length
""", re.VERBOSE)
+
_INDEX_RE = re.compile(r"""
- ^\s+INDEX # INDEX
- \s+(\d\d) # two-digit index number
- \s+(\d\d) # minutes
- :(\d\d) # seconds
- :(\d\d)$ # frames
+ ^INDEX # INDEX
+ \s(?P<offset>.+)$ # start offset
""", re.VERBOSE)
-
-class Cue:
+class TOC:
def __init__(self, path):
self._path = path
- self._rems = {}
self._messages = []
self.tracks = []
@@ -65,62 +65,60 @@ class Cue:
state = 'HEADER'
currentFile = None
currentTrack = None
+ trackNumber = 0
+ indexNumber = 0
+ offset = 0 # running count of where each track starts
handle = open(self._path, 'r')
for number, line in enumerate(handle.readlines()):
line = line.rstrip()
- m = _REM_RE.search(line)
+ m = _CATALOG_RE.search(line)
if m:
- tag = m.expand('\\1')
- value = m.expand('\\2')
- if state != 'HEADER':
- self.message(number, 'REM %s outside of header' % tag)
- else:
- self._rems[tag] = value
- continue
-
- # look for FILE lines
- m = _FILE_RE.search(line)
- if m:
- filePath = m.group('name')
- fileFormat = m.group('format')
- currentFile = File(filePath, fileFormat)
+ catalog = m.group('catalog')
# look for TRACK lines
m = _TRACK_RE.search(line)
if m:
- if not currentFile:
- self.message(number, 'TRACK without preceding FILE')
- continue
-
state = 'TRACK'
-
- trackNumber = int(m.group('track'))
+ trackNumber += 1
trackMode = m.group('mode')
currentTrack = Track(trackNumber)
self.tracks.append(currentTrack)
continue
- # look for INDEX lines
- m = _INDEX_RE.search(line)
+ # look for FILE lines
+ m = _FILE_RE.search(line)
+ if m:
+ filePath = m.group('name')
+ start = m.group('start')
+ length = m.group('length')
+ currentFile = File(filePath, start, length)
+ offset = self._parseMSF(start)
+ indexNumber = 1
+ currentTrack.index(1, offset, currentFile)
+
+ # look for START lines
+ m = _START_RE.search(line)
if m:
if not currentTrack:
- self.message(number, 'INDEX without preceding TRACK')
+ self.message(number, 'START without preceding TRACK')
print 'ouch'
continue
- indexNumber = int(m.expand('\\1'))
- minutes = int(m.expand('\\2'))
- seconds = int(m.expand('\\3'))
- frames = int(m.expand('\\4'))
-
- frameOffset = frames + seconds * 75 + minutes * 75 * 60
- currentTrack.index(indexNumber, frameOffset, currentFile)
- # print 'index %d, offset %d of track %r' % (indexNumber, frameOffset, currentTrack)
- continue
+ length = self._parseMSF(m.group('length'))
+ currentTrack.index(0, offset - length, currentFile)
+
+ # look for INDEX lines
+ m = _INDEX_RE.search(line)
+ if m:
+ if not currentTrack:
+ self.message(number, 'INDEX without preceding TRACK')
+ indexNumber += 1
+ offset = self._parseMSF(m.group('offset'))
+ currentTrack.index(indexNumber, offset, currentFile)
def message(self, number, message):
"""
@@ -179,17 +177,24 @@ class Cue:
raise KeyError, "Cannot find file for %s" % path
+ def _parseMSF(self, msf):
+ # parse str value in MM:SS:FF to frames
+ if not ':' in msf:
+ return int(msf)
+ m, s, f = msf.split(':')
+ return 60 * 75 * int(m) + 75 * int(s) + int(f)
class File:
"""
- I represent a FILE line in a cue file.
+ I represent a FILE line in a .toc file.
"""
- def __init__(self, path, format):
+ def __init__(self, path, start, length):
self.path = path
- self.format = format
+ self.start = start
+ self.length = length
def __repr__(self):
- return '<File "%s" of format %s>' % (self.path, self.format)
+ return '<File "%s">' % (self.path, )
# FIXME: add type ? separate AUDIO from others
diff --git a/morituri/test/test_image_toc.py b/morituri/test/test_image_toc.py
new file mode 100644
index 0000000..ab1c8f0
--- /dev/null
+++ b/morituri/test/test_image_toc.py
@@ -0,0 +1,28 @@
+# -*- Mode: Python; test-case-name: morituri.test.test_image_cue -*-
+# vi:si:et:sw=4:sts=4:ts=4
+
+import os
+import unittest
+
+from morituri.image import toc
+
+class CureTestCase(unittest.TestCase):
+ def setUp(self):
+ self.toc = toc.TOC(os.path.join(os.path.dirname(__file__),
+ 'cure.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[1]
+ (offset, file) = t.getIndex(0)
+ self.assertEquals(offset, 28166)
+ (offset, file) = t.getIndex(1)
+ self.assertEquals(offset, 28245)
--
morituri packaging
More information about the pkg-multimedia-commits
mailing list