removed a check that was too restrictive. any errors that are not caught here will...
[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
34 GType _gst_pad_type = 0;
35
36 /***** Start with the base GstPad class *****/
37 static void             gst_pad_class_init              (GstPadClass *klass);
38 static void             gst_pad_init                    (GstPad *pad);
39
40 static gboolean         gst_pad_try_reconnect_filtered_func (GstPad *pad, GstCaps *caps, gboolean clear);
41
42 #ifndef GST_DISABLE_LOADSAVE
43 static xmlNodePtr       gst_pad_save_thyself            (GstObject *object, xmlNodePtr parent);
44 #endif
45
46 static GstObject *pad_parent_class = NULL;
47
48 GType
49 gst_pad_get_type(void) 
50 {
51   if (!_gst_pad_type) {
52     static const GTypeInfo pad_info = {
53       sizeof(GstPadClass),
54       NULL,
55       NULL,
56       (GClassInitFunc)gst_pad_class_init,
57       NULL,
58       NULL,
59       sizeof(GstPad),
60       32,
61       (GInstanceInitFunc)gst_pad_init,
62       NULL
63     };
64     _gst_pad_type = g_type_register_static(GST_TYPE_OBJECT, "GstPad", &pad_info, 0);
65   }
66   return _gst_pad_type;
67 }
68
69 static void
70 gst_pad_class_init (GstPadClass *klass)
71 {
72   pad_parent_class = g_type_class_ref(GST_TYPE_OBJECT);
73 }
74
75 static void
76 gst_pad_init (GstPad *pad)
77 {
78   pad->element_private = NULL;
79
80   pad->padtemplate = NULL;
81 }
82
83
84
85 /***** Then do the Real Pad *****/
86 /* Pad signals and args */
87 enum {
88   REAL_SET_ACTIVE,
89   REAL_CAPS_CHANGED,
90   REAL_CAPS_NEGO_FAILED,
91   REAL_CONNECTED,
92   REAL_DISCONNECTED,
93   REAL_EVENT_RECEIVED,
94   /* FILL ME */
95   REAL_LAST_SIGNAL
96 };
97
98 enum {
99   REAL_ARG_0,
100   REAL_ARG_ACTIVE,
101   /* FILL ME */
102 };
103
104 static void     gst_real_pad_class_init         (GstRealPadClass *klass);
105 static void     gst_real_pad_init               (GstRealPad *pad);
106
107 static void     gst_real_pad_set_property       (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
108 static void     gst_real_pad_get_property       (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
109
110 static void     gst_real_pad_dispose            (GObject *object);
111
112 static void     gst_pad_push_func               (GstPad *pad, GstBuffer *buf);
113
114 GType _gst_real_pad_type = 0;
115
116 static GstPad *real_pad_parent_class = NULL;
117 static guint gst_real_pad_signals[REAL_LAST_SIGNAL] = { 0 };
118
119 GType
120 gst_real_pad_get_type(void) {
121   if (!_gst_real_pad_type) {
122     static const GTypeInfo pad_info = {
123       sizeof(GstRealPadClass),
124       NULL,
125       NULL,
126       (GClassInitFunc)gst_real_pad_class_init,
127       NULL,
128       NULL,
129       sizeof(GstRealPad),
130       32,
131       (GInstanceInitFunc)gst_real_pad_init,
132       NULL
133     };
134     _gst_real_pad_type = g_type_register_static(GST_TYPE_PAD, "GstRealPad", &pad_info, 0);
135   }
136   return _gst_real_pad_type;
137 }
138
139 static void
140 gst_real_pad_class_init (GstRealPadClass *klass)
141 {
142   GObjectClass *gobject_class;
143   GstObjectClass *gstobject_class;
144
145   gobject_class = (GObjectClass*) klass;
146   gstobject_class = (GstObjectClass*) klass;
147
148   real_pad_parent_class = g_type_class_ref (GST_TYPE_PAD);
149
150   gobject_class->dispose  = GST_DEBUG_FUNCPTR (gst_real_pad_dispose);
151   gobject_class->set_property  = GST_DEBUG_FUNCPTR (gst_real_pad_set_property);
152   gobject_class->get_property  = GST_DEBUG_FUNCPTR (gst_real_pad_get_property);
153
154   gst_real_pad_signals[REAL_SET_ACTIVE] =
155     g_signal_new ("set_active", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
156                     G_STRUCT_OFFSET (GstRealPadClass, set_active), NULL, NULL,
157                     gst_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1,
158                     G_TYPE_BOOLEAN);
159   gst_real_pad_signals[REAL_CAPS_CHANGED] =
160     g_signal_new ("caps_changed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
161                     G_STRUCT_OFFSET (GstRealPadClass, caps_changed), NULL, NULL,
162                     gst_marshal_VOID__POINTER, G_TYPE_NONE, 1,
163                     G_TYPE_POINTER);
164   gst_real_pad_signals[REAL_CAPS_NEGO_FAILED] =
165     g_signal_new ("caps_nego_failed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
166                     G_STRUCT_OFFSET (GstRealPadClass, caps_nego_failed), NULL, NULL,
167                     gst_marshal_VOID__POINTER, G_TYPE_NONE, 1,
168                     G_TYPE_POINTER);
169   gst_real_pad_signals[REAL_CONNECTED] =
170     g_signal_new ("connected", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
171                     G_STRUCT_OFFSET (GstRealPadClass, connected), NULL, NULL,
172                     gst_marshal_VOID__POINTER, G_TYPE_NONE, 1,
173                     G_TYPE_POINTER);
174   gst_real_pad_signals[REAL_DISCONNECTED] =
175     g_signal_new ("disconnected", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
176                     G_STRUCT_OFFSET (GstRealPadClass, disconnected), NULL, NULL,
177                     gst_marshal_VOID__POINTER, G_TYPE_NONE, 1,
178                     G_TYPE_POINTER);
179   gst_real_pad_signals[REAL_EVENT_RECEIVED] =
180     g_signal_new ("event_received", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
181                     G_STRUCT_OFFSET (GstRealPadClass, event_received), NULL, NULL,
182                     gst_marshal_VOID__POINTER, G_TYPE_NONE, 1,
183                     G_TYPE_POINTER);
184
185 /*  gtk_object_add_arg_type ("GstRealPad::active", G_TYPE_BOOLEAN, */
186 /*                           GTK_ARG_READWRITE, REAL_ARG_ACTIVE); */
187   g_object_class_install_property (G_OBJECT_CLASS (klass), REAL_ARG_ACTIVE,
188     g_param_spec_boolean ("active", "Active", "Whether the pad is active.",
189                           TRUE,G_PARAM_READWRITE));
190
191 #ifndef GST_DISABLE_LOADSAVE
192   gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_pad_save_thyself);
193 #endif
194   gstobject_class->path_string_separator = ".";
195 }
196
197 static void
198 gst_real_pad_init (GstRealPad *pad)
199 {
200   pad->direction = GST_PAD_UNKNOWN;
201   pad->peer = NULL;
202
203   pad->sched = NULL;
204   pad->sched_private = NULL;
205
206   pad->chainfunc = NULL;
207   pad->getfunc = NULL;
208   pad->getregionfunc = NULL;
209
210   pad->chainhandler = GST_DEBUG_FUNCPTR (gst_pad_push_func);
211   pad->gethandler = NULL;
212   pad->pullregionfunc = NULL;
213
214   pad->bufferpoolfunc = NULL;
215   pad->ghostpads = NULL;
216   pad->caps = NULL;
217
218   pad->connectfunc = NULL;
219   pad->getcapsfunc = NULL;
220 }
221
222 static void
223 gst_real_pad_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
224 {
225   g_return_if_fail (GST_IS_PAD (object));
226
227   switch (prop_id) {
228     case REAL_ARG_ACTIVE:
229       if (g_value_get_boolean (value)) {
230         GST_DEBUG (GST_CAT_PADS, "activating pad %s:%s\n", GST_DEBUG_PAD_NAME (object));
231         GST_FLAG_UNSET (object, GST_PAD_DISABLED);
232       } else {
233         GST_DEBUG (GST_CAT_PADS, "de-activating pad %s:%s\n", GST_DEBUG_PAD_NAME (object));
234         GST_FLAG_SET (object, GST_PAD_DISABLED);
235       }
236       g_signal_emit (G_OBJECT (object), gst_real_pad_signals[REAL_SET_ACTIVE], 0,
237                       !GST_FLAG_IS_SET (object, GST_PAD_DISABLED));
238       break;
239     default:
240       break;
241   }
242 }
243
244 static void
245 gst_real_pad_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
246 {
247   /* it's not null if we got it, but it might not be ours */
248   g_return_if_fail (GST_IS_PAD (object));
249
250   switch (prop_id) {
251     case REAL_ARG_ACTIVE:
252       g_value_set_boolean (value, !GST_FLAG_IS_SET (object, GST_PAD_DISABLED));
253       break;
254     default:
255       break;
256   }
257 }
258
259
260 /**
261  * gst_pad_new:
262  * @name: name of new pad
263  * @direction: either GST_PAD_SRC or GST_PAD_SINK
264  *
265  * Create a new pad with given name.
266  *
267  * Returns: new pad
268  */
269 GstPad*
270 gst_pad_new (gchar *name,
271              GstPadDirection direction)
272 {
273   GstRealPad *pad;
274
275   g_return_val_if_fail (name != NULL, NULL);
276   g_return_val_if_fail (direction != GST_PAD_UNKNOWN, NULL);
277
278   pad = g_object_new (gst_real_pad_get_type (), NULL);
279   gst_object_set_name (GST_OBJECT (pad), name);
280   GST_RPAD_DIRECTION (pad) = direction;
281
282   return GST_PAD (pad);
283 }
284
285 /**
286  * gst_pad_new_from_template:
287  * @templ: the pad template to use
288  * @name: the name of the element
289  *
290  * Create a new pad with given name from the given template.
291  *
292  * Returns: new pad
293  */
294 GstPad*
295 gst_pad_new_from_template (GstPadTemplate *templ,
296                            gchar *name)
297 {
298   GstPad *pad;
299
300   g_return_val_if_fail (name != NULL, NULL);
301   g_return_val_if_fail (templ != NULL, NULL);
302
303   pad = gst_pad_new (name, templ->direction);
304   
305   gst_object_ref (GST_OBJECT (templ));
306   GST_PAD_PADTEMPLATE (pad) = templ;
307   
308   return pad;
309 }
310
311 /**
312  * gst_pad_get_direction:
313  * @pad: the Pad to get the direction from
314  *
315  * Get the direction of the pad.
316  *
317  * Returns: the direction of the pad
318  */
319 GstPadDirection
320 gst_pad_get_direction (GstPad *pad)
321 {
322   g_return_val_if_fail (pad != NULL, GST_PAD_UNKNOWN);
323   g_return_val_if_fail (GST_IS_PAD (pad), GST_PAD_UNKNOWN);
324
325   return GST_PAD_DIRECTION (pad);
326 }
327
328 /**
329  * gst_pad_set_name:
330  * @pad: the pad to set the name of
331  * @name: the name of the pad
332  *
333  * Set the name of a pad.
334  */
335 void
336 gst_pad_set_name (GstPad *pad,
337                   const gchar *name)
338 {
339   g_return_if_fail (pad != NULL);
340   g_return_if_fail (GST_IS_PAD (pad));
341
342   gst_object_set_name (GST_OBJECT (pad), name);
343 }
344
345 /**
346  * gst_pad_get_name:
347  * @pad: the pad to get the name of
348  *
349  * Get the name of a pad.
350  *
351  * Returns: the name of the pad, don't free.
352  */
353 const gchar*
354 gst_pad_get_name (GstPad *pad)
355 {
356   g_return_val_if_fail (pad != NULL, NULL);
357   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
358
359   return GST_OBJECT_NAME (pad);
360 }
361
362 /**
363  * gst_pad_set_chain_function:
364  * @pad: the pad to set the chain function for
365  * @chain: the chain function
366  *
367  * Set the given chain function for the pad.
368  */
369 void gst_pad_set_chain_function (GstPad *pad,
370                                  GstPadChainFunction chain)
371 {
372   g_return_if_fail (pad != NULL);
373   g_return_if_fail (GST_IS_REAL_PAD (pad));
374
375   GST_RPAD_CHAINFUNC(pad) = chain;
376   GST_DEBUG (GST_CAT_PADS, "chainfunc for %s:%s set to %s\n",
377              GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (chain));
378 }
379
380 /**
381  * gst_pad_set_get_function:
382  * @pad: the pad to set the get function for
383  * @get: the get function
384  *
385  * Set the given get function for the pad.
386  */
387 void
388 gst_pad_set_get_function (GstPad *pad,
389                           GstPadGetFunction get)
390 {
391   g_return_if_fail (pad != NULL);
392   g_return_if_fail (GST_IS_REAL_PAD (pad));
393
394   GST_RPAD_GETFUNC(pad) = get;
395   GST_DEBUG (GST_CAT_PADS, "getfunc for %s:%s  set to %s\n",
396              GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (get));
397 }
398
399 /**
400  * gst_pad_set_event_function:
401  * @pad: the pad to set the event handler for
402  * @event: the event handler
403  *
404  * Set the given event handler for the pad.
405  */
406 void
407 gst_pad_set_event_function (GstPad *pad,
408                             GstPadEventFunction event)
409 {
410   g_return_if_fail (pad != NULL);
411   g_return_if_fail (GST_IS_REAL_PAD (pad));
412
413   GST_RPAD_EVENTFUNC(pad) = event;
414   GST_DEBUG (GST_CAT_PADS, "eventfunc for %s:%s  set to %s\n",
415              GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (event));
416 }
417
418 /**
419  * gst_pad_set_getregion_function:
420  * @pad: the pad to set the getregion function for
421  * @getregion: the getregion function
422  *
423  * Set the given getregion function for the pad.
424  */
425 void
426 gst_pad_set_getregion_function (GstPad *pad,
427                                 GstPadGetRegionFunction getregion)
428 {
429   g_return_if_fail (pad != NULL);
430   g_return_if_fail (GST_IS_REAL_PAD (pad));
431
432   GST_RPAD_GETREGIONFUNC(pad) = getregion;
433   GST_DEBUG (GST_CAT_PADS, "getregionfunc for %s:%s set to %s\n",
434              GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (getregion));
435 }
436
437 /**
438  * gst_pad_set_connect_function:
439  * @pad: the pad to set the connect function for
440  * @connect: the connect function
441  *
442  * Set the given connect function for the pad. It will be called
443  * when the pad is connected or reconnected with caps.
444  */
445 void
446 gst_pad_set_connect_function (GstPad *pad,
447                               GstPadConnectFunction connect)
448 {
449   g_return_if_fail (pad != NULL);
450   g_return_if_fail (GST_IS_REAL_PAD (pad));
451
452   GST_RPAD_CONNECTFUNC (pad) = connect;
453   GST_DEBUG (GST_CAT_PADS, "connectfunc for %s:%s set to %s\n",
454              GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (connect));
455 }
456
457 /**
458  * gst_pad_set_getcaps_function:
459  * @pad: the pad to set the getcaps function for
460  * @getcaps: the getcaps function
461  *
462  * Set the given getcaps function for the pad.
463  */
464 void
465 gst_pad_set_getcaps_function (GstPad *pad,
466                               GstPadGetCapsFunction getcaps)
467 {
468   g_return_if_fail (pad != NULL);
469   g_return_if_fail (GST_IS_REAL_PAD (pad));
470
471   GST_RPAD_GETCAPSFUNC (pad) = getcaps;
472   GST_DEBUG (GST_CAT_PADS, "getcapsfunc for %s:%s set to %s\n",
473              GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (getcaps));
474 }
475 /**
476  * gst_pad_set_bufferpool_function:
477  * @pad: the pad to set the bufferpool function for
478  * @bufpool: the bufferpool function
479  *
480  * Set the given bufferpool function for the pad.
481  */
482 void
483 gst_pad_set_bufferpool_function (GstPad *pad,
484                                  GstPadBufferPoolFunction bufpool)
485 {
486   g_return_if_fail (pad != NULL);
487   g_return_if_fail (GST_IS_REAL_PAD (pad));
488
489   GST_RPAD_BUFFERPOOLFUNC (pad) = bufpool;
490   GST_DEBUG (GST_CAT_PADS, "bufferpoolfunc for %s:%s set to %s\n",
491              GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (bufpool));
492 }
493
494 static void
495 gst_pad_push_func(GstPad *pad, GstBuffer *buf)
496 {
497   if (GST_RPAD_CHAINFUNC (GST_RPAD_PEER (pad)) != NULL) {
498     GST_DEBUG (GST_CAT_DATAFLOW, "calling chain function %s\n",
499                GST_DEBUG_FUNCPTR_NAME (GST_RPAD_CHAINFUNC (GST_RPAD_PEER (pad))));
500     (GST_RPAD_CHAINFUNC (GST_RPAD_PEER (pad))) (pad, buf);
501   } else {
502     GST_DEBUG (GST_CAT_DATAFLOW, "default pad_push handler in place, no chain function\n");
503     g_warning ("(internal error) default pad_push in place for pad %s:%s but it has no chain function", 
504                     GST_DEBUG_PAD_NAME (pad));
505   }
506 }
507
508
509 /**
510  * gst_pad_disconnect:
511  * @srcpad: the source pad to disconnect
512  * @sinkpad: the sink pad to disconnect
513  *
514  * Disconnects the source pad from the sink pad.
515  */
516 void
517 gst_pad_disconnect (GstPad *srcpad,
518                     GstPad *sinkpad)
519 {
520   GstRealPad *realsrc, *realsink;
521
522   /* generic checks */
523   g_return_if_fail (srcpad != NULL);
524   g_return_if_fail (GST_IS_PAD (srcpad));
525   g_return_if_fail (sinkpad != NULL);
526   g_return_if_fail (GST_IS_PAD (sinkpad));
527
528   GST_INFO (GST_CAT_ELEMENT_PADS, "disconnecting %s:%s(%p) and %s:%s(%p)",
529             GST_DEBUG_PAD_NAME (srcpad), srcpad, GST_DEBUG_PAD_NAME (sinkpad), sinkpad);
530
531   /* now we need to deal with the real/ghost stuff */
532   realsrc = GST_PAD_REALIZE (srcpad);
533   realsink = GST_PAD_REALIZE (sinkpad);
534
535   g_return_if_fail (GST_RPAD_PEER (realsrc) != NULL);
536   g_return_if_fail (GST_RPAD_PEER (realsink) != NULL);
537
538   if ((GST_RPAD_DIRECTION (realsrc) == GST_PAD_SINK) &&
539       (GST_RPAD_DIRECTION (realsink) == GST_PAD_SRC)) {
540     GstRealPad *temppad;
541
542     temppad = realsrc;
543     realsrc = realsink;
544     realsink = temppad;
545   }
546   g_return_if_fail ((GST_RPAD_DIRECTION (realsrc) == GST_PAD_SRC) &&
547                     (GST_RPAD_DIRECTION (realsink) == GST_PAD_SINK));
548
549   /* first clear peers */
550   GST_RPAD_PEER (realsrc) = NULL;
551   GST_RPAD_PEER (realsink) = NULL;
552
553   /* reset the filters, both filters are refcounted once */
554   if (GST_RPAD_FILTER (realsrc)) {
555     gst_caps_unref (GST_RPAD_FILTER (realsrc));
556     GST_RPAD_FILTER (realsink) = NULL;
557     GST_RPAD_FILTER (realsrc) = NULL;
558   }
559
560   /* now tell the scheduler */
561   if (GST_PAD_PARENT (realsrc)->sched)
562     gst_scheduler_pad_disconnect (GST_PAD_PARENT (realsrc)->sched, (GstPad *)realsrc, (GstPad *)realsink);
563   else if (GST_PAD_PARENT (realsink)->sched)
564     gst_scheduler_pad_disconnect (GST_PAD_PARENT (realsink)->sched, (GstPad *)realsrc, (GstPad *)realsink);
565
566   /* fire off a signal to each of the pads telling them that they've been disconnected */
567   g_signal_emit (G_OBJECT (realsrc), gst_real_pad_signals[REAL_DISCONNECTED], 0, realsink);
568   g_signal_emit (G_OBJECT (realsink), gst_real_pad_signals[REAL_DISCONNECTED], 0, realsrc);
569
570   GST_INFO (GST_CAT_ELEMENT_PADS, "disconnected %s:%s and %s:%s",
571             GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
572 }
573
574 /**
575  * gst_pad_connect_filtered:
576  * @srcpad: the source pad to connect
577  * @sinkpad: the sink pad to connect
578  * @filtercaps: the filter caps.
579  *
580  * Connects the source pad to the sink pad. The filter indicates the media type
581  * that should flow trought this connection.
582  *
583  * Returns: TRUE if the pad could be connected, FALSE otherwise
584  */
585 gboolean
586 gst_pad_connect_filtered (GstPad *srcpad, GstPad *sinkpad, GstCaps *filtercaps)
587 {
588   GstRealPad *realsrc, *realsink;
589   gboolean negotiated = FALSE;
590   gint num_decoupled = 0;
591
592   /* generic checks */
593   g_return_val_if_fail (srcpad != NULL, FALSE);
594   g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE);
595   g_return_val_if_fail (sinkpad != NULL, FALSE);
596   g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE);
597
598   GST_INFO (GST_CAT_PADS, "connecting %s:%s and %s:%s",
599             GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
600
601   /* now we need to deal with the real/ghost stuff */
602   realsrc = GST_PAD_REALIZE (srcpad);
603   realsink = GST_PAD_REALIZE (sinkpad);
604
605   if ((GST_PAD (realsrc) != srcpad) || (GST_PAD (realsink) != sinkpad))
606     GST_INFO (GST_CAT_PADS, "*actually* connecting %s:%s and %s:%s",
607               GST_DEBUG_PAD_NAME (realsrc), GST_DEBUG_PAD_NAME (realsink));
608
609   g_return_val_if_fail (GST_RPAD_PEER (realsrc) == NULL, FALSE);
610   g_return_val_if_fail (GST_RPAD_PEER (realsink) == NULL, FALSE);
611   g_return_val_if_fail (GST_PAD_PARENT (realsrc) != NULL, FALSE);
612   g_return_val_if_fail (GST_PAD_PARENT (realsink) != NULL, FALSE);
613
614   if (realsrc->sched && realsink->sched) {
615     if (GST_FLAG_IS_SET (GST_PAD_PARENT (realsrc), GST_ELEMENT_DECOUPLED))
616       num_decoupled++;
617     if (GST_FLAG_IS_SET (GST_PAD_PARENT (realsink), GST_ELEMENT_DECOUPLED))
618       num_decoupled++;
619
620     if (realsrc->sched == realsink->sched && num_decoupled != 0) {
621       g_warning ("cannot connect pads from decoupled elements with the same sched\n");
622       return FALSE;
623     } else if (realsrc->sched != realsink->sched && num_decoupled != 1) {
624       g_warning ("connecting pads with different scheds requires exactly one decoupled element (queue)\n");
625       return FALSE;
626     }
627   }
628
629   /* check for reversed directions and swap if necessary */
630   if ((GST_RPAD_DIRECTION (realsrc) == GST_PAD_SINK) &&
631       (GST_RPAD_DIRECTION (realsink) == GST_PAD_SRC)) {
632     GstRealPad *temppad;
633
634     temppad = realsrc;
635     realsrc = realsink;
636     realsink = temppad;
637   }
638   g_return_val_if_fail ((GST_RPAD_DIRECTION (realsrc) == GST_PAD_SRC) &&
639                         (GST_RPAD_DIRECTION (realsink) == GST_PAD_SINK), FALSE);
640
641   /* first set peers */
642   GST_RPAD_PEER (realsrc) = realsink;
643   GST_RPAD_PEER (realsink) = realsrc;
644
645   if (!gst_pad_try_reconnect_filtered_func (GST_PAD (realsrc), filtercaps, FALSE)) {
646     GST_DEBUG (GST_CAT_CAPS, "pads cannot connect\n");
647
648     GST_RPAD_PEER (realsrc) = NULL;
649     GST_RPAD_PEER (realsink) = NULL;
650
651     return FALSE;
652   }
653     
654   /* fire off a signal to each of the pads telling them that they've been connected */
655   g_signal_emit (G_OBJECT (realsrc), gst_real_pad_signals[REAL_CONNECTED], 0, realsink);
656   g_signal_emit (G_OBJECT (realsink), gst_real_pad_signals[REAL_CONNECTED], 0, realsrc);
657
658   /* now tell the scheduler(s) */
659   if (realsrc->sched)
660     gst_scheduler_pad_connect (realsrc->sched, (GstPad *)realsrc, (GstPad *)realsink);
661   else if (realsink->sched)
662     gst_scheduler_pad_connect (realsink->sched, (GstPad *)realsrc, (GstPad *)realsink);
663
664   GST_INFO (GST_CAT_PADS, "connected %s:%s and %s:%s",
665             GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
666
667   return TRUE;
668 }
669
670 /**
671  * gst_pad_connect:
672  * @srcpad: the source pad to connect
673  * @sinkpad: the sink pad to connect
674  *
675  * Connects the source pad to the sink pad.
676  *
677  * Returns: TRUE if the pad could be connected, FALSE otherwise
678  */
679 gboolean
680 gst_pad_connect (GstPad *srcpad, GstPad *sinkpad)
681 {
682   return gst_pad_connect_filtered (srcpad, sinkpad, NULL);
683 }
684
685 /**
686  * gst_pad_set_parent:
687  * @pad: the pad to set the parent
688  * @parent: the object to set the parent to
689  *
690  * Sets the parent object of a pad.
691  */
692 void
693 gst_pad_set_parent (GstPad *pad,
694                     GstObject *parent)
695 {
696   g_return_if_fail (pad != NULL);
697   g_return_if_fail (GST_IS_PAD (pad));
698   g_return_if_fail (GST_PAD_PARENT (pad) == NULL);
699   g_return_if_fail (parent != NULL);
700   g_return_if_fail (GST_IS_OBJECT (parent));
701   g_return_if_fail ((gpointer)pad != (gpointer)parent);
702
703   gst_object_set_parent (GST_OBJECT (pad), parent);
704 }
705
706 /**
707  * gst_pad_get_parent:
708  * @pad: the pad to get the parent from
709  *
710  * Get the parent object of this pad.
711  *
712  * Returns: the parent object
713  */
714 GstElement*
715 gst_pad_get_parent (GstPad *pad)
716 {
717   g_return_val_if_fail (pad != NULL, NULL);
718   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
719
720   return GST_PAD_PARENT (pad);
721 }
722
723 /**
724  * gst_pad_get_padtemplate:
725  * @pad: the pad to get the padtemplate from
726  *
727  * Get the padtemplate object of this pad.
728  *
729  * Returns: the padtemplate object
730  */
731 GstPadTemplate*
732 gst_pad_get_padtemplate (GstPad *pad)
733 {
734   g_return_val_if_fail (pad != NULL, NULL);
735   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
736
737   return GST_PAD_PADTEMPLATE (pad); 
738 }
739
740
741 /**
742  * gst_pad_set_sched:
743  * @pad: the pad to set the scheduler for
744  * @sched: The scheduler to set
745  *
746  * Set the scheduler for the pad
747  */
748 void
749 gst_pad_set_sched (GstPad *pad, GstScheduler *sched)
750 {
751   g_return_if_fail (pad != NULL);
752   g_return_if_fail (GST_IS_PAD (pad));
753  
754   GST_RPAD_SCHED(pad) = sched;
755 }
756  
757 /**
758  * gst_pad_get_sched:
759  * @pad: the pad to get the scheduler from
760  *
761  * Get the scheduler of the pad
762  *
763  * Returns: the scheduler of the pad.
764  */
765 GstScheduler*
766 gst_pad_get_sched (GstPad *pad)
767 {
768   g_return_val_if_fail (pad != NULL, NULL);
769   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
770  
771   return GST_RPAD_SCHED(pad);
772 }
773
774 /**
775  * gst_pad_unset_sched:
776  * @pad: the pad to unset the scheduler for
777  *
778  * Unset the scheduler for the pad
779  */
780 void
781 gst_pad_unset_sched (GstPad *pad)
782 {
783   g_return_if_fail (pad != NULL);
784   g_return_if_fail (GST_IS_PAD (pad));
785  
786   GST_RPAD_SCHED(pad) = NULL;
787 }
788  
789 /**
790  * gst_pad_get_real_parent:
791  * @pad: the pad to get the parent from
792  *
793  * Get the real parent object of this pad. If the pad
794  * is a ghostpad, the actual owner of the real pad is
795  * returned, as opposed to the gst_pad_get_parent().
796  *
797  * Returns: the parent object
798  */
799 GstElement*
800 gst_pad_get_real_parent (GstPad *pad)
801 {
802   g_return_val_if_fail (pad != NULL, NULL);
803   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
804
805   return GST_PAD_PARENT (GST_PAD (GST_PAD_REALIZE (pad)));
806 }
807
808 /**
809  * gst_pad_add_ghost_pad:
810  * @pad: the pad to set the ghost parent
811  * @ghostpad: the ghost pad to add
812  *
813  * Add a ghost pad to a pad.
814  */
815 void
816 gst_pad_add_ghost_pad (GstPad *pad,
817                        GstPad *ghostpad)
818 {
819   GstRealPad *realpad;
820
821   g_return_if_fail (pad != NULL);
822   g_return_if_fail (GST_IS_PAD (pad));
823   g_return_if_fail (ghostpad != NULL);
824   g_return_if_fail (GST_IS_GHOST_PAD (ghostpad));
825
826   realpad = GST_PAD_REALIZE (pad);
827
828   realpad->ghostpads = g_list_prepend (realpad->ghostpads, ghostpad);
829 }
830
831
832 /**
833  * gst_pad_remove_ghost_pad:
834  * @pad: the pad to remove the ghost parent
835  * @ghostpad: the ghost pad to remove from the pad
836  *
837  * Remove a ghost pad from a pad.
838  */
839 void
840 gst_pad_remove_ghost_pad (GstPad *pad,
841                           GstPad *ghostpad)
842 {
843   GstRealPad *realpad;
844
845   g_return_if_fail (pad != NULL);
846   g_return_if_fail (GST_IS_PAD (pad));
847   g_return_if_fail (ghostpad != NULL);
848   g_return_if_fail (GST_IS_GHOST_PAD (ghostpad));
849
850   realpad = GST_PAD_REALIZE (pad);
851
852   realpad->ghostpads = g_list_remove (realpad->ghostpads, ghostpad);
853 }
854
855 /**
856  * gst_pad_get_ghost_pad_list:
857  * @pad: the pad to get the ghost parents from
858  *
859  * Get the ghost parents of this pad.
860  *
861  * Returns: a GList of ghost pads
862  */
863 GList*
864 gst_pad_get_ghost_pad_list (GstPad *pad)
865 {
866   g_return_val_if_fail (pad != NULL, NULL);
867   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
868
869   return GST_PAD_REALIZE(pad)->ghostpads;
870 }
871
872 static GstPadConnectReturn
873 gst_pad_try_set_caps_func (GstPad *pad, GstCaps *caps, gboolean notify, gboolean set_caps)
874 {
875   GstCaps *oldcaps;
876
877   GST_INFO (GST_CAT_CAPS, "trying to set caps %p on pad %s:%s",
878             caps, GST_DEBUG_PAD_NAME (pad));
879
880   if (notify && GST_RPAD_CONNECTFUNC (pad)) {
881     GstPadConnectReturn res;
882     gchar *debug_string;
883
884     GST_INFO (GST_CAT_CAPS, "calling connect function on pad %s:%s",
885             GST_DEBUG_PAD_NAME (pad));
886
887     res = GST_RPAD_CONNECTFUNC (pad) (pad, caps);
888
889     switch (res) {
890       case GST_PAD_CONNECT_REFUSED:
891         debug_string = "REFUSED";
892         break;
893       case GST_PAD_CONNECT_OK:
894         debug_string = "OK";
895         break;
896       case GST_PAD_CONNECT_DONE:
897         debug_string = "DONE";
898         break;
899       case GST_PAD_CONNECT_DELAYED:
900         debug_string = "DELAYED";
901         break;
902       default:
903         g_warning ("unknown return code from connect function of pad %s:%s",
904             GST_DEBUG_PAD_NAME (pad));
905         return GST_PAD_CONNECT_REFUSED;
906     }
907
908     GST_INFO (GST_CAT_CAPS, "got reply %s (%d) from connect function on pad %s:%s",
909             debug_string, res, GST_DEBUG_PAD_NAME (pad));
910
911     if (res == GST_PAD_CONNECT_DONE) {
912       GST_INFO (GST_CAT_CAPS, "pad %s:%s is done", GST_DEBUG_PAD_NAME (pad));
913       return GST_PAD_CONNECT_DONE;
914     }
915     if (res == GST_PAD_CONNECT_REFUSED) {
916       GST_INFO (GST_CAT_CAPS, "pad %s:%s doesn't accept caps",
917                     GST_DEBUG_PAD_NAME (pad));
918       return GST_PAD_CONNECT_REFUSED;
919     }
920   }
921   /* we can only set caps on the pad if they are ficed */
922   if (GST_CAPS_IS_FIXED (caps)) {
923
924     if (set_caps) {
925       GST_INFO (GST_CAT_CAPS, "setting caps on pad %s:%s",
926               GST_DEBUG_PAD_NAME (pad));
927       /* if we got this far all is ok */
928       oldcaps = GST_PAD_CAPS (pad);
929       if (caps) gst_caps_ref (caps);
930       GST_PAD_CAPS (pad) = caps;
931       if (oldcaps) gst_caps_unref (oldcaps);
932     }
933     else {
934       GST_INFO (GST_CAT_CAPS, "NOT setting caps on pad %s:%s, as requested",
935               GST_DEBUG_PAD_NAME (pad));
936     }
937   }
938   else {
939     GST_INFO (GST_CAT_CAPS, "caps are not fixed on pad %s:%s, not setting them yet",
940               GST_DEBUG_PAD_NAME (pad));
941   }
942
943   return GST_PAD_CONNECT_OK;
944 }
945
946 gboolean
947 gst_pad_try_set_caps (GstPad *pad, GstCaps *caps)
948 {
949   GstCaps *oldcaps;
950   GstPad *peer;
951
952   peer = GST_PAD (GST_RPAD_PEER (pad));
953
954   GST_INFO (GST_CAT_CAPS, "trying to set caps %p on pad %s:%s",
955             caps, GST_DEBUG_PAD_NAME (pad));
956
957   if (!GST_CAPS_IS_FIXED (caps)) {
958     g_warning ("trying to set non fixed caps on pad %s:%s, caps dump follow",
959             GST_DEBUG_PAD_NAME (pad));
960     gst_caps_debug (caps);
961     return FALSE;
962   }
963   if (peer && !gst_pad_try_set_caps_func (peer, caps, TRUE, TRUE))
964     return FALSE;
965   if (!gst_pad_try_set_caps_func (pad, caps, FALSE, TRUE))
966     return FALSE;
967           
968   return TRUE;
969 }
970
971
972 static gboolean
973 gst_pad_try_reconnect_filtered_func (GstPad *pad, GstCaps *filtercaps, gboolean clear)
974 {
975   GstCaps *srccaps, *sinkcaps;
976   GstCaps *intersection = NULL;
977   GstRealPad *realsrc, *realsink;
978
979   g_return_val_if_fail (pad != NULL, FALSE);
980
981   realsrc = GST_PAD_REALIZE (pad);
982   realsink = GST_PAD_REALIZE (GST_RPAD_PEER (realsrc));
983
984   g_return_val_if_fail (GST_RPAD_PEER (realsrc) != NULL, FALSE);
985   g_return_val_if_fail (GST_RPAD_PEER (realsink) != NULL, FALSE);
986
987   GST_INFO (GST_CAT_PADS, "reconnect filtered %s:%s and %s:%s",
988         GST_DEBUG_PAD_NAME (realsrc), GST_DEBUG_PAD_NAME (realsink));
989
990   if (clear) {
991     GST_INFO (GST_CAT_PADS, "reconnect filtered %s:%s and %s:%s, clearing caps",
992         GST_DEBUG_PAD_NAME (realsrc), GST_DEBUG_PAD_NAME (realsink));
993
994     GST_PAD_CAPS (GST_PAD (realsrc)) = NULL;
995     GST_PAD_CAPS (GST_PAD (realsink)) = NULL;
996   }
997
998   srccaps = gst_pad_get_caps (GST_PAD (realsrc));
999   GST_INFO (GST_CAT_PADS, "dumping caps of pad %s:%s", GST_DEBUG_PAD_NAME (realsrc));
1000   gst_caps_debug (srccaps);
1001   sinkcaps = gst_pad_get_caps (GST_PAD (realsink));
1002   GST_INFO (GST_CAT_PADS, "dumping caps of pad %s:%s", GST_DEBUG_PAD_NAME (realsink));
1003   gst_caps_debug (sinkcaps);
1004
1005   intersection = gst_caps_intersect (srccaps, sinkcaps);
1006
1007   /* if we have no intersection but one of the caps was not NULL.. */
1008   if (!intersection && (srccaps || sinkcaps )) {
1009     /* the intersection is NULL, this means they have no common format */
1010     GST_INFO (GST_CAT_PADS, "pads %s:%s and %s:%s have no common type",
1011          GST_DEBUG_PAD_NAME (realsrc), GST_DEBUG_PAD_NAME (realsink));
1012     return FALSE;
1013   }
1014   else {
1015     GST_INFO (GST_CAT_PADS, "pads %s:%s and %s:%s intersected to %s caps",
1016          GST_DEBUG_PAD_NAME (realsrc), GST_DEBUG_PAD_NAME (realsink), 
1017          ((intersection && GST_CAPS_IS_FIXED (intersection)) ? "fixed" : "variable"));
1018
1019     if (filtercaps) {
1020       GstCaps *filtered_intersection = gst_caps_intersect (intersection, filtercaps);
1021
1022       /* get rid of the old intersection here */
1023       gst_caps_unref (intersection);
1024
1025       if (!filtered_intersection) {
1026         GST_INFO (GST_CAT_PADS, "filtered connection between pads %s:%s and %s:%s is empty, disconnecting",
1027              GST_DEBUG_PAD_NAME (realsrc), GST_DEBUG_PAD_NAME (realsink));
1028         return FALSE;
1029       }
1030       intersection = filtered_intersection;
1031
1032       GST_RPAD_APPFILTER (realsink) = filtercaps;
1033       GST_RPAD_APPFILTER (realsrc) = filtercaps;
1034     }
1035   }
1036   GST_DEBUG (GST_CAT_CAPS, "setting filter for connection to:\n");
1037   gst_caps_debug (intersection);
1038
1039   GST_RPAD_FILTER (realsrc) = intersection; 
1040   GST_RPAD_FILTER (realsink) = intersection; 
1041
1042   if (intersection) {
1043     GstPadConnectReturn res;
1044
1045     res = gst_pad_try_set_caps_func (GST_PAD (realsrc), intersection, TRUE, TRUE);
1046     if (res == GST_PAD_CONNECT_REFUSED) 
1047       return FALSE;
1048     if (res == GST_PAD_CONNECT_DONE) 
1049       return TRUE;
1050
1051     res = gst_pad_try_set_caps_func (GST_PAD (realsink), intersection, TRUE, TRUE);
1052     if (res == GST_PAD_CONNECT_REFUSED) 
1053       return FALSE;
1054     if (res == GST_PAD_CONNECT_DONE) 
1055       return TRUE;
1056   }
1057
1058   return TRUE;
1059 }
1060
1061 /**
1062  * gst_pad_try_reconnect_filtered:
1063  * @pad: the pad to reconnect
1064  * @caps: the capabilities to use in the reconnectiong
1065  *
1066  * Try to reconnect this pad and its peer with the specified caps
1067  *
1068  * Returns: a boolean indicating the peer pad could accept the caps.
1069  */
1070 gboolean
1071 gst_pad_try_reconnect_filtered (GstPad *pad, GstCaps *filtercaps)
1072 {
1073   g_return_val_if_fail (pad != NULL, FALSE);
1074   g_return_val_if_fail (GST_IS_REAL_PAD (pad), FALSE);  
1075   g_return_val_if_fail (GST_PAD_IS_CONNECTED (pad), FALSE);
1076   
1077   return gst_pad_try_reconnect_filtered_func (pad, filtercaps, TRUE);
1078 }
1079
1080 /**
1081  * gst_pad_reconnect_filtered:
1082  * @pad: the pad to reconnect
1083  * @caps: the capabilities to use in the reconnectiong
1084  *
1085  * Try to reconnect this pad and its peer with the specified caps. 
1086  *
1087  * Returns: a boolean indicating the peer pad could accept the caps.
1088  *    if FALSE is returned, the pads are disconnected.
1089  */
1090 gboolean
1091 gst_pad_reconnect_filtered (GstPad *pad, GstCaps *filtercaps)
1092 {
1093   g_return_val_if_fail (pad != NULL, FALSE);
1094   g_return_val_if_fail (GST_IS_REAL_PAD (pad), FALSE);
1095   g_return_val_if_fail (GST_PAD_IS_CONNECTED (pad), FALSE);
1096
1097   if (!gst_pad_try_reconnect_filtered_func (pad, filtercaps, TRUE)) {
1098     gst_pad_disconnect (pad, GST_PAD (GST_PAD_PEER (pad)));
1099     return FALSE;
1100   }
1101   return TRUE;
1102 }
1103
1104 /**
1105  * gst_pad_proxy_connect:
1106  * @pad: the pad to proxy to
1107  * @caps: the capabilities to use in the proxying
1108  *
1109  * Proxy the connect function to the specified pad.
1110  *
1111  * Returns: a boolean indicating the peer pad could accept the caps.
1112  */
1113 GstPadConnectReturn
1114 gst_pad_proxy_connect (GstPad *pad, GstCaps *caps)
1115 {
1116   GstPad *peer;
1117
1118   peer = GST_PAD (GST_RPAD_PEER (pad));
1119
1120   GST_INFO (GST_CAT_CAPS, "proxy connect to pad %s:%s",
1121             GST_DEBUG_PAD_NAME (pad));
1122
1123   if (peer && !gst_pad_try_set_caps_func (peer, caps, TRUE, TRUE))
1124     return GST_PAD_CONNECT_REFUSED;
1125   if (!gst_pad_try_set_caps_func (pad, caps, FALSE, TRUE))
1126     return GST_PAD_CONNECT_REFUSED;
1127
1128   return GST_PAD_CONNECT_OK;
1129 }
1130
1131 /**
1132  * gst_pad_get_caps:
1133  * @pad: the pad to get the capabilities from
1134  *
1135  * Get the capabilities of this pad.
1136  *
1137  * Returns: the capabilities of this pad
1138  */
1139 GstCaps*
1140 gst_pad_get_caps (GstPad *pad)
1141 {
1142   g_return_val_if_fail (pad != NULL, NULL);
1143   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
1144
1145   GST_DEBUG (GST_CAT_CAPS, "get pad caps of %s:%s (%p)\n",
1146             GST_DEBUG_PAD_NAME (pad), pad);
1147
1148   if (GST_PAD_CAPS (pad)) {
1149     GST_DEBUG (GST_CAT_CAPS, "using pad real caps\n");
1150     return GST_PAD_CAPS (pad);
1151   }
1152   else if GST_RPAD_GETCAPSFUNC (pad) {
1153     GST_DEBUG (GST_CAT_CAPS, "using pad get function\n");
1154     return GST_RPAD_GETCAPSFUNC (pad) (pad, NULL);
1155   }
1156   else if (GST_PAD_PADTEMPLATE (pad)) {
1157     GST_DEBUG (GST_CAT_CAPS, "using pad template\n");
1158     return GST_PADTEMPLATE_CAPS (GST_PAD_PADTEMPLATE (pad));
1159   }
1160   GST_DEBUG (GST_CAT_CAPS, "pad has no caps\n");
1161
1162   return NULL;
1163 }
1164
1165 /**
1166  * gst_pad_get_padtemplate_caps:
1167  * @pad: the pad to get the capabilities from
1168  *
1169  * Get the capabilities of this pad.
1170  *
1171  * Returns: a list of the capabilities of this pad
1172  */
1173 GstCaps*
1174 gst_pad_get_padtemplate_caps (GstPad *pad)
1175 {
1176   g_return_val_if_fail (pad != NULL, NULL);
1177   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
1178
1179   if (GST_PAD_PADTEMPLATE (pad))
1180     return GST_PADTEMPLATE_CAPS (GST_PAD_PADTEMPLATE (pad));
1181
1182   return NULL;
1183 }
1184
1185
1186 /**
1187  * gst_padtemplate_get_caps_by_name:
1188  * @templ: the padtemplate to get the capabilities from
1189  * @name: the name of the capability to get
1190  *
1191  * Get the capability with the given name from this padtemplate.
1192  *
1193  * Returns: a capability or NULL if not found
1194  */
1195 GstCaps*
1196 gst_padtemplate_get_caps_by_name (GstPadTemplate *templ, const gchar *name)
1197 {
1198   GstCaps *caps;
1199
1200   g_return_val_if_fail (templ != NULL, NULL);
1201
1202   caps = GST_PADTEMPLATE_CAPS (templ);
1203   if (!caps) 
1204     return NULL;
1205
1206   return gst_caps_get_by_name (caps, name);
1207 }
1208
1209 /**
1210  * gst_pad_check_compatibility:
1211  * @srcpad: the srcpad to check
1212  * @sinkpad: the sinkpad to check against
1213  *
1214  * Check if two pads have compatible capabilities.
1215  *
1216  * Returns: TRUE if they are compatible or the capabilities
1217  * could not be checked
1218  */
1219 gboolean
1220 gst_pad_check_compatibility (GstPad *srcpad, GstPad *sinkpad)
1221 {
1222   g_return_val_if_fail (srcpad != NULL, FALSE);
1223   g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE);
1224   g_return_val_if_fail (sinkpad != NULL, FALSE);
1225   g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE);
1226
1227   if (GST_PAD_CAPS (srcpad) && GST_PAD_CAPS (sinkpad)) {
1228     if (!gst_caps_check_compatibility (GST_PAD_CAPS (srcpad), GST_PAD_CAPS (sinkpad))) {
1229       return FALSE;
1230     }
1231     else {
1232       return TRUE;
1233     }
1234   }
1235   else {
1236     GST_DEBUG (GST_CAT_PADS, "could not check capabilities of pads (%s:%s) and (%s:%s) %p %p\n",
1237                     GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad), 
1238                     GST_PAD_CAPS (srcpad), GST_PAD_CAPS (sinkpad));
1239     return TRUE;
1240   }
1241 }
1242
1243 /**
1244  * gst_pad_get_peer:
1245  * @pad: the pad to get the peer from
1246  *
1247  * Get the peer pad of this pad.
1248  *
1249  * Returns: the peer pad
1250  */
1251 GstPad*
1252 gst_pad_get_peer (GstPad *pad)
1253 {
1254   g_return_val_if_fail (pad != NULL, NULL);
1255   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
1256
1257   return GST_PAD (GST_PAD_PEER (pad));
1258 }
1259
1260 /**
1261  * gst_pad_get_allowed_caps:
1262  * @pad: the pad to get the allowed caps from
1263  *
1264  * Gst the caps of the allowed media types that can
1265  * go through this pad.
1266  *
1267  * Returns: the allowed caps
1268  */
1269 GstCaps*
1270 gst_pad_get_allowed_caps (GstPad *pad)
1271 {
1272   GstRealPad *peer;
1273   
1274   g_return_val_if_fail (pad != NULL, NULL);
1275   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
1276
1277   peer = GST_RPAD_PEER (pad);
1278
1279   GST_DEBUG (GST_CAT_PROPERTIES, "get allowed caps of %s:%s\n", GST_DEBUG_PAD_NAME (pad));
1280   /* this is not very correct: ... 
1281   if (peer && GST_RPAD_GETCAPSFUNC (peer)) {
1282     GST_DEBUG (GST_CAT_PROPERTIES, "using getcaps function of peer %s:%s\n", 
1283                     GST_DEBUG_PAD_NAME (peer));
1284     return GST_RPAD_GETCAPSFUNC (peer) (GST_PAD (peer), NULL);
1285   }
1286   */
1287   return gst_caps_copy (GST_RPAD_FILTER (pad));
1288 }
1289
1290 /**
1291  * gst_pad_get_allowed_caps:
1292  * @pad: the pad to get the allowed caps from
1293  *
1294  * Gst the caps of the allowed media types that can
1295  * go through this pad.
1296  *
1297  * Returns: the allowed caps
1298  */
1299 gboolean
1300 gst_pad_recalc_allowed_caps (GstPad *pad)
1301 {
1302   GstRealPad *peer;
1303
1304   g_return_if_fail (pad != NULL);
1305   g_return_if_fail (GST_IS_PAD (pad));
1306
1307   GST_DEBUG (GST_CAT_PROPERTIES, "set allowed caps of %s:%s\n", GST_DEBUG_PAD_NAME (pad));
1308
1309   peer = GST_RPAD_PEER (pad);
1310   if (peer)
1311     gst_pad_try_reconnect_filtered (pad, GST_RPAD_APPFILTER (pad));
1312 }
1313
1314 /**
1315  * gst_pad_get_bufferpool:
1316  * @pad: the pad to get the bufferpool from
1317  *
1318  * Get the bufferpool of the peer pad of the given
1319  * pad
1320  *
1321  * Returns: The GstBufferPool or NULL.
1322  */
1323 GstBufferPool*          
1324 gst_pad_get_bufferpool (GstPad *pad)
1325 {
1326   GstRealPad *peer;
1327
1328   g_return_val_if_fail (pad != NULL, NULL);
1329   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
1330    
1331   peer = GST_RPAD_PEER (pad);
1332
1333   if (!peer)
1334     return NULL;
1335
1336   GST_DEBUG_ENTER ("(%s:%s)", GST_DEBUG_PAD_NAME (pad));
1337
1338   if (peer->bufferpoolfunc) {
1339     GST_DEBUG (GST_CAT_PADS, "calling bufferpoolfunc &%s (@%p) of peer pad %s:%s\n",
1340       GST_DEBUG_FUNCPTR_NAME (peer->bufferpoolfunc), &peer->bufferpoolfunc, GST_DEBUG_PAD_NAME (((GstPad*) peer)));
1341     return (peer->bufferpoolfunc) (((GstPad*) peer));
1342   } else {
1343     GST_DEBUG (GST_CAT_PADS, "no bufferpoolfunc for peer pad %s:%s at %p\n",
1344                     GST_DEBUG_PAD_NAME (((GstPad*) peer)), &peer->bufferpoolfunc);
1345     return NULL;
1346   }
1347 }
1348
1349 static void
1350 gst_real_pad_dispose (GObject *object)
1351 {
1352   GstPad *pad = GST_PAD (object);
1353   
1354   GST_DEBUG (GST_CAT_REFCOUNTING, "dispose %s:%s\n", GST_DEBUG_PAD_NAME(pad));
1355
1356   if (GST_PAD (pad)->padtemplate){
1357     GST_DEBUG (GST_CAT_REFCOUNTING, "unreffing padtemplate'%s'\n",GST_OBJECT_NAME(GST_OBJECT (GST_PAD (pad)->padtemplate)));
1358     gst_object_unref (GST_OBJECT (GST_PAD (pad)->padtemplate));
1359   }
1360   
1361   if (GST_PAD_PEER (pad)){
1362     GST_DEBUG (GST_CAT_REFCOUNTING, "disconnecting pad '%s'\n",GST_OBJECT_NAME(GST_OBJECT (GST_PAD (GST_PAD_PEER (pad)))));
1363     gst_pad_disconnect (pad, GST_PAD (GST_PAD_PEER (pad)));
1364   }
1365   
1366   /* we destroy the ghostpads, because they are nothing without the real pad  */
1367   if (GST_REAL_PAD (pad)->ghostpads) {
1368     GList *orig, *ghostpads;
1369
1370     orig = ghostpads = g_list_copy (GST_REAL_PAD (pad)->ghostpads);
1371
1372     while (ghostpads) {
1373       GstPad *ghostpad = GST_PAD (ghostpads->data);
1374
1375       if (GST_IS_ELEMENT (GST_OBJECT_PARENT (ghostpad))){
1376         GST_DEBUG (GST_CAT_REFCOUNTING, "removing ghost pad from element '%s'\n", 
1377                         GST_OBJECT_NAME (GST_OBJECT_PARENT (ghostpad)));
1378
1379         gst_element_remove_ghost_pad (GST_ELEMENT (GST_OBJECT_PARENT (ghostpad)), GST_PAD (ghostpad));
1380       }
1381       ghostpads = g_list_next (ghostpads);
1382     }
1383     g_list_free (orig);
1384     g_list_free (GST_REAL_PAD(pad)->ghostpads);
1385   }
1386
1387   if (GST_IS_ELEMENT (GST_OBJECT_PARENT (pad))){
1388     GST_DEBUG (GST_CAT_REFCOUNTING, "removing pad from element '%s'\n",
1389                     GST_OBJECT_NAME (GST_OBJECT (GST_ELEMENT (GST_OBJECT_PARENT (pad)))));
1390     
1391     gst_element_remove_pad (GST_ELEMENT (GST_OBJECT_PARENT (pad)), pad);
1392   }
1393   
1394   G_OBJECT_CLASS (real_pad_parent_class)->dispose (object);
1395 }
1396
1397
1398 #ifndef GST_DISABLE_LOADSAVE
1399 /**
1400  * gst_pad_load_and_connect:
1401  * @self: the XML node to read the description from
1402  * @parent: the element that has the pad
1403  *
1404  * Read the pad definition from the XML node and connect the given pad
1405  * in element to a pad of an element up in the hierarchy.
1406  */
1407 void
1408 gst_pad_load_and_connect (xmlNodePtr self,
1409                           GstObject *parent)
1410 {
1411   xmlNodePtr field = self->xmlChildrenNode;
1412   GstPad *pad = NULL, *targetpad;
1413   guchar *peer = NULL;
1414   gchar **split;
1415   GstElement *target;
1416   GstObject *grandparent;
1417
1418   while (field) {
1419     if (!strcmp (field->name, "name")) {
1420       pad = gst_element_get_pad (GST_ELEMENT (parent), xmlNodeGetContent (field));
1421     }
1422     else if (!strcmp(field->name, "peer")) {
1423       peer = xmlNodeGetContent (field);
1424     }
1425     field = field->next;
1426   }
1427   g_return_if_fail (pad != NULL);
1428
1429   if (peer == NULL) return;
1430
1431   split = g_strsplit (peer, ".", 2);
1432
1433   g_return_if_fail (split[0] != NULL);
1434   g_return_if_fail (split[1] != NULL);
1435
1436   grandparent = gst_object_get_parent (parent);
1437
1438   if (grandparent && GST_IS_BIN (grandparent)) {
1439     target = gst_bin_get_by_name_recurse_up (GST_BIN (grandparent), split[0]);
1440   }
1441   else
1442     goto cleanup;
1443
1444   if (target == NULL) goto cleanup;
1445
1446   targetpad = gst_element_get_pad (target, split[1]);
1447
1448   if (targetpad == NULL) goto cleanup;
1449
1450   gst_pad_connect (pad, targetpad);
1451
1452 cleanup:
1453   g_strfreev (split);
1454 }
1455
1456 /**
1457  * gst_pad_save_thyself:
1458  * @pad: the pad to save
1459  * @parent: the parent XML node to save the description in
1460  *
1461  * Saves the pad into an xml representation
1462  *
1463  * Returns: the xml representation of the pad
1464  */
1465 static xmlNodePtr
1466 gst_pad_save_thyself (GstObject *object,
1467                       xmlNodePtr parent)
1468 {
1469   GstRealPad *realpad;
1470   GstPad *peer;
1471
1472   g_return_val_if_fail (GST_IS_REAL_PAD (object), NULL);
1473
1474   realpad = GST_REAL_PAD(object);
1475
1476   xmlNewChild(parent,NULL,"name", GST_PAD_NAME (realpad));
1477   if (GST_RPAD_PEER(realpad) != NULL) {
1478     peer = GST_PAD(GST_RPAD_PEER(realpad));
1479     /* first check to see if the peer's parent's parent is the same */
1480     /* we just save it off */
1481     xmlNewChild(parent,NULL,"peer",g_strdup_printf("%s.%s",
1482                     GST_OBJECT_NAME (GST_PAD_PARENT (peer)), GST_PAD_NAME (peer)));
1483   } else
1484     xmlNewChild(parent,NULL,"peer","");
1485
1486   return parent;
1487 }
1488
1489 /**
1490  * gst_pad_ghost_save_thyself:
1491  * @pad: the pad to save
1492  * @bin: the bin
1493  * @parent: the parent XML node to save the description in
1494  *
1495  * Saves the ghost pad into an xml representation.
1496  *
1497  * Returns: the xml representation of the pad
1498  */
1499 xmlNodePtr
1500 gst_pad_ghost_save_thyself (GstPad *pad,
1501                             GstElement *bin,
1502                             xmlNodePtr parent)
1503 {
1504   xmlNodePtr self;
1505
1506   g_return_val_if_fail (GST_IS_GHOST_PAD (pad), NULL);
1507
1508   self = xmlNewChild(parent,NULL,"ghostpad",NULL);
1509   xmlNewChild(self,NULL,"name", GST_PAD_NAME (pad));
1510   xmlNewChild(self,NULL,"parent", GST_OBJECT_NAME (GST_PAD_PARENT (pad)));
1511
1512   /* FIXME FIXME FIXME! */
1513
1514   return self;
1515 }
1516 #endif /* GST_DISABLE_LOADSAVE */
1517
1518 #ifndef gst_pad_push
1519 /**
1520  * gst_pad_push:
1521  * @pad: the pad to push
1522  * @buf: the buffer to push
1523  *
1524  * Push a buffer to the peer of the pad.
1525  */
1526 void 
1527 gst_pad_push (GstPad *pad, GstBuffer *buf) 
1528 {
1529   GstRealPad *peer = GST_RPAD_PEER (pad);
1530
1531   GST_DEBUG_ENTER ("(%s:%s)", GST_DEBUG_PAD_NAME (pad));
1532
1533   g_return_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SRC);
1534
1535   if (!peer) {
1536     g_warning ("push on pad %s:%s but it is unconnected", GST_DEBUG_PAD_NAME (pad));
1537   }
1538   else {
1539     if (peer->chainhandler) {
1540       if (buf) {
1541         GST_DEBUG (GST_CAT_DATAFLOW, "calling chainhandler &%s of peer pad %s:%s\n",
1542             GST_DEBUG_FUNCPTR_NAME (peer->chainhandler), GST_DEBUG_PAD_NAME (GST_PAD (peer)));
1543         (peer->chainhandler) (GST_PAD_CAST (peer), buf);
1544         return;
1545       }
1546       else {
1547         g_warning ("trying to push a NULL buffer on pad %s:%s", GST_DEBUG_PAD_NAME (peer));
1548         return;
1549       }
1550     } 
1551     else {
1552       g_warning ("(internal error) push on pad %s:%s but it has no chainhandler", GST_DEBUG_PAD_NAME (peer));
1553     }
1554   }
1555   /* clean up the mess here */
1556   if (buf != NULL) {
1557     if (GST_IS_BUFFER (buf))
1558       gst_buffer_unref (buf);
1559     else
1560       gst_event_free (GST_EVENT (buf));
1561   }
1562 }
1563 #endif
1564
1565 #ifndef gst_pad_pull
1566 /**
1567  * gst_pad_pull:
1568  * @pad: the pad to pull
1569  *
1570  * Pull a buffer from the peer pad.
1571  *
1572  * Returns: a new buffer from the peer pad.
1573  */
1574 GstBuffer*
1575 gst_pad_pull (GstPad *pad) 
1576 {
1577   GstRealPad *peer = GST_RPAD_PEER(pad);
1578   
1579   GST_DEBUG_ENTER("(%s:%s)",GST_DEBUG_PAD_NAME(pad));
1580
1581   g_return_val_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SINK, NULL);
1582
1583   if (!peer) {
1584     gst_element_error (GST_PAD_PARENT (pad), 
1585                     "pull on pad %s:%s but it was unconnected", 
1586                     GST_ELEMENT_NAME (GST_PAD_PARENT (pad)), GST_PAD_NAME (pad),
1587                     NULL);
1588   }
1589   else {
1590     if (peer->gethandler) {
1591       GstBuffer *buf;
1592
1593       GST_DEBUG (GST_CAT_DATAFLOW, "calling gethandler %s of peer pad %s:%s\n",
1594         GST_DEBUG_FUNCPTR_NAME (peer->gethandler), GST_DEBUG_PAD_NAME (peer));
1595
1596       buf = (peer->gethandler) (GST_PAD_CAST (peer));
1597       if (buf)
1598         return buf;
1599       /* no null buffers allowed */
1600       gst_element_error (GST_PAD_PARENT (pad), 
1601                     "NULL buffer during pull on %s:%s", GST_DEBUG_PAD_NAME (pad), NULL);
1602           
1603     } else {
1604       gst_element_error (GST_PAD_PARENT (pad), 
1605                     "(internal error) pull on pad %s:%s but the peer pad %s:%s has no gethandler", 
1606                     GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (peer),
1607                     NULL);
1608     }
1609   }
1610   return NULL;
1611 }
1612 #endif
1613
1614 #ifndef gst_pad_pullregion
1615 /**
1616  * gst_pad_pullregion:
1617  * @pad: the pad to pull the region from
1618  * @type: the regiontype
1619  * @offset: the offset/start of the buffer to pull
1620  * @len: the length of the buffer to pull
1621  *
1622  * Pull a buffer region from the peer pad. The region to pull can be 
1623  * specified with a offset/lenght pair or with a start/legnth time
1624  * indicator as specified by the type parameter.
1625  *
1626  * Returns: a new buffer from the peer pad with data in the specified
1627  * region.
1628  */
1629 GstBuffer*
1630 gst_pad_pullregion (GstPad *pad, GstRegionType type, guint64 offset, guint64 len) 
1631 {
1632   GstRealPad *peer;
1633   GstBuffer *result = NULL;
1634   
1635   g_return_val_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SINK, NULL);
1636
1637   do {
1638     peer = GST_RPAD_PEER(pad);
1639     g_return_val_if_fail (peer != NULL, NULL);
1640
1641     if (result) 
1642       gst_buffer_unref (result);
1643
1644     GST_DEBUG_ENTER("(%s:%s,%d,%lld,%lld)",GST_DEBUG_PAD_NAME(pad),type,offset,len);
1645
1646     if (peer->pullregionfunc) {
1647       GST_DEBUG (GST_CAT_DATAFLOW, "calling pullregionfunc &%s of peer pad %s:%s\n",
1648           GST_DEBUG_FUNCPTR_NAME (peer->pullregionfunc), GST_DEBUG_PAD_NAME(GST_PAD_CAST (peer)));
1649       result = (peer->pullregionfunc) (GST_PAD_CAST (peer), type, offset, len);
1650     } else {
1651       GST_DEBUG (GST_CAT_DATAFLOW,"no pullregionfunc\n");
1652       result = NULL;
1653       break;
1654     }
1655   }
1656   /* FIXME */
1657   while (result && !(GST_BUFFER_OFFSET (result) == offset && 
1658            GST_BUFFER_SIZE (result) == len));
1659
1660   return result;
1661 }
1662 #endif
1663
1664 /**
1665  * gst_pad_peek:
1666  * @pad: the pad to peek
1667  *
1668  * Peek for a buffer from the peer pad.
1669  *
1670  * Returns: a from the peer pad or NULL if the peer has no buffer.
1671  */
1672 GstBuffer*
1673 gst_pad_peek (GstPad *pad)
1674 {
1675   g_return_val_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SINK, NULL);
1676
1677   return GST_RPAD_BUFPEN (GST_RPAD_PEER (pad));
1678 }
1679
1680 /**
1681  * gst_pad_select:
1682  * @padlist: A list of pads 
1683  *
1684  * Wait for a buffer on the list of pads.
1685  *
1686  * Returns: The pad that has a buffer available, use 
1687  * #gst_pad_pull to get the buffer.
1688  */
1689 GstPad*
1690 gst_pad_select (GList *padlist)
1691 {
1692   GstPad *pad;
1693
1694   pad = gst_scheduler_pad_select (GST_PAD_PARENT (padlist->data)->sched, padlist);
1695
1696   return pad;
1697 }
1698
1699 /**
1700  * gst_pad_selectv:
1701  * @pad: The first pad to perform the select on 
1702  * @...: More pads
1703  *
1704  * Wait for a buffer on the given of pads.
1705  *
1706  * Returns: The pad that has a buffer available, use 
1707  * #gst_pad_pull to get the buffer.
1708  */
1709 GstPad*
1710 gst_pad_selectv (GstPad *pad, ...)
1711 {
1712   GstPad *result;
1713   GList *padlist = NULL;
1714   va_list var_args;
1715
1716   if (pad == NULL)
1717     return NULL;
1718
1719   va_start (var_args, pad);
1720
1721   while (pad) {
1722     padlist = g_list_prepend (padlist, pad);
1723     pad = va_arg (var_args, GstPad *);
1724   }
1725   result = gst_pad_select (padlist);
1726   g_list_free (padlist);
1727
1728   va_end (var_args);
1729   
1730   return result;
1731 }
1732
1733 /************************************************************************
1734  *
1735  * templates
1736  *
1737  */
1738 static void             gst_padtemplate_class_init      (GstPadTemplateClass *klass);
1739 static void             gst_padtemplate_init            (GstPadTemplate *templ);
1740
1741 enum {
1742   TEMPL_PAD_CREATED,
1743   /* FILL ME */
1744   TEMPL_LAST_SIGNAL
1745 };
1746
1747 static GstObject *padtemplate_parent_class = NULL;
1748 static guint gst_padtemplate_signals[TEMPL_LAST_SIGNAL] = { 0 };
1749
1750 GType
1751 gst_padtemplate_get_type (void)
1752 {
1753   static GType padtemplate_type = 0;
1754
1755   if (!padtemplate_type) {
1756     static const GTypeInfo padtemplate_info = {
1757       sizeof(GstPadTemplateClass),
1758       NULL,
1759       NULL,
1760       (GClassInitFunc)gst_padtemplate_class_init,
1761       NULL,
1762       NULL,
1763       sizeof(GstPadTemplate),
1764       32,
1765       (GInstanceInitFunc)gst_padtemplate_init,
1766       NULL
1767     };
1768     padtemplate_type = g_type_register_static(GST_TYPE_OBJECT, "GstPadTemplate", &padtemplate_info, 0);
1769   }
1770   return padtemplate_type;
1771 }
1772
1773 static void
1774 gst_padtemplate_class_init (GstPadTemplateClass *klass)
1775 {
1776   GObjectClass *gobject_class;
1777   GstObjectClass *gstobject_class;
1778
1779   gobject_class = (GObjectClass*)klass;
1780   gstobject_class = (GstObjectClass*)klass;
1781
1782   padtemplate_parent_class = g_type_class_ref(GST_TYPE_OBJECT);
1783
1784   gst_padtemplate_signals[TEMPL_PAD_CREATED] =
1785     g_signal_new ("pad_created", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
1786                     G_STRUCT_OFFSET (GstPadTemplateClass, pad_created), NULL, NULL,
1787                     gst_marshal_VOID__POINTER, G_TYPE_NONE, 1,
1788                     G_TYPE_POINTER);
1789
1790
1791   gstobject_class->path_string_separator = "*";
1792 }
1793
1794 static void
1795 gst_padtemplate_init (GstPadTemplate *templ)
1796 {
1797 }
1798
1799 /**
1800  * gst_padtemplate_new:
1801  * @name_template: the name template
1802  * @direction: the direction for the template
1803  * @presence: the presence of the pad
1804  * @caps: a list of capabilities for the template
1805  * @...: more capabilities
1806  *
1807  * Creates a new padtemplate from the given arguments.
1808  *
1809  * Returns: the new padtemplate
1810  */
1811 GstPadTemplate*
1812 gst_padtemplate_new (gchar *name_template,
1813                      GstPadDirection direction, GstPadPresence presence,
1814                      GstCaps *caps, ...)
1815 {
1816   GstPadTemplate *new;
1817   va_list var_args;
1818   GstCaps *thecaps = NULL;
1819
1820   g_return_val_if_fail (name_template != NULL, NULL);
1821
1822   new = g_object_new(gst_padtemplate_get_type () ,NULL);
1823
1824   GST_PADTEMPLATE_NAME_TEMPLATE (new) = name_template;
1825   GST_PADTEMPLATE_DIRECTION (new) = direction;
1826   GST_PADTEMPLATE_PRESENCE (new) = presence;
1827
1828   va_start (var_args, caps);
1829
1830   while (caps) {
1831     new->fixed &= caps->fixed;
1832     thecaps = gst_caps_append (thecaps, caps);
1833     caps = va_arg (var_args, GstCaps*);
1834   }
1835   va_end (var_args);
1836   
1837   GST_PADTEMPLATE_CAPS (new) = thecaps;
1838
1839   return new;
1840 }
1841
1842 /**
1843  * gst_padtemplate_get_caps:
1844  * @templ: the padtemplate to use
1845  *
1846  * Get the capabilities of the padtemplate
1847  *
1848  * Returns: a GstCaps*
1849  */
1850 GstCaps*
1851 gst_padtemplate_get_caps (GstPadTemplate *templ)
1852 {
1853   g_return_val_if_fail (templ != NULL, NULL);
1854
1855   return GST_PADTEMPLATE_CAPS (templ);
1856 }
1857
1858 #ifndef GST_DISABLE_LOADSAVE
1859 /**
1860  * gst_padtemplate_save_thyself:
1861  * @templ: the padtemplate to save
1862  * @parent: the parent XML tree
1863  *
1864  * Saves the padtemplate into XML.
1865  *
1866  * Returns: the new XML tree
1867  */
1868 xmlNodePtr
1869 gst_padtemplate_save_thyself (GstPadTemplate *templ, xmlNodePtr parent)
1870 {
1871   xmlNodePtr subtree;
1872   guchar *presence;
1873
1874   GST_DEBUG (GST_CAT_XML,"saving padtemplate %s\n", templ->name_template);
1875
1876   xmlNewChild(parent,NULL,"nametemplate", templ->name_template);
1877   xmlNewChild(parent,NULL,"direction", (templ->direction == GST_PAD_SINK? "sink":"src"));
1878
1879   switch (templ->presence) {
1880     case GST_PAD_ALWAYS:
1881       presence = "always";
1882       break;
1883     case GST_PAD_SOMETIMES:
1884       presence = "sometimes";
1885       break;
1886     case GST_PAD_REQUEST:
1887       presence = "request";
1888       break;
1889     default:
1890       presence = "unknown";
1891       break;
1892   }
1893   xmlNewChild(parent,NULL,"presence", presence);
1894
1895   if (GST_PADTEMPLATE_CAPS (templ)) {
1896     subtree = xmlNewChild (parent, NULL, "caps", NULL);
1897     gst_caps_save_thyself (GST_PADTEMPLATE_CAPS (templ), subtree);
1898   }
1899
1900   return parent;
1901 }
1902
1903 /**
1904  * gst_padtemplate_load_thyself:
1905  * @parent: the source XML tree
1906  *
1907  * Loads a padtemplate from the XML tree.
1908  *
1909  * Returns: the new padtemplate
1910  */
1911 GstPadTemplate*
1912 gst_padtemplate_load_thyself (xmlNodePtr parent)
1913 {
1914   xmlNodePtr field = parent->xmlChildrenNode;
1915   GstPadTemplate *factory;
1916   gchar *name_template = NULL;
1917   GstPadDirection direction = GST_PAD_UNKNOWN;
1918   GstPadPresence presence = GST_PAD_ALWAYS;
1919   GstCaps *caps = NULL;
1920
1921   while (field) {
1922     if (!strcmp(field->name, "nametemplate")) {
1923       name_template = xmlNodeGetContent(field);
1924     }
1925     if (!strcmp(field->name, "direction")) {
1926       gchar *value = xmlNodeGetContent(field);
1927
1928       if (!strcmp(value, "sink")) {
1929         direction = GST_PAD_SINK;
1930       }
1931       else if (!strcmp(value, "src")) {
1932         direction = GST_PAD_SRC;
1933       }
1934       g_free (value);
1935     }
1936     if (!strcmp(field->name, "presence")) {
1937       gchar *value = xmlNodeGetContent(field);
1938
1939       if (!strcmp(value, "always")) {
1940         presence = GST_PAD_ALWAYS;
1941       }
1942       else if (!strcmp(value, "sometimes")) {
1943         presence = GST_PAD_SOMETIMES;
1944       }
1945       else if (!strcmp(value, "request")) {
1946         presence = GST_PAD_REQUEST;
1947       }
1948       g_free (value);
1949     }
1950     else if (!strcmp(field->name, "caps")) {
1951       caps = gst_caps_load_thyself (field);
1952     }
1953     field = field->next;
1954   }
1955
1956   factory = gst_padtemplate_new (name_template, direction, presence, caps, NULL);
1957
1958   return factory;
1959 }
1960 #endif /* !GST_DISABLE_LOADSAVE */
1961
1962
1963 /**
1964  * gst_pad_set_element_private:
1965  * @pad: the pad to set the private data to
1966  * @priv: The private data to attach to the pad
1967  *
1968  * Set the given private data pointer to the pad. This
1969  * function can only be used by the element that own the
1970  * pad.
1971  */
1972 void
1973 gst_pad_set_element_private (GstPad *pad, gpointer priv)
1974 {
1975   pad->element_private = priv;
1976 }
1977
1978 /**
1979  * gst_pad_get_element_private:
1980  * @pad: the pad to get the private data of
1981  *
1982  * Get the private data of a pad. The private data can
1983  * only be set by the parent element of this pad.
1984  *
1985  * Returns: a pointer to the private data.
1986  */
1987 gpointer
1988 gst_pad_get_element_private (GstPad *pad)
1989 {
1990   return pad->element_private;
1991 }
1992
1993
1994 /***** ghost pads *****/
1995 GType _gst_ghost_pad_type = 0;
1996
1997 static void     gst_ghost_pad_class_init         (GstGhostPadClass *klass);
1998 static void     gst_ghost_pad_init               (GstGhostPad *pad);
1999
2000 static GstPad *ghost_pad_parent_class = NULL;
2001 /* static guint gst_ghost_pad_signals[LAST_SIGNAL] = { 0 }; */
2002
2003 GType
2004 gst_ghost_pad_get_type(void) {
2005   if (!_gst_ghost_pad_type) {
2006     static const GTypeInfo pad_info = {
2007       sizeof(GstGhostPadClass),
2008       NULL,
2009       NULL,
2010       (GClassInitFunc)gst_ghost_pad_class_init,
2011       NULL,
2012       NULL,
2013       sizeof(GstGhostPad),
2014       8,
2015       (GInstanceInitFunc)gst_ghost_pad_init,
2016       NULL
2017     };
2018     _gst_ghost_pad_type = g_type_register_static(GST_TYPE_PAD, "GstGhostPad", &pad_info, 0);
2019   }
2020   return _gst_ghost_pad_type;
2021 }
2022
2023 static void
2024 gst_ghost_pad_class_init (GstGhostPadClass *klass)
2025 {
2026   GObjectClass *gobject_class;
2027
2028   gobject_class = (GObjectClass*)klass;
2029
2030   ghost_pad_parent_class = g_type_class_ref(GST_TYPE_PAD);
2031 }
2032
2033 static void
2034 gst_ghost_pad_init (GstGhostPad *pad)
2035 {
2036   pad->realpad = NULL;
2037 }
2038
2039 /**
2040  * gst_ghost_pad_new:
2041  * @name: name of the new ghost pad
2042  * @pad: the pad to create a ghost pad of
2043  *
2044  * Create a new ghost pad associated with the given pad.
2045  *
2046  * Returns: new ghost pad
2047  */
2048 GstPad*
2049 gst_ghost_pad_new (gchar *name,
2050                    GstPad *pad)
2051 {
2052   GstGhostPad *ghostpad;
2053
2054   g_return_val_if_fail (name != NULL, NULL);
2055   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
2056
2057   ghostpad = g_object_new (gst_ghost_pad_get_type () ,NULL);
2058   gst_pad_set_name (GST_PAD (ghostpad), name);
2059   GST_GPAD_REALPAD (ghostpad) = GST_PAD_REALIZE (pad);
2060   GST_PAD_PADTEMPLATE (ghostpad) = GST_PAD_PADTEMPLATE (pad);
2061
2062   /* add ourselves to the real pad's list of ghostpads */
2063   gst_pad_add_ghost_pad (pad, GST_PAD (ghostpad));
2064
2065   /* FIXME need to ref the real pad here... ? */
2066
2067   GST_DEBUG (GST_CAT_PADS, "created ghost pad \"%s\"\n", name);
2068
2069   return GST_PAD (ghostpad);
2070 }
2071
2072 static void 
2073 gst_pad_event_default_dispatch (GstPad *pad, GstElement *element, GstEvent *event)
2074 {
2075   GList *pads = element->pads;
2076
2077   while (pads) {
2078     GstPad *eventpad = GST_PAD (pads->data);
2079     pads = g_list_next (pads);
2080
2081     /* for all pads in the opposite direction that are connected */
2082     if (GST_PAD_DIRECTION (eventpad) != GST_PAD_DIRECTION (pad) && GST_PAD_IS_CONNECTED (eventpad)) {
2083       if (GST_PAD_DIRECTION (eventpad) == GST_PAD_SRC) {
2084         gst_pad_push (eventpad, GST_BUFFER (gst_event_new (GST_EVENT_TYPE (event))));
2085         
2086       }
2087       else {
2088         GstPad *peerpad = GST_PAD_CAST (GST_RPAD_PEER (eventpad));
2089
2090         gst_pad_send_event (peerpad, gst_event_new (GST_EVENT_TYPE (event)));
2091       }
2092     }
2093   }
2094 }
2095
2096 /**
2097  * gst_pad_event_default:
2098  * @pad: the pad to operate on
2099  * @event: the event to handle
2100  *
2101  * Invoke the default event handler for the given pad.
2102  */
2103 void 
2104 gst_pad_event_default (GstPad *pad, GstEvent *event)
2105 {
2106   GstElement *element = GST_PAD_PARENT (pad);
2107
2108   g_signal_emit (G_OBJECT (pad), gst_real_pad_signals[REAL_EVENT_RECEIVED], 0, event);
2109  
2110   switch (GST_EVENT_TYPE (event)) {
2111     case GST_EVENT_EOS:
2112       gst_element_set_eos (element);
2113       gst_pad_event_default_dispatch (pad, element, event);
2114       gst_event_free (event);
2115       /* we have to try to schedule another element because this one is disabled */
2116       gst_element_yield (element);
2117       break;
2118     case GST_EVENT_FLUSH:
2119     default:
2120       gst_pad_event_default_dispatch (pad, element, event);
2121       gst_event_free (event);
2122       break;
2123   }
2124 }
2125
2126 /**
2127  * gst_pad_send_event:
2128  * @pad: the pad to send the event to
2129  * @event: the event to send to the pad.
2130  *
2131  * Send the event to the pad.
2132  *
2133  * Returns: TRUE if the event was handled.
2134  */
2135 gboolean
2136 gst_pad_send_event (GstPad *pad, GstEvent *event)
2137 {
2138   gboolean handled = FALSE;
2139
2140   g_return_val_if_fail (event, FALSE);
2141
2142   if (GST_EVENT_SRC (event) == NULL)
2143     GST_EVENT_SRC (event) = gst_object_ref (GST_OBJECT (pad));
2144
2145   GST_DEBUG (GST_CAT_EVENT, "have event %d on pad %s:%s\n",
2146                   GST_EVENT_TYPE (event), GST_DEBUG_PAD_NAME (pad));
2147
2148   if (GST_RPAD_EVENTFUNC (pad))
2149     handled = GST_RPAD_EVENTFUNC (pad) (pad, event);
2150   else {
2151     GST_DEBUG(GST_CAT_EVENT, "there's no event function for pad %s:%s\n", GST_DEBUG_PAD_NAME (pad));
2152   }
2153
2154   if (!handled) {
2155     GST_DEBUG(GST_CAT_EVENT, "proceeding with default event behavior here\n");
2156     gst_pad_event_default (pad, event);
2157     handled = TRUE;
2158   }
2159
2160   return handled;
2161 }
2162