From 08fc4f67a6751d8505ff397a118ebbd623e52d49 Mon Sep 17 00:00:00 2001 From: Thomas Vander Stichele Date: Sun, 2 Jan 2011 17:14:26 +0000 Subject: [PATCH] * morituri/common/program.py: * morituri/image/table.py: * morituri/rip/cd.py: Get CDDB disc id. Use it to print info when not found on MusicBrainz. --- ChangeLog | 8 ++++ morituri/common/program.py | 16 ++++++++ morituri/image/table.py | 84 +++++++++++++++++++++++++++++++++++--- morituri/rip/cd.py | 14 +++++-- 4 files changed, 113 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2c30a0c..1d0951f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-01-02 Thomas Vander Stichele + + * morituri/common/program.py: + * morituri/image/table.py: + * morituri/rip/cd.py: + Get CDDB disc id. Use it to print info when not found on + MusicBrainz. + 2011-01-01 Thomas Vander Stichele * morituri/rip/cd.py: diff --git a/morituri/common/program.py b/morituri/common/program.py index ef03add..a52ea24 100644 --- a/morituri/common/program.py +++ b/morituri/common/program.py @@ -301,6 +301,22 @@ class Program(log.Loggable): return os.path.join(outdir, template % v) + def getCDDB(self, cddbdiscid): + """ + @param cddbdiscid: list of id, tracks, offsets, seconds + + @rtype: str + """ + # FIXME: convert to nonblocking? + import CDDB + code, md = CDDB.query(cddbdiscid) + self.debug('CDDB query result: %r, %r', code, md) + if code == 200: + return md['title'] + + return None + + def getMusicBrainz(self, ittoc, mbdiscid): # look up disc on musicbrainz ret = None diff --git a/morituri/image/table.py b/morituri/image/table.py index dbdc9d2..19921cf 100644 --- a/morituri/image/table.py +++ b/morituri/image/table.py @@ -239,13 +239,70 @@ class Table(object, log.Loggable): return ret - def getCDDBDiscId(self): + def _getCDDBValues(self): """ - Calculate the CDDB disc ID. + Get all CDDB values needed to calculate disc id and lookup URL. - @rtype: str - @returns: the 8-character hexadecimal disc ID + This includes: + - CDDB disc id + - number of audio tracks + - offset of index 1 of each track + - length of disc in seconds + + @rtype: list of int """ + result = [] + + # number of first track + result.append(1) + + # number of last audio track + result.append(self.getAudioTracks()) + + leadout = self.leadout + # if the disc is multi-session, last track is the data track, + # and we should subtract 11250 + 150 from the last track's offset + # for the leadout + if self.hasDataTracks(): + assert not self.tracks[-1].audio + leadout = self.tracks[-1].getIndex(1).absolute - 11250 - 150 + + # treat leadout offset as track 0 offset + result.append(150 + leadout) + + # offsets of tracks + for i in range(1, 100): + try: + track = self.tracks[i - 1] + if not track.audio: + continue + offset = track.getIndex(1).absolute + 150 + result.append(offset) + except IndexError: + pass + + + self.debug('CDDB values: %r', result) + return result + + + + def getCDDBValues(self): + """ + Get all CDDB values needed to calculate disc id and lookup URL. + + This includes: + - CDDB disc id + - number of audio tracks + - offset of index 1 of each track + - length of disc in seconds + + @rtype: list of int + """ + result = [] + + result.append(self.getAudioTracks()) + # cddb disc id takes into account data tracks # last byte is the number of tracks on the CD n = 0 @@ -259,6 +316,7 @@ class Table(object, log.Loggable): debug = [str(len(self.tracks))] for track in self.tracks: offset = self.getTrackStart(track.number) + delta + result.append(offset) debug.append(str(offset)) seconds = offset / common.FRAMES_PER_SECOND n += self._cddbSum(seconds) @@ -272,14 +330,30 @@ class Table(object, log.Loggable): leadoutSeconds = leadout / common.FRAMES_PER_SECOND t = leadoutSeconds - startSeconds debug.append(str(leadoutSeconds + 2)) # 2 is the 150 frame cddb offset + result.append(leadoutSeconds) value = (n % 0xff) << 24 | t << 8 | len(self.tracks) + result.insert(0, value) # compare this debug line to cd-discid output + self.debug('cddb values: %r', result) + self.debug('cddb disc id debug: %s', " ".join(["%08x" % value, ] + debug)) - return "%08x" % value + return result + + + def getCDDBDiscId(self): + """ + Calculate the CDDB disc ID. + + @rtype: str + @returns: the 8-character hexadecimal disc ID + """ + values = self.getCDDBValues() + return "%08x" % values[0] + def getMusicBrainzDiscId(self): """ diff --git a/morituri/rip/cd.py b/morituri/rip/cd.py index 1903252..0557e2c 100644 --- a/morituri/rip/cd.py +++ b/morituri/rip/cd.py @@ -137,10 +137,16 @@ See http://sourceforge.net/tracker/?func=detail&aid=604751&group_id=2171&atid=1 prog.metadata = prog.getMusicBrainz(ittoc, mbdiscid) - # stop if the cd is unknown and we don't want to continue - if not prog.metadata and not self.options.unknown: - prog.ejectDevice(device) - return -1 + if not prog.metadata: + # fall back to FreeDB for lookup + cddbid = ittoc.getCDDBValues() + cddbmd = prog.getCDDB(cddbid) + if cddbmd: + print 'FreeDB identifies disc as %s' % cddbmd + + if not self.options.unknown: + prog.ejectDevice(device) + return -1 # now, read the complete index table, which is slower itable = prog.getTable(runner, ittoc.getCDDBDiscId(), device)