From 18631a0fb680e6f3946adf28b80de53aae40bf12 Mon Sep 17 00:00:00 2001 From: Thomas Vander Stichele Date: Thu, 26 Mar 2009 14:23:25 +0000 Subject: [PATCH] * examples/ARcue.py: * morituri/common/task.py: Use an adapter to assemble CD frames. Take into account special rules for first and last track. Mention some bugs. Remember to drag the lake from the task. --- ChangeLog | 9 +++++ examples/ARcue.py | 8 ++-- morituri/common/task.py | 83 +++++++++++++++++++++++++++++++++-------- 3 files changed, 82 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index b2109de..5aa94e9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2009-03-26 Thomas Vander Stichele + + * examples/ARcue.py: + * morituri/common/task.py: + Use an adapter to assemble CD frames. + Take into account special rules for first and last track. + Mention some bugs. + Remember to drag the lake from the task. + 2009-03-22 Thomas Vander Stichele * examples/ARcue.py: diff --git a/examples/ARcue.py b/examples/ARcue.py index 9a92caa..48e08da 100644 --- a/examples/ARcue.py +++ b/examples/ARcue.py @@ -33,7 +33,7 @@ def main(path): cuefile = cue.Cue(path) cuefile.parse() - for track in cuefile.tracks: + for trackIndex, track in enumerate(cuefile.tracks): index = track._indexes[1] length = cuefile.getTrackLength(track) file = index[1] @@ -48,8 +48,10 @@ def main(path): for ext in ['wav', 'flac']: path = '%s.%s' % (noext, ext) if os.path.exists(path): - crctask = task.CRCAudioRipTask(path, offset * 588, - length * 588) + print 'CRCing %s from CD frame %r for %r' % (path, offset, length) + crctask = task.CRCAudioRipTask(path, + trackNumber=trackIndex + 1, trackCount=len(cuefile.tracks), + frameStart=offset * 588, frameLength=length * 588) if not crctask: print 'error: path %s not found' % file.path diff --git a/morituri/common/task.py b/morituri/common/task.py index bd38272..fe6a9de 100644 --- a/morituri/common/task.py +++ b/morituri/common/task.py @@ -38,8 +38,8 @@ class Task(object): _listeners = None def debug(self, *args, **kwargs): - #print args, kwargs - #sys.stdout.flush() + print args, kwargs + sys.stdout.flush() pass def start(self): @@ -91,6 +91,8 @@ class CRCTask(Task): self._bytes = 0 self._first = None self._last = None + self._adapter = gst.Adapter() + self._lake = '' self.crc = None # result @@ -99,6 +101,7 @@ class CRCTask(Task): self._pipeline = gst.parse_launch(''' filesrc location="%s" ! decodebin ! audio/x-raw-int ! + queue ! appsink name=sink sync=False emit-signals=True''' % self._path) self.debug('pausing') self._pipeline.set_state(gst.STATE_PAUSED) @@ -109,11 +112,15 @@ class CRCTask(Task): sink = self._pipeline.get_by_name('sink') if self._frameLength < 0: - length, _ = sink.query_duration(gst.FORMAT_DEFAULT) + length, format = sink.query_duration(gst.FORMAT_DEFAULT) + # wavparse 0.10.14 returns in bytes + if format == gst.FORMAT_BYTES: + self.debug('query returned in BYTES format') + length /= 4 print 'total length', length self._frameLength = length - self._frameStart - self.debug('frame length is', self._frameLength) - print 'frame length is', self._frameLength + self.debug('audio frame length is', self._frameLength) + print 'audio frame length is', self._frameLength self._frameEnd = self._frameStart + self._frameLength - 1 self.debug('event') @@ -147,14 +154,33 @@ class CRCTask(Task): assert len(buffer) % 4 == 0, "buffer is not a multiple of 4 bytes" - # update progress - frame = self._first + self._bytes / 4 - framesDone = frame - self._frameStart - progress = float(framesDone) / float((self._frameLength)) - self.setProgress(progress) + # FIXME: gst-python 0.10.14.1 doesn't have adapter_peek/_take wrapped + # see http://bugzilla.gnome.org/show_bug.cgi?id=576505 + self._adapter.push(buffer) - self._crc = self.do_crc_buffer(buffer, self._crc) - self._bytes += len(buffer) + while self._adapter.available() >= 588 * 4: + # FIXME: in 0.10.14.1, take_buffer leaks a ref + buffer = self._adapter.take_buffer(588 * 4) + +# self._lake += str(buffer) +# i = 0 +# while len(self._lake) >= (i + 1) * 2532: +# block = self._lake[i * 2532:(i + 1) * 2532] + + # update progress + frame = self._first + self._bytes / 4 + framesDone = frame - self._frameStart + progress = float(framesDone) / float((self._frameLength)) + self.setProgress(progress) + + self._crc = self.do_crc_buffer(buffer, self._crc) + self._bytes += len(buffer) + print 'after crc', buffer.__grefcount__ + sys.stdout.flush() + del buffer +# i += 1 +# if i > 0: +# self._lake = self._lake[i * 2532:] def do_crc_buffer(self, buffer, crc): """ @@ -191,15 +217,42 @@ class CRC32Task(CRCTask): return zlib.crc32(buffer, crc) class CRCAudioRipTask(CRCTask): + def __init__(self, path, trackNumber, trackCount, frameStart=0, frameLength=-1): + CRCTask.__init__(self, path, frameStart, frameLength) + self._trackNumber = trackNumber + self._trackCount = trackCount + self._frameCounter = 0 + def do_crc_buffer(self, buffer, crc): + self._frameCounter += 1 + + # on first track ... + if self._trackNumber == 1: + # ... skip first 4 CD frames + if self._frameCounter <= 4: + self.debug('skipping frame %d' % self._frameCounter) + return crc + # ... on 5th frame, only use last value + elif self._frameCounter == 5: + values = struct.unpack("= self._frameLength + 6: + self.debug('skipping frame %d' % self._frameCounter) + return 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) + if offset % 588 == 0: + print 'THOMAS: frame %d, offset %d, value %d, CRC %d' % ( + offset / 588, offset, value, crc) return crc class SyncRunner: