[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