From 03cb3b08808cafba9dac25a013243242f47997f6 Mon Sep 17 00:00:00 2001 From: Thomas Vander Stichele Date: Fri, 5 Jun 2009 09:47:03 +0000 Subject: [PATCH] * morituri/rip/cd.py: Use RipResult to store result information. * morituri/result/logger.py (added): Add a Logger to handle the RipResult, much like EAC's log file. --- ChangeLog | 8 +++ morituri/result/logger.py | 127 ++++++++++++++++++++++++++++++++++++++ morituri/rip/cd.py | 39 +++++++++++- 3 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 morituri/result/logger.py diff --git a/ChangeLog b/ChangeLog index 25ad955..2117663 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2009-06-05 Thomas Vander Stichele + + * morituri/rip/cd.py: + Use RipResult to store result information. + * morituri/result/logger.py (added): + Add a Logger to handle the RipResult, much like + EAC's log file. + 2009-06-05 Thomas Vander Stichele * morituri/rip/cd.py: diff --git a/morituri/result/logger.py b/morituri/result/logger.py new file mode 100644 index 0000000..05bbf1c --- /dev/null +++ b/morituri/result/logger.py @@ -0,0 +1,127 @@ +# -*- Mode: Python; test-case-name: morituri.test.test_result_logger -*- +# 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 . + +import os +import time + +from morituri.common import common +from morituri.configure import configure + +class MorituriLogger(object): + + def log(self, ripResult, epoch=time.time()): + lines = self.logRip(ripResult, epoch=epoch) + return '\n'.join(lines) + + + def logRip(self, ripResult, epoch): + + lines = [] + + ### global + + lines.append("Logfile created by: morituri %s" % configure.version) + date = time.strftime("%b %d %H:%M:%S", time.localtime(epoch)) + lines.append("Logfile created on: %s" % date) + lines.append("") + + # album + lines.append("Album: %s - %s" % (ripResult.artist, ripResult.title)) + lines.append("") + + # drive + lines.append( + "Drive: vendor %s, model %s" % ( + ripResult.vendor, ripResult.model)) + lines.append("") + + lines.append("Read offset correction: %d" % + ripResult.offset) + lines.append("") + + # toc + lines.append("Table of Contents:") + lines.append("") + lines.append( + " Track | Start | Length") + lines.append( + " ------------------------------------------------") + table = ripResult.toctable + + + for t in table.tracks: + start = t.getIndex(1).absolute + length = table.getTrackLength(t.number) + lines.append( + " %2d | %6d - %s | %6d - %s" % ( + t.number, + start, common.framesToMSF(start), + length, common.framesToMSF(length))) + + lines.append("") + lines.append("") + + ### per-track + for t in ripResult.tracks: + lines.extend(self.trackLog(t)) + lines.append('') + + return lines + + def trackLog(self, trackResult): + + lines = [] + + lines.append('Track %2d' % trackResult.number) + lines.append('') + lines.append(' Filename %s' % trackResult.filename) + lines.append('') + if trackResult.pregap: + lines.append(' Pre-gap: %s' % common.framesToMSF( + trackResult.pregap)) + lines.append('') + + lines.append(' Peak level %.1f %%' % (trackResult.peak * 100.0)) + if trackResult.copycrc is not None: + lines.append(' Copy CRC %08X' % trackResult.copycrc) + if trackResult.testcrc is not None: + lines.append(' Test CRC %08X' % trackResult.testcrc) + if trackResult.testcrc == trackResult.copycrc: + lines.append(' Copy OK') + else: + lines.append(" WARNING: CRCs don't match!") + else: + lines.append(" WARNING: no CRC check done") + + if trackResult.accurip: + if trackResult.accuripCRC == trackResult.accuripDatabaseCRC: + lines.append(' Accurately ripped (confidence %d) [%08X]' % ( + trackResult.accuripDatabaseConfidence, trackResult.accuripCRC)) + else: + lines.append(' Cannot be verified as accurate ' + '(confidence %d), [%08X], AccurateRip returned [%08x]' % ( + trackResult.accuripDatabaseConfidence, + trackResult.accuripCRC, trackResult.accuripDatabaseCRC)) + else: + lines.append(' Track not present in AccurateRip database') + + return lines diff --git a/morituri/rip/cd.py b/morituri/rip/cd.py index 5031104..c84ebd2 100644 --- a/morituri/rip/cd.py +++ b/morituri/rip/cd.py @@ -24,13 +24,16 @@ import os import sys import math +import cdio + import gobject gobject.threads_init() import gst -from morituri.common import logcommand, task, checksum, common, accurip +from morituri.common import logcommand, task, checksum, common, accurip, log from morituri.common import drive, encode +from morituri.result import result from morituri.image import image, cue, table from morituri.program import cdrdao, cdparanoia @@ -344,6 +347,14 @@ class Rip(logcommand.LogCommand): profile = encode.PROFILES[self.options.profile]() extension = profile.extension + # result + res = result.RipResult() + res.offset = int(self.options.offset) + res.toctable = itable + res.artist = metadata and metadata.artist or 'Unknown Artist' + res.title = metadata and metadata.title or 'Unknown Title' + _, res.vendor, res.model, __ = cdio.Device(device).get_hwinfo() + # check for hidden track one audio htoapath = None index = None @@ -389,11 +400,18 @@ class Rip(logcommand.LogCommand): for i, track in enumerate(itable.tracks): # FIXME: rip data tracks differently if not track.audio: + print 'Skipping data track %d' % (i + 1, ) # FIXME: make it work for now track.indexes[1].relative = 0 continue + trackResult = result.TrackResult() + res.tracks.append(trackResult) + path = getPath(outdir, self.options.track_template, metadata, i + 1) + '.' + extension + trackResult.number = i + 1 + trackResult.filename = path + dirname = os.path.dirname(path) if not os.path.exists(dirname): os.makedirs(dirname) @@ -415,6 +433,10 @@ class Rip(logcommand.LogCommand): print 'Checksums match for track %d' % (i + 1) else: print 'ERROR: checksums did not match for track %d' % (i + 1) + trackResult.testcrc = t.testchecksum + trackResult.copycrc = t.copychecksum + trackResult.peak = t.peak + print 'Peak level: %.2f %%' % (math.sqrt(t.peak) * 100.0, ) # overlay this rip onto the Table @@ -486,6 +508,9 @@ class Rip(logcommand.LogCommand): # loop over tracks for i, csum in enumerate(cuetask.checksums): + trackResult = res.tracks[i] + trackResult.accuripCRC = csum + status = 'rip NOT accurate' confidence = None @@ -501,8 +526,12 @@ class Rip(logcommand.LogCommand): "checksum %s" % ( csum, i + 1, j + 1, response.checksums[i]) status = 'rip accurate ' + trackResult.accurip = True + # FIXME: maybe checksums should be ints + trackResult.accuripDatabaseCRC = int(response.checksums[i], 16) # arsum = csum confidence = response.confidences[i] + trackResult.accuripDatabaseConfidence = confidence c = "(not found)" ar = "(not in database)" @@ -521,6 +550,14 @@ class Rip(logcommand.LogCommand): print "Track %2d: %s %s [%08x]%s" % ( i + 1, status, c, csum, ar) + # write log file + discName = getPath(outdir, self.options.disc_template, metadata, i) + logPath = '%s.log' % discName + logger = result.getLogger() + handle = open(logPath, 'w') + handle.write(logger.log(res)) + handle.close() + class CD(logcommand.LogCommand): summary = "handle CD's"