From ba10b573a218b01c3e3cd704fbf1af75c9fc7037 Mon Sep 17 00:00:00 2001 From: chrysn Date: Mon, 7 Nov 2016 14:57:17 +0100 Subject: [PATCH] Use soxi instead of gstreamer to determine a track's length Contributes-To: https://github.com/JoeLametta/whipper/issues/29 --- morituri/image/image.py | 55 +++------------------------------------- morituri/program/soxi.py | 47 ++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 52 deletions(-) create mode 100644 morituri/program/soxi.py diff --git a/morituri/image/image.py b/morituri/image/image.py index 97a3dc0..dc3cafe 100644 --- a/morituri/image/image.py +++ b/morituri/image/image.py @@ -29,7 +29,9 @@ import os from morituri.common import log, common from morituri.image import cue, table -from morituri.extern.task import task, gstreamer +from morituri.extern.task import task + +from morituri.program.soxi import AudioLengthTask class Image(object, log.Loggable): @@ -146,57 +148,6 @@ class AccurateRipChecksumTask(log.Loggable, task.MultiSeparateTask): task.MultiSeparateTask.stop(self) -class AudioLengthTask(log.Loggable, gstreamer.GstPipelineTask): - """ - I calculate the length of a track in audio samples. - - @ivar length: length of the decoded audio file, in audio samples. - """ - logCategory = 'AudioLengthTask' - description = 'Getting length of audio track' - length = None - - playing = False - - def __init__(self, path): - """ - @type path: unicode - """ - assert type(path) is unicode, "%r is not unicode" % path - - self._path = path - self.logName = os.path.basename(path).encode('utf-8') - - def getPipelineDesc(self): - return ''' - filesrc location="%s" ! - decodebin ! audio/x-raw-int ! - fakesink name=sink''' % \ - gstreamer.quoteParse(self._path).encode('utf-8') - - def paused(self): - self.debug('query duration') - sink = self.pipeline.get_by_name('sink') - assert sink, 'Error constructing pipeline' - - try: - length, qformat = sink.query_duration(self.gst.FORMAT_DEFAULT) - except self.gst.QueryError, e: - self.info('failed to query duration of %r' % self._path) - self.setException(e) - raise - - # wavparse 0.10.14 returns in bytes - if qformat == self.gst.FORMAT_BYTES: - self.debug('query returned in BYTES format') - length /= 4 - self.debug('total length of %r in samples: %d', self._path, length) - self.length = length - - self.pipeline.set_state(self.gst.STATE_NULL) - self.stop() - - class ImageVerifyTask(log.Loggable, task.MultiSeparateTask): """ I verify a disk image and get the necessary track lengths. diff --git a/morituri/program/soxi.py b/morituri/program/soxi.py new file mode 100644 index 0000000..42fbc8e --- /dev/null +++ b/morituri/program/soxi.py @@ -0,0 +1,47 @@ +import os + +from morituri.common import log, common +from morituri.common import task as ctask + +SOXI = 'soxi' + +class AudioLengthTask(ctask.PopenTask, log.Loggable): + """ + I calculate the length of a track in audio samples. + + @ivar length: length of the decoded audio file, in audio samples. + """ + logCategory = 'AudioLengthTask' + description = 'Getting length of audio track' + length = None + + def __init__(self, path): + """ + @type path: unicode + """ + assert type(path) is unicode, "%r is not unicode" % path + + self._path = path + self.logName = os.path.basename(path).encode('utf-8') + + self.command = [SOXI, '-s', self._path] + + self._error = [] + self._output = [] + + def commandMissing(self): + raise common.MissingDependencyException('sox') + + def readbytesout(self, bytes): + self._output.append(bytes) + + def readbyteserr(self, bytes): + self._error.append(bytes) + + def failed(self): + self.setException(Exception("soxi failed: %s"%"".join(self._error))) + + def done(self): + if self._error: + self.warning("soxi reported on stderr: %s", "".join(self._error)) + self.length = int("".join(self._output))