* morituri/common/program.py:
Move getPath to Program. Remove arguments to ripTrack that can be gotten from trackResult. * morituri/rip/cd.py: Continue without musicbrainz metadata. Unify htoa and normal track ripping. * morituri/result/result.py: Add getTrackResult so it's easier to look up track results when there's a HTOA.
This commit is contained in:
13
ChangeLog
13
ChangeLog
@@ -1,3 +1,16 @@
|
||||
2009-06-07 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||
|
||||
* morituri/common/program.py:
|
||||
Move getPath to Program.
|
||||
Remove arguments to ripTrack that can be gotten from
|
||||
trackResult.
|
||||
* morituri/rip/cd.py:
|
||||
Continue without musicbrainz metadata.
|
||||
Unify htoa and normal track ripping.
|
||||
* morituri/result/result.py:
|
||||
Add getTrackResult so it's easier to look up track results
|
||||
when there's a HTOA.
|
||||
|
||||
2009-06-07 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||
|
||||
* morituri/common/program.py:
|
||||
|
||||
@@ -121,62 +121,17 @@ def musicbrainz(discid):
|
||||
|
||||
return ret
|
||||
|
||||
def getPath(outdir, template, metadata, mbdiscid, i):
|
||||
"""
|
||||
Based on the template, get a complete path for the given track,
|
||||
minus extension.
|
||||
Also works for the disc name, using disc variables for the template.
|
||||
|
||||
@param outdir: the directory where to write the files
|
||||
@type outdir: str
|
||||
@param template: the template for writing the file
|
||||
@type template: str
|
||||
@param metadata:
|
||||
@type metadata: L{DiscMetadata}
|
||||
@param i: track number (0 for HTOA)
|
||||
@type i: int
|
||||
"""
|
||||
# returns without extension
|
||||
|
||||
v = {}
|
||||
|
||||
v['t'] = '%02d' % i
|
||||
|
||||
# default values
|
||||
v['A'] = 'Unknown Artist'
|
||||
v['d'] = mbdiscid
|
||||
|
||||
v['a'] = v['A']
|
||||
v['n'] = 'Unknown Track %d' % i
|
||||
|
||||
if metadata:
|
||||
v['A'] = filterForPath(metadata.artist)
|
||||
v['d'] = filterForPath(metadata.title)
|
||||
if i > 0:
|
||||
try:
|
||||
v['a'] = filterForPath(metadata.tracks[i - 1].artist)
|
||||
v['n'] = filterForPath(metadata.tracks[i - 1].title)
|
||||
except IndexError, e:
|
||||
print 'ERROR: no track %d found, %r' % (i, e)
|
||||
raise
|
||||
else:
|
||||
# htoa defaults to disc's artist
|
||||
v['a'] = filterForPath(metadata.artist)
|
||||
v['n'] = filterForPath('Hidden Track One Audio')
|
||||
|
||||
import re
|
||||
template = re.sub(r'%(\w)', r'%(\1)s', template)
|
||||
|
||||
return os.path.join(outdir, template % v)
|
||||
|
||||
|
||||
class Program(object):
|
||||
"""
|
||||
I maintain program state and functionality.
|
||||
|
||||
@ivar metadata:
|
||||
@type metadata: L{DiscMetadata}
|
||||
"""
|
||||
|
||||
cuePath = None
|
||||
logPath = None
|
||||
metadata = None
|
||||
|
||||
def __init__(self):
|
||||
self.result = result.RipResult()
|
||||
@@ -218,14 +173,58 @@ class Program(object):
|
||||
|
||||
return itable
|
||||
|
||||
def getTagList(self, metadata, i):
|
||||
def getPath(self, outdir, template, mbdiscid, i):
|
||||
"""
|
||||
Based on the template, get a complete path for the given track,
|
||||
minus extension.
|
||||
Also works for the disc name, using disc variables for the template.
|
||||
|
||||
@param outdir: the directory where to write the files
|
||||
@type outdir: str
|
||||
@param template: the template for writing the file
|
||||
@type template: str
|
||||
@param i: track number (0 for HTOA)
|
||||
@type i: int
|
||||
"""
|
||||
# returns without extension
|
||||
|
||||
v = {}
|
||||
|
||||
v['t'] = '%02d' % i
|
||||
|
||||
# default values
|
||||
v['A'] = 'Unknown Artist'
|
||||
v['d'] = mbdiscid
|
||||
|
||||
v['a'] = v['A']
|
||||
v['n'] = 'Unknown Track %d' % i
|
||||
|
||||
if self.metadata:
|
||||
v['A'] = filterForPath(self.metadata.artist)
|
||||
v['d'] = filterForPath(self.metadata.title)
|
||||
if i > 0:
|
||||
try:
|
||||
v['a'] = filterForPath(self.metadata.tracks[i - 1].artist)
|
||||
v['n'] = filterForPath(self.metadata.tracks[i - 1].title)
|
||||
except IndexError, e:
|
||||
print 'ERROR: no track %d found, %r' % (i, e)
|
||||
raise
|
||||
else:
|
||||
# htoa defaults to disc's artist
|
||||
v['a'] = filterForPath(self.metadata.artist)
|
||||
v['n'] = filterForPath('Hidden Track One Audio')
|
||||
|
||||
import re
|
||||
template = re.sub(r'%(\w)', r'%(\1)s', template)
|
||||
|
||||
return os.path.join(outdir, template % v)
|
||||
|
||||
def getTagList(self, number):
|
||||
"""
|
||||
Based on the metadata, get a gst.TagList for the given track.
|
||||
|
||||
@param metadata:
|
||||
@type metadata: L{DiscMetadata}
|
||||
@param i: track number (0 for HTOA)
|
||||
@type i: int
|
||||
@param number: track number (0 for HTOA)
|
||||
@type number: int
|
||||
|
||||
@rtype: L{gst.TagList}
|
||||
"""
|
||||
@@ -233,15 +232,15 @@ class Program(object):
|
||||
disc = u'Unknown Disc'
|
||||
title = u'Unknown Track'
|
||||
|
||||
if metadata:
|
||||
artist = metadata.artist
|
||||
disc = metadata.title
|
||||
if i > 0:
|
||||
if self.metadata:
|
||||
artist = self.metadata.artist
|
||||
disc = self.metadata.title
|
||||
if number > 0:
|
||||
try:
|
||||
artist = metadata.tracks[i - 1].artist
|
||||
title = metadata.tracks[i - 1].title
|
||||
artist = self.metadata.tracks[number - 1].artist
|
||||
title = self.metadata.tracks[number - 1].title
|
||||
except IndexError, e:
|
||||
print 'ERROR: no track %d found, %r' % (i, e)
|
||||
print 'ERROR: no track %d found, %r' % (number, e)
|
||||
raise
|
||||
else:
|
||||
# htoa defaults to disc's artist
|
||||
@@ -259,18 +258,18 @@ class Program(object):
|
||||
# see gst-python commit 26fa6dd184a8d6d103eaddf5f12bd7e5144413fb
|
||||
# FIXME: no way to compare against 'master' version after 0.10.15
|
||||
if gst.pygst_version >= (0, 10, 15):
|
||||
ret[gst.TAG_TRACK_NUMBER] = i
|
||||
if metadata:
|
||||
ret[gst.TAG_TRACK_NUMBER] = number
|
||||
if self.metadata:
|
||||
# works, but not sure we want this
|
||||
# if gst.pygst_version >= (0, 10, 15):
|
||||
# ret[gst.TAG_TRACK_COUNT] = len(metadata.tracks)
|
||||
# ret[gst.TAG_TRACK_COUNT] = len(self.metadata.tracks)
|
||||
# hack to get a GstDate which we cannot instantiate directly in
|
||||
# 0.10.15.1
|
||||
# FIXME: The dates are strings and must have the format 'YYYY',
|
||||
# 'YYYY-MM' or 'YYYY-MM-DD'.
|
||||
# GstDate expects a full date, so default to Jan and 1st if MM and DD
|
||||
# are missing
|
||||
date = metadata.release
|
||||
date = self.metadata.release
|
||||
if date:
|
||||
log.debug('metadata',
|
||||
'Converting release date %r to structure', date)
|
||||
@@ -300,21 +299,30 @@ class Program(object):
|
||||
return None
|
||||
|
||||
start = index.absolute
|
||||
stop = track.getIndex(1).absolute
|
||||
stop = track.getIndex(1).absolute - 1
|
||||
return (start, stop)
|
||||
|
||||
def ripTrack(self, runner, trackResult, path, number, offset, device, profile, taglist):
|
||||
def ripTrack(self, runner, trackResult, offset, device, profile, taglist):
|
||||
"""
|
||||
@param number: track number (1-based)
|
||||
"""
|
||||
t = cdparanoia.ReadVerifyTrackTask(path, self.result.table,
|
||||
self.result.table.getTrackStart(number),
|
||||
self.result.table.getTrackEnd(number),
|
||||
if trackResult.number == 0:
|
||||
start, stop = self.getHTOA()
|
||||
else:
|
||||
start = self.result.table.getTrackStart(trackResult.number)
|
||||
stop = self.result.table.getTrackEnd(trackResult.number)
|
||||
|
||||
dirname = os.path.dirname(trackResult.filename)
|
||||
if not os.path.exists(dirname):
|
||||
os.makedirs(dirname)
|
||||
|
||||
t = cdparanoia.ReadVerifyTrackTask(trackResult.filename,
|
||||
self.result.table, start, stop,
|
||||
offset=offset,
|
||||
device=device,
|
||||
profile=profile,
|
||||
taglist=taglist)
|
||||
t.description = 'Reading Track %d' % (number)
|
||||
t.description = 'Reading Track %d' % trackResult.number
|
||||
|
||||
runner.run(t)
|
||||
|
||||
|
||||
@@ -65,6 +65,19 @@ class RipResult:
|
||||
def __init__(self):
|
||||
self.tracks = []
|
||||
|
||||
def getTrackResult(self, number):
|
||||
"""
|
||||
@param number: the track number (0 for HTOA)
|
||||
|
||||
@type number: int
|
||||
@rtype: L{TrackResult}
|
||||
"""
|
||||
for t in self.tracks:
|
||||
if t.number == number:
|
||||
return t
|
||||
|
||||
return None
|
||||
|
||||
class Logger(object):
|
||||
"""
|
||||
I log the result of a rip.
|
||||
|
||||
@@ -102,9 +102,7 @@ class Rip(logcommand.LogCommand):
|
||||
metadatas = program.musicbrainz(mbdiscid)
|
||||
except program.MusicBrainzException, e:
|
||||
print "Error:", e
|
||||
return
|
||||
|
||||
metadata = None
|
||||
print 'Continuing without metadata'
|
||||
|
||||
if metadatas:
|
||||
print 'Matching releases:'
|
||||
@@ -113,7 +111,7 @@ class Rip(logcommand.LogCommand):
|
||||
print 'Title :', metadata.title
|
||||
|
||||
# Select one of the returned releases. We just pick the first one.
|
||||
metadata = metadatas[0]
|
||||
prog.metadata = metadatas[0]
|
||||
else:
|
||||
print 'Submit this disc to MusicBrainz at:'
|
||||
print ittoc.getMusicBrainzSubmitURL()
|
||||
@@ -138,8 +136,8 @@ class Rip(logcommand.LogCommand):
|
||||
|
||||
# result
|
||||
prog.result.offset = int(self.options.offset)
|
||||
prog.result.artist = metadata and metadata.artist or 'Unknown Artist'
|
||||
prog.result.title = metadata and metadata.title or 'Unknown Title'
|
||||
prog.result.artist = prog.metadata and prog.metadata.artist or 'Unknown Artist'
|
||||
prog.result.title = prog.metadata and prog.metadata.title or 'Unknown Title'
|
||||
# cdio is optional for now
|
||||
try:
|
||||
import cdio
|
||||
@@ -149,6 +147,44 @@ class Rip(logcommand.LogCommand):
|
||||
prog.result.vendor = 'Unknown'
|
||||
prog.result.model = 'Unknown'
|
||||
|
||||
def ripIfNotRipped(number):
|
||||
trackResult = result.TrackResult()
|
||||
prog.result.tracks.append(trackResult)
|
||||
|
||||
path = prog.getPath(outdir, self.options.track_template,
|
||||
mbdiscid, number) + '.' + extension
|
||||
trackResult.number = number
|
||||
trackResult.filename = path
|
||||
if number > 0:
|
||||
trackResult.pregap = itable.tracks[number - 1].getPregap()
|
||||
|
||||
# FIXME: optionally allow overriding reripping
|
||||
if not os.path.exists(path):
|
||||
print 'Ripping track %d of %d: %s' % (
|
||||
number, len(itable.tracks), os.path.basename(path))
|
||||
prog.ripTrack(runner, trackResult,
|
||||
offset=int(self.options.offset),
|
||||
device=self.parentCommand.options.device,
|
||||
profile=profile,
|
||||
taglist=prog.getTagList(number))
|
||||
|
||||
if trackResult.testcrc == trackResult.copycrc:
|
||||
print 'Checksums match for track %d' % (number)
|
||||
else:
|
||||
print 'ERROR: checksums did not match for track %d' % (
|
||||
number)
|
||||
print 'Peak level: %.2f %%' % (math.sqrt(trackResult.peak) * 100.0, )
|
||||
print 'Rip quality: %.2f %%' % (trackResult.quality * 100.0, )
|
||||
|
||||
# overlay this rip onto the Table
|
||||
if number == 0:
|
||||
# HTOA goes on index 0 of track 1
|
||||
itable.setFile(1, 0, path, ittoc.getTrackStart(1),
|
||||
number)
|
||||
else:
|
||||
itable.setFile(number, 1, path, ittoc.getTrackLength(number),
|
||||
number)
|
||||
|
||||
|
||||
# check for hidden track one audio
|
||||
htoa = prog.getHTOA()
|
||||
@@ -158,33 +194,8 @@ class Rip(logcommand.LogCommand):
|
||||
start, stop)
|
||||
|
||||
# rip it
|
||||
htoapath = program.getPath(outdir, self.options.track_template,
|
||||
metadata, mbdiscid, 0) + '.' + extension
|
||||
dirname = os.path.dirname(htoapath)
|
||||
if not os.path.exists(dirname):
|
||||
os.makedirs(dirname)
|
||||
|
||||
htoalength = stop - start
|
||||
if not os.path.exists(htoapath):
|
||||
print 'Ripping track %d: %s' % (0, os.path.basename(htoapath))
|
||||
t = cdparanoia.ReadVerifyTrackTask(htoapath, ittoc,
|
||||
start, stop - 1,
|
||||
offset=int(self.options.offset),
|
||||
device=self.parentCommand.options.device,
|
||||
profile=profile,
|
||||
taglist=prog.getTagList(metadata, 0))
|
||||
function(runner, t)
|
||||
|
||||
if t.checksum is not None:
|
||||
print 'Checksums match for track %d' % 0
|
||||
else:
|
||||
print 'ERROR: checksums did not match for track %d' % 0
|
||||
print 'Peak level: %.2f %%' % (t.peak * 100.0, )
|
||||
if t.peak == 0.0:
|
||||
print 'HTOA is completely silent'
|
||||
# overlay this rip onto the Table
|
||||
itable.setFile(1, 0, htoapath, htoalength, 0)
|
||||
|
||||
ripIfNotRipped(0)
|
||||
htoapath = prog.result.tracks[0].filename
|
||||
|
||||
for i, track in enumerate(itable.tracks):
|
||||
# FIXME: rip data tracks differently
|
||||
@@ -195,43 +206,10 @@ class Rip(logcommand.LogCommand):
|
||||
track.indexes[1].relative = 0
|
||||
continue
|
||||
|
||||
trackResult = result.TrackResult()
|
||||
prog.result.tracks.append(trackResult)
|
||||
|
||||
path = program.getPath(outdir, self.options.track_template, metadata,
|
||||
mbdiscid, i + 1) + '.' + extension
|
||||
trackResult.number = i + 1
|
||||
trackResult.filename = path
|
||||
trackResult.pregap = itable.tracks[i].getPregap()
|
||||
|
||||
dirname = os.path.dirname(path)
|
||||
if not os.path.exists(dirname):
|
||||
os.makedirs(dirname)
|
||||
|
||||
# FIXME: optionally allow overriding reripping
|
||||
if not os.path.exists(path):
|
||||
print 'Ripping track %d of %d: %s' % (
|
||||
i + 1, len(itable.tracks), os.path.basename(path))
|
||||
prog.ripTrack(runner, trackResult, path, i + 1,
|
||||
offset=int(self.options.offset),
|
||||
device=self.parentCommand.options.device,
|
||||
profile=profile,
|
||||
taglist=prog.getTagList(metadata, i + 1))
|
||||
|
||||
if trackResult.testcrc == trackResult.copycrc:
|
||||
print 'Checksums match for track %d' % (i + 1)
|
||||
else:
|
||||
print 'ERROR: checksums did not match for track %d' % (
|
||||
i + 1)
|
||||
print 'Peak level: %.2f %%' % (math.sqrt(trackResult.peak) * 100.0, )
|
||||
print 'Rip quality: %.2f %%' % (trackResult.quality * 100.0, )
|
||||
|
||||
# overlay this rip onto the Table
|
||||
itable.setFile(i + 1, 1, path, ittoc.getTrackLength(i + 1), i + 1)
|
||||
|
||||
ripIfNotRipped(i + 1)
|
||||
|
||||
### write disc files
|
||||
discName = program.getPath(outdir, self.options.disc_template, metadata,
|
||||
discName = prog.getPath(outdir, self.options.disc_template,
|
||||
mbdiscid, 0)
|
||||
dirname = os.path.dirname(discName)
|
||||
if not os.path.exists(dirname):
|
||||
@@ -245,7 +223,7 @@ class Rip(logcommand.LogCommand):
|
||||
handle.write('#EXTM3U\n')
|
||||
if htoapath:
|
||||
handle.write('#EXTINF:%d,%s\n' % (
|
||||
htoalength / common.FRAMES_PER_SECOND,
|
||||
itable.getTrackStart(1) / common.FRAMES_PER_SECOND,
|
||||
os.path.basename(htoapath[:-4])))
|
||||
handle.write('%s\n' % os.path.basename(htoapath))
|
||||
|
||||
@@ -253,7 +231,7 @@ class Rip(logcommand.LogCommand):
|
||||
if not track.audio:
|
||||
continue
|
||||
|
||||
path = program.getPath(outdir, self.options.track_template, metadata,
|
||||
path = prog.getPath(outdir, self.options.track_template,
|
||||
mbdiscid, i + 1) + '.' + extension
|
||||
u = u'#EXTINF:%d,%s\n' % (
|
||||
itable.getTrackLength(i + 1) / common.FRAMES_PER_SECOND,
|
||||
@@ -293,7 +271,7 @@ class Rip(logcommand.LogCommand):
|
||||
|
||||
# loop over tracks
|
||||
for i, csum in enumerate(cuetask.checksums):
|
||||
trackResult = prog.result.tracks[i]
|
||||
trackResult = prog.result.getTrackResult(i + 1)
|
||||
trackResult.accuripCRC = csum
|
||||
|
||||
status = 'rip NOT accurate'
|
||||
|
||||
Reference in New Issue
Block a user