[pitivi/ges] pipeline: Do not use an sync bus handler for element messages



commit bfe3b8aaa4afc5827b11c9b7aa50fb4fd9d5b0b7
Author: Thibault Saunier <thibault saunier collabora com>
Date:   Tue May 15 21:26:26 2012 -0400

    pipeline: Do not use an sync bus handler for element messages
    
    Just emit an xid-message and not message for any element message
    Do it synchonously the first time only

 pitivi/utils/pipeline.py |   29 +++++++++++++++++++----------
 pitivi/utils/timeline.py |    1 -
 pitivi/viewer.py         |   15 +++++----------
 3 files changed, 24 insertions(+), 21 deletions(-)
---
diff --git a/pitivi/utils/pipeline.py b/pitivi/utils/pipeline.py
index b185dec..9ed354b 100644
--- a/pitivi/utils/pipeline.py
+++ b/pitivi/utils/pipeline.py
@@ -152,7 +152,7 @@ class SimplePipeline(Loggable, Signallable):
         "duration-changed": ["duration"],
         "eos": [],
         "error": ["message", "details"],
-        "element-message": ["message"]}
+        "xid-message": ["message"]}
 
     def __init__(self, pipeline):
         Loggable.__init__(self)
@@ -161,7 +161,12 @@ class SimplePipeline(Loggable, Signallable):
         self._bus = self._pipeline.get_bus()
         self._bus.add_signal_watch()
         self._bus.connect("message", self._busMessageCb)
+        # Initially, we set a synchronous bus message handler so that the xid
+        # is known right away and we can set the viewer synchronously, avoiding
+        # the creation of an external window.
+        # Afterwards, the xid-message is handled async (to avoid deadlocks).
         self._bus.set_sync_handler(self._busSyncMessageHandler)
+        self._has_sync_bus_handler = True
         self._listening = False  # for the position handler
         self._listeningInterval = 300  # default 300ms
         self._listeningSigId = 0
@@ -180,7 +185,6 @@ class SimplePipeline(Loggable, Signallable):
         self.deactivatePositionListener()
         self._bus.disconnect_by_func(self._busMessageCb)
         self._bus.remove_signal_watch()
-        self._bus.set_sync_handler(None)
 
         self._pipeline.setState(gst.STATE_NULL)
         self._bus = None
@@ -417,6 +421,9 @@ class SimplePipeline(Loggable, Signallable):
             self.debug("Duration might have changed, querying it")
             gobject.idle_add(self._queryDurationAsync)
         else:
+            if self._has_sync_bus_handler is False:
+                # Pass message async to the sync bus handler
+                self._busSyncMessageHandler(unused_bus, message)
             self.info("%s [%r]" % (message.type, message.src))
 
     def _queryDurationAsync(self, *args, **kwargs):
@@ -432,18 +439,20 @@ class SimplePipeline(Loggable, Signallable):
 
     def _busSyncMessageHandler(self, unused_bus, message):
         if message.type == gst.MESSAGE_ELEMENT:
-            # handle element message synchronously
-            self.emit('element-message', message)
+            name = message.structure.get_name()
+            if name == 'prepare-xwindow-id':
+                # handle element message synchronously
+                self.emit('xid-message', message)
+                #Remove the bus sync handler avoiding deadlocks
+                self._bus.set_sync_handler(None)
+                self._has_sync_bus_handler = False
         return gst.BUS_PASS
 
 
 class Pipeline(ges.TimelinePipeline, SimplePipeline):
     """
-    The Pipeline is only responsible for:
-     - State changes
-     - Position seeking
-     - Position Querying
-       - Along with an periodic callback (optional)
+    Helper to handle ges.TimelinePipeline through the SimplePipeline API
+    and handle the Seeker properly
 
     Signals:
      - C{state-changed} : The state of the pipeline changed.
@@ -463,7 +472,7 @@ class Pipeline(ges.TimelinePipeline, SimplePipeline):
                         ()),
         "error": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
                         (gobject.TYPE_STRING, gobject.TYPE_STRING)),
-        "element-message": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
+        "xid-message": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
                         (gobject.TYPE_PYOBJECT,))}
 
     def __init__(self, pipeline=None):
diff --git a/pitivi/utils/timeline.py b/pitivi/utils/timeline.py
index 7a5075f..d889959 100644
--- a/pitivi/utils/timeline.py
+++ b/pitivi/utils/timeline.py
@@ -24,7 +24,6 @@ import ges
 import gtk
 import gst
 
-from pitivi.utils.misc import infinity
 from pitivi.utils.loggable import Loggable
 from pitivi.utils.signal import Signallable
 from pitivi.utils.receiver import receiver, handler
diff --git a/pitivi/viewer.py b/pitivi/viewer.py
index 64f66ae..3a4493a 100644
--- a/pitivi/viewer.py
+++ b/pitivi/viewer.py
@@ -133,7 +133,7 @@ class PitiviViewer(gtk.VBox, Loggable):
 
             self.pipeline.connect("state-changed", self._pipelineStateChangedCb)
             self.pipeline.connect("position", self._positionCb)
-            self.pipeline.connect("element-message", self._elementMessageCb)
+            self.pipeline.connect("xid-message", self.xidMessageCb)
             self.pipeline.connect("duration-changed", self._durationChangedCb)
 
         self._setUiActive()
@@ -145,7 +145,7 @@ class PitiviViewer(gtk.VBox, Loggable):
             return
 
         self.pipeline.disconnect_by_func(self._pipelineStateChangedCb)
-        self.pipeline.disconnect_by_func(self._elementMessageCb)
+        self.pipeline.disconnect_by_func(self.xidMessageCb)
         self.pipeline.disconnect_by_func(self._positionCb)
         self.pipeline.disconnect_by_func(self._durationChangedCb)
 
@@ -445,18 +445,13 @@ class PitiviViewer(gtk.VBox, Loggable):
             self.system.uninhibitScreensaver(self.INHIBIT_REASON)
         self.internal._currentStateCb(self.pipeline, state)
 
-    def _elementMessageCb(self, unused_pipeline, message):
+    def xidMessageCb(self, unused_pipeline, message):
         """
         When the pipeline sends us a message to prepare-xwindow-id,
         tell the viewer to switch its output window.
         """
-        if message.type == gst.MESSAGE_ELEMENT:
-            name = message.structure.get_name()
-            self.log('message:%s / %s', message, name)
-            if name == 'prepare-xwindow-id':
-                self.sink = message.src
-                self._switch_output_window()
-        return gst.BUS_PASS
+        self.sink = message.src
+        self._switch_output_window()
 
     def _switch_output_window(self):
         gtk.gdk.threads_enter()



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