Merge branch 'master' into 0.11
[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_checkgetrange_default:
287  * @pad: a src #GstPad, returns #GST_FLOW_ERROR if not.
288  *
289  * Invoke the default checkgetrange function of the proxy pad.
290  *
291  * Returns: a #gboolean from the pad.
292  *
293  * Since: 0.10.35
294  */
295 gboolean
296 gst_proxy_pad_checkgetrange_default (GstPad * pad)
297 {
298   gboolean result;
299   GstPad *internal;
300
301   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
302
303   internal = GST_PROXY_PAD_INTERNAL (pad);
304   result = gst_pad_check_pull_range (internal);
305
306   return result;
307 }
308
309 /**
310  * gst_proxy_pad_getcaps_default:
311  * @pad: a #GstPad to get the capabilities of.
312  * @filter: a #GstCaps filter.
313  *
314  * Invoke the default getcaps function of the proxy pad.
315  *
316  * Returns: (transfer full): the caps of the pad with incremented ref-count
317  *
318  * Since: 0.10.35
319  */
320 GstCaps *
321 gst_proxy_pad_getcaps_default (GstPad * pad, GstCaps * filter)
322 {
323   GstPad *target;
324   GstCaps *res;
325   GstPadTemplate *templ;
326
327   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), NULL);
328
329   templ = GST_PAD_PAD_TEMPLATE (pad);
330   target = gst_proxy_pad_get_target (pad);
331   if (target) {
332     /* if we have a real target, proxy the call */
333     res = gst_pad_get_caps (target, filter);
334
335     GST_DEBUG_OBJECT (pad, "get caps of target %s:%s : %" GST_PTR_FORMAT,
336         GST_DEBUG_PAD_NAME (target), res);
337
338     gst_object_unref (target);
339
340     /* filter against the template */
341     if (templ && res) {
342       GstCaps *filt, *tmp;
343
344       filt = GST_PAD_TEMPLATE_CAPS (templ);
345       if (filt) {
346         tmp = gst_caps_intersect_full (res, filt, GST_CAPS_INTERSECT_FIRST);
347         gst_caps_unref (res);
348         res = tmp;
349         GST_DEBUG_OBJECT (pad,
350             "filtered against template gives %" GST_PTR_FORMAT, res);
351       }
352     }
353   } else {
354     /* else, if we have a template, use its caps. */
355     if (templ) {
356       res = GST_PAD_TEMPLATE_CAPS (templ);
357       GST_DEBUG_OBJECT (pad,
358           "using pad template %p with caps %p %" GST_PTR_FORMAT, templ, res,
359           res);
360       res = gst_caps_ref (res);
361
362       if (filter) {
363         GstCaps *intersection =
364             gst_caps_intersect_full (filter, res, GST_CAPS_INTERSECT_FIRST);
365
366         gst_caps_unref (res);
367         res = intersection;
368       }
369
370       goto done;
371     }
372
373     /* last resort, any caps */
374     GST_DEBUG_OBJECT (pad, "pad has no template, returning ANY");
375     res = gst_caps_new_any ();
376   }
377
378 done:
379   return res;
380 }
381
382 /**
383  * gst_proxy_pad_acceptcaps_default:
384  * @pad: a #GstPad to check
385  * @caps: a #GstCaps to check on the pad
386  *
387  * Invoke the default acceptcaps function of the proxy pad.
388  *
389  * Returns: TRUE if the pad can accept the caps.
390  *
391  * Since: 0.10.35
392  */
393 gboolean
394 gst_proxy_pad_acceptcaps_default (GstPad * pad, GstCaps * caps)
395 {
396   GstPad *target;
397   gboolean res;
398
399   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
400   g_return_val_if_fail (caps == NULL || GST_IS_CAPS (caps), FALSE);
401
402   target = gst_proxy_pad_get_target (pad);
403   if (target) {
404     res = gst_pad_accept_caps (target, caps);
405     gst_object_unref (target);
406   } else {
407     /* We don't have a target, we return TRUE and we assume that any future
408      * target will be able to deal with any configured caps. */
409     res = TRUE;
410   }
411
412   return res;
413 }
414
415 /**
416  * gst_proxy_pad_fixatecaps_default:
417  * @pad: a  #GstPad to fixate
418  * @caps: the  #GstCaps to fixate
419  *
420  * Invoke the default fixatecaps function of the proxy pad.
421  *
422  * Since: 0.10.35
423  */
424 void
425 gst_proxy_pad_fixatecaps_default (GstPad * pad, GstCaps * caps)
426 {
427   GstPad *target;
428
429   g_return_if_fail (GST_IS_PROXY_PAD (pad));
430   g_return_if_fail (GST_IS_CAPS (caps));
431
432   target = gst_proxy_pad_get_target (pad);
433   if (target) {
434     gst_pad_fixate_caps (target, caps);
435     gst_object_unref (target);
436   }
437 }
438
439 /**
440  * gst_proxy_pad_setcaps_default:
441  * @pad: a  #GstPad to set the capabilities of.
442  * @caps: (transfer none): a #GstCaps to set.
443  *
444  * Invoke the default setcaps function of the proxy pad.
445  *
446  * Returns: TRUE if the caps could be set. FALSE if the caps were not fixed
447  * or bad parameters were provided to this function.
448  *
449  * Since: 0.10.35
450  */
451 gboolean
452 gst_proxy_pad_setcaps_default (GstPad * pad, GstCaps * caps)
453 {
454   GstPad *target;
455   gboolean res;
456
457   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
458   g_return_val_if_fail (caps == NULL || GST_IS_CAPS (caps), FALSE);
459
460   target = gst_proxy_pad_get_target (pad);
461   if (target) {
462 #if 0
463     /* FIXME, not needed, the caps event will propagate over the pads
464      * correctly */
465     res = gst_pad_set_caps (target, caps);
466 #endif
467     res = TRUE;
468     gst_object_unref (target);
469   } else {
470     /* We don't have any target, but we shouldn't return FALSE since this
471      * would stop the actual push of a buffer (which might trigger a pad block
472      * or probe, or properly return GST_FLOW_NOT_LINKED.
473      */
474     res = TRUE;
475   }
476   return res;
477 }
478
479 static gboolean
480 gst_proxy_pad_set_target_unlocked (GstPad * pad, GstPad * target)
481 {
482   GstPad *oldtarget;
483
484   if (target) {
485     GST_LOG_OBJECT (pad, "setting target %s:%s", GST_DEBUG_PAD_NAME (target));
486
487     if (G_UNLIKELY (GST_PAD_DIRECTION (pad) != GST_PAD_DIRECTION (target)))
488       goto wrong_direction;
489   } else
490     GST_LOG_OBJECT (pad, "clearing target");
491
492   /* clear old target */
493   if ((oldtarget = GST_PROXY_PAD_TARGET (pad)))
494     gst_object_unref (oldtarget);
495
496   /* set and ref new target if any */
497   if (target)
498     GST_PROXY_PAD_TARGET (pad) = gst_object_ref (target);
499   else
500     GST_PROXY_PAD_TARGET (pad) = NULL;
501
502   return TRUE;
503
504   /* ERRORS */
505 wrong_direction:
506   {
507     GST_ERROR_OBJECT (pad,
508         "target pad doesn't have the same direction as ourself");
509     return FALSE;
510   }
511 }
512
513 static gboolean
514 gst_proxy_pad_set_target (GstPad * pad, GstPad * target)
515 {
516   gboolean result;
517
518   GST_PROXY_LOCK (pad);
519   result = gst_proxy_pad_set_target_unlocked (pad, target);
520   GST_PROXY_UNLOCK (pad);
521
522   return result;
523 }
524
525 static GstPad *
526 gst_proxy_pad_get_target (GstPad * pad)
527 {
528   GstPad *target;
529
530   GST_PROXY_LOCK (pad);
531   target = GST_PROXY_PAD_TARGET (pad);
532   if (target)
533     gst_object_ref (target);
534   GST_PROXY_UNLOCK (pad);
535
536   return target;
537 }
538
539 /**
540  * gst_proxy_pad_get_internal:
541  * @pad: the #GstProxyPad
542  *
543  * Get the internal pad of @pad. Unref target pad after usage.
544  *
545  * The internal pad of a #GstGhostPad is the internally used
546  * pad of opposite direction, which is used to link to the target.
547  *
548  * Returns: (transfer full): the target #GstProxyPad, can be NULL.
549  * Unref target pad after usage.
550  *
551  * Since: 0.10.35
552  */
553 GstProxyPad *
554 gst_proxy_pad_get_internal (GstProxyPad * pad)
555 {
556   GstPad *internal;
557
558   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), NULL);
559
560   GST_PROXY_LOCK (pad);
561   internal = GST_PROXY_PAD_INTERNAL (pad);
562   if (internal)
563     gst_object_ref (internal);
564   GST_PROXY_UNLOCK (pad);
565
566   return GST_PROXY_PAD_CAST (internal);
567 }
568
569 /**
570  * gst_proxy_pad_unlink_default:
571  * @pad: a #GstPad to unlink
572  *
573  * Invoke the default unlink function of the proxy pad.
574  *
575  * Since: 0.10.35
576  */
577 void
578 gst_proxy_pad_unlink_default (GstPad * pad)
579 {
580   GstPad *internal;
581
582   /* don't do anything if this unlink resulted from retargeting the pad
583    * controlled by the ghostpad. We only want to invalidate the target pad when
584    * the element suddently unlinked with our internal pad. */
585   if (GST_PROXY_PAD_RETARGET (pad))
586     return;
587
588   internal = GST_PROXY_PAD_INTERNAL (pad);
589
590   GST_DEBUG_OBJECT (pad, "pad is unlinked");
591
592   gst_proxy_pad_set_target (internal, NULL);
593 }
594
595 static void
596 gst_proxy_pad_class_init (GstProxyPadClass * klass)
597 {
598   GObjectClass *gobject_class = (GObjectClass *) klass;
599
600   g_type_class_add_private (klass, sizeof (GstProxyPadPrivate));
601
602   gobject_class->dispose = gst_proxy_pad_dispose;
603   gobject_class->finalize = gst_proxy_pad_finalize;
604
605   /* Register common function pointer descriptions */
606   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_query_type_default);
607   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_event_default);
608   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_query_default);
609   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_iterate_internal_links_default);
610   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_getcaps_default);
611   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_acceptcaps_default);
612   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_fixatecaps_default);
613   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_setcaps_default);
614   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_unlink_default);
615   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_chain_default);
616   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_chain_list_default);
617   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_getrange_default);
618   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_checkgetrange_default);
619 }
620
621 static void
622 gst_proxy_pad_dispose (GObject * object)
623 {
624   GstPad *pad = GST_PAD (object);
625   GstPad **target_p;
626
627   GST_PROXY_LOCK (pad);
628   /* remove and unref the target */
629   target_p = &GST_PROXY_PAD_TARGET (pad);
630   gst_object_replace ((GstObject **) target_p, NULL);
631   /* The internal is only cleared by GstGhostPad::dispose, since it is the 
632    * parent of non-ghost GstProxyPad and owns the refcount on the internal.
633    */
634   GST_PROXY_UNLOCK (pad);
635
636   G_OBJECT_CLASS (gst_proxy_pad_parent_class)->dispose (object);
637 }
638
639 static void
640 gst_proxy_pad_finalize (GObject * object)
641 {
642   GstProxyPad *pad = GST_PROXY_PAD (object);
643
644   g_mutex_free (GST_PROXY_GET_LOCK (pad));
645   GST_PROXY_GET_LOCK (pad) = NULL;
646
647   G_OBJECT_CLASS (gst_proxy_pad_parent_class)->finalize (object);
648 }
649
650 static void
651 gst_proxy_pad_init (GstProxyPad * ppad)
652 {
653   GstPad *pad = (GstPad *) ppad;
654
655   GST_PROXY_PAD_PRIVATE (ppad) = G_TYPE_INSTANCE_GET_PRIVATE (ppad,
656       GST_TYPE_PROXY_PAD, GstProxyPadPrivate);
657   GST_PROXY_GET_LOCK (pad) = g_mutex_new ();
658
659   gst_pad_set_query_type_function (pad, gst_proxy_pad_query_type_default);
660   gst_pad_set_event_function (pad, gst_proxy_pad_event_default);
661   gst_pad_set_query_function (pad, gst_proxy_pad_query_default);
662   gst_pad_set_iterate_internal_links_function (pad,
663       gst_proxy_pad_iterate_internal_links_default);
664
665   gst_pad_set_getcaps_function (pad, gst_proxy_pad_getcaps_default);
666   gst_pad_set_acceptcaps_function (pad, gst_proxy_pad_acceptcaps_default);
667   gst_pad_set_fixatecaps_function (pad, gst_proxy_pad_fixatecaps_default);
668   gst_pad_set_setcaps_function (pad, gst_proxy_pad_setcaps_default);
669   gst_pad_set_unlink_function (pad, gst_proxy_pad_unlink_default);
670 }
671
672
673 /***********************************************************************
674  * Ghost pads, implemented as a pair of proxy pads (sort of)
675  */
676
677
678 #define GST_GHOST_PAD_PRIVATE(obj)      (GST_GHOST_PAD_CAST (obj)->priv)
679
680 struct _GstGhostPadPrivate
681 {
682   /* with PROXY_LOCK */
683   gboolean constructed;
684 };
685
686 G_DEFINE_TYPE (GstGhostPad, gst_ghost_pad, GST_TYPE_PROXY_PAD);
687
688 static void gst_ghost_pad_dispose (GObject * object);
689
690 /**
691  * gst_ghost_pad_internal_activate_push_default:
692  * @pad: the #GstPad to activate or deactivate.
693  * @active: whether the pad should be active or not.
694  *
695  * Invoke the default activate push function of a proxy pad that is
696  * owned by a ghost pad.
697  *
698  * Returns: %TRUE if the operation was successful.
699  *
700  * Since: 0.10.35
701  */
702 gboolean
703 gst_ghost_pad_internal_activate_push_default (GstPad * pad, gboolean active)
704 {
705   gboolean ret;
706   GstPad *other;
707
708   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
709
710   GST_LOG_OBJECT (pad, "%sactivate push on %s:%s, we're ok",
711       (active ? "" : "de"), GST_DEBUG_PAD_NAME (pad));
712
713   /* in both cases (SRC and SINK) we activate just the internal pad. The targets
714    * will be activated later (or already in case of a ghost sinkpad). */
715   other = GST_PROXY_PAD_INTERNAL (pad);
716   ret = gst_pad_activate_push (other, active);
717
718   return ret;
719 }
720
721 /**
722  * gst_ghost_pad_internal_activate_pull_default:
723  * @pad: the #GstPad to activate or deactivate.
724  * @active: whether the pad should be active or not.
725  *
726  * Invoke the default activate pull function of a proxy pad that is
727  * owned by a ghost pad.
728  *
729  * Returns: %TRUE if the operation was successful.
730  *
731  * Since: 0.10.35
732  */
733 gboolean
734 gst_ghost_pad_internal_activate_pull_default (GstPad * pad, gboolean active)
735 {
736   gboolean ret;
737   GstPad *other;
738
739   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
740
741   GST_LOG_OBJECT (pad, "%sactivate pull on %s:%s", (active ? "" : "de"),
742       GST_DEBUG_PAD_NAME (pad));
743
744   if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC) {
745     /* we are activated in pull mode by our peer element, which is a sinkpad
746      * that wants to operate in pull mode. This activation has to propagate
747      * upstream throught the pipeline. We call the internal activation function,
748      * which will trigger gst_ghost_pad_activate_pull_default, which propagates even
749      * further upstream */
750     GST_LOG_OBJECT (pad, "pad is src, activate internal");
751     other = GST_PROXY_PAD_INTERNAL (pad);
752     ret = gst_pad_activate_pull (other, active);
753   } else if (G_LIKELY ((other = gst_pad_get_peer (pad)))) {
754     /* We are SINK, the ghostpad is SRC, we propagate the activation upstream
755      * since we hold a pointer to the upstream peer. */
756     GST_LOG_OBJECT (pad, "activating peer");
757     ret = gst_pad_activate_pull (other, active);
758     gst_object_unref (other);
759   } else {
760     /* this is failure, we can't activate pull if there is no peer */
761     GST_LOG_OBJECT (pad, "not src and no peer, failing");
762     ret = FALSE;
763   }
764
765   return ret;
766 }
767
768 /**
769  * gst_ghost_pad_activate_push_default:
770  * @pad: the #GstPad to activate or deactivate.
771  * @active: whether the pad should be active or not.
772  *
773  * Invoke the default activate push function of a ghost pad.
774  *
775  * Returns: %TRUE if the operation was successful.
776  *
777  * Since: 0.10.35
778  */
779 gboolean
780 gst_ghost_pad_activate_push_default (GstPad * pad, gboolean active)
781 {
782   gboolean ret;
783   GstPad *other;
784
785   g_return_val_if_fail (GST_IS_GHOST_PAD (pad), FALSE);
786
787   GST_LOG_OBJECT (pad, "%sactivate push on %s:%s, proxy internal",
788       (active ? "" : "de"), GST_DEBUG_PAD_NAME (pad));
789
790   /* just activate the internal pad */
791   other = GST_PROXY_PAD_INTERNAL (pad);
792   ret = gst_pad_activate_push (other, active);
793
794   return ret;
795 }
796
797 /**
798  * gst_ghost_pad_activate_pull_default:
799  * @pad: the #GstPad to activate or deactivate.
800  * @active: whether the pad should be active or not.
801  *
802  * Invoke the default activate pull function of a ghost pad.
803  *
804  * Returns: %TRUE if the operation was successful.
805  *
806  * Since: 0.10.35
807  */
808 gboolean
809 gst_ghost_pad_activate_pull_default (GstPad * pad, gboolean active)
810 {
811   gboolean ret;
812   GstPad *other;
813
814   g_return_val_if_fail (GST_IS_GHOST_PAD (pad), FALSE);
815
816   GST_LOG_OBJECT (pad, "%sactivate pull on %s:%s", (active ? "" : "de"),
817       GST_DEBUG_PAD_NAME (pad));
818
819   if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC) {
820     /* the ghostpad is SRC and activated in pull mode by its peer, call the
821      * activation function of the internal pad to propagate the activation
822      * upstream */
823     GST_LOG_OBJECT (pad, "pad is src, activate internal");
824     other = GST_PROXY_PAD_INTERNAL (pad);
825     ret = gst_pad_activate_pull (other, active);
826   } else if (G_LIKELY ((other = gst_pad_get_peer (pad)))) {
827     /* We are SINK and activated by the internal pad, propagate activation
828      * upstream because we hold a ref to the upstream peer */
829     GST_LOG_OBJECT (pad, "activating peer");
830     ret = gst_pad_activate_pull (other, active);
831     gst_object_unref (other);
832   } else {
833     /* no peer, we fail */
834     GST_LOG_OBJECT (pad, "pad not src and no peer, failing");
835     ret = FALSE;
836   }
837
838   return ret;
839 }
840
841 /**
842  * gst_ghost_pad_link_default:
843  * @pad: the #GstPad to link.
844  * @peer: the #GstPad peer
845  *
846  * Invoke the default link function of a ghost pad.
847  *
848  * Returns: #GstPadLinkReturn of the operation
849  *
850  * Since: 0.10.35
851  */
852 GstPadLinkReturn
853 gst_ghost_pad_link_default (GstPad * pad, GstPad * peer)
854 {
855   GstPadLinkReturn ret;
856   GstPad *internal;
857
858   g_return_val_if_fail (GST_IS_GHOST_PAD (pad), GST_PAD_LINK_REFUSED);
859   g_return_val_if_fail (GST_IS_PAD (peer), GST_PAD_LINK_REFUSED);
860
861   GST_DEBUG_OBJECT (pad, "linking ghostpad");
862
863   internal = GST_PROXY_PAD_INTERNAL (pad);
864   if (!gst_proxy_pad_set_target (internal, peer))
865     goto target_failed;
866
867   ret = GST_PAD_LINK_OK;
868   /* if we are a source pad, we should call the peer link function
869    * if the peer has one, see design docs. */
870   if (GST_PAD_IS_SRC (pad)) {
871     if (GST_PAD_LINKFUNC (peer)) {
872       ret = GST_PAD_LINKFUNC (peer) (peer, pad);
873       if (ret != GST_PAD_LINK_OK)
874         goto link_failed;
875     }
876   }
877   return ret;
878
879   /* ERRORS */
880 target_failed:
881   {
882     GST_DEBUG_OBJECT (pad, "setting target failed");
883     return GST_PAD_LINK_REFUSED;
884   }
885 link_failed:
886   {
887     GST_DEBUG_OBJECT (pad, "linking failed");
888     /* clear target again */
889     gst_proxy_pad_set_target (internal, NULL);
890     return ret;
891   }
892 }
893
894 /**
895  * gst_ghost_pad_unlink_default:
896  * @pad: the #GstPad to link.
897  *
898  * Invoke the default unlink function of a ghost pad.
899  *
900  * Since: 0.10.35
901  */
902 void
903 gst_ghost_pad_unlink_default (GstPad * pad)
904 {
905   GstPad *internal;
906
907   g_return_if_fail (GST_IS_GHOST_PAD (pad));
908
909   internal = GST_PROXY_PAD_INTERNAL (pad);
910
911   GST_DEBUG_OBJECT (pad, "unlinking ghostpad");
912
913   /* The target of the internal pad is no longer valid */
914   gst_proxy_pad_set_target (internal, NULL);
915 }
916
917 /**
918  * gst_ghost_pad_setcaps_default:
919  * @pad: the #GstPad to link.
920  * @caps: (transfer none): the #GstCaps to set
921  *
922  * Invoke the default setcaps function of a ghost pad.
923  *
924  * Returns: %TRUE if the operation was successful
925  *
926  * Since: 0.10.35
927  */
928 gboolean
929 gst_ghost_pad_setcaps_default (GstPad * pad, GstCaps * caps)
930 {
931   g_return_val_if_fail (GST_IS_GHOST_PAD (pad), FALSE);
932   g_return_val_if_fail (caps == NULL || GST_IS_CAPS (caps), FALSE);
933
934   if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC)
935     return TRUE;
936
937   return gst_proxy_pad_setcaps_default (pad, caps);
938 }
939
940 static void
941 gst_ghost_pad_class_init (GstGhostPadClass * klass)
942 {
943   GObjectClass *gobject_class = (GObjectClass *) klass;
944
945   g_type_class_add_private (klass, sizeof (GstGhostPadPrivate));
946
947   gobject_class->dispose = gst_ghost_pad_dispose;
948
949   GST_DEBUG_REGISTER_FUNCPTR (gst_ghost_pad_setcaps_default);
950   GST_DEBUG_REGISTER_FUNCPTR (gst_ghost_pad_activate_pull_default);
951   GST_DEBUG_REGISTER_FUNCPTR (gst_ghost_pad_activate_push_default);
952   GST_DEBUG_REGISTER_FUNCPTR (gst_ghost_pad_link_default);
953 }
954
955 static void
956 gst_ghost_pad_init (GstGhostPad * pad)
957 {
958   GST_GHOST_PAD_PRIVATE (pad) = G_TYPE_INSTANCE_GET_PRIVATE (pad,
959       GST_TYPE_GHOST_PAD, GstGhostPadPrivate);
960
961   gst_pad_set_setcaps_function (GST_PAD_CAST (pad),
962       gst_ghost_pad_setcaps_default);
963   gst_pad_set_activatepull_function (GST_PAD_CAST (pad),
964       gst_ghost_pad_activate_pull_default);
965   gst_pad_set_activatepush_function (GST_PAD_CAST (pad),
966       gst_ghost_pad_activate_push_default);
967 }
968
969 static void
970 gst_ghost_pad_dispose (GObject * object)
971 {
972   GstPad *pad;
973   GstPad *internal;
974   GstPad *peer;
975
976   pad = GST_PAD (object);
977
978   GST_DEBUG_OBJECT (pad, "dispose");
979
980   gst_ghost_pad_set_target (GST_GHOST_PAD (pad), NULL);
981
982   /* Unlink here so that gst_pad_dispose doesn't. That would lead to a call to
983    * gst_ghost_pad_unlink_default when the ghost pad is in an inconsistent state */
984   peer = gst_pad_get_peer (pad);
985   if (peer) {
986     if (GST_PAD_IS_SRC (pad))
987       gst_pad_unlink (pad, peer);
988     else
989       gst_pad_unlink (peer, pad);
990
991     gst_object_unref (peer);
992   }
993
994   GST_PROXY_LOCK (pad);
995   internal = GST_PROXY_PAD_INTERNAL (pad);
996
997   gst_pad_set_activatepull_function (internal, NULL);
998   gst_pad_set_activatepush_function (internal, NULL);
999
1000   /* disposes of the internal pad, since the ghostpad is the only possible object
1001    * that has a refcount on the internal pad. */
1002   gst_object_unparent (GST_OBJECT_CAST (internal));
1003   GST_PROXY_PAD_INTERNAL (pad) = NULL;
1004
1005   GST_PROXY_UNLOCK (pad);
1006
1007   G_OBJECT_CLASS (gst_ghost_pad_parent_class)->dispose (object);
1008 }
1009
1010 /**
1011  * gst_ghost_pad_construct:
1012  * @gpad: the newly allocated ghost pad
1013  *
1014  * Finish initialization of a newly allocated ghost pad.
1015  *
1016  * This function is most useful in language bindings and when subclassing
1017  * #GstGhostPad; plugin and application developers normally will not call this
1018  * function. Call this function directly after a call to g_object_new
1019  * (GST_TYPE_GHOST_PAD, "direction", @dir, ..., NULL).
1020  *
1021  * Returns: %TRUE if the construction succeeds, %FALSE otherwise.
1022  *
1023  * Since: 0.10.22
1024  */
1025 gboolean
1026 gst_ghost_pad_construct (GstGhostPad * gpad)
1027 {
1028   GstPadDirection dir, otherdir;
1029   GstPadTemplate *templ;
1030   GstPad *pad, *internal;
1031
1032   g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), FALSE);
1033   g_return_val_if_fail (GST_GHOST_PAD_PRIVATE (gpad)->constructed == FALSE,
1034       FALSE);
1035
1036   g_object_get (gpad, "direction", &dir, "template", &templ, NULL);
1037
1038   g_return_val_if_fail (dir != GST_PAD_UNKNOWN, FALSE);
1039
1040   pad = GST_PAD (gpad);
1041
1042   /* Set directional padfunctions for ghostpad */
1043   if (dir == GST_PAD_SINK) {
1044     gst_pad_set_chain_function (pad, gst_proxy_pad_chain_default);
1045     gst_pad_set_chain_list_function (pad, gst_proxy_pad_chain_list_default);
1046   } else {
1047     gst_pad_set_getrange_function (pad, gst_proxy_pad_getrange_default);
1048     gst_pad_set_checkgetrange_function (pad,
1049         gst_proxy_pad_checkgetrange_default);
1050   }
1051
1052   /* link/unlink functions */
1053   gst_pad_set_link_function (pad, gst_ghost_pad_link_default);
1054   gst_pad_set_unlink_function (pad, gst_ghost_pad_unlink_default);
1055
1056   /* INTERNAL PAD, it always exists and is child of the ghostpad */
1057   otherdir = (dir == GST_PAD_SRC) ? GST_PAD_SINK : GST_PAD_SRC;
1058   if (templ) {
1059     internal =
1060         g_object_new (GST_TYPE_PROXY_PAD, "name", NULL,
1061         "direction", otherdir, "template", templ, NULL);
1062     /* release ref obtained via g_object_get */
1063     gst_object_unref (templ);
1064   } else {
1065     internal =
1066         g_object_new (GST_TYPE_PROXY_PAD, "name", NULL,
1067         "direction", otherdir, NULL);
1068   }
1069   GST_PAD_UNSET_FLUSHING (internal);
1070
1071   /* Set directional padfunctions for internal pad */
1072   if (dir == GST_PAD_SRC) {
1073     gst_pad_set_chain_function (internal, gst_proxy_pad_chain_default);
1074     gst_pad_set_chain_list_function (internal,
1075         gst_proxy_pad_chain_list_default);
1076   } else {
1077     gst_pad_set_getrange_function (internal, gst_proxy_pad_getrange_default);
1078     gst_pad_set_checkgetrange_function (internal,
1079         gst_proxy_pad_checkgetrange_default);
1080   }
1081
1082   GST_PROXY_LOCK (pad);
1083
1084   /* now make the ghostpad a parent of the internal pad */
1085   if (!gst_object_set_parent (GST_OBJECT_CAST (internal),
1086           GST_OBJECT_CAST (pad)))
1087     goto parent_failed;
1088
1089   /* The ghostpad is the parent of the internal pad and is the only object that
1090    * can have a refcount on the internal pad.
1091    * At this point, the GstGhostPad has a refcount of 1, and the internal pad has
1092    * a refcount of 1.
1093    * When the refcount of the GstGhostPad drops to 0, the ghostpad will dispose
1094    * its refcount on the internal pad in the dispose method by un-parenting it.
1095    * This is why we don't take extra refcounts in the assignments below
1096    */
1097   GST_PROXY_PAD_INTERNAL (pad) = internal;
1098   GST_PROXY_PAD_INTERNAL (internal) = pad;
1099
1100   /* special activation functions for the internal pad */
1101   gst_pad_set_activatepull_function (internal,
1102       gst_ghost_pad_internal_activate_pull_default);
1103   gst_pad_set_activatepush_function (internal,
1104       gst_ghost_pad_internal_activate_push_default);
1105
1106   GST_PROXY_UNLOCK (pad);
1107
1108   GST_GHOST_PAD_PRIVATE (gpad)->constructed = TRUE;
1109   return TRUE;
1110
1111   /* ERRORS */
1112 parent_failed:
1113   {
1114     GST_WARNING_OBJECT (gpad, "Could not set internal pad %s:%s",
1115         GST_DEBUG_PAD_NAME (internal));
1116     g_critical ("Could not set internal pad %s:%s",
1117         GST_DEBUG_PAD_NAME (internal));
1118     GST_PROXY_UNLOCK (pad);
1119     gst_object_unref (internal);
1120     return FALSE;
1121   }
1122 }
1123
1124 static GstPad *
1125 gst_ghost_pad_new_full (const gchar * name, GstPadDirection dir,
1126     GstPadTemplate * templ)
1127 {
1128   GstGhostPad *ret;
1129
1130   g_return_val_if_fail (dir != GST_PAD_UNKNOWN, NULL);
1131
1132   /* OBJECT CREATION */
1133   if (templ) {
1134     ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name,
1135         "direction", dir, "template", templ, NULL);
1136   } else {
1137     ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name,
1138         "direction", dir, NULL);
1139   }
1140
1141   if (!gst_ghost_pad_construct (ret))
1142     goto construct_failed;
1143
1144   return GST_PAD_CAST (ret);
1145
1146 construct_failed:
1147   /* already logged */
1148   gst_object_unref (ret);
1149   return NULL;
1150 }
1151
1152 /**
1153  * gst_ghost_pad_new_no_target:
1154  * @name: (allow-none): the name of the new pad, or NULL to assign a default name.
1155  * @dir: the direction of the ghostpad
1156  *
1157  * Create a new ghostpad without a target with the given direction.
1158  * A target can be set on the ghostpad later with the
1159  * gst_ghost_pad_set_target() function.
1160  *
1161  * The created ghostpad will not have a padtemplate.
1162  *
1163  * Returns: (transfer full): a new #GstPad, or NULL in case of an error.
1164  */
1165 GstPad *
1166 gst_ghost_pad_new_no_target (const gchar * name, GstPadDirection dir)
1167 {
1168   GstPad *ret;
1169
1170   g_return_val_if_fail (dir != GST_PAD_UNKNOWN, NULL);
1171
1172   GST_LOG ("name:%s, direction:%d", GST_STR_NULL (name), dir);
1173
1174   ret = gst_ghost_pad_new_full (name, dir, NULL);
1175
1176   return ret;
1177 }
1178
1179 /**
1180  * gst_ghost_pad_new:
1181  * @name: (allow-none): the name of the new pad, or NULL to assign a default name
1182  * @target: (transfer none): the pad to ghost.
1183  *
1184  * Create a new ghostpad with @target as the target. The direction will be taken
1185  * from the target pad. @target must be unlinked.
1186  *
1187  * Will ref the target.
1188  *
1189  * Returns: (transfer full): a new #GstPad, or NULL in case of an error.
1190  */
1191 GstPad *
1192 gst_ghost_pad_new (const gchar * name, GstPad * target)
1193 {
1194   GstPad *ret;
1195
1196   g_return_val_if_fail (GST_IS_PAD (target), NULL);
1197   g_return_val_if_fail (!gst_pad_is_linked (target), NULL);
1198
1199   GST_LOG ("name:%s, target:%s:%s", GST_STR_NULL (name),
1200       GST_DEBUG_PAD_NAME (target));
1201
1202   if ((ret = gst_ghost_pad_new_no_target (name, GST_PAD_DIRECTION (target))))
1203     if (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (ret), target))
1204       goto set_target_failed;
1205
1206   return ret;
1207
1208   /* ERRORS */
1209 set_target_failed:
1210   {
1211     GST_WARNING_OBJECT (ret, "failed to set target %s:%s",
1212         GST_DEBUG_PAD_NAME (target));
1213     gst_object_unref (ret);
1214     return NULL;
1215   }
1216 }
1217
1218 /**
1219  * gst_ghost_pad_new_from_template:
1220  * @name: (allow-none): the name of the new pad, or NULL to assign a default name.
1221  * @target: (transfer none): the pad to ghost.
1222  * @templ: (transfer none): the #GstPadTemplate to use on the ghostpad.
1223  *
1224  * Create a new ghostpad with @target as the target. The direction will be taken
1225  * from the target pad. The template used on the ghostpad will be @template.
1226  *
1227  * Will ref the target.
1228  *
1229  * Returns: (transfer full): a new #GstPad, or NULL in case of an error.
1230  *
1231  * Since: 0.10.10
1232  */
1233
1234 GstPad *
1235 gst_ghost_pad_new_from_template (const gchar * name, GstPad * target,
1236     GstPadTemplate * templ)
1237 {
1238   GstPad *ret;
1239
1240   g_return_val_if_fail (GST_IS_PAD (target), NULL);
1241   g_return_val_if_fail (!gst_pad_is_linked (target), NULL);
1242   g_return_val_if_fail (templ != NULL, NULL);
1243   g_return_val_if_fail (GST_PAD_TEMPLATE_DIRECTION (templ) ==
1244       GST_PAD_DIRECTION (target), NULL);
1245
1246   GST_LOG ("name:%s, target:%s:%s, templ:%p", GST_STR_NULL (name),
1247       GST_DEBUG_PAD_NAME (target), templ);
1248
1249   if ((ret = gst_ghost_pad_new_full (name, GST_PAD_DIRECTION (target), templ)))
1250     if (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (ret), target))
1251       goto set_target_failed;
1252
1253   return ret;
1254
1255   /* ERRORS */
1256 set_target_failed:
1257   {
1258     GST_WARNING_OBJECT (ret, "failed to set target %s:%s",
1259         GST_DEBUG_PAD_NAME (target));
1260     gst_object_unref (ret);
1261     return NULL;
1262   }
1263 }
1264
1265 /**
1266  * gst_ghost_pad_new_no_target_from_template:
1267  * @name: (allow-none): the name of the new pad, or NULL to assign a default name
1268  * @templ: (transfer none): the #GstPadTemplate to create the ghostpad from.
1269  *
1270  * Create a new ghostpad based on @templ, without setting a target. The
1271  * direction will be taken from the @templ.
1272  *
1273  * Returns: (transfer full): a new #GstPad, or NULL in case of an error.
1274  *
1275  * Since: 0.10.10
1276  */
1277 GstPad *
1278 gst_ghost_pad_new_no_target_from_template (const gchar * name,
1279     GstPadTemplate * templ)
1280 {
1281   GstPad *ret;
1282
1283   g_return_val_if_fail (templ != NULL, NULL);
1284
1285   ret =
1286       gst_ghost_pad_new_full (name, GST_PAD_TEMPLATE_DIRECTION (templ), templ);
1287
1288   return ret;
1289 }
1290
1291 /**
1292  * gst_ghost_pad_get_target:
1293  * @gpad: the #GstGhostPad
1294  *
1295  * Get the target pad of @gpad. Unref target pad after usage.
1296  *
1297  * Returns: (transfer full): the target #GstPad, can be NULL if the ghostpad
1298  * has no target set. Unref target pad after usage.
1299  */
1300 GstPad *
1301 gst_ghost_pad_get_target (GstGhostPad * gpad)
1302 {
1303   GstPad *ret;
1304
1305   g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), NULL);
1306
1307   ret = gst_proxy_pad_get_target (GST_PAD_CAST (gpad));
1308
1309   GST_DEBUG_OBJECT (gpad, "get target %s:%s", GST_DEBUG_PAD_NAME (ret));
1310
1311   return ret;
1312 }
1313
1314 /**
1315  * gst_ghost_pad_set_target:
1316  * @gpad: the #GstGhostPad
1317  * @newtarget: (transfer none) (allow-none): the new pad target
1318  *
1319  * Set the new target of the ghostpad @gpad. Any existing target
1320  * is unlinked and links to the new target are established. if @newtarget is
1321  * NULL the target will be cleared.
1322  *
1323  * Returns: (transfer full): TRUE if the new target could be set. This function
1324  *     can return FALSE when the internal pads could not be linked.
1325  */
1326 gboolean
1327 gst_ghost_pad_set_target (GstGhostPad * gpad, GstPad * newtarget)
1328 {
1329   GstPad *internal;
1330   GstPad *oldtarget;
1331   gboolean result;
1332   GstPadLinkReturn lret;
1333
1334   g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), FALSE);
1335   g_return_val_if_fail (GST_PAD_CAST (gpad) != newtarget, FALSE);
1336   g_return_val_if_fail (newtarget != GST_PROXY_PAD_INTERNAL (gpad), FALSE);
1337
1338   /* no need for locking, the internal pad's lifecycle is directly linked to the
1339    * ghostpad's */
1340   internal = GST_PROXY_PAD_INTERNAL (gpad);
1341
1342   if (newtarget)
1343     GST_DEBUG_OBJECT (gpad, "set target %s:%s", GST_DEBUG_PAD_NAME (newtarget));
1344   else
1345     GST_DEBUG_OBJECT (gpad, "clearing target");
1346
1347   /* clear old target */
1348   GST_PROXY_LOCK (gpad);
1349   if ((oldtarget = GST_PROXY_PAD_TARGET (gpad))) {
1350
1351     GST_PROXY_PAD_RETARGET (internal) = TRUE;
1352
1353     /* unlink internal pad */
1354     if (GST_PAD_IS_SRC (internal))
1355       gst_pad_unlink (internal, oldtarget);
1356     else
1357       gst_pad_unlink (oldtarget, internal);
1358
1359     GST_PROXY_PAD_RETARGET (internal) = FALSE;
1360   }
1361
1362   result = gst_proxy_pad_set_target_unlocked (GST_PAD_CAST (gpad), newtarget);
1363   GST_PROXY_UNLOCK (gpad);
1364
1365   if (result && newtarget) {
1366     /* and link to internal pad without any checks */
1367     GST_DEBUG_OBJECT (gpad, "connecting internal pad to target");
1368
1369     if (GST_PAD_IS_SRC (internal))
1370       lret =
1371           gst_pad_link_full (internal, newtarget, GST_PAD_LINK_CHECK_NOTHING);
1372     else
1373       lret =
1374           gst_pad_link_full (newtarget, internal, GST_PAD_LINK_CHECK_NOTHING);
1375
1376     if (lret != GST_PAD_LINK_OK)
1377       goto link_failed;
1378   }
1379
1380   return result;
1381
1382   /* ERRORS */
1383 link_failed:
1384   {
1385     GST_WARNING_OBJECT (gpad, "could not link internal and target, reason:%d",
1386         lret);
1387     /* and unset target again */
1388     GST_PROXY_LOCK (gpad);
1389     gst_proxy_pad_set_target_unlocked (GST_PAD_CAST (gpad), NULL);
1390     GST_PROXY_UNLOCK (gpad);
1391     return FALSE;
1392   }
1393 }