fix refcounting of warning and error messages
[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  * @query: the #GstQuery.
1181  *
1182  * Performs a query on the given element. If the format is set
1183  * to GST_FORMAT_DEFAULT and this function returns TRUE, the
1184  * format pointer will hold the default format.
1185  * For element that don't implement a query handler, this function
1186  * forwards the query to a random usable sinkpad of this element.
1187  *
1188  * Returns: TRUE if the query could be performed.
1189  *
1190  * MT safe.
1191  */
1192 gboolean
1193 gst_element_query (GstElement * element, GstQuery * query)
1194 {
1195   GstElementClass *oclass;
1196   gboolean result = FALSE;
1197
1198   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1199   g_return_val_if_fail (query != NULL, FALSE);
1200
1201   oclass = GST_ELEMENT_GET_CLASS (element);
1202
1203   if (oclass->query) {
1204     result = oclass->query (element, query);
1205   } else {
1206     GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SRC);
1207
1208     if (pad) {
1209       result = gst_pad_query (pad, query);
1210
1211       gst_object_unref (pad);
1212     } else {
1213       pad = gst_element_get_random_pad (element, GST_PAD_SINK);
1214       if (pad) {
1215         GstPad *peer = gst_pad_get_peer (pad);
1216
1217         if (peer) {
1218           result = gst_pad_query (peer, query);
1219
1220           gst_object_unref (peer);
1221         }
1222         gst_object_unref (pad);
1223       }
1224     }
1225   }
1226   return result;
1227 }
1228
1229 /**
1230  * gst_element_post_message:
1231  * @element: a #GstElement posting the message
1232  * @message: a #GstMessage to post
1233  *
1234  * Post a message on the element's #GstBus.
1235  *
1236  * Returns: TRUE if the message was successfully posted.
1237  *
1238  * MT safe.
1239  */
1240 gboolean
1241 gst_element_post_message (GstElement * element, GstMessage * message)
1242 {
1243   GstBus *bus;
1244   gboolean result = FALSE;
1245
1246   GST_DEBUG ("posting message %p ...", message);
1247
1248   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1249   g_return_val_if_fail (message != NULL, FALSE);
1250
1251   GST_LOCK (element);
1252   bus = element->bus;
1253
1254   if (G_UNLIKELY (bus == NULL)) {
1255     GST_DEBUG ("... but I won't because I have no bus");
1256     GST_UNLOCK (element);
1257     gst_message_unref (message);
1258     return FALSE;
1259   }
1260   gst_object_ref (bus);
1261   GST_DEBUG ("... on bus %" GST_PTR_FORMAT, bus);
1262   GST_UNLOCK (element);
1263
1264   result = gst_bus_post (bus, message);
1265   gst_object_unref (bus);
1266
1267   return result;
1268 }
1269
1270 /**
1271  * _gst_element_error_printf:
1272  * @format: the printf-like format to use, or NULL
1273  *
1274  * This function is only used internally by the #gst_element_error macro.
1275  *
1276  * Returns: a newly allocated string, or NULL if the format was NULL or ""
1277  *
1278  * MT safe.
1279  */
1280 gchar *
1281 _gst_element_error_printf (const gchar * format, ...)
1282 {
1283   va_list args;
1284   gchar *buffer;
1285
1286   if (format == NULL)
1287     return NULL;
1288   if (format[0] == 0)
1289     return NULL;
1290
1291   va_start (args, format);
1292   buffer = g_strdup_vprintf (format, args);
1293   va_end (args);
1294   return buffer;
1295 }
1296
1297 /**
1298  * gst_element_message_full:
1299  * @element:  a #GstElement to send message from
1300  * @type:     the #GstMessageType
1301  * @domain:   the GStreamer GError domain this message belongs to
1302  * @code:     the GError code belonging to the domain
1303  * @text:     an allocated text string to be used as a replacement for the
1304  *            default message connected to code, or NULL
1305  * @debug:    an allocated debug message to be used as a replacement for the
1306  *            default debugging information, or NULL
1307  * @file:     the source code file where the error was generated
1308  * @function: the source code function where the error was generated
1309  * @line:     the source code line where the error was generated
1310  *
1311  * Post an error or warning message on the bus from inside an element.
1312  *
1313  * MT safe.
1314  */
1315 void gst_element_message_full
1316     (GstElement * element, GstMessageType type,
1317     GQuark domain, gint code, gchar * text,
1318     gchar * debug, const gchar * file, const gchar * function, gint line)
1319 {
1320   GError *gerror = NULL;
1321   gchar *name;
1322   gchar *sent_text;
1323   gchar *sent_debug;
1324   GstMessage *message = NULL;
1325
1326   /* checks */
1327   GST_DEBUG ("start");
1328   g_return_if_fail (GST_IS_ELEMENT (element));
1329   g_return_if_fail ((type == GST_MESSAGE_ERROR) ||
1330       (type == GST_MESSAGE_WARNING));
1331
1332   /* check if we send the given text or the default error text */
1333   if ((text == NULL) || (text[0] == 0)) {
1334     /* text could have come from g_strdup_printf (""); */
1335     g_free (text);
1336     sent_text = gst_error_get_message (domain, code);
1337   } else
1338     sent_text = text;
1339
1340   /* construct a sent_debug with extra information from source */
1341   if ((debug == NULL) || (debug[0] == 0)) {
1342     /* debug could have come from g_strdup_printf (""); */
1343     sent_debug = NULL;
1344   } else {
1345     name = gst_object_get_path_string (GST_OBJECT (element));
1346     sent_debug = g_strdup_printf ("%s(%d): %s: %s:\n%s",
1347         file, line, function, name, debug ? debug : "");
1348     g_free (name);
1349   }
1350   g_free (debug);
1351
1352   /* create gerror and post message */
1353   GST_CAT_INFO_OBJECT (GST_CAT_ERROR_SYSTEM, element, "posting message: %s",
1354       sent_text);
1355   gerror = g_error_new_literal (domain, code, sent_text);
1356
1357   if (type == GST_MESSAGE_ERROR) {
1358     message = gst_message_new_error (GST_OBJECT (element), gerror, sent_debug);
1359   } else if (type == GST_MESSAGE_WARNING) {
1360     message = gst_message_new_warning (GST_OBJECT (element), gerror,
1361         sent_debug);
1362   } else {
1363     g_assert_not_reached ();
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_error_free (gerror);
1372   g_free (sent_debug);
1373   g_free (sent_text);
1374 }
1375
1376 /**
1377  * gst_element_is_locked_state:
1378  * @element: a #GstElement.
1379  *
1380  * Checks if the state of an element is locked.
1381  * If the state of an element is locked, state changes of the parent don't
1382  * affect the element.
1383  * This way you can leave currently unused elements inside bins. Just lock their
1384  * state before changing the state from #GST_STATE_NULL.
1385  *
1386  * Returns: TRUE, if the element's state is locked.
1387  *
1388  * MT safe.
1389  */
1390 gboolean
1391 gst_element_is_locked_state (GstElement * element)
1392 {
1393   gboolean result = FALSE;
1394
1395   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1396
1397   GST_LOCK (element);
1398   result = GST_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
1399   GST_UNLOCK (element);
1400
1401   return result;
1402 }
1403
1404 /**
1405  * gst_element_set_locked_state:
1406  * @element: a #GstElement
1407  * @locked_state: TRUE to lock the element's state
1408  *
1409  * Locks the state of an element, so state changes of the parent don't affect
1410  * this element anymore.
1411  *
1412  * Returns: TRUE if the state was changed, FALSE if bad params were given or
1413  * the element was already in the correct state.
1414  *
1415  * MT safe.
1416  */
1417 gboolean
1418 gst_element_set_locked_state (GstElement * element, gboolean locked_state)
1419 {
1420   gboolean old;
1421
1422   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1423
1424   GST_LOCK (element);
1425   old = GST_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
1426
1427   if (G_UNLIKELY (old == locked_state))
1428     goto was_ok;
1429
1430   if (locked_state) {
1431     GST_CAT_DEBUG (GST_CAT_STATES, "locking state of element %s",
1432         GST_ELEMENT_NAME (element));
1433     GST_FLAG_SET (element, GST_ELEMENT_LOCKED_STATE);
1434   } else {
1435     GST_CAT_DEBUG (GST_CAT_STATES, "unlocking state of element %s",
1436         GST_ELEMENT_NAME (element));
1437     GST_FLAG_UNSET (element, GST_ELEMENT_LOCKED_STATE);
1438   }
1439   GST_UNLOCK (element);
1440
1441   return TRUE;
1442
1443 was_ok:
1444   GST_UNLOCK (element);
1445
1446   return FALSE;
1447 }
1448
1449 /**
1450  * gst_element_sync_state_with_parent:
1451  * @element: a #GstElement.
1452  *
1453  * Tries to change the state of the element to the same as its parent.
1454  * If this function returns FALSE, the state of element is undefined.
1455  *
1456  * Returns: TRUE, if the element's state could be synced to the parent's state.
1457  */
1458 gboolean
1459 gst_element_sync_state_with_parent (GstElement * element)
1460 {
1461   GstElement *parent;
1462
1463   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1464   parent = GST_ELEMENT (GST_ELEMENT_PARENT (element));
1465   g_return_val_if_fail (GST_IS_BIN (parent), FALSE);
1466
1467   GST_CAT_DEBUG (GST_CAT_STATES, "syncing state of element %s (%s) to %s (%s)",
1468       GST_ELEMENT_NAME (element),
1469       gst_element_state_get_name (GST_STATE (element)),
1470       GST_ELEMENT_NAME (parent),
1471       gst_element_state_get_name (GST_STATE (parent)));
1472
1473   if (gst_element_set_state (element, GST_STATE (parent)) == GST_STATE_FAILURE) {
1474     return FALSE;
1475   }
1476   return TRUE;
1477 }
1478
1479 /* MT safe */
1480 static GstElementStateReturn
1481 gst_element_get_state_func (GstElement * element,
1482     GstElementState * state, GstElementState * pending, GTimeVal * timeout)
1483 {
1484   GstElementStateReturn ret = GST_STATE_FAILURE;
1485   GstElementState old_pending;
1486
1487   GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "getting state");
1488
1489   GST_STATE_LOCK (element);
1490   /* we got an error, report immediatly */
1491   if (GST_STATE_NO_PREROLL (element)) {
1492     ret = GST_STATE_NO_PREROLL;
1493     goto done;
1494   }
1495
1496   /* we got an error, report immediatly */
1497   if (GST_STATE_ERROR (element)) {
1498     ret = GST_STATE_FAILURE;
1499     goto done;
1500   }
1501
1502   old_pending = GST_STATE_PENDING (element);
1503   if (old_pending != GST_STATE_VOID_PENDING) {
1504     GTimeVal *timeval, abstimeout;
1505
1506     GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "wait for pending");
1507     if (timeout) {
1508       /* make timeout absolute */
1509       g_get_current_time (&abstimeout);
1510       g_time_val_add (&abstimeout,
1511           timeout->tv_sec * G_USEC_PER_SEC + timeout->tv_usec);
1512       timeval = &abstimeout;
1513     } else {
1514       timeval = NULL;
1515     }
1516     /* we have a pending state change, wait for it to complete */
1517     if (!GST_STATE_TIMED_WAIT (element, timeval)) {
1518       GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "timeout");
1519       /* timeout triggered */
1520       ret = GST_STATE_ASYNC;
1521     } else {
1522       /* could be success or failure */
1523       if (old_pending == GST_STATE (element)) {
1524         GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "got success");
1525         ret = GST_STATE_SUCCESS;
1526       } else {
1527         GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "got failure");
1528         ret = GST_STATE_FAILURE;
1529       }
1530     }
1531   }
1532   /* if nothing is pending anymore we can return SUCCESS */
1533   if (GST_STATE_PENDING (element) == GST_STATE_VOID_PENDING) {
1534     GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "nothing pending");
1535     ret = GST_STATE_SUCCESS;
1536   }
1537
1538 done:
1539   if (state)
1540     *state = GST_STATE (element);
1541   if (pending)
1542     *pending = GST_STATE_PENDING (element);
1543
1544   GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1545       "state current: %s, pending: %s, error: %d, no_preroll: %d, result: %d",
1546       gst_element_state_get_name (GST_STATE (element)),
1547       gst_element_state_get_name (GST_STATE_PENDING (element)),
1548       GST_STATE_ERROR (element), GST_STATE_NO_PREROLL (element), ret);
1549
1550   GST_STATE_UNLOCK (element);
1551
1552   return ret;
1553 }
1554
1555 /**
1556  * gst_element_get_state:
1557  * @element: a #GstElement to get the state of.
1558  * @state: a pointer to #GstElementState to hold the state. Can be NULL.
1559  * @pending: a pointer to #GstElementState to hold the pending state.
1560  *           Can be NULL.
1561  * @timeout: a #GTimeVal to specify the timeout for an async
1562  *           state change or NULL for infinite timeout.
1563  *
1564  * Gets the state of the element. 
1565  *
1566  * For elements that performed an ASYNC state change, as reported by 
1567  * #gst_element_set_state(), this function will block up to the 
1568  * specified timeout value for the state change to complete. 
1569  * If the element completes the state change or goes into
1570  * an error, this function returns immediatly with a return value of
1571  * GST_STATE_SUCCESS or GST_STATE_FAILURE respectively. 
1572  *
1573  * Returns: GST_STATE_SUCCESS if the element has no more pending state and
1574  *          the last state change succeeded, GST_STATE_ASYNC
1575  *          if the element is still performing a state change or 
1576  *          GST_STATE_FAILURE if the last state change failed.
1577  *
1578  * MT safe.
1579  */
1580 GstElementStateReturn
1581 gst_element_get_state (GstElement * element,
1582     GstElementState * state, GstElementState * pending, GTimeVal * timeout)
1583 {
1584   GstElementClass *oclass;
1585   GstElementStateReturn result = GST_STATE_FAILURE;
1586
1587   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
1588
1589   oclass = GST_ELEMENT_GET_CLASS (element);
1590
1591   if (oclass->get_state)
1592     result = (oclass->get_state) (element, state, pending, timeout);
1593
1594   return result;
1595 }
1596
1597 /**
1598  * gst_element_abort_state:
1599  * @element: a #GstElement to abort the state of.
1600  *
1601  * Abort the state change of the element. This function is used
1602  * by elements that do asynchronous state changes and find out 
1603  * something is wrong.
1604  *
1605  * This function should be called with the STATE_LOCK held.
1606  *
1607  * MT safe.
1608  */
1609 void
1610 gst_element_abort_state (GstElement * element)
1611 {
1612   GstElementState pending;
1613
1614   g_return_if_fail (GST_IS_ELEMENT (element));
1615
1616   pending = GST_STATE_PENDING (element);
1617
1618   if (pending != GST_STATE_VOID_PENDING && !GST_STATE_ERROR (element)) {
1619 #ifndef GST_DISABLE_GST_DEBUG
1620     GstElementState old_state = GST_STATE (element);
1621 #endif
1622
1623     GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1624         "aborting state from %s to %s", gst_element_state_get_name (old_state),
1625         gst_element_state_get_name (pending));
1626
1627     /* flag error */
1628     GST_STATE_ERROR (element) = TRUE;
1629
1630     GST_STATE_BROADCAST (element);
1631   }
1632 }
1633
1634 /**
1635  * gst_element_commit_state:
1636  * @element: a #GstElement to commit the state of.
1637  *
1638  * Commit the state change of the element. This function is used
1639  * by elements that do asynchronous state changes.
1640  *
1641  * This function can only be called with the STATE_LOCK held.
1642  *
1643  * MT safe.
1644  */
1645 void
1646 gst_element_commit_state (GstElement * element)
1647 {
1648   GstElementState pending;
1649   GstMessage *message;
1650
1651   g_return_if_fail (GST_IS_ELEMENT (element));
1652
1653   pending = GST_STATE_PENDING (element);
1654
1655   if (pending != GST_STATE_VOID_PENDING) {
1656     GstElementState old_state = GST_STATE (element);
1657
1658     GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1659         "commiting state from %s to %s", gst_element_state_get_name (old_state),
1660         gst_element_state_get_name (pending));
1661
1662     GST_STATE (element) = pending;
1663     GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING;
1664     GST_STATE_ERROR (element) = FALSE;
1665
1666     g_signal_emit (G_OBJECT (element), gst_element_signals[STATE_CHANGE],
1667         0, old_state, pending);
1668     message = gst_message_new_state_changed (GST_OBJECT (element),
1669         old_state, pending);
1670     gst_element_post_message (element, message);
1671     GST_STATE_BROADCAST (element);
1672   }
1673 }
1674
1675 /**
1676  * gst_element_lost_state:
1677  * @element: a #GstElement the state is lost of
1678  *
1679  * Brings the element to the lost state. The current state of the
1680  * element is copied to the pending state so that any call to
1681  * #gst_element_get_state() will return ASYNC.
1682  * This is mostly used for elements that lost their preroll buffer
1683  * in the PAUSED state after a flush, they become PAUSED again
1684  * if a new preroll buffer is queued.
1685  * This function can only be called when the element is currently
1686  * not in error or an async state change.
1687  *
1688  * This function can only be called with the STATE_LOCK held.
1689  *
1690  * MT safe.
1691  */
1692 void
1693 gst_element_lost_state (GstElement * element)
1694 {
1695   g_return_if_fail (GST_IS_ELEMENT (element));
1696
1697   if (GST_STATE_PENDING (element) == GST_STATE_VOID_PENDING &&
1698       !GST_STATE_ERROR (element)) {
1699     GstElementState current_state = GST_STATE (element);
1700
1701     GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1702         "lost state of %s", gst_element_state_get_name (current_state));
1703
1704     GST_STATE_PENDING (element) = current_state;
1705     GST_STATE_ERROR (element) = FALSE;
1706   }
1707 }
1708
1709 /**
1710  * gst_element_set_state:
1711  * @element: a #GstElement to change state of.
1712  * @state: the element's new #GstElementState.
1713  *
1714  * Sets the state of the element. This function will try to set the
1715  * requested state by going through all the intermediary states and calling
1716  * the class's state change function for each.
1717  *
1718  * Returns: Result of the state change using #GstElementStateReturn.
1719  *
1720  * MT safe.
1721  */
1722 GstElementStateReturn
1723 gst_element_set_state (GstElement * element, GstElementState state)
1724 {
1725   GstElementClass *oclass;
1726   GstElementState current;
1727   GstElementStateReturn return_val = GST_STATE_SUCCESS;
1728   GstElementStateReturn ret;
1729   GstElementState pending;
1730   GTimeVal tv;
1731
1732
1733   /* get current element state,  need to call the method so that
1734    * we call the virtual method and subclasses can implement their
1735    * own algorithms */
1736   GST_TIME_TO_TIMEVAL (0, tv);
1737   ret = gst_element_get_state (element, &current, &pending, &tv);
1738
1739   /* get the element state lock */
1740   GST_STATE_LOCK (element);
1741   /* this is the state we should go to */
1742   GST_STATE_FINAL (element) = state;
1743   if (ret == GST_STATE_ASYNC) {
1744     gst_element_commit_state (element);
1745   }
1746
1747   /* start with the current state */
1748   current = GST_STATE (element);
1749
1750   GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "setting state from %s to %s",
1751       gst_element_state_get_name (current), gst_element_state_get_name (state));
1752
1753   oclass = GST_ELEMENT_GET_CLASS (element);
1754
1755   /* We always perform at least one state change, even if the 
1756    * current state is equal to the required state. This is needed
1757    * for bins that sync their children. */
1758   do {
1759     GstElementState pending;
1760
1761     /* calculate the pending state */
1762     if (current < state)
1763       pending = current << 1;
1764     else if (current > state)
1765       pending = current >> 1;
1766     else
1767       pending = current;
1768
1769     /* set the pending state variable */
1770     GST_STATE_PENDING (element) = pending;
1771
1772     GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1773         "%s: setting state from %s to %s",
1774         (pending != state ? "intermediate" : "final"),
1775         gst_element_state_get_name (current),
1776         gst_element_state_get_name (pending));
1777
1778     /* call the state change function so it can set the state */
1779     if (oclass->change_state)
1780       return_val = (oclass->change_state) (element);
1781     else
1782       return_val = GST_STATE_FAILURE;
1783
1784     /* clear the error and preroll flag, we need to do that after
1785      * calling the virtual change_state function so that it can use the
1786      * old previous value. */
1787     GST_STATE_ERROR (element) = FALSE;
1788     GST_STATE_NO_PREROLL (element) = FALSE;
1789
1790     switch (return_val) {
1791       case GST_STATE_FAILURE:
1792         GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1793             "have failed change_state return");
1794         /* state change failure exits the loop */
1795         gst_element_abort_state (element);
1796         goto exit;
1797       case GST_STATE_ASYNC:
1798         GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1799             "element will change state async");
1800         /* an async state change exits the loop, we can only
1801          * go to the next state change when this one completes. */
1802         goto exit;
1803       case GST_STATE_SUCCESS:
1804         GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1805             "element changed state successfully");
1806         /* we can commit the state now and proceed to the next state */
1807         gst_element_commit_state (element);
1808         GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "commited state");
1809         break;
1810       case GST_STATE_NO_PREROLL:
1811         GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1812             "element changed state successfully and can't preroll");
1813         /* we can commit the state now and proceed to the next state */
1814         gst_element_commit_state (element);
1815         GST_STATE_NO_PREROLL (element) = TRUE;
1816         GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "commited state");
1817         break;
1818       default:
1819         goto invalid_return;
1820     }
1821     /* get the current state of the element and see if we need to do more
1822      * state changes */
1823     current = GST_STATE (element);
1824   }
1825   while (current != state);
1826
1827 exit:
1828   GST_STATE_FINAL (element) = GST_STATE_VOID_PENDING;
1829   GST_STATE_UNLOCK (element);
1830
1831   GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "exit state change");
1832
1833   return return_val;
1834
1835   /* ERROR */
1836 invalid_return:
1837   {
1838     GST_STATE_FINAL (element) = GST_STATE_VOID_PENDING;
1839     GST_STATE_UNLOCK (element);
1840     /* somebody added a GST_STATE_ and forgot to do stuff here ! */
1841     g_critical ("unknown return value %d from a state change function",
1842         return_val);
1843     return GST_STATE_FAILURE;
1844   }
1845 }
1846
1847 /* gst_iterator_fold functions for pads_activate */
1848
1849 static gboolean
1850 activate_pads (GstPad * pad, GValue * ret, gboolean * active)
1851 {
1852   if (!gst_pad_set_active (pad, *active))
1853     g_value_set_boolean (ret, FALSE);
1854
1855   gst_object_unref (pad);
1856   return TRUE;
1857 }
1858
1859 /* returns false on error or early cutout of the fold, true otherwise */
1860 static gboolean
1861 iterator_fold_with_resync (GstIterator * iter, GstIteratorFoldFunction func,
1862     GValue * ret, gpointer user_data)
1863 {
1864   GstIteratorResult ires;
1865   gboolean res = TRUE;
1866
1867   while (1) {
1868     ires = gst_iterator_fold (iter, func, ret, user_data);
1869
1870     switch (ires) {
1871       case GST_ITERATOR_RESYNC:
1872         break;
1873       case GST_ITERATOR_DONE:
1874         res = TRUE;
1875         goto done;
1876       default:
1877         res = FALSE;
1878         goto done;
1879     }
1880   }
1881
1882 done:
1883   return res;
1884 }
1885
1886 /* is called with STATE_LOCK
1887  */
1888 static gboolean
1889 gst_element_pads_activate (GstElement * element, gboolean active)
1890 {
1891   GValue ret = { 0, };
1892   GstIterator *iter;
1893   gboolean fold_ok;
1894
1895   /* no need to unset this later, it's just a boolean */
1896   g_value_init (&ret, G_TYPE_BOOLEAN);
1897   g_value_set_boolean (&ret, TRUE);
1898
1899   iter = gst_element_iterate_src_pads (element);
1900   fold_ok = iterator_fold_with_resync
1901       (iter, (GstIteratorFoldFunction) activate_pads, &ret, &active);
1902   gst_iterator_free (iter);
1903   if (!fold_ok || !g_value_get_boolean (&ret))
1904     return FALSE;
1905
1906   iter = gst_element_iterate_sink_pads (element);
1907   fold_ok = iterator_fold_with_resync
1908       (iter, (GstIteratorFoldFunction) activate_pads, &ret, &active);
1909   gst_iterator_free (iter);
1910   if (!fold_ok || !g_value_get_boolean (&ret))
1911     return FALSE;
1912
1913   return TRUE;
1914 }
1915
1916 /* is called with STATE_LOCK */
1917 static GstElementStateReturn
1918 gst_element_change_state (GstElement * element)
1919 {
1920   GstElementState old_state;
1921   gint old_pending, old_transition;
1922   GstElementStateReturn result = GST_STATE_SUCCESS;
1923
1924   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
1925
1926   old_state = GST_STATE (element);
1927   old_pending = GST_STATE_PENDING (element);
1928   old_transition = GST_STATE_TRANSITION (element);
1929
1930   /* if the element already is in the given state, we just return success */
1931   if (old_pending == GST_STATE_VOID_PENDING ||
1932       old_state == GST_STATE_PENDING (element)) {
1933     GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1934         "element is already in the %s state",
1935         gst_element_state_get_name (old_state));
1936     if (GST_STATE_NO_PREROLL (element))
1937       return GST_STATE_NO_PREROLL;
1938     else
1939       return GST_STATE_SUCCESS;
1940   }
1941
1942   GST_CAT_LOG_OBJECT (GST_CAT_STATES, element,
1943       "default handler tries setting state from %s to %s (%04x)",
1944       gst_element_state_get_name (old_state),
1945       gst_element_state_get_name (old_pending), old_transition);
1946
1947   switch (old_transition) {
1948     case GST_STATE_NULL_TO_READY:
1949       break;
1950     case GST_STATE_READY_TO_PAUSED:
1951       if (!gst_element_pads_activate (element, TRUE)) {
1952         result = GST_STATE_FAILURE;
1953       }
1954       break;
1955     case GST_STATE_PAUSED_TO_PLAYING:
1956       GST_LOCK (element);
1957       if (GST_ELEMENT_MANAGER (element)) {
1958         element->base_time =
1959             GST_ELEMENT_CAST (GST_ELEMENT_MANAGER (element))->base_time;
1960       }
1961       GST_UNLOCK (element);
1962       break;
1963     case GST_STATE_PLAYING_TO_PAUSED:
1964       break;
1965     case GST_STATE_PAUSED_TO_READY:
1966     case GST_STATE_READY_TO_NULL:
1967       /* deactivate pads in both cases, since they are activated on
1968          ready->paused but the element might not have made it to paused */
1969       if (!gst_element_pads_activate (element, FALSE)) {
1970         result = GST_STATE_FAILURE;
1971       } else {
1972         element->base_time = 0;
1973       }
1974       break;
1975     default:
1976       /* this will catch real but unhandled state changes;
1977        * can only be caused by:
1978        * - a new state was added
1979        * - somehow the element was asked to jump across an intermediate state
1980        */
1981       g_warning ("Unhandled state change from %s to %s",
1982           gst_element_state_get_name (old_state),
1983           gst_element_state_get_name (old_pending));
1984       break;
1985   }
1986
1987   return result;
1988 }
1989
1990 /**
1991  * gst_element_get_factory:
1992  * @element: a #GstElement to request the element factory of.
1993  *
1994  * Retrieves the factory that was used to create this element.
1995  *
1996  * Returns: the #GstElementFactory used for creating this element.
1997  */
1998 GstElementFactory *
1999 gst_element_get_factory (GstElement * element)
2000 {
2001   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
2002
2003   return GST_ELEMENT_GET_CLASS (element)->elementfactory;
2004 }
2005
2006 static void
2007 gst_element_dispose (GObject * object)
2008 {
2009   GstElement *element = GST_ELEMENT (object);
2010
2011   GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "dispose");
2012
2013   /* ref so we don't hit 0 again */
2014   gst_object_ref (object);
2015
2016   /* first we break all our links with the outside */
2017   while (element->pads) {
2018     gst_element_remove_pad (element, GST_PAD (element->pads->data));
2019   }
2020   if (G_UNLIKELY (element->pads != 0)) {
2021     g_critical ("could not remove pads from element %s",
2022         GST_STR_NULL (GST_OBJECT_NAME (object)));
2023   }
2024
2025   GST_LOCK (element);
2026   gst_object_replace ((GstObject **) & element->manager, NULL);
2027   gst_object_replace ((GstObject **) & element->clock, NULL);
2028   GST_UNLOCK (element);
2029
2030   GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "dispose parent");
2031
2032   G_OBJECT_CLASS (parent_class)->dispose (object);
2033 }
2034
2035 static void
2036 gst_element_finalize (GObject * object)
2037 {
2038   GstElement *element = GST_ELEMENT (object);
2039
2040   GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "finalize");
2041
2042   GST_STATE_LOCK (element);
2043   if (element->state_cond)
2044     g_cond_free (element->state_cond);
2045   element->state_cond = NULL;
2046   GST_STATE_UNLOCK (element);
2047   g_mutex_free (element->state_lock);
2048
2049   GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "finalize parent");
2050
2051   G_OBJECT_CLASS (parent_class)->finalize (object);
2052 }
2053
2054 #ifndef GST_DISABLE_LOADSAVE
2055 /**
2056  * gst_element_save_thyself:
2057  * @element: a #GstElement to save.
2058  * @parent: the xml parent node.
2059  *
2060  * Saves the element as part of the given XML structure.
2061  *
2062  * Returns: the new #xmlNodePtr.
2063  */
2064 static xmlNodePtr
2065 gst_element_save_thyself (GstObject * object, xmlNodePtr parent)
2066 {
2067   GList *pads;
2068   GstElementClass *oclass;
2069   GParamSpec **specs, *spec;
2070   guint nspecs;
2071   gint i;
2072   GValue value = { 0, };
2073   GstElement *element;
2074
2075   g_return_val_if_fail (GST_IS_ELEMENT (object), parent);
2076
2077   element = GST_ELEMENT (object);
2078
2079   oclass = GST_ELEMENT_GET_CLASS (element);
2080
2081   xmlNewChild (parent, NULL, (xmlChar *) "name",
2082       (xmlChar *) GST_ELEMENT_NAME (element));
2083
2084   if (oclass->elementfactory != NULL) {
2085     GstElementFactory *factory = (GstElementFactory *) oclass->elementfactory;
2086
2087     xmlNewChild (parent, NULL, (xmlChar *) "type",
2088         (xmlChar *) GST_PLUGIN_FEATURE (factory)->name);
2089   }
2090
2091 /* FIXME: what is this? */
2092 /*  if (element->manager) */
2093 /*    xmlNewChild(parent, NULL, "manager", GST_ELEMENT_NAME(element->manager)); */
2094
2095   /* params */
2096   specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (object), &nspecs);
2097
2098   for (i = 0; i < nspecs; i++) {
2099     spec = specs[i];
2100     if (spec->flags & G_PARAM_READABLE) {
2101       xmlNodePtr param;
2102       char *contents;
2103
2104       g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (spec));
2105
2106       g_object_get_property (G_OBJECT (element), spec->name, &value);
2107       param = xmlNewChild (parent, NULL, (xmlChar *) "param", NULL);
2108       xmlNewChild (param, NULL, (xmlChar *) "name", (xmlChar *) spec->name);
2109
2110       if (G_IS_PARAM_SPEC_STRING (spec))
2111         contents = g_value_dup_string (&value);
2112       else if (G_IS_PARAM_SPEC_ENUM (spec))
2113         contents = g_strdup_printf ("%d", g_value_get_enum (&value));
2114       else if (G_IS_PARAM_SPEC_INT64 (spec))
2115         contents = g_strdup_printf ("%" G_GINT64_FORMAT,
2116             g_value_get_int64 (&value));
2117       else
2118         contents = g_strdup_value_contents (&value);
2119
2120       xmlNewChild (param, NULL, (xmlChar *) "value", (xmlChar *) contents);
2121       g_free (contents);
2122
2123       g_value_unset (&value);
2124     }
2125   }
2126
2127   pads = GST_ELEMENT_PADS (element);
2128
2129   while (pads) {
2130     GstPad *pad = GST_PAD (pads->data);
2131
2132     /* figure out if it's a direct pad or a ghostpad */
2133     if (GST_ELEMENT (GST_OBJECT_PARENT (pad)) == element) {
2134       xmlNodePtr padtag = xmlNewChild (parent, NULL, (xmlChar *) "pad", NULL);
2135
2136       gst_object_save_thyself (GST_OBJECT (pad), padtag);
2137     }
2138     pads = g_list_next (pads);
2139   }
2140
2141   return parent;
2142 }
2143
2144 static void
2145 gst_element_restore_thyself (GstObject * object, xmlNodePtr self)
2146 {
2147   xmlNodePtr children;
2148   GstElement *element;
2149   gchar *name = NULL;
2150   gchar *value = NULL;
2151
2152   element = GST_ELEMENT (object);
2153   g_return_if_fail (element != NULL);
2154
2155   /* parameters */
2156   children = self->xmlChildrenNode;
2157   while (children) {
2158     if (!strcmp ((char *) children->name, "param")) {
2159       xmlNodePtr child = children->xmlChildrenNode;
2160
2161       while (child) {
2162         if (!strcmp ((char *) child->name, "name")) {
2163           name = (gchar *) xmlNodeGetContent (child);
2164         } else if (!strcmp ((char *) child->name, "value")) {
2165           value = (gchar *) xmlNodeGetContent (child);
2166         }
2167         child = child->next;
2168       }
2169       /* FIXME: can this just be g_object_set ? */
2170       gst_util_set_object_arg (G_OBJECT (element), name, value);
2171       /* g_object_set (G_OBJECT (element), name, value, NULL); */
2172       g_free (name);
2173       g_free (value);
2174     }
2175     children = children->next;
2176   }
2177
2178   /* pads */
2179   children = self->xmlChildrenNode;
2180   while (children) {
2181     if (!strcmp ((char *) children->name, "pad")) {
2182       gst_pad_load_and_link (children, GST_OBJECT (element));
2183     }
2184     children = children->next;
2185   }
2186
2187   if (GST_OBJECT_CLASS (parent_class)->restore_thyself)
2188     (GST_OBJECT_CLASS (parent_class)->restore_thyself) (object, self);
2189 }
2190 #endif /* GST_DISABLE_LOADSAVE */
2191
2192 static void
2193 gst_element_set_manager_func (GstElement * element, GstPipeline * manager)
2194 {
2195   g_return_if_fail (GST_IS_ELEMENT (element));
2196
2197   GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, element, "setting manager to %p",
2198       manager);
2199
2200   /* setting the manager cannot increase the refcount */
2201   GST_LOCK (element);
2202   GST_ELEMENT_MANAGER (element) = manager;
2203   GST_UNLOCK (element);
2204 }
2205
2206 static void
2207 gst_element_set_bus_func (GstElement * element, GstBus * bus)
2208 {
2209   g_return_if_fail (GST_IS_ELEMENT (element));
2210
2211   GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, element, "setting bus to %p", bus);
2212
2213   GST_LOCK (element);
2214   gst_object_replace ((GstObject **) & GST_ELEMENT_BUS (element),
2215       GST_OBJECT (bus));
2216   GST_UNLOCK (element);
2217 }
2218
2219 static void
2220 gst_element_set_scheduler_func (GstElement * element, GstScheduler * scheduler)
2221 {
2222   g_return_if_fail (GST_IS_ELEMENT (element));
2223
2224   GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, element, "setting scheduler to %p",
2225       scheduler);
2226
2227   GST_LOCK (element);
2228   gst_object_replace ((GstObject **) & GST_ELEMENT_SCHEDULER (element),
2229       GST_OBJECT (scheduler));
2230   GST_UNLOCK (element);
2231 }
2232
2233 /**
2234  * gst_element_set_manager:
2235  * @element: a #GstElement to set the manager of.
2236  * @manager: the #GstManager to set.
2237  *
2238  * Sets the manager of the element.  For internal use only, unless you're
2239  * writing a new bin subclass.
2240  *
2241  * MT safe.
2242  */
2243 void
2244 gst_element_set_manager (GstElement * element, GstPipeline * manager)
2245 {
2246   GstElementClass *oclass;
2247
2248   g_return_if_fail (GST_IS_ELEMENT (element));
2249
2250   oclass = GST_ELEMENT_GET_CLASS (element);
2251
2252   if (oclass->set_manager)
2253     oclass->set_manager (element, manager);
2254 }
2255
2256
2257 /**
2258  * gst_element_get_manager:
2259  * @element: a #GstElement to get the manager of.
2260  *
2261  * Returns the manager of the element.
2262  *
2263  * Returns: the element's #GstPipeline. unref after usage.
2264  *
2265  * MT safe.
2266  */
2267 GstPipeline *
2268 gst_element_get_manager (GstElement * element)
2269 {
2270   GstPipeline *result = NULL;
2271
2272   g_return_val_if_fail (GST_IS_ELEMENT (element), result);
2273
2274   GST_LOCK (element);
2275   result = GST_ELEMENT_MANAGER (element);
2276   gst_object_ref (result);
2277   GST_UNLOCK (element);
2278
2279   return result;
2280 }
2281
2282 /**
2283  * gst_element_set_bus:
2284  * @element: a #GstElement to set the bus of.
2285  * @bus: the #GstBus to set.
2286  *
2287  * Sets the bus of the element.  For internal use only, unless you're
2288  * testing elements.
2289  *
2290  * MT safe.
2291  */
2292 void
2293 gst_element_set_bus (GstElement * element, GstBus * bus)
2294 {
2295   GstElementClass *oclass;
2296
2297   g_return_if_fail (GST_IS_ELEMENT (element));
2298
2299   oclass = GST_ELEMENT_GET_CLASS (element);
2300
2301   if (oclass->set_bus)
2302     oclass->set_bus (element, bus);
2303 }
2304
2305 /**
2306  * gst_element_get_bus:
2307  * @element: a #GstElement to get the bus of.
2308  *
2309  * Returns the bus of the element.
2310  *
2311  * Returns: the element's #GstBus. unref after usage.
2312  *
2313  * MT safe.
2314  */
2315 GstBus *
2316 gst_element_get_bus (GstElement * element)
2317 {
2318   GstBus *result = NULL;
2319
2320   g_return_val_if_fail (GST_IS_ELEMENT (element), result);
2321
2322   GST_LOCK (element);
2323   result = GST_ELEMENT_BUS (element);
2324   gst_object_ref (result);
2325   GST_UNLOCK (element);
2326
2327   GST_DEBUG_OBJECT (element, "got bus %" GST_PTR_FORMAT, result);
2328
2329   return result;
2330 }
2331
2332 /**
2333  * gst_element_set_scheduler:
2334  * @element: a #GstElement to set the scheduler of.
2335  * @scheduler: the #GstScheduler to set.
2336  *
2337  * Sets the scheduler of the element.  For internal use only, unless you're
2338  * testing elements.
2339  *
2340  * MT safe.
2341  */
2342 void
2343 gst_element_set_scheduler (GstElement * element, GstScheduler * scheduler)
2344 {
2345   GstElementClass *oclass;
2346
2347   g_return_if_fail (GST_IS_ELEMENT (element));
2348
2349   oclass = GST_ELEMENT_GET_CLASS (element);
2350
2351   if (oclass->set_scheduler)
2352     oclass->set_scheduler (element, scheduler);
2353 }
2354
2355 /**
2356  * gst_element_get_scheduler:
2357  * @element: a #GstElement to get the scheduler of.
2358  *
2359  * Returns the scheduler of the element.
2360  *
2361  * Returns: the element's #GstScheduler.
2362  *
2363  * MT safe.
2364  */
2365 GstScheduler *
2366 gst_element_get_scheduler (GstElement * element)
2367 {
2368   GstScheduler *result = NULL;
2369
2370   g_return_val_if_fail (GST_IS_ELEMENT (element), result);
2371
2372   GST_LOCK (element);
2373   result = GST_ELEMENT_SCHEDULER (element);
2374   GST_UNLOCK (element);
2375
2376   return result;
2377 }