2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 * 2004 Wim Taymans <wim@fluendo.com>
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);
73 static void gst_element_finalize (GObject * object);
75 static GstElementStateReturn gst_element_change_state (GstElement * element);
76 static void gst_element_error_func (GstElement * element, GstElement * source,
77 GError * error, gchar * debug);
78 static void gst_element_found_tag_func (GstElement * element,
79 GstElement * source, const GstTagList * tag_list);
80 static GstElementStateReturn gst_element_set_state_func (GstElement * element,
81 GstElementState state);
83 #ifndef GST_DISABLE_LOADSAVE
84 static xmlNodePtr gst_element_save_thyself (GstObject * object,
86 static void gst_element_restore_thyself (GstObject * parent, xmlNodePtr self);
89 GType _gst_element_type = 0;
91 static GstObjectClass *parent_class = NULL;
92 static guint gst_element_signals[LAST_SIGNAL] = { 0 };
95 gst_element_get_type (void)
97 if (!_gst_element_type) {
98 static const GTypeInfo element_info = {
99 sizeof (GstElementClass),
100 gst_element_base_class_init,
101 gst_element_base_class_finalize,
102 (GClassInitFunc) gst_element_class_init,
107 (GInstanceInitFunc) gst_element_init,
111 _gst_element_type = g_type_register_static (GST_TYPE_OBJECT, "GstElement",
112 &element_info, G_TYPE_FLAG_ABSTRACT);
114 return _gst_element_type;
118 gst_element_class_init (GstElementClass * klass)
120 GObjectClass *gobject_class;
121 GstObjectClass *gstobject_class;
123 gobject_class = (GObjectClass *) klass;
124 gstobject_class = (GstObjectClass *) klass;
126 parent_class = g_type_class_ref (GST_TYPE_OBJECT);
129 * GstElement::state-change:
130 * @gstelement: the object which received the signal
134 * the #GstElementState of the element has been changed
136 gst_element_signals[STATE_CHANGE] =
137 g_signal_new ("state-change", G_TYPE_FROM_CLASS (klass),
138 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstElementClass, state_change), NULL,
139 NULL, gst_marshal_VOID__INT_INT, G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT);
141 * GstElement::new-pad:
142 * @gstelement: the object which received the signal
145 * a new #GstPad has been added to the element
147 gst_element_signals[NEW_PAD] =
148 g_signal_new ("new-pad", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
149 G_STRUCT_OFFSET (GstElementClass, new_pad), NULL, NULL,
150 gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT);
152 * GstElement::pad-removed:
153 * @gstelement: the object which received the signal
156 * a #GstPad has been removed from the element
158 gst_element_signals[PAD_REMOVED] =
159 g_signal_new ("pad-removed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
160 G_STRUCT_OFFSET (GstElementClass, pad_removed), NULL, NULL,
161 gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT);
164 * @gstelement: the object which received the signal
169 * a #GstError has occured during data processing
171 gst_element_signals[ERROR] =
172 g_signal_new ("error", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
173 G_STRUCT_OFFSET (GstElementClass, error), NULL, NULL,
174 gst_marshal_VOID__OBJECT_BOXED_STRING, G_TYPE_NONE, 3, GST_TYPE_ELEMENT,
175 GST_TYPE_G_ERROR, G_TYPE_STRING);
178 * @gstelement: the object which received the signal
180 * the end of the stream has been reached
182 gst_element_signals[EOS] =
183 g_signal_new ("eos", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
184 G_STRUCT_OFFSET (GstElementClass, eos), NULL, NULL,
185 gst_marshal_VOID__VOID, G_TYPE_NONE, 0);
187 * GstElement::found-tag:
188 * @gstelement: the object which received the signal
192 * tags for the incomming stream have been received
194 gst_element_signals[FOUND_TAG] =
195 g_signal_new ("found-tag", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
196 G_STRUCT_OFFSET (GstElementClass, found_tag), NULL, NULL,
197 gst_marshal_VOID__OBJECT_BOXED, G_TYPE_NONE, 2, GST_TYPE_ELEMENT,
200 * GstElement::no-more-pads:
201 * @gstelement: the object which received the signal
205 gst_element_signals[NO_MORE_PADS] =
206 g_signal_new ("no-more-pads", G_TYPE_FROM_CLASS (klass),
207 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstElementClass, no_more_pads), NULL,
208 NULL, gst_marshal_VOID__VOID, G_TYPE_NONE, 0);
210 gobject_class->set_property =
211 GST_DEBUG_FUNCPTR (gst_element_real_set_property);
212 gobject_class->get_property =
213 GST_DEBUG_FUNCPTR (gst_element_real_get_property);
215 gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_element_dispose);
216 gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_element_finalize);
218 #ifndef GST_DISABLE_LOADSAVE
219 gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_element_save_thyself);
220 gstobject_class->restore_thyself =
221 GST_DEBUG_FUNCPTR (gst_element_restore_thyself);
224 klass->change_state = GST_DEBUG_FUNCPTR (gst_element_change_state);
225 klass->error = GST_DEBUG_FUNCPTR (gst_element_error_func);
226 klass->found_tag = GST_DEBUG_FUNCPTR (gst_element_found_tag_func);
227 klass->numpadtemplates = 0;
228 klass->set_state = GST_DEBUG_FUNCPTR (gst_element_set_state_func);
230 klass->elementfactory = NULL;
234 gst_element_base_class_init (gpointer g_class)
236 GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
237 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
240 gobject_class->set_property =
241 GST_DEBUG_FUNCPTR (gst_element_real_set_property);
242 gobject_class->get_property =
243 GST_DEBUG_FUNCPTR (gst_element_real_get_property);
245 memset (&element_class->details, 0, sizeof (GstElementDetails));
246 element_class->padtemplates = NULL;
250 gst_element_base_class_finalize (gpointer g_class)
252 GstElementClass *klass = GST_ELEMENT_CLASS (g_class);
254 g_list_foreach (klass->padtemplates, (GFunc) gst_object_unref, NULL);
255 g_list_free (klass->padtemplates);
256 __gst_element_details_clear (&klass->details);
260 gst_element_init (GstElement * element)
262 element->current_state = GST_STATE_NULL;
263 element->pending_state = GST_STATE_VOID_PENDING;
264 element->numpads = 0;
265 element->numsrcpads = 0;
266 element->numsinkpads = 0;
267 element->pads_cookie = 0;
268 element->pads = NULL;
269 element->srcpads = NULL;
270 element->sinkpads = NULL;
271 element->loopfunc = NULL;
272 element->sched = NULL;
273 element->clock = NULL;
274 element->sched_private = NULL;
275 element->state_mutex = g_mutex_new ();
276 element->state_cond = g_cond_new ();
280 gst_element_real_set_property (GObject * object, guint prop_id,
281 const GValue * value, GParamSpec * pspec)
283 GstElementClass *oclass = GST_ELEMENT_GET_CLASS (object);
285 if (oclass->set_property)
286 (oclass->set_property) (object, prop_id, value, pspec);
290 gst_element_real_get_property (GObject * object, guint prop_id, GValue * value,
293 GstElementClass *oclass = GST_ELEMENT_GET_CLASS (object);
295 if (oclass->get_property)
296 (oclass->get_property) (object, prop_id, value, pspec);
300 * gst_element_default_error:
301 * @object: a #GObject that signalled the error.
302 * @orig: the #GstObject that initiated the error.
303 * @error: the GError.
304 * @debug: an additional debug information string, or NULL.
306 * A default error signal callback to attach to an element.
307 * The user data passed to the g_signal_connect is ignored.
309 * The default handler will simply print the error string using g_print.
314 gst_element_default_error (GObject * object, GstObject * source, GError * error,
317 gchar *name = gst_object_get_path_string (source);
319 g_print (_("ERROR: from element %s: %s\n"), name, error->message);
321 g_print (_("Additional debug info:\n%s\n"), debug);
328 const GParamSpec *pspec;
334 element_set_property (GstElement * element, const GParamSpec * pspec,
335 const GValue * value)
337 prop_value_t *prop_value = g_new0 (prop_value_t, 1);
339 prop_value->pspec = pspec;
340 prop_value->value = *value;
342 g_async_queue_push (element->prop_value_queue, prop_value);
346 element_get_property (GstElement * element, const GParamSpec * pspec,
349 g_mutex_lock (element->property_mutex);
350 g_object_get_property ((GObject *) element, pspec->name, value);
351 g_mutex_unlock (element->property_mutex);
355 gst_element_threadsafe_properties_pre_run (GstElement * element)
357 /* need to ref the object because we don't want to lose the object
358 * before the post run function is called */
359 gst_object_ref (GST_OBJECT (element));
360 GST_DEBUG ("locking element %s", GST_OBJECT_NAME (element));
361 g_mutex_lock (element->property_mutex);
362 gst_element_set_pending_properties (element);
366 gst_element_threadsafe_properties_post_run (GstElement * element)
368 GST_DEBUG ("unlocking element %s", GST_OBJECT_NAME (element));
369 g_mutex_unlock (element->property_mutex);
370 gst_object_unref (GST_OBJECT (element));
374 * gst_element_enable_threadsafe_properties:
375 * @element: a #GstElement to enable threadsafe properties on.
377 * Installs an asynchronous queue, a mutex and pre- and post-run functions on
378 * this element so that properties on the element can be set in a
382 gst_element_enable_threadsafe_properties (GstElement * element)
384 g_return_if_fail (GST_IS_ELEMENT (element));
386 GST_FLAG_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES);
387 element->pre_run_func = gst_element_threadsafe_properties_pre_run;
388 element->post_run_func = gst_element_threadsafe_properties_post_run;
389 if (!element->prop_value_queue)
390 element->prop_value_queue = g_async_queue_new ();
391 if (!element->property_mutex)
392 element->property_mutex = g_mutex_new ();
396 * gst_element_disable_threadsafe_properties:
397 * @element: a #GstElement to disable threadsafe properties on.
399 * Removes the threadsafe properties, post- and pre-run locks from
403 gst_element_disable_threadsafe_properties (GstElement * element)
405 g_return_if_fail (GST_IS_ELEMENT (element));
407 GST_FLAG_UNSET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES);
409 //element->pre_run_func = NULL;
410 //element->post_run_func = NULL;
411 /* let's keep around that async queue */
415 * gst_element_set_pending_properties:
416 * @element: a #GstElement to set the pending properties on.
418 * Sets all pending properties on the threadsafe properties enabled
422 gst_element_set_pending_properties (GstElement * element)
424 prop_value_t *prop_value;
426 while ((prop_value = g_async_queue_try_pop (element->prop_value_queue))) {
427 g_object_set_property ((GObject *) element, prop_value->pspec->name,
429 g_value_unset (&prop_value->value);
434 /* following 6 functions taken mostly from gobject.c */
438 * @element: a #GstElement to set properties on.
439 * @first_property_name: the first property to set.
440 * @...: value of the first property, and more properties to set, ending
443 * Sets properties on an element. If the element uses threadsafe properties,
444 * they will be queued and set on the object when it is scheduled again.
447 gst_element_set (GstElement * element, const gchar * first_property_name, ...)
451 g_return_if_fail (GST_IS_ELEMENT (element));
453 va_start (var_args, first_property_name);
454 gst_element_set_valist (element, first_property_name, var_args);
460 * @element: a #GstElement to get properties of.
461 * @first_property_name: the first property to get.
462 * @...: pointer to a variable to store the first property in, as well as
463 * more properties to get, ending with NULL.
465 * Gets properties from an element. If the element uses threadsafe properties,
466 * the element will be locked before getting the given properties.
469 gst_element_get (GstElement * element, const gchar * first_property_name, ...)
473 g_return_if_fail (GST_IS_ELEMENT (element));
475 va_start (var_args, first_property_name);
476 gst_element_get_valist (element, first_property_name, var_args);
481 * gst_element_set_valist:
482 * @element: a #GstElement to set properties on.
483 * @first_property_name: the first property to set.
484 * @var_args: the var_args list of other properties to get.
486 * Sets properties on an element. If the element uses threadsafe properties,
487 * the property change will be put on the async queue.
490 gst_element_set_valist (GstElement * element, const gchar * first_property_name,
496 g_return_if_fail (GST_IS_ELEMENT (element));
498 object = (GObject *) element;
500 GST_CAT_DEBUG (GST_CAT_PROPERTIES,
501 "setting valist of properties starting with %s on element %s",
502 first_property_name, gst_element_get_name (element));
504 if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
505 g_object_set_valist (object, first_property_name, var_args);
509 g_object_ref (object);
511 name = first_property_name;
514 GValue value = { 0, };
518 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), name);
521 g_warning ("%s: object class `%s' has no property named `%s'",
522 G_STRLOC, G_OBJECT_TYPE_NAME (object), name);
525 if (!(pspec->flags & G_PARAM_WRITABLE)) {
526 g_warning ("%s: property `%s' of object class `%s' is not writable",
527 G_STRLOC, pspec->name, G_OBJECT_TYPE_NAME (object));
531 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
533 G_VALUE_COLLECT (&value, var_args, 0, &error);
535 g_warning ("%s: %s", G_STRLOC, error);
538 /* we purposely leak the value here, it might not be
539 * in a sane state if an error condition occoured
544 element_set_property (element, pspec, &value);
545 g_value_unset (&value);
547 name = va_arg (var_args, gchar *);
550 g_object_unref (object);
554 * gst_element_get_valist:
555 * @element: a #GstElement to get properties of.
556 * @first_property_name: the first property to get.
557 * @var_args: the var_args list of other properties to get.
559 * Gets properties from an element. If the element uses threadsafe properties,
560 * the element will be locked before getting the given properties.
563 gst_element_get_valist (GstElement * element, const gchar * first_property_name,
569 g_return_if_fail (GST_IS_ELEMENT (element));
571 object = (GObject *) element;
573 if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
574 g_object_get_valist (object, first_property_name, var_args);
578 g_object_ref (object);
580 name = first_property_name;
583 GValue value = { 0, };
587 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), name);
590 g_warning ("%s: object class `%s' has no property named `%s'",
591 G_STRLOC, G_OBJECT_TYPE_NAME (object), name);
594 if (!(pspec->flags & G_PARAM_READABLE)) {
595 g_warning ("%s: property `%s' of object class `%s' is not readable",
596 G_STRLOC, pspec->name, G_OBJECT_TYPE_NAME (object));
600 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
602 element_get_property (element, pspec, &value);
604 G_VALUE_LCOPY (&value, var_args, 0, &error);
606 g_warning ("%s: %s", G_STRLOC, error);
608 g_value_unset (&value);
612 g_value_unset (&value);
614 name = va_arg (var_args, gchar *);
617 g_object_unref (object);
621 * gst_element_set_property:
622 * @element: a #GstElement to set properties on.
623 * @property_name: the first property to get.
624 * @value: the #GValue that holds the value to set.
626 * Sets a property on an element. If the element uses threadsafe properties,
627 * the property will be put on the async queue.
630 gst_element_set_property (GstElement * element, const gchar * property_name,
631 const GValue * value)
636 g_return_if_fail (GST_IS_ELEMENT (element));
637 g_return_if_fail (property_name != NULL);
638 g_return_if_fail (G_IS_VALUE (value));
640 object = (GObject *) element;
642 GST_CAT_DEBUG (GST_CAT_PROPERTIES, "setting property %s on element %s",
643 property_name, gst_element_get_name (element));
644 if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
645 g_object_set_property (object, property_name, value);
649 g_object_ref (object);
651 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object),
655 g_warning ("%s: object class `%s' has no property named `%s'",
656 G_STRLOC, G_OBJECT_TYPE_NAME (object), property_name);
658 element_set_property (element, pspec, value);
660 g_object_unref (object);
664 * gst_element_get_property:
665 * @element: a #GstElement to get properties of.
666 * @property_name: the first property to get.
667 * @value: the #GValue to store the property value in.
669 * Gets a property from an element. If the element uses threadsafe properties,
670 * the element will be locked before getting the given property.
673 gst_element_get_property (GstElement * element, const gchar * property_name,
679 g_return_if_fail (GST_IS_ELEMENT (element));
680 g_return_if_fail (property_name != NULL);
681 g_return_if_fail (G_IS_VALUE (value));
683 object = (GObject *) element;
685 if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
686 g_object_get_property (object, property_name, value);
690 g_object_ref (object);
693 g_object_class_find_property (G_OBJECT_GET_CLASS (object), property_name);
696 g_warning ("%s: object class `%s' has no property named `%s'",
697 G_STRLOC, G_OBJECT_TYPE_NAME (object), property_name);
699 GValue *prop_value, tmp_value = { 0, };
701 /* auto-conversion of the callers value type
703 if (G_VALUE_TYPE (value) == G_PARAM_SPEC_VALUE_TYPE (pspec)) {
704 g_value_reset (value);
706 } else if (!g_value_type_transformable (G_PARAM_SPEC_VALUE_TYPE (pspec),
707 G_VALUE_TYPE (value))) {
709 ("can't retrieve property `%s' of type `%s' as value of type `%s'",
710 pspec->name, g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
711 G_VALUE_TYPE_NAME (value));
712 g_object_unref (object);
715 g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
716 prop_value = &tmp_value;
718 element_get_property (element, pspec, prop_value);
719 if (prop_value != value) {
720 g_value_transform (prop_value, value);
721 g_value_unset (&tmp_value);
725 g_object_unref (object);
729 * gst_element_release_request_pad:
730 * @element: a #GstElement to release the request pad of.
731 * @pad: the #GstPad to release.
733 * Makes the element free the previously requested pad as obtained
734 * with gst_element_get_request_pad().
739 gst_element_release_request_pad (GstElement * element, GstPad * pad)
741 GstElementClass *oclass;
743 g_return_if_fail (GST_IS_ELEMENT (element));
744 g_return_if_fail (GST_IS_PAD (pad));
746 oclass = GST_ELEMENT_GET_CLASS (element);
748 if (oclass->release_pad)
749 (oclass->release_pad) (element, pad);
751 gst_element_remove_pad (element, pad);
755 * gst_element_requires_clock:
756 * @element: a #GstElement to query
758 * Query if the element requires a clock.
760 * Returns: TRUE if the element requires a clock
765 gst_element_requires_clock (GstElement * element)
767 gboolean result = FALSE;
769 g_return_val_if_fail (GST_IS_ELEMENT (element), result);
771 result = (GST_ELEMENT_GET_CLASS (element)->set_clock != NULL);
777 * gst_element_provides_clock:
778 * @element: a #GstElement to query
780 * Query if the element provides a clock.
782 * Returns: TRUE if the element provides a clock
787 gst_element_provides_clock (GstElement * element)
789 gboolean result = FALSE;
791 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
793 result = (GST_ELEMENT_GET_CLASS (element)->get_clock != NULL);
799 * gst_element_set_clock:
800 * @element: a #GstElement to set the clock for.
801 * @clock: the #GstClock to set for the element.
803 * Sets the clock for the element. This function increases the
804 * refcount on the clock. Any previously set clock on the object
810 gst_element_set_clock (GstElement * element, GstClock * clock)
812 GstElementClass *oclass;
814 g_return_if_fail (GST_IS_ELEMENT (element));
816 oclass = GST_ELEMENT_GET_CLASS (element);
818 if (oclass->set_clock)
819 oclass->set_clock (element, clock);
822 gst_object_replace ((GstObject **) & element->clock, (GstObject *) clock);
823 GST_UNLOCK (element);
827 * gst_element_get_clock:
828 * @element: a #GstElement to get the clock of.
830 * Gets the clock of the element. If the element provides a clock,
831 * this function will return this clock. For elements that do not
832 * provide a clock, this function returns NULL.
834 * Returns: the #GstClock of the element. unref after usage.
839 gst_element_get_clock (GstElement * element)
841 GstElementClass *oclass;
843 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
845 oclass = GST_ELEMENT_GET_CLASS (element);
847 if (oclass->get_clock)
848 return oclass->get_clock (element);
854 * gst_element_clock_wait:
855 * @element: a #GstElement.
856 * @id: the #GstClock to use.
857 * @jitter: the difference between requested time and actual time.
859 * Waits for a specific time on the clock.
861 * Returns: the #GstClockReturn result of the wait operation.
864 gst_element_clock_wait (GstElement * element, GstClockID id,
865 GstClockTimeDiff * jitter)
869 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_CLOCK_ERROR);
871 if (GST_ELEMENT_SCHEDULER (element)) {
872 GST_CAT_DEBUG (GST_CAT_CLOCK, "waiting on scheduler clock with id %d");
874 gst_scheduler_clock_wait (GST_ELEMENT_SCHEDULER (element), element, id,
877 GST_CAT_DEBUG (GST_CAT_CLOCK, "no scheduler, returning GST_CLOCK_OK");
884 #undef GST_CAT_DEFAULT
885 #define GST_CAT_DEFAULT GST_CAT_CLOCK
887 * gst_element_get_time:
888 * @element: element to query
890 * Query the element's time. FIXME: The element must use
892 * Returns: the current stream time in #GST_STATE_PLAYING,
893 * the element base time in #GST_STATE_PAUSED,
894 * or #GST_CLOCK_TIME_NONE otherwise.
896 /* FIXME: this should always return time on the same scale. Now it returns
897 * the (absolute) base_time in PAUSED and the (current running) time in
899 * Solution: have a get_base_time and make the element subtract if it needs
900 * to. In PAUSED return the same as PLAYING, ie. the current timestamp where
901 * the element is at according to the provided clock.
904 gst_element_get_time (GstElement * element)
906 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_CLOCK_TIME_NONE);
908 if (element->clock == NULL) {
909 GST_WARNING_OBJECT (element, "element queries time but has no clock");
910 return GST_CLOCK_TIME_NONE;
912 switch (element->current_state) {
914 case GST_STATE_READY:
915 return GST_CLOCK_TIME_NONE;
916 case GST_STATE_PAUSED:
917 return element->base_time;
918 case GST_STATE_PLAYING:
919 return gst_clock_get_time (element->clock) - element->base_time;
921 g_assert_not_reached ();
922 return GST_CLOCK_TIME_NONE;
928 * @element: element that should wait
929 * @timestamp: what timestamp to wait on
931 * Waits until the given relative time stamp for the element has arrived.
932 * When this function returns successfully, the relative time point specified
933 * in the timestamp has passed for this element.
934 * <note>This function can only be called on elements in
935 * #GST_STATE_PLAYING</note>
937 * Returns: TRUE on success.
940 gst_element_wait (GstElement * element, GstClockTime timestamp)
946 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
947 g_return_val_if_fail (GST_IS_CLOCK (element->clock), FALSE);
948 g_return_val_if_fail (element->current_state == GST_STATE_PLAYING, FALSE);
949 g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
951 /* shortcut when we're already late... */
952 time = gst_element_get_time (element);
953 GST_CAT_LOG_OBJECT (GST_CAT_CLOCK, element, "element time %" GST_TIME_FORMAT,
954 GST_TIME_ARGS (time));
955 if (time >= timestamp) {
956 GST_CAT_INFO_OBJECT (GST_CAT_CLOCK, element,
957 "called gst_element_wait (% " GST_TIME_FORMAT ") and was late (%"
958 GST_TIME_FORMAT, GST_TIME_ARGS (timestamp),
959 GST_TIME_ARGS (gst_element_get_time (element)));
963 id = gst_clock_new_single_shot_id (element->clock,
964 element->base_time + timestamp);
965 ret = gst_element_clock_wait (element, id, NULL);
966 gst_clock_id_unref (id);
968 return ret == GST_CLOCK_OK;
972 * gst_element_set_time:
973 * @element: element to set time on
976 * Sets the current time of the element. This function can be used when handling
977 * discont events. You can only call this function on an element with a clock in
978 * #GST_STATE_PAUSED or #GST_STATE_PLAYING. You might want to have a look at
979 * gst_element_adjust_time(), if you want to adjust by a difference as that is
983 gst_element_set_time (GstElement * element, GstClockTime time)
985 gst_element_set_time_delay (element, time, 0);
989 * gst_element_set_time_delay:
990 * @element: element to set time on
992 * @delay: a delay to discount from the given time
994 * Sets the current time of the element to time - delay. This function can be
995 * used when handling discont events in elements writing to an external buffer,
996 * i. e., an audio sink that writes to a sound card that buffers the sound
997 * before playing it. The delay should be the current buffering delay.
999 * You can only call this function on an element with a clock in
1000 * #GST_STATE_PAUSED or #GST_STATE_PLAYING. You might want to have a look at
1001 * gst_element_adjust_time(), if you want to adjust by a difference as that is
1005 gst_element_set_time_delay (GstElement * element, GstClockTime time,
1008 GstClockTime event_time;
1010 g_return_if_fail (GST_IS_ELEMENT (element));
1011 g_return_if_fail (GST_IS_CLOCK (element->clock));
1012 g_return_if_fail (element->current_state >= GST_STATE_PAUSED);
1013 g_return_if_fail (time >= delay);
1015 switch (element->current_state) {
1016 case GST_STATE_PAUSED:
1017 element->base_time = time - delay;
1019 case GST_STATE_PLAYING:
1020 event_time = GST_CLOCK_TIME_NONE;
1021 //gst_clock_get_event_time_delay (element->clock, delay);
1022 GST_CAT_LOG_OBJECT (GST_CAT_CLOCK, element,
1023 "clock time %" GST_TIME_FORMAT ": setting element time to %"
1024 GST_TIME_FORMAT, GST_TIME_ARGS (event_time), GST_TIME_ARGS (time));
1025 element->base_time = event_time - time;
1028 g_assert_not_reached ();
1034 * gst_element_adjust_time:
1035 * @element: element to adjust time on
1036 * @diff: difference to adjust
1038 * Adjusts the current time of the element by the specified difference. This
1039 * function can be used when handling discont events. You can only call this
1040 * function on an element with a clock in #GST_STATE_PAUSED or
1041 * #GST_STATE_PLAYING. It is more accurate than gst_element_set_time().
1044 gst_element_adjust_time (GstElement * element, GstClockTimeDiff diff)
1048 g_return_if_fail (GST_IS_ELEMENT (element));
1049 g_return_if_fail (GST_IS_CLOCK (element->clock));
1050 g_return_if_fail (element->current_state >= GST_STATE_PAUSED);
1052 switch (element->current_state) {
1053 case GST_STATE_PAUSED:
1054 if (diff < 0 && element->base_time < abs (diff)) {
1055 g_warning ("attempted to set the current time of element %s below 0",
1056 GST_OBJECT_NAME (element));
1057 element->base_time = 0;
1059 element->base_time += diff;
1062 case GST_STATE_PLAYING:
1063 time = gst_clock_get_time (element->clock);
1064 if (time < element->base_time - diff) {
1065 g_warning ("attempted to set the current time of element %s below 0",
1066 GST_OBJECT_NAME (element));
1067 element->base_time = time;
1069 element->base_time -= diff;
1073 g_assert_not_reached ();
1078 #undef GST_CAT_DEFAULT
1080 #ifndef GST_DISABLE_INDEX
1082 * gst_element_is_indexable:
1083 * @element: a #GstElement.
1085 * Queries if the element can be indexed.
1087 * Returns: TRUE if the element can be indexed.
1092 gst_element_is_indexable (GstElement * element)
1094 gboolean result = FALSE;
1096 g_return_val_if_fail (GST_IS_ELEMENT (element), result);
1098 result = (GST_ELEMENT_GET_CLASS (element)->set_index != NULL);
1104 * gst_element_set_index:
1105 * @element: a #GstElement.
1106 * @index: a #GstIndex.
1108 * Set the specified GstIndex on the element.
1113 gst_element_set_index (GstElement * element, GstIndex * index)
1115 GstElementClass *oclass;
1117 g_return_if_fail (GST_IS_ELEMENT (element));
1118 g_return_if_fail (GST_IS_INDEX (index));
1120 oclass = GST_ELEMENT_GET_CLASS (element);
1122 if (oclass->set_index)
1123 oclass->set_index (element, index);
1127 * gst_element_get_index:
1128 * @element: a #GstElement.
1130 * Gets the index from the element.
1132 * Returns: a #GstIndex or NULL when no index was set on the
1133 * element. unref after usage.
1138 gst_element_get_index (GstElement * element)
1140 GstElementClass *oclass;
1142 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1144 oclass = GST_ELEMENT_GET_CLASS (element);
1146 if (oclass->get_index)
1147 return oclass->get_index (element);
1154 * gst_element_release_locks:
1155 * @element: a #GstElement to release all locks on.
1157 * Instruct the element to release all the locks it is holding, such as
1158 * blocking reads, waiting for the clock, ...
1160 * Returns: TRUE if the locks could be released.
1163 gst_element_release_locks (GstElement * element)
1165 GstElementClass *oclass;
1167 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1169 oclass = GST_ELEMENT_GET_CLASS (element);
1171 if (oclass->release_locks)
1172 return oclass->release_locks (element);
1178 * gst_element_add_pad:
1179 * @element: a #GstElement to add the pad to.
1180 * @pad: the #GstPad to add to the element.
1182 * Adds a pad (link point) to @element. @pad's parent will be set to @element;
1183 * see gst_object_set_parent() for refcounting information.
1185 * Pads are automatically activated when the element is in state PLAYING.
1187 * The pad and the element should be unlocked when calling this function.
1189 * Returns: TRUE if the pad could be added. This function can fail when
1190 * passing bad arguments or when a pad with the same name already existed.
1195 gst_element_add_pad (GstElement * element, GstPad * pad)
1199 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1200 g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
1202 /* locking pad to look at the name */
1204 pad_name = g_strdup (GST_PAD_NAME (pad));
1205 GST_CAT_INFO_OBJECT (GST_CAT_ELEMENT_PADS, element, "adding pad '%s'",
1206 GST_STR_NULL (pad_name));
1209 /* then check to see if there's already a pad by that name here */
1211 if (G_UNLIKELY (!gst_object_check_uniqueness (element->pads, pad_name)))
1214 /* try to set the pad's parent */
1215 if (G_UNLIKELY (!gst_object_set_parent (GST_OBJECT_CAST (pad),
1216 GST_OBJECT_CAST (element))))
1221 /* add it to the list */
1222 switch (gst_pad_get_direction (pad)) {
1224 element->srcpads = g_list_prepend (element->srcpads, pad);
1225 element->numsrcpads++;
1228 element->sinkpads = g_list_prepend (element->sinkpads, pad);
1229 element->numsinkpads++;
1232 /* can happen for ghost pads */
1235 element->pads = g_list_prepend (element->pads, pad);
1237 element->pads_cookie++;
1238 GST_UNLOCK (element);
1240 /* emit the NEW_PAD signal */
1241 g_signal_emit (G_OBJECT (element), gst_element_signals[NEW_PAD], 0, pad);
1248 g_critical ("Padname %s is not unique in element %s, not adding",
1249 pad_name, GST_ELEMENT_NAME (element));
1250 GST_UNLOCK (element);
1257 ("Pad %s already has parent when trying to add to element %s",
1258 pad_name, GST_ELEMENT_NAME (element));
1259 GST_UNLOCK (element);
1266 * gst_element_add_ghost_pad:
1267 * @element: a #GstElement to add the ghost pad to.
1268 * @pad: the #GstPad from which the new ghost pad will be created.
1269 * @name: the name of the new ghost pad, or NULL to assign a unique name
1272 * Creates a ghost pad from @pad, and adds it to @element via
1273 * gst_element_add_pad().
1275 * Returns: the added ghost #GstPad, or NULL on error.
1280 gst_element_add_ghost_pad (GstElement * element, GstPad * pad,
1285 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1286 g_return_val_if_fail (GST_IS_PAD (pad), NULL);
1288 ghostpad = gst_ghost_pad_new (name, pad);
1290 if (!gst_element_add_pad (element, ghostpad)) {
1291 gst_object_unref (GST_OBJECT (ghostpad));
1299 * gst_element_remove_pad:
1300 * @element: a #GstElement to remove pad from.
1301 * @pad: the #GstPad to remove from the element.
1303 * Removes @pad from @element. @pad will be destroyed if it has not been
1304 * referenced elsewhere.
1306 * Returns: TRUE if the pad could be removed. Can return FALSE if the
1307 * pad is not belonging to the provided element or when wrong parameters
1308 * are passed to this function.
1313 gst_element_remove_pad (GstElement * element, GstPad * pad)
1317 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1318 g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
1320 /* locking pad to look at the name and parent */
1322 pad_name = g_strdup (GST_PAD_NAME (pad));
1324 GST_CAT_INFO_OBJECT (GST_CAT_ELEMENT_PADS, element, "removing pad '%s'",
1325 GST_STR_NULL (pad_name));
1327 if (G_UNLIKELY (GST_PAD_PARENT (pad) != element))
1333 /* FIXME, is this redundant with pad disposal? */
1334 if (GST_IS_REAL_PAD (pad)) {
1335 GstPad *peer = gst_pad_get_peer (pad);
1339 /* window for MT unsafeness, someone else could unlink here
1340 * and then we call unlink with wrong pads. The unlink
1341 * function would catch this and safely return failed. */
1342 if (GST_PAD_IS_SRC (pad))
1343 gst_pad_unlink (pad, GST_PAD_CAST (peer));
1345 gst_pad_unlink (GST_PAD_CAST (peer), pad);
1347 gst_object_unref (GST_OBJECT (peer));
1349 } else if (GST_IS_GHOST_PAD (pad)) {
1350 g_object_set (pad, "real-pad", NULL, NULL);
1354 /* remove it from the list */
1355 switch (gst_pad_get_direction (pad)) {
1357 element->srcpads = g_list_remove (element->srcpads, pad);
1358 element->numsrcpads--;
1361 element->sinkpads = g_list_remove (element->sinkpads, pad);
1362 element->numsinkpads--;
1365 /* can happen for ghost pads */
1368 element->pads = g_list_remove (element->pads, pad);
1370 element->pads_cookie++;
1371 GST_UNLOCK (element);
1373 g_signal_emit (G_OBJECT (element), gst_element_signals[PAD_REMOVED], 0, pad);
1375 gst_object_unparent (GST_OBJECT (pad));
1381 /* FIXME, locking order? */
1383 g_critical ("Padname %s:%s does not belong to element %s when removing",
1384 GST_ELEMENT_NAME (GST_PAD_PARENT (pad)), GST_PAD_NAME (pad),
1385 GST_ELEMENT_NAME (element));
1386 GST_UNLOCK (element);
1394 * gst_element_no_more_pads:
1395 * @element: a #GstElement
1397 * Use this function to signal that the element does not expect any more pads
1398 * to show up in the current pipeline. This function should be called whenever
1399 * pads have been added by the element itself. Elements with GST_PAD_SOMETIMES
1400 * pad templates use this in combination with autopluggers to figure out that
1401 * the element is done initializing its pads.
1406 gst_element_no_more_pads (GstElement * element)
1408 g_return_if_fail (GST_IS_ELEMENT (element));
1410 g_signal_emit (element, gst_element_signals[NO_MORE_PADS], 0);
1414 pad_compare_name (GstPad * pad1, const gchar * name)
1419 result = strcmp (GST_PAD_NAME (pad1), name);
1426 * gst_element_get_static_pad:
1427 * @element: a #GstElement to find a static pad of.
1428 * @name: the name of the static #GstPad to retrieve.
1430 * Retrieves a pad from @element by name. This version only retrieves
1431 * already-existing (i.e. 'static') pads.
1433 * Returns: the requested #GstPad if found, otherwise NULL. unref after
1439 gst_element_get_static_pad (GstElement * element, const gchar * name)
1442 GstPad *result = NULL;
1444 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1445 g_return_val_if_fail (name != NULL, NULL);
1449 g_list_find_custom (element->pads, name, (GCompareFunc) pad_compare_name);
1451 result = GST_PAD_CAST (find->data);
1452 gst_object_ref (GST_OBJECT_CAST (result));
1455 if (result == NULL) {
1456 GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "no such pad '%s' in element \"%s\"",
1457 name, GST_ELEMENT_NAME (element));
1459 GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "found pad %s:%s",
1460 GST_ELEMENT_NAME (element), name);
1462 GST_UNLOCK (element);
1468 gst_element_request_pad (GstElement * element, GstPadTemplate * templ,
1471 GstPad *newpad = NULL;
1472 GstElementClass *oclass;
1474 oclass = GST_ELEMENT_GET_CLASS (element);
1476 if (oclass->request_new_pad)
1477 newpad = (oclass->request_new_pad) (element, templ, name);
1483 * gst_element_get_request_pad:
1484 * @element: a #GstElement to find a request pad of.
1485 * @name: the name of the request #GstPad to retrieve.
1487 * Retrieves a pad from the element by name. This version only retrieves
1490 * Returns: requested #GstPad if found, otherwise NULL.
1493 gst_element_get_request_pad (GstElement * element, const gchar * name)
1495 GstPadTemplate *templ = NULL;
1497 const gchar *req_name = NULL;
1498 gboolean templ_found = FALSE;
1502 gchar *str, *endptr = NULL;
1503 GstElementClass *class;
1505 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1506 g_return_val_if_fail (name != NULL, NULL);
1508 class = GST_ELEMENT_GET_CLASS (element);
1510 if (strstr (name, "%")) {
1511 templ = gst_element_class_get_pad_template (class, name);
1516 list = gst_element_class_get_pad_template_list (class);
1517 while (!templ_found && list) {
1518 templ = (GstPadTemplate *) list->data;
1519 if (templ->presence == GST_PAD_REQUEST) {
1520 /* Because of sanity checks in gst_pad_template_new(), we know that %s
1521 and %d, occurring at the end of the name_template, are the only
1523 GST_CAT_DEBUG (GST_CAT_PADS, "comparing %s to %s", name,
1524 templ->name_template);
1525 if ((str = strchr (templ->name_template, '%'))
1526 && strncmp (templ->name_template, name,
1527 str - templ->name_template) == 0
1528 && strlen (name) > str - templ->name_template) {
1529 data = name + (str - templ->name_template);
1530 if (*(str + 1) == 'd') {
1532 n = (gint) strtol (data, &endptr, 10);
1533 if (endptr && *endptr == '\0') {
1553 pad = gst_element_request_pad (element, templ, req_name);
1559 * gst_element_get_pad:
1560 * @element: a #GstElement.
1561 * @name: the name of the pad to retrieve.
1563 * Retrieves a pad from @element by name. Tries gst_element_get_static_pad()
1564 * first, then gst_element_get_request_pad().
1566 * Returns: the #GstPad if found, otherwise %NULL. Unref after usage.
1569 gst_element_get_pad (GstElement * element, const gchar * name)
1573 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1574 g_return_val_if_fail (name != NULL, NULL);
1576 pad = gst_element_get_static_pad (element, name);
1578 pad = gst_element_get_request_pad (element, name);
1584 iterate_pad (GstIterator * it, GstPad * pad)
1586 gst_object_ref (GST_OBJECT_CAST (pad));
1587 return GST_ITERATOR_ITEM_PASS;
1591 * gst_element_iterate_pads:
1592 * @element: a #GstElement to iterate pads of.
1594 * Retrieves an iterattor of @element's pads.
1596 * Returns: the #GstIterator of pads.
1601 gst_element_iterate_pads (GstElement * element)
1603 GstIterator *result;
1605 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1608 gst_object_ref (GST_OBJECT (element));
1609 result = gst_iterator_new_list (GST_GET_LOCK (element),
1610 &element->pads_cookie,
1613 (GstIteratorItemFunction) iterate_pad,
1614 (GstIteratorDisposeFunction) gst_object_unref);
1615 GST_UNLOCK (element);
1622 * gst_element_class_add_pad_template:
1623 * @klass: the #GstElementClass to add the pad template to.
1624 * @templ: a #GstPadTemplate to add to the element class.
1626 * Adds a padtemplate to an element class. This is mainly used in the _base_init
1627 * functions of classes.
1630 gst_element_class_add_pad_template (GstElementClass * klass,
1631 GstPadTemplate * templ)
1633 g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
1634 g_return_if_fail (GST_IS_PAD_TEMPLATE (templ));
1636 /* avoid registering pad templates with the same name */
1637 g_return_if_fail (gst_element_class_get_pad_template (klass,
1638 templ->name_template) == NULL);
1640 klass->padtemplates = g_list_append (klass->padtemplates,
1641 gst_object_ref (GST_OBJECT (templ)));
1642 klass->numpadtemplates++;
1646 * gst_element_class_set_details:
1647 * @klass: class to set details for
1648 * @details: details to set
1650 * Sets the detailed information for a #GstElementClass.
1651 * <note>This function is for use in _base_init functions only.</note>
1654 gst_element_class_set_details (GstElementClass * klass,
1655 const GstElementDetails * details)
1657 g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
1658 g_return_if_fail (GST_IS_ELEMENT_DETAILS (details));
1660 __gst_element_details_copy (&klass->details, details);
1664 * gst_element_class_get_pad_template_list:
1665 * @element_class: a #GstElementClass to get pad templates of.
1667 * Retrieves a list of the pad templates associated with @element_class. The
1668 * list must not be modified by the calling code.
1669 * <note>If you use this function in the #GInstanceInitFunc of an object class
1670 * that has subclasses, make sure to pass the g_class parameter of the
1671 * #GInstanceInitFunc here.</note>
1673 * Returns: the #GList of padtemplates.
1676 gst_element_class_get_pad_template_list (GstElementClass * element_class)
1678 g_return_val_if_fail (GST_IS_ELEMENT_CLASS (element_class), NULL);
1680 return element_class->padtemplates;
1684 * gst_element_class_get_pad_template:
1685 * @element_class: a #GstElementClass to get the pad template of.
1686 * @name: the name of the #GstPadTemplate to get.
1688 * Retrieves a padtemplate from @element_class with the given name.
1689 * <note>If you use this function in the #GInstanceInitFunc of an object class
1690 * that has subclasses, make sure to pass the g_class parameter of the
1691 * #GInstanceInitFunc here.</note>
1693 * Returns: the #GstPadTemplate with the given name, or NULL if none was found.
1694 * No unreferencing is necessary.
1697 gst_element_class_get_pad_template (GstElementClass * element_class,
1702 g_return_val_if_fail (GST_IS_ELEMENT_CLASS (element_class), NULL);
1703 g_return_val_if_fail (name != NULL, NULL);
1705 padlist = gst_element_class_get_pad_template_list (element_class);
1708 GstPadTemplate *padtempl = (GstPadTemplate *) padlist->data;
1710 if (strcmp (padtempl->name_template, name) == 0)
1713 padlist = g_list_next (padlist);
1720 * gst_element_get_pad_template_list:
1721 * @element: a #GstElement to get pad templates of.
1723 * Retrieves a list of the pad templates associated with the element.
1724 * (FIXME: Should be deprecated in favor of
1725 * gst_element_class_get_pad_template_list).
1727 * Returns: the #GList of padtemplates.
1730 gst_element_get_pad_template_list (GstElement * element)
1732 g_return_val_if_fail (element != NULL, NULL);
1733 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1735 return GST_ELEMENT_GET_CLASS (element)->padtemplates;
1739 * gst_element_get_pad_template:
1740 * @element: a #GstElement to get the pad template of.
1741 * @name: the name of the #GstPadTemplate to get.
1743 * Retrieves a padtemplate from this element with the
1745 * (FIXME: Should be deprecated in favor of gst_element_class_get_pad_template).
1747 * Returns: the #GstPadTemplate with the given name, or NULL if none was found.
1748 * No unreferencing is necessary.
1751 gst_element_get_pad_template (GstElement * element, const gchar * name)
1753 g_return_val_if_fail (element != NULL, NULL);
1754 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1755 g_return_val_if_fail (name != NULL, NULL);
1757 return gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (element),
1762 gst_element_error_func (GstElement * element, GstElement * source,
1763 GError * error, gchar * debug)
1765 GstObject *parent = GST_OBJECT_PARENT (element);
1767 /* tell the parent */
1769 gst_object_ref (GST_OBJECT (element));
1770 gst_object_ref (parent);
1771 GST_CAT_DEBUG (GST_CAT_ERROR_SYSTEM,
1772 "forwarding error \"%s\" from %s to %s", error->message,
1773 GST_ELEMENT_NAME (element), GST_OBJECT_NAME (parent));
1775 g_signal_emit (G_OBJECT (parent),
1776 gst_element_signals[ERROR], 0, source, error, debug);
1777 GST_CAT_DEBUG (GST_CAT_ERROR_SYSTEM, "forwarded error \"%s\" from %s to %s",
1778 error->message, GST_ELEMENT_NAME (element), GST_OBJECT_NAME (parent));
1779 gst_object_unref (GST_OBJECT (element));
1780 gst_object_unref (GST_OBJECT (parent));
1785 gst_element_get_random_pad (GstElement * element, GstPadDirection dir)
1787 GstPad *result = NULL;
1790 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "getting a random pad");
1795 pads = element->srcpads;
1798 pads = element->sinkpads;
1801 g_warning ("unknown pad direction");
1804 for (; pads; pads = g_list_next (pads)) {
1805 GstPad *pad = GST_PAD (pads->data);
1808 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "checking pad %s:%s",
1809 GST_DEBUG_PAD_NAME (pad));
1811 if (GST_PAD_IS_LINKED (pad)) {
1816 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s is not linked",
1817 GST_DEBUG_PAD_NAME (pad));
1822 gst_object_ref (GST_OBJECT (result));
1824 GST_UNLOCK (element);
1830 * gst_element_get_event_masks:
1831 * @element: a #GstElement to query
1833 * Get an array of event masks from the element.
1834 * If the element doesn't implement an event masks function,
1835 * the query will be forwarded to a random linked sink pad.
1837 * Returns: An array of #GstEventMask elements. The array
1838 * cannot be modified or freed.
1842 const GstEventMask *
1843 gst_element_get_event_masks (GstElement * element)
1845 GstElementClass *oclass;
1846 const GstEventMask *result = NULL;
1848 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1850 oclass = GST_ELEMENT_GET_CLASS (element);
1852 if (oclass->get_event_masks) {
1853 result = oclass->get_event_masks (element);
1855 GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SINK);
1858 GstPad *peer = gst_pad_get_peer (pad);
1861 result = gst_pad_get_event_masks (peer);
1862 gst_object_unref (GST_OBJECT (peer));
1864 gst_object_unref (GST_OBJECT (pad));
1872 * gst_element_send_event:
1873 * @element: a #GstElement to send the event to.
1874 * @event: the #GstEvent to send to the element.
1876 * Sends an event to an element. If the element doesn't
1877 * implement an event handler, the event will be forwarded
1878 * to a random sink pad. This function takes owership of the
1879 * provided event so you should _ref it if you want to reuse
1880 * the event after this call.
1882 * Returns: TRUE if the event was handled.
1887 gst_element_send_event (GstElement * element, GstEvent * event)
1889 GstElementClass *oclass;
1890 gboolean result = FALSE;
1892 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1893 g_return_val_if_fail (event != NULL, FALSE);
1895 oclass = GST_ELEMENT_GET_CLASS (element);
1897 if (oclass->send_event) {
1898 result = oclass->send_event (element, event);
1900 GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SINK);
1903 GstPad *peer = gst_pad_get_peer (pad);
1906 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
1907 "sending event to random pad %s:%s", GST_DEBUG_PAD_NAME (pad));
1909 result = gst_pad_send_event (peer, event);
1910 gst_object_unref (GST_OBJECT (peer));
1912 gst_object_unref (GST_OBJECT (pad));
1915 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "can't send event on element %s",
1916 GST_ELEMENT_NAME (element));
1923 * @element: a #GstElement to send the event to.
1924 * @seek_type: the method to use for seeking.
1925 * @offset: the offset to seek to.
1927 * Sends a seek event to an element.
1929 * Returns: TRUE if the event was handled.
1934 gst_element_seek (GstElement * element, GstSeekType seek_type, guint64 offset)
1936 GstEvent *event = gst_event_new_seek (seek_type, offset);
1939 result = gst_element_send_event (element, event);
1945 * gst_element_get_query_types:
1946 * @element: a #GstElement to query
1948 * Get an array of query types from the element.
1949 * If the element doesn't implement a query types function,
1950 * the query will be forwarded to a random sink pad.
1952 * Returns: An array of #GstQueryType elements that should not
1953 * be freed or modified.
1957 const GstQueryType *
1958 gst_element_get_query_types (GstElement * element)
1960 GstElementClass *oclass;
1961 const GstQueryType *result = NULL;
1963 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1965 oclass = GST_ELEMENT_GET_CLASS (element);
1967 if (oclass->get_query_types) {
1968 result = oclass->get_query_types (element);
1970 GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SINK);
1973 GstPad *peer = gst_pad_get_peer (pad);
1976 result = gst_pad_get_query_types (peer);
1978 gst_object_unref (GST_OBJECT (peer));
1980 gst_object_unref (GST_OBJECT (pad));
1987 * gst_element_query:
1988 * @element: a #GstElement to perform the query on.
1989 * @type: the #GstQueryType.
1990 * @format: the #GstFormat pointer to hold the format of the result.
1991 * @value: the pointer to the value of the result.
1993 * Performs a query on the given element. If the format is set
1994 * to GST_FORMAT_DEFAULT and this function returns TRUE, the
1995 * format pointer will hold the default format.
1996 * For element that don't implement a query handler, this function
1997 * forwards the query to a random usable sinkpad of this element.
1999 * Returns: TRUE if the query could be performed.
2004 gst_element_query (GstElement * element, GstQueryType type,
2005 GstFormat * format, gint64 * value)
2007 GstElementClass *oclass;
2008 gboolean result = FALSE;
2010 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
2011 g_return_val_if_fail (format != NULL, FALSE);
2012 g_return_val_if_fail (value != NULL, FALSE);
2014 oclass = GST_ELEMENT_GET_CLASS (element);
2016 if (oclass->query) {
2017 result = oclass->query (element, type, format, value);
2019 GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SRC);
2022 result = gst_pad_query (pad, type, format, value);
2024 gst_object_unref (GST_OBJECT (pad));
2026 pad = gst_element_get_random_pad (element, GST_PAD_SINK);
2028 GstPad *peer = gst_pad_get_peer (pad);
2031 result = gst_pad_query (peer, type, format, value);
2033 gst_object_unref (GST_OBJECT (peer));
2035 gst_object_unref (GST_OBJECT (pad));
2043 * gst_element_get_formats:
2044 * @element: a #GstElement to query
2046 * Get an array of formats from the element.
2047 * If the element doesn't implement a formats function,
2048 * the query will be forwarded to a random sink pad.
2050 * Returns: An array of #GstFormat elements.
2055 gst_element_get_formats (GstElement * element)
2057 GstElementClass *oclass;
2058 const GstFormat *result = NULL;
2060 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
2062 oclass = GST_ELEMENT_GET_CLASS (element);
2064 if (oclass->get_formats) {
2065 result = oclass->get_formats (element);
2067 GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SINK);
2070 GstPad *peer = gst_pad_get_peer (pad);
2073 result = gst_pad_get_formats (peer);
2075 gst_object_unref (GST_OBJECT (peer));
2077 gst_object_unref (GST_OBJECT (pad));
2085 * gst_element_convert:
2086 * @element: a #GstElement to invoke the converter on.
2087 * @src_format: the source #GstFormat.
2088 * @src_value: the source value.
2089 * @dest_format: a pointer to the destination #GstFormat.
2090 * @dest_value: a pointer to the destination value.
2092 * Invokes a conversion on the element.
2093 * If the element doesn't implement a convert function,
2094 * the query will be forwarded to a random sink pad.
2096 * Returns: TRUE if the conversion could be performed.
2101 gst_element_convert (GstElement * element,
2102 GstFormat src_format, gint64 src_value,
2103 GstFormat * dest_format, gint64 * dest_value)
2105 GstElementClass *oclass;
2106 gboolean result = FALSE;
2108 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
2109 g_return_val_if_fail (dest_format != NULL, FALSE);
2110 g_return_val_if_fail (dest_value != NULL, FALSE);
2112 if (src_format == *dest_format) {
2113 *dest_value = src_value;
2117 oclass = GST_ELEMENT_GET_CLASS (element);
2119 if (oclass->convert) {
2120 result = oclass->convert (element,
2121 src_format, src_value, dest_format, dest_value);
2123 GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SINK);
2126 GstPad *peer = gst_pad_get_peer (pad);
2129 result = gst_pad_convert (peer,
2130 src_format, src_value, dest_format, dest_value);
2132 gst_object_unref (GST_OBJECT (peer));
2134 gst_object_unref (GST_OBJECT (pad));
2141 * _gst_element_error_printf:
2142 * @format: the printf-like format to use, or NULL
2144 * This function is only used internally by the #gst_element_error macro.
2146 * Returns: a newly allocated string, or NULL if the format was NULL or ""
2151 _gst_element_error_printf (const gchar * format, ...)
2161 va_start (args, format);
2162 buffer = g_strdup_vprintf (format, args);
2168 * gst_element_error_full:
2169 * @element: a #GstElement with the error.
2170 * @domain: the GStreamer error domain this error belongs to.
2171 * @code: the error code belonging to the domain
2172 * @message: an allocated message to be used as a replacement for the default
2173 * message connected to code, or NULL
2174 * @debug: an allocated debug message to be used as a replacement for the
2175 * default debugging information, or NULL
2176 * @file: the source code file where the error was generated
2177 * @function: the source code function where the error was generated
2178 * @line: the source code line where the error was generated
2180 * Signals an error condition on an element.
2181 * This function is used internally by elements.
2182 * It results in the "error" signal.
2184 void gst_element_error_full
2185 (GstElement * element, GQuark domain, gint code, gchar * message,
2186 gchar * debug, const gchar * file, const gchar * function, gint line)
2188 GError *error = NULL;
2190 gchar *sent_message;
2194 g_return_if_fail (GST_IS_ELEMENT (element));
2196 /* check if we send the given message or the default error message */
2197 if ((message == NULL) || (message[0] == 0)) {
2198 /* we got this message from g_strdup_printf (""); */
2200 sent_message = gst_error_get_message (domain, code);
2202 sent_message = message;
2204 if ((debug == NULL) || (debug[0] == 0)) {
2205 /* we got this debug from g_strdup_printf (""); */
2210 /* create error message */
2211 GST_CAT_INFO (GST_CAT_ERROR_SYSTEM, "signaling error in %s: %s",
2212 GST_ELEMENT_NAME (element), sent_message);
2213 error = g_error_new_literal (domain, code, sent_message);
2215 /* if the element was already in error, stop now */
2216 if (GST_FLAG_IS_SET (element, GST_ELEMENT_IN_ERROR)) {
2217 GST_CAT_INFO (GST_CAT_ERROR_SYSTEM, "recursive ERROR detected in %s",
2218 GST_ELEMENT_NAME (element));
2219 g_free (sent_message);
2225 GST_FLAG_SET (element, GST_ELEMENT_IN_ERROR);
2227 /* emit the signal, make sure the element stays available */
2228 gst_object_ref (GST_OBJECT (element));
2229 name = gst_object_get_path_string (GST_OBJECT (element));
2231 sent_debug = g_strdup_printf ("%s(%d): %s: %s:\n%s",
2232 file, line, function, name, debug ? debug : "");
2237 g_signal_emit (G_OBJECT (element), gst_element_signals[ERROR], 0, element,
2239 GST_CAT_INFO (GST_CAT_ERROR_SYSTEM, "signalled error in %s: %s",
2240 GST_ELEMENT_NAME (element), sent_message);
2242 /* tell the scheduler */
2243 if (element->sched) {
2244 gst_scheduler_error (element->sched, element);
2247 if (GST_STATE (element) == GST_STATE_PLAYING) {
2248 GstElementStateReturn ret;
2250 ret = gst_element_set_state (element, GST_STATE_PAUSED);
2251 if (ret != GST_STATE_SUCCESS) {
2252 g_warning ("could not PAUSE element \"%s\" after error, help!",
2253 GST_ELEMENT_NAME (element));
2257 GST_FLAG_UNSET (element, GST_ELEMENT_IN_ERROR);
2260 gst_object_unref (GST_OBJECT (element));
2261 g_free (sent_message);
2262 g_free (sent_debug);
2263 g_error_free (error);
2267 * gst_element_is_locked_state:
2268 * @element: a #GstElement.
2270 * Checks if the state of an element is locked.
2271 * If the state of an element is locked, state changes of the parent don't
2272 * affect the element.
2273 * This way you can leave currently unused elements inside bins. Just lock their
2274 * state before changing the state from #GST_STATE_NULL.
2276 * Returns: TRUE, if the element's state is locked.
2281 gst_element_is_locked_state (GstElement * element)
2283 gboolean result = FALSE;
2285 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
2288 result = GST_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
2289 GST_UNLOCK (element);
2295 * gst_element_set_locked_state:
2296 * @element: a #GstElement
2297 * @locked_state: TRUE to lock the element's state
2299 * Locks the state of an element, so state changes of the parent don't affect
2300 * this element anymore.
2302 * Returns: TRUE if the state was changed, FALSE if bad params were given or
2303 * the element was already in the correct state.
2308 gst_element_set_locked_state (GstElement * element, gboolean locked_state)
2312 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
2315 old = GST_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
2317 if (G_UNLIKELY (old == locked_state))
2321 GST_CAT_DEBUG (GST_CAT_STATES, "locking state of element %s",
2322 GST_ELEMENT_NAME (element));
2323 GST_FLAG_SET (element, GST_ELEMENT_LOCKED_STATE);
2325 GST_CAT_DEBUG (GST_CAT_STATES, "unlocking state of element %s",
2326 GST_ELEMENT_NAME (element));
2327 GST_FLAG_UNSET (element, GST_ELEMENT_LOCKED_STATE);
2329 GST_UNLOCK (element);
2334 GST_UNLOCK (element);
2340 * gst_element_sync_state_with_parent:
2341 * @element: a #GstElement.
2343 * Tries to change the state of the element to the same as its parent.
2344 * If this function returns FALSE, the state of element is undefined.
2346 * Returns: TRUE, if the element's state could be synced to the parent's state.
2349 gst_element_sync_state_with_parent (GstElement * element)
2353 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
2354 parent = GST_ELEMENT (GST_ELEMENT_PARENT (element));
2355 g_return_val_if_fail (GST_IS_BIN (parent), FALSE);
2357 GST_CAT_DEBUG (GST_CAT_STATES, "syncing state of element %s (%s) to %s (%s)",
2358 GST_ELEMENT_NAME (element),
2359 gst_element_state_get_name (GST_STATE (element)),
2360 GST_ELEMENT_NAME (parent),
2361 gst_element_state_get_name (GST_STATE (parent)));
2363 if (gst_element_set_state (element, GST_STATE (parent)) == GST_STATE_FAILURE) {
2370 * gst_element_get_state:
2371 * @element: a #GstElement to get the state of.
2373 * Gets the state of the element.
2375 * Returns: the #GstElementState of the element.
2378 gst_element_get_state (GstElement * element)
2380 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_VOID_PENDING);
2382 return GST_STATE (element);
2386 * gst_element_wait_state_change:
2387 * @element: a #GstElement to wait for a state change on.
2389 * Waits and blocks until the element changed its state.
2392 gst_element_wait_state_change (GstElement * element)
2394 g_mutex_lock (element->state_mutex);
2395 g_cond_wait (element->state_cond, element->state_mutex);
2396 g_mutex_unlock (element->state_mutex);
2400 * gst_element_set_state:
2401 * @element: a #GstElement to change state of.
2402 * @state: the element's new #GstElementState.
2404 * Sets the state of the element. This function will try to set the
2405 * requested state by going through all the intermediary states and calling
2406 * the class's state change function for each.
2408 * Returns: TRUE if the state was successfully set.
2409 * (using #GstElementStateReturn).
2411 GstElementStateReturn
2412 gst_element_set_state (GstElement * element, GstElementState state)
2414 GstElementClass *klass = GST_ELEMENT_GET_CLASS (element);
2415 GstElementStateReturn ret;
2417 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
2418 GST_DEBUG_OBJECT (element, "setting state to %s",
2419 gst_element_state_get_name (state));
2420 klass = GST_ELEMENT_GET_CLASS (element);
2421 g_return_val_if_fail (klass->set_state, GST_STATE_FAILURE);
2423 /* a set_state function is mandatory */
2424 gst_object_ref (GST_OBJECT (element));
2425 ret = klass->set_state (element, state);
2426 gst_object_unref (GST_OBJECT (element));
2431 static GstElementStateReturn
2432 gst_element_set_state_func (GstElement * element, GstElementState state)
2434 GstElementClass *oclass;
2435 GstElementState curpending;
2436 GstElementStateReturn return_val = GST_STATE_SUCCESS;
2438 oclass = GST_ELEMENT_GET_CLASS (element);
2440 /* start with the current state */
2441 curpending = GST_STATE (element);
2443 if (state == curpending) {
2444 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2445 "element is already in requested state %s, returning",
2446 gst_element_state_get_name (state));
2447 return GST_STATE_SUCCESS;
2450 /* reentrancy issues with signals in change_state) */
2451 gst_object_ref (GST_OBJECT (element));
2452 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "setting state from %s to %s",
2453 gst_element_state_get_name (curpending),
2454 gst_element_state_get_name (state));
2456 /* loop until the final requested state is set */
2458 while (GST_STATE (element) != state
2459 && GST_STATE (element) != GST_STATE_VOID_PENDING) {
2460 /* move the curpending state in the correct direction */
2461 if (curpending < state)
2466 /* set the pending state variable */
2467 GST_STATE_PENDING (element) = curpending;
2469 if (curpending != state) {
2470 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2471 "intermediate: setting state from %s to %s",
2472 gst_element_state_get_name (GST_STATE (element)),
2473 gst_element_state_get_name (curpending));
2475 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2476 "start: setting current state %s again",
2477 gst_element_state_get_name (GST_STATE (element)));
2480 /* call the state change function so it can set the state */
2481 if (oclass->change_state)
2482 return_val = (oclass->change_state) (element);
2484 switch (return_val) {
2485 case GST_STATE_FAILURE:
2486 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
2487 "have failed change_state return");
2489 case GST_STATE_ASYNC:
2490 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
2491 "element will change state async");
2493 case GST_STATE_SUCCESS:
2494 /* Last thing we do is verify that a successful state change really
2495 * did change the state... */
2496 /* if it did not, this is an error - fix the element that does this */
2497 if (GST_STATE (element) != curpending) {
2498 g_warning ("element %s claimed state-change success,"
2499 "but state didn't change to %s. State is %s (%s pending), "
2501 GST_ELEMENT_NAME (element),
2502 gst_element_state_get_name (curpending),
2503 gst_element_state_get_name (GST_STATE (element)),
2504 gst_element_state_get_name (GST_STATE_PENDING (element)));
2505 return_val = GST_STATE_FAILURE;
2510 /* somebody added a GST_STATE_ and forgot to do stuff here ! */
2511 g_assert_not_reached ();
2516 gst_object_unref (GST_OBJECT (element));
2522 gst_element_negotiate_pads (GstElement * element)
2526 GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, element, "negotiating pads");
2528 for (pads = GST_ELEMENT_PADS (element); pads; pads = g_list_next (pads)) {
2529 GstPad *pad = GST_PAD (pads->data);
2531 if (!GST_IS_REAL_PAD (pad))
2534 /* if we have a link on this pad and it doesn't have caps
2535 * allready, try to negotiate */
2536 if (!gst_pad_is_negotiated (pad)) {
2537 GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, element,
2538 "perform negotiate for %s:%s", GST_DEBUG_PAD_NAME (pad));
2539 if (gst_pad_renegotiate (pad) == GST_PAD_LINK_REFUSED)
2548 gst_element_clear_pad_caps (GstElement * element)
2550 GList *pads = GST_ELEMENT_PADS (element);
2552 GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, element, "clearing pad caps");
2555 GstPad *pad = GST_PAD (pads->data);
2557 gst_pad_unnegotiate (pad);
2558 if (GST_IS_REAL_PAD (pad)) {
2559 gst_caps_replace (&GST_RPAD_EXPLICIT_CAPS (pad), NULL);
2562 pads = g_list_next (pads);
2567 gst_element_pads_activate (GstElement * element, gboolean active)
2569 GList *pads = element->pads;
2572 GstPad *pad = GST_PAD (pads->data);
2574 pads = g_list_next (pads);
2576 if (!GST_IS_REAL_PAD (pad))
2579 gst_pad_set_active (pad, active);
2583 static GstElementStateReturn
2584 gst_element_change_state (GstElement * element)
2586 GstElementState old_state, old_pending;
2588 gint old_transition;
2590 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
2592 old_state = GST_STATE (element);
2593 old_pending = GST_STATE_PENDING (element);
2594 old_transition = GST_STATE_TRANSITION (element);
2596 /* if the element already is in the given state, we just return success */
2597 if (old_pending == GST_STATE_VOID_PENDING ||
2598 old_state == GST_STATE_PENDING (element)) {
2599 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2600 "element is already in the %s state",
2601 gst_element_state_get_name (old_state));
2602 return GST_STATE_SUCCESS;
2605 /* we need to ref the object because of reentrancy issues with the signal
2606 * handlers (including those in pads and gst_bin_child_state_change */
2607 gst_object_ref (GST_OBJECT (element));
2608 GST_CAT_LOG_OBJECT (GST_CAT_STATES, element,
2609 "default handler tries setting state from %s to %s (%04x)",
2610 gst_element_state_get_name (old_state),
2611 gst_element_state_get_name (old_pending), old_transition);
2613 /* we set the state change early for the negotiation functions */
2614 GST_STATE (element) = old_pending;
2615 GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING;
2617 switch (old_transition) {
2618 case GST_STATE_PLAYING_TO_PAUSED:
2619 if (element->clock) {
2620 GstClockTimeDiff time = GST_CLOCK_TIME_NONE; //gst_clock_get_event_time (element->clock);
2622 g_assert (time >= element->base_time);
2623 element->base_time = time - element->base_time;
2624 GST_CAT_LOG_OBJECT (GST_CAT_CLOCK, element, "setting base time to %"
2625 G_GINT64_FORMAT, element->base_time);
2627 gst_element_pads_activate (element, FALSE);
2629 case GST_STATE_PAUSED_TO_PLAYING:
2630 gst_element_pads_activate (element, TRUE);
2631 if (element->clock) {
2632 GstClockTime time = GST_CLOCK_TIME_NONE; //gst_clock_get_event_time (element->clock);
2634 element->base_time = time - element->base_time;
2635 GST_CAT_LOG_OBJECT (GST_CAT_CLOCK, element, "setting base time to %"
2636 GST_TIME_FORMAT, GST_TIME_ARGS (element->base_time));
2639 /* if we are going to paused, we try to negotiate the pads */
2640 case GST_STATE_READY_TO_PAUSED:
2641 g_assert (element->base_time == 0);
2642 if (!gst_element_negotiate_pads (element)) {
2643 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
2644 "failed state change, could not negotiate pads");
2648 /* going to the READY state clears all pad caps */
2649 /* FIXME: Why doesn't this happen on READY => NULL? -- Company */
2650 case GST_STATE_PAUSED_TO_READY:
2651 element->base_time = 0;
2652 gst_element_clear_pad_caps (element);
2654 case GST_STATE_NULL_TO_READY:
2655 case GST_STATE_READY_TO_NULL:
2658 /* this will catch real but unhandled state changes;
2659 * can only be caused by:
2660 * - a new state was added
2661 * - somehow the element was asked to jump across an intermediate state
2663 g_warning ("Unhandled state change from %s to %s",
2664 gst_element_state_get_name (old_state),
2665 gst_element_state_get_name (old_pending));
2669 parent = GST_ELEMENT_PARENT (element);
2671 GST_CAT_LOG_OBJECT (GST_CAT_STATES, element,
2672 "signaling state change from %s to %s",
2673 gst_element_state_get_name (old_state),
2674 gst_element_state_get_name (GST_STATE (element)));
2676 /* tell the scheduler if we have one */
2677 if (element->sched) {
2678 if (gst_scheduler_state_transition (element->sched, element,
2679 old_transition) != GST_STATE_SUCCESS) {
2680 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
2681 "scheduler could not change state");
2686 /* tell our parent about the state change */
2687 if (parent && GST_IS_BIN (parent)) {
2688 gst_bin_child_state_change (GST_BIN (parent), old_state,
2689 GST_STATE (element), element);
2691 /* at this point the state of the element could have changed again */
2693 g_signal_emit (G_OBJECT (element), gst_element_signals[STATE_CHANGE],
2694 0, old_state, GST_STATE (element));
2696 /* signal the state change in case somebody is waiting for us */
2697 g_cond_signal (element->state_cond);
2699 gst_object_unref (GST_OBJECT (element));
2700 return GST_STATE_SUCCESS;
2703 /* undo the state change */
2704 GST_STATE (element) = old_state;
2705 GST_STATE_PENDING (element) = old_pending;
2706 gst_object_unref (GST_OBJECT (element));
2708 return GST_STATE_FAILURE;
2712 * gst_element_get_factory:
2713 * @element: a #GstElement to request the element factory of.
2715 * Retrieves the factory that was used to create this element.
2717 * Returns: the #GstElementFactory used for creating this element.
2720 gst_element_get_factory (GstElement * element)
2722 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
2724 return GST_ELEMENT_GET_CLASS (element)->elementfactory;
2728 gst_element_dispose (GObject * object)
2730 GstElement *element = GST_ELEMENT (object);
2732 GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "dispose");
2734 gst_element_set_state (element, GST_STATE_NULL);
2736 /* first we break all our links with the ouside */
2737 while (element->pads) {
2738 gst_element_remove_pad (element, GST_PAD (element->pads->data));
2741 element->numsrcpads = 0;
2742 element->numsinkpads = 0;
2743 element->numpads = 0;
2744 if (element->state_mutex)
2745 g_mutex_free (element->state_mutex);
2746 element->state_mutex = NULL;
2747 if (element->state_cond)
2748 g_cond_free (element->state_cond);
2749 element->state_cond = NULL;
2751 if (element->prop_value_queue)
2752 g_async_queue_unref (element->prop_value_queue);
2753 element->prop_value_queue = NULL;
2754 if (element->property_mutex)
2755 g_mutex_free (element->property_mutex);
2756 element->property_mutex = NULL;
2758 gst_object_replace ((GstObject **) & element->sched, NULL);
2759 gst_object_replace ((GstObject **) & element->clock, NULL);
2761 G_OBJECT_CLASS (parent_class)->dispose (object);
2765 gst_element_finalize (GObject * object)
2767 //GstElement *element = GST_ELEMENT (object);
2769 G_OBJECT_CLASS (parent_class)->finalize (object);
2772 #ifndef GST_DISABLE_LOADSAVE
2774 * gst_element_save_thyself:
2775 * @element: a #GstElement to save.
2776 * @parent: the xml parent node.
2778 * Saves the element as part of the given XML structure.
2780 * Returns: the new #xmlNodePtr.
2783 gst_element_save_thyself (GstObject * object, xmlNodePtr parent)
2786 GstElementClass *oclass;
2787 GParamSpec **specs, *spec;
2789 GValue value = { 0, };
2790 GstElement *element;
2792 g_return_val_if_fail (GST_IS_ELEMENT (object), parent);
2794 element = GST_ELEMENT (object);
2796 oclass = GST_ELEMENT_GET_CLASS (element);
2798 xmlNewChild (parent, NULL, "name", GST_ELEMENT_NAME (element));
2800 if (oclass->elementfactory != NULL) {
2801 GstElementFactory *factory = (GstElementFactory *) oclass->elementfactory;
2803 xmlNewChild (parent, NULL, "type", GST_PLUGIN_FEATURE (factory)->name);
2806 /* FIXME: what is this? */
2807 /* if (element->manager) */
2808 /* xmlNewChild(parent, NULL, "manager", GST_ELEMENT_NAME(element->manager)); */
2811 specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (object), &nspecs);
2813 for (i = 0; i < nspecs; i++) {
2815 if (spec->flags & G_PARAM_READABLE) {
2819 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (spec));
2821 g_object_get_property (G_OBJECT (element), spec->name, &value);
2822 param = xmlNewChild (parent, NULL, "param", NULL);
2823 xmlNewChild (param, NULL, "name", spec->name);
2825 if (G_IS_PARAM_SPEC_STRING (spec))
2826 contents = g_value_dup_string (&value);
2827 else if (G_IS_PARAM_SPEC_ENUM (spec))
2828 contents = g_strdup_printf ("%d", g_value_get_enum (&value));
2829 else if (G_IS_PARAM_SPEC_INT64 (spec))
2830 contents = g_strdup_printf ("%" G_GINT64_FORMAT,
2831 g_value_get_int64 (&value));
2833 contents = g_strdup_value_contents (&value);
2835 xmlNewChild (param, NULL, "value", contents);
2838 g_value_unset (&value);
2842 pads = GST_ELEMENT_PADS (element);
2845 GstPad *pad = GST_PAD (pads->data);
2847 /* figure out if it's a direct pad or a ghostpad */
2848 if (GST_ELEMENT (GST_OBJECT_PARENT (pad)) == element) {
2849 xmlNodePtr padtag = xmlNewChild (parent, NULL, "pad", NULL);
2851 gst_object_save_thyself (GST_OBJECT (pad), padtag);
2853 pads = g_list_next (pads);
2860 gst_element_restore_thyself (GstObject * object, xmlNodePtr self)
2862 xmlNodePtr children;
2863 GstElement *element;
2865 gchar *value = NULL;
2867 element = GST_ELEMENT (object);
2868 g_return_if_fail (element != NULL);
2871 children = self->xmlChildrenNode;
2873 if (!strcmp (children->name, "param")) {
2874 xmlNodePtr child = children->xmlChildrenNode;
2877 if (!strcmp (child->name, "name")) {
2878 name = xmlNodeGetContent (child);
2879 } else if (!strcmp (child->name, "value")) {
2880 value = xmlNodeGetContent (child);
2882 child = child->next;
2884 /* FIXME: can this just be g_object_set ? */
2885 gst_util_set_object_arg (G_OBJECT (element), name, value);
2886 /* g_object_set (G_OBJECT (element), name, value, NULL); */
2890 children = children->next;
2894 children = self->xmlChildrenNode;
2896 if (!strcmp (children->name, "pad")) {
2897 gst_pad_load_and_link (children, GST_OBJECT (element));
2899 children = children->next;
2902 if (GST_OBJECT_CLASS (parent_class)->restore_thyself)
2903 (GST_OBJECT_CLASS (parent_class)->restore_thyself) (object, self);
2905 #endif /* GST_DISABLE_LOADSAVE */
2908 * gst_element_yield:
2909 * @element: a #GstElement to yield.
2911 * Requests a yield operation for the element. The scheduler will typically
2912 * give control to another element.
2915 gst_element_yield (GstElement * element)
2917 if (GST_ELEMENT_SCHEDULER (element)) {
2918 gst_scheduler_yield (GST_ELEMENT_SCHEDULER (element), element);
2923 * gst_element_interrupt:
2924 * @element: a #GstElement to interrupt.
2926 * Requests the scheduler of this element to interrupt the execution of
2927 * this element and scheduler another one.
2929 * Returns: TRUE if the element should exit its chain/loop/get
2930 * function ASAP, depending on the scheduler implementation.
2933 gst_element_interrupt (GstElement * element)
2935 if (GST_ELEMENT_SCHEDULER (element)) {
2936 return gst_scheduler_interrupt (GST_ELEMENT_SCHEDULER (element), element);
2942 * gst_element_set_scheduler:
2943 * @element: a #GstElement to set the scheduler of.
2944 * @scheduler: the #GstScheduler to set.
2946 * Sets the scheduler of the element. For internal use only, unless you're
2952 gst_element_set_scheduler (GstElement * element, GstScheduler * scheduler)
2954 GstElementClass *oclass;
2956 g_return_if_fail (GST_IS_ELEMENT (element));
2958 oclass = GST_ELEMENT_GET_CLASS (element);
2960 if (oclass->set_scheduler)
2961 oclass->set_scheduler (element, scheduler);
2965 * gst_element_get_scheduler:
2966 * @element: a #GstElement to get the scheduler of.
2968 * Returns the scheduler of the element.
2970 * Returns: the element's #GstScheduler.
2975 gst_element_get_scheduler (GstElement * element)
2977 GstScheduler *result = NULL;
2979 g_return_val_if_fail (GST_IS_ELEMENT (element), result);
2982 result = GST_ELEMENT_SCHEDULER (element);
2983 GST_UNLOCK (element);
2989 * gst_element_set_loop_function:
2990 * @element: a #GstElement to set the loop function of.
2991 * @loop: Pointer to #GstElementLoopFunction.
2993 * This sets the loop function for the element. The function pointed to
2994 * can deviate from the GstElementLoopFunction definition in type of
2997 * NOTE: in order for this to take effect, the current loop function *must*
2998 * exit. Assuming the loop function itself is the only one who will cause
2999 * a new loopfunc to be assigned, this should be no problem.
3002 gst_element_set_loop_function (GstElement * element,
3003 GstElementLoopFunction loop)
3005 gboolean need_notify = FALSE;
3007 g_return_if_fail (GST_IS_ELEMENT (element));
3009 /* if the element changed from loop based to chain/get based
3010 * or vice versa, we need to inform the scheduler about that */
3011 if ((element->loopfunc == NULL && loop != NULL) ||
3012 (element->loopfunc != NULL && loop == NULL)) {
3016 /* set the loop function */
3017 element->loopfunc = loop;
3020 /* set the NEW_LOOPFUNC flag so everyone knows to go try again */
3021 GST_FLAG_SET (element, GST_ELEMENT_NEW_LOOPFUNC);
3023 if (GST_ELEMENT_SCHEDULER (element)) {
3024 gst_scheduler_scheduling_change (GST_ELEMENT_SCHEDULER (element),
3030 gst_element_emit_found_tag (GstElement * element, GstElement * source,
3031 const GstTagList * tag_list)
3033 gst_object_ref (GST_OBJECT (element));
3034 g_signal_emit (element, gst_element_signals[FOUND_TAG], 0, source, tag_list);
3035 gst_object_unref (GST_OBJECT (element));
3038 gst_element_found_tag_func (GstElement * element, GstElement * source,
3039 const GstTagList * tag_list)
3041 /* tell the parent */
3042 if (GST_OBJECT_PARENT (element)) {
3043 GST_CAT_LOG_OBJECT (GST_CAT_EVENT, element, "forwarding tag event to %s",
3044 GST_OBJECT_NAME (GST_OBJECT_PARENT (element)));
3045 gst_element_emit_found_tag (GST_ELEMENT (GST_OBJECT_PARENT (element)),
3051 * gst_element_found_tags:
3052 * @element: the element that found the tags
3053 * @tag_list: the found tags
3055 * This function emits the found_tags signal. This is a recursive signal, so
3056 * every parent will emit that signal, too, before this function returns.
3057 * Only emit this signal, when you extracted these tags out of the data stream,
3058 * not when you handle an event.
3061 gst_element_found_tags (GstElement * element, const GstTagList * tag_list)
3063 gst_element_emit_found_tag (element, element, tag_list);
3067 * gst_element_found_tags_for_pad:
3068 * @element: element that found the tag
3069 * @pad: src pad the tags correspond to
3070 * @timestamp: time the tags were found
3071 * @list: the taglist
3073 * This is a convenience routine for tag finding. Most of the time you only
3074 * want to push the found tags down one pad, in that case this function is for
3075 * you. It takes ownership of the taglist, emits the found-tag signal and
3076 * pushes a tag event down the pad.
3077 * <note>This function may not be used in a #GstPadGetFunction, because it calls
3078 * gst_pad_push(). In those functions, call gst_element_found_tags(), create a
3079 * tag event with gst_event_new_tag() and return that from your
3080 * #GstPadGetFunction.</note>
3083 gst_element_found_tags_for_pad (GstElement * element, GstPad * pad,
3084 GstClockTime timestamp, GstTagList * list)
3086 GstEvent *tag_event;
3088 g_return_if_fail (GST_IS_ELEMENT (element));
3089 g_return_if_fail (GST_IS_REAL_PAD (pad));
3090 g_return_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SRC);
3091 g_return_if_fail (element == GST_PAD_PARENT (pad));
3092 g_return_if_fail (list != NULL);
3094 tag_event = gst_event_new_tag (list);
3095 GST_EVENT_TIMESTAMP (tag_event) = timestamp;
3096 gst_element_found_tags (element, gst_event_tag_get_list (tag_event));
3097 if (GST_PAD_IS_USABLE (pad)) {
3098 gst_pad_push (pad, GST_DATA (tag_event));
3100 gst_data_unref (GST_DATA (tag_event));
3105 gst_element_set_eos_recursive (GstElement * element)
3107 /* this function is only called, when we were in PLAYING before. So every
3108 parent that's PAUSED was PLAYING before. That means it has reached EOS. */
3111 GST_CAT_DEBUG (GST_CAT_EVENT, "setting recursive EOS on %s",
3112 GST_OBJECT_NAME (element));
3113 g_signal_emit (G_OBJECT (element), gst_element_signals[EOS], 0);
3115 if (!GST_OBJECT_PARENT (element))
3118 parent = GST_ELEMENT (GST_OBJECT_PARENT (element));
3119 if (GST_STATE (parent) == GST_STATE_PAUSED)
3120 gst_element_set_eos_recursive (parent);
3124 * gst_element_set_eos:
3125 * @element: a #GstElement to set to the EOS state.
3127 * Perform the actions needed to bring the element in the EOS state.
3130 gst_element_set_eos (GstElement * element)
3132 g_return_if_fail (GST_IS_ELEMENT (element));
3134 GST_CAT_DEBUG (GST_CAT_EVENT, "setting EOS on element %s",
3135 GST_OBJECT_NAME (element));
3137 if (GST_STATE (element) == GST_STATE_PLAYING) {
3138 gst_element_set_state (element, GST_STATE_PAUSED);
3139 gst_element_set_eos_recursive (element);
3141 g_signal_emit (G_OBJECT (element), gst_element_signals[EOS], 0);
3146 * gst_element_get_managing_bin:
3147 * @element: a #GstElement to get the managing bin of.
3149 * Gets the managing bin (a pipeline or a thread, for example) of an element.
3151 * Returns: the #GstBin, or NULL on failure.
3154 gst_element_get_managing_bin (GstElement * element)
3158 g_return_val_if_fail (element != NULL, NULL);
3160 bin = GST_BIN (gst_object_get_parent (GST_OBJECT (element)));
3162 while (bin && !GST_FLAG_IS_SET (GST_OBJECT (bin), GST_BIN_FLAG_MANAGER))
3163 bin = GST_BIN (gst_object_get_parent (GST_OBJECT (bin)));