[pitivi: 9/14] Refactor source factories a bit.



commit 2392a56e763f2a5e4dc6dc7e71c0400ab276b16a
Author: Alessandro Decina <alessandro d gmail com>
Date:   Fri Jun 19 19:39:31 2009 +0200

    Refactor source factories a bit.
    
    This change makes SourceFactory derived factories have an URI. This simplifies
    the code that deals with source factories, as it can assume factory.uri to be
    always there.
    It also removes ObjectFactory.displayname, changing it to ObjectFactory.name
    (ObjectFactory.name was previously either unused or used to store an URI...).
    I also removed some "Just In Case" code (try/except: and the like) from
    PictureFileSourceFactory._releaseBin.

 pitivi/device.py             |    6 +-
 pitivi/factories/base.py     |  243 +++++++++++++++++++-----------------------
 pitivi/factories/file.py     |   39 +++++---
 pitivi/factories/test.py     |   10 ++-
 pitivi/factories/timeline.py |    5 +-
 pitivi/sourcelist.py         |    3 +-
 tests/common.py              |   23 ++++-
 tests/test_factories_base.py |    5 +-
 tests/test_factories_file.py |   13 +--
 tests/test_timeline.py       |    9 +--
 tests/test_track.py          |   12 +--
 11 files changed, 185 insertions(+), 183 deletions(-)
---
diff --git a/pitivi/device.py b/pitivi/device.py
index 361aac0..5deb8f6 100644
--- a/pitivi/device.py
+++ b/pitivi/device.py
@@ -241,7 +241,8 @@ class AlsaSourceDeviceFactory(SourceDeviceFactory):
     """ObjectFactory for Alsa source devices"""
 
     def __init__(self, card, device, *args, **kwargs):
-        SourceDeviceFactory.__init__(self, *args, **kwargs)
+        # FIXME: create an URI handler for this
+        SourceDeviceFactory.__init__(self, "alsasrc://", *args, **kwargs)
         self.is_audio = True
         self._card = card
         self._device = device
@@ -279,7 +280,8 @@ class V4LSourceDeviceFactory(SourceDeviceFactory):
     """ObjectFactory for Video4Linux source devices"""
 
     def __init__(self, device, *args, **kwargs):
-        SourceDeviceFactory.__init__(self, *args, **kwargs)
+        # FIXME: create an URI handler for this
+        SourceDeviceFactory.__init__(self, "v4lsrc://", *args, **kwargs)
         self.is_video = True
         self._device = device
         self.__probed = False
diff --git a/pitivi/factories/base.py b/pitivi/factories/base.py
index c3f0649..614816c 100644
--- a/pitivi/factories/base.py
+++ b/pitivi/factories/base.py
@@ -205,8 +205,13 @@ class SourceFactory(ObjectFactory):
         'bin-released': ['bin']
     }
 
-    def __init__(self, name=''):
+    # make this an attribute to inject it from tests
+    singleDecodeBinClass = SingleDecodeBin
+
+    def __init__(self, uri, name=''):
+        name = name or os.path.basename(unquote(uri))
         ObjectFactory.__init__(self, name)
+        self.uri = uri
         self.max_bins = -1
         self.current_bins = 0
 
@@ -239,16 +244,12 @@ class SourceFactory(ObjectFactory):
 
         bin = self._makeBin(compatible_stream)
         bin.factory = self
-        if not bin in self.bins:
-            self.bins.append(bin)
+        self.bins.append(bin)
         self.current_bins += 1
         self.emit('bin-created', bin)
 
         return bin
 
