From 3872b816d245831ec2764915d17299c20e0b3ab2 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Sebastian=20Dr=C3=B6ge?= Date: Tue, 10 May 2011 16:37:44 +0200 Subject: [PATCH] element: Add GstElement::state_changed vfunc 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 | 7 +++++++ gst/gstbin.c | 18 ++++++++---------- gst/gstelement.c | 44 +++++++++++++++++++++++++++----------------- gst/gstelement.h | 6 +++++- 4 files changed, 47 insertions(+), 28 deletions(-) diff --git a/gst/gst_private.h b/gst/gst_private.h index 2cafbee..a8f780c 100644 --- a/gst/gst_private.h +++ b/gst/gst_private.h @@ -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) diff --git a/gst/gstbin.c b/gst/gstbin.c index 52777df..e0a8d4c 100644 --- a/gst/gstbin.c +++ b/gst/gstbin.c @@ -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. */ diff --git a/gst/gstelement.c b/gst/gstelement.c index c2a8eb3..ddbba3e 100644 --- a/gst/gstelement.c +++ b/gst/gstelement.c @@ -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); diff --git a/gst/gstelement.h b/gst/gstelement.h index 74f05dd..f1195e0 100644 --- a/gst/gstelement.h +++ b/gst/gstelement.h @@ -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 */ -- 2.7.4