code cleanup and more debug output
[platform/upstream/gstreamer.git] / gst / gstpad.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2000 Wim Taymans <wtay@chello.be>
4  *
5  * gstpad.c: Pads for connecting elements together
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 "gst_private.h"
25
26 #include "gstpad.h"
27 #include "gstutils.h"
28 #include "gstelement.h"
29 #include "gsttype.h"
30 #include "gstbin.h"
31 #include "gstscheduler.h"
32 #include "gstevent.h"
33 #include "gstlog.h"
34
35 enum {
36   TEMPL_PAD_CREATED,
37   /* FILL ME */
38   TEMPL_LAST_SIGNAL
39 };
40
41 static GstObject *padtemplate_parent_class = NULL;
42 static guint gst_pad_template_signals[TEMPL_LAST_SIGNAL] = { 0 };
43
44 GType _gst_pad_type = 0;
45
46 /***** Start with the base GstPad class *****/
47 static void             gst_pad_class_init              (GstPadClass *klass);
48 static void             gst_pad_init                    (GstPad *pad);
49
50 static gboolean         gst_pad_try_reconnect_filtered_func (GstRealPad *srcpad, GstRealPad *sinkpad, 
51                                                          GstCaps *caps, gboolean clear);
52
53 #ifndef GST_DISABLE_LOADSAVE
54 static xmlNodePtr       gst_pad_save_thyself            (GstObject *object, xmlNodePtr parent);
55 #endif
56
57 static GstObject *pad_parent_class = NULL;
58
59 GType
60 gst_pad_get_type (void) 
61 {
62   if (!_gst_pad_type) {
63     static const GTypeInfo pad_info = {
64       sizeof (GstPadClass), NULL, NULL,
65       (GClassInitFunc) gst_pad_class_init, NULL, NULL,
66       sizeof (GstPad), 
67       32,
68       (GInstanceInitFunc) gst_pad_init, NULL
69     };
70     _gst_pad_type = g_type_register_static (GST_TYPE_OBJECT, "GstPad", 
71                                             &pad_info, 0);
72   }
73   return _gst_pad_type;
74 }
75
76 static void
77 gst_pad_class_init (GstPadClass *klass)
78 {
79   pad_parent_class = g_type_class_ref (GST_TYPE_OBJECT);
80 }
81
82 static void
83 gst_pad_init (GstPad *pad)
84 {
85   pad->element_private = NULL;
86
87   pad->padtemplate = NULL;
88 }
89
90
91
92 /***** Then do the Real Pad *****/
93 /* Pad signals and args */
94 enum {
95   REAL_SET_ACTIVE,
96   REAL_CAPS_CHANGED,
97   REAL_CAPS_NEGO_FAILED,
98   REAL_CONNECTED,
99   REAL_DISCONNECTED,
100   REAL_EVENT_RECEIVED,
101   /* FILL ME */
102   REAL_LAST_SIGNAL
103 };
104
105 enum {
106   REAL_ARG_0,
107   REAL_ARG_ACTIVE,
108   /* FILL ME */
109 };
110
111 static void     gst_real_pad_class_init         (GstRealPadClass *klass);
112 static void     gst_real_pad_init               (GstRealPad *pad);
113
114 static void     gst_real_pad_set_property       (GObject *object, guint prop_id,
115                                                  const GValue *value, 
116                                                  GParamSpec *pspec);
117 static void     gst_real_pad_get_property       (GObject *object, guint prop_id,
118                                                  GValue *value, 
119                                                  GParamSpec *pspec);
120
121 static void     gst_real_pad_dispose            (GObject *object);
122
123 static void     gst_pad_push_func               (GstPad *pad, GstBuffer *buf);
124
125 GType _gst_real_pad_type = 0;
126
127 static GstPad *real_pad_parent_class = NULL;
128 static guint gst_real_pad_signals[REAL_LAST_SIGNAL] = { 0 };
129
130 GType
131 gst_real_pad_get_type (void) {
132   if (!_gst_real_pad_type) {
133     static const GTypeInfo pad_info = {
134       sizeof (GstRealPadClass), NULL, NULL,
135       (GClassInitFunc) gst_real_pad_class_init, NULL, NULL,
136       sizeof (GstRealPad),
137       32,
138       (GInstanceInitFunc) gst_real_pad_init, NULL
139     };
140     _gst_real_pad_type = g_type_register_static (GST_TYPE_PAD, "GstRealPad", 
141                                                  &pad_info, 0);
142   }
143   return _gst_real_pad_type;
144 }
145
146 static void
147 gst_real_pad_class_init (GstRealPadClass *klass)
148 {
149   GObjectClass *gobject_class;
150   GstObjectClass *gstobject_class;
151
152   gobject_class = (GObjectClass*) klass;
153   gstobject_class = (GstObjectClass*) klass;
154
155   real_pad_parent_class = g_type_class_ref (GST_TYPE_PAD);
156
157   gobject_class->dispose  = GST_DEBUG_FUNCPTR (gst_real_pad_dispose);
158   gobject_class->set_property  = GST_DEBUG_FUNCPTR (gst_real_pad_set_property);
159   gobject_class->get_property  = GST_DEBUG_FUNCPTR (gst_real_pad_get_property);
160
161   gst_real_pad_signals[REAL_SET_ACTIVE] =
162     g_signal_new ("set_active", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
163                   G_STRUCT_OFFSET (GstRealPadClass, set_active), NULL, NULL,
164                   gst_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1,
165                   G_TYPE_BOOLEAN);
166   gst_real_pad_signals[REAL_CAPS_CHANGED] =
167     g_signal_new ("caps_changed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
168                   G_STRUCT_OFFSET (GstRealPadClass, caps_changed), NULL, NULL,
169                   gst_marshal_VOID__POINTER, G_TYPE_NONE, 1,
170                   G_TYPE_POINTER);
171   gst_real_pad_signals[REAL_CAPS_NEGO_FAILED] =
172     g_signal_new ("caps_nego_failed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
173                   G_STRUCT_OFFSET (GstRealPadClass, caps_nego_failed), NULL, NULL,
174                   gst_marshal_VOID__POINTER, G_TYPE_NONE, 1,
175                   G_TYPE_POINTER);
176   gst_real_pad_signals[REAL_CONNECTED] =
177     g_signal_new ("connected", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
178                   G_STRUCT_OFFSET (GstRealPadClass, connected), NULL, NULL,
179                   gst_marshal_VOID__POINTER, G_TYPE_NONE, 1,
180                   G_TYPE_POINTER);
181   gst_real_pad_signals[REAL_DISCONNECTED] =
182     g_signal_new ("disconnected", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
183                   G_STRUCT_OFFSET (GstRealPadClass, disconnected), NULL, NULL,
184                   gst_marshal_VOID__POINTER, G_TYPE_NONE, 1,
185                   G_TYPE_POINTER);
186   gst_real_pad_signals[REAL_EVENT_RECEIVED] =
187     g_signal_new ("event_received", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
188                   G_STRUCT_OFFSET (GstRealPadClass, event_received), NULL, NULL,
189                   gst_marshal_VOID__POINTER, G_TYPE_NONE, 1,
190                   G_TYPE_POINTER);
191
192 /*  gtk_object_add_arg_type ("GstRealPad::active", G_TYPE_BOOLEAN, */
193 /*                           GTK_ARG_READWRITE, REAL_ARG_ACTIVE); */
194   g_object_class_install_property (G_OBJECT_CLASS (klass), REAL_ARG_ACTIVE,
195     g_param_spec_boolean ("active", "Active", "Whether the pad is active.",
196                           TRUE, G_PARAM_READWRITE));
197
198 #ifndef GST_DISABLE_LOADSAVE
199   gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_pad_save_thyself);
200 #endif
201   gstobject_class->path_string_separator = ".";
202 }
203
204 static void
205 gst_real_pad_init (GstRealPad *pad)
206 {
207   pad->direction = GST_PAD_UNKNOWN;
208   pad->peer = NULL;
209
210   pad->chainfunc = NULL;
211   pad->getfunc = NULL;
212
213   pad->chainhandler = GST_DEBUG_FUNCPTR (gst_pad_push_func);
214   pad->gethandler = NULL;
215
216   pad->bufferpoolfunc = NULL;
217   pad->ghostpads = NULL;
218   pad->caps = NULL;
219
220   pad->connectfunc = NULL;
221   pad->getcapsfunc = NULL;
222
223   pad->convertfunc      = gst_pad_convert_default;
224   pad->eventfunc        = gst_pad_event_default;
225   pad->convertfunc      = gst_pad_convert_default;
226   pad->queryfunc        = gst_pad_query_default;
227   pad->intconnfunc      = gst_pad_get_internal_connections_default;
228
229   pad->eventmaskfunc    = gst_pad_get_event_masks_default;
230   pad->formatsfunc      = gst_pad_get_formats_default;
231   pad->querytypefunc    = gst_pad_get_query_types_default;
232 }
233
234 static void
235 gst_real_pad_set_property (GObject *object, guint prop_id, 
236                            const GValue *value, GParamSpec *pspec)
237 {
238   g_return_if_fail (GST_IS_PAD (object));
239
240   switch (prop_id) {
241     case REAL_ARG_ACTIVE:
242       gst_pad_set_active (GST_PAD (object), g_value_get_boolean (value));
243       break;
244     default:
245       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
246       break;
247   }
248 }
249
250 static void
251 gst_real_pad_get_property (GObject *object, guint prop_id, 
252                            GValue *value, GParamSpec *pspec)
253 {
254   g_return_if_fail (GST_IS_PAD (object));
255
256   switch (prop_id) {
257     case REAL_ARG_ACTIVE:
258       g_value_set_boolean (value, !GST_FLAG_IS_SET (object, GST_PAD_DISABLED));
259       break;
260     default:
261       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
262       break;
263   }
264 }
265
266
267 /**
268  * gst_pad_custom_new:
269  * @type: the #Gtype of the pad.
270  * @name: the name of the new pad.
271  * @direction: the #GstPadDirection of the pad.
272  *
273  * Creates a new pad with the given name and type in the given direction.
274  * If name is NULL, a guaranteed unique name (across all pads) 
275  * will be assigned.
276  *
277  * Returns: a new #GstPad, or NULL in case of an error.
278  */
279 GstPad*
280 gst_pad_custom_new (GType type, const gchar *name,
281                     GstPadDirection direction)
282 {
283   GstRealPad *pad;
284
285   g_return_val_if_fail (direction != GST_PAD_UNKNOWN, NULL);
286
287   pad = g_object_new (type, NULL);
288   gst_object_set_name (GST_OBJECT (pad), name);
289   GST_RPAD_DIRECTION (pad) = direction;
290
291   return GST_PAD (pad);
292 }
293
294 /**
295  * gst_pad_new:
296  * @name: the name of the new pad.
297  * @direction: the #GstPadDirection of the pad.
298  *
299  * Creates a new real pad with the given name in the given direction.
300  * If name is NULL, a guaranteed unique name (across all pads) 
301  * will be assigned.
302  *
303  * Returns: a new #GstPad, or NULL in case of an error.
304  */
305 GstPad*
306 gst_pad_new (const gchar *name,
307              GstPadDirection direction)
308 {
309   return gst_pad_custom_new (gst_real_pad_get_type (), name, direction);
310 }
311
312 /**
313  * gst_pad_custom_new_from_template:
314  * @type: the custom #GType of the pad.
315  * @templ: the #GstPadTemplate to instantiate from.
316  * @name: the name of the new pad.
317  *
318  * Creates a new custom pad with the given name from the given template.
319  * If name is NULL, a guaranteed unique name (across all pads) 
320  * will be assigned.
321  *
322  * Returns: a new #GstPad, or NULL in case of an error.
323  */
324 GstPad*
325 gst_pad_custom_new_from_template (GType type, GstPadTemplate *templ,
326                                   const gchar *name)
327 {
328   GstPad *pad;
329
330   g_return_val_if_fail (templ != NULL, NULL);
331
332   pad = gst_pad_new (name, templ->direction);
333   
334   gst_object_ref (GST_OBJECT (templ));
335   GST_PAD_PAD_TEMPLATE (pad) = templ;
336
337   g_signal_emit (G_OBJECT (templ), gst_pad_template_signals[TEMPL_PAD_CREATED], 0, pad);
338   
339   return pad;
340 }
341
342 /**
343  * gst_pad_new_from_template:
344  * @templ: the pad template to use
345  * @name: the name of the element
346  *
347  * Creates a new real pad with the given name from the given template.
348  * If name is NULL, a guaranteed unique name (across all pads) 
349  * will be assigned.
350  *
351  * Returns: a new #GstPad, or NULL in case of an error.
352  */
353 GstPad*
354 gst_pad_new_from_template (GstPadTemplate *templ, const gchar *name)
355 {
356   return gst_pad_custom_new_from_template (gst_real_pad_get_type (), 
357                                            templ, name);
358 }
359
360 /**
361  * gst_pad_get_direction:
362  * @pad: a #GstPad to get the direction of.
363  *
364  * Gets the direction of the pad.
365  *
366  * Returns: the #GstPadDirection of the pad.
367  */
368 GstPadDirection
369 gst_pad_get_direction (GstPad *pad)
370 {
371   g_return_val_if_fail (pad != NULL, GST_PAD_UNKNOWN);
372   g_return_val_if_fail (GST_IS_PAD (pad), GST_PAD_UNKNOWN);
373
374   return GST_PAD_DIRECTION (pad);
375 }
376
377 /**
378  * gst_pad_set_active:
379  * @pad: the #GstPad to activate or deactivate.
380  *
381  * Activates or deactivates the given pad.
382  */
383 void
384 gst_pad_set_active (GstPad *pad, gboolean active)
385 {
386   GstRealPad *realpad;
387
388   g_return_if_fail (pad != NULL);
389   g_return_if_fail (GST_IS_PAD (pad));
390
391   if (GST_PAD_IS_ACTIVE (pad) == active)
392     return;
393
394   realpad = GST_PAD_REALIZE (pad);
395
396   if (active) {
397     GST_DEBUG (GST_CAT_PADS, "activating pad %s:%s", 
398                GST_DEBUG_PAD_NAME (realpad));
399     GST_FLAG_UNSET (realpad, GST_PAD_DISABLED);
400   } else {
401     GST_DEBUG (GST_CAT_PADS, "de-activating pad %s:%s", 
402                GST_DEBUG_PAD_NAME (realpad));
403     GST_FLAG_SET (realpad, GST_PAD_DISABLED);
404   }
405   g_signal_emit (G_OBJECT (realpad), gst_real_pad_signals[REAL_SET_ACTIVE], 0,
406                  !GST_FLAG_IS_SET (realpad, GST_PAD_DISABLED));
407 }
408
409 /**
410  * gst_pad_set_name:
411  * @pad: a #GstPad to set the name of.
412  * @name: the name of the pad.
413  *
414  * Sets the name of a pad.  If name is NULL, then a guaranteed unique
415  * name will be assigned.
416  */
417 void
418 gst_pad_set_name (GstPad *pad, const gchar *name)
419 {
420   g_return_if_fail (pad != NULL);
421   g_return_if_fail (GST_IS_PAD (pad));
422
423   gst_object_set_name (GST_OBJECT (pad), name);
424 }
425
426 /**
427  * gst_pad_get_name:
428  * @pad: a #GstPad to get the name of.
429  *
430  * Gets the name of a pad.
431  *
432  * Returns: the name of the pad.  This is not a newly allocated pointer
433  * so you must not free it.
434  */
435 const gchar*
436 gst_pad_get_name (GstPad *pad)
437 {
438   g_return_val_if_fail (pad != NULL, NULL);
439   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
440
441   return GST_OBJECT_NAME (pad);
442 }
443
444 /**
445  * gst_pad_set_chain_function:
446  * @pad: a #GstPad to set the chain function for.
447  * @chain: the #GstPadChainFunction to set.
448  *
449  * Sets the given chain function for the pad.
450  */
451 void 
452 gst_pad_set_chain_function (GstPad *pad, GstPadChainFunction chain)
453 {
454   g_return_if_fail (pad != NULL);
455   g_return_if_fail (GST_IS_REAL_PAD (pad));
456
457   GST_RPAD_CHAINFUNC (pad) = chain;
458   GST_DEBUG (GST_CAT_PADS, "chainfunc for %s:%s set to %s",
459              GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (chain));
460 }
461
462 /**
463  * gst_pad_set_get_function:
464  * @pad: a #GstPad to set the get function for.
465  * @get: the #GstPadGetFunction to set.
466  *
467  * Sets the given get function for the pad.
468  */
469 void
470 gst_pad_set_get_function (GstPad *pad,
471                           GstPadGetFunction get)
472 {
473   g_return_if_fail (pad != NULL);
474   g_return_if_fail (GST_IS_REAL_PAD (pad));
475
476   GST_RPAD_GETFUNC (pad) = get;
477   
478   GST_DEBUG (GST_CAT_PADS, "getfunc for %s:%s  set to %s",
479              GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (get));
480 }
481
482 /**
483  * gst_pad_set_event_function:
484  * @pad: a #GstPad to set the event handler for.
485  * @event: the #GstPadEventFunction to set.
486  *
487  * Sets the given event handler for the pad.
488  */
489 void
490 gst_pad_set_event_function (GstPad *pad,
491                             GstPadEventFunction event)
492 {
493   g_return_if_fail (pad != NULL);
494   g_return_if_fail (GST_IS_REAL_PAD (pad));
495
496   GST_RPAD_EVENTFUNC (pad) = event;
497
498   GST_DEBUG (GST_CAT_PADS, "eventfunc for %s:%s  set to %s",
499              GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (event));
500 }
501
502 void
503 gst_pad_set_event_mask_function (GstPad *pad, 
504                                  GstPadEventMaskFunction mask_function)
505 {
506   g_return_if_fail (pad != NULL);
507   g_return_if_fail (GST_IS_REAL_PAD (pad));
508
509   GST_RPAD_EVENTMASKFUNC (pad) = mask_function;
510
511   GST_DEBUG (GST_CAT_PADS, "eventmaskfunc for %s:%s  set to %s",
512              GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (mask_function));
513 }
514
515 const GstEventMask*
516 gst_pad_get_event_masks (GstPad *pad)
517 {
518   GstRealPad *rpad;
519   
520   if (pad == NULL)
521     return FALSE;
522
523   rpad = GST_PAD_REALIZE (pad);
524
525   g_return_val_if_fail (rpad, FALSE);
526
527   if (GST_RPAD_EVENTMASKFUNC (rpad))
528     return GST_RPAD_EVENTMASKFUNC (rpad) (GST_PAD_CAST (pad));
529
530   return NULL;
531 }
532
533 static gboolean
534 gst_pad_get_event_masks_dispatcher (GstPad *pad, const GstFormat **data)
535 {
536   *data = gst_pad_get_formats (pad);
537
538   return TRUE;
539 }
540
541 const GstEventMask* 
542 gst_pad_get_event_masks_default (GstPad *pad)
543 {
544   GstEventMask *result = NULL;
545
546   gst_pad_dispatcher (pad, (GstPadDispatcherFunction) 
547                            gst_pad_get_event_masks_dispatcher, &result);
548
549   return result;
550 }
551
552 gboolean
553 gst_pad_handles_event (GstPad *pad, GstEventMask *mask)
554 {
555   const GstEventMask *masks;
556
557   g_return_val_if_fail (pad != NULL, FALSE);
558   g_return_val_if_fail (mask != NULL, FALSE);
559
560   masks = gst_pad_get_event_masks (pad);
561   if (!masks)
562     return FALSE;
563
564   while (masks->type) {
565     if (masks->type == mask->type &&
566         (masks->flags & mask->flags) == mask->flags)
567       return TRUE;
568
569     masks++;
570   }
571
572   return FALSE;
573 }
574
575 /**
576  * gst_pad_set_convert_function:
577  * @pad: a #GstPad to set the convert function for.
578  * @convert: the #GstPadConvertFunction to set.
579  *
580  * Sets the given convert function for the pad.
581  */
582 void
583 gst_pad_set_convert_function (GstPad *pad,
584                               GstPadConvertFunction convert)
585 {
586   g_return_if_fail (pad != NULL);
587   g_return_if_fail (GST_IS_REAL_PAD (pad));
588
589   GST_RPAD_CONVERTFUNC (pad) = convert;
590
591   GST_DEBUG (GST_CAT_PADS, "convertfunc for %s:%s  set to %s",
592              GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (convert));
593 }
594
595 /**
596  * gst_pad_set_query_function:
597  * @pad: the #GstPad to set the query function for.
598  * @query: the #GstPadQueryFunction to set.
599  *
600  * Set the given query function for the pad.
601  */
602 void
603 gst_pad_set_query_function (GstPad *pad, GstPadQueryFunction query)
604 {
605   g_return_if_fail (pad != NULL);
606   g_return_if_fail (GST_IS_REAL_PAD (pad));
607
608   GST_RPAD_QUERYFUNC (pad) = query;
609
610   GST_DEBUG (GST_CAT_PADS, "queryfunc for %s:%s  set to %s",
611              GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (query));
612 }
613
614 void
615 gst_pad_set_query_type_function (GstPad *pad, GstPadQueryTypeFunction type_func)
616 {
617   g_return_if_fail (pad != NULL);
618   g_return_if_fail (GST_IS_REAL_PAD (pad));
619
620   GST_RPAD_QUERYTYPEFUNC (pad) = type_func;
621
622   GST_DEBUG (GST_CAT_PADS, "querytypefunc for %s:%s  set to %s",
623              GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (type_func));
624 }
625
626 const GstPadQueryType*
627 gst_pad_get_query_types (GstPad *pad)
628 {
629   GstRealPad *rpad;
630   
631   if (pad == NULL)
632     return FALSE;
633
634   rpad = GST_PAD_REALIZE (pad);
635
636   g_return_val_if_fail (rpad, FALSE);
637
638   if (GST_RPAD_QUERYTYPEFUNC (rpad))
639     return GST_RPAD_QUERYTYPEFUNC (rpad) (GST_PAD_CAST (pad));
640
641   return NULL;
642 }
643
644 static gboolean
645 gst_pad_get_query_types_dispatcher (GstPad *pad, const GstPadQueryType **data)
646 {
647   *data = gst_pad_get_query_types (pad);
648
649   return TRUE;
650 }
651
652 const GstPadQueryType*
653 gst_pad_get_query_types_default (GstPad *pad)
654 {
655   GstPadQueryType *result = NULL;
656
657   gst_pad_dispatcher (pad, (GstPadDispatcherFunction) 
658                            gst_pad_get_query_types_dispatcher, &result);
659
660   return result;
661 }
662
663 /**
664  * gst_pad_set_internal_connection_function:
665  * @pad: a #GstPad to set the internal connection function for.
666  * @intconn: the #GstPadIntConnFunction to set.
667  *
668  * Sets the given internal connection function for the pad.
669  */
670 void
671 gst_pad_set_internal_connection_function (GstPad *pad, 
672                                           GstPadIntConnFunction intconn)
673 {
674   g_return_if_fail (pad != NULL);
675   g_return_if_fail (GST_IS_REAL_PAD (pad));
676
677   GST_RPAD_INTCONNFUNC (pad) = intconn;
678   GST_DEBUG (GST_CAT_PADS, "internal connection for %s:%s  set to %s",
679              GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (intconn));
680 }
681
682 /**
683  * gst_pad_set_formats_function:
684  * @pad: the #GstPad to set the formats function for.
685  * @formats: the #GstPadFormatsFunction to set.
686  *
687  * Sets the given formats function for the pad.
688  */
689 void
690 gst_pad_set_formats_function (GstPad *pad, GstPadFormatsFunction formats)
691 {
692   g_return_if_fail (pad != NULL);
693   g_return_if_fail (GST_IS_REAL_PAD (pad));
694
695   GST_RPAD_FORMATSFUNC (pad) = formats;
696   GST_DEBUG (GST_CAT_PADS, "formats function for %s:%s  set to %s",
697              GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (formats));
698 }
699
700 /**
701  * gst_pad_set_connect_function:
702  * @pad: a #GstPad to set the connect function for.
703  * @connect: the #GstPadConnectFunction to set.
704  *
705  * Sets the given connect function for the pad. It will be called
706  * when the pad is connected or reconnected with caps.
707  */
708 void
709 gst_pad_set_connect_function (GstPad *pad,
710                               GstPadConnectFunction connect)
711 {
712   g_return_if_fail (pad != NULL);
713   g_return_if_fail (GST_IS_REAL_PAD (pad));
714
715   GST_RPAD_CONNECTFUNC (pad) = connect;
716   GST_DEBUG (GST_CAT_PADS, "connectfunc for %s:%s set to %s",
717              GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (connect));
718 }
719
720 /**
721  * gst_pad_set_getcaps_function:
722  * @pad: a #GstPad to set the getcaps function for.
723  * @getcaps: the #GstPadGetCapsFunction to set.
724  *
725  * Sets the given getcaps function for the pad.
726  */
727 void
728 gst_pad_set_getcaps_function (GstPad *pad,
729                               GstPadGetCapsFunction getcaps)
730 {
731   g_return_if_fail (pad != NULL);
732   g_return_if_fail (GST_IS_REAL_PAD (pad));
733
734   GST_RPAD_GETCAPSFUNC (pad) = getcaps;
735   GST_DEBUG (GST_CAT_PADS, "getcapsfunc for %s:%s set to %s",
736              GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (getcaps));
737 }
738 /**
739  * gst_pad_set_bufferpool_function:
740  * @pad: a #GstPad to set the bufferpool function for.
741  * @bufpool: the #GstPadBufferPoolFunction to set.
742  *
743  * Sets the given bufferpool function for the pad.
744  */
745 void
746 gst_pad_set_bufferpool_function (GstPad *pad,
747                                  GstPadBufferPoolFunction bufpool)
748 {
749   g_return_if_fail (pad != NULL);
750   g_return_if_fail (GST_IS_REAL_PAD (pad));
751
752   GST_RPAD_BUFFERPOOLFUNC (pad) = bufpool;
753   GST_DEBUG (GST_CAT_PADS, "bufferpoolfunc for %s:%s set to %s",
754              GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (bufpool));
755 }
756
757 static void
758 gst_pad_push_func (GstPad *pad, GstBuffer *buf)
759 {
760   if (GST_RPAD_CHAINFUNC (GST_RPAD_PEER (pad)) != NULL) {
761     GST_DEBUG (GST_CAT_DATAFLOW, "calling chain function %s",
762                GST_DEBUG_FUNCPTR_NAME (GST_RPAD_CHAINFUNC (GST_RPAD_PEER (pad))));
763     (GST_RPAD_CHAINFUNC (GST_RPAD_PEER (pad))) (pad, buf);
764   } else {
765     GST_DEBUG (GST_CAT_DATAFLOW, 
766                "default pad_push handler in place, no chain function");
767     g_warning ("(internal error) default pad_push in place for pad %s:%s"
768                "but it has no chain function", GST_DEBUG_PAD_NAME (pad));
769   }
770 }
771
772
773 /**
774  * gst_pad_disconnect:
775  * @srcpad: the source #GstPad to disconnect.
776  * @sinkpad: the sink #GstPad to disconnect.
777  *
778  * Disconnects the source pad from the sink pad.
779  */
780 void
781 gst_pad_disconnect (GstPad *srcpad,
782                     GstPad *sinkpad)
783 {
784   GstRealPad *realsrc, *realsink;
785   GstScheduler *src_sched, *sink_sched;
786
787   /* generic checks */
788   g_return_if_fail (srcpad != NULL);
789   g_return_if_fail (GST_IS_PAD (srcpad));
790   g_return_if_fail (sinkpad != NULL);
791   g_return_if_fail (GST_IS_PAD (sinkpad));
792
793   GST_INFO (GST_CAT_ELEMENT_PADS, "disconnecting %s:%s(%p) and %s:%s(%p)",
794             GST_DEBUG_PAD_NAME (srcpad), srcpad, 
795             GST_DEBUG_PAD_NAME (sinkpad), sinkpad);
796
797   /* now we need to deal with the real/ghost stuff */
798   realsrc = GST_PAD_REALIZE (srcpad);
799   realsink = GST_PAD_REALIZE (sinkpad);
800
801   g_return_if_fail (GST_RPAD_PEER (realsrc) != NULL);
802   g_return_if_fail (GST_RPAD_PEER (realsink) == realsrc);
803
804   if ((GST_RPAD_DIRECTION (realsrc) == GST_PAD_SINK) &&
805       (GST_RPAD_DIRECTION (realsink) == GST_PAD_SRC)) {
806     GstRealPad *temppad;
807
808     temppad = realsrc;
809     realsrc = realsink;
810     realsink = temppad;
811   }
812   g_return_if_fail ((GST_RPAD_DIRECTION (realsrc) == GST_PAD_SRC) &&
813                     (GST_RPAD_DIRECTION (realsink) == GST_PAD_SINK));
814
815   /* get the schedulers before we disconnect */
816   src_sched = gst_pad_get_scheduler (GST_PAD_CAST (realsrc));
817   sink_sched = gst_pad_get_scheduler (GST_PAD_CAST (realsink));
818
819   /* first clear peers */
820   GST_RPAD_PEER (realsrc) = NULL;
821   GST_RPAD_PEER (realsink) = NULL;
822
823   /* reset the filters, both filters are refcounted once */
824   if (GST_RPAD_FILTER (realsrc)) {
825     gst_caps_unref (GST_RPAD_FILTER (realsrc));
826     GST_RPAD_FILTER (realsink) = NULL;
827     GST_RPAD_FILTER (realsrc) = NULL;
828   }
829
830   /* now tell the scheduler */
831   if (src_sched) 
832     gst_scheduler_pad_disconnect (src_sched, 
833                                   GST_PAD_CAST (realsrc), GST_PAD_CAST (realsink));
834   else if (sink_sched)
835     gst_scheduler_pad_disconnect (sink_sched, 
836                                   GST_PAD_CAST (realsrc), GST_PAD_CAST (realsink));
837
838   /* hold a reference, as they can go away in the signal handlers */
839   gst_object_ref (GST_OBJECT (realsrc));
840   gst_object_ref (GST_OBJECT (realsink));
841
842   /* fire off a signal to each of the pads telling them 
843    * that they've been disconnected */
844   g_signal_emit (G_OBJECT (realsrc), gst_real_pad_signals[REAL_DISCONNECTED], 
845                  0, realsink);
846   g_signal_emit (G_OBJECT (realsink), gst_real_pad_signals[REAL_DISCONNECTED], 
847                  0, realsrc);
848
849   GST_INFO (GST_CAT_ELEMENT_PADS, "disconnected %s:%s and %s:%s",
850             GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
851
852   gst_object_unref (GST_OBJECT (realsrc));
853   gst_object_unref (GST_OBJECT (realsink));
854 }
855
856 static gboolean
857 gst_pad_check_schedulers (GstRealPad *realsrc, GstRealPad *realsink)
858 {
859   GstScheduler *src_sched, *sink_sched;
860   gint num_decoupled = 0;
861
862   src_sched = gst_pad_get_scheduler (GST_PAD_CAST (realsrc));
863   sink_sched = gst_pad_get_scheduler (GST_PAD_CAST (realsink));
864   
865   if (src_sched && sink_sched) {
866     if (GST_FLAG_IS_SET (GST_PAD_PARENT (realsrc), GST_ELEMENT_DECOUPLED))
867       num_decoupled++;
868     if (GST_FLAG_IS_SET (GST_PAD_PARENT (realsink), GST_ELEMENT_DECOUPLED))
869       num_decoupled++;
870
871     if (src_sched != sink_sched && num_decoupled != 1) {
872       return FALSE;
873     }
874   }
875   return TRUE;
876 }
877
878 /**
879  * gst_pad_can_connect_filtered:
880  * @srcpad: the source #GstPad to connect.
881  * @sinkpad: the sink #GstPad to connect.
882  * @filtercaps: the filter #GstCaps.
883  *
884  * Checks if the source pad and the sink pad can be connected when constrained
885  * by the given filter caps. 
886  *
887  * Returns: TRUE if the pads can be connected, FALSE otherwise.
888  */
889 gboolean
890 gst_pad_can_connect_filtered (GstPad *srcpad, GstPad *sinkpad, 
891                               GstCaps *filtercaps)
892 {
893   GstRealPad *realsrc, *realsink;
894
895   /* generic checks */
896   g_return_val_if_fail (srcpad != NULL, FALSE);
897   g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE);
898   g_return_val_if_fail (sinkpad != NULL, FALSE);
899   g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE);
900
901   /* now we need to deal with the real/ghost stuff */
902   realsrc = GST_PAD_REALIZE (srcpad);
903   realsink = GST_PAD_REALIZE (sinkpad);
904
905   g_return_val_if_fail (GST_RPAD_PEER (realsrc) == NULL, FALSE);
906   g_return_val_if_fail (GST_RPAD_PEER (realsink) == NULL, FALSE);
907   g_return_val_if_fail (GST_PAD_PARENT (realsrc) != NULL, FALSE);
908   g_return_val_if_fail (GST_PAD_PARENT (realsink) != NULL, FALSE);
909
910   if (!gst_pad_check_schedulers (realsrc, realsink)) {
911     g_warning ("connecting pads with different scheds requires "
912                "exactly one decoupled element (queue)");
913     return FALSE;
914   }
915   
916   /* check if the directions are compatible */
917   if (!(((GST_RPAD_DIRECTION (realsrc) == GST_PAD_SINK) &&
918          (GST_RPAD_DIRECTION (realsink) == GST_PAD_SRC)) ||
919         ((GST_RPAD_DIRECTION (realsrc) == GST_PAD_SRC) &&
920          (GST_RPAD_DIRECTION (realsink) == GST_PAD_SINK))))
921     return FALSE;
922   
923   return TRUE;
924 }
925 /**
926  * gst_pad_can_connect:
927  * @srcpad: the source #GstPad to connect.
928  * @sinkpad: the sink #GstPad to connect.
929  *
930  * Checks if the source pad and the sink pad can be connected.
931  *
932  * Returns: TRUE if the pads can be connected, FALSE otherwise.
933  */
934 gboolean
935 gst_pad_can_connect (GstPad *srcpad, GstPad *sinkpad)
936 {
937   return gst_pad_can_connect_filtered (srcpad, sinkpad, NULL);
938 }
939
940 /**
941  * gst_pad_connect_filtered:
942  * @srcpad: the source #GstPad to connect.
943  * @sinkpad: the sink #GstPad to connect.
944  * @filtercaps: the filter #GstCaps.
945  *
946  * Connects the source pad and the sink pad can be connected, constrained
947  * by the given filter caps. 
948  *
949  * Returns: TRUE if the pads have been connected, FALSE otherwise.
950  */
951 gboolean
952 gst_pad_connect_filtered (GstPad *srcpad, GstPad *sinkpad, GstCaps *filtercaps)
953 {
954   GstRealPad *realsrc, *realsink;
955   GstScheduler *src_sched, *sink_sched;
956
957   /* generic checks */
958   g_return_val_if_fail (srcpad != NULL, FALSE);
959   g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE);
960   g_return_val_if_fail (sinkpad != NULL, FALSE);
961   g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE);
962
963   GST_INFO (GST_CAT_PADS, "trying to connect %s:%s and %s:%s",
964             GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
965
966   /* now we need to deal with the real/ghost stuff */
967   realsrc = GST_PAD_REALIZE (srcpad);
968   realsink = GST_PAD_REALIZE (sinkpad);
969
970   if ((GST_PAD (realsrc) != srcpad) || (GST_PAD (realsink) != sinkpad)) {
971     GST_INFO (GST_CAT_PADS, "*actually* connecting %s:%s and %s:%s",
972               GST_DEBUG_PAD_NAME (realsrc), GST_DEBUG_PAD_NAME (realsink));
973   }
974   if (GST_RPAD_PEER (realsrc) != NULL)
975   {
976     GST_INFO (GST_CAT_PADS, "Real source pad %s:%s has a peer, failed",
977               GST_DEBUG_PAD_NAME (realsrc));
978     return FALSE;
979   }
980   if (GST_RPAD_PEER (realsink) != NULL)
981   {
982     GST_INFO (GST_CAT_PADS, "Real sink pad %s:%s has a peer, failed",
983               GST_DEBUG_PAD_NAME (realsink));
984     return FALSE;
985   }
986   if (GST_PAD_PARENT (realsrc) == NULL)
987   {
988     GST_INFO (GST_CAT_PADS, "Real src pad %s:%s has no parent, failed",
989               GST_DEBUG_PAD_NAME (realsrc));
990     return FALSE;
991   }
992   if (GST_PAD_PARENT (realsink) == NULL)
993   {
994     GST_INFO (GST_CAT_PADS, "Real src pad %s:%s has no parent, failed",
995               GST_DEBUG_PAD_NAME (realsrc));
996     return FALSE;
997   }
998
999   if (!gst_pad_check_schedulers (realsrc, realsink)) {
1000     g_warning ("connecting pads with different scheds requires "
1001                "exactly one decoupled element (such as queue)");
1002     return FALSE;
1003   }
1004   
1005   /* check for reversed directions and swap if necessary */
1006   if ((GST_RPAD_DIRECTION (realsrc) == GST_PAD_SINK) &&
1007       (GST_RPAD_DIRECTION (realsink) == GST_PAD_SRC)) {
1008     GstRealPad *temppad;
1009
1010     temppad = realsrc;
1011     realsrc = realsink;
1012     realsink = temppad;
1013   }
1014   if (GST_PAD_PARENT (realsink) == NULL)
1015   if (GST_RPAD_DIRECTION (realsrc) != GST_PAD_SRC)
1016   {
1017     GST_INFO (GST_CAT_PADS, "Real src pad %s:%s is not a source pad, failed",
1018               GST_DEBUG_PAD_NAME (realsrc));
1019     return FALSE;
1020   }    
1021   if (GST_RPAD_DIRECTION (realsink) != GST_PAD_SINK)
1022   {
1023     GST_INFO (GST_CAT_PADS, "Real sink pad %s:%s is not a sink pad, failed",
1024               GST_DEBUG_PAD_NAME (realsink));
1025     return FALSE;
1026   }    
1027   /* first set peers */
1028   GST_RPAD_PEER (realsrc) = realsink;
1029   GST_RPAD_PEER (realsink) = realsrc;
1030
1031   /* try to negotiate the pads, we don't need to clear the caps here */
1032   if (!gst_pad_try_reconnect_filtered_func (realsrc, realsink, 
1033                                             filtercaps, FALSE)) {
1034     GST_DEBUG (GST_CAT_CAPS, "reconnect_filtered_func failed, can't connect");
1035
1036     GST_RPAD_PEER (realsrc) = NULL;
1037     GST_RPAD_PEER (realsink) = NULL;
1038
1039     return FALSE;
1040   }
1041
1042   /* fire off a signal to each of the pads telling them 
1043    * that they've been connected */
1044   g_signal_emit (G_OBJECT (realsrc), gst_real_pad_signals[REAL_CONNECTED], 
1045                  0, realsink);
1046   g_signal_emit (G_OBJECT (realsink), gst_real_pad_signals[REAL_CONNECTED], 
1047                  0, realsrc);
1048
1049   src_sched = gst_pad_get_scheduler (GST_PAD_CAST (realsrc));
1050   sink_sched = gst_pad_get_scheduler (GST_PAD_CAST (realsink));
1051
1052   /* now tell the scheduler */
1053   if (src_sched) 
1054     gst_scheduler_pad_connect (src_sched, 
1055                                GST_PAD_CAST (realsrc), GST_PAD_CAST (realsink));
1056   else if (sink_sched)
1057     gst_scheduler_pad_connect (sink_sched, 
1058                                GST_PAD_CAST (realsrc), GST_PAD_CAST (realsink));
1059
1060   GST_INFO (GST_CAT_PADS, "connected %s:%s and %s:%s, successful",
1061             GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
1062   gst_caps_debug (gst_pad_get_caps (GST_PAD_CAST (realsrc)), 
1063                   "caps of newly connected src pad");
1064
1065   return TRUE;
1066 }
1067
1068 /**
1069  * gst_pad_connect:
1070  * @srcpad: the source #GstPad to connect.
1071  * @sinkpad: the sink #GstPad to connect.
1072  *
1073  * Connects the source pad to the sink pad.
1074  *
1075  * Returns: TRUE if the pad could be connected, FALSE otherwise.
1076  */
1077 gboolean
1078 gst_pad_connect (GstPad *srcpad, GstPad *sinkpad)
1079 {
1080   return gst_pad_connect_filtered (srcpad, sinkpad, NULL);
1081 }
1082
1083 /**
1084  * gst_pad_set_parent:
1085  * @pad: a #GstPad to set the parent of.
1086  * @parent: the new parent #GstElement.
1087  *
1088  * Sets the parent object of a pad.
1089  */
1090 void
1091 gst_pad_set_parent (GstPad *pad, GstElement *parent)
1092 {
1093   g_return_if_fail (pad != NULL);
1094   g_return_if_fail (GST_IS_PAD (pad));
1095   g_return_if_fail (GST_PAD_PARENT (pad) == NULL);
1096   g_return_if_fail (parent != NULL);
1097   g_return_if_fail (GST_IS_OBJECT (parent));
1098   g_return_if_fail ((gpointer) pad != (gpointer) parent);
1099
1100   gst_object_set_parent (GST_OBJECT (pad), GST_OBJECT (parent));
1101 }
1102
1103 /**
1104  * gst_pad_get_parent:
1105  * @pad: the #GstPad to get the parent of.
1106  *
1107  * Gets the parent object of this pad.
1108  *
1109  * Returns: the parent #GstElement.
1110  */
1111 GstElement*
1112 gst_pad_get_parent (GstPad *pad)
1113 {
1114   g_return_val_if_fail (pad != NULL, NULL);
1115   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
1116
1117   return GST_PAD_PARENT (pad);
1118 }
1119
1120 /**
1121  * gst_pad_get_pad_template:
1122  * @pad: a #GstPad to get the pad template of.
1123  *
1124  * Gets the pad template object of this pad.
1125  *
1126  * Returns: the #GstPadTemplate from which this pad was instantiated.
1127  */
1128 GstPadTemplate*
1129 gst_pad_get_pad_template (GstPad *pad)
1130 {
1131   g_return_val_if_fail (pad != NULL, NULL);
1132   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
1133
1134   return GST_PAD_PAD_TEMPLATE (pad); 
1135 }
1136
1137
1138 /**
1139  * gst_pad_get_scheduler:
1140  * @pad: a #GstPad to get the scheduler of.
1141  *
1142  * Gets the scheduler of the pad.
1143  *
1144  * Returns: the #GstScheduler of the pad.
1145  */
1146 GstScheduler*
1147 gst_pad_get_scheduler (GstPad *pad)
1148 {
1149   GstScheduler *scheduler = NULL;
1150   GstElement *parent;
1151   
1152   g_return_val_if_fail (pad != NULL, NULL);
1153   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
1154   
1155   parent = gst_pad_get_parent (pad);
1156   if (parent) {
1157     if (GST_FLAG_IS_SET (parent, GST_ELEMENT_DECOUPLED)) {
1158       GstRealPad *peer = GST_RPAD_PEER (pad);
1159
1160       if (peer) {
1161         scheduler = gst_element_get_scheduler (gst_pad_get_parent (GST_PAD_CAST (peer)));
1162       }
1163     }
1164     else {
1165       scheduler = gst_element_get_scheduler (parent);
1166     }
1167   }
1168  
1169   return scheduler;
1170 }
1171
1172 /**
1173  * gst_pad_get_real_parent:
1174  * @pad: a #GstPad to get the real parent of.
1175  *
1176  * Gets the real parent object of this pad. If the pad
1177  * is a ghost pad, the actual owner of the real pad is
1178  * returned, as opposed to #gst_pad_get_parent().
1179  *
1180  * Returns: the parent #GstElement.
1181  */
1182 GstElement*
1183 gst_pad_get_real_parent (GstPad *pad)
1184 {
1185   g_return_val_if_fail (pad != NULL, NULL);
1186   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
1187
1188   return GST_PAD_PARENT (GST_PAD (GST_PAD_REALIZE (pad)));
1189 }
1190
1191 /**
1192  * gst_pad_add_ghost_pad:
1193  * @pad: a #GstPad to attach the ghost pad to.
1194  * @ghostpad: the ghost #GstPad to to the pad.
1195  *
1196  * Adds a ghost pad to a pad.
1197  */
1198 void
1199 gst_pad_add_ghost_pad (GstPad *pad,
1200                        GstPad *ghostpad)
1201 {
1202   GstRealPad *realpad;
1203
1204   g_return_if_fail (pad != NULL);
1205   g_return_if_fail (GST_IS_PAD (pad));
1206   g_return_if_fail (ghostpad != NULL);
1207   g_return_if_fail (GST_IS_GHOST_PAD (ghostpad));
1208
1209   realpad = GST_PAD_REALIZE (pad);
1210
1211   realpad->ghostpads = g_list_prepend (realpad->ghostpads, ghostpad);
1212 }
1213
1214
1215 /**
1216  * gst_pad_remove_ghost_pad:
1217  * @pad: a #GstPad to remove the ghost pad from.
1218  * @ghostpad: the ghost #GstPad to remove from the pad.
1219  *
1220  * Removes a ghost pad from a pad.
1221  */
1222 void
1223 gst_pad_remove_ghost_pad (GstPad *pad,
1224                           GstPad *ghostpad)
1225 {
1226   GstRealPad *realpad;
1227
1228   g_return_if_fail (pad != NULL);
1229   g_return_if_fail (GST_IS_PAD (pad));
1230   g_return_if_fail (ghostpad != NULL);
1231   g_return_if_fail (GST_IS_GHOST_PAD (ghostpad));
1232
1233   realpad = GST_PAD_REALIZE (pad);
1234
1235   realpad->ghostpads = g_list_remove (realpad->ghostpads, ghostpad);
1236 }
1237
1238 /**
1239  * gst_pad_get_ghost_pad_list:
1240  * @pad: a #GstPad to get the ghost pads of.
1241  *
1242  * Gets the ghost pads of this pad.
1243  *
1244  * Returns: a #GList of ghost pads.
1245  */
1246 GList*
1247 gst_pad_get_ghost_pad_list (GstPad *pad)
1248 {
1249   g_return_val_if_fail (pad != NULL, NULL);
1250   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
1251
1252   return GST_PAD_REALIZE(pad)->ghostpads;
1253 }
1254
1255 /* an internal caps negotiation helper function:
1256  * 
1257  * 1. optionally calls the pad connect function with the provided caps
1258  * 2. deals with the result code of the connect function
1259  * 3. sets fixed caps on the pad.
1260  */
1261 static GstPadConnectReturn
1262 gst_pad_try_set_caps_func (GstRealPad *pad, GstCaps *caps, gboolean notify)
1263 {
1264   GstCaps *oldcaps;
1265   GstPadTemplate *template;
1266   GstElement *parent = GST_PAD_PARENT (pad);
1267
1268   g_return_val_if_fail (pad != NULL, GST_PAD_CONNECT_REFUSED);
1269   g_return_val_if_fail (GST_IS_PAD (pad), GST_PAD_CONNECT_REFUSED);
1270   
1271   /* if this pad has a parent and the parent is not READY, delay the
1272    * negotiation */
1273   if (parent && GST_STATE (parent) < GST_STATE_READY)
1274   {
1275     GST_DEBUG (GST_CAT_CAPS, "parent %s of pad %s:%s is not READY",
1276                GST_ELEMENT_NAME (parent), GST_DEBUG_PAD_NAME (pad));
1277     return GST_PAD_CONNECT_DELAYED;
1278   }
1279           
1280   GST_INFO (GST_CAT_CAPS, "trying to set caps %p on pad %s:%s",
1281             caps, GST_DEBUG_PAD_NAME (pad));
1282   
1283   if ((template = gst_pad_get_pad_template (GST_PAD_CAST (pad)))) {
1284     if (!gst_caps_intersect (caps, gst_pad_template_get_caps (template))) {
1285       GST_INFO (GST_CAT_CAPS, "caps did not intersect with %s:%s's padtemplate",
1286                 GST_DEBUG_PAD_NAME (pad));
1287       gst_caps_debug (caps, "caps themselves (attemped to set)");
1288       gst_caps_debug (gst_pad_template_get_caps (template),
1289                       "pad template caps that did not agree with caps");
1290       return GST_PAD_CONNECT_REFUSED;
1291     }
1292     /* given that the caps are fixed, we know that their intersection with the
1293      * padtemplate caps is the same as caps itself */
1294   }
1295
1296   /* we need to notify the connect function */
1297   if (notify && GST_RPAD_CONNECTFUNC (pad)) {
1298     GstPadConnectReturn res;
1299     gchar *debug_string;
1300
1301     GST_INFO (GST_CAT_CAPS, "calling connect function on pad %s:%s",
1302             GST_DEBUG_PAD_NAME (pad));
1303
1304     /* call the connect function */
1305     res = GST_RPAD_CONNECTFUNC (pad) (GST_PAD (pad), caps);
1306
1307     switch (res) {
1308       case GST_PAD_CONNECT_REFUSED:
1309         debug_string = "REFUSED";
1310         break;
1311       case GST_PAD_CONNECT_OK:
1312         debug_string = "OK";
1313         break;
1314       case GST_PAD_CONNECT_DONE:
1315         debug_string = "DONE";
1316         break;
1317       case GST_PAD_CONNECT_DELAYED:
1318         debug_string = "DELAYED";
1319         break;
1320       default:
1321         g_warning ("unknown return code from connect function of pad %s:%s %d",
1322                    GST_DEBUG_PAD_NAME (pad), res);
1323         return GST_PAD_CONNECT_REFUSED;
1324     }
1325
1326     GST_INFO (GST_CAT_CAPS, 
1327               "got reply %s (%d) from connect function on pad %s:%s",
1328               debug_string, res, GST_DEBUG_PAD_NAME (pad));
1329
1330     /* done means the connect function called another caps negotiate function
1331      * on this pad that succeeded, we dont need to continue */
1332     if (res == GST_PAD_CONNECT_DONE) {
1333       GST_INFO (GST_CAT_CAPS, "pad %s:%s is done", GST_DEBUG_PAD_NAME (pad));
1334       return GST_PAD_CONNECT_DONE;
1335     }
1336     if (res == GST_PAD_CONNECT_REFUSED) {
1337       GST_INFO (GST_CAT_CAPS, "pad %s:%s doesn't accept caps",
1338                 GST_DEBUG_PAD_NAME (pad));
1339       return GST_PAD_CONNECT_REFUSED;
1340     }
1341   }
1342   /* we can only set caps on the pad if they are fixed */
1343   if (GST_CAPS_IS_FIXED (caps)) {
1344
1345     GST_INFO (GST_CAT_CAPS, "setting caps on pad %s:%s",
1346               GST_DEBUG_PAD_NAME (pad));
1347     /* if we got this far all is ok, remove the old caps, set the new one */
1348     oldcaps = GST_PAD_CAPS (pad);
1349     if (caps) gst_caps_ref (caps);
1350     GST_PAD_CAPS (pad) = caps;
1351     if (oldcaps) gst_caps_unref (oldcaps);
1352   }
1353   else {
1354     GST_INFO (GST_CAT_CAPS, 
1355               "caps are not fixed on pad %s:%s, not setting them yet",
1356               GST_DEBUG_PAD_NAME (pad));
1357   }
1358   return GST_PAD_CONNECT_OK;
1359 }
1360
1361 /**
1362  * gst_pad_try_set_caps:
1363  * @pad: a #GstPad to try to set the caps on.
1364  * @caps: the #GstCaps to set.
1365  *
1366  * Tries to set the caps on the given pad.
1367  *
1368  * Returns: A GstPadConnectReturn value indicating whether the caps
1369  *              could be set.
1370  */
1371 GstPadConnectReturn
1372 gst_pad_try_set_caps (GstPad *pad, GstCaps *caps)
1373 {
1374   GstRealPad *peer, *realpad;
1375   GstPadConnectReturn set_retval;
1376
1377   realpad = GST_PAD_REALIZE (pad);
1378   peer = GST_RPAD_PEER (realpad);
1379
1380   GST_INFO (GST_CAT_CAPS, "trying to set caps %p on pad %s:%s",
1381             caps, GST_DEBUG_PAD_NAME (realpad));
1382
1383   gst_caps_debug (caps, "caps that we are trying to set");
1384
1385   /* setting non fixed caps on a pad is not allowed */
1386   if (!GST_CAPS_IS_FIXED (caps)) {
1387   GST_INFO (GST_CAT_CAPS, 
1388             "trying to set unfixed caps on pad %s:%s, not allowed",
1389             GST_DEBUG_PAD_NAME (realpad));
1390     g_warning ("trying to set non fixed caps on pad %s:%s, not allowed",
1391                GST_DEBUG_PAD_NAME (realpad));
1392     gst_caps_debug (caps, "unfixed caps");
1393     return GST_PAD_CONNECT_DELAYED;
1394   }
1395
1396   /* if we have a peer try to set the caps, notifying the peerpad
1397    * if it has a connect function */
1398   if (peer && ((set_retval = gst_pad_try_set_caps_func (peer, caps, TRUE)) <= 0))
1399   {
1400     GST_INFO (GST_CAT_CAPS, "tried to set caps on peerpad %s:%s but couldn't, return value %d",
1401               GST_DEBUG_PAD_NAME (peer), set_retval);
1402     return set_retval;
1403   }
1404
1405   /* then try to set our own caps, we don't need to be notified */
1406   if ((set_retval = gst_pad_try_set_caps_func (realpad, caps, FALSE)) <= 0)
1407   {
1408     GST_INFO (GST_CAT_CAPS, "tried to set own caps on pad %s:%s but couldn't, return value %d",
1409               GST_DEBUG_PAD_NAME (realpad), set_retval);
1410     return set_retval;
1411   }
1412   GST_INFO (GST_CAT_CAPS, "succeeded setting caps %p on pad %s:%s, return value %d",
1413             caps, GST_DEBUG_PAD_NAME (realpad), set_retval);
1414   g_assert (GST_PAD_CAPS (pad));
1415                           
1416   return set_retval;
1417 }
1418
1419 /* this is a caps negotiation convenience routine, it:
1420  *
1421  * 1. optionally clears any pad caps.
1422  * 2. calculates the intersection between the two pad tamplate/getcaps caps.
1423  * 3. calculates the intersection with the (optional) filtercaps.
1424  * 4. stores the intersection in the pad filter.
1425  * 5. stores the app filtercaps in the pad appfilter.
1426  * 6. starts the caps negotiation.
1427  */
1428 static gboolean
1429 gst_pad_try_reconnect_filtered_func (GstRealPad *srcpad, GstRealPad *sinkpad, 
1430                                      GstCaps *filtercaps, gboolean clear)
1431 {
1432   GstCaps *srccaps, *sinkcaps;
1433   GstCaps *intersection = NULL;
1434   GstRealPad *realsrc, *realsink;
1435
1436   realsrc = GST_PAD_REALIZE (srcpad);
1437   realsink = GST_PAD_REALIZE (sinkpad);
1438
1439   g_return_val_if_fail (GST_RPAD_PEER (realsrc) != NULL, FALSE);
1440   g_return_val_if_fail (GST_RPAD_PEER (realsink) == realsrc, FALSE);
1441
1442   /* optinally clear the caps */
1443   if (clear) {
1444     GST_INFO (GST_CAT_PADS, 
1445               "start reconnect filtered %s:%s and %s:%s, clearing caps",
1446               GST_DEBUG_PAD_NAME (realsrc), GST_DEBUG_PAD_NAME (realsink));
1447
1448     GST_PAD_CAPS (GST_PAD (realsrc)) = NULL;
1449     GST_PAD_CAPS (GST_PAD (realsink)) = NULL;
1450   }
1451   else {
1452     GST_INFO (GST_CAT_PADS, "start reconnect filtered %s:%s and %s:%s",
1453         GST_DEBUG_PAD_NAME (realsrc), GST_DEBUG_PAD_NAME (realsink));
1454   }
1455
1456   srccaps = gst_pad_get_caps (GST_PAD (realsrc));
1457   GST_DEBUG (GST_CAT_PADS, "dumping caps of pad %s:%s", 
1458              GST_DEBUG_PAD_NAME (realsrc));
1459   gst_caps_debug (srccaps, "caps of src pad (pre-reconnect)");
1460   sinkcaps = gst_pad_get_caps (GST_PAD (realsink));
1461   GST_DEBUG (GST_CAT_PADS, "dumping caps of pad %s:%s", 
1462              GST_DEBUG_PAD_NAME (realsink));
1463   gst_caps_debug (sinkcaps, "caps of sink pad (pre-reconnect)");
1464
1465   /* first take the intersection of the pad caps */
1466   intersection = gst_caps_intersect (srccaps, sinkcaps);
1467
1468   /* if we have no intersection but one of the caps was not NULL.. */
1469   if (!intersection && (srccaps || sinkcaps)) {
1470     /* the intersection is NULL but the pad caps were not both NULL,
1471      * this means they have no common format */
1472     GST_INFO (GST_CAT_PADS, "pads %s:%s and %s:%s have no common type",
1473               GST_DEBUG_PAD_NAME (realsrc), GST_DEBUG_PAD_NAME (realsink));
1474     return FALSE;
1475   } else if (intersection) {
1476     GST_INFO (GST_CAT_PADS, "pads %s:%s and %s:%s intersected to %s caps",
1477          GST_DEBUG_PAD_NAME (realsrc), GST_DEBUG_PAD_NAME (realsink), 
1478          ((intersection && GST_CAPS_IS_FIXED (intersection)) ? "fixed" : "variable"));
1479
1480     /* then filter this against the app filter */
1481     if (filtercaps) {
1482       GstCaps *filtered_intersection = gst_caps_intersect (intersection, 
1483                                                            filtercaps);
1484
1485       /* get rid of the old intersection here */
1486       gst_caps_unref (intersection);
1487
1488       if (!filtered_intersection) {
1489         GST_INFO (GST_CAT_PADS, 
1490                   "filtered connection between pads %s:%s and %s:%s is empty",
1491                   GST_DEBUG_PAD_NAME (realsrc), GST_DEBUG_PAD_NAME (realsink));
1492         return FALSE;
1493       }
1494       intersection = filtered_intersection;
1495
1496       /* keep a reference to the app caps */
1497       GST_RPAD_APPFILTER (realsink) = filtercaps;
1498       GST_RPAD_APPFILTER (realsrc) = filtercaps;
1499     }
1500   }
1501   GST_DEBUG (GST_CAT_CAPS, "setting filter for connection to:");
1502   gst_caps_debug (intersection, "filter for connection");
1503
1504   /* both the app filter and the filter, while stored on both peer pads, 
1505    * are equal to the same thing on both */
1506   GST_RPAD_FILTER (realsrc) = intersection; 
1507   GST_RPAD_FILTER (realsink) = intersection; 
1508
1509   return gst_pad_perform_negotiate (GST_PAD (realsrc), GST_PAD (realsink));
1510 }
1511
1512 /**
1513  * gst_pad_perform_negotiate:
1514  * @srcpad: the source #GstPad.
1515  * @sinkpad: the sink #GstPad.
1516  *
1517  * Tries to negotiate the pads.
1518  *
1519  * Returns: TRUE if the pads were succesfully negotiated, FALSE otherwise.
1520  */
1521 gboolean
1522 gst_pad_perform_negotiate (GstPad *srcpad, GstPad *sinkpad) 
1523 {
1524   GstCaps *intersection, *filtered_intersection;
1525   GstRealPad *realsrc, *realsink;
1526   GstCaps *srccaps, *sinkcaps, *filter;
1527
1528   g_return_val_if_fail (srcpad != NULL, FALSE);
1529   g_return_val_if_fail (sinkpad != NULL, FALSE);
1530   
1531   realsrc = GST_PAD_REALIZE (srcpad);
1532   realsink = GST_PAD_REALIZE (sinkpad);
1533     
1534   g_return_val_if_fail (GST_RPAD_PEER (realsrc) != NULL, FALSE);
1535   g_return_val_if_fail (GST_RPAD_PEER (realsink) == realsrc, FALSE);
1536
1537   filter = GST_RPAD_APPFILTER (realsrc);
1538   if (filter) {
1539     GST_INFO (GST_CAT_PADS, "dumping filter for connection %s:%s-%s:%s",
1540               GST_DEBUG_PAD_NAME (realsrc), GST_DEBUG_PAD_NAME (realsink));
1541     gst_caps_debug (filter, "connection filter caps");
1542   }
1543
1544   /* calculate the new caps here */
1545   srccaps = gst_pad_get_caps (GST_PAD (realsrc));
1546   GST_DEBUG (GST_CAT_PADS, "dumping caps of pad %s:%s", 
1547              GST_DEBUG_PAD_NAME (realsrc));
1548   gst_caps_debug (srccaps, 
1549                   "src caps, awaiting negotiation, after applying filter");
1550   sinkcaps = gst_pad_get_caps (GST_PAD (realsink));
1551   GST_DEBUG (GST_CAT_PADS, "dumping caps of pad %s:%s", 
1552              GST_DEBUG_PAD_NAME (realsink));
1553   gst_caps_debug (sinkcaps, 
1554                   "sink caps, awaiting negotiation, after applying filter");
1555   intersection = gst_caps_intersect (srccaps, sinkcaps);
1556   filtered_intersection = gst_caps_intersect (intersection, filter);
1557   if (filtered_intersection) {
1558     gst_caps_unref (intersection);
1559     intersection = filtered_intersection;
1560   }
1561
1562   /* no negotiation is performed if the pads have filtercaps */
1563   if (intersection) {
1564     GstPadConnectReturn res;
1565
1566     res = gst_pad_try_set_caps_func (realsrc, intersection, TRUE);
1567     if (res == GST_PAD_CONNECT_REFUSED) 
1568       return FALSE;
1569     if (res == GST_PAD_CONNECT_DONE) 
1570       return TRUE;
1571
1572     res = gst_pad_try_set_caps_func (realsink, intersection, TRUE);
1573     if (res == GST_PAD_CONNECT_REFUSED) 
1574       return FALSE;
1575     if (res == GST_PAD_CONNECT_DONE) 
1576       return TRUE;
1577   }
1578   return TRUE;
1579 }
1580
1581 /**
1582  * gst_pad_try_reconnect_filtered:
1583  * @srcpad: the source #GstPad to reconnect.
1584  * @sinkpad: the sink #GstPad to reconnect.
1585  * @filtercaps: the #GstPad to use as a filter in the reconnection.
1586  *
1587  * Tries to reconnect the given source and sink pad, constrained by the given
1588  * capabilities.
1589  *
1590  * Returns: TRUE if the pads were succesfully renegotiated, FALSE otherwise.
1591  */
1592 gboolean
1593 gst_pad_try_reconnect_filtered (GstPad *srcpad, GstPad *sinkpad, 
1594                                 GstCaps *filtercaps)
1595 {
1596   GstRealPad *realsrc, *realsink;
1597
1598   g_return_val_if_fail (srcpad != NULL, FALSE);
1599   g_return_val_if_fail (sinkpad != NULL, FALSE);
1600
1601   realsrc = GST_PAD_REALIZE (srcpad);
1602   realsink = GST_PAD_REALIZE (sinkpad);
1603
1604   g_return_val_if_fail (GST_RPAD_PEER (realsrc) != NULL, FALSE);
1605   g_return_val_if_fail (GST_RPAD_PEER (realsink) == realsrc, FALSE);
1606   
1607   return gst_pad_try_reconnect_filtered_func (realsrc, realsink, 
1608                                               filtercaps, TRUE);
1609 }
1610
1611 /**
1612  * gst_pad_reconnect_filtered:
1613  * @srcpad: the source #GstPad to reconnect.
1614  * @sinkpad: the sink #GstPad to reconnect.
1615  * @filtercaps: the #GstPad to use as a filter in the reconnection.
1616  *
1617  * Reconnects the given source and sink pad, constrained by the given
1618  * capabilities.  If the reconnection fails, the pads are disconnected
1619  * and FALSE is returned.
1620  *
1621  * Returns: TRUE if the pads were succesfully reconnected, FALSE otherwise.
1622  */
1623 gboolean
1624 gst_pad_reconnect_filtered (GstPad *srcpad, GstPad *sinkpad, 
1625                             GstCaps *filtercaps)
1626 {
1627   GstRealPad *realsrc, *realsink;
1628
1629   g_return_val_if_fail (srcpad != NULL, FALSE);
1630   g_return_val_if_fail (sinkpad != NULL, FALSE);
1631
1632   realsrc = GST_PAD_REALIZE (srcpad);
1633   realsink = GST_PAD_REALIZE (sinkpad);
1634
1635   g_return_val_if_fail (GST_RPAD_PEER (realsrc) != NULL, FALSE);
1636   g_return_val_if_fail (GST_RPAD_PEER (realsink) == realsrc, FALSE);
1637   
1638   if (! gst_pad_try_reconnect_filtered_func (realsrc, realsink, 
1639                                              filtercaps, TRUE)) {
1640     gst_pad_disconnect (srcpad, GST_PAD (GST_PAD_PEER (srcpad)));
1641     return FALSE;
1642   }
1643   return TRUE;
1644 }
1645
1646 /**
1647  * gst_pad_proxy_connect:
1648  * @pad: a #GstPad to proxy to.
1649  * @caps: the #GstCaps to use in proxying.
1650  *
1651  * Proxies the connect function to the specified pad.
1652  *
1653  * Returns: TRUE if the peer pad accepted the caps, FALSE otherwise.
1654  */
1655 GstPadConnectReturn
1656 gst_pad_proxy_connect (GstPad *pad, GstCaps *caps)
1657 {
1658   GstRealPad *peer, *realpad;
1659
1660   realpad = GST_PAD_REALIZE (pad);
1661
1662   peer = GST_RPAD_PEER (realpad);
1663
1664   GST_INFO (GST_CAT_CAPS, "proxy connect to pad %s:%s",
1665             GST_DEBUG_PAD_NAME (realpad));
1666
1667   if (peer && gst_pad_try_set_caps_func (peer, caps, TRUE) < 0)
1668     return GST_PAD_CONNECT_REFUSED;
1669   if (gst_pad_try_set_caps_func (realpad, caps, FALSE) < 0)
1670     return GST_PAD_CONNECT_REFUSED;
1671
1672   return GST_PAD_CONNECT_OK;
1673 }
1674
1675 /**
1676  * gst_pad_get_caps:
1677  * @pad: a  #GstPad to get the capabilities of.
1678  *
1679  * Gets the capabilities of this pad.
1680  *
1681  * Returns: the #GstCaps of this pad.
1682  */
1683 GstCaps*
1684 gst_pad_get_caps (GstPad *pad)
1685 {
1686   GstRealPad *realpad;
1687
1688   g_return_val_if_fail (pad != NULL, NULL);
1689   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
1690
1691   realpad = GST_PAD_REALIZE (pad);
1692
1693   GST_DEBUG (GST_CAT_CAPS, "get pad caps of %s:%s (%p)",
1694             GST_DEBUG_PAD_NAME (realpad), realpad);
1695
1696   if (GST_PAD_CAPS (realpad)) {
1697     GST_DEBUG (GST_CAT_CAPS, "using pad real caps %p", GST_PAD_CAPS (realpad));
1698     return GST_PAD_CAPS (realpad);
1699   }
1700   else if GST_RPAD_GETCAPSFUNC (realpad) {
1701     GST_DEBUG (GST_CAT_CAPS, "using pad get function");
1702     return GST_RPAD_GETCAPSFUNC (realpad) (GST_PAD_CAST (realpad), NULL);
1703   }
1704   else if (GST_PAD_PAD_TEMPLATE (realpad)) {
1705     GstPadTemplate *templ = GST_PAD_PAD_TEMPLATE (realpad);
1706     GST_DEBUG (GST_CAT_CAPS, "using pad template %p with caps %p", 
1707                templ, GST_PAD_TEMPLATE_CAPS (templ));
1708     return GST_PAD_TEMPLATE_CAPS (templ);
1709   }
1710   GST_DEBUG (GST_CAT_CAPS, "pad has no caps");
1711
1712   return NULL;
1713 }
1714
1715 /**
1716  * gst_pad_get_pad_template_caps:
1717  * @pad: a #GstPad to get the template capabilities from.
1718  *
1719  * Gets the template capabilities of this pad.
1720  *
1721  * Returns: the template #GstCaps of this pad.
1722  */
1723 GstCaps*
1724 gst_pad_get_pad_template_caps (GstPad *pad)
1725 {
1726   g_return_val_if_fail (pad != NULL, NULL);
1727   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
1728
1729   if (GST_PAD_PAD_TEMPLATE (pad))
1730     return GST_PAD_TEMPLATE_CAPS (GST_PAD_PAD_TEMPLATE (pad));
1731
1732   return NULL;
1733 }
1734
1735 /**
1736  * gst_pad_template_get_caps_by_name:
1737  * @templ: a #GstPadTemplate to get the capabilities of.
1738  * @name: the name of the capability to get.
1739  *
1740  * Gets the capability with the given name from this pad template.
1741  *
1742  * Returns: the #GstCaps, or NULL if not found or in case of an error.
1743  */
1744 GstCaps*
1745 gst_pad_template_get_caps_by_name (GstPadTemplate *templ, const gchar *name)
1746 {
1747   GstCaps *caps;
1748
1749   g_return_val_if_fail (templ != NULL, NULL);
1750
1751   caps = GST_PAD_TEMPLATE_CAPS (templ);
1752   if (!caps) 
1753     return NULL;
1754
1755   return gst_caps_get_by_name (caps, name);
1756 }
1757
1758 /**
1759  * gst_pad_check_compatibility:
1760  * @srcpad: the source #GstPad to check.
1761  * @sinkpad: the sink #GstPad to check against.
1762  *
1763  * Checks if two pads have compatible capabilities.
1764  *
1765  * Returns: TRUE if they are compatible or if the capabilities
1766  * could not be checked
1767  */
1768 gboolean
1769 gst_pad_check_compatibility (GstPad *srcpad, GstPad *sinkpad)
1770 {
1771   g_return_val_if_fail (srcpad != NULL, FALSE);
1772   g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE);
1773   g_return_val_if_fail (sinkpad != NULL, FALSE);
1774   g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE);
1775
1776   if (GST_PAD_CAPS (srcpad) && GST_PAD_CAPS (sinkpad)) {
1777     if (!gst_caps_check_compatibility (GST_PAD_CAPS (srcpad), 
1778                                        GST_PAD_CAPS (sinkpad))) {
1779       return FALSE;
1780     }
1781     else {
1782       return TRUE;
1783     }
1784   }
1785   else {
1786     GST_DEBUG (GST_CAT_PADS, 
1787                "could not check capabilities of pads (%s:%s) and (%s:%s) %p %p",
1788                GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad), 
1789                GST_PAD_CAPS (srcpad), GST_PAD_CAPS (sinkpad));
1790     return TRUE;
1791   }
1792 }
1793
1794 /**
1795  * gst_pad_get_peer:
1796  * @pad: a #GstPad to get the peer of.
1797  *
1798  * Gets the peer pad of this pad.
1799  *
1800  * Returns: the peer #GstPad.
1801  */
1802 GstPad*
1803 gst_pad_get_peer (GstPad *pad)
1804 {
1805   g_return_val_if_fail (pad != NULL, NULL);
1806   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
1807
1808   return GST_PAD (GST_PAD_PEER (pad));
1809 }
1810
1811 /**
1812  * gst_pad_get_allowed_caps:
1813  * @pad: a #GstPad to get the allowed caps of.
1814  *
1815  * Gets the capabilities of the allowed media types that can
1816  * flow through this pad.  The caller must free the resulting caps.
1817  *
1818  * Returns: a newly allocated copy of the allowed #GstCaps.
1819  */
1820 GstCaps*
1821 gst_pad_get_allowed_caps (GstPad *pad)
1822 {
1823   g_return_val_if_fail (pad != NULL, NULL);
1824   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
1825
1826   GST_DEBUG (GST_CAT_PROPERTIES, "get allowed caps of %s:%s", 
1827              GST_DEBUG_PAD_NAME (pad));
1828
1829   return gst_caps_copy (GST_RPAD_FILTER (pad));
1830 }
1831
1832 /**
1833  * gst_pad_recalc_allowed_caps:
1834  * @pad: a #GstPad to recalculate the capablities of.
1835  *
1836  * Attempts to reconnect the pad to its peer through its filter, 
1837  * set with gst_pad_[re]connect_filtered. This function is useful when a
1838  * plug-in has new capabilities on a pad and wants to notify the peer.
1839  *
1840  * Returns: TRUE on success, FALSE otherwise.
1841  */
1842 gboolean
1843 gst_pad_recalc_allowed_caps (GstPad *pad)
1844 {
1845   GstRealPad *peer;
1846
1847   g_return_val_if_fail (pad != NULL, FALSE);
1848   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
1849
1850   GST_DEBUG (GST_CAT_PROPERTIES, "set allowed caps of %s:%s", 
1851              GST_DEBUG_PAD_NAME (pad));
1852
1853   peer = GST_RPAD_PEER (pad);
1854   if (peer)
1855     return gst_pad_try_reconnect_filtered (pad, GST_PAD (peer), 
1856                                            GST_RPAD_APPFILTER (pad));
1857
1858   return TRUE;
1859 }
1860
1861 /**
1862  * gst_pad_get_bufferpool:
1863  * @pad: a #GstPad to get the bufferpool from.
1864  *
1865  * Gets the bufferpool of the peer pad of the given pad.
1866  *
1867  * Returns: the #GstBufferPool, or NULL in case of an error.
1868  */
1869 GstBufferPool*          
1870 gst_pad_get_bufferpool (GstPad *pad)
1871 {
1872   GstRealPad *peer;
1873
1874   g_return_val_if_fail (pad != NULL, NULL);
1875   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
1876    
1877   peer = GST_RPAD_PEER (pad);
1878
1879   if (!peer)
1880     return NULL;
1881
1882   GST_DEBUG_ENTER ("(%s:%s)", GST_DEBUG_PAD_NAME (pad));
1883
1884   if (peer->bufferpoolfunc) {
1885     GST_DEBUG (GST_CAT_PADS, 
1886                "calling bufferpoolfunc &%s (@%p) of peer pad %s:%s",
1887                GST_DEBUG_FUNCPTR_NAME (peer->bufferpoolfunc), 
1888                &peer->bufferpoolfunc, GST_DEBUG_PAD_NAME (((GstPad*) peer)));
1889     return (peer->bufferpoolfunc) (((GstPad*) peer));
1890   } else {
1891     GST_DEBUG (GST_CAT_PADS, "no bufferpoolfunc for peer pad %s:%s at %p",
1892                GST_DEBUG_PAD_NAME (((GstPad*) peer)), &peer->bufferpoolfunc);
1893     return NULL;
1894   }
1895 }
1896
1897 static void
1898 gst_real_pad_dispose (GObject *object)
1899 {
1900   GstPad *pad = GST_PAD (object);
1901   
1902   /* No connected pad can ever be disposed.
1903    * It has to have a parent to be connected 
1904    * and a parent would hold a reference */
1905   g_assert (GST_PAD_PEER (pad) == NULL);
1906
1907   GST_DEBUG (GST_CAT_REFCOUNTING, "dispose %s:%s", GST_DEBUG_PAD_NAME(pad));
1908
1909   if (GST_PAD_PAD_TEMPLATE (pad)){
1910     GST_DEBUG (GST_CAT_REFCOUNTING, "unreffing padtemplate'%s'", 
1911                GST_OBJECT_NAME (GST_PAD_PAD_TEMPLATE (pad)));
1912     gst_object_unref (GST_OBJECT (GST_PAD_PAD_TEMPLATE (pad)));
1913     GST_PAD_PAD_TEMPLATE (pad) = NULL;
1914   }
1915   
1916   /* we destroy the ghostpads, because they are nothing without the real pad */
1917   if (GST_REAL_PAD (pad)->ghostpads) {
1918     GList *orig, *ghostpads;
1919
1920     orig = ghostpads = g_list_copy (GST_REAL_PAD (pad)->ghostpads);
1921
1922     while (ghostpads) {
1923       GstPad *ghostpad = GST_PAD (ghostpads->data);
1924
1925       if (GST_IS_ELEMENT (GST_OBJECT_PARENT (ghostpad))){
1926         GST_DEBUG (GST_CAT_REFCOUNTING, "removing ghost pad from element '%s'", 
1927                    GST_OBJECT_NAME (GST_OBJECT_PARENT (ghostpad)));
1928
1929         gst_element_remove_ghost_pad (GST_ELEMENT (GST_OBJECT_PARENT (ghostpad)), GST_PAD (ghostpad));
1930       }
1931       ghostpads = g_list_next (ghostpads);
1932     }
1933     g_list_free (orig);
1934     g_list_free (GST_REAL_PAD(pad)->ghostpads);
1935   }
1936
1937   if (GST_IS_ELEMENT (GST_OBJECT_PARENT (pad))) {
1938     GST_DEBUG (GST_CAT_REFCOUNTING, "removing pad from element '%s'",
1939                GST_OBJECT_NAME (GST_OBJECT (GST_ELEMENT (GST_OBJECT_PARENT (pad)))));
1940     
1941     gst_element_remove_pad (GST_ELEMENT (GST_OBJECT_PARENT (pad)), pad);
1942   }
1943   
1944   G_OBJECT_CLASS (real_pad_parent_class)->dispose (object);
1945 }
1946
1947
1948 #ifndef GST_DISABLE_LOADSAVE
1949 /* FIXME: why isn't this on a GstElement ? */
1950 /**
1951  * gst_pad_load_and_connect:
1952  * @self: an #xmlNodePtr to read the description from.
1953  * @parent: the #GstObject element that owns the pad.
1954  *
1955  * Reads the pad definition from the XML node and connects the given pad
1956  * in the element to a pad of an element up in the hierarchy.
1957  */
1958 void
1959 gst_pad_load_and_connect (xmlNodePtr self, GstObject *parent)
1960 {
1961   xmlNodePtr field = self->xmlChildrenNode;
1962   GstPad *pad = NULL, *targetpad;
1963   gchar *peer = NULL;
1964   gchar **split;
1965   GstElement *target;
1966   GstObject *grandparent;
1967
1968   while (field) {
1969     if (!strcmp (field->name, "name")) {
1970       pad = gst_element_get_pad (GST_ELEMENT (parent), 
1971                                  xmlNodeGetContent (field));
1972     }
1973     else if (!strcmp(field->name, "peer")) {
1974       peer = xmlNodeGetContent (field);
1975     }
1976     field = field->next;
1977   }
1978   g_return_if_fail (pad != NULL);
1979
1980   if (peer == NULL) return;
1981
1982   split = g_strsplit (peer, ".", 2);
1983
1984   if (split[0] == NULL || split[1] == NULL) {
1985     GST_DEBUG (GST_CAT_XML, 
1986                "Could not parse peer '%s' for pad %s:%s, leaving unconnected",
1987                peer, GST_DEBUG_PAD_NAME (pad));
1988     return;
1989   }
1990   
1991   g_return_if_fail (split[0] != NULL);
1992   g_return_if_fail (split[1] != NULL);
1993
1994   grandparent = gst_object_get_parent (parent);
1995
1996   if (grandparent && GST_IS_BIN (grandparent)) {
1997     target = gst_bin_get_by_name_recurse_up (GST_BIN (grandparent), split[0]);
1998   }
1999   else
2000     goto cleanup;
2001
2002   if (target == NULL) goto cleanup;
2003
2004   targetpad = gst_element_get_pad (target, split[1]);
2005
2006   if (targetpad == NULL) goto cleanup;
2007
2008   gst_pad_connect (pad, targetpad);
2009
2010 cleanup:
2011   g_strfreev (split);
2012 }
2013
2014 /**
2015  * gst_pad_save_thyself:
2016  * @pad: a #GstPad to save.
2017  * @parent: the parent #xmlNodePtr to save the description in.
2018  *
2019  * Saves the pad into an xml representation.
2020  *
2021  * Returns: the #xmlNodePtr representation of the pad.
2022  */
2023 static xmlNodePtr
2024 gst_pad_save_thyself (GstObject *object, xmlNodePtr parent)
2025 {
2026   GstRealPad *realpad;
2027   GstPad *peer;
2028
2029   g_return_val_if_fail (GST_IS_REAL_PAD (object), NULL);
2030
2031   realpad = GST_REAL_PAD (object);
2032
2033   xmlNewChild (parent, NULL, "name", GST_PAD_NAME (realpad));
2034   if (GST_RPAD_PEER (realpad) != NULL) {
2035     gchar *content;
2036     
2037     peer = GST_PAD (GST_RPAD_PEER (realpad));
2038     /* first check to see if the peer's parent's parent is the same */
2039     /* we just save it off */
2040     content = g_strdup_printf ("%s.%s",
2041                                GST_OBJECT_NAME (GST_PAD_PARENT (peer)),
2042                                GST_PAD_NAME (peer));
2043     xmlNewChild (parent, NULL, "peer", content);
2044     g_free (content);
2045   } else
2046     xmlNewChild (parent, NULL, "peer", "");
2047
2048   return parent;
2049 }
2050
2051 /* FIXME: shouldn't pad and ghost be switched ?
2052  * FIXME: shouldn't the bin argument be dumped ?
2053  */
2054 /**
2055  * gst_ghost_pad_save_thyself:
2056  * @pad: a ghost #GstPad to save.
2057  * @bin: the #bin
2058  * @parent: the parent #xmlNodePtr to save the description in.
2059  *
2060  * Saves the ghost pad into an xml representation.
2061  *
2062  * Returns: the #xmlNodePtr representation of the pad.
2063  */
2064 xmlNodePtr
2065 gst_ghost_pad_save_thyself (GstPad *pad, xmlNodePtr parent)
2066 {
2067   xmlNodePtr self;
2068
2069   g_return_val_if_fail (GST_IS_GHOST_PAD (pad), NULL);
2070
2071   self = xmlNewChild (parent, NULL, "ghostpad", NULL);
2072   xmlNewChild (self, NULL, "name", GST_PAD_NAME (pad));
2073   xmlNewChild (self, NULL, "parent", GST_OBJECT_NAME (GST_PAD_PARENT (pad)));
2074
2075   /* FIXME FIXME FIXME! */
2076
2077   return self;
2078 }
2079 #endif /* GST_DISABLE_LOADSAVE */
2080
2081 /**
2082  * gst_pad_push:
2083  * @pad: a #GstPad to push the buffer out of.
2084  * @buf: the #GstBuffer to push.
2085  *
2086  * Pushes a buffer to the peer of the pad.
2087  */
2088 void 
2089 gst_pad_push (GstPad *pad, GstBuffer *buf) 
2090 {
2091   GstRealPad *peer = GST_RPAD_PEER (pad);
2092
2093   GST_DEBUG_ENTER ("(%s:%s)", GST_DEBUG_PAD_NAME (pad));
2094
2095   g_return_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SRC);
2096
2097   if (!peer) {
2098     g_warning ("push on pad %s:%s but it is unconnected", 
2099                GST_DEBUG_PAD_NAME (pad));
2100   }
2101   else {
2102     if (peer->chainhandler) {
2103       if (buf) {
2104         GST_DEBUG (GST_CAT_DATAFLOW, 
2105                    "calling chainhandler &%s of peer pad %s:%s",
2106                    GST_DEBUG_FUNCPTR_NAME (peer->chainhandler), 
2107                    GST_DEBUG_PAD_NAME (GST_PAD (peer)));
2108         (peer->chainhandler) (GST_PAD_CAST (peer), buf);
2109         return;
2110       }
2111       else {
2112         g_warning ("trying to push a NULL buffer on pad %s:%s", 
2113                    GST_DEBUG_PAD_NAME (peer));
2114         return;
2115       }
2116     } 
2117     else {
2118       g_warning ("internal error: push on pad %s:%s but it has no chainhandler",
2119                  GST_DEBUG_PAD_NAME (peer));
2120     }
2121   }
2122   /* clean up the mess here */
2123   if (buf != NULL) gst_data_unref (GST_DATA (buf));
2124 }
2125
2126 /**
2127  * gst_pad_pull:
2128  * @pad: a #GstPad to pull a buffer from.
2129  *
2130  * Pulls a buffer from the peer pad.
2131  *
2132  * Returns: a new #GstBuffer from the peer pad.
2133  */
2134 GstBuffer*
2135 gst_pad_pull (GstPad *pad) 
2136 {
2137   GstRealPad *peer;
2138
2139   peer = GST_RPAD_PEER (pad);
2140   
2141   GST_DEBUG_ENTER("(%s:%s)",GST_DEBUG_PAD_NAME(pad));
2142
2143   g_return_val_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SINK, NULL);
2144
2145   if (!peer) {
2146     gst_element_error (GST_PAD_PARENT (pad), 
2147                        "pull on pad %s:%s but it was unconnected", 
2148                        GST_ELEMENT_NAME (GST_PAD_PARENT (pad)), 
2149                        GST_PAD_NAME (pad), NULL);
2150   }
2151   else {
2152     if (peer->gethandler) {
2153       GstBuffer *buf;
2154
2155       GST_DEBUG (GST_CAT_DATAFLOW, "calling gethandler %s of peer pad %s:%s",
2156                  GST_DEBUG_FUNCPTR_NAME (peer->gethandler), 
2157                  GST_DEBUG_PAD_NAME (peer));
2158
2159       buf = (peer->gethandler) (GST_PAD_CAST (peer));
2160
2161       if (buf)
2162         return buf;
2163
2164       /* no null buffers allowed */
2165       gst_element_error (GST_PAD_PARENT (pad), 
2166                          "NULL buffer during pull on %s:%s", 
2167                          GST_DEBUG_PAD_NAME (pad), NULL);
2168           
2169     } else {
2170       gst_element_error (GST_PAD_PARENT (pad), 
2171                          "internal error: pull on pad %s:%s "
2172                          "but the peer pad %s:%s has no gethandler", 
2173                          GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (peer),
2174                          NULL);
2175     }
2176   }
2177   return NULL;
2178 }
2179
2180 /**
2181  * gst_pad_select:
2182  * @padlist: a #GList of pads.
2183  *
2184  * Waits for a buffer on any of the list of pads.
2185  *
2186  * Returns: the #GstPad that has a buffer available. 
2187  * Use #gst_pad_pull() to get the buffer.
2188  */
2189 GstPad*
2190 gst_pad_select (GList *padlist)
2191 {
2192   GstPad *pad;
2193
2194   pad = gst_scheduler_pad_select (GST_PAD_PARENT (padlist->data)->sched, 
2195                                   padlist);
2196   return pad;
2197 }
2198
2199 /**
2200  * gst_pad_selectv:
2201  * @pad: a first #GstPad to perform the select on.
2202  * @...: A NULL-terminated list of more pads to select on.
2203  *
2204  * Waits for a buffer on the given set of pads.
2205  *
2206  * Returns: the #GstPad that has a buffer available.
2207  * Use #gst_pad_pull() to get the buffer.
2208  */
2209 GstPad*
2210 gst_pad_selectv (GstPad *pad, ...)
2211 {
2212   GstPad *result;
2213   GList *padlist = NULL;
2214   va_list var_args;
2215
2216   if (pad == NULL)
2217     return NULL;
2218
2219   va_start (var_args, pad);
2220
2221   while (pad) {
2222     padlist = g_list_prepend (padlist, pad);
2223     pad = va_arg (var_args, GstPad *);
2224   }
2225   result = gst_pad_select (padlist);
2226   g_list_free (padlist);
2227
2228   va_end (var_args);
2229   
2230   return result;
2231 }
2232
2233 /************************************************************************
2234  *
2235  * templates
2236  *
2237  */
2238 static void             gst_pad_template_class_init     (GstPadTemplateClass *klass);
2239 static void             gst_pad_template_init           (GstPadTemplate *templ);
2240
2241 GType
2242 gst_pad_template_get_type (void)
2243 {
2244   static GType padtemplate_type = 0;
2245
2246   if (!padtemplate_type) {
2247     static const GTypeInfo padtemplate_info = {
2248       sizeof (GstPadTemplateClass), NULL, NULL,
2249       (GClassInitFunc) gst_pad_template_class_init, NULL, NULL,
2250       sizeof (GstPadTemplate),
2251       32,
2252       (GInstanceInitFunc) gst_pad_template_init, NULL
2253     };
2254     padtemplate_type = g_type_register_static(GST_TYPE_OBJECT, "GstPadTemplate",
2255                                               &padtemplate_info, 0);
2256   }
2257   return padtemplate_type;
2258 }
2259
2260 static void
2261 gst_pad_template_class_init (GstPadTemplateClass *klass)
2262 {
2263   GObjectClass *gobject_class;
2264   GstObjectClass *gstobject_class;
2265
2266   gobject_class = (GObjectClass*) klass;
2267   gstobject_class = (GstObjectClass*) klass;
2268
2269   padtemplate_parent_class = g_type_class_ref (GST_TYPE_OBJECT);
2270
2271   gst_pad_template_signals[TEMPL_PAD_CREATED] =
2272     g_signal_new ("pad_created", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
2273                   G_STRUCT_OFFSET (GstPadTemplateClass, pad_created), 
2274                   NULL, NULL, gst_marshal_VOID__POINTER, G_TYPE_NONE, 1,
2275                   G_TYPE_POINTER);
2276
2277   gstobject_class->path_string_separator = "*";
2278 }
2279
2280 static void
2281 gst_pad_template_init (GstPadTemplate *templ)
2282 {
2283 }
2284
2285 /* ALWAYS padtemplates cannot have conversion specifications, it doesn't make
2286  * sense.
2287  * SOMETIMES padtemplates can do whatever they want, they are provided by the
2288  * element.
2289  * REQUEST padtemplates can be reverse-parsed (the user asks for 'sink1', the
2290  * 'sink%d' template is automatically selected), so we need to restrict their
2291  * naming.
2292  */
2293 static gboolean
2294 name_is_valid (const gchar *name, GstPadPresence presence)
2295 {
2296   const gchar *str;
2297   
2298   if (presence == GST_PAD_ALWAYS) {
2299     if (strchr (name, '%')) {
2300       g_warning ("invalid name template %s: conversion specifications are not"
2301                  " allowed for GST_PAD_ALWAYS padtemplates", name);
2302       return FALSE;
2303     }
2304   } else if (presence == GST_PAD_REQUEST) {
2305     if ((str = strchr (name, '%')) && strchr (str + 1, '%')) {
2306       g_warning ("invalid name template %s: only one conversion specification"
2307                  " allowed in GST_PAD_REQUEST padtemplate", name);
2308       return FALSE;
2309     }
2310     if (str && (*(str+1) != 's' && *(str+1) != 'd')) {
2311       g_warning ("invalid name template %s: conversion specification must be of"
2312                  " type '%%d' or '%%s' for GST_PAD_REQUEST padtemplate", name);
2313       return FALSE;
2314     }
2315     if (str && (*(str+2) != '\0')) {
2316       g_warning ("invalid name template %s: conversion specification must"
2317                  " appear at the end of the GST_PAD_REQUEST padtemplate name", 
2318                  name);
2319       return FALSE;
2320     }
2321   }
2322   
2323   return TRUE;
2324 }
2325
2326 /**
2327  * gst_pad_template_new:
2328  * @name_template: the name template.
2329  * @direction: the #GstPadDirection of the template.
2330  * @presence: the #GstPadPresence of the pad.
2331  * @caps: a #GstCaps set for the template.
2332  * @...: a NULL-terminated list of #GstCaps.
2333  *
2334  * Creates a new pad template with a name according to the given template
2335  * and with the given arguments.
2336  *
2337  * Returns: a new #GstPadTemplate.
2338  */
2339 GstPadTemplate*
2340 gst_pad_template_new (const gchar *name_template,
2341                      GstPadDirection direction, GstPadPresence presence,
2342                      GstCaps *caps, ...)
2343 {
2344   GstPadTemplate *new;
2345   va_list var_args;
2346   GstCaps *thecaps = NULL;
2347
2348   g_return_val_if_fail (name_template != NULL, NULL);
2349
2350   if (!name_is_valid (name_template, presence))
2351     return NULL;
2352
2353   new = g_object_new (gst_pad_template_get_type (),
2354                       "name", name_template,
2355                       NULL);
2356
2357   GST_PAD_TEMPLATE_NAME_TEMPLATE (new) = g_strdup (name_template);
2358   GST_PAD_TEMPLATE_DIRECTION (new) = direction;
2359   GST_PAD_TEMPLATE_PRESENCE (new) = presence;
2360
2361   va_start (var_args, caps);
2362
2363   while (caps) {
2364     new->fixed &= caps->fixed;
2365     thecaps = gst_caps_append (thecaps, gst_caps_ref (caps));
2366     caps = va_arg (var_args, GstCaps*);
2367   }
2368   va_end (var_args);
2369   
2370   GST_PAD_TEMPLATE_CAPS (new) = thecaps;
2371
2372   return new;
2373 }
2374
2375 /**
2376  * gst_pad_template_get_caps:
2377  * @templ: a #GstPadTemplate to get capabilities of.
2378  *
2379  * Gets the capabilities of the pad template.
2380  *
2381  * Returns: the #GstCaps of the pad template.
2382  */
2383 GstCaps*
2384 gst_pad_template_get_caps (GstPadTemplate *templ)
2385 {
2386   g_return_val_if_fail (templ != NULL, NULL);
2387
2388   return GST_PAD_TEMPLATE_CAPS (templ);
2389 }
2390
2391 /**
2392  * gst_pad_set_element_private:
2393  * @pad: the #GstPad to set the private data of.
2394  * @priv: The private data to attach to the pad.
2395  *
2396  * Set the given private data gpointer on the pad. 
2397  * This function can only be used by the element that owns the pad.
2398  */
2399 void
2400 gst_pad_set_element_private (GstPad *pad, gpointer priv)
2401 {
2402   pad->element_private = priv;
2403 }
2404
2405 /**
2406  * gst_pad_get_element_private:
2407  * @pad: the #GstPad to get the private data of.
2408  *
2409  * Gets the private data of a pad.
2410  *
2411  * Returns: a #gpointer to the private data.
2412  */
2413 gpointer
2414 gst_pad_get_element_private (GstPad *pad)
2415 {
2416   return pad->element_private;
2417 }
2418
2419
2420 /***** ghost pads *****/
2421 GType _gst_ghost_pad_type = 0;
2422
2423 static void     gst_ghost_pad_class_init         (GstGhostPadClass *klass);
2424 static void     gst_ghost_pad_init               (GstGhostPad *pad);
2425
2426 static GstPad *ghost_pad_parent_class = NULL;
2427 /* static guint gst_ghost_pad_signals[LAST_SIGNAL] = { 0 }; */
2428
2429 GType
2430 gst_ghost_pad_get_type (void) 
2431 {
2432   if (!_gst_ghost_pad_type) {
2433     static const GTypeInfo pad_info = {
2434       sizeof (GstGhostPadClass), NULL, NULL,
2435       (GClassInitFunc) gst_ghost_pad_class_init, NULL, NULL,
2436       sizeof (GstGhostPad),
2437       8,
2438       (GInstanceInitFunc) gst_ghost_pad_init,
2439       NULL
2440     };
2441     _gst_ghost_pad_type = g_type_register_static (GST_TYPE_PAD, "GstGhostPad", 
2442                                                   &pad_info, 0);
2443   }
2444   return _gst_ghost_pad_type;
2445 }
2446
2447 static void
2448 gst_ghost_pad_class_init (GstGhostPadClass *klass)
2449 {
2450   GObjectClass *gobject_class;
2451
2452   gobject_class = (GObjectClass*) klass;
2453
2454   ghost_pad_parent_class = g_type_class_ref (GST_TYPE_PAD);
2455 }
2456
2457 static void
2458 gst_ghost_pad_init (GstGhostPad *pad)
2459 {
2460   pad->realpad = NULL;
2461 }
2462
2463 /**
2464  * gst_ghost_pad_new:
2465  * @name: the name of the new ghost pad.
2466  * @pad: the #GstPad to create a ghost pad for.
2467  *
2468  * Creates a new ghost pad associated with the given pad, and names it with
2469  * the given name.  If name is NULL, a guaranteed unique name (across all
2470  * ghost pads) will be assigned (most likely of the form ghostpad%d).
2471  *
2472  * Returns: a new ghost #GstPad, or NULL in case of an error.
2473  */
2474
2475 GstPad*
2476 gst_ghost_pad_new (const gchar *name,
2477                    GstPad *pad)
2478 {
2479   GstGhostPad *ghostpad;
2480   GstRealPad *realpad;
2481
2482   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
2483
2484   ghostpad = g_object_new (gst_ghost_pad_get_type () ,NULL);
2485   gst_pad_set_name (GST_PAD (ghostpad), name);
2486
2487   realpad = (GstRealPad *) pad;
2488
2489   while (!GST_IS_REAL_PAD (realpad)) {
2490     realpad = GST_PAD_REALIZE (realpad);
2491   }
2492   GST_GPAD_REALPAD (ghostpad) = realpad;
2493   GST_PAD_PAD_TEMPLATE (ghostpad) = GST_PAD_PAD_TEMPLATE (pad);
2494
2495   /* add ourselves to the real pad's list of ghostpads */
2496   gst_pad_add_ghost_pad (pad, GST_PAD (ghostpad));
2497
2498   /* FIXME need to ref the real pad here... ? */
2499
2500   GST_DEBUG (GST_CAT_PADS, "created ghost pad \"%s\"", 
2501              gst_pad_get_name (GST_PAD (ghostpad)));
2502
2503   return GST_PAD (ghostpad);
2504 }
2505
2506 /**
2507  * gst_pad_get_internal_connections_default:
2508  * @pad: the #GstPad to get the internal connections of.
2509  *
2510  * Gets a list of pads to which the given pad is connected to
2511  * inside of the parent element.
2512  * This is the default handler, and thus returns a list of all of the
2513  * pads inside the parent element with opposite direction.
2514  * The caller must free this list after use.
2515  *
2516  * Returns: a newly allocated #GList of pads.
2517  */
2518 GList*
2519 gst_pad_get_internal_connections_default (GstPad *pad)
2520 {
2521   GList *res = NULL;
2522   GstElement *parent;
2523   GList *parent_pads;
2524   GstPadDirection direction;
2525   GstRealPad *rpad;
2526   
2527   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
2528
2529   rpad = GST_PAD_REALIZE (pad);
2530   direction = rpad->direction;
2531
2532   parent = GST_PAD_PARENT (rpad);
2533   parent_pads = parent->pads;
2534
2535   while (parent_pads) {
2536     GstRealPad *parent_pad = GST_PAD_REALIZE (parent_pads->data);
2537     
2538     if (parent_pad->direction != direction) {
2539       res = g_list_prepend (res, parent_pad);
2540     }
2541     
2542     parent_pads = g_list_next (parent_pads);
2543   }
2544
2545   return res;
2546 }
2547
2548 /**
2549  * gst_pad_get_internal_connections:
2550  * @pad: the #GstPad to get the internal connections of.
2551  *
2552  * Gets a list of pads to which the given pad is connected to
2553  * inside of the parent element.
2554  * The caller must free this list after use.
2555  *
2556  * Returns: a newly allocated #GList of pads.
2557  */
2558 GList*
2559 gst_pad_get_internal_connections (GstPad *pad)
2560 {
2561   GList *res = NULL;
2562   GstRealPad *rpad;
2563
2564   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
2565
2566   rpad = GST_PAD_REALIZE (pad);
2567
2568   if (GST_RPAD_INTCONNFUNC (rpad))
2569     res = GST_RPAD_INTCONNFUNC (rpad) (GST_PAD_CAST (rpad));
2570
2571   return res;
2572 }
2573
2574
2575 static gboolean 
2576 gst_pad_event_default_dispatch (GstPad *pad, GstElement *element, 
2577                                 GstEvent *event)
2578 {
2579   GList *pads = element->pads;
2580
2581   while (pads) {
2582     GstPad *eventpad = GST_PAD (pads->data);
2583     pads = g_list_next (pads);
2584
2585     /* for all pads in the opposite direction that are connected */
2586     if (GST_PAD_DIRECTION (eventpad) != GST_PAD_DIRECTION (pad) 
2587      && GST_PAD_IS_USABLE (eventpad)) {
2588       if (GST_PAD_DIRECTION (eventpad) == GST_PAD_SRC) {
2589         /* increase the refcount */
2590         gst_event_ref (event);
2591         gst_pad_push (eventpad, GST_BUFFER (event));
2592       }
2593       else {
2594         GstPad *peerpad = GST_PAD_CAST (GST_RPAD_PEER (eventpad));
2595
2596         /* we only send the event on one pad, multi-sinkpad elements 
2597          * should implement a handler */
2598         return gst_pad_send_event (peerpad, event);
2599       }
2600     }
2601   }
2602   gst_event_unref (event);
2603   return TRUE;
2604 }
2605
2606 /**
2607  * gst_pad_event_default:
2608  * @pad: a #GstPad to call the default event handler on.
2609  * @event: the #GstEvent to handle.
2610  *
2611  * Invokes the default event handler for the given pad.
2612  *
2613  * Returns: TRUE if the event was sent succesfully.
2614  */
2615 gboolean 
2616 gst_pad_event_default (GstPad *pad, GstEvent *event)
2617 {
2618   GstElement *element = GST_PAD_PARENT (pad);
2619
2620   g_signal_emit (G_OBJECT (pad), gst_real_pad_signals[REAL_EVENT_RECEIVED], 
2621                  0, event);
2622  
2623   switch (GST_EVENT_TYPE (event)) {
2624     case GST_EVENT_EOS:
2625       gst_pad_event_default_dispatch (pad, element, event);
2626       gst_element_set_eos (element);
2627       /* we have to try to schedule another element 
2628        * because this one is disabled */
2629       gst_element_yield (element);
2630       break;
2631     case GST_EVENT_DISCONTINUOUS:
2632     {
2633       guint64 time;
2634       
2635       if (gst_event_discont_get_value (event, GST_FORMAT_TIME, &time)) {
2636         if (element->setclockfunc && element->clock) {
2637           gst_clock_handle_discont (element->clock, time); 
2638         }
2639       }
2640     }
2641     case GST_EVENT_FLUSH:
2642     default:
2643       return gst_pad_event_default_dispatch (pad, element, event);
2644   }
2645   return TRUE;
2646 }
2647
2648 /**
2649  * gst_pad_dispatcher:
2650  * @pad: a #GstPad to dispatch.
2651  * @dispatch: the #GstDispatcherFunction to call.
2652  * @data: gpointer user data passed to the dispatcher function.
2653  *
2654  * Invokes the given dispatcher function on all pads that are 
2655  * internally connected to the given pad. 
2656  * The GstPadDispatcherFunction should return TRUE when no further pads 
2657  * need to be processed.
2658  *
2659  * Returns: TRUE if one of the dispatcher functions returned TRUE.
2660  */
2661 gboolean
2662 gst_pad_dispatcher (GstPad *pad, GstPadDispatcherFunction dispatch, 
2663                     gpointer data)
2664 {
2665   gboolean res = FALSE;
2666   GList *int_pads, *orig;
2667   
2668   g_return_val_if_fail (pad, FALSE);
2669   g_return_val_if_fail (data, FALSE);
2670
2671   orig = int_pads = gst_pad_get_internal_connections (pad);
2672
2673   while (int_pads) {
2674     GstRealPad *int_rpad = GST_PAD_REALIZE (int_pads->data);
2675     GstRealPad *int_peer = GST_RPAD_PEER (int_rpad);
2676
2677     if (int_peer && GST_PAD_IS_USABLE (int_peer)) {
2678       res = dispatch (GST_PAD_CAST (int_peer), data);
2679       if (res)
2680         break;
2681     }
2682     int_pads = g_list_next (int_pads);
2683   }
2684
2685   g_list_free (orig);
2686   
2687   return res;
2688 }
2689
2690 /**
2691  * gst_pad_send_event:
2692  * @pad: a #GstPad to send the event to.
2693  * @event: the #GstEvent to send to the pad.
2694  *
2695  * Sends the event to the pad.
2696  *
2697  * Returns: TRUE if the event was handled.
2698  */
2699 gboolean
2700 gst_pad_send_event (GstPad *pad, GstEvent *event)
2701 {
2702   gboolean success = FALSE;
2703
2704   g_return_val_if_fail (event, FALSE);
2705
2706   if (!pad || (GST_PAD_IS_SINK (pad) && !GST_PAD_IS_USABLE (pad))) 
2707     return FALSE;
2708
2709   if (GST_EVENT_SRC (event) == NULL)
2710     GST_EVENT_SRC (event) = gst_object_ref (GST_OBJECT (pad));
2711
2712   GST_DEBUG (GST_CAT_EVENT, "have event %d on pad %s:%s",
2713                   GST_EVENT_TYPE (event), GST_DEBUG_PAD_NAME (pad));
2714
2715   if (GST_RPAD_EVENTFUNC (pad))
2716     success = GST_RPAD_EVENTFUNC (pad) (pad, event);
2717   else {
2718     GST_DEBUG (GST_CAT_EVENT, "there's no event function for pad %s:%s", 
2719                GST_DEBUG_PAD_NAME (pad));
2720     gst_event_unref (event);
2721   }
2722
2723   return success;
2724 }
2725
2726 typedef struct 
2727 {
2728   GstFormat      src_format;
2729   gint64         src_value;
2730   GstFormat      *dest_format;
2731   gint64         *dest_value;
2732 } GstPadConvertData;
2733
2734 static gboolean
2735 gst_pad_convert_dispatcher (GstPad *pad, GstPadConvertData *data)
2736 {
2737   return gst_pad_convert (pad, data->src_format, data->src_value, 
2738                                data->dest_format, data->dest_value);
2739 }
2740
2741 /**
2742  * gst_pad_convert_default:
2743  * @pad: a #GstPad to invoke the default converter on.
2744  * @src_format: the source #GstFormat.
2745  * @src_value: the source value.
2746  * @dest_format: a pointer to the destination #GstFormat.
2747  * @dest_value: a pointer to the destination value.
2748  *
2749  * Invokes the default converter on a pad. 
2750  * This will forward the call to the pad obtained 
2751  * using the internal connection of
2752  * the element.
2753  *
2754  * Returns: TRUE if the conversion could be performed.
2755  */
2756 gboolean
2757 gst_pad_convert_default (GstPad *pad, 
2758                          GstFormat src_format,  gint64  src_value,
2759                          GstFormat *dest_format, gint64 *dest_value)
2760 {
2761   GstPadConvertData data;
2762
2763   g_return_val_if_fail (pad, FALSE);
2764   g_return_val_if_fail (dest_format, FALSE);
2765   g_return_val_if_fail (dest_value, FALSE);
2766
2767   data.src_format = src_format;
2768   data.src_value = src_value;
2769   data.dest_format = dest_format;
2770   data.dest_value = dest_value;
2771
2772   return gst_pad_dispatcher (pad, (GstPadDispatcherFunction) 
2773                                     gst_pad_convert_dispatcher, &data);
2774 }
2775
2776 /**
2777  * gst_pad_convert:
2778  * @pad: a #GstPad to invoke the default converter on.
2779  * @src_format: the source #GstFormat.
2780  * @src_value: the source value.
2781  * @dest_format: a pointer to the destination #GstFormat.
2782  * @dest_value: a pointer to the destination value.
2783  *
2784  * Invokes a conversion on the pad.
2785  *
2786  * Returns: TRUE if the conversion could be performed.
2787  */
2788 gboolean
2789 gst_pad_convert (GstPad *pad, 
2790                  GstFormat src_format,  gint64  src_value,
2791                  GstFormat *dest_format, gint64 *dest_value)
2792 {
2793   GstRealPad *rpad;
2794   
2795   g_return_val_if_fail (pad, FALSE);
2796   g_return_val_if_fail (dest_format, FALSE);
2797   g_return_val_if_fail (dest_value, FALSE);
2798
2799   if (src_format == *dest_format) {
2800     *dest_value = src_value; 
2801     return TRUE;
2802   }     
2803
2804   rpad = GST_PAD_REALIZE (pad);
2805
2806   g_return_val_if_fail (rpad, FALSE);
2807
2808   if (GST_RPAD_CONVERTFUNC (rpad)) {
2809     return GST_RPAD_CONVERTFUNC (rpad) (GST_PAD_CAST (rpad), src_format, 
2810                                         src_value, dest_format, dest_value);
2811   }
2812
2813   return FALSE;
2814 }
2815
2816 typedef struct 
2817 {
2818   GstPadQueryType type;
2819   GstFormat      *format;
2820   gint64         *value;
2821 } GstPadQueryData;
2822
2823 static gboolean
2824 gst_pad_query_dispatcher (GstPad *pad, GstPadQueryData *data)
2825 {
2826   return gst_pad_query (pad, data->type, data->format, data->value);
2827 }
2828
2829 /**
2830  * gst_pad_query_default:
2831  * @pad: a #GstPad to invoke the default query on.
2832  * @type: the #GstPadQueryType of the query to perform.
2833  * @format: a pointer to the #GstFormat of the result.
2834  * @value: a pointer to the result.
2835  *
2836  * Invokes the default query function on a pad. 
2837  *
2838  * Returns: TRUE if the query could be performed.
2839  */
2840 gboolean
2841 gst_pad_query_default (GstPad *pad, GstPadQueryType type,
2842                        GstFormat *format,  gint64 *value)
2843 {
2844   GstPadQueryData data;
2845
2846   g_return_val_if_fail (pad, FALSE);
2847   g_return_val_if_fail (format, FALSE);
2848   g_return_val_if_fail (value, FALSE);
2849
2850   data.type = type;
2851   data.format = format;
2852   data.value = value;
2853
2854   return gst_pad_dispatcher (pad, (GstPadDispatcherFunction) 
2855                                    gst_pad_query_dispatcher, &data);
2856 }
2857
2858 /**
2859  * gst_pad_query:
2860  * @pad: a #GstPad to invoke the default query on.
2861  * @type: the #GstPadQueryType of the query to perform.
2862  * @format: a pointer to the #GstFormat of the result.
2863  * @value: a pointer to the result.
2864  *
2865  * Queries a pad for one of the available properties.
2866  *
2867  * Returns: TRUE if the query could be performed.
2868  */
2869 gboolean
2870 gst_pad_query (GstPad *pad, GstPadQueryType type,
2871                GstFormat *format, gint64 *value) 
2872 {
2873   GstRealPad *rpad;
2874   
2875   if (pad == NULL)
2876     return FALSE;
2877
2878   g_return_val_if_fail (format, FALSE);
2879   g_return_val_if_fail (value, FALSE);
2880
2881   rpad = GST_PAD_REALIZE (pad);
2882
2883   g_return_val_if_fail (rpad, FALSE);
2884
2885   if (GST_RPAD_QUERYFUNC (rpad))
2886     return GST_RPAD_QUERYFUNC (rpad) (GST_PAD_CAST (pad), type, format, value);
2887
2888   return FALSE;
2889 }
2890
2891 gboolean
2892 gst_pad_handles_format (GstPad *pad, GstFormat format)
2893 {
2894   const GstFormat *formats;
2895
2896   formats = gst_pad_get_formats (pad);
2897   if (!formats)
2898     return FALSE;
2899
2900   while (*formats) {
2901     if (*formats == format)
2902       return TRUE;
2903
2904     formats++;
2905   }
2906
2907   return FALSE;
2908 }
2909
2910 static gboolean
2911 gst_pad_get_formats_dispatcher (GstPad *pad, const GstFormat **data)
2912 {
2913   *data = gst_pad_get_formats (pad);
2914
2915   return TRUE;
2916 }
2917
2918 const GstFormat*
2919 gst_pad_get_formats_default (GstPad *pad)
2920 {
2921   GstFormat *result = NULL;
2922
2923   gst_pad_dispatcher (pad, (GstPadDispatcherFunction) 
2924                       gst_pad_get_formats_dispatcher, &result);
2925
2926   return result;
2927 }
2928
2929 const GstFormat*
2930 gst_pad_get_formats (GstPad *pad)
2931 {
2932   GstRealPad *rpad;
2933   
2934   if (pad == NULL)
2935     return FALSE;
2936
2937   rpad = GST_PAD_REALIZE (pad);
2938
2939   g_return_val_if_fail (rpad, FALSE);
2940
2941   if (GST_RPAD_FORMATSFUNC (rpad))
2942     return GST_RPAD_FORMATSFUNC (rpad) (GST_PAD_CAST (pad));
2943
2944   return NULL;
2945 }
2946