-    def _makeBin(self, output_stream=None):
-        raise NotImplementedError()
-
     def releaseBin(self, bin):
         """
         Release a bin created with L{makeBin}.
@@ -260,14 +261,107 @@ class SourceFactory(ObjectFactory):
         self._releaseBin(bin)
         self.debug("Finally releasing %r", bin)
         self.current_bins -= 1
-        if bin in self.bins:
-            self.bins.remove(bin)
+        self.bins.remove(bin)
         self.emit('bin-released', bin)
         del bin.factory
 
+    def _makeBin(self, output_stream):
+        if output_stream is None:
+            return self._makeDefaultBin()
+
+        return self._makeStreamBin(output_stream)
+
+    def _makeDefaultBin(self):
+        """
+        Return a bin that decodes all the available streams.
+
+        This is generally used to get an overview of the source media before
+        splitting it in separate streams.
+        """
+        bin = gst.Bin("%s" % self.name)
+        src = gst.element_make_from_uri(gst.URI_SRC, self.uri)
+        try:
+            dbin = gst.element_factory_make("decodebin2")
+        except:
+            dbin = gst.element_factory_make("decodebin")
+        bin.add(src, dbin)
+        src.link(dbin)
+
+        dbin.connect("new-decoded-pad", self._binNewDecodedPadCb, bin)
+        dbin.connect("removed-decoded-pad", self._binRemovedDecodedPadCb, bin)
+
+        bin.decodebin = dbin
+        return bin
+
+    def _binNewDecodedPadCb(self, unused_dbin, pad, unused_is_last, bin):
+        ghost_pad = gst.GhostPad(pad.get_name(), pad)
+        ghost_pad.set_active(True)
+        bin.add_pad(ghost_pad)
+
+    def _binRemovedDecodedPadCb(self, unused_dbin, pad, bin):
+        ghost_pad = bin.get_pad(pad.get_name())
+        bin.remove_pad(ghost_pad)
+
     def _releaseBin(self, bin):
-        # default implementation does nothing
-        pass
+        try:
+            # bin is a bin returned from makeDefaultBin
+            bin.decodebin.disconnect_by_func(self._binNewDecodedPadCb)
+            bin.decodebin.disconnect_by_func(self._binRemovedDecodedPadCb)
+        except TypeError:
+            # bin is a stream bin
+            bin.decodebin.disconnect_by_func(self._singlePadAddedCb)
+            bin.decodebin.disconnect_by_func(self._singlePadRemovedCb)
+
+        del bin.decodebin
+
+        if hasattr(bin, "volume"):
+            # only audio bins have a volume element
+            bin.volume.set_state(gst.STATE_NULL)
+            bin.remove(bin.volume)
+            del bin.volume
+
+        if hasattr(bin, "ghostpad"):
+            # singledecodebin found something on this pad
+            bin.ghostpad.set_active(False)
+            bin.remove_pad(bin.ghostpad)
+            del bin.ghostpad
+
+    def _makeStreamBin(self, output_stream):
+        self.debug("output_stream:%r", output_stream)
+        b = gst.Bin()
+        b.decodebin = self.singleDecodeBinClass(uri=self.uri, caps=output_stream.caps,
+                                           stream=output_stream)
+        b.decodebin.connect("pad-added", self._singlePadAddedCb, b)
+        b.decodebin.connect("pad-removed", self._singlePadRemovedCb, b)
+
+        if isinstance(output_stream, AudioStream):
+            self.debug("Adding volume element")
+            # add a volume element
+            b.volume = gst.element_factory_make("volume", "internal-volume")
+            b.add(b.volume)
+
+        b.add(b.decodebin)
+        return b
+
+    def _singlePadAddedCb(self, dbin, pad, topbin):
+        self.debug("dbin:%r, pad:%r, topbin:%r", dbin, pad, topbin)
+        if hasattr(topbin, "volume"):
+            pad.link(topbin.volume.get_pad("sink"))
+            topbin.ghostpad = gst.GhostPad("src", topbin.volume.get_pad("src"))
+        else:
+            topbin.ghostpad = gst.GhostPad("src", pad)
+        topbin.ghostpad.set_active(True)
+        topbin.add_pad(topbin.ghostpad)
+
+    def _singlePadRemovedCb(self, dbin, pad, topbin):
+        self.debug("dbin:%r, pad:%r, topbin:%r", dbin, pad, topbin)
+        topbin.remove_pad(topbin.ghostpad)
+        del topbin.ghostpad
+        if hasattr(topbin, "volume"):
+            pad.unlink(topbin.volume.get_pad("sink"))
+            topbin.volume.set_state(gst.STATE_NULL)
+            topbin.remove(topbin.volume)
+            del topbin.volume
 
     def addInputStream(self, stream):
         raise AssertionError("source factories can't have input streams")
@@ -323,8 +417,7 @@ class SinkFactory(ObjectFactory):
 
         bin = self._makeBin(input_stream)
         bin.factory = self
-        if not bin in self.bins:
-            self.bins.append(bin)
+        self.bins.append(bin)
         self.current_bins += 1
         self.emit('bin-created', bin)
 
@@ -363,8 +456,7 @@ class SinkFactory(ObjectFactory):
         """
         bin.set_state(gst.STATE_NULL)
         self._releaseBin(bin)
