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 gboolean gst_element_send_event_default (GstElement *element, GstEvent *event);
67 static gboolean gst_element_query_default (GstElement *element, GstPadQueryType type,
68 GstFormat *format, gint64 *value);
70 static GstElementStateReturn gst_element_change_state (GstElement *element);
71 static void gst_element_error_func (GstElement* element, GstElement *source, gchar *errormsg);
73 #ifndef GST_DISABLE_LOADSAVE
74 static xmlNodePtr gst_element_save_thyself (GstObject *object, xmlNodePtr parent);
75 static void gst_element_restore_thyself (GstObject *parent, xmlNodePtr self);
78 GType _gst_element_type = 0;
80 static GstObjectClass *parent_class = NULL;
81 static guint gst_element_signals[LAST_SIGNAL] = { 0 };
83 GType gst_element_get_type (void)
85 if (!_gst_element_type) {
86 static const GTypeInfo element_info = {
87 sizeof(GstElementClass),
88 (GBaseInitFunc)gst_element_base_class_init,
90 (GClassInitFunc)gst_element_class_init,
95 (GInstanceInitFunc)gst_element_init,
98 _gst_element_type = g_type_register_static(GST_TYPE_OBJECT, "GstElement",
99 &element_info, G_TYPE_FLAG_ABSTRACT);
101 return _gst_element_type;
105 gst_element_class_init (GstElementClass *klass)
107 GObjectClass *gobject_class;
108 GstObjectClass *gstobject_class;
110 gobject_class = (GObjectClass*) klass;
111 gstobject_class = (GstObjectClass*) klass;
113 parent_class = g_type_class_ref(GST_TYPE_OBJECT);
115 gst_element_signals[STATE_CHANGE] =
116 g_signal_new ("state_change", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
117 G_STRUCT_OFFSET (GstElementClass, state_change), NULL, NULL,
118 gst_marshal_VOID__INT_INT, G_TYPE_NONE, 2,
119 G_TYPE_INT, G_TYPE_INT);
120 gst_element_signals[NEW_PAD] =
121 g_signal_new ("new_pad", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
122 G_STRUCT_OFFSET (GstElementClass, new_pad), NULL, NULL,
123 gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
125 gst_element_signals[PAD_REMOVED] =
126 g_signal_new ("pad_removed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
127 G_STRUCT_OFFSET (GstElementClass, pad_removed), NULL, NULL,
128 gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
130 gst_element_signals[ERROR] =
131 g_signal_new ("error", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
132 G_STRUCT_OFFSET (GstElementClass, error), NULL, NULL,
133 gst_marshal_VOID__OBJECT_STRING, G_TYPE_NONE, 2,
134 G_TYPE_OBJECT, G_TYPE_STRING);
135 gst_element_signals[EOS] =
136 g_signal_new ("eos", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
137 G_STRUCT_OFFSET (GstElementClass,eos), NULL, NULL,
138 gst_marshal_VOID__VOID, G_TYPE_NONE, 0);
139 gst_element_signals[DEEP_NOTIFY] =
140 g_signal_new ("deep_notify", G_TYPE_FROM_CLASS (klass),
141 G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_DETAILED | G_SIGNAL_NO_HOOKS,
142 G_STRUCT_OFFSET (GstElementClass, deep_notify), NULL, NULL,
143 gst_marshal_VOID__OBJECT_PARAM, G_TYPE_NONE,
144 2, G_TYPE_OBJECT, G_TYPE_PARAM);
147 gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_element_real_set_property);
148 gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_element_real_get_property);
150 /* see the comments at gst_element_dispatch_properties_changed */
151 gobject_class->dispatch_properties_changed
152 = GST_DEBUG_FUNCPTR (gst_element_dispatch_properties_changed);
154 gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_element_dispose);
156 #ifndef GST_DISABLE_LOADSAVE
157 gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_element_save_thyself);
158 gstobject_class->restore_thyself = GST_DEBUG_FUNCPTR (gst_element_restore_thyself);
161 klass->change_state = GST_DEBUG_FUNCPTR (gst_element_change_state);
162 klass->error = GST_DEBUG_FUNCPTR (gst_element_error_func);
163 klass->elementfactory = NULL;
164 klass->padtemplates = NULL;
165 klass->numpadtemplates = 0;
166 klass->send_event = GST_DEBUG_FUNCPTR (gst_element_send_event_default);
167 klass->query = GST_DEBUG_FUNCPTR (gst_element_query_default);
171 gst_element_base_class_init (GstElementClass *klass)
173 GObjectClass *gobject_class;
175 gobject_class = (GObjectClass*) klass;
177 gobject_class->set_property = GST_DEBUG_FUNCPTR(gst_element_real_set_property);
178 gobject_class->get_property = GST_DEBUG_FUNCPTR(gst_element_real_get_property);
182 gst_element_init (GstElement *element)
184 element->current_state = GST_STATE_NULL;
185 element->pending_state = GST_STATE_VOID_PENDING;
186 element->numpads = 0;
187 element->numsrcpads = 0;
188 element->numsinkpads = 0;
189 element->pads = NULL;
190 element->loopfunc = NULL;
191 element->sched = NULL;
192 element->clock = NULL;
193 element->sched_private = NULL;
194 element->state_mutex = g_mutex_new ();
195 element->state_cond = g_cond_new ();
199 gst_element_real_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
201 GstElementClass *oclass = CLASS (object);
203 if (oclass->set_property)
204 (oclass->set_property) (object, prop_id, value, pspec);
208 gst_element_real_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
210 GstElementClass *oclass = CLASS (object);
212 if (oclass->get_property)
213 (oclass->get_property) (object, prop_id, value, pspec);
216 /* Changing a GObject property of an element will result in "deep_notify"
217 * signals being emitted by the element itself, as well as in each parent
218 * element. This is so that an application can connect a listener to the
219 * top-level bin to catch property-change notifications for all contained
222 gst_element_dispatch_properties_changed (GObject *object,
226 GstObject *gst_object;
229 /* do the standard dispatching */
230 G_OBJECT_CLASS (parent_class)->dispatch_properties_changed (object, n_pspecs, pspecs);
232 /* now let the parent dispatch those, too */
233 gst_object = GST_OBJECT_PARENT (object);
235 /* need own category? */
236 for (i = 0; i < n_pspecs; i++) {
237 GST_DEBUG (GST_CAT_EVENT, "deep notification from %s to %s (%s)", GST_OBJECT_NAME (object),
238 GST_OBJECT_NAME (gst_object), pspecs[i]->name);
239 g_signal_emit (gst_object, gst_element_signals[DEEP_NOTIFY], g_quark_from_string (pspecs[i]->name),
240 (GstObject *) object, pspecs[i]);
243 gst_object = GST_OBJECT_PARENT (gst_object);
248 const GParamSpec *pspec;
253 element_set_property (GstElement *element, const GParamSpec *pspec, const GValue *value)
255 prop_value_t *prop_value = g_new0 (prop_value_t, 1);
257 prop_value->pspec = pspec;
258 prop_value->value = value;
260 g_async_queue_push (element->prop_value_queue, prop_value);
264 element_get_property (GstElement *element, const GParamSpec *pspec, GValue *value)
266 g_mutex_lock (element->property_mutex);
267 g_object_get_property ((GObject*)element, pspec->name, value);
268 g_mutex_unlock (element->property_mutex);
272 gst_element_threadsafe_properties_pre_run (GstElement *element)
274 GST_DEBUG (GST_CAT_THREAD, "locking element %s", GST_OBJECT_NAME (element));
275 g_mutex_lock (element->property_mutex);
276 gst_element_set_pending_properties (element);
280 gst_element_threadsafe_properties_post_run (GstElement *element)
282 GST_DEBUG (GST_CAT_THREAD, "unlocking element %s", GST_OBJECT_NAME (element));
283 g_mutex_unlock (element->property_mutex);
287 gst_element_enable_threadsafe_properties (GstElement *element)
289 g_return_if_fail (GST_IS_ELEMENT (element));
291 GST_FLAG_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES);
292 element->pre_run_func = gst_element_threadsafe_properties_pre_run;
293 element->post_run_func = gst_element_threadsafe_properties_post_run;
294 if (!element->prop_value_queue)
295 element->prop_value_queue = g_async_queue_new ();
296 if (!element->property_mutex)
297 element->property_mutex = g_mutex_new ();
301 gst_element_disable_threadsafe_properties (GstElement *element)
303 g_return_if_fail (GST_IS_ELEMENT (element));
305 GST_FLAG_UNSET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES);
306 element->pre_run_func = NULL;
307 element->post_run_func = NULL;
308 /* let's keep around that async queue */
312 gst_element_set_pending_properties (GstElement *element)
314 prop_value_t *prop_value;
316 while ((prop_value = g_async_queue_try_pop (element->prop_value_queue))) {
317 g_object_set_property ((GObject*)element, prop_value->pspec->name, prop_value->value);
322 /* following 6 functions taken mostly from gobject.c */
325 gst_element_set (GstElement *element, const gchar *first_property_name, ...)
329 g_return_if_fail (GST_IS_ELEMENT (element));
331 va_start (var_args, first_property_name);
332 gst_element_set_valist (element, first_property_name, var_args);
337 gst_element_get (GstElement *element, const gchar *first_property_name, ...)
341 g_return_if_fail (GST_IS_ELEMENT (element));
343 va_start (var_args, first_property_name);
344 gst_element_get_valist (element, first_property_name, var_args);
349 gst_element_set_valist (GstElement *element, const gchar *first_property_name, va_list var_args)
354 g_return_if_fail (GST_IS_ELEMENT (element));
356 object = (GObject*)element;
358 if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
359 g_object_set_valist (object, first_property_name, var_args);
363 g_object_ref (object);
365 name = first_property_name;
369 GValue value = { 0, };
373 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), name);
377 g_warning ("%s: object class `%s' has no property named `%s'",
379 G_OBJECT_TYPE_NAME (object),
383 if (!(pspec->flags & G_PARAM_WRITABLE))
385 g_warning ("%s: property `%s' of object class `%s' is not writable",
388 G_OBJECT_TYPE_NAME (object));
392 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
394 G_VALUE_COLLECT (&value, var_args, 0, &error);
397 g_warning ("%s: %s", G_STRLOC, error);
400 /* we purposely leak the value here, it might not be
401 * in a sane state if an error condition occoured
406 element_set_property (element, pspec, &value);
407 g_value_unset (&value);
409 name = va_arg (var_args, gchar*);
412 g_object_unref (object);
416 gst_element_get_valist (GstElement *element, const gchar *first_property_name, va_list var_args)
421 g_return_if_fail (GST_IS_ELEMENT (element));
423 object = (GObject*)element;
425 if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
426 g_object_get_valist (object, first_property_name, var_args);
430 g_object_ref (object);
432 name = first_property_name;
436 GValue value = { 0, };
440 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), name);
444 g_warning ("%s: object class `%s' has no property named `%s'",
446 G_OBJECT_TYPE_NAME (object),
450 if (!(pspec->flags & G_PARAM_READABLE))
452 g_warning ("%s: property `%s' of object class `%s' is not readable",
455 G_OBJECT_TYPE_NAME (object));
459 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
461 element_get_property (element, pspec, &value);
463 G_VALUE_LCOPY (&value, var_args, 0, &error);
466 g_warning ("%s: %s", G_STRLOC, error);
468 g_value_unset (&value);
472 g_value_unset (&value);
474 name = va_arg (var_args, gchar*);
477 g_object_unref (object);
481 gst_element_set_property (GstElement *element, const gchar *property_name, const GValue *value)
486 g_return_if_fail (GST_IS_ELEMENT (element));
487 g_return_if_fail (property_name != NULL);
488 g_return_if_fail (G_IS_VALUE (value));
490 object = (GObject*)element;
492 if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
493 g_object_set_property (object, property_name, value);
497 g_object_ref (object);
499 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), property_name);
502 g_warning ("%s: object class `%s' has no property named `%s'",
504 G_OBJECT_TYPE_NAME (object),
507 element_set_property (element, pspec, value);
509 g_object_unref (object);
513 gst_element_get_property (GstElement *element, const gchar *property_name, GValue *value)
518 g_return_if_fail (GST_IS_ELEMENT (element));
519 g_return_if_fail (property_name != NULL);
520 g_return_if_fail (G_IS_VALUE (value));
522 object = (GObject*)element;
524 if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
525 g_object_get_property (object, property_name, value);
529 g_object_ref (object);
531 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), property_name);
534 g_warning ("%s: object class `%s' has no property named `%s'",
536 G_OBJECT_TYPE_NAME (object),
540 GValue *prop_value, tmp_value = { 0, };
542 /* auto-conversion of the callers value type
544 if (G_VALUE_TYPE (value) == G_PARAM_SPEC_VALUE_TYPE (pspec))
546 g_value_reset (value);
549 else if (!g_value_type_transformable (G_PARAM_SPEC_VALUE_TYPE (pspec), G_VALUE_TYPE (value)))
551 g_warning ("can't retrieve property `%s' of type `%s' as value of type `%s'",
553 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
554 G_VALUE_TYPE_NAME (value));
555 g_object_unref (object);
560 g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
561 prop_value = &tmp_value;
563 element_get_property (element, pspec, prop_value);
564 if (prop_value != value)
566 g_value_transform (prop_value, value);
567 g_value_unset (&tmp_value);
571 g_object_unref (object);
575 gst_element_request_pad (GstElement *element, GstPadTemplate *templ, const gchar* name)
577 GstPad *newpad = NULL;
578 GstElementClass *oclass;
580 oclass = CLASS (element);
581 if (oclass->request_new_pad)
582 newpad = (oclass->request_new_pad)(element, templ, name);
588 gst_element_release_request_pad (GstElement *element, GstPad *pad)
590 GstElementClass *oclass;
592 g_return_if_fail (GST_IS_ELEMENT (element));
593 g_return_if_fail (GST_IS_PAD (pad));
595 oclass = CLASS (element);
596 if (oclass->release_pad)
597 (oclass->release_pad) (element, pad);
602 * gst_element_set_name:
603 * @element: a #GstElement to set name of
604 * @name: new name of element
606 * Sets the name of the element, getting rid of the old name if there was
610 gst_element_set_name (GstElement *element, const gchar *name)
612 g_return_if_fail (element != NULL);
613 g_return_if_fail (GST_IS_ELEMENT (element));
615 gst_object_set_name (GST_OBJECT (element), name);
619 * gst_element_get_name:
620 * @element: a #GstElement to get name of
622 * Gets the name of the element.
624 * Returns: name of the element
627 gst_element_get_name (GstElement *element)
629 g_return_val_if_fail (element != NULL, NULL);
630 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
632 return GST_OBJECT_NAME (element);
636 * gst_element_set_parent:
637 * @element: a #GstElement to set parent of
638 * @parent: new parent of the object
640 * Sets the parent of the element.
643 gst_element_set_parent (GstElement *element, GstObject *parent)
645 g_return_if_fail (element != NULL);
646 g_return_if_fail (GST_IS_ELEMENT (element));
647 g_return_if_fail (GST_OBJECT_PARENT (element) == NULL);
648 g_return_if_fail (parent != NULL);
649 g_return_if_fail (GST_IS_OBJECT (parent));
650 g_return_if_fail ((gpointer)element != (gpointer)parent);
652 gst_object_set_parent (GST_OBJECT (element), parent);
656 * gst_element_get_parent:
657 * @element: a #GstElement to get the parent of
659 * Gets the parent of the element.
661 * Returns: the #GstElement parent of the element
664 gst_element_get_parent (GstElement *element)
666 g_return_val_if_fail (element != NULL, NULL);
667 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
669 return GST_OBJECT_PARENT (element);
673 * gst_element_set_clock:
674 * @element: a #GstElement to set the clock for
675 * @clock: the #GstClock to set for the element
677 * Sets the clock for the element.
680 gst_element_set_clock (GstElement *element, GstClock *clock)
682 g_return_if_fail (element != NULL);
683 g_return_if_fail (GST_IS_ELEMENT (element));
685 if (element->setclockfunc)
686 element->setclockfunc (element, clock);
688 element->clock = clock;
692 * gst_element_get_clock:
693 * @element: a #GstElement to get the clock of
695 * Gets the clock of the element.
697 * Returns: the #GstClock of the element.
700 gst_element_get_clock (GstElement *element)
702 g_return_val_if_fail (element != NULL, NULL);
703 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
705 if (element->getclockfunc)
706 return element->getclockfunc (element);
712 * gst_element_clock_wait:
713 * @element: a #GstElement
714 * @clock: the #GstClock to use
715 * @time: the #GstClockTime to wait for on the clock
717 * Waits for a specific time on the clock.
719 * Returns: the #GstClockReturn result of the wait operation
722 gst_element_clock_wait (GstElement *element, GstClock *clock, GstClockTime time, GstClockTimeDiff *jitter)
726 g_return_val_if_fail (element != NULL, GST_CLOCK_ERROR);
727 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_CLOCK_ERROR);
729 if (GST_ELEMENT_SCHED (element)) {
730 res = gst_scheduler_clock_wait (GST_ELEMENT_SCHED (element), element, clock, time, jitter);
733 res = GST_CLOCK_TIMEOUT;
740 * gst_element_release_locks:
741 * @element: an element
743 * Instruct the element to release all the locks it is holding, ex
744 * blocking reads, waiting for the clock, ...
746 * Returns: TRUE if the locks could be released.
749 gst_element_release_locks (GstElement *element)
751 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
753 if (CLASS (element)->release_locks)
754 return CLASS (element)->release_locks (element);
760 * gst_element_add_pad:
761 * @element: element to add pad to
764 * Add a pad (connection point) to the element, setting the parent of the
765 * pad to the element (and thus adding a reference).
768 gst_element_add_pad (GstElement *element, GstPad *pad)
770 g_return_if_fail (element != NULL);
771 g_return_if_fail (GST_IS_ELEMENT (element));
772 g_return_if_fail (pad != NULL);
773 g_return_if_fail (GST_IS_PAD (pad));
775 /* first check to make sure the pad's parent is already set */
776 g_return_if_fail (GST_PAD_PARENT (pad) == NULL);
778 /* then check to see if there's already a pad by that name here */
779 g_return_if_fail (gst_object_check_uniqueness (element->pads, GST_PAD_NAME(pad)) == TRUE);
781 /* set the pad's parent */
782 GST_DEBUG (GST_CAT_ELEMENT_PADS,"setting parent of pad '%s' to '%s'",
783 GST_PAD_NAME (pad), GST_ELEMENT_NAME (element));
784 gst_object_set_parent (GST_OBJECT (pad), GST_OBJECT (element));
786 /* add it to the list */
787 element->pads = g_list_append (element->pads, pad);
789 if (gst_pad_get_direction (pad) == GST_PAD_SRC)
790 element->numsrcpads++;
792 element->numsinkpads++;
794 /* emit the NEW_PAD signal */
795 g_signal_emit (G_OBJECT (element), gst_element_signals[NEW_PAD], 0, pad);
799 * gst_element_remove_pad:
800 * @element: element to remove pad from
801 * @pad: pad to remove
803 * Remove a pad (connection point) from the element,
806 gst_element_remove_pad (GstElement *element, GstPad *pad)
808 g_return_if_fail (element != NULL);
809 g_return_if_fail (GST_IS_ELEMENT (element));
810 g_return_if_fail (pad != NULL);
811 g_return_if_fail (GST_IS_PAD (pad));
813 g_return_if_fail (GST_PAD_PARENT (pad) == element);
815 /* check to see if the pad is still connected */
816 /* FIXME: what if someone calls _remove_pad instead of
817 _remove_ghost_pad? */
818 if (GST_IS_REAL_PAD (pad)) {
819 g_return_if_fail (GST_RPAD_PEER (pad) == NULL);
822 /* remove it from the list */
823 element->pads = g_list_remove (element->pads, pad);
825 if (gst_pad_get_direction (pad) == GST_PAD_SRC)
826 element->numsrcpads--;
828 element->numsinkpads--;
830 g_signal_emit (G_OBJECT (element), gst_element_signals[PAD_REMOVED], 0, pad);
832 gst_object_unparent (GST_OBJECT (pad));
836 * gst_element_add_ghost_pad:
837 * @element: element to add ghost pad to
838 * @pad: pad from which the new ghost pad will be created
839 * @name: name of the new ghost pad
841 * Create a ghost pad from the given pad, and add it to the list of pads
844 * Returns: the added ghost pad or NULL, if no ghost pad was created.
847 gst_element_add_ghost_pad (GstElement *element, GstPad *pad, gchar *name)
851 g_return_val_if_fail (element != NULL, NULL);
852 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
853 g_return_val_if_fail (pad != NULL, NULL);
854 g_return_val_if_fail (GST_IS_PAD (pad), NULL);
856 /* then check to see if there's already a pad by that name here */
857 g_return_val_if_fail (gst_object_check_uniqueness (element->pads, name) == TRUE, NULL);
859 GST_DEBUG(GST_CAT_ELEMENT_PADS,"creating new ghost pad called %s, from pad %s:%s",
860 name,GST_DEBUG_PAD_NAME(pad));
861 ghostpad = gst_ghost_pad_new (name, pad);
863 /* add it to the list */
864 GST_DEBUG(GST_CAT_ELEMENT_PADS,"adding ghost pad %s to element %s",
865 name, GST_ELEMENT_NAME (element));
866 element->pads = g_list_append (element->pads, ghostpad);
868 /* set the parent of the ghostpad */
869 gst_object_set_parent (GST_OBJECT (ghostpad), GST_OBJECT (element));
871 GST_DEBUG(GST_CAT_ELEMENT_PADS,"added ghostpad %s:%s",GST_DEBUG_PAD_NAME(ghostpad));
873 /* emit the NEW_GHOST_PAD signal */
874 g_signal_emit (G_OBJECT (element), gst_element_signals[NEW_PAD], 0, ghostpad);
880 * gst_element_remove_ghost_pad:
881 * @element: element to remove the ghost pad from
882 * @pad: ghost pad to remove
884 * removes a ghost pad from an element
887 gst_element_remove_ghost_pad (GstElement *element, GstPad *pad)
889 g_return_if_fail (element != NULL);
890 g_return_if_fail (GST_IS_ELEMENT (element));
891 g_return_if_fail (pad != NULL);
892 g_return_if_fail (GST_IS_GHOST_PAD (pad));
894 /* FIXME this is redundant?
895 * wingo 10-july-2001: I don't think so, you have to actually remove the pad
896 * from the element. gst_pad_remove_ghost_pad just removes the ghostpad from
897 * the real pad's ghost pad list
899 gst_pad_remove_ghost_pad (GST_PAD (GST_PAD_REALIZE (pad)), pad);
900 gst_element_remove_pad (element, pad);
905 * gst_element_get_pad:
906 * @element: element to find pad of
907 * @name: name of pad to retrieve
909 * Retrieve a pad from the element by name.
911 * Returns: requested pad if found, otherwise NULL.
914 gst_element_get_pad (GstElement *element, const gchar *name)
918 g_return_val_if_fail (element != NULL, NULL);
919 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
920 g_return_val_if_fail (name != NULL, NULL);
922 if ((pad = gst_element_get_static_pad (element, name)))
925 pad = gst_element_get_request_pad (element, name);
931 * gst_element_get_static_pad:
932 * @element: element to find pad of
933 * @name: name of pad to retrieve
935 * Retrieve a pad from the element by name. This version only retrieves
936 * already-existing (i.e. 'static') pads.
938 * Returns: requested pad if found, otherwise NULL.
941 gst_element_get_static_pad (GstElement *element, const gchar *name)
945 g_return_val_if_fail (element != NULL, NULL);
946 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
947 g_return_val_if_fail (name != NULL, NULL);
949 walk = element->pads;
953 pad = GST_PAD(walk->data);
954 if (strcmp (GST_PAD_NAME(pad), name) == 0) {
955 GST_INFO (GST_CAT_ELEMENT_PADS, "found pad %s:%s", GST_DEBUG_PAD_NAME (pad));
958 walk = g_list_next (walk);
961 GST_INFO (GST_CAT_ELEMENT_PADS, "no such pad '%s' in element \"%s\"", name, GST_OBJECT_NAME (element));
966 * gst_element_get_request_pad:
967 * @element: element to find pad of
968 * @name: name of pad to retrieve
970 * Retrieve a pad from the element by name. This version only retrieves
973 * Returns: requested pad if found, otherwise NULL.
976 gst_element_get_request_pad (GstElement *element, const gchar *name)
978 GstPadTemplate *templ = NULL;
980 const gchar *req_name = NULL;
981 gboolean templ_found = FALSE;
985 gchar *str, *endptr = NULL;
987 g_return_val_if_fail (element != NULL, NULL);
988 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
989 g_return_val_if_fail (name != NULL, NULL);
991 if (strstr (name, "%")) {
992 templ = gst_element_get_pad_template (element, name);
997 list = gst_element_get_pad_template_list(element);
998 while (!templ_found && list) {
999 templ = (GstPadTemplate*) list->data;
1000 if (templ->presence == GST_PAD_REQUEST) {
1001 /* we know that %s and %d are the only possibilities because of sanity
1002 checks in gst_pad_template_new */
1003 GST_DEBUG (GST_CAT_PADS, "comparing %s to %s", name, templ->name_template);
1004 if ((str = strchr (templ->name_template, '%')) &&
1005 strncmp (templ->name_template, name, str - templ->name_template) == 0 &&
1006 strlen (name) > str - templ->name_template) {
1007 data = name + (str - templ->name_template);
1008 if (*(str+1) == 'd') {
1010 n = (gint) strtol (data, &endptr, 10);
1011 if (endptr && *endptr == '\0') {
1031 pad = gst_element_request_pad (element, templ, req_name);
1037 * gst_element_get_pad_list:
1038 * @element: element to get pads of
1040 * Retrieve a list of the pads associated with the element.
1042 * Returns: GList of pads
1045 gst_element_get_pad_list (GstElement *element)
1047 g_return_val_if_fail (element != NULL, NULL);
1048 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1050 /* return the list of pads */
1051 return element->pads;
1055 * gst_element_class_add_pad_template:
1056 * @klass: element class to add padtemplate to
1057 * @templ: padtemplate to add
1059 * Add a padtemplate to an element class. This is useful if you have derived a custom
1060 * bin and wish to provide an on-request pad at runtime. Plugin writers should use
1061 * gst_element_factory_add_pad_template instead.
1064 gst_element_class_add_pad_template (GstElementClass *klass, GstPadTemplate *templ)
1066 g_return_if_fail (klass != NULL);
1067 g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
1068 g_return_if_fail (templ != NULL);
1069 g_return_if_fail (GST_IS_PAD_TEMPLATE (templ));
1071 klass->padtemplates = g_list_append (klass->padtemplates, templ);
1072 klass->numpadtemplates++;
1076 * gst_element_get_pad_template_list:
1077 * @element: element to get padtemplates of
1079 * Retrieve a list of the padtemplates associated with the element.
1081 * Returns: GList of padtemplates
1084 gst_element_get_pad_template_list (GstElement *element)
1086 g_return_val_if_fail (element != NULL, NULL);
1087 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1089 return CLASS (element)->padtemplates;
1093 * gst_element_get_pad_template:
1094 * @element: element to get padtemplate of
1095 * @name: the name of the padtemplate to get.
1097 * Retrieve a padtemplate from this element with the
1100 * Returns: the padtemplate with the given name. No unreferencing is necessary.
1103 gst_element_get_pad_template (GstElement *element, const guchar *name)
1107 g_return_val_if_fail (element != NULL, NULL);
1108 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1109 g_return_val_if_fail (name != NULL, NULL);
1111 padlist = gst_element_get_pad_template_list (element);
1114 GstPadTemplate *padtempl = (GstPadTemplate*) padlist->data;
1116 if (!strcmp (padtempl->name_template, name))
1119 padlist = g_list_next (padlist);
1126 * gst_element_get_compatible_pad_template:
1127 * @element: element to get padtemplate of
1128 * @templ: a template to find a compatible template for
1130 * Generate a padtemplate for this element compatible with the given
1131 * template, ie able to link to it.
1133 * Returns: the padtemplate. No unreferencing is necessary.
1136 gst_element_get_compatible_pad_template (GstElement *element, GstPadTemplate *compattempl)
1138 GstPadTemplate *newtempl = NULL;
1141 GST_DEBUG(GST_CAT_ELEMENT_PADS,"gst_element_get_pad_template_by_compatible()");
1143 g_return_val_if_fail (element != NULL, NULL);
1144 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1145 g_return_val_if_fail (compattempl != NULL, NULL);
1147 padlist = gst_element_get_pad_template_list (element);
1150 GstPadTemplate *padtempl = (GstPadTemplate*) padlist->data;
1151 gboolean compat = FALSE;
1155 * Check direction (must be opposite)
1158 GST_DEBUG(GST_CAT_CAPS,"checking direction and caps");
1159 if (padtempl->direction == GST_PAD_SRC &&
1160 compattempl->direction == GST_PAD_SINK) {
1161 GST_DEBUG(GST_CAT_CAPS,"compatible direction: found src pad template");
1162 compat = gst_caps_check_compatibility(GST_PAD_TEMPLATE_CAPS (padtempl),
1163 GST_PAD_TEMPLATE_CAPS (compattempl));
1164 GST_DEBUG(GST_CAT_CAPS,"caps are %scompatible", (compat?"":"not "));
1165 } else if (padtempl->direction == GST_PAD_SINK &&
1166 compattempl->direction == GST_PAD_SRC) {
1167 GST_DEBUG(GST_CAT_CAPS,"compatible direction: found sink pad template");
1168 compat = gst_caps_check_compatibility(GST_PAD_TEMPLATE_CAPS (compattempl),
1169 GST_PAD_TEMPLATE_CAPS (padtempl));
1170 GST_DEBUG(GST_CAT_CAPS,"caps are %scompatible", (compat?"":"not "));
1174 newtempl = padtempl;
1178 padlist = g_list_next (padlist);
1185 * gst_element_request_compatible_pad:
1186 * @element: element to request a new pad from
1187 * @templ: a pad template to which the new pad should be able to connect
1189 * Request a new pad from the element. The template will
1190 * be used to decide what type of pad to create. This function
1191 * is typically used for elements with a padtemplate with presence
1194 * Returns: the new pad that was created.
1197 gst_element_request_compatible_pad (GstElement *element, GstPadTemplate *templ)
1199 GstPadTemplate *templ_new;
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 (templ != NULL, NULL);
1206 templ_new = gst_element_get_compatible_pad_template (element, templ);
1207 if (templ_new != NULL)
1208 pad = gst_element_request_pad (element, templ_new, NULL);
1215 * gst_element_get_compatible_pad_filtered:
1216 * @element: the element in which the pad should be found
1217 * @pad: the pad to find a compatible one for
1218 * @filtercaps: the caps to use as a filter
1220 * Looks for an unconnected pad to which the given pad can connect to.
1221 * It is not guaranteed that connecting the pads will work, though
1222 * it should work in most cases.
1224 * Returns: the pad to which a connection can be made
1227 gst_element_get_compatible_pad_filtered (GstElement *element, GstPad *pad, GstCaps *filtercaps)
1230 GstPadTemplate *templ;
1232 GstPad *foundpad = NULL;
1235 g_return_val_if_fail (element != NULL, NULL);
1236 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1237 g_return_val_if_fail (pad != NULL, NULL);
1238 g_return_val_if_fail (GST_IS_PAD (pad), NULL);
1240 /* let's use the real pad */
1241 pad = (GstPad *) GST_PAD_REALIZE (pad);
1242 g_return_val_if_fail (pad != NULL, NULL);
1243 g_return_val_if_fail (GST_RPAD_PEER (pad) == NULL, NULL);
1245 /* try to get an existing unconnected pad */
1246 pads = gst_element_get_pad_list (element);
1248 GstPad *current = GST_PAD (pads->data);
1249 if ((GST_PAD_PEER (GST_PAD_REALIZE (current)) == NULL) &&
1250 gst_pad_can_connect_filtered (pad, current, filtercaps)) {
1253 pads = g_list_next (pads);
1256 /* try to create a new one */
1257 /* requesting is a little crazy, we need a template. Let's create one */
1258 if (filtercaps != NULL) {
1259 templcaps = gst_caps_intersect (filtercaps, (GstCaps *) GST_RPAD_CAPS (pad));
1260 if (templcaps == NULL)
1263 templcaps = gst_caps_copy (gst_pad_get_caps (pad));
1266 templ = gst_pad_template_new ((gchar *) GST_PAD_NAME (pad), GST_RPAD_DIRECTION (pad),
1267 GST_PAD_ALWAYS, templcaps, NULL);
1268 foundpad = gst_element_request_compatible_pad (element, templ);
1269 gst_object_unref (GST_OBJECT (templ)); /* this will take care of the caps too */
1271 /* FIXME: this is broken, but it's in here so autoplugging elements that don't
1272 have caps on their source padtemplates (spider) can connect... */
1273 if (!foundpad && !filtercaps) {
1274 templ = gst_pad_template_new ((gchar *) GST_PAD_NAME (pad), GST_RPAD_DIRECTION (pad),
1275 GST_PAD_ALWAYS, NULL, NULL);
1276 foundpad = gst_element_request_compatible_pad (element, templ);
1277 gst_object_unref (GST_OBJECT (templ));
1284 * gst_element_get_compatible_pad:
1285 * @element: the element in which the pad should be found
1286 * @pad: the pad to find a compatible one for
1288 * Looks for an unconnected pad to which the given pad can connect to.
1289 * It is not guaranteed that connecting the pads will work, though
1290 * it should work in most cases.
1292 * Returns: the pad to which a connection can be made
1295 gst_element_get_compatible_pad (GstElement *element, GstPad *pad)
1297 return gst_element_get_compatible_pad_filtered (element, pad, NULL);
1301 * gst_element_connect_filtered:
1302 * @src: the element containing source pad
1303 * @dest: the element containing destination pad
1304 * @filtercaps: the caps to use as filter
1306 * Connect the source to the destination element using the filtercaps.
1307 * The connection must be from source to destination, the other
1308 * direction will not be tried.
1309 * The functions looks for existing pads that aren't connected yet.
1310 + It will use request pads if possible. But both pads will not be requested.
1311 * If multiple connections are possible, only one is established.
1313 * Returns: TRUE if the elements could be connected.
1316 gst_element_connect_filtered (GstElement *src, GstElement *dest,
1317 GstCaps *filtercaps)
1319 GList *srcpads, *destpads, *srctempls, *desttempls, *l;
1320 GstPad *srcpad, *destpad;
1321 GstPadTemplate *srctempl, *desttempl;
1324 g_return_val_if_fail (src != NULL, FALSE);
1325 g_return_val_if_fail (GST_IS_ELEMENT(src), FALSE);
1326 g_return_val_if_fail (dest != NULL, FALSE);
1327 g_return_val_if_fail (GST_IS_ELEMENT(dest), FALSE);
1329 GST_DEBUG (GST_CAT_ELEMENT_PADS, "attempting to connect element %s to element %s", GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (dest));
1331 /* loop through the existing pads in the source */
1332 srcpads = gst_element_get_pad_list (src);
1333 destpads = gst_element_get_pad_list (dest);
1335 if (srcpads || destpads) {
1337 srcpad = (GstPad *) GST_PAD_REALIZE (srcpads->data);
1338 if ((GST_RPAD_DIRECTION (srcpad) == GST_PAD_SRC) &&
1339 (GST_PAD_PEER (srcpad) == NULL)) {
1340 destpad = gst_element_get_compatible_pad_filtered (dest, srcpad, filtercaps);
1341 if (destpad && gst_pad_connect_filtered (srcpad, destpad, filtercaps)) {
1342 GST_DEBUG (GST_CAT_ELEMENT_PADS, "connected pad %s:%s to pad %s:%s", GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad));
1346 srcpads = g_list_next (srcpads);
1349 /* loop through the existing pads in the destination */
1351 destpad = (GstPad *) GST_PAD_REALIZE (destpads->data);
1352 if ((GST_RPAD_DIRECTION (destpad) == GST_PAD_SINK) &&
1353 (GST_PAD_PEER (destpad) == NULL)) {
1354 srcpad = gst_element_get_compatible_pad_filtered (src, destpad, filtercaps);
1355 if (srcpad && gst_pad_connect_filtered (srcpad, destpad, filtercaps)) {
1356 GST_DEBUG (GST_CAT_ELEMENT_PADS, "connected pad %s:%s to pad %s:%s", GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad));
1360 destpads = g_list_next (destpads);
1364 GST_DEBUG (GST_CAT_ELEMENT_PADS, "we might have request pads on both sides, checking...");
1365 srctempls = gst_element_get_pad_template_list (src);
1366 desttempls = gst_element_get_pad_template_list (dest);
1368 if (srctempls && desttempls) {
1370 srctempl = (GstPadTemplate*) srctempls->data;
1371 if (srctempl->presence == GST_PAD_REQUEST) {
1372 for (l=desttempls; l; l=l->next) {
1373 desttempl = (GstPadTemplate*) desttempls->data;
1374 if (desttempl->presence == GST_PAD_REQUEST && desttempl->direction != srctempl->direction) {
1375 if (gst_caps_check_compatibility (gst_pad_template_get_caps (srctempl),
1376 gst_pad_template_get_caps (desttempl))) {
1377 srcpad = gst_element_get_request_pad (src, srctempl->name_template);
1378 destpad = gst_element_get_request_pad (dest, desttempl->name_template);
1379 if (gst_pad_connect_filtered (srcpad, destpad, filtercaps)) {
1380 GST_DEBUG (GST_CAT_ELEMENT_PADS, "connected pad %s:%s to pad %s:%s",
1381 GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad));
1384 /* FIXME: we have extraneous request pads lying around */
1389 srctempls = srctempls->next;
1393 GST_DEBUG (GST_CAT_ELEMENT_PADS, "no connection possible from %s to %s", GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (dest));
1398 * gst_element_connect_many:
1399 * @element_1: the first element in the connection chain
1400 * @element_2: the second element in the connection chain
1401 * @...: NULL-terminated list of elements to connect in order
1403 * Chain together a series of elements. Uses #gst_element_connect.
1405 * Returns: TRUE on success, FALSE otherwise.
1408 gst_element_connect_many (GstElement *element_1, GstElement *element_2, ...)
1412 g_return_val_if_fail (element_1 != NULL && element_2 != NULL, FALSE);
1413 g_return_val_if_fail (GST_IS_ELEMENT (element_1) && GST_IS_ELEMENT (element_2), FALSE);
1415 va_start (args, element_2);
1418 if (!gst_element_connect (element_1, element_2))
1421 element_1 = element_2;
1422 element_2 = va_arg (args, GstElement*);
1431 * gst_element_connect:
1432 * @src: element containing source pad
1433 * @dest: element containing destination pad
1435 * Connect the source to the destination element.
1436 * The connection must be from source to destination, the other
1437 * direction will not be tried.
1438 * The functions looks for existing pads and request pads that aren't
1439 * connected yet. If multiple connections are possible, only one is
1442 * Returns: TRUE if the elements could be connected.
1445 gst_element_connect (GstElement *src, GstElement *dest)
1447 return gst_element_connect_filtered (src, dest, NULL);
1451 * gst_element_connect_pads_filtered:
1452 * @src: element containing source pad
1453 * @srcpadname: name of pad in source element
1454 * @dest: element containing destination pad
1455 * @destpadname: name of pad in destination element
1456 * @filtercaps: the caps to use as a filter
1458 * Connect the two named pads of the source and destination elements.
1459 * Side effect is that if one of the pads has no parent, it becomes a
1460 * child of the parent of the other element. If they have different
1461 * parents, the connection fails.
1463 * Returns: TRUE if the pads could be connected.
1466 gst_element_connect_pads_filtered (GstElement *src, const gchar *srcpadname,
1467 GstElement *dest, const gchar *destpadname,
1468 GstCaps *filtercaps)
1470 GstPad *srcpad,*destpad;
1472 g_return_val_if_fail (src != NULL, FALSE);
1473 g_return_val_if_fail (GST_IS_ELEMENT (src), FALSE);
1474 g_return_val_if_fail (srcpadname != NULL, FALSE);
1475 g_return_val_if_fail (dest != NULL, FALSE);
1476 g_return_val_if_fail (GST_IS_ELEMENT (dest), FALSE);
1477 g_return_val_if_fail (destpadname != NULL, FALSE);
1479 /* obtain the pads requested */
1480 srcpad = gst_element_get_pad (src, srcpadname);
1481 if (srcpad == NULL) {
1482 GST_ERROR (src, "source element has no pad \"%s\"", srcpadname);
1485 destpad = gst_element_get_pad (dest, destpadname);
1486 if (srcpad == NULL) {
1487 GST_ERROR (dest, "destination element has no pad \"%s\"", destpadname);
1491 /* we're satisified they can be connected, let's do it */
1492 return gst_pad_connect_filtered (srcpad, destpad, filtercaps);
1496 * gst_element_connect_pads:
1497 * @src: element containing source pad
1498 * @srcpadname: name of pad in source element
1499 * @dest: element containing destination pad
1500 * @destpadname: name of pad in destination element
1502 * Connect the two named pads of the source and destination elements.
1503 * Side effect is that if one of the pads has no parent, it becomes a
1504 * child of the parent of the other element. If they have different
1505 * parents, the connection fails.
1507 * Returns: TRUE if the pads could be connected.
1510 gst_element_connect_pads (GstElement *src, const gchar *srcpadname,
1511 GstElement *dest, const gchar *destpadname)
1513 return gst_element_connect_pads_filtered (src, srcpadname, dest, destpadname, NULL);
1517 * gst_element_disconnect_pads:
1518 * @src: element containing source pad
1519 * @srcpadname: name of pad in source element
1520 * @dest: element containing destination pad
1521 * @destpadname: name of pad in destination element
1523 * Disconnect the two named pads of the source and destination elements.
1526 gst_element_disconnect_pads (GstElement *src, const gchar *srcpadname,
1527 GstElement *dest, const gchar *destpadname)
1529 GstPad *srcpad,*destpad;
1531 g_return_if_fail (src != NULL);
1532 g_return_if_fail (GST_IS_ELEMENT(src));
1533 g_return_if_fail (srcpadname != NULL);
1534 g_return_if_fail (dest != NULL);
1535 g_return_if_fail (GST_IS_ELEMENT(dest));
1536 g_return_if_fail (destpadname != NULL);
1538 /* obtain the pads requested */
1539 srcpad = gst_element_get_pad (src, srcpadname);
1540 if (srcpad == NULL) {
1541 GST_ERROR(src,"source element has no pad \"%s\"",srcpadname);
1544 destpad = gst_element_get_pad (dest, destpadname);
1545 if (srcpad == NULL) {
1546 GST_ERROR(dest,"destination element has no pad \"%s\"",destpadname);
1550 /* we're satisified they can be disconnected, let's do it */
1551 gst_pad_disconnect(srcpad,destpad);
1555 * gst_element_disconnect_many:
1556 * @element_1: the first element in the connection chain
1557 * @element_2: the second element in the connection chain
1558 * @...: NULL-terminated list of elements to disconnect in order
1560 * Disconnect a series of elements. Uses #gst_element_disconnect.
1563 gst_element_disconnect_many (GstElement *element_1, GstElement *element_2, ...)
1567 g_return_if_fail (element_1 != NULL && element_2 != NULL);
1568 g_return_if_fail (GST_IS_ELEMENT (element_1) && GST_IS_ELEMENT (element_2));
1570 va_start (args, element_2);
1573 gst_element_disconnect (element_1, element_2);
1575 element_1 = element_2;
1576 element_2 = va_arg (args, GstElement*);
1583 * gst_element_disconnect:
1584 * @src: source element
1585 * @dest: sink element
1587 * Disconnect all pads connecting the two elements in the direction src -> dest.
1590 gst_element_disconnect (GstElement *src, GstElement *dest)
1595 g_return_if_fail (GST_IS_ELEMENT(src));
1596 g_return_if_fail (GST_IS_ELEMENT(dest));
1598 GST_DEBUG (GST_CAT_ELEMENT_PADS, "disconnecting \"%s\" and \"%s\"", GST_ELEMENT_NAME (src),
1599 GST_ELEMENT_NAME (dest));
1601 srcpads = gst_element_get_pad_list (src);
1604 pad = GST_PAD_CAST (srcpads->data);
1606 if (GST_IS_REAL_PAD (pad) && GST_PAD_DIRECTION (pad) == GST_PAD_SRC) {
1607 GstPad *peerpad = GST_PAD_PEER (pad);
1609 if (peerpad && (GST_OBJECT_PARENT (GST_PAD_PEER (peerpad)) == (GstObject*) src)) {
1610 gst_pad_disconnect (pad, peerpad);
1614 srcpads = g_list_next (srcpads);
1619 gst_element_error_func (GstElement* element, GstElement *source, gchar *errormsg)
1621 /* tell the parent */
1622 if (GST_OBJECT_PARENT (element)) {
1623 GST_DEBUG (GST_CAT_EVENT, "forwarding error \"%s\" from %s to %s", errormsg,
1624 GST_ELEMENT_NAME (element), GST_OBJECT_NAME (GST_OBJECT_PARENT (element)));
1626 gst_object_ref (GST_OBJECT (element));
1627 g_signal_emit (G_OBJECT (GST_OBJECT_PARENT (element)), gst_element_signals[ERROR], 0, source, errormsg);
1628 gst_object_unref (GST_OBJECT (element));
1633 gst_element_send_event_default (GstElement *element, GstEvent *event)
1635 GList *pads = element->pads;
1636 gboolean res = FALSE;
1639 GstPad *pad = GST_PAD_CAST (pads->data);
1641 if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) {
1642 if (GST_PAD_IS_CONNECTED (pad)) {
1643 res = gst_pad_send_event (GST_PAD_PEER (pad), event);
1647 pads = g_list_next (pads);
1653 gst_element_send_event (GstElement *element, GstEvent *event)
1655 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1656 g_return_val_if_fail (event != NULL, FALSE);
1658 if (CLASS (element)->send_event)
1659 return CLASS (element)->send_event (element, event);
1665 gst_element_query_default (GstElement *element, GstPadQueryType type,
1666 GstFormat *format, gint64 *value)
1668 GList *pads = element->pads;
1669 gboolean res = FALSE;
1672 GstPad *pad = GST_PAD_CAST (pads->data);
1674 if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) {
1675 if (GST_PAD_IS_CONNECTED (pad)) {
1676 res = gst_pad_query (GST_PAD_PEER (pad), type, format, value);
1680 pads = g_list_next (pads);
1686 gst_element_query (GstElement *element, GstPadQueryType type,
1687 GstFormat *format, gint64 *value)
1689 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1690 g_return_val_if_fail (format != NULL, FALSE);
1691 g_return_val_if_fail (value != NULL, FALSE);
1693 if (CLASS (element)->query)
1694 return CLASS (element)->query (element, type, format, value);
1702 * gst_element_error:
1703 * @element: Element with the error
1704 * @error: A printf-like string describing the error
1705 * @...: optional arguments for the string
1707 * This function is used internally by elements to signal an error
1708 * condition. It results in the "error" signal.
1711 gst_element_error (GstElement *element, const gchar *error, ...)
1717 g_return_if_fail (GST_IS_ELEMENT (element));
1718 g_return_if_fail (error != NULL);
1720 /* create error message */
1721 va_start (var_args, error);
1722 string = g_strdup_vprintf (error, var_args);
1724 GST_INFO (GST_CAT_EVENT, "ERROR in %s: %s", GST_ELEMENT_NAME (element), string);
1726 /* emit the signal, make sure the element stays available */
1727 gst_object_ref (GST_OBJECT (element));
1728 g_signal_emit (G_OBJECT (element), gst_element_signals[ERROR], 0, element, string);
1730 /* tell the scheduler */
1731 if (element->sched) {
1732 gst_scheduler_error (element->sched, element);
1736 gst_object_unref (GST_OBJECT (element));
1741 * gst_element_get_state:
1742 * @element: a #GstElement to get state of
1744 * Gets the state of the element.
1746 * Returns: The #GstElementState of the element
1749 gst_element_get_state (GstElement *element)
1751 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_VOID_PENDING);
1753 return GST_STATE (element);
1757 * gst_element_wait_state_change:
1758 * @element: a #GstElement to wait for
1760 * Waits and blocks until the element changed its state.
1763 gst_element_wait_state_change (GstElement *element)
1765 g_mutex_lock (element->state_mutex);
1766 g_cond_wait (element->state_cond, element->state_mutex);
1767 g_mutex_unlock (element->state_mutex);
1771 * gst_element_set_state:
1772 * @element: a #GstElement to change state of
1773 * @state: the element's new #GstElementState
1775 * Sets the state of the element. This function will try to set the
1776 * requested state by going through all the intermediary states and calling
1777 * the class's state change function for each.
1779 * Returns: whether or not the state was successfully set
1780 * (using #GstElementStateReturn).
1783 gst_element_set_state (GstElement *element, GstElementState state)
1785 GstElementClass *oclass;
1786 GstElementState curpending;
1787 GstElementStateReturn return_val = GST_STATE_SUCCESS;
1789 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
1791 /* start with the current state */
1792 curpending = GST_STATE(element);
1794 GST_DEBUG_ELEMENT (GST_CAT_STATES, element, "setting state from %s to %s",
1795 gst_element_state_get_name (curpending),
1796 gst_element_state_get_name (state));
1798 /* loop until the final requested state is set */
1799 while (GST_STATE (element) != state
1800 && GST_STATE (element) != GST_STATE_VOID_PENDING) {
1801 /* move the curpending state in the correct direction */
1802 if (curpending < state)
1807 /* set the pending state variable */
1808 /* FIXME: should probably check to see that we don't already have one */
1809 GST_STATE_PENDING (element) = curpending;
1811 if (curpending != state) {
1812 GST_DEBUG_ELEMENT (GST_CAT_STATES, element,
1813 "intermediate: setting state from %s to %s",
1814 gst_element_state_get_name (GST_STATE (element)),
1815 gst_element_state_get_name (curpending));
1818 /* call the state change function so it can set the state */
1819 oclass = CLASS (element);
1820 if (oclass->change_state)
1821 return_val = (oclass->change_state) (element);
1823 switch (return_val) {
1824 case GST_STATE_FAILURE:
1825 GST_DEBUG_ELEMENT (GST_CAT_STATES, element, "have failed change_state return");
1827 case GST_STATE_ASYNC:
1828 GST_DEBUG_ELEMENT (GST_CAT_STATES, element, "element will change state async");
1830 case GST_STATE_SUCCESS:
1831 /* Last thing we do is verify that a successful state change really
1832 * did change the state... */
1833 if (GST_STATE (element) != curpending) {
1834 GST_DEBUG_ELEMENT (GST_CAT_STATES, element,
1835 "element claimed state-change success, but state didn't change %s, %s <-> %s",
1836 gst_element_state_get_name (GST_STATE (element)),
1837 gst_element_state_get_name (GST_STATE_PENDING (element)),
1838 gst_element_state_get_name (curpending));
1839 return GST_STATE_FAILURE;
1843 /* somebody added a GST_STATE_ and forgot to do stuff here ! */
1844 g_assert_not_reached ();
1853 gst_element_negotiate_pads (GstElement *element)
1855 GList *pads = GST_ELEMENT_PADS (element);
1857 GST_DEBUG_ELEMENT (GST_CAT_CAPS, element, "negotiating pads");
1860 GstPad *pad = GST_PAD (pads->data);
1863 pads = g_list_next (pads);
1865 if (!GST_IS_REAL_PAD (pad))
1868 srcpad = GST_PAD_REALIZE (pad);
1870 /* if we have a connection on this pad and it doesn't have caps
1871 * allready, try to negotiate */
1872 if (GST_PAD_IS_CONNECTED (srcpad) && !GST_PAD_CAPS (srcpad)) {
1873 GstRealPad *sinkpad;
1874 GstElementState otherstate;
1877 sinkpad = GST_RPAD_PEER (GST_PAD_REALIZE (srcpad));
1879 /* check the parent of the peer pad, if there is no parent do nothing */
1880 parent = GST_PAD_PARENT (sinkpad);
1884 otherstate = GST_STATE (parent);
1886 /* swap pads if needed */
1887 if (!GST_PAD_IS_SRC (srcpad)) {
1895 /* only try to negotiate if the peer element is in PAUSED or higher too */
1896 if (otherstate >= GST_STATE_READY) {
1897 GST_DEBUG_ELEMENT (GST_CAT_CAPS, element, "perform negotiate for %s:%s and %s:%s",
1898 GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
1899 if (!gst_pad_perform_negotiate (GST_PAD (srcpad), GST_PAD (sinkpad)))
1903 GST_DEBUG_ELEMENT (GST_CAT_CAPS, element, "not negotiatiating %s:%s and %s:%s, not in READY yet",
1904 GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
1913 gst_element_clear_pad_caps (GstElement *element)
1915 GList *pads = GST_ELEMENT_PADS (element);
1917 GST_DEBUG_ELEMENT (GST_CAT_CAPS, element, "clearing pad caps");
1920 GstRealPad *pad = GST_PAD_REALIZE (pads->data);
1922 if (GST_PAD_CAPS (pad)) {
1923 GST_PAD_CAPS (pad) = NULL;
1925 pads = g_list_next (pads);
1929 static GstElementStateReturn
1930 gst_element_change_state (GstElement *element)
1932 GstElementState old_state;
1934 gint old_pending, old_transition;
1936 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
1938 old_state = GST_STATE (element);
1939 old_pending = GST_STATE_PENDING (element);
1940 old_transition = GST_STATE_TRANSITION (element);
1942 if (old_pending == GST_STATE_VOID_PENDING || old_state == GST_STATE_PENDING (element)) {
1943 GST_INFO (GST_CAT_STATES, "no state change needed for element %s (VOID_PENDING)", GST_ELEMENT_NAME (element));
1944 return GST_STATE_SUCCESS;
1947 GST_INFO (GST_CAT_STATES, "%s default handler sets state from %s to %s %d", GST_ELEMENT_NAME (element),
1948 gst_element_state_get_name (old_state),
1949 gst_element_state_get_name (old_pending),
1950 GST_STATE_TRANSITION (element));
1952 /* we set the state change early for the negotiation functions */
1953 GST_STATE (element) = old_pending;
1954 GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING;
1956 /* if we are going to paused, we try to negotiate the pads */
1957 if (old_transition == GST_STATE_NULL_TO_READY) {
1958 if (!gst_element_negotiate_pads (element))
1961 /* going to the READY state clears all pad caps */
1962 else if (old_transition == GST_STATE_READY_TO_NULL) {
1963 gst_element_clear_pad_caps (element);
1966 /* tell the scheduler if we have one */
1967 if (element->sched) {
1968 if (gst_scheduler_state_transition (element->sched, element, old_transition)
1969 != GST_STATE_SUCCESS) {
1974 parent = GST_ELEMENT_PARENT (element);
1976 /* tell our parent about the state change */
1977 if (parent && GST_IS_BIN (parent)) {
1978 gst_bin_child_state_change (GST_BIN (parent), old_state, GST_STATE (element), element);
1981 g_signal_emit (G_OBJECT (element), gst_element_signals[STATE_CHANGE],
1982 0, old_state, GST_STATE (element));
1984 /* signal the state change in case somebody is waiting for us */
1985 g_mutex_lock (element->state_mutex);
1986 g_cond_signal (element->state_cond);
1987 g_mutex_unlock (element->state_mutex);
1989 return GST_STATE_SUCCESS;
1992 /* undo the state change */
1993 GST_STATE (element) = old_state;
1994 GST_STATE_PENDING (element) = old_pending;
1996 return GST_STATE_FAILURE;
2000 * gst_element_get_factory:
2001 * @element: element to request the factory
2003 * Retrieves the factory that was used to create this element
2005 * Returns: the factory used for creating this element
2008 gst_element_get_factory (GstElement *element)
2010 GstElementClass *oclass;
2012 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
2014 oclass = CLASS (element);
2016 return oclass->elementfactory;
2020 gst_element_dispose (GObject *object)
2022 GstElement *element = GST_ELEMENT (object);
2026 GST_DEBUG_ELEMENT (GST_CAT_REFCOUNTING, element, "dispose");
2028 gst_element_set_state (element, GST_STATE_NULL);
2030 /* first we break all our connections with the ouside */
2031 if (element->pads) {
2033 orig = pads = g_list_copy (element->pads);
2035 pad = GST_PAD (pads->data);
2037 if (GST_PAD_PEER (pad)) {
2038 GST_DEBUG (GST_CAT_REFCOUNTING, "disconnecting pad '%s'",
2039 GST_OBJECT_NAME (GST_OBJECT (GST_PAD (GST_PAD_PEER (pad)))));
2040 gst_pad_disconnect (pad, GST_PAD (GST_PAD_PEER (pad)));
2042 gst_element_remove_pad (element, pad);
2044 pads = g_list_next (pads);
2047 g_list_free (element->pads);
2048 element->pads = NULL;
2051 element->numsrcpads = 0;
2052 element->numsinkpads = 0;
2053 element->numpads = 0;
2054 g_mutex_free (element->state_mutex);
2055 g_cond_free (element->state_cond);
2057 if (element->prop_value_queue)
2058 g_async_queue_unref (element->prop_value_queue);
2059 element->prop_value_queue = NULL;
2060 if (element->property_mutex)
2061 g_mutex_free (element->property_mutex);
2063 G_OBJECT_CLASS (parent_class)->dispose (object);
2066 #ifndef GST_DISABLE_LOADSAVE
2068 * gst_element_save_thyself:
2069 * @element: GstElement to save
2070 * @parent: the xml parent node
2072 * Saves the element as part of the given XML structure
2074 * Returns: the new xml node
2077 gst_element_save_thyself (GstObject *object,
2081 GstElementClass *oclass;
2082 GParamSpec **specs, *spec;
2084 GValue value = { 0, };
2085 GstElement *element;
2087 g_return_val_if_fail (GST_IS_ELEMENT (object), parent);
2089 element = GST_ELEMENT (object);
2091 oclass = CLASS (element);
2093 xmlNewChild(parent, NULL, "name", GST_ELEMENT_NAME(element));
2095 if (oclass->elementfactory != NULL) {
2096 GstElementFactory *factory = (GstElementFactory *)oclass->elementfactory;
2098 xmlNewChild (parent, NULL, "type", GST_OBJECT_NAME (factory));
2099 xmlNewChild (parent, NULL, "version", factory->details->version);
2102 /* FIXME: what is this? */
2103 /* if (element->manager) */
2104 /* xmlNewChild(parent, NULL, "manager", GST_ELEMENT_NAME(element->manager)); */
2107 specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (object), &nspecs);
2109 for (i=0; i<nspecs; i++) {
2111 if (spec->flags & G_PARAM_READABLE) {
2114 g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE (spec));
2116 g_object_get_property (G_OBJECT (element), spec->name, &value);
2117 param = xmlNewChild (parent, NULL, "param", NULL);
2118 xmlNewChild (param, NULL, "name", spec->name);
2120 if (G_IS_PARAM_SPEC_STRING (spec))
2121 xmlNewChild (param, NULL, "value", g_value_dup_string (&value));
2122 else if (G_IS_PARAM_SPEC_ENUM (spec))
2123 xmlNewChild (param, NULL, "value", g_strdup_printf ("%d", g_value_get_enum (&value)));
2124 else if (G_IS_PARAM_SPEC_INT64 (spec))
2125 xmlNewChild (param, NULL, "value", g_strdup_printf ("%lld", g_value_get_int64 (&value)));
2127 xmlNewChild (param, NULL, "value", g_strdup_value_contents (&value));
2129 g_value_unset(&value);
2133 pads = GST_ELEMENT_PADS (element);
2136 GstPad *pad = GST_PAD (pads->data);
2137 /* figure out if it's a direct pad or a ghostpad */
2138 if (GST_ELEMENT (GST_OBJECT_PARENT (pad)) == element) {
2139 xmlNodePtr padtag = xmlNewChild (parent, NULL, "pad", NULL);
2140 gst_object_save_thyself (GST_OBJECT (pad), padtag);
2142 pads = g_list_next (pads);
2149 gst_element_restore_thyself (GstObject *object, xmlNodePtr self)
2151 xmlNodePtr children;
2152 GstElement *element;
2153 guchar *name = NULL;
2154 guchar *value = NULL;
2156 element = GST_ELEMENT (object);
2157 g_return_if_fail (element != NULL);
2160 children = self->xmlChildrenNode;
2162 if (!strcmp (children->name, "param")) {
2163 xmlNodePtr child = children->xmlChildrenNode;
2166 if (!strcmp (child->name, "name")) {
2167 name = xmlNodeGetContent (child);
2169 else if (!strcmp (child->name, "value")) {
2170 value = xmlNodeGetContent (child);
2172 child = child->next;
2174 /* FIXME: can this just be g_object_set ? */
2175 gst_util_set_object_arg ((GObject *)G_OBJECT (element), name, value);
2177 children = children->next;
2181 children = self->xmlChildrenNode;
2183 if (!strcmp (children->name, "pad")) {
2184 gst_pad_load_and_connect (children, GST_OBJECT (element));
2186 children = children->next;
2189 if (GST_OBJECT_CLASS(parent_class)->restore_thyself)
2190 (GST_OBJECT_CLASS(parent_class)->restore_thyself) (object, self);
2192 #endif /* GST_DISABLE_LOADSAVE */
2195 * gst_element_yield:
2196 * @element: Element to yield
2198 * Request a yield operation for the child. The scheduler will typically
2199 * give control to another element.
2202 gst_element_yield (GstElement *element)
2204 if (GST_ELEMENT_SCHED (element)) {
2205 gst_scheduler_yield (GST_ELEMENT_SCHED (element), element);
2210 * gst_element_interrupt:
2211 * @element: Element to interrupt
2213 * Request the scheduler of this element to interrupt the execution of
2214 * this element and scheduler another one.
2216 * Returns: a boolean indicating that the child should exit its chain/loop/get
2217 * function ASAP, depending on the scheduler implementation.
2220 gst_element_interrupt (GstElement *element)
2222 if (GST_ELEMENT_SCHED (element)) {
2223 return gst_scheduler_interrupt (GST_ELEMENT_SCHED (element), element);
2230 * gst_element_set_scheduler:
2231 * @element: Element to set manager of.
2232 * @sched: @GstScheduler to set.
2234 * Sets the scheduler of the element. For internal use only, unless you're
2235 * writing a new bin subclass.
2238 gst_element_set_scheduler (GstElement *element,
2239 GstScheduler *sched)
2241 g_return_if_fail (GST_IS_ELEMENT (element));
2243 GST_INFO_ELEMENT (GST_CAT_PARENTAGE, element, "setting scheduler to %p", sched);
2245 element->sched = sched;
2249 * gst_element_get_scheduler:
2250 * @element: Element to get manager of.
2252 * Returns the scheduler of the element.
2254 * Returns: Element's scheduler
2257 gst_element_get_scheduler (GstElement *element)
2259 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
2261 return element->sched;
2265 * gst_element_set_loop_function:
2266 * @element: Element to set loop function of.
2267 * @loop: Pointer to loop function.
2269 * This sets the loop function for the element. The function pointed to
2270 * can deviate from the GstElementLoopFunction definition in type of
2273 * NOTE: in order for this to take effect, the current loop function *must*
2274 * exit. Assuming the loop function itself is the only one who will cause
2275 * a new loopfunc to be assigned, this should be no problem.
2278 gst_element_set_loop_function (GstElement *element,
2279 GstElementLoopFunction loop)
2281 g_return_if_fail (GST_IS_ELEMENT (element));
2283 /* set the loop function */
2284 element->loopfunc = loop;
2286 /* set the NEW_LOOPFUNC flag so everyone knows to go try again */
2287 GST_FLAG_SET (element, GST_ELEMENT_NEW_LOOPFUNC);
2291 * gst_element_set_eos:
2292 * @element: element to set to the EOS state
2294 * Perform the actions needed to bring the element in the EOS state.
2297 gst_element_set_eos (GstElement *element)
2299 g_return_if_fail (GST_IS_ELEMENT (element));
2301 GST_DEBUG (GST_CAT_EVENT, "setting EOS on element %s", GST_OBJECT_NAME (element));
2303 gst_element_set_state (element, GST_STATE_PAUSED);
2305 g_signal_emit (G_OBJECT (element), gst_element_signals[EOS], 0);
2310 * gst_element_state_get_name:
2311 * @state: a #GstElementState to get the name of
2313 * Gets a string representing the given state.
2315 * Returns: a string with the statename.
2318 gst_element_state_get_name (GstElementState state)
2321 #ifdef GST_DEBUG_COLOR
2322 case GST_STATE_VOID_PENDING: return "NONE_PENDING";break;
2323 case GST_STATE_NULL: return "\033[01;37mNULL\033[00m";break;
2324 case GST_STATE_READY: return "\033[01;31mREADY\033[00m";break;
2325 case GST_STATE_PLAYING: return "\033[01;32mPLAYING\033[00m";break;
2326 case GST_STATE_PAUSED: return "\033[01;33mPAUSED\033[00m";break;
2327 default: return g_strdup_printf ("\033[01;37;41mUNKNOWN!\033[00m(%d)", state);
2329 case GST_STATE_VOID_PENDING: return "NONE_PENDING";break;
2330 case GST_STATE_NULL: return "NULL";break;
2331 case GST_STATE_READY: return "READY";break;
2332 case GST_STATE_PLAYING: return "PLAYING";break;
2333 case GST_STATE_PAUSED: return "PAUSED";break;
2334 default: return "UNKNOWN!";
2341 gst_element_populate_std_props (GObjectClass * klass,
2342 const gchar *prop_name, guint arg_id, GParamFlags flags)
2344 GQuark prop_id = g_quark_from_string (prop_name);
2347 static GQuark fd_id = 0;
2348 static GQuark blocksize_id;
2349 static GQuark bytesperread_id;
2350 static GQuark dump_id;
2351 static GQuark filesize_id;
2352 static GQuark mmapsize_id;
2353 static GQuark location_id;
2354 static GQuark offset_id;
2355 static GQuark silent_id;
2356 static GQuark touch_id;
2359 fd_id = g_quark_from_static_string ("fd");
2360 blocksize_id = g_quark_from_static_string ("blocksize");
2361 bytesperread_id = g_quark_from_static_string ("bytesperread");
2362 dump_id = g_quark_from_static_string ("dump");
2363 filesize_id = g_quark_from_static_string ("filesize");
2364 mmapsize_id = g_quark_from_static_string ("mmapsize");
2365 location_id = g_quark_from_static_string ("location");
2366 offset_id = g_quark_from_static_string ("offset");
2367 silent_id = g_quark_from_static_string ("silent");
2368 touch_id = g_quark_from_static_string ("touch");
2371 if (prop_id == fd_id) {
2372 pspec = g_param_spec_int ("fd", "File-descriptor",
2373 "File-descriptor for the file being read",
2374 0, G_MAXINT, 0, flags);
2376 else if (prop_id == blocksize_id) {
2377 pspec = g_param_spec_ulong ("blocksize", "Block Size",
2378 "Block size to read per buffer",
2379 0, G_MAXULONG, 4096, flags);
2382 else if (prop_id == bytesperread_id) {
2383 pspec = g_param_spec_int ("bytesperread", "Bytes per read",
2384 "Number of bytes to read per buffer",
2385 G_MININT, G_MAXINT, 0, flags);
2388 else if (prop_id == dump_id) {
2389 pspec = g_param_spec_boolean ("dump", "Dump", "Dump bytes to stdout", FALSE, flags);
2392 else if (prop_id == filesize_id) {
2393 pspec = g_param_spec_int64 ("filesize", "File Size",
2394 "Size of the file being read",
2395 0, G_MAXINT64, 0, flags);
2398 else if (prop_id == mmapsize_id) {
2399 pspec = g_param_spec_ulong ("mmapsize", "mmap() Block Size",
2400 "Size in bytes of mmap()d regions",
2401 0, G_MAXULONG, 4 * 1048576, flags);
2404 else if (prop_id == location_id) {
2405 pspec = g_param_spec_string ("location", "File Location",
2406 "Location of the file to read",
2410 else if (prop_id == offset_id) {
2411 pspec = g_param_spec_int64 ("offset", "File Offset",
2412 "Byte offset of current read pointer",
2413 0, G_MAXINT64, 0, flags);
2416 else if (prop_id == silent_id) {
2417 pspec = g_param_spec_boolean ("silent", "Silent", "Don't produce events",
2421 else if (prop_id == touch_id) {
2422 pspec = g_param_spec_boolean ("touch", "Touch read data",
2423 "Touch data to force disk read before "
2424 "push ()", TRUE, flags);
2427 g_warning ("Unknown - 'standard' property '%s' id %d from klass %s",
2428 prop_name, arg_id, g_type_name (G_OBJECT_CLASS_TYPE (klass)));
2433 g_object_class_install_property (klass, arg_id, pspec);
2438 * gst_element_class_install_std_props:
2439 * @klass: the class to add the properties to
2440 * @first_name: the first in a NULL terminated
2441 * 'name', 'id', 'flags' triplet list.
2442 * @...: the triplet list
2444 * Add a list of standardized properties with types to the @klass.
2445 * the id is for the property switch in your get_prop method, and
2446 * the flags determine readability / writeability.
2449 gst_element_class_install_std_props (GstElementClass * klass, const gchar *first_name, ...)
2455 g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
2457 va_start (args, first_name);
2462 int arg_id = va_arg (args, int);
2463 int flags = va_arg (args, int);
2465 gst_element_populate_std_props ((GObjectClass *) klass, name, arg_id, flags);
2467 name = va_arg (args, char *);
2474 * gst_element_get_managing_bin:
2475 * @element: a #GstElement
2477 * Gets the managing bin (a pipeline or a thread, for example) of an element.
2479 * Returns: the #GstBin, or NULL on failure
2482 gst_element_get_managing_bin (GstElement *element)
2486 g_return_val_if_fail (element != NULL, NULL);
2488 bin = GST_BIN (gst_object_get_parent (GST_OBJECT_CAST (element)));
2490 while (bin && !GST_FLAG_IS_SET (GST_OBJECT_CAST (bin), GST_BIN_FLAG_MANAGER))
2491 bin = GST_BIN (gst_object_get_parent (GST_OBJECT_CAST (bin)));