[SCM] morituri/master: * morituri/rip/Makefile.am: * morituri/rip/main.py: * morituri/rip/offset.py (added): Add first command, 'rip offset find'

js at users.alioth.debian.org js at users.alioth.debian.org
Sun Oct 19 20:09:03 UTC 2014


The following commit has been merged in the master branch:
commit 9e3e1d53cb76738b6eae49989caa6bb881eea230
Author: Thomas Vander Stichele <thomas (at) apestaart (dot) org>
Date:   Sat May 23 09:00:03 2009 +0000

    	* morituri/rip/Makefile.am:
    	* morituri/rip/main.py:
    	* morituri/rip/offset.py (added):
    	  Add first command, 'rip offset find'

diff --git a/ChangeLog b/ChangeLog
index f401110..b1a4edf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2009-05-23  Thomas Vander Stichele  <thomas at apestaart dot org>
 
+	* morituri/rip/Makefile.am:
+	* morituri/rip/main.py:
+	* morituri/rip/offset.py (added):
+	  Add first command, 'rip offset find'
+
+2009-05-23  Thomas Vander Stichele  <thomas at apestaart dot org>
+
 	* Makefile.am:
 	* morituri/test/Makefile.am:
 	  Make distcheck work.
diff --git a/morituri/rip/Makefile.am b/morituri/rip/Makefile.am
index 760ae03..7a47728 100644
--- a/morituri/rip/Makefile.am
+++ b/morituri/rip/Makefile.am
@@ -4,4 +4,5 @@ morituridir = $(PYTHONLIBDIR)/morituri/rip
 
 morituri_PYTHON = \
 	__init__.py \
-	main.py
+	main.py \
+	offset.py
diff --git a/morituri/rip/main.py b/morituri/rip/main.py
index b3a4911..8335e10 100644
--- a/morituri/rip/main.py
+++ b/morituri/rip/main.py
@@ -4,6 +4,7 @@
 import sys
 
 from morituri.common import log, logcommand
+from morituri.rip import offset
 
 def main(argv):
     c = Rip()
