- an element also has a failed state change if the scheduler setup failed.
[platform/upstream/gstreamer.git] / gst / gstelement.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2000 Wim Taymans <wtay@chello.be>
4  *
5  * gstelement.c: The base element, all elements derive from this
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 /* #define GST_DEBUG_ENABLED */
24 #include <glib.h>
25 #include <stdarg.h>
26 #include <gobject/gvaluecollector.h>
27 #include "gst_private.h"
28
29 #include "gstelement.h"
30 #include "gstextratypes.h"
31 #include "gstbin.h"
32 #include "gstscheduler.h"
33 #include "gstevent.h"
34 #include "gstutils.h"
35 #include "gstlog.h"
36
37 /* Element signals and args */
38 enum {
39   STATE_CHANGE,
40   NEW_PAD,
41   PAD_REMOVED,
42   ERROR,
43   EOS,
44   LAST_SIGNAL
45 };
46
47 enum {
48   ARG_0,
49   /* FILL ME */
50 };
51
52 #define CLASS(element)  GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS (element))
53
54 static void                     gst_element_class_init          (GstElementClass *klass);
55 static void                     gst_element_init                (GstElement *element);
56 static void                     gst_element_base_class_init     (GstElementClass *klass);
57
58 static void                     gst_element_real_set_property   (GObject *object, guint prop_id, 
59                                                                  const GValue *value, GParamSpec *pspec);
60 static void                     gst_element_real_get_property   (GObject *object, guint prop_id, GValue *value, 
61                                                                  GParamSpec *pspec);
62
63 static void                     gst_element_dispose             (GObject *object);
64
65 static gboolean                 gst_element_send_event_default  (GstElement *element, GstEvent *event);
66 static gboolean                 gst_element_query_default       (GstElement *element, GstPadQueryType type,
67                                                                  GstFormat *format, gint64 *value);
68
69 static GstElementStateReturn    gst_element_change_state        (GstElement *element);
70 static void                     gst_element_error_func          (GstElement* element, GstElement *source, gchar *errormsg);
71
72 #ifndef GST_DISABLE_LOADSAVE
73 static xmlNodePtr               gst_element_save_thyself        (GstObject *object, xmlNodePtr parent);
74 static void                     gst_element_restore_thyself     (GstObject *parent, xmlNodePtr self);
75 #endif
76
77 GType _gst_element_type = 0;
78
79 static GstObjectClass *parent_class = NULL;
80 static guint gst_element_signals[LAST_SIGNAL] = { 0 };
81
82 GType gst_element_get_type (void) 
83 {
84   if (!_gst_element_type) {
85     static const GTypeInfo element_info = {
86       sizeof(GstElementClass),
87       (GBaseInitFunc)gst_element_base_class_init,
88       NULL,
89       (GClassInitFunc)gst_element_class_init,
90       NULL,
91       NULL,
92       sizeof(GstElement),
93       0,
94       (GInstanceInitFunc)gst_element_init,
95       NULL
96     };
97     _gst_element_type = g_type_register_static(GST_TYPE_OBJECT, "GstElement", 
98                           &element_info, G_TYPE_FLAG_ABSTRACT);
99   }
100   return _gst_element_type;
101 }
102
103 static void
104 gst_element_class_init (GstElementClass *klass)
105 {
106   GObjectClass *gobject_class;
107   GstObjectClass *gstobject_class;
108
109   gobject_class = (GObjectClass*) klass;
110   gstobject_class = (GstObjectClass*) klass;
111
112   parent_class = g_type_class_ref(GST_TYPE_OBJECT);
113
114   gst_element_signals[STATE_CHANGE] =
115     g_signal_new ("state_change", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
116                   G_STRUCT_OFFSET (GstElementClass, state_change), NULL, NULL,
117                   gst_marshal_VOID__INT_INT, G_TYPE_NONE, 2,
118                   G_TYPE_INT, G_TYPE_INT);
119   gst_element_signals[NEW_PAD] =
120     g_signal_new ("new_pad", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
121                   G_STRUCT_OFFSET (GstElementClass, new_pad), NULL, NULL,
122                   gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
123                   G_TYPE_OBJECT);
124   gst_element_signals[PAD_REMOVED] =
125     g_signal_new ("pad_removed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
126                   G_STRUCT_OFFSET (GstElementClass, pad_removed), NULL, NULL,
127                   gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
128                   G_TYPE_OBJECT);
129   gst_element_signals[ERROR] =
130     g_signal_new ("error", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
131                   G_STRUCT_OFFSET (GstElementClass, error), NULL, NULL,
132                   gst_marshal_VOID__OBJECT_STRING, G_TYPE_NONE, 2,
133                   G_TYPE_OBJECT, G_TYPE_STRING);
134   gst_element_signals[EOS] =
135     g_signal_new ("eos", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
136                   G_STRUCT_OFFSET (GstElementClass,eos), NULL, NULL,
137                   gst_marshal_VOID__VOID, G_TYPE_NONE, 0);
138
139   gobject_class->set_property           = GST_DEBUG_FUNCPTR (gst_element_real_set_property);
140   gobject_class->get_property           = GST_DEBUG_FUNCPTR (gst_element_real_get_property);
141
142   gobject_class->dispose                = GST_DEBUG_FUNCPTR (gst_element_dispose);
143
144 #ifndef GST_DISABLE_LOADSAVE
145   gstobject_class->save_thyself         = GST_DEBUG_FUNCPTR (gst_element_save_thyself);
146   gstobject_class->restore_thyself      = GST_DEBUG_FUNCPTR (gst_element_restore_thyself);
147 #endif
148
149   klass->change_state                   = GST_DEBUG_FUNCPTR (gst_element_change_state);
150   klass->error                          = GST_DEBUG_FUNCPTR (gst_element_error_func);
151   klass->elementfactory                 = NULL;
152   klass->padtemplates                   = NULL;
153   klass->numpadtemplates                = 0;
154   klass->send_event                     = GST_DEBUG_FUNCPTR (gst_element_send_event_default);
155   klass->query                          = GST_DEBUG_FUNCPTR (gst_element_query_default);
156 }
157
158 static void
159 gst_element_base_class_init (GstElementClass *klass)
160 {
161   GObjectClass *gobject_class;
162
163   gobject_class = (GObjectClass*) klass;
164
165   gobject_class->set_property =         GST_DEBUG_FUNCPTR(gst_element_real_set_property);
166   gobject_class->get_property =         GST_DEBUG_FUNCPTR(gst_element_real_get_property);
167 }
168
169 static void
170 gst_element_init (GstElement *element)
171 {
172   element->current_state = GST_STATE_NULL;
173   element->pending_state = GST_STATE_VOID_PENDING;
174   element->numpads = 0;
175   element->numsrcpads = 0;
176   element->numsinkpads = 0;
177   element->pads = NULL;
178   element->loopfunc = NULL;
179   element->sched = NULL;
180   element->clock = NULL;
181   element->sched_private = NULL;
182   element->state_mutex = g_mutex_new ();
183   element->state_cond = g_cond_new ();
184 }
185
186 static void
187 gst_element_real_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
188 {
189   GstElementClass *oclass = CLASS (object);
190
191   if (oclass->set_property)
192     (oclass->set_property) (object, prop_id, value, pspec);
193 }
194
195 static void
196 gst_element_real_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
197 {
198   GstElementClass *oclass = CLASS (object);
199
200   if (oclass->get_property)
201     (oclass->get_property) (object, prop_id, value, pspec);
202 }
203
204 /** 
205  * gst_element_default_error:
206  * @object: a #GObject that signalled the error.
207  * @orig: the #GstObject that initiated the error.
208  * @error: the error message.
209  *
210  * Adds a default error signal callback to an
211  * element. The user data passed to the g_signal_connect is
212  * ignored.
213  * The default handler will simply print the error string 
214  * using g_print.
215  */
216 void
217 gst_element_default_error (GObject *object, GstObject *orig, gchar *error)
218
219   g_print ("ERROR: %s: %s\n", GST_OBJECT_NAME (orig), error);
220
221
222 typedef struct {
223   const GParamSpec *pspec;
224   GValue value;
225 } prop_value_t;
226
227 static void
228 element_set_property (GstElement *element, const GParamSpec *pspec, const GValue *value)
229 {
230   prop_value_t *prop_value = g_new0 (prop_value_t, 1);
231
232   prop_value->pspec = pspec;
233   prop_value->value = *value;
234
235   g_async_queue_push (element->prop_value_queue, prop_value);
236 }
237
238 static void
239 element_get_property (GstElement *element, const GParamSpec *pspec, GValue *value)
240 {
241   g_mutex_lock (element->property_mutex);
242   g_object_get_property ((GObject*)element, pspec->name, value);
243   g_mutex_unlock (element->property_mutex);
244 }
245
246 static void
247 gst_element_threadsafe_properties_pre_run (GstElement *element)
248 {
249   GST_DEBUG (GST_CAT_THREAD, "locking element %s", GST_OBJECT_NAME (element));
250   g_mutex_lock (element->property_mutex);
251   gst_element_set_pending_properties (element);
252 }
253
254 static void
255 gst_element_threadsafe_properties_post_run (GstElement *element)
256 {
257   GST_DEBUG (GST_CAT_THREAD, "unlocking element %s", GST_OBJECT_NAME (element));
258   g_mutex_unlock (element->property_mutex);
259 }
260
261 /**
262  * gst_element_enable_threadsafe_properties:
263  * @element: a #GstElement to enable threadsafe properties on.
264  *
265  * Installs an asynchronous queue, a mutex and pre- and post-run functions on
266  * this element so that properties on the element can be set in a 
267  * threadsafe way.
268  */
269 void
270 gst_element_enable_threadsafe_properties (GstElement *element)
271 {
272   g_return_if_fail (GST_IS_ELEMENT (element));
273   
274   GST_FLAG_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES);
275   element->pre_run_func = gst_element_threadsafe_properties_pre_run;
276   element->post_run_func = gst_element_threadsafe_properties_post_run;
277   if (!element->prop_value_queue)
278     element->prop_value_queue = g_async_queue_new ();
279   if (!element->property_mutex)
280     element->property_mutex = g_mutex_new ();
281 }
282
283 /**
284  * gst_element_disable_threadsafe_properties:
285  * @element: a #GstElement to disable threadsafe properties on.
286  *
287  * Removes the threadsafe properties, post- and pre-run locks from
288  * this element.
289  */
290 void
291 gst_element_disable_threadsafe_properties (GstElement *element)
292 {
293   g_return_if_fail (GST_IS_ELEMENT (element));
294   
295   GST_FLAG_UNSET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES);
296   element->pre_run_func = NULL;
297   element->post_run_func = NULL;
298   /* let's keep around that async queue */
299 }
300
301 /**
302  * gst_element_set_pending_properties:
303  * @element: a #GstElement to set the pending properties on.
304  *
305  * Sets all pending properties on the threadsafe properties enabled
306  * element.
307  */
308 void
309 gst_element_set_pending_properties (GstElement *element) 
310 {
311   prop_value_t *prop_value;
312
313   while ((prop_value = g_async_queue_try_pop (element->prop_value_queue))) {
314     g_object_set_property ((GObject*)element, prop_value->pspec->name, &prop_value->value);
315     g_value_unset (&prop_value->value);
316     g_free (prop_value);
317   }
318 }
319
320 /* following 6 functions taken mostly from gobject.c */
321
322 /**
323  * gst_element_set:
324  * @element: a #GstElement to set properties on.
325  * @first_property_name: the first property to set.
326  * @...: value of the first property, and more properties to set, ending
327  *       with NULL.
328  *
329  * Sets properties on an element. If the element uses threadsafe properties,
330  * they will be queued and set on the object when it is scheduled again.
331  */
332 void
333 gst_element_set (GstElement *element, const gchar *first_property_name, ...)
334 {
335   va_list var_args;
336   
337   g_return_if_fail (GST_IS_ELEMENT (element));
338   
339   va_start (var_args, first_property_name);
340   gst_element_set_valist (element, first_property_name, var_args);
341   va_end (var_args);
342 }
343
344 /**
345  * gst_element_get:
346  * @element: a #GstElement to get properties of.
347  * @first_property_name: the first property to get.
348  * @...: pointer to a variable to store the first property in, as well as 
349  * more properties to get, ending with NULL.
350  *
351  * Gets properties from an element. If the element uses threadsafe properties,
352  * the element will be locked before getting the given properties.
353  */
354 void
355 gst_element_get (GstElement *element, const gchar *first_property_name, ...)
356 {
357   va_list var_args;
358   
359   g_return_if_fail (GST_IS_ELEMENT (element));
360   
361   va_start (var_args, first_property_name);
362   gst_element_get_valist (element, first_property_name, var_args);
363   va_end (var_args);
364 }
365
366 /**
367  * gst_element_set_valist:
368  * @element: a #GstElement to set properties on.
369  * @first_property_name: the first property to set.
370  * @var_args: the var_args list of other properties to get.
371  *
372  * Sets properties on an element. If the element uses threadsafe properties,
373  * the property change will be put on the async queue.
374  */
375 void
376 gst_element_set_valist (GstElement *element, const gchar *first_property_name, va_list var_args)
377 {
378   const gchar *name;
379   GObject *object;
380   
381   g_return_if_fail (GST_IS_ELEMENT (element));
382   
383   object = (GObject *) element;
384
385   GST_DEBUG (GST_CAT_PROPERTIES, 
386              "setting valist of properties starting with %s on element %s",
387              first_property_name, gst_element_get_name (element));
388
389   if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
390     g_object_set_valist (object, first_property_name, var_args);
391     return;
392   }
393
394   g_object_ref (object);
395   
396   name = first_property_name;
397
398   while (name)
399     {
400       GValue value = { 0, };
401       GParamSpec *pspec;
402       gchar *error = NULL;
403       
404       pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), name);
405
406       if (!pspec)
407         {
408           g_warning ("%s: object class `%s' has no property named `%s'",
409                      G_STRLOC,
410                      G_OBJECT_TYPE_NAME (object),
411                      name);
412           break;
413         }
414       if (!(pspec->flags & G_PARAM_WRITABLE))
415         {
416           g_warning ("%s: property `%s' of object class `%s' is not writable",
417                      G_STRLOC,
418                      pspec->name,
419                      G_OBJECT_TYPE_NAME (object));
420           break;
421         }
422       
423       g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
424       
425       G_VALUE_COLLECT (&value, var_args, 0, &error);
426       if (error)
427         {
428           g_warning ("%s: %s", G_STRLOC, error);
429           g_free (error);
430           
431           /* we purposely leak the value here, it might not be
432            * in a sane state if an error condition occoured
433            */
434           break;
435         }
436       
437       element_set_property (element, pspec, &value);
438       g_value_unset (&value);
439       
440       name = va_arg (var_args, gchar*);
441     }
442
443   g_object_unref (object);
444 }
445
446 /**
447  * gst_element_get_valist:
448  * @element: a #GstElement to get properties of.
449  * @first_property_name: the first property to get.
450  * @var_args: the var_args list of other properties to get.
451  *
452  * Gets properties from an element. If the element uses threadsafe properties,
453  * the element will be locked before getting the given properties.
454  */
455 void
456 gst_element_get_valist (GstElement *element, const gchar *first_property_name, va_list var_args)
457 {
458   const gchar *name;
459   GObject *object;
460   
461   g_return_if_fail (GST_IS_ELEMENT (element));
462   
463   object = (GObject*)element;
464
465   if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
466     g_object_get_valist (object, first_property_name, var_args);
467     return;
468   }
469
470   g_object_ref (object);
471   
472   name = first_property_name;
473   
474   while (name)
475     {
476       GValue value = { 0, };
477       GParamSpec *pspec;
478       gchar *error;
479       
480       pspec =  g_object_class_find_property (G_OBJECT_GET_CLASS (object), name);
481
482       if (!pspec)
483         {
484           g_warning ("%s: object class `%s' has no property named `%s'",
485                      G_STRLOC,
486                      G_OBJECT_TYPE_NAME (object),
487                      name);
488           break;
489         }
490       if (!(pspec->flags & G_PARAM_READABLE))
491         {
492           g_warning ("%s: property `%s' of object class `%s' is not readable",
493                      G_STRLOC,
494                      pspec->name,
495                      G_OBJECT_TYPE_NAME (object));
496           break;
497         }
498       
499       g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
500       
501       element_get_property (element, pspec, &value);
502       
503       G_VALUE_LCOPY (&value, var_args, 0, &error);
504       if (error)
505         {
506           g_warning ("%s: %s", G_STRLOC, error);
507           g_free (error);
508           g_value_unset (&value);
509           break;
510         }
511       
512       g_value_unset (&value);
513       
514       name = va_arg (var_args, gchar*);
515     }
516   
517   g_object_unref (object);
518 }
519
520 /**
521  * gst_element_set_property:
522  * @element: a #GstElement to set properties on.
523  * @property_name: the first property to get.
524  * @value: the #GValue that holds the value to set.
525  *
526  * Sets a property on an element. If the element uses threadsafe properties,
527  * the property will be put on the async queue.
528  */
529 void
530 gst_element_set_property (GstElement *element, const gchar *property_name, 
531                           const GValue *value)
532 {
533   GParamSpec *pspec;
534   GObject *object;
535   
536   g_return_if_fail (GST_IS_ELEMENT (element));
537   g_return_if_fail (property_name != NULL);
538   g_return_if_fail (G_IS_VALUE (value));
539   
540   object = (GObject*) element;
541
542   GST_DEBUG (GST_CAT_PROPERTIES, "setting property %s on element %s",
543              property_name, gst_element_get_name (element));
544   if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
545     g_object_set_property (object, property_name, value);
546     return;
547   }
548
549   g_object_ref (object);
550   
551   pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), 
552                                         property_name);
553   
554   if (!pspec)
555     g_warning ("%s: object class `%s' has no property named `%s'",
556                G_STRLOC,
557                G_OBJECT_TYPE_NAME (object),
558                property_name);
559   else
560     element_set_property (element, pspec, value);
561   
562   g_object_unref (object);
563 }
564   
565 /**
566  * gst_element_get_property:
567  * @element: a #GstElement to get properties of.
568  * @property_name: the first property to get.
569  * @value: the #GValue to store the property value in.
570  *
571  * Gets a property from an element. If the element uses threadsafe properties,
572  * the element will be locked before getting the given property.
573  */
574 void
575 gst_element_get_property (GstElement *element, const gchar *property_name, GValue *value)
576 {
577   GParamSpec *pspec;
578   GObject *object;
579   
580   g_return_if_fail (GST_IS_ELEMENT (element));
581   g_return_if_fail (property_name != NULL);
582   g_return_if_fail (G_IS_VALUE (value));
583   
584   object = (GObject*)element;
585
586   if (!GST_FLAG_IS_SET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES)) {
587     g_object_get_property (object, property_name, value);
588     return;
589   }
590
591   g_object_ref (object);
592   
593   pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), property_name);
594   
595   if (!pspec)
596     g_warning ("%s: object class `%s' has no property named `%s'",
597                G_STRLOC,
598                G_OBJECT_TYPE_NAME (object),
599                property_name);
600   else
601     {
602       GValue *prop_value, tmp_value = { 0, };
603       
604       /* auto-conversion of the callers value type
605        */
606       if (G_VALUE_TYPE (value) == G_PARAM_SPEC_VALUE_TYPE (pspec))
607         {
608           g_value_reset (value);
609           prop_value = value;
610         }
611       else if (!g_value_type_transformable (G_PARAM_SPEC_VALUE_TYPE (pspec), G_VALUE_TYPE (value)))
612         {
613           g_warning ("can't retrieve property `%s' of type `%s' as value of type `%s'",
614                      pspec->name,
615                      g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
616                      G_VALUE_TYPE_NAME (value));
617           g_object_unref (object);
618           return;
619         }
620       else
621         {
622           g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
623           prop_value = &tmp_value;
624         }
625       element_get_property (element, pspec, prop_value);
626       if (prop_value != value)
627         {
628           g_value_transform (prop_value, value);
629           g_value_unset (&tmp_value);
630         }
631     }
632   
633   g_object_unref (object);
634 }
635
636 static GstPad*
637 gst_element_request_pad (GstElement *element, GstPadTemplate *templ, const gchar* name)
638 {
639   GstPad *newpad = NULL;
640   GstElementClass *oclass;
641
642   oclass = CLASS (element);
643   if (oclass->request_new_pad)
644     newpad = (oclass->request_new_pad)(element, templ, name);
645
646   return newpad;
647 }
648
649 /**
650  * gst_element_release_request_pad:
651  * @element: a #GstElement to release the request pad of.
652  * @pad: the #GstPad to release.
653  *
654  * Makes the element free the previously requested pad as obtained
655  * with gst_element_get_request_pad().
656  */
657 void
658 gst_element_release_request_pad (GstElement *element, GstPad *pad)
659 {
660   GstElementClass *oclass;
661
662   g_return_if_fail (GST_IS_ELEMENT (element));
663   g_return_if_fail (GST_IS_PAD (pad));
664
665   oclass = CLASS (element);
666   if (oclass->release_pad)
667     (oclass->release_pad) (element, pad);
668 }
669
670
671 /**
672  * gst_element_set_name:
673  * @element: a #GstElement to set the name of.
674  * @name: the new name of the element.
675  *
676  * Sets the name of the element, getting rid of the old name if there was
677  * one.
678  */
679 void
680 gst_element_set_name (GstElement *element, const gchar *name)
681 {
682   g_return_if_fail (element != NULL);
683   g_return_if_fail (GST_IS_ELEMENT (element));
684
685   gst_object_set_name (GST_OBJECT (element), name);
686 }
687
688 /**
689  * gst_element_get_name:
690  * @element: a #GstElement to get the name of.
691  *
692  * Gets the name of the element.
693  *
694  * Returns: the name of the element.
695  */
696 const gchar*
697 gst_element_get_name (GstElement *element)
698 {
699   g_return_val_if_fail (element != NULL, NULL);
700   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
701
702   return GST_OBJECT_NAME (element);
703 }
704
705 /**
706  * gst_element_set_parent:
707  * @element: a #GstElement to set parent of.
708  * @parent: the new #GstObject parent of the object.
709  *
710  * Sets the parent of the element.
711  */
712 void
713 gst_element_set_parent (GstElement *element, GstObject *parent)
714 {
715   g_return_if_fail (element != NULL);
716   g_return_if_fail (GST_IS_ELEMENT (element));
717   g_return_if_fail (GST_OBJECT_PARENT (element) == NULL);
718   g_return_if_fail (parent != NULL);
719   g_return_if_fail (GST_IS_OBJECT (parent));
720   g_return_if_fail ((gpointer)element != (gpointer)parent);
721
722   gst_object_set_parent (GST_OBJECT (element), parent);
723 }
724
725 /**
726  * gst_element_get_parent:
727  * @element: a #GstElement to get the parent of.
728  *
729  * Gets the parent of the element.
730  *
731  * Returns: the #GstObject parent of the element.
732  */
733 GstObject*
734 gst_element_get_parent (GstElement *element)
735 {
736   g_return_val_if_fail (element != NULL, NULL);
737   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
738
739   return GST_OBJECT_PARENT (element);
740 }
741
742 /**
743  * gst_element_set_clock:
744  * @element: a #GstElement to set the clock for.
745  * @clock: the #GstClock to set for the element.
746  *
747  * Sets the clock for the element.
748  */
749 void
750 gst_element_set_clock (GstElement *element, GstClock *clock)
751 {
752   g_return_if_fail (element != NULL);
753   g_return_if_fail (GST_IS_ELEMENT (element));
754
755   if (element->setclockfunc)
756     element->setclockfunc (element, clock);
757
758   element->clock = clock;
759 }
760
761 /**
762  * gst_element_get_clock:
763  * @element: a #GstElement to get the clock of.
764  *
765  * Gets the clock of the element.
766  *
767  * Returns: the #GstClock of the element.
768  */
769 GstClock*
770 gst_element_get_clock (GstElement *element)
771 {
772   g_return_val_if_fail (element != NULL, NULL);
773   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
774   
775   if (element->getclockfunc)
776     return element->getclockfunc (element);
777
778   return NULL;
779 }
780
781 /**
782  * gst_element_clock_wait:
783  * @element: a #GstElement.
784  * @clock: the #GstClock to use.
785  * @time: the #GstClockTime to wait for on the clock.
786  * @jitter: the difference between requested time and actual time.
787  *
788  * Waits for a specific time on the clock.
789  *
790  * Returns: the #GstClockReturn result of the wait operation.
791  */
792 GstClockReturn
793 gst_element_clock_wait (GstElement *element, GstClock *clock, GstClockTime time, GstClockTimeDiff *jitter)
794 {
795   GstClockReturn res;
796
797   g_return_val_if_fail (element != NULL, GST_CLOCK_ERROR);
798   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_CLOCK_ERROR);
799
800   if (GST_ELEMENT_SCHED (element)) {
801     res = gst_scheduler_clock_wait (GST_ELEMENT_SCHED (element), element, clock, time, jitter);
802   }
803   else 
804     res = GST_CLOCK_TIMEOUT;
805
806   return res;
807 }
808
809
810 /**
811  * gst_element_release_locks:
812  * @element: a #GstElement to release all locks on.
813  *
814  * Instruct the element to release all the locks it is holding, such as
815  * blocking reads, waiting for the clock, ...
816  *
817  * Returns: TRUE if the locks could be released.
818  */
819 gboolean
820 gst_element_release_locks (GstElement *element)
821 {
822   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
823
824   if (CLASS (element)->release_locks)
825     return CLASS (element)->release_locks (element);
826   
827   return TRUE;
828 }
829
830 /**
831  * gst_element_add_pad:
832  * @element: a #GstElement to add the pad to.
833  * @pad: the #GstPad to add to the element.
834  *
835  * Add a pad (connection point) to the element, setting the parent of the
836  * pad to the element (and thus adding a reference).
837  */
838 void
839 gst_element_add_pad (GstElement *element, GstPad *pad)
840 {
841   g_return_if_fail (element != NULL);
842   g_return_if_fail (GST_IS_ELEMENT (element));
843   g_return_if_fail (pad != NULL);
844   g_return_if_fail (GST_IS_PAD (pad));
845
846   /* first check to make sure the pad's parent is already set */
847   g_return_if_fail (GST_PAD_PARENT (pad) == NULL);
848
849   /* then check to see if there's already a pad by that name here */
850   g_return_if_fail (gst_object_check_uniqueness (element->pads, GST_PAD_NAME(pad)) == TRUE);
851
852   /* set the pad's parent */
853   GST_DEBUG (GST_CAT_ELEMENT_PADS,"setting parent of pad '%s' to '%s'",
854         GST_PAD_NAME (pad), GST_ELEMENT_NAME (element));
855   gst_object_set_parent (GST_OBJECT (pad), GST_OBJECT (element));
856
857   /* add it to the list */
858   element->pads = g_list_append (element->pads, pad);
859   element->numpads++;
860   if (gst_pad_get_direction (pad) == GST_PAD_SRC)
861     element->numsrcpads++;
862   else
863     element->numsinkpads++;
864
865   /* emit the NEW_PAD signal */
866   g_signal_emit (G_OBJECT (element), gst_element_signals[NEW_PAD], 0, pad);
867 }
868
869 /**
870  * gst_element_remove_pad:
871  * @element: a #GstElement to remove pad from.
872  * @pad: the #GstPad to remove from the element.
873  *
874  * Remove a pad (connection point) from the element.
875  */
876 void
877 gst_element_remove_pad (GstElement *element, GstPad *pad)
878 {
879   g_return_if_fail (element != NULL);
880   g_return_if_fail (GST_IS_ELEMENT (element));
881   g_return_if_fail (pad != NULL);
882   g_return_if_fail (GST_IS_PAD (pad));
883
884   g_return_if_fail (GST_PAD_PARENT (pad) == element);
885
886   /* check to see if the pad is still connected */
887   /* FIXME: what if someone calls _remove_pad instead of 
888     _remove_ghost_pad? */
889   if (GST_IS_REAL_PAD (pad)) {
890     g_return_if_fail (GST_RPAD_PEER (pad) == NULL);
891   }
892   
893   /* remove it from the list */
894   element->pads = g_list_remove (element->pads, pad);
895   element->numpads--;
896   if (gst_pad_get_direction (pad) == GST_PAD_SRC)
897     element->numsrcpads--;
898   else
899     element->numsinkpads--;
900
901   g_signal_emit (G_OBJECT (element), gst_element_signals[PAD_REMOVED], 0, pad);
902
903   gst_object_unparent (GST_OBJECT (pad));
904 }
905
906 /**
907  * gst_element_add_ghost_pad:
908  * @element: a #GstElement to add the ghost pad to.
909  * @pad: the #GstPad from which the new ghost pad will be created.
910  * @name: the name of the new ghost pad.
911  *
912  * Creates a ghost pad from the given pad, and adds it to the list of pads
913  * for this element.
914  * 
915  * Returns: the added ghost #GstPad, or NULL, if no ghost pad was created.
916  */
917 GstPad *
918 gst_element_add_ghost_pad (GstElement *element, GstPad *pad, const gchar *name)
919 {
920   GstPad *ghostpad;
921
922   g_return_val_if_fail (element != NULL, NULL);
923   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
924   g_return_val_if_fail (pad != NULL, NULL);
925   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
926
927   /* then check to see if there's already a pad by that name here */
928   g_return_val_if_fail (gst_object_check_uniqueness (element->pads, name) == TRUE, NULL);
929
930   GST_DEBUG (GST_CAT_ELEMENT_PADS, 
931              "creating new ghost pad called %s, from pad %s:%s",
932              name, GST_DEBUG_PAD_NAME(pad));
933   ghostpad = gst_ghost_pad_new (name, pad);
934
935   /* add it to the list */
936   GST_DEBUG(GST_CAT_ELEMENT_PADS,"adding ghost pad %s to element %s",
937             name, GST_ELEMENT_NAME (element));
938   element->pads = g_list_append (element->pads, ghostpad);
939   element->numpads++;
940   /* set the parent of the ghostpad */
941   gst_object_set_parent (GST_OBJECT (ghostpad), GST_OBJECT (element));
942
943   GST_DEBUG(GST_CAT_ELEMENT_PADS,"added ghostpad %s:%s",GST_DEBUG_PAD_NAME(ghostpad));
944
945   /* emit the NEW_GHOST_PAD signal */
946   g_signal_emit (G_OBJECT (element), gst_element_signals[NEW_PAD], 0, ghostpad);
947         
948   return ghostpad;
949 }
950
951 /**
952  * gst_element_remove_ghost_pad:
953  * @element: a #GstElement to remove the ghost pad from.
954  * @pad: ghost #GstPad to remove.
955  *
956  * Removes a ghost pad from an element.
957  */
958 void
959 gst_element_remove_ghost_pad (GstElement *element, GstPad *pad)
960 {
961   g_return_if_fail (element != NULL);
962   g_return_if_fail (GST_IS_ELEMENT (element));
963   g_return_if_fail (pad != NULL);
964   g_return_if_fail (GST_IS_GHOST_PAD (pad));
965
966   /* FIXME this is redundant?
967    * wingo 10-july-2001: I don't think so, you have to actually remove the pad
968    * from the element. gst_pad_remove_ghost_pad just removes the ghostpad from
969    * the real pad's ghost pad list
970    */
971   gst_pad_remove_ghost_pad (GST_PAD (GST_PAD_REALIZE (pad)), pad);
972   gst_element_remove_pad (element, pad);
973 }
974
975
976 /**
977  * gst_element_get_pad:
978  * @element: a #GstElement to find pad of.
979  * @name: the name of the pad to retrieve.
980  *
981  * Retrieves a pad from the element by name.
982  *
983  * Returns: requested #GstPad if found, otherwise NULL.
984  */
985 GstPad*
986 gst_element_get_pad (GstElement *element, const gchar *name)
987 {
988   GstPad *pad;
989
990   g_return_val_if_fail (element != NULL, NULL);
991   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
992   g_return_val_if_fail (name != NULL, NULL);
993
994   pad = gst_element_get_static_pad (element, name);
995   if (!pad) 
996     pad = gst_element_get_request_pad (element, name);
997
998   return pad;
999 }
1000
1001 /**
1002  * gst_element_get_static_pad:
1003  * @element: a #GstElement to find a static pad of.
1004  * @name: the name of the static #GstPad to retrieve.
1005  *
1006  * Retrieves a pad from the element by name. This version only retrieves
1007  * already-existing (i.e. 'static') pads.
1008  *
1009  * Returns: the requested #GstPad if found, otherwise NULL.
1010  */
1011 GstPad *
1012 gst_element_get_static_pad (GstElement *element, const gchar *name)
1013 {
1014   GList *walk;
1015   
1016   g_return_val_if_fail (element != NULL, NULL);
1017   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1018   g_return_val_if_fail (name != NULL, NULL);
1019
1020   walk = element->pads;
1021   while (walk) {
1022     GstPad *pad;
1023     
1024     pad = GST_PAD(walk->data);
1025     if (strcmp (GST_PAD_NAME(pad), name) == 0) {
1026       GST_INFO (GST_CAT_ELEMENT_PADS, "found pad %s:%s", GST_DEBUG_PAD_NAME (pad));
1027       return pad;
1028     }
1029     walk = g_list_next (walk);
1030   }
1031
1032   GST_INFO (GST_CAT_ELEMENT_PADS, "no such pad '%s' in element \"%s\"", name, GST_OBJECT_NAME (element));
1033   return NULL;
1034 }
1035
1036 /**
1037  * gst_element_get_request_pad:
1038  * @element: a #GstElement to find a request pad of.
1039  * @name: the name of the request #GstPad to retrieve.
1040  *
1041  * Retrieves a pad from the element by name. This version only retrieves
1042  * request pads.
1043  *
1044  * Returns: requested #GstPad if found, otherwise NULL.
1045  */
1046 GstPad*
1047 gst_element_get_request_pad (GstElement *element, const gchar *name)
1048 {
1049   GstPadTemplate *templ = NULL;
1050   GstPad *pad;
1051   const gchar *req_name = NULL;
1052   gboolean templ_found = FALSE;
1053   GList *list;
1054   gint n;
1055   const gchar *data;
1056   gchar *str, *endptr = NULL;
1057
1058   g_return_val_if_fail (element != NULL, NULL);
1059   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1060   g_return_val_if_fail (name != NULL, NULL);
1061
1062   if (strstr (name, "%")) {
1063     templ = gst_element_get_pad_template (element, name);
1064     req_name = NULL;
1065     if (templ)
1066       templ_found = TRUE;
1067   } else {
1068     list = gst_element_get_pad_template_list(element);
1069     while (!templ_found && list) {
1070       templ = (GstPadTemplate*) list->data;
1071       if (templ->presence == GST_PAD_REQUEST) {
1072         /* we know that %s and %d are the only possibilities because of sanity
1073            checks in gst_pad_template_new */
1074         GST_DEBUG (GST_CAT_PADS, "comparing %s to %s", name, templ->name_template);
1075         if ((str = strchr (templ->name_template, '%')) &&
1076             strncmp (templ->name_template, name, str - templ->name_template) == 0 &&
1077             strlen (name) > str - templ->name_template) {
1078           data = name + (str - templ->name_template);
1079           if (*(str+1) == 'd') {
1080             /* it's an int */
1081             n = (gint) strtol (data, &endptr, 10);
1082             if (endptr && *endptr == '\0') {
1083               templ_found = TRUE;
1084               req_name = name;
1085               break;
1086             }
1087           } else {
1088             /* it's a string */
1089             templ_found = TRUE;
1090             req_name = name;
1091             break;
1092           }
1093         }
1094       }
1095       list = list->next;
1096     }
1097   }
1098   
1099   if (!templ_found)
1100       return NULL;
1101   
1102   pad = gst_element_request_pad (element, templ, req_name);
1103   
1104   return pad;
1105 }
1106
1107 /**
1108  * gst_element_get_pad_list:
1109  * @element: a #GstElement to get pads of.
1110  *
1111  * Retrieves a list of the pads associated with the element.
1112  *
1113  * Returns: the #GList of pads.
1114  */
1115 const GList*
1116 gst_element_get_pad_list (GstElement *element)
1117 {
1118   g_return_val_if_fail (element != NULL, NULL);
1119   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1120
1121   /* return the list of pads */
1122   return element->pads;
1123 }
1124
1125 /**
1126  * gst_element_class_add_pad_template:
1127  * @klass: the #GstElementClass to add the pad template to.
1128  * @templ: a #GstPadTemplate to add to the element class.
1129  *
1130  * Adds a padtemplate to an element class. 
1131  * This is useful if you have derived a custom bin and wish to provide 
1132  * an on-request pad at runtime. Plug-in writers should use
1133  * gst_element_factory_add_pad_template instead.
1134  */
1135 void
1136 gst_element_class_add_pad_template (GstElementClass *klass, 
1137                                     GstPadTemplate *templ)
1138 {
1139   g_return_if_fail (klass != NULL);
1140   g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
1141   g_return_if_fail (templ != NULL);
1142   g_return_if_fail (GST_IS_PAD_TEMPLATE (templ));
1143   
1144   klass->padtemplates = g_list_append (klass->padtemplates, templ);
1145   klass->numpadtemplates++;
1146 }
1147
1148 /**
1149  * gst_element_get_pad_template_list:
1150  * @element: a #GstElement to get pad templates of.
1151  *
1152  * Retrieves a list of the pad templates associated with the element.
1153  *
1154  * Returns: the #GList of padtemplates.
1155  */
1156 GList*
1157 gst_element_get_pad_template_list (GstElement *element)
1158 {
1159   g_return_val_if_fail (element != NULL, NULL);
1160   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1161
1162   return CLASS (element)->padtemplates;
1163 }
1164
1165 /**
1166  * gst_element_get_pad_template:
1167  * @element: a #GstElement to get the pad template of.
1168  * @name: the name of the #GstPadTemplate to get.
1169  *
1170  * Retrieves a padtemplate from this element with the
1171  * given name.
1172  *
1173  * Returns: the #GstPadTemplate with the given name, or NULL if none was found. 
1174  * No unreferencing is necessary.
1175  */
1176 GstPadTemplate*
1177 gst_element_get_pad_template (GstElement *element, const gchar *name)
1178 {
1179   GList *padlist;
1180
1181   g_return_val_if_fail (element != NULL, NULL);
1182   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1183   g_return_val_if_fail (name != NULL, NULL);
1184
1185   padlist = gst_element_get_pad_template_list (element);
1186
1187   while (padlist) {
1188     GstPadTemplate *padtempl = (GstPadTemplate*) padlist->data;
1189
1190     if (!strcmp (padtempl->name_template, name))
1191       return padtempl;
1192
1193     padlist = g_list_next (padlist);
1194   }
1195
1196   return NULL;
1197 }
1198
1199 /**
1200  * gst_element_get_compatible_pad_template:
1201  * @element: a #GstElement to get a compatible pad template for.
1202  * @compattempl: the #GstPadTemplate to find a compatible template for.
1203  *
1204  * Generates a pad template for this element compatible with the given
1205  * template (meaning it is able to connect with it).
1206  *
1207  * Returns: the #GstPadTemplate of the element that is compatible with
1208  * the given GstPadTemplate, or NULL if none was found. No unreferencing 
1209  * is necessary.
1210  */
1211 GstPadTemplate*
1212 gst_element_get_compatible_pad_template (GstElement *element, 
1213                                          GstPadTemplate *compattempl)
1214 {
1215   GstPadTemplate *newtempl = NULL;
1216   GList *padlist;
1217
1218   GST_DEBUG (GST_CAT_ELEMENT_PADS, "gst_element_get_compatible_pad_template()");
1219
1220   g_return_val_if_fail (element != NULL, NULL);
1221   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1222   g_return_val_if_fail (compattempl != NULL, NULL);
1223
1224   padlist = gst_element_get_pad_template_list (element);
1225
1226   while (padlist) {
1227     GstPadTemplate *padtempl = (GstPadTemplate*) padlist->data;
1228     gboolean comp = FALSE;
1229
1230     /* Ignore name
1231      * Ignore presence
1232      * Check direction (must be opposite)
1233      * Check caps
1234      */
1235     GST_DEBUG (GST_CAT_CAPS, "checking direction and caps");
1236     if (padtempl->direction == GST_PAD_SRC &&
1237       compattempl->direction == GST_PAD_SINK) {
1238       GST_DEBUG (GST_CAT_CAPS, "compatible direction: found src pad template");
1239       comp = gst_caps_is_always_compatible (GST_PAD_TEMPLATE_CAPS (padtempl),
1240                                            GST_PAD_TEMPLATE_CAPS (compattempl));
1241       GST_DEBUG(GST_CAT_CAPS, "caps are %scompatible", (comp ? "" : "not "));
1242     } else if (padtempl->direction == GST_PAD_SINK &&
1243                compattempl->direction == GST_PAD_SRC) {
1244       GST_DEBUG (GST_CAT_CAPS, "compatible direction: found sink pad template");
1245       comp = gst_caps_is_always_compatible (GST_PAD_TEMPLATE_CAPS (compattempl),
1246                                            GST_PAD_TEMPLATE_CAPS (padtempl));
1247       GST_DEBUG (GST_CAT_CAPS, "caps are %scompatible", (comp ? "" : "not "));
1248     }
1249
1250     if (comp) {
1251       newtempl = padtempl;
1252       break;
1253     }
1254
1255     padlist = g_list_next (padlist);
1256   }
1257
1258   return newtempl;
1259 }
1260
1261 /**
1262  * gst_element_request_compatible_pad:
1263  * @element: a #GstElement to request a new pad from.
1264  * @templ: the #GstPadTemplate to which the new pad should be able to connect.
1265  *
1266  * Requests a new pad from the element. The template will
1267  * be used to decide what type of pad to create. This function
1268  * is typically used for elements with a padtemplate with presence
1269  * GST_PAD_REQUEST.
1270  *
1271  * Returns: the new #GstPad that was created, or NULL if none could be created.
1272  */
1273 GstPad*
1274 gst_element_request_compatible_pad (GstElement *element, GstPadTemplate *templ)
1275 {
1276   GstPadTemplate *templ_new;
1277   GstPad *pad = NULL;
1278
1279   g_return_val_if_fail (element != NULL, NULL);
1280   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1281   g_return_val_if_fail (templ != NULL, NULL);
1282
1283   templ_new = gst_element_get_compatible_pad_template (element, templ);
1284   if (templ_new != NULL)
1285       pad = gst_element_request_pad (element, templ_new, NULL);
1286
1287   return pad;
1288 }
1289
1290
1291 /**
1292  * gst_element_get_compatible_pad_filtered:
1293  * @element: a #GstElement in which the pad should be found.
1294  * @pad: the #GstPad to find a compatible one for.
1295  * @filtercaps: the #GstCaps to use as a filter.
1296  *
1297  * Looks for an unconnected pad to which the given pad can connect to.
1298  * It is not guaranteed that connecting the pads will work, though
1299  * it should work in most cases.
1300  *
1301  * Returns: the #GstPad to which a connection can be made.
1302  */
1303 GstPad*                 
1304 gst_element_get_compatible_pad_filtered (GstElement *element, GstPad *pad, 
1305                                          GstCaps *filtercaps)
1306 {
1307   const GList *pads;
1308   GstPadTemplate *templ;
1309   GstCaps *templcaps;
1310   GstPad *foundpad = NULL;
1311   
1312   /* checks */
1313   g_return_val_if_fail (element != NULL, NULL);
1314   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1315   g_return_val_if_fail (pad != NULL, NULL);
1316   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
1317   
1318   /* let's use the real pad */
1319   pad = (GstPad *) GST_PAD_REALIZE (pad);
1320   g_return_val_if_fail (pad != NULL, NULL);
1321   g_return_val_if_fail (GST_RPAD_PEER (pad) == NULL, NULL);
1322   
1323   /* try to get an existing unconnected pad */
1324   pads = gst_element_get_pad_list (element);
1325   while (pads) {
1326     GstPad *current = GST_PAD (pads->data);
1327     if ((GST_PAD_PEER (GST_PAD_REALIZE (current)) == NULL) &&
1328         gst_pad_can_connect_filtered (pad, current, filtercaps)) {
1329       return current;
1330     }
1331     pads = g_list_next (pads);
1332   }
1333   
1334   /* try to create a new one */
1335   /* requesting is a little crazy, we need a template. Let's create one */
1336   if (filtercaps != NULL) {
1337     templcaps = gst_caps_intersect (filtercaps, (GstCaps *) GST_RPAD_CAPS (pad));
1338     if (templcaps == NULL)
1339       return NULL;
1340   } else {
1341     templcaps = gst_caps_copy (gst_pad_get_caps (pad));
1342   }
1343   
1344   templ = gst_pad_template_new ((gchar *) GST_PAD_NAME (pad), GST_RPAD_DIRECTION (pad),
1345                                GST_PAD_ALWAYS, templcaps, NULL);
1346   foundpad = gst_element_request_compatible_pad (element, templ);
1347   gst_object_unref (GST_OBJECT (templ)); /* this will take care of the caps too */
1348   
1349   /* FIXME: this is broken, but it's in here so autoplugging elements that don't
1350      have caps on their source padtemplates (spider) can connect... */
1351   if (!foundpad && !filtercaps) {
1352     templ = gst_pad_template_new ((gchar *) GST_PAD_NAME (pad), GST_RPAD_DIRECTION (pad),
1353                                  GST_PAD_ALWAYS, NULL, NULL);
1354     foundpad = gst_element_request_compatible_pad (element, templ);
1355     gst_object_unref (GST_OBJECT (templ));
1356   }
1357   
1358   return foundpad;
1359 }
1360
1361 /**
1362  * gst_element_get_compatible_pad:
1363  * @element: a #GstElement in which the pad should be found.
1364  * @pad: the #GstPad to find a compatible one for.
1365  *
1366  * Looks for an unconnected pad to which the given pad can connect to.
1367  * It is not guaranteed that connecting the pads will work, though
1368  * it should work in most cases.
1369  *
1370  * Returns: the #GstPad to which a connection can be made, or NULL if none
1371  * could be found.
1372  */
1373 GstPad*                 
1374 gst_element_get_compatible_pad (GstElement *element, GstPad *pad)
1375 {
1376   return gst_element_get_compatible_pad_filtered (element, pad, NULL);
1377 }
1378
1379 /**
1380  * gst_element_connect_filtered:
1381  * @src: a #GstElement containing the source pad.
1382  * @dest: the #GstElement containing the destination pad.
1383  * @filtercaps: the #GstCaps to use as a filter.
1384  *
1385  * Connects the source to the destination element using the filtercaps.
1386  * The connection must be from source to destination, the other
1387  * direction will not be tried.
1388  * The functions looks for existing pads that aren't connected yet. 
1389  * It will use request pads if possible. But both pads will not be requested.
1390  * If multiple connections are possible, only one is established.
1391  *
1392  * Returns: TRUE if the elements could be connected.
1393  */
1394 gboolean
1395 gst_element_connect_filtered (GstElement *src, GstElement *dest, 
1396                               GstCaps *filtercaps)
1397 {
1398   const GList *srcpads, *destpads, *srctempls, *desttempls, *l;
1399   GstPad *srcpad, *destpad;
1400   GstPadTemplate *srctempl, *desttempl;
1401
1402   /* checks */
1403   g_return_val_if_fail (src != NULL, FALSE);
1404   g_return_val_if_fail (GST_IS_ELEMENT (src), FALSE);
1405   g_return_val_if_fail (dest != NULL, FALSE);
1406   g_return_val_if_fail (GST_IS_ELEMENT (dest), FALSE);
1407
1408   GST_DEBUG (GST_CAT_ELEMENT_PADS, "trying to connect element %s to element %s",
1409              GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (dest));
1410    
1411   srcpads = gst_element_get_pad_list (src);
1412   destpads = gst_element_get_pad_list (dest);
1413
1414   if (srcpads || destpads) {
1415     GST_DEBUG (GST_CAT_ELEMENT_PADS, "looping through src and dest pads");
1416     /* loop through the existing pads in the source, trying to find a
1417      * compatible destination pad */
1418     while (srcpads) {
1419       srcpad = (GstPad *) GST_PAD_REALIZE (srcpads->data);
1420       GST_DEBUG (GST_CAT_ELEMENT_PADS, "trying src pad %s:%s", 
1421                  GST_DEBUG_PAD_NAME (srcpad));
1422       if ((GST_RPAD_DIRECTION (srcpad) == GST_PAD_SRC) &&
1423           (GST_PAD_PEER (srcpad) == NULL)) {
1424         destpad = gst_element_get_compatible_pad_filtered (dest, srcpad, 
1425                                                            filtercaps);
1426         if (destpad && gst_pad_connect_filtered (srcpad, destpad, filtercaps)) {
1427           GST_DEBUG (GST_CAT_ELEMENT_PADS, "connected pad %s:%s to pad %s:%s", 
1428                      GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad));
1429           return TRUE;
1430         }
1431       }
1432       srcpads = g_list_next (srcpads);
1433     }
1434     
1435     /* loop through the existing pads in the destination */
1436     while (destpads) {
1437       destpad = (GstPad *) GST_PAD_REALIZE (destpads->data);
1438       GST_DEBUG (GST_CAT_ELEMENT_PADS, "trying dest pad %s:%s", 
1439                  GST_DEBUG_PAD_NAME (destpad));
1440       if ((GST_RPAD_DIRECTION (destpad) == GST_PAD_SINK) &&
1441           (GST_PAD_PEER (destpad) == NULL)) {
1442         srcpad = gst_element_get_compatible_pad_filtered (src, destpad, 
1443                                                           filtercaps);
1444         if (srcpad && gst_pad_connect_filtered (srcpad, destpad, filtercaps)) {
1445           GST_DEBUG (GST_CAT_ELEMENT_PADS, "connected pad %s:%s to pad %s:%s", 
1446                      GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad));
1447           return TRUE;
1448         }
1449       }
1450       destpads = g_list_next (destpads);
1451     }
1452   }
1453
1454   GST_DEBUG (GST_CAT_ELEMENT_PADS, 
1455              "we might have request pads on both sides, checking...");
1456   srctempls = gst_element_get_pad_template_list (src);
1457   desttempls = gst_element_get_pad_template_list (dest);
1458   
1459   if (srctempls && desttempls) {
1460     while (srctempls) {
1461       srctempl = (GstPadTemplate*) srctempls->data;
1462       if (srctempl->presence == GST_PAD_REQUEST) {
1463         for (l=desttempls; l; l=l->next) {
1464           desttempl = (GstPadTemplate*) desttempls->data;
1465           if (desttempl->presence == GST_PAD_REQUEST && 
1466               desttempl->direction != srctempl->direction) {
1467             if (gst_caps_is_always_compatible (gst_pad_template_get_caps (srctempl),
1468                                               gst_pad_template_get_caps (desttempl))) {
1469               srcpad = gst_element_get_request_pad (src, 
1470                                                     srctempl->name_template);
1471               destpad = gst_element_get_request_pad (dest, 
1472                                                      desttempl->name_template);
1473               if (gst_pad_connect_filtered (srcpad, destpad, filtercaps)) {
1474                 GST_DEBUG (GST_CAT_ELEMENT_PADS, 
1475                            "connected pad %s:%s to pad %s:%s",
1476                            GST_DEBUG_PAD_NAME (srcpad), 
1477                            GST_DEBUG_PAD_NAME (destpad));
1478                 return TRUE;
1479               }
1480               /* FIXME: we have extraneous request pads lying around */
1481             }
1482           }
1483         }
1484       }
1485       srctempls = srctempls->next;
1486     }
1487   }
1488   
1489   GST_DEBUG (GST_CAT_ELEMENT_PADS, "no connection possible from %s to %s", 
1490              GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (dest));
1491   return FALSE;  
1492 }
1493
1494 /**
1495  * gst_element_connect_many:
1496  * @element_1: the first #GstElement in the connection chain.
1497  * @element_2: the second #GstElement in the connection chain.
1498  * @...: the NULL-terminated list of elements to connect in order.
1499  * 
1500  * Chain together a series of elements. Uses #gst_element_connect.
1501  *
1502  * Returns: TRUE on success, FALSE otherwise.
1503  */
1504 gboolean
1505 gst_element_connect_many (GstElement *element_1, GstElement *element_2, ...)
1506 {
1507   va_list args;
1508
1509   g_return_val_if_fail (element_1 != NULL && element_2 != NULL, FALSE);
1510   g_return_val_if_fail (GST_IS_ELEMENT (element_1) && 
1511                         GST_IS_ELEMENT (element_2), FALSE);
1512
1513   va_start (args, element_2);
1514
1515   while (element_2) {
1516     if (!gst_element_connect (element_1, element_2))
1517       return FALSE;
1518     
1519     element_1 = element_2;
1520     element_2 = va_arg (args, GstElement*);
1521   }
1522
1523   va_end (args);
1524   
1525   return TRUE;
1526 }
1527
1528 /**
1529  * gst_element_connect:
1530  * @src: a #GstElement containing the source pad.
1531  * @dest: the #GstElement containing the destination pad.
1532  *
1533  * Connects the source to the destination element.
1534  * The connection must be from source to destination, the other
1535  * direction will not be tried.
1536  * The functions looks for existing pads and request pads that aren't
1537  * connected yet. If multiple connections are possible, only one is
1538  * established.
1539  *
1540  * Returns: TRUE if the elements could be connected.
1541  */
1542 gboolean
1543 gst_element_connect (GstElement *src, GstElement *dest)
1544 {
1545   return gst_element_connect_filtered (src, dest, NULL);
1546 }
1547
1548 /**
1549  * gst_element_connect_pads_filtered:
1550  * @src: a #GstElement containing the source pad.
1551  * @srcpadname: the name of the #GstPad in source element.
1552  * @dest: the #GstElement containing the destination pad.
1553  * @destpadname: the name of the #GstPad in destination element.
1554  * @filtercaps: the #GstCaps to use as a filter.
1555  *
1556  * Connects the two named pads of the source and destination elements.
1557  * Side effect is that if one of the pads has no parent, it becomes a
1558  * child of the parent of the other element.  If they have different
1559  * parents, the connection fails.
1560  *
1561  * Returns: TRUE if the pads could be connected.
1562  */
1563 gboolean
1564 gst_element_connect_pads_filtered (GstElement *src, const gchar *srcpadname,
1565                                    GstElement *dest, const gchar *destpadname, 
1566                                    GstCaps *filtercaps)
1567 {
1568   GstPad *srcpad,*destpad;
1569
1570   g_return_val_if_fail (src != NULL, FALSE);
1571   g_return_val_if_fail (GST_IS_ELEMENT (src), FALSE);
1572   g_return_val_if_fail (srcpadname != NULL, FALSE);
1573   g_return_val_if_fail (dest != NULL, FALSE);
1574   g_return_val_if_fail (GST_IS_ELEMENT (dest), FALSE);
1575   g_return_val_if_fail (destpadname != NULL, FALSE);
1576
1577   /* obtain the pads requested */
1578   srcpad = gst_element_get_pad (src, srcpadname);
1579   if (srcpad == NULL) {
1580     GST_ERROR (src, "source element has no pad \"%s\"", srcpadname);
1581     return FALSE;
1582   }
1583   destpad = gst_element_get_pad (dest, destpadname);
1584   if (srcpad == NULL) {
1585     GST_ERROR (dest, "destination element has no pad \"%s\"", destpadname);
1586     return FALSE;
1587   }
1588
1589   /* we're satisified they can be connected, let's do it */
1590   return gst_pad_connect_filtered (srcpad, destpad, filtercaps);
1591 }
1592
1593 /**
1594  * gst_element_connect_pads:
1595  * @src: a #GstElement containing the source pad.
1596  * @srcpadname: the name of the #GstPad in the source element.
1597  * @dest: the #GstElement containing the destination pad.
1598  * @destpadname: the name of the #GstPad in destination element.
1599  *
1600  * Connects the two named pads of the source and destination elements.
1601  * Side effect is that if one of the pads has no parent, it becomes a
1602  * child of the parent of the other element.  If they have different
1603  * parents, the connection fails.
1604  *
1605  * Returns: TRUE if the pads could be connected.
1606  */
1607 gboolean
1608 gst_element_connect_pads (GstElement *src, const gchar *srcpadname,
1609                           GstElement *dest, const gchar *destpadname)
1610 {
1611   return gst_element_connect_pads_filtered (src, srcpadname, dest, destpadname, NULL);
1612 }
1613
1614 /**
1615  * gst_element_disconnect_pads:
1616  * @src: a #GstElement containing the source pad.
1617  * @srcpadname: the name of the #GstPad in source element.
1618  * @dest: a #GstElement containing the destination pad.
1619  * @destpadname: the name of the #GstPad in destination element.
1620  *
1621  * Disconnects the two named pads of the source and destination elements.
1622  */
1623 void
1624 gst_element_disconnect_pads (GstElement *src, const gchar *srcpadname,
1625                              GstElement *dest, const gchar *destpadname)
1626 {
1627   GstPad *srcpad,*destpad;
1628
1629   g_return_if_fail (src != NULL);
1630   g_return_if_fail (GST_IS_ELEMENT(src));
1631   g_return_if_fail (srcpadname != NULL);
1632   g_return_if_fail (dest != NULL);
1633   g_return_if_fail (GST_IS_ELEMENT(dest));
1634   g_return_if_fail (destpadname != NULL);
1635
1636   /* obtain the pads requested */
1637   srcpad = gst_element_get_pad (src, srcpadname);
1638   if (srcpad == NULL) {
1639     GST_ERROR(src,"source element has no pad \"%s\"",srcpadname);
1640     return;
1641   }
1642   destpad = gst_element_get_pad (dest, destpadname);
1643   if (srcpad == NULL) {
1644     GST_ERROR(dest,"destination element has no pad \"%s\"",destpadname);
1645     return;
1646   }
1647
1648   /* we're satisified they can be disconnected, let's do it */
1649   gst_pad_disconnect(srcpad,destpad);
1650 }
1651
1652 /**
1653  * gst_element_disconnect_many:
1654  * @element_1: the first #GstElement in the connection chain.
1655  * @element_2: the second #GstElement in the connection chain.
1656  * @...: the NULL-terminated list of elements to disconnect in order.
1657  * 
1658  * Disconnects a series of elements. Uses #gst_element_disconnect.
1659  */
1660 void
1661 gst_element_disconnect_many (GstElement *element_1, GstElement *element_2, ...)
1662 {
1663   va_list args;
1664
1665   g_return_if_fail (element_1 != NULL && element_2 != NULL);
1666   g_return_if_fail (GST_IS_ELEMENT (element_1) && GST_IS_ELEMENT (element_2));
1667
1668   va_start (args, element_2);
1669
1670   while (element_2) {
1671     gst_element_disconnect (element_1, element_2);
1672     
1673     element_1 = element_2;
1674     element_2 = va_arg (args, GstElement*);
1675   }
1676
1677   va_end (args);
1678 }
1679
1680 /**
1681  * gst_element_disconnect:
1682  * @src: the source #GstElement to disconnect.
1683  * @dest: the sink #GstElement to disconnect.
1684  *
1685  * Disconnects all source pads of the source element with all sink pads
1686  * of the sink element to which they are connected.
1687  */
1688 void
1689 gst_element_disconnect (GstElement *src, GstElement *dest)
1690 {
1691   const GList *srcpads;
1692   GstPad *pad;
1693
1694   g_return_if_fail (GST_IS_ELEMENT (src));
1695   g_return_if_fail (GST_IS_ELEMENT (dest));
1696
1697   GST_DEBUG (GST_CAT_ELEMENT_PADS, "disconnecting \"%s\" and \"%s\"", 
1698              GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (dest));
1699
1700   srcpads = gst_element_get_pad_list (src);
1701
1702   while (srcpads) {
1703     pad = GST_PAD_CAST (srcpads->data);
1704     
1705     if (GST_IS_REAL_PAD (pad) && GST_PAD_DIRECTION (pad) == GST_PAD_SRC) {
1706       GstPad *peerpad = GST_PAD_PEER (pad);
1707
1708       if (peerpad && 
1709           (GST_OBJECT_PARENT (GST_PAD_PEER (peerpad)) == (GstObject*) src)) {
1710         gst_pad_disconnect (pad, peerpad);
1711       }
1712     }
1713
1714     srcpads = g_list_next (srcpads);
1715   }
1716 }
1717
1718 static void
1719 gst_element_error_func (GstElement* element, GstElement *source, 
1720                         gchar *errormsg)
1721 {
1722   /* tell the parent */
1723   if (GST_OBJECT_PARENT (element)) {
1724     GST_DEBUG (GST_CAT_EVENT, "forwarding error \"%s\" from %s to %s", 
1725                errormsg, GST_ELEMENT_NAME (element), 
1726                GST_OBJECT_NAME (GST_OBJECT_PARENT (element)));
1727
1728     gst_object_ref (GST_OBJECT (element));
1729     g_signal_emit (G_OBJECT (GST_OBJECT_PARENT (element)), 
1730                    gst_element_signals[ERROR], 0, source, errormsg);
1731     gst_object_unref (GST_OBJECT (element));
1732   }
1733 }
1734
1735 static gboolean
1736 gst_element_send_event_default (GstElement *element, GstEvent *event)
1737 {
1738   GList *pads = element->pads;
1739   gboolean res = FALSE;
1740
1741   while (pads) {
1742     GstPad *pad = GST_PAD_CAST (pads->data);
1743     
1744     if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) {
1745       if (GST_PAD_IS_USABLE (pad)) {
1746         res = gst_pad_send_event (GST_PAD_PEER (pad), event);
1747         break;
1748       }
1749     }
1750     pads = g_list_next (pads);
1751   }
1752   return res;
1753 }
1754
1755 /**
1756  * gst_element_send_event:
1757  * @element: a #GstElement to send the event to.
1758  * @event: the #GstEvent to send to the element.
1759  *
1760  * Sends an event to an element. If the element doesn't 
1761  * implement an event handler, the event will be forwarded
1762  * to a random sink pad.
1763  * 
1764  * Returns: TRUE if the event was handled.
1765  */
1766 gboolean
1767 gst_element_send_event (GstElement *element, GstEvent *event)
1768 {
1769   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1770   g_return_val_if_fail (event != NULL, FALSE);
1771   
1772   if (CLASS (element)->send_event)
1773     return CLASS (element)->send_event (element, event);
1774
1775   return FALSE;
1776 }
1777
1778 static gboolean
1779 gst_element_query_default (GstElement *element, GstPadQueryType type,
1780                            GstFormat *format, gint64 *value)
1781 {
1782   GList *pads = element->pads;
1783   gboolean res = FALSE;
1784
1785   while (pads) {
1786     GstPad *pad = GST_PAD_CAST (pads->data);
1787     
1788     if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) {
1789       if (GST_PAD_IS_USABLE (pad)) {
1790         res = gst_pad_query (GST_PAD_PEER (pad), type, format, value);
1791         break;
1792       }
1793     }
1794     pads = g_list_next (pads);
1795   }
1796   return res;
1797 }
1798
1799 /**
1800  * gst_element_query:
1801  * @element: a #GstElement to perform the query on.
1802  * @type: the #GstPadQueryType.
1803  * @format: the #GstFormat pointer to hold the format of the result.
1804  * @value: the pointer to the value of the result.
1805  *
1806  * Performs a query on the given element. If the format is set
1807  * to GST_FORMAT_DEFAULT and this function returns TRUE, the 
1808  * format pointer will hold the default format.
1809  * For element that don't implement a query handler, this function
1810  * forwards the query to a random connected sinkpad of this element.
1811  * 
1812  * Returns: TRUE if the query could be performed.
1813  */
1814 gboolean
1815 gst_element_query (GstElement *element, GstPadQueryType type,
1816                    GstFormat *format, gint64 *value)
1817 {
1818   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1819   g_return_val_if_fail (format != NULL, FALSE);
1820   g_return_val_if_fail (value != NULL, FALSE);
1821   
1822   if (CLASS (element)->query)
1823     return CLASS (element)->query (element, type, format, value);
1824
1825   return FALSE;
1826 }
1827
1828 /**
1829  * gst_element_error:
1830  * @element: a #GstElement with the error.
1831  * @error: the printf-style string describing the error.
1832  * @...: the optional arguments for the string.
1833  *
1834  * signals an error condition on an element.
1835  * This function is used internally by elements.
1836  * It results in the "error" signal.
1837  */
1838 void
1839 gst_element_error (GstElement *element, const gchar *error, ...)
1840 {
1841   va_list var_args;
1842   gchar *string;
1843   
1844   /* checks */
1845   g_return_if_fail (GST_IS_ELEMENT (element));
1846   g_return_if_fail (error != NULL);
1847
1848   /* create error message */
1849   va_start (var_args, error);
1850   string = g_strdup_vprintf (error, var_args);
1851   va_end (var_args);
1852   GST_INFO (GST_CAT_EVENT, "ERROR in %s: %s", GST_ELEMENT_NAME (element), string);
1853
1854   /* emit the signal, make sure the element stays available */
1855   gst_object_ref (GST_OBJECT (element));
1856   g_signal_emit (G_OBJECT (element), gst_element_signals[ERROR], 0, element, string);
1857   
1858  /* tell the scheduler */
1859   if (element->sched) {
1860     gst_scheduler_error (element->sched, element); 
1861   } 
1862
1863   /* cleanup */
1864   gst_object_unref (GST_OBJECT (element));
1865   g_free (string);
1866 }
1867
1868 /**
1869  * gst_element_get_state:
1870  * @element: a #GstElement to get the state of.
1871  *
1872  * Gets the state of the element. 
1873  *
1874  * Returns: the #GstElementState of the element.
1875  */
1876 GstElementState
1877 gst_element_get_state (GstElement *element)
1878 {
1879   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_VOID_PENDING);
1880
1881   return GST_STATE (element);
1882 }
1883
1884 /**
1885  * gst_element_wait_state_change:
1886  * @element: a #GstElement to wait for a state change on.
1887  *
1888  * Waits and blocks until the element changed its state.
1889  */
1890 void
1891 gst_element_wait_state_change (GstElement *element)
1892 {
1893   g_mutex_lock (element->state_mutex);
1894   g_cond_wait (element->state_cond, element->state_mutex);
1895   g_mutex_unlock (element->state_mutex);
1896 }
1897
1898 /**
1899  * gst_element_set_state:
1900  * @element: a #GstElement to change state of.
1901  * @state: the element's new #GstElementState.
1902  *
1903  * Sets the state of the element. This function will try to set the
1904  * requested state by going through all the intermediary states and calling
1905  * the class's state change function for each.
1906  *
1907  * Returns: TRUE if the state was successfully set.
1908  * (using #GstElementStateReturn).
1909  */
1910 GstElementStateReturn
1911 gst_element_set_state (GstElement *element, GstElementState state)
1912 {
1913   GstElementClass *oclass;
1914   GstElementState curpending;
1915   GstElementStateReturn return_val = GST_STATE_SUCCESS;
1916
1917   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
1918
1919   /* start with the current state */
1920   curpending = GST_STATE(element);
1921
1922   GST_DEBUG_ELEMENT (GST_CAT_STATES, element, "setting state from %s to %s",
1923                      gst_element_state_get_name (curpending),
1924                      gst_element_state_get_name (state));
1925
1926   /* loop until the final requested state is set */
1927   while (GST_STATE (element) != state 
1928       && GST_STATE (element) != GST_STATE_VOID_PENDING) {
1929     /* move the curpending state in the correct direction */
1930     if (curpending < state) 
1931       curpending <<= 1;
1932     else 
1933       curpending >>= 1;
1934
1935     /* set the pending state variable */
1936     /* FIXME: should probably check to see that we don't already have one */
1937     GST_STATE_PENDING (element) = curpending;
1938
1939     if (curpending != state) {
1940       GST_DEBUG_ELEMENT (GST_CAT_STATES, element, 
1941                          "intermediate: setting state from %s to %s",
1942                          gst_element_state_get_name (GST_STATE (element)),
1943                          gst_element_state_get_name (curpending));
1944     }
1945
1946     /* call the state change function so it can set the state */
1947     oclass = CLASS (element);
1948     if (oclass->change_state)
1949       return_val = (oclass->change_state) (element);
1950
1951     switch (return_val) {
1952       case GST_STATE_FAILURE:
1953         GST_DEBUG_ELEMENT (GST_CAT_STATES, element, 
1954                            "have failed change_state return");
1955         goto exit;
1956       case GST_STATE_ASYNC:
1957         GST_DEBUG_ELEMENT (GST_CAT_STATES, element, 
1958                            "element will change state async");
1959         goto exit;
1960       case GST_STATE_SUCCESS:
1961         /* Last thing we do is verify that a successful state change really
1962          * did change the state... */
1963         if (GST_STATE (element) != curpending) {
1964           GST_DEBUG_ELEMENT (GST_CAT_STATES, element, 
1965                              "element claimed state-change success,"
1966                              "but state didn't change %s, %s <-> %s",
1967                              gst_element_state_get_name (GST_STATE (element)),
1968                              gst_element_state_get_name (GST_STATE_PENDING (element)),
1969                              gst_element_state_get_name (curpending));
1970           return GST_STATE_FAILURE;
1971         }
1972         break;
1973       default:
1974         /* somebody added a GST_STATE_ and forgot to do stuff here ! */
1975         g_assert_not_reached ();
1976     }
1977   }
1978 exit:
1979
1980   return return_val;
1981 }
1982
1983 static gboolean
1984 gst_element_negotiate_pads (GstElement *element)
1985 {
1986   GList *pads = GST_ELEMENT_PADS (element);
1987
1988   GST_DEBUG_ELEMENT (GST_CAT_CAPS, element, "negotiating pads");
1989
1990   while (pads) {
1991     GstPad *pad = GST_PAD (pads->data);
1992     GstRealPad *srcpad;
1993
1994     pads = g_list_next (pads);
1995     
1996     if (!GST_IS_REAL_PAD (pad))
1997       continue;
1998
1999     srcpad = GST_PAD_REALIZE (pad);
2000
2001     /* if we have a connection on this pad and it doesn't have caps
2002      * allready, try to negotiate */
2003     if (GST_PAD_IS_USABLE (srcpad) && !GST_PAD_CAPS (srcpad)) {
2004       GstRealPad *sinkpad;
2005       GstElementState otherstate;
2006       GstElement *parent;
2007       
2008       sinkpad = GST_RPAD_PEER (GST_PAD_REALIZE (srcpad));
2009
2010       /* check the parent of the peer pad, if there is no parent do nothing */
2011       parent = GST_PAD_PARENT (sinkpad);
2012       if (!parent) 
2013         continue;
2014
2015       otherstate = GST_STATE (parent);
2016
2017       /* swap pads if needed */
2018       if (!GST_PAD_IS_SRC (srcpad)) {
2019         GstRealPad *temp;
2020
2021         temp = srcpad;
2022         srcpad = sinkpad;
2023         sinkpad = temp;
2024       }
2025
2026       /* only try to negotiate if the peer element is in PAUSED or higher too */
2027       if (otherstate >= GST_STATE_READY) {
2028         GST_DEBUG_ELEMENT (GST_CAT_CAPS, element, 
2029                            "perform negotiate for %s:%s and %s:%s",
2030                            GST_DEBUG_PAD_NAME (srcpad), 
2031                            GST_DEBUG_PAD_NAME (sinkpad));
2032         if (!gst_pad_perform_negotiate (GST_PAD (srcpad), GST_PAD (sinkpad)))
2033           return FALSE;
2034       }
2035       else {
2036         GST_DEBUG_ELEMENT (GST_CAT_CAPS, element, 
2037                            "not negotiating %s:%s and %s:%s, not in READY yet",
2038                            GST_DEBUG_PAD_NAME (srcpad), 
2039                            GST_DEBUG_PAD_NAME (sinkpad));
2040       }
2041     }
2042   }
2043
2044   return TRUE;
2045 }
2046
2047 static void
2048 gst_element_clear_pad_caps (GstElement *element)
2049 {
2050   GList *pads = GST_ELEMENT_PADS (element);
2051
2052   GST_DEBUG_ELEMENT (GST_CAT_CAPS, element, "clearing pad caps");
2053
2054   while (pads) {
2055     GstRealPad *pad = GST_PAD_REALIZE (pads->data);
2056
2057     if (GST_PAD_CAPS (pad)) {
2058       GST_PAD_CAPS (pad) = NULL;
2059     }
2060     pads = g_list_next (pads);
2061   }
2062 }
2063
2064 static GstElementStateReturn
2065 gst_element_change_state (GstElement *element)
2066 {
2067   GstElementState old_state;
2068   GstObject *parent;
2069   gint old_pending, old_transition;
2070
2071   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
2072
2073   old_state = GST_STATE (element);
2074   old_pending = GST_STATE_PENDING (element);
2075   old_transition = GST_STATE_TRANSITION (element);
2076
2077   if (old_pending == GST_STATE_VOID_PENDING || 
2078       old_state == GST_STATE_PENDING (element)) {
2079     GST_INFO (GST_CAT_STATES, 
2080               "no state change needed for element %s (VOID_PENDING)", 
2081               GST_ELEMENT_NAME (element));
2082     return GST_STATE_SUCCESS;
2083   }
2084   
2085   GST_INFO (GST_CAT_STATES, "%s default handler sets state from %s to %s %d", 
2086             GST_ELEMENT_NAME (element),
2087             gst_element_state_get_name (old_state),
2088             gst_element_state_get_name (old_pending),
2089             GST_STATE_TRANSITION (element));
2090
2091   /* we set the state change early for the negotiation functions */
2092   GST_STATE (element) = old_pending;
2093   GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING;
2094
2095   switch (old_transition) {
2096     /* if we are going to paused, we try to negotiate the pads */
2097     case GST_STATE_READY_TO_PAUSED:
2098       if (!gst_element_negotiate_pads (element)) 
2099         goto failure;
2100       break;
2101     /* going to the READY state clears all pad caps */
2102     case GST_STATE_PAUSED_TO_READY:
2103       gst_element_clear_pad_caps (element);
2104       break;
2105     default:
2106       break;
2107   }
2108
2109   parent = GST_ELEMENT_PARENT (element);
2110
2111   GST_DEBUG_ELEMENT (GST_CAT_STATES, element,
2112                      "signaling state change from %s to %s",
2113                      gst_element_state_get_name (old_state),
2114                      gst_element_state_get_name (GST_STATE (element)));
2115
2116   /* tell the scheduler if we have one */
2117   if (element->sched) {
2118     if (gst_scheduler_state_transition (element->sched, element, 
2119                                         old_transition) != GST_STATE_SUCCESS) {
2120       goto failure;
2121     }
2122   }
2123
2124   g_signal_emit (G_OBJECT (element), gst_element_signals[STATE_CHANGE],
2125                  0, old_state, GST_STATE (element));
2126
2127   /* tell our parent about the state change */
2128   if (parent && GST_IS_BIN (parent)) {
2129     gst_bin_child_state_change (GST_BIN (parent), old_state, 
2130                                 GST_STATE (element), element);
2131   }
2132
2133   /* signal the state change in case somebody is waiting for us */
2134   g_mutex_lock (element->state_mutex);
2135   g_cond_signal (element->state_cond);
2136   g_mutex_unlock (element->state_mutex);
2137
2138   return GST_STATE_SUCCESS;
2139
2140 failure:
2141   /* undo the state change */
2142   GST_STATE (element) = old_state;
2143   GST_STATE_PENDING (element) = old_pending;
2144
2145   return GST_STATE_FAILURE;
2146 }
2147
2148 /**
2149  * gst_element_get_factory:
2150  * @element: a #GstElement to request the element factory of.
2151  *
2152  * Retrieves the factory that was used to create this element.
2153  *
2154  * Returns: the #GstElementFactory used for creating this element.
2155  */
2156 GstElementFactory*
2157 gst_element_get_factory (GstElement *element)
2158 {
2159   GstElementClass *oclass;
2160
2161   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
2162
2163   oclass = CLASS (element);
2164
2165   return oclass->elementfactory;
2166 }
2167
2168 static void
2169 gst_element_dispose (GObject *object)
2170 {
2171   GstElement *element = GST_ELEMENT (object);
2172   GList *pads;
2173   GstPad *pad;
2174   
2175   GST_DEBUG_ELEMENT (GST_CAT_REFCOUNTING, element, "dispose");
2176
2177   gst_element_set_state (element, GST_STATE_NULL);
2178
2179   /* first we break all our connections with the ouside */
2180   if (element->pads) {
2181     GList *orig;
2182     orig = pads = g_list_copy (element->pads);
2183     while (pads) {
2184       pad = GST_PAD (pads->data);
2185
2186       if (GST_PAD_PEER (pad)) {
2187         GST_DEBUG (GST_CAT_REFCOUNTING, "disconnecting pad '%s'",
2188                    GST_OBJECT_NAME (GST_OBJECT (GST_PAD (GST_PAD_PEER (pad)))));
2189         gst_pad_disconnect (pad, GST_PAD (GST_PAD_PEER (pad)));
2190       }
2191       gst_element_remove_pad (element, pad);
2192
2193       pads = g_list_next (pads);
2194     }
2195     g_list_free (orig);
2196     g_list_free (element->pads);
2197     element->pads = NULL;
2198   }
2199
2200   element->numsrcpads = 0;
2201   element->numsinkpads = 0;
2202   element->numpads = 0;
2203   g_mutex_free (element->state_mutex);
2204   g_cond_free (element->state_cond);
2205
2206   if (element->prop_value_queue)
2207     g_async_queue_unref (element->prop_value_queue);
2208   element->prop_value_queue = NULL;
2209   if (element->property_mutex)
2210     g_mutex_free (element->property_mutex);
2211   
2212   G_OBJECT_CLASS (parent_class)->dispose (object);
2213 }
2214
2215 #ifndef GST_DISABLE_LOADSAVE
2216 /**
2217  * gst_element_save_thyself:
2218  * @element: a #GstElement to save.
2219  * @parent: the xml parent node.
2220  *
2221  * Saves the element as part of the given XML structure.
2222  *
2223  * Returns: the new #xmlNodePtr.
2224  */
2225 static xmlNodePtr
2226 gst_element_save_thyself (GstObject *object,
2227                           xmlNodePtr parent)
2228 {
2229   GList *pads;
2230   GstElementClass *oclass;
2231   GParamSpec **specs, *spec;
2232   gint nspecs, i;
2233   GValue value = { 0, };
2234   GstElement *element;
2235
2236   g_return_val_if_fail (GST_IS_ELEMENT (object), parent);
2237
2238   element = GST_ELEMENT (object);
2239
2240   oclass = CLASS (element);
2241
2242   xmlNewChild(parent, NULL, "name", GST_ELEMENT_NAME(element));
2243
2244   if (oclass->elementfactory != NULL) {
2245     GstElementFactory *factory = (GstElementFactory *)oclass->elementfactory;
2246
2247     xmlNewChild (parent, NULL, "type", GST_OBJECT_NAME (factory));
2248     xmlNewChild (parent, NULL, "version", factory->details->version);
2249   }
2250
2251 /* FIXME: what is this? */  
2252 /*  if (element->manager) */
2253 /*    xmlNewChild(parent, NULL, "manager", GST_ELEMENT_NAME(element->manager)); */
2254
2255   /* params */
2256   specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (object), &nspecs);
2257   
2258   for (i=0; i<nspecs; i++) {
2259     spec = specs[i];
2260     if (spec->flags & G_PARAM_READABLE) {
2261       xmlNodePtr param;
2262       char *contents;
2263       
2264       g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE (spec));
2265       
2266       g_object_get_property (G_OBJECT (element), spec->name, &value);
2267       param = xmlNewChild (parent, NULL, "param", NULL);
2268       xmlNewChild (param, NULL, "name", spec->name);
2269       
2270       if (G_IS_PARAM_SPEC_STRING (spec))
2271         contents = g_value_dup_string (&value);
2272       else if (G_IS_PARAM_SPEC_ENUM (spec))
2273         contents = g_strdup_printf ("%d", g_value_get_enum (&value));
2274       else if (G_IS_PARAM_SPEC_INT64 (spec))
2275         contents = g_strdup_printf ("%lld", g_value_get_int64 (&value));
2276       else
2277         contents = g_strdup_value_contents (&value);
2278       
2279       xmlNewChild (param, NULL, "value", contents);
2280       g_free (contents);
2281       
2282       g_value_unset(&value);
2283     }
2284   }
2285
2286   pads = GST_ELEMENT_PADS (element);
2287
2288   while (pads) {
2289     GstPad *pad = GST_PAD (pads->data);
2290     /* figure out if it's a direct pad or a ghostpad */
2291     if (GST_ELEMENT (GST_OBJECT_PARENT (pad)) == element) {
2292       xmlNodePtr padtag = xmlNewChild (parent, NULL, "pad", NULL);
2293       gst_object_save_thyself (GST_OBJECT (pad), padtag);
2294     }
2295     pads = g_list_next (pads);
2296   }
2297
2298   return parent;
2299 }
2300
2301 static void
2302 gst_element_restore_thyself (GstObject *object, xmlNodePtr self)
2303 {
2304   xmlNodePtr children;
2305   GstElement *element;
2306   gchar *name = NULL;
2307   gchar *value = NULL;
2308
2309   element = GST_ELEMENT (object);
2310   g_return_if_fail (element != NULL);
2311
2312   /* parameters */
2313   children = self->xmlChildrenNode;
2314   while (children) {
2315     if (!strcmp (children->name, "param")) {
2316       xmlNodePtr child = children->xmlChildrenNode;
2317
2318       while (child) {
2319         if (!strcmp (child->name, "name")) {
2320           name = xmlNodeGetContent (child);
2321         }
2322         else if (!strcmp (child->name, "value")) {
2323           value = xmlNodeGetContent (child);
2324         }
2325         child = child->next;
2326       }
2327       /* FIXME: can this just be g_object_set ? */
2328       gst_util_set_object_arg (G_OBJECT (element), name, value);
2329     }
2330     children = children->next;
2331   }
2332   
2333   /* pads */
2334   children = self->xmlChildrenNode;
2335   while (children) {
2336     if (!strcmp (children->name, "pad")) {
2337       gst_pad_load_and_connect (children, GST_OBJECT (element));
2338     }
2339     children = children->next;
2340   }
2341
2342   if (GST_OBJECT_CLASS(parent_class)->restore_thyself)
2343     (GST_OBJECT_CLASS(parent_class)->restore_thyself) (object, self);
2344 }
2345 #endif /* GST_DISABLE_LOADSAVE */
2346
2347 /**
2348  * gst_element_yield:
2349  * @element: a #GstElement to yield.
2350  *
2351  * Requests a yield operation for the element. The scheduler will typically
2352  * give control to another element.
2353  */
2354 void
2355 gst_element_yield (GstElement *element)
2356 {
2357   if (GST_ELEMENT_SCHED (element)) {
2358     gst_scheduler_yield (GST_ELEMENT_SCHED (element), element);
2359   }
2360 }
2361
2362 /**
2363  * gst_element_interrupt:
2364  * @element: a #GstElement to interrupt.
2365  *
2366  * Requests the scheduler of this element to interrupt the execution of
2367  * this element and scheduler another one.
2368  *
2369  * Returns: TRUE if the element should exit its chain/loop/get
2370  * function ASAP, depending on the scheduler implementation.
2371  */
2372 gboolean
2373 gst_element_interrupt (GstElement *element)
2374 {
2375   if (GST_ELEMENT_SCHED (element)) {
2376     return gst_scheduler_interrupt (GST_ELEMENT_SCHED (element), element);
2377   }
2378   else 
2379     return FALSE;
2380 }
2381
2382 /**
2383  * gst_element_set_scheduler:
2384  * @element: a #GstElement to set the scheduler of.
2385  * @sched: the #GstScheduler to set.
2386  *
2387  * Sets the scheduler of the element.  For internal use only, unless you're
2388  * writing a new bin subclass.
2389  */
2390 void
2391 gst_element_set_scheduler (GstElement *element,
2392                        GstScheduler *sched)
2393 {
2394   g_return_if_fail (GST_IS_ELEMENT (element));
2395   
2396   GST_INFO_ELEMENT (GST_CAT_PARENTAGE, element, "setting scheduler to %p", sched);
2397
2398   GST_ELEMENT_SCHED (element) = sched;
2399 }
2400
2401 /**
2402  * gst_element_get_scheduler:
2403  * @element: a #GstElement to get the scheduler of.
2404  *
2405  * Returns the scheduler of the element.
2406  *
2407  * Returns: the element's #GstScheduler.
2408  */
2409 GstScheduler*
2410 gst_element_get_scheduler (GstElement *element)
2411 {
2412   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
2413
2414   return GST_ELEMENT_SCHED (element);
2415 }
2416
2417 /**
2418  * gst_element_set_loop_function:
2419  * @element: a #GstElement to set the loop function of.
2420  * @loop: Pointer to #GstElementLoopFunction.
2421  *
2422  * This sets the loop function for the element.  The function pointed to
2423  * can deviate from the GstElementLoopFunction definition in type of
2424  * pointer only.
2425  *
2426  * NOTE: in order for this to take effect, the current loop function *must*
2427  * exit.  Assuming the loop function itself is the only one who will cause
2428  * a new loopfunc to be assigned, this should be no problem.
2429  */
2430 void
2431 gst_element_set_loop_function (GstElement *element,
2432                                GstElementLoopFunction loop)
2433 {
2434   g_return_if_fail (GST_IS_ELEMENT (element));
2435
2436   /* set the loop function */
2437   element->loopfunc = loop;
2438
2439   /* set the NEW_LOOPFUNC flag so everyone knows to go try again */
2440   GST_FLAG_SET (element, GST_ELEMENT_NEW_LOOPFUNC);
2441 }
2442
2443 /**
2444  * gst_element_set_eos:
2445  * @element: a #GstElement to set to the EOS state.
2446  *
2447  * Perform the actions needed to bring the element in the EOS state.
2448  */
2449 void
2450 gst_element_set_eos (GstElement *element)
2451 {
2452   g_return_if_fail (GST_IS_ELEMENT (element));
2453
2454   GST_DEBUG (GST_CAT_EVENT, "setting EOS on element %s", 
2455              GST_OBJECT_NAME (element));
2456
2457   gst_element_set_state (element, GST_STATE_PAUSED);
2458
2459   g_signal_emit (G_OBJECT (element), gst_element_signals[EOS], 0);
2460 }
2461
2462
2463 /**
2464  * gst_element_state_get_name:
2465  * @state: a #GstElementState to get the name of.
2466  *
2467  * Gets a string representing the given state.
2468  *
2469  * Returns: a string with the name of the state.
2470  */
2471 const gchar*
2472 gst_element_state_get_name (GstElementState state) 
2473 {
2474   switch (state) {
2475 #ifdef GST_DEBUG_COLOR
2476     case GST_STATE_VOID_PENDING: return "NONE_PENDING";break;
2477     case GST_STATE_NULL: return "\033[01;37mNULL\033[00m";break;
2478     case GST_STATE_READY: return "\033[01;31mREADY\033[00m";break;
2479     case GST_STATE_PLAYING: return "\033[01;32mPLAYING\033[00m";break;
2480     case GST_STATE_PAUSED: return "\033[01;33mPAUSED\033[00m";break;
2481     default:
2482       /* This is a memory leak */
2483       return g_strdup_printf ("\033[01;37;41mUNKNOWN!\033[00m(%d)", state);
2484 #else
2485     case GST_STATE_VOID_PENDING: return "NONE_PENDING";break;
2486     case GST_STATE_NULL: return "NULL";break;
2487     case GST_STATE_READY: return "READY";break;
2488     case GST_STATE_PLAYING: return "PLAYING";break;
2489     case GST_STATE_PAUSED: return "PAUSED";break;
2490     default: return "UNKNOWN!";
2491 #endif
2492   }
2493   return "";
2494 }
2495
2496 static void
2497 gst_element_populate_std_props (GObjectClass * klass, const gchar *prop_name, 
2498                                 guint arg_id, GParamFlags flags)
2499 {
2500   GQuark prop_id = g_quark_from_string (prop_name);
2501   GParamSpec *pspec;
2502
2503   static GQuark fd_id = 0;
2504   static GQuark blocksize_id;
2505   static GQuark bytesperread_id;
2506   static GQuark dump_id;
2507   static GQuark filesize_id;
2508   static GQuark mmapsize_id;
2509   static GQuark location_id;
2510   static GQuark offset_id;
2511   static GQuark silent_id;
2512   static GQuark touch_id;
2513
2514   if (!fd_id) {
2515     fd_id = g_quark_from_static_string ("fd");
2516     blocksize_id = g_quark_from_static_string ("blocksize");
2517     bytesperread_id = g_quark_from_static_string ("bytesperread");
2518     dump_id = g_quark_from_static_string ("dump");
2519     filesize_id = g_quark_from_static_string ("filesize");
2520     mmapsize_id = g_quark_from_static_string ("mmapsize");
2521     location_id = g_quark_from_static_string ("location");
2522     offset_id = g_quark_from_static_string ("offset");
2523     silent_id = g_quark_from_static_string ("silent");
2524     touch_id = g_quark_from_static_string ("touch");
2525   }
2526
2527   if (prop_id == fd_id) {
2528     pspec = g_param_spec_int ("fd", "File-descriptor",
2529                               "File-descriptor for the file being read",
2530                               0, G_MAXINT, 0, flags);
2531   }
2532   else if (prop_id == blocksize_id) {
2533     pspec = g_param_spec_ulong ("blocksize", "Block Size",
2534                                 "Block size to read per buffer",
2535                                 0, G_MAXULONG, 4096, flags);
2536
2537   }
2538   else if (prop_id == bytesperread_id) {
2539     pspec = g_param_spec_int ("bytesperread", "Bytes per read",
2540                               "Number of bytes to read per buffer",
2541                               G_MININT, G_MAXINT, 0, flags);
2542
2543   }
2544   else if (prop_id == dump_id) {
2545     pspec = g_param_spec_boolean ("dump", "Dump", 
2546                                   "Dump bytes to stdout", 
2547                                   FALSE, flags);
2548
2549   }
2550   else if (prop_id == filesize_id) {
2551     pspec = g_param_spec_int64 ("filesize", "File Size",
2552                                 "Size of the file being read",
2553                                 0, G_MAXINT64, 0, flags);
2554
2555   }
2556   else if (prop_id == mmapsize_id) {
2557     pspec = g_param_spec_ulong ("mmapsize", "mmap() Block Size",
2558                                 "Size in bytes of mmap()d regions",
2559                                 0, G_MAXULONG, 4 * 1048576, flags);
2560
2561   }
2562   else if (prop_id == location_id) {
2563     pspec = g_param_spec_string ("location", "File Location",
2564                                  "Location of the file to read",
2565                                  NULL, flags);
2566
2567   }
2568   else if (prop_id == offset_id) {
2569     pspec = g_param_spec_int64 ("offset", "File Offset",
2570                                 "Byte offset of current read pointer",
2571                                 0, G_MAXINT64, 0, flags);
2572
2573   }
2574   else if (prop_id == silent_id) {
2575     pspec = g_param_spec_boolean ("silent", "Silent", "Don't produce events",
2576                                   FALSE, flags);
2577
2578   }
2579   else if (prop_id == touch_id) {
2580     pspec = g_param_spec_boolean ("touch", "Touch read data",
2581                                   "Touch data to force disk read before "
2582                                   "push ()", TRUE, flags);
2583   }
2584   else {
2585     g_warning ("Unknown - 'standard' property '%s' id %d from klass %s",
2586                prop_name, arg_id, g_type_name (G_OBJECT_CLASS_TYPE (klass)));
2587     pspec = NULL;
2588   }
2589
2590   if (pspec) {
2591     g_object_class_install_property (klass, arg_id, pspec);
2592   }
2593 }
2594
2595 /**
2596  * gst_element_class_install_std_props:
2597  * @klass: the #GstElementClass to add the properties to.
2598  * @first_name: the name of the first property.
2599  * in a NULL terminated
2600  * @...: the id and flags of the first property, followed by
2601  * further 'name', 'id', 'flags' triplets and terminated by NULL.
2602  * 
2603  * Adds a list of standardized properties with types to the @klass.
2604  * the id is for the property switch in your get_prop method, and
2605  * the flags determine readability / writeability.
2606  **/
2607 void
2608 gst_element_class_install_std_props (GstElementClass * klass, 
2609                                      const gchar *first_name, ...)
2610 {
2611   const char *name;
2612
2613   va_list args;
2614
2615   g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
2616
2617   va_start (args, first_name);
2618
2619   name = first_name;
2620
2621   while (name) {
2622     int arg_id = va_arg (args, int);
2623     int flags = va_arg (args, int);
2624
2625     gst_element_populate_std_props ((GObjectClass *) klass, name, arg_id, flags);
2626
2627     name = va_arg (args, char *);
2628   }
2629
2630   va_end (args);
2631 }
2632
2633 /**
2634  * gst_element_get_managing_bin:
2635  * @element: a #GstElement to get the managing bin of.
2636  * 
2637  * Gets the managing bin (a pipeline or a thread, for example) of an element.
2638  *
2639  * Returns: the #GstBin, or NULL on failure.
2640  **/
2641 GstBin*
2642 gst_element_get_managing_bin (GstElement *element)
2643 {
2644   GstBin *bin;
2645
2646   g_return_val_if_fail (element != NULL, NULL);
2647
2648   bin = GST_BIN (gst_object_get_parent (GST_OBJECT_CAST (element)));
2649
2650   while (bin && !GST_FLAG_IS_SET (GST_OBJECT_CAST (bin), GST_BIN_FLAG_MANAGER))
2651     bin = GST_BIN (gst_object_get_parent (GST_OBJECT_CAST (bin)));
2652   
2653   return bin;
2654 }