*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
/**
* core when using the appropriate locking. Do not use this in plug-ins or
* applications in order to retain ABI compatibility.
*
- * All elements have pads (of the type #GstPad). These pads link to pads on
+ * Elements can have pads (of the type #GstPad). These pads link to pads on
* other elements. #GstBuffer flow between these linked pads.
* A #GstElement has a #GList of #GstPad structures for all their input (or sink)
* and output (or source) pads.
*
* An existing pad of an element can be retrieved by name with
* gst_element_get_static_pad(). A new dynamic pad can be created using
- * gst_element_request_pad() with a #GstPadTemplate or
- * gst_element_get_request_pad() with the template name such as "src_\%d".
+ * gst_element_request_pad() with a #GstPadTemplate.
* An iterator of all pads can be retrieved with gst_element_iterate_pads().
*
* Elements can be linked through their pads.
* You can get and set a #GstClock on an element using gst_element_get_clock()
* and gst_element_set_clock().
* Some elements can provide a clock for the pipeline if
- * gst_element_provides_clock() returns %TRUE. With the
+ * the #GST_ELEMENT_FLAG_PROVIDE_CLOCK flag is set. With the
* gst_element_provide_clock() method one can retrieve the clock provided by
* such an element.
- * Not all elements require a clock to operate correctly. If
- * gst_element_requires_clock() returns %TRUE, a clock should be set on the
+ * Not all elements require a clock to operate correctly. If the
+ * #GST_ELEMENT_FLAG_REQUIRE_CLOCK() flag is set, a clock should be set on the
* element with gst_element_set_clock().
*
- * Note that clock slection and distribution is normally handled by the
+ * Note that clock selection and distribution is normally handled by the
* toplevel #GstPipeline so the clock functions are only to be used in very
* specific situations.
- *
- * Last reviewed on 2009-05-29 (0.10.24)
*/
#include "gst_private.h"
#include "gstelementmetadata.h"
#include "gstenumtypes.h"
#include "gstbus.h"
-#include "gstmarshal.h"
#include "gsterror.h"
#include "gstevent.h"
#include "gstutils.h"
#include "gstinfo.h"
+#include "gstquark.h"
#include "gstvalue.h"
#include "gst-i18n-lib.h"
+#include "glib-compat-private.h"
+
+#ifndef GST_DISABLE_GST_DEBUG
+#include "printf/printf.h"
+#endif
/* Element signals and args */
enum
GstState * state, GstState * pending, GstClockTime timeout);
static GstStateChangeReturn gst_element_set_state_func (GstElement * element,
GstState state);
+static gboolean gst_element_set_clock_func (GstElement * element,
+ GstClock * clock);
static void gst_element_set_bus_func (GstElement * element, GstBus * bus);
+static gboolean gst_element_post_message_default (GstElement * element,
+ GstMessage * message);
static gboolean gst_element_default_send_event (GstElement * element,
GstEvent * event);
gst_element_signals[PAD_ADDED] =
g_signal_new ("pad-added", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GstElementClass, pad_added), NULL, NULL,
- gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_PAD);
+ g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_PAD);
/**
* GstElement::pad-removed:
* @gstelement: the object which received the signal
gst_element_signals[PAD_REMOVED] =
g_signal_new ("pad-removed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GstElementClass, pad_removed), NULL, NULL,
- gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_PAD);
+ g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_PAD);
/**
* GstElement::no-more-pads:
* @gstelement: the object which received the signal
gst_element_signals[NO_MORE_PADS] =
g_signal_new ("no-more-pads", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstElementClass, no_more_pads), NULL,
- NULL, gst_marshal_VOID__VOID, G_TYPE_NONE, 0);
+ NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 0);
gobject_class->dispose = gst_element_dispose;
gobject_class->finalize = gst_element_finalize;
klass->change_state = GST_DEBUG_FUNCPTR (gst_element_change_state_func);
klass->set_state = GST_DEBUG_FUNCPTR (gst_element_set_state_func);
klass->get_state = GST_DEBUG_FUNCPTR (gst_element_get_state_func);
+ klass->set_clock = GST_DEBUG_FUNCPTR (gst_element_set_clock_func);
klass->set_bus = GST_DEBUG_FUNCPTR (gst_element_set_bus_func);
klass->query = GST_DEBUG_FUNCPTR (gst_element_default_query);
klass->send_event = GST_DEBUG_FUNCPTR (gst_element_default_send_event);
klass->numpadtemplates = 0;
+ klass->post_message = GST_DEBUG_FUNCPTR (gst_element_post_message_default);
klass->elementfactory = NULL;
}
element_class->elementfactory =
g_type_get_qdata (G_TYPE_FROM_CLASS (element_class),
__gst_elementclass_factory);
- GST_DEBUG ("type %s : factory %p", G_OBJECT_CLASS_NAME (element_class),
- element_class->elementfactory);
+ GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "type %s : factory %p",
+ G_OBJECT_CLASS_NAME (element_class), element_class->elementfactory);
}
static void
GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING;
GST_STATE_RETURN (element) = GST_STATE_CHANGE_SUCCESS;
- g_static_rec_mutex_init (&element->state_lock);
- element->state_cond = g_cond_new ();
+ g_rec_mutex_init (&element->state_lock);
+ g_cond_init (&element->state_cond);
}
/**
* @pad: the #GstPad to release.
*
* Makes the element free the previously requested pad as obtained
- * with gst_element_get_request_pad().
+ * with gst_element_request_pad().
*
* This does not unref the pad. If the pad was created by using
- * gst_element_get_request_pad(), gst_element_release_request_pad() needs to be
+ * gst_element_request_pad(), gst_element_release_request_pad() needs to be
* followed by gst_object_unref() to free the @pad.
*
* MT safe.
g_return_if_fail (GST_IS_ELEMENT (element));
g_return_if_fail (GST_IS_PAD (pad));
+ g_return_if_fail (GST_PAD_PAD_TEMPLATE (pad) == NULL ||
+ GST_PAD_TEMPLATE_PRESENCE (GST_PAD_PAD_TEMPLATE (pad)) ==
+ GST_PAD_REQUEST);
oclass = GST_ELEMENT_GET_CLASS (element);
/* if the element implements a custom release function we call that, else we
* simply remove the pad from the element */
if (oclass->release_pad)
- (oclass->release_pad) (element, pad);
+ oclass->release_pad (element, pad);
else
gst_element_remove_pad (element, pad);
}
/**
- * gst_element_requires_clock:
- * @element: a #GstElement to query
- *
- * Query if the element requires a clock.
- *
- * Returns: %TRUE if the element requires a clock
- *
- * MT safe.
- */
-gboolean
-gst_element_requires_clock (GstElement * element)
-{
- gboolean result;
-
- g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
-
- result = (GST_ELEMENT_GET_CLASS (element)->set_clock != NULL);
-
- return result;
-}
-
-/**
- * gst_element_provides_clock:
- * @element: a #GstElement to query
- *
- * Query if the element provides a clock. A #GstClock provided by an
- * element can be used as the global #GstClock for the pipeline.
- * An element that can provide a clock is only required to do so in the PAUSED
- * state, this means when it is fully negotiated and has allocated the resources
- * to operate the clock.
- *
- * Returns: %TRUE if the element provides a clock
- *
- * MT safe.
- */
-gboolean
-gst_element_provides_clock (GstElement * element)
-{
- gboolean result;
-
- g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
-
- result = (GST_ELEMENT_GET_CLASS (element)->provide_clock != NULL);
-
- return result;
-}
-
-/**
* gst_element_provide_clock:
* @element: a #GstElement to query
*
return result;
}
+static gboolean
+gst_element_set_clock_func (GstElement * element, GstClock * clock)
+{
+ GstClock **clock_p;
+
+ GST_OBJECT_LOCK (element);
+ clock_p = &element->clock;
+ gst_object_replace ((GstObject **) clock_p, (GstObject *) clock);
+ GST_OBJECT_UNLOCK (element);
+
+ return TRUE;
+}
+
/**
* gst_element_set_clock:
* @element: a #GstElement to set the clock for.
gst_element_set_clock (GstElement * element, GstClock * clock)
{
GstElementClass *oclass;
- gboolean res = TRUE;
- GstClock **clock_p;
+ gboolean res = FALSE;
g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
g_return_val_if_fail (clock == NULL || GST_IS_CLOCK (clock), FALSE);
if (oclass->set_clock)
res = oclass->set_clock (element, clock);
- if (res) {
- /* only update the clock pointer if the element accepted the clock */
- GST_OBJECT_LOCK (element);
- clock_p = &element->clock;
- gst_object_replace ((GstObject **) clock_p, (GstObject *) clock);
- GST_OBJECT_UNLOCK (element);
- }
return res;
}
* pipelines, and you can also ensure that the pipelines have the same clock.
*
* MT safe.
- *
- * Since: 0.10.24
*/
void
gst_element_set_start_time (GstElement * element, GstClockTime time)
* MT safe.
*
* Returns: the start time of the element.
- *
- * Since: 0.10.24
*/
GstClockTime
gst_element_get_start_time (GstElement * element)
return result;
}
-/**
- * gst_element_is_indexable:
- * @element: a #GstElement.
- *
- * Queries if the element can be indexed.
- *
- * Returns: TRUE if the element can be indexed.
- *
- * MT safe.
- */
-gboolean
-gst_element_is_indexable (GstElement * element)
-{
- gboolean result;
-
- g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
-
- result = (GST_ELEMENT_GET_CLASS (element)->set_index != NULL);
-
- return result;
-}
-
+#if 0
/**
* gst_element_set_index:
* @element: a #GstElement.
return result;
}
+#endif
/**
* gst_element_add_pad:
GST_CAT_INFO_OBJECT (GST_CAT_ELEMENT_PADS, element, "adding pad '%s'",
GST_STR_NULL (pad_name));
flushing = GST_PAD_IS_FLUSHING (pad);
+ GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_NEED_PARENT);
GST_OBJECT_UNLOCK (pad);
/* then check to see if there's already a pad by that name here */
/* add it to the list */
switch (gst_pad_get_direction (pad)) {
case GST_PAD_SRC:
- element->srcpads = g_list_prepend (element->srcpads, pad);
+ element->srcpads = g_list_append (element->srcpads, pad);
element->numsrcpads++;
break;
case GST_PAD_SINK:
- element->sinkpads = g_list_prepend (element->sinkpads, pad);
+ element->sinkpads = g_list_append (element->sinkpads, pad);
element->numsinkpads++;
break;
default:
goto no_direction;
}
- element->pads = g_list_prepend (element->pads, pad);
+ element->pads = g_list_append (element->pads, pad);
element->numpads++;
element->pads_cookie++;
GST_OBJECT_UNLOCK (element);
/**
* gst_element_remove_pad:
* @element: a #GstElement to remove pad from.
- * @pad: (transfer none): the #GstPad to remove from the element.
+ * @pad: (transfer full): the #GstPad to remove from the element.
*
* Removes @pad from @element. @pad will be destroyed if it has not been
* referenced elsewhere using gst_object_unparent().
*
* This function is used by plugin developers and should not be used
* by applications. Pads that were dynamically requested from elements
- * with gst_element_get_request_pad() should be released with the
+ * with gst_element_request_pad() should be released with the
* gst_element_release_request_pad() function instead.
*
* Pads are not automatically deactivated so elements should perform the needed
break;
}
element->pads = g_list_remove (element->pads, pad);
+ GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_NEED_PARENT);
element->numpads--;
element->pads_cookie++;
GST_OBJECT_UNLOCK (element);
* Pad templates can be looked up using
* gst_element_factory_get_static_pad_templates().
*
- * If the @caps are specified and the element implements thew new
- * request_new_pad_full virtual method, the element will use them to select
- * which pad to create.
- *
* The pad should be released with gst_element_release_request_pad().
*
* Returns: (transfer full): requested #GstPad if found, otherwise %NULL.
* Release after usage.
- *
- * Since: 0.10.32
*/
GstPad *
gst_element_request_pad (GstElement * element,
{
g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
g_return_val_if_fail (templ != NULL, NULL);
+ g_return_val_if_fail (templ->presence == GST_PAD_REQUEST, NULL);
return _gst_element_request_pad (element, templ, name, caps);
}
* be freed after usage. Also more specialized iterators exists such as
* gst_element_iterate_src_pads() or gst_element_iterate_sink_pads().
*
- * Returns: (transfer full): the #GstIterator of #GstPad. Unref each pad
- * after use.
+ * The order of pads returned by the iterator will be the order in which
+ * the pads were added to the element.
+ *
+ * Returns: (transfer full): the #GstIterator of #GstPad.
*
* MT safe.
*/
*
* Retrieves an iterator of @element's source pads.
*
- * Returns: (transfer full): the #GstIterator of #GstPad. Unref each pad
- * after use.
+ * The order of pads returned by the iterator will be the order in which
+ * the pads were added to the element.
+ *
+ * Returns: (transfer full): the #GstIterator of #GstPad.
*
* MT safe.
*/
*
* Retrieves an iterator of @element's sink pads.
*
- * Returns: (transfer full): the #GstIterator of #GstPad. Unref each pad
- * after use.
+ * The order of pads returned by the iterator will be the order in which
+ * the pads were added to the element.
+ *
+ * Returns: (transfer full): the #GstIterator of #GstPad.
*
* MT safe.
*/
}
/* Take ownership of the floating ref */
- g_object_ref_sink (templ);
+ gst_object_ref_sink (templ);
klass->padtemplates = g_list_append (klass->padtemplates, templ);
klass->numpadtemplates++;
}
/**
+ * gst_element_class_add_static_metadata:
+ * @klass: class to set metadata for
+ * @key: the key to set
+ * @value: the value to set
+ *
+ * Set @key with @value as metadata in @klass.
+ *
+ * Same as gst_element_class_add_metadata(), but @value must be a static string
+ * or an inlined string, as it will not be copied. (GStreamer plugins will
+ * be made resident once loaded, so this function can be used even from
+ * dynamically loaded plugins.)
+ */
+void
+gst_element_class_add_static_metadata (GstElementClass * klass,
+ const gchar * key, const gchar * value)
+{
+ GValue val = G_VALUE_INIT;
+
+ g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
+ g_return_if_fail (key != NULL);
+ g_return_if_fail (value != NULL);
+
+ g_value_init (&val, G_TYPE_STRING);
+ g_value_set_static_string (&val, value);
+ gst_structure_take_value ((GstStructure *) klass->metadata, key, &val);
+}
+
+/**
* gst_element_class_set_metadata:
* @klass: class to set metadata for
* @longname: The long English name of the element. E.g. "File Sink"
const gchar * description, const gchar * author)
{
g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
+ g_return_if_fail (longname != NULL && *longname != '\0');
+ g_return_if_fail (classification != NULL && *classification != '\0');
+ g_return_if_fail (description != NULL && *description != '\0');
+ g_return_if_fail (author != NULL && *author != '\0');
- gst_structure_set ((GstStructure *) klass->metadata,
- GST_ELEMENT_METADATA_LONGNAME, G_TYPE_STRING, longname,
- GST_ELEMENT_METADATA_KLASS, G_TYPE_STRING, classification,
- GST_ELEMENT_METADATA_DESCRIPTION, G_TYPE_STRING, description,
- GST_ELEMENT_METADATA_AUTHOR, G_TYPE_STRING, author, NULL);
+ gst_structure_id_set ((GstStructure *) klass->metadata,
+ GST_QUARK (ELEMENT_METADATA_LONGNAME), G_TYPE_STRING, longname,
+ GST_QUARK (ELEMENT_METADATA_KLASS), G_TYPE_STRING, classification,
+ GST_QUARK (ELEMENT_METADATA_DESCRIPTION), G_TYPE_STRING, description,
+ GST_QUARK (ELEMENT_METADATA_AUTHOR), G_TYPE_STRING, author, NULL);
+}
+
+/**
+ * gst_element_class_set_static_metadata:
+ * @klass: class to set metadata for
+ * @longname: The long English name of the element. E.g. "File Sink"
+ * @classification: String describing the type of element, as an unordered list
+ * separated with slashes ('/'). See draft-klass.txt of the design docs
+ * for more details and common types. E.g: "Sink/File"
+ * @description: Sentence describing the purpose of the element.
+ * E.g: "Write stream to a file"
+ * @author: Name and contact details of the author(s). Use \n to separate
+ * multiple author metadata. E.g: "Joe Bloggs <joe.blogs at foo.com>"
+ *
+ * Sets the detailed information for a #GstElementClass.
+ * <note>This function is for use in _class_init functions only.</note>
+ *
+ * Same as gst_element_class_set_metadata(), but @longname, @classification,
+ * @description, and @author must be static strings or inlined strings, as
+ * they will not be copied. (GStreamer plugins will be made resident once
+ * loaded, so this function can be used even from dynamically loaded plugins.)
+ */
+void
+gst_element_class_set_static_metadata (GstElementClass * klass,
+ const gchar * longname, const gchar * classification,
+ const gchar * description, const gchar * author)
+{
+ GstStructure *s = (GstStructure *) klass->metadata;
+ GValue val = G_VALUE_INIT;
+
+ g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
+ g_return_if_fail (longname != NULL && *longname != '\0');
+ g_return_if_fail (classification != NULL && *classification != '\0');
+ g_return_if_fail (description != NULL && *description != '\0');
+ g_return_if_fail (author != NULL && *author != '\0');
+
+ g_value_init (&val, G_TYPE_STRING);
+
+ g_value_set_static_string (&val, longname);
+ gst_structure_id_set_value (s, GST_QUARK (ELEMENT_METADATA_LONGNAME), &val);
+
+ g_value_set_static_string (&val, classification);
+ gst_structure_id_set_value (s, GST_QUARK (ELEMENT_METADATA_KLASS), &val);
+
+ g_value_set_static_string (&val, description);
+ gst_structure_id_set_value (s, GST_QUARK (ELEMENT_METADATA_DESCRIPTION),
+ &val);
+
+ g_value_set_static_string (&val, author);
+ gst_structure_id_take_value (s, GST_QUARK (ELEMENT_METADATA_AUTHOR), &val);
}
/**
* event handler, the event will be pushed on a random linked sink pad for
* upstream events or a random linked source pad for downstream events.
*
- * This function takes owership of the provided event so you should
+ * This function takes ownership of the provided event so you should
* gst_event_ref() it if you want to reuse the event after this call.
*
- * Returns: %TRUE if the event was handled.
- *
* MT safe.
+ *
+ * Returns: %TRUE if the event was handled. Events that trigger a preroll (such
+ * as flushing seeks and steps) will emit %GST_MESSAGE_ASYNC_DONE.
*/
gboolean
gst_element_send_event (GstElement * element, GstEvent * event)
GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "send %s event on element %s",
GST_EVENT_TYPE_NAME (event), GST_ELEMENT_NAME (element));
result = oclass->send_event (element, event);
- } else {
- result = gst_element_default_send_event (element, event);
}
GST_STATE_UNLOCK (element);
* @rate: The new playback rate
* @format: The format of the seek values
* @flags: The optional seek flags.
- * @cur_type: The type and flags for the new current position
- * @cur: The value of the new current position
+ * @start_type: The type and flags for the new start position
+ * @start: The value of the new start position
* @stop_type: The type and flags for the new stop position
* @stop: The value of the new stop position
*
* the parameters. The seek event is sent to the element using
* gst_element_send_event().
*
- * Returns: %TRUE if the event was handled.
- *
* MT safe.
+ *
+ * Returns: %TRUE if the event was handled. Flushing seeks will trigger a
+ * preroll, which will emit %GST_MESSAGE_ASYNC_DONE.
*/
gboolean
gst_element_seek (GstElement * element, gdouble rate, GstFormat format,
- GstSeekFlags flags, GstSeekType cur_type, gint64 cur,
+ GstSeekFlags flags, GstSeekType start_type, gint64 start,
GstSeekType stop_type, gint64 stop)
{
GstEvent *event;
g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
event =
- gst_event_new_seek (rate, format, flags, cur_type, cur, stop_type, stop);
+ gst_event_new_seek (rate, format, flags, start_type, start, stop_type,
+ stop);
result = gst_element_send_event (element, event);
return result;
*
* Please note that some queries might need a running pipeline to work.
*
- * Returns: TRUE if the query could be performed.
+ * Returns: %TRUE if the query could be performed.
*
* MT safe.
*/
gboolean
gst_element_query (GstElement * element, GstQuery * query)
{
- GstElementClass *oclass;
- gboolean result = FALSE;
+ GstElementClass *klass;
g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
g_return_val_if_fail (query != NULL, FALSE);
- oclass = GST_ELEMENT_GET_CLASS (element);
-
- if (oclass->query) {
+ klass = GST_ELEMENT_GET_CLASS (element);
+ if (klass->query) {
GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "send query on element %s",
GST_ELEMENT_NAME (element));
- result = oclass->query (element, query);
- } else {
- result = gst_element_default_query (element, query);
+ return klass->query (element, query);
}
- return result;
+
+ return FALSE;
}
-/**
- * gst_element_post_message:
- * @element: a #GstElement posting the message
- * @message: (transfer full): a #GstMessage to post
- *
- * Post a message on the element's #GstBus. This function takes ownership of the
- * message; if you want to access the message after this call, you should add an
- * additional reference before calling.
- *
- * Returns: %TRUE if the message was successfully posted. The function returns
- * %FALSE if the element did not have a bus.
- *
- * MT safe.
- */
-gboolean
-gst_element_post_message (GstElement * element, GstMessage * message)
+static gboolean
+gst_element_post_message_default (GstElement * element, GstMessage * message)
{
GstBus *bus;
gboolean result = FALSE;
}
/**
+ * gst_element_post_message:
+ * @element: a #GstElement posting the message
+ * @message: (transfer full): a #GstMessage to post
+ *
+ * Post a message on the element's #GstBus. This function takes ownership of the
+ * message; if you want to access the message after this call, you should add an
+ * additional reference before calling.
+ *
+ * Returns: %TRUE if the message was successfully posted. The function returns
+ * %FALSE if the element did not have a bus.
+ *
+ * MT safe.
+ */
+gboolean
+gst_element_post_message (GstElement * element, GstMessage * message)
+{
+ GstElementClass *klass;
+
+ g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
+ g_return_val_if_fail (message != NULL, FALSE);
+
+ klass = GST_ELEMENT_GET_CLASS (element);
+ if (klass->post_message)
+ return klass->post_message (element, message);
+
+ return FALSE;
+}
+
+/**
* _gst_element_error_printf:
* @format: the printf-like format to use, or %NULL
*
{
va_list args;
gchar *buffer;
+ int len;
if (format == NULL)
return NULL;
return NULL;
va_start (args, format);
- buffer = g_strdup_vprintf (format, args);
+
+ len = __gst_vasprintf (&buffer, format, args);
+
va_end (args);
+
+ if (len < 0)
+ buffer = NULL;
+
return buffer;
}
*
* MT safe.
*
- * Returns: TRUE, if the element's state is locked.
+ * Returns: %TRUE, if the element's state is locked.
*/
gboolean
gst_element_is_locked_state (GstElement * element)
g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
GST_OBJECT_LOCK (element);
- result = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
+ result = GST_ELEMENT_IS_LOCKED_STATE (element);
GST_OBJECT_UNLOCK (element);
return result;
/**
* gst_element_set_locked_state:
* @element: a #GstElement
- * @locked_state: TRUE to lock the element's state
+ * @locked_state: %TRUE to lock the element's state
*
* Locks the state of an element, so state changes of the parent don't affect
* this element anymore.
*
* MT safe.
*
- * Returns: TRUE if the state was changed, FALSE if bad parameters were given
+ * Returns: %TRUE if the state was changed, %FALSE if bad parameters were given
* or the elements state-locking needed no change.
*/
gboolean
g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
GST_OBJECT_LOCK (element);
- old = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
+ old = GST_ELEMENT_IS_LOCKED_STATE (element);
if (G_UNLIKELY (old == locked_state))
goto was_ok;
if (locked_state) {
GST_CAT_DEBUG (GST_CAT_STATES, "locking state of element %s",
GST_ELEMENT_NAME (element));
- GST_OBJECT_FLAG_SET (element, GST_ELEMENT_LOCKED_STATE);
+ GST_OBJECT_FLAG_SET (element, GST_ELEMENT_FLAG_LOCKED_STATE);
} else {
GST_CAT_DEBUG (GST_CAT_STATES, "unlocking state of element %s",
GST_ELEMENT_NAME (element));
- GST_OBJECT_FLAG_UNSET (element, GST_ELEMENT_LOCKED_STATE);
+ GST_OBJECT_FLAG_UNSET (element, GST_ELEMENT_FLAG_LOCKED_STATE);
}
GST_OBJECT_UNLOCK (element);
* @element: a #GstElement.
*
* Tries to change the state of the element to the same as its parent.
- * If this function returns FALSE, the state of element is undefined.
+ * If this function returns %FALSE, the state of element is undefined.
*
- * Returns: TRUE, if the element's state could be synced to the parent's state.
+ * Returns: %TRUE, if the element's state could be synced to the parent's state.
*
* MT safe.
*/
old_pending = GST_STATE_PENDING (element);
if (old_pending != GST_STATE_VOID_PENDING) {
- GTimeVal *timeval, abstimeout;
+ gboolean signaled;
guint32 cookie;
- if (timeout != GST_CLOCK_TIME_NONE) {
- glong add = timeout / 1000;
-
- if (add == 0)
- goto done;
-
- /* make timeout absolute */
- g_get_current_time (&abstimeout);
- g_time_val_add (&abstimeout, add);
- timeval = &abstimeout;
- } else {
- timeval = NULL;
- }
/* get cookie to detect state changes during waiting */
cookie = element->state_cookie;
"waiting for element to commit state");
/* we have a pending state change, wait for it to complete */
- if (!GST_STATE_TIMED_WAIT (element, timeval)) {
+ if (timeout != GST_CLOCK_TIME_NONE) {
+ gint64 end_time;
+ /* make timeout absolute */
+ end_time = g_get_monotonic_time () + (timeout / 1000);
+ signaled = GST_STATE_WAIT_UNTIL (element, end_time);
+ } else {
+ GST_STATE_WAIT (element);
+ signaled = TRUE;
+ }
+
+ if (!signaled) {
GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "timed out");
/* timeout triggered */
ret = GST_STATE_CHANGE_ASYNC;
* element will perform the remainder of the state change asynchronously in
* another thread.
* An application can use gst_element_get_state() to wait for the completion
- * of the state change or it can wait for a state change message on the bus.
+ * of the state change or it can wait for a %GST_MESSAGE_ASYNC_DONE or
+ * %GST_MESSAGE_STATE_CHANGED on the bus.
*
* State changes to %GST_STATE_READY or %GST_STATE_NULL never return
* #GST_STATE_CHANGE_ASYNC.
gboolean res;
GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element,
- "pads_activate with active %d", active);
+ "%s pads", active ? "activate" : "deactivate");
iter = gst_element_iterate_src_pads (element);
res =
goto sink_failed;
GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element,
- "pads_activate successful");
+ "pad %sactivation successful", active ? "" : "de");
return TRUE;
src_failed:
{
GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element,
- "source pads_activate failed");
+ "pad %sactivation failed", active ? "" : "de");
return FALSE;
}
sink_failed:
GstElement *element = GST_ELEMENT_CAST (object);
GstClock **clock_p;
GstBus **bus_p;
+ GstElementClass *oclass;
+ GList *walk;
+
+ oclass = GST_ELEMENT_GET_CLASS (element);
GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "dispose");
if (GST_STATE (element) != GST_STATE_NULL)
goto not_null;
- GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element,
- "removing %d pads", g_list_length (element->pads));
- /* first we break all our links with the outside */
- while (element->pads && element->pads->data) {
- /* don't call _remove_pad with NULL */
- gst_element_remove_pad (element, GST_PAD_CAST (element->pads->data));
+ /* start by releasing all request pads, this might also remove some dynamic
+ * pads */
+ walk = element->pads;
+ while (walk) {
+ GstPad *pad = GST_PAD_CAST (walk->data);
+
+ walk = walk->next;
+
+ if (oclass->release_pad && GST_PAD_PAD_TEMPLATE (pad) &&
+ GST_PAD_TEMPLATE_PRESENCE (GST_PAD_PAD_TEMPLATE (pad))
+ == GST_PAD_REQUEST) {
+ GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element,
+ "removing request pad %s:%s", GST_DEBUG_PAD_NAME (pad));
+ oclass->release_pad (element, pad);
+
+ /* in case the release_pad function removed the next pad too */
+ if (walk && g_list_position (element->pads, walk) == -1)
+ walk = element->pads;
+ }
}
- if (G_UNLIKELY (element->pads != NULL)) {
- g_critical ("could not remove pads from element %s",
- GST_STR_NULL (GST_OBJECT_NAME (object)));
+ /* remove the remaining pads */
+ while (element->pads) {
+ GstPad *pad = GST_PAD_CAST (element->pads->data);
+ GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element,
+ "removing pad %s:%s", GST_DEBUG_PAD_NAME (pad));
+ if (!gst_element_remove_pad (element, pad)) {
+ /* only happens when someone unparented our pad.. */
+ g_critical ("failed to remove pad %s:%s", GST_DEBUG_PAD_NAME (pad));
+ break;
+ }
}
GST_OBJECT_LOCK (element);
{
gboolean is_locked;
- is_locked = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
+ is_locked = GST_ELEMENT_IS_LOCKED_STATE (element);
g_critical
("\nTrying to dispose element %s, but it is in %s%s instead of the NULL"
" state.\n"
GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "finalize");
- g_cond_free (element->state_cond);
- g_static_rec_mutex_free (&element->state_lock);
+ g_cond_clear (&element->state_cond);
+ g_rec_mutex_clear (&element->state_lock);
GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "finalize parent");
return result;
}
+
+/**
+ * gst_element_set_context:
+ * @element: a #GstElement to set the context of.
+ * @context: (transfer none): the #GstContext to set.
+ *
+ * Sets the context of the element. Increases the refcount of the context.
+ *
+ * MT safe.
+ */
+void
+gst_element_set_context (GstElement * element, GstContext * context)
+{
+ GstElementClass *oclass;
+
+ g_return_if_fail (GST_IS_ELEMENT (element));
+
+ oclass = GST_ELEMENT_GET_CLASS (element);
+
+ GST_CAT_DEBUG_OBJECT (GST_CAT_CONTEXT, element,
+ "set context %p %" GST_PTR_FORMAT, context,
+ gst_context_get_structure (context));
+
+ if (oclass->set_context)
+ oclass->set_context (element, context);
+}