element: Add GstElement::state_changed vfunc
authorSebastian Dröge <sebastian.droege@collabora.co.uk>
Tue, 10 May 2011 14:37:44 +0000 (16:37 +0200)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Sat, 14 May 2011 09:39:35 +0000 (11:39 +0200)
API: GstElement::state_changed

This is always called when the state of an element has changed and
before the corresponding state-changed message is posted on the bus.

gst/gst_private.h
gst/gstbin.c
gst/gstelement.c
gst/gstelement.h

index 2cafbee..a8f780c 100644 (file)
@@ -51,6 +51,9 @@ extern const char             g_log_domain_gstreamer[];
 /* for the pad cache */
 #include "gstpad.h"
 
+/* for GstElement */
+#include "gstelement.h"
+
 G_BEGIN_DECLS
 
 /* used by gstparse.c and grammar.y */
@@ -113,6 +116,10 @@ gboolean _gst_plugin_loader_client_run (void);
 
 void _priv_gst_pad_invalidate_cache (GstPad *pad);
 
+/* Used in GstBin for manual state handling */
+void _priv_gst_element_state_changed (GstElement *element, GstState oldstate,
+    GstState newstate, GstState pending);
+
 /* used in both gststructure.c and gstcaps.c; numbers are completely made up */
 #define STRUCTURE_ESTIMATED_STRING_LEN(s) (16 + (s)->fields->len * 22)
 
index 52777df..e0a8d4c 100644 (file)
@@ -2828,9 +2828,8 @@ bin_handle_async_start (GstBin * bin, gboolean new_base_time)
   GST_OBJECT_UNLOCK (bin);
 
   /* post message */
