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"
36 /* Element signals and args */
52 #define CLASS(element) GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS (element))
54 static void gst_element_class_init (GstElementClass *klass);
55 static void gst_element_init (GstElement *element);
56 static void gst_element_base_class_init (GstElementClass *klass);
58 static void gst_element_real_set_property (GObject *object, guint prop_id,
59 const GValue *value, GParamSpec *pspec);
60 static void gst_element_real_get_property (GObject *object, guint prop_id, GValue *value,
62 static void gst_element_dispatch_properties_changed (GObject * object, guint n_pspecs, GParamSpec **pspecs);
64 static void gst_element_dispose (GObject *object);
66 static GstElementStateReturn gst_element_change_state (GstElement *element);
67 static void gst_element_error_func (GstElement* element, GstElement *source, gchar *errormsg);
69 #ifndef GST_DISABLE_LOADSAVE
70 static xmlNodePtr gst_element_save_thyself (GstObject *object, xmlNodePtr parent);
71 static void gst_element_restore_thyself (GstObject *parent, xmlNodePtr self);
74 GType _gst_element_type = 0;
76 static GstObjectClass *parent_class = NULL;
77 static guint gst_element_signals[LAST_SIGNAL] = { 0 };
79 GType gst_element_get_type (void)
81 if (!_gst_element_type) {
82 static const GTypeInfo element_info = {
83 sizeof(GstElementClass),
84 (GBaseInitFunc)gst_element_base_class_init,
86 (GClassInitFunc)gst_element_class_init,
91 (GInstanceInitFunc)gst_element_init,
94 _gst_element_type = g_type_register_static(GST_TYPE_OBJECT, "GstElement",
95 &element_info, G_TYPE_FLAG_ABSTRACT);
97 return _gst_element_type;
101 gst_element_class_init (GstElementClass *klass)
103 GObjectClass *gobject_class;
104 GstObjectClass *gstobject_class;
106 gobject_class = (GObjectClass*) klass;
107 gstobject_class = (GstObjectClass*) klass;
109 parent_class = g_type_class_ref(GST_TYPE_OBJECT);
111 gst_element_signals[STATE_CHANGE] =
112 g_signal_new ("state_change", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
113 G_STRUCT_OFFSET (GstElementClass, state_change), NULL, NULL,
114 gst_marshal_VOID__INT_INT, G_TYPE_NONE, 2,
115 G_TYPE_INT, G_TYPE_INT);
116 gst_element_signals[NEW_PAD] =
117 g_signal_new ("new_pad", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
118 G_STRUCT_OFFSET (GstElementClass, new_pad), NULL, NULL,
119 gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
121 gst_element_signals[PAD_REMOVED] =
122 g_signal_new ("pad_removed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
123 G_STRUCT_OFFSET (GstElementClass, pad_removed), NULL, NULL,
124 gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
126 gst_element_signals[ERROR] =
127 g_signal_new ("error", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
128 G_STRUCT_OFFSET (GstElementClass, error), NULL, NULL,
129 gst_marshal_VOID__OBJECT_STRING, G_TYPE_NONE, 2,
130 G_TYPE_OBJECT, G_TYPE_STRING);
131 gst_element_signals[EOS] =
132 g_signal_new ("eos", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
133 G_STRUCT_OFFSET (GstElementClass,eos), NULL, NULL,
134 gst_marshal_VOID__VOID, G_TYPE_NONE, 0);
135 gst_element_signals[DEEP_NOTIFY] =
136 g_signal_new ("deep_notify", G_TYPE_FROM_CLASS (klass),
137 G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_DETAILED | G_SIGNAL_NO_HOOKS,
138 G_STRUCT_OFFSET (GstElementClass, deep_notify), NULL, NULL,
139 gst_marshal_VOID__OBJECT_PARAM, G_TYPE_NONE,
140 2, G_TYPE_OBJECT, G_TYPE_PARAM);
143 gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_element_real_set_property);
144 gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_element_real_get_property);
146 /* see the comments at gst_element_dispatch_properties_changed */
147 gobject_class->dispatch_properties_changed
148 = GST_DEBUG_FUNCPTR (gst_element_dispatch_properties_changed);
150 gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_element_dispose);
152 #ifndef GST_DISABLE_LOADSAVE
153 gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_element_save_thyself);
154 gstobject_class->restore_thyself = GST_DEBUG_FUNCPTR (gst_element_restore_thyself);
157 klass->change_state = GST_DEBUG_FUNCPTR (gst_element_change_state);
158 klass->error = GST_DEBUG_FUNCPTR (gst_element_error_func);
159 klass->elementfactory = NULL;
160 klass->padtemplates = NULL;
161 klass->numpadtemplates = 0;
165 gst_element_base_class_init (GstElementClass *klass)
167 GObjectClass *gobject_class;
169 gobject_class = (GObjectClass*) klass;
171 gobject_class->set_property = GST_DEBUG_FUNCPTR(gst_element_real_set_property);
172 gobject_class->get_property = GST_DEBUG_FUNCPTR(gst_element_real_get_property);
176 gst_element_init (GstElement *element)
178 element->current_state = GST_STATE_NULL;
179 element->pending_state = GST_STATE_VOID_PENDING;
180 element->numpads = 0;
181 element->numsrcpads = 0;
182 element->numsinkpads = 0;
183 element->pads = NULL;
184 element->loopfunc = NULL;
185 element->sched = NULL;
186 element->sched_private = NULL;
187 element->state_mutex = g_mutex_new ();
188 element->state_cond = g_cond_new ();
192 gst_element_real_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
194 GstElementClass *oclass = CLASS (object);
196 if (oclass->set_property)
197 (oclass->set_property) (object, prop_id, value, pspec);
201 gst_element_real_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
203 GstElementClass *oclass = CLASS (object);
205 if (oclass->get_property)
206 (oclass->get_property) (object, prop_id, value, pspec);
209 /* Changing a GObject property of an element will result in "deep_notify"
210 * signals being emitted by the element itself, as well as in each parent
211 * element. This is so that an application can connect a listener to the
212 * top-level bin to catch property-change notifications for all contained
215 gst_element_dispatch_properties_changed (GObject *object,
219 GstObject *gst_object;
222 /* do the standard dispatching */
223 G_OBJECT_CLASS (parent_class)->dispatch_properties_changed (object, n_pspecs, pspecs);
225 /* now let the parent dispatch those, too */
226 gst_object = GST_OBJECT (object);
229 /* need own category? */
230 for (i = 0; i < n_pspecs; i++) {
231 GST_DEBUG (GST_CAT_EVENT, "deep notification from %s to %s (%s)", GST_OBJECT_NAME (object),
232 GST_OBJECT_NAME (gst_object), pspecs[i]->name);
233 g_signal_emit (gst_object, gst_element_signals[DEEP_NOTIFY], g_quark_from_string (pspecs[i]->name),
234 (GstObject *) object, pspecs[i]);
237 gst_object = GST_OBJECT_PARENT (gst_object);
242 const GParamSpec *pspec;
247 element_set_property (GstElement *element, const GParamSpec *pspec, const GValue *value)
249 prop_value_t *prop_value = g_new0 (prop_value_t, 1);
251 prop_value->pspec = pspec;
252 prop_value->value = value;
254 g_async_queue_push (element->prop_value_queue, prop_value);
258 element_get_property (GstElement *element, const GParamSpec *pspec, GValue *value)
260 g_mutex_lock (element->property_mutex);
261 g_object_get_property ((GObject*)element, pspec->name, value);
262 g_mutex_unlock (element->property_mutex);
266 gst_element_threadsafe_properties_pre_run (GstElement *element)
268 GST_DEBUG (GST_CAT_THREAD, "locking element %s", GST_OBJECT_NAME (element));
269 g_mutex_lock (element->property_mutex);
270 gst_element_set_pending_properties (element);
274 gst_element_threadsafe_properties_post_run (GstElement *element)
276 GST_DEBUG (GST_CAT_THREAD, "unlocking element %s", GST_OBJECT_NAME (element));
277 g_mutex_unlock (element->property_mutex);
281 gst_element_enable_threadsafe_properties (GstElement *element)
283 g_return_if_fail (GST_IS_ELEMENT (element));
285 GST_FLAG_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES);
286 element->pre_run_func = gst_element_threadsafe_properties_pre_run;
287 element->post_run_func = gst_element_threadsafe_properties_post_run;
288 if (!element->prop_value_queue)
289 element->prop_value_queue = g_async_queue_new ();
290 if (!element->property_mutex)
291 element->property_mutex = g_mutex_new ();
295 gst_element_disable_threadsafe_properties (GstElement *element)
297 g_return_if_fail (GST_IS_ELEMENT (element));
299 GST_FLAG_UNSET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES);
300 element->pre_run_func = NULL;
301 element->post_run_func = NULL;
302 /* let's keep around that async queue */
306 gst_element_set_pending_properties (GstElement *element)
308 prop_value_t *prop_value;
310 while ((prop_value = g_async_queue_try_pop (element->prop_value_queue))) {
311 g_object_set_property ((GObject*)element, prop_value->pspec->name, prop_value->value);
316 /* following 6 functions taken mostly from gobject.c */
319 gst_element_set (GstElement *element, const gchar *first_property_name, ...)
323 g_return_if_fail (GST_IS_ELEMENT (element));
325 va_start (var_args, first_property_name);
326 gst_element_set_valist (element, first_property_name, var_args);
331 gst_element_get (GstElement *element, const gchar *first_property_name, ...)
335 g_return_if_fail (GST_IS_ELEMENT (element));
337 va_start (var_args, first_property_name);
338 gst_element_get_valist (element, first_property_name, var_args);
343 gst_element_set_valist (GstElement *element, const gchar *first_property_name, va_list var_args)
348 g_return_if_fail (GST_IS_ELEMENT (element));
350 object = (GObject*)element;
352 if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
353 g_object_set_valist (object, first_property_name, var_args);
357 g_object_ref (object);
359 name = first_property_name;
363 GValue value = { 0, };
367 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), name);
371 g_warning ("%s: object class `%s' has no property named `%s'",
373 G_OBJECT_TYPE_NAME (object),
377 if (!(pspec->flags & G_PARAM_WRITABLE))
379 g_warning ("%s: property `%s' of object class `%s' is not writable",
382 G_OBJECT_TYPE_NAME (object));
386 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
388 G_VALUE_COLLECT (&value, var_args, 0, &error);
391 g_warning ("%s: %s", G_STRLOC, error);
394 /* we purposely leak the value here, it might not be
395 * in a sane state if an error condition occoured
400 element_set_property (element, pspec, &value);
401 g_value_unset (&value);
403 name = va_arg (var_args, gchar*);
406 g_object_unref (object);
410 gst_element_get_valist (GstElement *element, const gchar *first_property_name, va_list var_args)
415 g_return_if_fail (GST_IS_ELEMENT (element));
417 object = (GObject*)element;
419 if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
420 g_object_get_valist (object, first_property_name, var_args);
424 g_object_ref (object);
426 name = first_property_name;
430 GValue value = { 0, };
434 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), name);
438 g_warning ("%s: object class `%s' has no property named `%s'",
440 G_OBJECT_TYPE_NAME (object),
444 if (!(pspec->flags & G_PARAM_READABLE))
446 g_warning ("%s: property `%s' of object class `%s' is not readable",
449 G_OBJECT_TYPE_NAME (object));
453 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
455 element_get_property (element, pspec, &value);
457 G_VALUE_LCOPY (&value, var_args, 0, &error);
460 g_warning ("%s: %s", G_STRLOC, error);
462 g_value_unset (&value);
466 g_value_unset (&value);
468 name = va_arg (var_args, gchar*);
471 g_object_unref (object);
475 gst_element_set_property (GstElement *element, const gchar *property_name, const GValue *value)
480 g_return_if_fail (GST_IS_ELEMENT (element));
481 g_return_if_fail (property_name != NULL);
482 g_return_if_fail (G_IS_VALUE (value));
484 object = (GObject*)element;
486 if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
487 g_object_set_property (object, property_name, value);
491 g_object_ref (object);
493 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), property_name);
496 g_warning ("%s: object class `%s' has no property named `%s'",
498 G_OBJECT_TYPE_NAME (object),
501 element_set_property (element, pspec, value);
503 g_object_unref (object);
507 gst_element_get_property (GstElement *element, const gchar *property_name, GValue *value)
512 g_return_if_fail (GST_IS_ELEMENT (element));
513 g_return_if_fail (property_name != NULL);
514 g_return_if_fail (G_IS_VALUE (value));
516 object = (GObject*)element;
518 if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
519 g_object_get_property (object, property_name, value);
523 g_object_ref (object);
525 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), property_name);
528 g_warning ("%s: object class `%s' has no property named `%s'",
530 G_OBJECT_TYPE_NAME (object),
534 GValue *prop_value, tmp_value = { 0, };
536 /* auto-conversion of the callers value type
538 if (G_VALUE_TYPE (value) == G_PARAM_SPEC_VALUE_TYPE (pspec))
540 g_value_reset (value);
543 else if (!g_value_type_transformable (G_PARAM_SPEC_VALUE_TYPE (pspec), G_VALUE_TYPE (value)))
545 g_warning ("can't retrieve property `%s' of type `%s' as value of type `%s'",
547 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
548 G_VALUE_TYPE_NAME (value));
549 g_object_unref (object);
554 g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
555 prop_value = &tmp_value;
557 element_get_property (element, pspec, prop_value);
558 if (prop_value != value)
560 g_value_transform (prop_value, value);
561 g_value_unset (&tmp_value);
565 g_object_unref (object);
569 gst_element_request_pad (GstElement *element, GstPadTemplate *templ, const gchar* name)
571 GstPad *newpad = NULL;
572 GstElementClass *oclass;
574 oclass = CLASS (element);
575 if (oclass->request_new_pad)
576 newpad = (oclass->request_new_pad)(element, templ, name);
582 gst_element_release_request_pad (GstElement *element, GstPad *pad)
584 GstElementClass *oclass;
586 g_return_if_fail (GST_IS_ELEMENT (element));
587 g_return_if_fail (GST_IS_PAD (pad));
589 oclass = CLASS (element);
590 if (oclass->release_pad)
591 (oclass->release_pad) (element, pad);
596 * gst_element_set_name:
597 * @element: a #GstElement to set name of
598 * @name: new name of element
600 * Sets the name of the element, getting rid of the old name if there was
604 gst_element_set_name (GstElement *element, const gchar *name)
606 g_return_if_fail (element != NULL);
607 g_return_if_fail (GST_IS_ELEMENT (element));
609 gst_object_set_name (GST_OBJECT (element), name);
613 * gst_element_get_name:
614 * @element: a #GstElement to get name of
616 * Gets the name of the element.
618 * Returns: name of the element
621 gst_element_get_name (GstElement *element)
623 g_return_val_if_fail (element != NULL, NULL);
624 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
626 return GST_OBJECT_NAME (element);
630 * gst_element_set_parent:
631 * @element: a #GstElement to set parent of
632 * @parent: new parent of the object
634 * Sets the parent of the element.
637 gst_element_set_parent (GstElement *element, GstObject *parent)
639 g_return_if_fail (element != NULL);
640 g_return_if_fail (GST_IS_ELEMENT (element));
641 g_return_if_fail (GST_OBJECT_PARENT (element) == NULL);
642 g_return_if_fail (parent != NULL);
643 g_return_if_fail (GST_IS_OBJECT (parent));
644 g_return_if_fail ((gpointer)element != (gpointer)parent);
646 gst_object_set_parent (GST_OBJECT (element), parent);
650 * gst_element_get_parent:
651 * @element: a #GstElement to get the parent of
653 * Gets the parent of the element.
655 * Returns: the #GstElement parent of the element
658 gst_element_get_parent (GstElement *element)
660 g_return_val_if_fail (element != NULL, NULL);
661 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
663 return GST_OBJECT_PARENT (element);
667 * gst_element_set_clock:
668 * @element: a #GstElement to set the clock for
669 * @clock: the #GstClock to set for the element
671 * Sets the clock for the element.
674 gst_element_set_clock (GstElement *element, GstClock *clock)
676 g_return_if_fail (element != NULL);
677 g_return_if_fail (GST_IS_ELEMENT (element));
679 if (element->setclockfunc)
680 element->setclockfunc (element, clock);
684 * gst_element_get_clock:
685 * @element: a #GstElement to get the clock of
687 * Gets the clock of the element.
689 * Returns: the #GstClock of the element.
692 gst_element_get_clock (GstElement *element)
694 g_return_val_if_fail (element != NULL, NULL);
695 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
697 if (element->getclockfunc)
698 return element->getclockfunc (element);
704 * gst_element_clock_wait:
705 * @element: a #GstElement
706 * @clock: the #GstClock to use
707 * @time: the #GstClockTime to wait for on the clock
709 * Waits for a specific time on the clock.
711 * Returns: the #GstClockReturn result of the wait operation
714 gst_element_clock_wait (GstElement *element, GstClock *clock, GstClockTime time)
716 g_return_val_if_fail (element != NULL, GST_CLOCK_ERROR);
717 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_CLOCK_ERROR);
719 if (GST_ELEMENT_SCHED (element)) {
720 return gst_scheduler_clock_wait (GST_ELEMENT_SCHED (element), element, clock, time);
723 return GST_CLOCK_TIMEOUT;
727 * gst_element_add_pad:
728 * @element: element to add pad to
731 * Add a pad (connection point) to the element, setting the parent of the
732 * pad to the element (and thus adding a reference).
735 gst_element_add_pad (GstElement *element, GstPad *pad)
737 g_return_if_fail (element != NULL);
738 g_return_if_fail (GST_IS_ELEMENT (element));
739 g_return_if_fail (pad != NULL);
740 g_return_if_fail (GST_IS_PAD (pad));
742 /* first check to make sure the pad's parent is already set */
743 g_return_if_fail (GST_PAD_PARENT (pad) == NULL);
745 /* then check to see if there's already a pad by that name here */
746 g_return_if_fail (gst_object_check_uniqueness (element->pads, GST_PAD_NAME(pad)) == TRUE);
748 /* set the pad's parent */
749 GST_DEBUG (GST_CAT_ELEMENT_PADS,"setting parent of pad '%s' to '%s'",
750 GST_PAD_NAME (pad), GST_ELEMENT_NAME (element));
751 gst_object_set_parent (GST_OBJECT (pad), GST_OBJECT (element));
753 /* add it to the list */
754 element->pads = g_list_append (element->pads, pad);
756 if (gst_pad_get_direction (pad) == GST_PAD_SRC)
757 element->numsrcpads++;
759 element->numsinkpads++;
761 /* emit the NEW_PAD signal */
762 g_signal_emit (G_OBJECT (element), gst_element_signals[NEW_PAD], 0, pad);
766 * gst_element_remove_pad:
767 * @element: element to remove pad from
768 * @pad: pad to remove
770 * Remove a pad (connection point) from the element,
773 gst_element_remove_pad (GstElement *element, GstPad *pad)
775 g_return_if_fail (element != NULL);
776 g_return_if_fail (GST_IS_ELEMENT (element));
777 g_return_if_fail (pad != NULL);
778 g_return_if_fail (GST_IS_PAD (pad));
780 g_return_if_fail (GST_PAD_PARENT (pad) == element);
782 /* check to see if the pad is still connected */
783 /* FIXME: what if someone calls _remove_pad instead of
784 _remove_ghost_pad? */
785 if (GST_IS_REAL_PAD (pad)) {
786 g_return_if_fail (GST_RPAD_PEER (pad) == NULL);
789 /* remove it from the list */
790 element->pads = g_list_remove (element->pads, pad);
792 if (gst_pad_get_direction (pad) == GST_PAD_SRC)
793 element->numsrcpads--;
795 element->numsinkpads--;
797 g_signal_emit (G_OBJECT (element), gst_element_signals[PAD_REMOVED], 0, pad);
799 gst_object_unparent (GST_OBJECT (pad));
803 * gst_element_add_ghost_pad:
804 * @element: element to add ghost pad to
805 * @pad: pad from which the new ghost pad will be created
806 * @name: name of the new ghost pad
808 * Create a ghost pad from the given pad, and add it to the list of pads
811 * Returns: the added ghost pad or NULL, if no ghost pad was created.
814 gst_element_add_ghost_pad (GstElement *element, GstPad *pad, gchar *name)
818 g_return_val_if_fail (element != NULL, NULL);
819 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
820 g_return_val_if_fail (pad != NULL, NULL);
821 g_return_val_if_fail (GST_IS_PAD (pad), NULL);
823 /* then check to see if there's already a pad by that name here */
824 g_return_val_if_fail (gst_object_check_uniqueness (element->pads, name) == TRUE, NULL);
826 GST_DEBUG(GST_CAT_ELEMENT_PADS,"creating new ghost pad called %s, from pad %s:%s",
827 name,GST_DEBUG_PAD_NAME(pad));
828 ghostpad = gst_ghost_pad_new (name, pad);
830 /* add it to the list */
831 GST_DEBUG(GST_CAT_ELEMENT_PADS,"adding ghost pad %s to element %s",
832 name, GST_ELEMENT_NAME (element));
833 element->pads = g_list_append (element->pads, ghostpad);
835 /* set the parent of the ghostpad */
836 gst_object_set_parent (GST_OBJECT (ghostpad), GST_OBJECT (element));
838 GST_DEBUG(GST_CAT_ELEMENT_PADS,"added ghostpad %s:%s",GST_DEBUG_PAD_NAME(ghostpad));
840 /* emit the NEW_GHOST_PAD signal */
841 g_signal_emit (G_OBJECT (element), gst_element_signals[NEW_PAD], 0, ghostpad);
847 * gst_element_remove_ghost_pad:
848 * @element: element to remove the ghost pad from
849 * @pad: ghost pad to remove
851 * removes a ghost pad from an element
854 gst_element_remove_ghost_pad (GstElement *element, GstPad *pad)
856 g_return_if_fail (element != NULL);
857 g_return_if_fail (GST_IS_ELEMENT (element));
858 g_return_if_fail (pad != NULL);
859 g_return_if_fail (GST_IS_GHOST_PAD (pad));
861 /* FIXME this is redundant?
862 * wingo 10-july-2001: I don't think so, you have to actually remove the pad
863 * from the element. gst_pad_remove_ghost_pad just removes the ghostpad from
864 * the real pad's ghost pad list
866 gst_pad_remove_ghost_pad (GST_PAD (GST_PAD_REALIZE (pad)), pad);
867 gst_element_remove_pad (element, pad);
872 * gst_element_get_pad:
873 * @element: element to find pad of
874 * @name: name of pad to retrieve
876 * Retrieve a pad from the element by name.
878 * Returns: requested pad if found, otherwise NULL.
881 gst_element_get_pad (GstElement *element, const gchar *name)
885 g_return_val_if_fail (element != NULL, NULL);
886 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
887 g_return_val_if_fail (name != NULL, NULL);
889 if ((pad = gst_element_get_static_pad (element, name)))
892 pad = gst_element_get_request_pad (element, name);
898 * gst_element_get_static_pad:
899 * @element: element to find pad of
900 * @name: name of pad to retrieve
902 * Retrieve a pad from the element by name. This version only retrieves
903 * already-existing (i.e. 'static') pads.
905 * Returns: requested pad if found, otherwise NULL.
908 gst_element_get_static_pad (GstElement *element, const gchar *name)
912 g_return_val_if_fail (element != NULL, NULL);
913 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
914 g_return_val_if_fail (name != NULL, NULL);
916 walk = element->pads;
920 pad = GST_PAD(walk->data);
921 if (strcmp (GST_PAD_NAME(pad), name) == 0) {
922 GST_INFO (GST_CAT_ELEMENT_PADS, "found pad %s:%s", GST_DEBUG_PAD_NAME (pad));
925 walk = g_list_next (walk);
928 GST_INFO (GST_CAT_ELEMENT_PADS, "no such pad '%s' in element \"%s\"", name, GST_OBJECT_NAME (element));
933 * gst_element_get_request_pad:
934 * @element: element to find pad of
935 * @name: name of pad to retrieve
937 * Retrieve a pad from the element by name. This version only retrieves
940 * Returns: requested pad if found, otherwise NULL.
943 gst_element_get_request_pad (GstElement *element, const gchar *name)
945 GstPadTemplate *templ = NULL;
947 const gchar *req_name = NULL;
948 gboolean templ_found = FALSE;
952 gchar *str, *endptr = NULL;
954 g_return_val_if_fail (element != NULL, NULL);
955 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
956 g_return_val_if_fail (name != NULL, NULL);
958 if (strstr (name, "%")) {
959 templ = gst_element_get_pad_template (element, name);
964 list = gst_element_get_pad_template_list(element);
965 while (!templ_found && list) {
966 templ = (GstPadTemplate*) list->data;
967 if (templ->presence == GST_PAD_REQUEST) {
968 /* we know that %s and %d are the only possibilities because of sanity
969 checks in gst_pad_template_new */
970 GST_DEBUG (GST_CAT_PADS, "comparing %s to %s", name, templ->name_template);
971 if ((str = strchr (templ->name_template, '%')) &&
972 strncmp (templ->name_template, name, str - templ->name_template) == 0 &&
973 strlen (name) > str - templ->name_template) {
974 data = name + (str - templ->name_template);
975 if (*(str+1) == 'd') {
977 n = (gint) strtol (data, &endptr, 10);
978 if (endptr && *endptr == '\0') {
998 pad = gst_element_request_pad (element, templ, req_name);
1004 * gst_element_get_pad_list:
1005 * @element: element to get pads of
1007 * Retrieve a list of the pads associated with the element.
1009 * Returns: GList of pads
1012 gst_element_get_pad_list (GstElement *element)
1014 g_return_val_if_fail (element != NULL, NULL);
1015 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1017 /* return the list of pads */
1018 return element->pads;
1022 * gst_element_class_add_pad_template:
1023 * @klass: element class to add padtemplate to
1024 * @templ: padtemplate to add
1026 * Add a padtemplate to an element class. This is useful if you have derived a custom
1027 * bin and wish to provide an on-request pad at runtime. Plugin writers should use
1028 * gst_element_factory_add_pad_template instead.
1031 gst_element_class_add_pad_template (GstElementClass *klass, GstPadTemplate *templ)
1033 g_return_if_fail (klass != NULL);
1034 g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
1035 g_return_if_fail (templ != NULL);
1036 g_return_if_fail (GST_IS_PAD_TEMPLATE (templ));
1038 klass->padtemplates = g_list_append (klass->padtemplates, templ);
1039 klass->numpadtemplates++;
1043 * gst_element_get_pad_template_list:
1044 * @element: element to get padtemplates of
1046 * Retrieve a list of the padtemplates associated with the element.
1048 * Returns: GList of padtemplates
1051 gst_element_get_pad_template_list (GstElement *element)
1053 g_return_val_if_fail (element != NULL, NULL);
1054 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1056 return CLASS (element)->padtemplates;
1060 * gst_element_get_pad_template:
1061 * @element: element to get padtemplate of
1062 * @name: the name of the padtemplate to get.
1064 * Retrieve a padtemplate from this element with the
1067 * Returns: the padtemplate with the given name. No unreferencing is necessary.
1070 gst_element_get_pad_template (GstElement *element, const guchar *name)
1074 g_return_val_if_fail (element != NULL, NULL);
1075 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1076 g_return_val_if_fail (name != NULL, NULL);
1078 padlist = gst_element_get_pad_template_list (element);
1081 GstPadTemplate *padtempl = (GstPadTemplate*) padlist->data;
1083 if (!strcmp (padtempl->name_template, name))
1086 padlist = g_list_next (padlist);
1093 * gst_element_get_compatible_pad_template:
1094 * @element: element to get padtemplate of
1095 * @templ: a template to find a compatible template for
1097 * Generate a padtemplate for this element compatible with the given
1098 * template, ie able to link to it.
1100 * Returns: the padtemplate. No unreferencing is necessary.
1103 gst_element_get_compatible_pad_template (GstElement *element, GstPadTemplate *compattempl)
1105 GstPadTemplate *newtempl = NULL;
1108 GST_DEBUG(GST_CAT_ELEMENT_PADS,"gst_element_get_pad_template_by_compatible()");
1110 g_return_val_if_fail (element != NULL, NULL);
1111 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1112 g_return_val_if_fail (compattempl != NULL, NULL);
1114 padlist = gst_element_get_pad_template_list (element);
1117 GstPadTemplate *padtempl = (GstPadTemplate*) padlist->data;
1118 gboolean compat = FALSE;
1122 * Check direction (must be opposite)
1125 GST_DEBUG(GST_CAT_CAPS,"checking direction and caps");
1126 if (padtempl->direction == GST_PAD_SRC &&
1127 compattempl->direction == GST_PAD_SINK) {
1128 GST_DEBUG(GST_CAT_CAPS,"compatible direction: found src pad template");
1129 compat = gst_caps_check_compatibility(GST_PAD_TEMPLATE_CAPS (padtempl),
1130 GST_PAD_TEMPLATE_CAPS (compattempl));
1131 GST_DEBUG(GST_CAT_CAPS,"caps are %scompatible", (compat?"":"not "));
1132 } else if (padtempl->direction == GST_PAD_SINK &&
1133 compattempl->direction == GST_PAD_SRC) {
1134 GST_DEBUG(GST_CAT_CAPS,"compatible direction: found sink pad template");
1135 compat = gst_caps_check_compatibility(GST_PAD_TEMPLATE_CAPS (compattempl),
1136 GST_PAD_TEMPLATE_CAPS (padtempl));
1137 GST_DEBUG(GST_CAT_CAPS,"caps are %scompatible", (compat?"":"not "));
1141 newtempl = padtempl;
1145 padlist = g_list_next (padlist);
1152 * gst_element_request_compatible_pad:
1153 * @element: element to request a new pad from
1154 * @templ: a pad template to which the new pad should be able to connect
1156 * Request a new pad from the element. The template will
1157 * be used to decide what type of pad to create. This function
1158 * is typically used for elements with a padtemplate with presence
1161 * Returns: the new pad that was created.
1164 gst_element_request_compatible_pad (GstElement *element, GstPadTemplate *templ)
1166 GstPadTemplate *templ_new;
1169 g_return_val_if_fail (element != NULL, NULL);
1170 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1171 g_return_val_if_fail (templ != NULL, NULL);
1173 templ_new = gst_element_get_compatible_pad_template (element, templ);
1174 if (templ_new != NULL)
1175 pad = gst_element_request_pad (element, templ_new, NULL);
1182 * gst_element_get_compatible_pad_filtered:
1183 * @element: the element in which the pad should be found
1184 * @pad: the pad to find a compatible one for
1185 * @filtercaps: the caps to use as a filter
1187 * Looks for an unconnected pad to which the given pad can connect to.
1188 * It is not guaranteed that connecting the pads will work, though
1189 * it should work in most cases.
1191 * Returns: the pad to which a connection can be made
1194 gst_element_get_compatible_pad_filtered (GstElement *element, GstPad *pad, GstCaps *filtercaps)
1197 GstPadTemplate *templ;
1199 GstPad *foundpad = NULL;
1202 g_return_val_if_fail (element != NULL, NULL);
1203 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1204 g_return_val_if_fail (pad != NULL, NULL);
1205 g_return_val_if_fail (GST_IS_PAD (pad), NULL);
1207 /* let's use the real pad */
1208 pad = (GstPad *) GST_PAD_REALIZE (pad);
1209 g_return_val_if_fail (pad != NULL, NULL);
1210 g_return_val_if_fail (GST_RPAD_PEER (pad) == NULL, NULL);
1212 /* try to get an existing unconnected pad */
1213 pads = gst_element_get_pad_list (element);
1215 GstPad *current = GST_PAD (pads->data);
1216 if ((GST_PAD_PEER (GST_PAD_REALIZE (current)) == NULL) &&
1217 gst_pad_can_connect_filtered (pad, current, filtercaps)) {
1220 pads = g_list_next (pads);
1223 /* try to create a new one */
1224 /* requesting is a little crazy, we need a template. Let's create one */
1225 if (filtercaps != NULL) {
1226 templcaps = gst_caps_intersect (filtercaps, (GstCaps *) GST_RPAD_CAPS (pad));
1227 if (templcaps == NULL)
1230 templcaps = gst_caps_copy (gst_pad_get_caps (pad));
1233 templ = gst_pad_template_new ((gchar *) GST_PAD_NAME (pad), GST_RPAD_DIRECTION (pad),
1234 GST_PAD_ALWAYS, templcaps, NULL);
1235 foundpad = gst_element_request_compatible_pad (element, templ);
1236 gst_object_unref (GST_OBJECT (templ)); /* this will take care of the caps too */
1238 /* FIXME: this is broken, but it's in here so autoplugging elements that don't
1239 have caps on their source padtemplates (spider) can connect... */
1240 if (!foundpad && !filtercaps) {
1241 templ = gst_pad_template_new ((gchar *) GST_PAD_NAME (pad), GST_RPAD_DIRECTION (pad),
1242 GST_PAD_ALWAYS, NULL, NULL);
1243 foundpad = gst_element_request_compatible_pad (element, templ);
1244 gst_object_unref (GST_OBJECT (templ));
1251 * gst_element_get_compatible_pad:
1252 * @element: the element in which the pad should be found
1253 * @pad: the pad to find a compatible one for
1255 * Looks for an unconnected pad to which the given pad can connect to.
1256 * It is not guaranteed that connecting the pads will work, though
1257 * it should work in most cases.
1259 * Returns: the pad to which a connection can be made
1262 gst_element_get_compatible_pad (GstElement *element, GstPad *pad)
1264 return gst_element_get_compatible_pad_filtered (element, pad, NULL);
1268 * gst_element_connect_filtered:
1269 * @src: the element containing source pad
1270 * @dest: the element containing destination pad
1271 * @filtercaps: the caps to use as filter
1273 * Connect the source to the destination element using the filtercaps.
1274 * The connection must be from source to destination, the other
1275 * direction will not be tried.
1276 * The functions looks for existing pads that aren't connected yet.
1277 + It will use request pads if possible. But both pads will not be requested.
1278 * If multiple connections are possible, only one is established.
1280 * Returns: TRUE if the elements could be connected.
1283 gst_element_connect_filtered (GstElement *src, GstElement *dest,
1284 GstCaps *filtercaps)
1286 GList *srcpads, *destpads, *srctempls, *desttempls, *l;
1287 GstPad *srcpad, *destpad;
1288 GstPadTemplate *srctempl, *desttempl;
1291 g_return_val_if_fail (src != NULL, FALSE);
1292 g_return_val_if_fail (GST_IS_ELEMENT(src), FALSE);
1293 g_return_val_if_fail (dest != NULL, FALSE);
1294 g_return_val_if_fail (GST_IS_ELEMENT(dest), FALSE);
1296 GST_DEBUG (GST_CAT_ELEMENT_PADS, "attempting to connect element %s to element %s", GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (dest));
1298 /* loop through the existing pads in the source */
1299 srcpads = gst_element_get_pad_list (src);
1300 destpads = gst_element_get_pad_list (dest);
1302 if (srcpads || destpads) {
1304 srcpad = (GstPad *) GST_PAD_REALIZE (srcpads->data);
1305 if ((GST_RPAD_DIRECTION (srcpad) == GST_PAD_SRC) &&
1306 (GST_PAD_PEER (srcpad) == NULL)) {
1307 destpad = gst_element_get_compatible_pad_filtered (dest, srcpad, filtercaps);
1308 if (destpad && gst_pad_connect_filtered (srcpad, destpad, filtercaps)) {
1309 GST_DEBUG (GST_CAT_ELEMENT_PADS, "connected pad %s:%s to pad %s:%s", GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad));
1313 srcpads = g_list_next (srcpads);
1316 /* loop through the existing pads in the destination */
1318 destpad = (GstPad *) GST_PAD_REALIZE (destpads->data);
1319 if ((GST_RPAD_DIRECTION (destpad) == GST_PAD_SINK) &&
1320 (GST_PAD_PEER (destpad) == NULL)) {
1321 srcpad = gst_element_get_compatible_pad_filtered (src, destpad, filtercaps);
1322 if (srcpad && gst_pad_connect_filtered (srcpad, destpad, filtercaps)) {
1323 GST_DEBUG (GST_CAT_ELEMENT_PADS, "connected pad %s:%s to pad %s:%s", GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad));
1327 destpads = g_list_next (destpads);
1331 GST_DEBUG (GST_CAT_ELEMENT_PADS, "we might have request pads on both sides, checking...");
1332 srctempls = gst_element_get_pad_template_list (src);
1333 desttempls = gst_element_get_pad_template_list (dest);
1335 if (srctempls && desttempls) {
1337 srctempl = (GstPadTemplate*) srctempls->data;
1338 if (srctempl->presence == GST_PAD_REQUEST) {
1339 for (l=desttempls; l; l=l->next) {
1340 desttempl = (GstPadTemplate*) desttempls->data;
1341 if (desttempl->presence == GST_PAD_REQUEST && desttempl->direction != srctempl->direction) {
1342 if (gst_caps_check_compatibility (gst_pad_template_get_caps (srctempl),
1343 gst_pad_template_get_caps (desttempl))) {
1344 srcpad = gst_element_get_request_pad (src, srctempl->name_template);
1345 destpad = gst_element_get_request_pad (dest, desttempl->name_template);
1346 if (gst_pad_connect_filtered (srcpad, destpad, filtercaps)) {
1347 GST_DEBUG (GST_CAT_ELEMENT_PADS, "connected pad %s:%s to pad %s:%s",
1348 GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad));
1351 /* FIXME: we have extraneous request pads lying around */
1356 srctempls = srctempls->next;
1360 GST_DEBUG (GST_CAT_ELEMENT_PADS, "no connection possible from %s to %s", GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (dest));
1365 * gst_element_connect_many:
1366 * @element_1: the first element in the connection chain
1367 * @element_2: the second element in the connection chain
1368 * @...: NULL-terminated list of elements to connect in order
1370 * Chain together a series of elements. Uses #gst_element_connect.
1372 * Returns: TRUE on success, FALSE otherwise.
1375 gst_element_connect_many (GstElement *element_1, GstElement *element_2, ...)
1379 g_return_val_if_fail (element_1 != NULL && element_2 != NULL, FALSE);
1380 g_return_val_if_fail (GST_IS_ELEMENT (element_1) && GST_IS_ELEMENT (element_2), FALSE);
1382 va_start (args, element_2);
1385 if (!gst_element_connect (element_1, element_2))
1388 element_1 = element_2;
1389 element_2 = va_arg (args, GstElement*);
1398 * gst_element_connect:
1399 * @src: element containing source pad
1400 * @dest: element containing destination pad
1402 * Connect the source to the destination element.
1403 * The connection must be from source to destination, the other
1404 * direction will not be tried.
1405 * The functions looks for existing pads and request pads that aren't
1406 * connected yet. If multiple connections are possible, only one is
1409 * Returns: TRUE if the elements could be connected.
1412 gst_element_connect (GstElement *src, GstElement *dest)
1414 return gst_element_connect_filtered (src, dest, NULL);
1418 * gst_element_connect_pads_filtered:
1419 * @src: element containing source pad
1420 * @srcpadname: name of pad in source element
1421 * @dest: element containing destination pad
1422 * @destpadname: name of pad in destination element
1423 * @filtercaps: the caps to use as a filter
1425 * Connect the two named pads of the source and destination elements.
1426 * Side effect is that if one of the pads has no parent, it becomes a
1427 * child of the parent of the other element. If they have different
1428 * parents, the connection fails.
1430 * Returns: TRUE if the pads could be connected.
1433 gst_element_connect_pads_filtered (GstElement *src, const gchar *srcpadname,
1434 GstElement *dest, const gchar *destpadname,
1435 GstCaps *filtercaps)
1437 GstPad *srcpad,*destpad;
1439 g_return_val_if_fail (src != NULL, FALSE);
1440 g_return_val_if_fail (GST_IS_ELEMENT (src), FALSE);
1441 g_return_val_if_fail (srcpadname != NULL, FALSE);
1442 g_return_val_if_fail (dest != NULL, FALSE);
1443 g_return_val_if_fail (GST_IS_ELEMENT (dest), FALSE);
1444 g_return_val_if_fail (destpadname != NULL, FALSE);
1446 /* obtain the pads requested */
1447 srcpad = gst_element_get_pad (src, srcpadname);
1448 if (srcpad == NULL) {
1449 GST_ERROR (src, "source element has no pad \"%s\"", srcpadname);
1452 destpad = gst_element_get_pad (dest, destpadname);
1453 if (srcpad == NULL) {
1454 GST_ERROR (dest, "destination element has no pad \"%s\"", destpadname);
1458 /* we're satisified they can be connected, let's do it */
1459 return gst_pad_connect_filtered (srcpad, destpad, filtercaps);
1463 * gst_element_connect_pads:
1464 * @src: element containing source pad
1465 * @srcpadname: name of pad in source element
1466 * @dest: element containing destination pad
1467 * @destpadname: name of pad in destination element
1469 * Connect the two named pads of the source and destination elements.
1470 * Side effect is that if one of the pads has no parent, it becomes a
1471 * child of the parent of the other element. If they have different
1472 * parents, the connection fails.
1474 * Returns: TRUE if the pads could be connected.
1477 gst_element_connect_pads (GstElement *src, const gchar *srcpadname,
1478 GstElement *dest, const gchar *destpadname)
1480 return gst_element_connect_pads_filtered (src, srcpadname, dest, destpadname, NULL);
1484 * gst_element_disconnect_pads:
1485 * @src: element containing source pad
1486 * @srcpadname: name of pad in source element
1487 * @dest: element containing destination pad
1488 * @destpadname: name of pad in destination element
1490 * Disconnect the two named pads of the source and destination elements.
1493 gst_element_disconnect_pads (GstElement *src, const gchar *srcpadname,
1494 GstElement *dest, const gchar *destpadname)
1496 GstPad *srcpad,*destpad;
1498 g_return_if_fail (src != NULL);
1499 g_return_if_fail (GST_IS_ELEMENT(src));
1500 g_return_if_fail (srcpadname != NULL);
1501 g_return_if_fail (dest != NULL);
1502 g_return_if_fail (GST_IS_ELEMENT(dest));
1503 g_return_if_fail (destpadname != NULL);
1505 /* obtain the pads requested */
1506 srcpad = gst_element_get_pad (src, srcpadname);
1507 if (srcpad == NULL) {
1508 GST_ERROR(src,"source element has no pad \"%s\"",srcpadname);
1511 destpad = gst_element_get_pad (dest, destpadname);
1512 if (srcpad == NULL) {
1513 GST_ERROR(dest,"destination element has no pad \"%s\"",destpadname);
1517 /* we're satisified they can be disconnected, let's do it */
1518 gst_pad_disconnect(srcpad,destpad);
1522 * gst_element_disconnect_many:
1523 * @element_1: the first element in the connection chain
1524 * @element_2: the second element in the connection chain
1525 * @...: NULL-terminated list of elements to disconnect in order
1527 * Disconnect a series of elements. Uses #gst_element_disconnect.
1530 gst_element_disconnect_many (GstElement *element_1, GstElement *element_2, ...)
1534 g_return_if_fail (element_1 != NULL && element_2 != NULL);
1535 g_return_if_fail (GST_IS_ELEMENT (element_1) && GST_IS_ELEMENT (element_2));
1537 va_start (args, element_2);
1540 gst_element_disconnect (element_1, element_2);
1542 element_1 = element_2;
1543 element_2 = va_arg (args, GstElement*);
1550 * gst_element_disconnect:
1551 * @src: source element
1552 * @dest: sink element
1554 * Disconnect all pads connecting the two elements in the direction src -> dest.
1557 gst_element_disconnect (GstElement *src, GstElement *dest)
1562 g_return_if_fail (GST_IS_ELEMENT(src));
1563 g_return_if_fail (GST_IS_ELEMENT(dest));
1565 srcpads = gst_element_get_pad_list (src);
1568 pad = GST_PAD (srcpads->data);
1570 if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC)
1571 if (GST_OBJECT_PARENT (GST_PAD_PEER (pad)) == (GstObject*) dest)
1572 gst_pad_disconnect (pad, GST_PAD_PEER (pad));
1574 srcpads = g_list_next (srcpads);
1579 gst_element_error_func (GstElement* element, GstElement *source, gchar *errormsg)
1581 /* tell the parent */
1582 if (GST_OBJECT_PARENT (element)) {
1583 GST_DEBUG (GST_CAT_EVENT, "forwarding error \"%s\" from %s to %s", errormsg,
1584 GST_ELEMENT_NAME (element), GST_OBJECT_NAME (GST_OBJECT_PARENT (element)));
1586 gst_object_ref (GST_OBJECT (element));
1587 g_signal_emit (G_OBJECT (GST_OBJECT_PARENT (element)), gst_element_signals[ERROR], 0, source, errormsg);
1588 gst_object_unref (GST_OBJECT (element));
1593 * gst_element_error:
1594 * @element: Element with the error
1595 * @error: A printf-like string describing the error
1596 * @...: optional arguments for the string
1598 * This function is used internally by elements to signal an error
1599 * condition. It results in the "error" signal.
1602 gst_element_error (GstElement *element, const gchar *error, ...)
1608 g_return_if_fail (GST_IS_ELEMENT (element));
1609 g_return_if_fail (element != NULL);
1610 g_return_if_fail (error != NULL);
1612 /* create error message */
1613 va_start (var_args, error);
1614 string = g_strdup_vprintf (error, var_args);
1616 GST_INFO (GST_CAT_EVENT, "ERROR in %s: %s", GST_ELEMENT_NAME (element), string);
1618 /* emit the signal, make sure the element stays available */
1619 gst_object_ref (GST_OBJECT (element));
1620 g_signal_emit (G_OBJECT (element), gst_element_signals[ERROR], 0, element, string);
1622 /* tell the scheduler */
1623 if (element->sched) {
1624 gst_scheduler_error (element->sched, element);
1628 gst_object_unref (GST_OBJECT (element));
1633 * gst_element_get_state:
1634 * @element: a #GstElement to get state of
1636 * Gets the state of the element.
1638 * Returns: The #GstElementState of the element
1641 gst_element_get_state (GstElement *element)
1643 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_VOID_PENDING);
1645 return GST_STATE (element);
1649 * gst_element_wait_state_change:
1650 * @element: a #GstElement to wait for
1652 * Waits and blocks until the element changed its state.
1655 gst_element_wait_state_change (GstElement *element)
1657 g_mutex_lock (element->state_mutex);
1658 g_cond_wait (element->state_cond, element->state_mutex);
1659 g_mutex_unlock (element->state_mutex);
1663 * gst_element_set_state:
1664 * @element: a #GstElement to change state of
1665 * @state: the element's new #GstElementState
1667 * Sets the state of the element. This function will try to set the
1668 * requested state by going through all the intermediary states and calling
1669 * the class's state change function for each.
1671 * Returns: whether or not the state was successfully set
1672 * (using #GstElementStateReturn).
1675 gst_element_set_state (GstElement *element, GstElementState state)
1677 GstElementClass *oclass;
1678 GstElementState curpending;
1679 GstElementStateReturn return_val = GST_STATE_SUCCESS;
1681 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
1683 /* start with the current state */
1684 curpending = GST_STATE(element);
1686 GST_DEBUG_ELEMENT (GST_CAT_STATES, element, "setting state from %s to %s",
1687 gst_element_state_get_name (curpending),
1688 gst_element_state_get_name (state));
1690 /* loop until the final requested state is set */
1691 while (GST_STATE (element) != state
1692 && GST_STATE (element) != GST_STATE_VOID_PENDING) {
1693 /* move the curpending state in the correct direction */
1694 if (curpending < state)
1699 /* set the pending state variable */
1700 /* FIXME: should probably check to see that we don't already have one */
1701 GST_STATE_PENDING (element) = curpending;
1703 if (curpending != state) {
1704 GST_DEBUG_ELEMENT (GST_CAT_STATES, element,
1705 "intermediate: setting state from %s to %s",
1706 gst_element_state_get_name (GST_STATE (element)),
1707 gst_element_state_get_name (curpending));
1710 /* call the state change function so it can set the state */
1711 oclass = CLASS (element);
1712 if (oclass->change_state)
1713 return_val = (oclass->change_state) (element);
1715 switch (return_val) {
1716 case GST_STATE_FAILURE:
1717 GST_DEBUG_ELEMENT (GST_CAT_STATES, element, "have failed change_state return");
1719 case GST_STATE_ASYNC:
1720 GST_DEBUG_ELEMENT (GST_CAT_STATES, element, "element will change state async");
1722 case GST_STATE_SUCCESS:
1723 /* Last thing we do is verify that a successful state change really
1724 * did change the state... */
1725 if (GST_STATE (element) != curpending) {
1726 GST_DEBUG_ELEMENT (GST_CAT_STATES, element,
1727 "element claimed state-change success, but state didn't change %s, %s <-> %s",
1728 gst_element_state_get_name (GST_STATE (element)),
1729 gst_element_state_get_name (GST_STATE_PENDING (element)),
1730 gst_element_state_get_name (curpending));
1731 return GST_STATE_FAILURE;
1735 /* somebody added a GST_STATE_ and forgot to do stuff here ! */
1736 g_assert_not_reached ();
1745 gst_element_negotiate_pads (GstElement *element)
1747 GList *pads = GST_ELEMENT_PADS (element);
1749 GST_DEBUG_ELEMENT (GST_CAT_CAPS, element, "negotiating pads");
1752 GstPad *pad = GST_PAD (pads->data);
1755 pads = g_list_next (pads);
1757 if (!GST_IS_REAL_PAD (pad))
1760 srcpad = GST_PAD_REALIZE (pad);
1762 /* if we have a connection on this pad and it doesn't have caps
1763 * allready, try to negotiate */
1764 if (GST_PAD_IS_CONNECTED (srcpad) && !GST_PAD_CAPS (srcpad)) {
1765 GstRealPad *sinkpad;
1766 GstElementState otherstate;
1769 sinkpad = GST_RPAD_PEER (GST_PAD_REALIZE (srcpad));
1771 /* check the parent of the peer pad, if there is no parent do nothing */
1772 parent = GST_PAD_PARENT (sinkpad);
1776 otherstate = GST_STATE (parent);
1778 /* swap pads if needed */
1779 if (!GST_PAD_IS_SRC (srcpad)) {
1787 /* only try to negotiate if the peer element is in PAUSED or higher too */
1788 if (otherstate >= GST_STATE_READY) {
1789 GST_DEBUG_ELEMENT (GST_CAT_CAPS, element, "perform negotiate for %s:%s and %s:%s",
1790 GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
1791 if (!gst_pad_perform_negotiate (GST_PAD (srcpad), GST_PAD (sinkpad)))
1795 GST_DEBUG_ELEMENT (GST_CAT_CAPS, element, "not negotiatiating %s:%s and %s:%s, not in READY yet",
1796 GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
1805 gst_element_clear_pad_caps (GstElement *element)
1807 GList *pads = GST_ELEMENT_PADS (element);
1809 GST_DEBUG_ELEMENT (GST_CAT_CAPS, element, "clearing pad caps");
1812 GstRealPad *pad = GST_PAD_REALIZE (pads->data);
1814 if (GST_PAD_CAPS (pad)) {
1815 GST_PAD_CAPS (pad) = NULL;
1817 pads = g_list_next (pads);
1821 static GstElementStateReturn
1822 gst_element_change_state (GstElement *element)
1824 GstElementState old_state;
1826 gint old_pending, old_transition;
1828 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
1830 old_state = GST_STATE (element);
1831 old_pending = GST_STATE_PENDING (element);
1832 old_transition = GST_STATE_TRANSITION (element);
1834 if (old_pending == GST_STATE_VOID_PENDING || old_state == GST_STATE_PENDING (element)) {
1835 GST_INFO (GST_CAT_STATES, "no state change needed for element %s (VOID_PENDING)", GST_ELEMENT_NAME (element));
1836 return GST_STATE_SUCCESS;
1839 GST_INFO (GST_CAT_STATES, "%s default handler sets state from %s to %s %d", GST_ELEMENT_NAME (element),
1840 gst_element_state_get_name (old_state),
1841 gst_element_state_get_name (old_pending),
1842 GST_STATE_TRANSITION (element));
1844 /* we set the state change early for the negotiation functions */
1845 GST_STATE (element) = old_pending;
1846 GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING;
1848 /* if we are going to paused, we try to negotiate the pads */
1849 if (old_transition == GST_STATE_NULL_TO_READY) {
1850 if (!gst_element_negotiate_pads (element))
1853 /* going to the READY state clears all pad caps */
1854 else if (old_transition == GST_STATE_READY_TO_NULL) {
1855 gst_element_clear_pad_caps (element);
1858 /* tell the scheduler if we have one */
1859 if (element->sched) {
1860 if (gst_scheduler_state_transition (element->sched, element, old_transition)
1861 != GST_STATE_SUCCESS) {
1866 parent = GST_ELEMENT_PARENT (element);
1868 /* tell our parent about the state change */
1869 if (parent && GST_IS_BIN (parent)) {
1870 gst_bin_child_state_change (GST_BIN (parent), old_state, GST_STATE (element), element);
1873 g_signal_emit (G_OBJECT (element), gst_element_signals[STATE_CHANGE],
1874 0, old_state, GST_STATE (element));
1876 /* signal the state change in case somebody is waiting for us */
1877 g_mutex_lock (element->state_mutex);
1878 g_cond_signal (element->state_cond);
1879 g_mutex_unlock (element->state_mutex);
1881 return GST_STATE_SUCCESS;
1884 /* undo the state change */
1885 GST_STATE (element) = old_state;
1886 GST_STATE_PENDING (element) = old_pending;
1888 return GST_STATE_FAILURE;
1892 * gst_element_get_factory:
1893 * @element: element to request the factory
1895 * Retrieves the factory that was used to create this element
1897 * Returns: the factory used for creating this element
1900 gst_element_get_factory (GstElement *element)
1902 GstElementClass *oclass;
1904 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1906 oclass = CLASS (element);
1908 return oclass->elementfactory;
1912 gst_element_dispose (GObject *object)
1914 GstElement *element = GST_ELEMENT (object);
1918 GST_DEBUG_ELEMENT (GST_CAT_REFCOUNTING, element, "dispose");
1920 gst_element_set_state (element, GST_STATE_NULL);
1922 /* first we break all our connections with the ouside */
1923 if (element->pads) {
1925 orig = pads = g_list_copy (element->pads);
1927 pad = GST_PAD (pads->data);
1929 if (GST_PAD_PEER (pad)) {
1930 GST_DEBUG (GST_CAT_REFCOUNTING, "disconnecting pad '%s'",
1931 GST_OBJECT_NAME (GST_OBJECT (GST_PAD (GST_PAD_PEER (pad)))));
1932 gst_pad_disconnect (pad, GST_PAD (GST_PAD_PEER (pad)));
1934 gst_element_remove_pad (element, pad);
1936 pads = g_list_next (pads);
1939 g_list_free (element->pads);
1940 element->pads = NULL;
1943 element->numsrcpads = 0;
1944 element->numsinkpads = 0;
1945 element->numpads = 0;
1946 g_mutex_free (element->state_mutex);
1947 g_cond_free (element->state_cond);
1949 if (element->prop_value_queue)
1950 g_async_queue_unref (element->prop_value_queue);
1951 element->prop_value_queue = NULL;
1952 if (element->property_mutex)
1953 g_mutex_free (element->property_mutex);
1955 G_OBJECT_CLASS (parent_class)->dispose (object);
1958 #ifndef GST_DISABLE_LOADSAVE
1960 * gst_element_save_thyself:
1961 * @element: GstElement to save
1962 * @parent: the xml parent node
1964 * Saves the element as part of the given XML structure
1966 * Returns: the new xml node
1969 gst_element_save_thyself (GstObject *object,
1973 GstElementClass *oclass;
1974 GParamSpec **specs, *spec;
1976 GValue value = { 0, };
1977 GstElement *element;
1979 g_return_val_if_fail (GST_IS_ELEMENT (object), parent);
1981 element = GST_ELEMENT (object);
1983 oclass = CLASS (element);
1985 xmlNewChild(parent, NULL, "name", GST_ELEMENT_NAME(element));
1987 if (oclass->elementfactory != NULL) {
1988 GstElementFactory *factory = (GstElementFactory *)oclass->elementfactory;
1990 xmlNewChild (parent, NULL, "type", GST_OBJECT_NAME (factory));
1991 xmlNewChild (parent, NULL, "version", factory->details->version);
1994 /* FIXME: what is this? */
1995 /* if (element->manager) */
1996 /* xmlNewChild(parent, NULL, "manager", GST_ELEMENT_NAME(element->manager)); */
1999 specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (object), &nspecs);
2001 for (i=0; i<nspecs; i++) {
2003 if (spec->flags & G_PARAM_READABLE) {
2006 g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE (spec));
2008 g_object_get_property (G_OBJECT (element), spec->name, &value);
2009 param = xmlNewChild (parent, NULL, "param", NULL);
2010 xmlNewChild (param, NULL, "name", spec->name);
2012 if (G_IS_PARAM_SPEC_STRING (spec))
2013 xmlNewChild (param, NULL, "value", g_value_dup_string (&value));
2014 else if (G_IS_PARAM_SPEC_ENUM (spec))
2015 xmlNewChild (param, NULL, "value", g_strdup_printf ("%d", g_value_get_enum (&value)));
2016 else if (G_IS_PARAM_SPEC_INT64 (spec))
2017 xmlNewChild (param, NULL, "value", g_strdup_printf ("%lld", g_value_get_int64 (&value)));
2019 xmlNewChild (param, NULL, "value", g_strdup_value_contents (&value));
2021 g_value_unset(&value);
2025 pads = GST_ELEMENT_PADS (element);
2028 GstPad *pad = GST_PAD (pads->data);
2029 /* figure out if it's a direct pad or a ghostpad */
2030 if (GST_ELEMENT (GST_OBJECT_PARENT (pad)) == element) {
2031 xmlNodePtr padtag = xmlNewChild (parent, NULL, "pad", NULL);
2032 gst_object_save_thyself (GST_OBJECT (pad), padtag);
2034 pads = g_list_next (pads);
2041 gst_element_restore_thyself (GstObject *object, xmlNodePtr self)
2043 xmlNodePtr children;
2044 GstElement *element;
2045 guchar *name = NULL;
2046 guchar *value = NULL;
2048 element = GST_ELEMENT (object);
2049 g_return_if_fail (element != NULL);
2052 children = self->xmlChildrenNode;
2054 if (!strcmp (children->name, "param")) {
2055 xmlNodePtr child = children->xmlChildrenNode;
2058 if (!strcmp (child->name, "name")) {
2059 name = xmlNodeGetContent (child);
2061 else if (!strcmp (child->name, "value")) {
2062 value = xmlNodeGetContent (child);
2064 child = child->next;
2066 /* FIXME: can this just be g_object_set ? */
2067 gst_util_set_object_arg ((GObject *)G_OBJECT (element), name, value);
2069 children = children->next;
2073 children = self->xmlChildrenNode;
2075 if (!strcmp (children->name, "pad")) {
2076 gst_pad_load_and_connect (children, GST_OBJECT (element));
2078 children = children->next;
2081 if (GST_OBJECT_CLASS(parent_class)->restore_thyself)
2082 (GST_OBJECT_CLASS(parent_class)->restore_thyself) (object, self);
2084 #endif /* GST_DISABLE_LOADSAVE */
2087 * gst_element_yield:
2088 * @element: Element to yield
2090 * Request a yield operation for the child. The scheduler will typically
2091 * give control to another element.
2094 gst_element_yield (GstElement *element)
2096 if (GST_ELEMENT_SCHED (element)) {
2097 gst_scheduler_yield (GST_ELEMENT_SCHED (element), element);
2102 * gst_element_interrupt:
2103 * @element: Element to interrupt
2105 * Request the scheduler of this element to interrupt the execution of
2106 * this element and scheduler another one.
2108 * Returns: a boolean indicating that the child should exit its chain/loop/get
2109 * function ASAP, depending on the scheduler implementation.
2112 gst_element_interrupt (GstElement *element)
2114 if (GST_ELEMENT_SCHED (element)) {
2115 return gst_scheduler_interrupt (GST_ELEMENT_SCHED (element), element);
2122 * gst_element_set_scheduler:
2123 * @element: Element to set manager of.
2124 * @sched: @GstScheduler to set.
2126 * Sets the scheduler of the element. For internal use only, unless you're
2127 * writing a new bin subclass.
2130 gst_element_set_scheduler (GstElement *element,
2131 GstScheduler *sched)
2133 g_return_if_fail (GST_IS_ELEMENT (element));
2135 GST_INFO_ELEMENT (GST_CAT_PARENTAGE, element, "setting scheduler to %p", sched);
2137 element->sched = sched;
2141 * gst_element_get_scheduler:
2142 * @element: Element to get manager of.
2144 * Returns the scheduler of the element.
2146 * Returns: Element's scheduler
2149 gst_element_get_scheduler (GstElement *element)
2151 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
2153 return element->sched;
2157 * gst_element_set_loop_function:
2158 * @element: Element to set loop function of.
2159 * @loop: Pointer to loop function.
2161 * This sets the loop function for the element. The function pointed to
2162 * can deviate from the GstElementLoopFunction definition in type of
2165 * NOTE: in order for this to take effect, the current loop function *must*
2166 * exit. Assuming the loop function itself is the only one who will cause
2167 * a new loopfunc to be assigned, this should be no problem.
2170 gst_element_set_loop_function (GstElement *element,
2171 GstElementLoopFunction loop)
2173 g_return_if_fail (GST_IS_ELEMENT (element));
2175 /* set the loop function */
2176 element->loopfunc = loop;
2178 /* set the NEW_LOOPFUNC flag so everyone knows to go try again */
2179 GST_FLAG_SET (element, GST_ELEMENT_NEW_LOOPFUNC);
2183 * gst_element_set_eos:
2184 * @element: element to set to the EOS state
2186 * Perform the actions needed to bring the element in the EOS state.
2189 gst_element_set_eos (GstElement *element)
2191 g_return_if_fail (GST_IS_ELEMENT (element));
2193 GST_DEBUG (GST_CAT_EVENT, "setting EOS on element %s", GST_OBJECT_NAME (element));
2195 gst_element_set_state (element, GST_STATE_PAUSED);
2197 g_signal_emit (G_OBJECT (element), gst_element_signals[EOS], 0);
2202 * gst_element_state_get_name:
2203 * @state: a #GstElementState to get the name of
2205 * Gets a string representing the given state.
2207 * Returns: a string with the statename.
2210 gst_element_state_get_name (GstElementState state)
2213 #ifdef GST_DEBUG_COLOR
2214 case GST_STATE_VOID_PENDING: return "NONE_PENDING";break;
2215 case GST_STATE_NULL: return "\033[01;37mNULL\033[00m";break;
2216 case GST_STATE_READY: return "\033[01;31mREADY\033[00m";break;
2217 case GST_STATE_PLAYING: return "\033[01;32mPLAYING\033[00m";break;
2218 case GST_STATE_PAUSED: return "\033[01;33mPAUSED\033[00m";break;
2219 default: return g_strdup_printf ("\033[01;37;41mUNKNOWN!\033[00m(%d)", state);
2221 case GST_STATE_VOID_PENDING: return "NONE_PENDING";break;
2222 case GST_STATE_NULL: return "NULL";break;
2223 case GST_STATE_READY: return "READY";break;
2224 case GST_STATE_PLAYING: return "PLAYING";break;
2225 case GST_STATE_PAUSED: return "PAUSED";break;
2226 default: return "UNKNOWN!";
2233 gst_element_populate_std_props (GObjectClass * klass,
2234 const gchar *prop_name, guint arg_id, GParamFlags flags)
2236 GQuark prop_id = g_quark_from_string (prop_name);
2239 static GQuark fd_id = 0;
2240 static GQuark blocksize_id;
2241 static GQuark bytesperread_id;
2242 static GQuark dump_id;
2243 static GQuark filesize_id;
2244 static GQuark mmapsize_id;
2245 static GQuark location_id;
2246 static GQuark offset_id;
2247 static GQuark silent_id;
2248 static GQuark touch_id;
2251 fd_id = g_quark_from_static_string ("fd");
2252 blocksize_id = g_quark_from_static_string ("blocksize");
2253 bytesperread_id = g_quark_from_static_string ("bytesperread");
2254 dump_id = g_quark_from_static_string ("dump");
2255 filesize_id = g_quark_from_static_string ("filesize");
2256 mmapsize_id = g_quark_from_static_string ("mmapsize");
2257 location_id = g_quark_from_static_string ("location");
2258 offset_id = g_quark_from_static_string ("offset");
2259 silent_id = g_quark_from_static_string ("silent");
2260 touch_id = g_quark_from_static_string ("touch");
2263 if (prop_id == fd_id) {
2264 pspec = g_param_spec_int ("fd", "File-descriptor",
2265 "File-descriptor for the file being read",
2266 0, G_MAXINT, 0, flags);
2268 else if (prop_id == blocksize_id) {
2269 pspec = g_param_spec_ulong ("blocksize", "Block Size",
2270 "Block size to read per buffer",
2271 0, G_MAXULONG, 4096, flags);
2274 else if (prop_id == bytesperread_id) {
2275 pspec = g_param_spec_int ("bytesperread", "Bytes per read",
2276 "Number of bytes to read per buffer",
2277 G_MININT, G_MAXINT, 0, flags);
2280 else if (prop_id == dump_id) {
2281 pspec = g_param_spec_boolean ("dump", "Dump", "Dump bytes to stdout", FALSE, flags);
2284 else if (prop_id == filesize_id) {
2285 pspec = g_param_spec_int64 ("filesize", "File Size",
2286 "Size of the file being read",
2287 0, G_MAXINT64, 0, flags);
2290 else if (prop_id == mmapsize_id) {
2291 pspec = g_param_spec_ulong ("mmapsize", "mmap() Block Size",
2292 "Size in bytes of mmap()d regions",
2293 0, G_MAXULONG, 4 * 1048576, flags);
2296 else if (prop_id == location_id) {
2297 pspec = g_param_spec_string ("location", "File Location",
2298 "Location of the file to read",
2302 else if (prop_id == offset_id) {
2303 pspec = g_param_spec_int64 ("offset", "File Offset",
2304 "Byte offset of current read pointer",
2305 0, G_MAXINT64, 0, flags);
2308 else if (prop_id == silent_id) {
2309 pspec = g_param_spec_boolean ("silent", "Silent", "Don't produce events",
2313 else if (prop_id == touch_id) {
2314 pspec = g_param_spec_boolean ("touch", "Touch read data",
2315 "Touch data to force disk read before "
2316 "push ()", TRUE, flags);
2319 g_warning ("Unknown - 'standard' property '%s' id %d from klass %s",
2320 prop_name, arg_id, g_type_name (G_OBJECT_CLASS_TYPE (klass)));
2325 g_object_class_install_property (klass, arg_id, pspec);
2330 * gst_element_class_install_std_props:
2331 * @klass: the class to add the properties to
2332 * @first_name: the first in a NULL terminated
2333 * 'name', 'id', 'flags' triplet list.
2334 * @...: the triplet list
2336 * Add a list of standardized properties with types to the @klass.
2337 * the id is for the property switch in your get_prop method, and
2338 * the flags determine readability / writeability.
2341 gst_element_class_install_std_props (GstElementClass * klass, const gchar *first_name, ...)
2347 g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
2349 va_start (args, first_name);
2354 int arg_id = va_arg (args, int);
2355 int flags = va_arg (args, int);
2357 gst_element_populate_std_props ((GObjectClass *) klass, name, arg_id, flags);
2359 name = va_arg (args, char *);
2366 * gst_element_get_managing_bin:
2367 * @element: a #GstElement
2369 * Gets the managing bin (a pipeline or a thread, for example) of an element.
2371 * Returns: the #GstBin, or NULL on failure
2374 gst_element_get_managing_bin (GstElement *element)
2378 g_return_val_if_fail (element != NULL, NULL);
2380 bin = GST_BIN (gst_object_get_parent (GST_OBJECT_CAST (element)));
2382 while (bin && !GST_FLAG_IS_SET (GST_OBJECT_CAST (bin), GST_BIN_FLAG_MANAGER))
2383 bin = GST_BIN (gst_object_get_parent (GST_OBJECT_CAST (bin)));