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