* morituri/common/gstreamer.py:

Add a cvar to stop going to playing.
	* morituri/image/image.py:
	  Convert AudioLengthTask to GstPipelineTask.
	* morituri/test/test_image_image.py:
	  Adapt to new typefind error we run in.
This commit is contained in:
Thomas Vander Stichele
2011-05-24 10:27:06 +00:00
parent c5593a4070
commit 8771d439dc
4 changed files with 37 additions and 43 deletions

View File

@@ -1,3 +1,12 @@
2011-05-24 Thomas Vander Stichele <thomas at apestaart dot org>
* morituri/common/gstreamer.py:
Add a cvar to stop going to playing.
* morituri/image/image.py:
Convert AudioLengthTask to GstPipelineTask.
* morituri/test/test_image_image.py:
Adapt to new typefind error we run in.
2011-05-23 Thomas Vander Stichele <thomas at apestaart dot org>
* morituri/common/gstreamer.py:

View File

@@ -40,9 +40,13 @@ class GstPipelineTask(task.Task):
@cvar gst: the GStreamer module, so code does not have to import gst
as a module in code everywhere to avoid option stealing.
@var playing: whether the pipeline should be set to playing after
paused. Some pipelines don't need to play for a task
to be done (for example, querying length)
"""
gst = None
playing = True
### task.Task implementations
def start(self, runner):
@@ -100,8 +104,9 @@ class GstPipelineTask(task.Task):
self.debug('set pipeline to PLAYING')
return False
self.debug('scheduling setting pipeline to PLAYING')
self.runner.schedule(0, playLater)
if self.playing:
self.debug('scheduling setting pipeline to PLAYING')
self.runner.schedule(0, playLater)
def stop(self):
self.debug('stopping')

View File

@@ -26,7 +26,7 @@ Wrap on-disk CD images based on the .cue file.
import os
from morituri.common import task, log, common
from morituri.common import task, log, common, gstreamer
from morituri.image import cue, table
class Image(object, log.Loggable):
@@ -133,17 +133,19 @@ class AccurateRipChecksumTask(task.MultiSeparateTask):
self.checksums = [t.checksum for t in self.tasks]
task.MultiSeparateTask.stop(self)
class AudioLengthTask(task.Task):
class AudioLengthTask(gstreamer.GstPipelineTask):
"""
I calculate the length of a track in audio frames.
@ivar length: length of the decoded audio file, in audio frames.
"""
logCategory = 'AudioLengthTask'
description = 'Getting length of audio track'
length = None
playing = False
def __init__(self, path):
"""
@type path: unicode
@@ -152,55 +154,32 @@ class AudioLengthTask(task.Task):
self._path = path
def start(self, runner):
# here to avoid import gst eating our options
import gst
task.Task.start(self, runner)
self._pipeline = gst.parse_launch('''
def getPipelineDesc(self):
return '''
filesrc location="%s" !
decodebin ! audio/x-raw-int !
fakesink name=sink''' %
common.quoteParse(self._path).encode('utf-8'))
self._bus = self._pipeline.get_bus()
self._bus.add_signal_watch()
self._bus.connect('message::error', self._error_cb)
self.debug('pausing')
self._pipeline.set_state(gst.STATE_PAUSED)
self.debug('waiting for ASYNC_DONE or ERROR')
message = self._bus.timed_pop_filtered(gst.CLOCK_TIME_NONE,
gst.MESSAGE_ASYNC_DONE | gst.MESSAGE_ERROR)
if message.type == gst.MESSAGE_ERROR:
self._error_cb(self._bus, message)
self._pipeline.set_state(gst.STATE_NULL)
return
fakesink name=sink''' % \
common.quoteParse(self._path).encode('utf-8')
def paused(self):
self.debug('query duration')
sink = self._pipeline.get_by_name('sink')
sink = self.pipeline.get_by_name('sink')
assert sink, 'Error constructing pipeline'
try:
length, qformat = sink.query_duration(gst.FORMAT_DEFAULT)
except gst.QueryError:
length, qformat = sink.query_duration(self.gst.FORMAT_DEFAULT)
except self.gst.QueryError:
self.info('failed to query duration of %r' % self._path)
raise
# wavparse 0.10.14 returns in bytes
if qformat == gst.FORMAT_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(gst.STATE_NULL)
self.stop()
def _error_cb(self, bus, msg):
error, debug = msg.parse_error()
self.debug('Got GStreamer error: %r, debug: %r' % (
error.message, debug))
self.setAndRaiseException(error)
self.pipeline.set_state(self.gst.STATE_NULL)
self.stop()
class ImageVerifyTask(task.MultiSeparateTask):

View File

@@ -10,7 +10,7 @@ gobject.threads_init()
import gst
from morituri.image import image
from morituri.common import task, common, log
from morituri.common import task, common, log, gstreamer
from morituri.test import common as tcommon
log.init()
@@ -93,11 +93,12 @@ class AudioLengthPathTestCase(tcommon.TestCase):
t = image.AudioLengthTask(path)
e = self.assertRaises(task.TaskException, self.runner.run,
t, verbose=False)
self.failUnless(isinstance(e.exception, gst.GError),
"%r is not a gst.GError" % e.exceptionMessage)
self.assertEquals(e.exception.domain, gst.STREAM_ERROR)
self.failUnless(isinstance(e.exception, gstreamer.GstException),
"%r is not a gstreamer.GstException" % e.exceptionMessage)
self.assertEquals(e.exception.gerror.domain, gst.STREAM_ERROR)
# our empty file triggers TYPE_NOT_FOUND
self.assertEquals(e.exception.code, gst.STREAM_ERROR_TYPE_NOT_FOUND)
self.assertEquals(e.exception.gerror.code,
gst.STREAM_ERROR_TYPE_NOT_FOUND)
os.unlink(path)
class NormalAudioLengthPathTestCase(AudioLengthPathTestCase):