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