Clear target when the target pad disappears
[platform/upstream/gstreamer.git] / gst / gstghostpad.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2000 Wim Taymans <wtay@chello.be>
4  *                    2005 Andy Wingo <wingo@pobox.com>
5  *                    2006 Edward Hervey <bilboed@bilboed.com>
6  *
7  * gstghostpad.c: Proxy pads
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public
20  * License along with this library; if not, write to the
21  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22  * Boston, MA 02111-1307, USA.
23  */
24
25 /**
26  * SECTION:gstghostpad
27  * @short_description: Pseudo link pads
28  * @see_also: #GstPad
29  *
30  * GhostPads are useful when organizing pipelines with #GstBin like elements.
31  * The idea here is to create hierarchical element graphs. The bin element
32  * contains a sub-graph. Now one would like to treat the bin-element like other
33  * #GstElements. This is where GhostPads come into play. A GhostPad acts as a
34  * proxy for another pad. Thus the bin can have sink and source ghost-pads that
35  * are associated with sink and source pads of the child elements.
36  *
37  * If the target pad is known at creation time, gst_ghost_pad_new() is the
38  * function to use to get a ghost-pad. Otherwise one can use gst_ghost_pad_new_no_target()
39  * to create the ghost-pad and use gst_ghost_pad_set_target() to establish the
40  * association later on.
41  *
42  * Note that GhostPads add overhead to the data processing of a pipeline.
43  *
44  * Last reviewed on 2005-11-18 (0.9.5)
45  */
46
47 #include "gst_private.h"
48 #include "gstinfo.h"
49
50 #include "gstghostpad.h"
51 #include "gst.h"
52
53 #define GST_CAT_DEFAULT GST_CAT_PADS
54
55 #define GST_PROXY_PAD_CAST(obj)         ((GstProxyPad *)obj)
56 #define GST_PROXY_PAD_PRIVATE(obj)      (GST_PROXY_PAD_CAST (obj)->priv)
57 #define GST_PROXY_PAD_TARGET(pad)       (GST_PROXY_PAD_PRIVATE (pad)->target)
58 #define GST_PROXY_PAD_INTERNAL(pad)     (GST_PROXY_PAD_PRIVATE (pad)->internal)
59 #define GST_PROXY_PAD_RETARGET(pad)     (GST_PROXY_PAD_PRIVATE (pad)->retarget)
60 #define GST_PROXY_GET_LOCK(pad) (GST_PROXY_PAD_PRIVATE (pad)->proxy_lock)
61 #define GST_PROXY_LOCK(pad)     (g_mutex_lock (GST_PROXY_GET_LOCK (pad)))
62 #define GST_PROXY_UNLOCK(pad)   (g_mutex_unlock (GST_PROXY_GET_LOCK (pad)))
63
64 struct _GstProxyPadPrivate
65 {
66   /* with PROXY_LOCK */
67   GMutex *proxy_lock;
68   GstPad *target;
69   GstPad *internal;
70   gboolean retarget;
71 };
72
73 G_DEFINE_TYPE (GstProxyPad, gst_proxy_pad, GST_TYPE_PAD);
74
75 static GstPad *gst_proxy_pad_get_target (GstPad * pad);
76
77 static void gst_proxy_pad_dispose (GObject * object);
78 static void gst_proxy_pad_finalize (GObject * object);
79
80 #ifndef GST_DISABLE_LOADSAVE
81 static xmlNodePtr gst_proxy_pad_save_thyself (GstObject * object,
82     xmlNodePtr parent);
83 #endif
84
85 static void on_src_target_notify (GstPad * target,
86     GParamSpec * unused, GstGhostPad * pad);
87
88
89 static void
90 gst_proxy_pad_class_init (GstProxyPadClass * klass)
91 {
92   GObjectClass *gobject_class = (GObjectClass *) klass;
93
94   g_type_class_add_private (klass, sizeof (GstProxyPadPrivate));
95
96   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_proxy_pad_dispose);
97   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_proxy_pad_finalize);
98
99 #ifndef GST_DISABLE_LOADSAVE
100   {
101     GstObjectClass *gstobject_class = (GstObjectClass *) klass;
102
103     gstobject_class->save_thyself =
104         GST_DEBUG_FUNCPTR (gst_proxy_pad_save_thyself);
105   }
106 #endif
107 }
108
109 static const GstQueryType *
110 gst_proxy_pad_do_query_type (GstPad * pad)
111 {
112   GstPad *target = gst_proxy_pad_get_target (pad);
113   const GstQueryType *res = NULL;
114
115   if (target) {
116     res = gst_pad_get_query_types (target);
117     gst_object_unref (target);
118   }
119   return res;
120 }
121
122 static gboolean
123 gst_proxy_pad_do_event (GstPad * pad, GstEvent * event)
124 {
125   gboolean res = FALSE;
126   GstPad *internal = GST_PROXY_PAD_INTERNAL (pad);
127
128   res = gst_pad_push_event (internal, event);
129
130   return res;
131 }
132
133 static gboolean
134 gst_proxy_pad_do_query (GstPad * pad, GstQuery * query)
135 {
136   gboolean res = FALSE;
137   GstPad *target = gst_proxy_pad_get_target (pad);
138
139   if (target) {
140     res = gst_pad_query (target, query);
141     gst_object_unref (target);
142   }
143
144   return res;
145 }
146
147 static GList *
148 gst_proxy_pad_do_internal_link (GstPad * pad)
149 {
150   GList *res = NULL;
151   GstPad *target = gst_proxy_pad_get_target (pad);
152
153   if (target) {
154     res = gst_pad_get_internal_links (target);
155     gst_object_unref (target);
156   }
157
158   return res;
159 }
160
161 static GstIterator *
162 gst_proxy_pad_do_iterate_internal_links (GstPad * pad)
163 {
164   GstIterator *res = NULL;
165   GstPad *target = gst_proxy_pad_get_target (pad);
166
167   if (target) {
168     res = gst_pad_iterate_internal_links (target);
169     gst_object_unref (target);
170   }
171
172   return res;
173 }
174
175 static GstFlowReturn
176 gst_proxy_pad_do_bufferalloc (GstPad * pad, guint64 offset, guint size,
177     GstCaps * caps, GstBuffer ** buf)
178 {
179   GstFlowReturn result;
180   GstPad *internal = GST_PROXY_PAD_INTERNAL (pad);
181
182   result = gst_pad_alloc_buffer (internal, offset, size, caps, buf);
183
184   return result;
185 }
186
187 static GstFlowReturn
188 gst_proxy_pad_do_chain (GstPad * pad, GstBuffer * buffer)
189 {
190   GstFlowReturn res;
191   GstPad *internal = GST_PROXY_PAD_INTERNAL (pad);
192
193   res = gst_pad_push (internal, buffer);
194
195   return res;
196 }
197
198 static GstFlowReturn
199 gst_proxy_pad_do_getrange (GstPad * pad, guint64 offset, guint size,
200     GstBuffer ** buffer)
201 {
202   GstFlowReturn res;
203   GstPad *internal = GST_PROXY_PAD_INTERNAL (pad);
204
205   res = gst_pad_pull_range (internal, offset, size, buffer);
206
207   return res;
208 }
209
210 static gboolean
211 gst_proxy_pad_do_checkgetrange (GstPad * pad)
212 {
213   gboolean result;
214   GstPad *internal = GST_PROXY_PAD_INTERNAL (pad);
215
216   result = gst_pad_check_pull_range (internal);
217
218   return result;
219 }
220
221 static GstCaps *
222 gst_proxy_pad_do_getcaps (GstPad * pad)
223 {
224   GstPad *target = gst_proxy_pad_get_target (pad);
225   GstCaps *res;
226   GstPadTemplate *templ = GST_PAD_PAD_TEMPLATE (pad);
227
228   if (target) {
229     /* if we have a real target, proxy the call */
230     res = gst_pad_get_caps (target);
231     gst_object_unref (target);
232
233     GST_DEBUG_OBJECT (pad, "get caps of target: %" GST_PTR_FORMAT, res);
234
235     /* filter against the template */
236     if (templ && res) {
237       GstCaps *filt, *tmp;
238
239       filt = GST_PAD_TEMPLATE_CAPS (templ);
240       if (filt) {
241         tmp = gst_caps_intersect (filt, res);
242         gst_caps_unref (res);
243         res = tmp;
244         GST_DEBUG_OBJECT (pad,
245             "filtered against template gives %" GST_PTR_FORMAT, res);
246       }
247     }
248   } else {
249     /* else, if we have a template, use its caps. */
250     if (templ) {
251       res = GST_PAD_TEMPLATE_CAPS (templ);
252       GST_DEBUG_OBJECT (pad,
253           "using pad template %p with caps %p %" GST_PTR_FORMAT, templ, res,
254           res);
255       res = gst_caps_ref (res);
256       goto done;
257     }
258
259     /* last resort, any caps */
260     GST_DEBUG_OBJECT (pad, "pad has no template, returning ANY");
261     res = gst_caps_new_any ();
262   }
263
264 done:
265   return res;
266 }
267
268 static gboolean
269 gst_proxy_pad_do_acceptcaps (GstPad * pad, GstCaps * caps)
270 {
271   GstPad *target = gst_proxy_pad_get_target (pad);
272   gboolean res;
273
274   if (target) {
275     res = gst_pad_accept_caps (target, caps);
276     gst_object_unref (target);
277   } else {
278     /* We don't have a target, we return TRUE and we assume that any future
279      * target will be able to deal with any configured caps. */
280     res = TRUE;
281   }
282
283   return res;
284 }
285
286 static void
287 gst_proxy_pad_do_fixatecaps (GstPad * pad, GstCaps * caps)
288 {
289   GstPad *target = gst_proxy_pad_get_target (pad);
290
291   if (target) {
292     gst_pad_fixate_caps (target, caps);
293     gst_object_unref (target);
294   }
295 }
296
297 static gboolean
298 gst_proxy_pad_do_setcaps (GstPad * pad, GstCaps * caps)
299 {
300   GstPad *target = gst_proxy_pad_get_target (pad);
301   gboolean res;
302
303   if (target) {
304     res = gst_pad_set_caps (target, caps);
305     gst_object_unref (target);
306   } else {
307     /* We don't have any target, but we shouldn't return FALSE since this
308      * would stop the actual push of a buffer (which might trigger a pad block
309      * or probe, or properly return GST_FLOW_NOT_LINKED.
310      */
311     res = TRUE;
312   }
313   return res;
314 }
315
316 static gboolean
317 gst_proxy_pad_set_target_unlocked (GstPad * pad, GstPad * target)
318 {
319   GstPad *oldtarget;
320
321   if (target) {
322     GST_LOG_OBJECT (pad, "setting target %s:%s", GST_DEBUG_PAD_NAME (target));
323
324     if (G_UNLIKELY (GST_PAD_DIRECTION (pad) != GST_PAD_DIRECTION (target)))
325       goto wrong_direction;
326   } else
327     GST_LOG_OBJECT (pad, "clearing target");
328
329   /* clear old target */
330   if ((oldtarget = GST_PROXY_PAD_TARGET (pad)))
331     gst_object_unref (oldtarget);
332
333   /* set and ref new target if any */
334   if (target)
335     GST_PROXY_PAD_TARGET (pad) = gst_object_ref (target);
336   else
337     GST_PROXY_PAD_TARGET (pad) = NULL;
338
339   return TRUE;
340
341   /* ERRORS */
342 wrong_direction:
343   {
344     GST_ERROR_OBJECT (pad,
345         "target pad doesn't have the same direction as ourself");
346     return FALSE;
347   }
348 }
349
350 static gboolean
351 gst_proxy_pad_set_target (GstPad * pad, GstPad * target)
352 {
353   gboolean result;
354
355   GST_PROXY_LOCK (pad);
356   result = gst_proxy_pad_set_target_unlocked (pad, target);
357   GST_PROXY_UNLOCK (pad);
358
359   return result;
360 }
361
362 static GstPad *
363 gst_proxy_pad_get_target (GstPad * pad)
364 {
365   GstPad *target;
366
367   GST_PROXY_LOCK (pad);
368   target = GST_PROXY_PAD_TARGET (pad);
369   if (target)
370     gst_object_ref (target);
371   GST_PROXY_UNLOCK (pad);
372
373   return target;
374 }
375
376 static void
377 gst_proxy_pad_do_unlink (GstPad * pad)
378 {
379   GstPad *internal;
380
381   /* don't do anything if this unlink resulted from retargeting the pad
382    * controlled by the ghostpad. We only want to invalidate the target pad when
383    * the element suddently unlinked with our internal pad. */
384   if (GST_PROXY_PAD_RETARGET (pad))
385     return;
386
387   internal = GST_PROXY_PAD_INTERNAL (pad);
388
389   GST_DEBUG_OBJECT (pad, "pad is unlinked");
390
391   gst_proxy_pad_set_target (internal, NULL);
392 }
393
394 static void
395 gst_proxy_pad_dispose (GObject * object)
396 {
397   GstPad *pad = GST_PAD (object);
398   GstPad **target_p;
399
400   GST_PROXY_LOCK (pad);
401   /* remove and unref the target */
402   target_p = &GST_PROXY_PAD_TARGET (pad);
403   gst_object_replace ((GstObject **) target_p, NULL);
404   /* The internal is only cleared by GstGhostPad::dispose, since it is the 
405    * parent of non-ghost GstProxyPad and owns the refcount on the internal.
406    */
407   GST_PROXY_UNLOCK (pad);
408
409   G_OBJECT_CLASS (gst_proxy_pad_parent_class)->dispose (object);
410 }
411
412 static void
413 gst_proxy_pad_finalize (GObject * object)
414 {
415   GstProxyPad *pad = GST_PROXY_PAD (object);
416
417   g_mutex_free (GST_PROXY_GET_LOCK (pad));
418   GST_PROXY_GET_LOCK (pad) = NULL;
419
420   G_OBJECT_CLASS (gst_proxy_pad_parent_class)->finalize (object);
421 }
422
423 static void
424 gst_proxy_pad_init (GstProxyPad * ppad)
425 {
426   GstPad *pad = (GstPad *) ppad;
427
428   GST_PROXY_PAD_PRIVATE (ppad) = G_TYPE_INSTANCE_GET_PRIVATE (ppad,
429       GST_TYPE_PROXY_PAD, GstProxyPadPrivate);
430   GST_PROXY_GET_LOCK (pad) = g_mutex_new ();
431
432   gst_pad_set_query_type_function (pad,
433       GST_DEBUG_FUNCPTR (gst_proxy_pad_do_query_type));
434   gst_pad_set_event_function (pad, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_event));
435   gst_pad_set_query_function (pad, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_query));
436   gst_pad_set_internal_link_function (pad,
437       GST_DEBUG_FUNCPTR (gst_proxy_pad_do_internal_link));
438   gst_pad_set_iterate_internal_links_function (pad,
439       GST_DEBUG_FUNCPTR (gst_proxy_pad_do_iterate_internal_links));
440
441   gst_pad_set_getcaps_function (pad,
442       GST_DEBUG_FUNCPTR (gst_proxy_pad_do_getcaps));
443   gst_pad_set_acceptcaps_function (pad,
444       GST_DEBUG_FUNCPTR (gst_proxy_pad_do_acceptcaps));
445   gst_pad_set_fixatecaps_function (pad,
446       GST_DEBUG_FUNCPTR (gst_proxy_pad_do_fixatecaps));
447   gst_pad_set_setcaps_function (pad,
448       GST_DEBUG_FUNCPTR (gst_proxy_pad_do_setcaps));
449   gst_pad_set_unlink_function (pad,
450       GST_DEBUG_FUNCPTR (gst_proxy_pad_do_unlink));
451 }
452
453 #ifndef GST_DISABLE_LOADSAVE
454 /**
455  * gst_proxy_pad_save_thyself:
456  * @pad: a ghost #GstPad to save.
457  * @parent: the parent #xmlNodePtr to save the description in.
458  *
459  * Saves the ghost pad into an xml representation.
460  *
461  * Returns: the #xmlNodePtr representation of the pad.
462  */
463 static xmlNodePtr
464 gst_proxy_pad_save_thyself (GstObject * object, xmlNodePtr parent)
465 {
466   xmlNodePtr self;
467   GstProxyPad *proxypad;
468   GstPad *pad;
469   GstPad *peer;
470
471   g_return_val_if_fail (GST_IS_PROXY_PAD (object), NULL);
472
473   self = xmlNewChild (parent, NULL, (xmlChar *) "ghostpad", NULL);
474   xmlNewChild (self, NULL, (xmlChar *) "name",
475       (xmlChar *) GST_OBJECT_NAME (object));
476   xmlNewChild (self, NULL, (xmlChar *) "parent",
477       (xmlChar *) GST_OBJECT_NAME (GST_OBJECT_PARENT (object)));
478
479   proxypad = GST_PROXY_PAD_CAST (object);
480   pad = GST_PAD_CAST (proxypad);
481   peer = GST_PAD_CAST (pad->peer);
482
483   if (GST_IS_PAD (pad)) {
484     if (GST_PAD_IS_SRC (pad))
485       xmlNewChild (self, NULL, (xmlChar *) "direction", (xmlChar *) "source");
486     else if (GST_PAD_IS_SINK (pad))
487       xmlNewChild (self, NULL, (xmlChar *) "direction", (xmlChar *) "sink");
488     else
489       xmlNewChild (self, NULL, (xmlChar *) "direction", (xmlChar *) "unknown");
490   } else {
491     xmlNewChild (self, NULL, (xmlChar *) "direction", (xmlChar *) "unknown");
492   }
493   if (GST_IS_PAD (peer)) {
494     gchar *content = g_strdup_printf ("%s.%s",
495         GST_OBJECT_NAME (GST_PAD_PARENT (peer)), GST_PAD_NAME (peer));
496
497     xmlNewChild (self, NULL, (xmlChar *) "peer", (xmlChar *) content);
498     g_free (content);
499   } else {
500     xmlNewChild (self, NULL, (xmlChar *) "peer", NULL);
501   }
502
503   return self;
504 }
505 #endif /* GST_DISABLE_LOADSAVE */
506
507
508 /***********************************************************************
509  * Ghost pads, implemented as a pair of proxy pads (sort of)
510  */
511
512
513 #define GST_GHOST_PAD_PRIVATE(obj)      (GST_GHOST_PAD_CAST (obj)->priv)
514
515 struct _GstGhostPadPrivate
516 {
517   /* with PROXY_LOCK */
518   gulong notify_id;
519
520   gboolean constructed;
521 };
522
523 G_DEFINE_TYPE (GstGhostPad, gst_ghost_pad, GST_TYPE_PROXY_PAD);
524
525 static void gst_ghost_pad_dispose (GObject * object);
526
527 static void
528 gst_ghost_pad_class_init (GstGhostPadClass * klass)
529 {
530   GObjectClass *gobject_class = (GObjectClass *) klass;
531
532   g_type_class_add_private (klass, sizeof (GstGhostPadPrivate));
533
534   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_ghost_pad_dispose);
535 }
536
537 /* see gstghostpad design docs */
538 static gboolean
539 gst_ghost_pad_internal_do_activate_push (GstPad * pad, gboolean active)
540 {
541   gboolean ret;
542   GstPad *other;
543
544   GST_LOG_OBJECT (pad, "%sactivate push on %s:%s, we're ok",
545       (active ? "" : "de"), GST_DEBUG_PAD_NAME (pad));
546
547   /* in both cases (SRC and SINK) we activate just the internal pad. The targets
548    * will be activated later (or already in case of a ghost sinkpad). */
549   other = GST_PROXY_PAD_INTERNAL (pad);
550   ret = gst_pad_activate_push (other, active);
551
552   return ret;
553 }
554
555 static gboolean
556 gst_ghost_pad_internal_do_activate_pull (GstPad * pad, gboolean active)
557 {
558   gboolean ret;
559   GstPad *other;
560
561   GST_LOG_OBJECT (pad, "%sactivate pull on %s:%s", (active ? "" : "de"),
562       GST_DEBUG_PAD_NAME (pad));
563
564   if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC) {
565     /* we are activated in pull mode by our peer element, which is a sinkpad
566      * that wants to operate in pull mode. This activation has to propagate
567      * upstream throught the pipeline. We call the internal activation function,
568      * which will trigger gst_ghost_pad_do_activate_pull, which propagates even
569      * further upstream */
570     GST_LOG_OBJECT (pad, "pad is src, activate internal");
571     other = GST_PROXY_PAD_INTERNAL (pad);
572     ret = gst_pad_activate_pull (other, active);
573   } else if (G_LIKELY ((other = gst_pad_get_peer (pad)))) {
574     /* We are SINK, the ghostpad is SRC, we propagate the activation upstream
575      * since we hold a pointer to the upstream peer. */
576     GST_LOG_OBJECT (pad, "activating peer");
577     ret = gst_pad_activate_pull (other, active);
578     gst_object_unref (other);
579   } else {
580     /* this is failure, we can't activate pull if there is no peer */
581     GST_LOG_OBJECT (pad, "not src and no peer, failing");
582     ret = FALSE;
583   }
584
585   return ret;
586 }
587
588 static gboolean
589 gst_ghost_pad_do_activate_push (GstPad * pad, gboolean active)
590 {
591   gboolean ret;
592   GstPad *other;
593
594   GST_LOG_OBJECT (pad, "%sactivate push on %s:%s, proxy internal",
595       (active ? "" : "de"), GST_DEBUG_PAD_NAME (pad));
596
597   /* just activate the internal pad */
598   other = GST_PROXY_PAD_INTERNAL (pad);
599   ret = gst_pad_activate_push (other, active);
600
601   return ret;
602 }
603
604 static gboolean
605 gst_ghost_pad_do_activate_pull (GstPad * pad, gboolean active)
606 {
607   gboolean ret;
608   GstPad *other;
609
610   GST_LOG_OBJECT (pad, "%sactivate pull on %s:%s", (active ? "" : "de"),
611       GST_DEBUG_PAD_NAME (pad));
612
613   if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC) {
614     /* the ghostpad is SRC and activated in pull mode by its peer, call the
615      * activation function of the internal pad to propagate the activation
616      * upstream */
617     GST_LOG_OBJECT (pad, "pad is src, activate internal");
618     other = GST_PROXY_PAD_INTERNAL (pad);
619     ret = gst_pad_activate_pull (other, active);
620   } else if (G_LIKELY ((other = gst_pad_get_peer (pad)))) {
621     /* We are SINK and activated by the internal pad, propagate activation
622      * upstream because we hold a ref to the upstream peer */
623     GST_LOG_OBJECT (pad, "activating peer");
624     ret = gst_pad_activate_pull (other, active);
625     gst_object_unref (other);
626   } else {
627     /* no peer, we fail */
628     GST_LOG_OBJECT (pad, "pad not src and no peer, failing");
629     ret = FALSE;
630   }
631
632   return ret;
633 }
634
635 static GstPadLinkReturn
636 gst_ghost_pad_do_link (GstPad * pad, GstPad * peer)
637 {
638   GstPadLinkReturn ret;
639   GstPad *internal;
640
641   GST_DEBUG_OBJECT (pad, "linking ghostpad");
642
643   internal = GST_PROXY_PAD_INTERNAL (pad);
644   if (!gst_proxy_pad_set_target (internal, peer))
645     goto target_failed;
646
647   ret = GST_PAD_LINK_OK;
648   /* if we are a source pad, we should call the peer link function
649    * if the peer has one, see design docs. */
650   if (GST_PAD_IS_SRC (pad)) {
651     if (GST_PAD_LINKFUNC (peer)) {
652       ret = GST_PAD_LINKFUNC (peer) (peer, pad);
653       if (ret != GST_PAD_LINK_OK)
654         goto link_failed;
655     }
656   }
657   return ret;
658
659   /* ERRORS */
660 target_failed:
661   {
662     GST_DEBUG_OBJECT (pad, "setting target failed");
663     return GST_PAD_LINK_REFUSED;
664   }
665 link_failed:
666   {
667     GST_DEBUG_OBJECT (pad, "linking failed");
668     /* clear target again */
669     gst_proxy_pad_set_target (internal, NULL);
670     return ret;
671   }
672 }
673
674 static void
675 gst_ghost_pad_do_unlink (GstPad * pad)
676 {
677   GstPad *internal;
678
679   internal = GST_PROXY_PAD_INTERNAL (pad);
680
681   GST_DEBUG_OBJECT (pad, "unlinking ghostpad");
682
683   /* The target of the internal pad is no longer valid */
684   gst_proxy_pad_set_target (internal, NULL);
685 }
686
687 static void
688 on_int_notify (GstPad * internal, GParamSpec * unused, GstGhostPad * pad)
689 {
690   GstCaps *caps;
691
692   g_object_get (internal, "caps", &caps, NULL);
693
694   GST_OBJECT_LOCK (pad);
695   gst_caps_replace (&(GST_PAD_CAPS (pad)), caps);
696   GST_OBJECT_UNLOCK (pad);
697
698   g_object_notify (G_OBJECT (pad), "caps");
699   if (caps)
700     gst_caps_unref (caps);
701 }
702
703 static void
704 on_src_target_notify (GstPad * target, GParamSpec * unused, GstGhostPad * pad)
705 {
706   GstCaps *caps;
707
708   g_object_get (target, "caps", &caps, NULL);
709
710   GST_OBJECT_LOCK (pad);
711   gst_caps_replace (&(GST_PAD_CAPS (pad)), caps);
712   GST_OBJECT_UNLOCK (pad);
713
714   g_object_notify (G_OBJECT (pad), "caps");
715   if (caps)
716     gst_caps_unref (caps);
717
718 }
719
720 static gboolean
721 gst_ghost_pad_do_setcaps (GstPad * pad, GstCaps * caps)
722 {
723   if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC)
724     return TRUE;
725
726   return gst_proxy_pad_do_setcaps (pad, caps);
727 }
728
729 static void
730 gst_ghost_pad_init (GstGhostPad * pad)
731 {
732   GST_GHOST_PAD_PRIVATE (pad) = G_TYPE_INSTANCE_GET_PRIVATE (pad,
733       GST_TYPE_GHOST_PAD, GstGhostPadPrivate);
734
735   gst_pad_set_setcaps_function (GST_PAD_CAST (pad),
736       GST_DEBUG_FUNCPTR (gst_ghost_pad_do_setcaps));
737   gst_pad_set_activatepull_function (GST_PAD_CAST (pad),
738       GST_DEBUG_FUNCPTR (gst_ghost_pad_do_activate_pull));
739   gst_pad_set_activatepush_function (GST_PAD_CAST (pad),
740       GST_DEBUG_FUNCPTR (gst_ghost_pad_do_activate_push));
741 }
742
743 static void
744 gst_ghost_pad_dispose (GObject * object)
745 {
746   GstPad *pad;
747   GstPad *internal;
748   GstPad *peer;
749
750   pad = GST_PAD (object);
751
752   GST_DEBUG_OBJECT (pad, "dispose");
753
754   gst_ghost_pad_set_target (GST_GHOST_PAD (pad), NULL);
755
756   /* Unlink here so that gst_pad_dispose doesn't. That would lead to a call to
757    * gst_ghost_pad_do_unlink when the ghost pad is in an inconsistent state */
758   peer = gst_pad_get_peer (pad);
759   if (peer) {
760     if (GST_PAD_IS_SRC (pad))
761       gst_pad_unlink (pad, peer);
762     else
763       gst_pad_unlink (peer, pad);
764
765     gst_object_unref (peer);
766   }
767
768   GST_PROXY_LOCK (pad);
769   internal = GST_PROXY_PAD_INTERNAL (pad);
770
771   gst_pad_set_activatepull_function (internal, NULL);
772   gst_pad_set_activatepush_function (internal, NULL);
773
774   g_signal_handler_disconnect (internal,
775       GST_GHOST_PAD_PRIVATE (pad)->notify_id);
776
777   /* disposes of the internal pad, since the ghostpad is the only possible object
778    * that has a refcount on the internal pad. */
779   gst_object_unparent (GST_OBJECT_CAST (internal));
780   GST_PROXY_PAD_INTERNAL (pad) = NULL;
781
782   GST_PROXY_UNLOCK (pad);
783
784   G_OBJECT_CLASS (gst_ghost_pad_parent_class)->dispose (object);
785 }
786
787 /**
788  * gst_ghost_pad_construct:
789  * @gpad: the newly allocated ghost pad
790  *
791  * Finish initialization of a newly allocated ghost pad.
792  *
793  * This function is most useful in language bindings and when subclassing
794  * #GstGhostPad; plugin and application developers normally will not call this
795  * function. Call this function directly after a call to g_object_new
796  * (GST_TYPE_GHOST_PAD, "direction", @dir, ..., NULL).
797  *
798  * Returns: %TRUE if the construction succeeds, %FALSE otherwise.
799  *
800  * Since: 0.10.22
801  */
802 gboolean
803 gst_ghost_pad_construct (GstGhostPad * gpad)
804 {
805   GstPadDirection dir, otherdir;
806   GstPadTemplate *templ;
807   GstPad *pad, *internal;
808
809   g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), FALSE);
810   g_return_val_if_fail (GST_GHOST_PAD_PRIVATE (gpad)->constructed == FALSE,
811       FALSE);
812
813   g_object_get (gpad, "direction", &dir, "template", &templ, NULL);
814
815   g_return_val_if_fail (dir != GST_PAD_UNKNOWN, FALSE);
816
817   pad = GST_PAD (gpad);
818
819   /* Set directional padfunctions for ghostpad */
820   if (dir == GST_PAD_SINK) {
821     gst_pad_set_bufferalloc_function (pad,
822         GST_DEBUG_FUNCPTR (gst_proxy_pad_do_bufferalloc));
823     gst_pad_set_chain_function (pad,
824         GST_DEBUG_FUNCPTR (gst_proxy_pad_do_chain));
825   } else {
826     gst_pad_set_getrange_function (pad,
827         GST_DEBUG_FUNCPTR (gst_proxy_pad_do_getrange));
828     gst_pad_set_checkgetrange_function (pad,
829         GST_DEBUG_FUNCPTR (gst_proxy_pad_do_checkgetrange));
830   }
831
832   /* link/unlink functions */
833   gst_pad_set_link_function (pad, GST_DEBUG_FUNCPTR (gst_ghost_pad_do_link));
834   gst_pad_set_unlink_function (pad,
835       GST_DEBUG_FUNCPTR (gst_ghost_pad_do_unlink));
836
837   /* INTERNAL PAD, it always exists and is child of the ghostpad */
838   otherdir = (dir == GST_PAD_SRC) ? GST_PAD_SINK : GST_PAD_SRC;
839   if (templ) {
840     internal =
841         g_object_new (GST_TYPE_PROXY_PAD, "name", NULL,
842         "direction", otherdir, "template", templ, NULL);
843     /* release ref obtained via g_object_get */
844     gst_object_unref (templ);
845   } else {
846     internal =
847         g_object_new (GST_TYPE_PROXY_PAD, "name", NULL,
848         "direction", otherdir, NULL);
849   }
850   GST_PAD_UNSET_FLUSHING (internal);
851
852   /* Set directional padfunctions for internal pad */
853   if (dir == GST_PAD_SRC) {
854     gst_pad_set_bufferalloc_function (internal,
855         GST_DEBUG_FUNCPTR (gst_proxy_pad_do_bufferalloc));
856     gst_pad_set_chain_function (internal,
857         GST_DEBUG_FUNCPTR (gst_proxy_pad_do_chain));
858   } else {
859     gst_pad_set_getrange_function (internal,
860         GST_DEBUG_FUNCPTR (gst_proxy_pad_do_getrange));
861     gst_pad_set_checkgetrange_function (internal,
862         GST_DEBUG_FUNCPTR (gst_proxy_pad_do_checkgetrange));
863   }
864
865   GST_PROXY_LOCK (pad);
866
867   /* now make the ghostpad a parent of the internal pad */
868   if (!gst_object_set_parent (GST_OBJECT_CAST (internal),
869           GST_OBJECT_CAST (pad)))
870     goto parent_failed;
871
872   /* The ghostpad is the parent of the internal pad and is the only object that
873    * can have a refcount on the internal pad.
874    * At this point, the GstGhostPad has a refcount of 1, and the internal pad has
875    * a refcount of 1.
876    * When the refcount of the GstGhostPad drops to 0, the ghostpad will dispose
877    * it's refcount on the internal pad in the dispose method by un-parenting it.
878    * This is why we don't take extra refcounts in the assignments below
879    */
880   GST_PROXY_PAD_INTERNAL (pad) = internal;
881   GST_PROXY_PAD_INTERNAL (internal) = pad;
882
883   /* could be more general here, iterating over all writable properties...
884    * taking the short road for now tho */
885   GST_GHOST_PAD_PRIVATE (pad)->notify_id =
886       g_signal_connect (internal, "notify::caps", G_CALLBACK (on_int_notify),
887       pad);
888
889   /* call function to init values of the pad caps */
890   on_int_notify (internal, NULL, GST_GHOST_PAD_CAST (pad));
891
892   /* special activation functions for the internal pad */
893   gst_pad_set_activatepull_function (internal,
894       GST_DEBUG_FUNCPTR (gst_ghost_pad_internal_do_activate_pull));
895   gst_pad_set_activatepush_function (internal,
896       GST_DEBUG_FUNCPTR (gst_ghost_pad_internal_do_activate_push));
897
898   GST_PROXY_UNLOCK (pad);
899
900   GST_GHOST_PAD_PRIVATE (gpad)->constructed = TRUE;
901   return TRUE;
902
903   /* ERRORS */
904 parent_failed:
905   {
906     GST_WARNING_OBJECT (gpad, "Could not set internal pad %s:%s",
907         GST_DEBUG_PAD_NAME (internal));
908     g_critical ("Could not set internal pad %s:%s",
909         GST_DEBUG_PAD_NAME (internal));
910     GST_PROXY_UNLOCK (pad);
911     gst_object_unref (internal);
912     return FALSE;
913   }
914 }
915
916 static GstPad *
917 gst_ghost_pad_new_full (const gchar * name, GstPadDirection dir,
918     GstPadTemplate * templ)
919 {
920   GstGhostPad *ret;
921
922   g_return_val_if_fail (dir != GST_PAD_UNKNOWN, NULL);
923
924   /* OBJECT CREATION */
925   if (templ) {
926     ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name,
927         "direction", dir, "template", templ, NULL);
928   } else {
929     ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name,
930         "direction", dir, NULL);
931   }
932
933   if (!gst_ghost_pad_construct (ret))
934     goto construct_failed;
935
936   return GST_PAD (ret);
937
938 construct_failed:
939   /* already logged */
940   gst_object_unref (ret);
941   return NULL;
942 }
943
944 /**
945  * gst_ghost_pad_new_no_target:
946  * @name: the name of the new pad, or NULL to assign a default name.
947  * @dir: the direction of the ghostpad
948  *
949  * Create a new ghostpad without a target with the given direction.
950  * A target can be set on the ghostpad later with the
951  * gst_ghost_pad_set_target() function.
952  *
953  * The created ghostpad will not have a padtemplate.
954  *
955  * Returns: a new #GstPad, or NULL in case of an error.
956  */
957 GstPad *
958 gst_ghost_pad_new_no_target (const gchar * name, GstPadDirection dir)
959 {
960   GstPad *ret;
961
962   g_return_val_if_fail (dir != GST_PAD_UNKNOWN, NULL);
963
964   GST_LOG ("name:%s, direction:%d", GST_STR_NULL (name), dir);
965
966   ret = gst_ghost_pad_new_full (name, dir, NULL);
967
968   return ret;
969 }
970
971 /**
972  * gst_ghost_pad_new:
973  * @name: the name of the new pad, or NULL to assign a default name.
974  * @target: the pad to ghost.
975  *
976  * Create a new ghostpad with @target as the target. The direction will be taken
977  * from the target pad. @target must be unlinked.
978  *
979  * Will ref the target.
980  *
981  * Returns: a new #GstPad, or NULL in case of an error.
982  */
983 GstPad *
984 gst_ghost_pad_new (const gchar * name, GstPad * target)
985 {
986   GstPad *ret;
987
988   g_return_val_if_fail (GST_IS_PAD (target), NULL);
989   g_return_val_if_fail (!gst_pad_is_linked (target), NULL);
990
991   GST_LOG ("name:%s, target:%s:%s", GST_STR_NULL (name),
992       GST_DEBUG_PAD_NAME (target));
993
994   if ((ret = gst_ghost_pad_new_no_target (name, GST_PAD_DIRECTION (target))))
995     if (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (ret), target))
996       goto set_target_failed;
997
998   return ret;
999
1000   /* ERRORS */
1001 set_target_failed:
1002   {
1003     GST_WARNING_OBJECT (ret, "failed to set target %s:%s",
1004         GST_DEBUG_PAD_NAME (target));
1005     gst_object_unref (ret);
1006     return NULL;
1007   }
1008 }
1009
1010 /**
1011  * gst_ghost_pad_new_from_template:
1012  * @name: the name of the new pad, or NULL to assign a default name.
1013  * @target: the pad to ghost.
1014  * @templ: the #GstPadTemplate to use on the ghostpad.
1015  *
1016  * Create a new ghostpad with @target as the target. The direction will be taken
1017  * from the target pad. The template used on the ghostpad will be @template.
1018  *
1019  * Will ref the target.
1020  *
1021  * Returns: a new #GstPad, or NULL in case of an error.
1022  *
1023  * Since: 0.10.10
1024  */
1025
1026 GstPad *
1027 gst_ghost_pad_new_from_template (const gchar * name, GstPad * target,
1028     GstPadTemplate * templ)
1029 {
1030   GstPad *ret;
1031
1032   g_return_val_if_fail (GST_IS_PAD (target), NULL);
1033   g_return_val_if_fail (!gst_pad_is_linked (target), NULL);
1034   g_return_val_if_fail (templ != NULL, NULL);
1035   g_return_val_if_fail (GST_PAD_TEMPLATE_DIRECTION (templ) ==
1036       GST_PAD_DIRECTION (target), NULL);
1037
1038   GST_LOG ("name:%s, target:%s:%s, templ:%p", GST_STR_NULL (name),
1039       GST_DEBUG_PAD_NAME (target), templ);
1040
1041   if ((ret = gst_ghost_pad_new_full (name, GST_PAD_DIRECTION (target), templ)))
1042     if (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (ret), target))
1043       goto set_target_failed;
1044
1045   return ret;
1046
1047   /* ERRORS */
1048 set_target_failed:
1049   {
1050     GST_WARNING_OBJECT (ret, "failed to set target %s:%s",
1051         GST_DEBUG_PAD_NAME (target));
1052     gst_object_unref (ret);
1053     return NULL;
1054   }
1055 }
1056
1057 /**
1058  * gst_ghost_pad_new_no_target_from_template:
1059  * @name: the name of the new pad, or NULL to assign a default name.
1060  * @templ: the #GstPadTemplate to create the ghostpad from.
1061  *
1062  * Create a new ghostpad based on @templ, without setting a target. The
1063  * direction will be taken from the @templ.
1064  *
1065  * Returns: a new #GstPad, or NULL in case of an error.
1066  *
1067  * Since: 0.10.10
1068  */
1069 GstPad *
1070 gst_ghost_pad_new_no_target_from_template (const gchar * name,
1071     GstPadTemplate * templ)
1072 {
1073   GstPad *ret;
1074
1075   g_return_val_if_fail (templ != NULL, NULL);
1076
1077   ret =
1078       gst_ghost_pad_new_full (name, GST_PAD_TEMPLATE_DIRECTION (templ), templ);
1079
1080   return ret;
1081 }
1082
1083 /**
1084  * gst_ghost_pad_get_target:
1085  * @gpad: the #GstGhostpad
1086  *
1087  * Get the target pad of #gpad. Unref target pad after usage.
1088  *
1089  * Returns: the target #GstPad, can be NULL if the ghostpad
1090  * has no target set. Unref target pad after usage.
1091  */
1092 GstPad *
1093 gst_ghost_pad_get_target (GstGhostPad * gpad)
1094 {
1095   GstPad *ret;
1096
1097   g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), NULL);
1098
1099   ret = gst_proxy_pad_get_target (GST_PAD_CAST (gpad));
1100
1101   GST_DEBUG_OBJECT (gpad, "get target %s:%s", GST_DEBUG_PAD_NAME (ret));
1102
1103   return ret;
1104 }
1105
1106 /**
1107  * gst_ghost_pad_set_target:
1108  * @gpad: the #GstGhostpad
1109  * @newtarget: the new pad target
1110  *
1111  * Set the new target of the ghostpad @gpad. Any existing target
1112  * is unlinked and links to the new target are established. if @newtarget is
1113  * NULL the target will be cleared.
1114  *
1115  * Returns: TRUE if the new target could be set. This function can return FALSE
1116  * when the internal pads could not be linked.
1117  */
1118 gboolean
1119 gst_ghost_pad_set_target (GstGhostPad * gpad, GstPad * newtarget)
1120 {
1121   GstPad *internal;
1122   GstPad *oldtarget;
1123   gboolean result;
1124   GstPadLinkReturn lret;
1125
1126   g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), FALSE);
1127
1128   GST_PROXY_LOCK (gpad);
1129   internal = GST_PROXY_PAD_INTERNAL (gpad);
1130   g_assert (internal);
1131
1132   if (newtarget)
1133     GST_DEBUG_OBJECT (gpad, "set target %s:%s", GST_DEBUG_PAD_NAME (newtarget));
1134   else
1135     GST_DEBUG_OBJECT (gpad, "clearing target");
1136
1137   /* clear old target */
1138   if ((oldtarget = GST_PROXY_PAD_TARGET (gpad))) {
1139     if (GST_PAD_IS_SRC (oldtarget)) {
1140       g_signal_handlers_disconnect_by_func (oldtarget,
1141           (gpointer) on_src_target_notify, gpad);
1142     }
1143
1144     GST_PROXY_PAD_RETARGET (internal) = TRUE;
1145
1146     /* unlink internal pad */
1147     if (GST_PAD_IS_SRC (internal))
1148       gst_pad_unlink (internal, oldtarget);
1149     else
1150       gst_pad_unlink (oldtarget, internal);
1151
1152     GST_PROXY_PAD_RETARGET (internal) = FALSE;
1153   }
1154
1155   result = gst_proxy_pad_set_target_unlocked (GST_PAD_CAST (gpad), newtarget);
1156
1157   if (result && newtarget) {
1158     if (GST_PAD_IS_SRC (newtarget)) {
1159       g_signal_connect (newtarget, "notify::caps",
1160           G_CALLBACK (on_src_target_notify), gpad);
1161     }
1162
1163     /* and link to internal pad */
1164     GST_DEBUG_OBJECT (gpad, "connecting internal pad to target");
1165
1166     if (GST_PAD_IS_SRC (internal))
1167       lret = gst_pad_link (internal, newtarget);
1168     else
1169       lret = gst_pad_link (newtarget, internal);
1170
1171     if (lret != GST_PAD_LINK_OK)
1172       goto link_failed;
1173   }
1174   GST_PROXY_UNLOCK (gpad);
1175
1176   return result;
1177
1178   /* ERRORS */
1179 link_failed:
1180   {
1181     GST_WARNING_OBJECT (gpad, "could not link internal and target, reason:%d",
1182         lret);
1183     /* and unset target again */
1184     gst_proxy_pad_set_target_unlocked (GST_PAD_CAST (gpad), NULL);
1185     GST_PROXY_UNLOCK (gpad);
1186     return FALSE;
1187   }
1188 }