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