2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 * 2000 Wim Taymans <wtay@chello.be>
5 * gstelement.c: The base element, all elements derive from this
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
23 /* #define GST_DEBUG_ENABLED */
26 #include <gobject/gvaluecollector.h>
27 #include "gst_private.h"
29 #include "gstelement.h"
30 #include "gstextratypes.h"
32 #include "gstscheduler.h"
37 /* Element signals and args */
53 #define CLASS(element) GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS (element))
55 static void gst_element_class_init (GstElementClass *klass);
56 static void gst_element_init (GstElement *element);
57 static void gst_element_base_class_init (GstElementClass *klass);
59 static void gst_element_real_set_property (GObject *object, guint prop_id,
60 const GValue *value, GParamSpec *pspec);
61 static void gst_element_real_get_property (GObject *object, guint prop_id, GValue *value,
63 static void gst_element_dispatch_properties_changed (GObject * object, guint n_pspecs, GParamSpec **pspecs);
65 static void gst_element_dispose (GObject *object);
67 static gboolean gst_element_send_event_default (GstElement *element, GstEvent *event);
68 static gboolean gst_element_query_default (GstElement *element, GstPadQueryType type,
69 GstFormat *format, gint64 *value);
71 static GstElementStateReturn gst_element_change_state (GstElement *element);
72 static void gst_element_error_func (GstElement* element, GstElement *source, gchar *errormsg);
74 #ifndef GST_DISABLE_LOADSAVE
75 static xmlNodePtr gst_element_save_thyself (GstObject *object, xmlNodePtr parent);
76 static void gst_element_restore_thyself (GstObject *parent, xmlNodePtr self);
79 GType _gst_element_type = 0;
81 static GstObjectClass *parent_class = NULL;
82 static guint gst_element_signals[LAST_SIGNAL] = { 0 };
84 GType gst_element_get_type (void)
86 if (!_gst_element_type) {
87 static const GTypeInfo element_info = {
88 sizeof(GstElementClass),
89 (GBaseInitFunc)gst_element_base_class_init,
91 (GClassInitFunc)gst_element_class_init,
96 (GInstanceInitFunc)gst_element_init,
99 _gst_element_type = g_type_register_static(GST_TYPE_OBJECT, "GstElement",
100 &element_info, G_TYPE_FLAG_ABSTRACT);
102 return _gst_element_type;
106 gst_element_class_init (GstElementClass *klass)
108 GObjectClass *gobject_class;
109 GstObjectClass *gstobject_class;
111 gobject_class = (GObjectClass*) klass;
112 gstobject_class = (GstObjectClass*) klass;
114 parent_class = g_type_class_ref(GST_TYPE_OBJECT);
116 gst_element_signals[STATE_CHANGE] =
117 g_signal_new ("state_change", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
118 G_STRUCT_OFFSET (GstElementClass, state_change), NULL, NULL,
119 gst_marshal_VOID__INT_INT, G_TYPE_NONE, 2,
120 G_TYPE_INT, G_TYPE_INT);
121 gst_element_signals[NEW_PAD] =
122 g_signal_new ("new_pad", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
123 G_STRUCT_OFFSET (GstElementClass, new_pad), NULL, NULL,
124 gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
126 gst_element_signals[PAD_REMOVED] =
127 g_signal_new ("pad_removed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
128 G_STRUCT_OFFSET (GstElementClass, pad_removed), NULL, NULL,
129 gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
131 gst_element_signals[ERROR] =
132 g_signal_new ("error", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
133 G_STRUCT_OFFSET (GstElementClass, error), NULL, NULL,
134 gst_marshal_VOID__OBJECT_STRING, G_TYPE_NONE, 2,
135 G_TYPE_OBJECT, G_TYPE_STRING);
136 gst_element_signals[EOS] =
137 g_signal_new ("eos", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
138 G_STRUCT_OFFSET (GstElementClass,eos), NULL, NULL,
139 gst_marshal_VOID__VOID, G_TYPE_NONE, 0);
140 gst_element_signals[DEEP_NOTIFY] =
141 g_signal_new ("deep_notify", G_TYPE_FROM_CLASS (klass),
142 G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_DETAILED | G_SIGNAL_NO_HOOKS,
143 G_STRUCT_OFFSET (GstElementClass, deep_notify), NULL, NULL,
144 gst_marshal_VOID__OBJECT_PARAM, G_TYPE_NONE,
145 2, G_TYPE_OBJECT, G_TYPE_PARAM);
148 gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_element_real_set_property);
149 gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_element_real_get_property);
151 /* see the comments at gst_element_dispatch_properties_changed */
152 gobject_class->dispatch_properties_changed
153 = GST_DEBUG_FUNCPTR (gst_element_dispatch_properties_changed);
155 gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_element_dispose);
157 #ifndef GST_DISABLE_LOADSAVE
158 gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_element_save_thyself);
159 gstobject_class->restore_thyself = GST_DEBUG_FUNCPTR (gst_element_restore_thyself);
162 klass->change_state = GST_DEBUG_FUNCPTR (gst_element_change_state);
163 klass->error = GST_DEBUG_FUNCPTR (gst_element_error_func);
164 klass->elementfactory = NULL;
165 klass->padtemplates = NULL;
166 klass->numpadtemplates = 0;
167 klass->send_event = GST_DEBUG_FUNCPTR (gst_element_send_event_default);
168 klass->query = GST_DEBUG_FUNCPTR (gst_element_query_default);
172 gst_element_base_class_init (GstElementClass *klass)
174 GObjectClass *gobject_class;
176 gobject_class = (GObjectClass*) klass;
178 gobject_class->set_property = GST_DEBUG_FUNCPTR(gst_element_real_set_property);
179 gobject_class->get_property = GST_DEBUG_FUNCPTR(gst_element_real_get_property);
183 gst_element_init (GstElement *element)
185 element->current_state = GST_STATE_NULL;
186 element->pending_state = GST_STATE_VOID_PENDING;
187 element->numpads = 0;
188 element->numsrcpads = 0;
189 element->numsinkpads = 0;
190 element->pads = NULL;
191 element->loopfunc = NULL;
192 element->sched = NULL;
193 element->clock = NULL;
194 element->sched_private = NULL;
195 element->state_mutex = g_mutex_new ();
196 element->state_cond = g_cond_new ();
200 gst_element_real_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
202 GstElementClass *oclass = CLASS (object);
204 if (oclass->set_property)
205 (oclass->set_property) (object, prop_id, value, pspec);
209 gst_element_real_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
211 GstElementClass *oclass = CLASS (object);
213 if (oclass->get_property)
214 (oclass->get_property) (object, prop_id, value, pspec);
217 /* Changing a GObject property of an element will result in "deep_notify"
218 * signals being emitted by the element itself, as well as in each parent
219 * element. This is so that an application can connect a listener to the
220 * top-level bin to catch property-change notifications for all contained
223 gst_element_dispatch_properties_changed (GObject *object,
227 GstObject *gst_object;
230 /* do the standard dispatching */
231 G_OBJECT_CLASS (parent_class)->dispatch_properties_changed (object, n_pspecs, pspecs);
233 /* now let the parent dispatch those, too */
234 gst_object = GST_OBJECT_PARENT (object);
236 /* need own category? */
237 for (i = 0; i < n_pspecs; i++) {
238 GST_DEBUG (GST_CAT_EVENT, "deep notification from %s to %s (%s)", GST_OBJECT_NAME (object),
239 GST_OBJECT_NAME (gst_object), pspecs[i]->name);
240 g_signal_emit (gst_object, gst_element_signals[DEEP_NOTIFY], g_quark_from_string (pspecs[i]->name),
241 (GstObject *) object, pspecs[i]);
244 gst_object = GST_OBJECT_PARENT (gst_object);
249 * gst_element_default_deep_notify:
250 * @object: the #GObject that signalled the notify.
251 * @orig: a #GstObject that initiated the notify.
252 * @pspec: a #GParamSpec of the property.
253 * @excluded_props: a set of user-specified properties to exclude.
255 * Adds a default deep_notify signal callback to an
256 * element. The user data should contain a pointer to an array of
257 * strings that should be excluded from the notify.
258 * The default handler will print the new value of the property
262 gst_element_default_deep_notify (GObject *object, GstObject *orig,
263 GParamSpec *pspec, gchar **excluded_props)
265 GValue value = { 0, }; /* the important thing is that value.type = 0 */
268 if (pspec->flags & G_PARAM_READABLE) {
269 /* let's not print these out for excluded properties... */
270 while (excluded_props != NULL && *excluded_props != NULL) {
271 if (strcmp (pspec->name, *excluded_props) == 0)
275 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
276 g_object_get_property (G_OBJECT (orig), pspec->name, &value);
278 if (G_IS_PARAM_SPEC_ENUM (pspec)) {
279 GEnumValue *enum_value;
280 enum_value = g_enum_get_value (G_ENUM_CLASS (g_type_class_ref (pspec->value_type)),
281 g_value_get_enum (&value));
283 str = g_strdup_printf ("%s (%d)", enum_value->value_nick,
287 str = g_strdup_value_contents (&value);
289 g_print ("%s: %s = %s\n", GST_OBJECT_NAME (orig), pspec->name, str);
291 g_value_unset (&value);
293 g_warning ("Parameter %s not readable in %s.",
294 pspec->name, GST_OBJECT_NAME (orig));
299 * gst_element_default_error:
300 * @object: a #GObject that signalled the error.
301 * @orig: the #GstObject that initiated the error.
302 * @error: the error message.
304 * Adds a default error signal callback to an
305 * element. The user data passed to the g_signal_connect is
307 * The default handler will simply print the error string
311 gst_element_default_error (GObject *object, GstObject *orig, gchar *error)
313 g_print ("ERROR: %s: %s\n", GST_OBJECT_NAME (orig), error);
317 const GParamSpec *pspec;
322 element_set_property (GstElement *element, const GParamSpec *pspec, const GValue *value)
324 prop_value_t *prop_value = g_new0 (prop_value_t, 1);
326 prop_value->pspec = pspec;
327 prop_value->value = *value;
329 g_async_queue_push (element->prop_value_queue, prop_value);
333 element_get_property (GstElement *element, const GParamSpec *pspec, GValue *value)
335 g_mutex_lock (element->property_mutex);
336 g_object_get_property ((GObject*)element, pspec->name, value);
337 g_mutex_unlock (element->property_mutex);
341 gst_element_threadsafe_properties_pre_run (GstElement *element)
343 GST_DEBUG (GST_CAT_THREAD, "locking element %s", GST_OBJECT_NAME (element));
344 g_mutex_lock (element->property_mutex);
345 gst_element_set_pending_properties (element);
349 gst_element_threadsafe_properties_post_run (GstElement *element)
351 GST_DEBUG (GST_CAT_THREAD, "unlocking element %s", GST_OBJECT_NAME (element));
352 g_mutex_unlock (element->property_mutex);
356 * gst_element_enable_threadsafe_properties:
357 * @element: a #GstElement to enable threadsafe properties on.
359 * Installs an asynchronous queue, a mutex and pre- and post-run functions on
360 * this element so that properties on the element can be set in a
364 gst_element_enable_threadsafe_properties (GstElement *element)
366 g_return_if_fail (GST_IS_ELEMENT (element));
368 GST_FLAG_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES);
369 element->pre_run_func = gst_element_threadsafe_properties_pre_run;
370 element->post_run_func = gst_element_threadsafe_properties_post_run;
371 if (!element->prop_value_queue)
372 element->prop_value_queue = g_async_queue_new ();
373 if (!element->property_mutex)
374 element->property_mutex = g_mutex_new ();
378 * gst_element_disable_threadsafe_properties:
379 * @element: a #GstElement to disable threadsafe properties on.
381 * Removes the threadsafe properties, post- and pre-run locks from
385 gst_element_disable_threadsafe_properties (GstElement *element)
387 g_return_if_fail (GST_IS_ELEMENT (element));
389 GST_FLAG_UNSET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES);
390 element->pre_run_func = NULL;
391 element->post_run_func = NULL;
392 /* let's keep around that async queue */
396 * gst_element_set_pending_properties:
397 * @element: a #GstElement to set the pending properties on.
399 * Sets all pending properties on the threadsafe properties enabled
403 gst_element_set_pending_properties (GstElement *element)
405 prop_value_t *prop_value;
407 while ((prop_value = g_async_queue_try_pop (element->prop_value_queue))) {
408 g_object_set_property ((GObject*)element, prop_value->pspec->name, &prop_value->value);
409 g_value_unset (&prop_value->value);
414 /* following 6 functions taken mostly from gobject.c */
418 * @element: a #GstElement to set properties on.
419 * @first_property_name: the first property to set.
420 * @...: value of the first property, and more properties to set, ending
423 * Sets properties on an element. If the element uses threadsafe properties,
424 * they will be queued and set on the object when it is scheduled again.
427 gst_element_set (GstElement *element, const gchar *first_property_name, ...)
431 g_return_if_fail (GST_IS_ELEMENT (element));
433 va_start (var_args, first_property_name);
434 gst_element_set_valist (element, first_property_name, var_args);
440 * @element: a #GstElement to get properties of.
441 * @first_property_name: the first property to get.
442 * @...: pointer to a variable to store the first property in, as well as
443 * more properties to get, ending with NULL.
445 * Gets properties from an element. If the element uses threadsafe properties,
446 * the element will be locked before getting the given properties.
449 gst_element_get (GstElement *element, const gchar *first_property_name, ...)
453 g_return_if_fail (GST_IS_ELEMENT (element));
455 va_start (var_args, first_property_name);
456 gst_element_get_valist (element, first_property_name, var_args);
461 * gst_element_set_valist:
462 * @element: a #GstElement to set properties on.
463 * @first_property_name: the first property to set.
464 * @var_args: the var_args list of other properties to get.
466 * Sets properties on an element. If the element uses threadsafe properties,
467 * the property change will be put on the async queue.
470 gst_element_set_valist (GstElement *element, const gchar *first_property_name, va_list var_args)
475 g_return_if_fail (GST_IS_ELEMENT (element));
477 object = (GObject *) element;
479 GST_DEBUG (GST_CAT_PROPERTIES,
480 "setting valist of properties starting with %s on element %s",
481 first_property_name, gst_element_get_name (element));
483 if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
484 g_object_set_valist (object, first_property_name, var_args);
488 g_object_ref (object);
490 name = first_property_name;
494 GValue value = { 0, };
498 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), name);
502 g_warning ("%s: object class `%s' has no property named `%s'",
504 G_OBJECT_TYPE_NAME (object),
508 if (!(pspec->flags & G_PARAM_WRITABLE))
510 g_warning ("%s: property `%s' of object class `%s' is not writable",
513 G_OBJECT_TYPE_NAME (object));
517 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
519 G_VALUE_COLLECT (&value, var_args, 0, &error);
522 g_warning ("%s: %s", G_STRLOC, error);
525 /* we purposely leak the value here, it might not be
526 * in a sane state if an error condition occoured
531 element_set_property (element, pspec, &value);
532 g_value_unset (&value);
534 name = va_arg (var_args, gchar*);
537 g_object_unref (object);
541 * gst_element_get_valist:
542 * @element: a #GstElement to get properties of.
543 * @first_property_name: the first property to get.
544 * @var_args: the var_args list of other properties to get.
546 * Gets properties from an element. If the element uses threadsafe properties,
547 * the element will be locked before getting the given properties.
550 gst_element_get_valist (GstElement *element, const gchar *first_property_name, va_list var_args)
555 g_return_if_fail (GST_IS_ELEMENT (element));
557 object = (GObject*)element;
559 if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
560 g_object_get_valist (object, first_property_name, var_args);
564 g_object_ref (object);
566 name = first_property_name;
570 GValue value = { 0, };
574 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), name);
578 g_warning ("%s: object class `%s' has no property named `%s'",
580 G_OBJECT_TYPE_NAME (object),
584 if (!(pspec->flags & G_PARAM_READABLE))
586 g_warning ("%s: property `%s' of object class `%s' is not readable",
589 G_OBJECT_TYPE_NAME (object));
593 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
595 element_get_property (element, pspec, &value);
597 G_VALUE_LCOPY (&value, var_args, 0, &error);
600 g_warning ("%s: %s", G_STRLOC, error);
602 g_value_unset (&value);
606 g_value_unset (&value);
608 name = va_arg (var_args, gchar*);
611 g_object_unref (object);
615 * gst_element_set_property:
616 * @element: a #GstElement to set properties on.
617 * @property_name: the first property to get.
618 * @value: the #GValue that holds the value to set.
620 * Sets a property on an element. If the element uses threadsafe properties,
621 * the property will be put on the async queue.
624 gst_element_set_property (GstElement *element, const gchar *property_name,
630 g_return_if_fail (GST_IS_ELEMENT (element));
631 g_return_if_fail (property_name != NULL);
632 g_return_if_fail (G_IS_VALUE (value));
634 object = (GObject*) element;
636 GST_DEBUG (GST_CAT_PROPERTIES, "setting property %s on element %s",
637 property_name, gst_element_get_name (element));
638 if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
639 g_object_set_property (object, property_name, value);
643 g_object_ref (object);
645 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object),
649 g_warning ("%s: object class `%s' has no property named `%s'",
651 G_OBJECT_TYPE_NAME (object),
654 element_set_property (element, pspec, value);
656 g_object_unref (object);
660 * gst_element_get_property:
661 * @element: a #GstElement to get properties of.
662 * @property_name: the first property to get.
663 * @value: the #GValue to store the property value in.
665 * Gets a property from an element. If the element uses threadsafe properties,
666 * the element will be locked before getting the given property.
669 gst_element_get_property (GstElement *element, const gchar *property_name, GValue *value)
674 g_return_if_fail (GST_IS_ELEMENT (element));
675 g_return_if_fail (property_name != NULL);
676 g_return_if_fail (G_IS_VALUE (value));
678 object = (GObject*)element;
680 if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
681 g_object_get_property (object, property_name, value);
685 g_object_ref (object);
687 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), property_name);
690 g_warning ("%s: object class `%s' has no property named `%s'",
692 G_OBJECT_TYPE_NAME (object),
696 GValue *prop_value, tmp_value = { 0, };
698 /* auto-conversion of the callers value type
700 if (G_VALUE_TYPE (value) == G_PARAM_SPEC_VALUE_TYPE (pspec))
702 g_value_reset (value);
705 else if (!g_value_type_transformable (G_PARAM_SPEC_VALUE_TYPE (pspec), G_VALUE_TYPE (value)))
707 g_warning ("can't retrieve property `%s' of type `%s' as value of type `%s'",
709 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
710 G_VALUE_TYPE_NAME (value));
711 g_object_unref (object);
716 g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
717 prop_value = &tmp_value;
719 element_get_property (element, pspec, prop_value);
720 if (prop_value != value)
722 g_value_transform (prop_value, value);
723 g_value_unset (&tmp_value);
727 g_object_unref (object);
731 gst_element_request_pad (GstElement *element, GstPadTemplate *templ, const gchar* name)
733 GstPad *newpad = NULL;
734 GstElementClass *oclass;
736 oclass = CLASS (element);
737 if (oclass->request_new_pad)
738 newpad = (oclass->request_new_pad)(element, templ, name);
744 * gst_element_release_request_pad:
745 * @element: a #GstElement to release the request pad of.
746 * @pad: the #GstPad to release.
748 * Makes the element free the previously requested pad as obtained
749 * with gst_element_get_request_pad().
752 gst_element_release_request_pad (GstElement *element, GstPad *pad)
754 GstElementClass *oclass;
756 g_return_if_fail (GST_IS_ELEMENT (element));
757 g_return_if_fail (GST_IS_PAD (pad));
759 oclass = CLASS (element);
760 if (oclass->release_pad)
761 (oclass->release_pad) (element, pad);
766 * gst_element_set_name:
767 * @element: a #GstElement to set the name of.
768 * @name: the new name of the element.
770 * Sets the name of the element, getting rid of the old name if there was
774 gst_element_set_name (GstElement *element, const gchar *name)
776 g_return_if_fail (element != NULL);
777 g_return_if_fail (GST_IS_ELEMENT (element));
779 gst_object_set_name (GST_OBJECT (element), name);
783 * gst_element_get_name:
784 * @element: a #GstElement to get the name of.
786 * Gets the name of the element.
788 * Returns: the name of the element.
791 gst_element_get_name (GstElement *element)
793 g_return_val_if_fail (element != NULL, NULL);
794 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
796 return GST_OBJECT_NAME (element);
800 * gst_element_set_parent:
801 * @element: a #GstElement to set parent of.
802 * @parent: the new #GstObject parent of the object.
804 * Sets the parent of the element.
807 gst_element_set_parent (GstElement *element, GstObject *parent)
809 g_return_if_fail (element != NULL);
810 g_return_if_fail (GST_IS_ELEMENT (element));
811 g_return_if_fail (GST_OBJECT_PARENT (element) == NULL);
812 g_return_if_fail (parent != NULL);
813 g_return_if_fail (GST_IS_OBJECT (parent));
814 g_return_if_fail ((gpointer)element != (gpointer)parent);
816 gst_object_set_parent (GST_OBJECT (element), parent);
820 * gst_element_get_parent:
821 * @element: a #GstElement to get the parent of.
823 * Gets the parent of the element.
825 * Returns: the #GstObject parent of the element.
828 gst_element_get_parent (GstElement *element)
830 g_return_val_if_fail (element != NULL, NULL);
831 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
833 return GST_OBJECT_PARENT (element);
837 * gst_element_set_clock:
838 * @element: a #GstElement to set the clock for.
839 * @clock: the #GstClock to set for the element.
841 * Sets the clock for the element.
844 gst_element_set_clock (GstElement *element, GstClock *clock)
846 g_return_if_fail (element != NULL);
847 g_return_if_fail (GST_IS_ELEMENT (element));
849 if (element->setclockfunc)
850 element->setclockfunc (element, clock);
852 element->clock = clock;
856 * gst_element_get_clock:
857 * @element: a #GstElement to get the clock of.
859 * Gets the clock of the element.
861 * Returns: the #GstClock of the element.
864 gst_element_get_clock (GstElement *element)
866 g_return_val_if_fail (element != NULL, NULL);
867 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
869 if (element->getclockfunc)
870 return element->getclockfunc (element);
876 * gst_element_clock_wait:
877 * @element: a #GstElement.
878 * @clock: the #GstClock to use.
879 * @time: the #GstClockTime to wait for on the clock.
880 * @jitter: the difference between requested time and actual time.
882 * Waits for a specific time on the clock.
884 * Returns: the #GstClockReturn result of the wait operation.
887 gst_element_clock_wait (GstElement *element, GstClock *clock, GstClockTime time, GstClockTimeDiff *jitter)
891 g_return_val_if_fail (element != NULL, GST_CLOCK_ERROR);
892 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_CLOCK_ERROR);
894 if (GST_ELEMENT_SCHED (element)) {
895 res = gst_scheduler_clock_wait (GST_ELEMENT_SCHED (element), element, clock, time, jitter);
898 res = GST_CLOCK_TIMEOUT;
905 * gst_element_release_locks:
906 * @element: a #GstElement to release all locks on.
908 * Instruct the element to release all the locks it is holding, such as
909 * blocking reads, waiting for the clock, ...
911 * Returns: TRUE if the locks could be released.
914 gst_element_release_locks (GstElement *element)
916 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
918 if (CLASS (element)->release_locks)
919 return CLASS (element)->release_locks (element);
925 * gst_element_add_pad:
926 * @element: a #GstElement to add the pad to.
927 * @pad: the #GstPad to add to the element.
929 * Add a pad (connection point) to the element, setting the parent of the
930 * pad to the element (and thus adding a reference).
933 gst_element_add_pad (GstElement *element, GstPad *pad)
935 g_return_if_fail (element != NULL);
936 g_return_if_fail (GST_IS_ELEMENT (element));
937 g_return_if_fail (pad != NULL);
938 g_return_if_fail (GST_IS_PAD (pad));
940 /* first check to make sure the pad's parent is already set */
941 g_return_if_fail (GST_PAD_PARENT (pad) == NULL);
943 /* then check to see if there's already a pad by that name here */
944 g_return_if_fail (gst_object_check_uniqueness (element->pads, GST_PAD_NAME(pad)) == TRUE);
946 /* set the pad's parent */
947 GST_DEBUG (GST_CAT_ELEMENT_PADS,"setting parent of pad '%s' to '%s'",
948 GST_PAD_NAME (pad), GST_ELEMENT_NAME (element));
949 gst_object_set_parent (GST_OBJECT (pad), GST_OBJECT (element));
951 /* add it to the list */
952 element->pads = g_list_append (element->pads, pad);
954 if (gst_pad_get_direction (pad) == GST_PAD_SRC)
955 element->numsrcpads++;
957 element->numsinkpads++;
959 /* emit the NEW_PAD signal */
960 g_signal_emit (G_OBJECT (element), gst_element_signals[NEW_PAD], 0, pad);
964 * gst_element_remove_pad:
965 * @element: a #GstElement to remove pad from.
966 * @pad: the #GstPad to remove from the element.
968 * Remove a pad (connection point) from the element.
971 gst_element_remove_pad (GstElement *element, GstPad *pad)
973 g_return_if_fail (element != NULL);
974 g_return_if_fail (GST_IS_ELEMENT (element));
975 g_return_if_fail (pad != NULL);
976 g_return_if_fail (GST_IS_PAD (pad));
978 g_return_if_fail (GST_PAD_PARENT (pad) == element);
980 /* check to see if the pad is still connected */
981 /* FIXME: what if someone calls _remove_pad instead of
982 _remove_ghost_pad? */
983 if (GST_IS_REAL_PAD (pad)) {
984 g_return_if_fail (GST_RPAD_PEER (pad) == NULL);
987 /* remove it from the list */
988 element->pads = g_list_remove (element->pads, pad);
990 if (gst_pad_get_direction (pad) == GST_PAD_SRC)
991 element->numsrcpads--;
993 element->numsinkpads--;
995 g_signal_emit (G_OBJECT (element), gst_element_signals[PAD_REMOVED], 0, pad);
997 gst_object_unparent (GST_OBJECT (pad));
1001 * gst_element_add_ghost_pad:
1002 * @element: a #GstElement to add the ghost pad to.
1003 * @pad: the #GstPad from which the new ghost pad will be created.
1004 * @name: the name of the new ghost pad.
1006 * Creates a ghost pad from the given pad, and adds it to the list of pads
1009 * Returns: the added ghost #GstPad, or NULL, if no ghost pad was created.
1012 gst_element_add_ghost_pad (GstElement *element, GstPad *pad, const gchar *name)
1016 g_return_val_if_fail (element != NULL, NULL);
1017 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1018 g_return_val_if_fail (pad != NULL, NULL);
1019 g_return_val_if_fail (GST_IS_PAD (pad), NULL);
1021 /* then check to see if there's already a pad by that name here */
1022 g_return_val_if_fail (gst_object_check_uniqueness (element->pads, name) == TRUE, NULL);
1024 GST_DEBUG (GST_CAT_ELEMENT_PADS,
1025 "creating new ghost pad called %s, from pad %s:%s",
1026 name, GST_DEBUG_PAD_NAME(pad));
1027 ghostpad = gst_ghost_pad_new (name, pad);
1029 /* add it to the list */
1030 GST_DEBUG(GST_CAT_ELEMENT_PADS,"adding ghost pad %s to element %s",
1031 name, GST_ELEMENT_NAME (element));
1032 element->pads = g_list_append (element->pads, ghostpad);
1034 /* set the parent of the ghostpad */
1035 gst_object_set_parent (GST_OBJECT (ghostpad), GST_OBJECT (element));
1037 GST_DEBUG(GST_CAT_ELEMENT_PADS,"added ghostpad %s:%s",GST_DEBUG_PAD_NAME(ghostpad));
1039 /* emit the NEW_GHOST_PAD signal */
1040 g_signal_emit (G_OBJECT (element), gst_element_signals[NEW_PAD], 0, ghostpad);
1046 * gst_element_remove_ghost_pad:
1047 * @element: a #GstElement to remove the ghost pad from.
1048 * @pad: ghost #GstPad to remove.
1050 * Removes a ghost pad from an element.
1053 gst_element_remove_ghost_pad (GstElement *element, GstPad *pad)
1055 g_return_if_fail (element != NULL);
1056 g_return_if_fail (GST_IS_ELEMENT (element));
1057 g_return_if_fail (pad != NULL);
1058 g_return_if_fail (GST_IS_GHOST_PAD (pad));
1060 /* FIXME this is redundant?
1061 * wingo 10-july-2001: I don't think so, you have to actually remove the pad
1062 * from the element. gst_pad_remove_ghost_pad just removes the ghostpad from
1063 * the real pad's ghost pad list
1065 gst_pad_remove_ghost_pad (GST_PAD (GST_PAD_REALIZE (pad)), pad);
1066 gst_element_remove_pad (element, pad);
1071 * gst_element_get_pad:
1072 * @element: a #GstElement to find pad of.
1073 * @name: the name of the pad to retrieve.
1075 * Retrieves a pad from the element by name.
1077 * Returns: requested #GstPad if found, otherwise NULL.
1080 gst_element_get_pad (GstElement *element, const gchar *name)
1084 g_return_val_if_fail (element != NULL, NULL);
1085 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1086 g_return_val_if_fail (name != NULL, NULL);
1088 if ((pad = gst_element_get_static_pad (element, name)))
1091 pad = gst_element_get_request_pad (element, name);
1097 * gst_element_get_static_pad:
1098 * @element: a #GstElement to find a static pad of.
1099 * @name: the name of the static #GstPad to retrieve.
1101 * Retrieves a pad from the element by name. This version only retrieves
1102 * already-existing (i.e. 'static') pads.
1104 * Returns: the requested #GstPad if found, otherwise NULL.
1107 gst_element_get_static_pad (GstElement *element, const gchar *name)
1111 g_return_val_if_fail (element != NULL, NULL);
1112 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1113 g_return_val_if_fail (name != NULL, NULL);
1115 walk = element->pads;
1119 pad = GST_PAD(walk->data);
1120 if (strcmp (GST_PAD_NAME(pad), name) == 0) {
1121 GST_INFO (GST_CAT_ELEMENT_PADS, "found pad %s:%s", GST_DEBUG_PAD_NAME (pad));
1124 walk = g_list_next (walk);
1127 GST_INFO (GST_CAT_ELEMENT_PADS, "no such pad '%s' in element \"%s\"", name, GST_OBJECT_NAME (element));
1132 * gst_element_get_request_pad:
1133 * @element: a #GstElement to find a request pad of.
1134 * @name: the name of the request #GstPad to retrieve.
1136 * Retrieves a pad from the element by name. This version only retrieves
1139 * Returns: requested #GstPad if found, otherwise NULL.
1142 gst_element_get_request_pad (GstElement *element, const gchar *name)
1144 GstPadTemplate *templ = NULL;
1146 const gchar *req_name = NULL;
1147 gboolean templ_found = FALSE;
1151 gchar *str, *endptr = NULL;
1153 g_return_val_if_fail (element != NULL, NULL);
1154 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1155 g_return_val_if_fail (name != NULL, NULL);
1157 if (strstr (name, "%")) {
1158 templ = gst_element_get_pad_template (element, name);
1163 list = gst_element_get_pad_template_list(element);
1164 while (!templ_found && list) {
1165 templ = (GstPadTemplate*) list->data;
1166 if (templ->presence == GST_PAD_REQUEST) {
1167 /* we know that %s and %d are the only possibilities because of sanity
1168 checks in gst_pad_template_new */
1169 GST_DEBUG (GST_CAT_PADS, "comparing %s to %s", name, templ->name_template);
1170 if ((str = strchr (templ->name_template, '%')) &&
1171 strncmp (templ->name_template, name, str - templ->name_template) == 0 &&
1172 strlen (name) > str - templ->name_template) {
1173 data = name + (str - templ->name_template);
1174 if (*(str+1) == 'd') {
1176 n = (gint) strtol (data, &endptr, 10);
1177 if (endptr && *endptr == '\0') {
1197 pad = gst_element_request_pad (element, templ, req_name);
1203 * gst_element_get_pad_list:
1204 * @element: a #GstElement to get pads of.
1206 * Retrieves a list of the pads associated with the element.
1208 * Returns: the #GList of pads.
1211 gst_element_get_pad_list (GstElement *element)
1213 g_return_val_if_fail (element != NULL, NULL);
1214 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1216 /* return the list of pads */
1217 return element->pads;
1221 * gst_element_class_add_pad_template:
1222 * @klass: the #GstElementClass to add the pad template to.
1223 * @templ: a #GstPadTemplate to add to the element class.
1225 * Adds a padtemplate to an element class.
1226 * This is useful if you have derived a custom bin and wish to provide
1227 * an on-request pad at runtime. Plug-in writers should use
1228 * gst_element_factory_add_pad_template instead.
1231 gst_element_class_add_pad_template (GstElementClass *klass,
1232 GstPadTemplate *templ)
1234 g_return_if_fail (klass != NULL);
1235 g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
1236 g_return_if_fail (templ != NULL);
1237 g_return_if_fail (GST_IS_PAD_TEMPLATE (templ));
1239 klass->padtemplates = g_list_append (klass->padtemplates, templ);
1240 klass->numpadtemplates++;
1244 * gst_element_get_pad_template_list:
1245 * @element: a #GstElement to get pad templates of.
1247 * Retrieves a list of the pad templates associated with the element.
1249 * Returns: the #GList of padtemplates.
1252 gst_element_get_pad_template_list (GstElement *element)
1254 g_return_val_if_fail (element != NULL, NULL);
1255 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1257 return CLASS (element)->padtemplates;
1261 * gst_element_get_pad_template:
1262 * @element: a #GstElement to get the pad template of.
1263 * @name: the name of the #GstPadTemplate to get.
1265 * Retrieves a padtemplate from this element with the
1268 * Returns: the #GstPadTemplate with the given name, or NULL if none was found.
1269 * No unreferencing is necessary.
1272 gst_element_get_pad_template (GstElement *element, const gchar *name)
1276 g_return_val_if_fail (element != NULL, NULL);
1277 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1278 g_return_val_if_fail (name != NULL, NULL);
1280 padlist = gst_element_get_pad_template_list (element);
1283 GstPadTemplate *padtempl = (GstPadTemplate*) padlist->data;
1285 if (!strcmp (padtempl->name_template, name))
1288 padlist = g_list_next (padlist);
1295 * gst_element_get_compatible_pad_template:
1296 * @element: a #GstElement to get a compatible pad template for.
1297 * @compattempl: the #GstPadTemplate to find a compatible template for.
1299 * Generates a pad template for this element compatible with the given
1300 * template (meaning it is able to connect with it).
1302 * Returns: the #GstPadTemplate of the element that is compatible with
1303 * the given GstPadTemplate, or NULL if none was found. No unreferencing
1307 gst_element_get_compatible_pad_template (GstElement *element,
1308 GstPadTemplate *compattempl)
1310 GstPadTemplate *newtempl = NULL;
1313 GST_DEBUG (GST_CAT_ELEMENT_PADS, "gst_element_get_compatible_pad_template()");
1315 g_return_val_if_fail (element != NULL, NULL);
1316 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1317 g_return_val_if_fail (compattempl != NULL, NULL);
1319 padlist = gst_element_get_pad_template_list (element);
1322 GstPadTemplate *padtempl = (GstPadTemplate*) padlist->data;
1323 gboolean comp = FALSE;
1327 * Check direction (must be opposite)
1330 GST_DEBUG (GST_CAT_CAPS, "checking direction and caps");
1331 if (padtempl->direction == GST_PAD_SRC &&
1332 compattempl->direction == GST_PAD_SINK) {
1333 GST_DEBUG (GST_CAT_CAPS, "compatible direction: found src pad template");
1334 comp = gst_caps_check_compatibility (GST_PAD_TEMPLATE_CAPS (padtempl),
1335 GST_PAD_TEMPLATE_CAPS (compattempl));
1336 GST_DEBUG(GST_CAT_CAPS, "caps are %scompatible", (comp ? "" : "not "));
1337 } else if (padtempl->direction == GST_PAD_SINK &&
1338 compattempl->direction == GST_PAD_SRC) {
1339 GST_DEBUG (GST_CAT_CAPS, "compatible direction: found sink pad template");
1340 comp = gst_caps_check_compatibility (GST_PAD_TEMPLATE_CAPS (compattempl),
1341 GST_PAD_TEMPLATE_CAPS (padtempl));
1342 GST_DEBUG (GST_CAT_CAPS, "caps are %scompatible", (comp ? "" : "not "));
1346 newtempl = padtempl;
1350 padlist = g_list_next (padlist);
1357 * gst_element_request_compatible_pad:
1358 * @element: a #GstElement to request a new pad from.
1359 * @templ: the #GstPadTemplate to which the new pad should be able to connect.
1361 * Requests a new pad from the element. The template will
1362 * be used to decide what type of pad to create. This function
1363 * is typically used for elements with a padtemplate with presence
1366 * Returns: the new #GstPad that was created, or NULL if none could be created.
1369 gst_element_request_compatible_pad (GstElement *element, GstPadTemplate *templ)
1371 GstPadTemplate *templ_new;
1374 g_return_val_if_fail (element != NULL, NULL);
1375 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1376 g_return_val_if_fail (templ != NULL, NULL);
1378 templ_new = gst_element_get_compatible_pad_template (element, templ);
1379 if (templ_new != NULL)
1380 pad = gst_element_request_pad (element, templ_new, NULL);
1387 * gst_element_get_compatible_pad_filtered:
1388 * @element: a #GstElement in which the pad should be found.
1389 * @pad: the #GstPad to find a compatible one for.
1390 * @filtercaps: the #GstCaps to use as a filter.
1392 * Looks for an unconnected pad to which the given pad can connect to.
1393 * It is not guaranteed that connecting the pads will work, though
1394 * it should work in most cases.
1396 * Returns: the #GstPad to which a connection can be made.
1399 gst_element_get_compatible_pad_filtered (GstElement *element, GstPad *pad,
1400 GstCaps *filtercaps)
1403 GstPadTemplate *templ;
1405 GstPad *foundpad = NULL;
1408 g_return_val_if_fail (element != NULL, NULL);
1409 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1410 g_return_val_if_fail (pad != NULL, NULL);
1411 g_return_val_if_fail (GST_IS_PAD (pad), NULL);
1413 /* let's use the real pad */
1414 pad = (GstPad *) GST_PAD_REALIZE (pad);
1415 g_return_val_if_fail (pad != NULL, NULL);
1416 g_return_val_if_fail (GST_RPAD_PEER (pad) == NULL, NULL);
1418 /* try to get an existing unconnected pad */
1419 pads = gst_element_get_pad_list (element);
1421 GstPad *current = GST_PAD (pads->data);
1422 if ((GST_PAD_PEER (GST_PAD_REALIZE (current)) == NULL) &&
1423 gst_pad_can_connect_filtered (pad, current, filtercaps)) {
1426 pads = g_list_next (pads);
1429 /* try to create a new one */
1430 /* requesting is a little crazy, we need a template. Let's create one */
1431 if (filtercaps != NULL) {
1432 templcaps = gst_caps_intersect (filtercaps, (GstCaps *) GST_RPAD_CAPS (pad));
1433 if (templcaps == NULL)
1436 templcaps = gst_caps_copy (gst_pad_get_caps (pad));
1439 templ = gst_pad_template_new ((gchar *) GST_PAD_NAME (pad), GST_RPAD_DIRECTION (pad),
1440 GST_PAD_ALWAYS, templcaps, NULL);
1441 foundpad = gst_element_request_compatible_pad (element, templ);
1442 gst_object_unref (GST_OBJECT (templ)); /* this will take care of the caps too */
1444 /* FIXME: this is broken, but it's in here so autoplugging elements that don't
1445 have caps on their source padtemplates (spider) can connect... */
1446 if (!foundpad && !filtercaps) {
1447 templ = gst_pad_template_new ((gchar *) GST_PAD_NAME (pad), GST_RPAD_DIRECTION (pad),
1448 GST_PAD_ALWAYS, NULL, NULL);
1449 foundpad = gst_element_request_compatible_pad (element, templ);
1450 gst_object_unref (GST_OBJECT (templ));
1457 * gst_element_get_compatible_pad:
1458 * @element: a #GstElement in which the pad should be found.
1459 * @pad: the #GstPad to find a compatible one for.
1461 * Looks for an unconnected pad to which the given pad can connect to.
1462 * It is not guaranteed that connecting the pads will work, though
1463 * it should work in most cases.
1465 * Returns: the #GstPad to which a connection can be made, or NULL if none
1469 gst_element_get_compatible_pad (GstElement *element, GstPad *pad)
1471 return gst_element_get_compatible_pad_filtered (element, pad, NULL);
1475 * gst_element_connect_filtered:
1476 * @src: a #GstElement containing the source pad.
1477 * @dest: the #GstElement containing the destination pad.
1478 * @filtercaps: the #GstCaps to use as a filter.
1480 * Connects the source to the destination element using the filtercaps.
1481 * The connection must be from source to destination, the other
1482 * direction will not be tried.
1483 * The functions looks for existing pads that aren't connected yet.
1484 * It will use request pads if possible. But both pads will not be requested.
1485 * If multiple connections are possible, only one is established.
1487 * Returns: TRUE if the elements could be connected.
1490 gst_element_connect_filtered (GstElement *src, GstElement *dest,
1491 GstCaps *filtercaps)
1493 const GList *srcpads, *destpads, *srctempls, *desttempls, *l;
1494 GstPad *srcpad, *destpad;
1495 GstPadTemplate *srctempl, *desttempl;
1498 g_return_val_if_fail (src != NULL, FALSE);
1499 g_return_val_if_fail (GST_IS_ELEMENT (src), FALSE);
1500 g_return_val_if_fail (dest != NULL, FALSE);
1501 g_return_val_if_fail (GST_IS_ELEMENT (dest), FALSE);
1503 GST_DEBUG (GST_CAT_ELEMENT_PADS, "trying to connect element %s to element %s",
1504 GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (dest));
1506 srcpads = gst_element_get_pad_list (src);
1507 destpads = gst_element_get_pad_list (dest);
1509 if (srcpads || destpads) {
1510 /* loop through the existing pads in the source, trying to find a
1511 * compatible destination pad */
1513 srcpad = (GstPad *) GST_PAD_REALIZE (srcpads->data);
1514 if ((GST_RPAD_DIRECTION (srcpad) == GST_PAD_SRC) &&
1515 (GST_PAD_PEER (srcpad) == NULL)) {
1516 destpad = gst_element_get_compatible_pad_filtered (dest, srcpad,
1518 if (destpad && gst_pad_connect_filtered (srcpad, destpad, filtercaps)) {
1519 GST_DEBUG (GST_CAT_ELEMENT_PADS, "connected pad %s:%s to pad %s:%s",
1520 GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad));
1524 srcpads = g_list_next (srcpads);
1527 /* loop through the existing pads in the destination */
1529 destpad = (GstPad *) GST_PAD_REALIZE (destpads->data);
1530 if ((GST_RPAD_DIRECTION (destpad) == GST_PAD_SINK) &&
1531 (GST_PAD_PEER (destpad) == NULL)) {
1532 srcpad = gst_element_get_compatible_pad_filtered (src, destpad,
1534 if (srcpad && gst_pad_connect_filtered (srcpad, destpad, filtercaps)) {
1535 GST_DEBUG (GST_CAT_ELEMENT_PADS, "connected pad %s:%s to pad %s:%s",
1536 GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad));
1540 destpads = g_list_next (destpads);
1544 GST_DEBUG (GST_CAT_ELEMENT_PADS,
1545 "we might have request pads on both sides, checking...");
1546 srctempls = gst_element_get_pad_template_list (src);
1547 desttempls = gst_element_get_pad_template_list (dest);
1549 if (srctempls && desttempls) {
1551 srctempl = (GstPadTemplate*) srctempls->data;
1552 if (srctempl->presence == GST_PAD_REQUEST) {
1553 for (l=desttempls; l; l=l->next) {
1554 desttempl = (GstPadTemplate*) desttempls->data;
1555 if (desttempl->presence == GST_PAD_REQUEST &&
1556 desttempl->direction != srctempl->direction) {
1557 if (gst_caps_check_compatibility (gst_pad_template_get_caps (srctempl),
1558 gst_pad_template_get_caps (desttempl))) {
1559 srcpad = gst_element_get_request_pad (src,
1560 srctempl->name_template);
1561 destpad = gst_element_get_request_pad (dest,
1562 desttempl->name_template);
1563 if (gst_pad_connect_filtered (srcpad, destpad, filtercaps)) {
1564 GST_DEBUG (GST_CAT_ELEMENT_PADS,
1565 "connected pad %s:%s to pad %s:%s",
1566 GST_DEBUG_PAD_NAME (srcpad),
1567 GST_DEBUG_PAD_NAME (destpad));
1570 /* FIXME: we have extraneous request pads lying around */
1575 srctempls = srctempls->next;
1579 GST_DEBUG (GST_CAT_ELEMENT_PADS, "no connection possible from %s to %s",
1580 GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (dest));
1585 * gst_element_connect_many:
1586 * @element_1: the first #GstElement in the connection chain.
1587 * @element_2: the second #GstElement in the connection chain.
1588 * @...: the NULL-terminated list of elements to connect in order.
1590 * Chain together a series of elements. Uses #gst_element_connect.
1592 * Returns: TRUE on success, FALSE otherwise.
1595 gst_element_connect_many (GstElement *element_1, GstElement *element_2, ...)
1599 g_return_val_if_fail (element_1 != NULL && element_2 != NULL, FALSE);
1600 g_return_val_if_fail (GST_IS_ELEMENT (element_1) &&
1601 GST_IS_ELEMENT (element_2), FALSE);
1603 va_start (args, element_2);
1606 if (!gst_element_connect (element_1, element_2))
1609 element_1 = element_2;
1610 element_2 = va_arg (args, GstElement*);
1619 * gst_element_connect:
1620 * @src: a #GstElement containing the source pad.
1621 * @dest: the #GstElement containing the destination pad.
1623 * Connects the source to the destination element.
1624 * The connection must be from source to destination, the other
1625 * direction will not be tried.
1626 * The functions looks for existing pads and request pads that aren't
1627 * connected yet. If multiple connections are possible, only one is
1630 * Returns: TRUE if the elements could be connected.
1633 gst_element_connect (GstElement *src, GstElement *dest)
1635 return gst_element_connect_filtered (src, dest, NULL);
1639 * gst_element_connect_pads_filtered:
1640 * @src: a #GstElement containing the source pad.
1641 * @srcpadname: the name of the #GstPad in source element.
1642 * @dest: the #GstElement containing the destination pad.
1643 * @destpadname: the name of the #GstPad in destination element.
1644 * @filtercaps: the #GstCaps to use as a filter.
1646 * Connects the two named pads of the source and destination elements.
1647 * Side effect is that if one of the pads has no parent, it becomes a
1648 * child of the parent of the other element. If they have different
1649 * parents, the connection fails.
1651 * Returns: TRUE if the pads could be connected.
1654 gst_element_connect_pads_filtered (GstElement *src, const gchar *srcpadname,
1655 GstElement *dest, const gchar *destpadname,
1656 GstCaps *filtercaps)
1658 GstPad *srcpad,*destpad;
1660 g_return_val_if_fail (src != NULL, FALSE);
1661 g_return_val_if_fail (GST_IS_ELEMENT (src), FALSE);
1662 g_return_val_if_fail (srcpadname != NULL, FALSE);
1663 g_return_val_if_fail (dest != NULL, FALSE);
1664 g_return_val_if_fail (GST_IS_ELEMENT (dest), FALSE);
1665 g_return_val_if_fail (destpadname != NULL, FALSE);
1667 /* obtain the pads requested */
1668 srcpad = gst_element_get_pad (src, srcpadname);
1669 if (srcpad == NULL) {
1670 GST_ERROR (src, "source element has no pad \"%s\"", srcpadname);
1673 destpad = gst_element_get_pad (dest, destpadname);
1674 if (srcpad == NULL) {
1675 GST_ERROR (dest, "destination element has no pad \"%s\"", destpadname);
1679 /* we're satisified they can be connected, let's do it */
1680 return gst_pad_connect_filtered (srcpad, destpad, filtercaps);
1684 * gst_element_connect_pads:
1685 * @src: a #GstElement containing the source pad.
1686 * @srcpadname: the name of the #GstPad in the source element.
1687 * @dest: the #GstElement containing the destination pad.
1688 * @destpadname: the name of the #GstPad in destination element.
1690 * Connects the two named pads of the source and destination elements.
1691 * Side effect is that if one of the pads has no parent, it becomes a
1692 * child of the parent of the other element. If they have different
1693 * parents, the connection fails.
1695 * Returns: TRUE if the pads could be connected.
1698 gst_element_connect_pads (GstElement *src, const gchar *srcpadname,
1699 GstElement *dest, const gchar *destpadname)
1701 return gst_element_connect_pads_filtered (src, srcpadname, dest, destpadname, NULL);
1705 * gst_element_disconnect_pads:
1706 * @src: a #GstElement containing the source pad.
1707 * @srcpadname: the name of the #GstPad in source element.
1708 * @dest: a #GstElement containing the destination pad.
1709 * @destpadname: the name of the #GstPad in destination element.
1711 * Disconnects the two named pads of the source and destination elements.
1714 gst_element_disconnect_pads (GstElement *src, const gchar *srcpadname,
1715 GstElement *dest, const gchar *destpadname)
1717 GstPad *srcpad,*destpad;
1719 g_return_if_fail (src != NULL);
1720 g_return_if_fail (GST_IS_ELEMENT(src));
1721 g_return_if_fail (srcpadname != NULL);
1722 g_return_if_fail (dest != NULL);
1723 g_return_if_fail (GST_IS_ELEMENT(dest));
1724 g_return_if_fail (destpadname != NULL);
1726 /* obtain the pads requested */
1727 srcpad = gst_element_get_pad (src, srcpadname);
1728 if (srcpad == NULL) {
1729 GST_ERROR(src,"source element has no pad \"%s\"",srcpadname);
1732 destpad = gst_element_get_pad (dest, destpadname);
1733 if (srcpad == NULL) {
1734 GST_ERROR(dest,"destination element has no pad \"%s\"",destpadname);
1738 /* we're satisified they can be disconnected, let's do it */
1739 gst_pad_disconnect(srcpad,destpad);
1743 * gst_element_disconnect_many:
1744 * @element_1: the first #GstElement in the connection chain.
1745 * @element_2: the second #GstElement in the connection chain.
1746 * @...: the NULL-terminated list of elements to disconnect in order.
1748 * Disconnects a series of elements. Uses #gst_element_disconnect.
1751 gst_element_disconnect_many (GstElement *element_1, GstElement *element_2, ...)
1755 g_return_if_fail (element_1 != NULL && element_2 != NULL);
1756 g_return_if_fail (GST_IS_ELEMENT (element_1) && GST_IS_ELEMENT (element_2));
1758 va_start (args, element_2);
1761 gst_element_disconnect (element_1, element_2);
1763 element_1 = element_2;
1764 element_2 = va_arg (args, GstElement*);
1771 * gst_element_disconnect:
1772 * @src: the source #GstElement to disconnect.
1773 * @dest: the sink #GstElement to disconnect.
1775 * Disconnects all source pads of the source element with all sink pads
1776 * of the sink element to which they are connected.
1779 gst_element_disconnect (GstElement *src, GstElement *dest)
1781 const GList *srcpads;
1784 g_return_if_fail (GST_IS_ELEMENT (src));
1785 g_return_if_fail (GST_IS_ELEMENT (dest));
1787 GST_DEBUG (GST_CAT_ELEMENT_PADS, "disconnecting \"%s\" and \"%s\"",
1788 GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (dest));
1790 srcpads = gst_element_get_pad_list (src);
1793 pad = GST_PAD_CAST (srcpads->data);
1795 if (GST_IS_REAL_PAD (pad) && GST_PAD_DIRECTION (pad) == GST_PAD_SRC) {
1796 GstPad *peerpad = GST_PAD_PEER (pad);
1799 (GST_OBJECT_PARENT (GST_PAD_PEER (peerpad)) == (GstObject*) src)) {
1800 gst_pad_disconnect (pad, peerpad);
1804 srcpads = g_list_next (srcpads);
1809 gst_element_error_func (GstElement* element, GstElement *source,
1812 /* tell the parent */
1813 if (GST_OBJECT_PARENT (element)) {
1814 GST_DEBUG (GST_CAT_EVENT, "forwarding error \"%s\" from %s to %s",
1815 errormsg, GST_ELEMENT_NAME (element),
1816 GST_OBJECT_NAME (GST_OBJECT_PARENT (element)));
1818 gst_object_ref (GST_OBJECT (element));
1819 g_signal_emit (G_OBJECT (GST_OBJECT_PARENT (element)),
1820 gst_element_signals[ERROR], 0, source, errormsg);
1821 gst_object_unref (GST_OBJECT (element));
1826 gst_element_send_event_default (GstElement *element, GstEvent *event)
1828 GList *pads = element->pads;
1829 gboolean res = FALSE;
1832 GstPad *pad = GST_PAD_CAST (pads->data);
1834 if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) {
1835 if (GST_PAD_IS_USABLE (pad)) {
1836 res = gst_pad_send_event (GST_PAD_PEER (pad), event);
1840 pads = g_list_next (pads);
1846 * gst_element_send_event:
1847 * @element: a #GstElement to send the event to.
1848 * @event: the #GstEvent to send to the element.
1850 * Sends an event to an element. If the element doesn't
1851 * implement an event handler, the event will be forwarded
1852 * to a random sink pad.
1854 * Returns: TRUE if the event was handled.
1857 gst_element_send_event (GstElement *element, GstEvent *event)
1859 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1860 g_return_val_if_fail (event != NULL, FALSE);
1862 if (CLASS (element)->send_event)
1863 return CLASS (element)->send_event (element, event);
1869 gst_element_query_default (GstElement *element, GstPadQueryType type,
1870 GstFormat *format, gint64 *value)
1872 GList *pads = element->pads;
1873 gboolean res = FALSE;
1876 GstPad *pad = GST_PAD_CAST (pads->data);
1878 if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) {
1879 if (GST_PAD_IS_USABLE (pad)) {
1880 res = gst_pad_query (GST_PAD_PEER (pad), type, format, value);
1884 pads = g_list_next (pads);
1890 * gst_element_query:
1891 * @element: a #GstElement to perform the query on.
1892 * @type: the #GstPadQueryType.
1893 * @format: the #GstFormat pointer to hold the format of the result.
1894 * @value: the pointer to the value of the result.
1896 * Performs a query on the given element. If the format is set
1897 * to GST_FORMAT_DEFAULT and this function returns TRUE, the
1898 * format pointer will hold the default format.
1899 * For element that don't implement a query handler, this function
1900 * forwards the query to a random connected sinkpad of this element.
1902 * Returns: TRUE if the query could be performed.
1905 gst_element_query (GstElement *element, GstPadQueryType type,
1906 GstFormat *format, gint64 *value)
1908 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1909 g_return_val_if_fail (format != NULL, FALSE);
1910 g_return_val_if_fail (value != NULL, FALSE);
1912 if (CLASS (element)->query)
1913 return CLASS (element)->query (element, type, format, value);
1919 * gst_element_error:
1920 * @element: a #GstElement with the error.
1921 * @error: the printf-style string describing the error.
1922 * @...: the optional arguments for the string.
1924 * signals an error condition on an element.
1925 * This function is used internally by elements.
1926 * It results in the "error" signal.
1929 gst_element_error (GstElement *element, const gchar *error, ...)
1935 g_return_if_fail (GST_IS_ELEMENT (element));
1936 g_return_if_fail (error != NULL);
1938 /* create error message */
1939 va_start (var_args, error);
1940 string = g_strdup_vprintf (error, var_args);
1942 GST_INFO (GST_CAT_EVENT, "ERROR in %s: %s", GST_ELEMENT_NAME (element), string);
1944 /* emit the signal, make sure the element stays available */
1945 gst_object_ref (GST_OBJECT (element));
1946 g_signal_emit (G_OBJECT (element), gst_element_signals[ERROR], 0, element, string);
1948 /* tell the scheduler */
1949 if (element->sched) {
1950 gst_scheduler_error (element->sched, element);
1954 gst_object_unref (GST_OBJECT (element));
1959 * gst_element_get_state:
1960 * @element: a #GstElement to get the state of.
1962 * Gets the state of the element.
1964 * Returns: the #GstElementState of the element.
1967 gst_element_get_state (GstElement *element)
1969 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_VOID_PENDING);
1971 return GST_STATE (element);
1975 * gst_element_wait_state_change:
1976 * @element: a #GstElement to wait for a state change on.
1978 * Waits and blocks until the element changed its state.
1981 gst_element_wait_state_change (GstElement *element)
1983 g_mutex_lock (element->state_mutex);
1984 g_cond_wait (element->state_cond, element->state_mutex);
1985 g_mutex_unlock (element->state_mutex);
1989 * gst_element_set_state:
1990 * @element: a #GstElement to change state of.
1991 * @state: the element's new #GstElementState.
1993 * Sets the state of the element. This function will try to set the
1994 * requested state by going through all the intermediary states and calling
1995 * the class's state change function for each.
1997 * Returns: TRUE if the state was successfully set.
1998 * (using #GstElementStateReturn).
2001 gst_element_set_state (GstElement *element, GstElementState state)
2003 GstElementClass *oclass;
2004 GstElementState curpending;
2005 GstElementStateReturn return_val = GST_STATE_SUCCESS;
2007 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
2009 /* start with the current state */
2010 curpending = GST_STATE(element);
2012 GST_DEBUG_ELEMENT (GST_CAT_STATES, element, "setting state from %s to %s",
2013 gst_element_state_get_name (curpending),
2014 gst_element_state_get_name (state));
2016 /* loop until the final requested state is set */
2017 while (GST_STATE (element) != state
2018 && GST_STATE (element) != GST_STATE_VOID_PENDING) {
2019 /* move the curpending state in the correct direction */
2020 if (curpending < state)
2025 /* set the pending state variable */
2026 /* FIXME: should probably check to see that we don't already have one */
2027 GST_STATE_PENDING (element) = curpending;
2029 if (curpending != state) {
2030 GST_DEBUG_ELEMENT (GST_CAT_STATES, element,
2031 "intermediate: setting state from %s to %s",
2032 gst_element_state_get_name (GST_STATE (element)),
2033 gst_element_state_get_name (curpending));
2036 /* call the state change function so it can set the state */
2037 oclass = CLASS (element);
2038 if (oclass->change_state)
2039 return_val = (oclass->change_state) (element);
2041 switch (return_val) {
2042 case GST_STATE_FAILURE:
2043 GST_DEBUG_ELEMENT (GST_CAT_STATES, element,
2044 "have failed change_state return");
2046 case GST_STATE_ASYNC:
2047 GST_DEBUG_ELEMENT (GST_CAT_STATES, element,
2048 "element will change state async");
2050 case GST_STATE_SUCCESS:
2051 /* Last thing we do is verify that a successful state change really
2052 * did change the state... */
2053 if (GST_STATE (element) != curpending) {
2054 GST_DEBUG_ELEMENT (GST_CAT_STATES, element,
2055 "element claimed state-change success,"
2056 "but state didn't change %s, %s <-> %s",
2057 gst_element_state_get_name (GST_STATE (element)),
2058 gst_element_state_get_name (GST_STATE_PENDING (element)),
2059 gst_element_state_get_name (curpending));
2060 return GST_STATE_FAILURE;
2064 /* somebody added a GST_STATE_ and forgot to do stuff here ! */
2065 g_assert_not_reached ();
2074 gst_element_negotiate_pads (GstElement *element)
2076 GList *pads = GST_ELEMENT_PADS (element);
2078 GST_DEBUG_ELEMENT (GST_CAT_CAPS, element, "negotiating pads");
2081 GstPad *pad = GST_PAD (pads->data);
2084 pads = g_list_next (pads);
2086 if (!GST_IS_REAL_PAD (pad))
2089 srcpad = GST_PAD_REALIZE (pad);
2091 /* if we have a connection on this pad and it doesn't have caps
2092 * allready, try to negotiate */
2093 if (GST_PAD_IS_USABLE (srcpad) && !GST_PAD_CAPS (srcpad)) {
2094 GstRealPad *sinkpad;
2095 GstElementState otherstate;
2098 sinkpad = GST_RPAD_PEER (GST_PAD_REALIZE (srcpad));
2100 /* check the parent of the peer pad, if there is no parent do nothing */
2101 parent = GST_PAD_PARENT (sinkpad);
2105 otherstate = GST_STATE (parent);
2107 /* swap pads if needed */
2108 if (!GST_PAD_IS_SRC (srcpad)) {
2116 /* only try to negotiate if the peer element is in PAUSED or higher too */
2117 if (otherstate >= GST_STATE_READY) {
2118 GST_DEBUG_ELEMENT (GST_CAT_CAPS, element,
2119 "perform negotiate for %s:%s and %s:%s",
2120 GST_DEBUG_PAD_NAME (srcpad),
2121 GST_DEBUG_PAD_NAME (sinkpad));
2122 if (!gst_pad_perform_negotiate (GST_PAD (srcpad), GST_PAD (sinkpad)))
2126 GST_DEBUG_ELEMENT (GST_CAT_CAPS, element,
2127 "not negotiating %s:%s and %s:%s, not in READY yet",
2128 GST_DEBUG_PAD_NAME (srcpad),
2129 GST_DEBUG_PAD_NAME (sinkpad));
2138 gst_element_clear_pad_caps (GstElement *element)
2140 GList *pads = GST_ELEMENT_PADS (element);
2142 GST_DEBUG_ELEMENT (GST_CAT_CAPS, element, "clearing pad caps");
2145 GstRealPad *pad = GST_PAD_REALIZE (pads->data);
2147 if (GST_PAD_CAPS (pad)) {
2148 GST_PAD_CAPS (pad) = NULL;
2150 pads = g_list_next (pads);
2154 static GstElementStateReturn
2155 gst_element_change_state (GstElement *element)
2157 GstElementState old_state;
2159 gint old_pending, old_transition;
2161 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
2163 old_state = GST_STATE (element);
2164 old_pending = GST_STATE_PENDING (element);
2165 old_transition = GST_STATE_TRANSITION (element);
2167 if (old_pending == GST_STATE_VOID_PENDING ||
2168 old_state == GST_STATE_PENDING (element)) {
2169 GST_INFO (GST_CAT_STATES,
2170 "no state change needed for element %s (VOID_PENDING)",
2171 GST_ELEMENT_NAME (element));
2172 return GST_STATE_SUCCESS;
2175 GST_INFO (GST_CAT_STATES, "%s default handler sets state from %s to %s %d",
2176 GST_ELEMENT_NAME (element),
2177 gst_element_state_get_name (old_state),
2178 gst_element_state_get_name (old_pending),
2179 GST_STATE_TRANSITION (element));
2181 /* we set the state change early for the negotiation functions */
2182 GST_STATE (element) = old_pending;
2183 GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING;
2185 switch (old_transition) {
2186 /* if we are going to paused, we try to negotiate the pads */
2187 case GST_STATE_READY_TO_PAUSED:
2188 if (!gst_element_negotiate_pads (element))
2191 /* going to the READY state clears all pad caps */
2192 case GST_STATE_PAUSED_TO_READY:
2193 gst_element_clear_pad_caps (element);
2199 /* tell the scheduler if we have one */
2200 if (element->sched) {
2201 if (gst_scheduler_state_transition (element->sched, element,
2202 old_transition) != GST_STATE_SUCCESS) {
2207 parent = GST_ELEMENT_PARENT (element);
2209 GST_DEBUG_ELEMENT (GST_CAT_STATES, element,
2210 "signaling state change from %s to %s",
2211 gst_element_state_get_name (old_state),
2212 gst_element_state_get_name (GST_STATE (element)));
2213 g_signal_emit (G_OBJECT (element), gst_element_signals[STATE_CHANGE],
2214 0, old_state, GST_STATE (element));
2216 /* tell our parent about the state change */
2217 if (parent && GST_IS_BIN (parent)) {
2218 gst_bin_child_state_change (GST_BIN (parent), old_state,
2219 GST_STATE (element), element);
2222 /* signal the state change in case somebody is waiting for us */
2223 g_mutex_lock (element->state_mutex);
2224 g_cond_signal (element->state_cond);
2225 g_mutex_unlock (element->state_mutex);
2227 return GST_STATE_SUCCESS;
2230 /* undo the state change */
2231 GST_STATE (element) = old_state;
2232 GST_STATE_PENDING (element) = old_pending;
2234 return GST_STATE_FAILURE;
2238 * gst_element_get_factory:
2239 * @element: a #GstElement to request the element factory of.
2241 * Retrieves the factory that was used to create this element.
2243 * Returns: the #GstElementFactory used for creating this element.
2246 gst_element_get_factory (GstElement *element)
2248 GstElementClass *oclass;
2250 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
2252 oclass = CLASS (element);
2254 return oclass->elementfactory;
2258 gst_element_dispose (GObject *object)
2260 GstElement *element = GST_ELEMENT (object);
2264 GST_DEBUG_ELEMENT (GST_CAT_REFCOUNTING, element, "dispose");
2266 gst_element_set_state (element, GST_STATE_NULL);
2268 /* first we break all our connections with the ouside */
2269 if (element->pads) {
2271 orig = pads = g_list_copy (element->pads);
2273 pad = GST_PAD (pads->data);
2275 if (GST_PAD_PEER (pad)) {
2276 GST_DEBUG (GST_CAT_REFCOUNTING, "disconnecting pad '%s'",
2277 GST_OBJECT_NAME (GST_OBJECT (GST_PAD (GST_PAD_PEER (pad)))));
2278 gst_pad_disconnect (pad, GST_PAD (GST_PAD_PEER (pad)));
2280 gst_element_remove_pad (element, pad);
2282 pads = g_list_next (pads);
2285 g_list_free (element->pads);
2286 element->pads = NULL;
2289 element->numsrcpads = 0;
2290 element->numsinkpads = 0;
2291 element->numpads = 0;
2292 g_mutex_free (element->state_mutex);
2293 g_cond_free (element->state_cond);
2295 if (element->prop_value_queue)
2296 g_async_queue_unref (element->prop_value_queue);
2297 element->prop_value_queue = NULL;
2298 if (element->property_mutex)
2299 g_mutex_free (element->property_mutex);
2301 G_OBJECT_CLASS (parent_class)->dispose (object);
2304 #ifndef GST_DISABLE_LOADSAVE
2306 * gst_element_save_thyself:
2307 * @element: a #GstElement to save.
2308 * @parent: the xml parent node.
2310 * Saves the element as part of the given XML structure.
2312 * Returns: the new #xmlNodePtr.
2315 gst_element_save_thyself (GstObject *object,
2319 GstElementClass *oclass;
2320 GParamSpec **specs, *spec;
2322 GValue value = { 0, };
2323 GstElement *element;
2325 g_return_val_if_fail (GST_IS_ELEMENT (object), parent);
2327 element = GST_ELEMENT (object);
2329 oclass = CLASS (element);
2331 xmlNewChild(parent, NULL, "name", GST_ELEMENT_NAME(element));
2333 if (oclass->elementfactory != NULL) {
2334 GstElementFactory *factory = (GstElementFactory *)oclass->elementfactory;
2336 xmlNewChild (parent, NULL, "type", GST_OBJECT_NAME (factory));
2337 xmlNewChild (parent, NULL, "version", factory->details->version);
2340 /* FIXME: what is this? */
2341 /* if (element->manager) */
2342 /* xmlNewChild(parent, NULL, "manager", GST_ELEMENT_NAME(element->manager)); */
2345 specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (object), &nspecs);
2347 for (i=0; i<nspecs; i++) {
2349 if (spec->flags & G_PARAM_READABLE) {
2353 g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE (spec));
2355 g_object_get_property (G_OBJECT (element), spec->name, &value);
2356 param = xmlNewChild (parent, NULL, "param", NULL);
2357 xmlNewChild (param, NULL, "name", spec->name);
2359 if (G_IS_PARAM_SPEC_STRING (spec))
2360 contents = g_value_dup_string (&value);
2361 else if (G_IS_PARAM_SPEC_ENUM (spec))
2362 contents = g_strdup_printf ("%d", g_value_get_enum (&value));
2363 else if (G_IS_PARAM_SPEC_INT64 (spec))
2364 contents = g_strdup_printf ("%lld", g_value_get_int64 (&value));
2366 contents = g_strdup_value_contents (&value);
2368 xmlNewChild (param, NULL, "value", contents);
2371 g_value_unset(&value);
2375 pads = GST_ELEMENT_PADS (element);
2378 GstPad *pad = GST_PAD (pads->data);
2379 /* figure out if it's a direct pad or a ghostpad */
2380 if (GST_ELEMENT (GST_OBJECT_PARENT (pad)) == element) {
2381 xmlNodePtr padtag = xmlNewChild (parent, NULL, "pad", NULL);
2382 gst_object_save_thyself (GST_OBJECT (pad), padtag);
2384 pads = g_list_next (pads);
2391 gst_element_restore_thyself (GstObject *object, xmlNodePtr self)
2393 xmlNodePtr children;
2394 GstElement *element;
2396 gchar *value = NULL;
2398 element = GST_ELEMENT (object);
2399 g_return_if_fail (element != NULL);
2402 children = self->xmlChildrenNode;
2404 if (!strcmp (children->name, "param")) {
2405 xmlNodePtr child = children->xmlChildrenNode;
2408 if (!strcmp (child->name, "name")) {
2409 name = xmlNodeGetContent (child);
2411 else if (!strcmp (child->name, "value")) {
2412 value = xmlNodeGetContent (child);
2414 child = child->next;
2416 /* FIXME: can this just be g_object_set ? */
2417 gst_util_set_object_arg (G_OBJECT (element), name, value);
2419 children = children->next;
2423 children = self->xmlChildrenNode;
2425 if (!strcmp (children->name, "pad")) {
2426 gst_pad_load_and_connect (children, GST_OBJECT (element));
2428 children = children->next;
2431 if (GST_OBJECT_CLASS(parent_class)->restore_thyself)
2432 (GST_OBJECT_CLASS(parent_class)->restore_thyself) (object, self);
2434 #endif /* GST_DISABLE_LOADSAVE */
2437 * gst_element_yield:
2438 * @element: a #GstElement to yield.
2440 * Requests a yield operation for the element. The scheduler will typically
2441 * give control to another element.
2444 gst_element_yield (GstElement *element)
2446 if (GST_ELEMENT_SCHED (element)) {
2447 gst_scheduler_yield (GST_ELEMENT_SCHED (element), element);
2452 * gst_element_interrupt:
2453 * @element: a #GstElement to interrupt.
2455 * Requests the scheduler of this element to interrupt the execution of
2456 * this element and scheduler another one.
2458 * Returns: TRUE if the element should exit its chain/loop/get
2459 * function ASAP, depending on the scheduler implementation.
2462 gst_element_interrupt (GstElement *element)
2464 if (GST_ELEMENT_SCHED (element)) {
2465 return gst_scheduler_interrupt (GST_ELEMENT_SCHED (element), element);
2472 * gst_element_set_scheduler:
2473 * @element: a #GstElement to set the scheduler of.
2474 * @sched: the #GstScheduler to set.
2476 * Sets the scheduler of the element. For internal use only, unless you're
2477 * writing a new bin subclass.
2480 gst_element_set_scheduler (GstElement *element,
2481 GstScheduler *sched)
2483 g_return_if_fail (GST_IS_ELEMENT (element));
2485 GST_INFO_ELEMENT (GST_CAT_PARENTAGE, element, "setting scheduler to %p", sched);
2487 GST_ELEMENT_SCHED (element) = sched;
2491 * gst_element_get_scheduler:
2492 * @element: a #GstElement to get the scheduler of.
2494 * Returns the scheduler of the element.
2496 * Returns: the element's #GstScheduler.
2499 gst_element_get_scheduler (GstElement *element)
2501 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
2503 return GST_ELEMENT_SCHED (element);
2507 * gst_element_set_loop_function:
2508 * @element: a #GstElement to set the loop function of.
2509 * @loop: Pointer to #GstElementLoopFunction.
2511 * This sets the loop function for the element. The function pointed to
2512 * can deviate from the GstElementLoopFunction definition in type of
2515 * NOTE: in order for this to take effect, the current loop function *must*
2516 * exit. Assuming the loop function itself is the only one who will cause
2517 * a new loopfunc to be assigned, this should be no problem.
2520 gst_element_set_loop_function (GstElement *element,
2521 GstElementLoopFunction loop)
2523 g_return_if_fail (GST_IS_ELEMENT (element));
2525 /* set the loop function */
2526 element->loopfunc = loop;
2528 /* set the NEW_LOOPFUNC flag so everyone knows to go try again */
2529 GST_FLAG_SET (element, GST_ELEMENT_NEW_LOOPFUNC);
2533 * gst_element_set_eos:
2534 * @element: a #GstElement to set to the EOS state.
2536 * Perform the actions needed to bring the element in the EOS state.
2539 gst_element_set_eos (GstElement *element)
2541 g_return_if_fail (GST_IS_ELEMENT (element));
2543 GST_DEBUG (GST_CAT_EVENT, "setting EOS on element %s",
2544 GST_OBJECT_NAME (element));
2546 gst_element_set_state (element, GST_STATE_PAUSED);
2548 g_signal_emit (G_OBJECT (element), gst_element_signals[EOS], 0);
2553 * gst_element_state_get_name:
2554 * @state: a #GstElementState to get the name of.
2556 * Gets a string representing the given state.
2558 * Returns: a string with the name of the state.
2561 gst_element_state_get_name (GstElementState state)
2564 #ifdef GST_DEBUG_COLOR
2565 case GST_STATE_VOID_PENDING: return "NONE_PENDING";break;
2566 case GST_STATE_NULL: return "\033[01;37mNULL\033[00m";break;
2567 case GST_STATE_READY: return "\033[01;31mREADY\033[00m";break;
2568 case GST_STATE_PLAYING: return "\033[01;32mPLAYING\033[00m";break;
2569 case GST_STATE_PAUSED: return "\033[01;33mPAUSED\033[00m";break;
2571 /* This is a memory leak */
2572 return g_strdup_printf ("\033[01;37;41mUNKNOWN!\033[00m(%d)", state);
2574 case GST_STATE_VOID_PENDING: return "NONE_PENDING";break;
2575 case GST_STATE_NULL: return "NULL";break;
2576 case GST_STATE_READY: return "READY";break;
2577 case GST_STATE_PLAYING: return "PLAYING";break;
2578 case GST_STATE_PAUSED: return "PAUSED";break;
2579 default: return "UNKNOWN!";
2586 gst_element_populate_std_props (GObjectClass * klass, const gchar *prop_name,
2587 guint arg_id, GParamFlags flags)
2589 GQuark prop_id = g_quark_from_string (prop_name);
2592 static GQuark fd_id = 0;
2593 static GQuark blocksize_id;
2594 static GQuark bytesperread_id;
2595 static GQuark dump_id;
2596 static GQuark filesize_id;
2597 static GQuark mmapsize_id;
2598 static GQuark location_id;
2599 static GQuark offset_id;
2600 static GQuark silent_id;
2601 static GQuark touch_id;
2604 fd_id = g_quark_from_static_string ("fd");
2605 blocksize_id = g_quark_from_static_string ("blocksize");
2606 bytesperread_id = g_quark_from_static_string ("bytesperread");
2607 dump_id = g_quark_from_static_string ("dump");
2608 filesize_id = g_quark_from_static_string ("filesize");
2609 mmapsize_id = g_quark_from_static_string ("mmapsize");
2610 location_id = g_quark_from_static_string ("location");
2611 offset_id = g_quark_from_static_string ("offset");
2612 silent_id = g_quark_from_static_string ("silent");
2613 touch_id = g_quark_from_static_string ("touch");
2616 if (prop_id == fd_id) {
2617 pspec = g_param_spec_int ("fd", "File-descriptor",
2618 "File-descriptor for the file being read",
2619 0, G_MAXINT, 0, flags);
2621 else if (prop_id == blocksize_id) {
2622 pspec = g_param_spec_ulong ("blocksize", "Block Size",
2623 "Block size to read per buffer",
2624 0, G_MAXULONG, 4096, flags);
2627 else if (prop_id == bytesperread_id) {
2628 pspec = g_param_spec_int ("bytesperread", "Bytes per read",
2629 "Number of bytes to read per buffer",
2630 G_MININT, G_MAXINT, 0, flags);
2633 else if (prop_id == dump_id) {
2634 pspec = g_param_spec_boolean ("dump", "Dump",
2635 "Dump bytes to stdout",
2639 else if (prop_id == filesize_id) {
2640 pspec = g_param_spec_int64 ("filesize", "File Size",
2641 "Size of the file being read",
2642 0, G_MAXINT64, 0, flags);
2645 else if (prop_id == mmapsize_id) {
2646 pspec = g_param_spec_ulong ("mmapsize", "mmap() Block Size",
2647 "Size in bytes of mmap()d regions",
2648 0, G_MAXULONG, 4 * 1048576, flags);
2651 else if (prop_id == location_id) {
2652 pspec = g_param_spec_string ("location", "File Location",
2653 "Location of the file to read",
2657 else if (prop_id == offset_id) {
2658 pspec = g_param_spec_int64 ("offset", "File Offset",
2659 "Byte offset of current read pointer",
2660 0, G_MAXINT64, 0, flags);
2663 else if (prop_id == silent_id) {
2664 pspec = g_param_spec_boolean ("silent", "Silent", "Don't produce events",
2668 else if (prop_id == touch_id) {
2669 pspec = g_param_spec_boolean ("touch", "Touch read data",
2670 "Touch data to force disk read before "
2671 "push ()", TRUE, flags);
2674 g_warning ("Unknown - 'standard' property '%s' id %d from klass %s",
2675 prop_name, arg_id, g_type_name (G_OBJECT_CLASS_TYPE (klass)));
2680 g_object_class_install_property (klass, arg_id, pspec);
2685 * gst_element_class_install_std_props:
2686 * @klass: the #GstElementClass to add the properties to.
2687 * @first_name: the name of the first property.
2688 * in a NULL terminated
2689 * @...: the id and flags of the first property, followed by
2690 * further 'name', 'id', 'flags' triplets and terminated by NULL.
2692 * Adds a list of standardized properties with types to the @klass.
2693 * the id is for the property switch in your get_prop method, and
2694 * the flags determine readability / writeability.
2697 gst_element_class_install_std_props (GstElementClass * klass,
2698 const gchar *first_name, ...)
2704 g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
2706 va_start (args, first_name);
2711 int arg_id = va_arg (args, int);
2712 int flags = va_arg (args, int);
2714 gst_element_populate_std_props ((GObjectClass *) klass, name, arg_id, flags);
2716 name = va_arg (args, char *);
2723 * gst_element_get_managing_bin:
2724 * @element: a #GstElement to get the managing bin of.
2726 * Gets the managing bin (a pipeline or a thread, for example) of an element.
2728 * Returns: the #GstBin, or NULL on failure.
2731 gst_element_get_managing_bin (GstElement *element)
2735 g_return_val_if_fail (element != NULL, NULL);
2737 bin = GST_BIN (gst_object_get_parent (GST_OBJECT_CAST (element)));
2739 while (bin && !GST_FLAG_IS_SET (GST_OBJECT_CAST (bin), GST_BIN_FLAG_MANAGER))
2740 bin = GST_BIN (gst_object_get_parent (GST_OBJECT_CAST (bin)));