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