def cue(self, cuePath='', program='whipper'): """ @param cuePath: path to the cue file to be written. If empty, will treat paths as if in current directory. Dump our internal representation to a .cue file content. @rtype: C{unicode} """ logger.debug('generating .cue for cuePath %r', cuePath) lines = [] def writeFile(path): targetPath = common.getRelativePath(path, cuePath) line = 'FILE "%s" WAVE' % targetPath lines.append(line) logger.debug('writeFile: %r' % line) # header main = ['PERFORMER', 'TITLE'] for key in CDTEXT_FIELDS: if key not in main and key in self.cdtext: lines.append(" %s %s" % (key, self.cdtext[key])) assert self.hasTOC(), "Table does not represent a full CD TOC" lines.append('REM DISCID %s' % self.getCDDBDiscId().upper()) lines.append('REM COMMENT "%s %s"' % (program, whipper.__version__)) if self.catalog: lines.append("CATALOG %s" % self.catalog) for key in main: if key in self.cdtext: lines.append('%s "%s"' % (key, self.cdtext[key])) # FIXME: # - the first FILE statement goes before the first TRACK, even if # there is a non-file-using PREGAP # - the following FILE statements come after the last INDEX that # use that FILE; so before a next TRACK, PREGAP silence, ... # add the first FILE line; EAC always puts the first FILE # statement before TRACK 01 and any possible PRE-GAP firstTrack = self.tracks[0] index = firstTrack.getFirstIndex() indexOne = firstTrack.getIndex(1) counter = index.counter track = firstTrack while not index.path: t, i = self.getNextTrackIndex(track.number, index.number) track = self.tracks[t - 1] index = track.getIndex(i) counter = index.counter if index.path: logger.debug('counter %d, writeFile' % counter) writeFile(index.path) for i, track in enumerate(self.tracks): logger.debug('track i %r, track %r' % (i, track)) # FIXME: skip data tracks for now if not track.audio: continue indexes = track.indexes.keys() indexes.sort() wroteTrack = False for number in indexes: index = track.indexes[number] logger.debug('index %r, %r' % (number, index)) # any time the source counter changes to a higher value, # write a FILE statement # it has to be higher, because we can run into the HTOA # at counter 0 here if index.counter > counter: if index.path: logger.debug('counter %d, writeFile' % counter) writeFile(index.path) logger.debug('setting counter to index.counter %r' % index.counter) counter = index.counter # any time we hit the first index, write a TRACK statement if not wroteTrack: wroteTrack = True line = " TRACK %02d %s" % (i + 1, 'AUDIO') lines.append(line) logger.debug('%r' % line) for key in CDTEXT_FIELDS: if key in track.cdtext: lines.append(' %s "%s"' % (key, track.cdtext[key])) if track.isrc is not None: lines.append(" ISRC %s" % track.isrc) if track.pre_emphasis is not None: lines.append(" FLAGS PRE") # handle TRACK 01 INDEX 00 specially if 0 in indexes: index00 = track.indexes[0] if i == 0: # if we have a silent pre-gap, output it if not index00.path: length = indexOne.absolute - index00.absolute lines.append(" PREGAP %s" % common.framesToMSF(length)) continue # handle any other INDEX 00 after its TRACK lines.append(" INDEX " "%02d %s" % (0, common.framesToMSF(index00.relative))) if number > 0: # index 00 is output after TRACK up above lines.append(" INDEX %02d %s" % (number, common.framesToMSF(index.relative))) lines.append("") return "\n".join(lines)
def logRip(self, ripResult, epoch): """Returns logfile lines list""" lines = [] # Ripper version lines.append("Log created by: whipper %s (internal logger)" % whipper.__version__) # Rip date date = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(epoch)).strip() lines.append("Log creation date: %s" % date) lines.append("") # Rip technical settings lines.append("Ripping phase information:") lines.append(" Drive: %s%s (revision %s)" % (ripResult.vendor, ripResult.model, ripResult.release)) lines.append(" Extraction engine: cdparanoia %s" % ripResult.cdparanoiaVersion) if ripResult.cdparanoiaDefeatsCache is None: defeat = "Unknown" elif ripResult.cdparanoiaDefeatsCache: defeat = "Yes" else: defeat = "No" lines.append(" Defeat audio cache: %s" % defeat) lines.append(" Read offset correction: %+d" % ripResult.offset) # Currently unsupported by the official cdparanoia package over = "No" # Only implemented in whipper (ripResult.overread) if ripResult.overread: over = "Yes" lines.append(" Overread into lead-out: %s" % over) # Next one fully works only using the patched cdparanoia package # lines.append("Fill up missing offset samples with silence: Yes") lines.append(" Gap detection: cdrdao %s" % ripResult.cdrdaoVersion) if ripResult.isCdr: isCdr = "Yes" else: isCdr = "No" lines.append(" CD-R detected: %s" % isCdr) lines.append("") # CD metadata lines.append("CD metadata:") lines.append(" Album: %s - %s" % (ripResult.artist, ripResult.title)) lines.append(" CDDB Disc ID: %s" % ripResult.table.getCDDBDiscId()) lines.append(" MusicBrainz Disc ID: %s" % ripResult.table.getMusicBrainzDiscId()) lines.append(" MusicBrainz lookup url: %s" % ripResult.table.getMusicBrainzSubmitURL()) lines.append("") # TOC section lines.append("TOC:") table = ripResult.table # Test for HTOA presence htoa = None try: htoa = table.tracks[0].getIndex(0) except KeyError: pass # If True, include HTOA line into log's TOC if htoa and htoa.path: htoastart = htoa.absolute htoaend = table.getTrackEnd(0) htoalength = table.tracks[0].getIndex(1).absolute - htoastart lines.append(" 00:") lines.append(" Start: %s" % common.framesToMSF(htoastart)) lines.append(" Length: %s" % common.framesToMSF(htoalength)) lines.append(" Start sector: %d" % htoastart) lines.append(" End sector: %d" % htoaend) lines.append("") # For every track include information in the TOC for t in table.tracks: # FIXME: what happens to a track start over 60 minutes ? # Answer: tested empirically, everything seems OK start = t.getIndex(1).absolute length = table.getTrackLength(t.number) end = table.getTrackEnd(t.number) lines.append(" %02d:" % t.number) lines.append(" Start: %s" % common.framesToMSF(start)) lines.append(" Length: %s" % common.framesToMSF(length)) lines.append(" Start sector: %d" % start) lines.append(" End sector: %d" % end) lines.append("") # Tracks section lines.append("Tracks:") duration = 0.0 for t in ripResult.tracks: if not t.filename: continue lines.extend(self.trackLog(t)) lines.append("") duration += t.testduration + t.copyduration # Status report lines.append("Conclusive status report:") arHeading = " AccurateRip summary:" if self._inARDatabase == 0: lines.append("%s None of the tracks are present in the " "AccurateRip database" % arHeading) else: nonHTOA = len(ripResult.tracks) if ripResult.tracks[0].number == 0: nonHTOA -= 1 if self._accuratelyRipped == 0: lines.append("%s No tracks could be verified as accurate " "(you may have a different pressing from the " "one(s) in the database)" % arHeading) elif self._accuratelyRipped < nonHTOA: accurateTracks = nonHTOA - self._accuratelyRipped lines.append("%s Some tracks could not be verified as " "accurate (%d/%d got no match)" % (arHeading, accurateTracks, nonHTOA)) else: lines.append("%s All tracks accurately ripped" % arHeading) hsHeading = " Health status:" if self._errors: lines.append("%s There were errors" % hsHeading) else: lines.append("%s No errors occurred" % hsHeading) lines.append(" EOF: End of status report") lines.append("") # Log hash hasher = hashlib.sha256() hasher.update("\n".join(lines).encode("utf-8")) lines.append("SHA-256 hash: %s" % hasher.hexdigest().upper()) lines.append("") return lines
def cue(self, cuePath='', program='whipper'): """ @param cuePath: path to the cue file to be written. If empty, will treat paths as if in current directory. Dump our internal representation to a .cue file content. @rtype: C{unicode} """ logger.debug('generating .cue for cuePath %r', cuePath) lines = [] def writeFile(path): targetPath = common.getRelativePath(path, cuePath) line = 'FILE "%s" WAVE' % targetPath lines.append(line) logger.debug('writeFile: %r' % line) # header main = ['PERFORMER', 'TITLE'] for key in CDTEXT_FIELDS: if key not in main and key in self.cdtext: lines.append(" %s %s" % (key, self.cdtext[key])) assert self.hasTOC(), "Table does not represent a full CD TOC" lines.append('REM DISCID %s' % self.getCDDBDiscId().upper()) lines.append('REM COMMENT "%s %s"' % (program, whipper.__version__)) if self.catalog: lines.append("CATALOG %s" % self.catalog) for key in main: if key in self.cdtext: lines.append('%s "%s"' % (key, self.cdtext[key])) # FIXME: # - the first FILE statement goes before the first TRACK, even if # there is a non-file-using PREGAP # - the following FILE statements come after the last INDEX that # use that FILE; so before a next TRACK, PREGAP silence, ... # add the first FILE line; EAC always puts the first FILE # statement before TRACK 01 and any possible PRE-GAP firstTrack = self.tracks[0] index = firstTrack.getFirstIndex() indexOne = firstTrack.getIndex(1) counter = index.counter track = firstTrack while not index.path: t, i = self.getNextTrackIndex(track.number, index.number) track = self.tracks[t - 1] index = track.getIndex(i) counter = index.counter if index.path: logger.debug('counter %d, writeFile' % counter) writeFile(index.path) for i, track in enumerate(self.tracks): logger.debug('track i %r, track %r' % (i, track)) # FIXME: skip data tracks for now if not track.audio: continue indexes = track.indexes.keys() indexes.sort() wroteTrack = False for number in indexes: index = track.indexes[number] logger.debug('index %r, %r' % (number, index)) # any time the source counter changes to a higher value, # write a FILE statement # it has to be higher, because we can run into the HTOA # at counter 0 here if index.counter > counter: if index.path: logger.debug('counter %d, writeFile' % counter) writeFile(index.path) logger.debug('setting counter to index.counter %r' % index.counter) counter = index.counter # any time we hit the first index, write a TRACK statement if not wroteTrack: wroteTrack = True line = " TRACK %02d %s" % (i + 1, 'AUDIO') lines.append(line) logger.debug('%r' % line) for key in CDTEXT_FIELDS: if key in track.cdtext: lines.append(' %s "%s"' % ( key, track.cdtext[key])) if track.isrc is not None: lines.append(" ISRC %s" % track.isrc) if track.pre_emphasis is not None: lines.append(" FLAGS PRE") # handle TRACK 01 INDEX 00 specially if 0 in indexes: index00 = track.indexes[0] if i == 0: # if we have a silent pre-gap, output it if not index00.path: length = indexOne.absolute - index00.absolute lines.append(" PREGAP %s" % common.framesToMSF(length)) continue # handle any other INDEX 00 after its TRACK lines.append(" INDEX %02d %s" % (0, common.framesToMSF(index00.relative))) if number > 0: # index 00 is output after TRACK up above lines.append(" INDEX %02d %s" % (number, common.framesToMSF(index.relative))) lines.append("") return "\n".join(lines)
def logRip(self, ripResult, epoch): """Returns logfile lines list""" lines = [] # Ripper version lines.append("Log created by: whipper %s (internal logger)" % whipper.__version__) # Rip date date = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(epoch)).strip() lines.append("Log creation date: %s" % date) lines.append("") # Rip technical settings lines.append("Ripping phase information:") lines.append(" Drive: %s%s (revision %s)" % ( ripResult.vendor, ripResult.model, ripResult.release)) if ripResult.cdparanoiaDefeatsCache is None: defeat = "Unknown" elif ripResult.cdparanoiaDefeatsCache: defeat = "Yes" else: defeat = "No" lines.append(" Defeat audio cache: %s" % defeat) lines.append(" Read offset correction: %+d" % ripResult.offset) # Currently unsupported by the official cdparanoia package over = "No" # Only implemented in whipper (ripResult.overread) if ripResult.overread: over = "Yes" lines.append(" Overread into lead-out: %s" % over) # Next one fully works only using the patched cdparanoia package # lines.append("Fill up missing offset samples with silence: Yes") lines.append(" Gap detection: cdrdao %s" % ripResult.cdrdaoVersion) lines.append("") # CD metadata lines.append("CD metadata:") lines.append(" Album: %s - %s" % (ripResult.artist, ripResult.title)) lines.append(" CDDB Disc ID: %s" % ripResult. table.getCDDBDiscId()) lines.append(" MusicBrainz Disc ID: %s" % ripResult. table.getMusicBrainzDiscId()) lines.append(" MusicBrainz lookup url: %s" % ripResult. table.getMusicBrainzSubmitURL()) lines.append("") # TOC section lines.append("TOC:") table = ripResult.table # Test for HTOA presence htoa = None try: htoa = table.tracks[0].getIndex(0) except KeyError: pass # If True, include HTOA line into log's TOC if htoa and htoa.path: htoastart = htoa.absolute htoaend = table.getTrackEnd(0) htoalength = table.tracks[0].getIndex(1).absolute - htoastart lines.append(" 00:") lines.append(" Start: %s" % common.framesToMSF(htoastart)) lines.append(" Length: %s" % common.framesToMSF(htoalength)) lines.append(" Start sector: %d" % htoastart) lines.append(" End sector: %d" % htoaend) lines.append("") # For every track include information in the TOC for t in table.tracks: # FIXME: what happens to a track start over 60 minutes ? # Answer: tested empirically, everything seems OK start = t.getIndex(1).absolute length = table.getTrackLength(t.number) end = table.getTrackEnd(t.number) lines.append(" %02d:" % t.number) lines.append(" Start: %s" % common.framesToMSF(start)) lines.append(" Length: %s" % common.framesToMSF(length)) lines.append(" Start sector: %d" % start) lines.append(" End sector: %d" % end) lines.append("") # Tracks section lines.append("Tracks:") duration = 0.0 for t in ripResult.tracks: if not t.filename: continue lines.extend(self.trackLog(t)) lines.append("") duration += t.testduration + t.copyduration # Status report lines.append("Conclusive status report:") arHeading = " AccurateRip summary:" if self._inARDatabase == 0: lines.append("%s None of the tracks are present in the " "AccurateRip database" % arHeading) else: nonHTOA = len(ripResult.tracks) if ripResult.tracks[0].number == 0: nonHTOA -= 1 if self._accuratelyRipped == 0: lines.append("%s No tracks could be verified as accurate " "(you may have a different pressing from the " "one(s) in the database)" % arHeading) elif self._accuratelyRipped < nonHTOA: accurateTracks = nonHTOA - self._accuratelyRipped lines.append("%s Some tracks could not be verified as " "accurate (%d/%d got no match)" % ( arHeading, accurateTracks, nonHTOA)) else: lines.append("%s All tracks accurately ripped" % arHeading) hsHeading = " Health status:" if self._errors: lines.append("%s There were errors" % hsHeading) else: lines.append("%s No errors occurred" % hsHeading) lines.append(" EOF: End of status report") lines.append("") # Log hash hasher = hashlib.sha256() hasher.update("\n".join(lines).encode("utf-8")) lines.append("SHA-256 hash: %s" % hasher.hexdigest().upper()) lines.append("") return lines
def trackLog(self, trackResult): """Returns Tracks section lines: data picked from trackResult""" lines = [] # Track number lines.append(" %02d:" % trackResult.number) # Filename (including path) of ripped track lines.append(" Filename: %s" % trackResult.filename) # Pre-gap length pregap = trackResult.pregap if pregap: lines.append(" Pre-gap length: %s" % common.framesToMSF(pregap)) # Peak level peak = trackResult.peak / 32768.0 lines.append(" Peak level: %.6f" % peak) # Pre-emphasis status # Only implemented in whipper (trackResult.pre_emphasis) if trackResult.pre_emphasis: preEmph = "Yes" else: preEmph = "No" lines.append(" Pre-emphasis: %s" % preEmph) # Extraction speed if trackResult.copyspeed: lines.append(" Extraction speed: %.1f X" % (trackResult.copyspeed)) # Extraction quality if trackResult.quality and trackResult.quality > 0.001: lines.append(" Extraction quality: %.2f %%" % (trackResult.quality * 100.0, )) # Ripper Test CRC if trackResult.testcrc is not None: lines.append(" Test CRC: %08X" % trackResult.testcrc) # Ripper Copy CRC if trackResult.copycrc is not None: lines.append(" Copy CRC: %08X" % trackResult.copycrc) # AccurateRip track status for v in ('v1', 'v2'): if trackResult.AR[v]['DBCRC']: lines.append(" AccurateRip %s:" % v) self._inARDatabase += 1 if trackResult.AR[v]['CRC'] == trackResult.AR[v]['DBCRC']: lines.append(" Result: Found, exact match") self._accuratelyRipped += 1 else: lines.append(" Result: Found, NO exact match") lines.append(" Confidence: %d" % trackResult.AR[v]['DBConfidence']) lines.append(" Local CRC: %s" % trackResult.AR[v]['CRC'].upper()) lines.append(" Remote CRC: %s" % trackResult.AR[v]['DBCRC'].upper()) elif trackResult.number != 0: lines.append(" AccurateRip %s:" % v) lines.append( " Result: Track not present in AccurateRip database") # Check if Test & Copy CRCs are equal if trackResult.testcrc == trackResult.copycrc: lines.append(" Status: Copy OK") else: self._errors = True lines.append(" Status: Error, CRC mismatch") return lines
def trackLog(self, trackResult): """Returns Tracks section lines: data picked from trackResult""" lines = [] # Track number lines.append(" %02d:" % trackResult.number) # Filename (including path) of ripped track lines.append(" Filename: %s" % trackResult.filename) # Pre-gap length pregap = trackResult.pregap if pregap: lines.append(" Pre-gap length: %s" % common.framesToMSF(pregap)) # Peak level peak = trackResult.peak lines.append(" Peak level: %.6f" % peak) # Pre-emphasis status # Only implemented in whipper (trackResult.pre_emphasis) if trackResult.pre_emphasis: preEmph = "Yes" else: preEmph = "No" lines.append(" Pre-emphasis: %s" % preEmph) # Extraction speed if trackResult.copyspeed: lines.append(" Extraction speed: %.1f X" % ( trackResult.copyspeed)) # Extraction quality if trackResult.quality and trackResult.quality > 0.001: lines.append(" Extraction quality: %.2f %%" % (trackResult.quality * 100.0, )) # Ripper Test CRC if trackResult.testcrc is not None: lines.append(" Test CRC: %08X" % trackResult.testcrc) # Ripper Copy CRC if trackResult.copycrc is not None: lines.append(" Copy CRC: %08X" % trackResult.copycrc) # AccurateRip track status # Currently there's no support for AccurateRip V2 if trackResult.accurip: lines.append(" AccurateRip V1:") self._inARDatabase += 1 if trackResult.ARCRC == trackResult.ARDBCRC: lines.append(" Result: Found, exact match") self._accuratelyRipped += 1 else: lines.append(" Result: Found, NO exact match") lines.append(" Confidence: %d" % trackResult.ARDBConfidence) lines.append(" Local CRC: %08X" % trackResult.ARCRC) lines.append(" Remote CRC: %08X" % trackResult.ARDBCRC) elif trackResult.number != 0: lines.append(" AccurateRip V1:") lines.append(" Result: Track not present in " "AccurateRip database") # Check if Test & Copy CRCs are equal if trackResult.testcrc == trackResult.copycrc: lines.append(" Status: Copy OK") else: self._errors = True lines.append(" Status: Error, CRC mismatch") return lines
def logRip(self, ripResult, epoch): """Return logfile as list of lines.""" riplog = OrderedDict() # Ripper version riplog["Log created by"] = "whipper %s (internal logger)" % ( whipper.__version__) # Rip date date = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(epoch)).strip() riplog["Log creation date"] = date # Rip technical settings data = OrderedDict() data["Drive"] = "%s%s (revision %s)" % ( ripResult.vendor, ripResult.model, ripResult.release) data["Extraction engine"] = "cdparanoia %s" % ( ripResult.cdparanoiaVersion) data["Defeat audio cache"] = ripResult.cdparanoiaDefeatsCache data["Read offset correction"] = ripResult.offset # Currently unsupported by the official cdparanoia package # Only implemented in whipper (ripResult.overread) data["Overread into lead-out"] = True if ripResult.overread else False # Next one fully works only using the patched cdparanoia package # lines.append("Fill up missing offset samples with silence: true") data["Gap detection"] = "cdrdao %s" % ripResult.cdrdaoVersion data["CD-R detected"] = ripResult.isCdr riplog["Ripping phase information"] = data # CD metadata release = OrderedDict() release["Artist"] = ripResult.artist release["Title"] = ripResult.title data = OrderedDict() data["Release"] = release data["CDDB Disc ID"] = ripResult.table.getCDDBDiscId() data["MusicBrainz Disc ID"] = ripResult.table.getMusicBrainzDiscId() data["MusicBrainz lookup URL"] = ( ripResult.table.getMusicBrainzSubmitURL()) if ripResult.metadata: data["MusicBrainz Release URL"] = ripResult.metadata.url riplog["CD metadata"] = data # TOC section data = OrderedDict() table = ripResult.table # Test for HTOA presence htoa = None try: htoa = table.tracks[0].getIndex(0) except KeyError: pass # If True, include HTOA line into log's TOC if htoa and htoa.path: htoastart = htoa.absolute htoaend = table.getTrackEnd(0) htoalength = table.tracks[0].getIndex(1).absolute - htoastart track = OrderedDict() track["Start"] = common.framesToMSF(htoastart) track["Length"] = common.framesToMSF(htoalength) track["Start sector"] = htoastart track["End sector"] = htoaend data[0] = track # For every track include information in the TOC for t in table.tracks: start = t.getIndex(1).absolute length = table.getTrackLength(t.number) end = table.getTrackEnd(t.number) track = OrderedDict() track["Start"] = common.framesToMSF(start) track["Length"] = common.framesToMSF(length) track["Start sector"] = start track["End sector"] = end data[t.number] = track riplog["TOC"] = data # Tracks section data = OrderedDict() duration = 0.0 for t in ripResult.tracks: if not t.filename: continue track_dict, ARDB_entry, ARDB_match = self.trackLog(t) self._inARDatabase += int(ARDB_entry) self._accuratelyRipped += int(ARDB_match) data[t.number] = track_dict duration += t.testduration + t.copyduration riplog["Tracks"] = data # Status report data = OrderedDict() if self._inARDatabase == 0: message = ("None of the tracks are present in the " "AccurateRip database") else: nonHTOA = len(ripResult.tracks) if ripResult.tracks[0].number == 0: nonHTOA -= 1 if self._accuratelyRipped == 0: message = ("No tracks could be verified as accurate " "(you may have a different pressing from the " "one(s) in the database)") elif self._accuratelyRipped < nonHTOA: accurateTracks = nonHTOA - self._accuratelyRipped message = ("Some tracks could not be verified as " "accurate (%d/%d got no match)") % (accurateTracks, nonHTOA) else: message = "All tracks accurately ripped" data["AccurateRip summary"] = message if self._errors: message = "There were errors" elif self._skippedTracks: message = "Some tracks were not ripped (skipped)" else: message = "No errors occurred" data["Health status"] = message data["EOF"] = "End of status report" riplog["Conclusive status report"] = data riplog = yaml.dump(riplog, default_flow_style=False, width=4000, Dumper=yaml.RoundTripDumper) # Add a newline after the "Log creation date" line riplog = re.sub(r'^(Log creation date: .*)$', "\\1\n", riplog, flags=re.MULTILINE) # Add a newline after a dictionary ends and returns to top-level riplog = re.sub(r"^(\s{2})([^\n]*)\n([A-Z][^\n]+)", "\\1\\2\n\n\\3", riplog, flags=re.MULTILINE) # Add a newline after a track closes riplog = re.sub(r"^(\s{4}[^\n]*)\n(\s{2}[0-9]+)", "\\1\n\n\\2", riplog, flags=re.MULTILINE) # Remove single quotes around the "Log creation date" value riplog = re.sub(r"^(Log creation date: )'(.*)'", "\\1\\2", riplog, flags=re.MULTILINE) # Log hash hasher = hashlib.sha256() hasher.update(riplog.encode("utf-8")) riplog += "\nSHA-256 hash: %s\n" % hasher.hexdigest().upper() return riplog
def trackLog(self, trackResult): """Return Tracks section lines: data picked from trackResult.""" track = OrderedDict() # Filename (including path) of ripped track track["Filename"] = trackResult.filename # Pre-gap length pregap = trackResult.pregap if pregap: track["Pre-gap length"] = common.framesToMSF(pregap) # Peak level peak = trackResult.peak / 32768.0 track["Peak level"] = float("%.6f" % peak) # Pre-emphasis status # Only implemented in whipper (trackResult.pre_emphasis) track["Pre-emphasis"] = trackResult.pre_emphasis # Extraction speed if trackResult.copyspeed: track["Extraction speed"] = "%.1f X" % trackResult.copyspeed # Extraction quality if trackResult.quality and trackResult.quality > 0.001: track["Extraction quality"] = "%.2f %%" % (trackResult.quality * 100.0, ) # Ripper Test CRC if trackResult.testcrc is not None: track["Test CRC"] = "%08X" % trackResult.testcrc # Ripper Copy CRC if trackResult.copycrc is not None: track["Copy CRC"] = "%08X" % trackResult.copycrc # AccurateRip track status ARDB_entry = 0 ARDB_match = 0 for v in ("v1", "v2"): data = OrderedDict() if trackResult.AR[v]["DBCRC"]: ARDB_entry += 1 if trackResult.AR[v]["CRC"] == trackResult.AR[v]["DBCRC"]: data["Result"] = "Found, exact match" ARDB_match += 1 else: data["Result"] = "Found, NO exact match" data["Confidence"] = trackResult.AR[v]["DBConfidence"] data["Local CRC"] = trackResult.AR[v]["CRC"].upper() data["Remote CRC"] = trackResult.AR[v]["DBCRC"].upper() elif trackResult.number != 0: data["Result"] = "Track not present in AccurateRip database" track["AccurateRip %s" % v] = data # Check if track has been skipped if trackResult.skipped: track["Status"] = "Track not ripped (skipped)" self._skippedTracks = True # Check if Test & Copy CRCs are equal elif trackResult.testcrc == trackResult.copycrc: track["Status"] = "Copy OK" else: self._errors = True track["Status"] = "Error, CRC mismatch" return track, bool(ARDB_entry), bool(ARDB_match)
def trackLog(self, trackResult): """Returns Tracks section lines: data picked from trackResult""" lines = [] # Track number lines.append(" %d:" % trackResult.number) # Filename (including path) of ripped track lines.append(" Filename: %s" % trackResult.filename) # Pre-gap length pregap = trackResult.pregap if pregap: lines.append(" Pre-gap length: %s" % common.framesToMSF(pregap)) # Peak level peak = trackResult.peak / 32768.0 lines.append(" Peak level: %.6f" % peak) # Pre-emphasis status # Only implemented in whipper (trackResult.pre_emphasis) if trackResult.pre_emphasis: preEmph = "Yes" else: preEmph = "No" lines.append(" Pre-emphasis: %s" % preEmph) # Extraction speed if trackResult.copyspeed: lines.append(" Extraction speed: %.1f X" % ( trackResult.copyspeed)) # Extraction quality if trackResult.quality and trackResult.quality > 0.001: lines.append(" Extraction quality: %.2f %%" % (trackResult.quality * 100.0, )) # Ripper Test CRC if trackResult.testcrc is not None: lines.append(" Test CRC: %08X" % trackResult.testcrc) # Ripper Copy CRC if trackResult.copycrc is not None: lines.append(" Copy CRC: %08X" % trackResult.copycrc) # AccurateRip track status ARDB_entry = 0 ARDB_match = 0 for v in ("v1", "v2"): if trackResult.AR[v]["DBCRC"]: lines.append(" AccurateRip %s:" % v) ARDB_entry += 1 if trackResult.AR[v]["CRC"] == trackResult.AR[v]["DBCRC"]: lines.append(" Result: Found, exact match") ARDB_match += 1 else: lines.append(" Result: Found, NO exact match") lines.append( " Confidence: %d" % trackResult.AR[v]["DBConfidence"] ) lines.append( " Local CRC: %s" % trackResult.AR[v]["CRC"].upper() ) lines.append( " Remote CRC: %s" % trackResult.AR[v]["DBCRC"].upper() ) elif trackResult.number != 0: lines.append(" AccurateRip %s:" % v) lines.append( " Result: Track not present in AccurateRip database" ) # Check if Test & Copy CRCs are equal if trackResult.testcrc == trackResult.copycrc: lines.append(" Status: Copy OK") else: self._errors = True lines.append(" Status: Error, CRC mismatch") return lines, bool(ARDB_entry), bool(ARDB_match)
def trackLog(self, trackResult): """Generate tracks section lines. Tracks information are mostly taken from ``trackResult``. :param trackResult: :type trackResult: :returns: tracks section lines. :rtype: list """ lines = [] # Track number lines.append(" %02d:" % trackResult.number) # Filename (including path) of ripped track lines.append(" Filename: %s" % trackResult.filename) # Pre-gap length pregap = trackResult.pregap if pregap: lines.append(" Pre-gap length: %s" % common.framesToMSF(pregap)) # Peak level peak = trackResult.peak lines.append(" Peak level: %.6f" % peak) # Pre-emphasis status # Only implemented in whipper (trackResult.pre_emphasis) if trackResult.pre_emphasis: preEmph = "Yes" else: preEmph = "No" lines.append(" Pre-emphasis: %s" % preEmph) # Extraction speed if trackResult.copyspeed: lines.append(" Extraction speed: %.1f X" % ( trackResult.copyspeed)) # Extraction quality if trackResult.quality and trackResult.quality > 0.001: lines.append(" Extraction quality: %.2f %%" % (trackResult.quality * 100.0, )) # Ripper Test CRC if trackResult.testcrc is not None: lines.append(" Test CRC: %08X" % trackResult.testcrc) # Ripper Copy CRC if trackResult.copycrc is not None: lines.append(" Copy CRC: %08X" % trackResult.copycrc) # AccurateRip track status for v in ('v1', 'v2'): if trackResult.AR[v]['DBCRC']: lines.append(" AccurateRip %s:" % v) self._inARDatabase += 1 if trackResult.AR[v]['CRC'] == trackResult.AR[v]['DBCRC']: lines.append(" Result: Found, exact match") self._accuratelyRipped += 1 else: lines.append(" Result: Found, NO exact match") lines.append( " Confidence: %d" % trackResult.AR[v]['DBConfidence'] ) lines.append( " Local CRC: %s" % trackResult.AR[v]['CRC'].upper() ) lines.append( " Remote CRC: %s" % trackResult.AR[v]['DBCRC'].upper() ) elif trackResult.number != 0: lines.append(" AccurateRip %s:" % v) lines.append( " Result: Track not present in AccurateRip database" ) # Check if Test & Copy CRCs are equal if trackResult.testcrc == trackResult.copycrc: lines.append(" Status: Copy OK") else: self._errors = True lines.append(" Status: Error, CRC mismatch") return lines