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