diff --git a/morituri/common/checksum.py b/morituri/common/checksum.py index 6fd60ad..da85026 100644 --- a/morituri/common/checksum.py +++ b/morituri/common/checksum.py @@ -32,6 +32,10 @@ from morituri.common import log from morituri.common import task from morituri.extern.task import gstreamer +from morituri.extern.task import task as etask + +from morituri.program.arc import accuraterip_checksum + # checksums are not CRC's. a CRC is a specific type of checksum. @@ -268,6 +272,29 @@ class CRC32Task(ChecksumTask): return zlib.crc32(buf, checksum) +class FastAccurateRipChecksumTask(etask.Task): + description = 'Calculating (Fast) AccurateRip checksum' + + def __init__(self, path, trackNumber, trackCount, wave, v2=False): + self.path = path + self.trackNumber = trackNumber + self.trackCount = trackCount + self._wave = wave + self._v2 = v2 + self.checksum = None + + def start(self, runner): + etask.Task.start(self, runner) + self.schedule(0.0, self._arc) + + def _arc(self): + arc = accuraterip_checksum(self.path, self.trackNumber, self.trackCount, + self._wave, self._v2) + self.checksum = arc + + self.stop() + + class AccurateRipChecksumTask(ChecksumTask): """ I implement the AccurateRip checksum. diff --git a/morituri/program/arc.py b/morituri/program/arc.py new file mode 100644 index 0000000..1d9a413 --- /dev/null +++ b/morituri/program/arc.py @@ -0,0 +1,50 @@ +import logging +from subprocess import Popen, PIPE +from os.path import exists + +ARB = 'accuraterip-checksum' +FLAC = 'flac' + +def accuraterip_checksum(f, track, tracks, wave=False, v2=False): + v = '--accuraterip-v1' + if v2: + v = '--accuraterip-v2' + + track, tracks = str(track), str(tracks) + + if not wave: + flac = Popen([FLAC, '-cds', f], stdout=PIPE) + + arc = Popen([ARB, v, '/dev/stdin', track, tracks], + stdin=flac.stdout, stdout=PIPE, stderr=PIPE) + else: + arc = Popen([ARB, v, f, track, tracks], + stdout=PIPE, stderr=PIPE) + + if not wave: + flac.stdout.close() + + out, err = arc.communicate() + + if not wave: + flac.wait() + flac_rc = flac.returncode + + arc_rc = arc.returncode + + if not wave and flac_rc != 0: + logging.warning('ARC calculation failed: flac return code is non zero') + return None + + if arc_rc != 0: + logging.warning('ARC calculation failed: arc return code is non zero') + return None + + out = out.strip() + try: + outh = int('0x%s' % out, base=16) + except ValueError: + logging.warning('ARC output is not usable') + return None + + return outh