gst/: remove now useless and leaky resurrection code in dispose
[platform/upstream/gstreamer.git] / gst / gstelement.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2004 Wim Taymans <wim@fluendo.com>
4  *
5  * gstelement.c: The base element, all elements derive from this
6  *
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.
11  *
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.
16  *
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.
21  */
22 /**
23  * SECTION:gstelement
24  * @short_description: Abstract base class for all pipeline elements
25  * @see_also: #GstElementFactory, #GstPad
26  *
27  * GstElement is the base class needed to construct an element that can be
28  * used in a GStreamer pipeline.  As such, it is not a functional entity, and
29  * cannot do anything when placed in a pipeline.
30  * 
31  * The name of a GstElement can be get with gst_element_get_name() and set with
32  * gst_element_set_name().  For speed, GST_ELEMENT_NAME() can be used in the 
33  * core. Do not use this in plug-ins or applications in order to retain ABI 
34  * compatibility.
35  * 
36  * All elements have pads (of the type #GstPad).  These pads link to pads on
37  * other elements.  Buffers flow between these linked pads.
38  * A GstElement has a GList of #GstPad structures for all their input (or sink)
39  * and output (or source) pads.  
40  * Core and plug-in writers can add and remove pads with gst_element_add_pad()
41  * and gst_element_remove_pad().
42  *
43  * A pad of an element can be retrieved by name with gst_element_get_pad().
44  * An iterator of all pads can be retrieved with gst_element_iterate_pads().
45  * 
46  * Elements can be linked through their pads.
47  * If the link is straightforward, use the gst_element_link() 
48  * convenience function to link two elements, or gst_element_link_many() 
49  * for more elements in a row.
50  * Use gst_element_link_filtered() to link two elements constrained by
51  * a specified set of #GstCaps.
52  * For finer control, use gst_element_link_pads() and 
53  * gst_element_link_pads_filtered() to specify the pads to link on 
54  * each element by name.
55  * 
56  * Each element has a state (see #GstState).  You can get and set the state
57  * of an element with gst_element_get_state() and gst_element_set_state().  
58  * You can wait for an element to change it's state with gst_element_wait_state_change().
59  * To get a string representation of a #GstState, use 
60  * gst_element_state_get_name().
61  * 
62  * You can get and set a #GstClock on an element using gst_element_get_clock()
63  * and gst_element_set_clock().  
64  */
65 #include "gst_private.h"
66 #include <glib.h>
67 #include <stdarg.h>
68 #include <gobject/gvaluecollector.h>
69
70 #include "gstelement.h"
71 #include "gstbus.h"
72 #include "gstmarshal.h"
73 #include "gsterror.h"
74 #include "gstevent.h"
75 #include "gstutils.h"
76 #include "gstinfo.h"
77 #include "gst-i18n-lib.h"
78
79 /* Element signals and args */
80 enum
81 {
82   STATE_CHANGE,
83   NEW_PAD,
84   PAD_REMOVED,
85   NO_MORE_PADS,
86   /* add more above */
87   LAST_SIGNAL
88 };
89
90 enum
91 {
92   ARG_0
93       /* FILL ME */
94 };
95
96 extern void __gst_element_details_clear (GstElementDetails * dp);
97 extern void __gst_element_details_copy (GstElementDetails * dest,
98     const GstElementDetails * src);
99
100 static void gst_element_class_init (GstElementClass * klass);
101 static void gst_element_init (GstElement * element);
102 static void gst_element_base_class_init (gpointer g_class);
103 static void gst_element_base_class_finalize (gpointer g_class);
104
105 static void gst_element_dispose (GObject * object);
106 static void gst_element_finalize (GObject * object);
107
108 static GstStateChangeReturn gst_element_change_state (GstElement * element,
109     GstStateChange transition);
110 static GstStateChangeReturn gst_element_get_state_func (GstElement * element,
111     GstState * state, GstState * pending, GTimeVal * timeout);
112 static void gst_element_set_bus_func (GstElement * element, GstBus * bus);
113
114 #ifndef GST_DISABLE_LOADSAVE
115 static xmlNodePtr gst_element_save_thyself (GstObject * object,
116     xmlNodePtr parent);
117 static void gst_element_restore_thyself (GstObject * parent, xmlNodePtr self);
118 #endif
119
120 GType _gst_element_type = 0;
121
122 static GstObjectClass *parent_class = NULL;
123 static guint gst_element_signals[LAST_SIGNAL] = { 0 };
124
125 GType
126 gst_element_get_type (void)
127 {
128   if (!_gst_element_type) {
129     static const GTypeInfo element_info = {
130       sizeof (GstElementClass),
131       gst_element_base_class_init,
132       gst_element_base_class_finalize,
133       (GClassInitFunc) gst_element_class_init,
134       NULL,
135       NULL,
136       sizeof (GstElement),
137       0,
138       (GInstanceInitFunc) gst_element_init,
139       NULL
140     };
141
142     _gst_element_type = g_type_register_static (GST_TYPE_OBJECT, "GstElement",
143         &element_info, G_TYPE_FLAG_ABSTRACT);
144   }
145   return _gst_element_type;
146 }
147
148 static void
149 gst_element_class_init (GstElementClass * klass)
150 {
151   GObjectClass *gobject_class;
152   GstObjectClass *gstobject_class;
153
154   gobject_class = (GObjectClass *) klass;
155   gstobject_class = (GstObjectClass *) klass;
156
157   parent_class = g_type_class_ref (GST_TYPE_OBJECT);
158
159   /**
160    * GstElement::state-changed:
161    * @gstelement: the object which received the signal
162    * @old_state: the GST_STATE_XXX before the change
163    * @new_state: the GST_STATE_XXX after the change
164    *
165    * the #GstState of the element has been changed
166    */
167   gst_element_signals[STATE_CHANGE] =
168       g_signal_new ("state-changed", G_TYPE_FROM_CLASS (klass),
169       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstElementClass, state_changed), NULL,
170       NULL, gst_marshal_VOID__INT_INT, G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT);
171   /**
172    * GstElement::pad-added:
173    * @gstelement: the object which received the signal
174    * @new_pad: the pad that has been added
175    *
176    * a new #GstPad has been added to the element
177    */
178   gst_element_signals[NEW_PAD] =
179       g_signal_new ("pad-added", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
180       G_STRUCT_OFFSET (GstElementClass, pad_added), NULL, NULL,
181       gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT);
182   /**
183    * GstElement::pad-removed:
184    * @gstelement: the object which received the signal
185    * @old_pad: the pad that has been removed
186    *
187    * a #GstPad has been removed from the element
188    */
189   gst_element_signals[PAD_REMOVED] =
190       g_signal_new ("pad-removed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
191       G_STRUCT_OFFSET (GstElementClass, pad_removed), NULL, NULL,
192       gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT);
193   /**
194    * GstElement::no-more-pads:
195    * @gstelement: the object which received the signal
196    *
197    * This signals that the element will not generate more dynamic pads.
198    */
199   gst_element_signals[NO_MORE_PADS] =
200       g_signal_new ("no-more-pads", G_TYPE_FROM_CLASS (klass),
201       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstElementClass, no_more_pads), NULL,
202       NULL, gst_marshal_VOID__VOID, G_TYPE_NONE, 0);
203
204   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_element_dispose);
205   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_element_finalize);
206
207 #ifndef GST_DISABLE_LOADSAVE
208   gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_element_save_thyself);
209   gstobject_class->restore_thyself =
210       GST_DEBUG_FUNCPTR (gst_element_restore_thyself);
211 #endif
212
213   klass->change_state = GST_DEBUG_FUNCPTR (gst_element_change_state);
214   klass->get_state = GST_DEBUG_FUNCPTR (gst_element_get_state_func);
215   klass->set_bus = GST_DEBUG_FUNCPTR (gst_element_set_bus_func);
216   klass->numpadtemplates = 0;
217
218   klass->elementfactory = NULL;
219 }
220
221 static void
222 gst_element_base_class_init (gpointer g_class)
223 {
224   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
225
226   memset (&element_class->details, 0, sizeof (GstElementDetails));
227   element_class->padtemplates = NULL;
228 }
229
230 static void
231 gst_element_base_class_finalize (gpointer g_class)
232 {
233   GstElementClass *klass = GST_ELEMENT_CLASS (g_class);
234
235   g_list_foreach (klass->padtemplates, (GFunc) gst_object_unref, NULL);
236   g_list_free (klass->padtemplates);
237   __gst_element_details_clear (&klass->details);
238 }
239
240 static void
241 gst_element_init (GstElement * element)
242 {
243   element->current_state = GST_STATE_NULL;
244   element->pending_state = GST_STATE_VOID_PENDING;
245   element->state_lock = g_mutex_new ();
246   element->state_cond = g_cond_new ();
247 }
248
249 /**
250  * gst_element_default_error:
251  * @object: a #GObject that signalled the error.
252  * @orig: the #GstObject that initiated the error.
253  * @error: the GError.
254  * @debug: an additional debug information string, or NULL.
255  *
256  * A default error signal callback to attach to an element.
257  * The user data passed to the g_signal_connect is ignored.
258  *
259  * The default handler will simply print the error string using g_print.
260  *
261  * MT safe.
262  */
263 void
264 gst_element_default_error (GObject * object, GstObject * source, GError * error,
265     gchar * debug)
266 {
267   gchar *name = gst_object_get_path_string (source);
268
269   g_print (_("ERROR: from element %s: %s\n"), name, error->message);
270   if (debug)
271     g_print (_("Additional debug info:\n%s\n"), debug);
272
273   g_free (name);
274 }
275
276 /**
277  * gst_element_release_request_pad:
278  * @element: a #GstElement to release the request pad of.
279  * @pad: the #GstPad to release.
280  *
281  * Makes the element free the previously requested pad as obtained
282  * with gst_element_get_request_pad().
283  *
284  * MT safe.
285  */
286 void
287 gst_element_release_request_pad (GstElement * element, GstPad * pad)
288 {
289   GstElementClass *oclass;
290
291   g_return_if_fail (GST_IS_ELEMENT (element));
292   g_return_if_fail (GST_IS_PAD (pad));
293
294   oclass = GST_ELEMENT_GET_CLASS (element);
295
296   if (oclass->release_pad)
297     (oclass->release_pad) (element, pad);
298   else
299     gst_element_remove_pad (element, pad);
300 }
301
302 /**
303  * gst_element_requires_clock:
304  * @element: a #GstElement to query
305  *
306  * Query if the element requires a clock.
307  *
308  * Returns: TRUE if the element requires a clock
309  *
310  * MT safe.
311  */
312 gboolean
313 gst_element_requires_clock (GstElement * element)
314 {
315   gboolean result = FALSE;
316
317   g_return_val_if_fail (GST_IS_ELEMENT (element), result);
318
319   result = (GST_ELEMENT_GET_CLASS (element)->set_clock != NULL);
320
321   return result;
322 }
323
324 /**
325  * gst_element_provides_clock:
326  * @element: a #GstElement to query
327  *
328  * Query if the element provides a clock.
329  *
330  * Returns: TRUE if the element provides a clock
331  *
332  * MT safe.
333  */
334 gboolean
335 gst_element_provides_clock (GstElement * element)
336 {
337   gboolean result = FALSE;
338
339   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
340
341   result = (GST_ELEMENT_GET_CLASS (element)->get_clock != NULL);
342
343   return result;
344 }
345
346 /**
347  * gst_element_set_clock:
348  * @element: a #GstElement to set the clock for.
349  * @clock: the #GstClock to set for the element.
350  *
351  * Sets the clock for the element. This function increases the
352  * refcount on the clock. Any previously set clock on the object
353  * is unreffed.
354  *
355  * MT safe.
356  */
357 void
358 gst_element_set_clock (GstElement * element, GstClock * clock)
359 {
360   GstElementClass *oclass;
361
362   g_return_if_fail (GST_IS_ELEMENT (element));
363
364   oclass = GST_ELEMENT_GET_CLASS (element);
365
366   if (oclass->set_clock)
367     oclass->set_clock (element, clock);
368
369   GST_LOCK (element);
370   gst_object_replace ((GstObject **) & element->clock, (GstObject *) clock);
371   GST_UNLOCK (element);
372 }
373
374 /**
375  * gst_element_get_clock:
376  * @element: a #GstElement to get the clock of.
377  *
378  * Gets the clock of the element. If the element provides a clock,
379  * this function will return this clock. For elements that do not
380  * provide a clock, this function returns NULL.
381  *
382  * Returns: the #GstClock of the element. unref after usage.
383  *
384  * MT safe.
385  */
386 GstClock *
387 gst_element_get_clock (GstElement * element)
388 {
389   GstElementClass *oclass;
390
391   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
392
393   oclass = GST_ELEMENT_GET_CLASS (element);
394
395   if (oclass->get_clock)
396     return oclass->get_clock (element);
397
398   return NULL;
399 }
400
401 /**
402  * gst_element_set_base_time:
403  * @element: a #GstElement.
404  * @time: the base time to set.
405  *
406  * Set the base time of an element. See @gst_element_get_base_time().
407  *
408  * MT safe.
409  */
410 void
411 gst_element_set_base_time (GstElement * element, GstClockTime time)
412 {
413   g_return_if_fail (GST_IS_ELEMENT (element));
414
415   GST_LOCK (element);
416   element->base_time = time;
417   GST_UNLOCK (element);
418 }
419
420 /**
421  * gst_element_get_base_time:
422  * @element: a #GstElement.
423  *
424  * Returns the base time of the element. The base time is the
425  * absolute time of the clock when this element was last put to
426  * PLAYING. Substracting the base time from the clock time gives
427  * the stream time of the element.
428  *
429  * Returns: the base time of the element.
430  *
431  * MT safe.
432  */
433 GstClockTime
434 gst_element_get_base_time (GstElement * element)
435 {
436   GstClockTime result;
437
438   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_CLOCK_TIME_NONE);
439
440   GST_LOCK (element);
441   result = element->base_time;
442   GST_UNLOCK (element);
443
444   return result;
445 }
446
447 #ifndef GST_DISABLE_INDEX
448 /**
449  * gst_element_is_indexable:
450  * @element: a #GstElement.
451  *
452  * Queries if the element can be indexed.
453  *
454  * Returns: TRUE if the element can be indexed.
455  *
456  * MT safe.
457  */
458 gboolean
459 gst_element_is_indexable (GstElement * element)
460 {
461   gboolean result = FALSE;
462
463   g_return_val_if_fail (GST_IS_ELEMENT (element), result);
464
465   result = (GST_ELEMENT_GET_CLASS (element)->set_index != NULL);
466
467   return result;
468 }
469
470 /**
471  * gst_element_set_index:
472  * @element: a #GstElement.
473  * @index: a #GstIndex.
474  *
475  * Set the specified GstIndex on the element.
476  *
477  * MT safe.
478  */
479 void
480 gst_element_set_index (GstElement * element, GstIndex * index)
481 {
482   GstElementClass *oclass;
483
484   g_return_if_fail (GST_IS_ELEMENT (element));
485   g_return_if_fail (GST_IS_INDEX (index));
486
487   oclass = GST_ELEMENT_GET_CLASS (element);
488
489   if (oclass->set_index)
490     oclass->set_index (element, index);
491 }
492
493 /**
494  * gst_element_get_index:
495  * @element: a #GstElement.
496  *
497  * Gets the index from the element.
498  *
499  * Returns: a #GstIndex or NULL when no index was set on the
500  * element. unref after usage.
501  *
502  * MT safe.
503  */
504 GstIndex *
505 gst_element_get_index (GstElement * element)
506 {
507   GstElementClass *oclass;
508
509   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
510
511   oclass = GST_ELEMENT_GET_CLASS (element);
512
513   if (oclass->get_index)
514     return oclass->get_index (element);
515
516   return NULL;
517 }
518 #endif
519
520 /**
521  * gst_element_add_pad:
522  * @element: a #GstElement to add the pad to.
523  * @pad: the #GstPad to add to the element.
524  *
525  * Adds a pad (link point) to @element. @pad's parent will be set to @element;
526  * see gst_object_set_parent() for refcounting information.
527  *
528  * Pads are not automatically activated so elements should perform the needed
529  * steps to activate the pad. 
530  *
531  * The pad and the element should be unlocked when calling this function.
532  *
533  * Returns: TRUE if the pad could be added. This function can fail when
534  * passing bad arguments or when a pad with the same name already existed.
535  *
536  * MT safe.
537  */
538 gboolean
539 gst_element_add_pad (GstElement * element, GstPad * pad)
540 {
541   gchar *pad_name;
542
543   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
544   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
545
546   /* locking pad to look at the name */
547   GST_LOCK (pad);
548   pad_name = g_strdup (GST_PAD_NAME (pad));
549   GST_CAT_INFO_OBJECT (GST_CAT_ELEMENT_PADS, element, "adding pad '%s'",
550       GST_STR_NULL (pad_name));
551   GST_UNLOCK (pad);
552
553   /* then check to see if there's already a pad by that name here */
554   GST_LOCK (element);
555   if (G_UNLIKELY (!gst_object_check_uniqueness (element->pads, pad_name)))
556     goto name_exists;
557
558   /* try to set the pad's parent */
559   if (G_UNLIKELY (!gst_object_set_parent (GST_OBJECT_CAST (pad),
560               GST_OBJECT_CAST (element))))
561     goto had_parent;
562
563   g_free (pad_name);
564
565   /* add it to the list */
566   switch (gst_pad_get_direction (pad)) {
567     case GST_PAD_SRC:
568       element->srcpads = g_list_prepend (element->srcpads, pad);
569       element->numsrcpads++;
570       break;
571     case GST_PAD_SINK:
572       element->sinkpads = g_list_prepend (element->sinkpads, pad);
573       element->numsinkpads++;
574       break;
575     default:
576       goto no_direction;
577   }
578   element->pads = g_list_prepend (element->pads, pad);
579   element->numpads++;
580   element->pads_cookie++;
581   GST_UNLOCK (element);
582
583   /* emit the NEW_PAD signal */
584   g_signal_emit (G_OBJECT (element), gst_element_signals[NEW_PAD], 0, pad);
585
586   return TRUE;
587
588   /* ERROR cases */
589 name_exists:
590   {
591     g_critical ("Padname %s is not unique in element %s, not adding",
592         pad_name, GST_ELEMENT_NAME (element));
593     GST_UNLOCK (element);
594     g_free (pad_name);
595     return FALSE;
596   }
597 had_parent:
598   {
599     g_critical
600         ("Pad %s already has parent when trying to add to element %s",
601         pad_name, GST_ELEMENT_NAME (element));
602     GST_UNLOCK (element);
603     g_free (pad_name);
604     return FALSE;
605   }
606 no_direction:
607   {
608     GST_LOCK (pad);
609     g_critical
610         ("Trying to add pad %s to element %s, but it has no direction",
611         GST_OBJECT_NAME (pad), GST_ELEMENT_NAME (element));
612     GST_UNLOCK (pad);
613     GST_UNLOCK (element);
614     return FALSE;
615   }
616 }
617
618 /**
619  * gst_element_remove_pad:
620  * @element: a #GstElement to remove pad from.
621  * @pad: the #GstPad to remove from the element.
622  *
623  * Removes @pad from @element. @pad will be destroyed if it has not been
624  * referenced elsewhere.
625  *
626  * Returns: TRUE if the pad could be removed. Can return FALSE if the
627  * pad is not belonging to the provided element or when wrong parameters
628  * are passed to this function.
629  *
630  * MT safe.
631  */
632 gboolean
633 gst_element_remove_pad (GstElement * element, GstPad * pad)
634 {
635   GstPad *peer;
636
637   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
638   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
639
640   /* locking pad to look at the name and parent */
641   GST_LOCK (pad);
642   GST_CAT_INFO_OBJECT (GST_CAT_ELEMENT_PADS, element, "removing pad '%s'",
643       GST_STR_NULL (GST_PAD_NAME (pad)));
644
645   if (G_UNLIKELY (GST_PAD_PARENT (pad) != element))
646     goto not_our_pad;
647   GST_UNLOCK (pad);
648
649   /* unlink */
650   if ((peer = gst_pad_get_peer (pad))) {
651     /* window for MT unsafeness, someone else could unlink here
652      * and then we call unlink with wrong pads. The unlink
653      * function would catch this and safely return failed. */
654     if (GST_PAD_IS_SRC (pad))
655       gst_pad_unlink (pad, peer);
656     else
657       gst_pad_unlink (peer, pad);
658
659     gst_object_unref (peer);
660   }
661
662   GST_LOCK (element);
663   /* remove it from the list */
664   switch (gst_pad_get_direction (pad)) {
665     case GST_PAD_SRC:
666       element->srcpads = g_list_remove (element->srcpads, pad);
667       element->numsrcpads--;
668       break;
669     case GST_PAD_SINK:
670       element->sinkpads = g_list_remove (element->sinkpads, pad);
671       element->numsinkpads--;
672       break;
673     default:
674       g_critical ("Removing pad without direction???");
675       break;
676   }
677   element->pads = g_list_remove (element->pads, pad);
678   element->numpads--;
679   element->pads_cookie++;
680   GST_UNLOCK (element);
681
682   g_signal_emit (G_OBJECT (element), gst_element_signals[PAD_REMOVED], 0, pad);
683
684   gst_object_unparent (GST_OBJECT (pad));
685
686   return TRUE;
687
688 not_our_pad:
689   {
690     /* FIXME, locking order? */
691     GST_LOCK (element);
692     g_critical ("Padname %s:%s does not belong to element %s when removing",
693         GST_ELEMENT_NAME (GST_PAD_PARENT (pad)), GST_PAD_NAME (pad),
694         GST_ELEMENT_NAME (element));
695     GST_UNLOCK (element);
696     GST_UNLOCK (pad);
697     return FALSE;
698   }
699 }
700
701 /**
702  * gst_element_no_more_pads:
703  * @element: a #GstElement
704  *
705  * Use this function to signal that the element does not expect any more pads
706  * to show up in the current pipeline. This function should be called whenever
707  * pads have been added by the element itself. Elements with GST_PAD_SOMETIMES
708  * pad templates use this in combination with autopluggers to figure out that
709  * the element is done initializing its pads.
710  *
711  * MT safe.
712  */
713 void
714 gst_element_no_more_pads (GstElement * element)
715 {
716   g_return_if_fail (GST_IS_ELEMENT (element));
717
718   g_signal_emit (element, gst_element_signals[NO_MORE_PADS], 0);
719 }
720
721 static gint
722 pad_compare_name (GstPad * pad1, const gchar * name)
723 {
724   gint result;
725
726   GST_LOCK (pad1);
727   result = strcmp (GST_PAD_NAME (pad1), name);
728   GST_UNLOCK (pad1);
729
730   return result;
731 }
732
733 /**
734  * gst_element_get_static_pad:
735  * @element: a #GstElement to find a static pad of.
736  * @name: the name of the static #GstPad to retrieve.
737  *
738  * Retrieves a pad from @element by name. This version only retrieves
739  * already-existing (i.e. 'static') pads.
740  *
741  * Returns: the requested #GstPad if found, otherwise NULL. unref after
742  * usage.
743  *
744  * MT safe.
745  */
746 GstPad *
747 gst_element_get_static_pad (GstElement * element, const gchar * name)
748 {
749   GList *find;
750   GstPad *result = NULL;
751
752   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
753   g_return_val_if_fail (name != NULL, NULL);
754
755   GST_LOCK (element);
756   find =
757       g_list_find_custom (element->pads, name, (GCompareFunc) pad_compare_name);
758   if (find) {
759     result = GST_PAD_CAST (find->data);
760     gst_object_ref (result);
761   }
762
763   if (result == NULL) {
764     GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "no such pad '%s' in element \"%s\"",
765         name, GST_ELEMENT_NAME (element));
766   } else {
767     GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "found pad %s:%s",
768         GST_ELEMENT_NAME (element), name);
769   }
770   GST_UNLOCK (element);
771
772   return result;
773 }
774
775 static GstPad *
776 gst_element_request_pad (GstElement * element, GstPadTemplate * templ,
777     const gchar * name)
778 {
779   GstPad *newpad = NULL;
780   GstElementClass *oclass;
781
782   oclass = GST_ELEMENT_GET_CLASS (element);
783
784   if (oclass->request_new_pad)
785     newpad = (oclass->request_new_pad) (element, templ, name);
786
787   if (newpad)
788     gst_object_ref (newpad);
789
790   return newpad;
791 }
792
793 /**
794  * gst_element_get_request_pad:
795  * @element: a #GstElement to find a request pad of.
796  * @name: the name of the request #GstPad to retrieve.
797  *
798  * Retrieves a pad from the element by name. This version only retrieves
799  * request pads.
800  *
801  * Returns: requested #GstPad if found, otherwise NULL. Unref after usage.
802  */
803 GstPad *
804 gst_element_get_request_pad (GstElement * element, const gchar * name)
805 {
806   GstPadTemplate *templ = NULL;
807   GstPad *pad;
808   const gchar *req_name = NULL;
809   gboolean templ_found = FALSE;
810   GList *list;
811   gint n;
812   const gchar *data;
813   gchar *str, *endptr = NULL;
814   GstElementClass *class;
815
816   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
817   g_return_val_if_fail (name != NULL, NULL);
818
819   class = GST_ELEMENT_GET_CLASS (element);
820
821   if (strstr (name, "%")) {
822     templ = gst_element_class_get_pad_template (class, name);
823     req_name = NULL;
824     if (templ)
825       templ_found = TRUE;
826   } else {
827     list = gst_element_class_get_pad_template_list (class);
828     while (!templ_found && list) {
829       templ = (GstPadTemplate *) list->data;
830       if (templ->presence == GST_PAD_REQUEST) {
831         /* Because of sanity checks in gst_pad_template_new(), we know that %s
832            and %d, occurring at the end of the name_template, are the only
833            possibilities. */
834         GST_CAT_DEBUG (GST_CAT_PADS, "comparing %s to %s", name,
835             templ->name_template);
836         if ((str = strchr (templ->name_template, '%'))
837             && strncmp (templ->name_template, name,
838                 str - templ->name_template) == 0
839             && strlen (name) > str - templ->name_template) {
840           data = name + (str - templ->name_template);
841           if (*(str + 1) == 'd') {
842             /* it's an int */
843             n = (gint) strtol (data, &endptr, 10);
844             if (endptr && *endptr == '\0') {
845               templ_found = TRUE;
846               req_name = name;
847               break;
848             }
849           } else {
850             /* it's a string */
851             templ_found = TRUE;
852             req_name = name;
853             break;
854           }
855         }
856       }
857       list = list->next;
858     }
859   }
860
861   if (!templ_found)
862     return NULL;
863
864   pad = gst_element_request_pad (element, templ, req_name);
865
866   return pad;
867 }
868
869 /**
870  * gst_element_get_pad:
871  * @element: a #GstElement.
872  * @name: the name of the pad to retrieve.
873  *
874  * Retrieves a pad from @element by name. Tries gst_element_get_static_pad()
875  * first, then gst_element_get_request_pad().
876  *
877  * Returns: the #GstPad if found, otherwise %NULL. Unref after usage.
878  */
879 GstPad *
880 gst_element_get_pad (GstElement * element, const gchar * name)
881 {
882   GstPad *pad;
883
884   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
885   g_return_val_if_fail (name != NULL, NULL);
886
887   pad = gst_element_get_static_pad (element, name);
888   if (!pad)
889     pad = gst_element_get_request_pad (element, name);
890
891   return pad;
892 }
893
894 GstIteratorItem
895 iterate_pad (GstIterator * it, GstPad * pad)
896 {
897   gst_object_ref (pad);
898   return GST_ITERATOR_ITEM_PASS;
899 }
900
901 /**
902  * gst_element_iterate_pads:
903  * @element: a #GstElement to iterate pads of.
904  *
905  * Retrieves an iterattor of @element's pads. 
906  *
907  * Returns: the #GstIterator of #GstPad. Unref each pad after use.
908  *
909  * MT safe.
910  */
911 GstIterator *
912 gst_element_iterate_pads (GstElement * element)
913 {
914   GstIterator *result;
915
916   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
917
918   GST_LOCK (element);
919   gst_object_ref (element);
920   result = gst_iterator_new_list (GST_GET_LOCK (element),
921       &element->pads_cookie,
922       &element->pads,
923       element,
924       (GstIteratorItemFunction) iterate_pad,
925       (GstIteratorDisposeFunction) gst_object_unref);
926   GST_UNLOCK (element);
927
928   return result;
929 }
930
931 static gint
932 direction_filter (gconstpointer pad, gconstpointer direction)
933 {
934   if (GST_PAD_DIRECTION (pad) == GPOINTER_TO_INT (direction)) {
935     /* pass the ref through */
936     return 0;
937   } else {
938     /* unref */
939     /* FIXME: this is very stupid */
940     gst_object_unref (GST_OBJECT_CAST (pad));
941     return 1;
942   }
943 }
944
945 /**
946  * gst_element_iterate_src_pads:
947  * @element: a #GstElement.
948  *
949  * Retrieves an iterator of @element's source pads. 
950  *
951  * Returns: the #GstIterator of #GstPad. Unref each pad after use.
952  *
953  * MT safe.
954  */
955 GstIterator *
956 gst_element_iterate_src_pads (GstElement * element)
957 {
958   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
959
960   return gst_iterator_filter (gst_element_iterate_pads (element),
961       direction_filter, GINT_TO_POINTER (GST_PAD_SRC));
962 }
963
964 /**
965  * gst_element_iterate_sink_pads:
966  * @element: a #GstElement.
967  *
968  * Retrieves an iterator of @element's sink pads. 
969  *
970  * Returns: the #GstIterator of #GstPad. Unref each pad after use.
971  *
972  * MT safe.
973  */
974 GstIterator *
975 gst_element_iterate_sink_pads (GstElement * element)
976 {
977   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
978
979   return gst_iterator_filter (gst_element_iterate_pads (element),
980       direction_filter, GINT_TO_POINTER (GST_PAD_SINK));
981 }
982
983 /**
984  * gst_element_class_add_pad_template:
985  * @klass: the #GstElementClass to add the pad template to.
986  * @templ: a #GstPadTemplate to add to the element class.
987  *
988  * Adds a padtemplate to an element class. This is mainly used in the _base_init
989  * functions of classes.
990  */
991 void
992 gst_element_class_add_pad_template (GstElementClass * klass,
993     GstPadTemplate * templ)
994 {
995   g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
996   g_return_if_fail (GST_IS_PAD_TEMPLATE (templ));
997
998   /* avoid registering pad templates with the same name */
999   g_return_if_fail (gst_element_class_get_pad_template (klass,
1000           templ->name_template) == NULL);
1001
1002   klass->padtemplates = g_list_append (klass->padtemplates,
1003       gst_object_ref (templ));
1004   klass->numpadtemplates++;
1005 }
1006
1007 /**
1008  * gst_element_class_set_details:
1009  * @klass: class to set details for
1010  * @details: details to set
1011  *
1012  * Sets the detailed information for a #GstElementClass.
1013  * <note>This function is for use in _base_init functions only.</note>
1014  */
1015 void
1016 gst_element_class_set_details (GstElementClass * klass,
1017     const GstElementDetails * details)
1018 {
1019   g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
1020   g_return_if_fail (GST_IS_ELEMENT_DETAILS (details));
1021
1022   __gst_element_details_copy (&klass->details, details);
1023 }
1024
1025 /**
1026  * gst_element_class_get_pad_template_list:
1027  * @element_class: a #GstElementClass to get pad templates of.
1028  *
1029  * Retrieves a list of the pad templates associated with @element_class. The
1030  * list must not be modified by the calling code.
1031  * <note>If you use this function in the #GInstanceInitFunc of an object class
1032  * that has subclasses, make sure to pass the g_class parameter of the
1033  * #GInstanceInitFunc here.</note>
1034  *
1035  * Returns: the #GList of padtemplates.
1036  */
1037 GList *
1038 gst_element_class_get_pad_template_list (GstElementClass * element_class)
1039 {
1040   g_return_val_if_fail (GST_IS_ELEMENT_CLASS (element_class), NULL);
1041
1042   return element_class->padtemplates;
1043 }
1044
1045 /**
1046  * gst_element_class_get_pad_template:
1047  * @element_class: a #GstElementClass to get the pad template of.
1048  * @name: the name of the #GstPadTemplate to get.
1049  *
1050  * Retrieves a padtemplate from @element_class with the given name.
1051  * <note>If you use this function in the #GInstanceInitFunc of an object class
1052  * that has subclasses, make sure to pass the g_class parameter of the
1053  * #GInstanceInitFunc here.</note>
1054  *
1055  * Returns: the #GstPadTemplate with the given name, or NULL if none was found.
1056  * No unreferencing is necessary.
1057  */
1058 GstPadTemplate *
1059 gst_element_class_get_pad_template (GstElementClass * element_class,
1060     const gchar * name)
1061 {
1062   GList *padlist;
1063
1064   g_return_val_if_fail (GST_IS_ELEMENT_CLASS (element_class), NULL);
1065   g_return_val_if_fail (name != NULL, NULL);
1066
1067   padlist = gst_element_class_get_pad_template_list (element_class);
1068
1069   while (padlist) {
1070     GstPadTemplate *padtempl = (GstPadTemplate *) padlist->data;
1071
1072     if (strcmp (padtempl->name_template, name) == 0)
1073       return padtempl;
1074
1075     padlist = g_list_next (padlist);
1076   }
1077
1078   return NULL;
1079 }
1080
1081 static GstPad *
1082 gst_element_get_random_pad (GstElement * element, GstPadDirection dir)
1083 {
1084   GstPad *result = NULL;
1085   GList *pads;
1086
1087   GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "getting a random pad");
1088
1089   switch (dir) {
1090     case GST_PAD_SRC:
1091       GST_LOCK (element);
1092       pads = element->srcpads;
1093       break;
1094     case GST_PAD_SINK:
1095       GST_LOCK (element);
1096       pads = element->sinkpads;
1097       break;
1098     default:
1099       goto wrong_direction;
1100   }
1101   for (; pads; pads = g_list_next (pads)) {
1102     GstPad *pad = GST_PAD (pads->data);
1103
1104     GST_LOCK (pad);
1105     GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "checking pad %s:%s",
1106         GST_DEBUG_PAD_NAME (pad));
1107
1108     if (GST_PAD_IS_LINKED (pad)) {
1109       GST_UNLOCK (pad);
1110       result = pad;
1111       break;
1112     } else {
1113       GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s is not linked",
1114           GST_DEBUG_PAD_NAME (pad));
1115     }
1116     GST_UNLOCK (pad);
1117   }
1118   if (result)
1119     gst_object_ref (result);
1120
1121   GST_UNLOCK (element);
1122
1123   return result;
1124
1125   /* ERROR handling */
1126 wrong_direction:
1127   {
1128     g_warning ("unknown pad direction %d", dir);
1129     return NULL;
1130   }
1131 }
1132
1133 /**
1134  * gst_element_send_event:
1135  * @element: a #GstElement to send the event to.
1136  * @event: the #GstEvent to send to the element.
1137  *
1138  * Sends an event to an element. If the element doesn't
1139  * implement an event handler, the event will be forwarded
1140  * to a random sink pad. This function takes owership of the
1141  * provided event so you should _ref it if you want to reuse
1142  * the event after this call.
1143  *
1144  * Returns: TRUE if the event was handled.
1145  *
1146  * MT safe.
1147  */
1148 gboolean
1149 gst_element_send_event (GstElement * element, GstEvent * event)
1150 {
1151   GstElementClass *oclass;
1152   gboolean result = FALSE;
1153
1154   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1155   g_return_val_if_fail (event != NULL, FALSE);
1156
1157   oclass = GST_ELEMENT_GET_CLASS (element);
1158
1159   if (oclass->send_event) {
1160     result = oclass->send_event (element, event);
1161   } else {
1162     GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SINK);
1163
1164     if (pad) {
1165       GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
1166           "pushing event to random pad %s:%s", GST_DEBUG_PAD_NAME (pad));
1167
1168       result = gst_pad_push_event (pad, event);
1169       gst_object_unref (pad);
1170     } else {
1171       GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "can't send event on element %s",
1172           GST_ELEMENT_NAME (element));
1173     }
1174   }
1175   return result;
1176 }
1177
1178 /**
1179  * gst_element_seek:
1180  * @element: a #GstElement to send the event to.
1181  * @rate: The new playback rate
1182  * @format: The format of the seek values
1183  * @flags: The optional seek flags.
1184  * @cur_type: The type and flags for the new current position
1185  * @cur: The value of the new current position
1186  * @stop_type: The type and flags for the new stop position
1187  * @stop: The value of the new stop position
1188  *
1189  * Sends a seek event to an element.
1190  *
1191  * Returns: %TRUE if the event was handled.
1192  *
1193  * MT safe.
1194  */
1195 gboolean
1196 gst_element_seek (GstElement * element, gdouble rate, GstFormat format,
1197     GstSeekFlags flags, GstSeekType cur_type, gint64 cur,
1198     GstSeekType stop_type, gint64 stop)
1199 {
1200   GstEvent *event;
1201   gboolean result;
1202
1203   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1204
1205   event =
1206       gst_event_new_seek (rate, format, flags, cur_type, cur, stop_type, stop);
1207   result = gst_element_send_event (element, event);
1208
1209   return result;
1210 }
1211
1212 /**
1213  * gst_element_get_query_types:
1214  * @element: a #GstElement to query
1215  *
1216  * Get an array of query types from the element.
1217  * If the element doesn't implement a query types function,
1218  * the query will be forwarded to a random sink pad.
1219  *
1220  * Returns: An array of #GstQueryType elements that should not
1221  * be freed or modified.
1222  *
1223  * MT safe.
1224  */
1225 const GstQueryType *
1226 gst_element_get_query_types (GstElement * element)
1227 {
1228   GstElementClass *oclass;
1229   const GstQueryType *result = NULL;
1230
1231   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1232
1233   oclass = GST_ELEMENT_GET_CLASS (element);
1234
1235   if (oclass->get_query_types) {
1236     result = oclass->get_query_types (element);
1237   } else {
1238     GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SINK);
1239
1240     if (pad) {
1241       GstPad *peer = gst_pad_get_peer (pad);
1242
1243       if (peer) {
1244         result = gst_pad_get_query_types (peer);
1245
1246         gst_object_unref (peer);
1247       }
1248       gst_object_unref (pad);
1249     }
1250   }
1251   return result;
1252 }
1253
1254 /**
1255  * gst_element_query:
1256  * @element: a #GstElement to perform the query on.
1257  * @query: the #GstQuery.
1258  *
1259  * Performs a query on the given element. If the format is set
1260  * to GST_FORMAT_DEFAULT and this function returns TRUE, the
1261  * format pointer will hold the default format.
1262  * For element that don't implement a query handler, this function
1263  * forwards the query to a random usable sinkpad of this element.
1264  *
1265  * Returns: TRUE if the query could be performed.
1266  *
1267  * MT safe.
1268  */
1269 gboolean
1270 gst_element_query (GstElement * element, GstQuery * query)
1271 {
1272   GstElementClass *oclass;
1273   gboolean result = FALSE;
1274
1275   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1276   g_return_val_if_fail (query != NULL, FALSE);
1277
1278   oclass = GST_ELEMENT_GET_CLASS (element);
1279
1280   if (oclass->query) {
1281     result = oclass->query (element, query);
1282   } else {
1283     GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SRC);
1284
1285     if (pad) {
1286       result = gst_pad_query (pad, query);
1287
1288       gst_object_unref (pad);
1289     } else {
1290       pad = gst_element_get_random_pad (element, GST_PAD_SINK);
1291       if (pad) {
1292         GstPad *peer = gst_pad_get_peer (pad);
1293
1294         if (peer) {
1295           result = gst_pad_query (peer, query);
1296
1297           gst_object_unref (peer);
1298         }
1299         gst_object_unref (pad);
1300       }
1301     }
1302   }
1303   return result;
1304 }
1305
1306 /**
1307  * gst_element_post_message:
1308  * @element: a #GstElement posting the message
1309  * @message: a #GstMessage to post
1310  *
1311  * Post a message on the element's #GstBus.
1312  *
1313  * Returns: TRUE if the message was successfully posted.
1314  *
1315  * MT safe.
1316  */
1317 gboolean
1318 gst_element_post_message (GstElement * element, GstMessage * message)
1319 {
1320   GstBus *bus;
1321   gboolean result = FALSE;
1322
1323   GST_DEBUG ("posting message %p ...", message);
1324
1325   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1326   g_return_val_if_fail (message != NULL, FALSE);
1327
1328   GST_LOCK (element);
1329   bus = element->bus;
1330
1331   if (G_UNLIKELY (bus == NULL)) {
1332     GST_DEBUG ("... but I won't because I have no bus");
1333     GST_UNLOCK (element);
1334     gst_message_unref (message);
1335     return FALSE;
1336   }
1337   gst_object_ref (bus);
1338   GST_DEBUG ("... on bus %" GST_PTR_FORMAT, bus);
1339   GST_UNLOCK (element);
1340
1341   result = gst_bus_post (bus, message);
1342   gst_object_unref (bus);
1343
1344   return result;
1345 }
1346
1347 /**
1348  * _gst_element_error_printf:
1349  * @format: the printf-like format to use, or NULL
1350  *
1351  * This function is only used internally by the #gst_element_error macro.
1352  *
1353  * Returns: a newly allocated string, or NULL if the format was NULL or ""
1354  *
1355  * MT safe.
1356  */
1357 gchar *
1358 _gst_element_error_printf (const gchar * format, ...)
1359 {
1360   va_list args;
1361   gchar *buffer;
1362
1363   if (format == NULL)
1364     return NULL;
1365   if (format[0] == 0)
1366     return NULL;
1367
1368   va_start (args, format);
1369   buffer = g_strdup_vprintf (format, args);
1370   va_end (args);
1371   return buffer;
1372 }
1373
1374 /**
1375  * gst_element_message_full:
1376  * @element:  a #GstElement to send message from
1377  * @type:     the #GstMessageType
1378  * @domain:   the GStreamer GError domain this message belongs to
1379  * @code:     the GError code belonging to the domain
1380  * @text:     an allocated text string to be used as a replacement for the
1381  *            default message connected to code, or NULL
1382  * @debug:    an allocated debug message to be used as a replacement for the
1383  *            default debugging information, or NULL
1384  * @file:     the source code file where the error was generated
1385  * @function: the source code function where the error was generated
1386  * @line:     the source code line where the error was generated
1387  *
1388  * Post an error or warning message on the bus from inside an element.
1389  *
1390  * MT safe.
1391  */
1392 void gst_element_message_full
1393     (GstElement * element, GstMessageType type,
1394     GQuark domain, gint code, gchar * text,
1395     gchar * debug, const gchar * file, const gchar * function, gint line)
1396 {
1397   GError *gerror = NULL;
1398   gchar *name;
1399   gchar *sent_text;
1400   gchar *sent_debug;
1401   GstMessage *message = NULL;
1402
1403   /* checks */
1404   GST_DEBUG ("start");
1405   g_return_if_fail (GST_IS_ELEMENT (element));
1406   g_return_if_fail ((type == GST_MESSAGE_ERROR) ||
1407       (type == GST_MESSAGE_WARNING));
1408
1409   /* check if we send the given text or the default error text */
1410   if ((text == NULL) || (text[0] == 0)) {
1411     /* text could have come from g_strdup_printf (""); */
1412     g_free (text);
1413     sent_text = gst_error_get_message (domain, code);
1414   } else
1415     sent_text = text;
1416
1417   /* construct a sent_debug with extra information from source */
1418   if ((debug == NULL) || (debug[0] == 0)) {
1419     /* debug could have come from g_strdup_printf (""); */
1420     sent_debug = NULL;
1421   } else {
1422     name = gst_object_get_path_string (GST_OBJECT (element));
1423     sent_debug = g_strdup_printf ("%s(%d): %s: %s:\n%s",
1424         file, line, function, name, debug ? debug : "");
1425     g_free (name);
1426   }
1427   g_free (debug);
1428
1429   /* create gerror and post message */
1430   GST_CAT_INFO_OBJECT (GST_CAT_ERROR_SYSTEM, element, "posting message: %s",
1431       sent_text);
1432   gerror = g_error_new_literal (domain, code, sent_text);
1433
1434   if (type == GST_MESSAGE_ERROR) {
1435     message = gst_message_new_error (GST_OBJECT (element), gerror, sent_debug);
1436   } else if (type == GST_MESSAGE_WARNING) {
1437     message = gst_message_new_warning (GST_OBJECT (element), gerror,
1438         sent_debug);
1439   } else {
1440     g_assert_not_reached ();
1441   }
1442   gst_element_post_message (element, message);
1443
1444   GST_CAT_INFO_OBJECT (GST_CAT_ERROR_SYSTEM, element, "posted message: %s",
1445       sent_text);
1446
1447   /* cleanup */
1448   g_error_free (gerror);
1449   g_free (sent_debug);
1450   g_free (sent_text);
1451 }
1452
1453 /**
1454  * gst_element_is_locked_state:
1455  * @element: a #GstElement.
1456  *
1457  * Checks if the state of an element is locked.
1458  * If the state of an element is locked, state changes of the parent don't
1459  * affect the element.
1460  * This way you can leave currently unused elements inside bins. Just lock their
1461  * state before changing the state from #GST_STATE_NULL.
1462  *
1463  * Returns: TRUE, if the element's state is locked.
1464  *
1465  * MT safe.
1466  */
1467 gboolean
1468 gst_element_is_locked_state (GstElement * element)
1469 {
1470   gboolean result = FALSE;
1471
1472   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1473
1474   GST_LOCK (element);
1475   result = GST_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
1476   GST_UNLOCK (element);
1477
1478   return result;
1479 }
1480
1481 /**
1482  * gst_element_set_locked_state:
1483  * @element: a #GstElement
1484  * @locked_state: TRUE to lock the element's state
1485  *
1486  * Locks the state of an element, so state changes of the parent don't affect
1487  * this element anymore.
1488  *
1489  * Returns: TRUE if the state was changed, FALSE if bad params were given or
1490  * the element was already in the correct state.
1491  *
1492  * MT safe.
1493  */
1494 gboolean
1495 gst_element_set_locked_state (GstElement * element, gboolean locked_state)
1496 {
1497   gboolean old;
1498
1499   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1500
1501   GST_LOCK (element);
1502   old = GST_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
1503
1504   if (G_UNLIKELY (old == locked_state))
1505     goto was_ok;
1506
1507   if (locked_state) {
1508     GST_CAT_DEBUG (GST_CAT_STATES, "locking state of element %s",
1509         GST_ELEMENT_NAME (element));
1510     GST_FLAG_SET (element, GST_ELEMENT_LOCKED_STATE);
1511   } else {
1512     GST_CAT_DEBUG (GST_CAT_STATES, "unlocking state of element %s",
1513         GST_ELEMENT_NAME (element));
1514     GST_FLAG_UNSET (element, GST_ELEMENT_LOCKED_STATE);
1515   }
1516   GST_UNLOCK (element);
1517
1518   return TRUE;
1519
1520 was_ok:
1521   GST_UNLOCK (element);
1522
1523   return FALSE;
1524 }
1525
1526 /**
1527  * gst_element_sync_state_with_parent:
1528  * @element: a #GstElement.
1529  *
1530  * Tries to change the state of the element to the same as its parent.
1531  * If this function returns FALSE, the state of element is undefined.
1532  *
1533  * Returns: TRUE, if the element's state could be synced to the parent's state.
1534  */
1535 gboolean
1536 gst_element_sync_state_with_parent (GstElement * element)
1537 {
1538   GstElement *parent;
1539
1540   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1541   parent = GST_ELEMENT (GST_ELEMENT_PARENT (element));
1542   g_return_val_if_fail (GST_IS_BIN (parent), FALSE);
1543
1544   GST_CAT_DEBUG (GST_CAT_STATES, "syncing state of element %s (%s) to %s (%s)",
1545       GST_ELEMENT_NAME (element),
1546       gst_element_state_get_name (GST_STATE (element)),
1547       GST_ELEMENT_NAME (parent),
1548       gst_element_state_get_name (GST_STATE (parent)));
1549
1550   if (gst_element_set_state (element,
1551           GST_STATE (parent)) == GST_STATE_CHANGE_FAILURE) {
1552     return FALSE;
1553   }
1554   return TRUE;
1555 }
1556
1557 /* MT safe */
1558 static GstStateChangeReturn
1559 gst_element_get_state_func (GstElement * element,
1560     GstState * state, GstState * pending, GTimeVal * timeout)
1561 {
1562   GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
1563   GstState old_pending;
1564
1565   GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "getting state");
1566
1567   GST_STATE_LOCK (element);
1568   /* we got an error, report immediatly */
1569   if (GST_STATE_NO_PREROLL (element)) {
1570     ret = GST_STATE_CHANGE_NO_PREROLL;
1571     goto done;
1572   }
1573
1574   /* we got an error, report immediatly */
1575   if (GST_STATE_ERROR (element)) {
1576     ret = GST_STATE_CHANGE_FAILURE;
1577     goto done;
1578   }
1579
1580   old_pending = GST_STATE_PENDING (element);
1581   if (old_pending != GST_STATE_VOID_PENDING) {
1582     GTimeVal *timeval, abstimeout;
1583
1584     GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "wait for pending");
1585     if (timeout) {
1586       /* make timeout absolute */
1587       g_get_current_time (&abstimeout);
1588       g_time_val_add (&abstimeout,
1589           timeout->tv_sec * G_USEC_PER_SEC + timeout->tv_usec);
1590       timeval = &abstimeout;
1591     } else {
1592       timeval = NULL;
1593     }
1594     /* we have a pending state change, wait for it to complete */
1595     if (!GST_STATE_TIMED_WAIT (element, timeval)) {
1596       GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "timeout");
1597       /* timeout triggered */
1598       ret = GST_STATE_CHANGE_ASYNC;
1599     } else {
1600       /* could be success or failure */
1601       if (old_pending == GST_STATE (element)) {
1602         GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "got success");
1603         ret = GST_STATE_CHANGE_SUCCESS;
1604       } else {
1605         GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "got failure");
1606         ret = GST_STATE_CHANGE_FAILURE;
1607       }
1608     }
1609   }
1610   /* if nothing is pending anymore we can return SUCCESS */
1611   if (GST_STATE_PENDING (element) == GST_STATE_VOID_PENDING) {
1612     GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "nothing pending");
1613     ret = GST_STATE_CHANGE_SUCCESS;
1614   }
1615
1616 done:
1617   if (state)
1618     *state = GST_STATE (element);
1619   if (pending)
1620     *pending = GST_STATE_PENDING (element);
1621
1622   GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1623       "state current: %s, pending: %s, error: %d, no_preroll: %d, result: %d",
1624       gst_element_state_get_name (GST_STATE (element)),
1625       gst_element_state_get_name (GST_STATE_PENDING (element)),
1626       GST_STATE_ERROR (element), GST_STATE_NO_PREROLL (element), ret);
1627
1628   GST_STATE_UNLOCK (element);
1629
1630   return ret;
1631 }
1632
1633 /**
1634  * gst_element_get_state:
1635  * @element: a #GstElement to get the state of.
1636  * @state: a pointer to #GstState to hold the state. Can be NULL.
1637  * @pending: a pointer to #GstState to hold the pending state.
1638  *           Can be NULL.
1639  * @timeout: a #GTimeVal to specify the timeout for an async
1640  *           state change or NULL for infinite timeout.
1641  *
1642  * Gets the state of the element. 
1643  *
1644  * For elements that performed an ASYNC state change, as reported by 
1645  * #gst_element_set_state(), this function will block up to the 
1646  * specified timeout value for the state change to complete. 
1647  * If the element completes the state change or goes into
1648  * an error, this function returns immediatly with a return value of
1649  * GST_STATE_CHANGE_SUCCESS or GST_STATE_CHANGE_FAILURE respectively. 
1650  *
1651  * Returns: GST_STATE_CHANGE_SUCCESS if the element has no more pending state and
1652  *          the last state change succeeded, GST_STATE_CHANGE_ASYNC
1653  *          if the element is still performing a state change or 
1654  *          GST_STATE_CHANGE_FAILURE if the last state change failed.
1655  *
1656  * MT safe.
1657  */
1658 GstStateChangeReturn
1659 gst_element_get_state (GstElement * element,
1660     GstState * state, GstState * pending, GTimeVal * timeout)
1661 {
1662   GstElementClass *oclass;
1663   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
1664
1665   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_CHANGE_FAILURE);
1666
1667   oclass = GST_ELEMENT_GET_CLASS (element);
1668
1669   if (oclass->get_state)
1670     result = (oclass->get_state) (element, state, pending, timeout);
1671
1672   return result;
1673 }
1674
1675 /**
1676  * gst_element_abort_state:
1677  * @element: a #GstElement to abort the state of.
1678  *
1679  * Abort the state change of the element. This function is used
1680  * by elements that do asynchronous state changes and find out 
1681  * something is wrong.
1682  *
1683  * This function should be called with the STATE_LOCK held.
1684  *
1685  * MT safe.
1686  */
1687 void
1688 gst_element_abort_state (GstElement * element)
1689 {
1690   GstState pending;
1691
1692   g_return_if_fail (GST_IS_ELEMENT (element));
1693
1694   pending = GST_STATE_PENDING (element);
1695
1696   if (pending != GST_STATE_VOID_PENDING && !GST_STATE_ERROR (element)) {
1697 #ifndef GST_DISABLE_GST_DEBUG
1698     GstState old_state = GST_STATE (element);
1699 #endif
1700
1701     GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1702         "aborting state from %s to %s", gst_element_state_get_name (old_state),
1703         gst_element_state_get_name (pending));
1704
1705     /* flag error */
1706     GST_STATE_ERROR (element) = TRUE;
1707
1708     GST_STATE_BROADCAST (element);
1709   }
1710 }
1711
1712 /**
1713  * gst_element_commit_state:
1714  * @element: a #GstElement to commit the state of.
1715  *
1716  * Commit the state change of the element. This function is used
1717  * by elements that do asynchronous state changes.
1718  *
1719  * This function can only be called with the STATE_LOCK held.
1720  *
1721  * MT safe.
1722  */
1723 void
1724 gst_element_commit_state (GstElement * element)
1725 {
1726   GstState pending;
1727   GstMessage *message;
1728
1729   g_return_if_fail (GST_IS_ELEMENT (element));
1730
1731   pending = GST_STATE_PENDING (element);
1732
1733   if (pending != GST_STATE_VOID_PENDING) {
1734     GstState old_state = GST_STATE (element);
1735
1736     GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1737         "committing state from %s to %s",
1738         gst_element_state_get_name (old_state),
1739         gst_element_state_get_name (pending));
1740
1741     GST_STATE (element) = pending;
1742     GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING;
1743     GST_STATE_ERROR (element) = FALSE;
1744
1745     g_signal_emit (G_OBJECT (element), gst_element_signals[STATE_CHANGE],
1746         0, old_state, pending);
1747     message = gst_message_new_state_changed (GST_OBJECT (element),
1748         old_state, pending);
1749     gst_element_post_message (element, message);
1750     GST_STATE_BROADCAST (element);
1751   }
1752 }
1753
1754 /**
1755  * gst_element_lost_state:
1756  * @element: a #GstElement the state is lost of
1757  *
1758  * Brings the element to the lost state. The current state of the
1759  * element is copied to the pending state so that any call to
1760  * #gst_element_get_state() will return ASYNC.
1761  * This is mostly used for elements that lost their preroll buffer
1762  * in the PAUSED state after a flush, they become PAUSED again
1763  * if a new preroll buffer is queued.
1764  * This function can only be called when the element is currently
1765  * not in error or an async state change.
1766  *
1767  * This function can only be called with the STATE_LOCK held.
1768  *
1769  * MT safe.
1770  */
1771 void
1772 gst_element_lost_state (GstElement * element)
1773 {
1774   g_return_if_fail (GST_IS_ELEMENT (element));
1775
1776   if (GST_STATE_PENDING (element) == GST_STATE_VOID_PENDING &&
1777       !GST_STATE_ERROR (element)) {
1778     GstState current_state = GST_STATE (element);
1779
1780     GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1781         "lost state of %s", gst_element_state_get_name (current_state));
1782
1783     GST_STATE_PENDING (element) = current_state;
1784     GST_STATE_ERROR (element) = FALSE;
1785   }
1786 }
1787
1788 /**
1789  * gst_element_set_state:
1790  * @element: a #GstElement to change state of.
1791  * @state: the element's new #GstState.
1792  *
1793  * Sets the state of the element. This function will try to set the
1794  * requested state by going through all the intermediary states and calling
1795  * the class's state change function for each.
1796  *
1797  * Returns: Result of the state change using #GstStateChangeReturn.
1798  *
1799  * MT safe.
1800  */
1801 GstStateChangeReturn
1802 gst_element_set_state (GstElement * element, GstState state)
1803 {
1804   GstElementClass *oclass;
1805   GstState current;
1806   GstStateChangeReturn return_val = GST_STATE_CHANGE_SUCCESS;
1807   GstStateChangeReturn ret;
1808   GstState pending;
1809   GTimeVal tv;
1810
1811   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_CHANGE_FAILURE);
1812
1813   GST_DEBUG_OBJECT (element, "set_state to %s",
1814       gst_element_state_get_name (state));
1815   /* get current element state,  need to call the method so that
1816    * we call the virtual method and subclasses can implement their
1817    * own algorithms */
1818   GST_TIME_TO_TIMEVAL (0, tv);
1819   ret = gst_element_get_state (element, &current, &pending, &tv);
1820
1821   /* get the element state lock */
1822   GST_STATE_LOCK (element);
1823   /* this is the state we should go to */
1824   GST_STATE_FINAL (element) = state;
1825   if (ret == GST_STATE_CHANGE_ASYNC) {
1826     /* force next state keeping ASYNC, this is atomic as we hold
1827      * the STATE_LOCK */
1828     gst_element_commit_state (element);
1829     gst_element_lost_state (element);
1830   }
1831
1832   /* start with the current state */
1833   current = GST_STATE (element);
1834
1835   GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "setting state from %s to %s",
1836       gst_element_state_get_name (current), gst_element_state_get_name (state));
1837
1838   oclass = GST_ELEMENT_GET_CLASS (element);
1839
1840   /* We always perform at least one state change, even if the 
1841    * current state is equal to the required state. This is needed
1842    * for bins that sync their children. */
1843   do {
1844     GstState pending;
1845
1846     /* calculate the pending state */
1847     if (current < state)
1848       pending = current + 1;
1849     else if (current > state)
1850       pending = current - 1;
1851     else
1852       pending = current;
1853
1854     /* set the pending state variable */
1855     GST_STATE_PENDING (element) = pending;
1856
1857     GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1858         "%s: setting state from %s to %s",
1859         (pending != state ? "intermediate" : "final"),
1860         gst_element_state_get_name (current),
1861         gst_element_state_get_name (pending));
1862
1863     /* call the state change function so it can set the state */
1864     if (oclass->change_state)
1865       return_val = (oclass->change_state) (element, GST_STATE_CHANGE (element));
1866     else
1867       return_val = GST_STATE_CHANGE_FAILURE;
1868
1869     /* clear the error and preroll flag, we need to do that after
1870      * calling the virtual change_state function so that it can use the
1871      * old previous value. */
1872     GST_STATE_ERROR (element) = FALSE;
1873     GST_STATE_NO_PREROLL (element) = FALSE;
1874
1875     switch (return_val) {
1876       case GST_STATE_CHANGE_FAILURE:
1877         GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1878             "have failed change_state return");
1879         /* state change failure exits the loop */
1880         gst_element_abort_state (element);
1881         goto exit;
1882       case GST_STATE_CHANGE_ASYNC:
1883         GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1884             "element will change state async");
1885         /* an async state change exits the loop, we can only
1886          * go to the next state change when this one completes. */
1887         goto exit;
1888       case GST_STATE_CHANGE_SUCCESS:
1889         GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1890             "element changed state successfully");
1891         /* we can commit the state now and proceed to the next state */
1892         gst_element_commit_state (element);
1893         GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "committed state");
1894         break;
1895       case GST_STATE_CHANGE_NO_PREROLL:
1896         GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1897             "element changed state successfully and can't preroll");
1898         /* we can commit the state now and proceed to the next state */
1899         gst_element_commit_state (element);
1900         GST_STATE_NO_PREROLL (element) = TRUE;
1901         GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "committed state");
1902         break;
1903       default:
1904         goto invalid_return;
1905     }
1906     /* get the current state of the element and see if we need to do more
1907      * state changes */
1908     current = GST_STATE (element);
1909   }
1910   while (current != state);
1911
1912 exit:
1913   GST_STATE_FINAL (element) = GST_STATE_VOID_PENDING;
1914   GST_STATE_UNLOCK (element);
1915
1916   GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "exit state change");
1917
1918   return return_val;
1919
1920   /* ERROR */
1921 invalid_return:
1922   {
1923     GST_STATE_FINAL (element) = GST_STATE_VOID_PENDING;
1924     GST_STATE_UNLOCK (element);
1925     /* somebody added a GST_STATE_ and forgot to do stuff here ! */
1926     g_critical ("unknown return value %d from a state change function",
1927         return_val);
1928     return GST_STATE_CHANGE_FAILURE;
1929   }
1930 }
1931
1932 /* gst_iterator_fold functions for pads_activate */
1933
1934 static gboolean
1935 activate_pads (GstPad * pad, GValue * ret, gboolean * active)
1936 {
1937   if (!gst_pad_set_active (pad, *active))
1938     g_value_set_boolean (ret, FALSE);
1939   else if (!*active)
1940     gst_pad_set_caps (pad, NULL);
1941
1942   gst_object_unref (pad);
1943   return TRUE;
1944 }
1945
1946 /* returns false on error or early cutout of the fold, true otherwise */
1947 static gboolean
1948 iterator_fold_with_resync (GstIterator * iter, GstIteratorFoldFunction func,
1949     GValue * ret, gpointer user_data)
1950 {
1951   GstIteratorResult ires;
1952   gboolean res = TRUE;
1953
1954   while (1) {
1955     ires = gst_iterator_fold (iter, func, ret, user_data);
1956
1957     switch (ires) {
1958       case GST_ITERATOR_RESYNC:
1959         gst_iterator_resync (iter);
1960         break;
1961       case GST_ITERATOR_DONE:
1962         res = TRUE;
1963         goto done;
1964       default:
1965         res = FALSE;
1966         goto done;
1967     }
1968   }
1969
1970 done:
1971   return res;
1972 }
1973
1974 /* is called with STATE_LOCK
1975  */
1976 static gboolean
1977 gst_element_pads_activate (GstElement * element, gboolean active)
1978 {
1979   GValue ret = { 0, };
1980   GstIterator *iter;
1981   gboolean fold_ok;
1982
1983   /* no need to unset this later, it's just a boolean */
1984   g_value_init (&ret, G_TYPE_BOOLEAN);
1985   g_value_set_boolean (&ret, TRUE);
1986
1987   iter = gst_element_iterate_src_pads (element);
1988   fold_ok = iterator_fold_with_resync
1989       (iter, (GstIteratorFoldFunction) activate_pads, &ret, &active);
1990   gst_iterator_free (iter);
1991   if (!fold_ok || !g_value_get_boolean (&ret))
1992     return FALSE;
1993
1994   iter = gst_element_iterate_sink_pads (element);
1995   fold_ok = iterator_fold_with_resync
1996       (iter, (GstIteratorFoldFunction) activate_pads, &ret, &active);
1997   gst_iterator_free (iter);
1998   if (!fold_ok || !g_value_get_boolean (&ret))
1999     return FALSE;
2000
2001   return TRUE;
2002 }
2003
2004 /* is called with STATE_LOCK */
2005 static GstStateChangeReturn
2006 gst_element_change_state (GstElement * element, GstStateChange transition)
2007 {
2008   GstState state, pending;
2009   GstStateChangeReturn result = GST_STATE_CHANGE_SUCCESS;
2010
2011   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_CHANGE_FAILURE);
2012
2013   state = GST_STATE (element);
2014   pending = GST_STATE_PENDING (element);
2015
2016   /* if the element already is in the given state, we just return success */
2017   if (pending == GST_STATE_VOID_PENDING || state == GST_STATE_PENDING (element)) {
2018     GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2019         "element is already in the %s state",
2020         gst_element_state_get_name (state));
2021     if (GST_STATE_NO_PREROLL (element))
2022       return GST_STATE_CHANGE_NO_PREROLL;
2023     else
2024       return GST_STATE_CHANGE_SUCCESS;
2025   }
2026
2027   GST_CAT_LOG_OBJECT (GST_CAT_STATES, element,
2028       "default handler tries setting state from %s to %s (%04x)",
2029       gst_element_state_get_name (state),
2030       gst_element_state_get_name (pending), transition);
2031
2032   switch (transition) {
2033     case GST_STATE_CHANGE_NULL_TO_READY:
2034       break;
2035     case GST_STATE_CHANGE_READY_TO_PAUSED:
2036       if (!gst_element_pads_activate (element, TRUE)) {
2037         result = GST_STATE_CHANGE_FAILURE;
2038       }
2039       break;
2040     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
2041       break;
2042     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
2043       break;
2044     case GST_STATE_CHANGE_PAUSED_TO_READY:
2045     case GST_STATE_CHANGE_READY_TO_NULL:
2046       /* deactivate pads in both cases, since they are activated on
2047          ready->paused but the element might not have made it to paused */
2048       if (!gst_element_pads_activate (element, FALSE)) {
2049         result = GST_STATE_CHANGE_FAILURE;
2050       } else {
2051         GST_LOCK (element);
2052         element->base_time = 0;
2053         GST_UNLOCK (element);
2054       }
2055       break;
2056     default:
2057       /* this will catch real but unhandled state changes;
2058        * can only be caused by:
2059        * - a new state was added
2060        * - somehow the element was asked to jump across an intermediate state
2061        */
2062       g_warning ("Unhandled state change from %s to %s",
2063           gst_element_state_get_name (state),
2064           gst_element_state_get_name (pending));
2065       break;
2066   }
2067
2068   return result;
2069 }
2070
2071 /**
2072  * gst_element_get_factory:
2073  * @element: a #GstElement to request the element factory of.
2074  *
2075  * Retrieves the factory that was used to create this element.
2076  *
2077  * Returns: the #GstElementFactory used for creating this element.
2078  */
2079 GstElementFactory *
2080 gst_element_get_factory (GstElement * element)
2081 {
2082   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
2083
2084   return GST_ELEMENT_GET_CLASS (element)->elementfactory;
2085 }
2086
2087 static void
2088 gst_element_dispose (GObject * object)
2089 {
2090   GstElement *element = GST_ELEMENT (object);
2091
2092   GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "dispose");
2093
2094   /* first we break all our links with the outside */
2095   while (element->pads) {
2096     gst_element_remove_pad (element, GST_PAD_CAST (element->pads->data));
2097   }
2098   if (G_UNLIKELY (element->pads != 0)) {
2099     g_critical ("could not remove pads from element %s",
2100         GST_STR_NULL (GST_OBJECT_NAME (object)));
2101   }
2102
2103   GST_LOCK (element);
2104   gst_object_replace ((GstObject **) & element->clock, NULL);
2105   gst_object_replace ((GstObject **) & element->bus, NULL);
2106   GST_UNLOCK (element);
2107
2108   GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "dispose parent");
2109
2110   G_OBJECT_CLASS (parent_class)->dispose (object);
2111 }
2112
2113 static void
2114 gst_element_finalize (GObject * object)
2115 {
2116   GstElement *element = GST_ELEMENT (object);
2117
2118   GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "finalize");
2119
2120   GST_STATE_LOCK (element);
2121   if (element->state_cond)
2122     g_cond_free (element->state_cond);
2123   element->state_cond = NULL;
2124   GST_STATE_UNLOCK (element);
2125   g_mutex_free (element->state_lock);
2126
2127   GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "finalize parent");
2128
2129   G_OBJECT_CLASS (parent_class)->finalize (object);
2130 }
2131
2132 #ifndef GST_DISABLE_LOADSAVE
2133 /**
2134  * gst_element_save_thyself:
2135  * @element: a #GstElement to save.
2136  * @parent: the xml parent node.
2137  *
2138  * Saves the element as part of the given XML structure.
2139  *
2140  * Returns: the new #xmlNodePtr.
2141  */
2142 static xmlNodePtr
2143 gst_element_save_thyself (GstObject * object, xmlNodePtr parent)
2144 {
2145   GList *pads;
2146   GstElementClass *oclass;
2147   GParamSpec **specs, *spec;
2148   guint nspecs;
2149   gint i;
2150   GValue value = { 0, };
2151   GstElement *element;
2152
2153   g_return_val_if_fail (GST_IS_ELEMENT (object), parent);
2154
2155   element = GST_ELEMENT (object);
2156
2157   oclass = GST_ELEMENT_GET_CLASS (element);
2158
2159   xmlNewChild (parent, NULL, (xmlChar *) "name",
2160       (xmlChar *) GST_ELEMENT_NAME (element));
2161
2162   if (oclass->elementfactory != NULL) {
2163     GstElementFactory *factory = (GstElementFactory *) oclass->elementfactory;
2164
2165     xmlNewChild (parent, NULL, (xmlChar *) "type",
2166         (xmlChar *) GST_PLUGIN_FEATURE (factory)->name);
2167   }
2168
2169   /* params */
2170   specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (object), &nspecs);
2171
2172   for (i = 0; i < nspecs; i++) {
2173     spec = specs[i];
2174     if (spec->flags & G_PARAM_READABLE) {
2175       xmlNodePtr param;
2176       char *contents;
2177
2178       g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (spec));
2179
2180       g_object_get_property (G_OBJECT (element), spec->name, &value);
2181       param = xmlNewChild (parent, NULL, (xmlChar *) "param", NULL);
2182       xmlNewChild (param, NULL, (xmlChar *) "name", (xmlChar *) spec->name);
2183
2184       if (G_IS_PARAM_SPEC_STRING (spec))
2185         contents = g_value_dup_string (&value);
2186       else if (G_IS_PARAM_SPEC_ENUM (spec))
2187         contents = g_strdup_printf ("%d", g_value_get_enum (&value));
2188       else if (G_IS_PARAM_SPEC_INT64 (spec))
2189         contents = g_strdup_printf ("%" G_GINT64_FORMAT,
2190             g_value_get_int64 (&value));
2191       else
2192         contents = g_strdup_value_contents (&value);
2193
2194       xmlNewChild (param, NULL, (xmlChar *) "value", (xmlChar *) contents);
2195       g_free (contents);
2196
2197       g_value_unset (&value);
2198     }
2199   }
2200
2201   g_free (specs);
2202
2203   pads = GST_ELEMENT_PADS (element);
2204
2205   while (pads) {
2206     GstPad *pad = GST_PAD (pads->data);
2207
2208     /* figure out if it's a direct pad or a ghostpad */
2209     if (GST_ELEMENT (GST_OBJECT_PARENT (pad)) == element) {
2210       xmlNodePtr padtag = xmlNewChild (parent, NULL, (xmlChar *) "pad", NULL);
2211
2212       gst_object_save_thyself (GST_OBJECT (pad), padtag);
2213     }
2214     pads = g_list_next (pads);
2215   }
2216
2217   return parent;
2218 }
2219
2220 static void
2221 gst_element_restore_thyself (GstObject * object, xmlNodePtr self)
2222 {
2223   xmlNodePtr children;
2224   GstElement *element;
2225   gchar *name = NULL;
2226   gchar *value = NULL;
2227
2228   element = GST_ELEMENT (object);
2229   g_return_if_fail (element != NULL);
2230
2231   /* parameters */
2232   children = self->xmlChildrenNode;
2233   while (children) {
2234     if (!strcmp ((char *) children->name, "param")) {
2235       xmlNodePtr child = children->xmlChildrenNode;
2236
2237       while (child) {
2238         if (!strcmp ((char *) child->name, "name")) {
2239           name = (gchar *) xmlNodeGetContent (child);
2240         } else if (!strcmp ((char *) child->name, "value")) {
2241           value = (gchar *) xmlNodeGetContent (child);
2242         }
2243         child = child->next;
2244       }
2245       /* FIXME: can this just be g_object_set ? */
2246       gst_util_set_object_arg (G_OBJECT (element), name, value);
2247       /* g_object_set (G_OBJECT (element), name, value, NULL); */
2248       g_free (name);
2249       g_free (value);
2250     }
2251     children = children->next;
2252   }
2253
2254   /* pads */
2255   children = self->xmlChildrenNode;
2256   while (children) {
2257     if (!strcmp ((char *) children->name, "pad")) {
2258       gst_pad_load_and_link (children, GST_OBJECT (element));
2259     }
2260     children = children->next;
2261   }
2262
2263   if (GST_OBJECT_CLASS (parent_class)->restore_thyself)
2264     (GST_OBJECT_CLASS (parent_class)->restore_thyself) (object, self);
2265 }
2266 #endif /* GST_DISABLE_LOADSAVE */
2267
2268 static void
2269 gst_element_set_bus_func (GstElement * element, GstBus * bus)
2270 {
2271   g_return_if_fail (GST_IS_ELEMENT (element));
2272
2273   GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, element, "setting bus to %p", bus);
2274
2275   GST_LOCK (element);
2276   gst_object_replace ((GstObject **) & GST_ELEMENT_BUS (element),
2277       GST_OBJECT (bus));
2278   GST_UNLOCK (element);
2279 }
2280
2281 /**
2282  * gst_element_set_bus:
2283  * @element: a #GstElement to set the bus of.
2284  * @bus: the #GstBus to set.
2285  *
2286  * Sets the bus of the element.  For internal use only, unless you're
2287  * testing elements.
2288  *
2289  * MT safe.
2290  */
2291 void
2292 gst_element_set_bus (GstElement * element, GstBus * bus)
2293 {
2294   GstElementClass *oclass;
2295
2296   g_return_if_fail (GST_IS_ELEMENT (element));
2297
2298   oclass = GST_ELEMENT_GET_CLASS (element);
2299
2300   if (oclass->set_bus)
2301     oclass->set_bus (element, bus);
2302 }
2303
2304 /**
2305  * gst_element_get_bus:
2306  * @element: a #GstElement to get the bus of.
2307  *
2308  * Returns the bus of the element.
2309  *
2310  * Returns: the element's #GstBus. unref after usage.
2311  *
2312  * MT safe.
2313  */
2314 GstBus *
2315 gst_element_get_bus (GstElement * element)
2316 {
2317   GstBus *result = NULL;
2318
2319   g_return_val_if_fail (GST_IS_ELEMENT (element), result);
2320
2321   GST_LOCK (element);
2322   result = GST_ELEMENT_BUS (element);
2323   gst_object_ref (result);
2324   GST_UNLOCK (element);
2325
2326   GST_DEBUG_OBJECT (element, "got bus %" GST_PTR_FORMAT, result);
2327
2328   return result;
2329 }