*.c: Don't cast to GST_OBJECT when reffing or unreffing. Large source-munging commit!!!
[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 (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 (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 (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 (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 use.
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 (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 static gint
858 direction_filter (gconstpointer pad, gconstpointer direction)
859 {
860   if (GST_PAD_DIRECTION (pad) == GPOINTER_TO_INT (direction)) {
861     /* pass the ref through */
862     return 0;
863   } else {
864     /* unref */
865     /* FIXME: this is very stupid */
866     gst_object_unref (GST_OBJECT_CAST (pad));
867     return 1;
868   }
869 }
870
871 /**
872  * gst_element_iterate_src_pads:
873  * @element: a #GstElement.
874  *
875  * Retrieves an iterator of @element's source pads. 
876  *
877  * Returns: the #GstIterator of #GstPad. Unref each pad after use.
878  *
879  * MT safe.
880  */
881 GstIterator *
882 gst_element_iterate_src_pads (GstElement * element)
883 {
884   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
885
886   return gst_iterator_filter (gst_element_iterate_pads (element),
887       direction_filter, GINT_TO_POINTER (GST_PAD_SRC));
888 }
889
890 /**
891  * gst_element_iterate_sink_pads:
892  * @element: a #GstElement.
893  *
894  * Retrieves an iterator of @element's sink pads. 
895  *
896  * Returns: the #GstIterator of #GstPad. Unref each pad after use.
897  *
898  * MT safe.
899  */
900 GstIterator *
901 gst_element_iterate_sink_pads (GstElement * element)
902 {
903   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
904
905   return gst_iterator_filter (gst_element_iterate_pads (element),
906       direction_filter, GINT_TO_POINTER (GST_PAD_SINK));
907 }
908
909 /**
910  * gst_element_class_add_pad_template:
911  * @klass: the #GstElementClass to add the pad template to.
912  * @templ: a #GstPadTemplate to add to the element class.
913  *
914  * Adds a padtemplate to an element class. This is mainly used in the _base_init
915  * functions of classes.
916  */
917 void
918 gst_element_class_add_pad_template (GstElementClass * klass,
919     GstPadTemplate * templ)
920 {
921   g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
922   g_return_if_fail (GST_IS_PAD_TEMPLATE (templ));
923
924   /* avoid registering pad templates with the same name */
925   g_return_if_fail (gst_element_class_get_pad_template (klass,
926           templ->name_template) == NULL);
927
928   klass->padtemplates = g_list_append (klass->padtemplates,
929       gst_object_ref (templ));
930   klass->numpadtemplates++;
931 }
932
933 /**
934  * gst_element_class_set_details:
935  * @klass: class to set details for
936  * @details: details to set
937  *
938  * Sets the detailed information for a #GstElementClass.
939  * <note>This function is for use in _base_init functions only.</note>
940  */
941 void
942 gst_element_class_set_details (GstElementClass * klass,
943     const GstElementDetails * details)
944 {
945   g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
946   g_return_if_fail (GST_IS_ELEMENT_DETAILS (details));
947
948   __gst_element_details_copy (&klass->details, details);
949 }
950
951 /**
952  * gst_element_class_get_pad_template_list:
953  * @element_class: a #GstElementClass to get pad templates of.
954  *
955  * Retrieves a list of the pad templates associated with @element_class. The
956  * list must not be modified by the calling code.
957  * <note>If you use this function in the #GInstanceInitFunc of an object class
958  * that has subclasses, make sure to pass the g_class parameter of the
959  * #GInstanceInitFunc here.</note>
960  *
961  * Returns: the #GList of padtemplates.
962  */
963 GList *
964 gst_element_class_get_pad_template_list (GstElementClass * element_class)
965 {
966   g_return_val_if_fail (GST_IS_ELEMENT_CLASS (element_class), NULL);
967
968   return element_class->padtemplates;
969 }
970
971 /**
972  * gst_element_class_get_pad_template:
973  * @element_class: a #GstElementClass to get the pad template of.
974  * @name: the name of the #GstPadTemplate to get.
975  *
976  * Retrieves a padtemplate from @element_class with the given name.
977  * <note>If you use this function in the #GInstanceInitFunc of an object class
978  * that has subclasses, make sure to pass the g_class parameter of the
979  * #GInstanceInitFunc here.</note>
980  *
981  * Returns: the #GstPadTemplate with the given name, or NULL if none was found.
982  * No unreferencing is necessary.
983  */
984 GstPadTemplate *
985 gst_element_class_get_pad_template (GstElementClass * element_class,
986     const gchar * name)
987 {
988   GList *padlist;
989
990   g_return_val_if_fail (GST_IS_ELEMENT_CLASS (element_class), NULL);
991   g_return_val_if_fail (name != NULL, NULL);
992
993   padlist = gst_element_class_get_pad_template_list (element_class);
994
995   while (padlist) {
996     GstPadTemplate *padtempl = (GstPadTemplate *) padlist->data;
997
998     if (strcmp (padtempl->name_template, name) == 0)
999       return padtempl;
1000
1001     padlist = g_list_next (padlist);
1002   }
1003
1004   return NULL;
1005 }
1006
1007 static GstPad *
1008 gst_element_get_random_pad (GstElement * element, GstPadDirection dir)
1009 {
1010   GstPad *result = NULL;
1011   GList *pads;
1012
1013   GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "getting a random pad");
1014
1015   switch (dir) {
1016     case GST_PAD_SRC:
1017       GST_LOCK (element);
1018       pads = element->srcpads;
1019       break;
1020     case GST_PAD_SINK:
1021       GST_LOCK (element);
1022       pads = element->sinkpads;
1023       break;
1024     default:
1025       goto wrong_direction;
1026   }
1027   for (; pads; pads = g_list_next (pads)) {
1028     GstPad *pad = GST_PAD (pads->data);
1029
1030     GST_LOCK (pad);
1031     GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "checking pad %s:%s",
1032         GST_DEBUG_PAD_NAME (pad));
1033
1034     if (GST_PAD_IS_LINKED (pad)) {
1035       GST_UNLOCK (pad);
1036       result = pad;
1037       break;
1038     } else {
1039       GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s is not linked",
1040           GST_DEBUG_PAD_NAME (pad));
1041     }
1042     GST_UNLOCK (pad);
1043   }
1044   if (result)
1045     gst_object_ref (result);
1046
1047   GST_UNLOCK (element);
1048
1049   return result;
1050
1051   /* ERROR handling */
1052 wrong_direction:
1053   {
1054     g_warning ("unknown pad direction %d", dir);
1055     return NULL;
1056   }
1057 }
1058
1059 /**
1060  * gst_element_send_event:
1061  * @element: a #GstElement to send the event to.
1062  * @event: the #GstEvent to send to the element.
1063  *
1064  * Sends an event to an element. If the element doesn't
1065  * implement an event handler, the event will be forwarded
1066  * to a random sink pad. This function takes owership of the
1067  * provided event so you should _ref it if you want to reuse
1068  * the event after this call.
1069  *
1070  * Returns: TRUE if the event was handled.
1071  *
1072  * MT safe.
1073  */
1074 gboolean
1075 gst_element_send_event (GstElement * element, GstEvent * event)
1076 {
1077   GstElementClass *oclass;
1078   gboolean result = FALSE;
1079
1080   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1081   g_return_val_if_fail (event != NULL, FALSE);
1082
1083   oclass = GST_ELEMENT_GET_CLASS (element);
1084
1085   if (oclass->send_event) {
1086     result = oclass->send_event (element, event);
1087   } else {
1088     GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SINK);
1089
1090     if (pad) {
1091       GstPad *peer = gst_pad_get_peer (pad);
1092
1093       if (peer) {
1094         GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
1095             "sending event to random pad %s:%s", GST_DEBUG_PAD_NAME (pad));
1096
1097         result = gst_pad_send_event (peer, event);
1098         gst_object_unref (peer);
1099       }
1100       gst_object_unref (pad);
1101     }
1102   }
1103   GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "can't send event on element %s",
1104       GST_ELEMENT_NAME (element));
1105
1106   return result;
1107 }
1108
1109 /**
1110  * gst_element_seek:
1111  * @element: a #GstElement to send the event to.
1112  * @seek_type: the method to use for seeking.
1113  * @offset: the offset to seek to.
1114  *
1115  * Sends a seek event to an element.
1116  *
1117  * Returns: TRUE if the event was handled.
1118  *
1119  * MT safe.
1120  */
1121 gboolean
1122 gst_element_seek (GstElement * element, GstSeekType seek_type, guint64 offset)
1123 {
1124   GstEvent *event;
1125   gboolean result;
1126
1127   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1128
1129   event = gst_event_new_seek (seek_type, offset);
1130   result = gst_element_send_event (element, event);
1131
1132   return result;
1133 }
1134
1135 /**
1136  * gst_element_get_query_types:
1137  * @element: a #GstElement to query
1138  *
1139  * Get an array of query types from the element.
1140  * If the element doesn't implement a query types function,
1141  * the query will be forwarded to a random sink pad.
1142  *
1143  * Returns: An array of #GstQueryType elements that should not
1144  * be freed or modified.
1145  *
1146  * MT safe.
1147  */
1148 const GstQueryType *
1149 gst_element_get_query_types (GstElement * element)
1150 {
1151   GstElementClass *oclass;
1152   const GstQueryType *result = NULL;
1153
1154   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1155
1156   oclass = GST_ELEMENT_GET_CLASS (element);
1157
1158   if (oclass->get_query_types) {
1159     result = oclass->get_query_types (element);
1160   } else {
1161     GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SINK);
1162
1163     if (pad) {
1164       GstPad *peer = gst_pad_get_peer (pad);
1165
1166       if (peer) {
1167         result = gst_pad_get_query_types (peer);
1168
1169         gst_object_unref (peer);
1170       }
1171       gst_object_unref (pad);
1172     }
1173   }
1174   return result;
1175 }
1176
1177 /**
1178  * gst_element_query:
1179  * @element: a #GstElement to perform the query on.
1180  * @type: the #GstQueryType.
1181  * @format: the #GstFormat pointer to hold the format of the result.
1182  * @value: the pointer to the value of the result.
1183  *
1184  * Performs a query on the given element. If the format is set
1185  * to GST_FORMAT_DEFAULT and this function returns TRUE, the
1186  * format pointer will hold the default format.
1187  * For element that don't implement a query handler, this function
1188  * forwards the query to a random usable sinkpad of this element.
1189  *
1190  * Returns: TRUE if the query could be performed.
1191  *
1192  * MT safe.
1193  */
1194 gboolean
1195 gst_element_query (GstElement * element, GstQuery * query)
1196 {
1197   GstElementClass *oclass;
1198   gboolean result = FALSE;
1199
1200   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1201   g_return_val_if_fail (query != NULL, FALSE);
1202
1203   oclass = GST_ELEMENT_GET_CLASS (element);
1204
1205   if (oclass->query) {
1206     result = oclass->query (element, query);
1207   } else {
1208     GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SRC);
1209
1210     if (pad) {
1211       result = gst_pad_query (pad, query);
1212
1213       gst_object_unref (pad);
1214     } else {
1215       pad = gst_element_get_random_pad (element, GST_PAD_SINK);
1216       if (pad) {
1217         GstPad *peer = gst_pad_get_peer (pad);
1218
1219         if (peer) {
1220           result = gst_pad_query (peer, query);
1221
1222           gst_object_unref (peer);
1223         }
1224         gst_object_unref (pad);
1225       }
1226     }
1227   }
1228   return result;
1229 }
1230
1231 /**
1232  * gst_element_post_message:
1233  * @element: a #GstElement posting the message
1234  * @message: a #GstMessage to post
1235  *
1236  * Post a message on the elements #GstBus.
1237  *
1238  * Returns: TRUE if the message was successfuly posted.
1239  *
1240  * MT safe.
1241  */
1242 gboolean
1243 gst_element_post_message (GstElement * element, GstMessage * message)
1244 {
1245   GstBus *bus;
1246   gboolean result = FALSE;
1247
1248   GST_DEBUG ("posting message %p ...", message);
1249
1250   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1251   g_return_val_if_fail (message != NULL, FALSE);
1252
1253   GST_LOCK (element);
1254   bus = element->bus;
1255
1256   if (G_UNLIKELY (bus == NULL)) {
1257     GST_DEBUG ("... but I won't because I have no bus");
1258     GST_UNLOCK (element);
1259     gst_message_unref (message);
1260     return FALSE;
1261   }
1262   gst_object_ref (bus);
1263   GST_DEBUG ("... on bus %p", bus);
1264   GST_UNLOCK (element);
1265
1266   result = gst_bus_post (bus, message);
1267   gst_object_unref (bus);
1268
1269   return result;
1270 }
1271
1272 /**
1273  * _gst_element_error_printf:
1274  * @format: the printf-like format to use, or NULL
1275  *
1276  * This function is only used internally by the #gst_element_error macro.
1277  *
1278  * Returns: a newly allocated string, or NULL if the format was NULL or ""
1279  *
1280  * MT safe.
1281  */
1282 gchar *
1283 _gst_element_error_printf (const gchar * format, ...)
1284 {
1285   va_list args;
1286   gchar *buffer;
1287
1288   if (format == NULL)
1289     return NULL;
1290   if (format[0] == 0)
1291     return NULL;
1292
1293   va_start (args, format);
1294   buffer = g_strdup_vprintf (format, args);
1295   va_end (args);
1296   return buffer;
1297 }
1298
1299 /**
1300  * gst_element_message_full:
1301  * @element:  a #GstElement to send message from
1302  * @type:     the #GstMessageType
1303  * @domain:   the GStreamer GError domain this message belongs to
1304  * @code:     the GError code belonging to the domain
1305  * @text:     an allocated text string to be used as a replacement for the
1306  *            default message connected to code, or NULL
1307  * @debug:    an allocated debug message to be used as a replacement for the
1308  *            default debugging information, or NULL
1309  * @file:     the source code file where the error was generated
1310  * @function: the source code function where the error was generated
1311  * @line:     the source code line where the error was generated
1312  *
1313  * Post an error or warning message on the bus from inside an element.
1314  *
1315  * MT safe.
1316  */
1317 void gst_element_message_full
1318     (GstElement * element, GstMessageType type,
1319     GQuark domain, gint code, gchar * text,
1320     gchar * debug, const gchar * file, const gchar * function, gint line)
1321 {
1322   GError *gerror = NULL;
1323   gchar *name;
1324   gchar *sent_text;
1325   gchar *sent_debug;
1326   GstMessage *message = NULL;
1327
1328   /* checks */
1329   GST_DEBUG ("start");
1330   g_return_if_fail (GST_IS_ELEMENT (element));
1331   g_return_if_fail ((type == GST_MESSAGE_ERROR) ||
1332       (type == GST_MESSAGE_WARNING));
1333
1334   /* check if we send the given text or the default error text */
1335   if ((text == NULL) || (text[0] == 0)) {
1336     /* text could have come from g_strdup_printf (""); */
1337     g_free (text);
1338     sent_text = gst_error_get_message (domain, code);
1339   } else
1340     sent_text = text;
1341
1342   /* construct a sent_debug with extra information from source */
1343   if ((debug == NULL) || (debug[0] == 0)) {
1344     /* debug could have come from g_strdup_printf (""); */
1345     sent_debug = NULL;
1346   } else {
1347     name = gst_object_get_path_string (GST_OBJECT (element));
1348     sent_debug = g_strdup_printf ("%s(%d): %s: %s:\n%s",
1349         file, line, function, name, debug ? debug : "");
1350     g_free (name);
1351   }
1352   g_free (debug);
1353
1354   /* create gerror and post message */
1355   GST_CAT_INFO_OBJECT (GST_CAT_ERROR_SYSTEM, element, "posting message: %s",
1356       sent_text);
1357   gerror = g_error_new_literal (domain, code, sent_text);
1358
1359   if (type == GST_MESSAGE_ERROR) {
1360     message = gst_message_new_error (GST_OBJECT (element), gerror, sent_debug);
1361   } else {
1362     message = gst_message_new_warning (GST_OBJECT (element), gerror,
1363         sent_debug);
1364   }
1365   gst_element_post_message (element, message);
1366
1367   GST_CAT_INFO_OBJECT (GST_CAT_ERROR_SYSTEM, element, "posted message: %s",
1368       sent_text);
1369
1370   /* cleanup */
1371   g_free (sent_text);
1372   /* sent_debug is not part of the gerror, so don't free it here */
1373 }
1374
1375 /**
1376  * gst_element_is_locked_state:
1377  * @element: a #GstElement.
1378  *
1379  * Checks if the state of an element is locked.
1380  * If the state of an element is locked, state changes of the parent don't
1381  * affect the element.
1382  * This way you can leave currently unused elements inside bins. Just lock their
1383  * state before changing the state from #GST_STATE_NULL.
1384  *
1385  * Returns: TRUE, if the element's state is locked.
1386  *
1387  * MT safe.
1388  */
1389 gboolean
1390 gst_element_is_locked_state (GstElement * element)
1391 {
1392   gboolean result = FALSE;
1393
1394   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1395
1396   GST_LOCK (element);
1397   result = GST_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
1398   GST_UNLOCK (element);
1399
1400   return result;
1401 }
1402
1403 /**
1404  * gst_element_set_locked_state:
1405  * @element: a #GstElement
1406  * @locked_state: TRUE to lock the element's state
1407  *
1408  * Locks the state of an element, so state changes of the parent don't affect
1409  * this element anymore.
1410  *
1411  * Returns: TRUE if the state was changed, FALSE if bad params were given or
1412  * the element was already in the correct state.
1413  *
1414  * MT safe.
1415  */
1416 gboolean
1417 gst_element_set_locked_state (GstElement * element, gboolean locked_state)
1418 {
1419   gboolean old;
1420
1421   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1422
1423   GST_LOCK (element);
1424   old = GST_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
1425
1426   if (G_UNLIKELY (old == locked_state))
1427     goto was_ok;
1428
1429   if (locked_state) {
1430     GST_CAT_DEBUG (GST_CAT_STATES, "locking state of element %s",
1431         GST_ELEMENT_NAME (element));
1432     GST_FLAG_SET (element, GST_ELEMENT_LOCKED_STATE);
1433   } else {
1434     GST_CAT_DEBUG (GST_CAT_STATES, "unlocking state of element %s",
1435         GST_ELEMENT_NAME (element));
1436     GST_FLAG_UNSET (element, GST_ELEMENT_LOCKED_STATE);
1437   }
1438   GST_UNLOCK (element);
1439
1440   return TRUE;
1441
1442 was_ok:
1443   GST_UNLOCK (element);
1444
1445   return FALSE;
1446 }
1447
1448 /**
1449  * gst_element_sync_state_with_parent:
1450  * @element: a #GstElement.
1451  *
1452  * Tries to change the state of the element to the same as its parent.
1453  * If this function returns FALSE, the state of element is undefined.
1454  *
1455  * Returns: TRUE, if the element's state could be synced to the parent's state.
1456  */
1457 gboolean
1458 gst_element_sync_state_with_parent (GstElement * element)
1459 {
1460   GstElement *parent;
1461
1462   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1463   parent = GST_ELEMENT (GST_ELEMENT_PARENT (element));
1464   g_return_val_if_fail (GST_IS_BIN (parent), FALSE);
1465
1466   GST_CAT_DEBUG (GST_CAT_STATES, "syncing state of element %s (%s) to %s (%s)",
1467       GST_ELEMENT_NAME (element),
1468       gst_element_state_get_name (GST_STATE (element)),
1469       GST_ELEMENT_NAME (parent),
1470       gst_element_state_get_name (GST_STATE (parent)));
1471
1472   if (gst_element_set_state (element, GST_STATE (parent)) == GST_STATE_FAILURE) {
1473     return FALSE;
1474   }
1475   return TRUE;
1476 }
1477
1478 /* MT safe */
1479 static GstElementStateReturn
1480 gst_element_get_state_func (GstElement * element,
1481     GstElementState * state, GstElementState * pending, GTimeVal * timeout)
1482 {
1483   GstElementStateReturn ret = GST_STATE_FAILURE;
1484   GstElementState old_pending;
1485
1486   GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "getting state");
1487
1488   GST_STATE_LOCK (element);
1489   /* we got an error, report immediatly */
1490   if (GST_STATE_NO_PREROLL (element)) {
1491     ret = GST_STATE_NO_PREROLL;
1492     goto done;
1493   }
1494
1495   /* we got an error, report immediatly */
1496   if (GST_STATE_ERROR (element)) {
1497     ret = GST_STATE_FAILURE;
1498     goto done;
1499   }
1500
1501   old_pending = GST_STATE_PENDING (element);
1502   if (old_pending != GST_STATE_VOID_PENDING) {
1503     GTimeVal *timeval, abstimeout;
1504
1505     GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "wait for pending");
1506     if (timeout) {
1507       /* make timeout absolute */
1508       g_get_current_time (&abstimeout);
1509       g_time_val_add (&abstimeout,
1510           timeout->tv_sec * G_USEC_PER_SEC + timeout->tv_usec);
1511       timeval = &abstimeout;
1512     } else {
1513       timeval = NULL;
1514     }
1515     /* we have a pending state change, wait for it to complete */
1516     if (!GST_STATE_TIMED_WAIT (element, timeval)) {
1517       GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "timeout");
1518       /* timeout triggered */
1519       ret = GST_STATE_ASYNC;
1520     } else {
1521       /* could be success or failure */
1522       if (old_pending == GST_STATE (element)) {
1523         GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "got success");
1524         ret = GST_STATE_SUCCESS;
1525       } else {
1526         GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "got failure");
1527         ret = GST_STATE_FAILURE;
1528       }
1529     }
1530   }
1531   /* if nothing is pending anymore we can return SUCCESS */
1532   if (GST_STATE_PENDING (element) == GST_STATE_VOID_PENDING) {
1533     GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "nothing pending");
1534     ret = GST_STATE_SUCCESS;
1535   }
1536
1537 done:
1538   if (state)
1539     *state = GST_STATE (element);
1540   if (pending)
1541     *pending = GST_STATE_PENDING (element);
1542
1543   GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1544       "state current: %s, pending: %s, error: %d, no_preroll: %d, result: %d",
1545       gst_element_state_get_name (GST_STATE (element)),
1546       gst_element_state_get_name (GST_STATE_PENDING (element)),
1547       GST_STATE_ERROR (element), GST_STATE_NO_PREROLL (element), ret);
1548
1549   GST_STATE_UNLOCK (element);
1550
1551   return ret;
1552 }
1553
1554 /**
1555  * gst_element_get_state:
1556  * @element: a #GstElement to get the state of.
1557  * @state: a pointer to #GstElementState to hold the state. Can be NULL.
1558  * @pending: a pointer to #GstElementState to hold the pending state.
1559  *           Can be NULL.
1560  * @timeout: a #GTimeVal to specify the timeout for an async
1561  *           state change or NULL for infinite timeout.
1562  *
1563  * Gets the state of the element. 
1564  *
1565  * For elements that performed an ASYNC state change, as reported by 
1566  * #gst_element_set_state(), this function will block up to the 
1567  * specified timeout value for the state change to complete. 
1568  * If the element completes the state change or goes into
1569  * an error, this function returns immediatly with a return value of
1570  * GST_STATE_SUCCESS or GST_STATE_FAILURE respectively. 
1571  *
1572  * Returns: GST_STATE_SUCCESS if the element has no more pending state and
1573  *          the last state change succeeded, GST_STATE_ASYNC
1574  *          if the element is still performing a state change or 
1575  *          GST_STATE_FAILURE if the last state change failed.
1576  *
1577  * MT safe.
1578  */
1579 GstElementStateReturn
1580 gst_element_get_state (GstElement * element,
1581     GstElementState * state, GstElementState * pending, GTimeVal * timeout)
1582 {
1583   GstElementClass *oclass;
1584   GstElementStateReturn result = GST_STATE_FAILURE;
1585
1586   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
1587
1588   oclass = GST_ELEMENT_GET_CLASS (element);
1589
1590   if (oclass->get_state)
1591     result = (oclass->get_state) (element, state, pending, timeout);
1592
1593   return result;
1594 }
1595
1596 /**
1597  * gst_element_abort_state:
1598  * @element: a #GstElement to abort the state of.
1599  *
1600  * Abort the state change of the element. This function is used
1601  * by elements that do asynchronous state changes and find out 
1602  * something is wrong.
1603  *
1604  * This function should be called with the STATE_LOCK held.
1605  *
1606  * MT safe.
1607  */
1608 void
1609 gst_element_abort_state (GstElement * element)
1610 {
1611   GstElementState pending;
1612
1613   g_return_if_fail (GST_IS_ELEMENT (element));
1614
1615   pending = GST_STATE_PENDING (element);
1616
1617   if (pending != GST_STATE_VOID_PENDING && !GST_STATE_ERROR (element)) {
1618 #ifndef GST_DISABLE_GST_DEBUG
1619     GstElementState old_state = GST_STATE (element);
1620 #endif
1621
1622     GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1623         "aborting state from %s to %s", gst_element_state_get_name (old_state),
1624         gst_element_state_get_name (pending));
1625
1626     /* flag error */
1627     GST_STATE_ERROR (element) = TRUE;
1628
1629     GST_STATE_BROADCAST (element);
1630   }
1631 }
1632
1633 /**
1634  * gst_element_commit_state:
1635  * @element: a #GstElement to commit the state of.
1636  *
1637  * Commit the state change of the element. This function is used
1638  * by elements that do asynchronous state changes.
1639  *
1640  * This function can only be called with the STATE_LOCK held.
1641  *
1642  * MT safe.
1643  */
1644 void
1645 gst_element_commit_state (GstElement * element)
1646 {
1647   GstElementState pending;
1648   GstMessage *message;
1649
1650   g_return_if_fail (GST_IS_ELEMENT (element));
1651
1652   pending = GST_STATE_PENDING (element);
1653
1654   if (pending != GST_STATE_VOID_PENDING) {
1655     GstElementState old_state = GST_STATE (element);
1656
1657     GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1658         "commiting state from %s to %s", gst_element_state_get_name (old_state),
1659         gst_element_state_get_name (pending));
1660
1661     GST_STATE (element) = pending;
1662     GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING;
1663     GST_STATE_ERROR (element) = FALSE;
1664
1665     g_signal_emit (G_OBJECT (element), gst_element_signals[STATE_CHANGE],
1666         0, old_state, pending);
1667     message = gst_message_new_state_changed (GST_OBJECT (element),
1668         old_state, pending);
1669     gst_element_post_message (element, message);
1670     GST_STATE_BROADCAST (element);
1671   }
1672 }
1673
1674 /**
1675  * gst_element_lost_state:
1676  * @element: a #GstElement the state is lost of
1677  *
1678  * Brings the element to the lost state. The current state of the
1679  * element is copied to the pending state so that any call to
1680  * #gst_element_get_state() will return ASYNC.
1681  * This is mostly used for elements that lost their preroll buffer
1682  * in the PAUSED state after a flush, they become PAUSED again
1683  * if a new preroll buffer is queued.
1684  * This function can only be called when the element is currently
1685  * not in error or an async state change.
1686  *
1687  * This function can only be called with the STATE_LOCK held.
1688  *
1689  * MT safe.
1690  */
1691 void
1692 gst_element_lost_state (GstElement * element)
1693 {
1694   g_return_if_fail (GST_IS_ELEMENT (element));
1695
1696   if (GST_STATE_PENDING (element) == GST_STATE_VOID_PENDING &&
1697       !GST_STATE_ERROR (element)) {
1698     GstElementState current_state = GST_STATE (element);
1699
1700     GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1701         "lost state of %s", gst_element_state_get_name (current_state));
1702
1703     GST_STATE_PENDING (element) = current_state;
1704     GST_STATE_ERROR (element) = FALSE;
1705   }
1706 }
1707
1708 /**
1709  * gst_element_set_state:
1710  * @element: a #GstElement to change state of.
1711  * @state: the element's new #GstElementState.
1712  *
1713  * Sets the state of the element. This function will try to set the
1714  * requested state by going through all the intermediary states and calling
1715  * the class's state change function for each.
1716  *
1717  * Returns: Result of the state change using #GstElementStateReturn.
1718  *
1719  * MT safe.
1720  */
1721 GstElementStateReturn
1722 gst_element_set_state (GstElement * element, GstElementState state)
1723 {
1724   GstElementClass *oclass;
1725   GstElementState current;
1726   GstElementStateReturn return_val = GST_STATE_SUCCESS;
1727   GstElementStateReturn ret;
1728   GstElementState pending;
1729   GTimeVal tv;
1730
1731
1732   /* get current element state,  need to call the method so that
1733    * we call the virtual method and subclasses can implement their
1734    * own algorithms */
1735   GST_TIME_TO_TIMEVAL (0, tv);
1736   ret = gst_element_get_state (element, &current, &pending, &tv);
1737
1738   /* get the element state lock */
1739   GST_STATE_LOCK (element);
1740   /* this is the state we should go to */
1741   GST_STATE_FINAL (element) = state;
1742   if (ret == GST_STATE_ASYNC) {
1743     gst_element_commit_state (element);
1744   }
1745
1746   /* start with the current state */
1747   current = GST_STATE (element);
1748
1749   GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "setting state from %s to %s",
1750       gst_element_state_get_name (current), gst_element_state_get_name (state));
1751
1752   oclass = GST_ELEMENT_GET_CLASS (element);
1753
1754   /* We always perform at least one state change, even if the 
1755    * current state is equal to the required state. This is needed
1756    * for bins that sync their children. */
1757   do {
1758     GstElementState pending;
1759
1760     /* calculate the pending state */
1761     if (current < state)
1762       pending = current << 1;
1763     else if (current > state)
1764       pending = current >> 1;
1765     else
1766       pending = current;
1767
1768     /* set the pending state variable */
1769     GST_STATE_PENDING (element) = pending;
1770
1771     GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1772         "%s: setting state from %s to %s",
1773         (pending != state ? "intermediate" : "final"),
1774         gst_element_state_get_name (current),
1775         gst_element_state_get_name (pending));
1776
1777     /* call the state change function so it can set the state */
1778     if (oclass->change_state)
1779       return_val = (oclass->change_state) (element);
1780     else
1781       return_val = GST_STATE_FAILURE;
1782
1783     /* clear the error and preroll flag, we need to do that after
1784      * calling the virtual change_state function so that it can use the
1785      * old previous value. */
1786     GST_STATE_ERROR (element) = FALSE;
1787     GST_STATE_NO_PREROLL (element) = FALSE;
1788
1789     switch (return_val) {
1790       case GST_STATE_FAILURE:
1791         GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1792             "have failed change_state return");
1793         /* state change failure exits the loop */
1794         gst_element_abort_state (element);
1795         goto exit;
1796       case GST_STATE_ASYNC:
1797         GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1798             "element will change state async");
1799         /* an async state change exits the loop, we can only
1800          * go to the next state change when this one completes. */
1801         goto exit;
1802       case GST_STATE_SUCCESS:
1803         GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1804             "element changed state successfuly");
1805         /* we can commit the state now and proceed to the next state */
1806         gst_element_commit_state (element);
1807         GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "commited state");
1808         break;
1809       case GST_STATE_NO_PREROLL:
1810         GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1811             "element changed state successfuly and can't preroll");
1812         /* we can commit the state now and proceed to the next state */
1813         gst_element_commit_state (element);
1814         GST_STATE_NO_PREROLL (element) = TRUE;
1815         GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "commited state");
1816         break;
1817       default:
1818         goto invalid_return;
1819     }
1820     /* get the current state of the element and see if we need to do more
1821      * state changes */
1822     current = GST_STATE (element);
1823   }
1824   while (current != state);
1825
1826 exit:
1827   GST_STATE_FINAL (element) = GST_STATE_VOID_PENDING;
1828   GST_STATE_UNLOCK (element);
1829
1830   GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "exit state change");
1831
1832   return return_val;
1833
1834   /* ERROR */
1835 invalid_return:
1836   {
1837     GST_STATE_FINAL (element) = GST_STATE_VOID_PENDING;
1838     GST_STATE_UNLOCK (element);
1839     /* somebody added a GST_STATE_ and forgot to do stuff here ! */
1840     g_critical ("unknown return value %d from a state change function",
1841         return_val);
1842     return GST_STATE_FAILURE;
1843   }
1844 }
1845
1846 /* gst_iterator_fold functions for pads_activate */
1847
1848 static gboolean
1849 activate_pads (GstPad * pad, GValue * ret, gboolean * active)
1850 {
1851   if (!gst_pad_set_active (pad, *active))
1852     g_value_set_boolean (ret, FALSE);
1853
1854   gst_object_unref (pad);
1855   return TRUE;
1856 }
1857
1858 /* returns false on error or early cutout of the fold, true otherwise */
1859 static gboolean
1860 iterator_fold_with_resync (GstIterator * iter, GstIteratorFoldFunction func,
1861     GValue * ret, gpointer user_data)
1862 {
1863   GstIteratorResult ires;
1864   gboolean res = TRUE;
1865
1866   while (1) {
1867     ires = gst_iterator_fold (iter, func, ret, user_data);
1868
1869     switch (ires) {
1870       case GST_ITERATOR_RESYNC:
1871         break;
1872       case GST_ITERATOR_DONE:
1873         res = TRUE;
1874         goto done;
1875       default:
1876         res = FALSE;
1877         goto done;
1878     }
1879   }
1880
1881 done:
1882   return res;
1883 }
1884
1885 /* is called with STATE_LOCK
1886  */
1887 static gboolean
1888 gst_element_pads_activate (GstElement * element, gboolean active)
1889 {
1890   GValue ret = { 0, };
1891   GstIterator *iter;
1892   gboolean fold_ok;
1893
1894   /* no need to unset this later, it's just a boolean */
1895   g_value_init (&ret, G_TYPE_BOOLEAN);
1896   g_value_set_boolean (&ret, TRUE);
1897
1898   iter = gst_element_iterate_src_pads (element);
1899   fold_ok = iterator_fold_with_resync
1900       (iter, (GstIteratorFoldFunction) activate_pads, &ret, &active);
1901   gst_iterator_free (iter);
1902   if (!fold_ok || !g_value_get_boolean (&ret))
1903     return FALSE;
1904
1905   iter = gst_element_iterate_sink_pads (element);
1906   fold_ok = iterator_fold_with_resync
1907       (iter, (GstIteratorFoldFunction) activate_pads, &ret, &active);
1908   gst_iterator_free (iter);
1909   if (!fold_ok || !g_value_get_boolean (&ret))
1910     return FALSE;
1911
1912   return TRUE;
1913 }
1914
1915 /* is called with STATE_LOCK */
1916 static GstElementStateReturn
1917 gst_element_change_state (GstElement * element)
1918 {
1919   GstElementState old_state;
1920   gint old_pending, old_transition;
1921   GstElementStateReturn result = GST_STATE_SUCCESS;
1922
1923   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
1924
1925   old_state = GST_STATE (element);
1926   old_pending = GST_STATE_PENDING (element);
1927   old_transition = GST_STATE_TRANSITION (element);
1928
1929   /* if the element already is in the given state, we just return success */
1930   if (old_pending == GST_STATE_VOID_PENDING ||
1931       old_state == GST_STATE_PENDING (element)) {
1932     GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1933         "element is already in the %s state",
1934         gst_element_state_get_name (old_state));
1935     if (GST_STATE_NO_PREROLL (element))
1936       return GST_STATE_NO_PREROLL;
1937     else
1938       return GST_STATE_SUCCESS;
1939   }
1940
1941   GST_CAT_LOG_OBJECT (GST_CAT_STATES, element,
1942       "default handler tries setting state from %s to %s (%04x)",
1943       gst_element_state_get_name (old_state),
1944       gst_element_state_get_name (old_pending), old_transition);
1945
1946   switch (old_transition) {
1947     case GST_STATE_NULL_TO_READY:
1948       break;
1949     case GST_STATE_READY_TO_PAUSED:
1950       if (!gst_element_pads_activate (element, TRUE)) {
1951         result = GST_STATE_FAILURE;
1952       }
1953       break;
1954     case GST_STATE_PAUSED_TO_PLAYING:
1955       GST_LOCK (element);
1956       if (GST_ELEMENT_MANAGER (element)) {
1957         element->base_time =
1958             GST_ELEMENT_CAST (GST_ELEMENT_MANAGER (element))->base_time;
1959       }
1960       GST_UNLOCK (element);
1961       break;
1962     case GST_STATE_PLAYING_TO_PAUSED:
1963       break;
1964     case GST_STATE_PAUSED_TO_READY:
1965     case GST_STATE_READY_TO_NULL:
1966       /* deactivate pads in both cases, since they are activated on
1967          ready->paused but the element might not have made it to paused */
1968       if (!gst_element_pads_activate (element, FALSE)) {
1969         result = GST_STATE_FAILURE;
1970       } else {
1971         element->base_time = 0;
1972       }
1973       break;
1974     default:
1975       /* this will catch real but unhandled state changes;
1976        * can only be caused by:
1977        * - a new state was added
1978        * - somehow the element was asked to jump across an intermediate state
1979        */
1980       g_warning ("Unhandled state change from %s to %s",
1981           gst_element_state_get_name (old_state),
1982           gst_element_state_get_name (old_pending));
1983       break;
1984   }
1985
1986   return result;
1987 }
1988
1989 /**
1990  * gst_element_get_factory:
1991  * @element: a #GstElement to request the element factory of.
1992  *
1993  * Retrieves the factory that was used to create this element.
1994  *
1995  * Returns: the #GstElementFactory used for creating this element.
1996  */
1997 GstElementFactory *
1998 gst_element_get_factory (GstElement * element)
1999 {
2000   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
2001
2002   return GST_ELEMENT_GET_CLASS (element)->elementfactory;
2003 }
2004
2005 static void
2006 gst_element_dispose (GObject * object)
2007 {
2008   GstElement *element = GST_ELEMENT (object);
2009
2010   GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "dispose");
2011
2012   /* ref so we don't hit 0 again */
2013   gst_object_ref (object);
2014
2015   /* first we break all our links with the ouside */
2016   while (element->pads) {
2017     gst_element_remove_pad (element, GST_PAD (element->pads->data));
2018   }
2019   if (G_UNLIKELY (element->pads != 0)) {
2020     g_critical ("could not remove pads from element %s",
2021         GST_STR_NULL (GST_OBJECT_NAME (object)));
2022   }
2023
2024   GST_LOCK (element);
2025   gst_object_replace ((GstObject **) & element->manager, NULL);
2026   gst_object_replace ((GstObject **) & element->clock, NULL);
2027   GST_UNLOCK (element);
2028
2029   GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "dispose parent");
2030
2031   G_OBJECT_CLASS (parent_class)->dispose (object);
2032 }
2033
2034 static void
2035 gst_element_finalize (GObject * object)
2036 {
2037   GstElement *element = GST_ELEMENT (object);
2038
2039   GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "finalize");
2040
2041   GST_STATE_LOCK (element);
2042   if (element->state_cond)
2043     g_cond_free (element->state_cond);
2044   element->state_cond = NULL;
2045   GST_STATE_UNLOCK (element);
2046   g_mutex_free (element->state_lock);
2047
2048   GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "finalize parent");
2049
2050   G_OBJECT_CLASS (parent_class)->finalize (object);
2051 }
2052
2053 #ifndef GST_DISABLE_LOADSAVE
2054 /**
2055  * gst_element_save_thyself:
2056  * @element: a #GstElement to save.
2057  * @parent: the xml parent node.
2058  *
2059  * Saves the element as part of the given XML structure.
2060  *
2061  * Returns: the new #xmlNodePtr.
2062  */
2063 static xmlNodePtr
2064 gst_element_save_thyself (GstObject * object, xmlNodePtr parent)
2065 {
2066   GList *pads;
2067   GstElementClass *oclass;
2068   GParamSpec **specs, *spec;
2069   guint nspecs;
2070   gint i;
2071   GValue value = { 0, };
2072   GstElement *element;
2073
2074   g_return_val_if_fail (GST_IS_ELEMENT (object), parent);
2075
2076   element = GST_ELEMENT (object);
2077
2078   oclass = GST_ELEMENT_GET_CLASS (element);
2079
2080   xmlNewChild (parent, NULL, (xmlChar *) "name",
2081       (xmlChar *) GST_ELEMENT_NAME (element));
2082
2083   if (oclass->elementfactory != NULL) {
2084     GstElementFactory *factory = (GstElementFactory *) oclass->elementfactory;
2085
2086     xmlNewChild (parent, NULL, (xmlChar *) "type",
2087         (xmlChar *) GST_PLUGIN_FEATURE (factory)->name);
2088   }
2089
2090 /* FIXME: what is this? */
2091 /*  if (element->manager) */
2092 /*    xmlNewChild(parent, NULL, "manager", GST_ELEMENT_NAME(element->manager)); */
2093
2094   /* params */
2095   specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (object), &nspecs);
2096
2097   for (i = 0; i < nspecs; i++) {
2098     spec = specs[i];
2099     if (spec->flags & G_PARAM_READABLE) {
2100       xmlNodePtr param;
2101       char *contents;
2102
2103       g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (spec));
2104
2105       g_object_get_property (G_OBJECT (element), spec->name, &value);
2106       param = xmlNewChild (parent, NULL, (xmlChar *) "param", NULL);
2107       xmlNewChild (param, NULL, (xmlChar *) "name", (xmlChar *) spec->name);
2108
2109       if (G_IS_PARAM_SPEC_STRING (spec))
2110         contents = g_value_dup_string (&value);
2111       else if (G_IS_PARAM_SPEC_ENUM (spec))
2112         contents = g_strdup_printf ("%d", g_value_get_enum (&value));
2113       else if (G_IS_PARAM_SPEC_INT64 (spec))
2114         contents = g_strdup_printf ("%" G_GINT64_FORMAT,
2115             g_value_get_int64 (&value));
2116       else
2117         contents = g_strdup_value_contents (&value);
2118
2119       xmlNewChild (param, NULL, (xmlChar *) "value", (xmlChar *) contents);
2120       g_free (contents);
2121
2122       g_value_unset (&value);
2123     }
2124   }
2125
2126   pads = GST_ELEMENT_PADS (element);
2127
2128   while (pads) {
2129     GstPad *pad = GST_PAD (pads->data);
2130
2131     /* figure out if it's a direct pad or a ghostpad */
2132     if (GST_ELEMENT (GST_OBJECT_PARENT (pad)) == element) {
2133       xmlNodePtr padtag = xmlNewChild (parent, NULL, (xmlChar *) "pad", NULL);
2134
2135       gst_object_save_thyself (GST_OBJECT (pad), padtag);
2136     }
2137     pads = g_list_next (pads);
2138   }
2139
2140   return parent;
2141 }
2142
2143 static void
2144 gst_element_restore_thyself (GstObject * object, xmlNodePtr self)
2145 {
2146   xmlNodePtr children;
2147   GstElement *element;
2148   gchar *name = NULL;
2149   gchar *value = NULL;
2150
2151   element = GST_ELEMENT (object);
2152   g_return_if_fail (element != NULL);
2153
2154   /* parameters */
2155   children = self->xmlChildrenNode;
2156   while (children) {
2157     if (!strcmp ((char *) children->name, "param")) {
2158       xmlNodePtr child = children->xmlChildrenNode;
2159
2160       while (child) {
2161         if (!strcmp ((char *) child->name, "name")) {
2162           name = (gchar *) xmlNodeGetContent (child);
2163         } else if (!strcmp ((char *) child->name, "value")) {
2164           value = (gchar *) xmlNodeGetContent (child);
2165         }
2166         child = child->next;
2167       }
2168       /* FIXME: can this just be g_object_set ? */
2169       gst_util_set_object_arg (G_OBJECT (element), name, value);
2170       /* g_object_set (G_OBJECT (element), name, value, NULL); */
2171       g_free (name);
2172       g_free (value);
2173     }
2174     children = children->next;
2175   }
2176
2177   /* pads */
2178   children = self->xmlChildrenNode;
2179   while (children) {
2180     if (!strcmp ((char *) children->name, "pad")) {
2181       gst_pad_load_and_link (children, GST_OBJECT (element));
2182     }
2183     children = children->next;
2184   }
2185
2186   if (GST_OBJECT_CLASS (parent_class)->restore_thyself)
2187     (GST_OBJECT_CLASS (parent_class)->restore_thyself) (object, self);
2188 }
2189 #endif /* GST_DISABLE_LOADSAVE */
2190
2191 static void
2192 gst_element_set_manager_func (GstElement * element, GstPipeline * manager)
2193 {
2194   g_return_if_fail (GST_IS_ELEMENT (element));
2195
2196   GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, element, "setting manager to %p",
2197       manager);
2198
2199   /* setting the manager cannot increase the refcount */
2200   GST_LOCK (element);
2201   GST_ELEMENT_MANAGER (element) = manager;
2202   GST_UNLOCK (element);
2203 }
2204
2205 static void
2206 gst_element_set_bus_func (GstElement * element, GstBus * bus)
2207 {
2208   g_return_if_fail (GST_IS_ELEMENT (element));
2209
2210   GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, element, "setting bus to %p", bus);
2211
2212   GST_LOCK (element);
2213   gst_object_replace ((GstObject **) & GST_ELEMENT_BUS (element),
2214       GST_OBJECT (bus));
2215   GST_UNLOCK (element);
2216 }
2217
2218 static void
2219 gst_element_set_scheduler_func (GstElement * element, GstScheduler * scheduler)
2220 {
2221   g_return_if_fail (GST_IS_ELEMENT (element));
2222
2223   GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, element, "setting scheduler to %p",
2224       scheduler);
2225
2226   GST_LOCK (element);
2227   gst_object_replace ((GstObject **) & GST_ELEMENT_SCHEDULER (element),
2228       GST_OBJECT (scheduler));
2229   GST_UNLOCK (element);
2230 }
2231
2232 /**
2233  * gst_element_set_manager:
2234  * @element: a #GstElement to set the manager of.
2235  * @manager: the #GstManager to set.
2236  *
2237  * Sets the manager of the element.  For internal use only, unless you're
2238  * writing a new bin subclass.
2239  *
2240  * MT safe.
2241  */
2242 void
2243 gst_element_set_manager (GstElement * element, GstPipeline * manager)
2244 {
2245   GstElementClass *oclass;
2246
2247   g_return_if_fail (GST_IS_ELEMENT (element));
2248
2249   oclass = GST_ELEMENT_GET_CLASS (element);
2250
2251   if (oclass->set_manager)
2252     oclass->set_manager (element, manager);
2253 }
2254
2255
2256 /**
2257  * gst_element_get_manager:
2258  * @element: a #GstElement to get the manager of.
2259  *
2260  * Returns the manager of the element.
2261  *
2262  * Returns: the element's #GstPipeline. unref after usage.
2263  *
2264  * MT safe.
2265  */
2266 GstPipeline *
2267 gst_element_get_manager (GstElement * element)
2268 {
2269   GstPipeline *result = NULL;
2270
2271   g_return_val_if_fail (GST_IS_ELEMENT (element), result);
2272
2273   GST_LOCK (element);
2274   result = GST_ELEMENT_MANAGER (element);
2275   gst_object_ref (result);
2276   GST_UNLOCK (element);
2277
2278   return result;
2279 }
2280
2281 /**
2282  * gst_element_set_bus:
2283  * @element: a #GstElement to set the bus of.
2284  * @bus: the #GstBus to set.
2285  *
2286  * Sets the bus of the element.  For internal use only, unless you're
2287  * testing elements.
2288  *
2289  * MT safe.
2290  */
2291 void
2292 gst_element_set_bus (GstElement * element, GstBus * bus)
2293 {
2294   GstElementClass *oclass;
2295
2296   g_return_if_fail (GST_IS_ELEMENT (element));
2297
2298   oclass = GST_ELEMENT_GET_CLASS (element);
2299
2300   if (oclass->set_bus)
2301     oclass->set_bus (element, bus);
2302 }
2303
2304 /**
2305  * gst_element_get_bus:
2306  * @element: a #GstElement to get the bus of.
2307  *
2308  * Returns the bus of the element.
2309  *
2310  * Returns: the element's #GstBus.
2311  *
2312  * MT safe.
2313  */
2314 GstBus *
2315 gst_element_get_bus (GstElement * element)
2316 {
2317   GstBus *result = NULL;
2318
2319   g_return_val_if_fail (GST_IS_ELEMENT (element), result);
2320
2321   GST_LOCK (element);
2322   result = GST_ELEMENT_BUS (element);
2323   GST_UNLOCK (element);
2324
2325   return result;
2326 }
2327
2328 /**
2329  * gst_element_set_scheduler:
2330  * @element: a #GstElement to set the scheduler of.
2331  * @scheduler: the #GstScheduler to set.
2332  *
2333  * Sets the scheduler of the element.  For internal use only, unless you're
2334  * testing elements.
2335  *
2336  * MT safe.
2337  */
2338 void
2339 gst_element_set_scheduler (GstElement * element, GstScheduler * scheduler)
2340 {
2341   GstElementClass *oclass;
2342
2343   g_return_if_fail (GST_IS_ELEMENT (element));
2344
2345   oclass = GST_ELEMENT_GET_CLASS (element);
2346
2347   if (oclass->set_scheduler)
2348     oclass->set_scheduler (element, scheduler);
2349 }
2350
2351 /**
2352  * gst_element_get_scheduler:
2353  * @element: a #GstElement to get the scheduler of.
2354  *
2355  * Returns the scheduler of the element.
2356  *
2357  * Returns: the element's #GstScheduler.
2358  *
2359  * MT safe.
2360  */
2361 GstScheduler *
2362 gst_element_get_scheduler (GstElement * element)
2363 {
2364   GstScheduler *result = NULL;
2365
2366   g_return_val_if_fail (GST_IS_ELEMENT (element), result);
2367
2368   GST_LOCK (element);
2369   result = GST_ELEMENT_SCHEDULER (element);
2370   GST_UNLOCK (element);
2371
2372   return result;
2373 }