summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@collabora.co.uk>2010-05-25 19:17:44 +0200
committerWim Taymans <wim.taymans@collabora.co.uk>2010-05-25 19:17:44 +0200
commit88c6896fb9db7d61429d6305314d549c818545da (patch)
tree82231857ea3da1a88e1be1149dcc5cf114326fef
parent4c37bae46392a8f7a9342525d98cce5b12d1ef6e (diff)
gstbin: unlock _get_state() on error
When an error message is received on the bus, mark the bin as being in the error state and unlock all current _get_state() calls with an error. Fixes #505770
-rw-r--r--gst/gstbin.c11
-rw-r--r--tests/check/gst/gstbin.c46
2 files changed, 57 insertions, 0 deletions
diff --git a/gst/gstbin.c b/gst/gstbin.c
index e1850c9e15..5a94c3a270 100644
--- a/gst/gstbin.c
+++ b/gst/gstbin.c
@@ -3002,6 +3002,17 @@ gst_bin_handle_message_func (GstBin * bin, GstMessage * message)
GST_MESSAGE_TYPE_NAME (message));
switch (type) {
+ case GST_MESSAGE_ERROR:
+ {
+ GST_OBJECT_LOCK (bin);
+ /* flag error */
+ GST_DEBUG_OBJECT (bin, "got ERROR message, unlocking state change");
+ GST_STATE_RETURN (bin) = GST_STATE_CHANGE_FAILURE;
+ GST_STATE_BROADCAST (bin);
+ GST_OBJECT_UNLOCK (bin);
+
+ goto forward;
+ }
case GST_MESSAGE_EOS:
{
gboolean eos;
diff --git a/tests/check/gst/gstbin.c b/tests/check/gst/gstbin.c
index badb0491a2..6b80d1db13 100644
--- a/tests/check/gst/gstbin.c
+++ b/tests/check/gst/gstbin.c
@@ -444,6 +444,51 @@ GST_START_TEST (test_watch_for_state_change)
GST_END_TEST;
+GST_START_TEST (test_state_change_error_message)
+{
+ GstElement *src, *sink, *bin;
+ GstBus *bus;
+ GstStateChangeReturn ret;
+
+ bin = gst_element_factory_make ("bin", NULL);
+ fail_unless (bin != NULL, "Could not create bin");
+
+ bus = g_object_new (gst_bus_get_type (), NULL);
+ gst_element_set_bus (GST_ELEMENT_CAST (bin), bus);
+
+ src = gst_element_factory_make ("fakesrc", NULL);
+ fail_if (src == NULL, "Could not create fakesrc");
+ sink = gst_element_factory_make ("fakesink", NULL);
+ fail_if (sink == NULL, "Could not create fakesink");
+
+ /* add but don't link elements */
+ gst_bin_add (GST_BIN (bin), sink);
+ gst_bin_add (GST_BIN (bin), src);
+
+ /* change state, this should succeed */
+ ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED);
+ fail_unless (ret == GST_STATE_CHANGE_ASYNC);
+
+ /* now wait, the streaming thread will error because the source is not
+ * linked. */
+ ret = gst_element_get_state (GST_ELEMENT (bin), NULL, NULL,
+ GST_CLOCK_TIME_NONE);
+ fail_unless (ret == GST_STATE_CHANGE_FAILURE);
+
+ gst_bus_set_flushing (bus, TRUE);
+
+ /* setting bin to NULL flushes the bus automatically */
+ ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL);
+ fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
+
+ /* clean up */
+ gst_object_unref (bus);
+ gst_object_unref (bin);
+}
+
+GST_END_TEST;
+
+
/* adding an element with linked pads to a bin unlinks the
* pads */
GST_START_TEST (test_add_linked)
@@ -1042,6 +1087,7 @@ gst_bin_suite (void)
tcase_add_test (tc_chain, test_message_state_changed_child);
tcase_add_test (tc_chain, test_message_state_changed_children);
tcase_add_test (tc_chain, test_watch_for_state_change);
+ tcase_add_test (tc_chain, test_state_change_error_message);
tcase_add_test (tc_chain, test_add_linked);
tcase_add_test (tc_chain, test_add_self);
tcase_add_test (tc_chain, test_iterate_sorted);