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 #include "gst_private.h"
26 #include <gobject/gvaluecollector.h>
28 #include "gstelement.h"
30 #include "gstmarshal.h"
32 #include "gstscheduler.h"
36 #include "gst-i18n-lib.h"
38 /* Element signals and args */
58 extern void __gst_element_details_clear (GstElementDetails * dp);
59 extern void __gst_element_details_copy (GstElementDetails * dest,
60 const GstElementDetails * src);
62 static void gst_element_class_init (GstElementClass * klass);
63 static void gst_element_init (GstElement * element);
64 static void gst_element_base_class_init (gpointer g_class);
65 static void gst_element_base_class_finalize (gpointer g_class);
67 static void gst_element_real_set_property (GObject * object, guint prop_id,
68 const GValue * value, GParamSpec * pspec);
69 static void gst_element_real_get_property (GObject * object, guint prop_id,
70 GValue * value, GParamSpec * pspec);
72 static void gst_element_dispose (GObject * object);
74 static GstElementStateReturn gst_element_change_state (GstElement * element);
75 static void gst_element_error_func (GstElement * element, GstElement * source,
76 GError * error, gchar * debug);
77 static void gst_element_found_tag_func (GstElement * element,
78 GstElement * source, const GstTagList * tag_list);
80 #ifndef GST_DISABLE_LOADSAVE
81 static xmlNodePtr gst_element_save_thyself (GstObject * object,
83 static void gst_element_restore_thyself (GstObject * parent, xmlNodePtr self);
86 GType _gst_element_type = 0;
88 static GstObjectClass *parent_class = NULL;
89 static guint gst_element_signals[LAST_SIGNAL] = { 0 };
92 gst_element_get_type (void)
94 if (!_gst_element_type) {
95 static const GTypeInfo element_info = {
96 sizeof (GstElementClass),
97 gst_element_base_class_init,
98 gst_element_base_class_finalize,
99 (GClassInitFunc) gst_element_class_init,
104 (GInstanceInitFunc) gst_element_init,
108 _gst_element_type = g_type_register_static (GST_TYPE_OBJECT, "GstElement",
109 &element_info, G_TYPE_FLAG_ABSTRACT);
111 return _gst_element_type;
115 gst_element_class_init (GstElementClass * klass)
117 GObjectClass *gobject_class;
118 GstObjectClass *gstobject_class;
120 gobject_class = (GObjectClass *) klass;
121 gstobject_class = (GstObjectClass *) klass;
123 parent_class = g_type_class_ref (GST_TYPE_OBJECT);
125 gst_element_signals[STATE_CHANGE] =
126 g_signal_new ("state-change", G_TYPE_FROM_CLASS (klass),
127 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstElementClass, state_change), NULL,
128 NULL, gst_marshal_VOID__INT_INT, G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT);
129 gst_element_signals[NEW_PAD] =
130 g_signal_new ("new-pad", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
131 G_STRUCT_OFFSET (GstElementClass, new_pad), NULL, NULL,
132 gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT);
133 gst_element_signals[PAD_REMOVED] =
134 g_signal_new ("pad-removed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
135 G_STRUCT_OFFSET (GstElementClass, pad_removed), NULL, NULL,
136 gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT);
137 gst_element_signals[ERROR] =
138 g_signal_new ("error", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
139 G_STRUCT_OFFSET (GstElementClass, error), NULL, NULL,
140 gst_marshal_VOID__OBJECT_OBJECT_STRING, G_TYPE_NONE, 3, GST_TYPE_ELEMENT,
141 GST_TYPE_G_ERROR, G_TYPE_STRING);
142 gst_element_signals[EOS] =
143 g_signal_new ("eos", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
144 G_STRUCT_OFFSET (GstElementClass, eos), NULL, NULL,
145 gst_marshal_VOID__VOID, G_TYPE_NONE, 0);
146 gst_element_signals[FOUND_TAG] =
147 g_signal_new ("found-tag", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
148 G_STRUCT_OFFSET (GstElementClass, found_tag), NULL, NULL,
149 gst_marshal_VOID__OBJECT_BOXED, G_TYPE_NONE, 2, GST_TYPE_ELEMENT,
151 gst_element_signals[NO_MORE_PADS] =
152 g_signal_new ("no-more-pads", G_TYPE_FROM_CLASS (klass),
153 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstElementClass, no_more_pads), NULL,
154 NULL, gst_marshal_VOID__VOID, G_TYPE_NONE, 0);
156 gobject_class->set_property =
157 GST_DEBUG_FUNCPTR (gst_element_real_set_property);
158 gobject_class->get_property =
159 GST_DEBUG_FUNCPTR (gst_element_real_get_property);
161 gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_element_dispose);
163 #ifndef GST_DISABLE_LOADSAVE
164 gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_element_save_thyself);
165 gstobject_class->restore_thyself =
166 GST_DEBUG_FUNCPTR (gst_element_restore_thyself);
169 klass->change_state = GST_DEBUG_FUNCPTR (gst_element_change_state);
170 klass->error = GST_DEBUG_FUNCPTR (gst_element_error_func);
171 klass->found_tag = GST_DEBUG_FUNCPTR (gst_element_found_tag_func);
172 klass->numpadtemplates = 0;
174 klass->elementfactory = NULL;
178 gst_element_base_class_init (gpointer g_class)
180 GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
181 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
184 gobject_class->set_property =
185 GST_DEBUG_FUNCPTR (gst_element_real_set_property);
186 gobject_class->get_property =
187 GST_DEBUG_FUNCPTR (gst_element_real_get_property);
189 memset (&element_class->details, 0, sizeof (GstElementDetails));
190 element_class->padtemplates = NULL;
194 gst_element_base_class_finalize (gpointer g_class)
196 GstElementClass *klass = GST_ELEMENT_CLASS (g_class);
198 g_list_foreach (klass->padtemplates, (GFunc) gst_object_unref, NULL);
199 g_list_free (klass->padtemplates);
200 __gst_element_details_clear (&klass->details);
204 gst_element_init (GstElement * element)
206 element->current_state = GST_STATE_NULL;
207 element->pending_state = GST_STATE_VOID_PENDING;
208 element->numpads = 0;
209 element->numsrcpads = 0;
210 element->numsinkpads = 0;
211 element->pads = NULL;
212 element->loopfunc = NULL;
213 element->sched = NULL;
214 element->clock = NULL;
215 element->sched_private = NULL;
216 element->state_mutex = g_mutex_new ();
217 element->state_cond = g_cond_new ();
221 gst_element_real_set_property (GObject * object, guint prop_id,
222 const GValue * value, GParamSpec * pspec)
224 GstElementClass *oclass = GST_ELEMENT_GET_CLASS (object);
226 if (oclass->set_property)
227 (oclass->set_property) (object, prop_id, value, pspec);
231 gst_element_real_get_property (GObject * object, guint prop_id, GValue * value,
234 GstElementClass *oclass = GST_ELEMENT_GET_CLASS (object);
236 if (oclass->get_property)
237 (oclass->get_property) (object, prop_id, value, pspec);
241 * gst_element_default_error:
242 * @object: a #GObject that signalled the error.
243 * @orig: the #GstObject that initiated the error.
244 * @error: the GError.
245 * @debug: an additional debug information string, or NULL.
247 * A default error signal callback to attach to an element.
248 * The user data passed to the g_signal_connect is ignored.
250 * The default handler will simply print the error string using g_print.
253 gst_element_default_error (GObject * object, GstObject * source, GError * error,
256 gchar *name = gst_object_get_path_string (source);
258 g_print (_("ERROR: from element %s: %s\n"), name, error->message);
260 g_print (_("Additional debug info:\n%s\n"), debug);
267 const GParamSpec *pspec;
273 element_set_property (GstElement * element, const GParamSpec * pspec,
274 const GValue * value)
276 prop_value_t *prop_value = g_new0 (prop_value_t, 1);
278 prop_value->pspec = pspec;
279 prop_value->value = *value;
281 g_async_queue_push (element->prop_value_queue, prop_value);
285 element_get_property (GstElement * element, const GParamSpec * pspec,
288 g_mutex_lock (element->property_mutex);
289 g_object_get_property ((GObject *) element, pspec->name, value);
290 g_mutex_unlock (element->property_mutex);
294 gst_element_threadsafe_properties_pre_run (GstElement * element)
296 GST_DEBUG ("locking element %s", GST_OBJECT_NAME (element));
297 g_mutex_lock (element->property_mutex);
298 gst_element_set_pending_properties (element);
302 gst_element_threadsafe_properties_post_run (GstElement * element)
304 GST_DEBUG ("unlocking element %s", GST_OBJECT_NAME (element));
305 g_mutex_unlock (element->property_mutex);
309 * gst_element_enable_threadsafe_properties:
310 * @element: a #GstElement to enable threadsafe properties on.
312 * Installs an asynchronous queue, a mutex and pre- and post-run functions on
313 * this element so that properties on the element can be set in a
317 gst_element_enable_threadsafe_properties (GstElement * element)
319 g_return_if_fail (GST_IS_ELEMENT (element));
321 GST_FLAG_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES);
322 element->pre_run_func = gst_element_threadsafe_properties_pre_run;
323 element->post_run_func = gst_element_threadsafe_properties_post_run;
324 if (!element->prop_value_queue)
325 element->prop_value_queue = g_async_queue_new ();
326 if (!element->property_mutex)
327 element->property_mutex = g_mutex_new ();
331 * gst_element_disable_threadsafe_properties:
332 * @element: a #GstElement to disable threadsafe properties on.
334 * Removes the threadsafe properties, post- and pre-run locks from
338 gst_element_disable_threadsafe_properties (GstElement * element)
340 g_return_if_fail (GST_IS_ELEMENT (element));
342 GST_FLAG_UNSET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES);
343 element->pre_run_func = NULL;
344 element->post_run_func = NULL;
345 /* let's keep around that async queue */
349 * gst_element_set_pending_properties:
350 * @element: a #GstElement to set the pending properties on.
352 * Sets all pending properties on the threadsafe properties enabled
356 gst_element_set_pending_properties (GstElement * element)
358 prop_value_t *prop_value;
360 while ((prop_value = g_async_queue_try_pop (element->prop_value_queue))) {
361 g_object_set_property ((GObject *) element, prop_value->pspec->name,
363 g_value_unset (&prop_value->value);
368 /* following 6 functions taken mostly from gobject.c */
372 * @element: a #GstElement to set properties on.
373 * @first_property_name: the first property to set.
374 * @...: value of the first property, and more properties to set, ending
377 * Sets properties on an element. If the element uses threadsafe properties,
378 * they will be queued and set on the object when it is scheduled again.
381 gst_element_set (GstElement * element, const gchar * first_property_name, ...)
385 g_return_if_fail (GST_IS_ELEMENT (element));
387 va_start (var_args, first_property_name);
388 gst_element_set_valist (element, first_property_name, var_args);
394 * @element: a #GstElement to get properties of.
395 * @first_property_name: the first property to get.
396 * @...: pointer to a variable to store the first property in, as well as
397 * more properties to get, ending with NULL.
399 * Gets properties from an element. If the element uses threadsafe properties,
400 * the element will be locked before getting the given properties.
403 gst_element_get (GstElement * element, const gchar * first_property_name, ...)
407 g_return_if_fail (GST_IS_ELEMENT (element));
409 va_start (var_args, first_property_name);
410 gst_element_get_valist (element, first_property_name, var_args);
415 * gst_element_set_valist:
416 * @element: a #GstElement to set properties on.
417 * @first_property_name: the first property to set.
418 * @var_args: the var_args list of other properties to get.
420 * Sets properties on an element. If the element uses threadsafe properties,
421 * the property change will be put on the async queue.
424 gst_element_set_valist (GstElement * element, const gchar * first_property_name,
430 g_return_if_fail (GST_IS_ELEMENT (element));
432 object = (GObject *) element;
434 GST_CAT_DEBUG (GST_CAT_PROPERTIES,
435 "setting valist of properties starting with %s on element %s",
436 first_property_name, gst_element_get_name (element));
438 if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
439 g_object_set_valist (object, first_property_name, var_args);
443 g_object_ref (object);
445 name = first_property_name;
448 GValue value = { 0, };
452 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), name);
455 g_warning ("%s: object class `%s' has no property named `%s'",
456 G_STRLOC, G_OBJECT_TYPE_NAME (object), name);
459 if (!(pspec->flags & G_PARAM_WRITABLE)) {
460 g_warning ("%s: property `%s' of object class `%s' is not writable",
461 G_STRLOC, pspec->name, G_OBJECT_TYPE_NAME (object));
465 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
467 G_VALUE_COLLECT (&value, var_args, 0, &error);
469 g_warning ("%s: %s", G_STRLOC, error);
472 /* we purposely leak the value here, it might not be
473 * in a sane state if an error condition occoured
478 element_set_property (element, pspec, &value);
479 g_value_unset (&value);
481 name = va_arg (var_args, gchar *);
484 g_object_unref (object);
488 * gst_element_get_valist:
489 * @element: a #GstElement to get properties of.
490 * @first_property_name: the first property to get.
491 * @var_args: the var_args list of other properties to get.
493 * Gets properties from an element. If the element uses threadsafe properties,
494 * the element will be locked before getting the given properties.
497 gst_element_get_valist (GstElement * element, const gchar * first_property_name,
503 g_return_if_fail (GST_IS_ELEMENT (element));
505 object = (GObject *) element;
507 if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
508 g_object_get_valist (object, first_property_name, var_args);
512 g_object_ref (object);
514 name = first_property_name;
517 GValue value = { 0, };
521 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), name);
524 g_warning ("%s: object class `%s' has no property named `%s'",
525 G_STRLOC, G_OBJECT_TYPE_NAME (object), name);
528 if (!(pspec->flags & G_PARAM_READABLE)) {
529 g_warning ("%s: property `%s' of object class `%s' is not readable",
530 G_STRLOC, pspec->name, G_OBJECT_TYPE_NAME (object));
534 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
536 element_get_property (element, pspec, &value);
538 G_VALUE_LCOPY (&value, var_args, 0, &error);
540 g_warning ("%s: %s", G_STRLOC, error);
542 g_value_unset (&value);
546 g_value_unset (&value);
548 name = va_arg (var_args, gchar *);
551 g_object_unref (object);
555 * gst_element_set_property:
556 * @element: a #GstElement to set properties on.
557 * @property_name: the first property to get.
558 * @value: the #GValue that holds the value to set.
560 * Sets a property on an element. If the element uses threadsafe properties,
561 * the property will be put on the async queue.
564 gst_element_set_property (GstElement * element, const gchar * property_name,
565 const GValue * value)
570 g_return_if_fail (GST_IS_ELEMENT (element));
571 g_return_if_fail (property_name != NULL);
572 g_return_if_fail (G_IS_VALUE (value));
574 object = (GObject *) element;
576 GST_CAT_DEBUG (GST_CAT_PROPERTIES, "setting property %s on element %s",
577 property_name, gst_element_get_name (element));
578 if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
579 g_object_set_property (object, property_name, value);
583 g_object_ref (object);
585 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object),
589 g_warning ("%s: object class `%s' has no property named `%s'",
590 G_STRLOC, G_OBJECT_TYPE_NAME (object), property_name);
592 element_set_property (element, pspec, value);
594 g_object_unref (object);
598 * gst_element_get_property:
599 * @element: a #GstElement to get properties of.
600 * @property_name: the first property to get.
601 * @value: the #GValue to store the property value in.
603 * Gets a property from an element. If the element uses threadsafe properties,
604 * the element will be locked before getting the given property.
607 gst_element_get_property (GstElement * element, const gchar * property_name,
613 g_return_if_fail (GST_IS_ELEMENT (element));
614 g_return_if_fail (property_name != NULL);
615 g_return_if_fail (G_IS_VALUE (value));
617 object = (GObject *) element;
619 if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
620 g_object_get_property (object, property_name, value);
624 g_object_ref (object);
627 g_object_class_find_property (G_OBJECT_GET_CLASS (object), property_name);
630 g_warning ("%s: object class `%s' has no property named `%s'",
631 G_STRLOC, G_OBJECT_TYPE_NAME (object), property_name);
633 GValue *prop_value, tmp_value = { 0, };
635 /* auto-conversion of the callers value type
637 if (G_VALUE_TYPE (value) == G_PARAM_SPEC_VALUE_TYPE (pspec)) {
638 g_value_reset (value);
640 } else if (!g_value_type_transformable (G_PARAM_SPEC_VALUE_TYPE (pspec),
641 G_VALUE_TYPE (value))) {
643 ("can't retrieve property `%s' of type `%s' as value of type `%s'",
644 pspec->name, g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
645 G_VALUE_TYPE_NAME (value));
646 g_object_unref (object);
649 g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
650 prop_value = &tmp_value;
652 element_get_property (element, pspec, prop_value);
653 if (prop_value != value) {
654 g_value_transform (prop_value, value);
655 g_value_unset (&tmp_value);
659 g_object_unref (object);
663 gst_element_request_pad (GstElement * element, GstPadTemplate * templ,
666 GstPad *newpad = NULL;
667 GstElementClass *oclass;
669 oclass = GST_ELEMENT_GET_CLASS (element);
671 if (oclass->request_new_pad)
672 newpad = (oclass->request_new_pad) (element, templ, name);
678 * gst_element_release_request_pad:
679 * @element: a #GstElement to release the request pad of.
680 * @pad: the #GstPad to release.
682 * Makes the element free the previously requested pad as obtained
683 * with gst_element_get_request_pad().
686 gst_element_release_request_pad (GstElement * element, GstPad * pad)
688 GstElementClass *oclass;
690 g_return_if_fail (GST_IS_ELEMENT (element));
691 g_return_if_fail (GST_IS_PAD (pad));
693 oclass = GST_ELEMENT_GET_CLASS (element);
695 if (oclass->release_pad)
696 (oclass->release_pad) (element, pad);
700 * gst_element_requires_clock:
701 * @element: a #GstElement to query
703 * Query if the element requiresd a clock
705 * Returns: TRUE if the element requires a clock
708 gst_element_requires_clock (GstElement * element)
710 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
712 return (GST_ELEMENT_GET_CLASS (element)->set_clock != NULL);
716 * gst_element_provides_clock:
717 * @element: a #GstElement to query
719 * Query if the element provides a clock
721 * Returns: TRUE if the element provides a clock
724 gst_element_provides_clock (GstElement * element)
726 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
728 return (GST_ELEMENT_GET_CLASS (element)->get_clock != NULL);
732 * gst_element_set_clock:
733 * @element: a #GstElement to set the clock for.
734 * @clock: the #GstClock to set for the element.
736 * Sets the clock for the element.
739 gst_element_set_clock (GstElement * element, GstClock * clock)
741 GstElementClass *oclass;
743 g_return_if_fail (GST_IS_ELEMENT (element));
745 oclass = GST_ELEMENT_GET_CLASS (element);
747 if (oclass->set_clock)
748 oclass->set_clock (element, clock);
750 gst_object_replace ((GstObject **) & element->clock, (GstObject *) clock);
754 * gst_element_get_clock:
755 * @element: a #GstElement to get the clock of.
757 * Gets the clock of the element.
759 * Returns: the #GstClock of the element.
762 gst_element_get_clock (GstElement * element)
764 GstElementClass *oclass;
766 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
768 oclass = GST_ELEMENT_GET_CLASS (element);
770 if (oclass->get_clock)
771 return oclass->get_clock (element);
777 * gst_element_clock_wait:
778 * @element: a #GstElement.
779 * @id: the #GstClock to use.
780 * @jitter: the difference between requested time and actual time.
782 * Waits for a specific time on the clock.
784 * Returns: the #GstClockReturn result of the wait operation.
787 gst_element_clock_wait (GstElement * element, GstClockID id,
788 GstClockTimeDiff * jitter)
792 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_CLOCK_ERROR);
794 if (GST_ELEMENT_SCHED (element)) {
795 GST_CAT_DEBUG (GST_CAT_CLOCK, "waiting on scheduler clock with id %d");
797 gst_scheduler_clock_wait (GST_ELEMENT_SCHED (element), element, id,
800 GST_CAT_DEBUG (GST_CAT_CLOCK, "no scheduler, returning GST_CLOCK_TIMEOUT");
801 res = GST_CLOCK_TIMEOUT;
807 #undef GST_CAT_DEFAULT
808 #define GST_CAT_DEFAULT GST_CAT_CLOCK
810 * gst_element_get_time:
811 * @element: element to query
813 * Query the element's time. FIXME: The element must use
815 * Returns: the current stream time in #GST_STATE_PLAYING,
816 * the element base time in #GST_STATE_PAUSED,
817 * or #GST_CLOCK_TIME_NONE otherwise.
819 /* FIXME: this should always return time on the same scale. Now it returns
820 * the (absolute) base_time in PAUSED and the (current running) time in
822 * Solution: have a get_base_time and make the element subtract if it needs
823 * to. In PAUSED return the same as PLAYING, ie. the current timestamp where
824 * the element is at according to the provided clock.
827 gst_element_get_time (GstElement * element)
829 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_CLOCK_TIME_NONE);
831 if (element->clock == NULL) {
832 GST_WARNING_OBJECT (element, "element queries time but has no clock");
833 return GST_CLOCK_TIME_NONE;
835 switch (element->current_state) {
837 case GST_STATE_READY:
838 return GST_CLOCK_TIME_NONE;
839 case GST_STATE_PAUSED:
840 return element->base_time;
841 case GST_STATE_PLAYING:
842 return gst_clock_get_time (element->clock) - element->base_time;
844 g_assert_not_reached ();
845 return GST_CLOCK_TIME_NONE;
851 * @element: element that should wait
852 * @timestamp: what timestamp to wait on
854 * Waits until the given relative time stamp for the element has arrived.
855 * When this function returns successfully, the relative time point specified
856 * in the timestamp has passed for this element.
857 * <note>This function can only be called on elements in
858 * #GST_STATE_PLAYING</note>
860 * Returns: TRUE on success.
863 gst_element_wait (GstElement * element, GstClockTime timestamp)
869 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
870 g_return_val_if_fail (GST_IS_CLOCK (element->clock), FALSE);
871 g_return_val_if_fail (element->current_state == GST_STATE_PLAYING, FALSE);
872 g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
874 /* shortcut when we're already late... */
875 time = gst_element_get_time (element);
876 GST_CAT_LOG_OBJECT (GST_CAT_CLOCK, element, "element time %" GST_TIME_FORMAT,
877 GST_TIME_ARGS (time));
878 if (time >= timestamp) {
879 GST_CAT_INFO_OBJECT (GST_CAT_CLOCK, element,
880 "called gst_element_wait (% " GST_TIME_FORMAT ") and was late (%"
881 GST_TIME_FORMAT, GST_TIME_ARGS (timestamp),
882 GST_TIME_ARGS (gst_element_get_time (element)));
886 id = gst_clock_new_single_shot_id (element->clock,
887 element->base_time + timestamp);
888 ret = gst_element_clock_wait (element, id, NULL);
889 gst_clock_id_free (id);
891 return ret == GST_CLOCK_STOPPED;
895 * gst_element_set_time:
896 * @element: element to set time on
899 * Sets the current time of the element. This function can be used when handling
900 * discont events. You can only call this function on an element with a clock in
901 * #GST_STATE_PAUSED or #GST_STATE_PLAYING. You might want to have a look at
902 * gst_element_adjust_time(), if you want to adjust by a difference as that is
906 gst_element_set_time (GstElement * element, GstClockTime time)
908 gst_element_set_time_delay (element, time, 0);
912 * gst_element_set_time_delay:
913 * @element: element to set time on
915 * @delay: a delay to discount from the given time
917 * Sets the current time of the element to time - delay. This function can be
918 * used when handling discont events in elements writing to an external buffer,
919 * i. e., an audio sink that writes to a sound card that buffers the sound
920 * before playing it. The delay should be the current buffering delay.
922 * You can only call this function on an element with a clock in
923 * #GST_STATE_PAUSED or #GST_STATE_PLAYING. You might want to have a look at
924 * gst_element_adjust_time(), if you want to adjust by a difference as that is
928 gst_element_set_time_delay (GstElement * element, GstClockTime time,
931 GstClockTime event_time;
933 g_return_if_fail (GST_IS_ELEMENT (element));
934 g_return_if_fail (GST_IS_CLOCK (element->clock));
935 g_return_if_fail (element->current_state >= GST_STATE_PAUSED);
936 g_return_if_fail (time >= delay);
938 switch (element->current_state) {
939 case GST_STATE_PAUSED:
940 element->base_time = time - delay;
942 case GST_STATE_PLAYING:
943 event_time = gst_clock_get_event_time_delay (element->clock, delay);
944 GST_CAT_LOG_OBJECT (GST_CAT_CLOCK, element,
945 "clock time %" GST_TIME_FORMAT ": setting element time to %"
946 GST_TIME_FORMAT, GST_TIME_ARGS (event_time), GST_TIME_ARGS (time));
947 element->base_time = event_time - time;
950 g_assert_not_reached ();
956 * gst_element_adjust_time:
957 * @element: element to adjust time on
958 * @diff: difference to adjust
960 * Adjusts the current time of the element by the specified difference. This
961 * function can be used when handling discont events. You can only call this
962 * function on an element with a clock in #GST_STATE_PAUSED or
963 * #GST_STATE_PLAYING. It is more accurate than gst_element_set_time().
966 gst_element_adjust_time (GstElement * element, GstClockTimeDiff diff)
970 g_return_if_fail (GST_IS_ELEMENT (element));
971 g_return_if_fail (GST_IS_CLOCK (element->clock));
972 g_return_if_fail (element->current_state >= GST_STATE_PAUSED);
974 switch (element->current_state) {
975 case GST_STATE_PAUSED:
976 if (diff < 0 && element->base_time < abs (diff)) {
977 g_warning ("attempted to set the current time of element %s below 0",
978 GST_OBJECT_NAME (element));
979 element->base_time = 0;
981 element->base_time += diff;
984 case GST_STATE_PLAYING:
985 time = gst_clock_get_time (element->clock);
986 if (time < element->base_time - diff) {
987 g_warning ("attempted to set the current time of element %s below 0",
988 GST_OBJECT_NAME (element));
989 element->base_time = time;
991 element->base_time -= diff;
995 g_assert_not_reached ();
1000 #undef GST_CAT_DEFAULT
1002 #ifndef GST_DISABLE_INDEX
1004 * gst_element_is_indexable:
1005 * @element: a #GstElement.
1007 * Queries if the element can be indexed.
1009 * Returns: TRUE if the element can be indexed.
1012 gst_element_is_indexable (GstElement * element)
1014 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1016 return (GST_ELEMENT_GET_CLASS (element)->set_index != NULL);
1020 * gst_element_set_index:
1021 * @element: a #GstElement.
1022 * @index: a #GstIndex.
1024 * Set the specified GstIndex on the element.
1027 gst_element_set_index (GstElement * element, GstIndex * index)
1029 GstElementClass *oclass;
1031 g_return_if_fail (GST_IS_ELEMENT (element));
1032 g_return_if_fail (GST_IS_INDEX (index));
1034 oclass = GST_ELEMENT_GET_CLASS (element);
1036 if (oclass->set_index)
1037 oclass->set_index (element, index);
1041 * gst_element_get_index:
1042 * @element: a #GstElement.
1044 * Gets the index from the element.
1046 * Returns: a #GstIndex or NULL when no index was set on the
1050 gst_element_get_index (GstElement * element)
1052 GstElementClass *oclass;
1054 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1056 oclass = GST_ELEMENT_GET_CLASS (element);
1058 if (oclass->get_index)
1059 return oclass->get_index (element);
1066 * gst_element_release_locks:
1067 * @element: a #GstElement to release all locks on.
1069 * Instruct the element to release all the locks it is holding, such as
1070 * blocking reads, waiting for the clock, ...
1072 * Returns: TRUE if the locks could be released.
1075 gst_element_release_locks (GstElement * element)
1077 GstElementClass *oclass;
1079 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1081 oclass = GST_ELEMENT_GET_CLASS (element);
1083 if (oclass->release_locks)
1084 return oclass->release_locks (element);
1090 * gst_element_add_pad:
1091 * @element: a #GstElement to add the pad to.
1092 * @pad: the #GstPad to add to the element.
1094 * Adds a pad (link point) to @element. @pad's parent will be set to @element;
1095 * see gst_object_set_parent() for refcounting information.
1097 * Pads are automatically activated when the element is in state PLAYING.
1100 gst_element_add_pad (GstElement * element, GstPad * pad)
1102 g_return_if_fail (GST_IS_ELEMENT (element));
1103 g_return_if_fail (GST_IS_PAD (pad));
1105 /* first check to make sure the pad hasn't already been added to another
1107 g_return_if_fail (GST_PAD_PARENT (pad) == NULL);
1109 /* then check to see if there's already a pad by that name here */
1110 g_return_if_fail (gst_object_check_uniqueness (element->pads,
1111 GST_PAD_NAME (pad)) == TRUE);
1113 GST_CAT_INFO_OBJECT (GST_CAT_ELEMENT_PADS, element, "adding pad '%s'",
1114 GST_STR_NULL (GST_OBJECT_NAME (pad)));
1116 /* set the pad's parent */
1117 gst_object_set_parent (GST_OBJECT (pad), GST_OBJECT (element));
1119 /* add it to the list */
1120 element->pads = g_list_append (element->pads, pad);
1123 switch (gst_pad_get_direction (pad)) {
1125 element->numsrcpads++;
1128 element->numsinkpads++;
1131 /* can happen for ghost pads */
1135 /* activate element when we are playing */
1136 if (GST_STATE (element) == GST_STATE_PLAYING)
1137 gst_pad_set_active (pad, TRUE);
1139 /* emit the NEW_PAD signal */
1140 g_signal_emit (G_OBJECT (element), gst_element_signals[NEW_PAD], 0, pad);
1144 * gst_element_add_ghost_pad:
1145 * @element: a #GstElement to add the ghost pad to.
1146 * @pad: the #GstPad from which the new ghost pad will be created.
1147 * @name: the name of the new ghost pad, or NULL to assign a unique name
1150 * Creates a ghost pad from @pad, and adds it to @element via
1151 * gst_element_add_pad().
1153 * Returns: the added ghost #GstPad, or NULL on error.
1156 gst_element_add_ghost_pad (GstElement * element, GstPad * pad,
1161 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1162 g_return_val_if_fail (GST_IS_PAD (pad), NULL);
1164 /* then check to see if there's already a pad by that name here */
1165 g_return_val_if_fail (gst_object_check_uniqueness (element->pads,
1166 name) == TRUE, NULL);
1168 ghostpad = gst_ghost_pad_new (name, pad);
1170 gst_element_add_pad (element, ghostpad);
1176 * gst_element_remove_pad:
1177 * @element: a #GstElement to remove pad from.
1178 * @pad: the #GstPad to remove from the element.
1180 * Removes @pad from @element. @pad will be destroyed if it has not been
1181 * referenced elsewhere.
1184 gst_element_remove_pad (GstElement * element, GstPad * pad)
1186 g_return_if_fail (element != NULL);
1187 g_return_if_fail (GST_IS_ELEMENT (element));
1188 g_return_if_fail (pad != NULL);
1189 g_return_if_fail (GST_IS_PAD (pad));
1191 g_return_if_fail (GST_PAD_PARENT (pad) == element);
1193 if (GST_IS_REAL_PAD (pad)) {
1194 /* unlink if necessary */
1195 if (GST_RPAD_PEER (pad) != NULL) {
1196 gst_pad_unlink (pad, GST_PAD (GST_RPAD_PEER (pad)));
1198 gst_caps_replace (&GST_RPAD_EXPLICIT_CAPS (pad), NULL);
1199 } else if (GST_IS_GHOST_PAD (pad)) {
1200 g_object_set (pad, "real-pad", NULL, NULL);
1203 /* remove it from the list */
1204 element->pads = g_list_remove (element->pads, pad);
1206 switch (gst_pad_get_direction (pad)) {
1208 element->numsrcpads--;
1211 element->numsinkpads--;
1214 /* can happen for ghost pads */
1218 g_signal_emit (G_OBJECT (element), gst_element_signals[PAD_REMOVED], 0, pad);
1220 gst_object_unparent (GST_OBJECT (pad));
1224 * gst_element_remove_ghost_pad:
1225 * @element: a #GstElement to remove the ghost pad from.
1226 * @pad: ghost #GstPad to remove.
1228 * Removes a ghost pad from an element. Deprecated, use gst_element_remove_pad()
1232 gst_element_remove_ghost_pad (GstElement * element, GstPad * pad)
1234 g_return_if_fail (GST_IS_ELEMENT (element));
1235 g_return_if_fail (GST_IS_GHOST_PAD (pad));
1237 g_warning ("gst_element_remove_ghost_pad is deprecated.\n"
1238 "Use gst_element_remove_pad instead.");
1240 gst_element_remove_pad (element, pad);
1244 * gst_element_no_more_pads:
1245 * @element: a #GstElement
1247 * Use this function to signal that the element does not expect any more pads
1248 * to show up in the current pipeline. This function should be called whenever
1249 * pads have been added by the element itself. Elements with GST_PAD_SOMETIMES
1250 * pad templates use this in combination with autopluggers to figure out that
1251 * the element is done initializing its pads.
1254 gst_element_no_more_pads (GstElement * element)
1256 g_return_if_fail (GST_IS_ELEMENT (element));
1258 g_signal_emit (element, gst_element_signals[NO_MORE_PADS], 0);
1262 * gst_element_get_pad:
1263 * @element: a #GstElement.
1264 * @name: the name of the pad to retrieve.
1266 * Retrieves a pad from @element by name. Tries gst_element_get_static_pad()
1267 * first, then gst_element_get_request_pad().
1269 * Returns: the #GstPad if found, otherwise %NULL.
1272 gst_element_get_pad (GstElement * element, const gchar * name)
1276 g_return_val_if_fail (element != NULL, NULL);
1277 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1278 g_return_val_if_fail (name != NULL, NULL);
1280 pad = gst_element_get_static_pad (element, name);
1282 pad = gst_element_get_request_pad (element, name);
1288 * gst_element_get_static_pad:
1289 * @element: a #GstElement to find a static pad of.
1290 * @name: the name of the static #GstPad to retrieve.
1292 * Retrieves a pad from @element by name. This version only retrieves
1293 * already-existing (i.e. 'static') pads.
1295 * Returns: the requested #GstPad if found, otherwise NULL.
1298 gst_element_get_static_pad (GstElement * element, const gchar * name)
1302 g_return_val_if_fail (element != NULL, NULL);
1303 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1304 g_return_val_if_fail (name != NULL, NULL);
1306 walk = element->pads;
1310 pad = GST_PAD (walk->data);
1311 if (strcmp (GST_PAD_NAME (pad), name) == 0) {
1312 GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "found pad %s:%s",
1313 GST_DEBUG_PAD_NAME (pad));
1316 walk = g_list_next (walk);
1319 GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "no such pad '%s' in element \"%s\"",
1320 name, GST_OBJECT_NAME (element));
1325 * gst_element_get_request_pad:
1326 * @element: a #GstElement to find a request pad of.
1327 * @name: the name of the request #GstPad to retrieve.
1329 * Retrieves a pad from the element by name. This version only retrieves
1332 * Returns: requested #GstPad if found, otherwise NULL.
1335 gst_element_get_request_pad (GstElement * element, const gchar * name)
1337 GstPadTemplate *templ = NULL;
1339 const gchar *req_name = NULL;
1340 gboolean templ_found = FALSE;
1344 gchar *str, *endptr = NULL;
1346 g_return_val_if_fail (element != NULL, NULL);
1347 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1348 g_return_val_if_fail (name != NULL, NULL);
1350 if (strstr (name, "%")) {
1351 templ = gst_element_get_pad_template (element, name);
1356 list = gst_element_get_pad_template_list (element);
1357 while (!templ_found && list) {
1358 templ = (GstPadTemplate *) list->data;
1359 if (templ->presence == GST_PAD_REQUEST) {
1360 /* Because of sanity checks in gst_pad_template_new(), we know that %s
1361 and %d, occurring at the end of the name_template, are the only
1363 GST_CAT_DEBUG (GST_CAT_PADS, "comparing %s to %s", name,
1364 templ->name_template);
1365 if ((str = strchr (templ->name_template, '%'))
1366 && strncmp (templ->name_template, name,
1367 str - templ->name_template) == 0
1368 && strlen (name) > str - templ->name_template) {
1369 data = name + (str - templ->name_template);
1370 if (*(str + 1) == 'd') {
1372 n = (gint) strtol (data, &endptr, 10);
1373 if (endptr && *endptr == '\0') {
1393 pad = gst_element_request_pad (element, templ, req_name);
1399 * gst_element_get_pad_list:
1400 * @element: a #GstElement to get pads of.
1402 * Retrieves a list of @element's pads. The list must not be modified by the
1405 * Returns: the #GList of pads.
1408 gst_element_get_pad_list (GstElement * element)
1410 g_return_val_if_fail (element != NULL, NULL);
1411 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1413 /* return the list of pads */
1414 return element->pads;
1418 * gst_element_class_add_pad_template:
1419 * @klass: the #GstElementClass to add the pad template to.
1420 * @templ: a #GstPadTemplate to add to the element class.
1422 * Adds a padtemplate to an element class. This is mainly used in the _base_init
1423 * functions of classes.
1426 gst_element_class_add_pad_template (GstElementClass * klass,
1427 GstPadTemplate * templ)
1429 g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
1430 g_return_if_fail (GST_IS_PAD_TEMPLATE (templ));
1432 /* avoid registering pad templates with the same name */
1433 g_return_if_fail (gst_element_class_get_pad_template (klass,
1434 templ->name_template) == NULL);
1436 klass->padtemplates = g_list_append (klass->padtemplates,
1437 gst_object_ref (GST_OBJECT (templ)));
1438 klass->numpadtemplates++;
1442 * gst_element_class_set_details:
1443 * @klass: class to set details for
1444 * @details: details to set
1446 * Sets the detailed information for a #GstElementClass.
1447 * <note>This function is for use in _base_init functions only.</note>
1450 gst_element_class_set_details (GstElementClass * klass,
1451 const GstElementDetails * details)
1453 g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
1454 g_return_if_fail (GST_IS_ELEMENT_DETAILS (details));
1456 __gst_element_details_copy (&klass->details, details);
1460 * gst_element_class_get_pad_template_list:
1461 * @element_class: a #GstElementClass to get pad templates of.
1463 * Retrieves a list of the pad templates associated with @element_class. The
1464 * list must not be modified by the calling code.
1465 * <note>If you use this function in the #GInstanceInitFunc of an object class
1466 * that has subclasses, make sure to pass the g_class parameter of the
1467 * #GInstanceInitFunc here.</note>
1469 * Returns: the #GList of padtemplates.
1472 gst_element_class_get_pad_template_list (GstElementClass * element_class)
1474 g_return_val_if_fail (element_class != NULL, NULL);
1475 g_return_val_if_fail (GST_IS_ELEMENT_CLASS (element_class), NULL);
1477 return element_class->padtemplates;
1481 * gst_element_class_get_pad_template:
1482 * @element_class: a #GstElementClass to get the pad template of.
1483 * @name: the name of the #GstPadTemplate to get.
1485 * Retrieves a padtemplate from @element_class with the given name.
1486 * <note>If you use this function in the #GInstanceInitFunc of an object class
1487 * that has subclasses, make sure to pass the g_class parameter of the
1488 * #GInstanceInitFunc here.</note>
1490 * Returns: the #GstPadTemplate with the given name, or NULL if none was found.
1491 * No unreferencing is necessary.
1494 gst_element_class_get_pad_template (GstElementClass * element_class,
1499 g_return_val_if_fail (element_class != NULL, NULL);
1500 g_return_val_if_fail (GST_IS_ELEMENT_CLASS (element_class), NULL);
1501 g_return_val_if_fail (name != NULL, NULL);
1503 padlist = gst_element_class_get_pad_template_list (element_class);
1506 GstPadTemplate *padtempl = (GstPadTemplate *) padlist->data;
1508 if (strcmp (padtempl->name_template, name) == 0)
1511 padlist = g_list_next (padlist);
1518 * gst_element_get_pad_template_list:
1519 * @element: a #GstElement to get pad templates of.
1521 * Retrieves a list of the pad templates associated with the element.
1522 * (FIXME: Should be deprecated in favor of gst_element_class_get_pad_template_list).
1524 * Returns: the #GList of padtemplates.
1527 gst_element_get_pad_template_list (GstElement * element)
1529 g_return_val_if_fail (element != NULL, NULL);
1530 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1532 return GST_ELEMENT_GET_CLASS (element)->padtemplates;
1536 * gst_element_get_pad_template:
1537 * @element: a #GstElement to get the pad template of.
1538 * @name: the name of the #GstPadTemplate to get.
1540 * Retrieves a padtemplate from this element with the
1542 * (FIXME: Should be deprecated in favor of gst_element_class_get_pad_template).
1544 * Returns: the #GstPadTemplate with the given name, or NULL if none was found.
1545 * No unreferencing is necessary.
1548 gst_element_get_pad_template (GstElement * element, const gchar * name)
1550 g_return_val_if_fail (element != NULL, NULL);
1551 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1552 g_return_val_if_fail (name != NULL, NULL);
1554 return gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (element),
1559 * gst_element_get_compatible_pad_template:
1560 * @element: a #GstElement to get a compatible pad template for.
1561 * @compattempl: the #GstPadTemplate to find a compatible template for.
1563 * Retrieves a pad template from @element that is compatible with @compattempl.
1564 * Pads from compatible templates can be linked together.
1566 * Returns: a compatible #GstPadTemplate, or NULL if none was found. No
1567 * unreferencing is necessary.
1570 gst_element_get_compatible_pad_template (GstElement * element,
1571 GstPadTemplate * compattempl)
1573 GstPadTemplate *newtempl = NULL;
1576 g_return_val_if_fail (element != NULL, NULL);
1577 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1578 g_return_val_if_fail (compattempl != NULL, NULL);
1580 padlist = gst_element_get_pad_template_list (element);
1582 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
1583 "Looking for a suitable pad template in %s out of %d templates...",
1584 GST_ELEMENT_NAME (element), g_list_length (padlist));
1587 GstPadTemplate *padtempl = (GstPadTemplate *) padlist->data;
1588 GstCaps *intersection;
1592 * Check direction (must be opposite)
1595 GST_CAT_LOG (GST_CAT_CAPS,
1596 "checking pad template %s", padtempl->name_template);
1597 if (padtempl->direction != compattempl->direction) {
1598 GST_CAT_DEBUG (GST_CAT_CAPS,
1599 "compatible direction: found %s pad template \"%s\"",
1600 padtempl->direction == GST_PAD_SRC ? "src" : "sink",
1601 padtempl->name_template);
1603 intersection = gst_caps_intersect (GST_PAD_TEMPLATE_CAPS (compattempl),
1604 GST_PAD_TEMPLATE_CAPS (padtempl));
1606 GST_CAT_DEBUG (GST_CAT_CAPS, "caps are %scompatible",
1607 (intersection ? "" : "not "));
1609 if (!gst_caps_is_empty (intersection))
1610 newtempl = padtempl;
1611 gst_caps_free (intersection);
1616 padlist = g_list_next (padlist);
1619 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
1620 "Returning new pad template %p", newtempl);
1622 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "No compatible pad template found");
1628 * gst_element_get_pad_from_template:
1629 * @element: a #GstElement.
1630 * @templ: a #GstPadTemplate belonging to @element.
1632 * Gets a pad from @element described by @templ. If the presence of @templ is
1633 * #GST_PAD_REQUEST, requests a new pad. Can return %NULL for #GST_PAD_SOMETIMES
1636 * Returns: the #GstPad, or NULL if one could not be found or created.
1639 gst_element_get_pad_from_template (GstElement * element, GstPadTemplate * templ)
1642 GstPadPresence presence;
1644 /* If this function is ever exported, we need check the validity of `element'
1645 * and `templ', and to make sure the template actually belongs to the
1648 presence = GST_PAD_TEMPLATE_PRESENCE (templ);
1651 case GST_PAD_ALWAYS:
1652 case GST_PAD_SOMETIMES:
1653 ret = gst_element_get_static_pad (element, templ->name_template);
1654 if (!ret && presence == GST_PAD_ALWAYS)
1656 ("Element %s has an ALWAYS template %s, but no pad of the same name",
1657 GST_OBJECT_NAME (element), templ->name_template);
1660 case GST_PAD_REQUEST:
1661 ret = gst_element_request_pad (element, templ, NULL);
1669 * gst_element_request_compatible_pad:
1670 * @element: a #GstElement.
1671 * @templ: the #GstPadTemplate to which the new pad should be able to link.
1673 * Requests a pad from @element. The returned pad should be unlinked and
1674 * compatible with @templ. Might return an existing pad, or request a new one.
1676 * Returns: a #GstPad, or %NULL if one could not be found or created.
1679 gst_element_request_compatible_pad (GstElement * element,
1680 GstPadTemplate * templ)
1682 GstPadTemplate *templ_new;
1685 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1686 g_return_val_if_fail (GST_IS_PAD_TEMPLATE (templ), NULL);
1688 /* FIXME: should really loop through the templates, testing each for
1689 compatibility and pad availability. */
1690 templ_new = gst_element_get_compatible_pad_template (element, templ);
1692 pad = gst_element_get_pad_from_template (element, templ_new);
1694 /* This can happen for non-request pads. No need to unref. */
1695 if (pad && GST_PAD_PEER (pad))
1702 * gst_element_get_compatible_pad_filtered:
1703 * @element: a #GstElement in which the pad should be found.
1704 * @pad: the #GstPad to find a compatible one for.
1705 * @filtercaps: the #GstCaps to use as a filter.
1707 * Looks for an unlinked pad to which the given pad can link. It is not
1708 * guaranteed that linking the pads will work, though it should work in most
1711 * Returns: the #GstPad to which a link can be made, or %NULL if one cannot be
1715 gst_element_get_compatible_pad_filtered (GstElement * element, GstPad * pad,
1716 const GstCaps * filtercaps)
1719 GstPadTemplate *templ;
1721 GstPad *foundpad = NULL;
1723 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1724 g_return_val_if_fail (GST_IS_PAD (pad), NULL);
1726 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
1727 "finding pad in %s compatible with %s:%s and filter %" GST_PTR_FORMAT,
1728 GST_ELEMENT_NAME (element), GST_DEBUG_PAD_NAME (pad), filtercaps);
1730 /* let's use the real pad */
1731 pad = (GstPad *) GST_PAD_REALIZE (pad);
1732 g_return_val_if_fail (pad != NULL, NULL);
1733 g_return_val_if_fail (GST_RPAD_PEER (pad) == NULL, NULL);
1735 /* try to get an existing unlinked pad */
1736 pads = gst_element_get_pad_list (element);
1738 GstPad *current = GST_PAD (pads->data);
1740 GST_CAT_LOG (GST_CAT_ELEMENT_PADS, "examing pad %s:%s",
1741 GST_DEBUG_PAD_NAME (current));
1742 if (GST_PAD_PEER (current) == NULL &&
1743 gst_pad_can_link_filtered (pad, current, filtercaps)) {
1744 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
1745 "found existing unlinked pad %s:%s", GST_DEBUG_PAD_NAME (current));
1748 pads = g_list_next (pads);
1751 /* try to create a new one */
1752 /* requesting is a little crazy, we need a template. Let's create one */
1753 templcaps = gst_pad_get_caps (pad);
1754 if (filtercaps != NULL) {
1757 temp = gst_caps_intersect (filtercaps, templcaps);
1758 gst_caps_free (templcaps);
1762 templ = gst_pad_template_new ((gchar *) GST_PAD_NAME (pad),
1763 GST_PAD_DIRECTION (pad), GST_PAD_ALWAYS, templcaps);
1764 foundpad = gst_element_request_compatible_pad (element, templ);
1765 gst_object_unref (GST_OBJECT (templ));
1768 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
1769 "found existing request pad %s:%s", GST_DEBUG_PAD_NAME (foundpad));
1773 GST_CAT_INFO_OBJECT (GST_CAT_ELEMENT_PADS, element,
1774 "Could not find a compatible pad to link to %s:%s",
1775 GST_DEBUG_PAD_NAME (pad));
1780 * gst_element_get_compatible_pad:
1781 * @element: a #GstElement in which the pad should be found.
1782 * @pad: the #GstPad to find a compatible one for.
1784 * Looks for an unlinked pad to which the given pad can link to.
1785 * It is not guaranteed that linking the pads will work, though
1786 * it should work in most cases.
1788 * Returns: the #GstPad to which a link can be made, or %NULL if one
1789 * could not be found.
1792 gst_element_get_compatible_pad (GstElement * element, GstPad * pad)
1794 return gst_element_get_compatible_pad_filtered (element, pad, NULL);
1798 * gst_element_link_pads_filtered:
1799 * @src: a #GstElement containing the source pad.
1800 * @srcpadname: the name of the #GstPad in source element or NULL for any pad.
1801 * @dest: the #GstElement containing the destination pad.
1802 * @destpadname: the name of the #GstPad in destination element or NULL for any pad.
1803 * @filtercaps: the #GstCaps to use as a filter.
1805 * Links the two named pads of the source and destination elements.
1806 * Side effect is that if one of the pads has no parent, it becomes a
1807 * child of the parent of the other element. If they have different
1808 * parents, the link fails.
1810 * Returns: TRUE if the pads could be linked, FALSE otherwise.
1813 gst_element_link_pads_filtered (GstElement * src, const gchar * srcpadname,
1814 GstElement * dest, const gchar * destpadname, const GstCaps * filtercaps)
1816 const GList *srcpads, *destpads, *srctempls, *desttempls, *l;
1817 GstPad *srcpad, *destpad;
1818 GstPadTemplate *srctempl, *desttempl;
1821 g_return_val_if_fail (GST_IS_ELEMENT (src), FALSE);
1822 g_return_val_if_fail (GST_IS_ELEMENT (dest), FALSE);
1824 GST_CAT_INFO (GST_CAT_ELEMENT_PADS,
1825 "trying to link element %s:%s to element %s:%s", GST_ELEMENT_NAME (src),
1826 srcpadname ? srcpadname : "(any)", GST_ELEMENT_NAME (dest),
1827 destpadname ? destpadname : "(any)");
1829 /* now get the pads we're trying to link and a list of all remaining pads */
1831 srcpad = gst_element_get_pad (src, srcpadname);
1833 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no pad %s:%s",
1834 GST_ELEMENT_NAME (src), srcpadname);
1837 if (!(GST_PAD_DIRECTION (srcpad) == GST_PAD_SRC)) {
1838 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s is no src pad",
1839 GST_DEBUG_PAD_NAME (srcpad));
1842 if (GST_PAD_PEER (srcpad) != NULL) {
1843 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s is already linked",
1844 GST_DEBUG_PAD_NAME (srcpad));
1850 srcpads = gst_element_get_pad_list (src);
1851 srcpad = srcpads ? (GstPad *) GST_PAD_REALIZE (srcpads->data) : NULL;
1854 destpad = gst_element_get_pad (dest, destpadname);
1856 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no pad %s:%s",
1857 GST_ELEMENT_NAME (dest), destpadname);
1860 if (!(GST_PAD_DIRECTION (destpad) == GST_PAD_SINK)) {
1861 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s is no sink pad",
1862 GST_DEBUG_PAD_NAME (destpad));
1865 if (GST_PAD_PEER (destpad) != NULL) {
1866 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s is already linked",
1867 GST_DEBUG_PAD_NAME (destpad));
1873 destpads = gst_element_get_pad_list (dest);
1874 destpad = destpads ? (GstPad *) GST_PAD_REALIZE (destpads->data) : NULL;
1877 if (srcpadname && destpadname) {
1878 /* two explicitly specified pads */
1879 return gst_pad_link_filtered (srcpad, destpad, filtercaps);
1882 /* loop through the allowed pads in the source, trying to find a
1883 * compatible destination pad */
1884 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
1885 "looping through allowed src and dest pads");
1887 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "trying src pad %s:%s",
1888 GST_DEBUG_PAD_NAME (srcpad));
1889 if ((GST_PAD_DIRECTION (srcpad) == GST_PAD_SRC) &&
1890 (GST_PAD_PEER (srcpad) == NULL)) {
1891 GstPad *temp = gst_element_get_compatible_pad_filtered (dest, srcpad,
1894 if (temp && gst_pad_link_filtered (srcpad, temp, filtercaps)) {
1895 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "linked pad %s:%s to pad %s:%s",
1896 GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (temp));
1900 /* find a better way for this mess */
1902 srcpads = g_list_next (srcpads);
1904 srcpad = (GstPad *) GST_PAD_REALIZE (srcpads->data);
1909 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no link possible from %s:%s to %s",
1910 GST_DEBUG_PAD_NAME (srcpad), GST_ELEMENT_NAME (dest));
1914 /* loop through the existing pads in the destination */
1916 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "trying dest pad %s:%s",
1917 GST_DEBUG_PAD_NAME (destpad));
1918 if ((GST_PAD_DIRECTION (destpad) == GST_PAD_SINK) &&
1919 (GST_PAD_PEER (destpad) == NULL)) {
1920 GstPad *temp = gst_element_get_compatible_pad_filtered (src, destpad,
1923 if (temp && gst_pad_link_filtered (temp, destpad, filtercaps)) {
1924 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "linked pad %s:%s to pad %s:%s",
1925 GST_DEBUG_PAD_NAME (temp), GST_DEBUG_PAD_NAME (destpad));
1930 destpads = g_list_next (destpads);
1932 destpad = (GstPad *) GST_PAD_REALIZE (destpads->data);
1937 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no link possible from %s to %s:%s",
1938 GST_ELEMENT_NAME (src), GST_DEBUG_PAD_NAME (destpad));
1942 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
1943 "we might have request pads on both sides, checking...");
1944 srctempls = gst_element_get_pad_template_list (src);
1945 desttempls = gst_element_get_pad_template_list (dest);
1947 if (srctempls && desttempls) {
1949 srctempl = (GstPadTemplate *) srctempls->data;
1950 if (srctempl->presence == GST_PAD_REQUEST) {
1951 for (l = desttempls; l; l = l->next) {
1952 desttempl = (GstPadTemplate *) l->data;
1953 if (desttempl->presence == GST_PAD_REQUEST &&
1954 desttempl->direction != srctempl->direction) {
1955 if (gst_caps_is_always_compatible (gst_pad_template_get_caps
1956 (srctempl), gst_pad_template_get_caps (desttempl))) {
1958 gst_element_get_request_pad (src, srctempl->name_template);
1960 gst_element_get_request_pad (dest, desttempl->name_template);
1961 if (gst_pad_link_filtered (srcpad, destpad, filtercaps)) {
1962 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
1963 "linked pad %s:%s to pad %s:%s",
1964 GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad));
1967 /* it failed, so we release the request pads */
1968 gst_element_release_request_pad (src, srcpad);
1969 gst_element_release_request_pad (dest, destpad);
1974 srctempls = srctempls->next;
1978 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no link possible from %s to %s",
1979 GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (dest));
1984 * gst_element_link_filtered:
1985 * @src: a #GstElement containing the source pad.
1986 * @dest: the #GstElement containing the destination pad.
1987 * @filtercaps: the #GstCaps to use as a filter.
1989 * Links @src to @dest, filtered by @filtercaps. The link must be from source to
1990 * destination; the other direction will not be tried. The function looks for
1991 * existing pads that aren't linked yet. It will request new pads if necessary.
1992 * If multiple links are possible, only one is established.
1994 * Returns: TRUE if the elements could be linked, FALSE otherwise.
1997 gst_element_link_filtered (GstElement * src, GstElement * dest,
1998 const GstCaps * filtercaps)
2000 return gst_element_link_pads_filtered (src, NULL, dest, NULL, filtercaps);
2004 * gst_element_link_many:
2005 * @element_1: the first #GstElement in the link chain.
2006 * @element_2: the second #GstElement in the link chain.
2007 * @...: the NULL-terminated list of elements to link in order.
2009 * Chain together a series of elements. Uses gst_element_link().
2011 * Returns: TRUE on success, FALSE otherwise.
2014 gst_element_link_many (GstElement * element_1, GstElement * element_2, ...)
2018 g_return_val_if_fail (element_1 != NULL && element_2 != NULL, FALSE);
2019 g_return_val_if_fail (GST_IS_ELEMENT (element_1) &&
2020 GST_IS_ELEMENT (element_2), FALSE);
2022 va_start (args, element_2);
2025 if (!gst_element_link (element_1, element_2))
2028 element_1 = element_2;
2029 element_2 = va_arg (args, GstElement *);
2039 * @src: a #GstElement containing the source pad.
2040 * @dest: the #GstElement containing the destination pad.
2042 * Links @src to @dest with no filter caps. See gst_element_link_filtered() for
2045 * Returns: TRUE if the elements could be linked, FALSE otherwise.
2048 gst_element_link (GstElement * src, GstElement * dest)
2050 return gst_element_link_pads_filtered (src, NULL, dest, NULL, NULL);
2054 * gst_element_link_pads:
2055 * @src: a #GstElement containing the source pad.
2056 * @srcpadname: the name of the #GstPad in the source element.
2057 * @dest: the #GstElement containing the destination pad.
2058 * @destpadname: the name of the #GstPad in destination element.
2060 * Links the two named pads of the source and destination elements.
2061 * Side effect is that if one of the pads has no parent, it becomes a
2062 * child of the parent of the other element. If they have different
2063 * parents, the link fails.
2065 * Returns: TRUE if the pads could be linked, FALSE otherwise.
2068 gst_element_link_pads (GstElement * src, const gchar * srcpadname,
2069 GstElement * dest, const gchar * destpadname)
2071 return gst_element_link_pads_filtered (src, srcpadname, dest, destpadname,
2076 * gst_element_unlink_pads:
2077 * @src: a #GstElement containing the source pad.
2078 * @srcpadname: the name of the #GstPad in source element.
2079 * @dest: a #GstElement containing the destination pad.
2080 * @destpadname: the name of the #GstPad in destination element.
2082 * Unlinks the two named pads of the source and destination elements.
2085 gst_element_unlink_pads (GstElement * src, const gchar * srcpadname,
2086 GstElement * dest, const gchar * destpadname)
2088 GstPad *srcpad, *destpad;
2090 g_return_if_fail (src != NULL);
2091 g_return_if_fail (GST_IS_ELEMENT (src));
2092 g_return_if_fail (srcpadname != NULL);
2093 g_return_if_fail (dest != NULL);
2094 g_return_if_fail (GST_IS_ELEMENT (dest));
2095 g_return_if_fail (destpadname != NULL);
2097 /* obtain the pads requested */
2098 srcpad = gst_element_get_pad (src, srcpadname);
2099 if (srcpad == NULL) {
2100 GST_WARNING_OBJECT (src, "source element has no pad \"%s\"", srcpadname);
2103 destpad = gst_element_get_pad (dest, destpadname);
2104 if (srcpad == NULL) {
2105 GST_WARNING_OBJECT (dest, "destination element has no pad \"%s\"",
2110 /* we're satisified they can be unlinked, let's do it */
2111 gst_pad_unlink (srcpad, destpad);
2115 * gst_element_unlink_many:
2116 * @element_1: the first #GstElement in the link chain.
2117 * @element_2: the second #GstElement in the link chain.
2118 * @...: the NULL-terminated list of elements to unlink in order.
2120 * Unlinks a series of elements. Uses gst_element_unlink().
2123 gst_element_unlink_many (GstElement * element_1, GstElement * element_2, ...)
2127 g_return_if_fail (element_1 != NULL && element_2 != NULL);
2128 g_return_if_fail (GST_IS_ELEMENT (element_1) && GST_IS_ELEMENT (element_2));
2130 va_start (args, element_2);
2133 gst_element_unlink (element_1, element_2);
2135 element_1 = element_2;
2136 element_2 = va_arg (args, GstElement *);
2143 * gst_element_unlink:
2144 * @src: the source #GstElement to unlink.
2145 * @dest: the sink #GstElement to unlink.
2147 * Unlinks all source pads of the source element with all sink pads
2148 * of the sink element to which they are linked.
2151 gst_element_unlink (GstElement * src, GstElement * dest)
2153 const GList *srcpads;
2156 g_return_if_fail (GST_IS_ELEMENT (src));
2157 g_return_if_fail (GST_IS_ELEMENT (dest));
2159 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "unlinking \"%s\" and \"%s\"",
2160 GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (dest));
2162 srcpads = gst_element_get_pad_list (src);
2165 pad = GST_PAD (srcpads->data);
2167 /* we only care about real src pads */
2168 if (GST_IS_REAL_PAD (pad) && GST_PAD_IS_SRC (pad)) {
2169 GstPad *peerpad = GST_PAD_PEER (pad);
2171 /* see if the pad is connected and is really a pad
2173 if (peerpad && (GST_OBJECT_PARENT (peerpad) == (GstObject *) dest)) {
2174 gst_pad_unlink (pad, peerpad);
2178 srcpads = g_list_next (srcpads);
2183 gst_element_error_func (GstElement * element, GstElement * source,
2184 GError * error, gchar * debug)
2186 GstObject *parent = GST_OBJECT_PARENT (element);
2188 /* tell the parent */
2190 gst_object_ref (GST_OBJECT (element));
2191 gst_object_ref (parent);
2192 GST_CAT_DEBUG (GST_CAT_ERROR_SYSTEM,
2193 "forwarding error \"%s\" from %s to %s", error->message,
2194 GST_ELEMENT_NAME (element), GST_OBJECT_NAME (parent));
2196 g_signal_emit (G_OBJECT (parent),
2197 gst_element_signals[ERROR], 0, source, error, debug);
2198 GST_CAT_DEBUG (GST_CAT_ERROR_SYSTEM, "forwarded error \"%s\" from %s to %s",
2199 error->message, GST_ELEMENT_NAME (element), GST_OBJECT_NAME (parent));
2200 gst_object_unref (GST_OBJECT (element));
2201 gst_object_unref (GST_OBJECT (parent));
2206 gst_element_get_random_pad (GstElement * element, GstPadDirection dir)
2208 GList *pads = element->pads;
2210 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "getting a random pad");
2212 GstPad *pad = GST_PAD (pads->data);
2214 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "checking pad %s:%s",
2215 GST_DEBUG_PAD_NAME (pad));
2217 if (GST_PAD_DIRECTION (pad) == dir) {
2218 if (GST_PAD_IS_LINKED (pad)) {
2221 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s is not linked",
2222 GST_DEBUG_PAD_NAME (pad));
2225 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s is in wrong direction",
2226 GST_DEBUG_PAD_NAME (pad));
2229 pads = g_list_next (pads);
2235 * gst_element_get_event_masks:
2236 * @element: a #GstElement to query
2238 * Get an array of event masks from the element.
2239 * If the element doesn't
2240 * implement an event masks function, the query will be forwarded
2241 * to a random linked sink pad.
2243 * Returns: An array of #GstEventMask elements.
2245 const GstEventMask *
2246 gst_element_get_event_masks (GstElement * element)
2248 GstElementClass *oclass;
2250 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
2252 oclass = GST_ELEMENT_GET_CLASS (element);
2254 if (oclass->get_event_masks)
2255 return oclass->get_event_masks (element);
2257 GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SINK);
2260 return gst_pad_get_event_masks (GST_PAD_PEER (pad));
2267 * gst_element_send_event:
2268 * @element: a #GstElement to send the event to.
2269 * @event: the #GstEvent to send to the element.
2271 * Sends an event to an element. If the element doesn't
2272 * implement an event handler, the event will be forwarded
2273 * to a random sink pad.
2275 * Returns: TRUE if the event was handled.
2278 gst_element_send_event (GstElement * element, GstEvent * event)
2280 GstElementClass *oclass;
2282 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
2283 g_return_val_if_fail (event != NULL, FALSE);
2285 oclass = GST_ELEMENT_GET_CLASS (element);
2287 if (oclass->send_event)
2288 return oclass->send_event (element, event);
2290 GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SINK);
2293 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "sending event to random pad %s:%s",
2294 GST_DEBUG_PAD_NAME (pad));
2295 return gst_pad_send_event (GST_PAD_PEER (pad), event);
2298 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "can't send event on element %s",
2299 GST_ELEMENT_NAME (element));
2305 * @element: a #GstElement to send the event to.
2306 * @seek_type: the method to use for seeking.
2307 * @offset: the offset to seek to.
2309 * Sends a seek event to an element.
2311 * Returns: TRUE if the event was handled.
2314 gst_element_seek (GstElement * element, GstSeekType seek_type, guint64 offset)
2316 GstEvent *event = gst_event_new_seek (seek_type, offset);
2318 return gst_element_send_event (element, event);
2322 * gst_element_get_query_types:
2323 * @element: a #GstElement to query
2325 * Get an array of query types from the element.
2326 * If the element doesn't
2327 * implement a query types function, the query will be forwarded
2328 * to a random sink pad.
2330 * Returns: An array of #GstQueryType elements.
2332 const GstQueryType *
2333 gst_element_get_query_types (GstElement * element)
2335 GstElementClass *oclass;
2337 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
2339 oclass = GST_ELEMENT_GET_CLASS (element);
2341 if (oclass->get_query_types)
2342 return oclass->get_query_types (element);
2344 GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SINK);
2347 return gst_pad_get_query_types (GST_PAD_PEER (pad));
2354 * gst_element_query:
2355 * @element: a #GstElement to perform the query on.
2356 * @type: the #GstQueryType.
2357 * @format: the #GstFormat pointer to hold the format of the result.
2358 * @value: the pointer to the value of the result.
2360 * Performs a query on the given element. If the format is set
2361 * to GST_FORMAT_DEFAULT and this function returns TRUE, the
2362 * format pointer will hold the default format.
2363 * For element that don't implement a query handler, this function
2364 * forwards the query to a random usable sinkpad of this element.
2366 * Returns: TRUE if the query could be performed.
2369 gst_element_query (GstElement * element, GstQueryType type,
2370 GstFormat * format, gint64 * value)
2372 GstElementClass *oclass;
2374 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
2375 g_return_val_if_fail (format != NULL, FALSE);
2376 g_return_val_if_fail (value != NULL, FALSE);
2378 oclass = GST_ELEMENT_GET_CLASS (element);
2381 return oclass->query (element, type, format, value);
2383 GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SRC);
2386 return gst_pad_query (pad, type, format, value);
2387 pad = gst_element_get_random_pad (element, GST_PAD_SINK);
2389 return gst_pad_query (GST_PAD_PEER (pad), type, format, value);
2396 * gst_element_get_formats:
2397 * @element: a #GstElement to query
2399 * Get an array of formst from the element.
2400 * If the element doesn't
2401 * implement a formats function, the query will be forwarded
2402 * to a random sink pad.
2404 * Returns: An array of #GstFormat elements.
2407 gst_element_get_formats (GstElement * element)
2409 GstElementClass *oclass;
2411 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
2413 oclass = GST_ELEMENT_GET_CLASS (element);
2415 if (oclass->get_formats)
2416 return oclass->get_formats (element);
2418 GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SINK);
2421 return gst_pad_get_formats (GST_PAD_PEER (pad));
2428 * gst_element_convert:
2429 * @element: a #GstElement to invoke the converter on.
2430 * @src_format: the source #GstFormat.
2431 * @src_value: the source value.
2432 * @dest_format: a pointer to the destination #GstFormat.
2433 * @dest_value: a pointer to the destination value.
2435 * Invokes a conversion on the element.
2436 * If the element doesn't
2437 * implement a convert function, the query will be forwarded
2438 * to a random sink pad.
2440 * Returns: TRUE if the conversion could be performed.
2443 gst_element_convert (GstElement * element,
2444 GstFormat src_format, gint64 src_value,
2445 GstFormat * dest_format, gint64 * dest_value)
2447 GstElementClass *oclass;
2449 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
2450 g_return_val_if_fail (dest_format != NULL, FALSE);
2451 g_return_val_if_fail (dest_value != NULL, FALSE);
2453 if (src_format == *dest_format) {
2454 *dest_value = src_value;
2458 oclass = GST_ELEMENT_GET_CLASS (element);
2460 if (oclass->convert)
2461 return oclass->convert (element,
2462 src_format, src_value, dest_format, dest_value);
2464 GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SINK);
2467 return gst_pad_convert (GST_PAD_PEER (pad),
2468 src_format, src_value, dest_format, dest_value);
2475 * _gst_element_error_printf:
2476 * @format: the printf-like format to use, or NULL
2478 * This function is only used internally by the #gst_element_error macro.
2480 * Returns: a newly allocated string, or NULL if the format was NULL or ""
2483 _gst_element_error_printf (const gchar * format, ...)
2493 va_start (args, format);
2494 buffer = g_strdup_vprintf (format, args);
2500 * gst_element_error_full:
2501 * @element: a #GstElement with the error.
2502 * @domain: the GStreamer error domain this error belongs to.
2503 * @code: the error code belonging to the domain
2504 * @message: an allocated message to be used as a replacement for the default
2505 * message connected to code, or NULL
2506 * @debug: an allocated debug message to be used as a replacement for the
2507 * default debugging information, or NULL
2508 * @file: the source code file where the error was generated
2509 * @function: the source code function where the error was generated
2510 * @line: the source code line where the error was generated
2512 * Signals an error condition on an element.
2513 * This function is used internally by elements.
2514 * It results in the "error" signal.
2516 void gst_element_error_full
2517 (GstElement * element, GQuark domain, gint code, gchar * message,
2518 gchar * debug, const gchar * file, const gchar * function, gint line)
2520 GError *error = NULL;
2522 gchar *sent_message;
2526 g_return_if_fail (GST_IS_ELEMENT (element));
2528 /* check if we send the given message or the default error message */
2529 if ((message == NULL) || (message[0] == 0)) {
2530 /* we got this message from g_strdup_printf (""); */
2532 sent_message = gst_error_get_message (domain, code);
2534 sent_message = message;
2536 if ((debug == NULL) || (debug[0] == 0)) {
2537 /* we got this debug from g_strdup_printf (""); */
2542 /* create error message */
2543 GST_CAT_INFO (GST_CAT_ERROR_SYSTEM, "signaling error in %s: %s",
2544 GST_ELEMENT_NAME (element), sent_message);
2545 error = g_error_new (domain, code, sent_message);
2547 /* if the element was already in error, stop now */
2548 if (GST_FLAG_IS_SET (element, GST_ELEMENT_IN_ERROR)) {
2549 GST_CAT_INFO (GST_CAT_ERROR_SYSTEM, "recursive ERROR detected in %s",
2550 GST_ELEMENT_NAME (element));
2551 g_free (sent_message);
2557 GST_FLAG_SET (element, GST_ELEMENT_IN_ERROR);
2559 /* emit the signal, make sure the element stays available */
2560 gst_object_ref (GST_OBJECT (element));
2561 name = gst_object_get_path_string (GST_OBJECT (element));
2563 sent_debug = g_strdup_printf ("%s(%d): %s: %s:\n%s",
2564 file, line, function, name, debug ? debug : "");
2569 g_signal_emit (G_OBJECT (element), gst_element_signals[ERROR], 0, element,
2571 GST_CAT_INFO (GST_CAT_ERROR_SYSTEM, "signalled error in %s: %s",
2572 GST_ELEMENT_NAME (element), sent_message);
2574 /* tell the scheduler */
2575 if (element->sched) {
2576 gst_scheduler_error (element->sched, element);
2579 if (GST_STATE (element) == GST_STATE_PLAYING) {
2580 GstElementStateReturn ret;
2582 ret = gst_element_set_state (element, GST_STATE_PAUSED);
2583 if (ret != GST_STATE_SUCCESS) {
2584 g_warning ("could not PAUSE element \"%s\" after error, help!",
2585 GST_ELEMENT_NAME (element));
2589 GST_FLAG_UNSET (element, GST_ELEMENT_IN_ERROR);
2592 gst_object_unref (GST_OBJECT (element));
2593 g_free (sent_message);
2594 g_free (sent_debug);
2595 g_error_free (error);
2599 * gst_element_is_locked_state:
2600 * @element: a #GstElement.
2602 * Checks if the state of an element is locked.
2603 * If the state of an element is locked, state changes of the parent don't
2604 * affect the element.
2605 * This way you can leave currently unused elements inside bins. Just lock their
2606 * state before changing the state from #GST_STATE_NULL.
2608 * Returns: TRUE, if the element's state is locked.
2611 gst_element_is_locked_state (GstElement * element)
2613 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
2615 return GST_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE) ? TRUE : FALSE;
2619 * gst_element_set_locked_state:
2620 * @element: a #GstElement
2621 * @locked_state: TRUE to lock the element's state
2623 * Locks the state of an element, so state changes of the parent don't affect
2624 * this element anymore.
2627 gst_element_set_locked_state (GstElement * element, gboolean locked_state)
2631 g_return_if_fail (GST_IS_ELEMENT (element));
2633 old = GST_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
2635 if (old == locked_state)
2639 GST_CAT_DEBUG (GST_CAT_STATES, "locking state of element %s",
2640 GST_ELEMENT_NAME (element));
2641 GST_FLAG_SET (element, GST_ELEMENT_LOCKED_STATE);
2643 GST_CAT_DEBUG (GST_CAT_STATES, "unlocking state of element %s",
2644 GST_ELEMENT_NAME (element));
2645 GST_FLAG_UNSET (element, GST_ELEMENT_LOCKED_STATE);
2650 * gst_element_sync_state_with_parent:
2651 * @element: a #GstElement.
2653 * Tries to change the state of the element to the same as its parent.
2654 * If this function returns FALSE, the state of element is undefined.
2656 * Returns: TRUE, if the element's state could be synced to the parent's state.
2659 gst_element_sync_state_with_parent (GstElement * element)
2663 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
2664 parent = GST_ELEMENT (GST_ELEMENT_PARENT (element));
2665 g_return_val_if_fail (GST_IS_BIN (parent), FALSE);
2667 GST_CAT_DEBUG (GST_CAT_STATES, "syncing state of element %s (%s) to %s (%s)",
2668 GST_ELEMENT_NAME (element),
2669 gst_element_state_get_name (GST_STATE (element)),
2670 GST_ELEMENT_NAME (parent),
2671 gst_element_state_get_name (GST_STATE (parent)));
2672 if (gst_element_set_state (element, GST_STATE (parent)) == GST_STATE_FAILURE) {
2679 * gst_element_get_state:
2680 * @element: a #GstElement to get the state of.
2682 * Gets the state of the element.
2684 * Returns: the #GstElementState of the element.
2687 gst_element_get_state (GstElement * element)
2689 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_VOID_PENDING);
2691 return GST_STATE (element);
2695 * gst_element_wait_state_change:
2696 * @element: a #GstElement to wait for a state change on.
2698 * Waits and blocks until the element changed its state.
2701 gst_element_wait_state_change (GstElement * element)
2703 g_mutex_lock (element->state_mutex);
2704 g_cond_wait (element->state_cond, element->state_mutex);
2705 g_mutex_unlock (element->state_mutex);
2709 * gst_element_set_state:
2710 * @element: a #GstElement to change state of.
2711 * @state: the element's new #GstElementState.
2713 * Sets the state of the element. This function will try to set the
2714 * requested state by going through all the intermediary states and calling
2715 * the class's state change function for each.
2717 * Returns: TRUE if the state was successfully set.
2718 * (using #GstElementStateReturn).
2720 GstElementStateReturn
2721 gst_element_set_state (GstElement * element, GstElementState state)
2723 GstElementClass *oclass;
2724 GstElementState curpending;
2725 GstElementStateReturn return_val = GST_STATE_SUCCESS;
2727 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
2728 oclass = GST_ELEMENT_GET_CLASS (element);
2730 /* for bins, we allow calls to change_state where old == new
2731 * for elements, too many of them break with g_assert_not_reached(),
2732 * so weed those out first. This is done in gst-plugins CVS and can
2733 * be fixed here after a new plugins reelase.
2734 * FIXME: of course this file should not have ties to gstbin.h *at all*,
2735 * but someone else added a function at the bottom using it.
2736 * Fix this properly for 0.9 */
2738 /* start with the current state */
2739 curpending = GST_STATE (element);
2741 if (!GST_IS_BIN (element) && state == curpending) {
2742 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2743 "non-bin element is already in requested state %s, returning",
2744 gst_element_state_get_name (state));
2745 return (GST_STATE_SUCCESS);
2748 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "setting state from %s to %s",
2749 gst_element_state_get_name (curpending),
2750 gst_element_state_get_name (state));
2752 /* loop until the final requested state is set;
2753 * loop at least once, starting with the current state */
2756 /* set the pending state variable */
2757 GST_STATE_PENDING (element) = curpending;
2759 if (curpending != state) {
2760 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2761 "intermediate: setting state from %s to %s",
2762 gst_element_state_get_name (GST_STATE (element)),
2763 gst_element_state_get_name (curpending));
2765 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2766 "start: setting current state %s again",
2767 gst_element_state_get_name (GST_STATE (element)));
2770 /* call the state change function so it can set the state */
2771 if (oclass->change_state)
2772 return_val = (oclass->change_state) (element);
2774 switch (return_val) {
2775 case GST_STATE_FAILURE:
2776 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
2777 "have failed change_state return");
2779 case GST_STATE_ASYNC:
2780 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
2781 "element will change state async");
2783 case GST_STATE_SUCCESS:
2784 /* Last thing we do is verify that a successful state change really
2785 * did change the state... */
2786 /* if it did not, this is an error - fix the element that does this */
2787 if (GST_STATE (element) != curpending) {
2788 g_warning ("element %s claimed state-change success,"
2789 "but state didn't change to %s. State is %s (%s pending), "
2791 GST_ELEMENT_NAME (element),
2792 gst_element_state_get_name (curpending),
2793 gst_element_state_get_name (GST_STATE (element)),
2794 gst_element_state_get_name (GST_STATE_PENDING (element)));
2795 return_val = GST_STATE_FAILURE;
2800 /* somebody added a GST_STATE_ and forgot to do stuff here ! */
2801 g_assert_not_reached ();
2803 /* move the curpending state in the correct direction */
2804 if (curpending < state)
2808 } while (GST_STATE (element) != state
2809 && GST_STATE (element) != GST_STATE_VOID_PENDING);
2817 gst_element_negotiate_pads (GstElement * element)
2819 GList *pads = GST_ELEMENT_PADS (element);
2821 GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, element, "negotiating pads");
2824 GstPad *pad = GST_PAD (pads->data);
2827 pads = g_list_next (pads);
2829 if (!GST_IS_REAL_PAD (pad))
2832 srcpad = GST_PAD_REALIZE (pad);
2834 /* if we have a link on this pad and it doesn't have caps
2835 * allready, try to negotiate */
2836 if (GST_PAD_IS_LINKED (srcpad) && !GST_PAD_CAPS (srcpad)) {
2837 GstRealPad *sinkpad;
2838 GstElementState otherstate;
2841 sinkpad = GST_RPAD_PEER (GST_PAD_REALIZE (srcpad));
2843 /* check the parent of the peer pad, if there is no parent do nothing */
2844 parent = GST_PAD_PARENT (sinkpad);
2848 /* skips pads that were already negotiating */
2849 if (GST_FLAG_IS_SET (sinkpad, GST_PAD_NEGOTIATING) ||
2850 GST_FLAG_IS_SET (srcpad, GST_PAD_NEGOTIATING))
2853 otherstate = GST_STATE (parent);
2855 /* swap pads if needed */
2856 if (!GST_PAD_IS_SRC (srcpad)) {
2864 /* only try to negotiate if the peer element is in PAUSED or higher too */
2865 if (otherstate >= GST_STATE_READY) {
2866 GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, element,
2867 "perform negotiate for %s:%s and %s:%s",
2868 GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
2869 if (gst_pad_renegotiate (pad) == GST_PAD_LINK_REFUSED)
2872 GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, element,
2873 "not negotiating %s:%s and %s:%s, not in READY yet",
2874 GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
2883 gst_element_clear_pad_caps (GstElement * element)
2885 GList *pads = GST_ELEMENT_PADS (element);
2887 GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, element, "clearing pad caps");
2890 GstPad *pad = GST_PAD (pads->data);
2892 gst_pad_unnegotiate (pad);
2893 if (GST_IS_REAL_PAD (pad)) {
2894 gst_caps_replace (&GST_RPAD_EXPLICIT_CAPS (pad), NULL);
2897 pads = g_list_next (pads);
2902 gst_element_pads_activate (GstElement * element, gboolean active)
2904 GList *pads = element->pads;
2907 GstPad *pad = GST_PAD (pads->data);
2909 pads = g_list_next (pads);
2911 if (!GST_IS_REAL_PAD (pad))
2914 gst_pad_set_active (pad, active);
2918 static GstElementStateReturn
2919 gst_element_change_state (GstElement * element)
2921 GstElementState old_state;
2923 gint old_pending, old_transition;
2925 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
2927 old_state = GST_STATE (element);
2928 old_pending = GST_STATE_PENDING (element);
2929 old_transition = GST_STATE_TRANSITION (element);
2931 /* if the element already is in the given state, we just return success */
2932 if (old_pending == GST_STATE_VOID_PENDING ||
2933 old_state == GST_STATE_PENDING (element)) {
2934 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2935 "element is already in the %s state",
2936 gst_element_state_get_name (old_state));
2937 return GST_STATE_SUCCESS;
2940 GST_CAT_LOG_OBJECT (GST_CAT_STATES, element,
2941 "default handler tries setting state from %s to %s %04x",
2942 gst_element_state_get_name (old_state),
2943 gst_element_state_get_name (old_pending), old_transition);
2945 /* we set the state change early for the negotiation functions */
2946 GST_STATE (element) = old_pending;
2947 GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING;
2949 switch (old_transition) {
2950 case GST_STATE_PLAYING_TO_PAUSED:
2951 if (element->clock) {
2952 GstClockTimeDiff time = gst_clock_get_event_time (element->clock);
2954 g_assert (time >= element->base_time);
2955 element->base_time = time - element->base_time;
2956 GST_CAT_LOG_OBJECT (GST_CAT_CLOCK, element, "setting base time to %"
2957 G_GINT64_FORMAT, element->base_time);
2959 gst_element_pads_activate (element, FALSE);
2961 case GST_STATE_PAUSED_TO_PLAYING:
2962 gst_element_pads_activate (element, TRUE);
2963 if (element->clock) {
2964 GstClockTime time = gst_clock_get_event_time (element->clock);
2966 element->base_time = time - element->base_time;
2967 GST_CAT_LOG_OBJECT (GST_CAT_CLOCK, element, "setting base time to %"
2968 GST_TIME_FORMAT, GST_TIME_ARGS (element->base_time));
2971 /* if we are going to paused, we try to negotiate the pads */
2972 case GST_STATE_READY_TO_PAUSED:
2973 g_assert (element->base_time == 0);
2974 if (!gst_element_negotiate_pads (element)) {
2975 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
2976 "failed state change, could not negotiate pads");
2980 /* going to the READY state clears all pad caps */
2981 /* FIXME: Why doesn't this happen on READY => NULL? -- Company */
2982 case GST_STATE_PAUSED_TO_READY:
2983 element->base_time = 0;
2984 gst_element_clear_pad_caps (element);
2986 case GST_STATE_NULL_TO_READY:
2987 case GST_STATE_READY_TO_NULL:
2990 /* this will catch real but unhandled state changes;
2991 * can only be caused by:
2992 * - a new state was added
2993 * - somehow the element was asked to jump across an intermediate state
2995 g_assert_not_reached ();
2999 parent = GST_ELEMENT_PARENT (element);
3001 GST_CAT_LOG_OBJECT (GST_CAT_STATES, element,
3002 "signaling state change from %s to %s",
3003 gst_element_state_get_name (old_state),
3004 gst_element_state_get_name (GST_STATE (element)));
3006 /* tell the scheduler if we have one */
3007 if (element->sched) {
3008 if (gst_scheduler_state_transition (element->sched, element,
3009 old_transition) != GST_STATE_SUCCESS) {
3010 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
3011 "scheduler could not change state");
3016 /* tell our parent about the state change */
3017 if (parent && GST_IS_BIN (parent)) {
3018 gst_bin_child_state_change (GST_BIN (parent), old_state,
3019 GST_STATE (element), element);
3021 /* at this point the state of the element could have changed again */
3023 g_signal_emit (G_OBJECT (element), gst_element_signals[STATE_CHANGE],
3024 0, old_state, GST_STATE (element));
3026 /* signal the state change in case somebody is waiting for us */
3027 g_mutex_lock (element->state_mutex);
3028 g_cond_signal (element->state_cond);
3029 g_mutex_unlock (element->state_mutex);
3031 return GST_STATE_SUCCESS;
3034 /* undo the state change */
3035 GST_STATE (element) = old_state;
3036 GST_STATE_PENDING (element) = old_pending;
3038 return GST_STATE_FAILURE;
3042 * gst_element_get_factory:
3043 * @element: a #GstElement to request the element factory of.
3045 * Retrieves the factory that was used to create this element.
3047 * Returns: the #GstElementFactory used for creating this element.
3050 gst_element_get_factory (GstElement * element)
3052 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
3054 return GST_ELEMENT_GET_CLASS (element)->elementfactory;
3058 gst_element_dispose (GObject * object)
3060 GstElement *element = GST_ELEMENT (object);
3062 GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "dispose");
3064 gst_element_set_state (element, GST_STATE_NULL);
3066 /* first we break all our links with the ouside */
3067 while (element->pads) {
3068 gst_element_remove_pad (element, GST_PAD (element->pads->data));
3071 element->numsrcpads = 0;
3072 element->numsinkpads = 0;
3073 element->numpads = 0;
3074 if (element->state_mutex)
3075 g_mutex_free (element->state_mutex);
3076 element->state_mutex = NULL;
3077 if (element->state_cond)
3078 g_cond_free (element->state_cond);
3079 element->state_cond = NULL;
3081 if (element->prop_value_queue)
3082 g_async_queue_unref (element->prop_value_queue);
3083 element->prop_value_queue = NULL;
3084 if (element->property_mutex)
3085 g_mutex_free (element->property_mutex);
3086 element->property_mutex = NULL;
3088 gst_object_replace ((GstObject **) & element->sched, NULL);
3089 gst_object_replace ((GstObject **) & element->clock, NULL);
3091 G_OBJECT_CLASS (parent_class)->dispose (object);
3094 #ifndef GST_DISABLE_LOADSAVE
3096 * gst_element_save_thyself:
3097 * @element: a #GstElement to save.
3098 * @parent: the xml parent node.
3100 * Saves the element as part of the given XML structure.
3102 * Returns: the new #xmlNodePtr.
3105 gst_element_save_thyself (GstObject * object, xmlNodePtr parent)
3108 GstElementClass *oclass;
3109 GParamSpec **specs, *spec;
3111 GValue value = { 0, };
3112 GstElement *element;
3114 g_return_val_if_fail (GST_IS_ELEMENT (object), parent);
3116 element = GST_ELEMENT (object);
3118 oclass = GST_ELEMENT_GET_CLASS (element);
3120 xmlNewChild (parent, NULL, "name", GST_ELEMENT_NAME (element));
3122 if (oclass->elementfactory != NULL) {
3123 GstElementFactory *factory = (GstElementFactory *) oclass->elementfactory;
3125 xmlNewChild (parent, NULL, "type", GST_PLUGIN_FEATURE (factory)->name);
3128 /* FIXME: what is this? */
3129 /* if (element->manager) */
3130 /* xmlNewChild(parent, NULL, "manager", GST_ELEMENT_NAME(element->manager)); */
3133 specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (object), &nspecs);
3135 for (i = 0; i < nspecs; i++) {
3137 if (spec->flags & G_PARAM_READABLE) {
3141 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (spec));
3143 g_object_get_property (G_OBJECT (element), spec->name, &value);
3144 param = xmlNewChild (parent, NULL, "param", NULL);
3145 xmlNewChild (param, NULL, "name", spec->name);
3147 if (G_IS_PARAM_SPEC_STRING (spec))
3148 contents = g_value_dup_string (&value);
3149 else if (G_IS_PARAM_SPEC_ENUM (spec))
3150 contents = g_strdup_printf ("%d", g_value_get_enum (&value));
3151 else if (G_IS_PARAM_SPEC_INT64 (spec))
3152 contents = g_strdup_printf ("%" G_GINT64_FORMAT,
3153 g_value_get_int64 (&value));
3155 contents = g_strdup_value_contents (&value);
3157 xmlNewChild (param, NULL, "value", contents);
3160 g_value_unset (&value);
3164 pads = GST_ELEMENT_PADS (element);
3167 GstPad *pad = GST_PAD (pads->data);
3169 /* figure out if it's a direct pad or a ghostpad */
3170 if (GST_ELEMENT (GST_OBJECT_PARENT (pad)) == element) {
3171 xmlNodePtr padtag = xmlNewChild (parent, NULL, "pad", NULL);
3173 gst_object_save_thyself (GST_OBJECT (pad), padtag);
3175 pads = g_list_next (pads);
3182 gst_element_restore_thyself (GstObject * object, xmlNodePtr self)
3184 xmlNodePtr children;
3185 GstElement *element;
3187 gchar *value = NULL;
3189 element = GST_ELEMENT (object);
3190 g_return_if_fail (element != NULL);
3193 children = self->xmlChildrenNode;
3195 if (!strcmp (children->name, "param")) {
3196 xmlNodePtr child = children->xmlChildrenNode;
3199 if (!strcmp (child->name, "name")) {
3200 name = xmlNodeGetContent (child);
3201 } else if (!strcmp (child->name, "value")) {
3202 value = xmlNodeGetContent (child);
3204 child = child->next;
3206 /* FIXME: can this just be g_object_set ? */
3207 gst_util_set_object_arg (G_OBJECT (element), name, value);
3208 /* g_object_set (G_OBJECT (element), name, value, NULL); */
3210 children = children->next;
3214 children = self->xmlChildrenNode;
3216 if (!strcmp (children->name, "pad")) {
3217 gst_pad_load_and_link (children, GST_OBJECT (element));
3219 children = children->next;
3222 if (GST_OBJECT_CLASS (parent_class)->restore_thyself)
3223 (GST_OBJECT_CLASS (parent_class)->restore_thyself) (object, self);
3225 #endif /* GST_DISABLE_LOADSAVE */
3228 * gst_element_yield:
3229 * @element: a #GstElement to yield.
3231 * Requests a yield operation for the element. The scheduler will typically
3232 * give control to another element.
3235 gst_element_yield (GstElement * element)
3237 if (GST_ELEMENT_SCHED (element)) {
3238 gst_scheduler_yield (GST_ELEMENT_SCHED (element), element);
3243 * gst_element_interrupt:
3244 * @element: a #GstElement to interrupt.
3246 * Requests the scheduler of this element to interrupt the execution of
3247 * this element and scheduler another one.
3249 * Returns: TRUE if the element should exit its chain/loop/get
3250 * function ASAP, depending on the scheduler implementation.
3253 gst_element_interrupt (GstElement * element)
3255 if (GST_ELEMENT_SCHED (element)) {
3256 return gst_scheduler_interrupt (GST_ELEMENT_SCHED (element), element);
3262 * gst_element_set_scheduler:
3263 * @element: a #GstElement to set the scheduler of.
3264 * @sched: the #GstScheduler to set.
3266 * Sets the scheduler of the element. For internal use only, unless you're
3267 * writing a new bin subclass.
3270 gst_element_set_scheduler (GstElement * element, GstScheduler * sched)
3272 g_return_if_fail (GST_IS_ELEMENT (element));
3274 GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, element, "setting scheduler to %p",
3277 gst_object_replace ((GstObject **) & GST_ELEMENT_SCHED (element),
3278 GST_OBJECT (sched));
3282 * gst_element_get_scheduler:
3283 * @element: a #GstElement to get the scheduler of.
3285 * Returns the scheduler of the element.
3287 * Returns: the element's #GstScheduler.
3290 gst_element_get_scheduler (GstElement * element)
3292 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
3294 return GST_ELEMENT_SCHED (element);
3298 * gst_element_set_loop_function:
3299 * @element: a #GstElement to set the loop function of.
3300 * @loop: Pointer to #GstElementLoopFunction.
3302 * This sets the loop function for the element. The function pointed to
3303 * can deviate from the GstElementLoopFunction definition in type of
3306 * NOTE: in order for this to take effect, the current loop function *must*
3307 * exit. Assuming the loop function itself is the only one who will cause
3308 * a new loopfunc to be assigned, this should be no problem.
3311 gst_element_set_loop_function (GstElement * element,
3312 GstElementLoopFunction loop)
3314 gboolean need_notify = FALSE;
3316 g_return_if_fail (GST_IS_ELEMENT (element));
3318 /* if the element changed from loop based to chain/get based
3319 * or vice versa, we need to inform the scheduler about that */
3320 if ((element->loopfunc == NULL && loop != NULL) ||
3321 (element->loopfunc != NULL && loop == NULL)) {
3325 /* set the loop function */
3326 element->loopfunc = loop;
3329 /* set the NEW_LOOPFUNC flag so everyone knows to go try again */
3330 GST_FLAG_SET (element, GST_ELEMENT_NEW_LOOPFUNC);
3332 if (GST_ELEMENT_SCHED (element)) {
3333 gst_scheduler_scheduling_change (GST_ELEMENT_SCHED (element), element);
3338 gst_element_emit_found_tag (GstElement * element, GstElement * source,
3339 const GstTagList * tag_list)
3341 gst_object_ref (GST_OBJECT (element));
3342 g_signal_emit (element, gst_element_signals[FOUND_TAG], 0, source, tag_list);
3343 gst_object_unref (GST_OBJECT (element));
3346 gst_element_found_tag_func (GstElement * element, GstElement * source,
3347 const GstTagList * tag_list)
3349 /* tell the parent */
3350 if (GST_OBJECT_PARENT (element)) {
3351 GST_CAT_LOG_OBJECT (GST_CAT_EVENT, element, "forwarding tag event to %s",
3352 GST_OBJECT_NAME (GST_OBJECT_PARENT (element)));
3353 gst_element_emit_found_tag (GST_ELEMENT (GST_OBJECT_PARENT (element)),
3359 * gst_element_found_tags:
3360 * @element: the element that found the tags
3361 * @tag_list: the found tags
3363 * This function emits the found_tags signal. This is a recursive signal, so
3364 * every parent will emit that signal, too, before this function returns.
3365 * Only emit this signal, when you extracted these tags out of the data stream,
3366 * not when you handle an event.
3369 gst_element_found_tags (GstElement * element, const GstTagList * tag_list)
3371 gst_element_emit_found_tag (element, element, tag_list);
3375 * gst_element_found_tags_for_pad:
3376 * @element: element that found the tag
3377 * @pad: src pad the tags correspond to
3378 * @timestamp: time the tags were found
3379 * @list: the taglist
3381 * This is a convenience routine for tag finding. Most of the time you only
3382 * want to push the found tags down one pad, in that case this function is for
3383 * you. It takes ownership of the taglist, emits the found-tag signal and pushes
3384 * a tag event down the pad.
3385 * <note>This function may not be used in a #GstPadGetFunction, because it calls
3386 * gst_pad_push(). In those functions, call gst_element_found_tags(), create a
3387 * tag event with gst_event_new_tag() and return that from your
3388 * #GstPadGetFunction.</note>
3391 gst_element_found_tags_for_pad (GstElement * element, GstPad * pad,
3392 GstClockTime timestamp, GstTagList * list)
3394 GstEvent *tag_event;
3396 g_return_if_fail (GST_IS_ELEMENT (element));
3397 g_return_if_fail (GST_IS_REAL_PAD (pad));
3398 g_return_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SRC);
3399 g_return_if_fail (element == GST_PAD_PARENT (pad));
3400 g_return_if_fail (list != NULL);
3402 tag_event = gst_event_new_tag (list);
3403 GST_EVENT_TIMESTAMP (tag_event) = timestamp;
3404 gst_element_found_tags (element, gst_event_tag_get_list (tag_event));
3405 if (GST_PAD_IS_USABLE (pad)) {
3406 gst_pad_push (pad, GST_DATA (tag_event));
3408 gst_data_unref (GST_DATA (tag_event));
3413 gst_element_set_eos_recursive (GstElement * element)
3415 /* this function is only called, when we were in PLAYING before. So every
3416 parent that's PAUSED was PLAYING before. That means it has reached EOS. */
3419 GST_CAT_DEBUG (GST_CAT_EVENT, "setting recursive EOS on %s",
3420 GST_OBJECT_NAME (element));
3421 g_signal_emit (G_OBJECT (element), gst_element_signals[EOS], 0);
3423 if (!GST_OBJECT_PARENT (element))
3426 parent = GST_ELEMENT (GST_OBJECT_PARENT (element));
3427 if (GST_STATE (parent) == GST_STATE_PAUSED)
3428 gst_element_set_eos_recursive (parent);
3432 * gst_element_set_eos:
3433 * @element: a #GstElement to set to the EOS state.
3435 * Perform the actions needed to bring the element in the EOS state.
3438 gst_element_set_eos (GstElement * element)
3440 g_return_if_fail (GST_IS_ELEMENT (element));
3442 GST_CAT_DEBUG (GST_CAT_EVENT, "setting EOS on element %s",
3443 GST_OBJECT_NAME (element));
3445 if (GST_STATE (element) == GST_STATE_PLAYING) {
3446 gst_element_set_state (element, GST_STATE_PAUSED);
3447 gst_element_set_eos_recursive (element);
3449 g_signal_emit (G_OBJECT (element), gst_element_signals[EOS], 0);
3455 * gst_element_state_get_name:
3456 * @state: a #GstElementState to get the name of.
3458 * Gets a string representing the given state.
3460 * Returns: a string with the name of the state.
3463 gst_element_state_get_name (GstElementState state)
3466 #ifdef GST_DEBUG_COLOR
3467 case GST_STATE_VOID_PENDING:
3468 return "NONE_PENDING";
3470 case GST_STATE_NULL:
3471 return "\033[01;34mNULL\033[00m";
3473 case GST_STATE_READY:
3474 return "\033[01;31mREADY\033[00m";
3476 case GST_STATE_PLAYING:
3477 return "\033[01;32mPLAYING\033[00m";
3479 case GST_STATE_PAUSED:
3480 return "\033[01;33mPAUSED\033[00m";
3483 /* This is a memory leak */
3484 return g_strdup_printf ("\033[01;35;41mUNKNOWN!\033[00m(%d)", state);
3486 case GST_STATE_VOID_PENDING:
3487 return "NONE_PENDING";
3489 case GST_STATE_NULL:
3492 case GST_STATE_READY:
3495 case GST_STATE_PLAYING:
3498 case GST_STATE_PAUSED:
3509 gst_element_populate_std_props (GObjectClass * klass, const gchar * prop_name,
3510 guint arg_id, GParamFlags flags)
3512 GQuark prop_id = g_quark_from_string (prop_name);
3515 static GQuark fd_id = 0;
3516 static GQuark blocksize_id;
3517 static GQuark bytesperread_id;
3518 static GQuark dump_id;
3519 static GQuark filesize_id;
3520 static GQuark mmapsize_id;
3521 static GQuark location_id;
3522 static GQuark offset_id;
3523 static GQuark silent_id;
3524 static GQuark touch_id;
3527 fd_id = g_quark_from_static_string ("fd");
3528 blocksize_id = g_quark_from_static_string ("blocksize");
3529 bytesperread_id = g_quark_from_static_string ("bytesperread");
3530 dump_id = g_quark_from_static_string ("dump");
3531 filesize_id = g_quark_from_static_string ("filesize");
3532 mmapsize_id = g_quark_from_static_string ("mmapsize");
3533 location_id = g_quark_from_static_string ("location");
3534 offset_id = g_quark_from_static_string ("offset");
3535 silent_id = g_quark_from_static_string ("silent");
3536 touch_id = g_quark_from_static_string ("touch");
3539 if (prop_id == fd_id) {
3540 pspec = g_param_spec_int ("fd", "File-descriptor",
3541 "File-descriptor for the file being read", 0, G_MAXINT, 0, flags);
3542 } else if (prop_id == blocksize_id) {
3543 pspec = g_param_spec_ulong ("blocksize", "Block Size",
3544 "Block size to read per buffer", 0, G_MAXULONG, 4096, flags);
3546 } else if (prop_id == bytesperread_id) {
3547 pspec = g_param_spec_int ("bytesperread", "Bytes per read",
3548 "Number of bytes to read per buffer", G_MININT, G_MAXINT, 0, flags);
3550 } else if (prop_id == dump_id) {
3551 pspec = g_param_spec_boolean ("dump", "Dump",
3552 "Dump bytes to stdout", FALSE, flags);
3554 } else if (prop_id == filesize_id) {
3555 pspec = g_param_spec_int64 ("filesize", "File Size",
3556 "Size of the file being read", 0, G_MAXINT64, 0, flags);
3558 } else if (prop_id == mmapsize_id) {
3559 pspec = g_param_spec_ulong ("mmapsize", "mmap() Block Size",
3560 "Size in bytes of mmap()d regions", 0, G_MAXULONG, 4 * 1048576, flags);
3562 } else if (prop_id == location_id) {
3563 pspec = g_param_spec_string ("location", "File Location",
3564 "Location of the file to read", NULL, flags);
3566 } else if (prop_id == offset_id) {
3567 pspec = g_param_spec_int64 ("offset", "File Offset",
3568 "Byte offset of current read pointer", 0, G_MAXINT64, 0, flags);
3570 } else if (prop_id == silent_id) {
3571 pspec = g_param_spec_boolean ("silent", "Silent", "Don't produce events",
3574 } else if (prop_id == touch_id) {
3575 pspec = g_param_spec_boolean ("touch", "Touch read data",
3576 "Touch data to force disk read before " "push ()", TRUE, flags);
3578 g_warning ("Unknown - 'standard' property '%s' id %d from klass %s",
3579 prop_name, arg_id, g_type_name (G_OBJECT_CLASS_TYPE (klass)));
3584 g_object_class_install_property (klass, arg_id, pspec);
3589 * gst_element_class_install_std_props:
3590 * @klass: the #GstElementClass to add the properties to.
3591 * @first_name: the name of the first property.
3592 * in a NULL terminated
3593 * @...: the id and flags of the first property, followed by
3594 * further 'name', 'id', 'flags' triplets and terminated by NULL.
3596 * Adds a list of standardized properties with types to the @klass.
3597 * the id is for the property switch in your get_prop method, and
3598 * the flags determine readability / writeability.
3601 gst_element_class_install_std_props (GstElementClass * klass,
3602 const gchar * first_name, ...)
3608 g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
3610 va_start (args, first_name);
3615 int arg_id = va_arg (args, int);
3616 int flags = va_arg (args, int);
3618 gst_element_populate_std_props ((GObjectClass *) klass, name, arg_id,
3621 name = va_arg (args, char *);
3628 * gst_element_get_managing_bin:
3629 * @element: a #GstElement to get the managing bin of.
3631 * Gets the managing bin (a pipeline or a thread, for example) of an element.
3633 * Returns: the #GstBin, or NULL on failure.
3636 gst_element_get_managing_bin (GstElement * element)
3640 g_return_val_if_fail (element != NULL, NULL);
3642 bin = GST_BIN (gst_object_get_parent (GST_OBJECT (element)));
3644 while (bin && !GST_FLAG_IS_SET (GST_OBJECT (bin), GST_BIN_FLAG_MANAGER))
3645 bin = GST_BIN (gst_object_get_parent (GST_OBJECT (bin)));