* 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_get_request_pad() with the template name such as "src_\%u".
* 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
* toplevel #GstPipeline so the clock functions are only to be used in very
* specific situations.
*
- * Last reviewed on 2009-05-29 (0.10.24)
+ * Last reviewed on 2012-03-28 (0.11.3)
*/
#include "gst_private.h"
#include <gobject/gvaluecollector.h>
#include "gstelement.h"
-#include "gstelementdetails.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 "gstvalue.h"
#include "gst-i18n-lib.h"
+#include "glib-compat-private.h"
/* Element signals and args */
enum
/* FILL ME */
};
-#ifdef GST_DISABLE_DEPRECATED
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
-#include <libxml/parser.h>
-xmlNodePtr gst_object_save_thyself (const GstObject * object,
- xmlNodePtr parent);
-GstObject *gst_object_load_thyself (xmlNodePtr parent);
-void gst_pad_load_and_link (xmlNodePtr self, GstObject * parent);
-#endif
-#endif
-
static void gst_element_class_init (GstElementClass * klass);
static void gst_element_init (GstElement * element);
static void gst_element_base_class_init (gpointer g_class);
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_default_send_event (GstElement * element,
* gst_element_class_get_request_pad_template (GstElementClass *
element_class, const gchar * name);
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
-static xmlNodePtr gst_element_save_thyself (GstObject * object,
- xmlNodePtr parent);
-static void gst_element_restore_thyself (GstObject * parent, xmlNodePtr self);
-#endif
-
static GstObjectClass *parent_class = NULL;
static guint gst_element_signals[LAST_SIGNAL] = { 0 };
/* this is used in gstelementfactory.c:gst_element_register() */
-GQuark _gst_elementclass_factory = 0;
+GQuark __gst_elementclass_factory = 0;
GType
gst_element_get_type (void)
_type = g_type_register_static (GST_TYPE_OBJECT, "GstElement",
&element_info, G_TYPE_FLAG_ABSTRACT);
- _gst_elementclass_factory =
+ __gst_elementclass_factory =
g_quark_from_static_string ("GST_ELEMENTCLASS_FACTORY");
g_once_init_leave (&gst_element_type, _type);
}
static void
gst_element_class_init (GstElementClass * klass)
{
- GObjectClass *gobject_class = (GObjectClass *) klass;
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
- GstObjectClass *gstobject_class = (GstObjectClass *) klass;
-#endif
+ GObjectClass *gobject_class;
+
+ gobject_class = (GObjectClass *) klass;
parent_class = g_type_class_peek_parent (klass);
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;
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
- gstobject_class->save_thyself =
- ((gpointer (*)(GstObject * object,
- gpointer self)) * GST_DEBUG_FUNCPTR (gst_element_save_thyself));
- gstobject_class->restore_thyself =
- ((void (*)(GstObject * object,
- gpointer self)) *GST_DEBUG_FUNCPTR (gst_element_restore_thyself));
-#endif
-
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);
gst_element_base_class_init (gpointer g_class)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- /* FIXME 0.11: Copy the element details and instead of clearing the
- * pad template list copy the list and increase the refcount of
- * the pad templates by one.
- *
- * This will make it possible to add pad templates and set element
- * details in the class_init functions and is the real GObject way
- * of doing things.
- * See http://bugzilla.gnome.org/show_bug.cgi?id=491501
+ GList *node, *padtemplates;
+
+ /* Copy the element details here so elements can inherit the
+ * details from their base class and classes only need to set
+ * the details in class_init instead of base_init */
+ element_class->metadata =
+ element_class->metadata ? gst_structure_copy (element_class->metadata) :
+ gst_structure_new_empty ("metadata");
+
+ /* Copy the pad templates so elements inherit them
+ * from their base class but elements can add pad templates in class_init
+ * instead of base_init.
*/
- memset (&element_class->details, 0, sizeof (GstElementDetails));
- element_class->meta_data = NULL;
- element_class->padtemplates = NULL;
+ padtemplates = g_list_copy (element_class->padtemplates);
+ for (node = padtemplates; node != NULL; node = node->next) {
+ GstPadTemplate *tmpl = (GstPadTemplate *) node->data;
+ gst_object_ref (tmpl);
+ }
+ element_class->padtemplates = padtemplates;
/* set the factory, see gst_element_register() */
element_class->elementfactory =
g_type_get_qdata (G_TYPE_FROM_CLASS (element_class),
- _gst_elementclass_factory);
+ __gst_elementclass_factory);
GST_DEBUG ("type %s : factory %p", G_OBJECT_CLASS_NAME (element_class),
element_class->elementfactory);
}
g_list_foreach (klass->padtemplates, (GFunc) gst_object_unref, NULL);
g_list_free (klass->padtemplates);
- __gst_element_details_clear (&klass->details);
- if (klass->meta_data) {
- gst_structure_free (klass->meta_data);
- klass->meta_data = NULL;
- }
+
+ gst_structure_free (klass->metadata);
}
static void
GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING;
GST_STATE_RETURN (element) = GST_STATE_CHANGE_SUCCESS;
- /* FIXME 0.11: Store this directly in the instance struct */
- element->state_lock = g_slice_new (GStaticRecMutex);
- 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);
}
/**
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);
}
/**
- * 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;
}
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 */
/* ERRORS */
not_our_pad:
{
- /* FIXME, locking order? */
+ /* locking order is element > pad */
+ GST_OBJECT_UNLOCK (pad);
+
GST_OBJECT_LOCK (element);
+ GST_OBJECT_LOCK (pad);
g_critical ("Padname %s:%s does not belong to element %s when removing",
GST_DEBUG_PAD_NAME (pad), GST_ELEMENT_NAME (element));
- GST_OBJECT_UNLOCK (element);
GST_OBJECT_UNLOCK (pad);
+ GST_OBJECT_UNLOCK (element);
return FALSE;
}
}
}
#endif
- if (oclass->request_new_pad_full)
- newpad = (oclass->request_new_pad_full) (element, templ, name, caps);
- else if (oclass->request_new_pad)
- newpad = (oclass->request_new_pad) (element, templ, name);
+ if (oclass->request_new_pad)
+ newpad = (oclass->request_new_pad) (element, templ, name, caps);
if (newpad)
gst_object_ref (newpad);
* 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.
return _gst_element_request_pad (element, templ, name, caps);
}
-/**
- * gst_element_get_pad:
- * @element: a #GstElement.
- * @name: the name of the pad to retrieve.
- *
- * Retrieves a pad from @element by name. Tries gst_element_get_static_pad()
- * first, then gst_element_get_request_pad().
- *
- * Deprecated: This function is deprecated as it's unclear if the reference
- * to the result pad should be released with gst_object_unref() in case of a static pad
- * or gst_element_release_request_pad() in case of a request pad.
- * Use gst_element_get_static_pad() or gst_element_get_request_pad() instead.
- *
- * Returns: (transfer full): the #GstPad if found, otherwise %NULL. Unref or Release after usage,
- * depending on the type of the pad.
- */
-#ifndef GST_REMOVE_DEPRECATED
-#ifdef GST_DISABLE_DEPRECATED
-GstPad *gst_element_get_pad (GstElement * element, const gchar * name);
-#endif
-GstPad *
-gst_element_get_pad (GstElement * element, const gchar * name)
-{
- GstPad *pad;
-
- g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
- g_return_val_if_fail (name != NULL, NULL);
-
- pad = gst_element_get_static_pad (element, name);
- if (!pad)
- pad = gst_element_get_request_pad (element, name);
-
- return pad;
-}
-#endif /* GST_REMOVE_DEPRECATED */
-
-static GstIteratorItem
-iterate_pad (GstIterator * it, GstPad * pad)
-{
- gst_object_ref (pad);
- return GST_ITERATOR_ITEM_PASS;
-}
-
static GstIterator *
gst_element_iterate_pad_list (GstElement * element, GList ** padlist)
{
GstIterator *result;
GST_OBJECT_LOCK (element);
- gst_object_ref (element);
result = gst_iterator_new_list (GST_TYPE_PAD,
GST_OBJECT_GET_LOCK (element),
- &element->pads_cookie,
- padlist,
- element,
- (GstIteratorItemFunction) iterate_pad,
- (GstIteratorDisposeFunction) gst_object_unref);
+ &element->pads_cookie, padlist, (GObject *) element, NULL);
GST_OBJECT_UNLOCK (element);
return result;
/**
* gst_element_class_add_pad_template:
* @klass: the #GstElementClass to add the pad template to.
- * @templ: (transfer none): a #GstPadTemplate to add to the element class.
+ * @templ: (transfer full): a #GstPadTemplate to add to the element class.
+ *
+ * Adds a padtemplate to an element class. This is mainly used in the _class_init
+ * functions of classes. If a pad template with the same name as an already
+ * existing one is added the old one is replaced by the new one.
*
- * Adds a padtemplate to an element class. This is mainly used in the _base_init
- * functions of classes.
*/
void
gst_element_class_add_pad_template (GstElementClass * klass,
GstPadTemplate * templ)
{
- g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
- g_return_if_fail (GST_IS_PAD_TEMPLATE (templ));
-
- /* FIXME 0.11: allow replacing the pad templates by
- * calling this with the same name as an already existing pad
- * template. For this we _must_ _not_ ref the added pad template
- * a second time and _must_ document that this function takes
- * ownership of the pad template. Otherwise we will leak pad templates
- * or the caller unref's the pad template and it disappears */
- /* avoid registering pad templates with the same name */
- g_return_if_fail (gst_element_class_get_pad_template (klass,
- templ->name_template) == NULL);
-
- klass->padtemplates = g_list_append (klass->padtemplates,
- gst_object_ref (templ));
- klass->numpadtemplates++;
-}
-
-/**
- * gst_element_class_add_static_pad_template:
- * @klass: the #GstElementClass to add the pad template to.
- * @templ: (transfer none): a #GstStaticPadTemplate describing the pad
- * to add to the element class.
- *
- * Adds a padtemplate to an element class. This is mainly used in the _base_init
- * functions of classes.
- *
- * Since: 0.10.36
- */
-void
-gst_element_class_add_static_pad_template (GstElementClass * klass,
- GstStaticPadTemplate * templ)
-{
- GstPadTemplate *pt;
+ GList *template_list = klass->padtemplates;
g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
+ g_return_if_fail (GST_IS_PAD_TEMPLATE (templ));
- pt = gst_static_pad_template_get (templ);
- gst_element_class_add_pad_template (klass, pt);
- gst_object_unref (pt);
-}
+ /* If we already have a pad template with the same name replace the
+ * old one. */
+ while (template_list) {
+ GstPadTemplate *padtempl = (GstPadTemplate *) template_list->data;
-static void
-gst_element_class_add_meta_data (GstElementClass * klass,
- const gchar * key, const gchar * value)
-{
- if (!klass->meta_data) {
- /* FIXME: use a quark for "metadata" */
- klass->meta_data = gst_structure_empty_new ("metadata");
+ /* Found pad with the same name, replace and return */
+ if (strcmp (templ->name_template, padtempl->name_template) == 0) {
+ gst_object_unref (padtempl);
+ template_list->data = templ;
+ return;
+ }
+ template_list = g_list_next (template_list);
}
- gst_structure_set ((GstStructure *) klass->meta_data,
- key, G_TYPE_STRING, value, NULL);
-}
+ /* Take ownership of the floating ref */
+ gst_object_ref_sink (templ);
-/**
- * gst_element_class_set_documentation_uri:
- * @klass: class to set details for
- * @uri: uri of element documentation
- *
- * Set uri pointing to user documentation. Applications can use this to show
- * help for e.g. effects to users.
- *
- * Since: 0.10.31
- */
-void
-gst_element_class_set_documentation_uri (GstElementClass * klass,
- const gchar * uri)
-{
- g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
-
- gst_element_class_add_meta_data (klass, "doc-uri", uri);
+ klass->padtemplates = g_list_append (klass->padtemplates, templ);
+ klass->numpadtemplates++;
}
/**
- * gst_element_class_set_icon_name:
- * @klass: class to set details for
- * @name: name of an icon
- *
- * Elements that bridge to certain other products can include an icon of that
- * used product. Application can show the icon in menus/selectors to help
- * identifying specific elements.
+ * gst_element_class_add_metadata:
+ * @klass: class to set metadata for
+ * @key: the key to set
+ * @value: the value to set
*
- * Since: 0.10.31
+ * Set @key with @value as metadata in @klass.
*/
void
-gst_element_class_set_icon_name (GstElementClass * klass, const gchar * name)
-{
- g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
-
- gst_element_class_add_meta_data (klass, "icon-name", name);
-}
-
-/* FIXME-0.11: deprecate and remove gst_element_class_set_details*() */
-/**
- * gst_element_class_set_details:
- * @klass: class to set details for
- * @details: details to set
- *
- * Sets the detailed information for a #GstElementClass.
- * <note>This function is for use in _base_init functions only.</note>
- *
- * The @details are copied.
- *
- * Deprecated: Use gst_element_class_set_details_simple() instead.
- */
-#ifndef GST_REMOVE_DEPRECATED
-#ifdef GST_DISABLE_DEPRECATED
-void gst_element_class_set_details (GstElementClass * klass,
- const GstElementDetails * details);
-#endif
-void
-gst_element_class_set_details (GstElementClass * klass,
- const GstElementDetails * details)
+gst_element_class_add_metadata (GstElementClass * klass,
+ const gchar * key, const gchar * value)
{
g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
- g_return_if_fail (GST_IS_ELEMENT_DETAILS (details));
+ g_return_if_fail (key != NULL);
+ g_return_if_fail (value != NULL);
- __gst_element_details_copy (&klass->details, details);
+ gst_structure_set ((GstStructure *) klass->metadata,
+ key, G_TYPE_STRING, value, NULL);
}
-#endif
/**
- * gst_element_class_set_details_simple:
- * @klass: class to set details for
+ * gst_element_class_set_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
* @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 details. E.g: "Joe Bloggs <joe.blogs at foo.com>"
- *
- * Sets the detailed information for a #GstElementClass. Simpler version of
- * gst_element_class_set_details() that generates less linker overhead.
- * <note>This function is for use in _base_init functions only.</note>
+ * multiple author metadata. E.g: "Joe Bloggs <joe.blogs at foo.com>"
*
- * The detail parameter strings are copied into the #GstElementDetails for
- * the element class.
- *
- * Since: 0.10.14
+ * Sets the detailed information for a #GstElementClass.
+ * <note>This function is for use in _class_init functions only.</note>
*/
void
-gst_element_class_set_details_simple (GstElementClass * klass,
+gst_element_class_set_metadata (GstElementClass * klass,
const gchar * longname, const gchar * classification,
const gchar * description, const gchar * author)
{
- const GstElementDetails details =
- GST_ELEMENT_DETAILS ((gchar *) longname, (gchar *) classification,
- (gchar *) description, (gchar *) author);
-
g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
- __gst_element_details_copy (&klass->details, &details);
+ 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_element_class_get_metadata:
+ * @klass: class to get metadata for
+ * @key: the key to get
+ *
+ * Get metadata with @key in @klass.
+ *
+ * Returns: the metadata for @key.
+ */
+const gchar *
+gst_element_class_get_metadata (GstElementClass * klass, const gchar * key)
+{
+ g_return_val_if_fail (GST_IS_ELEMENT_CLASS (klass), NULL);
+ g_return_val_if_fail (key != NULL, NULL);
+
+ return gst_structure_get_string ((GstStructure *) klass->metadata, key);
}
/**
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);
return result;
}
-/**
- * gst_element_get_query_types:
- * @element: a #GstElement to query
- *
- * Get an array of query types from the element.
- * If the element doesn't implement a query types function,
- * the query will be forwarded to the peer of a random linked sink pad.
- *
- * Returns: An array of #GstQueryType elements that should not
- * be freed or modified.
- *
- * MT safe.
- */
-const GstQueryType *
-gst_element_get_query_types (GstElement * element)
-{
- GstElementClass *oclass;
- const GstQueryType *result = NULL;
-
- g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
-
- oclass = GST_ELEMENT_GET_CLASS (element);
-
- if (oclass->get_query_types) {
- result = oclass->get_query_types (element);
- } else {
- GstPad *pad = gst_element_get_random_pad (element, TRUE, GST_PAD_SINK);
-
- if (pad) {
- GstPad *peer = gst_pad_get_peer (pad);
-
- if (peer) {
- result = gst_pad_get_query_types (peer);
-
- gst_object_unref (peer);
- }
- gst_object_unref (pad);
- }
- }
- return result;
-}
-
static gboolean
gst_element_default_query (GstElement * element, GstQuery * 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 result;
}
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;
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);
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;
}
/**
- * gst_element_lost_state_full:
+ * gst_element_lost_state:
* @element: a #GstElement the state is lost of
- * @new_base_time: if a new base time should be distributed
*
* Brings the element to the lost state. The current state of the
* element is copied to the pending state so that any call to
* gst_element_get_state() will return %GST_STATE_CHANGE_ASYNC.
*
- * An ASYNC_START message is posted with indication to distribute a new
- * base_time to the element when @new_base_time is %TRUE.
- * If the element was PLAYING, it will go to PAUSED. The element
- * will be restored to its PLAYING state by the parent pipeline when it
- * prerolls again.
+ * An ASYNC_START message is posted. If the element was PLAYING, it will
+ * go to PAUSED. The element will be restored to its PLAYING state by
+ * the parent pipeline when it prerolls again.
*
* This is mostly used for elements that lost their preroll buffer
* in the %GST_STATE_PAUSED or %GST_STATE_PLAYING state after a flush,
*
* This function is used internally and should normally not be called from
* plugins or applications.
- *
- * MT safe.
- *
- * Since: 0.10.24
*/
void
-gst_element_lost_state_full (GstElement * element, gboolean new_base_time)
+gst_element_lost_state (GstElement * element)
{
GstState old_state, new_state;
GstMessage *message;
GST_STATE_NEXT (element) = new_state;
GST_STATE_PENDING (element) = new_state;
GST_STATE_RETURN (element) = GST_STATE_CHANGE_ASYNC;
- if (new_base_time)
- GST_ELEMENT_START_TIME (element) = 0;
GST_OBJECT_UNLOCK (element);
_priv_gst_element_state_changed (element, new_state, new_state, new_state);
- message =
- gst_message_new_async_start (GST_OBJECT_CAST (element), new_base_time);
+ message = gst_message_new_async_start (GST_OBJECT_CAST (element));
gst_element_post_message (element, message);
return;
{
GST_OBJECT_UNLOCK (element);
- message = gst_message_new_async_start (GST_OBJECT_CAST (element), TRUE);
+ message = gst_message_new_async_start (GST_OBJECT_CAST (element));
gst_element_post_message (element, message);
return;
}
}
/**
- * gst_element_lost_state:
- * @element: a #GstElement the state is lost of
- *
- * Brings the element to the lost state. This function calls
- * gst_element_lost_state_full() with the new_base_time set to %TRUE.
- *
- * This function is used internally and should normally not be called from
- * plugins or applications.
- *
- * MT safe.
- */
-void
-gst_element_lost_state (GstElement * element)
-{
- gst_element_lost_state_full (element, TRUE);
-}
-
-/**
* gst_element_set_state:
* @element: a #GstElement to change state of.
* @state: the element's new #GstState.
/* gst_iterator_fold functions for pads_activate
* Stop the iterator if activating one pad failed. */
static gboolean
-activate_pads (GstPad * pad, GValue * ret, gboolean * active)
+activate_pads (const GValue * vpad, GValue * ret, gboolean * active)
{
+ GstPad *pad = g_value_get_object (vpad);
gboolean cont = TRUE;
if (!(cont = gst_pad_set_active (pad, *active)))
g_value_set_boolean (ret, FALSE);
- /* unref the object that was reffed for us by _fold */
- gst_object_unref (pad);
return cont;
}
-/* set the caps on the pad to NULL */
-static gboolean
-clear_caps (GstPad * pad, GValue * ret, gboolean * active)
-{
- gst_pad_set_caps (pad, NULL);
- gst_object_unref (pad);
- return TRUE;
-}
-
/* returns false on error or early cutout of the fold, true if all
* pads in @iter were (de)activated successfully. */
static gboolean
if (G_UNLIKELY (!res))
goto sink_failed;
- if (!active) {
- /* clear the caps on all pads, this should never fail */
- iter = gst_element_iterate_pads (element);
- res =
- iterator_activate_fold_with_resync (iter,
- (GstIteratorFoldFunction) clear_caps, &active);
- gst_iterator_free (iter);
- if (G_UNLIKELY (!res))
- goto caps_failed;
- }
-
GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element,
"pads_activate successful");
"sink pads_activate failed");
return FALSE;
}
-caps_failed:
- {
- GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element,
- "failed to clear caps on pads");
- return FALSE;
- }
}
/* is called with STATE_LOCK */
{
GstState state, next;
GstStateChangeReturn result = GST_STATE_CHANGE_SUCCESS;
- GstClock **clock_p;
g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_CHANGE_FAILURE);
ready->paused but the element might not have made it to paused */
if (!gst_element_pads_activate (element, FALSE)) {
result = GST_STATE_CHANGE_FAILURE;
- } else {
- gst_element_set_base_time (element, 0);
}
-
- /* In null state release the reference to the clock */
- GST_OBJECT_LOCK (element);
- clock_p = &element->clock;
- gst_object_replace ((GstObject **) clock_p, NULL);
- GST_OBJECT_UNLOCK (element);
break;
default:
/* this will catch real but unhandled state changes;
GstElement *element = GST_ELEMENT_CAST (object);
GstClock **clock_p;
GstBus **bus_p;
+ GstElementClass *oclass;
+
+ oclass = GST_ELEMENT_GET_CLASS (element);
GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "dispose");
"removing %d pads", g_list_length (element->pads));
/* first we break all our links with the outside */
while (element->pads && element->pads->data) {
+ GstPad *pad = GST_PAD_CAST (element->pads->data);
+
/* don't call _remove_pad with NULL */
- gst_element_remove_pad (element, GST_PAD_CAST (element->pads->data));
+ if (oclass->release_pad && GST_PAD_PAD_TEMPLATE (pad) &&
+ GST_PAD_TEMPLATE_PRESENCE (GST_PAD_PAD_TEMPLATE (pad))
+ == GST_PAD_REQUEST)
+ (oclass->release_pad) (element, GST_PAD_CAST (element->pads->data));
+ else
+ gst_element_remove_pad (element, GST_PAD_CAST (element->pads->data));
}
if (G_UNLIKELY (element->pads != NULL)) {
g_critical ("could not remove pads from element %s",
{
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");
- GST_STATE_LOCK (element);
- if (element->state_cond)
- g_cond_free (element->state_cond);
- element->state_cond = NULL;
- GST_STATE_UNLOCK (element);
- g_static_rec_mutex_free (element->state_lock);
- g_slice_free (GStaticRecMutex, element->state_lock);
- element->state_lock = NULL;
+ g_cond_clear (&element->state_cond);
+ g_rec_mutex_clear (&element->state_lock);
GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "finalize parent");
G_OBJECT_CLASS (parent_class)->finalize (object);
}
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
-/**
- * gst_element_save_thyself:
- * @element: a #GstElement to save.
- * @parent: the xml parent node.
- *
- * Saves the element as part of the given XML structure.
- *
- * Returns: the new #xmlNodePtr.
- */
-static xmlNodePtr
-gst_element_save_thyself (GstObject * object, xmlNodePtr parent)
-{
- GList *pads;
- GstElementClass *oclass;
- GParamSpec **specs, *spec;
- guint nspecs;
- guint i;
- GValue value = { 0, };
- GstElement *element;
-
- g_return_val_if_fail (GST_IS_ELEMENT (object), parent);
-
- element = GST_ELEMENT_CAST (object);
-
- oclass = GST_ELEMENT_GET_CLASS (element);
-
- xmlNewChild (parent, NULL, (xmlChar *) "name",
- (xmlChar *) GST_ELEMENT_NAME (element));
-
- if (oclass->elementfactory != NULL) {
- GstElementFactory *factory = (GstElementFactory *) oclass->elementfactory;
-
- xmlNewChild (parent, NULL, (xmlChar *) "type",
- (xmlChar *) GST_PLUGIN_FEATURE (factory)->name);
- }
-
- /* params */
- specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (object), &nspecs);
-
- for (i = 0; i < nspecs; i++) {
- spec = specs[i];
- if (spec->flags & G_PARAM_READABLE) {
- xmlNodePtr param;
- char *contents;
-
- g_value_init (&value, spec->value_type);
-
- g_object_get_property (G_OBJECT (element), spec->name, &value);
- param = xmlNewChild (parent, NULL, (xmlChar *) "param", NULL);
- xmlNewChild (param, NULL, (xmlChar *) "name", (xmlChar *) spec->name);
-
- if (G_IS_PARAM_SPEC_STRING (spec))
- contents = g_value_dup_string (&value);
- else if (G_IS_PARAM_SPEC_ENUM (spec))
- contents = g_strdup_printf ("%d", g_value_get_enum (&value));
- else if (G_IS_PARAM_SPEC_INT64 (spec))
- contents = g_strdup_printf ("%" G_GINT64_FORMAT,
- g_value_get_int64 (&value));
- else if (GST_VALUE_HOLDS_STRUCTURE (&value)) {
- if (g_value_get_boxed (&value) != NULL) {
- contents = g_strdup_value_contents (&value);
- } else {
- contents = g_strdup ("NULL");
- }
- } else
- contents = g_strdup_value_contents (&value);
-
- xmlNewChild (param, NULL, (xmlChar *) "value", (xmlChar *) contents);
- g_free (contents);
-
- g_value_unset (&value);
- }
- }
-
- g_free (specs);
-
- pads = g_list_last (GST_ELEMENT_PADS (element));
-
- while (pads) {
- GstPad *pad = GST_PAD_CAST (pads->data);
-
- /* figure out if it's a direct pad or a ghostpad */
- if (GST_ELEMENT_CAST (GST_OBJECT_PARENT (pad)) == element) {
- xmlNodePtr padtag = xmlNewChild (parent, NULL, (xmlChar *) "pad", NULL);
-
- gst_object_save_thyself (GST_OBJECT_CAST (pad), padtag);
- }
- pads = g_list_previous (pads);
- }
-
- return parent;
-}
-
-static void
-gst_element_restore_thyself (GstObject * object, xmlNodePtr self)
-{
- xmlNodePtr children;
- GstElement *element;
- gchar *name = NULL;
- gchar *value = NULL;
-
- element = GST_ELEMENT_CAST (object);
- g_return_if_fail (element != NULL);
-
- /* parameters */
- children = self->xmlChildrenNode;
- while (children) {
- if (!strcmp ((char *) children->name, "param")) {
- xmlNodePtr child = children->xmlChildrenNode;
-
- while (child) {
- if (!strcmp ((char *) child->name, "name")) {
- name = (gchar *) xmlNodeGetContent (child);
- } else if (!strcmp ((char *) child->name, "value")) {
- value = (gchar *) xmlNodeGetContent (child);
- }
- child = child->next;
- }
- /* FIXME: can this just be g_object_set ? */
- gst_util_set_object_arg (G_OBJECT (element), name, value);
- /* g_object_set (G_OBJECT (element), name, value, NULL); */
- g_free (name);
- g_free (value);
- }
- children = children->next;
- }
-
- /* pads */
- children = self->xmlChildrenNode;
- while (children) {
- if (!strcmp ((char *) children->name, "pad")) {
- gst_pad_load_and_link (children, GST_OBJECT_CAST (element));
- }
- children = children->next;
- }
-
- if (GST_OBJECT_CLASS (parent_class)->restore_thyself)
- (GST_OBJECT_CLASS (parent_class)->restore_thyself) (object, self);
-}
-#endif /* GST_DISABLE_LOADSAVE */
-
static void
gst_element_set_bus_func (GstElement * element, GstBus * bus)
{