* examples/ARcue.py:
* morituri/common/task.py: First version that seems to get some AccurateRip checksums right.
This commit is contained in:
@@ -1,3 +1,9 @@
|
|||||||
|
2009-03-22 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||||
|
|
||||||
|
* examples/ARcue.py:
|
||||||
|
* morituri/common/task.py:
|
||||||
|
First version that seems to get some AccurateRip checksums right.
|
||||||
|
|
||||||
2009-02-28 Thomas Vander Stichele <thomas at apestaart dot org>
|
2009-02-28 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||||
|
|
||||||
* morituri/image/cue.py:
|
* morituri/image/cue.py:
|
||||||
|
|||||||
@@ -35,7 +35,9 @@ def main(path):
|
|||||||
|
|
||||||
for track in cuefile.tracks:
|
for track in cuefile.tracks:
|
||||||
index = track._indexes[1]
|
index = track._indexes[1]
|
||||||
|
length = cuefile.getTrackLength(track)
|
||||||
file = index[1]
|
file = index[1]
|
||||||
|
offset = index[0]
|
||||||
|
|
||||||
# find an actual potential file
|
# find an actual potential file
|
||||||
crctask = None
|
crctask = None
|
||||||
@@ -46,12 +48,13 @@ def main(path):
|
|||||||
for ext in ['wav', 'flac']:
|
for ext in ['wav', 'flac']:
|
||||||
path = '%s.%s' % (noext, ext)
|
path = '%s.%s' % (noext, ext)
|
||||||
if os.path.exists(path):
|
if os.path.exists(path):
|
||||||
crctask = task.CRCTask(path)
|
crctask = task.CRCAudioRipTask(path, offset * 588,
|
||||||
|
length * 588)
|
||||||
|
|
||||||
if not crctask:
|
if not crctask:
|
||||||
print 'error: path %s not found' % file.path
|
print 'error: path %s not found' % file.path
|
||||||
|
|
||||||
print 'Analyzing', file.path
|
print 'Analyzing', file.path, "from CD frame ", offset, length, "CD frames"
|
||||||
runner = task.SyncRunner(crctask)
|
runner = task.SyncRunner(crctask)
|
||||||
runner.run()
|
runner.run()
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
import struct
|
||||||
import zlib
|
import zlib
|
||||||
|
|
||||||
import gobject
|
import gobject
|
||||||
@@ -37,8 +38,8 @@ class Task(object):
|
|||||||
_listeners = None
|
_listeners = None
|
||||||
|
|
||||||
def debug(self, *args, **kwargs):
|
def debug(self, *args, **kwargs):
|
||||||
print args, kwargs
|
#print args, kwargs
|
||||||
sys.stdout.flush()
|
#sys.stdout.flush()
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
@@ -70,13 +71,22 @@ class CRCTask(Task):
|
|||||||
# this object needs a main loop to stop
|
# this object needs a main loop to stop
|
||||||
description = 'Calculating CRC checksum...'
|
description = 'Calculating CRC checksum...'
|
||||||
|
|
||||||
def __init__(self, path, frameStart=0, frameEnd=-1):
|
def __init__(self, path, frameStart=0, frameLength=-1):
|
||||||
|
"""
|
||||||
|
A frame is considered a set of samples for each channel;
|
||||||
|
ie 16 bit stereo is 4 bytes per frame.
|
||||||
|
If frameLength < 0 it is treated as 'unknown' and calculated.
|
||||||
|
|
||||||
|
@type frameStart: int
|
||||||
|
@param frameStart: the frame to start at
|
||||||
|
"""
|
||||||
if not os.path.exists(path):
|
if not os.path.exists(path):
|
||||||
raise IndexError, '%s does not exist' % path
|
raise IndexError, '%s does not exist' % path
|
||||||
|
|
||||||
self._path = path
|
self._path = path
|
||||||
self._frameStart = frameStart
|
self._frameStart = frameStart
|
||||||
self._frameEnd = frameEnd
|
self._frameLength = frameLength
|
||||||
|
self._frameEnd = None
|
||||||
self._crc = 0
|
self._crc = 0
|
||||||
self._bytes = 0
|
self._bytes = 0
|
||||||
self._first = None
|
self._first = None
|
||||||
@@ -98,10 +108,13 @@ class CRCTask(Task):
|
|||||||
self.debug('query duration')
|
self.debug('query duration')
|
||||||
sink = self._pipeline.get_by_name('sink')
|
sink = self._pipeline.get_by_name('sink')
|
||||||
|
|
||||||
if self._frameEnd == -1:
|
if self._frameLength < 0:
|
||||||
length, _ = sink.query_duration(gst.FORMAT_DEFAULT)
|
length, _ = sink.query_duration(gst.FORMAT_DEFAULT)
|
||||||
self._frameEnd = length - 1
|
print 'total length', length
|
||||||
self.debug('last frame is', self._frameEnd)
|
self._frameLength = length - self._frameStart
|
||||||
|
self.debug('frame length is', self._frameLength)
|
||||||
|
print 'frame length is', self._frameLength
|
||||||
|
self._frameEnd = self._frameStart + self._frameLength - 1
|
||||||
|
|
||||||
self.debug('event')
|
self.debug('event')
|
||||||
|
|
||||||
@@ -111,7 +124,8 @@ class CRCTask(Task):
|
|||||||
gst.SEEK_FLAG_FLUSH,
|
gst.SEEK_FLAG_FLUSH,
|
||||||
gst.SEEK_TYPE_SET, self._frameStart,
|
gst.SEEK_TYPE_SET, self._frameStart,
|
||||||
gst.SEEK_TYPE_SET, self._frameEnd + 1) # half-inclusive interval
|
gst.SEEK_TYPE_SET, self._frameEnd + 1) # half-inclusive interval
|
||||||
# FIXME: sending it with frameEnd set screws up the seek, we don't get everything
|
# FIXME: sending it with frameEnd set screws up the seek, we don't get
|
||||||
|
# everything for flac; fixed in recent -good
|
||||||
result = sink.send_event(event)
|
result = sink.send_event(event)
|
||||||
#self.debug('event sent')
|
#self.debug('event sent')
|
||||||
#self.debug(result)
|
#self.debug(result)
|
||||||
@@ -132,14 +146,21 @@ class CRCTask(Task):
|
|||||||
self._last = buffer
|
self._last = buffer
|
||||||
|
|
||||||
assert len(buffer) % 4 == 0, "buffer is not a multiple of 4 bytes"
|
assert len(buffer) % 4 == 0, "buffer is not a multiple of 4 bytes"
|
||||||
self._bytes += len(buffer)
|
|
||||||
|
|
||||||
# update progress
|
# update progress
|
||||||
frame = self._first + self._bytes / 4
|
frame = self._first + self._bytes / 4
|
||||||
progress = float((frame - self._frameStart)) / float((self._frameEnd - self._frameStart))
|
framesDone = frame - self._frameStart
|
||||||
|
progress = float(framesDone) / float((self._frameLength))
|
||||||
self.setProgress(progress)
|
self.setProgress(progress)
|
||||||
|
|
||||||
self._crc = zlib.crc32(buffer, self._crc)
|
self._crc = self.do_crc_buffer(buffer, self._crc)
|
||||||
|
self._bytes += len(buffer)
|
||||||
|
|
||||||
|
def do_crc_buffer(self, buffer, crc):
|
||||||
|
"""
|
||||||
|
Subclasses should implement this.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
def _eos_cb(self, sink):
|
def _eos_cb(self, sink):
|
||||||
# get the last one; FIXME: why does this not get to us before ?
|
# get the last one; FIXME: why does this not get to us before ?
|
||||||
@@ -153,14 +174,34 @@ class CRCTask(Task):
|
|||||||
self._crc = self._crc % 2 ** 32
|
self._crc = self._crc % 2 ** 32
|
||||||
last = self._last.offset + len(self._last) / 4 - 1
|
last = self._last.offset + len(self._last) / 4 - 1
|
||||||
self.debug("last sample:", last)
|
self.debug("last sample:", last)
|
||||||
self.debug("frame end:", self._frameEnd)
|
self.debug("frame length:", self._frameLength)
|
||||||
self.debug("CRC: %08X" % self._crc)
|
self.debug("CRC: %08X" % self._crc)
|
||||||
self.debug("bytes: %d" % self._bytes)
|
self.debug("bytes: %d" % self._bytes)
|
||||||
if self._frameEnd != last:
|
if self._frameEnd != last:
|
||||||
print 'ERROR: did not get all frames, %d missing' % (self._frameEnd - last)
|
print 'ERROR: did not get all frames, %d missing' % (
|
||||||
|
self._frameEnd - last)
|
||||||
self.crc = self._crc
|
self.crc = self._crc
|
||||||
Task.stop(self)
|
Task.stop(self)
|
||||||
|
|
||||||
|
class CRC32Task(CRCTask):
|
||||||
|
"""
|
||||||
|
I do a simple CRC32 check.
|
||||||
|
"""
|
||||||
|
def do_crc_buffer(self, buffer, crc):
|
||||||
|
return zlib.crc32(buffer, crc)
|
||||||
|
|
||||||
|
class CRCAudioRipTask(CRCTask):
|
||||||
|
def do_crc_buffer(self, buffer, crc):
|
||||||
|
values = struct.unpack("<%dI" % (len(buffer) / 4), buffer)
|
||||||
|
for i, value in enumerate(values):
|
||||||
|
crc += (self._bytes / 4 + i + 1) * value
|
||||||
|
crc &= 0xFFFFFFFF
|
||||||
|
offset = self._bytes / 4 + i + 1
|
||||||
|
#if offset % 588 == 0:
|
||||||
|
# print 'THOMAS: frame %d, offset %d, value %d, CRC %d' % (
|
||||||
|
# offset / 588, offset, value, crc)
|
||||||
|
return crc
|
||||||
|
|
||||||
class SyncRunner:
|
class SyncRunner:
|
||||||
def __init__(self, task):
|
def __init__(self, task):
|
||||||
self._task = task
|
self._task = task
|
||||||
@@ -175,7 +216,11 @@ class SyncRunner:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def progress(self, value):
|
def progress(self, value):
|
||||||
pass
|
sys.stdout.write('Progress: %3d %%\r' % (value * 100.0))
|
||||||
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
if value >= 1.0:
|
||||||
|
print 'Progress: 100 %'
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
self._loop.quit()
|
self._loop.quit()
|
||||||
|
|||||||
Reference in New Issue
Block a user