s/gst_element_install_std_props/gst_element_class_install_std_props/ -- it just makes...
[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 "gst_private.h"
27
28 #include "gstelement.h"
29 #include "gstextratypes.h"
30 #include "gstbin.h"
31 #include "gstscheduler.h"
32 #include "gstevent.h"
33 #include "gstutils.h"
34
35 /* Element signals and args */
36 enum {
37   STATE_CHANGE,
38   NEW_PAD,
39   PAD_REMOVED,
40   ERROR,
41   EOS,
42   LAST_SIGNAL
43 };
44
45 enum {
46   ARG_0,
47   /* FILL ME */
48 };
49
50 #define CLASS(element)  GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS (element))
51
52 static void                     gst_element_class_init          (GstElementClass *klass);
53 static void                     gst_element_init                (GstElement *element);
54 static void                     gst_element_base_class_init     (GstElementClass *klass);
55
56 static void                     gst_element_set_property        (GObject *object, guint prop_id, 
57                                                                  const GValue *value, GParamSpec *pspec);
58 static void                     gst_element_get_property        (GObject *object, guint prop_id, GValue *value, 
59                                                                  GParamSpec *pspec);
60
61 static void                     gst_element_dispose             (GObject *object);
62
63 static GstElementStateReturn    gst_element_change_state        (GstElement *element);
64 static void                     gst_element_error_func          (GstElement* element, GstElement *source, gchar *errormsg);
65
66 #ifndef GST_DISABLE_LOADSAVE
67 static xmlNodePtr               gst_element_save_thyself        (GstObject *object, xmlNodePtr parent);
68 static void                     gst_element_restore_thyself     (GstObject *parent, xmlNodePtr self);
69 #endif
70
71 GType _gst_element_type = 0;
72
73 static GstObjectClass *parent_class = NULL;
74 static guint gst_element_signals[LAST_SIGNAL] = { 0 };
75
76 GType gst_element_get_type (void) 
77 {
78   if (!_gst_element_type) {
79     static const GTypeInfo element_info = {
80       sizeof(GstElementClass),
81       (GBaseInitFunc)gst_element_base_class_init,
82       NULL,
83       (GClassInitFunc)gst_element_class_init,
84       NULL,
85       NULL,
86       sizeof(GstElement),
87       0,
88       (GInstanceInitFunc)gst_element_init,
89       NULL
90     };
91     _gst_element_type = g_type_register_static(GST_TYPE_OBJECT, "GstElement", &element_info, G_TYPE_FLAG_ABSTRACT);
92   }
93   return _gst_element_type;
94 }
95
96 static void
97 gst_element_class_init (GstElementClass *klass)
98 {
99   GObjectClass *gobject_class;
100   GstObjectClass *gstobject_class;
101
102   gobject_class = (GObjectClass*) klass;
103   gstobject_class = (GstObjectClass*) klass;
104
105   parent_class = g_type_class_ref(GST_TYPE_OBJECT);
106
107   gst_element_signals[STATE_CHANGE] =
108     g_signal_new ("state_change", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
109                   G_STRUCT_OFFSET (GstElementClass, state_change), NULL, NULL,
110                   gst_marshal_VOID__INT_INT, G_TYPE_NONE, 2,
111                   G_TYPE_INT, G_TYPE_INT);
112   gst_element_signals[NEW_PAD] =
113     g_signal_new ("new_pad", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
114                   G_STRUCT_OFFSET (GstElementClass, new_pad), NULL, NULL,
115                   gst_marshal_VOID__POINTER, G_TYPE_NONE, 1,
116                   G_TYPE_POINTER);
117   gst_element_signals[PAD_REMOVED] =
118     g_signal_new ("pad_removed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
119                   G_STRUCT_OFFSET (GstElementClass, pad_removed), NULL, NULL,
120                   gst_marshal_VOID__POINTER, G_TYPE_NONE, 1,
121                   G_TYPE_POINTER);
122   gst_element_signals[ERROR] =
123     g_signal_new ("error", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
124                   G_STRUCT_OFFSET (GstElementClass, error), NULL, NULL,
125                   gst_marshal_VOID__OBJECT_STRING, G_TYPE_NONE, 2,
126                   G_TYPE_OBJECT, G_TYPE_STRING);
127   gst_element_signals[EOS] =
128     g_signal_new ("eos", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
129                   G_STRUCT_OFFSET (GstElementClass,eos), NULL, NULL,
130                   gst_marshal_VOID__VOID, G_TYPE_NONE, 0);
131
132
133
134   gobject_class->set_property           = GST_DEBUG_FUNCPTR (gst_element_set_property);
135   gobject_class->get_property           = GST_DEBUG_FUNCPTR (gst_element_get_property);
136   gobject_class->dispose                = GST_DEBUG_FUNCPTR (gst_element_dispose);
137
138 #ifndef GST_DISABLE_LOADSAVE
139   gstobject_class->save_thyself         = GST_DEBUG_FUNCPTR (gst_element_save_thyself);
140   gstobject_class->restore_thyself      = GST_DEBUG_FUNCPTR (gst_element_restore_thyself);
141 #endif
142
143   klass->change_state                   = GST_DEBUG_FUNCPTR (gst_element_change_state);
144   klass->error                          = GST_DEBUG_FUNCPTR (gst_element_error_func);
145   klass->elementfactory                 = NULL;
146   klass->padtemplates                   = NULL;
147   klass->numpadtemplates                = 0;
148 }
149
150 static void
151 gst_element_base_class_init (GstElementClass *klass)
152 {
153   GObjectClass *gobject_class;
154
155   gobject_class = (GObjectClass*) klass;
156
157   gobject_class->set_property =         GST_DEBUG_FUNCPTR(gst_element_set_property);
158   gobject_class->get_property =         GST_DEBUG_FUNCPTR(gst_element_get_property);
159 }
160
161 static void
162 gst_element_init (GstElement *element)
163 {
164   element->current_state = GST_STATE_NULL;
165   element->pending_state = GST_STATE_VOID_PENDING;
166   element->numpads = 0;
167   element->numsrcpads = 0;
168   element->numsinkpads = 0;
169   element->pads = NULL;
170   element->loopfunc = NULL;
171   element->sched = NULL;
172   element->sched_private = NULL;
173   element->state_mutex = g_mutex_new ();
174   element->state_cond = g_cond_new ();
175 }
176
177
178 static void
179 gst_element_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
180 {
181   GstElementClass *oclass = CLASS (object);
182
183   if (oclass->set_property)
184     (oclass->set_property) (object, prop_id, value, pspec);
185 }
186
187
188 static void
189 gst_element_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
190 {
191   GstElementClass *oclass = CLASS (object);
192
193   if (oclass->get_property)
194     (oclass->get_property) (object, prop_id, value, pspec);
195 }
196
197
198 /**
199  * gst_element_set_name:
200  * @element: GstElement to set name of
201  * @name: new name of element
202  *
203  * Set the name of the element, getting rid of the old name if there was
204  * one.
205  */
206 void
207 gst_element_set_name (GstElement *element, const gchar *name)
208 {
209   g_return_if_fail (element != NULL);
210   g_return_if_fail (GST_IS_ELEMENT (element));
211
212   gst_object_set_name (GST_OBJECT (element), name);
213 }
214
215 /**
216  * gst_element_get_name:
217  * @element: GstElement to get name of
218  *
219  * Get the name of the element.
220  *
221  * Returns: name of the element
222  */
223 const gchar*
224 gst_element_get_name (GstElement *element)
225 {
226   g_return_val_if_fail (element != NULL, NULL);
227   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
228
229   return GST_OBJECT_NAME (element);
230 }
231
232 /**
233  * gst_element_set_parent:
234  * @element: GstElement to set parent of
235  * @parent: new parent of the object
236  *
237  * Set the parent of the element.
238  */
239 void
240 gst_element_set_parent (GstElement *element, GstObject *parent)
241 {
242   g_return_if_fail (element != NULL);
243   g_return_if_fail (GST_IS_ELEMENT (element));
244   g_return_if_fail (GST_OBJECT_PARENT (element) == NULL);
245   g_return_if_fail (parent != NULL);
246   g_return_if_fail (GST_IS_OBJECT (parent));
247   g_return_if_fail ((gpointer)element != (gpointer)parent);
248
249   gst_object_set_parent (GST_OBJECT (element), parent);
250 }
251
252 /**
253  * gst_element_get_parent:
254  * @element: GstElement to get the parent of
255  *
256  * Get the parent of the element.
257  *
258  * Returns: parent of the element
259  */
260 GstObject*
261 gst_element_get_parent (GstElement *element)
262 {
263   g_return_val_if_fail (element != NULL, NULL);
264   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
265
266   return GST_OBJECT_PARENT (element);
267 }
268
269 /**
270  * gst_element_set_clock:
271  * @element: GstElement to set the clock to
272  * @clock: the clock to set for the element
273  *
274  * Set the clock for the element
275  */
276 void
277 gst_element_set_clock (GstElement *element, GstClock *clock)
278 {
279   g_return_if_fail (element != NULL);
280   g_return_if_fail (GST_IS_ELEMENT (element));
281
282   if (element->setclockfunc)
283     element->setclockfunc (element, clock);
284 }
285
286 /**
287  * gst_element_get_clock:
288  * @element: GstElement to get the clock of
289  *
290  * Get the clock of the element
291  */
292 GstClock*
293 gst_element_get_clock (GstElement *element)
294 {
295   g_return_val_if_fail (element != NULL, NULL);
296   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
297   
298   if (element->getclockfunc)
299     return element->getclockfunc (element);
300
301   return NULL;
302 }
303
304 /**
305  * gst_element_clock_wait:
306  * @element: GstElement to wait for the clock
307  * @clock: the clock to wait for
308  * @time: the time to wait for
309  *
310  * Wait for a specific time on the clock
311  */
312 GstClockReturn
313 gst_element_clock_wait (GstElement *element, GstClock *clock, GstClockTime time)
314 {
315   g_return_val_if_fail (element != NULL, GST_CLOCK_ERROR);
316   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_CLOCK_ERROR);
317
318   /* FIXME inform the scheduler */
319   return gst_clock_wait (clock, time);
320 }
321
322 /**
323  * gst_element_add_pad:
324  * @element: element to add pad to
325  * @pad: pad to add
326  *
327  * Add a pad (connection point) to the element, setting the parent of the
328  * pad to the element (and thus adding a reference).
329  */
330 void
331 gst_element_add_pad (GstElement *element, GstPad *pad)
332 {
333   g_return_if_fail (element != NULL);
334   g_return_if_fail (GST_IS_ELEMENT (element));
335   g_return_if_fail (pad != NULL);
336   g_return_if_fail (GST_IS_PAD (pad));
337
338   /* first check to make sure the pad's parent is already set */
339   g_return_if_fail (GST_PAD_PARENT (pad) == NULL);
340
341   /* then check to see if there's already a pad by that name here */
342   g_return_if_fail (gst_object_check_uniqueness (element->pads, GST_PAD_NAME(pad)) == TRUE);
343
344   /* set the pad's parent */
345   GST_DEBUG (GST_CAT_ELEMENT_PADS,"setting parent of pad '%s' to '%s'\n",
346         GST_PAD_NAME (pad), GST_ELEMENT_NAME (element));
347   gst_object_set_parent (GST_OBJECT (pad), GST_OBJECT (element));
348
349   /* add it to the list */
350   element->pads = g_list_append (element->pads, pad);
351   element->numpads++;
352   if (gst_pad_get_direction (pad) == GST_PAD_SRC)
353     element->numsrcpads++;
354   else
355     element->numsinkpads++;
356
357   /* emit the NEW_PAD signal */
358   g_signal_emit (G_OBJECT (element), gst_element_signals[NEW_PAD], 0, pad);
359 }
360
361 /**
362  * gst_element_remove_pad:
363  * @element: element to remove pad from
364  * @pad: pad to remove
365  *
366  * Remove a pad (connection point) from the element, 
367  */
368 void
369 gst_element_remove_pad (GstElement *element, GstPad *pad)
370 {
371   g_return_if_fail (element != NULL);
372   g_return_if_fail (GST_IS_ELEMENT (element));
373   g_return_if_fail (pad != NULL);
374   g_return_if_fail (GST_IS_PAD (pad));
375
376   g_return_if_fail (GST_PAD_PARENT (pad) == element);
377
378   /* check to see if the pad is still connected */
379   /* FIXME: what if someone calls _remove_pad instead of 
380     _remove_ghost_pad? */
381   if (GST_IS_REAL_PAD (pad)) {
382     g_return_if_fail (GST_RPAD_PEER (pad) == NULL);
383   }
384   
385   /* remove it from the list */
386   element->pads = g_list_remove (element->pads, pad);
387   element->numpads--;
388   if (gst_pad_get_direction (pad) == GST_PAD_SRC)
389     element->numsrcpads--;
390   else
391     element->numsinkpads--;
392
393   g_signal_emit (G_OBJECT (element), gst_element_signals[PAD_REMOVED], 0, pad);
394
395   gst_object_unparent (GST_OBJECT (pad));
396 }
397
398 /**
399  * gst_element_add_ghost_pad:
400  * @element: element to add ghost pad to
401  * @pad: pad from which the new ghost pad will be created
402  * @name: name of the new ghost pad
403  *
404  * Create a ghost pad from the given pad, and add it to the list of pads
405  * for this element.
406  * 
407  * Returns: the added ghost pad or NULL, if no ghost pad was created.
408  */
409 GstPad *
410 gst_element_add_ghost_pad (GstElement *element, GstPad *pad, gchar *name)
411 {
412   GstPad *ghostpad;
413
414   g_return_val_if_fail (element != NULL, NULL);
415   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
416   g_return_val_if_fail (pad != NULL, NULL);
417   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
418
419   /* then check to see if there's already a pad by that name here */
420   g_return_val_if_fail (gst_object_check_uniqueness (element->pads, name) == TRUE, NULL);
421
422   GST_DEBUG(GST_CAT_ELEMENT_PADS,"creating new ghost pad called %s, from pad %s:%s\n",
423             name,GST_DEBUG_PAD_NAME(pad));
424   ghostpad = gst_ghost_pad_new (name, pad);
425
426   /* add it to the list */
427   GST_DEBUG(GST_CAT_ELEMENT_PADS,"adding ghost pad %s to element %s\n",
428             name, GST_ELEMENT_NAME (element));
429   element->pads = g_list_append (element->pads, ghostpad);
430   element->numpads++;
431   /* set the parent of the ghostpad */
432   gst_object_set_parent (GST_OBJECT (ghostpad), GST_OBJECT (element));
433
434   GST_DEBUG(GST_CAT_ELEMENT_PADS,"added ghostpad %s:%s\n",GST_DEBUG_PAD_NAME(ghostpad));
435
436   /* emit the NEW_GHOST_PAD signal */
437   g_signal_emit (G_OBJECT (element), gst_element_signals[NEW_PAD], 0, ghostpad);
438         
439   return ghostpad;
440 }
441
442 /**
443  * gst_element_remove_ghost_pad:
444  * @element: element to remove the ghost pad from
445  * @pad: ghost pad to remove
446  *
447  * removes a ghost pad from an element
448  */
449 void
450 gst_element_remove_ghost_pad (GstElement *element, GstPad *pad)
451 {
452   g_return_if_fail (element != NULL);
453   g_return_if_fail (GST_IS_ELEMENT (element));
454   g_return_if_fail (pad != NULL);
455   g_return_if_fail (GST_IS_GHOST_PAD (pad));
456
457   /* FIXME this is redundant?
458    * wingo 10-july-2001: I don't think so, you have to actually remove the pad
459    * from the element. gst_pad_remove_ghost_pad just removes the ghostpad from
460    * the real pad's ghost pad list
461    */
462   gst_pad_remove_ghost_pad (GST_PAD (GST_PAD_REALIZE (pad)), pad);
463   gst_element_remove_pad (element, pad);
464 }
465
466
467 /**
468  * gst_element_get_pad:
469  * @element: element to find pad of
470  * @name: name of pad to retrieve
471  *
472  * Retrieve a pad from the element by name.
473  *
474  * Returns: requested pad if found, otherwise NULL.
475  */
476 GstPad*
477 gst_element_get_pad (GstElement *element, const gchar *name)
478 {
479   GList *walk;
480
481   g_return_val_if_fail (element != NULL, NULL);
482   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
483   g_return_val_if_fail (name != NULL, NULL);
484
485   /* if there aren't any pads, well, we're not likely to find one */
486   if (!element->numpads)
487     return NULL;
488
489   /* look through the list, matching by name */
490   walk = element->pads;
491   while (walk) {
492     GstPad *pad = GST_PAD(walk->data);
493     if (!strcmp (GST_PAD_NAME(pad), name)) {
494       GST_INFO(GST_CAT_ELEMENT_PADS,"found pad %s:%s",GST_DEBUG_PAD_NAME(pad));
495       return pad;
496     }
497     walk = g_list_next (walk);
498   }
499
500   GST_INFO(GST_CAT_ELEMENT_PADS,"no such pad '%s' in element \"%s\"",name,GST_ELEMENT_NAME(element));
501   return NULL;
502 }
503
504 /**
505  * gst_element_get_pad_list:
506  * @element: element to get pads of
507  *
508  * Retrieve a list of the pads associated with the element.
509  *
510  * Returns: GList of pads
511  */
512 GList*
513 gst_element_get_pad_list (GstElement *element)
514 {
515   g_return_val_if_fail (element != NULL, NULL);
516   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
517
518   /* return the list of pads */
519   return element->pads;
520 }
521
522 /**
523  * gst_element_class_add_padtemplate:
524  * @klass: element class to add padtemplate to
525  * @templ: padtemplate to add
526  *
527  * Add a padtemplate to an element class. This is useful if you have derived a custom
528  * bin and wish to provide an on-request pad at runtime. Plugin writers should use
529  * gst_elementfactory_add_padtemplate instead.
530  */
531 void
532 gst_element_class_add_padtemplate (GstElementClass *klass, GstPadTemplate *templ)
533 {
534   g_return_if_fail (klass != NULL);
535   g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
536   g_return_if_fail (templ != NULL);
537   g_return_if_fail (GST_IS_PADTEMPLATE (templ));
538   
539   klass->padtemplates = g_list_append (klass->padtemplates, templ);
540   klass->numpadtemplates++;
541 }
542
543 /**
544  * gst_element_get_padtemplate_list:
545  * @element: element to get padtemplates of
546  *
547  * Retrieve a list of the padtemplates associated with the element.
548  *
549  * Returns: GList of padtemplates
550  */
551 GList*
552 gst_element_get_padtemplate_list (GstElement *element)
553 {
554   g_return_val_if_fail (element != NULL, NULL);
555   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
556
557   return CLASS (element)->padtemplates;
558 }
559
560 /**
561  * gst_element_get_padtemplate_by_name:
562  * @element: element to get padtemplate of
563  * @name: the name of the padtemplate to get.
564  *
565  * Retrieve a padtemplate from this element with the
566  * given name.
567  *
568  * Returns: the padtemplate with the given name
569  */
570 GstPadTemplate*
571 gst_element_get_padtemplate_by_name (GstElement *element, const guchar *name)
572 {
573   GList *padlist;
574
575   g_return_val_if_fail (element != NULL, NULL);
576   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
577   g_return_val_if_fail (name != NULL, NULL);
578
579   padlist = gst_element_get_padtemplate_list (element);
580
581   while (padlist) {
582     GstPadTemplate *padtempl = (GstPadTemplate*) padlist->data;
583
584     if (!strcmp (padtempl->name_template, name))
585       return padtempl;
586
587     padlist = g_list_next (padlist);
588   }
589
590   return NULL;
591 }
592
593 /**
594  * gst_element_get_padtemplate_by_compatible:
595  * @element: element to get padtemplate of
596  * @templ: a template to find a compatible template for
597  *
598  * Generate a padtemplate for this element compatible with the given
599  * template, ie able to link to it.
600  *
601  * Returns: the padtemplate
602  */
603 static GstPadTemplate*
604 gst_element_get_padtemplate_by_compatible (GstElement *element, GstPadTemplate *compattempl)
605 {
606   GstPadTemplate *newtempl = NULL;
607   GList *padlist;
608
609   GST_DEBUG(GST_CAT_ELEMENT_PADS,"gst_element_get_padtemplate_by_compatible()\n");
610
611   g_return_val_if_fail (element != NULL, NULL);
612   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
613   g_return_val_if_fail (compattempl != NULL, NULL);
614
615   padlist = gst_element_get_padtemplate_list (element);
616
617   while (padlist) {
618     GstPadTemplate *padtempl = (GstPadTemplate*) padlist->data;
619     gboolean compat = FALSE;
620
621     /* Ignore name
622      * Ignore presence
623      * Check direction (must be opposite)
624      * Check caps
625      */
626     GST_DEBUG(GST_CAT_CAPS,"checking direction and caps\n");
627     if (padtempl->direction == GST_PAD_SRC &&
628       compattempl->direction == GST_PAD_SINK) {
629       GST_DEBUG(GST_CAT_CAPS,"compatible direction: found src pad template\n");
630       compat = gst_caps_check_compatibility(GST_PADTEMPLATE_CAPS (padtempl),
631                                             GST_PADTEMPLATE_CAPS (compattempl));
632       GST_DEBUG(GST_CAT_CAPS,"caps are %scompatible\n", (compat?"":"not "));
633     } else if (padtempl->direction == GST_PAD_SINK &&
634                compattempl->direction == GST_PAD_SRC) {
635       GST_DEBUG(GST_CAT_CAPS,"compatible direction: found sink pad template\n");
636       compat = gst_caps_check_compatibility(GST_PADTEMPLATE_CAPS (compattempl),
637                                             GST_PADTEMPLATE_CAPS (padtempl));
638       GST_DEBUG(GST_CAT_CAPS,"caps are %scompatible\n", (compat?"":"not "));
639     }
640
641     if (compat) {
642       newtempl = padtempl;
643       break;
644     }
645
646     padlist = g_list_next (padlist);
647   }
648
649   return newtempl;
650 }
651
652 static GstPad*
653 gst_element_request_pad (GstElement *element, GstPadTemplate *templ, const gchar* name)
654 {
655   GstPad *newpad = NULL;
656   GstElementClass *oclass;
657
658   oclass = CLASS (element);
659   if (oclass->request_new_pad)
660     newpad = (oclass->request_new_pad)(element, templ, name);
661
662   return newpad;
663 }
664
665 /**
666  * gst_element_request_compatible_pad:
667  * @element: element to request a new pad from
668  * @templ: a pad template to which the new pad should be able to connect
669  *
670  * Request a new pad from the element. The template will
671  * be used to decide what type of pad to create. This function
672  * is typically used for elements with a padtemplate with presence
673  * GST_PAD_REQUEST.
674  *
675  * Returns: the new pad that was created.
676  */
677 GstPad*
678 gst_element_request_compatible_pad (GstElement *element, GstPadTemplate *templ)
679 {
680   GstPadTemplate *templ_new;
681   GstPad *pad = NULL;
682
683   g_return_val_if_fail (element != NULL, NULL);
684   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
685   g_return_val_if_fail (templ != NULL, NULL);
686
687   templ_new = gst_element_get_padtemplate_by_compatible (element, templ);
688   if (templ_new != NULL)
689       pad = gst_element_request_pad (element, templ_new, NULL);
690
691   return pad;
692 }
693
694 /**
695  * gst_element_request_pad_by_name:
696  * @element: element to request a new pad from
697  * @name: the name of the padtemplate to use.
698  *
699  * Request a new pad from the element. The name argument will
700  * be used to decide what padtemplate to use. This function
701  * is typically used for elements with a padtemplate with presence
702  * GST_PAD_REQUEST.
703  *
704  * Returns: the new pad that was created.
705  */
706 GstPad*
707 gst_element_request_pad_by_name (GstElement *element, const gchar *name)
708 {
709   GstPadTemplate *templ = NULL;
710   GstPad *pad;
711   const gchar *req_name = NULL;
712   gboolean templ_found = FALSE;
713   GList *list;
714   gint n;
715   gchar *str;
716
717   g_return_val_if_fail (element != NULL, NULL);
718   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
719   g_return_val_if_fail (name != NULL, NULL);
720
721   if (strstr (name, "%")) {
722     templ = gst_element_get_padtemplate_by_name (element, name);
723     req_name = NULL;
724     if (templ)
725       templ_found = TRUE;
726   } else {
727     list = gst_element_get_padtemplate_list(element);
728     while (!templ_found && list) {
729       templ = (GstPadTemplate*) list->data;
730       if (templ->presence == GST_PAD_REQUEST) {
731         /* we know that %s and %d are the ony possibilities because of sanity
732            checks in gst_padtemplate_new */
733         if (strstr (templ->name_template, "%d")) {
734           if (sscanf(name, templ->name_template, &n)) {
735             templ_found = TRUE;
736             req_name = name;
737             break;
738           }
739         } else if (strstr (templ->name_template, "%s")) {
740           if (sscanf(name, templ->name_template, &str)) {
741             templ_found = TRUE;
742             req_name = name;
743             break;
744           }
745         }
746       }
747       list = list->next;
748     }
749   }
750   
751   if (!templ_found)
752       return NULL;
753   
754   pad = gst_element_request_pad (element, templ, req_name);
755   
756   return pad;
757 }
758
759 /**
760  * gst_element_get_compatible_pad_filtered:
761  * @element: the element in which the pad should be found
762  * @pad: the pad to find a compatible one for
763  * @filtercaps: the caps to use as a filter
764  *
765  * Looks for an unconnected pad to which the given pad can connect to.
766  * It is not guaranteed that connecting the pads will work, though
767  * it should work in most cases.
768  *
769  * Returns: the pad to which a connection can be made
770  */
771
772 GstPad*                 
773 gst_element_get_compatible_pad_filtered (GstElement *element, GstPad *pad, GstCaps *filtercaps)
774 {
775   GList *pads;
776   GstPadTemplate *templ;
777   GstCaps *templcaps;
778   GstPad *foundpad = NULL;
779   
780   /* checks */
781   g_return_val_if_fail (element != NULL, NULL);
782   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
783   g_return_val_if_fail (pad != NULL, NULL);
784   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
785   
786   /* let's use the real pad */
787   pad = (GstPad *) GST_PAD_REALIZE (pad);
788   g_return_val_if_fail (pad != NULL, NULL);
789   g_return_val_if_fail (GST_RPAD_PEER (pad) == NULL, NULL);
790   
791   /* try to get an existing unconnected pad */
792   pads = gst_element_get_pad_list (element);
793   while (pads) {
794     GstPad *current = GST_PAD (pads->data);
795     if ((GST_PAD_PEER (GST_PAD_REALIZE (current)) == NULL) &&
796         gst_pad_can_connect_filtered (pad, current, filtercaps)) {
797       return current;
798     }
799     pads = g_list_next (pads);
800   }
801   
802   /* try to create a new one */
803   /* requesting is a little crazy, we need a template. Let's create one */
804   if (filtercaps != NULL) {
805     templcaps = gst_caps_intersect (filtercaps, (GstCaps *) GST_RPAD_CAPS (pad));
806     if (templcaps == NULL)
807       return NULL;
808   } else {
809     templcaps = gst_caps_copy (gst_pad_get_caps (pad));
810   }
811   
812   templ = gst_padtemplate_new ((gchar *) GST_PAD_NAME (pad), GST_RPAD_DIRECTION (pad),
813                                GST_PAD_ALWAYS, templcaps, NULL);
814   foundpad = gst_element_request_compatible_pad (element, templ);
815   gst_object_unref (GST_OBJECT (templ)); /* this will take care of the caps too */
816   
817   /* FIXME: this is broken, but it's in here so autoplugging elements that don't
818      have caps on their source padtemplates (spider) can connect... */
819   if (!foundpad && !filtercaps) {
820     templ = gst_padtemplate_new ((gchar *) GST_PAD_NAME (pad), GST_RPAD_DIRECTION (pad),
821                                  GST_PAD_ALWAYS, NULL, NULL);
822     foundpad = gst_element_request_compatible_pad (element, templ);
823     gst_object_unref (GST_OBJECT (templ));
824   }
825   
826   return foundpad;
827 }
828
829 /**
830  * gst_element_get_compatible_pad:
831  * @element: the element in which the pad should be found
832  * @pad: the pad to find a compatible one for
833  *
834  * Looks for an unconnected pad to which the given pad can connect to.
835  * It is not guaranteed that connecting the pads will work, though
836  * it should work in most cases.
837  *
838  * Returns: the pad to which a connection can be made
839  */
840 GstPad*                 
841 gst_element_get_compatible_pad (GstElement *element, GstPad *pad)
842 {
843   return gst_element_get_compatible_pad_filtered (element, pad, NULL);
844 }
845
846 /**
847  * gst_element_connect_elements_filtered:
848  * @src: the element containing source pad
849  * @dest: the element containing destination pad
850  * @filtercaps: the caps to use as filter
851  *
852  * Connect the source to the destination element using the filtercaps.
853  * The connection must be from source to destination, the other
854  * direction will not be tried.
855  * The functions looks for existing pads that aren't connected yet. 
856  + It will use request pads if possible. But both pads will not be requested.
857  * If multiple connections are possible, only one is established.
858  *
859  * Return: TRUE if the elements could be connected.
860  */
861 gboolean
862 gst_element_connect_elements_filtered (GstElement *src, GstElement *dest, 
863                                        GstCaps *filtercaps)
864 {
865   GList *srcpads, *destpads, *srctempls, *desttempls, *l;
866   GstPad *srcpad, *destpad;
867   GstPadTemplate *srctempl, *desttempl;
868
869   /* checks */
870   g_return_val_if_fail (src != NULL, FALSE);
871   g_return_val_if_fail (GST_IS_ELEMENT(src), FALSE);
872   g_return_val_if_fail (dest != NULL, FALSE);
873   g_return_val_if_fail (GST_IS_ELEMENT(dest), FALSE);
874
875   GST_DEBUG (GST_CAT_ELEMENT_PADS, "attempting to connect element %s to element %s\n", GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (dest));
876    
877   /* loop through the existing pads in the source */
878   srcpads = gst_element_get_pad_list (src);
879   destpads = gst_element_get_pad_list (dest);
880
881   if (srcpads || destpads) {
882     while (srcpads) {
883       srcpad = (GstPad *) GST_PAD_REALIZE (srcpads->data);
884       if ((GST_RPAD_DIRECTION (srcpad) == GST_PAD_SRC) &&
885           (GST_PAD_PEER (srcpad) == NULL)) {
886         destpad = gst_element_get_compatible_pad_filtered (dest, srcpad, filtercaps);
887         if (destpad && gst_pad_connect_filtered (srcpad, destpad, filtercaps)) {
888           GST_DEBUG (GST_CAT_ELEMENT_PADS, "connected pad %s:%s to pad %s:%s\n", GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad));
889           return TRUE;
890         }
891       }
892       srcpads = g_list_next (srcpads);
893     }
894     
895     /* loop through the existing pads in the destination */
896     while (destpads) {
897       destpad = (GstPad *) GST_PAD_REALIZE (destpads->data);
898       if ((GST_RPAD_DIRECTION (destpad) == GST_PAD_SINK) &&
899           (GST_PAD_PEER (destpad) == NULL)) {
900         srcpad = gst_element_get_compatible_pad_filtered (src, destpad, filtercaps);
901         if (srcpad && gst_pad_connect_filtered (srcpad, destpad, filtercaps)) {
902           GST_DEBUG (GST_CAT_ELEMENT_PADS, "connected pad %s:%s to pad %s:%s\n", GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad));
903           return TRUE;
904         }
905       }
906       destpads = g_list_next (destpads);
907     }
908   }
909
910   GST_DEBUG (GST_CAT_ELEMENT_PADS, "we might have request pads on both sides, checking...\n");
911   srctempls = gst_element_get_padtemplate_list (src);
912   desttempls = gst_element_get_padtemplate_list (dest);
913   
914   if (srctempls && desttempls) {
915     while (srctempls) {
916       srctempl = (GstPadTemplate*) srctempls->data;
917       if (srctempl->presence == GST_PAD_REQUEST) {
918         for (l=desttempls; l; l=l->next) {
919           desttempl = (GstPadTemplate*) desttempls->data;
920           if (desttempl->presence == GST_PAD_REQUEST && desttempl->direction != srctempl->direction) {
921             if (gst_caps_check_compatibility (gst_padtemplate_get_caps (srctempl),
922                                               gst_padtemplate_get_caps (desttempl))) {
923               srcpad = gst_element_request_pad_by_name (src, srctempl->name_template);
924               destpad = gst_element_request_pad_by_name (dest, desttempl->name_template);
925               if (gst_pad_connect_filtered (srcpad, destpad, filtercaps)) {
926                 GST_DEBUG (GST_CAT_ELEMENT_PADS, "connected pad %s:%s to pad %s:%s\n",
927                            GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad));
928                 return TRUE;
929               }
930               /* FIXME: we have extraneous request pads lying around */
931             }
932           }
933         }
934       }
935       srctempls = srctempls->next;
936     }
937   }
938   
939   GST_DEBUG (GST_CAT_ELEMENT_PADS, "no connection possible from %s to %s\n", GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (dest));
940   return FALSE;  
941 }
942
943 /**
944  * gst_element_connect_elements_many:
945  * @element_1: the first element in the connection chain
946  * @element_2: the second element in the connection chain
947  * @...: NULL-terminated list of elements to connect in order
948  * 
949  * Chain together a series of elements. Uses #gst_element_connect_elements.
950  *
951  * Returns: TRUE on success, FALSE otherwise.
952  **/
953 /* API FIXME: this should be called gst_element_connect_many, and connect_elements
954  * should just be connect */
955 gboolean
956 gst_element_connect_elements_many (GstElement *element_1, GstElement *element_2, ...)
957 {
958   va_list args;
959
960   g_return_val_if_fail (element_1 != NULL && element_2 != NULL, FALSE);
961   g_return_val_if_fail (GST_IS_ELEMENT (element_1) && GST_IS_ELEMENT (element_2), FALSE);
962
963   va_start (args, element_2);
964
965   while (element_2) {
966     if (!gst_element_connect_elements (element_1, element_2))
967       return FALSE;
968     
969     element_1 = element_2;
970     element_2 = va_arg (args, GstElement*);
971   }
972
973   va_end (args);
974   
975   return TRUE;
976 }
977
978 /**
979  * gst_element_connect_elements:
980  * @src: element containing source pad
981  * @dest: element containing destination pad
982  *
983  * Connect the source to the destination element.
984  * The connection must be from source to destination, the other
985  * direction will not be tried.
986  * The functions looks for existing pads and request pads that aren't
987  * connected yet. If multiple connections are possible, only one is
988  * established.
989  *
990  * Return: TRUE if the elements could be connected.
991  */
992 gboolean
993 gst_element_connect_elements (GstElement *src, GstElement *dest)
994 {
995   return gst_element_connect_elements_filtered (src, dest, NULL);
996 }
997
998 /**
999  * gst_element_connect_filtered:
1000  * @src: element containing source pad
1001  * @srcpadname: name of pad in source element
1002  * @dest: element containing destination pad
1003  * @destpadname: name of pad in destination element
1004  * @filtercaps: the caps to use as a filter
1005  *
1006  * Connect the two named pads of the source and destination elements.
1007  * Side effect is that if one of the pads has no parent, it becomes a
1008  * child of the parent of the other element.  If they have different
1009  * parents, the connection fails.
1010  *
1011  * Return: TRUE if the pads could be connected.
1012  */
1013 gboolean
1014 gst_element_connect_filtered (GstElement *src, const gchar *srcpadname,
1015                               GstElement *dest, const gchar *destpadname, 
1016                               GstCaps *filtercaps)
1017 {
1018   GstPad *srcpad,*destpad;
1019
1020   g_return_val_if_fail (src != NULL, FALSE);
1021   g_return_val_if_fail (GST_IS_ELEMENT(src), FALSE);
1022   g_return_val_if_fail (srcpadname != NULL, FALSE);
1023   g_return_val_if_fail (dest != NULL, FALSE);
1024   g_return_val_if_fail (GST_IS_ELEMENT(dest), FALSE);
1025   g_return_val_if_fail (destpadname != NULL, FALSE);
1026
1027   /* obtain the pads requested */
1028   srcpad = gst_element_get_pad (src, srcpadname);
1029   if (srcpad == NULL) {
1030     GST_ERROR (src, "source element has no pad \"%s\"", srcpadname);
1031     return FALSE;
1032   }
1033   destpad = gst_element_get_pad (dest, destpadname);
1034   if (srcpad == NULL) {
1035     GST_ERROR (dest, "destination element has no pad \"%s\"", destpadname);
1036     return FALSE;
1037   }
1038
1039   /* we're satisified they can be connected, let's do it */
1040   return gst_pad_connect_filtered (srcpad, destpad, filtercaps);
1041 }
1042
1043 /**
1044  * gst_element_connect:
1045  * @src: element containing source pad
1046  * @srcpadname: name of pad in source element
1047  * @dest: element containing destination pad
1048  * @destpadname: name of pad in destination element
1049  *
1050  * Connect the two named pads of the source and destination elements.
1051  * Side effect is that if one of the pads has no parent, it becomes a
1052  * child of the parent of the other element.  If they have different
1053  * parents, the connection fails.
1054  *
1055  * Return: TRUE if the pads could be connected.
1056  */
1057 gboolean
1058 gst_element_connect (GstElement *src, const gchar *srcpadname,
1059                      GstElement *dest, const gchar *destpadname)
1060 {
1061   return gst_element_connect_filtered (src, srcpadname, dest, destpadname, NULL);
1062 }
1063
1064 /**
1065  * gst_element_disconnect:
1066  * @src: element containing source pad
1067  * @srcpadname: name of pad in source element
1068  * @dest: element containing destination pad
1069  * @destpadname: name of pad in destination element
1070  *
1071  * Disconnect the two named pads of the source and destination elements.
1072  */
1073 void
1074 gst_element_disconnect (GstElement *src, const gchar *srcpadname,
1075                         GstElement *dest, const gchar *destpadname)
1076 {
1077   GstPad *srcpad,*destpad;
1078
1079   g_return_if_fail (src != NULL);
1080   g_return_if_fail (GST_IS_ELEMENT(src));
1081   g_return_if_fail (srcpadname != NULL);
1082   g_return_if_fail (dest != NULL);
1083   g_return_if_fail (GST_IS_ELEMENT(dest));
1084   g_return_if_fail (destpadname != NULL);
1085
1086   /* obtain the pads requested */
1087   srcpad = gst_element_get_pad (src, srcpadname);
1088   if (srcpad == NULL) {
1089     GST_ERROR(src,"source element has no pad \"%s\"",srcpadname);
1090     return;
1091   }
1092   destpad = gst_element_get_pad (dest, destpadname);
1093   if (srcpad == NULL) {
1094     GST_ERROR(dest,"destination element has no pad \"%s\"",destpadname);
1095     return;
1096   }
1097
1098   /* we're satisified they can be disconnected, let's do it */
1099   gst_pad_disconnect(srcpad,destpad);
1100 }
1101
1102 /**
1103  * gst_element_disconnect_elements:
1104  * @src: source element
1105  * @dest: sink element
1106  *
1107  * Disconnect all pads connecting the two elements in the direction src -> dest.
1108  */
1109 void
1110 gst_element_disconnect_elements (GstElement *src, GstElement *dest)
1111 {
1112   GList *srcpads;
1113   GstPad *pad;
1114
1115   g_return_if_fail (GST_IS_ELEMENT(src));
1116   g_return_if_fail (GST_IS_ELEMENT(dest));
1117
1118   srcpads = gst_element_get_pad_list (src);
1119
1120   while (srcpads) {
1121     pad = GST_PAD (srcpads->data);
1122     
1123     if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC)
1124       if (GST_OBJECT_PARENT (GST_PAD_PEER (pad)) == (GstObject*) dest)
1125         gst_pad_disconnect (pad, GST_PAD_PEER (pad));
1126
1127     srcpads = g_list_next (srcpads);
1128   }
1129 }
1130
1131 static void
1132 gst_element_error_func (GstElement* element, GstElement *source, gchar *errormsg)
1133 {
1134   /* tell the parent */
1135   if (GST_OBJECT_PARENT (element)) {
1136     GST_DEBUG (GST_CAT_EVENT, "forwarding error \"%s\" from %s to %s\n", errormsg, 
1137                GST_ELEMENT_NAME (element), GST_OBJECT_NAME (GST_OBJECT_PARENT (element)));
1138
1139     gst_object_ref (GST_OBJECT (element));
1140     g_signal_emit (G_OBJECT (GST_OBJECT_PARENT (element)), gst_element_signals[ERROR], 0, source, errormsg);
1141     gst_object_unref (GST_OBJECT (element));
1142   }
1143 }
1144 /**
1145  * gst_element_error:
1146  * @element: Element with the error
1147  * @error: A printf-like string describing the error
1148  * @...: optional arguments for the string 
1149  *
1150  * This function is used internally by elements to signal an error
1151  * condition.  It results in the "error" signal.
1152  */
1153 void
1154 gst_element_error (GstElement *element, const gchar *error, ...)
1155 {
1156   va_list var_args;
1157   gchar *string;
1158   
1159   /* checks */
1160   g_return_if_fail (GST_IS_ELEMENT (element));
1161   g_return_if_fail (element != NULL);
1162   g_return_if_fail (error != NULL);
1163
1164   /* create error message */
1165   va_start (var_args, error);
1166   string = g_strdup_vprintf (error, var_args);
1167   va_end (var_args);
1168   GST_INFO (GST_CAT_EVENT, "ERROR in %s: %s", GST_ELEMENT_NAME (element), string);
1169
1170   /* emit the signal, make sure the element stays available */
1171   gst_object_ref (GST_OBJECT (element));
1172   g_signal_emit (G_OBJECT (element), gst_element_signals[ERROR], 0, element, string);
1173   
1174  /* tell the scheduler */
1175   if (element->sched) {
1176     gst_scheduler_error (element->sched, element); 
1177   } 
1178
1179   /* cleanup */
1180   gst_object_unref (GST_OBJECT (element));
1181   g_free (string);
1182 }
1183
1184 /**
1185  * gst_element_info:
1186  * @element: Element with the info
1187  * @info: String describing the info
1188  * @...: arguments for the string.
1189  *
1190  * This function is used internally by elements to signal an info
1191  * condition.  It results in the "info" signal.
1192  */
1193 void
1194 gst_element_info (GstElement *element, const gchar *info, ...)
1195 {
1196   g_warning ("The function gst_element_info is gone. Use g_object_notify instead.");
1197 }
1198
1199
1200 /**
1201  * gst_element_send_event:
1202  * @element: Element generating the event
1203  * @event: the event to send
1204  *
1205  * This function is deprecated and doesn't work anymore.
1206  */
1207 void
1208 gst_element_send_event (GstElement *element, GstEvent *event)
1209 {
1210   g_warning ("The function gst_element_send_event is gone. Use g_object_notify instead.");
1211 }
1212
1213 /**
1214  * gst_element_get_state:
1215  * @element: element to get state of
1216  *
1217  * Gets the state of the element. 
1218  *
1219  * Returns: The element state
1220  */
1221 GstElementState
1222 gst_element_get_state (GstElement *element)
1223 {
1224   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_VOID_PENDING);
1225
1226   return GST_STATE (element);
1227 }
1228
1229 /**
1230  * gst_element_wait_state_change:
1231  * @element: element wait for
1232  *
1233  * Wait and block until the element changed its state.
1234  */
1235 void
1236 gst_element_wait_state_change (GstElement *element)
1237 {
1238   g_mutex_lock (element->state_mutex);
1239   g_cond_wait (element->state_cond, element->state_mutex);
1240   g_mutex_unlock (element->state_mutex);
1241 }
1242 /**
1243  * gst_element_set_state:
1244  * @element: element to change state of
1245  * @state: new element state
1246  *
1247  * Sets the state of the element. This function will only set
1248  * the elements pending state.
1249  *
1250  * Returns: whether or not the state was successfully set.
1251  */
1252 gint
1253 gst_element_set_state (GstElement *element, GstElementState state)
1254 {
1255   GstElementClass *oclass;
1256   GstElementState curpending;
1257   GstElementStateReturn return_val = GST_STATE_SUCCESS;
1258
1259   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
1260
1261   GST_DEBUG_ELEMENT (GST_CAT_STATES, element, "setting state from %s to %s\n",
1262                      gst_element_statename (GST_STATE (element)),
1263                      gst_element_statename (state));
1264
1265   /* start with the current state */
1266   curpending = GST_STATE(element);
1267
1268   /* loop until the final requested state is set */
1269   while (GST_STATE (element) != state && GST_STATE (element) != GST_STATE_VOID_PENDING) {
1270     /* move the curpending state in the correct direction */
1271     if (curpending < state) 
1272       curpending<<=1;
1273     else 
1274       curpending>>=1;
1275
1276     /* set the pending state variable */
1277     /* FIXME: should probably check to see that we don't already have one */
1278     GST_STATE_PENDING (element) = curpending;
1279
1280     if (curpending != state)
1281       GST_DEBUG_ELEMENT (GST_CAT_STATES, element, "intermediate: setting state to %s\n",
1282                          gst_element_statename (curpending));
1283
1284     /* call the state change function so it can set the state */
1285     oclass = CLASS (element);
1286     if (oclass->change_state)
1287       return_val = (oclass->change_state) (element);
1288
1289     switch (return_val) {
1290       case GST_STATE_FAILURE:
1291         GST_DEBUG_ELEMENT (GST_CAT_STATES, element, "have failed change_state return\n");
1292         return return_val;
1293       case GST_STATE_ASYNC:
1294         GST_DEBUG_ELEMENT (GST_CAT_STATES, element, "element will change state async\n");
1295         return return_val;
1296       default:
1297         /* Last thing we do is verify that a successful state change really
1298          * did change the state... */
1299         if (GST_STATE (element) != curpending) {
1300           GST_DEBUG_ELEMENT (GST_CAT_STATES, element, "element claimed state-change success, but state didn't change\n");
1301           return GST_STATE_FAILURE;
1302         }
1303         break;
1304     }
1305   }
1306
1307   return return_val;
1308 }
1309
1310 static gboolean
1311 gst_element_negotiate_pads (GstElement *element)
1312 {
1313   GList *pads = GST_ELEMENT_PADS (element);
1314
1315   GST_DEBUG_ELEMENT (GST_CAT_CAPS, element, "negotiating pads\n");
1316
1317   while (pads) {
1318     GstPad *pad = GST_PAD (pads->data);
1319     GstRealPad *srcpad;
1320
1321     pads = g_list_next (pads);
1322     
1323     if (!GST_IS_REAL_PAD (pad))
1324       continue;
1325
1326     srcpad = GST_PAD_REALIZE (pad);
1327
1328     /* if we have a connection on this pad and it doesn't have caps
1329      * allready, try to negotiate */
1330     if (GST_PAD_IS_CONNECTED (srcpad) && !GST_PAD_CAPS (srcpad)) {
1331       GstRealPad *sinkpad;
1332       GstElementState otherstate;
1333       GstElement *parent;
1334       
1335       sinkpad = GST_RPAD_PEER (GST_PAD_REALIZE (srcpad));
1336
1337       /* check the parent of the peer pad, if there is no parent do nothing */
1338       parent = GST_PAD_PARENT (sinkpad);
1339       if (!parent) 
1340         continue;
1341
1342       otherstate = GST_STATE (parent);
1343
1344       /* swap pads if needed */
1345       if (!GST_PAD_IS_SRC (srcpad)) {
1346         GstRealPad *temp;
1347
1348         temp = srcpad;
1349         srcpad = sinkpad;
1350         sinkpad = temp;
1351       }
1352
1353       /* only try to negotiate if the peer element is in PAUSED or higher too */
1354       if (otherstate >= GST_STATE_READY) {
1355         GST_DEBUG_ELEMENT (GST_CAT_CAPS, element, "perform negotiate for %s:%s and %s:%s\n",
1356                       GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
1357         if (!gst_pad_perform_negotiate (GST_PAD (srcpad), GST_PAD (sinkpad)))
1358           return FALSE;
1359       }
1360       else {
1361         GST_DEBUG_ELEMENT (GST_CAT_CAPS, element, "not negotiatiating %s:%s and %s:%s, not in READY yet\n",
1362                       GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
1363       }
1364     }
1365   }
1366
1367   return TRUE;
1368 }
1369
1370 static void
1371 gst_element_clear_pad_caps (GstElement *element)
1372 {
1373   GList *pads = GST_ELEMENT_PADS (element);
1374
1375   GST_DEBUG_ELEMENT (GST_CAT_CAPS, element, "clearing pad caps\n");
1376
1377   while (pads) {
1378     GstRealPad *pad = GST_PAD_REALIZE (pads->data);
1379
1380     if (GST_PAD_CAPS (pad)) {
1381       GST_PAD_CAPS (pad) = NULL;
1382     }
1383     pads = g_list_next (pads);
1384   }
1385 }
1386
1387 static GstElementStateReturn
1388 gst_element_change_state (GstElement *element)
1389 {
1390   GstElementState old_state;
1391   GstObject *parent;
1392   gint old_pending, old_transition;
1393
1394   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
1395
1396   old_state = GST_STATE (element);
1397   old_pending = GST_STATE_PENDING (element);
1398   old_transition = GST_STATE_TRANSITION (element);
1399
1400   if (old_pending == GST_STATE_VOID_PENDING || old_state == GST_STATE_PENDING (element)) {
1401     GST_INFO (GST_CAT_STATES, "no state change needed for element %s (VOID_PENDING)", GST_ELEMENT_NAME (element));
1402     return GST_STATE_SUCCESS;
1403   }
1404   
1405   GST_INFO (GST_CAT_STATES, "%s default handler sets state from %s to %s %d", GST_ELEMENT_NAME (element),
1406                      gst_element_statename (old_state),
1407                      gst_element_statename (old_pending),
1408                      GST_STATE_TRANSITION (element));
1409
1410   /* we set the state change early for the negotiation functions */
1411   GST_STATE (element) = old_pending;
1412   GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING;
1413
1414   /* if we are going to paused, we try to negotiate the pads */
1415   if (old_transition == GST_STATE_NULL_TO_READY) {
1416     if (!gst_element_negotiate_pads (element)) 
1417       goto failure;
1418   }
1419   /* going to the READY state clears all pad caps */
1420   else if (old_transition == GST_STATE_READY_TO_NULL) {
1421     gst_element_clear_pad_caps (element);
1422   }
1423
1424   /* tell the scheduler if we have one */
1425   if (element->sched) {
1426     if (gst_scheduler_state_transition (element->sched, element, old_transition) 
1427                     != GST_STATE_SUCCESS) {
1428       goto failure;
1429     }
1430   }
1431
1432   g_signal_emit (G_OBJECT (element), gst_element_signals[STATE_CHANGE],
1433                   0, old_state, GST_STATE (element));
1434
1435   parent = GST_ELEMENT_PARENT (element);
1436
1437   /* tell our parent about the state change */
1438   if (parent && GST_IS_BIN (parent)) {
1439     gst_bin_child_state_change (GST_BIN (parent), old_state, GST_STATE (element), element);
1440   }
1441
1442   /* signal the state change in case somebody is waiting for us */
1443   g_mutex_lock (element->state_mutex);
1444   g_cond_signal (element->state_cond);
1445   g_mutex_unlock (element->state_mutex);
1446
1447   return GST_STATE_SUCCESS;
1448
1449 failure:
1450   /* undo the state change */
1451   GST_STATE (element) = old_state;
1452   GST_STATE_PENDING (element) = old_pending;
1453
1454   return GST_STATE_FAILURE;
1455 }
1456
1457 /**
1458  * gst_element_get_factory:
1459  * @element: element to request the factory
1460  *
1461  * Retrieves the factory that was used to create this element
1462  *
1463  * Returns: the factory used for creating this element
1464  */
1465 GstElementFactory*
1466 gst_element_get_factory (GstElement *element)
1467 {
1468   GstElementClass *oclass;
1469
1470   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1471
1472   oclass = CLASS (element);
1473
1474   return oclass->elementfactory;
1475 }
1476
1477 static void
1478 gst_element_dispose (GObject *object)
1479 {
1480   GstElement *element = GST_ELEMENT (object);
1481   GList *pads;
1482   GstPad *pad;
1483   
1484   GST_DEBUG_ELEMENT (GST_CAT_REFCOUNTING, element, "dispose\n");
1485
1486   gst_element_set_state (element, GST_STATE_NULL);
1487
1488   /* first we break all our connections with the ouside */
1489   if (element->pads) {
1490     GList *orig;
1491     orig = pads = g_list_copy (element->pads);
1492     while (pads) {
1493       pad = GST_PAD (pads->data);
1494
1495       if (GST_PAD_PEER (pad)) {
1496         GST_DEBUG (GST_CAT_REFCOUNTING, "disconnecting pad '%s'\n",
1497                         GST_OBJECT_NAME (GST_OBJECT (GST_PAD (GST_PAD_PEER (pad)))));
1498         gst_pad_disconnect (pad, GST_PAD (GST_PAD_PEER (pad)));
1499       }
1500       gst_element_remove_pad (element, pad);
1501
1502       pads = g_list_next (pads);
1503     }
1504     g_list_free (orig);
1505     g_list_free (element->pads);
1506     element->pads = NULL;
1507   }
1508
1509   element->numsrcpads = 0;
1510   element->numsinkpads = 0;
1511   element->numpads = 0;
1512   g_mutex_free (element->state_mutex);
1513   g_cond_free (element->state_cond);
1514
1515   G_OBJECT_CLASS (parent_class)->dispose (object);
1516 }
1517
1518 #ifndef GST_DISABLE_LOADSAVE
1519 /**
1520  * gst_element_save_thyself:
1521  * @element: GstElement to save
1522  * @parent: the xml parent node
1523  *
1524  * Saves the element as part of the given XML structure
1525  *
1526  * Returns: the new xml node
1527  */
1528 static xmlNodePtr
1529 gst_element_save_thyself (GstObject *object,
1530                           xmlNodePtr parent)
1531 {
1532   GList *pads;
1533   GstElementClass *oclass;
1534   GParamSpec **specs, *spec;
1535   gint nspecs, i;
1536   GValue value = { 0, };
1537   GstElement *element;
1538
1539   g_return_val_if_fail (GST_IS_ELEMENT (object), parent);
1540
1541   element = GST_ELEMENT (object);
1542
1543   oclass = CLASS (element);
1544
1545   xmlNewChild(parent, NULL, "name", GST_ELEMENT_NAME(element));
1546
1547   if (oclass->elementfactory != NULL) {
1548     GstElementFactory *factory = (GstElementFactory *)oclass->elementfactory;
1549
1550     xmlNewChild (parent, NULL, "type", GST_OBJECT_NAME (factory));
1551     xmlNewChild (parent, NULL, "version", factory->details->version);
1552   }
1553
1554 /* FIXME: what is this? */  
1555 /*  if (element->manager) */
1556 /*    xmlNewChild(parent, NULL, "manager", GST_ELEMENT_NAME(element->manager)); */
1557
1558   /* params */
1559   specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (object), &nspecs);
1560   
1561   for (i=0; i<nspecs; i++) {
1562     spec = specs[i];
1563     if (spec->flags & G_PARAM_READABLE) {
1564       xmlNodePtr param;
1565       
1566       g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE (spec));
1567       
1568       g_object_get_property (G_OBJECT (element), spec->name, &value);
1569       param = xmlNewChild (parent, NULL, "param", NULL);
1570       xmlNewChild (param, NULL, "name", spec->name);
1571       
1572       if (G_IS_PARAM_SPEC_STRING (spec))
1573         xmlNewChild (param, NULL, "value", g_value_dup_string (&value));
1574       else if (G_IS_PARAM_SPEC_ENUM (spec))
1575         xmlNewChild (param, NULL, "value", g_strdup_printf ("%d", g_value_get_enum (&value)));
1576       else if (G_IS_PARAM_SPEC_INT64 (spec))
1577         xmlNewChild (param, NULL, "value", g_strdup_printf ("%lld", g_value_get_int64 (&value)));
1578       else
1579         xmlNewChild (param, NULL, "value", g_strdup_value_contents (&value));
1580       
1581       g_value_unset(&value);
1582     }
1583   }
1584
1585   pads = GST_ELEMENT_PADS (element);
1586
1587   while (pads) {
1588     GstPad *pad = GST_PAD (pads->data);
1589     /* figure out if it's a direct pad or a ghostpad */
1590     if (GST_ELEMENT (GST_OBJECT_PARENT (pad)) == element) {
1591       xmlNodePtr padtag = xmlNewChild (parent, NULL, "pad", NULL);
1592       gst_object_save_thyself (GST_OBJECT (pad), padtag);
1593     }
1594     pads = g_list_next (pads);
1595   }
1596
1597   return parent;
1598 }
1599
1600 static void
1601 gst_element_restore_thyself (GstObject *object, xmlNodePtr self)
1602 {
1603   xmlNodePtr children;
1604   GstElement *element;
1605   guchar *name = NULL;
1606   guchar *value = NULL;
1607
1608   element = GST_ELEMENT (object);
1609   g_return_if_fail (element != NULL);
1610
1611   /* parameters */
1612   children = self->xmlChildrenNode;
1613   while (children) {
1614     if (!strcmp (children->name, "param")) {
1615       xmlNodePtr child = children->xmlChildrenNode;
1616
1617       while (child) {
1618         if (!strcmp (child->name, "name")) {
1619           name = xmlNodeGetContent (child);
1620         }
1621         else if (!strcmp (child->name, "value")) {
1622           value = xmlNodeGetContent (child);
1623         }
1624         child = child->next;
1625       }
1626       /* FIXME: can this just be g_object_set ? */
1627       gst_util_set_object_arg ((GObject *)G_OBJECT (element), name, value);
1628     }
1629     children = children->next;
1630   }
1631   
1632   /* pads */
1633   children = self->xmlChildrenNode;
1634   while (children) {
1635     if (!strcmp (children->name, "pad")) {
1636       gst_pad_load_and_connect (children, GST_OBJECT (element));
1637     }
1638     children = children->next;
1639   }
1640
1641   if (GST_OBJECT_CLASS(parent_class)->restore_thyself)
1642     (GST_OBJECT_CLASS(parent_class)->restore_thyself) (object, self);
1643 }
1644 #endif /* GST_DISABLE_LOADSAVE */
1645
1646 /**
1647  * gst_element_yield:
1648  * @element: Element to yield
1649  *
1650  * Request a yield operation for the child. The scheduler will typically
1651  * give control to another element.
1652  */
1653 void
1654 gst_element_yield (GstElement *element)
1655 {
1656   if (GST_ELEMENT_SCHED (element)) {
1657     gst_scheduler_yield (GST_ELEMENT_SCHED (element), element);
1658   }
1659 }
1660
1661 /**
1662  * gst_element_interrupt:
1663  * @element: Element to interrupt
1664  *
1665  * Request the scheduler of this element to interrupt the execution of
1666  * this element and scheduler another one.
1667  *
1668  * Returns: a boolean indicating that the child should exit its chain/loop/get
1669  * function ASAP, depending on the scheduler implementation.
1670  */
1671 gboolean
1672 gst_element_interrupt (GstElement *element)
1673 {
1674   if (GST_ELEMENT_SCHED (element)) {
1675     return gst_scheduler_interrupt (GST_ELEMENT_SCHED (element), element);
1676   }
1677   else 
1678     return FALSE;
1679 }
1680
1681 /**
1682  * gst_element_set_sched:
1683  * @element: Element to set manager of.
1684  * @sched: @GstScheduler to set.
1685  *
1686  * Sets the scheduler of the element.  For internal use only, unless you're
1687  * writing a new bin subclass.
1688  */
1689 void
1690 gst_element_set_sched (GstElement *element,
1691                          GstScheduler *sched)
1692 {
1693   g_return_if_fail (GST_IS_ELEMENT (element));
1694   
1695   GST_INFO_ELEMENT (GST_CAT_PARENTAGE, element, "setting scheduler to %p", sched);
1696
1697   element->sched = sched;
1698 }
1699
1700 /**
1701  * gst_element_get_sched:
1702  * @element: Element to get manager of.
1703  *
1704  * Returns the scheduler of the element.
1705  *
1706  * Returns: Element's scheduler
1707  */
1708 GstScheduler*
1709 gst_element_get_sched (GstElement *element)
1710 {
1711   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1712
1713   return element->sched;
1714 }
1715
1716 /**
1717  * gst_element_set_loop_function:
1718  * @element: Element to set loop function of.
1719  * @loop: Pointer to loop function.
1720  *
1721  * This sets the loop function for the element.  The function pointed to
1722  * can deviate from the GstElementLoopFunction definition in type of
1723  * pointer only.
1724  *
1725  * NOTE: in order for this to take effect, the current loop function *must*
1726  * exit.  Assuming the loop function itself is the only one who will cause
1727  * a new loopfunc to be assigned, this should be no problem.
1728  */
1729 void
1730 gst_element_set_loop_function(GstElement *element,
1731                               GstElementLoopFunction loop)
1732 {
1733   g_return_if_fail (GST_IS_ELEMENT (element));
1734
1735   /* set the loop function */
1736   element->loopfunc = loop;
1737
1738   /* set the NEW_LOOPFUNC flag so everyone knows to go try again */
1739   GST_FLAG_SET (element, GST_ELEMENT_NEW_LOOPFUNC);
1740 }
1741
1742 /**
1743  * gst_element_set_eos:
1744  * @element: element to set to the EOS state
1745  *
1746  * Perform the actions needed to bring the element in the EOS state.
1747  */
1748 void
1749 gst_element_set_eos (GstElement *element)
1750 {
1751   g_return_if_fail (GST_IS_ELEMENT (element));
1752
1753   GST_DEBUG (GST_CAT_EVENT, "setting EOS on element %s\n", GST_OBJECT_NAME (element));
1754
1755   gst_element_set_state (element, GST_STATE_PAUSED);
1756
1757   g_signal_emit (G_OBJECT (element), gst_element_signals[EOS], 0);
1758 }
1759
1760
1761 /**
1762  * gst_element_statename:
1763  * @state: The state to get the name of
1764  *
1765  * Gets a string representing the given state.
1766  *
1767  * Returns: a string with the statename.
1768  */
1769 const gchar*
1770 gst_element_statename (GstElementState state) 
1771 {
1772   switch (state) {
1773 #ifdef GST_DEBUG_COLOR
1774     case GST_STATE_VOID_PENDING: return "NONE_PENDING";break;
1775     case GST_STATE_NULL: return "\033[01;37mNULL\033[00m";break;
1776     case GST_STATE_READY: return "\033[01;31mREADY\033[00m";break;
1777     case GST_STATE_PLAYING: return "\033[01;32mPLAYING\033[00m";break;
1778     case GST_STATE_PAUSED: return "\033[01;33mPAUSED\033[00m";break;
1779     default: return g_strdup_printf ("\033[01;37;41mUNKNOWN!\033[00m(%d)", state);
1780 #else
1781     case GST_STATE_VOID_PENDING: return "NONE_PENDING";break;
1782     case GST_STATE_NULL: return "NULL";break;
1783     case GST_STATE_READY: return "READY";break;
1784     case GST_STATE_PLAYING: return "PLAYING";break;
1785     case GST_STATE_PAUSED: return "PAUSED";break;
1786     default: return "UNKNOWN!";
1787 #endif
1788   }
1789   return "";
1790 }
1791
1792 static void
1793 gst_element_populate_std_props (GObjectClass * klass,
1794                                 const char *prop_name, guint arg_id, GParamFlags flags)
1795 {
1796   GQuark prop_id = g_quark_from_string (prop_name);
1797   GParamSpec *pspec;
1798
1799   static GQuark fd_id = 0;
1800   static GQuark blocksize_id;
1801   static GQuark bytesperread_id;
1802   static GQuark dump_id;
1803   static GQuark filesize_id;
1804   static GQuark mmapsize_id;
1805   static GQuark location_id;
1806   static GQuark offset_id;
1807   static GQuark silent_id;
1808   static GQuark touch_id;
1809
1810   if (!fd_id) {
1811     fd_id = g_quark_from_static_string ("fd");
1812     blocksize_id = g_quark_from_static_string ("blocksize");
1813     bytesperread_id = g_quark_from_static_string ("bytesperread");
1814     dump_id = g_quark_from_static_string ("dump");
1815     filesize_id = g_quark_from_static_string ("filesize");
1816     mmapsize_id = g_quark_from_static_string ("mmapsize");
1817     location_id = g_quark_from_static_string ("location");
1818     offset_id = g_quark_from_static_string ("offset");
1819     silent_id = g_quark_from_static_string ("silent");
1820     touch_id = g_quark_from_static_string ("touch");
1821   }
1822
1823   if (prop_id == fd_id) {
1824     pspec = g_param_spec_int ("fd", "File-descriptor",
1825                               "File-descriptor for the file being read",
1826                               0, G_MAXINT, 0, flags);
1827   }
1828   else if (prop_id == blocksize_id) {
1829     pspec = g_param_spec_ulong ("blocksize", "Block Size",
1830                                 "Block size to read per buffer",
1831                                 0, G_MAXULONG, 4096, flags);
1832
1833   }
1834   else if (prop_id == bytesperread_id) {
1835     pspec = g_param_spec_int ("bytesperread", "bytesperread",
1836                               "bytesperread",
1837                               G_MININT, G_MAXINT, 0, flags);
1838
1839   }
1840   else if (prop_id == dump_id) {
1841     pspec = g_param_spec_boolean ("dump", "dump", "dump", FALSE, flags);
1842
1843   }
1844   else if (prop_id == filesize_id) {
1845     pspec = g_param_spec_int64 ("filesize", "File Size",
1846                                 "Size of the file being read",
1847                                 0, G_MAXINT64, 0, flags);
1848
1849   }
1850   else if (prop_id == mmapsize_id) {
1851     pspec = g_param_spec_ulong ("mmapsize", "mmap() Block Size",
1852                                 "Size in bytes of mmap()d regions",
1853                                 0, G_MAXULONG, 4 * 1048576, flags);
1854
1855   }
1856   else if (prop_id == location_id) {
1857     pspec = g_param_spec_string ("location", "File Location",
1858                                  "Location of the file to read",
1859                                  NULL, flags);
1860
1861   }
1862   else if (prop_id == offset_id) {
1863     pspec = g_param_spec_int64 ("offset", "File Offset",
1864                                 "Byte offset of current read pointer",
1865                                 0, G_MAXINT64, 0, flags);
1866
1867   }
1868   else if (prop_id == silent_id) {
1869     pspec = g_param_spec_boolean ("silent", "silent", "silent",
1870                                   FALSE, flags);
1871
1872   }
1873   else if (prop_id == touch_id) {
1874     pspec = g_param_spec_boolean ("touch", "Touch read data",
1875                                   "Touch data to force disk read before "
1876                                   "push ()", TRUE, flags);
1877   }
1878   else {
1879     g_warning ("Unknown - 'standard' property '%s' id %d from klass %s",
1880                prop_name, arg_id, g_type_name (G_OBJECT_CLASS_TYPE (klass)));
1881     pspec = NULL;
1882   }
1883
1884   if (pspec) {
1885     g_object_class_install_property (klass, arg_id, pspec);
1886   }
1887 }
1888
1889 /**
1890  * gst_element_class_install_std_props:
1891  * @klass: the class to add the properties to
1892  * @first_name: the first in a NULL terminated
1893  * 'name', 'id', 'flags' triplet list.
1894  * @...: the triplet list
1895  * 
1896  * Add a list of standardized properties with types to the @klass.
1897  * the id is for the property switch in your get_prop method, and
1898  * the flags determine readability / writeability.
1899  **/
1900 void
1901 gst_element_class_install_std_props (GstElementClass * klass, const char *first_name, ...)
1902 {
1903   const char *name;
1904
1905   va_list args;
1906
1907   g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
1908
1909   va_start (args, first_name);
1910
1911   name = first_name;
1912
1913   while (name) {
1914     int arg_id = va_arg (args, int);
1915     int flags = va_arg (args, int);
1916
1917     gst_element_populate_std_props ((GObjectClass *) klass, name, arg_id, flags);
1918
1919     name = va_arg (args, char *);
1920   }
1921
1922   va_end (args);
1923 }
1924
1925 /**
1926  * gst_element_get_managing_bin:
1927  * @element: the element in question
1928  * 
1929  * Get the managing bin (a pipeline or a thread, for example) of an element.
1930  *
1931  * Returns: the bin, or NULL on failure
1932  **/
1933 GstBin*
1934 gst_element_get_managing_bin (GstElement *element)
1935 {
1936   GstBin *bin;
1937
1938   g_return_val_if_fail (element != NULL, NULL);
1939
1940   bin = GST_BIN (gst_object_get_parent (GST_OBJECT_CAST (element)));
1941
1942   while (bin && !GST_FLAG_IS_SET (GST_OBJECT_CAST (bin), GST_BIN_FLAG_MANAGER))
1943     bin = GST_BIN (gst_object_get_parent (GST_OBJECT_CAST (bin)));
1944   
1945   return bin;
1946 }