From 297451ea0e6ccf8adb332bfc4d6cf2be2efe9a9d Mon Sep 17 00:00:00 2001 From: Thomas Vander Stichele Date: Tue, 13 Apr 2010 21:57:29 +0000 Subject: [PATCH] * morituri/common/program.py: Add a retagging command. Add a getMusicBrainz() method. * morituri/rip/cd.py: Use it. * morituri/image/image.py: Add a task to retag an image. * morituri/rip/image.py: Add a command to retag an image. --- ChangeLog | 12 +++++++++ morituri/common/program.py | 53 ++++++++++++++++++++++++++++++++++++-- morituri/image/image.py | 33 +++++++++++++++++++----- morituri/rip/cd.py | 21 +-------------- morituri/rip/image.py | 30 +++++++++++++++++++-- 5 files changed, 119 insertions(+), 30 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8dc4a3e..6cb47a1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2010-04-13 Thomas Vander Stichele + + * morituri/common/program.py: + Add a retagging command. + Add a getMusicBrainz() method. + * morituri/rip/cd.py: + Use it. + * morituri/image/image.py: + Add a task to retag an image. + * morituri/rip/image.py: + Add a command to retag an image. + 2010-04-13 Thomas Vander Stichele * morituri/common/encode.py: diff --git a/morituri/common/program.py b/morituri/common/program.py index eb004b0..5045309 100644 --- a/morituri/common/program.py +++ b/morituri/common/program.py @@ -25,6 +25,7 @@ Common functionality and class for all programs using morituri. """ import os +import urlparse from morituri.common import common, log from morituri.result import result @@ -71,18 +72,23 @@ def getMetadata(release): metadata.artist = release.artist.name metadata.sortName = release.artist.sortName metadata.release = release.getEarliestReleaseDate() + metadata.mbid = urlparse.urlparse(release.id)[2].split("/")[-1] + metadata.artistMBID = urlparse.urlparse(release.artist.id)[2].split("/")[-1] + for t in release.tracks: track = TrackMetadata() if isSingleArtist: track.artist = metadata.artist track.sortName = metadata.sortName - track.title = t.title + track.artistMBID = metadata.artistMBID else: # various artists discs can have tracks with no artist track.artist = t.artist and t.artist.name or release.artist.name track.sortName = t.artist.sortName - track.title = t.title + + track.title = t.title + track.mbid = urlparse.urlparse(t.id)[2].split("/")[-1] metadata.tracks.append(track) return metadata @@ -276,6 +282,34 @@ class Program(log.Loggable): return os.path.join(outdir, template % v) + def getMusicBrainz(self, ittoc, mbdiscid): + # look up disc on musicbrainz + ret = None + + metadatas = None + try: + metadatas = musicbrainz(mbdiscid) + except MusicBrainzException, e: + print "Error:", e + print 'Continuing without metadata' + + if metadatas: + print 'Matching releases:' + for metadata in metadatas: + print 'Artist : %s' % metadata.artist.encode('utf-8') + print 'Title : %s' % metadata.title.encode('utf-8') + + # Select one of the returned releases. We just pick the first one. + ret = metadatas[0] + else: + print 'Submit this disc to MusicBrainz at:' + print ittoc.getMusicBrainzSubmitURL() + ret = None + + print + return ret + + def getTagList(self, number): """ Based on the metadata, get a gst.TagList for the given track. @@ -292,10 +326,15 @@ class Program(log.Loggable): if self.metadata: artist = self.metadata.artist disc = self.metadata.title + albumMBID = self.metadata.mbid + albumArtistMBID = self.metadata.artistMBID + if number > 0: try: artist = self.metadata.tracks[number - 1].artist title = self.metadata.tracks[number - 1].title + trackMBID = self.metadata.tracks[number - 1].mbid + trackArtistMBID = self.metadata.tracks[number - 1].artistMBID except IndexError, e: print 'ERROR: no track %d found, %r' % (number, e) raise @@ -342,6 +381,11 @@ class Program(log.Loggable): str(date)) ret[gst.TAG_DATE] = s['date'] + ret["musicbrainz-trackid"] = trackMBID + ret["musicbrainz-artistid"] = trackArtistMBID + ret["musicbrainz-albumid"] = albumMBID + ret["musicbrainz-albumartistid"] = albumArtistMBID + # FIXME: gst.TAG_ISRC return ret @@ -404,6 +448,11 @@ class Program(log.Loggable): trackResult.peak = t.peak trackResult.quality = t.quality + def retagImage(self, runner, taglists): + cueImage = image.Image(self.cuePath) + t = image.ImageRetagTask(cueImage, taglists) + runner.run(t) + def verifyImage(self, runner, responses): """ Verify our image against the given AccurateRip responses. diff --git a/morituri/image/image.py b/morituri/image/image.py index 8076f29..e209ab7 100644 --- a/morituri/image/image.py +++ b/morituri/image/image.py @@ -200,12 +200,7 @@ class AudioLengthTask(task.Task): error, debug = msg.parse_error() self.debug('Got GStreamer error: %r, debug: %r' % ( error.message, debug)) - # give us an exception stack for debugging - try: - raise error - except: - pass - self.setException(error) + self.setAndRaiseException(error) self.stop() class ImageVerifyTask(task.MultiSeparateTask): @@ -300,4 +295,30 @@ class ImageEncodeTask(task.MultiSeparateTask): index = track.indexes[1] add(index) +class ImageRetagTask(task.MultiSeparateTask): + """ + I retag files in a disk image. + """ + + description = "Retagging tracks" + def __init__(self, image, taglists): + task.MultiSeparateTask.__init__(self) + + # here to avoid import gst eating our options + from morituri.common import encode + + self._image = image + self._taglists = taglists + cue = image.cue + self._tasks = [] + self.lengths = {} + + for trackIndex, track in enumerate(cue.table.tracks): + self.debug('retagging track %d', trackIndex + 1) + index = track.indexes[1] + path = image.getRealPath(index.path) + assert type(path) is unicode, "%r is not unicode" % path + self.debug('schedule retag of %r', path) + root, ext = os.path.splitext(os.path.basename(path)) + taskk = encode.RetagTask(path, taglists[trackIndex]) diff --git a/morituri/rip/cd.py b/morituri/rip/cd.py index 5b7dd9f..86227f9 100644 --- a/morituri/rip/cd.py +++ b/morituri/rip/cd.py @@ -113,26 +113,7 @@ See http://sourceforge.net/tracker/?func=detail&aid=604751&group_id=2171&atid=1 mbdiscid = ittoc.getMusicBrainzDiscId() print "MusicBrainz disc id", mbdiscid - # look up disc on musicbrainz - metadatas = None - try: - metadatas = program.musicbrainz(mbdiscid) - except program.MusicBrainzException, e: - print "Error:", e - print 'Continuing without metadata' - - if metadatas: - print 'Matching releases:' - for metadata in metadatas: - print 'Artist : %s' % metadata.artist.encode('utf-8') - print 'Title : %s' % metadata.title.encode('utf-8') - - # Select one of the returned releases. We just pick the first one. - prog.metadata = metadatas[0] - else: - print 'Submit this disc to MusicBrainz at:' - print ittoc.getMusicBrainzSubmitURL() - print + prog.metadata = prog.getMusicBrainz(ittoc, mbdiscid) # now, read the complete index table, which is slower itable = prog.getTable(runner, ittoc.getCDDBDiscId(), device) diff --git a/morituri/rip/image.py b/morituri/rip/image.py index 3a750e9..3743309 100644 --- a/morituri/rip/image.py +++ b/morituri/rip/image.py @@ -22,7 +22,7 @@ import os -from morituri.common import logcommand, task, accurip, program +from morituri.common import logcommand, task, accurip, program, encode from morituri.image import image, cue from morituri.result import result from morituri.program import cdrdao, cdparanoia @@ -97,6 +97,32 @@ class Encode(logcommand.LogCommand): outm3u.write('%s' % root) outm3u.close() +class Retag(logcommand.LogCommand): + summary = "retag image files" + + def do(self, args): + prog = program.Program() + runner = task.SyncRunner() + cache = accurip.AccuCache() + + for arg in args: + arg = unicode(arg) + cueImage = image.Image(arg) + cueImage.setup(runner) + + mbdiscid = cueImage.table.getMusicBrainzDiscId() + prog.metadata = prog.getMusicBrainz(cueImage.table, mbdiscid) + + # FIXME: this feels like we're poking at internals. + prog.cuePath = arg + prog.result = result.RipResult() + for track in cueImage.table.tracks: + path = track.indexes[1].path + taglist = prog.getTagList(track.number) + self.debug('possibly retagging %r with taglist %r', + path, taglist) + runner.run(encode.SafeRetagTask(path, taglist)) + class Verify(logcommand.LogCommand): summary = "verify image" @@ -128,4 +154,4 @@ class Verify(logcommand.LogCommand): class Image(logcommand.LogCommand): summary = "handle images" - subCommandClasses = [Encode, Verify, ] + subCommandClasses = [Encode, Retag, Verify, ]