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