From 2d892291a8f82c9515080420bb93440130d3a2fa Mon Sep 17 00:00:00 2001 From: Thomas Vander Stichele Date: Sun, 7 Jun 2009 17:10:54 +0000 Subject: [PATCH] * 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. --- ChangeLog | 13 ++++ morituri/common/program.py | 150 +++++++++++++++++++------------------ morituri/result/result.py | 13 ++++ morituri/rip/cd.py | 120 ++++++++++++----------------- 4 files changed, 154 insertions(+), 142 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6e42f82..4c2e5f3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2009-06-07 Thomas Vander Stichele + + * 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 * morituri/common/program.py: diff --git a/morituri/common/program.py b/morituri/common/program.py index 50407cc..966b55a 100644 --- a/morituri/common/program.py +++ b/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) diff --git a/morituri/result/result.py b/morituri/result/result.py index b7a1339..f5215bc 100644 --- a/morituri/result/result.py +++ b/morituri/result/result.py @@ -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. diff --git a/morituri/rip/cd.py b/morituri/rip/cd.py index ef592c4..ae28330 100644 --- a/morituri/rip/cd.py +++ b/morituri/rip/cd.py @@ -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'