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