docs/gst/Makefile.am: Disable a bunch of headers from being scanned
[platform/upstream/gstreamer.git] / gst / gstelement.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2000 Wim Taymans <wtay@chello.be>
4  *
5  * gstelement.c: The base element, all elements derive from this
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #include <glib.h>
24 #include <stdarg.h>
25 #include <gobject/gvaluecollector.h>
26 #include "gst_private.h"
27
28 #include "gstelement.h"
29 #include "gstbin.h"
30 #include "gstmarshal.h"
31 #include "gsterror.h"
32 #include "gstscheduler.h"
33 #include "gstevent.h"
34 #include "gstutils.h"
35 #include "gstinfo.h"
36 #include "gst-i18n-lib.h"
37
38 /* Element signals and args */
39 enum
40 {
41   STATE_CHANGE,
42   NEW_PAD,
43   PAD_REMOVED,
44   ERROR,
45   EOS,
46   FOUND_TAG,
47   /* add more above */
48   LAST_SIGNAL
49 };
50
51 enum
52 {
53   ARG_0
54       /* FILL ME */
55 };
56
57 extern void __gst_element_details_clear (GstElementDetails * dp);
58 extern void __gst_element_details_copy (GstElementDetails * dest,
59     const GstElementDetails * src);
60
61 static void gst_element_class_init (GstElementClass * klass);
62 static void gst_element_init (GstElement * element);
63 static void gst_element_base_class_init (gpointer g_class);
64 static void gst_element_base_class_finalize (gpointer g_class);
65
66 static void gst_element_real_set_property (GObject * object, guint prop_id,
67     const GValue * value, GParamSpec * pspec);
68 static void gst_element_real_get_property (GObject * object, guint prop_id,
69     GValue * value, GParamSpec * pspec);
70
71 static void gst_element_dispose (GObject * object);
72
73 static GstElementStateReturn gst_element_change_state (GstElement * element);
74 static void gst_element_error_func (GstElement * element, GstElement * source,
75     GError * error, gchar * debug);
76 static void gst_element_found_tag_func (GstElement * element,
77     GstElement * source, const GstTagList * tag_list);
78
79 #ifndef GST_DISABLE_LOADSAVE
80 static xmlNodePtr gst_element_save_thyself (GstObject * object,
81     xmlNodePtr parent);
82 static void gst_element_restore_thyself (GstObject * parent, xmlNodePtr self);
83 #endif
84
85 GType _gst_element_type = 0;
86
87 static GstObjectClass *parent_class = NULL;
88 static guint gst_element_signals[LAST_SIGNAL] = { 0 };
89
90 GType
91 gst_element_get_type (void)
92 {
93   if (!_gst_element_type) {
94     static const GTypeInfo element_info = {
95       sizeof (GstElementClass),
96       gst_element_base_class_init,
97       gst_element_base_class_finalize,
98       (GClassInitFunc) gst_element_class_init,
99       NULL,
100       NULL,
101       sizeof (GstElement),
102       0,
103       (GInstanceInitFunc) gst_element_init,
104       NULL
105     };
106
107     _gst_element_type = g_type_register_static (GST_TYPE_OBJECT, "GstElement",
108         &element_info, G_TYPE_FLAG_ABSTRACT);
109   }
110   return _gst_element_type;
111 }
112
113 static void
114 gst_element_class_init (GstElementClass * klass)
115 {
116   GObjectClass *gobject_class;
117   GstObjectClass *gstobject_class;
118
119   gobject_class = (GObjectClass *) klass;
120   gstobject_class = (GstObjectClass *) klass;
121
122   parent_class = g_type_class_ref (GST_TYPE_OBJECT);
123
124   gst_element_signals[STATE_CHANGE] =
125       g_signal_new ("state-change", G_TYPE_FROM_CLASS (klass),
126       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstElementClass, state_change), NULL,
127       NULL, gst_marshal_VOID__INT_INT, G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT);
128   gst_element_signals[NEW_PAD] =
129       g_signal_new ("new-pad", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
130       G_STRUCT_OFFSET (GstElementClass, new_pad), NULL, NULL,
131       gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT);
132   gst_element_signals[PAD_REMOVED] =
133       g_signal_new ("pad-removed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
134       G_STRUCT_OFFSET (GstElementClass, pad_removed), NULL, NULL,
135       gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT);
136   gst_element_signals[ERROR] =
137       g_signal_new ("error", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
138       G_STRUCT_OFFSET (GstElementClass, error), NULL, NULL,
139       gst_marshal_VOID__OBJECT_OBJECT_STRING, G_TYPE_NONE, 3, GST_TYPE_ELEMENT,
140       GST_TYPE_G_ERROR, G_TYPE_STRING);
141   gst_element_signals[EOS] =
142       g_signal_new ("eos", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
143       G_STRUCT_OFFSET (GstElementClass, eos), NULL, NULL,
144       gst_marshal_VOID__VOID, G_TYPE_NONE, 0);
145   gst_element_signals[FOUND_TAG] =
146       g_signal_new ("found-tag", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
147       G_STRUCT_OFFSET (GstElementClass, found_tag), NULL, NULL,
148       gst_marshal_VOID__OBJECT_BOXED, G_TYPE_NONE, 2, GST_TYPE_ELEMENT,
149       GST_TYPE_TAG_LIST);
150
151   gobject_class->set_property =
152       GST_DEBUG_FUNCPTR (gst_element_real_set_property);
153   gobject_class->get_property =
154       GST_DEBUG_FUNCPTR (gst_element_real_get_property);
155
156   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_element_dispose);
157
158 #ifndef GST_DISABLE_LOADSAVE
159   gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_element_save_thyself);
160   gstobject_class->restore_thyself =
161       GST_DEBUG_FUNCPTR (gst_element_restore_thyself);
162 #endif
163
164   klass->change_state = GST_DEBUG_FUNCPTR (gst_element_change_state);
165   klass->error = GST_DEBUG_FUNCPTR (gst_element_error_func);
166   klass->found_tag = GST_DEBUG_FUNCPTR (gst_element_found_tag_func);
167   klass->numpadtemplates = 0;
168
169   klass->elementfactory = NULL;
170 }
171
172 static void
173 gst_element_base_class_init (gpointer g_class)
174 {
175   GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
176   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
177
178
179   gobject_class->set_property =
180       GST_DEBUG_FUNCPTR (gst_element_real_set_property);
181   gobject_class->get_property =
182       GST_DEBUG_FUNCPTR (gst_element_real_get_property);
183
184   memset (&element_class->details, 0, sizeof (GstElementDetails));
185   element_class->padtemplates = NULL;
186 }
187
188 static void
189 gst_element_base_class_finalize (gpointer g_class)
190 {
191   GstElementClass *klass = GST_ELEMENT_CLASS (g_class);
192
193   g_list_foreach (klass->padtemplates, (GFunc) g_object_unref, NULL);
194   g_list_free (klass->padtemplates);
195   __gst_element_details_clear (&klass->details);
196 }
197
198 static void
199 gst_element_init (GstElement * element)
200 {
201   element->current_state = GST_STATE_NULL;
202   element->pending_state = GST_STATE_VOID_PENDING;
203   element->numpads = 0;
204   element->numsrcpads = 0;
205   element->numsinkpads = 0;
206   element->pads = NULL;
207   element->loopfunc = NULL;
208   element->sched = NULL;
209   element->clock = NULL;
210   element->sched_private = NULL;
211   element->state_mutex = g_mutex_new ();
212   element->state_cond = g_cond_new ();
213 }
214
215 static void
216 gst_element_real_set_property (GObject * object, guint prop_id,
217     const GValue * value, GParamSpec * pspec)
218 {
219   GstElementClass *oclass = GST_ELEMENT_GET_CLASS (object);
220
221   if (oclass->set_property)
222     (oclass->set_property) (object, prop_id, value, pspec);
223 }
224
225 static void
226 gst_element_real_get_property (GObject * object, guint prop_id, GValue * value,
227     GParamSpec * pspec)
228 {
229   GstElementClass *oclass = GST_ELEMENT_GET_CLASS (object);
230
231   if (oclass->get_property)
232     (oclass->get_property) (object, prop_id, value, pspec);
233 }
234
235 /** 
236  * gst_element_default_error:
237  * @object: a #GObject that signalled the error.
238  * @orig: the #GstObject that initiated the error.
239  * @error: the GError.
240  * @debug: an additional debug information string, or NULL.
241  *
242  * A default error signal callback to attach to an element.
243  * The user data passed to the g_signal_connect is ignored.
244  *
245  * The default handler will simply print the error string using g_print.
246  */
247 void
248 gst_element_default_error (GObject * object, GstObject * source, GError * error,
249     gchar * debug)
250 {
251   gchar *name = gst_object_get_path_string (source);
252
253   g_print (_("ERROR: from element %s: %s\n"), name, error->message);
254   if (debug)
255     g_print (_("Additional debug info:\n%s\n"), debug);
256
257   g_free (name);
258 }
259
260 typedef struct
261 {
262   const GParamSpec *pspec;
263   GValue value;
264 }
265 prop_value_t;
266
267 static void
268 element_set_property (GstElement * element, const GParamSpec * pspec,
269     const GValue * value)
270 {
271   prop_value_t *prop_value = g_new0 (prop_value_t, 1);
272
273   prop_value->pspec = pspec;
274   prop_value->value = *value;
275
276   g_async_queue_push (element->prop_value_queue, prop_value);
277 }
278
279 static void
280 element_get_property (GstElement * element, const GParamSpec * pspec,
281     GValue * value)
282 {
283   g_mutex_lock (element->property_mutex);
284   g_object_get_property ((GObject *) element, pspec->name, value);
285   g_mutex_unlock (element->property_mutex);
286 }
287
288 static void
289 gst_element_threadsafe_properties_pre_run (GstElement * element)
290 {
291   GST_DEBUG ("locking element %s", GST_OBJECT_NAME (element));
292   g_mutex_lock (element->property_mutex);
293   gst_element_set_pending_properties (element);
294 }
295
296 static void
297 gst_element_threadsafe_properties_post_run (GstElement * element)
298 {
299   GST_DEBUG ("unlocking element %s", GST_OBJECT_NAME (element));
300   g_mutex_unlock (element->property_mutex);
301 }
302
303 /**
304  * gst_element_enable_threadsafe_properties:
305  * @element: a #GstElement to enable threadsafe properties on.
306  *
307  * Installs an asynchronous queue, a mutex and pre- and post-run functions on
308  * this element so that properties on the element can be set in a 
309  * threadsafe way.
310  */
311 void
312 gst_element_enable_threadsafe_properties (GstElement * element)
313 {
314   g_return_if_fail (GST_IS_ELEMENT (element));
315
316   GST_FLAG_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES);
317   element->pre_run_func = gst_element_threadsafe_properties_pre_run;
318   element->post_run_func = gst_element_threadsafe_properties_post_run;
319   if (!element->prop_value_queue)
320     element->prop_value_queue = g_async_queue_new ();
321   if (!element->property_mutex)
322     element->property_mutex = g_mutex_new ();
323 }
324
325 /**
326  * gst_element_disable_threadsafe_properties:
327  * @element: a #GstElement to disable threadsafe properties on.
328  *
329  * Removes the threadsafe properties, post- and pre-run locks from
330  * this element.
331  */
332 void
333 gst_element_disable_threadsafe_properties (GstElement * element)
334 {
335   g_return_if_fail (GST_IS_ELEMENT (element));
336
337   GST_FLAG_UNSET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES);
338   element->pre_run_func = NULL;
339   element->post_run_func = NULL;
340   /* let's keep around that async queue */
341 }
342
343 /**
344  * gst_element_set_pending_properties:
345  * @element: a #GstElement to set the pending properties on.
346  *
347  * Sets all pending properties on the threadsafe properties enabled
348  * element.
349  */
350 void
351 gst_element_set_pending_properties (GstElement * element)
352 {
353   prop_value_t *prop_value;
354
355   while ((prop_value = g_async_queue_try_pop (element->prop_value_queue))) {
356     g_object_set_property ((GObject *) element, prop_value->pspec->name,
357         &prop_value->value);
358     g_value_unset (&prop_value->value);
359     g_free (prop_value);
360   }
361 }
362
363 /* following 6 functions taken mostly from gobject.c */
364
365 /**
366  * gst_element_set:
367  * @element: a #GstElement to set properties on.
368  * @first_property_name: the first property to set.
369  * @...: value of the first property, and more properties to set, ending
370  *       with NULL.
371  *
372  * Sets properties on an element. If the element uses threadsafe properties,
373  * they will be queued and set on the object when it is scheduled again.
374  */
375 void
376 gst_element_set (GstElement * element, const gchar * first_property_name, ...)
377 {
378   va_list var_args;
379
380   g_return_if_fail (GST_IS_ELEMENT (element));
381
382   va_start (var_args, first_property_name);
383   gst_element_set_valist (element, first_property_name, var_args);
384   va_end (var_args);
385 }
386
387 /**
388  * gst_element_get:
389  * @element: a #GstElement to get properties of.
390  * @first_property_name: the first property to get.
391  * @...: pointer to a variable to store the first property in, as well as 
392  * more properties to get, ending with NULL.
393  *
394  * Gets properties from an element. If the element uses threadsafe properties,
395  * the element will be locked before getting the given properties.
396  */
397 void
398 gst_element_get (GstElement * element, const gchar * first_property_name, ...)
399 {
400   va_list var_args;
401
402   g_return_if_fail (GST_IS_ELEMENT (element));
403
404   va_start (var_args, first_property_name);
405   gst_element_get_valist (element, first_property_name, var_args);
406   va_end (var_args);
407 }
408
409 /**
410  * gst_element_set_valist:
411  * @element: a #GstElement to set properties on.
412  * @first_property_name: the first property to set.
413  * @var_args: the var_args list of other properties to get.
414  *
415  * Sets properties on an element. If the element uses threadsafe properties,
416  * the property change will be put on the async queue.
417  */
418 void
419 gst_element_set_valist (GstElement * element, const gchar * first_property_name,
420     va_list var_args)
421 {
422   const gchar *name;
423   GObject *object;
424
425   g_return_if_fail (GST_IS_ELEMENT (element));
426
427   object = (GObject *) element;
428
429   GST_CAT_DEBUG (GST_CAT_PROPERTIES,
430       "setting valist of properties starting with %s on element %s",
431       first_property_name, gst_element_get_name (element));
432
433   if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
434     g_object_set_valist (object, first_property_name, var_args);
435     return;
436   }
437
438   g_object_ref (object);
439
440   name = first_property_name;
441
442   while (name) {
443     GValue value = { 0, };
444     GParamSpec *pspec;
445     gchar *error = NULL;
446
447     pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), name);
448
449     if (!pspec) {
450       g_warning ("%s: object class `%s' has no property named `%s'",
451           G_STRLOC, G_OBJECT_TYPE_NAME (object), name);
452       break;
453     }
454     if (!(pspec->flags & G_PARAM_WRITABLE)) {
455       g_warning ("%s: property `%s' of object class `%s' is not writable",
456           G_STRLOC, pspec->name, G_OBJECT_TYPE_NAME (object));
457       break;
458     }
459
460     g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
461
462     G_VALUE_COLLECT (&value, var_args, 0, &error);
463     if (error) {
464       g_warning ("%s: %s", G_STRLOC, error);
465       g_free (error);
466
467       /* we purposely leak the value here, it might not be
468        * in a sane state if an error condition occoured
469        */
470       break;
471     }
472
473     element_set_property (element, pspec, &value);
474     g_value_unset (&value);
475
476     name = va_arg (var_args, gchar *);
477   }
478
479   g_object_unref (object);
480 }
481
482 /**
483  * gst_element_get_valist:
484  * @element: a #GstElement to get properties of.
485  * @first_property_name: the first property to get.
486  * @var_args: the var_args list of other properties to get.
487  *
488  * Gets properties from an element. If the element uses threadsafe properties,
489  * the element will be locked before getting the given properties.
490  */
491 void
492 gst_element_get_valist (GstElement * element, const gchar * first_property_name,
493     va_list var_args)
494 {
495   const gchar *name;
496   GObject *object;
497
498   g_return_if_fail (GST_IS_ELEMENT (element));
499
500   object = (GObject *) element;
501
502   if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
503     g_object_get_valist (object, first_property_name, var_args);
504     return;
505   }
506
507   g_object_ref (object);
508
509   name = first_property_name;
510
511   while (name) {
512     GValue value = { 0, };
513     GParamSpec *pspec;
514     gchar *error;
515
516     pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), name);
517
518     if (!pspec) {
519       g_warning ("%s: object class `%s' has no property named `%s'",
520           G_STRLOC, G_OBJECT_TYPE_NAME (object), name);
521       break;
522     }
523     if (!(pspec->flags & G_PARAM_READABLE)) {
524       g_warning ("%s: property `%s' of object class `%s' is not readable",
525           G_STRLOC, pspec->name, G_OBJECT_TYPE_NAME (object));
526       break;
527     }
528
529     g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
530
531     element_get_property (element, pspec, &value);
532
533     G_VALUE_LCOPY (&value, var_args, 0, &error);
534     if (error) {
535       g_warning ("%s: %s", G_STRLOC, error);
536       g_free (error);
537       g_value_unset (&value);
538       break;
539     }
540
541     g_value_unset (&value);
542
543     name = va_arg (var_args, gchar *);
544   }
545
546   g_object_unref (object);
547 }
548
549 /**
550  * gst_element_set_property:
551  * @element: a #GstElement to set properties on.
552  * @property_name: the first property to get.
553  * @value: the #GValue that holds the value to set.
554  *
555  * Sets a property on an element. If the element uses threadsafe properties,
556  * the property will be put on the async queue.
557  */
558 void
559 gst_element_set_property (GstElement * element, const gchar * property_name,
560     const GValue * value)
561 {
562   GParamSpec *pspec;
563   GObject *object;
564
565   g_return_if_fail (GST_IS_ELEMENT (element));
566   g_return_if_fail (property_name != NULL);
567   g_return_if_fail (G_IS_VALUE (value));
568
569   object = (GObject *) element;
570
571   GST_CAT_DEBUG (GST_CAT_PROPERTIES, "setting property %s on element %s",
572       property_name, gst_element_get_name (element));
573   if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
574     g_object_set_property (object, property_name, value);
575     return;
576   }
577
578   g_object_ref (object);
579
580   pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object),
581       property_name);
582
583   if (!pspec)
584     g_warning ("%s: object class `%s' has no property named `%s'",
585         G_STRLOC, G_OBJECT_TYPE_NAME (object), property_name);
586   else
587     element_set_property (element, pspec, value);
588
589   g_object_unref (object);
590 }
591
592 /**
593  * gst_element_get_property:
594  * @element: a #GstElement to get properties of.
595  * @property_name: the first property to get.
596  * @value: the #GValue to store the property value in.
597  *
598  * Gets a property from an element. If the element uses threadsafe properties,
599  * the element will be locked before getting the given property.
600  */
601 void
602 gst_element_get_property (GstElement * element, const gchar * property_name,
603     GValue * value)
604 {
605   GParamSpec *pspec;
606   GObject *object;
607
608   g_return_if_fail (GST_IS_ELEMENT (element));
609   g_return_if_fail (property_name != NULL);
610   g_return_if_fail (G_IS_VALUE (value));
611
612   object = (GObject *) element;
613
614   if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
615     g_object_get_property (object, property_name, value);
616     return;
617   }
618
619   g_object_ref (object);
620
621   pspec =
622       g_object_class_find_property (G_OBJECT_GET_CLASS (object), property_name);
623
624   if (!pspec)
625     g_warning ("%s: object class `%s' has no property named `%s'",
626         G_STRLOC, G_OBJECT_TYPE_NAME (object), property_name);
627   else {
628     GValue *prop_value, tmp_value = { 0, };
629
630     /* auto-conversion of the callers value type
631      */
632     if (G_VALUE_TYPE (value) == G_PARAM_SPEC_VALUE_TYPE (pspec)) {
633       g_value_reset (value);
634       prop_value = value;
635     } else if (!g_value_type_transformable (G_PARAM_SPEC_VALUE_TYPE (pspec),
636             G_VALUE_TYPE (value))) {
637       g_warning
638           ("can't retrieve property `%s' of type `%s' as value of type `%s'",
639           pspec->name, g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
640           G_VALUE_TYPE_NAME (value));
641       g_object_unref (object);
642       return;
643     } else {
644       g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
645       prop_value = &tmp_value;
646     }
647     element_get_property (element, pspec, prop_value);
648     if (prop_value != value) {
649       g_value_transform (prop_value, value);
650       g_value_unset (&tmp_value);
651     }
652   }
653
654   g_object_unref (object);
655 }
656
657 static GstPad *
658 gst_element_request_pad (GstElement * element, GstPadTemplate * templ,
659     const gchar * name)
660 {
661   GstPad *newpad = NULL;
662   GstElementClass *oclass;
663
664   oclass = GST_ELEMENT_GET_CLASS (element);
665
666   if (oclass->request_new_pad)
667     newpad = (oclass->request_new_pad) (element, templ, name);
668
669   return newpad;
670 }
671
672 /**
673  * gst_element_release_request_pad:
674  * @element: a #GstElement to release the request pad of.
675  * @pad: the #GstPad to release.
676  *
677  * Makes the element free the previously requested pad as obtained
678  * with gst_element_get_request_pad().
679  */
680 void
681 gst_element_release_request_pad (GstElement * element, GstPad * pad)
682 {
683   GstElementClass *oclass;
684
685   g_return_if_fail (GST_IS_ELEMENT (element));
686   g_return_if_fail (GST_IS_PAD (pad));
687
688   oclass = GST_ELEMENT_GET_CLASS (element);
689
690   if (oclass->release_pad)
691     (oclass->release_pad) (element, pad);
692 }
693
694 /**
695  * gst_element_requires_clock:
696  * @element: a #GstElement to query
697  *
698  * Query if the element requiresd a clock
699  *
700  * Returns: TRUE if the element requires a clock
701  */
702 gboolean
703 gst_element_requires_clock (GstElement * element)
704 {
705   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
706
707   return (GST_ELEMENT_GET_CLASS (element)->set_clock != NULL);
708 }
709
710 /**
711  * gst_element_provides_clock:
712  * @element: a #GstElement to query
713  *
714  * Query if the element provides a clock
715  *
716  * Returns: TRUE if the element provides a clock
717  */
718 gboolean
719 gst_element_provides_clock (GstElement * element)
720 {
721   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
722
723   return (GST_ELEMENT_GET_CLASS (element)->get_clock != NULL);
724 }
725
726 /**
727  * gst_element_set_clock:
728  * @element: a #GstElement to set the clock for.
729  * @clock: the #GstClock to set for the element.
730  *
731  * Sets the clock for the element.
732  */
733 void
734 gst_element_set_clock (GstElement * element, GstClock * clock)
735 {
736   GstElementClass *oclass;
737
738   g_return_if_fail (GST_IS_ELEMENT (element));
739
740   oclass = GST_ELEMENT_GET_CLASS (element);
741
742   if (oclass->set_clock)
743     oclass->set_clock (element, clock);
744
745   gst_object_replace ((GstObject **) & element->clock, (GstObject *) clock);
746 }
747
748 /**
749  * gst_element_get_clock:
750  * @element: a #GstElement to get the clock of.
751  *
752  * Gets the clock of the element.
753  *
754  * Returns: the #GstClock of the element.
755  */
756 GstClock *
757 gst_element_get_clock (GstElement * element)
758 {
759   GstElementClass *oclass;
760
761   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
762
763   oclass = GST_ELEMENT_GET_CLASS (element);
764
765   if (oclass->get_clock)
766     return oclass->get_clock (element);
767
768   return NULL;
769 }
770
771 /**
772  * gst_element_clock_wait:
773  * @element: a #GstElement.
774  * @id: the #GstClock to use.
775  * @jitter: the difference between requested time and actual time.
776  *
777  * Waits for a specific time on the clock.
778  *
779  * Returns: the #GstClockReturn result of the wait operation.
780  */
781 GstClockReturn
782 gst_element_clock_wait (GstElement * element, GstClockID id,
783     GstClockTimeDiff * jitter)
784 {
785   GstClockReturn res;
786
787   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_CLOCK_ERROR);
788
789   if (GST_ELEMENT_SCHED (element)) {
790     GST_CAT_DEBUG (GST_CAT_CLOCK, "waiting on scheduler clock");
791     res =
792         gst_scheduler_clock_wait (GST_ELEMENT_SCHED (element), element, id,
793         jitter);
794   } else {
795     GST_CAT_DEBUG (GST_CAT_CLOCK, "no scheduler, returning GST_CLOCK_TIMEOUT");
796     res = GST_CLOCK_TIMEOUT;
797   }
798
799   return res;
800 }
801
802 #undef GST_CAT_DEFAULT
803 #define GST_CAT_DEFAULT GST_CAT_CLOCK
804 /**
805  * gst_element_get_time:
806  * @element: element to query
807  *
808  * Query the element's time. The element must use 
809  * 
810  * Returns: the current time of the element or #GST_CLOCK_TIME_NONE when there
811  *          is no time available.
812  */
813 GstClockTime
814 gst_element_get_time (GstElement * element)
815 {
816   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_CLOCK_TIME_NONE);
817
818   if (element->clock == NULL) {
819     GST_WARNING_OBJECT (element, "element queries time but has no clock");
820     return GST_CLOCK_TIME_NONE;
821   }
822   switch (element->current_state) {
823     case GST_STATE_NULL:
824     case GST_STATE_READY:
825       return GST_CLOCK_TIME_NONE;
826     case GST_STATE_PAUSED:
827       return element->base_time;
828     case GST_STATE_PLAYING:
829       return gst_clock_get_time (element->clock) - element->base_time;
830     default:
831       g_assert_not_reached ();
832       return GST_CLOCK_TIME_NONE;
833   }
834 }
835
836 /**
837  * gst_element_wait:
838  * @element: element that should wait
839  * @timestamp: wait until this time has arrived
840  *
841  * Waits until the given time has arrived. When this function returns successfully, 
842  * the time specified in the timestamp has passed.
843  * <note>This function can only be called on elements in #GST_STATE_PLAYING</note>
844  *
845  * Returns: TRUE on success
846  */
847 gboolean
848 gst_element_wait (GstElement * element, GstClockTime timestamp)
849 {
850   GstClockID id;
851   GstClockReturn ret;
852
853   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
854   g_return_val_if_fail (GST_IS_CLOCK (element->clock), FALSE);
855   g_return_val_if_fail (element->current_state == GST_STATE_PLAYING, FALSE);
856   g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
857
858   /* shortcut when we're already late... */
859   if (gst_element_get_time (element) >= timestamp) {
860     GST_INFO_OBJECT (element, "called gst_element_wait and was late");
861     return TRUE;
862   }
863
864   id = gst_clock_new_single_shot_id (element->clock,
865       element->base_time + timestamp);
866   ret = gst_element_clock_wait (element, id, NULL);
867   gst_clock_id_free (id);
868
869   return ret == GST_CLOCK_STOPPED;
870 }
871
872 /**
873  * gst_element_set_time:
874  * @element: element to set time on
875  * @time: time to set
876  *
877  * Sets the current time of the element. This function can be used when handling
878  * discont events. You can only call this function on an element with a clock in
879  * #GST_STATE_PAUSED or #GST_STATE_PLAYING. You might want to have a look at 
880  * gst_element_adjust_time(), if you want to adjust by a difference as that is
881  * more accurate.
882  */
883 void
884 gst_element_set_time (GstElement * element, GstClockTime time)
885 {
886   gst_element_set_time_delay (element, time, 0);
887 }
888
889 /**
890  * gst_element_set_time_delay:
891  * @element: element to set time on
892  * @time: time to set
893  * @delay: a delay to discount from the given time
894  *
895  * Sets the current time of the element to time - delay. This function can be
896  * used when handling discont events in elements writing to an external buffer,
897  * i. e., an audio sink that writes to a sound card that buffers the sound
898  * before playing it. The delay should be the current buffering delay.
899  *
900  * You can only call this function on an element with a clock in
901  * #GST_STATE_PAUSED or #GST_STATE_PLAYING. You might want to have a look at
902  * gst_element_adjust_time(), if you want to adjust by a difference as that is
903  * more accurate.
904  */
905 void
906 gst_element_set_time_delay (GstElement * element, GstClockTime time,
907     GstClockTime delay)
908 {
909   GstClockTime event_time;
910
911   g_return_if_fail (GST_IS_ELEMENT (element));
912   g_return_if_fail (GST_IS_CLOCK (element->clock));
913   g_return_if_fail (element->current_state >= GST_STATE_PAUSED);
914
915   switch (element->current_state) {
916     case GST_STATE_PAUSED:
917       element->base_time = time - delay;
918       break;
919     case GST_STATE_PLAYING:
920       event_time = gst_clock_get_event_time_delay (element->clock, delay);
921       GST_CAT_LOG_OBJECT (GST_CAT_CLOCK, element,
922           "clock time %llu: setting element time to %llu", event_time, time);
923       element->base_time = event_time - time;
924       break;
925     default:
926       g_assert_not_reached ();
927       break;
928   }
929 }
930
931 /**
932  * gst_element_adjust_time:
933  * @element: element to adjust time on
934  * @diff: difference to adjust
935  *
936  * Adjusts the current time of the element by the specified difference. This 
937  * function can be used when handling discont events. You can only call this 
938  * function on an element with a clock in #GST_STATE_PAUSED or 
939  * #GST_STATE_PLAYING. It is more accurate than gst_element_set_time().
940  */
941 void
942 gst_element_adjust_time (GstElement * element, GstClockTimeDiff diff)
943 {
944   GstClockTime time;
945
946   g_return_if_fail (GST_IS_ELEMENT (element));
947   g_return_if_fail (GST_IS_CLOCK (element->clock));
948   g_return_if_fail (element->current_state >= GST_STATE_PAUSED);
949
950   switch (element->current_state) {
951     case GST_STATE_PAUSED:
952       if (diff < 0 && element->base_time < abs (diff)) {
953         g_warning ("attempted to set the current time of element %s below 0",
954             GST_OBJECT_NAME (element));
955         element->base_time = 0;
956       } else {
957         element->base_time += diff;
958       }
959       break;
960     case GST_STATE_PLAYING:
961       time = gst_clock_get_time (element->clock);
962       if (time < element->base_time - diff) {
963         g_warning ("attempted to set the current time of element %s below 0",
964             GST_OBJECT_NAME (element));
965         element->base_time = time;
966       } else {
967         element->base_time -= diff;
968       }
969       break;
970     default:
971       g_assert_not_reached ();
972       break;
973   }
974 }
975
976 #undef GST_CAT_DEFAULT
977
978 #ifndef GST_DISABLE_INDEX
979 /**
980  * gst_element_is_indexable:
981  * @element: a #GstElement.
982  *
983  * Queries if the element can be indexed.
984  *
985  * Returns: TRUE if the element can be indexed.
986  */
987 gboolean
988 gst_element_is_indexable (GstElement * element)
989 {
990   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
991
992   return (GST_ELEMENT_GET_CLASS (element)->set_index != NULL);
993 }
994
995 /**
996  * gst_element_set_index:
997  * @element: a #GstElement.
998  * @index: a #GstIndex.
999  *
1000  * Set the specified GstIndex on the element.
1001  */
1002 void
1003 gst_element_set_index (GstElement * element, GstIndex * index)
1004 {
1005   GstElementClass *oclass;
1006
1007   g_return_if_fail (GST_IS_ELEMENT (element));
1008   g_return_if_fail (GST_IS_INDEX (index));
1009
1010   oclass = GST_ELEMENT_GET_CLASS (element);
1011
1012   if (oclass->set_index)
1013     oclass->set_index (element, index);
1014 }
1015
1016 /**
1017  * gst_element_get_index:
1018  * @element: a #GstElement.
1019  *
1020  * Gets the index from the element.
1021  *
1022  * Returns: a #GstIndex or NULL when no index was set on the
1023  * element.
1024  */
1025 GstIndex *
1026 gst_element_get_index (GstElement * element)
1027 {
1028   GstElementClass *oclass;
1029
1030   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1031
1032   oclass = GST_ELEMENT_GET_CLASS (element);
1033
1034   if (oclass->get_index)
1035     return oclass->get_index (element);
1036
1037   return NULL;
1038 }
1039 #endif
1040
1041 /**
1042  * gst_element_release_locks:
1043  * @element: a #GstElement to release all locks on.
1044  *
1045  * Instruct the element to release all the locks it is holding, such as
1046  * blocking reads, waiting for the clock, ...
1047  *
1048  * Returns: TRUE if the locks could be released.
1049  */
1050 gboolean
1051 gst_element_release_locks (GstElement * element)
1052 {
1053   GstElementClass *oclass;
1054
1055   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1056
1057   oclass = GST_ELEMENT_GET_CLASS (element);
1058
1059   if (oclass->release_locks)
1060     return oclass->release_locks (element);
1061
1062   return TRUE;
1063 }
1064
1065 /**
1066  * gst_element_add_pad:
1067  * @element: a #GstElement to add the pad to.
1068  * @pad: the #GstPad to add to the element.
1069  *
1070  * Adds a pad (link point) to @element. @pad's parent will be set to @element;
1071  * see gst_object_set_parent() for refcounting information.
1072  *
1073  * Pads are automatically activated when the element is in state PLAYING.
1074  */
1075 void
1076 gst_element_add_pad (GstElement * element, GstPad * pad)
1077 {
1078   g_return_if_fail (GST_IS_ELEMENT (element));
1079   g_return_if_fail (GST_IS_PAD (pad));
1080
1081   /* first check to make sure the pad hasn't already been added to another
1082    * element */
1083   g_return_if_fail (GST_PAD_PARENT (pad) == NULL);
1084
1085   /* then check to see if there's already a pad by that name here */
1086   g_return_if_fail (gst_object_check_uniqueness (element->pads,
1087           GST_PAD_NAME (pad)) == TRUE);
1088
1089   GST_CAT_INFO_OBJECT (GST_CAT_ELEMENT_PADS, element, "adding pad '%s'",
1090       GST_STR_NULL (GST_OBJECT_NAME (pad)));
1091
1092   /* set the pad's parent */
1093   gst_object_set_parent (GST_OBJECT (pad), GST_OBJECT (element));
1094
1095   /* add it to the list */
1096   element->pads = g_list_append (element->pads, pad);
1097   element->numpads++;
1098
1099   switch (gst_pad_get_direction (pad)) {
1100     case GST_PAD_SRC:
1101       element->numsrcpads++;
1102       break;
1103     case GST_PAD_SINK:
1104       element->numsinkpads++;
1105       break;
1106     default:
1107       /* can happen for ghost pads */
1108       break;
1109   }
1110
1111   /* activate element when we are playing */
1112   if (GST_STATE (element) == GST_STATE_PLAYING)
1113     gst_pad_set_active (pad, TRUE);
1114
1115   /* emit the NEW_PAD signal */
1116   g_signal_emit (G_OBJECT (element), gst_element_signals[NEW_PAD], 0, pad);
1117 }
1118
1119 /**
1120  * gst_element_add_ghost_pad:
1121  * @element: a #GstElement to add the ghost pad to.
1122  * @pad: the #GstPad from which the new ghost pad will be created.
1123  * @name: the name of the new ghost pad, or NULL to assign a unique name
1124  * automatically.
1125  *
1126  * Creates a ghost pad from @pad, and adds it to @element via
1127  * gst_element_add_pad().
1128  * 
1129  * Returns: the added ghost #GstPad, or NULL on error.
1130  */
1131 GstPad *
1132 gst_element_add_ghost_pad (GstElement * element, GstPad * pad,
1133     const gchar * name)
1134 {
1135   GstPad *ghostpad;
1136
1137   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1138   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
1139
1140   /* then check to see if there's already a pad by that name here */
1141   g_return_val_if_fail (gst_object_check_uniqueness (element->pads,
1142           name) == TRUE, NULL);
1143
1144   ghostpad = gst_ghost_pad_new (name, pad);
1145
1146   gst_element_add_pad (element, ghostpad);
1147
1148   return ghostpad;
1149 }
1150
1151 /**
1152  * gst_element_remove_pad:
1153  * @element: a #GstElement to remove pad from.
1154  * @pad: the #GstPad to remove from the element.
1155  *
1156  * Removes @pad from @element. @pad will be destroyed if it has not been
1157  * referenced elsewhere.
1158  */
1159 void
1160 gst_element_remove_pad (GstElement * element, GstPad * pad)
1161 {
1162   g_return_if_fail (element != NULL);
1163   g_return_if_fail (GST_IS_ELEMENT (element));
1164   g_return_if_fail (pad != NULL);
1165   g_return_if_fail (GST_IS_PAD (pad));
1166
1167   g_return_if_fail (GST_PAD_PARENT (pad) == element);
1168
1169   if (GST_IS_REAL_PAD (pad)) {
1170     /* unlink if necessary */
1171     if (GST_RPAD_PEER (pad) != NULL) {
1172       gst_pad_unlink (pad, GST_PAD (GST_RPAD_PEER (pad)));
1173     }
1174     gst_caps_replace (&GST_RPAD_EXPLICIT_CAPS (pad), NULL);
1175   } else if (GST_IS_GHOST_PAD (pad)) {
1176     g_object_set (pad, "real-pad", NULL, NULL);
1177   }
1178
1179   /* remove it from the list */
1180   element->pads = g_list_remove (element->pads, pad);
1181   element->numpads--;
1182   switch (gst_pad_get_direction (pad)) {
1183     case GST_PAD_SRC:
1184       element->numsrcpads--;
1185       break;
1186     case GST_PAD_SINK:
1187       element->numsinkpads--;
1188       break;
1189     default:
1190       /* can happen for ghost pads */
1191       break;
1192   }
1193
1194   g_signal_emit (G_OBJECT (element), gst_element_signals[PAD_REMOVED], 0, pad);
1195
1196   gst_object_unparent (GST_OBJECT (pad));
1197 }
1198
1199 /**
1200  * gst_element_remove_ghost_pad:
1201  * @element: a #GstElement to remove the ghost pad from.
1202  * @pad: ghost #GstPad to remove.
1203  *
1204  * Removes a ghost pad from an element. Deprecated, use gst_element_remove_pad()
1205  * instead.
1206  */
1207 void
1208 gst_element_remove_ghost_pad (GstElement * element, GstPad * pad)
1209 {
1210   g_return_if_fail (GST_IS_ELEMENT (element));
1211   g_return_if_fail (GST_IS_GHOST_PAD (pad));
1212
1213   g_warning ("gst_element_remove_ghost_pad is deprecated.\n"
1214       "Use gst_element_remove_pad instead.");
1215
1216   gst_element_remove_pad (element, pad);
1217 }
1218
1219
1220 /**
1221  * gst_element_get_pad:
1222  * @element: a #GstElement.
1223  * @name: the name of the pad to retrieve.
1224  *
1225  * Retrieves a pad from @element by name. Tries gst_element_get_static_pad()
1226  * first, then gst_element_get_request_pad().
1227  *
1228  * Returns: the #GstPad if found, otherwise %NULL.
1229  */
1230 GstPad *
1231 gst_element_get_pad (GstElement * element, const gchar * name)
1232 {
1233   GstPad *pad;
1234
1235   g_return_val_if_fail (element != NULL, NULL);
1236   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1237   g_return_val_if_fail (name != NULL, NULL);
1238
1239   pad = gst_element_get_static_pad (element, name);
1240   if (!pad)
1241     pad = gst_element_get_request_pad (element, name);
1242
1243   return pad;
1244 }
1245
1246 /**
1247  * gst_element_get_static_pad:
1248  * @element: a #GstElement to find a static pad of.
1249  * @name: the name of the static #GstPad to retrieve.
1250  *
1251  * Retrieves a pad from @element by name. This version only retrieves
1252  * already-existing (i.e. 'static') pads.
1253  *
1254  * Returns: the requested #GstPad if found, otherwise NULL.
1255  */
1256 GstPad *
1257 gst_element_get_static_pad (GstElement * element, const gchar * name)
1258 {
1259   GList *walk;
1260
1261   g_return_val_if_fail (element != NULL, NULL);
1262   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1263   g_return_val_if_fail (name != NULL, NULL);
1264
1265   walk = element->pads;
1266   while (walk) {
1267     GstPad *pad;
1268
1269     pad = GST_PAD (walk->data);
1270     if (strcmp (GST_PAD_NAME (pad), name) == 0) {
1271       GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "found pad %s:%s",
1272           GST_DEBUG_PAD_NAME (pad));
1273       return pad;
1274     }
1275     walk = g_list_next (walk);
1276   }
1277
1278   GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "no such pad '%s' in element \"%s\"",
1279       name, GST_OBJECT_NAME (element));
1280   return NULL;
1281 }
1282
1283 /**
1284  * gst_element_get_request_pad:
1285  * @element: a #GstElement to find a request pad of.
1286  * @name: the name of the request #GstPad to retrieve.
1287  *
1288  * Retrieves a pad from the element by name. This version only retrieves
1289  * request pads.
1290  *
1291  * Returns: requested #GstPad if found, otherwise NULL.
1292  */
1293 GstPad *
1294 gst_element_get_request_pad (GstElement * element, const gchar * name)
1295 {
1296   GstPadTemplate *templ = NULL;
1297   GstPad *pad;
1298   const gchar *req_name = NULL;
1299   gboolean templ_found = FALSE;
1300   GList *list;
1301   gint n;
1302   const gchar *data;
1303   gchar *str, *endptr = NULL;
1304
1305   g_return_val_if_fail (element != NULL, NULL);
1306   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1307   g_return_val_if_fail (name != NULL, NULL);
1308
1309   if (strstr (name, "%")) {
1310     templ = gst_element_get_pad_template (element, name);
1311     req_name = NULL;
1312     if (templ)
1313       templ_found = TRUE;
1314   } else {
1315     list = gst_element_get_pad_template_list (element);
1316     while (!templ_found && list) {
1317       templ = (GstPadTemplate *) list->data;
1318       if (templ->presence == GST_PAD_REQUEST) {
1319         /* Because of sanity checks in gst_pad_template_new(), we know that %s
1320            and %d, occurring at the end of the name_template, are the only
1321            possibilities. */
1322         GST_CAT_DEBUG (GST_CAT_PADS, "comparing %s to %s", name,
1323             templ->name_template);
1324         if ((str = strchr (templ->name_template, '%'))
1325             && strncmp (templ->name_template, name,
1326                 str - templ->name_template) == 0
1327             && strlen (name) > str - templ->name_template) {
1328           data = name + (str - templ->name_template);
1329           if (*(str + 1) == 'd') {
1330             /* it's an int */
1331             n = (gint) strtol (data, &endptr, 10);
1332             if (endptr && *endptr == '\0') {
1333               templ_found = TRUE;
1334               req_name = name;
1335               break;
1336             }
1337           } else {
1338             /* it's a string */
1339             templ_found = TRUE;
1340             req_name = name;
1341             break;
1342           }
1343         }
1344       }
1345       list = list->next;
1346     }
1347   }
1348
1349   if (!templ_found)
1350     return NULL;
1351
1352   pad = gst_element_request_pad (element, templ, req_name);
1353
1354   return pad;
1355 }
1356
1357 /**
1358  * gst_element_get_pad_list:
1359  * @element: a #GstElement to get pads of.
1360  *
1361  * Retrieves a list of @element's pads. The list must not be modified by the
1362  * calling code.
1363  *
1364  * Returns: the #GList of pads.
1365  */
1366 const GList *
1367 gst_element_get_pad_list (GstElement * element)
1368 {
1369   g_return_val_if_fail (element != NULL, NULL);
1370   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1371
1372   /* return the list of pads */
1373   return element->pads;
1374 }
1375
1376 /**
1377  * gst_element_class_add_pad_template:
1378  * @klass: the #GstElementClass to add the pad template to.
1379  * @templ: a #GstPadTemplate to add to the element class.
1380  *
1381  * Adds a padtemplate to an element class. This is mainly used in the _base_init
1382  * functions of classes.
1383  */
1384 void
1385 gst_element_class_add_pad_template (GstElementClass * klass,
1386     GstPadTemplate * templ)
1387 {
1388   g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
1389   g_return_if_fail (GST_IS_PAD_TEMPLATE (templ));
1390
1391   /* avoid registering pad templates with the same name */
1392   g_return_if_fail (gst_element_class_get_pad_template (klass,
1393           templ->name_template) == NULL);
1394
1395   klass->padtemplates = g_list_append (klass->padtemplates,
1396       gst_object_ref (GST_OBJECT (templ)));
1397   klass->numpadtemplates++;
1398 }
1399
1400 /**
1401  * gst_element_class_set_details:
1402  * @klass: class to set details for
1403  * @details: details to set
1404  *
1405  * Sets the detailed information for a #GstElementClass.
1406  * <note>This function is for use in _base_init functions only.</note>
1407  */
1408 void
1409 gst_element_class_set_details (GstElementClass * klass,
1410     const GstElementDetails * details)
1411 {
1412   g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
1413   g_return_if_fail (GST_IS_ELEMENT_DETAILS (details));
1414
1415   __gst_element_details_copy (&klass->details, details);
1416 }
1417
1418 /**
1419  * gst_element_class_get_pad_template_list:
1420  * @element_class: a #GstElementClass to get pad templates of.
1421  *
1422  * Retrieves a list of the pad templates associated with @element_class. The
1423  * list must not be modified by the calling code.
1424  * <note>If you use this function in the #GInstanceInitFunc of an object class
1425  * that has subclasses, make sure to pass the g_class parameter of the 
1426  * #GInstanceInitFunc here.</note>
1427  *
1428  * Returns: the #GList of padtemplates.
1429  */
1430 GList *
1431 gst_element_class_get_pad_template_list (GstElementClass * element_class)
1432 {
1433   g_return_val_if_fail (element_class != NULL, NULL);
1434   g_return_val_if_fail (GST_IS_ELEMENT_CLASS (element_class), NULL);
1435
1436   return element_class->padtemplates;
1437 }
1438
1439 /**
1440  * gst_element_class_get_pad_template:
1441  * @element_class: a #GstElementClass to get the pad template of.
1442  * @name: the name of the #GstPadTemplate to get.
1443  *
1444  * Retrieves a padtemplate from @element_class with the given name.
1445  * <note>If you use this function in the #GInstanceInitFunc of an object class
1446  * that has subclasses, make sure to pass the g_class parameter of the 
1447  * #GInstanceInitFunc here.</note>
1448  *
1449  * Returns: the #GstPadTemplate with the given name, or NULL if none was found. 
1450  * No unreferencing is necessary.
1451  */
1452 GstPadTemplate *
1453 gst_element_class_get_pad_template (GstElementClass * element_class,
1454     const gchar * name)
1455 {
1456   GList *padlist;
1457
1458   g_return_val_if_fail (element_class != NULL, NULL);
1459   g_return_val_if_fail (GST_IS_ELEMENT_CLASS (element_class), NULL);
1460   g_return_val_if_fail (name != NULL, NULL);
1461
1462   padlist = gst_element_class_get_pad_template_list (element_class);
1463
1464   while (padlist) {
1465     GstPadTemplate *padtempl = (GstPadTemplate *) padlist->data;
1466
1467     if (strcmp (padtempl->name_template, name) == 0)
1468       return padtempl;
1469
1470     padlist = g_list_next (padlist);
1471   }
1472
1473   return NULL;
1474 }
1475
1476 /**
1477  * gst_element_get_pad_template_list:
1478  * @element: a #GstElement to get pad templates of.
1479  *
1480  * Retrieves a list of the pad templates associated with the element.
1481  * (FIXME: Should be deprecated in favor of gst_element_class_get_pad_template_list).
1482  *
1483  * Returns: the #GList of padtemplates.
1484  */
1485 GList *
1486 gst_element_get_pad_template_list (GstElement * element)
1487 {
1488   g_return_val_if_fail (element != NULL, NULL);
1489   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1490
1491   return GST_ELEMENT_GET_CLASS (element)->padtemplates;
1492 }
1493
1494 /**
1495  * gst_element_get_pad_template:
1496  * @element: a #GstElement to get the pad template of.
1497  * @name: the name of the #GstPadTemplate to get.
1498  *
1499  * Retrieves a padtemplate from this element with the
1500  * given name.
1501  * (FIXME: Should be deprecated in favor of gst_element_class_get_pad_template).
1502  *
1503  * Returns: the #GstPadTemplate with the given name, or NULL if none was found. 
1504  * No unreferencing is necessary.
1505  */
1506 GstPadTemplate *
1507 gst_element_get_pad_template (GstElement * element, const gchar * name)
1508 {
1509   g_return_val_if_fail (element != NULL, NULL);
1510   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1511   g_return_val_if_fail (name != NULL, NULL);
1512
1513   return gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (element),
1514       name);
1515 }
1516
1517 /**
1518  * gst_element_get_compatible_pad_template:
1519  * @element: a #GstElement to get a compatible pad template for.
1520  * @compattempl: the #GstPadTemplate to find a compatible template for.
1521  *
1522  * Retrieves a pad template from @element that is compatible with @compattempl.
1523  * Pads from compatible templates can be linked together.
1524  *
1525  * Returns: a compatible #GstPadTemplate, or NULL if none was found. No
1526  * unreferencing is necessary.
1527  */
1528 GstPadTemplate *
1529 gst_element_get_compatible_pad_template (GstElement * element,
1530     GstPadTemplate * compattempl)
1531 {
1532   GstPadTemplate *newtempl = NULL;
1533   GList *padlist;
1534
1535   g_return_val_if_fail (element != NULL, NULL);
1536   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1537   g_return_val_if_fail (compattempl != NULL, NULL);
1538
1539   padlist = gst_element_get_pad_template_list (element);
1540
1541   GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
1542       "Looking for a suitable pad template...");
1543
1544   while (padlist) {
1545     GstPadTemplate *padtempl = (GstPadTemplate *) padlist->data;
1546     GstCaps *intersection;
1547
1548     /* Ignore name
1549      * Ignore presence
1550      * Check direction (must be opposite)
1551      * Check caps
1552      */
1553     if (padtempl->direction != compattempl->direction) {
1554       GST_CAT_DEBUG (GST_CAT_CAPS,
1555           "compatible direction: found %s pad template \"%s\"",
1556           padtempl->direction == GST_PAD_SRC ? "src" : "sink",
1557           padtempl->name_template);
1558
1559       intersection = gst_caps_intersect (GST_PAD_TEMPLATE_CAPS (compattempl),
1560           GST_PAD_TEMPLATE_CAPS (padtempl));
1561
1562       GST_CAT_DEBUG (GST_CAT_CAPS, "caps are %scompatible",
1563           (intersection ? "" : "not "));
1564
1565       if (!gst_caps_is_empty (intersection))
1566         newtempl = padtempl;
1567       gst_caps_free (intersection);
1568       if (newtempl)
1569         break;
1570     }
1571
1572     padlist = g_list_next (padlist);
1573   }
1574
1575   return newtempl;
1576 }
1577
1578 /**
1579  * gst_element_get_pad_from_template:
1580  * @element: a #GstElement.
1581  * @templ: a #GstPadTemplate belonging to @element.
1582  *
1583  * Gets a pad from @element described by @templ. If the presence of @templ is
1584  * #GST_PAD_REQUEST, requests a new pad. Can return %NULL for #GST_PAD_SOMETIMES
1585  * templates.
1586  *
1587  * Returns: the #GstPad, or NULL if one could not be found or created.
1588  */
1589 static GstPad *
1590 gst_element_get_pad_from_template (GstElement * element, GstPadTemplate * templ)
1591 {
1592   GstPad *ret = NULL;
1593   GstPadPresence presence;
1594
1595   /* If this function is ever exported, we need check the validity of `element'
1596    * and `templ', and to make sure the template actually belongs to the
1597    * element. */
1598
1599   presence = GST_PAD_TEMPLATE_PRESENCE (templ);
1600
1601   switch (presence) {
1602     case GST_PAD_ALWAYS:
1603     case GST_PAD_SOMETIMES:
1604       ret = gst_element_get_static_pad (element, templ->name_template);
1605       if (!ret && presence == GST_PAD_ALWAYS)
1606         g_warning
1607             ("Element %s has an ALWAYS template %s, but no pad of the same name",
1608             GST_OBJECT_NAME (element), templ->name_template);
1609       break;
1610
1611     case GST_PAD_REQUEST:
1612       ret = gst_element_request_pad (element, templ, NULL);
1613       break;
1614   }
1615
1616   return ret;
1617 }
1618
1619 /**
1620  * gst_element_request_compatible_pad:
1621  * @element: a #GstElement.
1622  * @templ: the #GstPadTemplate to which the new pad should be able to link.
1623  *
1624  * Requests a pad from @element. The returned pad should be unlinked and
1625  * compatible with @templ. Might return an existing pad, or request a new one.
1626  *
1627  * Returns: a #GstPad, or %NULL if one could not be found or created.
1628  */
1629 GstPad *
1630 gst_element_request_compatible_pad (GstElement * element,
1631     GstPadTemplate * templ)
1632 {
1633   GstPadTemplate *templ_new;
1634   GstPad *pad = NULL;
1635
1636   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1637   g_return_val_if_fail (GST_IS_PAD_TEMPLATE (templ), NULL);
1638
1639   /* FIXME: should really loop through the templates, testing each for
1640      compatibility and pad availability. */
1641   templ_new = gst_element_get_compatible_pad_template (element, templ);
1642   if (templ_new)
1643     pad = gst_element_get_pad_from_template (element, templ_new);
1644
1645   /* This can happen for non-request pads. No need to unref. */
1646   if (pad && GST_PAD_PEER (pad))
1647     pad = NULL;
1648
1649   return pad;
1650 }
1651
1652 /**
1653  * gst_element_get_compatible_pad_filtered:
1654  * @element: a #GstElement in which the pad should be found.
1655  * @pad: the #GstPad to find a compatible one for.
1656  * @filtercaps: the #GstCaps to use as a filter.
1657  *
1658  * Looks for an unlinked pad to which the given pad can link. It is not
1659  * guaranteed that linking the pads will work, though it should work in most
1660  * cases.
1661  *
1662  * Returns: the #GstPad to which a link can be made, or %NULL if one cannot be
1663  * found.
1664  */
1665 GstPad *
1666 gst_element_get_compatible_pad_filtered (GstElement * element, GstPad * pad,
1667     const GstCaps * filtercaps)
1668 {
1669   const GList *pads;
1670   GstPadTemplate *templ;
1671   GstCaps *templcaps;
1672   GstPad *foundpad = NULL;
1673
1674   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1675   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
1676
1677   GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
1678       "finding pad in %s compatible with %s:%s", GST_ELEMENT_NAME (element),
1679       GST_DEBUG_PAD_NAME (pad));
1680
1681   /* let's use the real pad */
1682   pad = (GstPad *) GST_PAD_REALIZE (pad);
1683   g_return_val_if_fail (pad != NULL, NULL);
1684   g_return_val_if_fail (GST_RPAD_PEER (pad) == NULL, NULL);
1685
1686   /* try to get an existing unlinked pad */
1687   pads = gst_element_get_pad_list (element);
1688   while (pads) {
1689     GstPad *current = GST_PAD (pads->data);
1690
1691     if (GST_PAD_PEER (current) == NULL &&
1692         gst_pad_can_link_filtered (pad, current, filtercaps)) {
1693       return current;
1694     }
1695     pads = g_list_next (pads);
1696   }
1697
1698   /* try to create a new one */
1699   /* requesting is a little crazy, we need a template. Let's create one */
1700   templcaps = gst_pad_get_caps (pad);
1701   if (filtercaps != NULL) {
1702     GstCaps *temp;
1703
1704     temp = gst_caps_intersect (filtercaps, templcaps);
1705     gst_caps_free (templcaps);
1706     templcaps = temp;
1707   }
1708
1709   templ = gst_pad_template_new ((gchar *) GST_PAD_NAME (pad),
1710       GST_PAD_DIRECTION (pad), GST_PAD_ALWAYS, templcaps);
1711   foundpad = gst_element_request_compatible_pad (element, templ);
1712   gst_object_unref (GST_OBJECT (templ));
1713
1714   if (foundpad)
1715     return foundpad;
1716
1717   GST_CAT_INFO_OBJECT (GST_CAT_ELEMENT_PADS, element,
1718       "Could not find a compatible pad to link to %s:%s",
1719       GST_DEBUG_PAD_NAME (pad));
1720
1721   return NULL;
1722 }
1723
1724 /**
1725  * gst_element_get_compatible_pad:
1726  * @element: a #GstElement in which the pad should be found.
1727  * @pad: the #GstPad to find a compatible one for.
1728  *
1729  * Looks for an unlinked pad to which the given pad can link to.
1730  * It is not guaranteed that linking the pads will work, though
1731  * it should work in most cases.
1732  *
1733  * Returns: the #GstPad to which a link can be made, or %NULL if one
1734  * could not be found.
1735  */
1736 GstPad *
1737 gst_element_get_compatible_pad (GstElement * element, GstPad * pad)
1738 {
1739   return gst_element_get_compatible_pad_filtered (element, pad, NULL);
1740 }
1741
1742 /**
1743  * gst_element_link_pads_filtered:
1744  * @src: a #GstElement containing the source pad.
1745  * @srcpadname: the name of the #GstPad in source element or NULL for any pad.
1746  * @dest: the #GstElement containing the destination pad.
1747  * @destpadname: the name of the #GstPad in destination element or NULL for any pad.
1748  * @filtercaps: the #GstCaps to use as a filter.
1749  *
1750  * Links the two named pads of the source and destination elements.
1751  * Side effect is that if one of the pads has no parent, it becomes a
1752  * child of the parent of the other element.  If they have different
1753  * parents, the link fails.
1754  *
1755  * Returns: TRUE if the pads could be linked, FALSE otherwise.
1756  */
1757 gboolean
1758 gst_element_link_pads_filtered (GstElement * src, const gchar * srcpadname,
1759     GstElement * dest, const gchar * destpadname, const GstCaps * filtercaps)
1760 {
1761   const GList *srcpads, *destpads, *srctempls, *desttempls, *l;
1762   GstPad *srcpad, *destpad;
1763   GstPadTemplate *srctempl, *desttempl;
1764
1765   /* checks */
1766   g_return_val_if_fail (GST_IS_ELEMENT (src), FALSE);
1767   g_return_val_if_fail (GST_IS_ELEMENT (dest), FALSE);
1768
1769   GST_CAT_INFO (GST_CAT_ELEMENT_PADS,
1770       "trying to link element %s:%s to element %s:%s", GST_ELEMENT_NAME (src),
1771       srcpadname ? srcpadname : "(any)", GST_ELEMENT_NAME (dest),
1772       destpadname ? destpadname : "(any)");
1773
1774   /* now get the pads we're trying to link and a list of all remaining pads */
1775   if (srcpadname) {
1776     srcpad = gst_element_get_pad (src, srcpadname);
1777     if (!srcpad) {
1778       GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no pad %s:%s",
1779           GST_ELEMENT_NAME (src), srcpadname);
1780       return FALSE;
1781     } else {
1782       if (!(GST_PAD_DIRECTION (srcpad) == GST_PAD_SRC)) {
1783         GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s is no src pad",
1784             GST_DEBUG_PAD_NAME (srcpad));
1785         return FALSE;
1786       }
1787       if (GST_PAD_PEER (srcpad) != NULL) {
1788         GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s is already linked",
1789             GST_DEBUG_PAD_NAME (srcpad));
1790         return FALSE;
1791       }
1792     }
1793     srcpads = NULL;
1794   } else {
1795     srcpads = gst_element_get_pad_list (src);
1796     srcpad = srcpads ? (GstPad *) GST_PAD_REALIZE (srcpads->data) : NULL;
1797   }
1798   if (destpadname) {
1799     destpad = gst_element_get_pad (dest, destpadname);
1800     if (!destpad) {
1801       GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no pad %s:%s",
1802           GST_ELEMENT_NAME (dest), destpadname);
1803       return FALSE;
1804     } else {
1805       if (!(GST_PAD_DIRECTION (destpad) == GST_PAD_SINK)) {
1806         GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s is no sink pad",
1807             GST_DEBUG_PAD_NAME (destpad));
1808         return FALSE;
1809       }
1810       if (GST_PAD_PEER (destpad) != NULL) {
1811         GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s is already linked",
1812             GST_DEBUG_PAD_NAME (destpad));
1813         return FALSE;
1814       }
1815     }
1816     destpads = NULL;
1817   } else {
1818     destpads = gst_element_get_pad_list (dest);
1819     destpad = destpads ? (GstPad *) GST_PAD_REALIZE (destpads->data) : NULL;
1820   }
1821
1822   if (srcpadname && destpadname) {
1823     /* two explicitly specified pads */
1824     return gst_pad_link_filtered (srcpad, destpad, filtercaps);
1825   }
1826   if (srcpad) {
1827     /* loop through the allowed pads in the source, trying to find a
1828      * compatible destination pad */
1829     GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
1830         "looping through allowed src and dest pads");
1831     do {
1832       GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "trying src pad %s:%s",
1833           GST_DEBUG_PAD_NAME (srcpad));
1834       if ((GST_PAD_DIRECTION (srcpad) == GST_PAD_SRC) &&
1835           (GST_PAD_PEER (srcpad) == NULL)) {
1836         GstPad *temp = gst_element_get_compatible_pad_filtered (dest, srcpad,
1837             filtercaps);
1838
1839         if (temp && gst_pad_link_filtered (srcpad, temp, filtercaps)) {
1840           GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "linked pad %s:%s to pad %s:%s",
1841               GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (temp));
1842           return TRUE;
1843         }
1844       }
1845       /* find a better way for this mess */
1846       if (srcpads) {
1847         srcpads = g_list_next (srcpads);
1848         if (srcpads)
1849           srcpad = (GstPad *) GST_PAD_REALIZE (srcpads->data);
1850       }
1851     } while (srcpads);
1852   }
1853   if (srcpadname) {
1854     GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no link possible from %s:%s to %s",
1855         GST_DEBUG_PAD_NAME (srcpad), GST_ELEMENT_NAME (dest));
1856     return FALSE;
1857   }
1858   if (destpad) {
1859     /* loop through the existing pads in the destination */
1860     do {
1861       GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "trying dest pad %s:%s",
1862           GST_DEBUG_PAD_NAME (destpad));
1863       if ((GST_PAD_DIRECTION (destpad) == GST_PAD_SINK) &&
1864           (GST_PAD_PEER (destpad) == NULL)) {
1865         GstPad *temp = gst_element_get_compatible_pad_filtered (src, destpad,
1866             filtercaps);
1867
1868         if (temp && gst_pad_link_filtered (temp, destpad, filtercaps)) {
1869           GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "linked pad %s:%s to pad %s:%s",
1870               GST_DEBUG_PAD_NAME (temp), GST_DEBUG_PAD_NAME (destpad));
1871           return TRUE;
1872         }
1873       }
1874       if (destpads) {
1875         destpads = g_list_next (destpads);
1876         if (destpads)
1877           destpad = (GstPad *) GST_PAD_REALIZE (destpads->data);
1878       }
1879     } while (destpads);
1880   }
1881   if (destpadname) {
1882     GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no link possible from %s to %s:%s",
1883         GST_ELEMENT_NAME (src), GST_DEBUG_PAD_NAME (destpad));
1884     return FALSE;
1885   }
1886
1887   GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
1888       "we might have request pads on both sides, checking...");
1889   srctempls = gst_element_get_pad_template_list (src);
1890   desttempls = gst_element_get_pad_template_list (dest);
1891
1892   if (srctempls && desttempls) {
1893     while (srctempls) {
1894       srctempl = (GstPadTemplate *) srctempls->data;
1895       if (srctempl->presence == GST_PAD_REQUEST) {
1896         for (l = desttempls; l; l = l->next) {
1897           desttempl = (GstPadTemplate *) l->data;
1898           if (desttempl->presence == GST_PAD_REQUEST &&
1899               desttempl->direction != srctempl->direction) {
1900             if (gst_caps_is_always_compatible (gst_pad_template_get_caps
1901                     (srctempl), gst_pad_template_get_caps (desttempl))) {
1902               srcpad =
1903                   gst_element_get_request_pad (src, srctempl->name_template);
1904               destpad =
1905                   gst_element_get_request_pad (dest, desttempl->name_template);
1906               if (gst_pad_link_filtered (srcpad, destpad, filtercaps)) {
1907                 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
1908                     "linked pad %s:%s to pad %s:%s",
1909                     GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad));
1910                 return TRUE;
1911               }
1912               /* it failed, so we release the request pads */
1913               gst_element_release_request_pad (src, srcpad);
1914               gst_element_release_request_pad (dest, destpad);
1915             }
1916           }
1917         }
1918       }
1919       srctempls = srctempls->next;
1920     }
1921   }
1922
1923   GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no link possible from %s to %s",
1924       GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (dest));
1925   return FALSE;
1926 }
1927
1928 /**
1929  * gst_element_link_filtered:
1930  * @src: a #GstElement containing the source pad.
1931  * @dest: the #GstElement containing the destination pad.
1932  * @filtercaps: the #GstCaps to use as a filter.
1933  *
1934  * Links @src to @dest, filtered by @filtercaps. The link must be from source to
1935  * destination; the other direction will not be tried. The function looks for
1936  * existing pads that aren't linked yet. It will request new pads if necessary.
1937  * If multiple links are possible, only one is established.
1938  *
1939  * Returns: TRUE if the elements could be linked, FALSE otherwise.
1940  */
1941 gboolean
1942 gst_element_link_filtered (GstElement * src, GstElement * dest,
1943     const GstCaps * filtercaps)
1944 {
1945   return gst_element_link_pads_filtered (src, NULL, dest, NULL, filtercaps);
1946 }
1947
1948 /**
1949  * gst_element_link_many:
1950  * @element_1: the first #GstElement in the link chain.
1951  * @element_2: the second #GstElement in the link chain.
1952  * @...: the NULL-terminated list of elements to link in order.
1953  * 
1954  * Chain together a series of elements. Uses gst_element_link().
1955  *
1956  * Returns: TRUE on success, FALSE otherwise.
1957  */
1958 gboolean
1959 gst_element_link_many (GstElement * element_1, GstElement * element_2, ...)
1960 {
1961   va_list args;
1962
1963   g_return_val_if_fail (element_1 != NULL && element_2 != NULL, FALSE);
1964   g_return_val_if_fail (GST_IS_ELEMENT (element_1) &&
1965       GST_IS_ELEMENT (element_2), FALSE);
1966
1967   va_start (args, element_2);
1968
1969   while (element_2) {
1970     if (!gst_element_link (element_1, element_2))
1971       return FALSE;
1972
1973     element_1 = element_2;
1974     element_2 = va_arg (args, GstElement *);
1975   }
1976
1977   va_end (args);
1978
1979   return TRUE;
1980 }
1981
1982 /**
1983  * gst_element_link:
1984  * @src: a #GstElement containing the source pad.
1985  * @dest: the #GstElement containing the destination pad.
1986  *
1987  * Links @src to @dest with no filter caps. See gst_element_link_filtered() for
1988  * more information.
1989  *
1990  * Returns: TRUE if the elements could be linked, FALSE otherwise.
1991  */
1992 gboolean
1993 gst_element_link (GstElement * src, GstElement * dest)
1994 {
1995   return gst_element_link_pads_filtered (src, NULL, dest, NULL, NULL);
1996 }
1997
1998 /**
1999  * gst_element_link_pads:
2000  * @src: a #GstElement containing the source pad.
2001  * @srcpadname: the name of the #GstPad in the source element.
2002  * @dest: the #GstElement containing the destination pad.
2003  * @destpadname: the name of the #GstPad in destination element.
2004  *
2005  * Links the two named pads of the source and destination elements.
2006  * Side effect is that if one of the pads has no parent, it becomes a
2007  * child of the parent of the other element.  If they have different
2008  * parents, the link fails.
2009  *
2010  * Returns: TRUE if the pads could be linked, FALSE otherwise.
2011  */
2012 gboolean
2013 gst_element_link_pads (GstElement * src, const gchar * srcpadname,
2014     GstElement * dest, const gchar * destpadname)
2015 {
2016   return gst_element_link_pads_filtered (src, srcpadname, dest, destpadname,
2017       NULL);
2018 }
2019
2020 /**
2021  * gst_element_unlink_pads:
2022  * @src: a #GstElement containing the source pad.
2023  * @srcpadname: the name of the #GstPad in source element.
2024  * @dest: a #GstElement containing the destination pad.
2025  * @destpadname: the name of the #GstPad in destination element.
2026  *
2027  * Unlinks the two named pads of the source and destination elements.
2028  */
2029 void
2030 gst_element_unlink_pads (GstElement * src, const gchar * srcpadname,
2031     GstElement * dest, const gchar * destpadname)
2032 {
2033   GstPad *srcpad, *destpad;
2034
2035   g_return_if_fail (src != NULL);
2036   g_return_if_fail (GST_IS_ELEMENT (src));
2037   g_return_if_fail (srcpadname != NULL);
2038   g_return_if_fail (dest != NULL);
2039   g_return_if_fail (GST_IS_ELEMENT (dest));
2040   g_return_if_fail (destpadname != NULL);
2041
2042   /* obtain the pads requested */
2043   srcpad = gst_element_get_pad (src, srcpadname);
2044   if (srcpad == NULL) {
2045     GST_WARNING_OBJECT (src, "source element has no pad \"%s\"", srcpadname);
2046     return;
2047   }
2048   destpad = gst_element_get_pad (dest, destpadname);
2049   if (srcpad == NULL) {
2050     GST_WARNING_OBJECT (dest, "destination element has no pad \"%s\"",
2051         destpadname);
2052     return;
2053   }
2054
2055   /* we're satisified they can be unlinked, let's do it */
2056   gst_pad_unlink (srcpad, destpad);
2057 }
2058
2059 /**
2060  * gst_element_unlink_many:
2061  * @element_1: the first #GstElement in the link chain.
2062  * @element_2: the second #GstElement in the link chain.
2063  * @...: the NULL-terminated list of elements to unlink in order.
2064  * 
2065  * Unlinks a series of elements. Uses gst_element_unlink().
2066  */
2067 void
2068 gst_element_unlink_many (GstElement * element_1, GstElement * element_2, ...)
2069 {
2070   va_list args;
2071
2072   g_return_if_fail (element_1 != NULL && element_2 != NULL);
2073   g_return_if_fail (GST_IS_ELEMENT (element_1) && GST_IS_ELEMENT (element_2));
2074
2075   va_start (args, element_2);
2076
2077   while (element_2) {
2078     gst_element_unlink (element_1, element_2);
2079
2080     element_1 = element_2;
2081     element_2 = va_arg (args, GstElement *);
2082   }
2083
2084   va_end (args);
2085 }
2086
2087 /**
2088  * gst_element_unlink:
2089  * @src: the source #GstElement to unlink.
2090  * @dest: the sink #GstElement to unlink.
2091  *
2092  * Unlinks all source pads of the source element with all sink pads
2093  * of the sink element to which they are linked.
2094  */
2095 void
2096 gst_element_unlink (GstElement * src, GstElement * dest)
2097 {
2098   const GList *srcpads;
2099   GstPad *pad;
2100
2101   g_return_if_fail (GST_IS_ELEMENT (src));
2102   g_return_if_fail (GST_IS_ELEMENT (dest));
2103
2104   GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "unlinking \"%s\" and \"%s\"",
2105       GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (dest));
2106
2107   srcpads = gst_element_get_pad_list (src);
2108
2109   while (srcpads) {
2110     pad = GST_PAD (srcpads->data);
2111
2112     /* we only care about real src pads */
2113     if (GST_IS_REAL_PAD (pad) && GST_PAD_IS_SRC (pad)) {
2114       GstPad *peerpad = GST_PAD_PEER (pad);
2115
2116       /* see if the pad is connected and is really a pad
2117        * of dest */
2118       if (peerpad && (GST_OBJECT_PARENT (peerpad) == (GstObject *) dest)) {
2119         gst_pad_unlink (pad, peerpad);
2120       }
2121     }
2122
2123     srcpads = g_list_next (srcpads);
2124   }
2125 }
2126
2127 static void
2128 gst_element_error_func (GstElement * element, GstElement * source,
2129     GError * error, gchar * debug)
2130 {
2131   /* tell the parent */
2132   if (GST_OBJECT_PARENT (element)) {
2133     GST_CAT_DEBUG (GST_CAT_ERROR_SYSTEM,
2134         "forwarding error \"%s\" from %s to %s", error->message,
2135         GST_ELEMENT_NAME (element),
2136         GST_OBJECT_NAME (GST_OBJECT_PARENT (element)));
2137
2138     gst_object_ref (GST_OBJECT (element));
2139     g_signal_emit (G_OBJECT (GST_OBJECT_PARENT (element)),
2140         gst_element_signals[ERROR], 0, source, error, debug);
2141     gst_object_unref (GST_OBJECT (element));
2142     GST_CAT_DEBUG (GST_CAT_ERROR_SYSTEM, "forwarded error \"%s\" from %s to %s",
2143         error->message, GST_ELEMENT_NAME (element),
2144         GST_OBJECT_NAME (GST_OBJECT_PARENT (element)));
2145   }
2146 }
2147
2148 static GstPad *
2149 gst_element_get_random_pad (GstElement * element, GstPadDirection dir)
2150 {
2151   GList *pads = element->pads;
2152
2153   GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "getting a random pad");
2154   while (pads) {
2155     GstPad *pad = GST_PAD (pads->data);
2156
2157     GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "checking pad %s:%s",
2158         GST_DEBUG_PAD_NAME (pad));
2159
2160     if (GST_PAD_DIRECTION (pad) == dir) {
2161       if (GST_PAD_IS_LINKED (pad)) {
2162         return pad;
2163       } else {
2164         GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s is not linked",
2165             GST_DEBUG_PAD_NAME (pad));
2166       }
2167     } else {
2168       GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s is in wrong direction",
2169           GST_DEBUG_PAD_NAME (pad));
2170     }
2171
2172     pads = g_list_next (pads);
2173   }
2174   return NULL;
2175 }
2176
2177 /**
2178  * gst_element_get_event_masks:
2179  * @element: a #GstElement to query
2180  *
2181  * Get an array of event masks from the element.
2182  * If the element doesn't 
2183  * implement an event masks function, the query will be forwarded
2184  * to a random linked sink pad.
2185  * 
2186  * Returns: An array of #GstEventMask elements.
2187  */
2188 const GstEventMask *
2189 gst_element_get_event_masks (GstElement * element)
2190 {
2191   GstElementClass *oclass;
2192
2193   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
2194
2195   oclass = GST_ELEMENT_GET_CLASS (element);
2196
2197   if (oclass->get_event_masks)
2198     return oclass->get_event_masks (element);
2199   else {
2200     GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SINK);
2201
2202     if (pad)
2203       return gst_pad_get_event_masks (GST_PAD_PEER (pad));
2204   }
2205
2206   return FALSE;
2207 }
2208
2209 /**
2210  * gst_element_send_event:
2211  * @element: a #GstElement to send the event to.
2212  * @event: the #GstEvent to send to the element.
2213  *
2214  * Sends an event to an element. If the element doesn't
2215  * implement an event handler, the event will be forwarded
2216  * to a random sink pad.
2217  *
2218  * Returns: TRUE if the event was handled.
2219  */
2220 gboolean
2221 gst_element_send_event (GstElement * element, GstEvent * event)
2222 {
2223   GstElementClass *oclass;
2224
2225   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
2226   g_return_val_if_fail (event != NULL, FALSE);
2227
2228   oclass = GST_ELEMENT_GET_CLASS (element);
2229
2230   if (oclass->send_event)
2231     return oclass->send_event (element, event);
2232   else {
2233     GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SINK);
2234
2235     if (pad) {
2236       GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "sending event to random pad %s:%s",
2237           GST_DEBUG_PAD_NAME (pad));
2238       return gst_pad_send_event (GST_PAD_PEER (pad), event);
2239     }
2240   }
2241   GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "can't send event on element %s",
2242       GST_ELEMENT_NAME (element));
2243   return FALSE;
2244 }
2245
2246 /**
2247  * gst_element_seek:
2248  * @element: a #GstElement to send the event to.
2249  * @seek_type: the method to use for seeking.
2250  * @offset: the offset to seek to.
2251  *
2252  * Sends a seek event to an element.
2253  *
2254  * Returns: TRUE if the event was handled.
2255  */
2256 gboolean
2257 gst_element_seek (GstElement * element, GstSeekType seek_type, guint64 offset)
2258 {
2259   GstEvent *event = gst_event_new_seek (seek_type, offset);
2260
2261   return gst_element_send_event (element, event);
2262 }
2263
2264 /**
2265  * gst_element_get_query_types:
2266  * @element: a #GstElement to query
2267  *
2268  * Get an array of query types from the element.
2269  * If the element doesn't 
2270  * implement a query types function, the query will be forwarded
2271  * to a random sink pad.
2272  * 
2273  * Returns: An array of #GstQueryType elements.
2274  */
2275 const GstQueryType *
2276 gst_element_get_query_types (GstElement * element)
2277 {
2278   GstElementClass *oclass;
2279
2280   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
2281
2282   oclass = GST_ELEMENT_GET_CLASS (element);
2283
2284   if (oclass->get_query_types)
2285     return oclass->get_query_types (element);
2286   else {
2287     GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SINK);
2288
2289     if (pad)
2290       return gst_pad_get_query_types (GST_PAD_PEER (pad));
2291   }
2292
2293   return FALSE;
2294 }
2295
2296 /**
2297  * gst_element_query:
2298  * @element: a #GstElement to perform the query on.
2299  * @type: the #GstQueryType.
2300  * @format: the #GstFormat pointer to hold the format of the result.
2301  * @value: the pointer to the value of the result.
2302  *
2303  * Performs a query on the given element. If the format is set
2304  * to GST_FORMAT_DEFAULT and this function returns TRUE, the 
2305  * format pointer will hold the default format.
2306  * For element that don't implement a query handler, this function
2307  * forwards the query to a random usable sinkpad of this element.
2308  * 
2309  * Returns: TRUE if the query could be performed.
2310  */
2311 gboolean
2312 gst_element_query (GstElement * element, GstQueryType type,
2313     GstFormat * format, gint64 * value)
2314 {
2315   GstElementClass *oclass;
2316
2317   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
2318   g_return_val_if_fail (format != NULL, FALSE);
2319   g_return_val_if_fail (value != NULL, FALSE);
2320
2321   oclass = GST_ELEMENT_GET_CLASS (element);
2322
2323   if (oclass->query)
2324     return oclass->query (element, type, format, value);
2325   else {
2326     GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SRC);
2327
2328     if (pad)
2329       return gst_pad_query (pad, type, format, value);
2330     pad = gst_element_get_random_pad (element, GST_PAD_SINK);
2331     if (pad)
2332       return gst_pad_query (GST_PAD_PEER (pad), type, format, value);
2333   }
2334
2335   return FALSE;
2336 }
2337
2338 /**
2339  * gst_element_get_formats:
2340  * @element: a #GstElement to query
2341  *
2342  * Get an array of formst from the element.
2343  * If the element doesn't 
2344  * implement a formats function, the query will be forwarded
2345  * to a random sink pad.
2346  * 
2347  * Returns: An array of #GstFormat elements.
2348  */
2349 const GstFormat *
2350 gst_element_get_formats (GstElement * element)
2351 {
2352   GstElementClass *oclass;
2353
2354   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
2355
2356   oclass = GST_ELEMENT_GET_CLASS (element);
2357
2358   if (oclass->get_formats)
2359     return oclass->get_formats (element);
2360   else {
2361     GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SINK);
2362
2363     if (pad)
2364       return gst_pad_get_formats (GST_PAD_PEER (pad));
2365   }
2366
2367   return FALSE;
2368 }
2369
2370 /**
2371  * gst_element_convert:
2372  * @element: a #GstElement to invoke the converter on.
2373  * @src_format: the source #GstFormat.
2374  * @src_value: the source value.
2375  * @dest_format: a pointer to the destination #GstFormat.
2376  * @dest_value: a pointer to the destination value.
2377  *
2378  * Invokes a conversion on the element.
2379  * If the element doesn't 
2380  * implement a convert function, the query will be forwarded
2381  * to a random sink pad.
2382  *
2383  * Returns: TRUE if the conversion could be performed.
2384  */
2385 gboolean
2386 gst_element_convert (GstElement * element,
2387     GstFormat src_format, gint64 src_value,
2388     GstFormat * dest_format, gint64 * dest_value)
2389 {
2390   GstElementClass *oclass;
2391
2392   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
2393   g_return_val_if_fail (dest_format != NULL, FALSE);
2394   g_return_val_if_fail (dest_value != NULL, FALSE);
2395
2396   if (src_format == *dest_format) {
2397     *dest_value = src_value;
2398     return TRUE;
2399   }
2400
2401   oclass = GST_ELEMENT_GET_CLASS (element);
2402
2403   if (oclass->convert)
2404     return oclass->convert (element,
2405         src_format, src_value, dest_format, dest_value);
2406   else {
2407     GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SINK);
2408
2409     if (pad)
2410       return gst_pad_convert (GST_PAD_PEER (pad),
2411           src_format, src_value, dest_format, dest_value);
2412   }
2413
2414   return FALSE;
2415 }
2416
2417 /**
2418  * _gst_element_error_printf:
2419  * @format: the printf-like format to use, or NULL
2420  *
2421  * This function is only used internally by the #gst_element_error macro.
2422  *
2423  * Returns: a newly allocated string, or NULL if the format was NULL or ""
2424  */
2425 gchar *
2426 _gst_element_error_printf (const gchar * format, ...)
2427 {
2428   va_list args;
2429   gchar *buffer;
2430
2431   if (format == NULL)
2432     return NULL;
2433   if (format[0] == 0)
2434     return NULL;
2435
2436   va_start (args, format);
2437   buffer = g_strdup_vprintf (format, args);
2438   va_end (args);
2439   return buffer;
2440 }
2441
2442 /**
2443  * gst_element_error_full:
2444  * @element: a #GstElement with the error.
2445  * @domain: the GStreamer error domain this error belongs to.
2446  * @code: the error code belonging to the domain
2447  * @message: an allocated message to be used as a replacement for the default
2448  *           message connected to code, or NULL
2449  * @debug: an allocated debug message to be used as a replacement for the
2450  *        default debugging information, or NULL
2451  * @file: source filename
2452  * @function: source function
2453  * @line: source line
2454  *
2455  * Signals an error condition on an element.
2456  * This function is used internally by elements.
2457  * It results in the "error" signal.
2458  */
2459 void gst_element_error_full
2460     (GstElement * element, GQuark domain, gint code, gchar * message,
2461     gchar * debug, const gchar * file, const gchar * function, gint line)
2462 {
2463   GError *error = NULL;
2464   gchar *name;
2465   gchar *sent_message;
2466   gchar *sent_debug;
2467
2468   /* checks */
2469   g_return_if_fail (GST_IS_ELEMENT (element));
2470
2471   /* check if we send the given message or the default error message */
2472   if ((message == NULL) || (message[0] == 0)) {
2473     /* we got this message from g_strdup_printf (""); */
2474     g_free (message);
2475     sent_message = gst_error_get_message (domain, code);
2476   } else
2477     sent_message = message;
2478
2479   if ((debug == NULL) || (debug[0] == 0)) {
2480     /* we got this debug from g_strdup_printf (""); */
2481     g_free (debug);
2482     debug = NULL;
2483   }
2484
2485   /* create error message */
2486   GST_CAT_INFO (GST_CAT_ERROR_SYSTEM, "signaling error in %s: %s",
2487       GST_ELEMENT_NAME (element), sent_message);
2488   error = g_error_new (domain, code, sent_message);
2489
2490   /* if the element was already in error, stop now */
2491   if (GST_FLAG_IS_SET (element, GST_ELEMENT_IN_ERROR)) {
2492     GST_CAT_INFO (GST_CAT_ERROR_SYSTEM, "recursive ERROR detected in %s",
2493         GST_ELEMENT_NAME (element));
2494     g_free (sent_message);
2495     if (debug)
2496       g_free (debug);
2497     return;
2498   }
2499
2500   GST_FLAG_SET (element, GST_ELEMENT_IN_ERROR);
2501
2502   /* emit the signal, make sure the element stays available */
2503   gst_object_ref (GST_OBJECT (element));
2504   name = gst_object_get_path_string (GST_OBJECT (element));
2505   if (debug)
2506     sent_debug = g_strdup_printf ("%s(%d): %s: %s:\n%s",
2507         file, line, function, name, debug ? debug : "");
2508   else
2509     sent_debug = NULL;
2510   g_free (debug);
2511   g_free (name);
2512   g_signal_emit (G_OBJECT (element), gst_element_signals[ERROR], 0, element,
2513       error, sent_debug);
2514   GST_CAT_INFO (GST_CAT_ERROR_SYSTEM, "signalled error in %s: %s",
2515       GST_ELEMENT_NAME (element), sent_message);
2516
2517   /* tell the scheduler */
2518   if (element->sched) {
2519     gst_scheduler_error (element->sched, element);
2520   }
2521
2522   if (GST_STATE (element) == GST_STATE_PLAYING) {
2523     GstElementStateReturn ret;
2524
2525     ret = gst_element_set_state (element, GST_STATE_PAUSED);
2526     if (ret != GST_STATE_SUCCESS) {
2527       g_warning ("could not PAUSE element \"%s\" after error, help!",
2528           GST_ELEMENT_NAME (element));
2529     }
2530   }
2531
2532   GST_FLAG_UNSET (element, GST_ELEMENT_IN_ERROR);
2533
2534   /* cleanup */
2535   gst_object_unref (GST_OBJECT (element));
2536   g_free (sent_message);
2537   g_free (sent_debug);
2538   g_error_free (error);
2539 }
2540
2541 /**
2542  * gst_element_is_locked_state:
2543  * @element: a #GstElement.
2544  *
2545  * Checks if the state of an element is locked.
2546  * If the state of an element is locked, state changes of the parent don't 
2547  * affect the element.
2548  * This way you can leave currently unused elements inside bins. Just lock their
2549  * state before changing the state from #GST_STATE_NULL.
2550  *
2551  * Returns: TRUE, if the element's state is locked.
2552  */
2553 gboolean
2554 gst_element_is_locked_state (GstElement * element)
2555 {
2556   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
2557
2558   return GST_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE) ? TRUE : FALSE;
2559 }
2560
2561 /**
2562  * gst_element_set_locked_state:
2563  * @element: a #GstElement
2564  * @locked_state: TRUE to lock the element's state
2565  *
2566  * Locks the state of an element, so state changes of the parent don't affect
2567  * this element anymore.
2568  */
2569 void
2570 gst_element_set_locked_state (GstElement * element, gboolean locked_state)
2571 {
2572   gboolean old;
2573
2574   g_return_if_fail (GST_IS_ELEMENT (element));
2575
2576   old = GST_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
2577
2578   if (old == locked_state)
2579     return;
2580
2581   if (locked_state) {
2582     GST_CAT_DEBUG (GST_CAT_STATES, "locking state of element %s",
2583         GST_ELEMENT_NAME (element));
2584     GST_FLAG_SET (element, GST_ELEMENT_LOCKED_STATE);
2585   } else {
2586     GST_CAT_DEBUG (GST_CAT_STATES, "unlocking state of element %s",
2587         GST_ELEMENT_NAME (element));
2588     GST_FLAG_UNSET (element, GST_ELEMENT_LOCKED_STATE);
2589   }
2590 }
2591
2592 /**
2593  * gst_element_sync_state_with_parent:
2594  * @element: a #GstElement.
2595  *
2596  * Tries to change the state of the element to the same as its parent.
2597  * If this function returns FALSE, the state of element is undefined.
2598  *
2599  * Returns: TRUE, if the element's state could be synced to the parent's state.
2600  */
2601 gboolean
2602 gst_element_sync_state_with_parent (GstElement * element)
2603 {
2604   GstElement *parent;
2605
2606   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
2607   parent = GST_ELEMENT (GST_ELEMENT_PARENT (element));
2608   g_return_val_if_fail (GST_IS_BIN (parent), FALSE);
2609
2610   GST_CAT_DEBUG (GST_CAT_STATES, "syncing state of element %s (%s) to %s (%s)",
2611       GST_ELEMENT_NAME (element),
2612       gst_element_state_get_name (GST_STATE (element)),
2613       GST_ELEMENT_NAME (parent),
2614       gst_element_state_get_name (GST_STATE (parent)));
2615   if (gst_element_set_state (element, GST_STATE (parent)) == GST_STATE_FAILURE) {
2616     return FALSE;
2617   }
2618   return TRUE;
2619 }
2620
2621 /**
2622  * gst_element_get_state:
2623  * @element: a #GstElement to get the state of.
2624  *
2625  * Gets the state of the element. 
2626  *
2627  * Returns: the #GstElementState of the element.
2628  */
2629 GstElementState
2630 gst_element_get_state (GstElement * element)
2631 {
2632   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_VOID_PENDING);
2633
2634   return GST_STATE (element);
2635 }
2636
2637 /**
2638  * gst_element_wait_state_change:
2639  * @element: a #GstElement to wait for a state change on.
2640  *
2641  * Waits and blocks until the element changed its state.
2642  */
2643 void
2644 gst_element_wait_state_change (GstElement * element)
2645 {
2646   g_mutex_lock (element->state_mutex);
2647   g_cond_wait (element->state_cond, element->state_mutex);
2648   g_mutex_unlock (element->state_mutex);
2649 }
2650
2651 /**
2652  * gst_element_set_state:
2653  * @element: a #GstElement to change state of.
2654  * @state: the element's new #GstElementState.
2655  *
2656  * Sets the state of the element. This function will try to set the
2657  * requested state by going through all the intermediary states and calling
2658  * the class's state change function for each.
2659  *
2660  * Returns: TRUE if the state was successfully set.
2661  * (using #GstElementStateReturn).
2662  */
2663 GstElementStateReturn
2664 gst_element_set_state (GstElement * element, GstElementState state)
2665 {
2666   GstElementClass *oclass;
2667   GstElementState curpending;
2668   GstElementStateReturn return_val = GST_STATE_SUCCESS;
2669
2670   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
2671
2672   /* start with the current state */
2673   curpending = GST_STATE (element);
2674
2675   if (state == curpending) {
2676     GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2677         "element is already in requested state %s",
2678         gst_element_state_get_name (state));
2679     return (GST_STATE_SUCCESS);
2680   }
2681
2682   GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "setting state from %s to %s",
2683       gst_element_state_get_name (curpending),
2684       gst_element_state_get_name (state));
2685
2686   /* loop until the final requested state is set */
2687   while (GST_STATE (element) != state
2688       && GST_STATE (element) != GST_STATE_VOID_PENDING) {
2689     /* move the curpending state in the correct direction */
2690     if (curpending < state)
2691       curpending <<= 1;
2692     else
2693       curpending >>= 1;
2694
2695     /* set the pending state variable */
2696     /* FIXME: should probably check to see that we don't already have one */
2697     GST_STATE_PENDING (element) = curpending;
2698
2699     if (curpending != state) {
2700       GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2701           "intermediate: setting state from %s to %s",
2702           gst_element_state_get_name (GST_STATE (element)),
2703           gst_element_state_get_name (curpending));
2704     }
2705
2706     /* call the state change function so it can set the state */
2707     oclass = GST_ELEMENT_GET_CLASS (element);
2708     if (oclass->change_state)
2709       return_val = (oclass->change_state) (element);
2710
2711     switch (return_val) {
2712       case GST_STATE_FAILURE:
2713         GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
2714             "have failed change_state return");
2715         goto exit;
2716       case GST_STATE_ASYNC:
2717         GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
2718             "element will change state async");
2719         goto exit;
2720       case GST_STATE_SUCCESS:
2721         /* Last thing we do is verify that a successful state change really
2722          * did change the state... */
2723         /* if it did not, this is an error - fix the element that does this */
2724         if (GST_STATE (element) != curpending) {
2725           g_warning ("element %s claimed state-change success,"
2726               "but state didn't change to %s. State is %s (%s pending), fix the element",
2727               GST_ELEMENT_NAME (element),
2728               gst_element_state_get_name (curpending),
2729               gst_element_state_get_name (GST_STATE (element)),
2730               gst_element_state_get_name (GST_STATE_PENDING (element)));
2731           return_val = GST_STATE_FAILURE;
2732           goto exit;
2733         }
2734         break;
2735       default:
2736         /* somebody added a GST_STATE_ and forgot to do stuff here ! */
2737         g_assert_not_reached ();
2738     }
2739   }
2740 exit:
2741
2742   return return_val;
2743 }
2744
2745 static gboolean
2746 gst_element_negotiate_pads (GstElement * element)
2747 {
2748   GList *pads = GST_ELEMENT_PADS (element);
2749
2750   GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, element, "negotiating pads");
2751
2752   while (pads) {
2753     GstPad *pad = GST_PAD (pads->data);
2754     GstRealPad *srcpad;
2755
2756     pads = g_list_next (pads);
2757
2758     if (!GST_IS_REAL_PAD (pad))
2759       continue;
2760
2761     srcpad = GST_PAD_REALIZE (pad);
2762
2763     /* if we have a link on this pad and it doesn't have caps
2764      * allready, try to negotiate */
2765     if (GST_PAD_IS_LINKED (srcpad) && !GST_PAD_CAPS (srcpad)) {
2766       GstRealPad *sinkpad;
2767       GstElementState otherstate;
2768       GstElement *parent;
2769
2770       sinkpad = GST_RPAD_PEER (GST_PAD_REALIZE (srcpad));
2771
2772       /* check the parent of the peer pad, if there is no parent do nothing */
2773       parent = GST_PAD_PARENT (sinkpad);
2774       if (!parent)
2775         continue;
2776
2777       /* skips pads that were already negotiating */
2778       if (GST_FLAG_IS_SET (sinkpad, GST_PAD_NEGOTIATING) ||
2779           GST_FLAG_IS_SET (srcpad, GST_PAD_NEGOTIATING))
2780         continue;
2781
2782       otherstate = GST_STATE (parent);
2783
2784       /* swap pads if needed */
2785       if (!GST_PAD_IS_SRC (srcpad)) {
2786         GstRealPad *temp;
2787
2788         temp = srcpad;
2789         srcpad = sinkpad;
2790         sinkpad = temp;
2791       }
2792
2793       /* only try to negotiate if the peer element is in PAUSED or higher too */
2794       if (otherstate >= GST_STATE_READY) {
2795         GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, element,
2796             "perform negotiate for %s:%s and %s:%s",
2797             GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
2798         if (gst_pad_renegotiate (pad) == GST_PAD_LINK_REFUSED)
2799           return FALSE;
2800       } else {
2801         GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, element,
2802             "not negotiating %s:%s and %s:%s, not in READY yet",
2803             GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
2804       }
2805     }
2806   }
2807
2808   return TRUE;
2809 }
2810
2811 static void
2812 gst_element_clear_pad_caps (GstElement * element)
2813 {
2814   GList *pads = GST_ELEMENT_PADS (element);
2815
2816   GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, element, "clearing pad caps");
2817
2818   while (pads) {
2819     GstPad *pad = GST_PAD (pads->data);
2820
2821     gst_pad_unnegotiate (pad);
2822     if (GST_IS_REAL_PAD (pad)) {
2823       gst_caps_replace (&GST_RPAD_EXPLICIT_CAPS (pad), NULL);
2824     }
2825
2826     pads = g_list_next (pads);
2827   }
2828 }
2829
2830 static void
2831 gst_element_pads_activate (GstElement * element, gboolean active)
2832 {
2833   GList *pads = element->pads;
2834
2835   while (pads) {
2836     GstPad *pad = GST_PAD (pads->data);
2837
2838     pads = g_list_next (pads);
2839
2840     if (!GST_IS_REAL_PAD (pad))
2841       continue;
2842
2843     gst_pad_set_active (pad, active);
2844   }
2845 }
2846
2847 static GstElementStateReturn
2848 gst_element_change_state (GstElement * element)
2849 {
2850   GstElementState old_state;
2851   GstObject *parent;
2852   gint old_pending, old_transition;
2853
2854   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
2855
2856   old_state = GST_STATE (element);
2857   old_pending = GST_STATE_PENDING (element);
2858   old_transition = GST_STATE_TRANSITION (element);
2859
2860   if (old_pending == GST_STATE_VOID_PENDING ||
2861       old_state == GST_STATE_PENDING (element)) {
2862     GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2863         "element is already in the %s state",
2864         gst_element_state_get_name (old_state));
2865     return GST_STATE_SUCCESS;
2866   }
2867
2868   GST_CAT_LOG_OBJECT (GST_CAT_STATES, element,
2869       "default handler sets state from %s to %s %04x",
2870       gst_element_state_get_name (old_state),
2871       gst_element_state_get_name (old_pending), old_transition);
2872
2873   /* we set the state change early for the negotiation functions */
2874   GST_STATE (element) = old_pending;
2875   GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING;
2876
2877   switch (old_transition) {
2878     case GST_STATE_PLAYING_TO_PAUSED:
2879       if (element->clock) {
2880         GstClockTime time = gst_clock_get_event_time (element->clock);
2881
2882         g_assert (time >= element->base_time);
2883         element->base_time = time - element->base_time;
2884         GST_CAT_LOG_OBJECT (GST_CAT_CLOCK, element, "setting base time to %"
2885             G_GINT64_FORMAT, element->base_time);
2886       }
2887       gst_element_pads_activate (element, FALSE);
2888       break;
2889     case GST_STATE_PAUSED_TO_PLAYING:
2890       gst_element_pads_activate (element, TRUE);
2891       if (element->clock) {
2892         GstClockTime time = gst_clock_get_event_time (element->clock);
2893
2894         element->base_time = time - element->base_time;
2895         GST_CAT_LOG_OBJECT (GST_CAT_CLOCK, element, "setting base time to %"
2896             G_GINT64_FORMAT, element->base_time);
2897       }
2898       break;
2899       /* if we are going to paused, we try to negotiate the pads */
2900     case GST_STATE_READY_TO_PAUSED:
2901       g_assert (element->base_time == 0);
2902       if (!gst_element_negotiate_pads (element))
2903         goto failure;
2904       break;
2905       /* going to the READY state clears all pad caps */
2906       /* FIXME: Why doesn't this happen on READY => NULL? -- Company */
2907     case GST_STATE_PAUSED_TO_READY:
2908       element->base_time = 0;
2909       gst_element_clear_pad_caps (element);
2910       break;
2911     default:
2912       break;
2913   }
2914
2915   parent = GST_ELEMENT_PARENT (element);
2916
2917   GST_CAT_LOG_OBJECT (GST_CAT_STATES, element,
2918       "signaling state change from %s to %s",
2919       gst_element_state_get_name (old_state),
2920       gst_element_state_get_name (GST_STATE (element)));
2921
2922   /* tell the scheduler if we have one */
2923   if (element->sched) {
2924     if (gst_scheduler_state_transition (element->sched, element,
2925             old_transition) != GST_STATE_SUCCESS) {
2926       GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
2927           "scheduler could not change state");
2928       goto failure;
2929     }
2930   }
2931
2932   /* tell our parent about the state change */
2933   if (parent && GST_IS_BIN (parent)) {
2934     gst_bin_child_state_change (GST_BIN (parent), old_state,
2935         GST_STATE (element), element);
2936   }
2937   /* at this point the state of the element could have changed again */
2938
2939   g_signal_emit (G_OBJECT (element), gst_element_signals[STATE_CHANGE],
2940       0, old_state, GST_STATE (element));
2941
2942   /* signal the state change in case somebody is waiting for us */
2943   g_mutex_lock (element->state_mutex);
2944   g_cond_signal (element->state_cond);
2945   g_mutex_unlock (element->state_mutex);
2946
2947   return GST_STATE_SUCCESS;
2948
2949 failure:
2950   /* undo the state change */
2951   GST_STATE (element) = old_state;
2952   GST_STATE_PENDING (element) = old_pending;
2953
2954   return GST_STATE_FAILURE;
2955 }
2956
2957 /**
2958  * gst_element_get_factory:
2959  * @element: a #GstElement to request the element factory of.
2960  *
2961  * Retrieves the factory that was used to create this element.
2962  *
2963  * Returns: the #GstElementFactory used for creating this element.
2964  */
2965 GstElementFactory *
2966 gst_element_get_factory (GstElement * element)
2967 {
2968   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
2969
2970   return GST_ELEMENT_GET_CLASS (element)->elementfactory;
2971 }
2972
2973 static void
2974 gst_element_dispose (GObject * object)
2975 {
2976   GstElement *element = GST_ELEMENT (object);
2977   GList *pads;
2978   GstPad *pad;
2979
2980   GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "dispose");
2981
2982   gst_element_set_state (element, GST_STATE_NULL);
2983
2984   /* first we break all our links with the ouside */
2985   if (element->pads) {
2986     GList *orig;
2987
2988     orig = pads = g_list_copy (element->pads);
2989     while (pads) {
2990       pad = GST_PAD (pads->data);
2991
2992       if (GST_PAD_PEER (pad)) {
2993         GST_CAT_DEBUG (GST_CAT_REFCOUNTING, "unlinking pad '%s'",
2994             GST_OBJECT_NAME (GST_OBJECT (GST_PAD (GST_PAD_PEER (pad)))));
2995         gst_pad_unlink (pad, GST_PAD (GST_PAD_PEER (pad)));
2996       }
2997       gst_element_remove_pad (element, pad);
2998
2999       pads = g_list_next (pads);
3000     }
3001     g_list_free (orig);
3002     g_list_free (element->pads);
3003     element->pads = NULL;
3004   }
3005
3006   element->numsrcpads = 0;
3007   element->numsinkpads = 0;
3008   element->numpads = 0;
3009   if (element->state_mutex)
3010     g_mutex_free (element->state_mutex);
3011   element->state_mutex = NULL;
3012   if (element->state_cond)
3013     g_cond_free (element->state_cond);
3014   element->state_cond = NULL;
3015
3016   if (element->prop_value_queue)
3017     g_async_queue_unref (element->prop_value_queue);
3018   element->prop_value_queue = NULL;
3019   if (element->property_mutex)
3020     g_mutex_free (element->property_mutex);
3021   element->property_mutex = NULL;
3022
3023   gst_object_replace ((GstObject **) & element->sched, NULL);
3024   gst_object_replace ((GstObject **) & element->clock, NULL);
3025
3026   G_OBJECT_CLASS (parent_class)->dispose (object);
3027 }
3028
3029 #ifndef GST_DISABLE_LOADSAVE
3030 /**
3031  * gst_element_save_thyself:
3032  * @element: a #GstElement to save.
3033  * @parent: the xml parent node.
3034  *
3035  * Saves the element as part of the given XML structure.
3036  *
3037  * Returns: the new #xmlNodePtr.
3038  */
3039 static xmlNodePtr
3040 gst_element_save_thyself (GstObject * object, xmlNodePtr parent)
3041 {
3042   GList *pads;
3043   GstElementClass *oclass;
3044   GParamSpec **specs, *spec;
3045   gint nspecs, i;
3046   GValue value = { 0, };
3047   GstElement *element;
3048
3049   g_return_val_if_fail (GST_IS_ELEMENT (object), parent);
3050
3051   element = GST_ELEMENT (object);
3052
3053   oclass = GST_ELEMENT_GET_CLASS (element);
3054
3055   xmlNewChild (parent, NULL, "name", GST_ELEMENT_NAME (element));
3056
3057   if (oclass->elementfactory != NULL) {
3058     GstElementFactory *factory = (GstElementFactory *) oclass->elementfactory;
3059
3060     xmlNewChild (parent, NULL, "type", GST_PLUGIN_FEATURE (factory)->name);
3061   }
3062
3063 /* FIXME: what is this? */
3064 /*  if (element->manager) */
3065 /*    xmlNewChild(parent, NULL, "manager", GST_ELEMENT_NAME(element->manager)); */
3066
3067   /* params */
3068   specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (object), &nspecs);
3069
3070   for (i = 0; i < nspecs; i++) {
3071     spec = specs[i];
3072     if (spec->flags & G_PARAM_READABLE) {
3073       xmlNodePtr param;
3074       char *contents;
3075
3076       g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (spec));
3077
3078       g_object_get_property (G_OBJECT (element), spec->name, &value);
3079       param = xmlNewChild (parent, NULL, "param", NULL);
3080       xmlNewChild (param, NULL, "name", spec->name);
3081
3082       if (G_IS_PARAM_SPEC_STRING (spec))
3083         contents = g_value_dup_string (&value);
3084       else if (G_IS_PARAM_SPEC_ENUM (spec))
3085         contents = g_strdup_printf ("%d", g_value_get_enum (&value));
3086       else if (G_IS_PARAM_SPEC_INT64 (spec))
3087         contents = g_strdup_printf ("%" G_GINT64_FORMAT,
3088             g_value_get_int64 (&value));
3089       else
3090         contents = g_strdup_value_contents (&value);
3091
3092       xmlNewChild (param, NULL, "value", contents);
3093       g_free (contents);
3094
3095       g_value_unset (&value);
3096     }
3097   }
3098
3099   pads = GST_ELEMENT_PADS (element);
3100
3101   while (pads) {
3102     GstPad *pad = GST_PAD (pads->data);
3103
3104     /* figure out if it's a direct pad or a ghostpad */
3105     if (GST_ELEMENT (GST_OBJECT_PARENT (pad)) == element) {
3106       xmlNodePtr padtag = xmlNewChild (parent, NULL, "pad", NULL);
3107
3108       gst_object_save_thyself (GST_OBJECT (pad), padtag);
3109     }
3110     pads = g_list_next (pads);
3111   }
3112
3113   return parent;
3114 }
3115
3116 static void
3117 gst_element_restore_thyself (GstObject * object, xmlNodePtr self)
3118 {
3119   xmlNodePtr children;
3120   GstElement *element;
3121   gchar *name = NULL;
3122   gchar *value = NULL;
3123
3124   element = GST_ELEMENT (object);
3125   g_return_if_fail (element != NULL);
3126
3127   /* parameters */
3128   children = self->xmlChildrenNode;
3129   while (children) {
3130     if (!strcmp (children->name, "param")) {
3131       xmlNodePtr child = children->xmlChildrenNode;
3132
3133       while (child) {
3134         if (!strcmp (child->name, "name")) {
3135           name = xmlNodeGetContent (child);
3136         } else if (!strcmp (child->name, "value")) {
3137           value = xmlNodeGetContent (child);
3138         }
3139         child = child->next;
3140       }
3141       /* FIXME: can this just be g_object_set ? */
3142       gst_util_set_object_arg (G_OBJECT (element), name, value);
3143       /* g_object_set (G_OBJECT (element), name, value, NULL); */
3144     }
3145     children = children->next;
3146   }
3147
3148   /* pads */
3149   children = self->xmlChildrenNode;
3150   while (children) {
3151     if (!strcmp (children->name, "pad")) {
3152       gst_pad_load_and_link (children, GST_OBJECT (element));
3153     }
3154     children = children->next;
3155   }
3156
3157   if (GST_OBJECT_CLASS (parent_class)->restore_thyself)
3158     (GST_OBJECT_CLASS (parent_class)->restore_thyself) (object, self);
3159 }
3160 #endif /* GST_DISABLE_LOADSAVE */
3161
3162 /**
3163  * gst_element_yield:
3164  * @element: a #GstElement to yield.
3165  *
3166  * Requests a yield operation for the element. The scheduler will typically
3167  * give control to another element.
3168  */
3169 void
3170 gst_element_yield (GstElement * element)
3171 {
3172   if (GST_ELEMENT_SCHED (element)) {
3173     gst_scheduler_yield (GST_ELEMENT_SCHED (element), element);
3174   }
3175 }
3176
3177 /**
3178  * gst_element_interrupt:
3179  * @element: a #GstElement to interrupt.
3180  *
3181  * Requests the scheduler of this element to interrupt the execution of
3182  * this element and scheduler another one.
3183  *
3184  * Returns: TRUE if the element should exit its chain/loop/get
3185  * function ASAP, depending on the scheduler implementation.
3186  */
3187 gboolean
3188 gst_element_interrupt (GstElement * element)
3189 {
3190   if (GST_ELEMENT_SCHED (element)) {
3191     return gst_scheduler_interrupt (GST_ELEMENT_SCHED (element), element);
3192   } else
3193     return TRUE;
3194 }
3195
3196 /**
3197  * gst_element_set_scheduler:
3198  * @element: a #GstElement to set the scheduler of.
3199  * @sched: the #GstScheduler to set.
3200  *
3201  * Sets the scheduler of the element.  For internal use only, unless you're
3202  * writing a new bin subclass.
3203  */
3204 void
3205 gst_element_set_scheduler (GstElement * element, GstScheduler * sched)
3206 {
3207   g_return_if_fail (GST_IS_ELEMENT (element));
3208
3209   GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, element, "setting scheduler to %p",
3210       sched);
3211
3212   gst_object_replace ((GstObject **) & GST_ELEMENT_SCHED (element),
3213       GST_OBJECT (sched));
3214 }
3215
3216 /**
3217  * gst_element_get_scheduler:
3218  * @element: a #GstElement to get the scheduler of.
3219  *
3220  * Returns the scheduler of the element.
3221  *
3222  * Returns: the element's #GstScheduler.
3223  */
3224 GstScheduler *
3225 gst_element_get_scheduler (GstElement * element)
3226 {
3227   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
3228
3229   return GST_ELEMENT_SCHED (element);
3230 }
3231
3232 /**
3233  * gst_element_set_loop_function:
3234  * @element: a #GstElement to set the loop function of.
3235  * @loop: Pointer to #GstElementLoopFunction.
3236  *
3237  * This sets the loop function for the element.  The function pointed to
3238  * can deviate from the GstElementLoopFunction definition in type of
3239  * pointer only.
3240  *
3241  * NOTE: in order for this to take effect, the current loop function *must*
3242  * exit.  Assuming the loop function itself is the only one who will cause
3243  * a new loopfunc to be assigned, this should be no problem.
3244  */
3245 void
3246 gst_element_set_loop_function (GstElement * element,
3247     GstElementLoopFunction loop)
3248 {
3249   gboolean need_notify = FALSE;
3250
3251   g_return_if_fail (GST_IS_ELEMENT (element));
3252
3253   /* if the element changed from loop based to chain/get based
3254    * or vice versa, we need to inform the scheduler about that */
3255   if ((element->loopfunc == NULL && loop != NULL) ||
3256       (element->loopfunc != NULL && loop == NULL)) {
3257     need_notify = TRUE;
3258   }
3259
3260   /* set the loop function */
3261   element->loopfunc = loop;
3262
3263   if (need_notify) {
3264     /* set the NEW_LOOPFUNC flag so everyone knows to go try again */
3265     GST_FLAG_SET (element, GST_ELEMENT_NEW_LOOPFUNC);
3266
3267     if (GST_ELEMENT_SCHED (element)) {
3268       gst_scheduler_scheduling_change (GST_ELEMENT_SCHED (element), element);
3269     }
3270   }
3271 }
3272 static inline void
3273 gst_element_emit_found_tag (GstElement * element, GstElement * source,
3274     const GstTagList * tag_list)
3275 {
3276   gst_object_ref (GST_OBJECT (element));
3277   g_signal_emit (element, gst_element_signals[FOUND_TAG], 0, source, tag_list);
3278   gst_object_unref (GST_OBJECT (element));
3279 }
3280 static void
3281 gst_element_found_tag_func (GstElement * element, GstElement * source,
3282     const GstTagList * tag_list)
3283 {
3284   /* tell the parent */
3285   if (GST_OBJECT_PARENT (element)) {
3286     GST_CAT_LOG_OBJECT (GST_CAT_EVENT, element, "forwarding tag event to %s",
3287         GST_OBJECT_NAME (GST_OBJECT_PARENT (element)));
3288     gst_element_emit_found_tag (GST_ELEMENT (GST_OBJECT_PARENT (element)),
3289         source, tag_list);
3290   }
3291 }
3292
3293 /**
3294  * gst_element_found_tags:
3295  * @element: the element that found the tags
3296  * @tag_list: the found tags
3297  *
3298  * This function emits the found_tags signal. This is a recursive signal, so
3299  * every parent will emit that signal, too, before this function returns.
3300  * Only emit this signal, when you extracted these tags out of the data stream,
3301  * not when you handle an event.
3302  */
3303 void
3304 gst_element_found_tags (GstElement * element, const GstTagList * tag_list)
3305 {
3306   gst_element_emit_found_tag (element, element, tag_list);
3307 }
3308
3309 /**
3310  * gst_element_found_tags_for_pad:
3311  * @element: element that found the tag
3312  * @pad: src pad the tags correspond to
3313  * @timestamp: time the tags were found
3314  * @list: the taglist
3315  *
3316  * This is a convenience routine for tag finding. Most of the time you only
3317  * want to push the found tags down one pad, in that case this function is for
3318  * you. It takes ownership of the taglist, emits the found-tag signal and pushes 
3319  * a tag event down the pad.
3320  * <note>This function may not be used in a #GstPadGetFunction, because it calls 
3321  * gst_pad_push(). In those functions, call gst_element_found_tags(), create a 
3322  * tag event with gst_event_new_tag() and return that from your 
3323  * #GstPadGetFunction.</note>
3324  */
3325 void
3326 gst_element_found_tags_for_pad (GstElement * element, GstPad * pad,
3327     GstClockTime timestamp, GstTagList * list)
3328 {
3329   GstEvent *tag_event;
3330
3331   g_return_if_fail (GST_IS_ELEMENT (element));
3332   g_return_if_fail (GST_IS_REAL_PAD (pad));
3333   g_return_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SRC);
3334   g_return_if_fail (element == GST_PAD_PARENT (pad));
3335   g_return_if_fail (list != NULL);
3336
3337   tag_event = gst_event_new_tag (list);
3338   GST_EVENT_TIMESTAMP (tag_event) = timestamp;
3339   gst_element_found_tags (element, gst_event_tag_get_list (tag_event));
3340   if (GST_PAD_IS_USABLE (pad)) {
3341     gst_pad_push (pad, GST_DATA (tag_event));
3342   } else {
3343     gst_data_unref (GST_DATA (tag_event));
3344   }
3345 }
3346
3347 static inline void
3348 gst_element_set_eos_recursive (GstElement * element)
3349 {
3350   /* this function is only called, when we were in PLAYING before. So every 
3351      parent that's PAUSED was PLAYING before. That means it has reached EOS. */
3352   GstElement *parent;
3353
3354   GST_CAT_DEBUG (GST_CAT_EVENT, "setting recursive EOS on %s",
3355       GST_OBJECT_NAME (element));
3356   g_signal_emit (G_OBJECT (element), gst_element_signals[EOS], 0);
3357
3358   if (!GST_OBJECT_PARENT (element))
3359     return;
3360
3361   parent = GST_ELEMENT (GST_OBJECT_PARENT (element));
3362   if (GST_STATE (parent) == GST_STATE_PAUSED)
3363     gst_element_set_eos_recursive (parent);
3364 }
3365
3366 /**
3367  * gst_element_set_eos:
3368  * @element: a #GstElement to set to the EOS state.
3369  *
3370  * Perform the actions needed to bring the element in the EOS state.
3371  */
3372 void
3373 gst_element_set_eos (GstElement * element)
3374 {
3375   g_return_if_fail (GST_IS_ELEMENT (element));
3376
3377   GST_CAT_DEBUG (GST_CAT_EVENT, "setting EOS on element %s",
3378       GST_OBJECT_NAME (element));
3379
3380   if (GST_STATE (element) == GST_STATE_PLAYING) {
3381     gst_element_set_state (element, GST_STATE_PAUSED);
3382     gst_element_set_eos_recursive (element);
3383   } else {
3384     g_signal_emit (G_OBJECT (element), gst_element_signals[EOS], 0);
3385   }
3386 }
3387
3388
3389 /**
3390  * gst_element_state_get_name:
3391  * @state: a #GstElementState to get the name of.
3392  *
3393  * Gets a string representing the given state.
3394  *
3395  * Returns: a string with the name of the state.
3396  */
3397 const gchar *
3398 gst_element_state_get_name (GstElementState state)
3399 {
3400   switch (state) {
3401 #ifdef GST_DEBUG_COLOR
3402     case GST_STATE_VOID_PENDING:
3403       return "NONE_PENDING";
3404       break;
3405     case GST_STATE_NULL:
3406       return "\033[01;34mNULL\033[00m";
3407       break;
3408     case GST_STATE_READY:
3409       return "\033[01;31mREADY\033[00m";
3410       break;
3411     case GST_STATE_PLAYING:
3412       return "\033[01;32mPLAYING\033[00m";
3413       break;
3414     case GST_STATE_PAUSED:
3415       return "\033[01;33mPAUSED\033[00m";
3416       break;
3417     default:
3418       /* This is a memory leak */
3419       return g_strdup_printf ("\033[01;35;41mUNKNOWN!\033[00m(%d)", state);
3420 #else
3421     case GST_STATE_VOID_PENDING:
3422       return "NONE_PENDING";
3423       break;
3424     case GST_STATE_NULL:
3425       return "NULL";
3426       break;
3427     case GST_STATE_READY:
3428       return "READY";
3429       break;
3430     case GST_STATE_PLAYING:
3431       return "PLAYING";
3432       break;
3433     case GST_STATE_PAUSED:
3434       return "PAUSED";
3435       break;
3436     default:
3437       return "UNKNOWN!";
3438 #endif
3439   }
3440   return "";
3441 }
3442
3443 static void
3444 gst_element_populate_std_props (GObjectClass * klass, const gchar * prop_name,
3445     guint arg_id, GParamFlags flags)
3446 {
3447   GQuark prop_id = g_quark_from_string (prop_name);
3448   GParamSpec *pspec;
3449
3450   static GQuark fd_id = 0;
3451   static GQuark blocksize_id;
3452   static GQuark bytesperread_id;
3453   static GQuark dump_id;
3454   static GQuark filesize_id;
3455   static GQuark mmapsize_id;
3456   static GQuark location_id;
3457   static GQuark offset_id;
3458   static GQuark silent_id;
3459   static GQuark touch_id;
3460
3461   if (!fd_id) {
3462     fd_id = g_quark_from_static_string ("fd");
3463     blocksize_id = g_quark_from_static_string ("blocksize");
3464     bytesperread_id = g_quark_from_static_string ("bytesperread");
3465     dump_id = g_quark_from_static_string ("dump");
3466     filesize_id = g_quark_from_static_string ("filesize");
3467     mmapsize_id = g_quark_from_static_string ("mmapsize");
3468     location_id = g_quark_from_static_string ("location");
3469     offset_id = g_quark_from_static_string ("offset");
3470     silent_id = g_quark_from_static_string ("silent");
3471     touch_id = g_quark_from_static_string ("touch");
3472   }
3473
3474   if (prop_id == fd_id) {
3475     pspec = g_param_spec_int ("fd", "File-descriptor",
3476         "File-descriptor for the file being read", 0, G_MAXINT, 0, flags);
3477   } else if (prop_id == blocksize_id) {
3478     pspec = g_param_spec_ulong ("blocksize", "Block Size",
3479         "Block size to read per buffer", 0, G_MAXULONG, 4096, flags);
3480
3481   } else if (prop_id == bytesperread_id) {
3482     pspec = g_param_spec_int ("bytesperread", "Bytes per read",
3483         "Number of bytes to read per buffer", G_MININT, G_MAXINT, 0, flags);
3484
3485   } else if (prop_id == dump_id) {
3486     pspec = g_param_spec_boolean ("dump", "Dump",
3487         "Dump bytes to stdout", FALSE, flags);
3488
3489   } else if (prop_id == filesize_id) {
3490     pspec = g_param_spec_int64 ("filesize", "File Size",
3491         "Size of the file being read", 0, G_MAXINT64, 0, flags);
3492
3493   } else if (prop_id == mmapsize_id) {
3494     pspec = g_param_spec_ulong ("mmapsize", "mmap() Block Size",
3495         "Size in bytes of mmap()d regions", 0, G_MAXULONG, 4 * 1048576, flags);
3496
3497   } else if (prop_id == location_id) {
3498     pspec = g_param_spec_string ("location", "File Location",
3499         "Location of the file to read", NULL, flags);
3500
3501   } else if (prop_id == offset_id) {
3502     pspec = g_param_spec_int64 ("offset", "File Offset",
3503         "Byte offset of current read pointer", 0, G_MAXINT64, 0, flags);
3504
3505   } else if (prop_id == silent_id) {
3506     pspec = g_param_spec_boolean ("silent", "Silent", "Don't produce events",
3507         FALSE, flags);
3508
3509   } else if (prop_id == touch_id) {
3510     pspec = g_param_spec_boolean ("touch", "Touch read data",
3511         "Touch data to force disk read before " "push ()", TRUE, flags);
3512   } else {
3513     g_warning ("Unknown - 'standard' property '%s' id %d from klass %s",
3514         prop_name, arg_id, g_type_name (G_OBJECT_CLASS_TYPE (klass)));
3515     pspec = NULL;
3516   }
3517
3518   if (pspec) {
3519     g_object_class_install_property (klass, arg_id, pspec);
3520   }
3521 }
3522
3523 /**
3524  * gst_element_class_install_std_props:
3525  * @klass: the #GstElementClass to add the properties to.
3526  * @first_name: the name of the first property.
3527  * in a NULL terminated
3528  * @...: the id and flags of the first property, followed by
3529  * further 'name', 'id', 'flags' triplets and terminated by NULL.
3530  * 
3531  * Adds a list of standardized properties with types to the @klass.
3532  * the id is for the property switch in your get_prop method, and
3533  * the flags determine readability / writeability.
3534  **/
3535 void
3536 gst_element_class_install_std_props (GstElementClass * klass,
3537     const gchar * first_name, ...)
3538 {
3539   const char *name;
3540
3541   va_list args;
3542
3543   g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
3544
3545   va_start (args, first_name);
3546
3547   name = first_name;
3548
3549   while (name) {
3550     int arg_id = va_arg (args, int);
3551     int flags = va_arg (args, int);
3552
3553     gst_element_populate_std_props ((GObjectClass *) klass, name, arg_id,
3554         flags);
3555
3556     name = va_arg (args, char *);
3557   }
3558
3559   va_end (args);
3560 }
3561
3562 /**
3563  * gst_element_get_managing_bin:
3564  * @element: a #GstElement to get the managing bin of.
3565  * 
3566  * Gets the managing bin (a pipeline or a thread, for example) of an element.
3567  *
3568  * Returns: the #GstBin, or NULL on failure.
3569  **/
3570 GstBin *
3571 gst_element_get_managing_bin (GstElement * element)
3572 {
3573   GstBin *bin;
3574
3575   g_return_val_if_fail (element != NULL, NULL);
3576
3577   bin = GST_BIN (gst_object_get_parent (GST_OBJECT (element)));
3578
3579   while (bin && !GST_FLAG_IS_SET (GST_OBJECT (bin), GST_BIN_FLAG_MANAGER))
3580     bin = GST_BIN (gst_object_get_parent (GST_OBJECT (bin)));
3581
3582   return bin;
3583 }