def main(argv): parser = optparse.OptionParser() default = 'cli' parser.add_option('-r', '--runner', action="store", dest="runner", help="runner ('cli' or 'gtk', defaults to %s)" % default, default=default) # see http://www.accuraterip.com/driveoffsets.htm default = "0, 6, 12, 48, 91, 97, 102, 108, 120, " + \ "564, 594, 667, 685, 691, 704, 738, 1194, 1292, 1336, 1776, -582" parser.add_option('-o', '--offsets', action="store", dest="offsets", help="list of offsets, comma-separated, " "colon-separated for ranges (defaults to %s)" % default, default=default) options, args = parser.parse_args(argv[1:]) offsets = [] blocks = options.offsets.split(',') for b in blocks: if ':' in b: a, b = b.split(':') offsets.extend(range(int(a), int(b) + 1)) else: offsets.append(int(b)) # first get the Table Of Contents of the CD t = cdrdao.ReadTOCTask() if options.runner == 'cli': runner = task.SyncRunner() function = climain elif options.runner == 'gtk': from morituri.common import taskgtk runner = taskgtk.GtkProgressRunner() function = gtkmain function(runner, t) table = t.table print "CDDB disc id", table.getCDDBDiscId() url = table.getAccurateRipURL() print "AccurateRip URL", url # FIXME: download url as a task too responses = [] import urllib2 try: handle = urllib2.urlopen(url) data = handle.read() responses = image.getAccurateRipResponses(data) except urllib2.HTTPError, e: if e.code == 404: print 'Album not found in AccurateRip database' sys.exit(1) else: raise
def main(argv): parser = optparse.OptionParser() default = 'cli' parser.add_option('-r', '--runner', action="store", dest="runner", help="runner ('cli' or 'gtk', defaults to %s)" % default, default=default) default = 0 parser.add_option('-o', '--offset', action="store", dest="offset", help="sample offset (defaults to %d)" % default, default=default) parser.add_option('-t', '--table-pickle', action="store", dest="table_pickle", help="pickle to use for reading and writing the table", default=default) parser.add_option('-T', '--toc-pickle', action="store", dest="toc_pickle", help="pickle to use for reading and writing the TOC", default=default) default = '%A - %d/%t. %a - %n' parser.add_option('', '--track-template', action="store", dest="track_template", help="template for track file naming (default %s)" % default, default=default) default = '%A - %d/%A - %d' parser.add_option('', '--disc-template', action="store", dest="disc_template", help="template for disc file naming (default %s)" % default, default=default) options, args = parser.parse_args(argv[1:]) if options.runner == 'cli': runner = task.SyncRunner() function = climain elif options.runner == 'gtk': from morituri.common import taskgtk runner = taskgtk.GtkProgressRunner() function = gtkmain # first, read the normal TOC, which is fast ptoc = common.Persister(options.toc_pickle or None) if not ptoc.object: t = cdrdao.ReadTOCTask() function(runner, t) ptoc.persist(t.table) ittoc = ptoc.object assert ittoc.hasTOC() # already show us some info based on this print "CDDB disc id", ittoc.getCDDBDiscId() metadata = musicbrainz(ittoc.getMusicBrainzDiscId()) # now, read the complete index table, which is slower ptable = common.Persister(options.table_pickle or None) if not ptable.object: t = cdrdao.ReadTableTask() function(runner, t) ptable.persist(t.table) itable = ptable.object assert itable.hasTOC() assert itable.getCDDBDiscId() == ittoc.getCDDBDiscId(), \ "full table's id %s differs from toc id %s" % ( itable.getCDDBDiscId(), ittoc.getCDDBDiscId()) assert itable.getMusicBrainzDiscId() == ittoc.getMusicBrainzDiscId() lastTrackStart = 0 # check for hidden track one audio htoapath = None index = None track = itable.tracks[0] try: index = track.getIndex(0) except KeyError: pass if index: start = index.absolute stop = track.getIndex(1).absolute print 'Found Hidden Track One Audio from frame %d to %d' % (start, stop) # rip it htoapath = getPath(options.track_template, metadata, -1) + '.wav' 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(options.offset)) function(runner, t) if t.checksum: print 'Checksums match for track %d' % 0 else: print 'ERROR: checksums did not match for track %d' % 0 # overlay this rip onto the Table itable.setFile(1, 0, htoapath, htoalength, 0) for i, track in enumerate(itable.tracks): path = getPath(options.track_template, metadata, i) + '.wav' 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: %s' % (i + 1, os.path.basename(path)) t = cdparanoia.ReadVerifyTrackTask(path, ittoc, ittoc.getTrackStart(i + 1), ittoc.getTrackEnd(i + 1), offset=int(options.offset)) t.description = 'Reading Track %d' % (i + 1) function(runner, t) if t.checksum: print 'Checksums match for track %d' % (i + 1) else: print 'ERROR: checksums did not match for track %d' % (i + 1) # overlay this rip onto the Table itable.setFile(i + 1, 1, path, ittoc.getTrackLength(i + 1), i + 1) ### write disc files discName = getPath(options.disc_template, metadata, i) dirname = os.path.dirname(discName) if not os.path.exists(dirname): os.makedirs(dirname) # write .cue file cuePath = '%s.cue' % discName handle = open(cuePath, 'w') handle.write(itable.cue()) handle.close() # write .m3u file m3uPath = '%s.m3u' % discName handle = open(m3uPath, 'w') handle.write('#EXTM3U\n') if htoapath: handle.write('#EXTINF:%d,%s\n' % ( htoalength / common.FRAMES_PER_SECOND, os.path.basename(htoapath[:-4]))) handle.write('%s\n' % os.path.basename(htoapath)) for i, track in enumerate(itable.tracks): path = getPath(options.track_template, metadata, i) + '.wav' handle.write('#EXTINF:%d,%s\n' % ( itable.getTrackLength(i + 1) / common.FRAMES_PER_SECOND, os.path.basename(path))) handle.write('%s\n' % os.path.basename(path)) handle.close() # verify using accuraterip print "CDDB disc id", itable.getCDDBDiscId() print "MusicBrainz disc id", itable.getMusicBrainzDiscId() url = itable.getAccurateRipURL() print "AccurateRip URL", url # FIXME: download url as a task too responses = [] import urllib2 try: handle = urllib2.urlopen(url) data = handle.read() responses = image.getAccurateRipResponses(data) except urllib2.HTTPError, e: if e.code == 404: print 'Album not found in AccurateRip database' else: raise