Make sure that when a pipeline goes to PLAYING, that data has actually hit the sink.
[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    * @old_state: the GST_STATE_XXX before the change
120    * @new_state: the GST_STATE_XXX after the change
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    * @new_pad: the pad that has been added
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    * @old_pad: the pad that has been removed
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    * This signals that the element will not generate more dynamic pads.
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     gst_element_lost_state (element);
1782   }
1783
1784   /* start with the current state */
1785   current = GST_STATE (element);
1786
1787   GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "setting state from %s to %s",
1788       gst_element_state_get_name (current), gst_element_state_get_name (state));
1789
1790   oclass = GST_ELEMENT_GET_CLASS (element);
1791
1792   /* We always perform at least one state change, even if the 
1793    * current state is equal to the required state. This is needed
1794    * for bins that sync their children. */
1795   do {
1796     GstElementState pending;
1797
1798     /* calculate the pending state */
1799     if (current < state)
1800       pending = current << 1;
1801     else if (current > state)
1802       pending = current >> 1;
1803     else
1804       pending = current;
1805
1806     /* set the pending state variable */
1807     GST_STATE_PENDING (element) = pending;
1808
1809     GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1810         "%s: setting state from %s to %s",
1811         (pending != state ? "intermediate" : "final"),
1812         gst_element_state_get_name (current),
1813         gst_element_state_get_name (pending));
1814
1815     /* call the state change function so it can set the state */
1816     if (oclass->change_state)
1817       return_val = (oclass->change_state) (element);
1818     else
1819       return_val = GST_STATE_FAILURE;
1820
1821     /* clear the error and preroll flag, we need to do that after
1822      * calling the virtual change_state function so that it can use the
1823      * old previous value. */
1824     GST_STATE_ERROR (element) = FALSE;
1825     GST_STATE_NO_PREROLL (element) = FALSE;
1826
1827     switch (return_val) {
1828       case GST_STATE_FAILURE:
1829         GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1830             "have failed change_state return");
1831         /* state change failure exits the loop */
1832         gst_element_abort_state (element);
1833         goto exit;
1834       case GST_STATE_ASYNC:
1835         GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1836             "element will change state async");
1837         /* an async state change exits the loop, we can only
1838          * go to the next state change when this one completes. */
1839         goto exit;
1840       case GST_STATE_SUCCESS:
1841         GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1842             "element changed state successfully");
1843         /* we can commit the state now and proceed to the next state */
1844         gst_element_commit_state (element);
1845         GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "commited state");
1846         break;
1847       case GST_STATE_NO_PREROLL:
1848         GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1849             "element changed state successfully and can't preroll");
1850         /* we can commit the state now and proceed to the next state */
1851         gst_element_commit_state (element);
1852         GST_STATE_NO_PREROLL (element) = TRUE;
1853         GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "commited state");
1854         break;
1855       default:
1856         goto invalid_return;
1857     }
1858     /* get the current state of the element and see if we need to do more
1859      * state changes */
1860     current = GST_STATE (element);
1861   }
1862   while (current != state);
1863
1864 exit:
1865   GST_STATE_FINAL (element) = GST_STATE_VOID_PENDING;
1866   GST_STATE_UNLOCK (element);
1867
1868   GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "exit state change");
1869
1870   return return_val;
1871
1872   /* ERROR */
1873 invalid_return:
1874   {
1875     GST_STATE_FINAL (element) = GST_STATE_VOID_PENDING;
1876     GST_STATE_UNLOCK (element);
1877     /* somebody added a GST_STATE_ and forgot to do stuff here ! */
1878     g_critical ("unknown return value %d from a state change function",
1879         return_val);
1880     return GST_STATE_FAILURE;
1881   }
1882 }
1883
1884 /* gst_iterator_fold functions for pads_activate */
1885
1886 static gboolean
1887 activate_pads (GstPad * pad, GValue * ret, gboolean * active)
1888 {
1889   if (!gst_pad_set_active (pad, *active))
1890     g_value_set_boolean (ret, FALSE);
1891   else if (!*active)
1892     gst_pad_set_caps (pad, NULL);
1893
1894   gst_object_unref (pad);
1895   return TRUE;
1896 }
1897
1898 /* returns false on error or early cutout of the fold, true otherwise */
1899 static gboolean
1900 iterator_fold_with_resync (GstIterator * iter, GstIteratorFoldFunction func,
1901     GValue * ret, gpointer user_data)
1902 {
1903   GstIteratorResult ires;
1904   gboolean res = TRUE;
1905
1906   while (1) {
1907     ires = gst_iterator_fold (iter, func, ret, user_data);
1908
1909     switch (ires) {
1910       case GST_ITERATOR_RESYNC:
1911         gst_iterator_resync (iter);
1912         break;
1913       case GST_ITERATOR_DONE:
1914         res = TRUE;
1915         goto done;
1916       default:
1917         res = FALSE;
1918         goto done;
1919     }
1920   }
1921
1922 done:
1923   return res;
1924 }
1925
1926 /* is called with STATE_LOCK
1927  */
1928 static gboolean
1929 gst_element_pads_activate (GstElement * element, gboolean active)
1930 {
1931   GValue ret = { 0, };
1932   GstIterator *iter;
1933   gboolean fold_ok;
1934
1935   /* no need to unset this later, it's just a boolean */
1936   g_value_init (&ret, G_TYPE_BOOLEAN);
1937   g_value_set_boolean (&ret, TRUE);
1938
1939   iter = gst_element_iterate_src_pads (element);
1940   fold_ok = iterator_fold_with_resync
1941       (iter, (GstIteratorFoldFunction) activate_pads, &ret, &active);
1942   gst_iterator_free (iter);
1943   if (!fold_ok || !g_value_get_boolean (&ret))
1944     return FALSE;
1945
1946   iter = gst_element_iterate_sink_pads (element);
1947   fold_ok = iterator_fold_with_resync
1948       (iter, (GstIteratorFoldFunction) activate_pads, &ret, &active);
1949   gst_iterator_free (iter);
1950   if (!fold_ok || !g_value_get_boolean (&ret))
1951     return FALSE;
1952
1953   return TRUE;
1954 }
1955
1956 /* is called with STATE_LOCK */
1957 static GstElementStateReturn
1958 gst_element_change_state (GstElement * element)
1959 {
1960   GstElementState old_state;
1961   gint old_pending, old_transition;
1962   GstElementStateReturn result = GST_STATE_SUCCESS;
1963
1964   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
1965
1966   old_state = GST_STATE (element);
1967   old_pending = GST_STATE_PENDING (element);
1968   old_transition = GST_STATE_TRANSITION (element);
1969
1970   /* if the element already is in the given state, we just return success */
1971   if (old_pending == GST_STATE_VOID_PENDING ||
1972       old_state == GST_STATE_PENDING (element)) {
1973     GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1974         "element is already in the %s state",
1975         gst_element_state_get_name (old_state));
1976     if (GST_STATE_NO_PREROLL (element))
1977       return GST_STATE_NO_PREROLL;
1978     else
1979       return GST_STATE_SUCCESS;
1980   }
1981
1982   GST_CAT_LOG_OBJECT (GST_CAT_STATES, element,
1983       "default handler tries setting state from %s to %s (%04x)",
1984       gst_element_state_get_name (old_state),
1985       gst_element_state_get_name (old_pending), old_transition);
1986
1987   switch (old_transition) {
1988     case GST_STATE_NULL_TO_READY:
1989       break;
1990     case GST_STATE_READY_TO_PAUSED:
1991       if (!gst_element_pads_activate (element, TRUE)) {
1992         result = GST_STATE_FAILURE;
1993       }
1994       break;
1995     case GST_STATE_PAUSED_TO_PLAYING:
1996       break;
1997     case GST_STATE_PLAYING_TO_PAUSED:
1998       break;
1999     case GST_STATE_PAUSED_TO_READY:
2000     case GST_STATE_READY_TO_NULL:
2001       /* deactivate pads in both cases, since they are activated on
2002          ready->paused but the element might not have made it to paused */
2003       if (!gst_element_pads_activate (element, FALSE)) {
2004         result = GST_STATE_FAILURE;
2005       } else {
2006         GST_LOCK (element);
2007         element->base_time = 0;
2008         GST_UNLOCK (element);
2009       }
2010       break;
2011     default:
2012       /* this will catch real but unhandled state changes;
2013        * can only be caused by:
2014        * - a new state was added
2015        * - somehow the element was asked to jump across an intermediate state
2016        */
2017       g_warning ("Unhandled state change from %s to %s",
2018           gst_element_state_get_name (old_state),
2019           gst_element_state_get_name (old_pending));
2020       break;
2021   }
2022
2023   return result;
2024 }
2025
2026 /**
2027  * gst_element_get_factory:
2028  * @element: a #GstElement to request the element factory of.
2029  *
2030  * Retrieves the factory that was used to create this element.
2031  *
2032  * Returns: the #GstElementFactory used for creating this element.
2033  */
2034 GstElementFactory *
2035 gst_element_get_factory (GstElement * element)
2036 {
2037   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
2038
2039   return GST_ELEMENT_GET_CLASS (element)->elementfactory;
2040 }
2041
2042 static void
2043 gst_element_dispose (GObject * object)
2044 {
2045   GstElement *element = GST_ELEMENT (object);
2046
2047   GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "dispose");
2048
2049   /* ref so we don't hit 0 again */
2050   gst_object_ref (object);
2051
2052   /* first we break all our links with the outside */
2053   while (element->pads) {
2054     gst_element_remove_pad (element, GST_PAD_CAST (element->pads->data));
2055   }
2056   if (G_UNLIKELY (element->pads != 0)) {
2057     g_critical ("could not remove pads from element %s",
2058         GST_STR_NULL (GST_OBJECT_NAME (object)));
2059   }
2060
2061   GST_LOCK (element);
2062   gst_object_replace ((GstObject **) & element->clock, NULL);
2063   GST_UNLOCK (element);
2064
2065   GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "dispose parent");
2066
2067   G_OBJECT_CLASS (parent_class)->dispose (object);
2068 }
2069
2070 static void
2071 gst_element_finalize (GObject * object)
2072 {
2073   GstElement *element = GST_ELEMENT (object);
2074
2075   GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "finalize");
2076
2077   GST_STATE_LOCK (element);
2078   if (element->state_cond)
2079     g_cond_free (element->state_cond);
2080   element->state_cond = NULL;
2081   GST_STATE_UNLOCK (element);
2082   g_mutex_free (element->state_lock);
2083
2084   GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "finalize parent");
2085
2086   G_OBJECT_CLASS (parent_class)->finalize (object);
2087 }
2088
2089 #ifndef GST_DISABLE_LOADSAVE
2090 /**
2091  * gst_element_save_thyself:
2092  * @element: a #GstElement to save.
2093  * @parent: the xml parent node.
2094  *
2095  * Saves the element as part of the given XML structure.
2096  *
2097  * Returns: the new #xmlNodePtr.
2098  */
2099 static xmlNodePtr
2100 gst_element_save_thyself (GstObject * object, xmlNodePtr parent)
2101 {
2102   GList *pads;
2103   GstElementClass *oclass;
2104   GParamSpec **specs, *spec;
2105   guint nspecs;
2106   gint i;
2107   GValue value = { 0, };
2108   GstElement *element;
2109
2110   g_return_val_if_fail (GST_IS_ELEMENT (object), parent);
2111
2112   element = GST_ELEMENT (object);
2113
2114   oclass = GST_ELEMENT_GET_CLASS (element);
2115
2116   xmlNewChild (parent, NULL, (xmlChar *) "name",
2117       (xmlChar *) GST_ELEMENT_NAME (element));
2118
2119   if (oclass->elementfactory != NULL) {
2120     GstElementFactory *factory = (GstElementFactory *) oclass->elementfactory;
2121
2122     xmlNewChild (parent, NULL, (xmlChar *) "type",
2123         (xmlChar *) GST_PLUGIN_FEATURE (factory)->name);
2124   }
2125
2126   /* params */
2127   specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (object), &nspecs);
2128
2129   for (i = 0; i < nspecs; i++) {
2130     spec = specs[i];
2131     if (spec->flags & G_PARAM_READABLE) {
2132       xmlNodePtr param;
2133       char *contents;
2134
2135       g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (spec));
2136
2137       g_object_get_property (G_OBJECT (element), spec->name, &value);
2138       param = xmlNewChild (parent, NULL, (xmlChar *) "param", NULL);
2139       xmlNewChild (param, NULL, (xmlChar *) "name", (xmlChar *) spec->name);
2140
2141       if (G_IS_PARAM_SPEC_STRING (spec))
2142         contents = g_value_dup_string (&value);
2143       else if (G_IS_PARAM_SPEC_ENUM (spec))
2144         contents = g_strdup_printf ("%d", g_value_get_enum (&value));
2145       else if (G_IS_PARAM_SPEC_INT64 (spec))
2146         contents = g_strdup_printf ("%" G_GINT64_FORMAT,
2147             g_value_get_int64 (&value));
2148       else
2149         contents = g_strdup_value_contents (&value);
2150
2151       xmlNewChild (param, NULL, (xmlChar *) "value", (xmlChar *) contents);
2152       g_free (contents);
2153
2154       g_value_unset (&value);
2155     }
2156   }
2157
2158   pads = GST_ELEMENT_PADS (element);
2159
2160   while (pads) {
2161     GstPad *pad = GST_PAD (pads->data);
2162
2163     /* figure out if it's a direct pad or a ghostpad */
2164     if (GST_ELEMENT (GST_OBJECT_PARENT (pad)) == element) {
2165       xmlNodePtr padtag = xmlNewChild (parent, NULL, (xmlChar *) "pad", NULL);
2166
2167       gst_object_save_thyself (GST_OBJECT (pad), padtag);
2168     }
2169     pads = g_list_next (pads);
2170   }
2171
2172   return parent;
2173 }
2174
2175 static void
2176 gst_element_restore_thyself (GstObject * object, xmlNodePtr self)
2177 {
2178   xmlNodePtr children;
2179   GstElement *element;
2180   gchar *name = NULL;
2181   gchar *value = NULL;
2182
2183   element = GST_ELEMENT (object);
2184   g_return_if_fail (element != NULL);
2185
2186   /* parameters */
2187   children = self->xmlChildrenNode;
2188   while (children) {
2189     if (!strcmp ((char *) children->name, "param")) {
2190       xmlNodePtr child = children->xmlChildrenNode;
2191
2192       while (child) {
2193         if (!strcmp ((char *) child->name, "name")) {
2194           name = (gchar *) xmlNodeGetContent (child);
2195         } else if (!strcmp ((char *) child->name, "value")) {
2196           value = (gchar *) xmlNodeGetContent (child);
2197         }
2198         child = child->next;
2199       }
2200       /* FIXME: can this just be g_object_set ? */
2201       gst_util_set_object_arg (G_OBJECT (element), name, value);
2202       /* g_object_set (G_OBJECT (element), name, value, NULL); */
2203       g_free (name);
2204       g_free (value);
2205     }
2206     children = children->next;
2207   }
2208
2209   /* pads */
2210   children = self->xmlChildrenNode;
2211   while (children) {
2212     if (!strcmp ((char *) children->name, "pad")) {
2213       gst_pad_load_and_link (children, GST_OBJECT (element));
2214     }
2215     children = children->next;
2216   }
2217
2218   if (GST_OBJECT_CLASS (parent_class)->restore_thyself)
2219     (GST_OBJECT_CLASS (parent_class)->restore_thyself) (object, self);
2220 }
2221 #endif /* GST_DISABLE_LOADSAVE */
2222
2223 static void
2224 gst_element_set_bus_func (GstElement * element, GstBus * bus)
2225 {
2226   g_return_if_fail (GST_IS_ELEMENT (element));
2227
2228   GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, element, "setting bus to %p", bus);
2229
2230   GST_LOCK (element);
2231   gst_object_replace ((GstObject **) & GST_ELEMENT_BUS (element),
2232       GST_OBJECT (bus));
2233   GST_UNLOCK (element);
2234 }
2235
2236 /**
2237  * gst_element_set_bus:
2238  * @element: a #GstElement to set the bus of.
2239  * @bus: the #GstBus to set.
2240  *
2241  * Sets the bus of the element.  For internal use only, unless you're
2242  * testing elements.
2243  *
2244  * MT safe.
2245  */
2246 void
2247 gst_element_set_bus (GstElement * element, GstBus * bus)
2248 {
2249   GstElementClass *oclass;
2250
2251   g_return_if_fail (GST_IS_ELEMENT (element));
2252
2253   oclass = GST_ELEMENT_GET_CLASS (element);
2254
2255   if (oclass->set_bus)
2256     oclass->set_bus (element, bus);
2257 }
2258
2259 /**
2260  * gst_element_get_bus:
2261  * @element: a #GstElement to get the bus of.
2262  *
2263  * Returns the bus of the element.
2264  *
2265  * Returns: the element's #GstBus. unref after usage.
2266  *
2267  * MT safe.
2268  */
2269 GstBus *
2270 gst_element_get_bus (GstElement * element)
2271 {
2272   GstBus *result = NULL;
2273
2274   g_return_val_if_fail (GST_IS_ELEMENT (element), result);
2275
2276   GST_LOCK (element);
2277   result = GST_ELEMENT_BUS (element);
2278   gst_object_ref (result);
2279   GST_UNLOCK (element);
2280
2281   GST_DEBUG_OBJECT (element, "got bus %" GST_PTR_FORMAT, result);
2282
2283   return result;
2284 }