gst/gstelement.c: Expose default element send_event and query handling as vmethods...
[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 /**
24  * SECTION:gstelement
25  * @short_description: Abstract base class for all pipeline elements
26  * @see_also: #GstElementFactory, #GstPad
27  *
28  * GstElement is the abstract base class needed to construct an element that 
29  * can be used in a GStreamer pipeline. Please refer to the plugin writers
30  * guide for more information on creating #GstElement subclasses.
31  *
32  * The name of a #GstElement can be get with gst_element_get_name() and set with
33  * gst_element_set_name().  For speed, GST_ELEMENT_NAME() can be used in the
34  * core when using the appropriate locking. Do not use this in plug-ins or
35  * applications in order to retain ABI compatibility.
36  *
37  * All elements have pads (of the type #GstPad).  These pads link to pads on
38  * other elements.  #GstBuffer flow between these linked pads.
39  * A #GstElement has a #GList of #GstPad structures for all their input (or sink)
40  * and output (or source) pads.
41  * Core and plug-in writers can add and remove pads with gst_element_add_pad()
42  * and gst_element_remove_pad().
43  *
44  * A pad of an element can be retrieved by name with gst_element_get_pad().
45  * An iterator of all pads can be retrieved with gst_element_iterate_pads().
46  *
47  * Elements can be linked through their pads.
48  * If the link is straightforward, use the gst_element_link()
49  * convenience function to link two elements, or gst_element_link_many()
50  * for more elements in a row.
51  * Use gst_element_link_filtered() to link two elements constrained by
52  * a specified set of #GstCaps.
53  * For finer control, use gst_element_link_pads() and
54  * gst_element_link_pads_filtered() to specify the pads to link on
55  * each element by name.
56  *
57  * Each element has a state (see #GstState).  You can get and set the state
58  * of an element with gst_element_get_state() and gst_element_set_state().
59  * To get a string representation of a #GstState, use
60  * gst_element_state_get_name().
61  *
62  * You can get and set a #GstClock on an element using gst_element_get_clock()
63  * and gst_element_set_clock().
64  * Some elements can provide a clock for the pipeline if
65  * gst_element_provides_clock() returns %TRUE. With the
66  * gst_element_provide_clock() method one can retrieve the clock provided by
67  * such an element.
68  * Not all elements require a clock to operate correctly. If
69  * gst_element_requires_clock() returns %TRUE, a clock should be set on the
70  * element with gst_element_set_clock().
71  *
72  * Note that clock slection and distribution is normally handled by the
73  * toplevel #GstPipeline so the clock functions are only to be used in very
74  * specific situations.
75  *
76  * Last reviewed on 2006-03-12 (0.10.5)
77  */
78
79 #include "gst_private.h"
80 #include <glib.h>
81 #include <stdarg.h>
82 #include <gobject/gvaluecollector.h>
83
84 #include "gstelement.h"
85 #include "gstbus.h"
86 #include "gstmarshal.h"
87 #include "gsterror.h"
88 #include "gstevent.h"
89 #include "gstutils.h"
90 #include "gstinfo.h"
91 #include "gst-i18n-lib.h"
92
93 /* Element signals and args */
94 enum
95 {
96   PAD_ADDED,
97   PAD_REMOVED,
98   NO_MORE_PADS,
99   /* add more above */
100   LAST_SIGNAL
101 };
102
103 enum
104 {
105   ARG_0
106       /* FILL ME */
107 };
108
109 extern void __gst_element_details_clear (GstElementDetails * dp);
110 extern void __gst_element_details_copy (GstElementDetails * dest,
111     const GstElementDetails * src);
112
113 static void gst_element_class_init (GstElementClass * klass);
114 static void gst_element_init (GstElement * element);
115 static void gst_element_base_class_init (gpointer g_class);
116 static void gst_element_base_class_finalize (gpointer g_class);
117
118 static void gst_element_dispose (GObject * object);
119 static void gst_element_finalize (GObject * object);
120
121 static GstStateChangeReturn gst_element_change_state (GstElement * element,
122     GstStateChange transition);
123 static GstStateChangeReturn gst_element_change_state_func (GstElement * element,
124     GstStateChange transition);
125 static GstStateChangeReturn gst_element_get_state_func (GstElement * element,
126     GstState * state, GstState * pending, GstClockTime timeout);
127 static GstStateChangeReturn gst_element_set_state_func (GstElement * element,
128     GstState state);
129 static void gst_element_set_bus_func (GstElement * element, GstBus * bus);
130
131 static gboolean gst_element_default_send_event (GstElement * element,
132     GstEvent * event);
133 static gboolean gst_element_default_query (GstElement * element,
134     GstQuery * query);
135
136 #ifndef GST_DISABLE_LOADSAVE
137 static xmlNodePtr gst_element_save_thyself (GstObject * object,
138     xmlNodePtr parent);
139 static void gst_element_restore_thyself (GstObject * parent, xmlNodePtr self);
140 #endif
141
142 static GstObjectClass *parent_class = NULL;
143 static guint gst_element_signals[LAST_SIGNAL] = { 0 };
144
145 GType
146 gst_element_get_type (void)
147 {
148   static GType gst_element_type = 0;
149
150   if (G_UNLIKELY (gst_element_type == 0)) {
151     static const GTypeInfo element_info = {
152       sizeof (GstElementClass),
153       gst_element_base_class_init,
154       gst_element_base_class_finalize,
155       (GClassInitFunc) gst_element_class_init,
156       NULL,
157       NULL,
158       sizeof (GstElement),
159       0,
160       (GInstanceInitFunc) gst_element_init,
161       NULL
162     };
163
164     gst_element_type = g_type_register_static (GST_TYPE_OBJECT, "GstElement",
165         &element_info, G_TYPE_FLAG_ABSTRACT);
166   }
167   return gst_element_type;
168 }
169
170 static void
171 gst_element_class_init (GstElementClass * klass)
172 {
173   GObjectClass *gobject_class;
174   GstObjectClass *gstobject_class;
175
176   gobject_class = (GObjectClass *) klass;
177   gstobject_class = (GstObjectClass *) klass;
178
179   parent_class = g_type_class_peek_parent (klass);
180
181   /**
182    * GstElement::pad-added:
183    * @gstelement: the object which received the signal
184    * @new_pad: the pad that has been added
185    *
186    * a new #GstPad has been added to the element.
187    */
188   gst_element_signals[PAD_ADDED] =
189       g_signal_new ("pad-added", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
190       G_STRUCT_OFFSET (GstElementClass, pad_added), NULL, NULL,
191       gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT);
192   /**
193    * GstElement::pad-removed:
194    * @gstelement: the object which received the signal
195    * @old_pad: the pad that has been removed
196    *
197    * a #GstPad has been removed from the element
198    */
199   gst_element_signals[PAD_REMOVED] =
200       g_signal_new ("pad-removed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
201       G_STRUCT_OFFSET (GstElementClass, pad_removed), NULL, NULL,
202       gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT);
203   /**
204    * GstElement::no-more-pads:
205    * @gstelement: the object which received the signal
206    *
207    * This signals that the element will not generate more dynamic pads.
208    */
209   gst_element_signals[NO_MORE_PADS] =
210       g_signal_new ("no-more-pads", G_TYPE_FROM_CLASS (klass),
211       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstElementClass, no_more_pads), NULL,
212       NULL, gst_marshal_VOID__VOID, G_TYPE_NONE, 0);
213
214   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_element_dispose);
215   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_element_finalize);
216
217 #ifndef GST_DISABLE_LOADSAVE
218   gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_element_save_thyself);
219   gstobject_class->restore_thyself =
220       GST_DEBUG_FUNCPTR (gst_element_restore_thyself);
221 #endif
222
223   klass->change_state = GST_DEBUG_FUNCPTR (gst_element_change_state_func);
224   klass->set_state = GST_DEBUG_FUNCPTR (gst_element_set_state_func);
225   klass->get_state = GST_DEBUG_FUNCPTR (gst_element_get_state_func);
226   klass->set_bus = GST_DEBUG_FUNCPTR (gst_element_set_bus_func);
227   klass->query = GST_DEBUG_FUNCPTR (gst_element_default_query);
228   klass->send_event = GST_DEBUG_FUNCPTR (gst_element_default_send_event);
229   klass->numpadtemplates = 0;
230
231   klass->elementfactory = NULL;
232 }
233
234 static void
235 gst_element_base_class_init (gpointer g_class)
236 {
237   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
238
239   memset (&element_class->details, 0, sizeof (GstElementDetails));
240   element_class->padtemplates = NULL;
241 }
242
243 static void
244 gst_element_base_class_finalize (gpointer g_class)
245 {
246   GstElementClass *klass = GST_ELEMENT_CLASS (g_class);
247
248   g_list_foreach (klass->padtemplates, (GFunc) gst_object_unref, NULL);
249   g_list_free (klass->padtemplates);
250   __gst_element_details_clear (&klass->details);
251 }
252
253 static void
254 gst_element_init (GstElement * element)
255 {
256   GST_STATE (element) = GST_STATE_NULL;
257   GST_STATE_NEXT (element) = GST_STATE_VOID_PENDING;
258   GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING;
259   GST_STATE_RETURN (element) = GST_STATE_CHANGE_SUCCESS;
260
261   element->state_lock = g_new0 (GStaticRecMutex, 1);
262   g_static_rec_mutex_init (element->state_lock);
263   element->state_cond = g_cond_new ();
264 }
265
266 /**
267  * gst_element_default_error:
268  * @object: a #GObject that signalled the error.
269  * @orig: the #GstObject that initiated the error.
270  * @error: the GError.
271  * @debug: an additional debug information string, or %NULL.
272  *
273  * A default error signal callback to attach to an element.
274  * The user data passed to the g_signal_connect is ignored.
275  *
276  * The default handler will simply print the error string using g_print.
277  *
278  * MT safe.
279  */
280 void
281 gst_element_default_error (GObject * object, GstObject * source, GError * error,
282     gchar * debug)
283 {
284   gchar *name = gst_object_get_path_string (source);
285
286   g_print (_("ERROR: from element %s: %s\n"), name, error->message);
287   if (debug)
288     g_print (_("Additional debug info:\n%s\n"), debug);
289
290   g_free (name);
291 }
292
293 /**
294  * gst_element_release_request_pad:
295  * @element: a #GstElement to release the request pad of.
296  * @pad: the #GstPad to release.
297  *
298  * Makes the element free the previously requested pad as obtained
299  * with gst_element_get_request_pad().
300  *
301  * MT safe.
302  */
303 void
304 gst_element_release_request_pad (GstElement * element, GstPad * pad)
305 {
306   GstElementClass *oclass;
307
308   g_return_if_fail (GST_IS_ELEMENT (element));
309   g_return_if_fail (GST_IS_PAD (pad));
310
311   oclass = GST_ELEMENT_GET_CLASS (element);
312
313   /* if the element implements a custom release function we call that, else we
314    * simply remove the pad from the element */
315   if (oclass->release_pad)
316     (oclass->release_pad) (element, pad);
317   else
318     gst_element_remove_pad (element, pad);
319 }
320
321 /**
322  * gst_element_requires_clock:
323  * @element: a #GstElement to query
324  *
325  * Query if the element requires a clock.
326  *
327  * Returns: %TRUE if the element requires a clock
328  *
329  * MT safe.
330  */
331 gboolean
332 gst_element_requires_clock (GstElement * element)
333 {
334   gboolean result;
335
336   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
337
338   result = (GST_ELEMENT_GET_CLASS (element)->set_clock != NULL);
339
340   return result;
341 }
342
343 /**
344  * gst_element_provides_clock:
345  * @element: a #GstElement to query
346  *
347  * Query if the element provides a clock. A #GstClock provided by an
348  * element can be used as the global #GstClock for the pipeline. 
349  * An element that can provide a clock is only required to do so in the PAUSED
350  * state, this means when it is fully negotiated and has allocated the resources
351  * to operate the clock.
352  *
353  * Returns: %TRUE if the element provides a clock
354  *
355  * MT safe.
356  */
357 gboolean
358 gst_element_provides_clock (GstElement * element)
359 {
360   gboolean result;
361
362   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
363
364   result = (GST_ELEMENT_GET_CLASS (element)->provide_clock != NULL);
365
366   return result;
367 }
368
369 /**
370  * gst_element_provide_clock:
371  * @element: a #GstElement to query
372  *
373  * Get the clock provided by the given element. 
374  * <note>An element is only required to provide a clock in the PAUSED
375  * state. Some elements can provide a clock in other states.</note>
376  *
377  * Returns: the GstClock provided by the element or %NULL
378  * if no clock could be provided.  Unref after usage.
379  *
380  * MT safe.
381  */
382 GstClock *
383 gst_element_provide_clock (GstElement * element)
384 {
385   GstClock *result = NULL;
386   GstElementClass *oclass;
387
388   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
389
390   oclass = GST_ELEMENT_GET_CLASS (element);
391
392   if (oclass->provide_clock)
393     result = oclass->provide_clock (element);
394
395   return result;
396 }
397
398 /**
399  * gst_element_set_clock:
400  * @element: a #GstElement to set the clock for.
401  * @clock: the #GstClock to set for the element.
402  *
403  * Sets the clock for the element. This function increases the
404  * refcount on the clock. Any previously set clock on the object
405  * is unreffed.
406  *
407  * Returns: %TRUE if the element accepted the clock. An element can refuse a
408  * clock when it, for example, is not able to slave its internal clock to the
409  * @clock or when it requires a specific clock to operate.
410  *
411  * MT safe.
412  */
413 gboolean
414 gst_element_set_clock (GstElement * element, GstClock * clock)
415 {
416   GstElementClass *oclass;
417   gboolean res = TRUE;
418   GstClock **clock_p;
419
420   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
421
422   oclass = GST_ELEMENT_GET_CLASS (element);
423
424   GST_DEBUG_OBJECT (element, "setting clock %p", clock);
425
426   if (oclass->set_clock)
427     res = oclass->set_clock (element, clock);
428
429   if (res) {
430     /* only update the clock pointer if the element accepted the clock */
431     GST_OBJECT_LOCK (element);
432     clock_p = &element->clock;
433     gst_object_replace ((GstObject **) clock_p, (GstObject *) clock);
434     GST_OBJECT_UNLOCK (element);
435   }
436   return res;
437 }
438
439 /**
440  * gst_element_get_clock:
441  * @element: a #GstElement to get the clock of.
442  *
443  * Gets the currently configured clock of the element. This is the clock as was
444  * last set with gst_element_set_clock().
445  *
446  * Returns: the #GstClock of the element. unref after usage.
447  *
448  * MT safe.
449  */
450 GstClock *
451 gst_element_get_clock (GstElement * element)
452 {
453   GstClock *result;
454
455   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
456
457   GST_OBJECT_LOCK (element);
458   if ((result = element->clock))
459     gst_object_ref (result);
460   GST_OBJECT_UNLOCK (element);
461
462   return result;
463 }
464
465 /**
466  * gst_element_set_base_time:
467  * @element: a #GstElement.
468  * @time: the base time to set.
469  *
470  * Set the base time of an element. See gst_element_get_base_time().
471  *
472  * MT safe.
473  */
474 void
475 gst_element_set_base_time (GstElement * element, GstClockTime time)
476 {
477   g_return_if_fail (GST_IS_ELEMENT (element));
478
479   GST_OBJECT_LOCK (element);
480   element->base_time = time;
481   GST_OBJECT_UNLOCK (element);
482
483   GST_DEBUG_OBJECT (element, "set base_time=%" GST_TIME_FORMAT,
484       GST_TIME_ARGS (time));
485 }
486
487 /**
488  * gst_element_get_base_time:
489  * @element: a #GstElement.
490  *
491  * Returns the base time of the element. The base time is the
492  * absolute time of the clock when this element was last put to
493  * PLAYING. Subtracting the base time from the clock time gives
494  * the stream time of the element.
495  *
496  * Returns: the base time of the element.
497  *
498  * MT safe.
499  */
500 GstClockTime
501 gst_element_get_base_time (GstElement * element)
502 {
503   GstClockTime result;
504
505   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_CLOCK_TIME_NONE);
506
507   GST_OBJECT_LOCK (element);
508   result = element->base_time;
509   GST_OBJECT_UNLOCK (element);
510
511   return result;
512 }
513
514 #ifndef GST_DISABLE_INDEX
515 /**
516  * gst_element_is_indexable:
517  * @element: a #GstElement.
518  *
519  * Queries if the element can be indexed.
520  *
521  * Returns: TRUE if the element can be indexed.
522  *
523  * MT safe.
524  */
525 gboolean
526 gst_element_is_indexable (GstElement * element)
527 {
528   gboolean result;
529
530   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
531
532   result = (GST_ELEMENT_GET_CLASS (element)->set_index != NULL);
533
534   return result;
535 }
536
537 /**
538  * gst_element_set_index:
539  * @element: a #GstElement.
540  * @index: a #GstIndex.
541  *
542  * Set @index on the element. The refcount of the index
543  * will be increased, any previously set index is unreffed.
544  *
545  * MT safe.
546  */
547 void
548 gst_element_set_index (GstElement * element, GstIndex * index)
549 {
550   GstElementClass *oclass;
551
552   g_return_if_fail (GST_IS_ELEMENT (element));
553   g_return_if_fail (GST_IS_INDEX (index));
554
555   oclass = GST_ELEMENT_GET_CLASS (element);
556
557   if (oclass->set_index)
558     oclass->set_index (element, index);
559 }
560
561 /**
562  * gst_element_get_index:
563  * @element: a #GstElement.
564  *
565  * Gets the index from the element.
566  *
567  * Returns: a #GstIndex or %NULL when no index was set on the
568  * element. unref after usage.
569  *
570  * MT safe.
571  */
572 GstIndex *
573 gst_element_get_index (GstElement * element)
574 {
575   GstElementClass *oclass;
576   GstIndex *result = NULL;
577
578   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
579
580   oclass = GST_ELEMENT_GET_CLASS (element);
581
582   if (oclass->get_index)
583     result = oclass->get_index (element);
584
585   return result;
586 }
587 #endif
588
589 /**
590  * gst_element_add_pad:
591  * @element: a #GstElement to add the pad to.
592  * @pad: the #GstPad to add to the element.
593  *
594  * Adds a pad (link point) to @element. @pad's parent will be set to @element;
595  * see gst_object_set_parent() for refcounting information.
596  *
597  * Pads are not automatically activated so elements should perform the needed
598  * steps to activate the pad in case this pad is added in the PAUSED or PLAYING
599  * state. See gst_pad_set_active() for more information about activating pads.
600  *
601  * The pad and the element should be unlocked when calling this function.
602  *
603  * This function will emit the #GstElement::pad-added signal on the element.
604  *
605  * Returns: %TRUE if the pad could be added. This function can fail when
606  * a pad with the same name already existed or the pad already had another
607  * parent.
608  *
609  * MT safe.
610  */
611 gboolean
612 gst_element_add_pad (GstElement * element, GstPad * pad)
613 {
614   gchar *pad_name;
615
616   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
617   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
618
619   /* locking pad to look at the name */
620   GST_OBJECT_LOCK (pad);
621   pad_name = g_strdup (GST_PAD_NAME (pad));
622   GST_CAT_INFO_OBJECT (GST_CAT_ELEMENT_PADS, element, "adding pad '%s'",
623       GST_STR_NULL (pad_name));
624   GST_OBJECT_UNLOCK (pad);
625
626   /* then check to see if there's already a pad by that name here */
627   GST_OBJECT_LOCK (element);
628   if (G_UNLIKELY (!gst_object_check_uniqueness (element->pads, pad_name)))
629     goto name_exists;
630
631   /* try to set the pad's parent */
632   if (G_UNLIKELY (!gst_object_set_parent (GST_OBJECT_CAST (pad),
633               GST_OBJECT_CAST (element))))
634     goto had_parent;
635
636   g_free (pad_name);
637
638   /* add it to the list */
639   switch (gst_pad_get_direction (pad)) {
640     case GST_PAD_SRC:
641       element->srcpads = g_list_prepend (element->srcpads, pad);
642       element->numsrcpads++;
643       break;
644     case GST_PAD_SINK:
645       element->sinkpads = g_list_prepend (element->sinkpads, pad);
646       element->numsinkpads++;
647       break;
648     default:
649       goto no_direction;
650   }
651   element->pads = g_list_prepend (element->pads, pad);
652   element->numpads++;
653   element->pads_cookie++;
654   GST_OBJECT_UNLOCK (element);
655
656   /* emit the PAD_ADDED signal */
657   g_signal_emit (element, gst_element_signals[PAD_ADDED], 0, pad);
658
659   return TRUE;
660
661   /* ERROR cases */
662 name_exists:
663   {
664     g_critical ("Padname %s is not unique in element %s, not adding",
665         pad_name, GST_ELEMENT_NAME (element));
666     GST_OBJECT_UNLOCK (element);
667     g_free (pad_name);
668     return FALSE;
669   }
670 had_parent:
671   {
672     g_critical
673         ("Pad %s already has parent when trying to add to element %s",
674         pad_name, GST_ELEMENT_NAME (element));
675     GST_OBJECT_UNLOCK (element);
676     g_free (pad_name);
677     return FALSE;
678   }
679 no_direction:
680   {
681     GST_OBJECT_LOCK (pad);
682     g_critical
683         ("Trying to add pad %s to element %s, but it has no direction",
684         GST_OBJECT_NAME (pad), GST_ELEMENT_NAME (element));
685     GST_OBJECT_UNLOCK (pad);
686     GST_OBJECT_UNLOCK (element);
687     return FALSE;
688   }
689 }
690
691 /**
692  * gst_element_remove_pad:
693  * @element: a #GstElement to remove pad from.
694  * @pad: the #GstPad to remove from the element.
695  *
696  * Removes @pad from @element. @pad will be destroyed if it has not been
697  * referenced elsewhere using gst_object_unparent().
698  *
699  * This function is used by plugin developers and should not be used
700  * by applications. Pads that were dynamically requested from elements
701  * with gst_element_get_request_pad() should be released with the
702  * gst_element_release_request_pad() function instead.
703  *
704  * Pads are not automatically deactivated so elements should perform the needed
705  * steps to deactivate the pad in case this pad is removed in the PAUSED or
706  * PLAYING state. See gst_pad_set_active() for more information about
707  * deactivating pads.
708  *
709  * The pad and the element should be unlocked when calling this function.
710  *
711  * This function will emit the #GstElement::pad-removed signal on the element.
712  *
713  * Returns: %TRUE if the pad could be removed. Can return %FALSE if the
714  * pad does not belong to the provided element.
715  *
716  * MT safe.
717  */
718 gboolean
719 gst_element_remove_pad (GstElement * element, GstPad * pad)
720 {
721   GstPad *peer;
722
723   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
724   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
725
726   /* locking pad to look at the name and parent */
727   GST_OBJECT_LOCK (pad);
728   GST_CAT_INFO_OBJECT (GST_CAT_ELEMENT_PADS, element, "removing pad '%s'",
729       GST_STR_NULL (GST_PAD_NAME (pad)));
730
731   if (G_UNLIKELY (GST_PAD_PARENT (pad) != element))
732     goto not_our_pad;
733   GST_OBJECT_UNLOCK (pad);
734
735   /* unlink */
736   if ((peer = gst_pad_get_peer (pad))) {
737     /* window for MT unsafeness, someone else could unlink here
738      * and then we call unlink with wrong pads. The unlink
739      * function would catch this and safely return failed. */
740     if (GST_PAD_IS_SRC (pad))
741       gst_pad_unlink (pad, peer);
742     else
743       gst_pad_unlink (peer, pad);
744
745     gst_object_unref (peer);
746   }
747
748   GST_OBJECT_LOCK (element);
749   /* remove it from the list */
750   switch (gst_pad_get_direction (pad)) {
751     case GST_PAD_SRC:
752       element->srcpads = g_list_remove (element->srcpads, pad);
753       element->numsrcpads--;
754       break;
755     case GST_PAD_SINK:
756       element->sinkpads = g_list_remove (element->sinkpads, pad);
757       element->numsinkpads--;
758       break;
759     default:
760       g_critical ("Removing pad without direction???");
761       break;
762   }
763   element->pads = g_list_remove (element->pads, pad);
764   element->numpads--;
765   element->pads_cookie++;
766   GST_OBJECT_UNLOCK (element);
767
768   /* emit the PAD_REMOVED signal before unparenting and losing the last ref. */
769   g_signal_emit (element, gst_element_signals[PAD_REMOVED], 0, pad);
770
771   gst_object_unparent (GST_OBJECT_CAST (pad));
772
773   return TRUE;
774
775   /* ERRORS */
776 not_our_pad:
777   {
778     /* FIXME, locking order? */
779     GST_OBJECT_LOCK (element);
780     g_critical ("Padname %s:%s does not belong to element %s when removing",
781         GST_DEBUG_PAD_NAME (pad), GST_ELEMENT_NAME (element));
782     GST_OBJECT_UNLOCK (element);
783     GST_OBJECT_UNLOCK (pad);
784     return FALSE;
785   }
786 }
787
788 /**
789  * gst_element_no_more_pads:
790  * @element: a #GstElement
791  *
792  * Use this function to signal that the element does not expect any more pads
793  * to show up in the current pipeline. This function should be called whenever
794  * pads have been added by the element itself. Elements with #GST_PAD_SOMETIMES
795  * pad templates use this in combination with autopluggers to figure out that
796  * the element is done initializing its pads.
797  *
798  * This function emits the #GstElement::no-more-pads signal.
799  *
800  * MT safe.
801  */
802 void
803 gst_element_no_more_pads (GstElement * element)
804 {
805   g_return_if_fail (GST_IS_ELEMENT (element));
806
807   g_signal_emit (element, gst_element_signals[NO_MORE_PADS], 0);
808 }
809
810 static gint
811 pad_compare_name (GstPad * pad1, const gchar * name)
812 {
813   gint result;
814
815   GST_OBJECT_LOCK (pad1);
816   result = strcmp (GST_PAD_NAME (pad1), name);
817   GST_OBJECT_UNLOCK (pad1);
818
819   return result;
820 }
821
822 /**
823  * gst_element_get_static_pad:
824  * @element: a #GstElement to find a static pad of.
825  * @name: the name of the static #GstPad to retrieve.
826  *
827  * Retrieves a pad from @element by name. This version only retrieves
828  * already-existing (i.e. 'static') pads.
829  *
830  * Returns: the requested #GstPad if found, otherwise %NULL. unref after
831  * usage.
832  *
833  * MT safe.
834  */
835 GstPad *
836 gst_element_get_static_pad (GstElement * element, const gchar * name)
837 {
838   GList *find;
839   GstPad *result = NULL;
840
841   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
842   g_return_val_if_fail (name != NULL, NULL);
843
844   GST_OBJECT_LOCK (element);
845   find =
846       g_list_find_custom (element->pads, name, (GCompareFunc) pad_compare_name);
847   if (find) {
848     result = GST_PAD_CAST (find->data);
849     gst_object_ref (result);
850   }
851
852   if (result == NULL) {
853     GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "no such pad '%s' in element \"%s\"",
854         name, GST_ELEMENT_NAME (element));
855   } else {
856     GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "found pad %s:%s",
857         GST_ELEMENT_NAME (element), name);
858   }
859   GST_OBJECT_UNLOCK (element);
860
861   return result;
862 }
863
864 static GstPad *
865 gst_element_request_pad (GstElement * element, GstPadTemplate * templ,
866     const gchar * name)
867 {
868   GstPad *newpad = NULL;
869   GstElementClass *oclass;
870
871   oclass = GST_ELEMENT_GET_CLASS (element);
872
873   if (oclass->request_new_pad)
874     newpad = (oclass->request_new_pad) (element, templ, name);
875
876   if (newpad)
877     gst_object_ref (newpad);
878
879   return newpad;
880 }
881
882 /**
883  * gst_element_get_request_pad:
884  * @element: a #GstElement to find a request pad of.
885  * @name: the name of the request #GstPad to retrieve.
886  *
887  * Retrieves a pad from the element by name. This version only retrieves
888  * request pads. The pad should be released with 
889  * gst_element_release_request_pad().
890  *
891  * Returns: requested #GstPad if found, otherwise %NULL. Release after usage.
892  */
893 GstPad *
894 gst_element_get_request_pad (GstElement * element, const gchar * name)
895 {
896   GstPadTemplate *templ = NULL;
897   GstPad *pad;
898   const gchar *req_name = NULL;
899   gboolean templ_found = FALSE;
900   GList *list;
901   gint n;
902   const gchar *data;
903   gchar *str, *endptr = NULL;
904   GstElementClass *class;
905
906   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
907   g_return_val_if_fail (name != NULL, NULL);
908
909   class = GST_ELEMENT_GET_CLASS (element);
910
911   if (strstr (name, "%")) {
912     templ = gst_element_class_get_pad_template (class, name);
913     req_name = NULL;
914     if (templ)
915       templ_found = TRUE;
916   } else {
917     list = gst_element_class_get_pad_template_list (class);
918     while (!templ_found && list) {
919       templ = (GstPadTemplate *) list->data;
920       if (templ->presence == GST_PAD_REQUEST) {
921         /* Because of sanity checks in gst_pad_template_new(), we know that %s
922            and %d, occurring at the end of the name_template, are the only
923            possibilities. */
924         GST_CAT_DEBUG (GST_CAT_PADS, "comparing %s to %s", name,
925             templ->name_template);
926         if ((str = strchr (templ->name_template, '%'))
927             && strncmp (templ->name_template, name,
928                 str - templ->name_template) == 0
929             && strlen (name) > str - templ->name_template) {
930           data = name + (str - templ->name_template);
931           if (*(str + 1) == 'd') {
932             /* it's an int */
933             n = (gint) strtol (data, &endptr, 10);
934             if (endptr && *endptr == '\0') {
935               templ_found = TRUE;
936               req_name = name;
937               break;
938             }
939           } else {
940             /* it's a string */
941             templ_found = TRUE;
942             req_name = name;
943             break;
944           }
945         }
946       }
947       list = list->next;
948     }
949   }
950
951   if (!templ_found)
952     return NULL;
953
954   pad = gst_element_request_pad (element, templ, req_name);
955
956   return pad;
957 }
958
959 /**
960  * gst_element_get_pad:
961  * @element: a #GstElement.
962  * @name: the name of the pad to retrieve.
963  *
964  * Retrieves a pad from @element by name. Tries gst_element_get_static_pad()
965  * first, then gst_element_get_request_pad().
966  *
967  * <note>Usage of this function is not recommended as it is unclear if the reference
968  * to the result pad should be released with gst_object_unref() in case of a static pad
969  * or gst_element_release_request_pad() in case of a request pad.</note>
970  *
971  * Returns: the #GstPad if found, otherwise %NULL. Unref or Release after usage,
972  * depending on the type of the pad.
973  */
974 GstPad *
975 gst_element_get_pad (GstElement * element, const gchar * name)
976 {
977   GstPad *pad;
978
979   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
980   g_return_val_if_fail (name != NULL, NULL);
981
982   pad = gst_element_get_static_pad (element, name);
983   if (!pad)
984     pad = gst_element_get_request_pad (element, name);
985
986   return pad;
987 }
988
989 static GstIteratorItem
990 iterate_pad (GstIterator * it, GstPad * pad)
991 {
992   gst_object_ref (pad);
993   return GST_ITERATOR_ITEM_PASS;
994 }
995
996 static GstIterator *
997 gst_element_iterate_pad_list (GstElement * element, GList ** padlist)
998 {
999   GstIterator *result;
1000
1001   GST_OBJECT_LOCK (element);
1002   gst_object_ref (element);
1003   result = gst_iterator_new_list (GST_TYPE_PAD,
1004       GST_OBJECT_GET_LOCK (element),
1005       &element->pads_cookie,
1006       padlist,
1007       element,
1008       (GstIteratorItemFunction) iterate_pad,
1009       (GstIteratorDisposeFunction) gst_object_unref);
1010   GST_OBJECT_UNLOCK (element);
1011
1012   return result;
1013 }
1014
1015 /**
1016  * gst_element_iterate_pads:
1017  * @element: a #GstElement to iterate pads of.
1018  *
1019  * Retrieves an iterattor of @element's pads. The iterator should
1020  * be freed after usage.
1021  *
1022  * Returns: the #GstIterator of #GstPad. Unref each pad after use.
1023  *
1024  * MT safe.
1025  */
1026 GstIterator *
1027 gst_element_iterate_pads (GstElement * element)
1028 {
1029   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1030
1031   return gst_element_iterate_pad_list (element, &element->pads);
1032 }
1033
1034 /**
1035  * gst_element_iterate_src_pads:
1036  * @element: a #GstElement.
1037  *
1038  * Retrieves an iterator of @element's source pads.
1039  *
1040  * Returns: the #GstIterator of #GstPad. Unref each pad after use.
1041  *
1042  * MT safe.
1043  */
1044 GstIterator *
1045 gst_element_iterate_src_pads (GstElement * element)
1046 {
1047   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1048
1049   return gst_element_iterate_pad_list (element, &element->srcpads);
1050 }
1051
1052 /**
1053  * gst_element_iterate_sink_pads:
1054  * @element: a #GstElement.
1055  *
1056  * Retrieves an iterator of @element's sink pads.
1057  *
1058  * Returns: the #GstIterator of #GstPad. Unref each pad after use.
1059  *
1060  * MT safe.
1061  */
1062 GstIterator *
1063 gst_element_iterate_sink_pads (GstElement * element)
1064 {
1065   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1066
1067   return gst_element_iterate_pad_list (element, &element->sinkpads);
1068 }
1069
1070 /**
1071  * gst_element_class_add_pad_template:
1072  * @klass: the #GstElementClass to add the pad template to.
1073  * @templ: a #GstPadTemplate to add to the element class.
1074  *
1075  * Adds a padtemplate to an element class. This is mainly used in the _base_init
1076  * functions of classes.
1077  */
1078 void
1079 gst_element_class_add_pad_template (GstElementClass * klass,
1080     GstPadTemplate * templ)
1081 {
1082   g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
1083   g_return_if_fail (GST_IS_PAD_TEMPLATE (templ));
1084
1085   /* avoid registering pad templates with the same name */
1086   g_return_if_fail (gst_element_class_get_pad_template (klass,
1087           templ->name_template) == NULL);
1088
1089   klass->padtemplates = g_list_append (klass->padtemplates,
1090       gst_object_ref (templ));
1091   klass->numpadtemplates++;
1092 }
1093
1094 /**
1095  * gst_element_class_set_details:
1096  * @klass: class to set details for
1097  * @details: details to set
1098  *
1099  * Sets the detailed information for a #GstElementClass.
1100  * <note>This function is for use in _base_init functions only.</note>
1101  *
1102  * The @details are copied.
1103  */
1104 void
1105 gst_element_class_set_details (GstElementClass * klass,
1106     const GstElementDetails * details)
1107 {
1108   g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
1109   g_return_if_fail (GST_IS_ELEMENT_DETAILS (details));
1110
1111   __gst_element_details_copy (&klass->details, details);
1112 }
1113
1114 /**
1115  * gst_element_class_get_pad_template_list:
1116  * @element_class: a #GstElementClass to get pad templates of.
1117  *
1118  * Retrieves a list of the pad templates associated with @element_class. The
1119  * list must not be modified by the calling code.
1120  * <note>If you use this function in the #GInstanceInitFunc of an object class
1121  * that has subclasses, make sure to pass the g_class parameter of the
1122  * #GInstanceInitFunc here.</note>
1123  *
1124  * Returns: the #GList of padtemplates.
1125  */
1126 GList *
1127 gst_element_class_get_pad_template_list (GstElementClass * element_class)
1128 {
1129   g_return_val_if_fail (GST_IS_ELEMENT_CLASS (element_class), NULL);
1130
1131   return element_class->padtemplates;
1132 }
1133
1134 /**
1135  * gst_element_class_get_pad_template:
1136  * @element_class: a #GstElementClass to get the pad template of.
1137  * @name: the name of the #GstPadTemplate to get.
1138  *
1139  * Retrieves a padtemplate from @element_class with the given name.
1140  * <note>If you use this function in the #GInstanceInitFunc of an object class
1141  * that has subclasses, make sure to pass the g_class parameter of the
1142  * #GInstanceInitFunc here.</note>
1143  *
1144  * Returns: the #GstPadTemplate with the given name, or %NULL if none was found.
1145  * No unreferencing is necessary.
1146  */
1147 GstPadTemplate *
1148 gst_element_class_get_pad_template (GstElementClass * element_class,
1149     const gchar * name)
1150 {
1151   GList *padlist;
1152
1153   g_return_val_if_fail (GST_IS_ELEMENT_CLASS (element_class), NULL);
1154   g_return_val_if_fail (name != NULL, NULL);
1155
1156   padlist = gst_element_class_get_pad_template_list (element_class);
1157
1158   while (padlist) {
1159     GstPadTemplate *padtempl = (GstPadTemplate *) padlist->data;
1160
1161     if (strcmp (padtempl->name_template, name) == 0)
1162       return padtempl;
1163
1164     padlist = g_list_next (padlist);
1165   }
1166
1167   return NULL;
1168 }
1169
1170 /* get a random pad on element of the given direction.
1171  * The pad is random in a sense that it is the first pad that is (optionaly) linked.
1172  */
1173 static GstPad *
1174 gst_element_get_random_pad (GstElement * element, gboolean need_linked,
1175     GstPadDirection dir)
1176 {
1177   GstPad *result = NULL;
1178   GList *pads;
1179
1180   GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "getting a random pad");
1181
1182   switch (dir) {
1183     case GST_PAD_SRC:
1184       GST_OBJECT_LOCK (element);
1185       pads = element->srcpads;
1186       break;
1187     case GST_PAD_SINK:
1188       GST_OBJECT_LOCK (element);
1189       pads = element->sinkpads;
1190       break;
1191     default:
1192       goto wrong_direction;
1193   }
1194   for (; pads; pads = g_list_next (pads)) {
1195     GstPad *pad = GST_PAD_CAST (pads->data);
1196
1197     GST_OBJECT_LOCK (pad);
1198     GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "checking pad %s:%s",
1199         GST_DEBUG_PAD_NAME (pad));
1200
1201     if (need_linked && !GST_PAD_IS_LINKED (pad)) {
1202       /* if we require a linked pad, and it is not linked, continue the
1203        * search */
1204       GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s is not linked",
1205           GST_DEBUG_PAD_NAME (pad));
1206       GST_OBJECT_UNLOCK (pad);
1207       continue;
1208     } else {
1209       /* found a pad, stop search */
1210       GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "found pad %s:%s",
1211           GST_DEBUG_PAD_NAME (pad));
1212       GST_OBJECT_UNLOCK (pad);
1213       result = pad;
1214       break;
1215     }
1216   }
1217   if (result)
1218     gst_object_ref (result);
1219
1220   GST_OBJECT_UNLOCK (element);
1221
1222   return result;
1223
1224   /* ERROR handling */
1225 wrong_direction:
1226   {
1227     g_warning ("unknown pad direction %d", dir);
1228     return NULL;
1229   }
1230 }
1231
1232 static gboolean
1233 gst_element_default_send_event (GstElement * element, GstEvent * event)
1234 {
1235   gboolean result = FALSE;
1236   GstPad *pad;
1237
1238   pad = GST_EVENT_IS_DOWNSTREAM (event) ?
1239       gst_element_get_random_pad (element, TRUE, GST_PAD_SRC) :
1240       gst_element_get_random_pad (element, TRUE, GST_PAD_SINK);
1241
1242   if (pad) {
1243     GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
1244         "pushing %s event to random %s pad %s:%s",
1245         GST_EVENT_TYPE_NAME (event),
1246         (GST_PAD_DIRECTION (pad) == GST_PAD_SRC ? "src" : "sink"),
1247         GST_DEBUG_PAD_NAME (pad));
1248
1249     result = gst_pad_push_event (pad, event);
1250     gst_object_unref (pad);
1251   } else {
1252     GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "can't send %s event on element %s",
1253         GST_EVENT_TYPE_NAME (event), GST_ELEMENT_NAME (element));
1254   }
1255   return result;
1256 }
1257
1258 /**
1259  * gst_element_send_event:
1260  * @element: a #GstElement to send the event to.
1261  * @event: the #GstEvent to send to the element.
1262  *
1263  * Sends an event to an element. If the element doesn't implement an
1264  * event handler, the event will be pushed on a random linked sink pad for
1265  * upstream events or a random linked source pad for downstream events. 
1266  *
1267  * This function takes owership of the provided event so you should
1268  * gst_event_ref() it if you want to reuse the event after this call.
1269  *
1270  * Returns: %TRUE if the event was handled.
1271  *
1272  * MT safe.
1273  */
1274 gboolean
1275 gst_element_send_event (GstElement * element, GstEvent * event)
1276 {
1277   GstElementClass *oclass;
1278   gboolean result = FALSE;
1279
1280   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1281   g_return_val_if_fail (event != NULL, FALSE);
1282
1283   oclass = GST_ELEMENT_GET_CLASS (element);
1284
1285   if (oclass->send_event) {
1286     GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "send %s event on element %s",
1287         GST_EVENT_TYPE_NAME (event), GST_ELEMENT_NAME (element));
1288     result = oclass->send_event (element, event);
1289   } else {
1290     result = gst_element_default_send_event (element, event);
1291   }
1292   return result;
1293 }
1294
1295 /**
1296  * gst_element_seek:
1297  * @element: a #GstElement to send the event to.
1298  * @rate: The new playback rate
1299  * @format: The format of the seek values
1300  * @flags: The optional seek flags.
1301  * @cur_type: The type and flags for the new current position
1302  * @cur: The value of the new current position
1303  * @stop_type: The type and flags for the new stop position
1304  * @stop: The value of the new stop position
1305  *
1306  * Sends a seek event to an element. See gst_event_new_seek() for the details of
1307  * the parameters. The seek event is sent to the element using
1308  * gst_element_send_event().
1309  *
1310  * Returns: %TRUE if the event was handled.
1311  *
1312  * MT safe.
1313  */
1314 gboolean
1315 gst_element_seek (GstElement * element, gdouble rate, GstFormat format,
1316     GstSeekFlags flags, GstSeekType cur_type, gint64 cur,
1317     GstSeekType stop_type, gint64 stop)
1318 {
1319   GstEvent *event;
1320   gboolean result;
1321
1322   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1323
1324   event =
1325       gst_event_new_seek (rate, format, flags, cur_type, cur, stop_type, stop);
1326   result = gst_element_send_event (element, event);
1327
1328   return result;
1329 }
1330
1331 /**
1332  * gst_element_get_query_types:
1333  * @element: a #GstElement to query
1334  *
1335  * Get an array of query types from the element.
1336  * If the element doesn't implement a query types function,
1337  * the query will be forwarded to the peer of a random linked sink pad.
1338  *
1339  * Returns: An array of #GstQueryType elements that should not
1340  * be freed or modified.
1341  *
1342  * MT safe.
1343  */
1344 const GstQueryType *
1345 gst_element_get_query_types (GstElement * element)
1346 {
1347   GstElementClass *oclass;
1348   const GstQueryType *result = NULL;
1349
1350   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1351
1352   oclass = GST_ELEMENT_GET_CLASS (element);
1353
1354   if (oclass->get_query_types) {
1355     result = oclass->get_query_types (element);
1356   } else {
1357     GstPad *pad = gst_element_get_random_pad (element, TRUE, GST_PAD_SINK);
1358
1359     if (pad) {
1360       GstPad *peer = gst_pad_get_peer (pad);
1361
1362       if (peer) {
1363         result = gst_pad_get_query_types (peer);
1364
1365         gst_object_unref (peer);
1366       }
1367       gst_object_unref (pad);
1368     }
1369   }
1370   return result;
1371 }
1372
1373 static gboolean
1374 gst_element_default_query (GstElement * element, GstQuery * query)
1375 {
1376   gboolean result = FALSE;
1377   GstPad *pad;
1378
1379   pad = gst_element_get_random_pad (element, FALSE, GST_PAD_SRC);
1380   if (pad) {
1381     result = gst_pad_query (pad, query);
1382
1383     gst_object_unref (pad);
1384   } else {
1385     pad = gst_element_get_random_pad (element, TRUE, GST_PAD_SINK);
1386     if (pad) {
1387       GstPad *peer = gst_pad_get_peer (pad);
1388
1389       if (peer) {
1390         result = gst_pad_query (peer, query);
1391
1392         gst_object_unref (peer);
1393       }
1394       gst_object_unref (pad);
1395     }
1396   }
1397   return result;
1398 }
1399
1400 /**
1401  * gst_element_query:
1402  * @element: a #GstElement to perform the query on.
1403  * @query: the #GstQuery.
1404  *
1405  * Performs a query on the given element.
1406  *
1407  * For elements that don't implement a query handler, this function
1408  * forwards the query to a random srcpad or to the peer of a
1409  * random linked sinkpad of this element.
1410  *
1411  * Returns: TRUE if the query could be performed.
1412  *
1413  * MT safe.
1414  */
1415 gboolean
1416 gst_element_query (GstElement * element, GstQuery * query)
1417 {
1418   GstElementClass *oclass;
1419   gboolean result = FALSE;
1420
1421   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1422   g_return_val_if_fail (query != NULL, FALSE);
1423
1424   oclass = GST_ELEMENT_GET_CLASS (element);
1425
1426   if (oclass->query) {
1427     GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "send query on element %s",
1428         GST_ELEMENT_NAME (element));
1429     result = oclass->query (element, query);
1430   } else {
1431     result = gst_element_default_query (element, query);
1432   }
1433   return result;
1434 }
1435
1436 /**
1437  * gst_element_post_message:
1438  * @element: a #GstElement posting the message
1439  * @message: a #GstMessage to post
1440  *
1441  * Post a message on the element's #GstBus. This function takes ownership of the
1442  * message; if you want to access the message after this call, you should add an
1443  * additional reference before calling.
1444  *
1445  * Returns: %TRUE if the message was successfully posted. The function returns
1446  * %FALSE if the element did not have a bus.
1447  *
1448  * MT safe.
1449  */
1450 gboolean
1451 gst_element_post_message (GstElement * element, GstMessage * message)
1452 {
1453   GstBus *bus;
1454   gboolean result = FALSE;
1455
1456   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1457   g_return_val_if_fail (message != NULL, FALSE);
1458
1459   GST_OBJECT_LOCK (element);
1460   bus = element->bus;
1461
1462   if (G_UNLIKELY (bus == NULL))
1463     goto no_bus;
1464
1465   gst_object_ref (bus);
1466   GST_OBJECT_UNLOCK (element);
1467
1468   /* we release the element lock when posting the message so that any
1469    * (synchronous) message handlers can operate on the element */
1470   result = gst_bus_post (bus, message);
1471   gst_object_unref (bus);
1472
1473   return result;
1474
1475   /* ERRORS */
1476 no_bus:
1477   {
1478     GST_DEBUG_OBJECT (element, "not posting message %p: no bus", message);
1479     GST_OBJECT_UNLOCK (element);
1480     gst_message_unref (message);
1481     return FALSE;
1482   }
1483 }
1484
1485 /**
1486  * _gst_element_error_printf:
1487  * @format: the printf-like format to use, or %NULL
1488  *
1489  * This function is only used internally by the gst_element_error() macro.
1490  *
1491  * Returns: a newly allocated string, or %NULL if the format was %NULL or ""
1492  *
1493  * MT safe.
1494  */
1495 gchar *
1496 _gst_element_error_printf (const gchar * format, ...)
1497 {
1498   va_list args;
1499   gchar *buffer;
1500
1501   if (format == NULL)
1502     return NULL;
1503   if (format[0] == 0)
1504     return NULL;
1505
1506   va_start (args, format);
1507   buffer = g_strdup_vprintf (format, args);
1508   va_end (args);
1509   return buffer;
1510 }
1511
1512 /**
1513  * gst_element_message_full:
1514  * @element:  a #GstElement to send message from
1515  * @type:     the #GstMessageType
1516  * @domain:   the GStreamer GError domain this message belongs to
1517  * @code:     the GError code belonging to the domain
1518  * @text:     an allocated text string to be used as a replacement for the
1519  *            default message connected to code, or %NULL
1520  * @debug:    an allocated debug message to be used as a replacement for the
1521  *            default debugging information, or %NULL
1522  * @file:     the source code file where the error was generated
1523  * @function: the source code function where the error was generated
1524  * @line:     the source code line where the error was generated
1525  *
1526  * Post an error or warning message on the bus from inside an element.
1527  *
1528  * MT safe.
1529  */
1530 void gst_element_message_full
1531     (GstElement * element, GstMessageType type,
1532     GQuark domain, gint code, gchar * text,
1533     gchar * debug, const gchar * file, const gchar * function, gint line)
1534 {
1535   GError *gerror = NULL;
1536   gchar *name;
1537   gchar *sent_text;
1538   gchar *sent_debug;
1539   gboolean has_debug = TRUE;
1540   GstMessage *message = NULL;
1541
1542   /* checks */
1543   GST_DEBUG_OBJECT (element, "start");
1544   g_return_if_fail (GST_IS_ELEMENT (element));
1545   g_return_if_fail ((type == GST_MESSAGE_ERROR) ||
1546       (type == GST_MESSAGE_WARNING));
1547
1548   /* check if we send the given text or the default error text */
1549   if ((text == NULL) || (text[0] == 0)) {
1550     /* text could have come from g_strdup_printf (""); */
1551     g_free (text);
1552     sent_text = gst_error_get_message (domain, code);
1553   } else
1554     sent_text = text;
1555
1556   /* construct a sent_debug with extra information from source */
1557   if ((debug == NULL) || (debug[0] == 0)) {
1558     /* debug could have come from g_strdup_printf (""); */
1559     has_debug = FALSE;
1560   }
1561
1562   name = gst_object_get_path_string (GST_OBJECT_CAST (element));
1563   if (has_debug)
1564     sent_debug = g_strdup_printf ("%s(%d): %s (): %s:\n%s",
1565         file, line, function, name, debug);
1566   else
1567     sent_debug = g_strdup_printf ("%s(%d): %s (): %s",
1568         file, line, function, name);
1569   g_free (name);
1570   g_free (debug);
1571
1572   /* create gerror and post message */
1573   GST_CAT_INFO_OBJECT (GST_CAT_ERROR_SYSTEM, element, "posting message: %s",
1574       sent_text);
1575   gerror = g_error_new_literal (domain, code, sent_text);
1576
1577   if (type == GST_MESSAGE_ERROR) {
1578     message =
1579         gst_message_new_error (GST_OBJECT_CAST (element), gerror, sent_debug);
1580   } else if (type == GST_MESSAGE_WARNING) {
1581     message = gst_message_new_warning (GST_OBJECT_CAST (element), gerror,
1582         sent_debug);
1583   } else {
1584     g_assert_not_reached ();
1585   }
1586   gst_element_post_message (element, message);
1587
1588   GST_CAT_INFO_OBJECT (GST_CAT_ERROR_SYSTEM, element, "posted %s message: %s",
1589       (type == GST_MESSAGE_ERROR ? "error" : "warning"), sent_text);
1590
1591   /* cleanup */
1592   g_error_free (gerror);
1593   g_free (sent_debug);
1594   g_free (sent_text);
1595 }
1596
1597 /**
1598  * gst_element_is_locked_state:
1599  * @element: a #GstElement.
1600  *
1601  * Checks if the state of an element is locked.
1602  * If the state of an element is locked, state changes of the parent don't
1603  * affect the element.
1604  * This way you can leave currently unused elements inside bins. Just lock their
1605  * state before changing the state from #GST_STATE_NULL.
1606  *
1607  * MT safe.
1608  *
1609  * Returns: TRUE, if the element's state is locked.
1610  */
1611 gboolean
1612 gst_element_is_locked_state (GstElement * element)
1613 {
1614   gboolean result;
1615
1616   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1617
1618   GST_OBJECT_LOCK (element);
1619   result = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
1620   GST_OBJECT_UNLOCK (element);
1621
1622   return result;
1623 }
1624
1625 /**
1626  * gst_element_set_locked_state:
1627  * @element: a #GstElement
1628  * @locked_state: TRUE to lock the element's state
1629  *
1630  * Locks the state of an element, so state changes of the parent don't affect
1631  * this element anymore.
1632  *
1633  * MT safe.
1634  *
1635  * Returns: TRUE if the state was changed, FALSE if bad parameterss were given
1636  * or the elements state-locking needed no change.
1637  */
1638 gboolean
1639 gst_element_set_locked_state (GstElement * element, gboolean locked_state)
1640 {
1641   gboolean old;
1642
1643   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1644
1645   GST_OBJECT_LOCK (element);
1646   old = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
1647
1648   if (G_UNLIKELY (old == locked_state))
1649     goto was_ok;
1650
1651   if (locked_state) {
1652     GST_CAT_DEBUG (GST_CAT_STATES, "locking state of element %s",
1653         GST_ELEMENT_NAME (element));
1654     GST_OBJECT_FLAG_SET (element, GST_ELEMENT_LOCKED_STATE);
1655   } else {
1656     GST_CAT_DEBUG (GST_CAT_STATES, "unlocking state of element %s",
1657         GST_ELEMENT_NAME (element));
1658     GST_OBJECT_FLAG_UNSET (element, GST_ELEMENT_LOCKED_STATE);
1659   }
1660   GST_OBJECT_UNLOCK (element);
1661
1662   return TRUE;
1663
1664 was_ok:
1665   GST_CAT_DEBUG (GST_CAT_STATES, "elements %s was in locked state %d",
1666       GST_ELEMENT_NAME (element), old);
1667   GST_OBJECT_UNLOCK (element);
1668
1669   return FALSE;
1670 }
1671
1672 /**
1673  * gst_element_sync_state_with_parent:
1674  * @element: a #GstElement.
1675  *
1676  * Tries to change the state of the element to the same as its parent.
1677  * If this function returns FALSE, the state of element is undefined.
1678  *
1679  * Returns: TRUE, if the element's state could be synced to the parent's state.
1680  *
1681  * MT safe.
1682  */
1683 gboolean
1684 gst_element_sync_state_with_parent (GstElement * element)
1685 {
1686   GstElement *parent;
1687
1688   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1689
1690   if ((parent = GST_ELEMENT_CAST (gst_element_get_parent (element)))) {
1691     GstState parent_current, parent_pending;
1692     GstStateChangeReturn ret;
1693
1694     GST_OBJECT_LOCK (parent);
1695     parent_current = GST_STATE (parent);
1696     parent_pending = GST_STATE_PENDING (parent);
1697     GST_OBJECT_UNLOCK (parent);
1698
1699     GST_CAT_DEBUG (GST_CAT_STATES,
1700         "syncing state of element %s (%s) to %s (%s, %s)",
1701         GST_ELEMENT_NAME (element),
1702         gst_element_state_get_name (GST_STATE (element)),
1703         GST_ELEMENT_NAME (parent), gst_element_state_get_name (parent_current),
1704         gst_element_state_get_name (parent_pending));
1705
1706     ret = gst_element_set_state (element, parent_current);
1707     if (ret == GST_STATE_CHANGE_FAILURE)
1708       goto failed;
1709
1710     gst_object_unref (parent);
1711
1712     return TRUE;
1713   }
1714   return FALSE;
1715
1716   /* ERROR */
1717 failed:
1718   {
1719     return FALSE;
1720   }
1721 }
1722
1723 /* MT safe */
1724 static GstStateChangeReturn
1725 gst_element_get_state_func (GstElement * element,
1726     GstState * state, GstState * pending, GstClockTime timeout)
1727 {
1728   GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
1729   GstState old_pending;
1730
1731   GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "getting state");
1732
1733   GST_OBJECT_LOCK (element);
1734   ret = GST_STATE_RETURN (element);
1735
1736   /* we got an error, report immediatly */
1737   if (ret == GST_STATE_CHANGE_FAILURE)
1738     goto done;
1739
1740   /* we got no_preroll, report immediatly */
1741   if (ret == GST_STATE_CHANGE_NO_PREROLL)
1742     goto done;
1743
1744   /* no need to wait async if we are not async */
1745   if (ret != GST_STATE_CHANGE_ASYNC)
1746     goto done;
1747
1748   old_pending = GST_STATE_PENDING (element);
1749   if (old_pending != GST_STATE_VOID_PENDING) {
1750     GTimeVal *timeval, abstimeout;
1751     guint32 cookie;
1752
1753     if (timeout != GST_CLOCK_TIME_NONE) {
1754       glong add = timeout / 1000;
1755
1756       if (add == 0)
1757         goto done;
1758
1759       /* make timeout absolute */
1760       g_get_current_time (&abstimeout);
1761       g_time_val_add (&abstimeout, add);
1762       timeval = &abstimeout;
1763     } else {
1764       timeval = NULL;
1765     }
1766     /* get cookie to dected state change during waiting */
1767     cookie = element->state_cookie;
1768
1769     GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1770         "waiting for element to commit state");
1771
1772     /* we have a pending state change, wait for it to complete */
1773     if (!GST_STATE_TIMED_WAIT (element, timeval)) {
1774       GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "timed out");
1775       /* timeout triggered */
1776       ret = GST_STATE_CHANGE_ASYNC;
1777     } else {
1778       if (cookie != element->state_cookie)
1779         goto interrupted;
1780
1781       /* could be success or failure */
1782       if (old_pending == GST_STATE (element)) {
1783         GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "got success");
1784         ret = GST_STATE_CHANGE_SUCCESS;
1785       } else {
1786         GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "got failure");
1787         ret = GST_STATE_CHANGE_FAILURE;
1788       }
1789     }
1790   }
1791   /* if nothing is pending anymore we can return SUCCESS */
1792   if (GST_STATE_PENDING (element) == GST_STATE_VOID_PENDING) {
1793     GST_CAT_LOG_OBJECT (GST_CAT_STATES, element, "nothing pending");
1794     ret = GST_STATE_CHANGE_SUCCESS;
1795   }
1796
1797 done:
1798   if (state)
1799     *state = GST_STATE (element);
1800   if (pending)
1801     *pending = GST_STATE_PENDING (element);
1802
1803   GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1804       "state current: %s, pending: %s, result: %s",
1805       gst_element_state_get_name (GST_STATE (element)),
1806       gst_element_state_get_name (GST_STATE_PENDING (element)),
1807       gst_element_state_change_return_get_name (ret));
1808   GST_OBJECT_UNLOCK (element);
1809
1810   return ret;
1811
1812 interrupted:
1813   {
1814     if (state)
1815       *state = GST_STATE_VOID_PENDING;
1816     if (pending)
1817       *pending = GST_STATE_VOID_PENDING;
1818
1819     GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "get_state() interruped");
1820
1821     GST_OBJECT_UNLOCK (element);
1822
1823     return GST_STATE_CHANGE_FAILURE;
1824   }
1825 }
1826
1827 /**
1828  * gst_element_get_state:
1829  * @element: a #GstElement to get the state of.
1830  * @state: a pointer to #GstState to hold the state. Can be %NULL.
1831  * @pending: a pointer to #GstState to hold the pending state.
1832  *           Can be %NULL.
1833  * @timeout: a #GstClockTime to specify the timeout for an async
1834  *           state change or %GST_CLOCK_TIME_NONE for infinite timeout.
1835  *
1836  * Gets the state of the element.
1837  *
1838  * For elements that performed an ASYNC state change, as reported by
1839  * gst_element_set_state(), this function will block up to the
1840  * specified timeout value for the state change to complete.
1841  * If the element completes the state change or goes into
1842  * an error, this function returns immediately with a return value of
1843  * %GST_STATE_CHANGE_SUCCESS or %GST_STATE_CHANGE_FAILURE respectively.
1844  *
1845  * For elements that did not return %GST_STATE_CHANGE_ASYNC, this function
1846  * returns the current and pending state immediately.
1847  *
1848  * This function returns %GST_STATE_CHANGE_NO_PREROLL if the element
1849  * successfully changed its state but is not able to provide data yet.
1850  * This mostly
1851  * happens for live sources that only produce data in the PLAYING state.
1852  * While the state change return is equivalent to %GST_STATE_CHANGE_SUCCESS, it
1853  * is returned to the application to signal that some sink elements might not
1854  * be able to complete their state change because an element is not producing
1855  * data to complete the preroll. When setting the element to playing,
1856  * the preroll will complete and playback will start.
1857  *
1858  * Returns: %GST_STATE_CHANGE_SUCCESS if the element has no more pending state
1859  *          and the last state change succeeded, %GST_STATE_CHANGE_ASYNC if the
1860  *          element is still performing a state change or
1861  *          %GST_STATE_CHANGE_FAILURE if the last state change failed.
1862  *
1863  * MT safe.
1864  */
1865 GstStateChangeReturn
1866 gst_element_get_state (GstElement * element,
1867     GstState * state, GstState * pending, GstClockTime timeout)
1868 {
1869   GstElementClass *oclass;
1870   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
1871
1872   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_CHANGE_FAILURE);
1873
1874   oclass = GST_ELEMENT_GET_CLASS (element);
1875
1876   if (oclass->get_state)
1877     result = (oclass->get_state) (element, state, pending, timeout);
1878
1879   return result;
1880 }
1881
1882 /**
1883  * gst_element_abort_state:
1884  * @element: a #GstElement to abort the state of.
1885  *
1886  * Abort the state change of the element. This function is used
1887  * by elements that do asynchronous state changes and find out
1888  * something is wrong.
1889  *
1890  * This function should be called with the STATE_LOCK held.
1891  *
1892  * MT safe.
1893  */
1894 void
1895 gst_element_abort_state (GstElement * element)
1896 {
1897   GstState pending;
1898
1899 #ifndef GST_DISABLE_GST_DEBUG
1900   GstState old_state;
1901 #endif
1902
1903   g_return_if_fail (GST_IS_ELEMENT (element));
1904
1905   GST_OBJECT_LOCK (element);
1906   pending = GST_STATE_PENDING (element);
1907
1908   if (pending == GST_STATE_VOID_PENDING ||
1909       GST_STATE_RETURN (element) == GST_STATE_CHANGE_FAILURE)
1910     goto nothing_aborted;
1911
1912 #ifndef GST_DISABLE_GST_DEBUG
1913   old_state = GST_STATE (element);
1914
1915   GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1916       "aborting state from %s to %s", gst_element_state_get_name (old_state),
1917       gst_element_state_get_name (pending));
1918 #endif
1919
1920   /* flag error */
1921   GST_STATE_RETURN (element) = GST_STATE_CHANGE_FAILURE;
1922
1923   GST_STATE_BROADCAST (element);
1924   GST_OBJECT_UNLOCK (element);
1925
1926   return;
1927
1928 nothing_aborted:
1929   {
1930     GST_OBJECT_UNLOCK (element);
1931     return;
1932   }
1933 }
1934
1935 /**
1936  * gst_element_continue_state:   
1937  * @element: a #GstElement to continue the state change of.      
1938  * @ret: The previous state return value
1939  *       
1940  * Commit the state change of the element and proceed to the next 
1941  * pending state if any. This function is used   
1942  * by elements that do asynchronous state changes.       
1943  * The core will normally call this method automatically when an         
1944  * element returned %GST_STATE_CHANGE_SUCCESS from the state change function.      
1945  * Elements that return %GST_STATE_CHANGE_ASYNC from the change_state function
1946  * should eventually call this method from the streaming thread to signal       
1947  * successfull state change completion.          
1948  *       
1949  * If after calling this method the element still has not reached        
1950  * the pending state, the next state change is performed.        
1951  *       
1952  * Returns: The result of the commit state change.       
1953  *       
1954  * MT safe.      
1955  */
1956 GstStateChangeReturn
1957 gst_element_continue_state (GstElement * element, GstStateChangeReturn ret)
1958 {
1959   GstState pending;
1960   GstState old_ret, old_state, old_next;
1961   GstState current, next;
1962   GstMessage *message;
1963   GstStateChange transition;
1964
1965   GST_OBJECT_LOCK (element);
1966   old_ret = (GstState) GST_STATE_RETURN (element);
1967   GST_STATE_RETURN (element) = ret;
1968   pending = GST_STATE_PENDING (element);
1969
1970   /* check if there is something to commit */
1971   if (pending == GST_STATE_VOID_PENDING)
1972     goto nothing_pending;
1973
1974   old_state = GST_STATE (element);
1975   /* this is the state we should go to next */
1976   old_next = GST_STATE_NEXT (element);
1977   /* update current state */
1978   current = GST_STATE (element) = old_next;
1979
1980   /* see if we reached the final state */
1981   if (pending == current)
1982     goto complete;
1983
1984   next = GST_STATE_GET_NEXT (current, pending);
1985   transition = (GstStateChange) GST_STATE_TRANSITION (current, next);
1986
1987   GST_STATE_NEXT (element) = next;
1988   /* mark busy */
1989   GST_STATE_RETURN (element) = GST_STATE_CHANGE_ASYNC;
1990   GST_OBJECT_UNLOCK (element);
1991
1992   GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1993       "committing state from %s to %s, pending %s",
1994       gst_element_state_get_name (old_state),
1995       gst_element_state_get_name (old_next),
1996       gst_element_state_get_name (pending));
1997
1998   message = gst_message_new_state_changed (GST_OBJECT_CAST (element),
1999       old_state, old_next, pending);
2000   gst_element_post_message (element, message);
2001
2002   GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
2003       "continue state change %s to %s, final %s",
2004       gst_element_state_get_name (current),
2005       gst_element_state_get_name (next), gst_element_state_get_name (pending));
2006
2007   ret = gst_element_change_state (element, transition);
2008
2009   return ret;
2010
2011 nothing_pending:
2012   {
2013     GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "nothing pending");
2014     GST_OBJECT_UNLOCK (element);
2015     return ret;
2016   }
2017 complete:
2018   {
2019     GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING;
2020     GST_STATE_NEXT (element) = GST_STATE_VOID_PENDING;
2021
2022     GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "completed state change");
2023     GST_OBJECT_UNLOCK (element);
2024
2025     /* don't post silly messages with the same state. This can happen
2026      * when an element state is changed to what it already was. For bins
2027      * this can be the result of a lost state, which we check with the
2028      * previous return value. 
2029      * We do signal the cond though as a _get_state() might be blocking 
2030      * on it. */
2031     if (old_state != old_next || old_ret == GST_STATE_CHANGE_ASYNC) {
2032       message = gst_message_new_state_changed (GST_OBJECT_CAST (element),
2033           old_state, old_next, GST_STATE_VOID_PENDING);
2034       gst_element_post_message (element, message);
2035     }
2036
2037     GST_STATE_BROADCAST (element);
2038
2039     return ret;
2040   }
2041 }
2042
2043 /**
2044  * gst_element_lost_state:
2045  * @element: a #GstElement the state is lost of
2046  *
2047  * Brings the element to the lost state. The current state of the
2048  * element is copied to the pending state so that any call to
2049  * gst_element_get_state() will return %GST_STATE_CHANGE_ASYNC.
2050  *
2051  * This is mostly used for elements that lost their preroll buffer
2052  * in the %GST_STATE_PAUSED state after a flush, they become %GST_STATE_PAUSED
2053  * again if a new preroll buffer is queued.
2054  * This function can only be called when the element is currently
2055  * not in error or an async state change.
2056  *
2057  * This function can only be called with the STATE_LOCK held.
2058  *
2059  * MT safe.
2060  */
2061 void
2062 gst_element_lost_state (GstElement * element)
2063 {
2064   GstState current_state;
2065   GstMessage *message;
2066
2067   g_return_if_fail (GST_IS_ELEMENT (element));
2068
2069   GST_OBJECT_LOCK (element);
2070   if (GST_STATE_PENDING (element) != GST_STATE_VOID_PENDING ||
2071       GST_STATE_RETURN (element) == GST_STATE_CHANGE_FAILURE)
2072     goto nothing_lost;
2073
2074   current_state = GST_STATE (element);
2075
2076   GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2077       "lost state of %s", gst_element_state_get_name (current_state));
2078
2079   GST_STATE_NEXT (element) = current_state;
2080   GST_STATE_PENDING (element) = current_state;
2081   GST_STATE_RETURN (element) = GST_STATE_CHANGE_ASYNC;
2082   GST_OBJECT_UNLOCK (element);
2083
2084   message = gst_message_new_state_changed (GST_OBJECT_CAST (element),
2085       current_state, current_state, current_state);
2086   gst_element_post_message (element, message);
2087
2088   /* and mark us dirty */
2089   message = gst_message_new_state_dirty (GST_OBJECT_CAST (element));
2090   gst_element_post_message (element, message);
2091
2092   return;
2093
2094 nothing_lost:
2095   {
2096     GST_OBJECT_UNLOCK (element);
2097     return;
2098   }
2099 }
2100
2101 /**
2102  * gst_element_set_state:
2103  * @element: a #GstElement to change state of.
2104  * @state: the element's new #GstState.
2105  *
2106  * Sets the state of the element. This function will try to set the
2107  * requested state by going through all the intermediary states and calling
2108  * the class's state change function for each.
2109  *
2110  * This function can return #GST_STATE_CHANGE_ASYNC, in which case the
2111  * element will perform the remainder of the state change asynchronously in
2112  * another thread.
2113  * An application can use gst_element_get_state() to wait for the completion
2114  * of the state change or it can wait for a state change message on the bus.
2115  *
2116  * Returns: Result of the state change using #GstStateChangeReturn.
2117  *
2118  * MT safe.
2119  */
2120 GstStateChangeReturn
2121 gst_element_set_state (GstElement * element, GstState state)
2122 {
2123   GstElementClass *oclass;
2124   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2125
2126   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_CHANGE_FAILURE);
2127
2128   oclass = GST_ELEMENT_GET_CLASS (element);
2129
2130   if (oclass->set_state)
2131     result = (oclass->set_state) (element, state);
2132
2133   return result;
2134 }
2135
2136 /*
2137  * default set state function, calculates the next state based
2138  * on current state and calls the change_state function 
2139  */
2140 static GstStateChangeReturn
2141 gst_element_set_state_func (GstElement * element, GstState state)
2142 {
2143   GstState current, next, old_pending;
2144   GstStateChangeReturn ret;
2145   GstStateChange transition;
2146   GstStateChangeReturn old_ret;
2147
2148   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_CHANGE_FAILURE);
2149
2150   GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "set_state to %s",
2151       gst_element_state_get_name (state));
2152
2153   /* state lock is taken to protect the set_state() and get_state() 
2154    * procedures, it does not lock any variables. */
2155   GST_STATE_LOCK (element);
2156
2157   /* now calculate how to get to the new state */
2158   GST_OBJECT_LOCK (element);
2159   old_ret = GST_STATE_RETURN (element);
2160   /* previous state change returned an error, remove all pending
2161    * and next states */
2162   if (old_ret == GST_STATE_CHANGE_FAILURE) {
2163     GST_STATE_NEXT (element) = GST_STATE_VOID_PENDING;
2164     GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING;
2165     GST_STATE_RETURN (element) = GST_STATE_CHANGE_SUCCESS;
2166   }
2167
2168   current = GST_STATE (element);
2169   next = GST_STATE_NEXT (element);
2170   old_pending = GST_STATE_PENDING (element);
2171   /* increment state cookie so that we can track each state change */
2172   element->state_cookie++;
2173
2174   /* this is the (new) state we should go to */
2175   GST_STATE_PENDING (element) = state;
2176
2177   GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2178       "current %s, old_pending %s, next %s, old return %s",
2179       gst_element_state_get_name (current),
2180       gst_element_state_get_name (old_pending),
2181       gst_element_state_get_name (next),
2182       gst_element_state_change_return_get_name (old_ret));
2183
2184   /* if the element was busy doing a state change, we just update the
2185    * target state, it'll get to it async then. */
2186   if (old_pending != GST_STATE_VOID_PENDING) {
2187     /* upwards state change will happen ASYNC */
2188     if (old_pending <= state)
2189       goto was_busy;
2190     /* element is going to this state already */
2191     else if (next == state)
2192       goto was_busy;
2193     /* element was performing an ASYNC upward state change and
2194      * we request to go downward again. Start from the next pending
2195      * state then. */
2196     else if (next > state
2197         && GST_STATE_RETURN (element) == GST_STATE_CHANGE_ASYNC) {
2198       current = next;
2199     }
2200   }
2201   next = GST_STATE_GET_NEXT (current, state);
2202   /* now we store the next state */
2203   GST_STATE_NEXT (element) = next;
2204   /* mark busy, we need to check that there is actually a state change
2205    * to be done else we could accidentally override SUCCESS/NO_PREROLL and
2206    * the default element change_state function has no way to know what the
2207    * old value was... could consider this a FIXME...*/
2208   if (current != next)
2209     GST_STATE_RETURN (element) = GST_STATE_CHANGE_ASYNC;
2210
2211   transition = (GstStateChange) GST_STATE_TRANSITION (current, next);
2212
2213   GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2214       "%s: setting state from %s to %s",
2215       (next != state ? "intermediate" : "final"),
2216       gst_element_state_get_name (current), gst_element_state_get_name (next));
2217
2218   /* now signal any waiters, they will error since the cookie was increased */
2219   GST_STATE_BROADCAST (element);
2220
2221   GST_OBJECT_UNLOCK (element);
2222
2223   ret = gst_element_change_state (element, transition);
2224
2225   GST_STATE_UNLOCK (element);
2226
2227   GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "returned %s",
2228       gst_element_state_change_return_get_name (ret));
2229
2230   return ret;
2231
2232 was_busy:
2233   {
2234     GST_STATE_RETURN (element) = GST_STATE_CHANGE_ASYNC;
2235     GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2236         "element was busy with async state change");
2237     GST_OBJECT_UNLOCK (element);
2238
2239     GST_STATE_UNLOCK (element);
2240
2241     return GST_STATE_CHANGE_ASYNC;
2242   }
2243 }
2244
2245 /* with STATE_LOCK */
2246 static GstStateChangeReturn
2247 gst_element_change_state (GstElement * element, GstStateChange transition)
2248 {
2249   GstElementClass *oclass;
2250   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
2251   GstState current;
2252   GstState next;
2253
2254   oclass = GST_ELEMENT_GET_CLASS (element);
2255
2256   /* start with the current state. */
2257   current = (GstState) GST_STATE_TRANSITION_CURRENT (transition);
2258   next = GST_STATE_TRANSITION_NEXT (transition);
2259
2260   /* call the state change function so it can set the state */
2261   if (oclass->change_state)
2262     ret = (oclass->change_state) (element, transition);
2263   else
2264     ret = GST_STATE_CHANGE_FAILURE;
2265
2266   switch (ret) {
2267     case GST_STATE_CHANGE_FAILURE:
2268       GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
2269           "have FAILURE change_state return");
2270       /* state change failure */
2271       gst_element_abort_state (element);
2272       break;
2273     case GST_STATE_CHANGE_ASYNC:
2274       GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2275           "element will change state ASYNC");
2276
2277       /* if we go upwards, we give the app a change to wait for
2278        * completion */
2279       if (current < next)
2280         goto async;
2281
2282       /* else we just continue the state change downwards */
2283       GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
2284           "forcing commit state %s < %s",
2285           gst_element_state_get_name (current),
2286           gst_element_state_get_name (next));
2287
2288       ret = gst_element_continue_state (element, GST_STATE_CHANGE_SUCCESS);
2289       break;
2290     case GST_STATE_CHANGE_SUCCESS:
2291       GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2292           "element changed state SUCCESS");
2293       /* we can commit the state now which will proceeed to
2294        * the next state */
2295       ret = gst_element_continue_state (element, ret);
2296       break;
2297     case GST_STATE_CHANGE_NO_PREROLL:
2298       GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2299           "element changed state NO_PREROLL");
2300       /* we can commit the state now which will proceeed to
2301        * the next state */
2302       ret = gst_element_continue_state (element, ret);
2303       break;
2304     default:
2305       goto invalid_return;
2306   }
2307
2308   GST_CAT_LOG_OBJECT (GST_CAT_STATES, element, "exit state change %d", ret);
2309
2310   return ret;
2311
2312 async:
2313   GST_CAT_LOG_OBJECT (GST_CAT_STATES, element, "exit async state change %d",
2314       ret);
2315
2316   return ret;
2317
2318   /* ERROR */
2319 invalid_return:
2320   {
2321     GST_OBJECT_LOCK (element);
2322     /* somebody added a GST_STATE_ and forgot to do stuff here ! */
2323     g_critical ("%s: unknown return value %d from a state change function",
2324         GST_ELEMENT_NAME (element), ret);
2325
2326     ret = GST_STATE_CHANGE_FAILURE;
2327     GST_STATE_RETURN (element) = ret;
2328     GST_OBJECT_UNLOCK (element);
2329
2330     return ret;
2331   }
2332 }
2333
2334 /* gst_iterator_fold functions for pads_activate
2335  * Note how we don't stop the iterator when we fail an activation. This is
2336  * probably a FIXME since when one pad activation fails, we don't want to
2337  * continue our state change. */
2338 static gboolean
2339 activate_pads (GstPad * pad, GValue * ret, gboolean * active)
2340 {
2341   if (!gst_pad_set_active (pad, *active))
2342     g_value_set_boolean (ret, FALSE);
2343
2344   /* unref the object that was reffed for us by _fold */
2345   gst_object_unref (pad);
2346   return TRUE;
2347 }
2348
2349 /* set the caps on the pad to NULL */
2350 static gboolean
2351 clear_caps (GstPad * pad, GValue * ret, gboolean * active)
2352 {
2353   gst_pad_set_caps (pad, NULL);
2354   gst_object_unref (pad);
2355   return TRUE;
2356 }
2357
2358 /* returns false on error or early cutout (will never happen because the fold
2359  * function always returns TRUE, see FIXME above) of the fold, true if all
2360  * pads in @iter were (de)activated successfully. */
2361 static gboolean
2362 iterator_activate_fold_with_resync (GstIterator * iter,
2363     GstIteratorFoldFunction func, gpointer user_data)
2364 {
2365   GstIteratorResult ires;
2366   GValue ret = { 0 };
2367
2368   /* no need to unset this later, it's just a boolean */
2369   g_value_init (&ret, G_TYPE_BOOLEAN);
2370   g_value_set_boolean (&ret, TRUE);
2371
2372   while (1) {
2373     ires = gst_iterator_fold (iter, func, &ret, user_data);
2374     switch (ires) {
2375       case GST_ITERATOR_RESYNC:
2376         /* need to reset the result again */
2377         g_value_set_boolean (&ret, TRUE);
2378         gst_iterator_resync (iter);
2379         break;
2380       case GST_ITERATOR_DONE:
2381         /* all pads iterated, return collected value */
2382         goto done;
2383       default:
2384         /* iterator returned _ERROR or premature end with _OK, 
2385          * mark an error and exit */
2386         g_value_set_boolean (&ret, FALSE);
2387         goto done;
2388     }
2389   }
2390 done:
2391   /* return collected value */
2392   return g_value_get_boolean (&ret);
2393 }
2394
2395 /* is called with STATE_LOCK
2396  *
2397  * Pads are activated from source pads to sinkpads. 
2398  */
2399 static gboolean
2400 gst_element_pads_activate (GstElement * element, gboolean active)
2401 {
2402   GstIterator *iter;
2403   gboolean res;
2404
2405   GST_DEBUG_OBJECT (element, "pads_activate with active %d", active);
2406
2407   iter = gst_element_iterate_src_pads (element);
2408   res =
2409       iterator_activate_fold_with_resync (iter,
2410       (GstIteratorFoldFunction) activate_pads, &active);
2411   gst_iterator_free (iter);
2412   if (G_UNLIKELY (!res))
2413     goto src_failed;
2414
2415   iter = gst_element_iterate_sink_pads (element);
2416   res =
2417       iterator_activate_fold_with_resync (iter,
2418       (GstIteratorFoldFunction) activate_pads, &active);
2419   gst_iterator_free (iter);
2420   if (G_UNLIKELY (!res))
2421     goto sink_failed;
2422
2423   if (!active) {
2424     /* clear the caps on all pads, this should never fail */
2425     iter = gst_element_iterate_pads (element);
2426     res =
2427         iterator_activate_fold_with_resync (iter,
2428         (GstIteratorFoldFunction) clear_caps, &active);
2429     gst_iterator_free (iter);
2430     if (G_UNLIKELY (!res))
2431       goto caps_failed;
2432   }
2433
2434   GST_DEBUG_OBJECT (element, "pads_activate successful");
2435
2436   return TRUE;
2437
2438   /* ERRORS */
2439 src_failed:
2440   {
2441     GST_DEBUG_OBJECT (element, "source pads_activate failed");
2442     return FALSE;
2443   }
2444 sink_failed:
2445   {
2446     GST_DEBUG_OBJECT (element, "sink pads_activate failed");
2447     return FALSE;
2448   }
2449 caps_failed:
2450   {
2451     GST_DEBUG_OBJECT (element, "failed to clear caps on pads");
2452     return FALSE;
2453   }
2454 }
2455
2456 /* is called with STATE_LOCK */
2457 static GstStateChangeReturn
2458 gst_element_change_state_func (GstElement * element, GstStateChange transition)
2459 {
2460   GstState state, next;
2461   GstStateChangeReturn result = GST_STATE_CHANGE_SUCCESS;
2462
2463   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_CHANGE_FAILURE);
2464
2465   state = (GstState) GST_STATE_TRANSITION_CURRENT (transition);
2466   next = GST_STATE_TRANSITION_NEXT (transition);
2467
2468   /* if the element already is in the given state, we just return success */
2469   if (next == GST_STATE_VOID_PENDING || state == next)
2470     goto was_ok;
2471
2472   GST_CAT_LOG_OBJECT (GST_CAT_STATES, element,
2473       "default handler tries setting state from %s to %s (%04x)",
2474       gst_element_state_get_name (state),
2475       gst_element_state_get_name (next), transition);
2476
2477   switch (transition) {
2478     case GST_STATE_CHANGE_NULL_TO_READY:
2479       break;
2480     case GST_STATE_CHANGE_READY_TO_PAUSED:
2481       if (!gst_element_pads_activate (element, TRUE)) {
2482         result = GST_STATE_CHANGE_FAILURE;
2483       }
2484       break;
2485     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
2486       break;
2487     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
2488       break;
2489     case GST_STATE_CHANGE_PAUSED_TO_READY:
2490     case GST_STATE_CHANGE_READY_TO_NULL:
2491       /* deactivate pads in both cases, since they are activated on
2492          ready->paused but the element might not have made it to paused */
2493       if (!gst_element_pads_activate (element, FALSE)) {
2494         result = GST_STATE_CHANGE_FAILURE;
2495       } else {
2496         gst_element_set_base_time (element, 0);
2497       }
2498       break;
2499     default:
2500       /* this will catch real but unhandled state changes;
2501        * can only be caused by:
2502        * - a new state was added
2503        * - somehow the element was asked to jump across an intermediate state
2504        */
2505       g_warning ("Unhandled state change from %s to %s",
2506           gst_element_state_get_name (state),
2507           gst_element_state_get_name (next));
2508       break;
2509   }
2510   return result;
2511
2512 was_ok:
2513   {
2514     GST_OBJECT_LOCK (element);
2515     result = GST_STATE_RETURN (element);
2516     GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2517         "element is already in the %s state",
2518         gst_element_state_get_name (state));
2519     GST_OBJECT_UNLOCK (element);
2520
2521     return result;
2522   }
2523 }
2524
2525 /**
2526  * gst_element_get_factory:
2527  * @element: a #GstElement to request the element factory of.
2528  *
2529  * Retrieves the factory that was used to create this element.
2530  *
2531  * Returns: the #GstElementFactory used for creating this element.
2532  * no refcounting is needed.
2533  */
2534 GstElementFactory *
2535 gst_element_get_factory (GstElement * element)
2536 {
2537   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
2538
2539   return GST_ELEMENT_GET_CLASS (element)->elementfactory;
2540 }
2541
2542 static void
2543 gst_element_dispose (GObject * object)
2544 {
2545   GstElement *element = GST_ELEMENT (object);
2546   GstClock **clock_p;
2547   GstBus **bus_p;
2548
2549   GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "dispose");
2550
2551   if (GST_STATE (element) != GST_STATE_NULL)
2552     goto not_null;
2553
2554   g_return_if_fail (GST_STATE_PENDING (element) == GST_STATE_VOID_PENDING);
2555
2556   GST_DEBUG_OBJECT (element, "removing %d pads", g_list_length (element->pads));
2557   /* first we break all our links with the outside */
2558   while (element->pads && element->pads->data) {
2559     /* don't call _remove_pad with NULL */
2560     gst_element_remove_pad (element, GST_PAD_CAST (element->pads->data));
2561   }
2562   if (G_UNLIKELY (element->pads != 0)) {
2563     g_critical ("could not remove pads from element %s",
2564         GST_STR_NULL (GST_OBJECT_NAME (object)));
2565   }
2566
2567   GST_OBJECT_LOCK (element);
2568   clock_p = &element->clock;
2569   bus_p = &element->bus;
2570   gst_object_replace ((GstObject **) clock_p, NULL);
2571   gst_object_replace ((GstObject **) bus_p, NULL);
2572   GST_OBJECT_UNLOCK (element);
2573
2574   GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "parent class dispose");
2575
2576   G_OBJECT_CLASS (parent_class)->dispose (object);
2577
2578   return;
2579
2580   /* ERRORS */
2581 not_null:
2582   {
2583     g_critical
2584         ("\nTrying to dispose element %s, but it is not in the NULL state.\n"
2585         "You need to explicitly set elements to the NULL state before\n"
2586         "dropping the final reference, to allow them to clean up.\n",
2587         GST_OBJECT_NAME (element));
2588     return;
2589   }
2590 }
2591
2592 static void
2593 gst_element_finalize (GObject * object)
2594 {
2595   GstElement *element = GST_ELEMENT (object);
2596
2597   GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "finalize");
2598
2599   GST_STATE_LOCK (element);
2600   if (element->state_cond)
2601     g_cond_free (element->state_cond);
2602   element->state_cond = NULL;
2603   GST_STATE_UNLOCK (element);
2604   g_static_rec_mutex_free (element->state_lock);
2605   g_free (element->state_lock);
2606   element->state_lock = NULL;
2607
2608   GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "finalize parent");
2609
2610   G_OBJECT_CLASS (parent_class)->finalize (object);
2611 }
2612
2613 #ifndef GST_DISABLE_LOADSAVE
2614 /**
2615  * gst_element_save_thyself:
2616  * @element: a #GstElement to save.
2617  * @parent: the xml parent node.
2618  *
2619  * Saves the element as part of the given XML structure.
2620  *
2621  * Returns: the new #xmlNodePtr.
2622  */
2623 static xmlNodePtr
2624 gst_element_save_thyself (GstObject * object, xmlNodePtr parent)
2625 {
2626   GList *pads;
2627   GstElementClass *oclass;
2628   GParamSpec **specs, *spec;
2629   guint nspecs;
2630   guint i;
2631   GValue value = { 0, };
2632   GstElement *element;
2633
2634   g_return_val_if_fail (GST_IS_ELEMENT (object), parent);
2635
2636   element = GST_ELEMENT (object);
2637
2638   oclass = GST_ELEMENT_GET_CLASS (element);
2639
2640   xmlNewChild (parent, NULL, (xmlChar *) "name",
2641       (xmlChar *) GST_ELEMENT_NAME (element));
2642
2643   if (oclass->elementfactory != NULL) {
2644     GstElementFactory *factory = (GstElementFactory *) oclass->elementfactory;
2645
2646     xmlNewChild (parent, NULL, (xmlChar *) "type",
2647         (xmlChar *) GST_PLUGIN_FEATURE (factory)->name);
2648   }
2649
2650   /* params */
2651   specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (object), &nspecs);
2652
2653   for (i = 0; i < nspecs; i++) {
2654     spec = specs[i];
2655     if (spec->flags & G_PARAM_READABLE) {
2656       xmlNodePtr param;
2657       char *contents;
2658
2659       g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (spec));
2660
2661       g_object_get_property (G_OBJECT (element), spec->name, &value);
2662       param = xmlNewChild (parent, NULL, (xmlChar *) "param", NULL);
2663       xmlNewChild (param, NULL, (xmlChar *) "name", (xmlChar *) spec->name);
2664
2665       if (G_IS_PARAM_SPEC_STRING (spec))
2666         contents = g_value_dup_string (&value);
2667       else if (G_IS_PARAM_SPEC_ENUM (spec))
2668         contents = g_strdup_printf ("%d", g_value_get_enum (&value));
2669       else if (G_IS_PARAM_SPEC_INT64 (spec))
2670         contents = g_strdup_printf ("%" G_GINT64_FORMAT,
2671             g_value_get_int64 (&value));
2672       else
2673         contents = g_strdup_value_contents (&value);
2674
2675       xmlNewChild (param, NULL, (xmlChar *) "value", (xmlChar *) contents);
2676       g_free (contents);
2677
2678       g_value_unset (&value);
2679     }
2680   }
2681
2682   g_free (specs);
2683
2684   pads = GST_ELEMENT_PADS (element);
2685
2686   while (pads) {
2687     GstPad *pad = GST_PAD_CAST (pads->data);
2688
2689     /* figure out if it's a direct pad or a ghostpad */
2690     if (GST_ELEMENT (GST_OBJECT_PARENT (pad)) == element) {
2691       xmlNodePtr padtag = xmlNewChild (parent, NULL, (xmlChar *) "pad", NULL);
2692
2693       gst_object_save_thyself (GST_OBJECT_CAST (pad), padtag);
2694     }
2695     pads = g_list_next (pads);
2696   }
2697
2698   return parent;
2699 }
2700
2701 static void
2702 gst_element_restore_thyself (GstObject * object, xmlNodePtr self)
2703 {
2704   xmlNodePtr children;
2705   GstElement *element;
2706   gchar *name = NULL;
2707   gchar *value = NULL;
2708
2709   element = GST_ELEMENT (object);
2710   g_return_if_fail (element != NULL);
2711
2712   /* parameters */
2713   children = self->xmlChildrenNode;
2714   while (children) {
2715     if (!strcmp ((char *) children->name, "param")) {
2716       xmlNodePtr child = children->xmlChildrenNode;
2717
2718       while (child) {
2719         if (!strcmp ((char *) child->name, "name")) {
2720           name = (gchar *) xmlNodeGetContent (child);
2721         } else if (!strcmp ((char *) child->name, "value")) {
2722           value = (gchar *) xmlNodeGetContent (child);
2723         }
2724         child = child->next;
2725       }
2726       /* FIXME: can this just be g_object_set ? */
2727       gst_util_set_object_arg (G_OBJECT (element), name, value);
2728       /* g_object_set (G_OBJECT (element), name, value, NULL); */
2729       g_free (name);
2730       g_free (value);
2731     }
2732     children = children->next;
2733   }
2734
2735   /* pads */
2736   children = self->xmlChildrenNode;
2737   while (children) {
2738     if (!strcmp ((char *) children->name, "pad")) {
2739       gst_pad_load_and_link (children, GST_OBJECT_CAST (element));
2740     }
2741     children = children->next;
2742   }
2743
2744   if (GST_OBJECT_CLASS (parent_class)->restore_thyself)
2745     (GST_OBJECT_CLASS (parent_class)->restore_thyself) (object, self);
2746 }
2747 #endif /* GST_DISABLE_LOADSAVE */
2748
2749 static void
2750 gst_element_set_bus_func (GstElement * element, GstBus * bus)
2751 {
2752   GstBus **bus_p;
2753
2754   g_return_if_fail (GST_IS_ELEMENT (element));
2755
2756   GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, element, "setting bus to %p", bus);
2757
2758   GST_OBJECT_LOCK (element);
2759   bus_p = &GST_ELEMENT_BUS (element);
2760   gst_object_replace ((GstObject **) bus_p, GST_OBJECT_CAST (bus));
2761   GST_OBJECT_UNLOCK (element);
2762 }
2763
2764 /**
2765  * gst_element_set_bus:
2766  * @element: a #GstElement to set the bus of.
2767  * @bus: the #GstBus to set.
2768  *
2769  * Sets the bus of the element. Increases the refcount on the bus.
2770  * For internal use only, unless you're testing elements.
2771  *
2772  * MT safe.
2773  */
2774 void
2775 gst_element_set_bus (GstElement * element, GstBus * bus)
2776 {
2777   GstElementClass *oclass;
2778
2779   g_return_if_fail (GST_IS_ELEMENT (element));
2780
2781   oclass = GST_ELEMENT_GET_CLASS (element);
2782
2783   if (oclass->set_bus)
2784     oclass->set_bus (element, bus);
2785 }
2786
2787 /**
2788  * gst_element_get_bus:
2789  * @element: a #GstElement to get the bus of.
2790  *
2791  * Returns the bus of the element.
2792  *
2793  * Returns: the element's #GstBus. unref after usage.
2794  *
2795  * MT safe.
2796  */
2797 GstBus *
2798 gst_element_get_bus (GstElement * element)
2799 {
2800   GstBus *result = NULL;
2801
2802   g_return_val_if_fail (GST_IS_ELEMENT (element), result);
2803
2804   GST_OBJECT_LOCK (element);
2805   if ((result = GST_ELEMENT_BUS (element)))
2806     gst_object_ref (result);
2807   GST_OBJECT_UNLOCK (element);
2808
2809   GST_DEBUG_OBJECT (element, "got bus %" GST_PTR_FORMAT, result);
2810
2811   return result;
2812 }