Change default logger to 'morituri-whatlogger'
This commit is contained in:
@@ -1,26 +1,5 @@
|
||||
# -*- 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
import time
|
||||
import hashlib
|
||||
|
||||
from morituri.common import common
|
||||
from morituri.configure import configure
|
||||
@@ -29,125 +8,191 @@ from morituri.result import result
|
||||
|
||||
class MorituriLogger(result.Logger):
|
||||
|
||||
_accuratelyRipped = 0
|
||||
_inARDatabase = 0
|
||||
_errors = False
|
||||
|
||||
def _framesToMSF(self, frames):
|
||||
# format specifically for EAC log; examples (5:39.57)
|
||||
f = frames % common.FRAMES_PER_SECOND
|
||||
frames -= f
|
||||
s = (frames / common.FRAMES_PER_SECOND) % 60
|
||||
frames -= s * 60
|
||||
m = frames / common.FRAMES_PER_SECOND / 60
|
||||
return "%2d:%02d.%02d" % (m, s, f)
|
||||
|
||||
def _framesToHMSH(self, frames):
|
||||
# format specifically for EAC log; examples (0:00.00.70)
|
||||
f = frames % common.FRAMES_PER_SECOND
|
||||
frames -= f
|
||||
s = (frames / common.FRAMES_PER_SECOND) % 60
|
||||
frames -= s * 60
|
||||
m = frames / common.FRAMES_PER_SECOND / 60
|
||||
frames -= m * 60
|
||||
h = frames / common.FRAMES_PER_SECOND / 60 / 60
|
||||
return "%2d:%02d:%02d.%02d" % (h, m, s, f)
|
||||
|
||||
def log(self, ripResult, epoch=time.time()):
|
||||
"""
|
||||
@type ripResult: L{morituri.result.result.RipResult}
|
||||
"""
|
||||
lines = self.logRip(ripResult, epoch=epoch)
|
||||
return '\n'.join(lines)
|
||||
return "\n".join(lines)
|
||||
|
||||
def logRip(self, ripResult, epoch):
|
||||
|
||||
lines = []
|
||||
|
||||
### global
|
||||
|
||||
lines.append("Logfile created by: morituri %s" % configure.version)
|
||||
# FIXME: when we localize this, see #49 to handle unicode properly.
|
||||
import locale
|
||||
old = locale.getlocale(locale.LC_TIME)
|
||||
locale.setlocale(locale.LC_TIME, 'C')
|
||||
date = time.strftime("%b %d %H:%M:%S", time.localtime(epoch))
|
||||
locale.setlocale(locale.LC_TIME, old)
|
||||
lines.append("Logfile created on: %s" % date)
|
||||
lines.append("Ripper: morituri %s" % configure.version)
|
||||
date = time.strftime("%Y-%m-%dT%H:%M:%S", time.gmtime(epoch)).strip()
|
||||
lines.append("Ripped at: %s" % date)
|
||||
lines.append("Drive: %s%s{%s}" %
|
||||
(ripResult.vendor, ripResult.model, ripResult.release))
|
||||
defeat = "Unknown"
|
||||
if ripResult.cdparanoiaDefeatsCache is True:
|
||||
defeat = "Yes"
|
||||
if ripResult.cdparanoiaDefeatsCache is False:
|
||||
defeat = "No"
|
||||
lines.append("Defeat audio cache: %s" % defeat)
|
||||
lines.append("")
|
||||
|
||||
# album
|
||||
lines.append("Album: %s - %s" % (ripResult.artist, ripResult.title))
|
||||
lines.append("Read offset correction: %d" % ripResult.offset)
|
||||
# Currently unsupported by the official cdparanoia package
|
||||
lines.append("Overread: No")
|
||||
# Fully working only using the patched cdparanoia package
|
||||
# lines.append("Fill up missing offset samples with silence: Yes")
|
||||
lines.append("Gap detection: cdrdao %s" % ripResult.cdrdaoVersion)
|
||||
lines.append("")
|
||||
|
||||
lines.append("CDDB disc id: %s" % ripResult. table.getCDDBDiscId())
|
||||
lines.append("MusicBrainz disc id: %s" % ripResult. table.getMusicBrainzDiscId())
|
||||
lines.append("MusicBrainz lookup URL: %s" % ripResult. table.getMusicBrainzSubmitURL())
|
||||
lines.append("Used output format: %s" % ripResult.profileName)
|
||||
lines.append("GStreamer:")
|
||||
lines.append(" Pipeline: %s" % ripResult.profilePipeline)
|
||||
lines.append(" Version: %s" % ripResult.gstreamerVersion)
|
||||
lines.append(" Python version: %s" % ripResult.gstPythonVersion)
|
||||
lines.append(" Encoder plugin version: %s" % ripResult.encoderVersion)
|
||||
lines.append("")
|
||||
|
||||
# drive
|
||||
lines.append(
|
||||
"Drive: vendor %s, model %s" % (
|
||||
ripResult.vendor, ripResult.model))
|
||||
lines.append("")
|
||||
|
||||
lines.append("Read offset correction: %d" %
|
||||
ripResult.offset)
|
||||
overread = "Unknown"
|
||||
if ripResult.overread is True:
|
||||
overread = "Yes (Lead-Out)"
|
||||
if ripResult.overread is False:
|
||||
overread = "No"
|
||||
lines.append("Overread: %s" % overread)
|
||||
lines.append("")
|
||||
|
||||
# toc
|
||||
lines.append("Table of Contents:")
|
||||
lines.append("")
|
||||
lines.append(
|
||||
" Track | Start | Length")
|
||||
lines.append(
|
||||
" ------------------------------------------------")
|
||||
lines.append("TOC:")
|
||||
table = ripResult.table
|
||||
|
||||
|
||||
htoa = None
|
||||
try:
|
||||
htoa = table.tracks[0].getIndex(0)
|
||||
except KeyError:
|
||||
pass
|
||||
if htoa and htoa.path:
|
||||
htoastart = htoa.absolute
|
||||
htoaend = table.getTrackEnd(0)
|
||||
htoalength = table.tracks[0].getIndex(1).absolute - htoastart + 1
|
||||
lines.append(" 0:")
|
||||
lines.append(" Start: %s" % self._framesToMSF(htoastart))
|
||||
lines.append(" Length: %s" % self._framesToMSF(htoalength))
|
||||
lines.append(" Start sector: %d" % htoastart)
|
||||
lines.append(" End sector: %d" % htoaend)
|
||||
for t in table.tracks:
|
||||
# FIXME: what happens to a track start over 60 minutes ?
|
||||
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)))
|
||||
end = table.getTrackEnd(t.number)
|
||||
lines.append(" %d:" % t.number)
|
||||
lines.append(" Start: %s" % self._framesToMSF(start))
|
||||
lines.append(" Length: %s" % self._framesToMSF(length))
|
||||
lines.append(" Start sector: %d" % start)
|
||||
lines.append(" End sector: %d" % end)
|
||||
lines.append("")
|
||||
|
||||
lines.append("")
|
||||
lines.append("")
|
||||
|
||||
### per-track
|
||||
lines.append("Tracks:")
|
||||
duration = 0.0
|
||||
for t in ripResult.tracks:
|
||||
if not t.filename:
|
||||
continue
|
||||
lines.extend(self.trackLog(t))
|
||||
lines.append('')
|
||||
lines.append("")
|
||||
duration += t.testduration + t.copyduration
|
||||
|
||||
lines.append("AccurateRip Summary:")
|
||||
if self._inARDatabase == 0:
|
||||
lines.append(" None of the tracks are present in "
|
||||
"the AccurateRip database")
|
||||
else:
|
||||
nonHTOA = len(ripResult.tracks)
|
||||
if ripResult.tracks[0].number == 0:
|
||||
nonHTOA -= 1
|
||||
if self._accuratelyRipped == 0:
|
||||
lines.append(" No tracks could be verified as accurate")
|
||||
lines.append(" You may have a different pressing "
|
||||
"from the one(s) in the database")
|
||||
elif self._accuratelyRipped < nonHTOA:
|
||||
lines.append(" %d track(s) accurately ripped" %
|
||||
self._accuratelyRipped)
|
||||
lines.append(" %d track(s) could not be verified as"
|
||||
"accurate" % (nonHTOA - self._accuratelyRipped))
|
||||
lines.append("")
|
||||
lines.append(" Some tracks could not be verified as accurate")
|
||||
else:
|
||||
lines.append(" All tracks accurately ripped")
|
||||
lines.append("")
|
||||
|
||||
lines.append("Errors:")
|
||||
if self._errors:
|
||||
lines.append(" There were errors")
|
||||
else:
|
||||
lines.append(" No errors occurred")
|
||||
lines.append("")
|
||||
lines.append("End of status report")
|
||||
lines.append("")
|
||||
|
||||
hasher = hashlib.sha256()
|
||||
hasher.update("\n".join(lines).encode("utf-8"))
|
||||
lines.append("==== Log checksum %s ====" % hasher.hexdigest())
|
||||
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))
|
||||
lines.append(" %d:" % trackResult.number)
|
||||
lines.append(" Filename: %s" % trackResult.filename)
|
||||
# EAC adds the 2 seconds to the first track pregap
|
||||
pregap = trackResult.pregap
|
||||
# if trackResult.number == 1:
|
||||
# pregap += 2 * common.FRAMES_PER_SECOND
|
||||
if pregap:
|
||||
lines.append(" Pre-gap length: %s" % self._framesToHMSH(pregap))
|
||||
# EAC seems to format peak differently, truncating to the 3rd digit,
|
||||
# and also calculating it against a max of 32767
|
||||
# MBV - Feed me with your kiss: replaygain 0.809875,
|
||||
# EAC's peak level 80.9 % instead of 90.0 %
|
||||
peak = trackResult.peak
|
||||
# lines.append(' Peak level %r' % peak)
|
||||
lines.append(" Peak level: %.6f %%" % peak)
|
||||
# level = "%.2f" % (trackResult.peak * 100.0)
|
||||
# level = level[:-1]
|
||||
# lines.append(' Peak level %s %%' % level)
|
||||
if trackResult.copyspeed:
|
||||
lines.append(' Extraction Speed (Copy) %.4f X' % (
|
||||
lines.append(" Extraction speed: %.1f X" % (
|
||||
trackResult.copyspeed))
|
||||
if trackResult.testspeed:
|
||||
lines.append(' Extraction Speed (Test) %.4f X' % (
|
||||
trackResult.testspeed))
|
||||
|
||||
if trackResult.copycrc is not None:
|
||||
lines.append(' Copy CRC %08X' % trackResult.copycrc)
|
||||
# Track quality is shown in secure mode
|
||||
if trackResult.quality and trackResult.quality > 0.001:
|
||||
lines.append(" Track quality: %.1f %%" %
|
||||
(trackResult.quality * 100.0, ))
|
||||
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")
|
||||
|
||||
|
||||
lines.append(" Test CRC: %08X" % trackResult.testcrc)
|
||||
if trackResult.copycrc is not None:
|
||||
lines.append(" Copy CRC: %08X" % trackResult.copycrc)
|
||||
lines.append(" AccurateRip v1:")
|
||||
if trackResult.accurip:
|
||||
lines.append(' Accurately ripped (confidence %d) [%08X]' % (
|
||||
trackResult.ARDBConfidence, trackResult.ARCRC))
|
||||
else:
|
||||
if trackResult.ARDBCRC:
|
||||
lines.append(' Cannot be verified as accurate '
|
||||
'[%08X], AccurateRip returned [%08X]' % (
|
||||
trackResult.ARCRC, trackResult.ARDBCRC))
|
||||
self._inARDatabase += 1
|
||||
if trackResult.ARCRC == trackResult.ARDBCRC:
|
||||
lines.append(" Confidence: %d" %
|
||||
trackResult.ARDBConfidence)
|
||||
lines.append(" Checksum: %08X" % trackResult.ARCRC)
|
||||
self._accuratelyRipped += 1
|
||||
else:
|
||||
lines.append(' Track not present in AccurateRip database')
|
||||
lines.append(" Cannot be verified as accurate "
|
||||
"(confidence %d), [%08X], "
|
||||
"AccurateRip returned [%08x]" % (
|
||||
trackResult.ARDBConfidence,
|
||||
trackResult.ARCRC, trackResult.ARDBCRC))
|
||||
else:
|
||||
lines.append(" Track not present in AccurateRip database")
|
||||
|
||||
if trackResult.testcrc == trackResult.copycrc:
|
||||
lines.append(" Copy OK")
|
||||
else:
|
||||
self._errors = True
|
||||
lines.append(" Error: CRC mismatch!")
|
||||
return lines
|
||||
|
||||
Reference in New Issue
Block a user