-get_state_func (GstElement * element, gpointer unused)
-{
- GstStateChangeReturn ret = GST_STATE_CHANGE_ASYNC;
-
- GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
- "new thread waiting on state change");
-
- /* wait indefinitely */
- while (ret == GST_STATE_CHANGE_ASYNC)
- ret = gst_element_get_state (element, NULL, NULL, NULL);
-
- GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
- "thread done waiting on state change");
-
- gst_object_unref (element);
-}
-
-/**
- * gst_bin_watch_for_state_change:
- * @bin: the bin to watch for state changes
- *
- * Spawns a thread calling gst_element_get_state on @bin with infinite timeout.
- *
- * In practice this is done because if a bin returns %GST_STATE_CHANGE_ASYNC
- * from a state change, it will not commit its state until someone calls
- * gst_element_get_state() on it. Thus having another thread checking the bin's
- * state will ensure that a state-changed message gets posted on the bus
- * eventually.
- *
- * This function is admittedly a bit of a hack. Bins should always post
- * messages. However this behavior was broken out into this function to avoid
- * spawning threads when scrubbing, when the bin's state is changing quickly and
- * asynchronously.
- */
-void
-gst_bin_watch_for_state_change (GstBin * bin)
-{
- static GThreadPool *pool = NULL;
- static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
-
- g_static_mutex_lock (&mutex);
- if (pool == NULL)
- pool = g_thread_pool_new ((GFunc) get_state_func, NULL, -1, FALSE, NULL);
- g_static_mutex_unlock (&mutex);
-
- g_thread_pool_push (pool, gst_object_ref (bin), NULL);
-}
-
-struct _GstAsyncThreadData
-{
- GstElement *element;
- GstState state;
-};
-
-static void
-set_state_async_thread_func (struct _GstAsyncThreadData *data, gpointer unused)
-{
- GstState current, pending;
- GstStateChangeReturn ret = GST_STATE_CHANGE_ASYNC;
-
- GST_CAT_INFO_OBJECT (GST_CAT_STATES, data->element,
- "new thread ensuring state change to %s",
- gst_element_state_get_name (data->state));
-
- while (TRUE) {
- /* wait indefinitely */
- ret = gst_element_get_state (data->element, ¤t, &pending, NULL);
- GST_CAT_INFO_OBJECT (GST_CAT_STATES, data->element,
- "get_state returned %d, current %s, pending %s", ret,
- gst_element_state_get_name (current),
- gst_element_state_get_name (pending));
-
- /* can only be SUCCESS or FAILURE */
- if (ret == GST_STATE_CHANGE_FAILURE) {
- /* we can only break, hopefully an error message was posted as well */
- GST_CAT_INFO_OBJECT (GST_CAT_STATES, data->element,
- "FAILURE during state change");
- break;
- } else if (ret == GST_STATE_CHANGE_SUCCESS) {
- if (current == data->state) {
- GST_CAT_INFO_OBJECT (GST_CAT_STATES, data->element,
- "successfully reached final state");
- break;
- }
- GST_CAT_INFO_OBJECT (GST_CAT_STATES, data->element,
- "setting target state %s again",
- gst_element_state_get_name (data->state));
- gst_element_set_state (data->element, data->state);
- } else {
- g_assert_not_reached ();
- }
- }
-
- GST_CAT_INFO_OBJECT (GST_CAT_STATES, data->element,
- "thread done waiting on state change");
-
- gst_object_unref (data->element);
- g_free (data);
-}
-
-/**
- * gst_element_set_state_async:
- * @element: a #GstElement to change state of
- * @state: the element's new #GstState
- *
- * Sets the state of the element. This function will try to set the
- * requested state by going through all the intermediary states and calling
- * the class's state change function for each. If the state change returns
- * #GST_STATE_CHANGE_ASYNC at any time, a thread will be started to
- * monitor the state change and make sure the element is brought to the
- * requested state.
- *
- * Returns: Result of the state change using #GstStateChangeReturn.
- *
- * MT safe.
- */
-GstStateChangeReturn
-gst_element_set_state_async (GstElement * element, GstState state)
-{
- GstStateChangeReturn ret;
- struct _GstAsyncThreadData *data;
-
- ret = gst_element_set_state (element, state);
- if (ret == GST_STATE_CHANGE_ASYNC) {
- static GThreadPool *pool = NULL;
- static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
-
- GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
- "starting new thread to ensure state change to %s",
- gst_element_state_get_name (state));
- g_static_mutex_lock (&mutex);
- if (pool == NULL)
- pool = g_thread_pool_new ((GFunc) set_state_async_thread_func,
- NULL, -1, FALSE, NULL);
- g_static_mutex_unlock (&mutex);
-
- data = g_new0 (struct _GstAsyncThreadData, 1);
-
- gst_object_ref (element);
- data->element = element;
- data->state = state;
- g_thread_pool_push (pool, data, NULL);
- }
-
- return ret;
-}
-
-static void