def do(self, args): prog = program.Program(self.getRootCommand().config) runner = ctask.SyncRunner() device = self.options.device # if necessary, load and unmount self.stdout.write('Checking device %s\n' % device) prog.loadDevice(device) prog.unmountDevice(device) # first get the Table Of Contents of the CD t = cdrdao.ReadTOCTask(device) table = t.table self.debug("CDDB disc id: %r", table.getCDDBDiscId()) url = table.getAccurateRipURL() self.debug("AccurateRip URL: %s", url) # FIXME: download url as a task too responses = [] import urllib2 try: handle = urllib2.urlopen(url) data = handle.read() responses = accurip.getAccurateRipResponses(data) except urllib2.HTTPError, e: if e.code == 404: self.stdout.write( 'Album not found in AccurateRip database.\n') return 1 else: raise
def do(self, args): prog = program.Program() runner = task.SyncRunner() for arg in args: print 'Retagging image %r' % arg arg = arg.decode('utf-8') cueImage = image.Image(arg) cueImage.setup(runner) mbdiscid = cueImage.table.getMusicBrainzDiscId() prog.metadata = prog.getMusicBrainz(cueImage.table, mbdiscid) if not prog.metadata: print 'Not in MusicBrainz database, skipping' continue # 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) t = encode.SafeRetagTask(path, taglist) runner.run(t) path = os.path.basename(path) if t.changed: print 'Retagged %s' % path else: print '%s already tagged correctly' % path print
def testIssue66TemplateFilled(self): prog = program.Program() md = musicbrainzngs.DiscMetadata() md.artist = md.sortName = 'Jeff Buckley' md.title = 'Grace' prog.metadata = md path = prog.getPath(u'/tmp', u'%A/%d', 'mbdiscid', 0) self.assertEquals(path, u'/tmp/Jeff Buckley/Grace')
def testStandardTemplateEmpty(self): prog = program.Program(config.Config()) path = prog.getPath(u'/tmp', rcommon.DEFAULT_DISC_TEMPLATE, 'mbdiscid', 0) self.assertEquals( path, u'/tmp/unknown/Unknown Artist - mbdiscid/Unknown Artist - mbdiscid' )
def testStandardTemplateFilled(self): prog = program.Program() md = musicbrainzngs.DiscMetadata() md.artist = md.sortName = 'Jeff Buckley' md.title = 'Grace' prog.metadata = md path = prog.getPath(u'/tmp', cd.DEFAULT_DISC_TEMPLATE, 'mbdiscid', 0) self.assertEquals(path, u'/tmp/Jeff Buckley - Grace/Jeff Buckley - Grace')
def testStandardTemplateFilled(self): prog = program.Program(config.Config()) md = mbngs.DiscMetadata() md.artist = md.sortName = 'Jeff Buckley' md.title = 'Grace' prog.metadata = md path = prog.getPath(u'/tmp', rcommon.DEFAULT_DISC_TEMPLATE, 'mbdiscid', 0) self.assertEquals( path, u'/tmp/unknown/Jeff Buckley - Grace/Jeff Buckley - Grace')
def testVerify(self): path = os.path.join(os.path.dirname(__file__), 'dBAR-020-002e5023-029d8e49-040eaa14.bin') data = open(path, "rb").read() responses = accurip.getAccurateRipResponses(data) # these crc's were calculated from an actual rip checksums = [ 1644890007, 2945205445, 3983436658, 1528082495, 1203704270, 1163423644, 3649097244, 100524219, 1583356174, 373652058, 1842579359, 2850056507, 1329730252, 2526965856, 2525886806, 209743350, 3184062337, 2099956663, 2943874164, 2321637196 ] prog = program.Program() prog.result = result.RipResult() # fill it with empty trackresults for i, c in enumerate(checksums): r = result.TrackResult() r.number = i + 1 prog.result.tracks.append(r) prog._verifyImageWithChecksums(responses, checksums) # now check if the results were filled in properly tr = prog.result.getTrackResult(1) self.assertEquals(tr.accurip, False) self.assertEquals(tr.ARDBMaxConfidence, 0) self.assertEquals(tr.ARDBCRC, 0) self.assertEquals(tr.ARDBCRC, 0) tr = prog.result.getTrackResult(2) self.assertEquals(tr.accurip, True) self.assertEquals(tr.ARDBMaxConfidence, 2) self.assertEquals(tr.ARDBCRC, checksums[2 - 1]) tr = prog.result.getTrackResult(10) self.assertEquals(tr.accurip, False) self.assertEquals(tr.ARDBMaxConfidence, 2) # we know track 10 was ripped wrong self.assertNotEquals(tr.ARDBCRC, checksums[10 - 1]) res = prog.getAccurateRipResults() self.assertEquals( res[1 - 1], "Track 1: rip NOT accurate (not found) " "[620b0797], DB [notfound]") self.assertEquals( res[2 - 1], "Track 2: rip accurate (max confidence 2) " "[af8c44c5], DB [af8c44c5]") self.assertEquals( res[10 - 1], "Track 10: rip NOT accurate (max confidence 2) " "[16457a5a], DB [eb6e55b4]")
def do(self, args): # here to avoid import gst eating our options from morituri.common import encode prog = program.Program(self.getRootCommand().config, stdout=self.stdout) runner = task.SyncRunner() for arg in args: self.stdout.write('Retagging image %r\n' % arg) arg = arg.decode('utf-8') cueImage = image.Image(arg) cueImage.setup(runner) mbdiscid = cueImage.table.getMusicBrainzDiscId() self.stdout.write('MusicBrainz disc id is %s\n' % mbdiscid) self.stdout.write("MusicBrainz lookup URL %s\n" % cueImage.table.getMusicBrainzSubmitURL()) prog.metadata = prog.getMusicBrainz( cueImage.table, mbdiscid, release=self.options.release_id, country=self.options.country, prompt=self.options.prompt) if not prog.metadata: print 'Not in MusicBrainz database, skipping' continue prog.metadata.discid = mbdiscid # FIXME: this feels like we're poking at internals. prog.cuePath = arg prog.result = result.RipResult() for track in cueImage.table.tracks: path = cueImage.getRealPath(track.indexes[1].path) taglist = prog.getTagList(track.number) self.debug( 'possibly retagging %r from cue path %r with taglist %r', path, arg, taglist) t = encode.SafeRetagTask(path, taglist) runner.run(t) path = os.path.basename(path) if t.changed: print 'Retagged %s' % path else: print '%s already tagged correctly' % path print
def do(self, args): prog = program.Program(self.getRootCommand().config) prog.outdir = (self.options.output_directory or os.getcwd()) prog.outdir = prog.outdir.decode('utf-8') # here to avoid import gst eating our options from morituri.common import encode profile = encode.ALL_PROFILES[self.options.profile]() runner = task.SyncRunner() for arg in args: arg = arg.decode('utf-8') indir = os.path.dirname(arg) cueImage = image.Image(arg) cueImage.setup(runner) # FIXME: find a decent way to get an album-specific outdir root = os.path.basename(indir) outdir = os.path.join(prog.outdir, root) try: os.makedirs(outdir) except: # FIXME: handle other exceptions than OSError Errno 17 pass # FIXME: handle this nicer assert outdir != indir taskk = image.ImageEncodeTask(cueImage, profile, outdir) runner.run(taskk) # FIXME: translate .m3u file if it exists root, ext = os.path.splitext(arg) m3upath = root + '.m3u' if os.path.exists(m3upath): self.debug('translating .m3u file') inm3u = open(m3upath) outm3u = open(os.path.join(outdir, os.path.basename(m3upath)), 'w') for line in inm3u.readlines(): root, ext = os.path.splitext(line) if ext: # newline is swallowed by splitext here outm3u.write('%s.%s\n' % (root, profile.extension)) else: outm3u.write('%s' % root) outm3u.close()
def do(self, args): prog = program.Program(self.getRootCommand().config) runner = ctask.SyncRunner() device = self.options.device # if necessary, load and unmount self.stdout.write('Checking device %s\n' % device) prog.loadDevice(device) prog.unmountDevice(device) # first get the Table Of Contents of the CD t = cdrdao.ReadTOCTask(device=device) try: runner.run(t) except cdrdao.DeviceOpenException, e: self.error(e.msg) return 3
def do(self, args): prog = program.Program(self.getRootCommand.config(), stdout=self.stdout) runner = task.SyncRunner() for arg in args: self.stdout.write('Renaming image %r\n' % arg) arg = arg.decode('utf-8') cueImage = image.Image(arg) cueImage.setup(runner) mbdiscid = cueImage.table.getMusicBrainzDiscId() operator = renamer.Operator(statePath, mbdiscid) self.stdout.write('MusicBrainz disc id is %s\n' % mbdiscid) prog.metadata = prog.getMusicBrainz( cueImage.table, mbdiscid, release=self.options.release_id) if not prog.metadata: print 'Not in MusicBrainz database, skipping' continue # FIXME: this feels like we're poking at internals. prog.cuePath = arg prog.result = result.RipResult() for track in cueImage.table.tracks: path = cueImage.getRealPath(track.indexes[1].path) taglist = prog.getTagList(track.number) self.debug( 'possibly retagging %r from cue path %r with taglist %r', path, arg, taglist) t = encode.SafeRetagTask(path, taglist) runner.run(t) path = os.path.basename(path) if t.changed: print 'Retagged %s' % path else: print '%s already tagged correctly' % path print
def do(self, args): prog = program.Program(self.getRootCommand().config) runner = task.SyncRunner() cache = accurip.AccuCache() for arg in args: arg = arg.decode('utf-8') cueImage = image.Image(arg) cueImage.setup(runner) url = cueImage.table.getAccurateRipURL() responses = cache.retrieve(url) # FIXME: this feels like we're poking at internals. prog.cuePath = arg prog.result = result.RipResult() for track in cueImage.table.tracks: tr = result.TrackResult() tr.number = track.number prog.result.tracks.append(tr) prog.verifyImage(runner, responses) print "\n".join(prog.getAccurateRipResults()) + "\n"
def do(self, args): self.program = program.Program(self.getRootCommand().config, record=self.getRootCommand().record, stdout=self.stdout) self.runner = task.SyncRunner() # if the device is mounted (data session), unmount it self.device = self.parentCommand.options.device self.stdout.write('Checking device %s\n' % self.device) self.program.loadDevice(self.device) self.program.unmountDevice(self.device) # first, read the normal TOC, which is fast self.ittoc = self.program.getFastToc(self.runner, self.options.toc_pickle, self.device) # already show us some info based on this self.program.getRipResult(self.ittoc.getCDDBDiscId()) self.stdout.write("CDDB disc id: %s\n" % self.ittoc.getCDDBDiscId()) self.mbdiscid = self.ittoc.getMusicBrainzDiscId() self.stdout.write("MusicBrainz disc id %s\n" % self.mbdiscid) self.stdout.write("MusicBrainz lookup URL %s\n" % self.ittoc.getMusicBrainzSubmitURL()) self.program.metadata = self.program.getMusicBrainz( self.ittoc, self.mbdiscid, release=self.options.release_id, country=self.options.country, prompt=self.options.prompt) if not self.program.metadata: # fall back to FreeDB for lookup cddbid = self.ittoc.getCDDBValues() cddbmd = self.program.getCDDB(cddbid) if cddbmd: self.stdout.write('FreeDB identifies disc as %s\n' % cddbmd) # also used by rip cd info if not getattr(self.options, 'unknown', False): if self.eject: self.program.ejectDevice(self.device) return -1 # Hackish fix for broken commit offset = 0 info = drive.getDeviceInfo(self.parentCommand.options.device) if info: try: offset = self.getRootCommand().config.getReadOffset(*info) except KeyError: pass # now, read the complete index table, which is slower self.itable = self.program.getTable(self.runner, self.ittoc.getCDDBDiscId(), self.ittoc.getMusicBrainzDiscId(), self.device, offset) assert self.itable.getCDDBDiscId() == self.ittoc.getCDDBDiscId(), \ "full table's id %s differs from toc id %s" % ( self.itable.getCDDBDiscId(), self.ittoc.getCDDBDiscId()) assert self.itable.getMusicBrainzDiscId() == \ self.ittoc.getMusicBrainzDiscId(), \ "full table's mb id %s differs from toc id mb %s" % ( self.itable.getMusicBrainzDiscId(), self.ittoc.getMusicBrainzDiscId()) assert self.itable.getAccurateRipURL() == \ self.ittoc.getAccurateRipURL(), \ "full table's AR URL %s differs from toc AR URL %s" % ( self.itable.getAccurateRipURL(), self.ittoc.getAccurateRipURL()) if self.program.metadata: self.program.metadata.discid = self.ittoc.getMusicBrainzDiscId() # result self.program.result.cdrdaoVersion = cdrdao.getCDRDAOVersion() self.program.result.cdparanoiaVersion = \ cdparanoia.getCdParanoiaVersion() info = drive.getDeviceInfo(self.parentCommand.options.device) if info: try: self.program.result.cdparanoiaDefeatsCache = \ self.getRootCommand().config.getDefeatsCache(*info) except KeyError, e: self.debug('Got key error: %r' % (e, ))
def do(self, args): prog = program.Program(record=self.getRootCommand().record) runner = task.SyncRunner() def function(r, t): r.run(t) # if the device is mounted (data session), unmount it device = self.parentCommand.options.device self.stdout.write('Checking device %s\n' % device) prog.loadDevice(device) prog.unmountDevice(device) version = None # first, read the normal TOC, which is fast ptoc = common.Persister(self.options.toc_pickle or None) if not ptoc.object: t = cdrdao.ReadTOCTask(device=device) function(runner, t) version = t.tasks[1].parser.version from pkg_resources import parse_version as V # we've built a cdrdao 1.2.3rc2 modified package with the patch if V(version) < V('1.2.3rc2p1'): self.stdout.write(''' Warning: cdrdao older than 1.2.3 has a pre-gap length bug. See http://sourceforge.net/tracker/?func=detail&aid=604751&group_id=2171&atid=102171 ''') ptoc.persist(t.table) ittoc = ptoc.object assert ittoc.hasTOC() # already show us some info based on this prog.getRipResult(ittoc.getCDDBDiscId()) self.stdout.write("CDDB disc id: %s\n" % ittoc.getCDDBDiscId()) mbdiscid = ittoc.getMusicBrainzDiscId() self.stdout.write("MusicBrainz disc id %s\n" % mbdiscid) self.stdout.write("MusicBrainz lookup URL %s\n" % ittoc.getMusicBrainzSubmitURL()) prog.metadata = prog.getMusicBrainz(ittoc, mbdiscid, self.options.release) if not prog.metadata: # fall back to FreeDB for lookup cddbid = ittoc.getCDDBValues() cddbmd = prog.getCDDB(cddbid) if cddbmd: self.stdout.write('FreeDB identifies disc as %s\n' % 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) assert itable.getCDDBDiscId() == ittoc.getCDDBDiscId(), \ "full table's id %s differs from toc id %s" % ( itable.getCDDBDiscId(), ittoc.getCDDBDiscId()) assert itable.getMusicBrainzDiscId() == ittoc.getMusicBrainzDiscId(), \ "full table's mb id %s differs from toc id mb %s" % ( itable.getMusicBrainzDiscId(), ittoc.getMusicBrainzDiscId()) assert itable.getAccurateRipURL() == ittoc.getAccurateRipURL(), \ "full table's AR URL %s differs from toc AR URL %s" % ( itable.getAccurateRipURL(), ittoc.getAccurateRipURL()) prog.outdir = (self.options.output_directory or os.getcwd()) prog.outdir = prog.outdir.decode('utf-8') # here to avoid import gst eating our options from morituri.common import encode profile = encode.PROFILES[self.options.profile]() # result prog.result.cdrdao_version = version prog.result.cdparanoia_version = cdparanoia.ParanoiaVersion() prog.result.offset = int(self.options.offset) 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 _, prog.result.vendor, prog.result.model, prog.result.release = \ cdio.Device(device).get_hwinfo() except ImportError: self.stdout.write( 'WARNING: pycdio not installed, cannot identify drive\n') prog.result.vendor = 'Unknown' prog.result.model = 'Unknown' prog.result.release = 'Unknown' # FIXME: turn this into a method def ripIfNotRipped(number): # we can have a previous result trackResult = prog.result.getTrackResult(number) if not trackResult: trackResult = result.TrackResult() prog.result.tracks.append(trackResult) path = prog.getPath(prog.outdir, self.options.track_template, mbdiscid, number) + '.' + profile.extension trackResult.number = number assert type(path) is unicode, "%r is not unicode" % path trackResult.filename = path if number > 0: trackResult.pregap = itable.tracks[number - 1].getPregap() # FIXME: optionally allow overriding reripping if os.path.exists(path): self.stdout.write('Verifying track %d of %d: %s\n' % (number, len(itable.tracks), os.path.basename(path).encode('utf-8'))) if not prog.verifyTrack(runner, trackResult): self.stdout.write('Verification failed, reripping...\n') os.unlink(path) if not os.path.exists(path): tries = 0 self.stdout.write('Ripping track %d of %d: %s\n' % (number, len(itable.tracks), os.path.basename(path).encode('utf-8'))) while tries < MAX_TRIES: tries += 1 try: self.debug('ripIfNotRipped: track %d, try %d', number, tries) prog.ripTrack(runner, trackResult, offset=int(self.options.offset), device=self.parentCommand.options.device, profile=profile, taglist=prog.getTagList(number), what='track %d of %d' % (number, len(itable.tracks))) break except Exception, e: self.debug('Got exception %r on try %d', e, tries) if tries == MAX_TRIES: self.error('Giving up on track %d after %d times' % (number, tries)) if trackResult.testcrc == trackResult.copycrc: self.stdout.write('Checksums match for track %d\n' % number) else: self.stdout.write( 'ERROR: checksums did not match for track %d\n' % number) raise self.stdout.write('Peak level: %.2f %%\n' % (math.sqrt(trackResult.peak) * 100.0, )) self.stdout.write('Rip quality: %.2f %%\n' % (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, trackResult.filename, ittoc.getTrackStart(1), number) else: itable.setFile(number, 1, trackResult.filename, ittoc.getTrackLength(number), number) prog.saveRipResult()
def testGetAccurateRipResults(self): prog = program.Program() prog.result = result.RipResult() prog.result.tracks = self._tracks prog.getAccurateRipResults()