def test_report_no_result(self): track = TrackResult() track.number = 1 self.result.tracks[0] = track print_report(self.result) self.assertEqual(sys.stdout.getvalue(), 'track 1: unknown (error)\n')
def test_report_v1_and_v2_max_confidence(self): print_report(self.result) self.assertEquals( sys.stdout.getvalue(), 'track 1: rip accurate (max confidence 12)' ' v1 [284fc705], v2 [dc77f9ab], DB [284fc705, dc77f9ab]\n' )
def test_htoa_not_tracked(self): self.result.tracks[0].number = 0 self.result.tracks[0].AR['v1']['CRC'] = None self.result.tracks[0].AR['v2']['CRC'] = None print_report(self.result) self.assertEqual(sys.stdout.getvalue(), 'track 0: unknown (not tracked)\n')
def do(self): prog = program.Program(config.Config()) runner = task.SyncRunner() for arg in self.options.cuefile: arg = arg.decode('utf-8') cueImage = image.Image(arg) cueImage.setup(runner) # 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) verified = False try: verified = prog.verifyImage(runner, cueImage.table) except accurip.EntryNotFound: print('AccurateRip entry not found') accurip.print_report(prog.result) if not verified: sys.exit(1)
def test_report_v1_and_v2(self): self.result.tracks[0].AR['DBMaxConfidence'] = 66 print_report(self.result) self.assertEqual( sys.stdout.getvalue(), 'track 1: rip accurate (confidence 12 of 66)' ' v1 [284fc705], v2 [dc77f9ab], DB [284fc705, dc77f9ab]\n')
def test_track_not_found(self): self.result.tracks[0].AR['DBMaxConfidence'] = None print_report(self.result) self.assertEqual( sys.stdout.getvalue(), 'track 1: rip NOT accurate (not found) ' ' v1 [284fc705], v2 [dc77f9ab], DB [notfound]\n')
def test_report_v1_and_v2(self): self.result.tracks[0].AR['DBMaxConfidence'] = 66 print_report(self.result) self.assertEquals( sys.stdout.getvalue(), 'track 1: rip accurate (confidence 12 of 66)' ' v1 [284fc705], v2 [dc77f9ab], DB [284fc705, dc77f9ab]\n' )
def test_track_not_found(self): self.result.tracks[0].AR['DBMaxConfidence'] = None print_report(self.result) self.assertEquals( sys.stdout.getvalue(), 'track 1: rip NOT accurate (not found) ' ' v1 [284fc705], v2 [dc77f9ab], DB [notfound]\n' )
def test_report_v2_only(self): self.result.tracks[0].AR['v1']['DBCRC'] = None self.result.tracks[0].AR['v1']['DBConfidence'] = None print_report(self.result) self.assertEqual( sys.stdout.getvalue(), 'track 1: rip accurate (confidence 4 of 12)' ' v1 [284fc705], v2 [dc77f9ab], DB [dc77f9ab]\n')
def test_htoa_not_tracked(self): self.result.tracks[0].number = 0 self.result.tracks[0].AR['v1']['CRC'] = None self.result.tracks[0].AR['v2']['CRC'] = None print_report(self.result) self.assertEquals( sys.stdout.getvalue(), 'track 0: unknown (not tracked)\n' )
def test_report_no_result(self): track = TrackResult() track.number = 1 self.result.tracks[0] = track print_report(self.result) self.assertEquals( sys.stdout.getvalue(), 'track 1: unknown (error)\n' )
def test_report_v2_only(self): self.result.tracks[0].AR['v1']['DBCRC'] = None self.result.tracks[0].AR['v1']['DBConfidence'] = None print_report(self.result) self.assertEquals( sys.stdout.getvalue(), 'track 1: rip accurate (confidence 4 of 12)' ' v1 [284fc705], v2 [dc77f9ab], DB [dc77f9ab]\n' )
def doCommand(self): self.program.setWorkingDirectory(self.options.working_directory) self.program.outdir = self.options.output_directory.decode('utf-8') self.program.result.offset = int(self.options.offset) self.program.result.overread = self.options.overread self.program.result.logger = self.options.logger discName = self.program.getPath(self.program.outdir, self.options.disc_template, self.mbdiscid, self.program.metadata) dirname = os.path.dirname(discName) if os.path.exists(dirname): logs = glob.glob(os.path.join(dirname, '*.log')) if logs: msg = ("output directory %s is a finished rip" % dirname.encode('utf-8')) logger.critical(msg) raise RuntimeError(msg) else: sys.stdout.write("output directory %s already exists\n" % dirname.encode('utf-8')) else: print("creating output directory %s" % dirname.encode('utf-8')) os.makedirs(dirname) # FIXME: turn this into a method def _ripIfNotRipped(number): logger.debug('ripIfNotRipped for track %d' % number) # we can have a previous result trackResult = self.program.result.getTrackResult(number) if not trackResult: trackResult = result.TrackResult() self.program.result.tracks.append(trackResult) else: logger.debug('ripIfNotRipped have trackresult, path %r' % trackResult.filename) path = self.program.getPath(self.program.outdir, self.options.track_template, self.mbdiscid, self.program.metadata, track_number=number) + '.flac' logger.debug('ripIfNotRipped: path %r' % path) trackResult.number = number assert type(path) is unicode, "%r is not unicode" % path trackResult.filename = path if number > 0: trackResult.pregap = self.itable.tracks[number - 1].getPregap() trackResult.pre_emphasis = ( self.itable.tracks[number - 1].pre_emphasis ) # FIXME: optionally allow overriding reripping if os.path.exists(path): if path != trackResult.filename: # the path is different (different name/template ?) # but we can copy it logger.debug('previous result %r, expected %r' % ( trackResult.filename, path)) sys.stdout.write('Verifying track %d of %d: %s\n' % ( number, len(self.itable.tracks), os.path.basename(path).encode('utf-8'))) if not self.program.verifyTrack(self.runner, trackResult): sys.stdout.write('Verification failed, reripping...\n') os.unlink(path) if not os.path.exists(path): logger.debug('path %r does not exist, ripping...' % path) tries = 0 # we reset durations for test and copy here trackResult.testduration = 0.0 trackResult.copyduration = 0.0 extra = "" while tries < MAX_TRIES: tries += 1 if tries > 1: extra = " (try %d)" % tries sys.stdout.write('Ripping track %d of %d%s: %s\n' % ( number, len(self.itable.tracks), extra, os.path.basename(path).encode('utf-8'))) try: logger.debug('ripIfNotRipped: track %d, try %d', number, tries) self.program.ripTrack(self.runner, trackResult, offset=int(self.options.offset), device=self.device, taglist=self.program.getTagList( number), overread=self.options.overread, what='track %d of %d%s' % ( number, len(self.itable.tracks), extra)) break except Exception as e: logger.debug('Got exception %r on try %d', e, tries) if tries == MAX_TRIES: logger.critical('Giving up on track %d after %d times' % ( number, tries)) raise RuntimeError( "track can't be ripped. " "Rip attempts number is equal to 'MAX_TRIES'") if trackResult.testcrc == trackResult.copycrc: sys.stdout.write('CRCs match for track %d\n' % number) else: raise RuntimeError( "CRCs did not match for track %d\n" % number ) sys.stdout.write( 'Peak level: {:.2%} \n'.format(trackResult.peak)) sys.stdout.write( 'Rip quality: {:.2%}\n'.format(trackResult.quality)) # overlay this rip onto the Table if number == 0: # HTOA goes on index 0 of track 1 # ignore silence in PREGAP if trackResult.peak <= SILENT: logger.debug( 'HTOA peak %r is below SILENT ' 'threshold, disregarding', trackResult.peak) self.itable.setFile(1, 0, None, self.ittoc.getTrackStart(1), number) logger.debug('Unlinking %r', trackResult.filename) os.unlink(trackResult.filename) trackResult.filename = None sys.stdout.write( 'HTOA discarded, contains digital silence\n') else: self.itable.setFile(1, 0, trackResult.filename, self.ittoc.getTrackStart(1), number) else: self.itable.setFile(number, 1, trackResult.filename, self.ittoc.getTrackLength(number), number) self.program.saveRipResult() # check for hidden track one audio htoa = self.program.getHTOA() if htoa: start, stop = htoa print('found Hidden Track One Audio from frame %d to %d' % ( start, stop)) _ripIfNotRipped(0) for i, track in enumerate(self.itable.tracks): # FIXME: rip data tracks differently if not track.audio: print('skipping data track %d, not implemented' % (i + 1)) # FIXME: make it work for now track.indexes[1].relative = 0 continue _ripIfNotRipped(i + 1) logger.debug('writing cue file for %r', discName) self.program.writeCue(discName) logger.debug('writing m3u file for %r', discName) self.program.write_m3u(discName) try: self.program.verifyImage(self.runner, self.ittoc) except accurip.EntryNotFound: print('AccurateRip entry not found') accurip.print_report(self.program.result) self.program.saveRipResult() self.program.writeLog(discName, self.logger)
def doCommand(self): self.program.setWorkingDirectory(self.options.working_directory) self.program.outdir = self.options.output_directory.decode('utf-8') self.program.result.offset = int(self.options.offset) self.program.result.overread = self.options.overread self.program.result.logger = self.options.logger discName = self.program.getPath(self.program.outdir, self.options.disc_template, self.mbdiscid, self.program.metadata) dirname = os.path.dirname(discName) if os.path.exists(dirname): logs = glob.glob(os.path.join(dirname, '*.log')) if logs: msg = ("output directory %s is a finished rip" % dirname.encode('utf-8')) logger.critical(msg) raise RuntimeError(msg) else: sys.stdout.write("output directory %s already exists\n" % dirname.encode('utf-8')) print("creating output directory %s" % dirname.encode('utf-8')) os.makedirs(dirname) # FIXME: turn this into a method def _ripIfNotRipped(number): logger.debug('ripIfNotRipped for track %d' % number) # we can have a previous result trackResult = self.program.result.getTrackResult(number) if not trackResult: trackResult = result.TrackResult() self.program.result.tracks.append(trackResult) else: logger.debug('ripIfNotRipped have trackresult, path %r' % trackResult.filename) path = self.program.getPath(self.program.outdir, self.options.track_template, self.mbdiscid, self.program.metadata, track_number=number) + '.flac' logger.debug('ripIfNotRipped: path %r' % path) trackResult.number = number assert type(path) is unicode, "%r is not unicode" % path trackResult.filename = path if number > 0: trackResult.pregap = self.itable.tracks[number - 1].getPregap() trackResult.pre_emphasis = ( self.itable.tracks[number - 1].pre_emphasis ) # FIXME: optionally allow overriding reripping if os.path.exists(path): if path != trackResult.filename: # the path is different (different name/template ?) # but we can copy it logger.debug('previous result %r, expected %r' % ( trackResult.filename, path)) sys.stdout.write('Verifying track %d of %d: %s\n' % ( number, len(self.itable.tracks), os.path.basename(path).encode('utf-8'))) if not self.program.verifyTrack(self.runner, trackResult): sys.stdout.write('Verification failed, reripping...\n') os.unlink(path) if not os.path.exists(path): logger.debug('path %r does not exist, ripping...' % path) tries = 0 # we reset durations for test and copy here trackResult.testduration = 0.0 trackResult.copyduration = 0.0 extra = "" while tries < MAX_TRIES: tries += 1 if tries > 1: extra = " (try %d)" % tries sys.stdout.write('Ripping track %d of %d%s: %s\n' % ( number, len(self.itable.tracks), extra, os.path.basename(path).encode('utf-8'))) try: logger.debug('ripIfNotRipped: track %d, try %d', number, tries) self.program.ripTrack(self.runner, trackResult, offset=int(self.options.offset), device=self.device, taglist=self.program.getTagList( number), overread=self.options.overread, what='track %d of %d%s' % ( number, len(self.itable.tracks), extra)) break except Exception as e: logger.debug('Got exception %r on try %d', e, tries) if tries == MAX_TRIES: logger.critical('Giving up on track %d after %d times' % ( number, tries)) raise RuntimeError( "track can't be ripped. " "Rip attempts number is equal to 'MAX_TRIES'") if trackResult.testcrc == trackResult.copycrc: sys.stdout.write('CRCs match for track %d\n' % number) else: raise RuntimeError( "CRCs did not match for track %d\n" % number ) sys.stdout.write( 'Peak level: {:.2%} \n'.format(trackResult.peak)) sys.stdout.write( 'Rip quality: {:.2%}\n'.format(trackResult.quality)) # overlay this rip onto the Table if number == 0: # HTOA goes on index 0 of track 1 # ignore silence in PREGAP if trackResult.peak <= SILENT: logger.debug( 'HTOA peak %r is below SILENT ' 'threshold, disregarding', trackResult.peak) self.itable.setFile(1, 0, None, self.ittoc.getTrackStart(1), number) logger.debug('Unlinking %r', trackResult.filename) os.unlink(trackResult.filename) trackResult.filename = None sys.stdout.write( 'HTOA discarded, contains digital silence\n') else: self.itable.setFile(1, 0, trackResult.filename, self.ittoc.getTrackStart(1), number) else: self.itable.setFile(number, 1, trackResult.filename, self.ittoc.getTrackLength(number), number) self.program.saveRipResult() # check for hidden track one audio htoa = self.program.getHTOA() if htoa: start, stop = htoa print('found Hidden Track One Audio from frame %d to %d' % ( start, stop)) _ripIfNotRipped(0) for i, track in enumerate(self.itable.tracks): # FIXME: rip data tracks differently if not track.audio: print('skipping data track %d, not implemented' % (i + 1)) # FIXME: make it work for now track.indexes[1].relative = 0 continue _ripIfNotRipped(i + 1) logger.debug('writing cue file for %r', discName) self.program.writeCue(discName) logger.debug('writing m3u file for %r', discName) self.program.write_m3u(discName) try: self.program.verifyImage(self.runner, self.ittoc) except accurip.EntryNotFound: print('AccurateRip entry not found') accurip.print_report(self.program.result) self.program.saveRipResult() self.program.writeLog(discName, self.logger)
class Rip(_CD): summary = "rip CD" # see whipper.common.program.Program.getPath for expansion description = """ Rips a CD. %s Paths to track files referenced in .cue and .m3u files will be made relative to the directory of the disc files. All files will be created relative to the given output directory. Log files will log the path to tracks relative to this directory. """ % TEMPLATE_DESCRIPTION formatter_class = argparse.ArgumentDefaultsHelpFormatter # Requires opts.record # Requires opts.device def add_arguments(self): loggers = result.getLoggers().keys() default_offset = None info = drive.getDeviceInfo(self.opts.device) if info: try: default_offset = config.Config().getReadOffset(*info) sys.stdout.write("Using configured read offset %d\n" % default_offset) except KeyError: pass _CD.add_arguments(self.parser) self.parser.add_argument('-L', '--logger', action="store", dest="logger", default='whipper', help="logger to use (choose from '" "', '".join(loggers) + "')") # FIXME: get from config self.parser.add_argument('-o', '--offset', action="store", dest="offset", default=default_offset, help="sample read offset") self.parser.add_argument('-x', '--force-overread', action="store_true", dest="overread", default=False, help="Force overreading into the " "lead-out portion of the disc. Works only " "if the patched cdparanoia package is " "installed and the drive " "supports this feature. ") self.parser.add_argument('-O', '--output-directory', action="store", dest="output_directory", default=os.path.relpath(os.getcwd()), help="output directory; will be included " "in file paths in log") self.parser.add_argument('-W', '--working-directory', action="store", dest="working_directory", help="working directory; whipper will " "change to this directory " "and files will be created relative to " "it when not absolute") self.parser.add_argument('--track-template', action="store", dest="track_template", default=DEFAULT_TRACK_TEMPLATE, help="template for track file naming") self.parser.add_argument('--disc-template', action="store", dest="disc_template", default=DEFAULT_DISC_TEMPLATE, help="template for disc file naming") self.parser.add_argument('-U', '--unknown', action="store_true", dest="unknown", help="whether to continue ripping if " "the CD is unknown", default=False) self.parser.add_argument('--cdr', action="store_true", dest="cdr", help="whether to continue ripping if " "the disc is a CD-R", default=False) def handle_arguments(self): self.options.output_directory = os.path.expanduser( self.options.output_directory) self.options.track_template = self.options.track_template.decode( 'utf-8') self.options.disc_template = self.options.disc_template.decode('utf-8') if self.options.offset is None: raise ValueError("Drive offset is unconfigured.\n" "Please install pycdio and run 'whipper offset " "find' to detect your drive's offset or set it " "manually in the configuration file. It can " "also be specified at runtime using the " "'--offset=value' argument") if self.options.working_directory is not None: self.options.working_directory = os.path.expanduser( self.options.working_directory) if self.options.logger: try: self.logger = result.getLoggers()[self.options.logger]() except KeyError: msg = "No logger named %s found!" % self.options.logger logger.critical(msg) raise ValueError(msg) def doCommand(self): self.program.setWorkingDirectory(self.options.working_directory) self.program.outdir = self.options.output_directory.decode('utf-8') self.program.result.offset = int(self.options.offset) self.program.result.overread = self.options.overread self.program.result.logger = self.options.logger discName = self.program.getPath(self.program.outdir, self.options.disc_template, self.mbdiscid, self.program.metadata) dirname = os.path.dirname(discName) if os.path.exists(dirname): logs = glob.glob(os.path.join(dirname, '*.log')) if logs: msg = ("output directory %s is a finished rip" % dirname.encode('utf-8')) logger.critical(msg) raise RuntimeError(msg) else: sys.stdout.write("output directory %s already exists\n" % dirname.encode('utf-8')) print("creating output directory %s" % dirname.encode('utf-8')) os.makedirs(dirname) # FIXME: turn this into a method def _ripIfNotRipped(number): logger.debug('ripIfNotRipped for track %d' % number) # we can have a previous result trackResult = self.program.result.getTrackResult(number) if not trackResult: trackResult = result.TrackResult() self.program.result.tracks.append(trackResult) else: logger.debug('ripIfNotRipped have trackresult, path %r' % trackResult.filename) path = self.program.getPath(self.program.outdir, self.options.track_template, self.mbdiscid, self.program.metadata, track_number=number) + '.flac' logger.debug('ripIfNotRipped: path %r' % path) trackResult.number = number assert type(path) is unicode, "%r is not unicode" % path trackResult.filename = path if number > 0: trackResult.pregap = self.itable.tracks[number - 1].getPregap() trackResult.pre_emphasis = (self.itable.tracks[number - 1].pre_emphasis) # FIXME: optionally allow overriding reripping if os.path.exists(path): if path != trackResult.filename: # the path is different (different name/template ?) # but we can copy it logger.debug('previous result %r, expected %r' % (trackResult.filename, path)) sys.stdout.write('Verifying track %d of %d: %s\n' % (number, len(self.itable.tracks), os.path.basename(path).encode('utf-8'))) if not self.program.verifyTrack(self.runner, trackResult): sys.stdout.write('Verification failed, reripping...\n') os.unlink(path) if not os.path.exists(path): logger.debug('path %r does not exist, ripping...' % path) tries = 0 # we reset durations for test and copy here trackResult.testduration = 0.0 trackResult.copyduration = 0.0 extra = "" while tries < MAX_TRIES: tries += 1 if tries > 1: extra = " (try %d)" % tries sys.stdout.write('Ripping track %d of %d%s: %s\n' % (number, len(self.itable.tracks), extra, os.path.basename(path).encode('utf-8'))) try: logger.debug('ripIfNotRipped: track %d, try %d', number, tries) self.program.ripTrack( self.runner, trackResult, offset=int(self.options.offset), device=self.device, taglist=self.program.getTagList(number), overread=self.options.overread, what='track %d of %d%s' % (number, len(self.itable.tracks), extra)) break except Exception, e: logger.debug('Got exception %r on try %d', e, tries) if tries == MAX_TRIES: logger.critical('Giving up on track %d after %d times' % (number, tries)) raise RuntimeError( "track can't be ripped. " "Rip attempts number is equal to 'MAX_TRIES'") if trackResult.testcrc == trackResult.copycrc: sys.stdout.write('CRCs match for track %d\n' % number) else: raise RuntimeError("CRCs did not match for track %d\n" % number) sys.stdout.write('Peak level: {:.2%} \n'.format( trackResult.peak)) sys.stdout.write('Rip quality: {:.2%}\n'.format( trackResult.quality)) # overlay this rip onto the Table if number == 0: # HTOA goes on index 0 of track 1 # ignore silence in PREGAP if trackResult.peak <= SILENT: logger.debug( 'HTOA peak %r is below SILENT ' 'threshold, disregarding', trackResult.peak) self.itable.setFile(1, 0, None, self.ittoc.getTrackStart(1), number) logger.debug('Unlinking %r', trackResult.filename) os.unlink(trackResult.filename) trackResult.filename = None sys.stdout.write( 'HTOA discarded, contains digital silence\n') else: self.itable.setFile(1, 0, trackResult.filename, self.ittoc.getTrackStart(1), number) else: self.itable.setFile(number, 1, trackResult.filename, self.ittoc.getTrackLength(number), number) self.program.saveRipResult() # check for hidden track one audio htoa = self.program.getHTOA() if htoa: start, stop = htoa print('found Hidden Track One Audio from frame %d to %d' % (start, stop)) _ripIfNotRipped(0) for i, track in enumerate(self.itable.tracks): # FIXME: rip data tracks differently if not track.audio: print('skipping data track %d, not implemented' % (i + 1)) # FIXME: make it work for now track.indexes[1].relative = 0 continue _ripIfNotRipped(i + 1) logger.debug('writing cue file for %r', discName) self.program.writeCue(discName) logger.debug('writing m3u file for %r', discName) self.program.write_m3u(discName) try: self.program.verifyImage(self.runner, self.ittoc) except accurip.EntryNotFound: print('AccurateRip entry not found') accurip.print_report(self.program.result) self.program.saveRipResult() self.program.writeLog(discName, self.logger)
def doCommand(self): self.program.setWorkingDirectory(self.options.working_directory) self.program.outdir = self.options.output_directory self.program.result.offset = int(self.options.offset) self.program.result.overread = self.options.overread self.program.result.logger = self.options.logger discName = self.program.getPath(self.program.outdir, self.options.disc_template, self.mbdiscid, self.program.metadata) dirname = os.path.dirname(discName) if os.path.exists(dirname): logs = glob.glob(os.path.join(dirname, '*.log')) if logs: msg = ("output directory %s is a finished rip" % dirname) logger.debug(msg) raise RuntimeError(msg) else: logger.info("creating output directory %s", dirname) os.makedirs(dirname) self.coverArtPath = None if (self.options.cover_art in {"embed", "complete"} and importlib.util.find_spec("PIL") is None): logger.warning("the cover art option '%s' won't be honored " "because the 'pillow' module isn't available", self.options.cover_art) elif self.options.cover_art in {"file", "embed", "complete"}: if getattr(self.program.metadata, "mbid", None) is not None: self.coverArtPath = self.program.getCoverArt( dirname, self.program.metadata.mbid) else: logger.warning("the cover art option '%s' won't be honored " "because disc metadata isn't available", self.options.cover_art) if self.options.cover_art == "file": self.coverArtPath = None # NOTE: avoid image embedding (hacky) # FIXME: turn this into a method def _ripIfNotRipped(number): logger.debug('ripIfNotRipped for track %d', number) # we can have a previous result trackResult = self.program.result.getTrackResult(number) if not trackResult: trackResult = result.TrackResult() self.program.result.tracks.append(trackResult) else: logger.debug('ripIfNotRipped have trackresult, path %r', trackResult.filename) path = self.program.getPath(self.program.outdir, self.options.track_template, self.mbdiscid, self.program.metadata, track_number=number) + '.flac' logger.debug('ripIfNotRipped: path %r', path) trackResult.number = number assert isinstance(path, str), "%r is not str" % path trackResult.filename = path if number > 0: trackResult.pregap = self.itable.tracks[number - 1].getPregap() trackResult.pre_emphasis = ( self.itable.tracks[number - 1].pre_emphasis ) # FIXME: optionally allow overriding reripping if os.path.exists(path): if path != trackResult.filename: # the path is different (different name/template ?) # but we can copy it logger.debug('previous result %r, expected %r', trackResult.filename, path) logger.info('verifying track %d of %d: %s', number, len(self.itable.tracks), os.path.basename(path)) if not self.program.verifyTrack(self.runner, trackResult): logger.warning('verification failed, reripping...') os.unlink(path) if not os.path.exists(path): logger.debug('path %r does not exist, ripping...', path) # we reset durations for test and copy here trackResult.testduration = 0.0 trackResult.copyduration = 0.0 extra = "" tries = 1 while tries <= self.options.max_retries: if tries > 1: extra = " (try %d)" % tries logger.info('ripping track %d of %d%s: %s', number, len(self.itable.tracks), extra, os.path.basename(path)) logger.debug('ripIfNotRipped: track %d, try %d', number, tries) tag_list = self.program.getTagList(number, self.mbdiscid) # An HTOA can't have an ISRC value if (number > 0 and self.itable.tracks[number - 1].isrc is not None): tag_list['ISRC'] = self.itable.tracks[number - 1].isrc try: self.program.ripTrack(self.runner, trackResult, offset=int(self.options.offset), device=self.device, taglist=tag_list, overread=self.options.overread, what='track %d of %d%s' % ( number, len(self.itable.tracks), extra), coverArtPath=self.coverArtPath) break # FIXME: catching too general exception (Exception) except Exception as e: logger.debug('got exception %r on try %d', e, tries) tries += 1 if tries > self.options.max_retries: tries -= 1 logger.critical('giving up on track %d after %d times', number, tries) if self.options.keep_going: logger.warning("track %d failed to rip.", number) logger.debug("adding %s to skipped_tracks", trackResult) self.skipped_tracks.append(trackResult) logger.debug("skipped_tracks = %s", self.skipped_tracks) trackResult.skipped = True else: raise RuntimeError("track can't be ripped. " "Rip attempts number is equal " "to %d", self.options.max_retries) if trackResult in self.skipped_tracks: print("Skipping CRC comparison for track %d " "due to rip failure" % number) else: if trackResult.testcrc == trackResult.copycrc: logger.info('CRCs match for track %d', number) else: raise RuntimeError( "CRCs did not match for track %d" % number ) print('Peak level: %.6f' % (trackResult.peak / 32768.0)) print('Rip quality: {:.2%}'.format(trackResult.quality)) # overlay this rip onto the Table if number == 0: # HTOA goes on index 0 of track 1 # ignore silence in PREGAP if trackResult.peak == SILENT: logger.debug('HTOA peak %r is equal to the SILENT ' 'threshold, disregarding', trackResult.peak) self.itable.setFile(1, 0, None, self.itable.getTrackStart(1), number) logger.debug('unlinking %r', trackResult.filename) os.unlink(trackResult.filename) trackResult.filename = None logger.info('HTOA discarded, contains digital silence') else: self.itable.setFile(1, 0, trackResult.filename, self.itable.getTrackStart(1), number) else: self.itable.setFile(number, 1, trackResult.filename, self.itable.getTrackLength(number), number) # check for hidden track one audio htoa = self.program.getHTOA() if htoa: start, stop = htoa logger.info('found Hidden Track One Audio from frame %d to %d', start, stop) _ripIfNotRipped(0) for i, track in enumerate(self.itable.tracks): # FIXME: rip data tracks differently if not track.audio: logger.warning('skipping data track %d, not implemented', i + 1) # FIXME: make it work for now track.indexes[1].relative = 0 continue _ripIfNotRipped(i + 1) # NOTE: Seems like some kind of with … or try: … finally: … clause # would be more appropriate, since otherwise this would potentially # leave stray files lying around in case of crashes etc. # <Freso 2020-01-03, GitHub comment> if (self.options.cover_art == "embed" and self.coverArtPath is not None): logger.debug('deleting cover art file at: %r', self.coverArtPath) os.remove(self.coverArtPath) logger.debug('writing cue file for %r', discName) self.program.writeCue(discName) logger.debug('writing m3u file for %r', discName) self.program.write_m3u(discName) if len(self.skipped_tracks) > 0: logger.warning("the generated cue sheet references %d track(s) " "which failed to rip so the associated file(s) " "won't be available", len(self.skipped_tracks)) self.program.skipped_tracks = self.skipped_tracks try: self.program.verifyImage(self.runner, self.itable) except accurip.EntryNotFound: logger.warning('AccurateRip entry not found') accurip.print_report(self.program.result) self.program.writeLog(discName, self.logger) if len(self.skipped_tracks) > 0: logger.warning('%d tracks have been skipped from this rip attempt', len(self.skipped_tracks)) return 5