@@ -30,7 +31,7 @@ Rip gives you a tree of subcommands to work with.
 You can get help on subcommands by using the -h option to the subcommand.
 """
 
-    subCommandClasses = []
+    subCommandClasses = [offset.Offset, ]
 
     def addOptions(self):
         # FIXME: is this the right place ?
diff --git a/morituri/rip/offset.py b/morituri/rip/offset.py
new file mode 100644
index 0000000..df4a2ef
--- /dev/null
+++ b/morituri/rip/offset.py
@@ -0,0 +1,165 @@
+# -*- Mode: Python -*-
+# vi:si:et:sw=4:sts=4:ts=4
+
+# Morituri - for those about to RIP
+
+# Copyright (C) 2009 Thomas Vander Stichele
+
+# This file is part of morituri.
+# 
+# morituri is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+# 
+# morituri is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with morituri.  If not, see <http://www.gnu.org/licenses/>.
+
+import os
+import tempfile
+
+import gobject
+gobject.threads_init()
+
+from morituri.common import logcommand, task, checksum
+from morituri.image import image
+from morituri.program import cdrdao, cdparanoia
+
+
+class Find(logcommand.LogCommand):
+    summary = "find drive read offset"
+    description = """Find drive's read offset by ripping tracks from a
+CD in the AccurateRip database."""
+
+    def addOptions(self):
+        # see http://www.accuraterip.com/driveoffsets.htm
+        default = "0, 6, 12, 48, 91, 97, 102, 108, 120, " + \
+            "564, 594, 667, 685, 691, 704, 738, 1194, 1292, 1336, 1776, -582"
+        self.parser.add_option('-o', '--offsets',
+            action="store", dest="offsets",
+            help="list of offsets, comma-separated, "
+                "colon-separated for ranges (defaults to %s)" % default,
+            default=default)
+
+    def handleOptions(self, options):
+        self.options = options
+        self._offsets = []
+        blocks = options.offsets.split(',')
+        for b in blocks:
+            if ':' in b:
+                a, b = b.split(':')
+                self._offsets.extend(range(int(a), int(b) + 1))
+            else:
+                self._offsets.append(int(b))
+
+        self.debug('Trying with offsets %r', self._offsets)
+
+    def do(self, args):
+        runner = task.SyncRunner()
+
+        # first get the Table Of Contents of the CD
+        t = cdrdao.ReadTOCTask()
+
+        runner.run(t)
+        table = t.table
+
+        self.debug("CDDB disc id: %r", table.getCDDBDiscId())
+        url = table.getAccurateRipURL()
+        self.debug("AccurateRip URL: %s", url)
+
+        # FIXME: download url as a task too
+        responses = []
+        import urllib2
+        try:
+            handle = urllib2.urlopen(url)
+            data = handle.read()
+            responses = image.getAccurateRipResponses(data)
+        except urllib2.HTTPError, e:
+            if e.code == 404:
+                print 'Album not found in AccurateRip database.'
+                return 1
+            else:
+                raise
+
+        if responses:
+            self.debug('%d AccurateRip reponses found.' % len(responses))
+
+            if responses[0].cddbDiscId != table.getCDDBDiscId():
+                self.warning("AccurateRip response discid different: %s",
+                    responses[0].cddbDiscId)
+
+        # now rip the first track at various offsets, calculating AccurateRip
+        # CRC, and matching it against the retrieved ones
+        
+        def match(archecksum, track, responses):
+            for i, r in enumerate(responses):
+                if archecksum == r.checksums[track - 1]:
+                    return archecksum, i
+
+            return None, None
+
+        for offset in self._offsets:
+            print 'Trying read offset %d ...' % offset
+            archecksum = self._arcs(runner, table, 1, offset)
+
+            self.debug('AR checksum calculated: %s' % archecksum)
+
+            c, i = match(archecksum, 1, responses)
+            if c:
+                count = 1
+                self.debug('MATCHED against response %d' % i)
+                print 'Offset of device is likely %d, confirming ...' % offset
+
+                # now try and rip all other tracks as well
+                for track in range(2, len(table.tracks) + 1):
+                    archecksum = self._arcs(runner, table, track, offset)
+                    c, i = match(archecksum, track, responses)
+                    if c:
+                        self.debug('MATCHED track %d against response %d' % (
+                            track, i))
+                        count += 1
+
+                if count == len(table.tracks):
+                    print
+                    print 'Read offset of device is: %d.' % offset
+                    return 0
+                else:
+                    print 'Only %d of %d tracks matched, continuing ...' % (
+                        count, len(table.tracks))
+                    
+        print 'No matching offset found.'
+        print 'Consider trying again with a different disc.'
+                 
+    def _arcs(self, runner, table, track, offset):
+        # rips the track with the given offset, return the arcs checksum
+        self.debug('Ripping track %r with offset %d ...', track, offset)
+
+        fd, path = tempfile.mkstemp(
+            suffix='.track%02d.offset%d.morituri.wav' % (
+                track, offset))
+        os.close(fd)
+
+        t = cdparanoia.ReadTrackTask(path, table, table.getTrackStart(track),
+            table.getTrackEnd(track), offset)
+        t.description = 'Ripping track %d with read offset %d' % (
+            track, offset)
+        runner.run(t)
+
+        t = checksum.AccurateRipChecksumTask(path, trackNumber=track,
+            trackCount=len(table.tracks))
+        runner.run(t)
+        
+        os.unlink(path)
+        return "%08x" % t.checksum
+
+class Offset(logcommand.LogCommand):
+    summary = "handle drive offsets"
+
+    subCommandClasses = [Find, ]
+
+

-- 
morituri packaging



More information about the pkg-multimedia-commits mailing list