-        if bin in self.bins:
-            self.bins.remove(bin)
+        self.bins.remove(bin)
         self.current_bins -= 1
         del bin.factory
         self.emit('bin-released', bin)
@@ -416,8 +508,7 @@ class OperationFactory(ObjectFactory):
 
         bin = self._makeBin(input_stream)
         bin.factory = self
-        if not bin in self.bins:
-            self.bins.append(bin)
+        self.bins.append(bin)
         self.current_bins += 1
         self.emit('bin-created', bin)
 
@@ -456,8 +547,7 @@ class OperationFactory(ObjectFactory):
         """
         bin.set_state(gst.STATE_NULL)
         self._releaseBin(bin)
-        if bin in self.bins:
-            self.bins.remove(bin)
+        self.bins.remove(bin)
         self.current_bins -= 1
         del bin.factory
         self.emit('bin-released', bin)
@@ -476,8 +566,8 @@ class LiveSourceFactory(SourceFactory):
     timeline.
     """
 
-    def __init__(self, name, default_duration=None):
-        SourceFactory.__init__(self, name)
+    def __init__(self, uri, name='', default_duration=None):
+        SourceFactory.__init__(self, uri, name)
         if default_duration is None:
             default_duration = 5 * gst.SECOND
 
@@ -498,12 +588,12 @@ class RandomAccessSourceFactory(SourceFactory):
     @type abs_offset_length: C{int}
     """
 
-    def __init__(self, name='',
+    def __init__(self, uri, name='',
             offset=0, offset_length=gst.CLOCK_TIME_NONE):
         self.offset = offset
         self.offset_length = offset_length
 
-        SourceFactory.__init__(self, name)
+        SourceFactory.__init__(self, uri, name)
 
     def _getAbsOffset(self):
         if self.parent is None:
@@ -531,112 +621,3 @@ class RandomAccessSourceFactory(SourceFactory):
         return offset_length
 
     abs_offset_length = property(_getAbsOffsetLength)
-
-class URISourceFactoryMixin(object):
-    """
-    Abstract mixin for sources that access an URI.
-    """
-
-    # make this an attribute to inject it from tests
-    singleDecodeBinClass = SingleDecodeBin
-
-    def __init__(self, uri):
-        self.uri = uri
-        self.name = os.path.basename(unquote(uri))
-
-    def _makeBin(self, output_stream):
-        if output_stream is None:
-            return self._makeDefaultBin()
-
-        return self._makeStreamBin(output_stream)
-
-    def _makeDefaultBin(self):
-        """
-        Return a bin that decodes all the available streams.
-
-        This is generally used to get an overview of the source media before
-        splitting it in separate streams.
-        """
-        bin = gst.Bin("%s" % self.name)
-        src = gst.element_make_from_uri(gst.URI_SRC, self.uri)
-        try:
-            dbin = gst.element_factory_make("decodebin2")
-        except:
-            dbin = gst.element_factory_make("decodebin")
-        bin.add(src, dbin)
-        src.link(dbin)
-
-        dbin.connect("new-decoded-pad", self._binNewDecodedPadCb, bin)
-        dbin.connect("removed-decoded-pad", self._binRemovedDecodedPadCb, bin)
-
-        bin.decodebin = dbin
-        return bin
-
-    def _binNewDecodedPadCb(self, unused_dbin, pad, unused_is_last, bin):
-        ghost_pad = gst.GhostPad(pad.get_name(), pad)
-        ghost_pad.set_active(True)
-        bin.add_pad(ghost_pad)
-
-    def _binRemovedDecodedPadCb(self, unused_dbin, pad, bin):
-        ghost_pad = bin.get_pad(pad.get_name())
-        bin.remove_pad(ghost_pad)
-
-    def _releaseBin(self, bin):
-        if hasattr(bin, "dbin"):
-            self.debug("has dbin")
-            bin.dbin.disconnect_by_func(self._singlePadAddedCb)
-            bin.dbin.disconnect_by_func(self._singlePadRemovedCb)
-            del bin.dbin
-        if hasattr(bin, "volume"):
-            bin.volume.set_state(gst.STATE_NULL)
-            bin.remove(bin.volume)
-            del bin.volume
-        if hasattr(bin, "ghostpad"):
-            del bin.ghostpad
-
-    def _makeStreamBin(self, output_stream):
-        self.debug("output_stream:%r", output_stream)
-        b = gst.Bin()
-        b.dbin = self.singleDecodeBinClass(uri=self.uri, caps=output_stream.caps,
-                                           stream=output_stream)
-        b.dbin.connect("pad-added", self._singlePadAddedCb, b)
-        b.dbin.connect("pad-removed", self._singlePadRemovedCb, b)
-
-        if isinstance(output_stream, AudioStream):
-            self.debug("Adding volume element")
-            # add a volume element
-            b.volume = gst.element_factory_make("volume", "internal-volume")
-            b.add(b.volume)
-
-        b.add(b.dbin)
-        return b
-
-    def _singlePadAddedCb(self, dbin, pad, topbin):
-        self.debug("dbin:%r, pad:%r, topbin:%r", dbin, pad, topbin)
-        if hasattr(topbin, "volume"):
-            pad.link(topbin.volume.get_pad("sink"))
-            topbin.ghostpad = gst.GhostPad("src", topbin.volume.get_pad("src"))
-        else:
-            topbin.ghostpad = gst.GhostPad("src", pad)
-        topbin.ghostpad.set_active(True)
-        topbin.add_pad(topbin.ghostpad)
-
-    def _singlePadRemovedCb(self, dbin, pad, topbin):
-        self.debug("dbin:%r, pad:%r, topbin:%r", dbin, pad, topbin)
-        topbin.remove_pad(topbin.ghostpad)
-        del topbin.ghostpad
-        if hasattr(topbin, "volume"):
-            pad.unlink(topbin.volume.get_pad("sink"))
-            topbin.volume.set_state(gst.STATE_NULL)
-            topbin.remove(topbin.volume)
-            del topbin.volume
-
-class LiveURISourceFactory(URISourceFactoryMixin, LiveSourceFactory):
-    """
-    Factory for live sources accessible at a given URI.
-
-    @see L{LiveSourceFactory}.
-    """
-    def __init__(self, uri, name='', default_duration=None):
-        URISourceFactoryMixin.__init__(self, uri)
-        LiveSourceFactory.__init__(self, name, default_duration)
diff --git a/pitivi/factories/file.py b/pitivi/factories/file.py
index 1f1db9e..4343452 100644
--- a/pitivi/factories/file.py
+++ b/pitivi/factories/file.py
@@ -4,7 +4,7 @@
 #       :base.py
 #
 # Copyright (c) 2005-2008, Edward Hervey <bilboed bilboed com>
-#               2008, Alessandro Decina <alessandro decina collabora co uk>
+#               2008,2009 Alessandro Decina <alessandro decina collabora co uk>
 #
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
@@ -25,22 +25,22 @@ import gst
 import os
 
 from pitivi.factories.base import RandomAccessSourceFactory, \
-        URISourceFactoryMixin, SinkFactory
+        SinkFactory
 from pitivi.elements.imagefreeze import ImageFreeze
 from pitivi.stream import MultimediaStream
 
-class FileSourceFactory(URISourceFactoryMixin, RandomAccessSourceFactory):
+class FileSourceFactory(RandomAccessSourceFactory):
     """
     Factory for local files.
 
     @see: L{RandomAccessSourceFactory}.
     """
 
-    def __init__(self, filename, name=''):
-        name = name or os.path.basename(filename)
-        self.filename = filename
-        URISourceFactoryMixin.__init__(self, filename)
-        RandomAccessSourceFactory.__init__(self, name)
+    def __init__(self, uri, name=''):
+        name = name or os.path.basename(uri)
+        RandomAccessSourceFactory.__init__(self, uri, name)
+        # FIXME: backward compatibility
+        self.filename = uri
 
 class PictureFileSourceFactory(FileSourceFactory):
     """
