ghostpad: remove setcaps functions
[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 any
33  * other #GstElement. This is where GhostPads come into play. A GhostPad acts as
34  * a proxy for another pad. Thus the bin can have sink and source ghost-pads
35  * that 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 /**
81  * gst_proxy_pad_query_type_default:
82  * @pad: a #GstPad.
83  *
84  * Invoke the default query type handler of the proxy pad.
85  *
86  * Returns: (transfer none) (array zero-terminated=1): a zero-terminated array
87  *     of #GstQueryType.
88  *
89  * Since: 0.10.35
90  */
91 const GstQueryType *
92 gst_proxy_pad_query_type_default (GstPad * pad)
93 {
94   GstPad *target;
95   const GstQueryType *res = NULL;
96
97   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), NULL);
98
99   target = gst_proxy_pad_get_target (pad);
100   if (target) {
101     res = gst_pad_get_query_types (target);
102     gst_object_unref (target);
103   }
104   return res;
105 }
106
107 /**
108  * gst_proxy_pad_event_default:
109  * @pad: a #GstPad to push the event to.
110  * @event: (transfer full): the #GstEvent to send to the pad.
111  *
112  * Invoke the default event of the proxy pad.
113  *
114  * Returns: TRUE if the event was handled.
115  *
116  * Since: 0.10.35
117  */
118 gboolean
119 gst_proxy_pad_event_default (GstPad * pad, GstEvent * event)
120 {
121   gboolean res = FALSE;
122   GstPad *internal;
123
124   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
125   g_return_val_if_fail (GST_IS_EVENT (event), FALSE);
126
127   internal =
128       GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD_CAST (pad)));
129   if (internal) {
130     res = gst_pad_push_event (internal, event);
131     gst_object_unref (internal);
132   }
133
134   return res;
135 }
136
137 /**
138  * gst_proxy_pad_query_default:
139  * @pad: a #GstPad to invoke the default query on.
140  * @query: (transfer none): the #GstQuery to perform.
141  *
142  * Invoke the default query function of the proxy pad.
143  *
144  * Returns: TRUE if the query could be performed.
145  *
146  * Since: 0.10.35
147  */
148 gboolean
149 gst_proxy_pad_query_default (GstPad * pad, GstQuery * query)
150 {
151   gboolean res = FALSE;
152   GstPad *target;
153
154   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
155   g_return_val_if_fail (GST_IS_QUERY (query), FALSE);
156
157   target = gst_proxy_pad_get_target (pad);
158   if (target) {
159     res = gst_pad_query (target, query);
160     gst_object_unref (target);
161   }
162
163   return res;
164 }
165
166 /**
167  * gst_proyx_pad_iterate_internal_links_default:
168  * @pad: the #GstPad to get the internal links of.
169  *
170  * Invoke the default iterate internal links function of the proxy pad.
171  *
172  * Returns: a #GstIterator of #GstPad, or NULL if @pad has no parent. Unref each
173  * returned pad with gst_object_unref().
174  *
175  * Since: 0.10.35
176  */
177 GstIterator *
178 gst_proxy_pad_iterate_internal_links_default (GstPad * pad)
179 {
180   GstIterator *res = NULL;
181   GstPad *internal;
182
183   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), NULL);
184
185   internal =
186       GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD_CAST (pad)));
187
188   if (internal) {
189     GValue v = { 0, };
190
191     g_value_init (&v, GST_TYPE_PAD);
192     g_value_set_object (&v, internal);
193     res = gst_iterator_new_single (GST_TYPE_PAD, &v);
194     g_value_unset (&v);
195     gst_object_unref (internal);
196   }
197
198   return res;
199 }
200
201 /**
202  * gst_proxy_pad_chain_default:
203  * @pad: a sink #GstPad, returns GST_FLOW_ERROR if not.
204  * @buffer: (transfer full): the #GstBuffer to send, return GST_FLOW_ERROR
205  *     if not.
206  *
207  * Invoke the default chain function of the proxy pad.
208  *
209  * Returns: a #GstFlowReturn from the pad.
210  *
211  * Since: 0.10.35
212  */
213 GstFlowReturn
214 gst_proxy_pad_chain_default (GstPad * pad, GstBuffer * buffer)
215 {
216   GstFlowReturn res;
217   GstPad *internal;
218
219   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), GST_FLOW_ERROR);
220   g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR);
221
222   internal = GST_PROXY_PAD_INTERNAL (pad);
223   res = gst_pad_push (internal, buffer);
224
225   return res;
226 }
227
228 /**
229  * gst_proxy_pad_chain_list_default:
230  * @pad: a sink #GstPad, returns GST_FLOW_ERROR if not.
231  * @list: (transfer full): the #GstBufferList to send, return GST_FLOW_ERROR
232  *     if not.
233  *
234  * Invoke the default chain list function of the proxy pad.
235  *
236  * Returns: a #GstFlowReturn from the pad.
237  *
238  * Since: 0.10.35
239  */
240 GstFlowReturn
241 gst_proxy_pad_chain_list_default (GstPad * pad, GstBufferList * list)
242 {
243   GstFlowReturn res;
244   GstPad *internal;
245
246   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), GST_FLOW_ERROR);
247   g_return_val_if_fail (GST_IS_BUFFER_LIST (list), GST_FLOW_ERROR);
248
249   internal = GST_PROXY_PAD_INTERNAL (pad);
250   res = gst_pad_push_list (internal, list);
251
252   return res;
253 }
254
255 /**
256  * gst_proxy_pad_get_range_default:
257  * @pad: a src #GstPad, returns #GST_FLOW_ERROR if not.
258  * @offset: The start offset of the buffer
259  * @size: The length of the buffer
260  * @buffer: (out callee-allocates): a pointer to hold the #GstBuffer,
261  *     returns #GST_FLOW_ERROR if %NULL.
262  *
263  * Invoke the default getrange function of the proxy pad.
264  *
265  * Returns: a #GstFlowReturn from the pad.
266  *
267  * Since: 0.10.35
268  */
269 GstFlowReturn
270 gst_proxy_pad_getrange_default (GstPad * pad, guint64 offset, guint size,
271     GstBuffer ** buffer)
272 {
273   GstFlowReturn res;
274   GstPad *internal;
275
276   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), GST_FLOW_ERROR);
277   g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
278
279   internal = GST_PROXY_PAD_INTERNAL (pad);
280   res = gst_pad_pull_range (internal, offset, size, buffer);
281
282   return res;
283 }
284
285 /**
286  * gst_proxy_pad_getcaps_default:
287  * @pad: a #GstPad to get the capabilities of.
288  * @filter: a #GstCaps filter.
289  *
290  * Invoke the default getcaps function of the proxy pad.
291  *
292  * Returns: (transfer full): the caps of the pad with incremented ref-count
293  *
294  * Since: 0.10.35
295  */
296 GstCaps *
297 gst_proxy_pad_getcaps_default (GstPad * pad, GstCaps * filter)
298 {
299   GstPad *target;
300   GstCaps *res;
301   GstPadTemplate *templ;
302
303   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), NULL);
304
305   templ = GST_PAD_PAD_TEMPLATE (pad);
306   target = gst_proxy_pad_get_target (pad);
307   if (target) {
308     /* if we have a real target, proxy the call */
309     res = gst_pad_get_caps (target, filter);
310
311     GST_DEBUG_OBJECT (pad, "get caps of target %s:%s : %" GST_PTR_FORMAT,
312         GST_DEBUG_PAD_NAME (target), res);
313
314     gst_object_unref (target);
315
316     /* filter against the template */
317     if (templ && res) {
318       GstCaps *filt, *tmp;
319
320       filt = GST_PAD_TEMPLATE_CAPS (templ);
321       if (filt) {
322         tmp = gst_caps_intersect_full (res, filt, GST_CAPS_INTERSECT_FIRST);
323         gst_caps_unref (res);
324         res = tmp;
325         GST_DEBUG_OBJECT (pad,
326             "filtered against template gives %" GST_PTR_FORMAT, res);
327       }
328     }
329   } else {
330     /* else, if we have a template, use its caps. */
331     if (templ) {
332       res = GST_PAD_TEMPLATE_CAPS (templ);
333       GST_DEBUG_OBJECT (pad,
334           "using pad template %p with caps %p %" GST_PTR_FORMAT, templ, res,
335           res);
336       res = gst_caps_ref (res);
337
338       if (filter) {
339         GstCaps *intersection =
340             gst_caps_intersect_full (filter, res, GST_CAPS_INTERSECT_FIRST);
341
342         gst_caps_unref (res);
343         res = intersection;
344       }
345
346       goto done;
347     }
348
349     /* last resort, any caps */
350     GST_DEBUG_OBJECT (pad, "pad has no template, returning ANY");
351     res = gst_caps_new_any ();
352   }
353
354 done:
355   return res;
356 }
357
358 /**
359  * gst_proxy_pad_acceptcaps_default:
360  * @pad: a #GstPad to check
361  * @caps: a #GstCaps to check on the pad
362  *
363  * Invoke the default acceptcaps function of the proxy pad.
364  *
365  * Returns: TRUE if the pad can accept the caps.
366  *
367  * Since: 0.10.35
368  */
369 gboolean
370 gst_proxy_pad_acceptcaps_default (GstPad * pad, GstCaps * caps)
371 {
372   GstPad *target;
373   gboolean res;
374
375   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
376   g_return_val_if_fail (caps == NULL || GST_IS_CAPS (caps), FALSE);
377
378   target = gst_proxy_pad_get_target (pad);
379   if (target) {
380     res = gst_pad_accept_caps (target, caps);
381     gst_object_unref (target);
382   } else {
383     /* We don't have a target, we return TRUE and we assume that any future
384      * target will be able to deal with any configured caps. */
385     res = TRUE;
386   }
387
388   return res;
389 }
390
391 /**
392  * gst_proxy_pad_fixatecaps_default:
393  * @pad: a  #GstPad to fixate
394  * @caps: the  #GstCaps to fixate
395  *
396  * Invoke the default fixatecaps function of the proxy pad.
397  *
398  * Since: 0.10.35
399  */
400 void
401 gst_proxy_pad_fixatecaps_default (GstPad * pad, GstCaps * caps)
402 {
403   GstPad *target;
404
405   g_return_if_fail (GST_IS_PROXY_PAD (pad));
406   g_return_if_fail (GST_IS_CAPS (caps));
407
408   target = gst_proxy_pad_get_target (pad);
409   if (target) {
410     gst_pad_fixate_caps (target, caps);
411     gst_object_unref (target);
412   }
413 }
414
415 static gboolean
416 gst_proxy_pad_set_target_unlocked (GstPad * pad, GstPad * target)
417 {
418   GstPad *oldtarget;
419
420   if (target) {
421     GST_LOG_OBJECT (pad, "setting target %s:%s", GST_DEBUG_PAD_NAME (target));
422
423     if (G_UNLIKELY (GST_PAD_DIRECTION (pad) != GST_PAD_DIRECTION (target)))
424       goto wrong_direction;
425   } else
426     GST_LOG_OBJECT (pad, "clearing target");
427
428   /* clear old target */
429   if ((oldtarget = GST_PROXY_PAD_TARGET (pad)))
430     gst_object_unref (oldtarget);
431
432   /* set and ref new target if any */
433   if (target)
434     GST_PROXY_PAD_TARGET (pad) = gst_object_ref (target);
435   else
436     GST_PROXY_PAD_TARGET (pad) = NULL;
437
438   return TRUE;
439
440   /* ERRORS */
441 wrong_direction:
442   {
443     GST_ERROR_OBJECT (pad,
444         "target pad doesn't have the same direction as ourself");
445     return FALSE;
446   }
447 }
448
449 static gboolean
450 gst_proxy_pad_set_target (GstPad * pad, GstPad * target)
451 {
452   gboolean result;
453
454   GST_PROXY_LOCK (pad);
455   result = gst_proxy_pad_set_target_unlocked (pad, target);
456   GST_PROXY_UNLOCK (pad);
457
458   return result;
459 }
460
461 static GstPad *
462 gst_proxy_pad_get_target (GstPad * pad)
463 {
464   GstPad *target;
465
466   GST_PROXY_LOCK (pad);
467   target = GST_PROXY_PAD_TARGET (pad);
468   if (target)
469     gst_object_ref (target);
470   GST_PROXY_UNLOCK (pad);
471
472   return target;
473 }
474
475 /**
476  * gst_proxy_pad_get_internal:
477  * @pad: the #GstProxyPad
478  *
479  * Get the internal pad of @pad. Unref target pad after usage.
480  *
481  * The internal pad of a #GstGhostPad is the internally used
482  * pad of opposite direction, which is used to link to the target.
483  *
484  * Returns: (transfer full): the target #GstProxyPad, can be NULL.
485  * Unref target pad after usage.
486  *
487  * Since: 0.10.35
488  */
489 GstProxyPad *
490 gst_proxy_pad_get_internal (GstProxyPad * pad)
491 {
492   GstPad *internal;
493
494   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), NULL);
495
496   GST_PROXY_LOCK (pad);
497   internal = GST_PROXY_PAD_INTERNAL (pad);
498   if (internal)
499     gst_object_ref (internal);
500   GST_PROXY_UNLOCK (pad);
501
502   return GST_PROXY_PAD_CAST (internal);
503 }
504
505 /**
506  * gst_proxy_pad_unlink_default:
507  * @pad: a #GstPad to unlink
508  *
509  * Invoke the default unlink function of the proxy pad.
510  *
511  * Since: 0.10.35
512  */
513 void
514 gst_proxy_pad_unlink_default (GstPad * pad)
515 {
516   GstPad *internal;
517
518   /* don't do anything if this unlink resulted from retargeting the pad
519    * controlled by the ghostpad. We only want to invalidate the target pad when
520    * the element suddently unlinked with our internal pad. */
521   if (GST_PROXY_PAD_RETARGET (pad))
522     return;
523
524   internal = GST_PROXY_PAD_INTERNAL (pad);
525
526   GST_DEBUG_OBJECT (pad, "pad is unlinked");
527
528   gst_proxy_pad_set_target (internal, NULL);
529 }
530
531 static void
532 gst_proxy_pad_class_init (GstProxyPadClass * klass)
533 {
534   GObjectClass *gobject_class = (GObjectClass *) klass;
535
536   g_type_class_add_private (klass, sizeof (GstProxyPadPrivate));
537
538   gobject_class->dispose = gst_proxy_pad_dispose;
539   gobject_class->finalize = gst_proxy_pad_finalize;
540
541   /* Register common function pointer descriptions */
542   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_query_type_default);
543   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_event_default);
544   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_query_default);
545   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_iterate_internal_links_default);
546   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_getcaps_default);
547   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_acceptcaps_default);
548   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_fixatecaps_default);
549   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_unlink_default);
550   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_chain_default);
551   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_chain_list_default);
552   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_getrange_default);
553 }
554
555 static void
556 gst_proxy_pad_dispose (GObject * object)
557 {
558   GstPad *pad = GST_PAD (object);
559   GstPad **target_p;
560
561   GST_PROXY_LOCK (pad);
562   /* remove and unref the target */
563   target_p = &GST_PROXY_PAD_TARGET (pad);
564   gst_object_replace ((GstObject **) target_p, NULL);
565   /* The internal is only cleared by GstGhostPad::dispose, since it is the 
566    * parent of non-ghost GstProxyPad and owns the refcount on the internal.
567    */
568   GST_PROXY_UNLOCK (pad);
569
570   G_OBJECT_CLASS (gst_proxy_pad_parent_class)->dispose (object);
571 }
572
573 static void
574 gst_proxy_pad_finalize (GObject * object)
575 {
576   GstProxyPad *pad = GST_PROXY_PAD (object);
577
578   g_mutex_free (GST_PROXY_GET_LOCK (pad));
579   GST_PROXY_GET_LOCK (pad) = NULL;
580
581   G_OBJECT_CLASS (gst_proxy_pad_parent_class)->finalize (object);
582 }
583
584 static void
585 gst_proxy_pad_init (GstProxyPad * ppad)
586 {
587   GstPad *pad = (GstPad *) ppad;
588
589   GST_PROXY_PAD_PRIVATE (ppad) = G_TYPE_INSTANCE_GET_PRIVATE (ppad,
590       GST_TYPE_PROXY_PAD, GstProxyPadPrivate);
591   GST_PROXY_GET_LOCK (pad) = g_mutex_new ();
592
593   gst_pad_set_query_type_function (pad, gst_proxy_pad_query_type_default);
594   gst_pad_set_event_function (pad, gst_proxy_pad_event_default);
595   gst_pad_set_query_function (pad, gst_proxy_pad_query_default);
596   gst_pad_set_iterate_internal_links_function (pad,
597       gst_proxy_pad_iterate_internal_links_default);
598
599   gst_pad_set_getcaps_function (pad, gst_proxy_pad_getcaps_default);
600   gst_pad_set_acceptcaps_function (pad, gst_proxy_pad_acceptcaps_default);
601   gst_pad_set_fixatecaps_function (pad, gst_proxy_pad_fixatecaps_default);
602   gst_pad_set_unlink_function (pad, gst_proxy_pad_unlink_default);
603 }
604
605
606 /***********************************************************************
607  * Ghost pads, implemented as a pair of proxy pads (sort of)
608  */
609
610
611 #define GST_GHOST_PAD_PRIVATE(obj)      (GST_GHOST_PAD_CAST (obj)->priv)
612
613 struct _GstGhostPadPrivate
614 {
615   /* with PROXY_LOCK */
616   gboolean constructed;
617 };
618
619 G_DEFINE_TYPE (GstGhostPad, gst_ghost_pad, GST_TYPE_PROXY_PAD);
620
621 static void gst_ghost_pad_dispose (GObject * object);
622
623 /**
624  * gst_ghost_pad_internal_activate_push_default:
625  * @pad: the #GstPad to activate or deactivate.
626  * @active: whether the pad should be active or not.
627  *
628  * Invoke the default activate push function of a proxy pad that is
629  * owned by a ghost pad.
630  *
631  * Returns: %TRUE if the operation was successful.
632  *
633  * Since: 0.10.35
634  */
635 gboolean
636 gst_ghost_pad_internal_activate_push_default (GstPad * pad, gboolean active)
637 {
638   gboolean ret;
639   GstPad *other;
640
641   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
642
643   GST_LOG_OBJECT (pad, "%sactivate push on %s:%s, we're ok",
644       (active ? "" : "de"), GST_DEBUG_PAD_NAME (pad));
645
646   /* in both cases (SRC and SINK) we activate just the internal pad. The targets
647    * will be activated later (or already in case of a ghost sinkpad). */
648   other = GST_PROXY_PAD_INTERNAL (pad);
649   ret = gst_pad_activate_push (other, active);
650
651   return ret;
652 }
653
654 /**
655  * gst_ghost_pad_internal_activate_pull_default:
656  * @pad: the #GstPad to activate or deactivate.
657  * @active: whether the pad should be active or not.
658  *
659  * Invoke the default activate pull function of a proxy pad that is
660  * owned by a ghost pad.
661  *
662  * Returns: %TRUE if the operation was successful.
663  *
664  * Since: 0.10.35
665  */
666 gboolean
667 gst_ghost_pad_internal_activate_pull_default (GstPad * pad, gboolean active)
668 {
669   gboolean ret;
670   GstPad *other;
671
672   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
673
674   GST_LOG_OBJECT (pad, "%sactivate pull on %s:%s", (active ? "" : "de"),
675       GST_DEBUG_PAD_NAME (pad));
676
677   if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC) {
678     /* we are activated in pull mode by our peer element, which is a sinkpad
679      * that wants to operate in pull mode. This activation has to propagate
680      * upstream throught the pipeline. We call the internal activation function,
681      * which will trigger gst_ghost_pad_activate_pull_default, which propagates even
682      * further upstream */
683     GST_LOG_OBJECT (pad, "pad is src, activate internal");
684     other = GST_PROXY_PAD_INTERNAL (pad);
685     ret = gst_pad_activate_pull (other, active);
686   } else if (G_LIKELY ((other = gst_pad_get_peer (pad)))) {
687     /* We are SINK, the ghostpad is SRC, we propagate the activation upstream
688      * since we hold a pointer to the upstream peer. */
689     GST_LOG_OBJECT (pad, "activating peer");
690     ret = gst_pad_activate_pull (other, active);
691     gst_object_unref (other);
692   } else {
693     /* this is failure, we can't activate pull if there is no peer */
694     GST_LOG_OBJECT (pad, "not src and no peer, failing");
695     ret = FALSE;
696   }
697
698   return ret;
699 }
700
701 /**
702  * gst_ghost_pad_activate_push_default:
703  * @pad: the #GstPad to activate or deactivate.
704  * @active: whether the pad should be active or not.
705  *
706  * Invoke the default activate push function of a ghost pad.
707  *
708  * Returns: %TRUE if the operation was successful.
709  *
710  * Since: 0.10.35
711  */
712 gboolean
713 gst_ghost_pad_activate_push_default (GstPad * pad, gboolean active)
714 {
715   gboolean ret;
716   GstPad *other;
717
718   g_return_val_if_fail (GST_IS_GHOST_PAD (pad), FALSE);
719
720   GST_LOG_OBJECT (pad, "%sactivate push on %s:%s, proxy internal",
721       (active ? "" : "de"), GST_DEBUG_PAD_NAME (pad));
722
723   /* just activate the internal pad */
724   other = GST_PROXY_PAD_INTERNAL (pad);
725   ret = gst_pad_activate_push (other, active);
726
727   return ret;
728 }
729
730 /**
731  * gst_ghost_pad_activate_pull_default:
732  * @pad: the #GstPad to activate or deactivate.
733  * @active: whether the pad should be active or not.
734  *
735  * Invoke the default activate pull function of a ghost pad.
736  *
737  * Returns: %TRUE if the operation was successful.
738  *
739  * Since: 0.10.35
740  */
741 gboolean
742 gst_ghost_pad_activate_pull_default (GstPad * pad, gboolean active)
743 {
744   gboolean ret;
745   GstPad *other;
746
747   g_return_val_if_fail (GST_IS_GHOST_PAD (pad), FALSE);
748
749   GST_LOG_OBJECT (pad, "%sactivate pull on %s:%s", (active ? "" : "de"),
750       GST_DEBUG_PAD_NAME (pad));
751
752   if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC) {
753     /* the ghostpad is SRC and activated in pull mode by its peer, call the
754      * activation function of the internal pad to propagate the activation
755      * upstream */
756     GST_LOG_OBJECT (pad, "pad is src, activate internal");
757     other = GST_PROXY_PAD_INTERNAL (pad);
758     ret = gst_pad_activate_pull (other, active);
759   } else if (G_LIKELY ((other = gst_pad_get_peer (pad)))) {
760     /* We are SINK and activated by the internal pad, propagate activation
761      * upstream because we hold a ref to the upstream peer */
762     GST_LOG_OBJECT (pad, "activating peer");
763     ret = gst_pad_activate_pull (other, active);
764     gst_object_unref (other);
765   } else {
766     /* no peer, we fail */
767     GST_LOG_OBJECT (pad, "pad not src and no peer, failing");
768     ret = FALSE;
769   }
770
771   return ret;
772 }
773
774 /**
775  * gst_ghost_pad_link_default:
776  * @pad: the #GstPad to link.
777  * @peer: the #GstPad peer
778  *
779  * Invoke the default link function of a ghost pad.
780  *
781  * Returns: #GstPadLinkReturn of the operation
782  *
783  * Since: 0.10.35
784  */
785 GstPadLinkReturn
786 gst_ghost_pad_link_default (GstPad * pad, GstPad * peer)
787 {
788   GstPadLinkReturn ret;
789   GstPad *internal;
790
791   g_return_val_if_fail (GST_IS_GHOST_PAD (pad), GST_PAD_LINK_REFUSED);
792   g_return_val_if_fail (GST_IS_PAD (peer), GST_PAD_LINK_REFUSED);
793
794   GST_DEBUG_OBJECT (pad, "linking ghostpad");
795
796   internal = GST_PROXY_PAD_INTERNAL (pad);
797   if (!gst_proxy_pad_set_target (internal, peer))
798     goto target_failed;
799
800   ret = GST_PAD_LINK_OK;
801   /* if we are a source pad, we should call the peer link function
802    * if the peer has one, see design docs. */
803   if (GST_PAD_IS_SRC (pad)) {
804     if (GST_PAD_LINKFUNC (peer)) {
805       ret = GST_PAD_LINKFUNC (peer) (peer, pad);
806       if (ret != GST_PAD_LINK_OK)
807         goto link_failed;
808     }
809   }
810   return ret;
811
812   /* ERRORS */
813 target_failed:
814   {
815     GST_DEBUG_OBJECT (pad, "setting target failed");
816     return GST_PAD_LINK_REFUSED;
817   }
818 link_failed:
819   {
820     GST_DEBUG_OBJECT (pad, "linking failed");
821     /* clear target again */
822     gst_proxy_pad_set_target (internal, NULL);
823     return ret;
824   }
825 }
826
827 /**
828  * gst_ghost_pad_unlink_default:
829  * @pad: the #GstPad to link.
830  *
831  * Invoke the default unlink function of a ghost pad.
832  *
833  * Since: 0.10.35
834  */
835 void
836 gst_ghost_pad_unlink_default (GstPad * pad)
837 {
838   GstPad *internal;
839
840   g_return_if_fail (GST_IS_GHOST_PAD (pad));
841
842   internal = GST_PROXY_PAD_INTERNAL (pad);
843
844   GST_DEBUG_OBJECT (pad, "unlinking ghostpad");
845
846   /* The target of the internal pad is no longer valid */
847   gst_proxy_pad_set_target (internal, NULL);
848 }
849
850 static void
851 gst_ghost_pad_class_init (GstGhostPadClass * klass)
852 {
853   GObjectClass *gobject_class = (GObjectClass *) klass;
854
855   g_type_class_add_private (klass, sizeof (GstGhostPadPrivate));
856
857   gobject_class->dispose = gst_ghost_pad_dispose;
858
859   GST_DEBUG_REGISTER_FUNCPTR (gst_ghost_pad_activate_pull_default);
860   GST_DEBUG_REGISTER_FUNCPTR (gst_ghost_pad_activate_push_default);
861   GST_DEBUG_REGISTER_FUNCPTR (gst_ghost_pad_link_default);
862 }
863
864 static void
865 gst_ghost_pad_init (GstGhostPad * pad)
866 {
867   GST_GHOST_PAD_PRIVATE (pad) = G_TYPE_INSTANCE_GET_PRIVATE (pad,
868       GST_TYPE_GHOST_PAD, GstGhostPadPrivate);
869
870   gst_pad_set_activatepull_function (GST_PAD_CAST (pad),
871       gst_ghost_pad_activate_pull_default);
872   gst_pad_set_activatepush_function (GST_PAD_CAST (pad),
873       gst_ghost_pad_activate_push_default);
874 }
875
876 static void
877 gst_ghost_pad_dispose (GObject * object)
878 {
879   GstPad *pad;
880   GstPad *internal;
881   GstPad *peer;
882
883   pad = GST_PAD (object);
884
885   GST_DEBUG_OBJECT (pad, "dispose");
886
887   gst_ghost_pad_set_target (GST_GHOST_PAD (pad), NULL);
888
889   /* Unlink here so that gst_pad_dispose doesn't. That would lead to a call to
890    * gst_ghost_pad_unlink_default when the ghost pad is in an inconsistent state */
891   peer = gst_pad_get_peer (pad);
892   if (peer) {
893     if (GST_PAD_IS_SRC (pad))
894       gst_pad_unlink (pad, peer);
895     else
896       gst_pad_unlink (peer, pad);
897
898     gst_object_unref (peer);
899   }
900
901   GST_PROXY_LOCK (pad);
902   internal = GST_PROXY_PAD_INTERNAL (pad);
903
904   gst_pad_set_activatepull_function (internal, NULL);
905   gst_pad_set_activatepush_function (internal, NULL);
906
907   /* disposes of the internal pad, since the ghostpad is the only possible object
908    * that has a refcount on the internal pad. */
909   gst_object_unparent (GST_OBJECT_CAST (internal));
910   GST_PROXY_PAD_INTERNAL (pad) = NULL;
911
912   GST_PROXY_UNLOCK (pad);
913
914   G_OBJECT_CLASS (gst_ghost_pad_parent_class)->dispose (object);
915 }
916
917 /**
918  * gst_ghost_pad_construct:
919  * @gpad: the newly allocated ghost pad
920  *
921  * Finish initialization of a newly allocated ghost pad.
922  *
923  * This function is most useful in language bindings and when subclassing
924  * #GstGhostPad; plugin and application developers normally will not call this
925  * function. Call this function directly after a call to g_object_new
926  * (GST_TYPE_GHOST_PAD, "direction", @dir, ..., NULL).
927  *
928  * Returns: %TRUE if the construction succeeds, %FALSE otherwise.
929  *
930  * Since: 0.10.22
931  */
932 gboolean
933 gst_ghost_pad_construct (GstGhostPad * gpad)
934 {
935   GstPadDirection dir, otherdir;
936   GstPadTemplate *templ;
937   GstPad *pad, *internal;
938
939   g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), FALSE);
940   g_return_val_if_fail (GST_GHOST_PAD_PRIVATE (gpad)->constructed == FALSE,
941       FALSE);
942
943   g_object_get (gpad, "direction", &dir, "template", &templ, NULL);
944
945   g_return_val_if_fail (dir != GST_PAD_UNKNOWN, FALSE);
946
947   pad = GST_PAD (gpad);
948
949   /* Set directional padfunctions for ghostpad */
950   if (dir == GST_PAD_SINK) {
951     gst_pad_set_chain_function (pad, gst_proxy_pad_chain_default);
952     gst_pad_set_chain_list_function (pad, gst_proxy_pad_chain_list_default);
953   } else {
954     gst_pad_set_getrange_function (pad, gst_proxy_pad_getrange_default);
955   }
956
957   /* link/unlink functions */
958   gst_pad_set_link_function (pad, gst_ghost_pad_link_default);
959   gst_pad_set_unlink_function (pad, gst_ghost_pad_unlink_default);
960
961   /* INTERNAL PAD, it always exists and is child of the ghostpad */
962   otherdir = (dir == GST_PAD_SRC) ? GST_PAD_SINK : GST_PAD_SRC;
963   if (templ) {
964     internal =
965         g_object_new (GST_TYPE_PROXY_PAD, "name", NULL,
966         "direction", otherdir, "template", templ, NULL);
967     /* release ref obtained via g_object_get */
968     gst_object_unref (templ);
969   } else {
970     internal =
971         g_object_new (GST_TYPE_PROXY_PAD, "name", NULL,
972         "direction", otherdir, NULL);
973   }
974   GST_PAD_UNSET_FLUSHING (internal);
975
976   /* Set directional padfunctions for internal pad */
977   if (dir == GST_PAD_SRC) {
978     gst_pad_set_chain_function (internal, gst_proxy_pad_chain_default);
979     gst_pad_set_chain_list_function (internal,
980         gst_proxy_pad_chain_list_default);
981   } else {
982     gst_pad_set_getrange_function (internal, gst_proxy_pad_getrange_default);
983   }
984
985   GST_PROXY_LOCK (pad);
986
987   /* now make the ghostpad a parent of the internal pad */
988   if (!gst_object_set_parent (GST_OBJECT_CAST (internal),
989           GST_OBJECT_CAST (pad)))
990     goto parent_failed;
991
992   /* The ghostpad is the parent of the internal pad and is the only object that
993    * can have a refcount on the internal pad.
994    * At this point, the GstGhostPad has a refcount of 1, and the internal pad has
995    * a refcount of 1.
996    * When the refcount of the GstGhostPad drops to 0, the ghostpad will dispose
997    * its refcount on the internal pad in the dispose method by un-parenting it.
998    * This is why we don't take extra refcounts in the assignments below
999    */
1000   GST_PROXY_PAD_INTERNAL (pad) = internal;
1001   GST_PROXY_PAD_INTERNAL (internal) = pad;
1002
1003   /* special activation functions for the internal pad */
1004   gst_pad_set_activatepull_function (internal,
1005       gst_ghost_pad_internal_activate_pull_default);
1006   gst_pad_set_activatepush_function (internal,
1007       gst_ghost_pad_internal_activate_push_default);
1008
1009   GST_PROXY_UNLOCK (pad);
1010
1011   GST_GHOST_PAD_PRIVATE (gpad)->constructed = TRUE;
1012   return TRUE;
1013
1014   /* ERRORS */
1015 parent_failed:
1016   {
1017     GST_WARNING_OBJECT (gpad, "Could not set internal pad %s:%s",
1018         GST_DEBUG_PAD_NAME (internal));
1019     g_critical ("Could not set internal pad %s:%s",
1020         GST_DEBUG_PAD_NAME (internal));
1021     GST_PROXY_UNLOCK (pad);
1022     gst_object_unref (internal);
1023     return FALSE;
1024   }
1025 }
1026
1027 static GstPad *
1028 gst_ghost_pad_new_full (const gchar * name, GstPadDirection dir,
1029     GstPadTemplate * templ)
1030 {
1031   GstGhostPad *ret;
1032
1033   g_return_val_if_fail (dir != GST_PAD_UNKNOWN, NULL);
1034
1035   /* OBJECT CREATION */
1036   if (templ) {
1037     ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name,
1038         "direction", dir, "template", templ, NULL);
1039   } else {
1040     ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name,
1041         "direction", dir, NULL);
1042   }
1043
1044   if (!gst_ghost_pad_construct (ret))
1045     goto construct_failed;
1046
1047   return GST_PAD_CAST (ret);
1048
1049 construct_failed:
1050   /* already logged */
1051   gst_object_unref (ret);
1052   return NULL;
1053 }
1054
1055 /**
1056  * gst_ghost_pad_new_no_target:
1057  * @name: (allow-none): the name of the new pad, or NULL to assign a default name.
1058  * @dir: the direction of the ghostpad
1059  *
1060  * Create a new ghostpad without a target with the given direction.
1061  * A target can be set on the ghostpad later with the
1062  * gst_ghost_pad_set_target() function.
1063  *
1064  * The created ghostpad will not have a padtemplate.
1065  *
1066  * Returns: (transfer full): a new #GstPad, or NULL in case of an error.
1067  */
1068 GstPad *
1069 gst_ghost_pad_new_no_target (const gchar * name, GstPadDirection dir)
1070 {
1071   GstPad *ret;
1072
1073   g_return_val_if_fail (dir != GST_PAD_UNKNOWN, NULL);
1074
1075   GST_LOG ("name:%s, direction:%d", GST_STR_NULL (name), dir);
1076
1077   ret = gst_ghost_pad_new_full (name, dir, NULL);
1078
1079   return ret;
1080 }
1081
1082 /**
1083  * gst_ghost_pad_new:
1084  * @name: (allow-none): the name of the new pad, or NULL to assign a default name
1085  * @target: (transfer none): the pad to ghost.
1086  *
1087  * Create a new ghostpad with @target as the target. The direction will be taken
1088  * from the target pad. @target must be unlinked.
1089  *
1090  * Will ref the target.
1091  *
1092  * Returns: (transfer full): a new #GstPad, or NULL in case of an error.
1093  */
1094 GstPad *
1095 gst_ghost_pad_new (const gchar * name, GstPad * target)
1096 {
1097   GstPad *ret;
1098
1099   g_return_val_if_fail (GST_IS_PAD (target), NULL);
1100   g_return_val_if_fail (!gst_pad_is_linked (target), NULL);
1101
1102   GST_LOG ("name:%s, target:%s:%s", GST_STR_NULL (name),
1103       GST_DEBUG_PAD_NAME (target));
1104
1105   if ((ret = gst_ghost_pad_new_no_target (name, GST_PAD_DIRECTION (target))))
1106     if (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (ret), target))
1107       goto set_target_failed;
1108
1109   return ret;
1110
1111   /* ERRORS */
1112 set_target_failed:
1113   {
1114     GST_WARNING_OBJECT (ret, "failed to set target %s:%s",
1115         GST_DEBUG_PAD_NAME (target));
1116     gst_object_unref (ret);
1117     return NULL;
1118   }
1119 }
1120
1121 /**
1122  * gst_ghost_pad_new_from_template:
1123  * @name: (allow-none): the name of the new pad, or NULL to assign a default name.
1124  * @target: (transfer none): the pad to ghost.
1125  * @templ: (transfer none): the #GstPadTemplate to use on the ghostpad.
1126  *
1127  * Create a new ghostpad with @target as the target. The direction will be taken
1128  * from the target pad. The template used on the ghostpad will be @template.
1129  *
1130  * Will ref the target.
1131  *
1132  * Returns: (transfer full): a new #GstPad, or NULL in case of an error.
1133  *
1134  * Since: 0.10.10
1135  */
1136
1137 GstPad *
1138 gst_ghost_pad_new_from_template (const gchar * name, GstPad * target,
1139     GstPadTemplate * templ)
1140 {
1141   GstPad *ret;
1142
1143   g_return_val_if_fail (GST_IS_PAD (target), NULL);
1144   g_return_val_if_fail (!gst_pad_is_linked (target), NULL);
1145   g_return_val_if_fail (templ != NULL, NULL);
1146   g_return_val_if_fail (GST_PAD_TEMPLATE_DIRECTION (templ) ==
1147       GST_PAD_DIRECTION (target), NULL);
1148
1149   GST_LOG ("name:%s, target:%s:%s, templ:%p", GST_STR_NULL (name),
1150       GST_DEBUG_PAD_NAME (target), templ);
1151
1152   if ((ret = gst_ghost_pad_new_full (name, GST_PAD_DIRECTION (target), templ)))
1153     if (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (ret), target))
1154       goto set_target_failed;
1155
1156   return ret;
1157
1158   /* ERRORS */
1159 set_target_failed:
1160   {
1161     GST_WARNING_OBJECT (ret, "failed to set target %s:%s",
1162         GST_DEBUG_PAD_NAME (target));
1163     gst_object_unref (ret);
1164     return NULL;
1165   }
1166 }
1167
1168 /**
1169  * gst_ghost_pad_new_no_target_from_template:
1170  * @name: (allow-none): the name of the new pad, or NULL to assign a default name
1171  * @templ: (transfer none): the #GstPadTemplate to create the ghostpad from.
1172  *
1173  * Create a new ghostpad based on @templ, without setting a target. The
1174  * direction will be taken from the @templ.
1175  *
1176  * Returns: (transfer full): a new #GstPad, or NULL in case of an error.
1177  *
1178  * Since: 0.10.10
1179  */
1180 GstPad *
1181 gst_ghost_pad_new_no_target_from_template (const gchar * name,
1182     GstPadTemplate * templ)
1183 {
1184   GstPad *ret;
1185
1186   g_return_val_if_fail (templ != NULL, NULL);
1187
1188   ret =
1189       gst_ghost_pad_new_full (name, GST_PAD_TEMPLATE_DIRECTION (templ), templ);
1190
1191   return ret;
1192 }
1193
1194 /**
1195  * gst_ghost_pad_get_target:
1196  * @gpad: the #GstGhostPad
1197  *
1198  * Get the target pad of @gpad. Unref target pad after usage.
1199  *
1200  * Returns: (transfer full): the target #GstPad, can be NULL if the ghostpad
1201  * has no target set. Unref target pad after usage.
1202  */
1203 GstPad *
1204 gst_ghost_pad_get_target (GstGhostPad * gpad)
1205 {
1206   GstPad *ret;
1207
1208   g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), NULL);
1209
1210   ret = gst_proxy_pad_get_target (GST_PAD_CAST (gpad));
1211
1212   GST_DEBUG_OBJECT (gpad, "get target %s:%s", GST_DEBUG_PAD_NAME (ret));
1213
1214   return ret;
1215 }
1216
1217 /**
1218  * gst_ghost_pad_set_target:
1219  * @gpad: the #GstGhostPad
1220  * @newtarget: (transfer none) (allow-none): the new pad target
1221  *
1222  * Set the new target of the ghostpad @gpad. Any existing target
1223  * is unlinked and links to the new target are established. if @newtarget is
1224  * NULL the target will be cleared.
1225  *
1226  * Returns: (transfer full): TRUE if the new target could be set. This function
1227  *     can return FALSE when the internal pads could not be linked.
1228  */
1229 gboolean
1230 gst_ghost_pad_set_target (GstGhostPad * gpad, GstPad * newtarget)
1231 {
1232   GstPad *internal;
1233   GstPad *oldtarget;
1234   gboolean result;
1235   GstPadLinkReturn lret;
1236
1237   g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), FALSE);
1238   g_return_val_if_fail (GST_PAD_CAST (gpad) != newtarget, FALSE);
1239   g_return_val_if_fail (newtarget != GST_PROXY_PAD_INTERNAL (gpad), FALSE);
1240
1241   /* no need for locking, the internal pad's lifecycle is directly linked to the
1242    * ghostpad's */
1243   internal = GST_PROXY_PAD_INTERNAL (gpad);
1244
1245   if (newtarget)
1246     GST_DEBUG_OBJECT (gpad, "set target %s:%s", GST_DEBUG_PAD_NAME (newtarget));
1247   else
1248     GST_DEBUG_OBJECT (gpad, "clearing target");
1249
1250   /* clear old target */
1251   GST_PROXY_LOCK (gpad);
1252   if ((oldtarget = GST_PROXY_PAD_TARGET (gpad))) {
1253
1254     GST_PROXY_PAD_RETARGET (internal) = TRUE;
1255
1256     /* unlink internal pad */
1257     if (GST_PAD_IS_SRC (internal))
1258       gst_pad_unlink (internal, oldtarget);
1259     else
1260       gst_pad_unlink (oldtarget, internal);
1261
1262     GST_PROXY_PAD_RETARGET (internal) = FALSE;
1263   }
1264
1265   result = gst_proxy_pad_set_target_unlocked (GST_PAD_CAST (gpad), newtarget);
1266   GST_PROXY_UNLOCK (gpad);
1267
1268   if (result && newtarget) {
1269     /* and link to internal pad without any checks */
1270     GST_DEBUG_OBJECT (gpad, "connecting internal pad to target");
1271
1272     if (GST_PAD_IS_SRC (internal))
1273       lret =
1274           gst_pad_link_full (internal, newtarget, GST_PAD_LINK_CHECK_NOTHING);
1275     else
1276       lret =
1277           gst_pad_link_full (newtarget, internal, GST_PAD_LINK_CHECK_NOTHING);
1278
1279     if (lret != GST_PAD_LINK_OK)
1280       goto link_failed;
1281   }
1282
1283   return result;
1284
1285   /* ERRORS */
1286 link_failed:
1287   {
1288     GST_WARNING_OBJECT (gpad, "could not link internal and target, reason:%d",
1289         lret);
1290     /* and unset target again */
1291     GST_PROXY_LOCK (gpad);
1292     gst_proxy_pad_set_target_unlocked (GST_PAD_CAST (gpad), NULL);
1293     GST_PROXY_UNLOCK (gpad);
1294     return FALSE;
1295   }
1296 }