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 */
52 static void gst_element_class_init (GstElementClass *klass);
53 static void gst_element_init (GstElement *element);
54 static void gst_element_base_class_init (GstElementClass *klass);
56 static void gst_element_real_set_property (GObject *object, guint prop_id,
57 const GValue *value, GParamSpec *pspec);
58 static void gst_element_real_get_property (GObject *object, guint prop_id, GValue *value,
61 static void gst_element_dispose (GObject *object);
63 static GstElementStateReturn gst_element_change_state (GstElement *element);
64 static void gst_element_error_func (GstElement* element, GstElement *source, gchar *errormsg);
66 #ifndef GST_DISABLE_LOADSAVE
67 static xmlNodePtr gst_element_save_thyself (GstObject *object, xmlNodePtr parent);
68 static void gst_element_restore_thyself (GstObject *parent, xmlNodePtr self);
71 GType _gst_element_type = 0;
73 static GstObjectClass *parent_class = NULL;
74 static guint gst_element_signals[LAST_SIGNAL] = { 0 };
76 GType gst_element_get_type (void)
78 if (!_gst_element_type) {
79 static const GTypeInfo element_info = {
80 sizeof(GstElementClass),
81 (GBaseInitFunc)gst_element_base_class_init,
83 (GClassInitFunc)gst_element_class_init,
88 (GInstanceInitFunc)gst_element_init,
91 _gst_element_type = g_type_register_static(GST_TYPE_OBJECT, "GstElement",
92 &element_info, G_TYPE_FLAG_ABSTRACT);
94 return _gst_element_type;
98 gst_element_class_init (GstElementClass *klass)
100 GObjectClass *gobject_class;
101 GstObjectClass *gstobject_class;
103 gobject_class = (GObjectClass*) klass;
104 gstobject_class = (GstObjectClass*) klass;
106 parent_class = g_type_class_ref(GST_TYPE_OBJECT);
108 gst_element_signals[STATE_CHANGE] =
109 g_signal_new ("state_change", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
110 G_STRUCT_OFFSET (GstElementClass, state_change), NULL, NULL,
111 gst_marshal_VOID__INT_INT, G_TYPE_NONE, 2,
112 G_TYPE_INT, G_TYPE_INT);
113 gst_element_signals[NEW_PAD] =
114 g_signal_new ("new_pad", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
115 G_STRUCT_OFFSET (GstElementClass, new_pad), NULL, NULL,
116 gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
118 gst_element_signals[PAD_REMOVED] =
119 g_signal_new ("pad_removed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
120 G_STRUCT_OFFSET (GstElementClass, pad_removed), NULL, NULL,
121 gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
123 gst_element_signals[ERROR] =
124 g_signal_new ("error", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
125 G_STRUCT_OFFSET (GstElementClass, error), NULL, NULL,
126 gst_marshal_VOID__OBJECT_STRING, G_TYPE_NONE, 2,
127 G_TYPE_OBJECT, G_TYPE_STRING);
128 gst_element_signals[EOS] =
129 g_signal_new ("eos", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
130 G_STRUCT_OFFSET (GstElementClass,eos), NULL, NULL,
131 gst_marshal_VOID__VOID, G_TYPE_NONE, 0);
133 gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_element_real_set_property);
134 gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_element_real_get_property);
136 gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_element_dispose);
138 #ifndef GST_DISABLE_LOADSAVE
139 gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_element_save_thyself);
140 gstobject_class->restore_thyself = GST_DEBUG_FUNCPTR (gst_element_restore_thyself);
143 klass->change_state = GST_DEBUG_FUNCPTR (gst_element_change_state);
144 klass->error = GST_DEBUG_FUNCPTR (gst_element_error_func);
145 klass->elementfactory = NULL;
146 klass->padtemplates = NULL;
147 klass->numpadtemplates = 0;
148 klass->send_event = NULL;
153 gst_element_base_class_init (GstElementClass *klass)
155 GObjectClass *gobject_class;
157 gobject_class = (GObjectClass*) klass;
159 gobject_class->set_property = GST_DEBUG_FUNCPTR(gst_element_real_set_property);
160 gobject_class->get_property = GST_DEBUG_FUNCPTR(gst_element_real_get_property);
164 gst_element_init (GstElement *element)
166 element->current_state = GST_STATE_NULL;
167 element->pending_state = GST_STATE_VOID_PENDING;
168 element->numpads = 0;
169 element->numsrcpads = 0;
170 element->numsinkpads = 0;
171 element->pads = NULL;
172 element->loopfunc = NULL;
173 element->sched = NULL;
174 element->clock = NULL;
175 element->sched_private = NULL;
176 element->state_mutex = g_mutex_new ();
177 element->state_cond = g_cond_new ();
181 gst_element_real_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
183 GstElementClass *oclass = GST_ELEMENT_GET_CLASS (object);
185 if (oclass->set_property)
186 (oclass->set_property) (object, prop_id, value, pspec);
190 gst_element_real_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
192 GstElementClass *oclass = GST_ELEMENT_GET_CLASS (object);
194 if (oclass->get_property)
195 (oclass->get_property) (object, prop_id, value, pspec);
199 * gst_element_default_error:
200 * @object: a #GObject that signalled the error.
201 * @orig: the #GstObject that initiated the error.
202 * @error: the error message.
204 * Adds a default error signal callback to an
205 * element. The user data passed to the g_signal_connect is
207 * The default handler will simply print the error string
211 gst_element_default_error (GObject *object, GstObject *orig, gchar *error)
213 gchar *name = gst_object_get_path_string (orig);
214 g_print ("ERROR: %s: %s\n", name, error);
219 const GParamSpec *pspec;
224 element_set_property (GstElement *element, const GParamSpec *pspec, const GValue *value)
226 prop_value_t *prop_value = g_new0 (prop_value_t, 1);
228 prop_value->pspec = pspec;
229 prop_value->value = *value;
231 g_async_queue_push (element->prop_value_queue, prop_value);
235 element_get_property (GstElement *element, const GParamSpec *pspec, GValue *value)
237 g_mutex_lock (element->property_mutex);
238 g_object_get_property ((GObject*)element, pspec->name, value);
239 g_mutex_unlock (element->property_mutex);
243 gst_element_threadsafe_properties_pre_run (GstElement *element)
245 GST_DEBUG (GST_CAT_THREAD, "locking element %s", GST_OBJECT_NAME (element));
246 g_mutex_lock (element->property_mutex);
247 gst_element_set_pending_properties (element);
251 gst_element_threadsafe_properties_post_run (GstElement *element)
253 GST_DEBUG (GST_CAT_THREAD, "unlocking element %s", GST_OBJECT_NAME (element));
254 g_mutex_unlock (element->property_mutex);
258 * gst_element_enable_threadsafe_properties:
259 * @element: a #GstElement to enable threadsafe properties on.
261 * Installs an asynchronous queue, a mutex and pre- and post-run functions on
262 * this element so that properties on the element can be set in a
266 gst_element_enable_threadsafe_properties (GstElement *element)
268 g_return_if_fail (GST_IS_ELEMENT (element));
270 GST_FLAG_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES);
271 element->pre_run_func = gst_element_threadsafe_properties_pre_run;
272 element->post_run_func = gst_element_threadsafe_properties_post_run;
273 if (!element->prop_value_queue)
274 element->prop_value_queue = g_async_queue_new ();
275 if (!element->property_mutex)
276 element->property_mutex = g_mutex_new ();
280 * gst_element_disable_threadsafe_properties:
281 * @element: a #GstElement to disable threadsafe properties on.
283 * Removes the threadsafe properties, post- and pre-run locks from
287 gst_element_disable_threadsafe_properties (GstElement *element)
289 g_return_if_fail (GST_IS_ELEMENT (element));
291 GST_FLAG_UNSET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES);
292 element->pre_run_func = NULL;
293 element->post_run_func = NULL;
294 /* let's keep around that async queue */
298 * gst_element_set_pending_properties:
299 * @element: a #GstElement to set the pending properties on.
301 * Sets all pending properties on the threadsafe properties enabled
305 gst_element_set_pending_properties (GstElement *element)
307 prop_value_t *prop_value;
309 while ((prop_value = g_async_queue_try_pop (element->prop_value_queue))) {
310 g_object_set_property ((GObject*)element, prop_value->pspec->name, &prop_value->value);
311 g_value_unset (&prop_value->value);
316 /* following 6 functions taken mostly from gobject.c */
320 * @element: a #GstElement to set properties on.
321 * @first_property_name: the first property to set.
322 * @...: value of the first property, and more properties to set, ending
325 * Sets properties on an element. If the element uses threadsafe properties,
326 * they will be queued and set on the object when it is scheduled again.
329 gst_element_set (GstElement *element, const gchar *first_property_name, ...)
333 g_return_if_fail (GST_IS_ELEMENT (element));
335 va_start (var_args, first_property_name);
336 gst_element_set_valist (element, first_property_name, var_args);
342 * @element: a #GstElement to get properties of.
343 * @first_property_name: the first property to get.
344 * @...: pointer to a variable to store the first property in, as well as
345 * more properties to get, ending with NULL.
347 * Gets properties from an element. If the element uses threadsafe properties,
348 * the element will be locked before getting the given properties.
351 gst_element_get (GstElement *element, const gchar *first_property_name, ...)
355 g_return_if_fail (GST_IS_ELEMENT (element));
357 va_start (var_args, first_property_name);
358 gst_element_get_valist (element, first_property_name, var_args);
363 * gst_element_set_valist:
364 * @element: a #GstElement to set properties on.
365 * @first_property_name: the first property to set.
366 * @var_args: the var_args list of other properties to get.
368 * Sets properties on an element. If the element uses threadsafe properties,
369 * the property change will be put on the async queue.
372 gst_element_set_valist (GstElement *element, const gchar *first_property_name, va_list var_args)
377 g_return_if_fail (GST_IS_ELEMENT (element));
379 object = (GObject *) element;
381 GST_DEBUG (GST_CAT_PROPERTIES,
382 "setting valist of properties starting with %s on element %s",
383 first_property_name, gst_element_get_name (element));
385 if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
386 g_object_set_valist (object, first_property_name, var_args);
390 g_object_ref (object);
392 name = first_property_name;
396 GValue value = { 0, };
400 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), name);
404 g_warning ("%s: object class `%s' has no property named `%s'",
406 G_OBJECT_TYPE_NAME (object),
410 if (!(pspec->flags & G_PARAM_WRITABLE))
412 g_warning ("%s: property `%s' of object class `%s' is not writable",
415 G_OBJECT_TYPE_NAME (object));
419 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
421 G_VALUE_COLLECT (&value, var_args, 0, &error);
424 g_warning ("%s: %s", G_STRLOC, error);
427 /* we purposely leak the value here, it might not be
428 * in a sane state if an error condition occoured
433 element_set_property (element, pspec, &value);
434 g_value_unset (&value);
436 name = va_arg (var_args, gchar*);
439 g_object_unref (object);
443 * gst_element_get_valist:
444 * @element: a #GstElement to get properties of.
445 * @first_property_name: the first property to get.
446 * @var_args: the var_args list of other properties to get.
448 * Gets properties from an element. If the element uses threadsafe properties,
449 * the element will be locked before getting the given properties.
452 gst_element_get_valist (GstElement *element, const gchar *first_property_name, va_list var_args)
457 g_return_if_fail (GST_IS_ELEMENT (element));
459 object = (GObject*)element;
461 if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
462 g_object_get_valist (object, first_property_name, var_args);
466 g_object_ref (object);
468 name = first_property_name;
472 GValue value = { 0, };
476 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), name);
480 g_warning ("%s: object class `%s' has no property named `%s'",
482 G_OBJECT_TYPE_NAME (object),
486 if (!(pspec->flags & G_PARAM_READABLE))
488 g_warning ("%s: property `%s' of object class `%s' is not readable",
491 G_OBJECT_TYPE_NAME (object));
495 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
497 element_get_property (element, pspec, &value);
499 G_VALUE_LCOPY (&value, var_args, 0, &error);
502 g_warning ("%s: %s", G_STRLOC, error);
504 g_value_unset (&value);
508 g_value_unset (&value);
510 name = va_arg (var_args, gchar*);
513 g_object_unref (object);
517 * gst_element_set_property:
518 * @element: a #GstElement to set properties on.
519 * @property_name: the first property to get.
520 * @value: the #GValue that holds the value to set.
522 * Sets a property on an element. If the element uses threadsafe properties,
523 * the property will be put on the async queue.
526 gst_element_set_property (GstElement *element, const gchar *property_name,
532 g_return_if_fail (GST_IS_ELEMENT (element));
533 g_return_if_fail (property_name != NULL);
534 g_return_if_fail (G_IS_VALUE (value));
536 object = (GObject*) element;
538 GST_DEBUG (GST_CAT_PROPERTIES, "setting property %s on element %s",
539 property_name, gst_element_get_name (element));
540 if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
541 g_object_set_property (object, property_name, value);
545 g_object_ref (object);
547 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object),
551 g_warning ("%s: object class `%s' has no property named `%s'",
553 G_OBJECT_TYPE_NAME (object),
556 element_set_property (element, pspec, value);
558 g_object_unref (object);
562 * gst_element_get_property:
563 * @element: a #GstElement to get properties of.
564 * @property_name: the first property to get.
565 * @value: the #GValue to store the property value in.
567 * Gets a property from an element. If the element uses threadsafe properties,
568 * the element will be locked before getting the given property.
571 gst_element_get_property (GstElement *element, const gchar *property_name, GValue *value)
576 g_return_if_fail (GST_IS_ELEMENT (element));
577 g_return_if_fail (property_name != NULL);
578 g_return_if_fail (G_IS_VALUE (value));
580 object = (GObject*)element;
582 if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
583 g_object_get_property (object, property_name, value);
587 g_object_ref (object);
589 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), property_name);
592 g_warning ("%s: object class `%s' has no property named `%s'",
594 G_OBJECT_TYPE_NAME (object),
598 GValue *prop_value, tmp_value = { 0, };
600 /* auto-conversion of the callers value type
602 if (G_VALUE_TYPE (value) == G_PARAM_SPEC_VALUE_TYPE (pspec))
604 g_value_reset (value);
607 else if (!g_value_type_transformable (G_PARAM_SPEC_VALUE_TYPE (pspec), G_VALUE_TYPE (value)))
609 g_warning ("can't retrieve property `%s' of type `%s' as value of type `%s'",
611 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
612 G_VALUE_TYPE_NAME (value));
613 g_object_unref (object);
618 g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
619 prop_value = &tmp_value;
621 element_get_property (element, pspec, prop_value);
622 if (prop_value != value)
624 g_value_transform (prop_value, value);
625 g_value_unset (&tmp_value);
629 g_object_unref (object);
633 gst_element_request_pad (GstElement *element, GstPadTemplate *templ, const gchar* name)
635 GstPad *newpad = NULL;
636 GstElementClass *oclass;
638 oclass = GST_ELEMENT_GET_CLASS (element);
640 if (oclass->request_new_pad)
641 newpad = (oclass->request_new_pad)(element, templ, name);
647 * gst_element_release_request_pad:
648 * @element: a #GstElement to release the request pad of.
649 * @pad: the #GstPad to release.
651 * Makes the element free the previously requested pad as obtained
652 * with gst_element_get_request_pad().
655 gst_element_release_request_pad (GstElement *element, GstPad *pad)
657 GstElementClass *oclass;
659 g_return_if_fail (GST_IS_ELEMENT (element));
660 g_return_if_fail (GST_IS_PAD (pad));
662 oclass = GST_ELEMENT_GET_CLASS (element);
664 if (oclass->release_pad)
665 (oclass->release_pad) (element, pad);
669 * gst_element_requires_clock:
670 * @element: a #GstElement to query
672 * Query if the element requiresd a clock
674 * Returns: TRUE if the element requires a clock
677 gst_element_requires_clock (GstElement *element)
679 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
681 return (GST_ELEMENT_GET_CLASS (element)->set_clock != NULL);
685 * gst_element_provides_clock:
686 * @element: a #GstElement to query
688 * Query if the element provides a clock
690 * Returns: TRUE if the element provides a clock
693 gst_element_provides_clock (GstElement *element)
695 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
697 return (GST_ELEMENT_GET_CLASS (element)->get_clock != NULL);
701 * gst_element_set_clock:
702 * @element: a #GstElement to set the clock for.
703 * @clock: the #GstClock to set for the element.
705 * Sets the clock for the element.
708 gst_element_set_clock (GstElement *element, GstClock *clock)
710 GstElementClass *oclass;
712 g_return_if_fail (GST_IS_ELEMENT (element));
714 oclass = GST_ELEMENT_GET_CLASS (element);
716 if (oclass->set_clock)
717 oclass->set_clock (element, clock);
719 element->clock = clock;
723 * gst_element_get_clock:
724 * @element: a #GstElement to get the clock of.
726 * Gets the clock of the element.
728 * Returns: the #GstClock of the element.
731 gst_element_get_clock (GstElement *element)
733 GstElementClass *oclass;
735 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
737 oclass = GST_ELEMENT_GET_CLASS (element);
739 if (oclass->get_clock)
740 return oclass->get_clock (element);
746 * gst_element_clock_wait:
747 * @element: a #GstElement.
748 * @id: the #GstClock to use.
749 * @jitter: the difference between requested time and actual time.
751 * Waits for a specific time on the clock.
753 * Returns: the #GstClockReturn result of the wait operation.
756 gst_element_clock_wait (GstElement *element, GstClockID id, GstClockTimeDiff *jitter)
760 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_CLOCK_ERROR);
762 if (GST_ELEMENT_SCHED (element)) {
763 res = gst_scheduler_clock_wait (GST_ELEMENT_SCHED (element), element, id, jitter);
766 res = GST_CLOCK_TIMEOUT;
772 * gst_element_is_indexable:
773 * @element: a #GstElement.
775 * Queries if the element can be indexed/
777 * Returns: TRUE if the element can be indexed.
780 gst_element_is_indexable (GstElement *element)
782 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
784 return (GST_ELEMENT_GET_CLASS (element)->set_index != NULL);
788 * gst_element_set_index:
789 * @element: a #GstElement.
790 * @index: a #GstIndex.
792 * Set the specified GstIndex on the element.
795 gst_element_set_index (GstElement *element, GstIndex *index)
797 GstElementClass *oclass;
799 g_return_if_fail (GST_IS_ELEMENT (element));
800 g_return_if_fail (GST_IS_INDEX (index));
802 oclass = GST_ELEMENT_GET_CLASS (element);
804 if (oclass->set_index)
805 oclass->set_index (element, index);
809 * gst_element_get_index:
810 * @element: a #GstElement.
812 * Gets the index from the element.
814 * Returns: a #GstIndex or NULL when no index was set on the
818 gst_element_get_index (GstElement *element)
820 GstElementClass *oclass;
822 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
824 oclass = GST_ELEMENT_GET_CLASS (element);
826 if (oclass->get_index)
827 return oclass->get_index (element);
833 * gst_element_release_locks:
834 * @element: a #GstElement to release all locks on.
836 * Instruct the element to release all the locks it is holding, such as
837 * blocking reads, waiting for the clock, ...
839 * Returns: TRUE if the locks could be released.
842 gst_element_release_locks (GstElement *element)
844 GstElementClass *oclass;
846 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
848 oclass = GST_ELEMENT_GET_CLASS (element);
850 if (oclass->release_locks)
851 return oclass->release_locks (element);
857 * gst_element_add_pad:
858 * @element: a #GstElement to add the pad to.
859 * @pad: the #GstPad to add to the element.
861 * Add a pad (connection point) to the element, setting the parent of the
862 * pad to the element (and thus adding a reference).
865 gst_element_add_pad (GstElement *element, GstPad *pad)
867 g_return_if_fail (element != NULL);
868 g_return_if_fail (GST_IS_ELEMENT (element));
869 g_return_if_fail (pad != NULL);
870 g_return_if_fail (GST_IS_PAD (pad));
872 /* first check to make sure the pad's parent is already set */
873 g_return_if_fail (GST_PAD_PARENT (pad) == NULL);
875 /* then check to see if there's already a pad by that name here */
876 g_return_if_fail (gst_object_check_uniqueness (element->pads, GST_PAD_NAME(pad)) == TRUE);
878 /* set the pad's parent */
879 GST_DEBUG (GST_CAT_ELEMENT_PADS,"setting parent of pad '%s' to '%s'",
880 GST_PAD_NAME (pad), GST_ELEMENT_NAME (element));
881 gst_object_set_parent (GST_OBJECT (pad), GST_OBJECT (element));
883 /* add it to the list */
884 element->pads = g_list_append (element->pads, pad);
886 if (gst_pad_get_direction (pad) == GST_PAD_SRC)
887 element->numsrcpads++;
889 element->numsinkpads++;
891 /* emit the NEW_PAD signal */
892 g_signal_emit (G_OBJECT (element), gst_element_signals[NEW_PAD], 0, pad);
896 * gst_element_remove_pad:
897 * @element: a #GstElement to remove pad from.
898 * @pad: the #GstPad to remove from the element.
900 * Remove a pad (connection point) from the element.
903 gst_element_remove_pad (GstElement *element, GstPad *pad)
905 g_return_if_fail (element != NULL);
906 g_return_if_fail (GST_IS_ELEMENT (element));
907 g_return_if_fail (pad != NULL);
908 g_return_if_fail (GST_IS_PAD (pad));
910 g_return_if_fail (GST_PAD_PARENT (pad) == element);
912 /* check to see if the pad is still connected */
913 /* FIXME: what if someone calls _remove_pad instead of
914 _remove_ghost_pad? */
915 if (GST_IS_REAL_PAD (pad)) {
916 g_return_if_fail (GST_RPAD_PEER (pad) == NULL);
919 /* remove it from the list */
920 element->pads = g_list_remove (element->pads, pad);
922 if (gst_pad_get_direction (pad) == GST_PAD_SRC)
923 element->numsrcpads--;
925 element->numsinkpads--;
927 g_signal_emit (G_OBJECT (element), gst_element_signals[PAD_REMOVED], 0, pad);
929 gst_object_unparent (GST_OBJECT (pad));
933 * gst_element_add_ghost_pad:
934 * @element: a #GstElement to add the ghost pad to.
935 * @pad: the #GstPad from which the new ghost pad will be created.
936 * @name: the name of the new ghost pad.
938 * Creates a ghost pad from the given pad, and adds it to the list of pads
941 * Returns: the added ghost #GstPad, or NULL, if no ghost pad was created.
944 gst_element_add_ghost_pad (GstElement *element, GstPad *pad, const gchar *name)
948 g_return_val_if_fail (element != NULL, NULL);
949 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
950 g_return_val_if_fail (pad != NULL, NULL);
951 g_return_val_if_fail (GST_IS_PAD (pad), NULL);
953 /* then check to see if there's already a pad by that name here */
954 g_return_val_if_fail (gst_object_check_uniqueness (element->pads, name) == TRUE, NULL);
956 GST_DEBUG (GST_CAT_ELEMENT_PADS,
957 "creating new ghost pad called %s, from pad %s:%s",
958 name, GST_DEBUG_PAD_NAME(pad));
959 ghostpad = gst_ghost_pad_new (name, pad);
961 /* add it to the list */
962 GST_DEBUG(GST_CAT_ELEMENT_PADS,"adding ghost pad %s to element %s",
963 name, GST_ELEMENT_NAME (element));
964 element->pads = g_list_append (element->pads, ghostpad);
966 /* set the parent of the ghostpad */
967 gst_object_set_parent (GST_OBJECT (ghostpad), GST_OBJECT (element));
969 GST_DEBUG(GST_CAT_ELEMENT_PADS,"added ghostpad %s:%s",GST_DEBUG_PAD_NAME(ghostpad));
971 /* emit the NEW_GHOST_PAD signal */
972 g_signal_emit (G_OBJECT (element), gst_element_signals[NEW_PAD], 0, ghostpad);
978 * gst_element_remove_ghost_pad:
979 * @element: a #GstElement to remove the ghost pad from.
980 * @pad: ghost #GstPad to remove.
982 * Removes a ghost pad from an element.
985 gst_element_remove_ghost_pad (GstElement *element, GstPad *pad)
987 g_return_if_fail (element != NULL);
988 g_return_if_fail (GST_IS_ELEMENT (element));
989 g_return_if_fail (pad != NULL);
990 g_return_if_fail (GST_IS_GHOST_PAD (pad));
992 /* FIXME this is redundant?
993 * wingo 10-july-2001: I don't think so, you have to actually remove the pad
994 * from the element. gst_pad_remove_ghost_pad just removes the ghostpad from
995 * the real pad's ghost pad list
997 gst_pad_remove_ghost_pad (GST_PAD (GST_PAD_REALIZE (pad)), pad);
998 gst_element_remove_pad (element, pad);
1003 * gst_element_get_pad:
1004 * @element: a #GstElement to find pad of.
1005 * @name: the name of the pad to retrieve.
1007 * Retrieves a pad from the element by name.
1009 * Returns: requested #GstPad if found, otherwise NULL.
1012 gst_element_get_pad (GstElement *element, 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 (name != NULL, NULL);
1020 pad = gst_element_get_static_pad (element, name);
1022 pad = gst_element_get_request_pad (element, name);
1028 * gst_element_get_static_pad:
1029 * @element: a #GstElement to find a static pad of.
1030 * @name: the name of the static #GstPad to retrieve.
1032 * Retrieves a pad from the element by name. This version only retrieves
1033 * already-existing (i.e. 'static') pads.
1035 * Returns: the requested #GstPad if found, otherwise NULL.
1038 gst_element_get_static_pad (GstElement *element, const gchar *name)
1042 g_return_val_if_fail (element != NULL, NULL);
1043 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1044 g_return_val_if_fail (name != NULL, NULL);
1046 walk = element->pads;
1050 pad = GST_PAD(walk->data);
1051 if (strcmp (GST_PAD_NAME(pad), name) == 0) {
1052 GST_INFO (GST_CAT_ELEMENT_PADS, "found pad %s:%s", GST_DEBUG_PAD_NAME (pad));
1055 walk = g_list_next (walk);
1058 GST_INFO (GST_CAT_ELEMENT_PADS, "no such pad '%s' in element \"%s\"", name, GST_OBJECT_NAME (element));
1063 * gst_element_get_request_pad:
1064 * @element: a #GstElement to find a request pad of.
1065 * @name: the name of the request #GstPad to retrieve.
1067 * Retrieves a pad from the element by name. This version only retrieves
1070 * Returns: requested #GstPad if found, otherwise NULL.
1073 gst_element_get_request_pad (GstElement *element, const gchar *name)
1075 GstPadTemplate *templ = NULL;
1077 const gchar *req_name = NULL;
1078 gboolean templ_found = FALSE;
1082 gchar *str, *endptr = NULL;
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 (strstr (name, "%")) {
1089 templ = gst_element_get_pad_template (element, name);
1094 list = gst_element_get_pad_template_list(element);
1095 while (!templ_found && list) {
1096 templ = (GstPadTemplate*) list->data;
1097 if (templ->presence == GST_PAD_REQUEST) {
1098 /* we know that %s and %d are the only possibilities because of sanity
1099 checks in gst_pad_template_new */
1100 GST_DEBUG (GST_CAT_PADS, "comparing %s to %s", name, templ->name_template);
1101 if ((str = strchr (templ->name_template, '%')) &&
1102 strncmp (templ->name_template, name, str - templ->name_template) == 0 &&
1103 strlen (name) > str - templ->name_template) {
1104 data = name + (str - templ->name_template);
1105 if (*(str+1) == 'd') {
1107 n = (gint) strtol (data, &endptr, 10);
1108 if (endptr && *endptr == '\0') {
1128 pad = gst_element_request_pad (element, templ, req_name);
1134 * gst_element_get_pad_list:
1135 * @element: a #GstElement to get pads of.
1137 * Retrieves a list of the pads associated with the element.
1139 * Returns: the #GList of pads.
1142 gst_element_get_pad_list (GstElement *element)
1144 g_return_val_if_fail (element != NULL, NULL);
1145 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1147 /* return the list of pads */
1148 return element->pads;
1152 * gst_element_class_add_pad_template:
1153 * @klass: the #GstElementClass to add the pad template to.
1154 * @templ: a #GstPadTemplate to add to the element class.
1156 * Adds a padtemplate to an element class.
1157 * This is useful if you have derived a custom bin and wish to provide
1158 * an on-request pad at runtime. Plug-in writers should use
1159 * gst_element_factory_add_pad_template instead.
1162 gst_element_class_add_pad_template (GstElementClass *klass,
1163 GstPadTemplate *templ)
1165 g_return_if_fail (klass != NULL);
1166 g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
1167 g_return_if_fail (templ != NULL);
1168 g_return_if_fail (GST_IS_PAD_TEMPLATE (templ));
1170 klass->padtemplates = g_list_append (klass->padtemplates, templ);
1171 klass->numpadtemplates++;
1175 * gst_element_get_pad_template_list:
1176 * @element: a #GstElement to get pad templates of.
1178 * Retrieves a list of the pad templates associated with the element.
1180 * Returns: the #GList of padtemplates.
1183 gst_element_get_pad_template_list (GstElement *element)
1185 g_return_val_if_fail (element != NULL, NULL);
1186 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1188 return GST_ELEMENT_GET_CLASS (element)->padtemplates;
1192 * gst_element_get_pad_template:
1193 * @element: a #GstElement to get the pad template of.
1194 * @name: the name of the #GstPadTemplate to get.
1196 * Retrieves a padtemplate from this element with the
1199 * Returns: the #GstPadTemplate with the given name, or NULL if none was found.
1200 * No unreferencing is necessary.
1203 gst_element_get_pad_template (GstElement *element, const gchar *name)
1207 g_return_val_if_fail (element != NULL, NULL);
1208 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1209 g_return_val_if_fail (name != NULL, NULL);
1211 padlist = gst_element_get_pad_template_list (element);
1214 GstPadTemplate *padtempl = (GstPadTemplate*) padlist->data;
1216 if (!strcmp (padtempl->name_template, name))
1219 padlist = g_list_next (padlist);
1226 * gst_element_get_compatible_pad_template:
1227 * @element: a #GstElement to get a compatible pad template for.
1228 * @compattempl: the #GstPadTemplate to find a compatible template for.
1230 * Generates a pad template for this element compatible with the given
1231 * template (meaning it is able to connect with it).
1233 * Returns: the #GstPadTemplate of the element that is compatible with
1234 * the given GstPadTemplate, or NULL if none was found. No unreferencing
1238 gst_element_get_compatible_pad_template (GstElement *element,
1239 GstPadTemplate *compattempl)
1241 GstPadTemplate *newtempl = NULL;
1244 GST_DEBUG (GST_CAT_ELEMENT_PADS, "gst_element_get_compatible_pad_template()");
1246 g_return_val_if_fail (element != NULL, NULL);
1247 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1248 g_return_val_if_fail (compattempl != NULL, NULL);
1250 padlist = gst_element_get_pad_template_list (element);
1253 GstPadTemplate *padtempl = (GstPadTemplate*) padlist->data;
1254 gboolean comp = FALSE;
1258 * Check direction (must be opposite)
1261 GST_DEBUG (GST_CAT_CAPS, "checking direction and caps");
1262 if (padtempl->direction == GST_PAD_SRC &&
1263 compattempl->direction == GST_PAD_SINK) {
1264 GST_DEBUG (GST_CAT_CAPS, "compatible direction: found src pad template");
1265 comp = gst_caps_is_always_compatible (GST_PAD_TEMPLATE_CAPS (padtempl),
1266 GST_PAD_TEMPLATE_CAPS (compattempl));
1267 GST_DEBUG(GST_CAT_CAPS, "caps are %scompatible", (comp ? "" : "not "));
1268 } else if (padtempl->direction == GST_PAD_SINK &&
1269 compattempl->direction == GST_PAD_SRC) {
1270 GST_DEBUG (GST_CAT_CAPS, "compatible direction: found sink pad template");
1271 comp = gst_caps_is_always_compatible (GST_PAD_TEMPLATE_CAPS (compattempl),
1272 GST_PAD_TEMPLATE_CAPS (padtempl));
1273 GST_DEBUG (GST_CAT_CAPS, "caps are %scompatible", (comp ? "" : "not "));
1277 newtempl = padtempl;
1281 padlist = g_list_next (padlist);
1288 * gst_element_request_compatible_pad:
1289 * @element: a #GstElement to request a new pad from.
1290 * @templ: the #GstPadTemplate to which the new pad should be able to connect.
1292 * Requests a new pad from the element. The template will
1293 * be used to decide what type of pad to create. This function
1294 * is typically used for elements with a padtemplate with presence
1297 * Returns: the new #GstPad that was created, or NULL if none could be created.
1300 gst_element_request_compatible_pad (GstElement *element, GstPadTemplate *templ)
1302 GstPadTemplate *templ_new;
1305 g_return_val_if_fail (element != NULL, NULL);
1306 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1307 g_return_val_if_fail (templ != NULL, NULL);
1309 templ_new = gst_element_get_compatible_pad_template (element, templ);
1310 if (templ_new != NULL)
1311 pad = gst_element_request_pad (element, templ_new, NULL);
1318 * gst_element_get_compatible_pad_filtered:
1319 * @element: a #GstElement in which the pad should be found.
1320 * @pad: the #GstPad to find a compatible one for.
1321 * @filtercaps: the #GstCaps to use as a filter.
1323 * Looks for an unconnected pad to which the given pad can connect to.
1324 * It is not guaranteed that connecting the pads will work, though
1325 * it should work in most cases.
1327 * Returns: the #GstPad to which a connection can be made.
1330 gst_element_get_compatible_pad_filtered (GstElement *element, GstPad *pad,
1331 GstCaps *filtercaps)
1334 GstPadTemplate *templ;
1336 GstPad *foundpad = NULL;
1339 g_return_val_if_fail (element != NULL, NULL);
1340 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1341 g_return_val_if_fail (pad != NULL, NULL);
1342 g_return_val_if_fail (GST_IS_PAD (pad), NULL);
1344 /* let's use the real pad */
1345 pad = (GstPad *) GST_PAD_REALIZE (pad);
1346 g_return_val_if_fail (pad != NULL, NULL);
1347 g_return_val_if_fail (GST_RPAD_PEER (pad) == NULL, NULL);
1349 /* try to get an existing unconnected pad */
1350 pads = gst_element_get_pad_list (element);
1352 GstPad *current = GST_PAD (pads->data);
1353 if ((GST_PAD_PEER (GST_PAD_REALIZE (current)) == NULL) &&
1354 gst_pad_can_connect_filtered (pad, current, filtercaps)) {
1357 pads = g_list_next (pads);
1360 /* try to create a new one */
1361 /* requesting is a little crazy, we need a template. Let's create one */
1362 if (filtercaps != NULL) {
1363 templcaps = gst_caps_intersect (filtercaps, (GstCaps *) GST_RPAD_CAPS (pad));
1364 if (templcaps == NULL)
1367 templcaps = gst_caps_copy (gst_pad_get_caps (pad));
1370 templ = gst_pad_template_new ((gchar *) GST_PAD_NAME (pad), GST_RPAD_DIRECTION (pad),
1371 GST_PAD_ALWAYS, templcaps, NULL);
1372 foundpad = gst_element_request_compatible_pad (element, templ);
1373 gst_object_unref (GST_OBJECT (templ)); /* this will take care of the caps too */
1375 /* FIXME: this is broken, but it's in here so autoplugging elements that don't
1376 have caps on their source padtemplates (spider) can connect... */
1377 if (!foundpad && !filtercaps) {
1378 templ = gst_pad_template_new ((gchar *) GST_PAD_NAME (pad), GST_RPAD_DIRECTION (pad),
1379 GST_PAD_ALWAYS, NULL, NULL);
1380 foundpad = gst_element_request_compatible_pad (element, templ);
1381 gst_object_unref (GST_OBJECT (templ));
1388 * gst_element_get_compatible_pad:
1389 * @element: a #GstElement in which the pad should be found.
1390 * @pad: the #GstPad to find a compatible one for.
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, or NULL if none
1400 gst_element_get_compatible_pad (GstElement *element, GstPad *pad)
1402 return gst_element_get_compatible_pad_filtered (element, pad, NULL);
1406 * gst_element_connect_filtered:
1407 * @src: a #GstElement containing the source pad.
1408 * @dest: the #GstElement containing the destination pad.
1409 * @filtercaps: the #GstCaps to use as a filter.
1411 * Connects the source to the destination element using the filtercaps.
1412 * The connection must be from source to destination, the other
1413 * direction will not be tried.
1414 * The functions looks for existing pads that aren't connected yet.
1415 * It will use request pads if possible. But both pads will not be requested.
1416 * If multiple connections are possible, only one is established.
1418 * Returns: TRUE if the elements could be connected.
1421 gst_element_connect_filtered (GstElement *src, GstElement *dest,
1422 GstCaps *filtercaps)
1424 const GList *srcpads, *destpads, *srctempls, *desttempls, *l;
1425 GstPad *srcpad, *destpad;
1426 GstPadTemplate *srctempl, *desttempl;
1429 g_return_val_if_fail (src != NULL, FALSE);
1430 g_return_val_if_fail (GST_IS_ELEMENT (src), FALSE);
1431 g_return_val_if_fail (dest != NULL, FALSE);
1432 g_return_val_if_fail (GST_IS_ELEMENT (dest), FALSE);
1434 GST_DEBUG (GST_CAT_ELEMENT_PADS, "trying to connect element %s to element %s",
1435 GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (dest));
1437 srcpads = gst_element_get_pad_list (src);
1438 destpads = gst_element_get_pad_list (dest);
1440 if (srcpads || destpads) {
1441 GST_DEBUG (GST_CAT_ELEMENT_PADS, "looping through src and dest pads");
1442 /* loop through the existing pads in the source, trying to find a
1443 * compatible destination pad */
1445 srcpad = (GstPad *) GST_PAD_REALIZE (srcpads->data);
1446 GST_DEBUG (GST_CAT_ELEMENT_PADS, "trying src pad %s:%s",
1447 GST_DEBUG_PAD_NAME (srcpad));
1448 if ((GST_RPAD_DIRECTION (srcpad) == GST_PAD_SRC) &&
1449 (GST_PAD_PEER (srcpad) == NULL)) {
1450 destpad = gst_element_get_compatible_pad_filtered (dest, srcpad,
1452 if (destpad && gst_pad_connect_filtered (srcpad, destpad, filtercaps)) {
1453 GST_DEBUG (GST_CAT_ELEMENT_PADS, "connected pad %s:%s to pad %s:%s",
1454 GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad));
1458 srcpads = g_list_next (srcpads);
1461 /* loop through the existing pads in the destination */
1463 destpad = (GstPad *) GST_PAD_REALIZE (destpads->data);
1464 GST_DEBUG (GST_CAT_ELEMENT_PADS, "trying dest pad %s:%s",
1465 GST_DEBUG_PAD_NAME (destpad));
1466 if ((GST_RPAD_DIRECTION (destpad) == GST_PAD_SINK) &&
1467 (GST_PAD_PEER (destpad) == NULL)) {
1468 srcpad = gst_element_get_compatible_pad_filtered (src, destpad,
1470 if (srcpad && gst_pad_connect_filtered (srcpad, destpad, filtercaps)) {
1471 GST_DEBUG (GST_CAT_ELEMENT_PADS, "connected pad %s:%s to pad %s:%s",
1472 GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad));
1476 destpads = g_list_next (destpads);
1480 GST_DEBUG (GST_CAT_ELEMENT_PADS,
1481 "we might have request pads on both sides, checking...");
1482 srctempls = gst_element_get_pad_template_list (src);
1483 desttempls = gst_element_get_pad_template_list (dest);
1485 if (srctempls && desttempls) {
1487 srctempl = (GstPadTemplate*) srctempls->data;
1488 if (srctempl->presence == GST_PAD_REQUEST) {
1489 for (l=desttempls; l; l=l->next) {
1490 desttempl = (GstPadTemplate*) desttempls->data;
1491 if (desttempl->presence == GST_PAD_REQUEST &&
1492 desttempl->direction != srctempl->direction) {
1493 if (gst_caps_is_always_compatible (gst_pad_template_get_caps (srctempl),
1494 gst_pad_template_get_caps (desttempl))) {
1495 srcpad = gst_element_get_request_pad (src,
1496 srctempl->name_template);
1497 destpad = gst_element_get_request_pad (dest,
1498 desttempl->name_template);
1499 if (gst_pad_connect_filtered (srcpad, destpad, filtercaps)) {
1500 GST_DEBUG (GST_CAT_ELEMENT_PADS,
1501 "connected pad %s:%s to pad %s:%s",
1502 GST_DEBUG_PAD_NAME (srcpad),
1503 GST_DEBUG_PAD_NAME (destpad));
1506 /* FIXME: we have extraneous request pads lying around */
1511 srctempls = srctempls->next;
1515 GST_DEBUG (GST_CAT_ELEMENT_PADS, "no connection possible from %s to %s",
1516 GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (dest));
1521 * gst_element_connect_many:
1522 * @element_1: the first #GstElement in the connection chain.
1523 * @element_2: the second #GstElement in the connection chain.
1524 * @...: the NULL-terminated list of elements to connect in order.
1526 * Chain together a series of elements. Uses #gst_element_connect.
1528 * Returns: TRUE on success, FALSE otherwise.
1531 gst_element_connect_many (GstElement *element_1, GstElement *element_2, ...)
1535 g_return_val_if_fail (element_1 != NULL && element_2 != NULL, FALSE);
1536 g_return_val_if_fail (GST_IS_ELEMENT (element_1) &&
1537 GST_IS_ELEMENT (element_2), FALSE);
1539 va_start (args, element_2);
1542 if (!gst_element_connect (element_1, element_2))
1545 element_1 = element_2;
1546 element_2 = va_arg (args, GstElement*);
1555 * gst_element_connect:
1556 * @src: a #GstElement containing the source pad.
1557 * @dest: the #GstElement containing the destination pad.
1559 * Connects the source to the destination element.
1560 * The connection must be from source to destination, the other
1561 * direction will not be tried.
1562 * The functions looks for existing pads and request pads that aren't
1563 * connected yet. If multiple connections are possible, only one is
1566 * Returns: TRUE if the elements could be connected.
1569 gst_element_connect (GstElement *src, GstElement *dest)
1571 return gst_element_connect_filtered (src, dest, NULL);
1575 * gst_element_connect_pads_filtered:
1576 * @src: a #GstElement containing the source pad.
1577 * @srcpadname: the name of the #GstPad in source element.
1578 * @dest: the #GstElement containing the destination pad.
1579 * @destpadname: the name of the #GstPad in destination element.
1580 * @filtercaps: the #GstCaps to use as a filter.
1582 * Connects the two named pads of the source and destination elements.
1583 * Side effect is that if one of the pads has no parent, it becomes a
1584 * child of the parent of the other element. If they have different
1585 * parents, the connection fails.
1587 * Returns: TRUE if the pads could be connected.
1590 gst_element_connect_pads_filtered (GstElement *src, const gchar *srcpadname,
1591 GstElement *dest, const gchar *destpadname,
1592 GstCaps *filtercaps)
1594 GstPad *srcpad,*destpad;
1596 g_return_val_if_fail (src != NULL, FALSE);
1597 g_return_val_if_fail (GST_IS_ELEMENT (src), FALSE);
1598 g_return_val_if_fail (srcpadname != NULL, FALSE);
1599 g_return_val_if_fail (dest != NULL, FALSE);
1600 g_return_val_if_fail (GST_IS_ELEMENT (dest), FALSE);
1601 g_return_val_if_fail (destpadname != NULL, FALSE);
1603 /* obtain the pads requested */
1604 srcpad = gst_element_get_pad (src, srcpadname);
1605 if (srcpad == NULL) {
1606 GST_ERROR (src, "source element has no pad \"%s\"", srcpadname);
1609 destpad = gst_element_get_pad (dest, destpadname);
1610 if (srcpad == NULL) {
1611 GST_ERROR (dest, "destination element has no pad \"%s\"", destpadname);
1615 /* we're satisified they can be connected, let's do it */
1616 return gst_pad_connect_filtered (srcpad, destpad, filtercaps);
1620 * gst_element_connect_pads:
1621 * @src: a #GstElement containing the source pad.
1622 * @srcpadname: the name of the #GstPad in the source element.
1623 * @dest: the #GstElement containing the destination pad.
1624 * @destpadname: the name of the #GstPad in destination element.
1626 * Connects the two named pads of the source and destination elements.
1627 * Side effect is that if one of the pads has no parent, it becomes a
1628 * child of the parent of the other element. If they have different
1629 * parents, the connection fails.
1631 * Returns: TRUE if the pads could be connected.
1634 gst_element_connect_pads (GstElement *src, const gchar *srcpadname,
1635 GstElement *dest, const gchar *destpadname)
1637 return gst_element_connect_pads_filtered (src, srcpadname, dest, destpadname, NULL);
1641 * gst_element_disconnect_pads:
1642 * @src: a #GstElement containing the source pad.
1643 * @srcpadname: the name of the #GstPad in source element.
1644 * @dest: a #GstElement containing the destination pad.
1645 * @destpadname: the name of the #GstPad in destination element.
1647 * Disconnects the two named pads of the source and destination elements.
1650 gst_element_disconnect_pads (GstElement *src, const gchar *srcpadname,
1651 GstElement *dest, const gchar *destpadname)
1653 GstPad *srcpad,*destpad;
1655 g_return_if_fail (src != NULL);
1656 g_return_if_fail (GST_IS_ELEMENT(src));
1657 g_return_if_fail (srcpadname != NULL);
1658 g_return_if_fail (dest != NULL);
1659 g_return_if_fail (GST_IS_ELEMENT(dest));
1660 g_return_if_fail (destpadname != NULL);
1662 /* obtain the pads requested */
1663 srcpad = gst_element_get_pad (src, srcpadname);
1664 if (srcpad == NULL) {
1665 GST_ERROR(src,"source element has no pad \"%s\"",srcpadname);
1668 destpad = gst_element_get_pad (dest, destpadname);
1669 if (srcpad == NULL) {
1670 GST_ERROR(dest,"destination element has no pad \"%s\"",destpadname);
1674 /* we're satisified they can be disconnected, let's do it */
1675 gst_pad_disconnect(srcpad,destpad);
1679 * gst_element_disconnect_many:
1680 * @element_1: the first #GstElement in the connection chain.
1681 * @element_2: the second #GstElement in the connection chain.
1682 * @...: the NULL-terminated list of elements to disconnect in order.
1684 * Disconnects a series of elements. Uses #gst_element_disconnect.
1687 gst_element_disconnect_many (GstElement *element_1, GstElement *element_2, ...)
1691 g_return_if_fail (element_1 != NULL && element_2 != NULL);
1692 g_return_if_fail (GST_IS_ELEMENT (element_1) && GST_IS_ELEMENT (element_2));
1694 va_start (args, element_2);
1697 gst_element_disconnect (element_1, element_2);
1699 element_1 = element_2;
1700 element_2 = va_arg (args, GstElement*);
1707 * gst_element_disconnect:
1708 * @src: the source #GstElement to disconnect.
1709 * @dest: the sink #GstElement to disconnect.
1711 * Disconnects all source pads of the source element with all sink pads
1712 * of the sink element to which they are connected.
1715 gst_element_disconnect (GstElement *src, GstElement *dest)
1717 const GList *srcpads;
1720 g_return_if_fail (GST_IS_ELEMENT (src));
1721 g_return_if_fail (GST_IS_ELEMENT (dest));
1723 GST_DEBUG (GST_CAT_ELEMENT_PADS, "disconnecting \"%s\" and \"%s\"",
1724 GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (dest));
1726 srcpads = gst_element_get_pad_list (src);
1729 pad = GST_PAD_CAST (srcpads->data);
1731 if (GST_IS_REAL_PAD (pad) && GST_PAD_DIRECTION (pad) == GST_PAD_SRC) {
1732 GstPad *peerpad = GST_PAD_PEER (pad);
1735 (GST_OBJECT_PARENT (GST_PAD_PEER (peerpad)) == (GstObject*) src)) {
1736 gst_pad_disconnect (pad, peerpad);
1740 srcpads = g_list_next (srcpads);
1745 gst_element_error_func (GstElement* element, GstElement *source,
1748 /* tell the parent */
1749 if (GST_OBJECT_PARENT (element)) {
1750 GST_DEBUG (GST_CAT_EVENT, "forwarding error \"%s\" from %s to %s",
1751 errormsg, GST_ELEMENT_NAME (element),
1752 GST_OBJECT_NAME (GST_OBJECT_PARENT (element)));
1754 gst_object_ref (GST_OBJECT (element));
1755 g_signal_emit (G_OBJECT (GST_OBJECT_PARENT (element)),
1756 gst_element_signals[ERROR], 0, source, errormsg);
1757 gst_object_unref (GST_OBJECT (element));
1762 gst_element_get_random_pad (GstElement *element, GstPadDirection dir)
1764 GList *pads = element->pads;
1766 GstPad *pad = GST_PAD_CAST (pads->data);
1768 if (GST_PAD_DIRECTION (pad) == dir) {
1769 if (GST_PAD_IS_USABLE (pad)) {
1773 pads = g_list_next (pads);
1779 * gst_element_get_event_masks:
1780 * @element: a #GstElement to query
1782 * Get an array of event masks from the element.
1783 * If the element doesn't
1784 * implement an event masks function, the query will be forwarded
1785 * to a random sink pad.
1787 * Returns: An array of #GstEventMask elements.
1790 gst_element_get_event_masks (GstElement *element)
1792 GstElementClass *oclass;
1794 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1796 oclass = GST_ELEMENT_GET_CLASS (element);
1798 if (oclass->get_event_masks)
1799 return oclass->get_event_masks (element);
1801 GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SINK);
1803 return gst_pad_get_event_masks (GST_PAD_PEER (pad));
1810 * gst_element_send_event:
1811 * @element: a #GstElement to send the event to.
1812 * @event: the #GstEvent to send to the element.
1814 * Sends an event to an element. If the element doesn't
1815 * implement an event handler, the event will be forwarded
1816 * to a random sink pad.
1818 * Returns: TRUE if the event was handled.
1821 gst_element_send_event (GstElement *element, GstEvent *event)
1823 GstElementClass *oclass;
1825 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1826 g_return_val_if_fail (event != NULL, FALSE);
1828 oclass = GST_ELEMENT_GET_CLASS (element);
1830 if (oclass->send_event)
1831 return oclass->send_event (element, event);
1833 GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SINK);
1835 GST_DEBUG (GST_CAT_ELEMENT_PADS, "sending event to random pad %s:%s",
1836 GST_DEBUG_PAD_NAME (pad));
1837 return gst_pad_send_event (GST_PAD_PEER (pad), event);
1840 GST_DEBUG (GST_CAT_ELEMENT_PADS, "can't send event on element %s",
1841 GST_ELEMENT_NAME (element));
1846 * gst_element_get_query_types:
1847 * @element: a #GstElement to query
1849 * Get an array of query types from the element.
1850 * If the element doesn't
1851 * implement a query types function, the query will be forwarded
1852 * to a random sink pad.
1854 * Returns: An array of #GstQueryType elements.
1857 gst_element_get_query_types (GstElement *element)
1859 GstElementClass *oclass;
1861 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1863 oclass = GST_ELEMENT_GET_CLASS (element);
1865 if (oclass->get_query_types)
1866 return oclass->get_query_types (element);
1868 GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SINK);
1870 return gst_pad_get_query_types (GST_PAD_PEER (pad));
1877 * gst_element_query:
1878 * @element: a #GstElement to perform the query on.
1879 * @type: the #GstQueryType.
1880 * @format: the #GstFormat pointer to hold the format of the result.
1881 * @value: the pointer to the value of the result.
1883 * Performs a query on the given element. If the format is set
1884 * to GST_FORMAT_DEFAULT and this function returns TRUE, the
1885 * format pointer will hold the default format.
1886 * For element that don't implement a query handler, this function
1887 * forwards the query to a random usable sinkpad of this element.
1889 * Returns: TRUE if the query could be performed.
1892 gst_element_query (GstElement *element, GstQueryType type,
1893 GstFormat *format, gint64 *value)
1895 GstElementClass *oclass;
1897 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1898 g_return_val_if_fail (format != NULL, FALSE);
1899 g_return_val_if_fail (value != NULL, FALSE);
1901 oclass = GST_ELEMENT_GET_CLASS (element);
1904 return oclass->query (element, type, format, value);
1906 GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SINK);
1908 return gst_pad_query (GST_PAD_PEER (pad), type, format, value);
1915 * gst_element_get_formats:
1916 * @element: a #GstElement to query
1918 * Get an array of formst from the element.
1919 * If the element doesn't
1920 * implement a formats function, the query will be forwarded
1921 * to a random sink pad.
1923 * Returns: An array of #GstFormat elements.
1926 gst_element_get_formats (GstElement *element)
1928 GstElementClass *oclass;
1930 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1932 oclass = GST_ELEMENT_GET_CLASS (element);
1934 if (oclass->get_formats)
1935 return oclass->get_formats (element);
1937 GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SINK);
1939 return gst_pad_get_formats (GST_PAD_PEER (pad));
1946 * gst_element_convert:
1947 * @element: a #GstElement to invoke the converter on.
1948 * @src_format: the source #GstFormat.
1949 * @src_value: the source value.
1950 * @dest_format: a pointer to the destination #GstFormat.
1951 * @dest_value: a pointer to the destination value.
1953 * Invokes a conversion on the element.
1954 * If the element doesn't
1955 * implement a convert function, the query will be forwarded
1956 * to a random sink pad.
1958 * Returns: TRUE if the conversion could be performed.
1961 gst_element_convert (GstElement *element,
1962 GstFormat src_format, gint64 src_value,
1963 GstFormat *dest_format, gint64 *dest_value)
1965 GstElementClass *oclass;
1967 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1968 g_return_val_if_fail (dest_format != NULL, FALSE);
1969 g_return_val_if_fail (dest_value != NULL, FALSE);
1971 if (src_format == *dest_format) {
1972 *dest_value = src_value;
1976 oclass = GST_ELEMENT_GET_CLASS (element);
1978 if (oclass->convert)
1979 return oclass->convert (element,
1980 src_format, src_value,
1981 dest_format, dest_value);
1983 GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SINK);
1985 return gst_pad_convert (GST_PAD_PEER (pad),
1986 src_format, src_value,
1987 dest_format, dest_value);
1994 * gst_element_error:
1995 * @element: a #GstElement with the error.
1996 * @error: the printf-style string describing the error.
1997 * @...: the optional arguments for the string.
1999 * signals an error condition on an element.
2000 * This function is used internally by elements.
2001 * It results in the "error" signal.
2004 gst_element_error (GstElement *element, const gchar *error, ...)
2010 g_return_if_fail (GST_IS_ELEMENT (element));
2011 g_return_if_fail (error != NULL);
2013 /* create error message */
2014 va_start (var_args, error);
2015 string = g_strdup_vprintf (error, var_args);
2017 GST_INFO (GST_CAT_EVENT, "ERROR in %s: %s", GST_ELEMENT_NAME (element), string);
2019 /* emit the signal, make sure the element stays available */
2020 gst_object_ref (GST_OBJECT (element));
2021 g_signal_emit (G_OBJECT (element), gst_element_signals[ERROR], 0, element, string);
2023 /* tell the scheduler */
2024 if (element->sched) {
2025 gst_scheduler_error (element->sched, element);
2028 gst_element_set_state (element, GST_STATE_PAUSED);
2031 gst_object_unref (GST_OBJECT (element));
2036 * gst_element_get_state:
2037 * @element: a #GstElement to get the state of.
2039 * Gets the state of the element.
2041 * Returns: the #GstElementState of the element.
2044 gst_element_get_state (GstElement *element)
2046 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_VOID_PENDING);
2048 return GST_STATE (element);
2052 * gst_element_wait_state_change:
2053 * @element: a #GstElement to wait for a state change on.
2055 * Waits and blocks until the element changed its state.
2058 gst_element_wait_state_change (GstElement *element)
2060 g_mutex_lock (element->state_mutex);
2061 g_cond_wait (element->state_cond, element->state_mutex);
2062 g_mutex_unlock (element->state_mutex);
2066 * gst_element_set_state:
2067 * @element: a #GstElement to change state of.
2068 * @state: the element's new #GstElementState.
2070 * Sets the state of the element. This function will try to set the
2071 * requested state by going through all the intermediary states and calling
2072 * the class's state change function for each.
2074 * Returns: TRUE if the state was successfully set.
2075 * (using #GstElementStateReturn).
2077 GstElementStateReturn
2078 gst_element_set_state (GstElement *element, GstElementState state)
2080 GstElementClass *oclass;
2081 GstElementState curpending;
2082 GstElementStateReturn return_val = GST_STATE_SUCCESS;
2084 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
2086 /* start with the current state */
2087 curpending = GST_STATE(element);
2089 GST_DEBUG_ELEMENT (GST_CAT_STATES, element, "setting state from %s to %s",
2090 gst_element_state_get_name (curpending),
2091 gst_element_state_get_name (state));
2093 /* loop until the final requested state is set */
2094 while (GST_STATE (element) != state
2095 && GST_STATE (element) != GST_STATE_VOID_PENDING) {
2096 /* move the curpending state in the correct direction */
2097 if (curpending < state)
2102 /* set the pending state variable */
2103 /* FIXME: should probably check to see that we don't already have one */
2104 GST_STATE_PENDING (element) = curpending;
2106 if (curpending != state) {
2107 GST_DEBUG_ELEMENT (GST_CAT_STATES, element,
2108 "intermediate: setting state from %s to %s",
2109 gst_element_state_get_name (GST_STATE (element)),
2110 gst_element_state_get_name (curpending));
2113 /* call the state change function so it can set the state */
2114 oclass = GST_ELEMENT_GET_CLASS (element);
2115 if (oclass->change_state)
2116 return_val = (oclass->change_state) (element);
2118 switch (return_val) {
2119 case GST_STATE_FAILURE:
2120 GST_DEBUG_ELEMENT (GST_CAT_STATES, element,
2121 "have failed change_state return");
2123 case GST_STATE_ASYNC:
2124 GST_DEBUG_ELEMENT (GST_CAT_STATES, element,
2125 "element will change state async");
2127 case GST_STATE_SUCCESS:
2128 /* Last thing we do is verify that a successful state change really
2129 * did change the state... */
2130 if (GST_STATE (element) != curpending) {
2131 GST_DEBUG_ELEMENT (GST_CAT_STATES, element,
2132 "element claimed state-change success,"
2133 "but state didn't change %s, %s <-> %s",
2134 gst_element_state_get_name (GST_STATE (element)),
2135 gst_element_state_get_name (GST_STATE_PENDING (element)),
2136 gst_element_state_get_name (curpending));
2137 return GST_STATE_FAILURE;
2141 /* somebody added a GST_STATE_ and forgot to do stuff here ! */
2142 g_assert_not_reached ();
2151 gst_element_negotiate_pads (GstElement *element)
2153 GList *pads = GST_ELEMENT_PADS (element);
2155 GST_DEBUG_ELEMENT (GST_CAT_CAPS, element, "negotiating pads");
2158 GstPad *pad = GST_PAD (pads->data);
2161 pads = g_list_next (pads);
2163 if (!GST_IS_REAL_PAD (pad))
2166 srcpad = GST_PAD_REALIZE (pad);
2168 /* if we have a connection on this pad and it doesn't have caps
2169 * allready, try to negotiate */
2170 if (GST_PAD_IS_USABLE (srcpad) && !GST_PAD_CAPS (srcpad)) {
2171 GstRealPad *sinkpad;
2172 GstElementState otherstate;
2175 sinkpad = GST_RPAD_PEER (GST_PAD_REALIZE (srcpad));
2177 /* check the parent of the peer pad, if there is no parent do nothing */
2178 parent = GST_PAD_PARENT (sinkpad);
2182 otherstate = GST_STATE (parent);
2184 /* swap pads if needed */
2185 if (!GST_PAD_IS_SRC (srcpad)) {
2193 /* only try to negotiate if the peer element is in PAUSED or higher too */
2194 if (otherstate >= GST_STATE_READY) {
2195 GST_DEBUG_ELEMENT (GST_CAT_CAPS, element,
2196 "perform negotiate for %s:%s and %s:%s",
2197 GST_DEBUG_PAD_NAME (srcpad),
2198 GST_DEBUG_PAD_NAME (sinkpad));
2199 if (!gst_pad_perform_negotiate (GST_PAD (srcpad), GST_PAD (sinkpad)))
2203 GST_DEBUG_ELEMENT (GST_CAT_CAPS, element,
2204 "not negotiating %s:%s and %s:%s, not in READY yet",
2205 GST_DEBUG_PAD_NAME (srcpad),
2206 GST_DEBUG_PAD_NAME (sinkpad));
2215 gst_element_clear_pad_caps (GstElement *element)
2217 GList *pads = GST_ELEMENT_PADS (element);
2219 GST_DEBUG_ELEMENT (GST_CAT_CAPS, element, "clearing pad caps");
2222 GstRealPad *pad = GST_PAD_REALIZE (pads->data);
2224 if (GST_PAD_CAPS (pad)) {
2225 GST_PAD_CAPS (pad) = NULL;
2227 pads = g_list_next (pads);
2232 gst_element_pads_activate (GstElement *element, gboolean active)
2234 GList *pads = element->pads;
2237 GstPad *pad = GST_PAD_CAST (pads->data);
2238 pads = g_list_next (pads);
2240 if (!GST_IS_REAL_PAD (pad))
2243 gst_pad_set_active (pad, active);
2247 static GstElementStateReturn
2248 gst_element_change_state (GstElement *element)
2250 GstElementState old_state;
2252 gint old_pending, old_transition;
2254 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
2256 old_state = GST_STATE (element);
2257 old_pending = GST_STATE_PENDING (element);
2258 old_transition = GST_STATE_TRANSITION (element);
2260 if (old_pending == GST_STATE_VOID_PENDING ||
2261 old_state == GST_STATE_PENDING (element)) {
2262 GST_INFO (GST_CAT_STATES,
2263 "no state change needed for element %s (VOID_PENDING)",
2264 GST_ELEMENT_NAME (element));
2265 return GST_STATE_SUCCESS;
2268 GST_INFO (GST_CAT_STATES, "%s default handler sets state from %s to %s %04x",
2269 GST_ELEMENT_NAME (element),
2270 gst_element_state_get_name (old_state),
2271 gst_element_state_get_name (old_pending),
2274 /* we set the state change early for the negotiation functions */
2275 GST_STATE (element) = old_pending;
2276 GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING;
2278 switch (old_transition) {
2279 case GST_STATE_PLAYING_TO_PAUSED:
2280 gst_element_pads_activate (element, FALSE);
2282 case GST_STATE_PAUSED_TO_PLAYING:
2283 gst_element_pads_activate (element, TRUE);
2285 /* if we are going to paused, we try to negotiate the pads */
2286 case GST_STATE_READY_TO_PAUSED:
2287 if (!gst_element_negotiate_pads (element))
2290 /* going to the READY state clears all pad caps */
2291 case GST_STATE_PAUSED_TO_READY:
2292 gst_element_clear_pad_caps (element);
2298 parent = GST_ELEMENT_PARENT (element);
2300 GST_DEBUG_ELEMENT (GST_CAT_STATES, element,
2301 "signaling state change from %s to %s",
2302 gst_element_state_get_name (old_state),
2303 gst_element_state_get_name (GST_STATE (element)));
2305 /* tell the scheduler if we have one */
2306 if (element->sched) {
2307 if (gst_scheduler_state_transition (element->sched, element,
2308 old_transition) != GST_STATE_SUCCESS) {
2313 g_signal_emit (G_OBJECT (element), gst_element_signals[STATE_CHANGE],
2314 0, old_state, GST_STATE (element));
2316 /* tell our parent about the state change */
2317 if (parent && GST_IS_BIN (parent)) {
2318 gst_bin_child_state_change (GST_BIN (parent), old_state,
2319 GST_STATE (element), element);
2322 /* signal the state change in case somebody is waiting for us */
2323 g_mutex_lock (element->state_mutex);
2324 g_cond_signal (element->state_cond);
2325 g_mutex_unlock (element->state_mutex);
2327 return GST_STATE_SUCCESS;
2330 /* undo the state change */
2331 GST_STATE (element) = old_state;
2332 GST_STATE_PENDING (element) = old_pending;
2334 return GST_STATE_FAILURE;
2338 * gst_element_get_factory:
2339 * @element: a #GstElement to request the element factory of.
2341 * Retrieves the factory that was used to create this element.
2343 * Returns: the #GstElementFactory used for creating this element.
2346 gst_element_get_factory (GstElement *element)
2348 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
2350 return GST_ELEMENT_GET_CLASS (element)->elementfactory;
2354 gst_element_dispose (GObject *object)
2356 GstElement *element = GST_ELEMENT (object);
2360 GST_DEBUG_ELEMENT (GST_CAT_REFCOUNTING, element, "dispose");
2362 gst_element_set_state (element, GST_STATE_NULL);
2364 /* first we break all our connections with the ouside */
2365 if (element->pads) {
2367 orig = pads = g_list_copy (element->pads);
2369 pad = GST_PAD (pads->data);
2371 if (GST_PAD_PEER (pad)) {
2372 GST_DEBUG (GST_CAT_REFCOUNTING, "disconnecting pad '%s'",
2373 GST_OBJECT_NAME (GST_OBJECT (GST_PAD (GST_PAD_PEER (pad)))));
2374 gst_pad_disconnect (pad, GST_PAD (GST_PAD_PEER (pad)));
2376 gst_element_remove_pad (element, pad);
2378 pads = g_list_next (pads);
2381 g_list_free (element->pads);
2382 element->pads = NULL;
2385 element->numsrcpads = 0;
2386 element->numsinkpads = 0;
2387 element->numpads = 0;
2388 g_mutex_free (element->state_mutex);
2389 g_cond_free (element->state_cond);
2391 if (element->prop_value_queue)
2392 g_async_queue_unref (element->prop_value_queue);
2393 element->prop_value_queue = NULL;
2394 if (element->property_mutex)
2395 g_mutex_free (element->property_mutex);
2397 G_OBJECT_CLASS (parent_class)->dispose (object);
2400 #ifndef GST_DISABLE_LOADSAVE
2402 * gst_element_save_thyself:
2403 * @element: a #GstElement to save.
2404 * @parent: the xml parent node.
2406 * Saves the element as part of the given XML structure.
2408 * Returns: the new #xmlNodePtr.
2411 gst_element_save_thyself (GstObject *object,
2415 GstElementClass *oclass;
2416 GParamSpec **specs, *spec;
2418 GValue value = { 0, };
2419 GstElement *element;
2421 g_return_val_if_fail (GST_IS_ELEMENT (object), parent);
2423 element = GST_ELEMENT (object);
2425 oclass = GST_ELEMENT_GET_CLASS (element);
2427 xmlNewChild(parent, NULL, "name", GST_ELEMENT_NAME(element));
2429 if (oclass->elementfactory != NULL) {
2430 GstElementFactory *factory = (GstElementFactory *)oclass->elementfactory;
2432 xmlNewChild (parent, NULL, "type", GST_OBJECT_NAME (factory));
2433 xmlNewChild (parent, NULL, "version", factory->details->version);
2436 /* FIXME: what is this? */
2437 /* if (element->manager) */
2438 /* xmlNewChild(parent, NULL, "manager", GST_ELEMENT_NAME(element->manager)); */
2441 specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (object), &nspecs);
2443 for (i=0; i<nspecs; i++) {
2445 if (spec->flags & G_PARAM_READABLE) {
2449 g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE (spec));
2451 g_object_get_property (G_OBJECT (element), spec->name, &value);
2452 param = xmlNewChild (parent, NULL, "param", NULL);
2453 xmlNewChild (param, NULL, "name", spec->name);
2455 if (G_IS_PARAM_SPEC_STRING (spec))
2456 contents = g_value_dup_string (&value);
2457 else if (G_IS_PARAM_SPEC_ENUM (spec))
2458 contents = g_strdup_printf ("%d", g_value_get_enum (&value));
2459 else if (G_IS_PARAM_SPEC_INT64 (spec))
2460 contents = g_strdup_printf ("%" G_GINT64_FORMAT,
2461 g_value_get_int64 (&value));
2463 contents = g_strdup_value_contents (&value);
2465 xmlNewChild (param, NULL, "value", contents);
2468 g_value_unset(&value);
2472 pads = GST_ELEMENT_PADS (element);
2475 GstPad *pad = GST_PAD (pads->data);
2476 /* figure out if it's a direct pad or a ghostpad */
2477 if (GST_ELEMENT (GST_OBJECT_PARENT (pad)) == element) {
2478 xmlNodePtr padtag = xmlNewChild (parent, NULL, "pad", NULL);
2479 gst_object_save_thyself (GST_OBJECT (pad), padtag);
2481 pads = g_list_next (pads);
2488 gst_element_restore_thyself (GstObject *object, xmlNodePtr self)
2490 xmlNodePtr children;
2491 GstElement *element;
2493 gchar *value = NULL;
2495 element = GST_ELEMENT (object);
2496 g_return_if_fail (element != NULL);
2499 children = self->xmlChildrenNode;
2501 if (!strcmp (children->name, "param")) {
2502 xmlNodePtr child = children->xmlChildrenNode;
2505 if (!strcmp (child->name, "name")) {
2506 name = xmlNodeGetContent (child);
2508 else if (!strcmp (child->name, "value")) {
2509 value = xmlNodeGetContent (child);
2511 child = child->next;
2513 /* FIXME: can this just be g_object_set ? */
2514 gst_util_set_object_arg (G_OBJECT (element), name, value);
2516 children = children->next;
2520 children = self->xmlChildrenNode;
2522 if (!strcmp (children->name, "pad")) {
2523 gst_pad_load_and_connect (children, GST_OBJECT (element));
2525 children = children->next;
2528 if (GST_OBJECT_CLASS (parent_class)->restore_thyself)
2529 (GST_OBJECT_CLASS (parent_class)->restore_thyself) (object, self);
2531 #endif /* GST_DISABLE_LOADSAVE */
2534 * gst_element_yield:
2535 * @element: a #GstElement to yield.
2537 * Requests a yield operation for the element. The scheduler will typically
2538 * give control to another element.
2541 gst_element_yield (GstElement *element)
2543 if (GST_ELEMENT_SCHED (element)) {
2544 gst_scheduler_yield (GST_ELEMENT_SCHED (element), element);
2549 * gst_element_interrupt:
2550 * @element: a #GstElement to interrupt.
2552 * Requests the scheduler of this element to interrupt the execution of
2553 * this element and scheduler another one.
2555 * Returns: TRUE if the element should exit its chain/loop/get
2556 * function ASAP, depending on the scheduler implementation.
2559 gst_element_interrupt (GstElement *element)
2561 if (GST_ELEMENT_SCHED (element)) {
2562 return gst_scheduler_interrupt (GST_ELEMENT_SCHED (element), element);
2569 * gst_element_set_scheduler:
2570 * @element: a #GstElement to set the scheduler of.
2571 * @sched: the #GstScheduler to set.
2573 * Sets the scheduler of the element. For internal use only, unless you're
2574 * writing a new bin subclass.
2577 gst_element_set_scheduler (GstElement *element,
2578 GstScheduler *sched)
2580 g_return_if_fail (GST_IS_ELEMENT (element));
2582 GST_INFO_ELEMENT (GST_CAT_PARENTAGE, element, "setting scheduler to %p", sched);
2584 GST_ELEMENT_SCHED (element) = sched;
2588 * gst_element_get_scheduler:
2589 * @element: a #GstElement to get the scheduler of.
2591 * Returns the scheduler of the element.
2593 * Returns: the element's #GstScheduler.
2596 gst_element_get_scheduler (GstElement *element)
2598 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
2600 return GST_ELEMENT_SCHED (element);
2604 * gst_element_set_loop_function:
2605 * @element: a #GstElement to set the loop function of.
2606 * @loop: Pointer to #GstElementLoopFunction.
2608 * This sets the loop function for the element. The function pointed to
2609 * can deviate from the GstElementLoopFunction definition in type of
2612 * NOTE: in order for this to take effect, the current loop function *must*
2613 * exit. Assuming the loop function itself is the only one who will cause
2614 * a new loopfunc to be assigned, this should be no problem.
2617 gst_element_set_loop_function (GstElement *element,
2618 GstElementLoopFunction loop)
2620 g_return_if_fail (GST_IS_ELEMENT (element));
2622 /* set the loop function */
2623 element->loopfunc = loop;
2625 /* set the NEW_LOOPFUNC flag so everyone knows to go try again */
2626 GST_FLAG_SET (element, GST_ELEMENT_NEW_LOOPFUNC);
2628 if (GST_ELEMENT_SCHED (element)) {
2629 gst_scheduler_scheduling_change (GST_ELEMENT_SCHED (element), element);
2634 * gst_element_set_eos:
2635 * @element: a #GstElement to set to the EOS state.
2637 * Perform the actions needed to bring the element in the EOS state.
2640 gst_element_set_eos (GstElement *element)
2642 g_return_if_fail (GST_IS_ELEMENT (element));
2644 GST_DEBUG (GST_CAT_EVENT, "setting EOS on element %s",
2645 GST_OBJECT_NAME (element));
2647 gst_element_set_state (element, GST_STATE_PAUSED);
2649 g_signal_emit (G_OBJECT (element), gst_element_signals[EOS], 0);
2654 * gst_element_state_get_name:
2655 * @state: a #GstElementState to get the name of.
2657 * Gets a string representing the given state.
2659 * Returns: a string with the name of the state.
2662 gst_element_state_get_name (GstElementState state)
2665 #ifdef GST_DEBUG_COLOR
2666 case GST_STATE_VOID_PENDING: return "NONE_PENDING";break;
2667 case GST_STATE_NULL: return "\033[01;37mNULL\033[00m";break;
2668 case GST_STATE_READY: return "\033[01;31mREADY\033[00m";break;
2669 case GST_STATE_PLAYING: return "\033[01;32mPLAYING\033[00m";break;
2670 case GST_STATE_PAUSED: return "\033[01;33mPAUSED\033[00m";break;
2672 /* This is a memory leak */
2673 return g_strdup_printf ("\033[01;37;41mUNKNOWN!\033[00m(%d)", state);
2675 case GST_STATE_VOID_PENDING: return "NONE_PENDING";break;
2676 case GST_STATE_NULL: return "NULL";break;
2677 case GST_STATE_READY: return "READY";break;
2678 case GST_STATE_PLAYING: return "PLAYING";break;
2679 case GST_STATE_PAUSED: return "PAUSED";break;
2680 default: return "UNKNOWN!";
2687 gst_element_populate_std_props (GObjectClass * klass, const gchar *prop_name,
2688 guint arg_id, GParamFlags flags)
2690 GQuark prop_id = g_quark_from_string (prop_name);
2693 static GQuark fd_id = 0;
2694 static GQuark blocksize_id;
2695 static GQuark bytesperread_id;
2696 static GQuark dump_id;
2697 static GQuark filesize_id;
2698 static GQuark mmapsize_id;
2699 static GQuark location_id;
2700 static GQuark offset_id;
2701 static GQuark silent_id;
2702 static GQuark touch_id;
2705 fd_id = g_quark_from_static_string ("fd");
2706 blocksize_id = g_quark_from_static_string ("blocksize");
2707 bytesperread_id = g_quark_from_static_string ("bytesperread");
2708 dump_id = g_quark_from_static_string ("dump");
2709 filesize_id = g_quark_from_static_string ("filesize");
2710 mmapsize_id = g_quark_from_static_string ("mmapsize");
2711 location_id = g_quark_from_static_string ("location");
2712 offset_id = g_quark_from_static_string ("offset");
2713 silent_id = g_quark_from_static_string ("silent");
2714 touch_id = g_quark_from_static_string ("touch");
2717 if (prop_id == fd_id) {
2718 pspec = g_param_spec_int ("fd", "File-descriptor",
2719 "File-descriptor for the file being read",
2720 0, G_MAXINT, 0, flags);
2722 else if (prop_id == blocksize_id) {
2723 pspec = g_param_spec_ulong ("blocksize", "Block Size",
2724 "Block size to read per buffer",
2725 0, G_MAXULONG, 4096, flags);
2728 else if (prop_id == bytesperread_id) {
2729 pspec = g_param_spec_int ("bytesperread", "Bytes per read",
2730 "Number of bytes to read per buffer",
2731 G_MININT, G_MAXINT, 0, flags);
2734 else if (prop_id == dump_id) {
2735 pspec = g_param_spec_boolean ("dump", "Dump",
2736 "Dump bytes to stdout",
2740 else if (prop_id == filesize_id) {
2741 pspec = g_param_spec_int64 ("filesize", "File Size",
2742 "Size of the file being read",
2743 0, G_MAXINT64, 0, flags);
2746 else if (prop_id == mmapsize_id) {
2747 pspec = g_param_spec_ulong ("mmapsize", "mmap() Block Size",
2748 "Size in bytes of mmap()d regions",
2749 0, G_MAXULONG, 4 * 1048576, flags);
2752 else if (prop_id == location_id) {
2753 pspec = g_param_spec_string ("location", "File Location",
2754 "Location of the file to read",
2758 else if (prop_id == offset_id) {
2759 pspec = g_param_spec_int64 ("offset", "File Offset",
2760 "Byte offset of current read pointer",
2761 0, G_MAXINT64, 0, flags);
2764 else if (prop_id == silent_id) {
2765 pspec = g_param_spec_boolean ("silent", "Silent", "Don't produce events",
2769 else if (prop_id == touch_id) {
2770 pspec = g_param_spec_boolean ("touch", "Touch read data",
2771 "Touch data to force disk read before "
2772 "push ()", TRUE, flags);
2775 g_warning ("Unknown - 'standard' property '%s' id %d from klass %s",
2776 prop_name, arg_id, g_type_name (G_OBJECT_CLASS_TYPE (klass)));
2781 g_object_class_install_property (klass, arg_id, pspec);
2786 * gst_element_class_install_std_props:
2787 * @klass: the #GstElementClass to add the properties to.
2788 * @first_name: the name of the first property.
2789 * in a NULL terminated
2790 * @...: the id and flags of the first property, followed by
2791 * further 'name', 'id', 'flags' triplets and terminated by NULL.
2793 * Adds a list of standardized properties with types to the @klass.
2794 * the id is for the property switch in your get_prop method, and
2795 * the flags determine readability / writeability.
2798 gst_element_class_install_std_props (GstElementClass * klass,
2799 const gchar *first_name, ...)
2805 g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
2807 va_start (args, first_name);
2812 int arg_id = va_arg (args, int);
2813 int flags = va_arg (args, int);
2815 gst_element_populate_std_props ((GObjectClass *) klass, name, arg_id, flags);
2817 name = va_arg (args, char *);
2824 * gst_element_get_managing_bin:
2825 * @element: a #GstElement to get the managing bin of.
2827 * Gets the managing bin (a pipeline or a thread, for example) of an element.
2829 * Returns: the #GstBin, or NULL on failure.
2832 gst_element_get_managing_bin (GstElement *element)
2836 g_return_val_if_fail (element != NULL, NULL);
2838 bin = GST_BIN (gst_object_get_parent (GST_OBJECT_CAST (element)));
2840 while (bin && !GST_FLAG_IS_SET (GST_OBJECT_CAST (bin), GST_BIN_FLAG_MANAGER))
2841 bin = GST_BIN (gst_object_get_parent (GST_OBJECT_CAST (bin)));