+
+/**
+ * gst_element_get_contexts:
+ * @element: a #GstElement to set the context of.
+ *
+ * Gets the contexts set on the element.
+ *
+ * MT safe.
+ *
+ * Returns: (element-type Gst.Context) (transfer full): List of #GstContext
+ *
+ * Since: 1.8
+ */
+GList *
+gst_element_get_contexts (GstElement * element)
+{
+ GList *ret;
+
+ g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
+
+ GST_OBJECT_LOCK (element);
+ ret = g_list_copy_deep (element->contexts, (GCopyFunc) gst_context_ref, NULL);
+ GST_OBJECT_UNLOCK (element);
+
+ return ret;
+}
+
+static gint
+_match_context_type (GstContext * c1, const gchar * context_type)
+{
+ const gchar *c1_type;
+
+ c1_type = gst_context_get_context_type (c1);
+
+ return g_strcmp0 (c1_type, context_type);
+}
+
+/**
+ * gst_element_get_context_unlocked:
+ * @element: a #GstElement to get the context of.
+ * @context_type: a name of a context to retrieve
+ *
+ * Gets the context with @context_type set on the element or NULL.
+ *
+ * Returns: (transfer full) (nullable): A #GstContext or NULL
+ *
+ * Since: 1.8
+ */
+GstContext *
+gst_element_get_context_unlocked (GstElement * element,
+ const gchar * context_type)
+{
+ GstContext *ret = NULL;
+ GList *node;
+
+ g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
+
+ node =
+ g_list_find_custom (element->contexts, context_type,
+ (GCompareFunc) _match_context_type);
+ if (node && node->data)
+ ret = gst_context_ref (node->data);
+
+ return ret;
+}
+
+/**
+ * gst_element_get_context:
+ * @element: a #GstElement to get the context of.
+ * @context_type: a name of a context to retrieve
+ *
+ * Gets the context with @context_type set on the element or NULL.
+ *
+ * MT safe.
+ *
+ * Returns: (transfer full): A #GstContext or NULL
+ *
+ * Since: 1.8
+ */
+GstContext *
+gst_element_get_context (GstElement * element, const gchar * context_type)
+{
+ GstContext *ret = NULL;
+
+ g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
+
+ GST_OBJECT_LOCK (element);
+ ret = gst_element_get_context_unlocked (element, context_type);
+ GST_OBJECT_UNLOCK (element);
+
+ return ret;
+}
+
+static void
+gst_element_property_post_notify_msg (GstElement * element, GObject * obj,
+ GParamSpec * pspec, gboolean include_value)
+{
+ GValue val = G_VALUE_INIT;
+ GValue *v;
+
+ GST_LOG_OBJECT (element, "property '%s' of object %" GST_PTR_FORMAT " has "
+ "changed, posting message with%s value", pspec->name, obj,
+ include_value ? "" : "out");
+
+ if (include_value && (pspec->flags & G_PARAM_READABLE) != 0) {
+ g_value_init (&val, pspec->value_type);
+ g_object_get_property (obj, pspec->name, &val);
+ v = &val;
+ } else {
+ v = NULL;
+ }
+ gst_element_post_message (element,
+ gst_message_new_property_notify (GST_OBJECT_CAST (obj), pspec->name, v));
+}
+
+static void
+gst_element_property_deep_notify_cb (GstElement * element, GObject * prop_obj,
+ GParamSpec * pspec, gpointer user_data)
+{
+ gboolean include_value = GPOINTER_TO_INT (user_data);
+
+ gst_element_property_post_notify_msg (element, prop_obj, pspec,
+ include_value);
+}
+
+static void
+gst_element_property_notify_cb (GObject * obj, GParamSpec * pspec,
+ gpointer user_data)
+{
+ gboolean include_value = GPOINTER_TO_INT (user_data);
+
+ gst_element_property_post_notify_msg (GST_ELEMENT_CAST (obj), obj, pspec,
+ include_value);
+}
+
+/**
+ * gst_element_add_property_notify_watch:
+ * @element: a #GstElement to watch for property changes
+ * @property_name: (allow-none): name of property to watch for changes, or
+ * NULL to watch all properties
+ * @include_value: whether to include the new property value in the message
+ *
+ * Returns: a watch id, which can be used in connection with
+ * gst_element_remove_property_notify_watch() to remove the watch again.
+ *
+ * Since: 1.10
+ */
+gulong
+gst_element_add_property_notify_watch (GstElement * element,
+ const gchar * property_name, gboolean include_value)
+{
+ const gchar *sep;
+ gchar *signal_name;
+ gulong id;
+
+ g_return_val_if_fail (GST_IS_ELEMENT (element), 0);
+
+ sep = (property_name != NULL) ? "::" : NULL;
+ signal_name = g_strconcat ("notify", sep, property_name, NULL);
+ id = g_signal_connect (element, signal_name,
+ G_CALLBACK (gst_element_property_notify_cb),
+ GINT_TO_POINTER (include_value));
+ g_free (signal_name);
+
+ return id;
+}
+
+/**
+ * gst_element_add_property_deep_notify_watch:
+ * @element: a #GstElement to watch (recursively) for property changes
+ * @property_name: (allow-none): name of property to watch for changes, or
+ * NULL to watch all properties
+ * @include_value: whether to include the new property value in the message
+ *
+ * Returns: a watch id, which can be used in connection with
+ * gst_element_remove_property_notify_watch() to remove the watch again.
+ *
+ * Since: 1.10
+ */
+gulong
+gst_element_add_property_deep_notify_watch (GstElement * element,
+ const gchar * property_name, gboolean include_value)
+{
+ const gchar *sep;
+ gchar *signal_name;
+ gulong id;
+
+ g_return_val_if_fail (GST_IS_ELEMENT (element), 0);
+
+ sep = (property_name != NULL) ? "::" : NULL;
+ signal_name = g_strconcat ("deep-notify", sep, property_name, NULL);
+ id = g_signal_connect (element, signal_name,
+ G_CALLBACK (gst_element_property_deep_notify_cb),
+ GINT_TO_POINTER (include_value));
+ g_free (signal_name);
+
+ return id;
+}
+
+/**
+ * gst_element_remove_property_notify_watch:
+ * @element: a #GstElement being watched for property changes
+ * @watch_id: watch id to remove
+ *
+ * Since: 1.10
+ */
+void
+gst_element_remove_property_notify_watch (GstElement * element, gulong watch_id)
+{
+ g_signal_handler_disconnect (element, watch_id);
+}
+
+typedef struct
+{
+ GstElement *element;
+ GstElementCallAsyncFunc func;
+ gpointer user_data;
+ GDestroyNotify destroy_notify;
+} GstElementCallAsyncData;
+
+static void
+gst_element_call_async_func (gpointer data, gpointer user_data)
+{
+ GstElementCallAsyncData *async_data = data;
+
+ async_data->func (async_data->element, async_data->user_data);
+ if (async_data->destroy_notify)
+ async_data->destroy_notify (async_data->user_data);
+ gst_object_unref (async_data->element);
+ g_free (async_data);
+}
+
+/**
+ * gst_element_call_async:
+ * @element: a #GstElement
+ * @func: Function to call asynchronously from another thread
+ * @user_data: Data to pass to @func
+ * @destroy_notify: GDestroyNotify for @user_data
+ *
+ * Calls @func from another thread and passes @user_data to it. This is to be
+ * used for cases when a state change has to be performed from a streaming
+ * thread, directly via gst_element_set_state() or indirectly e.g. via SEEK
+ * events.
+ *
+ * Calling those functions directly from the streaming thread will cause
+ * deadlocks in many situations, as they might involve waiting for the
+ * streaming thread to shut down from this very streaming thread.
+ *
+ * MT safe.
+ *
+ * Since: 1.10
+ */
+void
+gst_element_call_async (GstElement * element, GstElementCallAsyncFunc func,
+ gpointer user_data, GDestroyNotify destroy_notify)
+{
+ GstElementCallAsyncData *async_data;
+
+ g_return_if_fail (GST_IS_ELEMENT (element));
+
+ async_data = g_new0 (GstElementCallAsyncData, 1);
+ async_data->element = gst_object_ref (element);
+ async_data->func = func;
+ async_data->user_data = user_data;
+ async_data->destroy_notify = destroy_notify;
+
+ g_thread_pool_push (gst_element_pool, async_data, NULL);
+}
+
+void
+_priv_gst_element_cleanup (void)
+{
+ if (gst_element_pool) {
+ g_thread_pool_free (gst_element_pool, FALSE, TRUE);
+ gst_element_setup_thread_pool ();
+ }
+}
+
+GstStructure *
+gst_make_element_message_details (const char *name, ...)
+{
+ GstStructure *structure;
+ va_list varargs;
+
+ if (name == NULL)
+ return NULL;
+
+ va_start (varargs, name);
+ structure = gst_structure_new_valist ("details", name, varargs);
+ va_end (varargs);
+
+ return structure;
+}