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