@@ -55,6 +55,17 @@ class PictureFileSourceFactory(FileSourceFactory):
     # make this overridable in tests
     ffscale_factory = 'ffvideoscale'
 
+    def _makeDefaultBin(self):
+        # we override this so we always return a bin having
+        # bin.decodebin = <bin as returned by FileSourceFactory>
+        # this makes our _releaseBin simpler
+        bin = gst.Bin()
+        dbin = FileSourceFactory._makeDefaultBin(self)
+        bin.add(dbin)
+        bin.decodebin = dbin
+
+        return bin
+
     def _makeStreamBin(self, output_stream):
         self.debug("making picture bin for %s", self.name)
         res = gst.Bin("picture-%s" % self.name)
@@ -100,12 +111,12 @@ class PictureFileSourceFactory(FileSourceFactory):
         pad.unlink(scale.get_pad("sink"))
 
     def _releaseBin(self, bin):
-        if hasattr(bin, "decodebin"):
-            try:
-                bin.decodebin.disconnect_by_func(self._dbinPadAddedCb)
-                bin.decodebin.disconnect_by_func(self._dbinPadRemovedCb)
-            except:
-                pass
+        try:
+            bin.decodebin.disconnect_by_func(self._dbinPadAddedCb)
+            bin.decodebin.disconnect_by_func(self._dbinPadRemovedCb)
+        except TypeError:
+            # bin is a bin returned from makeDefaultBin
+            pass
         FileSourceFactory._releaseBin(self, bin.decodebin)
 
 class URISinkFactory(SinkFactory):
