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 object that signalled the notify
251 * @orig: the object that intiated the notify
252 * @psepc: the paramspec of the property
253 * @excluded_props: user specified properties to exclude
255 * A default deep_notify signal callback that can be added 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, GParamSpec *pspec, gchar **excluded_props)
264 GValue value = { 0, }; /* the important thing is that value.type = 0 */
267 if (pspec->flags & G_PARAM_READABLE) {
268 /* let's not print these out for excluded properties... */
269 while (excluded_props != NULL && *excluded_props != NULL) {
270 if (strcmp (pspec->name, *excluded_props) == 0)
274 g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
275 g_object_get_property (G_OBJECT (orig), pspec->name, &value);
277 if (G_IS_PARAM_SPEC_ENUM (pspec)) {
278 GEnumValue *enum_value;
279 enum_value = g_enum_get_value (G_ENUM_CLASS (g_type_class_ref (pspec->value_type)),
280 g_value_get_enum (&value));
282 str = g_strdup_printf ("%s (%d)", enum_value->value_nick, enum_value->value);
285 str = g_strdup_value_contents (&value);
287 g_print ("%s: %s = %s\n", GST_OBJECT_NAME (orig), pspec->name, str);
289 g_value_unset(&value);
291 g_warning ("Parameter %s not readable in %s.", pspec->name, GST_OBJECT_NAME (orig));
296 * gst_element_default_error:
297 * @object: the object that signalled the error
298 * @orig: the object that intiated the error
299 * @error: the error message
301 * A default error signal callback that can be added to an
302 * element. The user data passed to the g_signal_connect is
304 * The default handler will smply print the error string
308 gst_element_default_error (GObject *object, GstObject *orig, gchar *error)
310 g_print ("ERROR: %s: %s\n", GST_OBJECT_NAME (orig), error);
314 const GParamSpec *pspec;
319 element_set_property (GstElement *element, const GParamSpec *pspec, const GValue *value)
321 prop_value_t *prop_value = g_new0 (prop_value_t, 1);
323 prop_value->pspec = pspec;
324 prop_value->value = value;
326 g_async_queue_push (element->prop_value_queue, prop_value);
330 element_get_property (GstElement *element, const GParamSpec *pspec, GValue *value)
332 g_mutex_lock (element->property_mutex);
333 g_object_get_property ((GObject*)element, pspec->name, value);
334 g_mutex_unlock (element->property_mutex);
338 gst_element_threadsafe_properties_pre_run (GstElement *element)
340 GST_DEBUG (GST_CAT_THREAD, "locking element %s", GST_OBJECT_NAME (element));
341 g_mutex_lock (element->property_mutex);
342 gst_element_set_pending_properties (element);
346 gst_element_threadsafe_properties_post_run (GstElement *element)
348 GST_DEBUG (GST_CAT_THREAD, "unlocking element %s", GST_OBJECT_NAME (element));
349 g_mutex_unlock (element->property_mutex);
353 * gst_element_enable_threadsafe_properties:
354 * @element: a #GstElement to enable the threadsafe properties on
356 * Install an async queue, a mutex and pre and post run functions on
357 * this element so that properties on the element can be set in a
361 gst_element_enable_threadsafe_properties (GstElement *element)
363 g_return_if_fail (GST_IS_ELEMENT (element));
365 GST_FLAG_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES);
366 element->pre_run_func = gst_element_threadsafe_properties_pre_run;
367 element->post_run_func = gst_element_threadsafe_properties_post_run;
368 if (!element->prop_value_queue)
369 element->prop_value_queue = g_async_queue_new ();
370 if (!element->property_mutex)
371 element->property_mutex = g_mutex_new ();
375 * gst_element_disable_threadsafe_properties:
376 * @element: a #GstElement to disable the threadsafe properties on
378 * Remove the threadsafe properties post and pre run locks from
382 gst_element_disable_threadsafe_properties (GstElement *element)
384 g_return_if_fail (GST_IS_ELEMENT (element));
386 GST_FLAG_UNSET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES);
387 element->pre_run_func = NULL;
388 element->post_run_func = NULL;
389 /* let's keep around that async queue */
393 * gst_element_set_pending_properties:
394 * @element: a #GstElement to set the pending properties on
396 * Set all pending properties on the threadsafe properties enabled
400 gst_element_set_pending_properties (GstElement *element)
402 prop_value_t *prop_value;
404 while ((prop_value = g_async_queue_try_pop (element->prop_value_queue))) {
405 g_object_set_property ((GObject*)element, prop_value->pspec->name, prop_value->value);
410 /* following 6 functions taken mostly from gobject.c */
414 * @element: a #GstElement to set properties on
415 * @first_property_name: The first property to set
416 * @...: more properties to set
418 * Set properties on an element. If the element uses threadsafe properties,
419 * they will be queued and set to the object when it is scheduled again.
422 gst_element_set (GstElement *element, const gchar *first_property_name, ...)
426 g_return_if_fail (GST_IS_ELEMENT (element));
428 va_start (var_args, first_property_name);
429 gst_element_set_valist (element, first_property_name, var_args);
435 * @element: a #GstElement to get properties of
436 * @first_property_name: The first property to get
437 * @...: more properties to get
439 * Get properties from an element. If the element uses threadsafe properties,
440 * the element will be locked before getting the given properties.
443 gst_element_get (GstElement *element, const gchar *first_property_name, ...)
447 g_return_if_fail (GST_IS_ELEMENT (element));
449 va_start (var_args, first_property_name);
450 gst_element_get_valist (element, first_property_name, var_args);
455 * gst_element_set_valist:
456 * @element: a #GstElement to set properties on
457 * @first_property_name: The first property to set
458 * @var_args: a var_args list of other properties to get
460 * Set properties on an element. If the element uses threadsafe properties,
461 * the property change will be put on the async queue.
464 gst_element_set_valist (GstElement *element, const gchar *first_property_name, va_list var_args)
469 g_return_if_fail (GST_IS_ELEMENT (element));
471 object = (GObject*)element;
473 if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
474 g_object_set_valist (object, first_property_name, var_args);
478 g_object_ref (object);
480 name = first_property_name;
484 GValue value = { 0, };
488 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), name);
492 g_warning ("%s: object class `%s' has no property named `%s'",
494 G_OBJECT_TYPE_NAME (object),
498 if (!(pspec->flags & G_PARAM_WRITABLE))
500 g_warning ("%s: property `%s' of object class `%s' is not writable",
503 G_OBJECT_TYPE_NAME (object));
507 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
509 G_VALUE_COLLECT (&value, var_args, 0, &error);
512 g_warning ("%s: %s", G_STRLOC, error);
515 /* we purposely leak the value here, it might not be
516 * in a sane state if an error condition occoured
521 element_set_property (element, pspec, &value);
522 g_value_unset (&value);
524 name = va_arg (var_args, gchar*);
527 g_object_unref (object);
531 * gst_element_get_valist:
532 * @element: a #GstElement to get properties of
533 * @first_property_name: The first property to get
534 * @var_args: a var_args list of other properties to get
536 * Get properties from an element. If the element uses threadsafe properties,
537 * the element will be locked before getting the given properties.
540 gst_element_get_valist (GstElement *element, const gchar *first_property_name, va_list var_args)
545 g_return_if_fail (GST_IS_ELEMENT (element));
547 object = (GObject*)element;
549 if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
550 g_object_get_valist (object, first_property_name, var_args);
554 g_object_ref (object);
556 name = first_property_name;
560 GValue value = { 0, };
564 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), name);
568 g_warning ("%s: object class `%s' has no property named `%s'",
570 G_OBJECT_TYPE_NAME (object),
574 if (!(pspec->flags & G_PARAM_READABLE))
576 g_warning ("%s: property `%s' of object class `%s' is not readable",
579 G_OBJECT_TYPE_NAME (object));
583 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
585 element_get_property (element, pspec, &value);
587 G_VALUE_LCOPY (&value, var_args, 0, &error);
590 g_warning ("%s: %s", G_STRLOC, error);
592 g_value_unset (&value);
596 g_value_unset (&value);
598 name = va_arg (var_args, gchar*);
601 g_object_unref (object);
605 * gst_element_set_property:
606 * @element: a #GstElement to set properties on
607 * @property_name: The first property to get
608 * @value: GValue that hold the value to set
610 * Set a property on an element. If the element uses threadsafe properties,
611 * the property will be put on the async queue.
614 gst_element_set_property (GstElement *element, const gchar *property_name, const GValue *value)
619 g_return_if_fail (GST_IS_ELEMENT (element));
620 g_return_if_fail (property_name != NULL);
621 g_return_if_fail (G_IS_VALUE (value));
623 object = (GObject*)element;
625 if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
626 g_object_set_property (object, property_name, value);
630 g_object_ref (object);
632 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), property_name);
635 g_warning ("%s: object class `%s' has no property named `%s'",
637 G_OBJECT_TYPE_NAME (object),
640 element_set_property (element, pspec, value);
642 g_object_unref (object);
646 * gst_element_get_property:
647 * @element: a #GstElement to get properties of
648 * @property_name: The first property to get
649 * @value: Target GValue to hold the property value
651 * Get a property from an element. If the element uses threadsafe properties,
652 * the element will be locked before getting the given property.
655 gst_element_get_property (GstElement *element, const gchar *property_name, GValue *value)
660 g_return_if_fail (GST_IS_ELEMENT (element));
661 g_return_if_fail (property_name != NULL);
662 g_return_if_fail (G_IS_VALUE (value));
664 object = (GObject*)element;
666 if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
667 g_object_get_property (object, property_name, value);
671 g_object_ref (object);
673 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), property_name);
676 g_warning ("%s: object class `%s' has no property named `%s'",
678 G_OBJECT_TYPE_NAME (object),
682 GValue *prop_value, tmp_value = { 0, };
684 /* auto-conversion of the callers value type
686 if (G_VALUE_TYPE (value) == G_PARAM_SPEC_VALUE_TYPE (pspec))
688 g_value_reset (value);
691 else if (!g_value_type_transformable (G_PARAM_SPEC_VALUE_TYPE (pspec), G_VALUE_TYPE (value)))
693 g_warning ("can't retrieve property `%s' of type `%s' as value of type `%s'",
695 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
696 G_VALUE_TYPE_NAME (value));
697 g_object_unref (object);
702 g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
703 prop_value = &tmp_value;
705 element_get_property (element, pspec, prop_value);
706 if (prop_value != value)
708 g_value_transform (prop_value, value);
709 g_value_unset (&tmp_value);
713 g_object_unref (object);
717 gst_element_request_pad (GstElement *element, GstPadTemplate *templ, const gchar* name)
719 GstPad *newpad = NULL;
720 GstElementClass *oclass;
722 oclass = CLASS (element);
723 if (oclass->request_new_pad)
724 newpad = (oclass->request_new_pad)(element, templ, name);
730 * gst_element_release_request_pad:
731 * @element: a #GstElement to release the request pad of
732 * @pad: The pad to release
734 * Make the element free the previously requested pad as obtained
735 * with gst_element_get_request_pad().
738 gst_element_release_request_pad (GstElement *element, GstPad *pad)
740 GstElementClass *oclass;
742 g_return_if_fail (GST_IS_ELEMENT (element));
743 g_return_if_fail (GST_IS_PAD (pad));
745 oclass = CLASS (element);
746 if (oclass->release_pad)
747 (oclass->release_pad) (element, pad);
752 * gst_element_set_name:
753 * @element: a #GstElement to set name of
754 * @name: new name of element
756 * Sets the name of the element, getting rid of the old name if there was
760 gst_element_set_name (GstElement *element, const gchar *name)
762 g_return_if_fail (element != NULL);
763 g_return_if_fail (GST_IS_ELEMENT (element));
765 gst_object_set_name (GST_OBJECT (element), name);
769 * gst_element_get_name:
770 * @element: a #GstElement to get name of
772 * Gets the name of the element.
774 * Returns: name of the element
777 gst_element_get_name (GstElement *element)
779 g_return_val_if_fail (element != NULL, NULL);
780 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
782 return GST_OBJECT_NAME (element);
786 * gst_element_set_parent:
787 * @element: a #GstElement to set parent of
788 * @parent: new parent of the object
790 * Sets the parent of the element.
793 gst_element_set_parent (GstElement *element, GstObject *parent)
795 g_return_if_fail (element != NULL);
796 g_return_if_fail (GST_IS_ELEMENT (element));
797 g_return_if_fail (GST_OBJECT_PARENT (element) == NULL);
798 g_return_if_fail (parent != NULL);
799 g_return_if_fail (GST_IS_OBJECT (parent));
800 g_return_if_fail ((gpointer)element != (gpointer)parent);
802 gst_object_set_parent (GST_OBJECT (element), parent);
806 * gst_element_get_parent:
807 * @element: a #GstElement to get the parent of
809 * Gets the parent of the element.
811 * Returns: the #GstElement parent of the element
814 gst_element_get_parent (GstElement *element)
816 g_return_val_if_fail (element != NULL, NULL);
817 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
819 return GST_OBJECT_PARENT (element);
823 * gst_element_set_clock:
824 * @element: a #GstElement to set the clock for
825 * @clock: the #GstClock to set for the element
827 * Sets the clock for the element.
830 gst_element_set_clock (GstElement *element, GstClock *clock)
832 g_return_if_fail (element != NULL);
833 g_return_if_fail (GST_IS_ELEMENT (element));
835 if (element->setclockfunc)
836 element->setclockfunc (element, clock);
838 element->clock = clock;
842 * gst_element_get_clock:
843 * @element: a #GstElement to get the clock of
845 * Gets the clock of the element.
847 * Returns: the #GstClock of the element.
850 gst_element_get_clock (GstElement *element)
852 g_return_val_if_fail (element != NULL, NULL);
853 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
855 if (element->getclockfunc)
856 return element->getclockfunc (element);
862 * gst_element_clock_wait:
863 * @element: a #GstElement
864 * @clock: the #GstClock to use
865 * @time: the #GstClockTime to wait for on the clock
866 * @jitter: The difference between requested time and actual time
868 * Waits for a specific time on the clock.
870 * Returns: the #GstClockReturn result of the wait operation
873 gst_element_clock_wait (GstElement *element, GstClock *clock, GstClockTime time, GstClockTimeDiff *jitter)
877 g_return_val_if_fail (element != NULL, GST_CLOCK_ERROR);
878 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_CLOCK_ERROR);
880 if (GST_ELEMENT_SCHED (element)) {
881 res = gst_scheduler_clock_wait (GST_ELEMENT_SCHED (element), element, clock, time, jitter);
884 res = GST_CLOCK_TIMEOUT;
891 * gst_element_release_locks:
892 * @element: an element
894 * Instruct the element to release all the locks it is holding, such as
895 * blocking reads, waiting for the clock, ...
897 * Returns: TRUE if the locks could be released.
900 gst_element_release_locks (GstElement *element)
902 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
904 if (CLASS (element)->release_locks)
905 return CLASS (element)->release_locks (element);
911 * gst_element_add_pad:
912 * @element: element to add pad to
915 * Add a pad (connection point) to the element, setting the parent of the
916 * pad to the element (and thus adding a reference).
919 gst_element_add_pad (GstElement *element, GstPad *pad)
921 g_return_if_fail (element != NULL);
922 g_return_if_fail (GST_IS_ELEMENT (element));
923 g_return_if_fail (pad != NULL);
924 g_return_if_fail (GST_IS_PAD (pad));
926 /* first check to make sure the pad's parent is already set */
927 g_return_if_fail (GST_PAD_PARENT (pad) == NULL);
929 /* then check to see if there's already a pad by that name here */
930 g_return_if_fail (gst_object_check_uniqueness (element->pads, GST_PAD_NAME(pad)) == TRUE);
932 /* set the pad's parent */
933 GST_DEBUG (GST_CAT_ELEMENT_PADS,"setting parent of pad '%s' to '%s'",
934 GST_PAD_NAME (pad), GST_ELEMENT_NAME (element));
935 gst_object_set_parent (GST_OBJECT (pad), GST_OBJECT (element));
937 /* add it to the list */
938 element->pads = g_list_append (element->pads, pad);
940 if (gst_pad_get_direction (pad) == GST_PAD_SRC)
941 element->numsrcpads++;
943 element->numsinkpads++;
945 /* emit the NEW_PAD signal */
946 g_signal_emit (G_OBJECT (element), gst_element_signals[NEW_PAD], 0, pad);
950 * gst_element_remove_pad:
951 * @element: element to remove pad from
952 * @pad: pad to remove
954 * Remove a pad (connection point) from the element,
957 gst_element_remove_pad (GstElement *element, GstPad *pad)
959 g_return_if_fail (element != NULL);
960 g_return_if_fail (GST_IS_ELEMENT (element));
961 g_return_if_fail (pad != NULL);
962 g_return_if_fail (GST_IS_PAD (pad));
964 g_return_if_fail (GST_PAD_PARENT (pad) == element);
966 /* check to see if the pad is still connected */
967 /* FIXME: what if someone calls _remove_pad instead of
968 _remove_ghost_pad? */
969 if (GST_IS_REAL_PAD (pad)) {
970 g_return_if_fail (GST_RPAD_PEER (pad) == NULL);
973 /* remove it from the list */
974 element->pads = g_list_remove (element->pads, pad);
976 if (gst_pad_get_direction (pad) == GST_PAD_SRC)
977 element->numsrcpads--;
979 element->numsinkpads--;
981 g_signal_emit (G_OBJECT (element), gst_element_signals[PAD_REMOVED], 0, pad);
983 gst_object_unparent (GST_OBJECT (pad));
987 * gst_element_add_ghost_pad:
988 * @element: element to add ghost pad to
989 * @pad: pad from which the new ghost pad will be created
990 * @name: name of the new ghost pad
992 * Create a ghost pad from the given pad, and add it to the list of pads
995 * Returns: the added ghost pad or NULL, if no ghost pad was created.
998 gst_element_add_ghost_pad (GstElement *element, GstPad *pad, gchar *name)
1002 g_return_val_if_fail (element != NULL, NULL);
1003 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1004 g_return_val_if_fail (pad != NULL, NULL);
1005 g_return_val_if_fail (GST_IS_PAD (pad), NULL);
1007 /* then check to see if there's already a pad by that name here */
1008 g_return_val_if_fail (gst_object_check_uniqueness (element->pads, name) == TRUE, NULL);
1010 GST_DEBUG(GST_CAT_ELEMENT_PADS,"creating new ghost pad called %s, from pad %s:%s",
1011 name,GST_DEBUG_PAD_NAME(pad));
1012 ghostpad = gst_ghost_pad_new (name, pad);
1014 /* add it to the list */
1015 GST_DEBUG(GST_CAT_ELEMENT_PADS,"adding ghost pad %s to element %s",
1016 name, GST_ELEMENT_NAME (element));
1017 element->pads = g_list_append (element->pads, ghostpad);
1019 /* set the parent of the ghostpad */
1020 gst_object_set_parent (GST_OBJECT (ghostpad), GST_OBJECT (element));
1022 GST_DEBUG(GST_CAT_ELEMENT_PADS,"added ghostpad %s:%s",GST_DEBUG_PAD_NAME(ghostpad));
1024 /* emit the NEW_GHOST_PAD signal */
1025 g_signal_emit (G_OBJECT (element), gst_element_signals[NEW_PAD], 0, ghostpad);
1031 * gst_element_remove_ghost_pad:
1032 * @element: element to remove the ghost pad from
1033 * @pad: ghost pad to remove
1035 * removes a ghost pad from an element
1038 gst_element_remove_ghost_pad (GstElement *element, GstPad *pad)
1040 g_return_if_fail (element != NULL);
1041 g_return_if_fail (GST_IS_ELEMENT (element));
1042 g_return_if_fail (pad != NULL);
1043 g_return_if_fail (GST_IS_GHOST_PAD (pad));
1045 /* FIXME this is redundant?
1046 * wingo 10-july-2001: I don't think so, you have to actually remove the pad
1047 * from the element. gst_pad_remove_ghost_pad just removes the ghostpad from
1048 * the real pad's ghost pad list
1050 gst_pad_remove_ghost_pad (GST_PAD (GST_PAD_REALIZE (pad)), pad);
1051 gst_element_remove_pad (element, pad);
1056 * gst_element_get_pad:
1057 * @element: element to find pad of
1058 * @name: name of pad to retrieve
1060 * Retrieve a pad from the element by name.
1062 * Returns: requested pad if found, otherwise NULL.
1065 gst_element_get_pad (GstElement *element, const gchar *name)
1069 g_return_val_if_fail (element != NULL, NULL);
1070 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1071 g_return_val_if_fail (name != NULL, NULL);
1073 if ((pad = gst_element_get_static_pad (element, name)))
1076 pad = gst_element_get_request_pad (element, name);
1082 * gst_element_get_static_pad:
1083 * @element: element to find pad of
1084 * @name: name of pad to retrieve
1086 * Retrieve a pad from the element by name. This version only retrieves
1087 * already-existing (i.e. 'static') pads.
1089 * Returns: requested pad if found, otherwise NULL.
1092 gst_element_get_static_pad (GstElement *element, const gchar *name)
1096 g_return_val_if_fail (element != NULL, NULL);
1097 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1098 g_return_val_if_fail (name != NULL, NULL);
1100 walk = element->pads;
1104 pad = GST_PAD(walk->data);
1105 if (strcmp (GST_PAD_NAME(pad), name) == 0) {
1106 GST_INFO (GST_CAT_ELEMENT_PADS, "found pad %s:%s", GST_DEBUG_PAD_NAME (pad));
1109 walk = g_list_next (walk);
1112 GST_INFO (GST_CAT_ELEMENT_PADS, "no such pad '%s' in element \"%s\"", name, GST_OBJECT_NAME (element));
1117 * gst_element_get_request_pad:
1118 * @element: element to find pad of
1119 * @name: name of pad to retrieve
1121 * Retrieve a pad from the element by name. This version only retrieves
1124 * Returns: requested pad if found, otherwise NULL.
1127 gst_element_get_request_pad (GstElement *element, const gchar *name)
1129 GstPadTemplate *templ = NULL;
1131 const gchar *req_name = NULL;
1132 gboolean templ_found = FALSE;
1136 gchar *str, *endptr = NULL;
1138 g_return_val_if_fail (element != NULL, NULL);
1139 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1140 g_return_val_if_fail (name != NULL, NULL);
1142 if (strstr (name, "%")) {
1143 templ = gst_element_get_pad_template (element, name);
1148 list = gst_element_get_pad_template_list(element);
1149 while (!templ_found && list) {
1150 templ = (GstPadTemplate*) list->data;
1151 if (templ->presence == GST_PAD_REQUEST) {
1152 /* we know that %s and %d are the only possibilities because of sanity
1153 checks in gst_pad_template_new */
1154 GST_DEBUG (GST_CAT_PADS, "comparing %s to %s", name, templ->name_template);
1155 if ((str = strchr (templ->name_template, '%')) &&
1156 strncmp (templ->name_template, name, str - templ->name_template) == 0 &&
1157 strlen (name) > str - templ->name_template) {
1158 data = name + (str - templ->name_template);
1159 if (*(str+1) == 'd') {
1161 n = (gint) strtol (data, &endptr, 10);
1162 if (endptr && *endptr == '\0') {
1182 pad = gst_element_request_pad (element, templ, req_name);
1188 * gst_element_get_pad_list:
1189 * @element: element to get pads of
1191 * Retrieve a list of the pads associated with the element.
1193 * Returns: GList of pads
1196 gst_element_get_pad_list (GstElement *element)
1198 g_return_val_if_fail (element != NULL, NULL);
1199 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1201 /* return the list of pads */
1202 return element->pads;
1206 * gst_element_class_add_pad_template:
1207 * @klass: element class to add padtemplate to
1208 * @templ: padtemplate to add
1210 * Add a padtemplate to an element class. This is useful if you have derived a custom
1211 * bin and wish to provide an on-request pad at runtime. Plugin writers should use
1212 * gst_element_factory_add_pad_template instead.
1215 gst_element_class_add_pad_template (GstElementClass *klass, GstPadTemplate *templ)
1217 g_return_if_fail (klass != NULL);
1218 g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
1219 g_return_if_fail (templ != NULL);
1220 g_return_if_fail (GST_IS_PAD_TEMPLATE (templ));
1222 klass->padtemplates = g_list_append (klass->padtemplates, templ);
1223 klass->numpadtemplates++;
1227 * gst_element_get_pad_template_list:
1228 * @element: element to get padtemplates of
1230 * Retrieve a list of the padtemplates associated with the element.
1232 * Returns: GList of padtemplates
1235 gst_element_get_pad_template_list (GstElement *element)
1237 g_return_val_if_fail (element != NULL, NULL);
1238 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1240 return CLASS (element)->padtemplates;
1244 * gst_element_get_pad_template:
1245 * @element: element to get padtemplate of
1246 * @name: the name of the padtemplate to get.
1248 * Retrieve a padtemplate from this element with the
1251 * Returns: the padtemplate with the given name. No unreferencing is necessary.
1254 gst_element_get_pad_template (GstElement *element, const guchar *name)
1258 g_return_val_if_fail (element != NULL, NULL);
1259 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1260 g_return_val_if_fail (name != NULL, NULL);
1262 padlist = gst_element_get_pad_template_list (element);
1265 GstPadTemplate *padtempl = (GstPadTemplate*) padlist->data;
1267 if (!strcmp (padtempl->name_template, name))
1270 padlist = g_list_next (padlist);
1277 * gst_element_get_compatible_pad_template:
1278 * @element: element to get padtemplate of
1279 * @compattempl: a template to find a compatible template for
1281 * Generate a padtemplate for this element compatible with the given
1282 * template, ie able to link to it.
1284 * Returns: the padtemplate. No unreferencing is necessary.
1287 gst_element_get_compatible_pad_template (GstElement *element, GstPadTemplate *compattempl)
1289 GstPadTemplate *newtempl = NULL;
1292 GST_DEBUG(GST_CAT_ELEMENT_PADS,"gst_element_get_compatible_pad_template()");
1294 g_return_val_if_fail (element != NULL, NULL);
1295 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1296 g_return_val_if_fail (compattempl != NULL, NULL);
1298 padlist = gst_element_get_pad_template_list (element);
1301 GstPadTemplate *padtempl = (GstPadTemplate*) padlist->data;
1302 gboolean compat = FALSE;
1306 * Check direction (must be opposite)
1309 GST_DEBUG(GST_CAT_CAPS,"checking direction and caps");
1310 if (padtempl->direction == GST_PAD_SRC &&
1311 compattempl->direction == GST_PAD_SINK) {
1312 GST_DEBUG(GST_CAT_CAPS,"compatible direction: found src pad template");
1313 compat = gst_caps_check_compatibility(GST_PAD_TEMPLATE_CAPS (padtempl),
1314 GST_PAD_TEMPLATE_CAPS (compattempl));
1315 GST_DEBUG(GST_CAT_CAPS,"caps are %scompatible", (compat?"":"not "));
1316 } else if (padtempl->direction == GST_PAD_SINK &&
1317 compattempl->direction == GST_PAD_SRC) {
1318 GST_DEBUG(GST_CAT_CAPS,"compatible direction: found sink pad template");
1319 compat = gst_caps_check_compatibility(GST_PAD_TEMPLATE_CAPS (compattempl),
1320 GST_PAD_TEMPLATE_CAPS (padtempl));
1321 GST_DEBUG(GST_CAT_CAPS,"caps are %scompatible", (compat?"":"not "));
1325 newtempl = padtempl;
1329 padlist = g_list_next (padlist);
1336 * gst_element_request_compatible_pad:
1337 * @element: element to request a new pad from
1338 * @templ: a pad template to which the new pad should be able to connect
1340 * Request a new pad from the element. The template will
1341 * be used to decide what type of pad to create. This function
1342 * is typically used for elements with a padtemplate with presence
1345 * Returns: the new pad that was created.
1348 gst_element_request_compatible_pad (GstElement *element, GstPadTemplate *templ)
1350 GstPadTemplate *templ_new;
1353 g_return_val_if_fail (element != NULL, NULL);
1354 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1355 g_return_val_if_fail (templ != NULL, NULL);
1357 templ_new = gst_element_get_compatible_pad_template (element, templ);
1358 if (templ_new != NULL)
1359 pad = gst_element_request_pad (element, templ_new, NULL);
1366 * gst_element_get_compatible_pad_filtered:
1367 * @element: the element in which the pad should be found
1368 * @pad: the pad to find a compatible one for
1369 * @filtercaps: the caps to use as a filter
1371 * Looks for an unconnected pad to which the given pad can connect to.
1372 * It is not guaranteed that connecting the pads will work, though
1373 * it should work in most cases.
1375 * Returns: the pad to which a connection can be made
1378 gst_element_get_compatible_pad_filtered (GstElement *element, GstPad *pad, GstCaps *filtercaps)
1381 GstPadTemplate *templ;
1383 GstPad *foundpad = NULL;
1386 g_return_val_if_fail (element != NULL, NULL);
1387 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1388 g_return_val_if_fail (pad != NULL, NULL);
1389 g_return_val_if_fail (GST_IS_PAD (pad), NULL);
1391 /* let's use the real pad */
1392 pad = (GstPad *) GST_PAD_REALIZE (pad);
1393 g_return_val_if_fail (pad != NULL, NULL);
1394 g_return_val_if_fail (GST_RPAD_PEER (pad) == NULL, NULL);
1396 /* try to get an existing unconnected pad */
1397 pads = gst_element_get_pad_list (element);
1399 GstPad *current = GST_PAD (pads->data);
1400 if ((GST_PAD_PEER (GST_PAD_REALIZE (current)) == NULL) &&
1401 gst_pad_can_connect_filtered (pad, current, filtercaps)) {
1404 pads = g_list_next (pads);
1407 /* try to create a new one */
1408 /* requesting is a little crazy, we need a template. Let's create one */
1409 if (filtercaps != NULL) {
1410 templcaps = gst_caps_intersect (filtercaps, (GstCaps *) GST_RPAD_CAPS (pad));
1411 if (templcaps == NULL)
1414 templcaps = gst_caps_copy (gst_pad_get_caps (pad));
1417 templ = gst_pad_template_new ((gchar *) GST_PAD_NAME (pad), GST_RPAD_DIRECTION (pad),
1418 GST_PAD_ALWAYS, templcaps, NULL);
1419 foundpad = gst_element_request_compatible_pad (element, templ);
1420 gst_object_unref (GST_OBJECT (templ)); /* this will take care of the caps too */
1422 /* FIXME: this is broken, but it's in here so autoplugging elements that don't
1423 have caps on their source padtemplates (spider) can connect... */
1424 if (!foundpad && !filtercaps) {
1425 templ = gst_pad_template_new ((gchar *) GST_PAD_NAME (pad), GST_RPAD_DIRECTION (pad),
1426 GST_PAD_ALWAYS, NULL, NULL);
1427 foundpad = gst_element_request_compatible_pad (element, templ);
1428 gst_object_unref (GST_OBJECT (templ));
1435 * gst_element_get_compatible_pad:
1436 * @element: the element in which the pad should be found
1437 * @pad: the pad to find a compatible one for
1439 * Looks for an unconnected pad to which the given pad can connect to.
1440 * It is not guaranteed that connecting the pads will work, though
1441 * it should work in most cases.
1443 * Returns: the pad to which a connection can be made
1446 gst_element_get_compatible_pad (GstElement *element, GstPad *pad)
1448 return gst_element_get_compatible_pad_filtered (element, pad, NULL);
1452 * gst_element_connect_filtered:
1453 * @src: the element containing source pad
1454 * @dest: the element containing destination pad
1455 * @filtercaps: the caps to use as filter
1457 * Connect the source to the destination element using the filtercaps.
1458 * The connection must be from source to destination, the other
1459 * direction will not be tried.
1460 * The functions looks for existing pads that aren't connected yet.
1461 + It will use request pads if possible. But both pads will not be requested.
1462 * If multiple connections are possible, only one is established.
1464 * Returns: TRUE if the elements could be connected.
1467 gst_element_connect_filtered (GstElement *src, GstElement *dest,
1468 GstCaps *filtercaps)
1470 GList *srcpads, *destpads, *srctempls, *desttempls, *l;
1471 GstPad *srcpad, *destpad;
1472 GstPadTemplate *srctempl, *desttempl;
1475 g_return_val_if_fail (src != NULL, FALSE);
1476 g_return_val_if_fail (GST_IS_ELEMENT(src), FALSE);
1477 g_return_val_if_fail (dest != NULL, FALSE);
1478 g_return_val_if_fail (GST_IS_ELEMENT(dest), FALSE);
1480 GST_DEBUG (GST_CAT_ELEMENT_PADS, "attempting to connect element %s to element %s", GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (dest));
1482 /* loop through the existing pads in the source */
1483 srcpads = gst_element_get_pad_list (src);
1484 destpads = gst_element_get_pad_list (dest);
1486 if (srcpads || destpads) {
1488 srcpad = (GstPad *) GST_PAD_REALIZE (srcpads->data);
1489 if ((GST_RPAD_DIRECTION (srcpad) == GST_PAD_SRC) &&
1490 (GST_PAD_PEER (srcpad) == NULL)) {
1491 destpad = gst_element_get_compatible_pad_filtered (dest, srcpad, filtercaps);
1492 if (destpad && gst_pad_connect_filtered (srcpad, destpad, filtercaps)) {
1493 GST_DEBUG (GST_CAT_ELEMENT_PADS, "connected pad %s:%s to pad %s:%s", GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad));
1497 srcpads = g_list_next (srcpads);
1500 /* loop through the existing pads in the destination */
1502 destpad = (GstPad *) GST_PAD_REALIZE (destpads->data);
1503 if ((GST_RPAD_DIRECTION (destpad) == GST_PAD_SINK) &&
1504 (GST_PAD_PEER (destpad) == NULL)) {
1505 srcpad = gst_element_get_compatible_pad_filtered (src, destpad, filtercaps);
1506 if (srcpad && gst_pad_connect_filtered (srcpad, destpad, filtercaps)) {
1507 GST_DEBUG (GST_CAT_ELEMENT_PADS, "connected pad %s:%s to pad %s:%s", GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad));
1511 destpads = g_list_next (destpads);
1515 GST_DEBUG (GST_CAT_ELEMENT_PADS, "we might have request pads on both sides, checking...");
1516 srctempls = gst_element_get_pad_template_list (src);
1517 desttempls = gst_element_get_pad_template_list (dest);
1519 if (srctempls && desttempls) {
1521 srctempl = (GstPadTemplate*) srctempls->data;
1522 if (srctempl->presence == GST_PAD_REQUEST) {
1523 for (l=desttempls; l; l=l->next) {
1524 desttempl = (GstPadTemplate*) desttempls->data;
1525 if (desttempl->presence == GST_PAD_REQUEST && desttempl->direction != srctempl->direction) {
1526 if (gst_caps_check_compatibility (gst_pad_template_get_caps (srctempl),
1527 gst_pad_template_get_caps (desttempl))) {
1528 srcpad = gst_element_get_request_pad (src, srctempl->name_template);
1529 destpad = gst_element_get_request_pad (dest, desttempl->name_template);
1530 if (gst_pad_connect_filtered (srcpad, destpad, filtercaps)) {
1531 GST_DEBUG (GST_CAT_ELEMENT_PADS, "connected pad %s:%s to pad %s:%s",
1532 GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad));
1535 /* FIXME: we have extraneous request pads lying around */
1540 srctempls = srctempls->next;
1544 GST_DEBUG (GST_CAT_ELEMENT_PADS, "no connection possible from %s to %s", GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (dest));
1549 * gst_element_connect_many:
1550 * @element_1: the first element in the connection chain
1551 * @element_2: the second element in the connection chain
1552 * @...: NULL-terminated list of elements to connect in order
1554 * Chain together a series of elements. Uses #gst_element_connect.
1556 * Returns: TRUE on success, FALSE otherwise.
1559 gst_element_connect_many (GstElement *element_1, GstElement *element_2, ...)
1563 g_return_val_if_fail (element_1 != NULL && element_2 != NULL, FALSE);
1564 g_return_val_if_fail (GST_IS_ELEMENT (element_1) && GST_IS_ELEMENT (element_2), FALSE);
1566 va_start (args, element_2);
1569 if (!gst_element_connect (element_1, element_2))
1572 element_1 = element_2;
1573 element_2 = va_arg (args, GstElement*);
1582 * gst_element_connect:
1583 * @src: element containing source pad
1584 * @dest: element containing destination pad
1586 * Connect the source to the destination element.
1587 * The connection must be from source to destination, the other
1588 * direction will not be tried.
1589 * The functions looks for existing pads and request pads that aren't
1590 * connected yet. If multiple connections are possible, only one is
1593 * Returns: TRUE if the elements could be connected.
1596 gst_element_connect (GstElement *src, GstElement *dest)
1598 return gst_element_connect_filtered (src, dest, NULL);
1602 * gst_element_connect_pads_filtered:
1603 * @src: element containing source pad
1604 * @srcpadname: name of pad in source element
1605 * @dest: element containing destination pad
1606 * @destpadname: name of pad in destination element
1607 * @filtercaps: the caps to use as a filter
1609 * Connect the two named pads of the source and destination elements.
1610 * Side effect is that if one of the pads has no parent, it becomes a
1611 * child of the parent of the other element. If they have different
1612 * parents, the connection fails.
1614 * Returns: TRUE if the pads could be connected.
1617 gst_element_connect_pads_filtered (GstElement *src, const gchar *srcpadname,
1618 GstElement *dest, const gchar *destpadname,
1619 GstCaps *filtercaps)
1621 GstPad *srcpad,*destpad;
1623 g_return_val_if_fail (src != NULL, FALSE);
1624 g_return_val_if_fail (GST_IS_ELEMENT (src), FALSE);
1625 g_return_val_if_fail (srcpadname != NULL, FALSE);
1626 g_return_val_if_fail (dest != NULL, FALSE);
1627 g_return_val_if_fail (GST_IS_ELEMENT (dest), FALSE);
1628 g_return_val_if_fail (destpadname != NULL, FALSE);
1630 /* obtain the pads requested */
1631 srcpad = gst_element_get_pad (src, srcpadname);
1632 if (srcpad == NULL) {
1633 GST_ERROR (src, "source element has no pad \"%s\"", srcpadname);
1636 destpad = gst_element_get_pad (dest, destpadname);
1637 if (srcpad == NULL) {
1638 GST_ERROR (dest, "destination element has no pad \"%s\"", destpadname);
1642 /* we're satisified they can be connected, let's do it */
1643 return gst_pad_connect_filtered (srcpad, destpad, filtercaps);
1647 * gst_element_connect_pads:
1648 * @src: element containing source pad
1649 * @srcpadname: name of pad in source element
1650 * @dest: element containing destination pad
1651 * @destpadname: name of pad in destination element
1653 * Connect the two named pads of the source and destination elements.
1654 * Side effect is that if one of the pads has no parent, it becomes a
1655 * child of the parent of the other element. If they have different
1656 * parents, the connection fails.
1658 * Returns: TRUE if the pads could be connected.
1661 gst_element_connect_pads (GstElement *src, const gchar *srcpadname,
1662 GstElement *dest, const gchar *destpadname)
1664 return gst_element_connect_pads_filtered (src, srcpadname, dest, destpadname, NULL);
1668 * gst_element_disconnect_pads:
1669 * @src: element containing source pad
1670 * @srcpadname: name of pad in source element
1671 * @dest: element containing destination pad
1672 * @destpadname: name of pad in destination element
1674 * Disconnect the two named pads of the source and destination elements.
1677 gst_element_disconnect_pads (GstElement *src, const gchar *srcpadname,
1678 GstElement *dest, const gchar *destpadname)
1680 GstPad *srcpad,*destpad;
1682 g_return_if_fail (src != NULL);
1683 g_return_if_fail (GST_IS_ELEMENT(src));
1684 g_return_if_fail (srcpadname != NULL);
1685 g_return_if_fail (dest != NULL);
1686 g_return_if_fail (GST_IS_ELEMENT(dest));
1687 g_return_if_fail (destpadname != NULL);
1689 /* obtain the pads requested */
1690 srcpad = gst_element_get_pad (src, srcpadname);
1691 if (srcpad == NULL) {
1692 GST_ERROR(src,"source element has no pad \"%s\"",srcpadname);
1695 destpad = gst_element_get_pad (dest, destpadname);
1696 if (srcpad == NULL) {
1697 GST_ERROR(dest,"destination element has no pad \"%s\"",destpadname);
1701 /* we're satisified they can be disconnected, let's do it */
1702 gst_pad_disconnect(srcpad,destpad);
1706 * gst_element_disconnect_many:
1707 * @element_1: the first element in the connection chain
1708 * @element_2: the second element in the connection chain
1709 * @...: NULL-terminated list of elements to disconnect in order
1711 * Disconnect a series of elements. Uses #gst_element_disconnect.
1714 gst_element_disconnect_many (GstElement *element_1, GstElement *element_2, ...)
1718 g_return_if_fail (element_1 != NULL && element_2 != NULL);
1719 g_return_if_fail (GST_IS_ELEMENT (element_1) && GST_IS_ELEMENT (element_2));
1721 va_start (args, element_2);
1724 gst_element_disconnect (element_1, element_2);
1726 element_1 = element_2;
1727 element_2 = va_arg (args, GstElement*);
1734 * gst_element_disconnect:
1735 * @src: source element
1736 * @dest: sink element
1738 * Disconnect all pads connecting the two elements in the direction src -> dest.
1741 gst_element_disconnect (GstElement *src, GstElement *dest)
1746 g_return_if_fail (GST_IS_ELEMENT(src));
1747 g_return_if_fail (GST_IS_ELEMENT(dest));
1749 GST_DEBUG (GST_CAT_ELEMENT_PADS, "disconnecting \"%s\" and \"%s\"", GST_ELEMENT_NAME (src),
1750 GST_ELEMENT_NAME (dest));
1752 srcpads = gst_element_get_pad_list (src);
1755 pad = GST_PAD_CAST (srcpads->data);
1757 if (GST_IS_REAL_PAD (pad) && GST_PAD_DIRECTION (pad) == GST_PAD_SRC) {
1758 GstPad *peerpad = GST_PAD_PEER (pad);
1760 if (peerpad && (GST_OBJECT_PARENT (GST_PAD_PEER (peerpad)) == (GstObject*) src)) {
1761 gst_pad_disconnect (pad, peerpad);
1765 srcpads = g_list_next (srcpads);
1770 gst_element_error_func (GstElement* element, GstElement *source, gchar *errormsg)
1772 /* tell the parent */
1773 if (GST_OBJECT_PARENT (element)) {
1774 GST_DEBUG (GST_CAT_EVENT, "forwarding error \"%s\" from %s to %s", errormsg,
1775 GST_ELEMENT_NAME (element), GST_OBJECT_NAME (GST_OBJECT_PARENT (element)));
1777 gst_object_ref (GST_OBJECT (element));
1778 g_signal_emit (G_OBJECT (GST_OBJECT_PARENT (element)), gst_element_signals[ERROR], 0, source, errormsg);
1779 gst_object_unref (GST_OBJECT (element));
1784 gst_element_send_event_default (GstElement *element, GstEvent *event)
1786 GList *pads = element->pads;
1787 gboolean res = FALSE;
1790 GstPad *pad = GST_PAD_CAST (pads->data);
1792 if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) {
1793 if (GST_PAD_IS_USABLE (pad)) {
1794 res = gst_pad_send_event (GST_PAD_PEER (pad), event);
1798 pads = g_list_next (pads);
1804 * gst_element_send_event:
1805 * @element: The element to send the event to.
1806 * @event: The event to send to the object.
1808 * Sends an event to an element. If the element doesn't
1809 * implement an event handler, the event will be forwarded
1810 * to a random sinkpad.
1812 * Returns: TRUE if the event was handled.
1815 gst_element_send_event (GstElement *element, GstEvent *event)
1817 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1818 g_return_val_if_fail (event != NULL, FALSE);
1820 if (CLASS (element)->send_event)
1821 return CLASS (element)->send_event (element, event);
1827 gst_element_query_default (GstElement *element, GstPadQueryType type,
1828 GstFormat *format, gint64 *value)
1830 GList *pads = element->pads;
1831 gboolean res = FALSE;
1834 GstPad *pad = GST_PAD_CAST (pads->data);
1836 if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) {
1837 if (GST_PAD_IS_USABLE (pad)) {
1838 res = gst_pad_query (GST_PAD_PEER (pad), type, format, value);
1842 pads = g_list_next (pads);
1848 * gst_element_query:
1849 * @element: The element to perform the query on.
1850 * @type: The query type
1851 * @format: a pointer to hold the format of the result
1852 * @value: a pointer to the value of the result
1854 * Perform a query on the given element. If the format is set
1855 * to GST_FORMAT_DEFAULT and this function returns TRUE, the
1856 * format pointer will hold the default format.
1857 * For element that don't implement a query handler, this function
1858 * forwards the query to a random connected sinkpad of this element.
1860 * Returns: TRUE if the query could be performed.
1863 gst_element_query (GstElement *element, GstPadQueryType type,
1864 GstFormat *format, gint64 *value)
1866 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1867 g_return_val_if_fail (format != NULL, FALSE);
1868 g_return_val_if_fail (value != NULL, FALSE);
1870 if (CLASS (element)->query)
1871 return CLASS (element)->query (element, type, format, value);
1877 * gst_element_error:
1878 * @element: Element with the error
1879 * @error: A printf-like string describing the error
1880 * @...: optional arguments for the string
1882 * This function is used internally by elements to signal an error
1883 * condition. It results in the "error" signal.
1886 gst_element_error (GstElement *element, const gchar *error, ...)
1892 g_return_if_fail (GST_IS_ELEMENT (element));
1893 g_return_if_fail (error != NULL);
1895 /* create error message */
1896 va_start (var_args, error);
1897 string = g_strdup_vprintf (error, var_args);
1899 GST_INFO (GST_CAT_EVENT, "ERROR in %s: %s", GST_ELEMENT_NAME (element), string);
1901 /* emit the signal, make sure the element stays available */
1902 gst_object_ref (GST_OBJECT (element));
1903 g_signal_emit (G_OBJECT (element), gst_element_signals[ERROR], 0, element, string);
1905 /* tell the scheduler */
1906 if (element->sched) {
1907 gst_scheduler_error (element->sched, element);
1911 gst_object_unref (GST_OBJECT (element));
1916 * gst_element_get_state:
1917 * @element: a #GstElement to get state of
1919 * Gets the state of the element.
1921 * Returns: The #GstElementState of the element
1924 gst_element_get_state (GstElement *element)
1926 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_VOID_PENDING);
1928 return GST_STATE (element);
1932 * gst_element_wait_state_change:
1933 * @element: a #GstElement to wait for
1935 * Waits and blocks until the element changed its state.
1938 gst_element_wait_state_change (GstElement *element)
1940 g_mutex_lock (element->state_mutex);
1941 g_cond_wait (element->state_cond, element->state_mutex);
1942 g_mutex_unlock (element->state_mutex);
1946 * gst_element_set_state:
1947 * @element: a #GstElement to change state of
1948 * @state: the element's new #GstElementState
1950 * Sets the state of the element. This function will try to set the
1951 * requested state by going through all the intermediary states and calling
1952 * the class's state change function for each.
1954 * Returns: whether or not the state was successfully set
1955 * (using #GstElementStateReturn).
1958 gst_element_set_state (GstElement *element, GstElementState state)
1960 GstElementClass *oclass;
1961 GstElementState curpending;
1962 GstElementStateReturn return_val = GST_STATE_SUCCESS;
1964 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
1966 /* start with the current state */
1967 curpending = GST_STATE(element);
1969 GST_DEBUG_ELEMENT (GST_CAT_STATES, element, "setting state from %s to %s",
1970 gst_element_state_get_name (curpending),
1971 gst_element_state_get_name (state));
1973 /* loop until the final requested state is set */
1974 while (GST_STATE (element) != state
1975 && GST_STATE (element) != GST_STATE_VOID_PENDING) {
1976 /* move the curpending state in the correct direction */
1977 if (curpending < state)
1982 /* set the pending state variable */
1983 /* FIXME: should probably check to see that we don't already have one */
1984 GST_STATE_PENDING (element) = curpending;
1986 if (curpending != state) {
1987 GST_DEBUG_ELEMENT (GST_CAT_STATES, element,
1988 "intermediate: setting state from %s to %s",
1989 gst_element_state_get_name (GST_STATE (element)),
1990 gst_element_state_get_name (curpending));
1993 /* call the state change function so it can set the state */
1994 oclass = CLASS (element);
1995 if (oclass->change_state)
1996 return_val = (oclass->change_state) (element);
1998 switch (return_val) {
1999 case GST_STATE_FAILURE:
2000 GST_DEBUG_ELEMENT (GST_CAT_STATES, element, "have failed change_state return");
2002 case GST_STATE_ASYNC:
2003 GST_DEBUG_ELEMENT (GST_CAT_STATES, element, "element will change state async");
2005 case GST_STATE_SUCCESS:
2006 /* Last thing we do is verify that a successful state change really
2007 * did change the state... */
2008 if (GST_STATE (element) != curpending) {
2009 GST_DEBUG_ELEMENT (GST_CAT_STATES, element,
2010 "element claimed state-change success, but state didn't change %s, %s <-> %s",
2011 gst_element_state_get_name (GST_STATE (element)),
2012 gst_element_state_get_name (GST_STATE_PENDING (element)),
2013 gst_element_state_get_name (curpending));
2014 return GST_STATE_FAILURE;
2018 /* somebody added a GST_STATE_ and forgot to do stuff here ! */
2019 g_assert_not_reached ();
2028 gst_element_negotiate_pads (GstElement *element)
2030 GList *pads = GST_ELEMENT_PADS (element);
2032 GST_DEBUG_ELEMENT (GST_CAT_CAPS, element, "negotiating pads");
2035 GstPad *pad = GST_PAD (pads->data);
2038 pads = g_list_next (pads);
2040 if (!GST_IS_REAL_PAD (pad))
2043 srcpad = GST_PAD_REALIZE (pad);
2045 /* if we have a connection on this pad and it doesn't have caps
2046 * allready, try to negotiate */
2047 if (GST_PAD_IS_USABLE (srcpad) && !GST_PAD_CAPS (srcpad)) {
2048 GstRealPad *sinkpad;
2049 GstElementState otherstate;
2052 sinkpad = GST_RPAD_PEER (GST_PAD_REALIZE (srcpad));
2054 /* check the parent of the peer pad, if there is no parent do nothing */
2055 parent = GST_PAD_PARENT (sinkpad);
2059 otherstate = GST_STATE (parent);
2061 /* swap pads if needed */
2062 if (!GST_PAD_IS_SRC (srcpad)) {
2070 /* only try to negotiate if the peer element is in PAUSED or higher too */
2071 if (otherstate >= GST_STATE_READY) {
2072 GST_DEBUG_ELEMENT (GST_CAT_CAPS, element, "perform negotiate for %s:%s and %s:%s",
2073 GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
2074 if (!gst_pad_perform_negotiate (GST_PAD (srcpad), GST_PAD (sinkpad)))
2078 GST_DEBUG_ELEMENT (GST_CAT_CAPS, element, "not negotiatiating %s:%s and %s:%s, not in READY yet",
2079 GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
2088 gst_element_clear_pad_caps (GstElement *element)
2090 GList *pads = GST_ELEMENT_PADS (element);
2092 GST_DEBUG_ELEMENT (GST_CAT_CAPS, element, "clearing pad caps");
2095 GstRealPad *pad = GST_PAD_REALIZE (pads->data);
2097 if (GST_PAD_CAPS (pad)) {
2098 GST_PAD_CAPS (pad) = NULL;
2100 pads = g_list_next (pads);
2104 static GstElementStateReturn
2105 gst_element_change_state (GstElement *element)
2107 GstElementState old_state;
2109 gint old_pending, old_transition;
2111 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
2113 old_state = GST_STATE (element);
2114 old_pending = GST_STATE_PENDING (element);
2115 old_transition = GST_STATE_TRANSITION (element);
2117 if (old_pending == GST_STATE_VOID_PENDING || old_state == GST_STATE_PENDING (element)) {
2118 GST_INFO (GST_CAT_STATES, "no state change needed for element %s (VOID_PENDING)", GST_ELEMENT_NAME (element));
2119 return GST_STATE_SUCCESS;
2122 GST_INFO (GST_CAT_STATES, "%s default handler sets state from %s to %s %d", GST_ELEMENT_NAME (element),
2123 gst_element_state_get_name (old_state),
2124 gst_element_state_get_name (old_pending),
2125 GST_STATE_TRANSITION (element));
2127 /* we set the state change early for the negotiation functions */
2128 GST_STATE (element) = old_pending;
2129 GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING;
2131 switch (old_transition) {
2132 /* if we are going to paused, we try to negotiate the pads */
2133 case GST_STATE_READY_TO_PAUSED:
2134 if (!gst_element_negotiate_pads (element))
2137 /* going to the READY state clears all pad caps */
2138 case GST_STATE_PAUSED_TO_READY:
2139 gst_element_clear_pad_caps (element);
2145 /* tell the scheduler if we have one */
2146 if (element->sched) {
2147 if (gst_scheduler_state_transition (element->sched, element, old_transition)
2148 != GST_STATE_SUCCESS) {
2153 parent = GST_ELEMENT_PARENT (element);
2155 GST_DEBUG_ELEMENT (GST_CAT_STATES, element, "signaling state change from %s to %s",
2156 gst_element_state_get_name (old_state),
2157 gst_element_state_get_name (GST_STATE (element)));
2158 g_signal_emit (G_OBJECT (element), gst_element_signals[STATE_CHANGE],
2159 0, old_state, GST_STATE (element));
2161 /* tell our parent about the state change */
2162 if (parent && GST_IS_BIN (parent)) {
2163 gst_bin_child_state_change (GST_BIN (parent), old_state, GST_STATE (element), element);
2166 /* signal the state change in case somebody is waiting for us */
2167 g_mutex_lock (element->state_mutex);
2168 g_cond_signal (element->state_cond);
2169 g_mutex_unlock (element->state_mutex);
2171 return GST_STATE_SUCCESS;
2174 /* undo the state change */
2175 GST_STATE (element) = old_state;
2176 GST_STATE_PENDING (element) = old_pending;
2178 return GST_STATE_FAILURE;
2182 * gst_element_get_factory:
2183 * @element: element to request the factory
2185 * Retrieves the factory that was used to create this element
2187 * Returns: the factory used for creating this element
2190 gst_element_get_factory (GstElement *element)
2192 GstElementClass *oclass;
2194 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
2196 oclass = CLASS (element);
2198 return oclass->elementfactory;
2202 gst_element_dispose (GObject *object)
2204 GstElement *element = GST_ELEMENT (object);
2208 GST_DEBUG_ELEMENT (GST_CAT_REFCOUNTING, element, "dispose");
2210 gst_element_set_state (element, GST_STATE_NULL);
2212 /* first we break all our connections with the ouside */
2213 if (element->pads) {
2215 orig = pads = g_list_copy (element->pads);
2217 pad = GST_PAD (pads->data);
2219 if (GST_PAD_PEER (pad)) {
2220 GST_DEBUG (GST_CAT_REFCOUNTING, "disconnecting pad '%s'",
2221 GST_OBJECT_NAME (GST_OBJECT (GST_PAD (GST_PAD_PEER (pad)))));
2222 gst_pad_disconnect (pad, GST_PAD (GST_PAD_PEER (pad)));
2224 gst_element_remove_pad (element, pad);
2226 pads = g_list_next (pads);
2229 g_list_free (element->pads);
2230 element->pads = NULL;
2233 element->numsrcpads = 0;
2234 element->numsinkpads = 0;
2235 element->numpads = 0;
2236 g_mutex_free (element->state_mutex);
2237 g_cond_free (element->state_cond);
2239 if (element->prop_value_queue)
2240 g_async_queue_unref (element->prop_value_queue);
2241 element->prop_value_queue = NULL;
2242 if (element->property_mutex)
2243 g_mutex_free (element->property_mutex);
2245 G_OBJECT_CLASS (parent_class)->dispose (object);
2248 #ifndef GST_DISABLE_LOADSAVE
2250 * gst_element_save_thyself:
2251 * @element: GstElement to save
2252 * @parent: the xml parent node
2254 * Saves the element as part of the given XML structure
2256 * Returns: the new xml node
2259 gst_element_save_thyself (GstObject *object,
2263 GstElementClass *oclass;
2264 GParamSpec **specs, *spec;
2266 GValue value = { 0, };
2267 GstElement *element;
2269 g_return_val_if_fail (GST_IS_ELEMENT (object), parent);
2271 element = GST_ELEMENT (object);
2273 oclass = CLASS (element);
2275 xmlNewChild(parent, NULL, "name", GST_ELEMENT_NAME(element));
2277 if (oclass->elementfactory != NULL) {
2278 GstElementFactory *factory = (GstElementFactory *)oclass->elementfactory;
2280 xmlNewChild (parent, NULL, "type", GST_OBJECT_NAME (factory));
2281 xmlNewChild (parent, NULL, "version", factory->details->version);
2284 /* FIXME: what is this? */
2285 /* if (element->manager) */
2286 /* xmlNewChild(parent, NULL, "manager", GST_ELEMENT_NAME(element->manager)); */
2289 specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (object), &nspecs);
2291 for (i=0; i<nspecs; i++) {
2293 if (spec->flags & G_PARAM_READABLE) {
2296 g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE (spec));
2298 g_object_get_property (G_OBJECT (element), spec->name, &value);
2299 param = xmlNewChild (parent, NULL, "param", NULL);
2300 xmlNewChild (param, NULL, "name", spec->name);
2302 if (G_IS_PARAM_SPEC_STRING (spec))
2303 xmlNewChild (param, NULL, "value", g_value_dup_string (&value));
2304 else if (G_IS_PARAM_SPEC_ENUM (spec))
2305 xmlNewChild (param, NULL, "value", g_strdup_printf ("%d", g_value_get_enum (&value)));
2306 else if (G_IS_PARAM_SPEC_INT64 (spec))
2307 xmlNewChild (param, NULL, "value", g_strdup_printf ("%lld", g_value_get_int64 (&value)));
2309 xmlNewChild (param, NULL, "value", g_strdup_value_contents (&value));
2311 g_value_unset(&value);
2315 pads = GST_ELEMENT_PADS (element);
2318 GstPad *pad = GST_PAD (pads->data);
2319 /* figure out if it's a direct pad or a ghostpad */
2320 if (GST_ELEMENT (GST_OBJECT_PARENT (pad)) == element) {
2321 xmlNodePtr padtag = xmlNewChild (parent, NULL, "pad", NULL);
2322 gst_object_save_thyself (GST_OBJECT (pad), padtag);
2324 pads = g_list_next (pads);
2331 gst_element_restore_thyself (GstObject *object, xmlNodePtr self)
2333 xmlNodePtr children;
2334 GstElement *element;
2335 guchar *name = NULL;
2336 guchar *value = NULL;
2338 element = GST_ELEMENT (object);
2339 g_return_if_fail (element != NULL);
2342 children = self->xmlChildrenNode;
2344 if (!strcmp (children->name, "param")) {
2345 xmlNodePtr child = children->xmlChildrenNode;
2348 if (!strcmp (child->name, "name")) {
2349 name = xmlNodeGetContent (child);
2351 else if (!strcmp (child->name, "value")) {
2352 value = xmlNodeGetContent (child);
2354 child = child->next;
2356 /* FIXME: can this just be g_object_set ? */
2357 gst_util_set_object_arg ((GObject *)G_OBJECT (element), name, value);
2359 children = children->next;
2363 children = self->xmlChildrenNode;
2365 if (!strcmp (children->name, "pad")) {
2366 gst_pad_load_and_connect (children, GST_OBJECT (element));
2368 children = children->next;
2371 if (GST_OBJECT_CLASS(parent_class)->restore_thyself)
2372 (GST_OBJECT_CLASS(parent_class)->restore_thyself) (object, self);
2374 #endif /* GST_DISABLE_LOADSAVE */
2377 * gst_element_yield:
2378 * @element: Element to yield
2380 * Request a yield operation for the child. The scheduler will typically
2381 * give control to another element.
2384 gst_element_yield (GstElement *element)
2386 if (GST_ELEMENT_SCHED (element)) {
2387 gst_scheduler_yield (GST_ELEMENT_SCHED (element), element);
2392 * gst_element_interrupt:
2393 * @element: Element to interrupt
2395 * Request the scheduler of this element to interrupt the execution of
2396 * this element and scheduler another one.
2398 * Returns: a boolean indicating that the child should exit its chain/loop/get
2399 * function ASAP, depending on the scheduler implementation.
2402 gst_element_interrupt (GstElement *element)
2404 if (GST_ELEMENT_SCHED (element)) {
2405 return gst_scheduler_interrupt (GST_ELEMENT_SCHED (element), element);
2412 * gst_element_set_scheduler:
2413 * @element: Element to set manager of.
2414 * @sched: @GstScheduler to set.
2416 * Sets the scheduler of the element. For internal use only, unless you're
2417 * writing a new bin subclass.
2420 gst_element_set_scheduler (GstElement *element,
2421 GstScheduler *sched)
2423 g_return_if_fail (GST_IS_ELEMENT (element));
2425 GST_INFO_ELEMENT (GST_CAT_PARENTAGE, element, "setting scheduler to %p", sched);
2427 element->sched = sched;
2431 * gst_element_get_scheduler:
2432 * @element: Element to get manager of.
2434 * Returns the scheduler of the element.
2436 * Returns: Element's scheduler
2439 gst_element_get_scheduler (GstElement *element)
2441 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
2443 return element->sched;
2447 * gst_element_set_loop_function:
2448 * @element: Element to set loop function of.
2449 * @loop: Pointer to loop function.
2451 * This sets the loop function for the element. The function pointed to
2452 * can deviate from the GstElementLoopFunction definition in type of
2455 * NOTE: in order for this to take effect, the current loop function *must*
2456 * exit. Assuming the loop function itself is the only one who will cause
2457 * a new loopfunc to be assigned, this should be no problem.
2460 gst_element_set_loop_function (GstElement *element,
2461 GstElementLoopFunction loop)
2463 g_return_if_fail (GST_IS_ELEMENT (element));
2465 /* set the loop function */
2466 element->loopfunc = loop;
2468 /* set the NEW_LOOPFUNC flag so everyone knows to go try again */
2469 GST_FLAG_SET (element, GST_ELEMENT_NEW_LOOPFUNC);
2473 * gst_element_set_eos:
2474 * @element: element to set to the EOS state
2476 * Perform the actions needed to bring the element in the EOS state.
2479 gst_element_set_eos (GstElement *element)
2481 g_return_if_fail (GST_IS_ELEMENT (element));
2483 GST_DEBUG (GST_CAT_EVENT, "setting EOS on element %s", GST_OBJECT_NAME (element));
2485 gst_element_set_state (element, GST_STATE_PAUSED);
2487 g_signal_emit (G_OBJECT (element), gst_element_signals[EOS], 0);
2492 * gst_element_state_get_name:
2493 * @state: a #GstElementState to get the name of
2495 * Gets a string representing the given state.
2497 * Returns: a string with the statename.
2500 gst_element_state_get_name (GstElementState state)
2503 #ifdef GST_DEBUG_COLOR
2504 case GST_STATE_VOID_PENDING: return "NONE_PENDING";break;
2505 case GST_STATE_NULL: return "\033[01;37mNULL\033[00m";break;
2506 case GST_STATE_READY: return "\033[01;31mREADY\033[00m";break;
2507 case GST_STATE_PLAYING: return "\033[01;32mPLAYING\033[00m";break;
2508 case GST_STATE_PAUSED: return "\033[01;33mPAUSED\033[00m";break;
2509 default: return g_strdup_printf ("\033[01;37;41mUNKNOWN!\033[00m(%d)", state);
2511 case GST_STATE_VOID_PENDING: return "NONE_PENDING";break;
2512 case GST_STATE_NULL: return "NULL";break;
2513 case GST_STATE_READY: return "READY";break;
2514 case GST_STATE_PLAYING: return "PLAYING";break;
2515 case GST_STATE_PAUSED: return "PAUSED";break;
2516 default: return "UNKNOWN!";
2523 gst_element_populate_std_props (GObjectClass * klass,
2524 const gchar *prop_name, guint arg_id, GParamFlags flags)
2526 GQuark prop_id = g_quark_from_string (prop_name);
2529 static GQuark fd_id = 0;
2530 static GQuark blocksize_id;
2531 static GQuark bytesperread_id;
2532 static GQuark dump_id;
2533 static GQuark filesize_id;
2534 static GQuark mmapsize_id;
2535 static GQuark location_id;
2536 static GQuark offset_id;
2537 static GQuark silent_id;
2538 static GQuark touch_id;
2541 fd_id = g_quark_from_static_string ("fd");
2542 blocksize_id = g_quark_from_static_string ("blocksize");
2543 bytesperread_id = g_quark_from_static_string ("bytesperread");
2544 dump_id = g_quark_from_static_string ("dump");
2545 filesize_id = g_quark_from_static_string ("filesize");
2546 mmapsize_id = g_quark_from_static_string ("mmapsize");
2547 location_id = g_quark_from_static_string ("location");
2548 offset_id = g_quark_from_static_string ("offset");
2549 silent_id = g_quark_from_static_string ("silent");
2550 touch_id = g_quark_from_static_string ("touch");
2553 if (prop_id == fd_id) {
2554 pspec = g_param_spec_int ("fd", "File-descriptor",
2555 "File-descriptor for the file being read",
2556 0, G_MAXINT, 0, flags);
2558 else if (prop_id == blocksize_id) {
2559 pspec = g_param_spec_ulong ("blocksize", "Block Size",
2560 "Block size to read per buffer",
2561 0, G_MAXULONG, 4096, flags);
2564 else if (prop_id == bytesperread_id) {
2565 pspec = g_param_spec_int ("bytesperread", "Bytes per read",
2566 "Number of bytes to read per buffer",
2567 G_MININT, G_MAXINT, 0, flags);
2570 else if (prop_id == dump_id) {
2571 pspec = g_param_spec_boolean ("dump", "Dump", "Dump bytes to stdout", FALSE, flags);
2574 else if (prop_id == filesize_id) {
2575 pspec = g_param_spec_int64 ("filesize", "File Size",
2576 "Size of the file being read",
2577 0, G_MAXINT64, 0, flags);
2580 else if (prop_id == mmapsize_id) {
2581 pspec = g_param_spec_ulong ("mmapsize", "mmap() Block Size",
2582 "Size in bytes of mmap()d regions",
2583 0, G_MAXULONG, 4 * 1048576, flags);
2586 else if (prop_id == location_id) {
2587 pspec = g_param_spec_string ("location", "File Location",
2588 "Location of the file to read",
2592 else if (prop_id == offset_id) {
2593 pspec = g_param_spec_int64 ("offset", "File Offset",
2594 "Byte offset of current read pointer",
2595 0, G_MAXINT64, 0, flags);
2598 else if (prop_id == silent_id) {
2599 pspec = g_param_spec_boolean ("silent", "Silent", "Don't produce events",
2603 else if (prop_id == touch_id) {
2604 pspec = g_param_spec_boolean ("touch", "Touch read data",
2605 "Touch data to force disk read before "
2606 "push ()", TRUE, flags);
2609 g_warning ("Unknown - 'standard' property '%s' id %d from klass %s",
2610 prop_name, arg_id, g_type_name (G_OBJECT_CLASS_TYPE (klass)));
2615 g_object_class_install_property (klass, arg_id, pspec);
2620 * gst_element_class_install_std_props:
2621 * @klass: the class to add the properties to
2622 * @first_name: the first in a NULL terminated
2623 * 'name', 'id', 'flags' triplet list.
2624 * @...: the triplet list
2626 * Add a list of standardized properties with types to the @klass.
2627 * the id is for the property switch in your get_prop method, and
2628 * the flags determine readability / writeability.
2631 gst_element_class_install_std_props (GstElementClass * klass, const gchar *first_name, ...)
2637 g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
2639 va_start (args, first_name);
2644 int arg_id = va_arg (args, int);
2645 int flags = va_arg (args, int);
2647 gst_element_populate_std_props ((GObjectClass *) klass, name, arg_id, flags);
2649 name = va_arg (args, char *);
2656 * gst_element_get_managing_bin:
2657 * @element: a #GstElement
2659 * Gets the managing bin (a pipeline or a thread, for example) of an element.
2661 * Returns: the #GstBin, or NULL on failure
2664 gst_element_get_managing_bin (GstElement *element)
2668 g_return_val_if_fail (element != NULL, NULL);
2670 bin = GST_BIN (gst_object_get_parent (GST_OBJECT_CAST (element)));
2672 while (bin && !GST_FLAG_IS_SET (GST_OBJECT_CAST (bin), GST_BIN_FLAG_MANAGER))
2673 bin = GST_BIN (gst_object_get_parent (GST_OBJECT_CAST (bin)));