-  gst_element_post_message (GST_ELEMENT_CAST (bin),
-      gst_message_new_state_changed (GST_OBJECT_CAST (bin),
-          new_state, new_state, new_state));
+  _priv_gst_element_state_changed (GST_ELEMENT_CAST (bin), new_state, new_state,
+      new_state);
 
 post_start:
   if (amessage) {
@@ -2872,8 +2871,8 @@ bin_handle_async_done (GstBin * bin, GstStateChangeReturn ret,
   GstState current, pending, target;
   GstStateChangeReturn old_ret;
   GstState old_state, old_next;
-  gboolean toplevel;
-  GstMessage *smessage = NULL, *amessage = NULL;
+  gboolean toplevel, state_changed = FALSE;
+  GstMessage *amessage = NULL;
   BinContinueData *cont = NULL;
 
   if (GST_STATE_RETURN (bin) == GST_STATE_CHANGE_FAILURE)
@@ -2952,15 +2951,14 @@ bin_handle_async_done (GstBin * bin, GstStateChangeReturn ret,
 
   if (old_next != GST_STATE_PLAYING) {
     if (old_state != old_next || old_ret == GST_STATE_CHANGE_ASYNC) {
-      smessage = gst_message_new_state_changed (GST_OBJECT_CAST (bin),
-          old_state, old_next, pending);
+      state_changed = TRUE;
     }
   }
   GST_OBJECT_UNLOCK (bin);
 
-  if (smessage) {
-    GST_DEBUG_OBJECT (bin, "posting state change message");
-    gst_element_post_message (GST_ELEMENT_CAST (bin), smessage);
+  if (state_changed) {
+    _priv_gst_element_state_changed (GST_ELEMENT_CAST (bin), old_state,
+        old_next, pending);
   }
   if (amessage) {
     /* post our combined ASYNC_DONE when all is ASYNC_DONE. */
index c2a8eb3..ddbba3e 100644 (file)
@@ -2317,6 +2317,28 @@ nothing_aborted:
   }
 }
 
+/* Not static because GstBin has manual state handling too */
+void
+_priv_gst_element_state_changed (GstElement * element, GstState oldstate,
+    GstState newstate, GstState pending)
+{
+  GstElementClass *klass = GST_ELEMENT_GET_CLASS (element);
+  GstMessage *message;
+
+  GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
+      "notifying about state-changed %s to %s (%s pending)",
+      gst_element_state_get_name (oldstate),
+      gst_element_state_get_name (newstate),
+      gst_element_state_get_name (pending));
+
+  if (klass->state_changed)
+    klass->state_changed (element, oldstate, newstate, pending);
+
+  message = gst_message_new_state_changed (GST_OBJECT_CAST (element),
+      oldstate, newstate, pending);
+  gst_element_post_message (element, message);
+}
+
 /**
  * gst_element_continue_state:
  * @element: a #GstElement to continue the state change of.
@@ -2344,7 +2366,6 @@ gst_element_continue_state (GstElement * element, GstStateChangeReturn ret)
   GstStateChangeReturn old_ret;
   GstState old_state, old_next;
   GstState current, next, pending;
-  GstMessage *message;
   GstStateChange transition;
 
   GST_OBJECT_LOCK (element);
@@ -2380,9 +2401,7 @@ gst_element_continue_state (GstElement * element, GstStateChangeReturn ret)
       gst_element_state_get_name (old_next),
       gst_element_state_get_name (pending), gst_element_state_get_name (next));
 
-  message = gst_message_new_state_changed (GST_OBJECT_CAST (element),
-      old_state, old_next, pending);
-  gst_element_post_message (element, message);
+  _priv_gst_element_state_changed (element, old_state, old_next, pending);
 
   GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
       "continue state change %s to %s, final %s",
@@ -2414,16 +2433,9 @@ complete:
      * previous return value.
      * We do signal the cond though as a _get_state() might be blocking
      * on it. */
-    if (old_state != old_next || old_ret == GST_STATE_CHANGE_ASYNC) {
-      GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
-          "posting state-changed %s to %s",
-          gst_element_state_get_name (old_state),
-          gst_element_state_get_name (old_next));
-      message =
-          gst_message_new_state_changed (GST_OBJECT_CAST (element), old_state,
-          old_next, GST_STATE_VOID_PENDING);
-      gst_element_post_message (element, message);
-    }
+    if (old_state != old_next || old_ret == GST_STATE_CHANGE_ASYNC)
+      _priv_gst_element_state_changed (element, old_state, old_next,
+          GST_STATE_VOID_PENDING);
 
     GST_STATE_BROADCAST (element);
 
@@ -2496,9 +2508,7 @@ gst_element_lost_state_full (GstElement * element, gboolean new_base_time)
     GST_ELEMENT_START_TIME (element) = 0;
   GST_OBJECT_UNLOCK (element);
 
-  message = gst_message_new_state_changed (GST_OBJECT_CAST (element),
-      new_state, new_state, new_state);
-  gst_element_post_message (element, message);
+  _priv_gst_element_state_changed (element, new_state, new_state, new_state);
 
   message =
       gst_message_new_async_start (GST_OBJECT_CAST (element), new_base_time);
index 74f05dd..f1195e0 100644 (file)
@@ -602,6 +602,7 @@ struct _GstElement
  * @get_query_types: get the supported #GstQueryType of this element
  * @query: perform a #GstQuery on the element
  * @request_new_pad_full: called when a new pad is requested. Since: 0.10.32.
+ * @state_changed: called immediately after a new state was set. Since: 0.10.34.
  *
  * GStreamer element class. Override the vmethods to implement the element
  * functionality.
@@ -669,8 +670,11 @@ struct _GstElementClass
   GstPad*              (*request_new_pad_full) (GstElement *element, GstPadTemplate *templ,
                                                 const gchar* name, const GstCaps *caps);
 
+  void                  (*state_changed)        (GstElement *element, GstState oldstate,
+                                                 GstState newstate, GstState pending);
+
   /*< private >*/
-  gpointer _gst_reserved[GST_PADDING-2];
+  gpointer _gst_reserved[GST_PADDING-3];
 };
 
 /* element class pad templates */