diff --git a/pitivi/factories/test.py b/pitivi/factories/test.py
index 959d7cb..73bbd3f 100644
--- a/pitivi/factories/test.py
+++ b/pitivi/factories/test.py
@@ -27,7 +27,7 @@ from pitivi.stream import VideoStream, AudioStream
 
 class VideoTestSourceFactory(SourceFactory):
     def __init__(self, pattern=0):
-        SourceFactory.__init__(self)
+        SourceFactory.__init__(self, "videotestsrc://")
         self.pattern = pattern
 
         caps = gst.Caps('video/x-raw-yuv; video/x-raw-rgb')
@@ -53,9 +53,12 @@ class VideoTestSourceFactory(SourceFactory):
 
         return bin
 
+    def _releaseBin(self, bin):
+        pass
+
 class AudioTestSourceFactory(SourceFactory):
     def __init__(self, wave=0):
-        SourceFactory.__init__(self)
+        SourceFactory.__init__(self, "audiotestsrc://")
         self.wave = wave
 
         caps = gst.Caps('audio/x-raw-int; audio/x-raw-float')
@@ -81,3 +84,6 @@ class AudioTestSourceFactory(SourceFactory):
         bin.add_pad(ghost)
 
         return bin
+
+    def _releaseBin(self, bin):
+        pass
diff --git a/pitivi/factories/timeline.py b/pitivi/factories/timeline.py
index 18dc371..a2f2320 100644
--- a/pitivi/factories/timeline.py
+++ b/pitivi/factories/timeline.py
@@ -59,7 +59,7 @@ gobject.type_register(FixSeekStart)
 
 class TimelineSourceFactory(SourceFactory):
     def __init__(self, timeline):
-        SourceFactory.__init__(self, 'timeline')
+        SourceFactory.__init__(self, "timeline://", "timeline")
         self.bin = gst.Bin()
         self.max_bins = 1
         self.timeline = timeline
@@ -86,6 +86,9 @@ class TimelineSourceFactory(SourceFactory):
 
         return self.bin
 
+    def _releaseBin(self, bin):
+        pass
+
     def _connectTimeline(self):
         self.timeline.connect('track-added', self._timelineTrackAddedCb)
         self.timeline.connect('track-removed', self._timelineTrackRemovedCb)
