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