diff --git a/ChangeLog b/ChangeLog index 2d1d921..d1302ff 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2009-04-13 Thomas Vander Stichele + + * morituri/image/image.py: + Add the 150 frames for the leadin only to the CDDB calculation. + Add methods to calculate AccurateRip id's and URL. + * morituri/test/test_image_image.py: + Add tests for it. + * examples/ARcue.py: + Show AccurateRip URL. + 2009-04-12 Thomas Vander Stichele * examples/ARcue.py: diff --git a/examples/ARcue.py b/examples/ARcue.py index 955a7dc..f37aa82 100644 --- a/examples/ARcue.py +++ b/examples/ARcue.py @@ -70,13 +70,15 @@ def main(argv): if options.runner == 'cli': runner = task.SyncRunner() cueImage.setup(runner) - print "CDDB disc id", cueImage.cddbDiscId() + print "CDDB disc id", cueImage.getCDDBDiscId() + print "AccurateRip URL", cueImage.getAccurateRipURL() climain(runner, verifytask) climain(runner, cuetask) elif options.runner == 'gtk': runner = task.GtkProgressRunner() cueImage.setup(runner) - print "CDDB disc id", cueImage.cddbDiscId() + print "CDDB disc id", cueImage.getCDDBDiscId() + print "AccurateRip URL", cueImage.getAccurateRipURL() gtkmain(runner, verifytask) gtkmain(runner, cuetask) diff --git a/morituri/image/image.py b/morituri/image/image.py index f2545c9..45f5193 100644 --- a/morituri/image/image.py +++ b/morituri/image/image.py @@ -72,9 +72,9 @@ class Image: # calculate offset and length for each track - # CD's have a standard lead-in time of 2 seconds - offset = 2 * crc.DISC_FRAMES_PER_SECOND \ - + self.cue.tracks[0].getIndex(1)[0] + # CD's have a standard lead-in time of 2 seconds; + # checksums that use it should add it there + offset = self.cue.tracks[0].getIndex(1)[0] for i in range(len(self.cue.tracks)): self._offsets.append(offset) @@ -99,11 +99,13 @@ class Image: return ret - def cddbDiscId(self): + def getCDDBDiscId(self): n = 0 for track in self.cue.tracks: - offset = self.getTrackOffset(track) + # CD's have a standard lead-in time of 2 seconds + # which gets added for CDDB disc id's + offset = self.getTrackOffset(track) + 2 * crc.DISC_FRAMES_PER_SECOND seconds = offset / crc.DISC_FRAMES_PER_SECOND n += self._cddbSum(seconds) @@ -116,6 +118,37 @@ class Image: return "%08x" % value + def getAccurateRipIds(self): + """ + @rtype: two-tuple of (str, str) + """ + discId1 = 0 + discId2 = 0 + + for i, track in enumerate(self.cue.tracks): + offset = self.getTrackOffset(track) + discId1 += offset + discId2 += (offset or 1) * (i + 1) + + # also add end offsets + last = self.cue.tracks[-1] + leadout = self.getTrackOffset(last) + self.getTrackLength(last) + discId1 += leadout + discId2 += leadout * (len(self.cue.tracks) + 1) + + discId1 &= 0xffffffff + discId2 &= 0xffffffff + + return ("%08x" % discId1, "%08x" % discId2) + + def getAccurateRipURL(self): + discId1, discId2 = self.getAccurateRipIds() + + return "http://www.accuraterip.com/accuraterip/" \ + "%s/%s/%s/dBAR-%.3d-%s-%s-%s.bin" % ( + discId1[-1], discId1[-2], discId1[-3], + len(self.cue.tracks), discId1, discId2, self.getCDDBDiscId()) + class MultiTask(task.Task): """ I perform multiple tasks. diff --git a/morituri/test/test_image_image.py b/morituri/test/test_image_image.py index 05a378e..9a872f5 100644 --- a/morituri/test/test_image_image.py +++ b/morituri/test/test_image_image.py @@ -38,7 +38,11 @@ class TrackSingleTestCase(unittest.TestCase): self.assertEquals(self.image.getTrackLength(tracks[3]), 4) def testCDDB(self): - self.assertEquals(self.image.cddbDiscId(), "08000004") + self.assertEquals(self.image.getCDDBDiscId(), "08000004") + + def testAccurateRip(self): + self.assertEquals(self.image.getAccurateRipIds(), ( + "00000016", "0000005b")) class TracSeparateTestCase(unittest.TestCase): def setUp(self): @@ -65,7 +69,11 @@ class TracSeparateTestCase(unittest.TestCase): self.assertEquals(self.image.getTrackLength(tracks[3]), 10) def testCDDB(self): - self.assertEquals(self.image.cddbDiscId(), "08000004") + self.assertEquals(self.image.getCDDBDiscId(), "08000004") + + def testAccurateRip(self): + self.assertEquals(self.image.getAccurateRipIds(), ( + "00000064", "00000191")) class AudioLengthTestCase(unittest.TestCase): def testLength(self):