diff --git a/pitivi/sourcelist.py b/pitivi/sourcelist.py
index 58918b8..37702b3 100644
--- a/pitivi/sourcelist.py
+++ b/pitivi/sourcelist.py
@@ -26,7 +26,6 @@ import urllib
 from pitivi.discoverer import Discoverer
 from pitivi.signalinterface import Signallable
 from pitivi.log.loggable import Loggable
-from pitivi.factories.base import URISourceFactoryMixin
 
 class SourceList(Signallable, Loggable):
     """
@@ -148,7 +147,7 @@ class SourceList(Signallable, Loggable):
         """
         Add an objectfactory for the given uri.
         """
-        if uri==None and isinstance(factory, URISourceFactoryMixin):
+        if uri==None:
             uri = factory.uri
         if uri in self and self[uri]:
             raise Exception("We already have an objectfactory for uri %s", uri)
diff --git a/tests/common.py b/tests/common.py
index 97542dd..a211ad2 100644
--- a/tests/common.py
+++ b/tests/common.py
@@ -55,11 +55,14 @@ class TestCase(unittest.TestCase):
 # Some fake factories
 class FakeSourceFactory(SourceFactory):
     def __init__(self, factoryname="fakesrc", *args, **kwargs):
-        SourceFactory.__init__(self, *args, **kwargs)
-        self.__factoryname=factoryname
+        SourceFactory.__init__(self, "fakesrc://", *args, **kwargs)
+        self._factoryname = factoryname
 
     def _makeBin(self, output_stream=None):
-        return gst.element_factory_make(self.__factoryname)
+        return gst.element_factory_make(self._factoryname)
+
+    def _releaseBin(self, bin):
+        pass
 
 class FakeSinkFactory(SinkFactory):
     def __init__(self, factoryname="fakesink", *args, **kwargs):
@@ -75,7 +78,7 @@ class FakeGnlFactory(SourceFactory):
                  *args, **kwargs):
         self.__duration = duration
         self.__media_duration = media_duration
-        SourceFactory.__init__(self, *args, **kwargs)
+        SourceFactory.__init__(self, "fakegnl://", *args, **kwargs)
 
     def _makeBin(self, output_stream=None):
         # let's make a gnlsource with videotestsrc inside of it
@@ -86,6 +89,8 @@ class FakeGnlFactory(SourceFactory):
         gnl.props.media_duration=self.__media_duration
         return gnl
 
+    def _releaseBin(self, bin):
+        pass
 
 class SignalMonitor(object):
     def __init__(self, obj, *signals):
@@ -118,3 +123,13 @@ class SignalMonitor(object):
         field = self._getSignalCollectName(name)
         setattr(self, field, getattr(self, field, []) + [args[:-1]])
 
+class StubFactory(SourceFactory):
+    def __init__(self):
+        SourceFactory.__init__(self, "stub://")
+        self.duration = 42 * gst.SECOND
+
+    def _makeBin(self, stream=None):
+        return gst.element_factory_make('fakesrc')
+
+    def _releaseBin(self, bin):
+        pass
diff --git a/tests/test_factories_base.py b/tests/test_factories_base.py
index 6a3a1b6..ebbfda1 100644
--- a/tests/test_factories_base.py
+++ b/tests/test_factories_base.py
@@ -73,6 +73,9 @@ class StubSourceFactory(SourceFactory):
     def _makeBin(self, output_stream=None):
         return gst.Bin()
 
+    def _releaseBin(self, bin):
+        pass
+
 class TestSourceFactory(TestCase):
     def setUp(self):
         TestCase.setUp(self)
@@ -122,7 +125,7 @@ class TestSourceFactory(TestCase):
 class TestLiveSourceFactory(TestCase):
     def testDefaultDuration(self):
         # pass an explicit default_duration
-        factory = LiveSourceFactory('name', 10 * gst.SECOND)
+        factory = LiveSourceFactory('live://', 'name', 10 * gst.SECOND)
         self.failUnlessEqual(factory.default_duration, 10 * gst.SECOND)
         
         # check that if a LiveSourceFactory derived class doesn't pass a
diff --git a/tests/test_factories_file.py b/tests/test_factories_file.py
index 3393fca..509bd6d 100644
--- a/tests/test_factories_file.py
+++ b/tests/test_factories_file.py
@@ -74,13 +74,12 @@ class TestFileSourceFactory(TestCase):
         audio = AudioStream(gst.Caps('audio/x-raw-int'), pad_name='src1')
         self.factory.addOutputStream(video)
         self.factory.addOutputStream(audio)
-
         bin = self.factory.makeBin(video)
-        self.failUnless(hasattr(bin, "dbin"))
-        self.failUnless(isinstance(bin.dbin, StubSingleDecodeBin))
-        self.failUnlessEqual(bin.dbin.uri, 'file:///path/to/file')
-        self.failUnlessEqual(video.caps, bin.dbin.caps)
-        self.failUnlessEqual(video, bin.dbin.stream)
+        self.failUnless(hasattr(bin, "decodebin"))
+        self.failUnless(isinstance(bin.decodebin, StubSingleDecodeBin))
+        self.failUnlessEqual(bin.decodebin.uri, 'file:///path/to/file')
+        self.failUnlessEqual(video.caps, bin.decodebin.caps)
+        self.failUnlessEqual(video, bin.decodebin.stream)
         self.factory.releaseBin(bin)
 
 class StubPictureFileSourceFactory(PictureFileSourceFactory):
@@ -104,7 +103,7 @@ class TestPictureFileSourceFactory(TestCase):
 
     def testDefaultMakeBin(self):
         # the default bin for FileSource is a bin containing decodebin
-        # TODO?: what we're testing here is that the method does return a bin and
+        # what we're testing here is that the method does return a bin and
         # doesn't rise exceptions. We're NOT changing the state of the bin.
         bin = self.factory.makeBin()
         self.failUnless(isinstance(bin, gst.Bin))
diff --git a/tests/test_timeline.py b/tests/test_timeline.py
index 2b7bbae..a7b890b 100644
--- a/tests/test_timeline.py
+++ b/tests/test_timeline.py
@@ -26,21 +26,14 @@ from pitivi.timeline.timeline import Timeline, TimelineObject, TimelineError, \
 from pitivi.timeline.track import Track, SourceTrackObject
 from pitivi.stream import AudioStream, VideoStream
 from pitivi.utils import UNKNOWN_DURATION
-from pitivi.factories.base import SourceFactory
 
-from common import SignalMonitor, TestCase
+from common import SignalMonitor, TestCase, StubFactory
 
 class TimelineSignalMonitor(SignalMonitor):
     def __init__(self, track_object):
         SignalMonitor.__init__(self, track_object, 'start-changed',
                 'duration-changed', 'in-point-changed', 'media-duration-changed')
 
-class StubFactory(SourceFactory):
-    duration = 42 * gst.SECOND
-
-    def _makeBin(self, stream=None):
-        return gst.element_factory_make('fakesrc')
-
 class TestTimelineObjectAddRemoveTrackObjects(TestCase):
     def testAddRemoveTrackObjects(self):
         factory = StubFactory()
diff --git a/tests/test_track.py b/tests/test_track.py
index 6e258a3..14fb659 100644
--- a/tests/test_track.py
+++ b/tests/test_track.py
@@ -23,18 +23,8 @@ from common import TestCase
 import gst
 
 from pitivi.timeline.track import Track, SourceTrackObject, TrackError
-from pitivi.factories.base import SourceFactory
 from pitivi.stream import AudioStream, VideoStream
-from pitivi.utils import UNKNOWN_DURATION
-from common import SignalMonitor
-
-class StubFactory(SourceFactory):
-    def __init__(self, *args, **kwargs):
-        SourceFactory.__init__(self, *args, **kwargs)
-        self.duration = 42 * gst.SECOND
-
-    def _makeBin(self, stream=None):
-        return gst.element_factory_make('audiotestsrc')
+from common import SignalMonitor, StubFactory
 
 class TrackSignalMonitor(SignalMonitor):
     def __init__(self, track_object):



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]