summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@collabora.co.uk>2010-09-16 19:06:35 +0200
committerWim Taymans <wim.taymans@collabora.co.uk>2010-09-16 19:17:53 +0200
commita9a82da134a84ad181935134fd67e16c74660e29 (patch)
tree180a004d920a2020488c33ee1cb19c805a8d115f
parent30fe3b2be98c1edf876f04ba9ab3da7310fdd8fc (diff)
bin: add message-forward option
Add an option to forward all the internal messages that would otherwise be filtered such as EOS, SEGMENT and ASYNC messages. This allows the application to, for example, detect that a partial pipeline is prerolled or reached eos. The original messages are wrapped inside an element message because the parent bins are not supposed to see those internal messages escape.
-rw-r--r--gst/gstbin.c76
1 files changed, 70 insertions, 6 deletions
diff --git a/gst/gstbin.c b/gst/gstbin.c
index b825d4ce24..735b76f68c 100644
--- a/gst/gstbin.c
+++ b/gst/gstbin.c
@@ -218,6 +218,8 @@ struct _GstBinPrivate
/* cached index */
GstIndex *index;
+ /* forward messages from our children */
+ gboolean message_forward;
};
typedef struct
@@ -283,12 +285,14 @@ enum
};
#define DEFAULT_ASYNC_HANDLING FALSE
+#define DEFAULT_MESSAGE_FORWARD FALSE
enum
{
PROP_0,
- PROP_ASYNC_HANDLING
- /* FILL ME */
+ PROP_ASYNC_HANDLING,
+ PROP_MESSAGE_FORWARD,
+ PROP_LAST
};
static void gst_bin_child_proxy_init (gpointer g_iface, gpointer iface_data);
@@ -466,6 +470,25 @@ gst_bin_class_init (GstBinClass * klass)
_gst_boolean_accumulator, NULL, gst_marshal_BOOLEAN__VOID,
G_TYPE_BOOLEAN, 0, G_TYPE_NONE);
+ /**
+ * GstBin:message-forward
+ *
+ * Forward all children messages, even those that would normally be filtered by
+ * the bin. This can be interesting when one wants to be notified of the EOS
+ * state of individual elements, for example.
+ *
+ * The messages are converted to an APPLICATION message with the bin as the
+ * source. The structure of the message is named 'GstBinForwarded' and contains
+ * a field named 'message' of type GST_TYPE_MESSAGE that contains the original
+ * forwarded message.
+ *
+ * Since: 0.10.31
+ */
+ g_object_class_install_property (gobject_class, PROP_MESSAGE_FORWARD,
+ g_param_spec_boolean ("message-forward", "Message Forward",
+ "Forwards all children messages",
+ DEFAULT_MESSAGE_FORWARD, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
gobject_class->dispose = gst_bin_dispose;
#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
@@ -526,6 +549,7 @@ gst_bin_init (GstBin * bin, GstBinClass * klass)
bin->priv = GST_BIN_GET_PRIVATE (bin);
bin->priv->asynchandling = DEFAULT_ASYNC_HANDLING;
bin->priv->structure_cookie = 0;
+ bin->priv->message_forward = DEFAULT_MESSAGE_FORWARD;
}
static void
@@ -586,6 +610,11 @@ gst_bin_set_property (GObject * object, guint prop_id,
gstbin->priv->asynchandling = g_value_get_boolean (value);
GST_OBJECT_UNLOCK (gstbin);
break;
+ case PROP_MESSAGE_FORWARD:
+ GST_OBJECT_LOCK (gstbin);
+ gstbin->priv->message_forward = g_value_get_boolean (value);
+ GST_OBJECT_UNLOCK (gstbin);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -606,6 +635,11 @@ gst_bin_get_property (GObject * object, guint prop_id,
g_value_set_boolean (value, gstbin->priv->asynchandling);
GST_OBJECT_UNLOCK (gstbin);
break;
+ case PROP_MESSAGE_FORWARD:
+ GST_OBJECT_LOCK (gstbin);
+ g_value_set_boolean (value, gstbin->priv->message_forward);
+ GST_OBJECT_UNLOCK (gstbin);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -2948,6 +2982,31 @@ nothing_pending:
}
}
+/* must be called with the object lock. This function releases the lock to post
+ * the message. */
+static void
+bin_do_message_forward (GstBin * bin, GstMessage * message)
+{
+ if (bin->priv->message_forward) {
+ GstMessage *forwarded;
+
+ GST_DEBUG_OBJECT (bin, "pass %s message upward",
+ GST_MESSAGE_TYPE_NAME (message));
+ GST_OBJECT_UNLOCK (bin);
+
+ /* we need to convert these messages to element messages so that our parent
+ * bin can easily ignore them and so that the application can easily
+ * distinguish between the internally forwarded and the real messages. */
+ forwarded = gst_message_new_element (GST_OBJECT_CAST (bin),
+ gst_structure_new ("GstBinForwarded",
+ "message", GST_TYPE_MESSAGE, message, NULL));
+
+ gst_element_post_message (GST_ELEMENT_CAST (bin), forwarded);
+
+ GST_OBJECT_LOCK (bin);
+ }
+}
+
/* handle child messages:
*
* This method is called synchronously when a child posts a message on
@@ -3035,6 +3094,7 @@ gst_bin_handle_message_func (GstBin * bin, GstMessage * message)
/* collect all eos messages from the children */
GST_OBJECT_LOCK (bin);
+ bin_do_message_forward (bin, message);
/* ref message for future use */
gst_message_ref (message);
bin_replace_message (bin, message, GST_MESSAGE_EOS);
@@ -3071,6 +3131,7 @@ gst_bin_handle_message_func (GstBin * bin, GstMessage * message)
seqnum = gst_message_get_seqnum (message);
GST_OBJECT_LOCK (bin);
+ bin_do_message_forward (bin, message);
/* if this is the first segment-start, post to parent but not to the
* application */
if (!find_message (bin, NULL, GST_MESSAGE_SEGMENT_START) &&
@@ -3103,6 +3164,7 @@ gst_bin_handle_message_func (GstBin * bin, GstMessage * message)
seqnum = gst_message_get_seqnum (message);
GST_OBJECT_LOCK (bin);
+ bin_do_message_forward (bin, message);
bin_replace_message (bin, message, GST_MESSAGE_SEGMENT_START);
/* if there are no more segment_start messages, everybody posted
* a segment_done and we can post one on the bus. */
@@ -3201,9 +3263,10 @@ gst_bin_handle_message_func (GstBin * bin, GstMessage * message)
gst_message_parse_async_start (message, &new_base_time);
GST_OBJECT_LOCK (bin);
+ bin_do_message_forward (bin, message);
+
/* we ignore the message if we are going to <= READY */
- target = GST_STATE_TARGET (bin);
- if (target <= GST_STATE_READY)
+ if ((target = GST_STATE_TARGET (bin)) <= GST_STATE_READY)
goto ignore_start_message;
/* takes ownership of the message */
@@ -3230,9 +3293,10 @@ gst_bin_handle_message_func (GstBin * bin, GstMessage * message)
src ? GST_OBJECT_NAME (src) : "(NULL)");
GST_OBJECT_LOCK (bin);
- target = GST_STATE_TARGET (bin);
+ bin_do_message_forward (bin, message);
+
/* ignore messages if we are shutting down */
- if (target <= GST_STATE_READY)
+ if ((target = GST_STATE_TARGET (bin)) <= GST_STATE_READY)
goto ignore_done_message;
bin_replace_message (bin, message, GST_MESSAGE_ASYNC_START);