ghostpad: remove custom function
[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_PAD_PEER (GST_PROXY_PAD_INTERNAL (pad)))
58 #define GST_PROXY_PAD_INTERNAL(pad)     (GST_PROXY_PAD_PRIVATE (pad)->internal)
59
60 struct _GstProxyPadPrivate
61 {
62   GstPad *internal;
63 };
64
65 G_DEFINE_TYPE (GstProxyPad, gst_proxy_pad, GST_TYPE_PAD);
66
67 static GstPad *gst_proxy_pad_get_target (GstPad * pad);
68
69 /**
70  * gst_proxy_pad_iterate_internal_links_default:
71  * @pad: the #GstPad to get the internal links of.
72  * @parent: the parent of @pad or NULL
73  *
74  * Invoke the default iterate internal links function of the proxy pad.
75  *
76  * Returns: a #GstIterator of #GstPad, or NULL if @pad has no parent. Unref each
77  * returned pad with gst_object_unref().
78  */
79 GstIterator *
80 gst_proxy_pad_iterate_internal_links_default (GstPad * pad, GstObject * parent)
81 {
82   GstIterator *res = NULL;
83   GstPad *internal;
84   GValue v = { 0, };
85
86   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), NULL);
87
88   internal = GST_PROXY_PAD_INTERNAL (pad);
89   g_value_init (&v, GST_TYPE_PAD);
90   g_value_set_object (&v, internal);
91   res = gst_iterator_new_single (GST_TYPE_PAD, &v);
92   g_value_unset (&v);
93
94   return res;
95 }
96
97 /**
98  * gst_proxy_pad_chain_default:
99  * @pad: a sink #GstPad, returns GST_FLOW_ERROR if not.
100  * @parent: the parent of @pad or NULL
101  * @buffer: (transfer full): the #GstBuffer to send, return GST_FLOW_ERROR
102  *     if not.
103  *
104  * Invoke the default chain function of the proxy pad.
105  *
106  * Returns: a #GstFlowReturn from the pad.
107  */
108 GstFlowReturn
109 gst_proxy_pad_chain_default (GstPad * pad, GstObject * parent,
110     GstBuffer * buffer)
111 {
112   GstFlowReturn res;
113   GstPad *internal;
114
115   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), GST_FLOW_ERROR);
116   g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR);
117
118   internal = GST_PROXY_PAD_INTERNAL (pad);
119   res = gst_pad_push (internal, buffer);
120
121   return res;
122 }
123
124 /**
125  * gst_proxy_pad_chain_list_default:
126  * @pad: a sink #GstPad, returns GST_FLOW_ERROR if not.
127  * @parent: the parent of @pad or NULL
128  * @list: (transfer full): the #GstBufferList to send, return GST_FLOW_ERROR
129  *     if not.
130  *
131  * Invoke the default chain list function of the proxy pad.
132  *
133  * Returns: a #GstFlowReturn from the pad.
134  */
135 GstFlowReturn
136 gst_proxy_pad_chain_list_default (GstPad * pad, GstObject * parent,
137     GstBufferList * list)
138 {
139   GstFlowReturn res;
140   GstPad *internal;
141
142   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), GST_FLOW_ERROR);
143   g_return_val_if_fail (GST_IS_BUFFER_LIST (list), GST_FLOW_ERROR);
144
145   internal = GST_PROXY_PAD_INTERNAL (pad);
146   res = gst_pad_push_list (internal, list);
147
148   return res;
149 }
150
151 /**
152  * gst_proxy_pad_getrange_default:
153  * @pad: a src #GstPad, returns #GST_FLOW_ERROR if not.
154  * @parent: the parent of @pad
155  * @offset: The start offset of the buffer
156  * @size: The length of the buffer
157  * @buffer: (out callee-allocates): a pointer to hold the #GstBuffer,
158  *     returns #GST_FLOW_ERROR if %NULL.
159  *
160  * Invoke the default getrange function of the proxy pad.
161  *
162  * Returns: a #GstFlowReturn from the pad.
163  */
164 GstFlowReturn
165 gst_proxy_pad_getrange_default (GstPad * pad, GstObject * parent,
166     guint64 offset, guint size, GstBuffer ** buffer)
167 {
168   GstFlowReturn res;
169   GstPad *internal;
170
171   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), GST_FLOW_ERROR);
172   g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
173
174   internal = GST_PROXY_PAD_INTERNAL (pad);
175   res = gst_pad_pull_range (internal, offset, size, buffer);
176
177   return res;
178 }
179
180 static GstPad *
181 gst_proxy_pad_get_target (GstPad * pad)
182 {
183   GstPad *target;
184
185   GST_OBJECT_LOCK (pad);
186   target = GST_PROXY_PAD_TARGET (pad);
187   if (target)
188     gst_object_ref (target);
189   GST_OBJECT_UNLOCK (pad);
190
191   return target;
192 }
193
194 /**
195  * gst_proxy_pad_get_internal:
196  * @pad: the #GstProxyPad
197  *
198  * Get the internal pad of @pad. Unref target pad after usage.
199  *
200  * The internal pad of a #GstGhostPad is the internally used
201  * pad of opposite direction, which is used to link to the target.
202  *
203  * Returns: (transfer full): the target #GstProxyPad, can be NULL.
204  * Unref target pad after usage.
205  */
206 GstProxyPad *
207 gst_proxy_pad_get_internal (GstProxyPad * pad)
208 {
209   GstPad *internal;
210
211   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), NULL);
212
213   GST_OBJECT_LOCK (pad);
214   internal = GST_PROXY_PAD_INTERNAL (pad);
215   if (internal)
216     gst_object_ref (internal);
217   GST_OBJECT_UNLOCK (pad);
218
219   return GST_PROXY_PAD_CAST (internal);
220 }
221
222 static void
223 gst_proxy_pad_class_init (GstProxyPadClass * klass)
224 {
225   g_type_class_add_private (klass, sizeof (GstProxyPadPrivate));
226
227   /* Register common function pointer descriptions */
228   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_iterate_internal_links_default);
229   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_chain_default);
230   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_chain_list_default);
231   GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_getrange_default);
232 }
233
234 static void
235 gst_proxy_pad_init (GstProxyPad * ppad)
236 {
237   GstPad *pad = (GstPad *) ppad;
238
239   GST_PROXY_PAD_PRIVATE (ppad) = G_TYPE_INSTANCE_GET_PRIVATE (ppad,
240       GST_TYPE_PROXY_PAD, GstProxyPadPrivate);
241
242   gst_pad_set_iterate_internal_links_function (pad,
243       gst_proxy_pad_iterate_internal_links_default);
244
245   GST_PAD_SET_PROXY_CAPS (pad);
246   GST_PAD_SET_PROXY_SCHEDULING (pad);
247   GST_PAD_SET_PROXY_ALLOCATION (pad);
248 }
249
250
251 /***********************************************************************
252  * Ghost pads, implemented as a pair of proxy pads (sort of)
253  */
254
255
256 #define GST_GHOST_PAD_PRIVATE(obj)      (GST_GHOST_PAD_CAST (obj)->priv)
257
258 struct _GstGhostPadPrivate
259 {
260   /* with PROXY_LOCK */
261   gboolean constructed;
262 };
263
264 G_DEFINE_TYPE (GstGhostPad, gst_ghost_pad, GST_TYPE_PROXY_PAD);
265
266 static void gst_ghost_pad_dispose (GObject * object);
267
268 static gboolean
269 gst_ghost_pad_internal_activate_push_default (GstPad * pad, GstObject * parent,
270     gboolean active)
271 {
272   gboolean ret;
273   GstPad *other;
274
275   GST_LOG_OBJECT (pad, "%sactivate push on %s:%s, we're ok",
276       (active ? "" : "de"), GST_DEBUG_PAD_NAME (pad));
277
278   /* in both cases (SRC and SINK) we activate just the internal pad. The targets
279    * will be activated later (or already in case of a ghost sinkpad). */
280   other = GST_PROXY_PAD_INTERNAL (pad);
281   ret = gst_pad_activate_mode (other, GST_PAD_MODE_PUSH, active);
282
283   return ret;
284 }
285
286 static gboolean
287 gst_ghost_pad_internal_activate_pull_default (GstPad * pad, GstObject * parent,
288     gboolean active)
289 {
290   gboolean ret;
291   GstPad *other;
292
293   GST_LOG_OBJECT (pad, "%sactivate pull on %s:%s", (active ? "" : "de"),
294       GST_DEBUG_PAD_NAME (pad));
295
296   if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC) {
297     /* we are activated in pull mode by our peer element, which is a sinkpad
298      * that wants to operate in pull mode. This activation has to propagate
299      * upstream through the pipeline. We call the internal activation function,
300      * which will trigger gst_ghost_pad_activate_pull_default, which propagates even
301      * further upstream */
302     GST_LOG_OBJECT (pad, "pad is src, activate internal");
303     other = GST_PROXY_PAD_INTERNAL (pad);
304     ret = gst_pad_activate_mode (other, GST_PAD_MODE_PULL, active);
305   } else if (G_LIKELY ((other = gst_pad_get_peer (pad)))) {
306     /* We are SINK, the ghostpad is SRC, we propagate the activation upstream
307      * since we hold a pointer to the upstream peer. */
308     GST_LOG_OBJECT (pad, "activating peer");
309     ret = gst_pad_activate_mode (other, GST_PAD_MODE_PULL, active);
310     gst_object_unref (other);
311   } else {
312     /* this is failure, we can't activate pull if there is no peer */
313     GST_LOG_OBJECT (pad, "not src and no peer, failing");
314     ret = FALSE;
315   }
316
317   return ret;
318 }
319
320 /**
321  * gst_ghost_pad_internal_activate_mode_default:
322  * @pad: the #GstPad to activate or deactivate.
323  * @parent: the parent of @pad or NULL
324  * @mode: the requested activation mode
325  * @active: whether the pad should be active or not.
326  *
327  * Invoke the default activate mode function of a proxy pad that is
328  * owned by a ghost pad.
329  *
330  * Returns: %TRUE if the operation was successful.
331  */
332 gboolean
333 gst_ghost_pad_internal_activate_mode_default (GstPad * pad, GstObject * parent,
334     GstPadMode mode, gboolean active)
335 {
336   gboolean res;
337
338   g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
339
340   switch (mode) {
341     case GST_PAD_MODE_PULL:
342       res = gst_ghost_pad_internal_activate_pull_default (pad, parent, active);
343       break;
344     case GST_PAD_MODE_PUSH:
345       res = gst_ghost_pad_internal_activate_push_default (pad, parent, active);
346       break;
347     default:
348       GST_LOG_OBJECT (pad, "unknown activation mode %d", mode);
349       res = FALSE;
350       break;
351   }
352   return res;
353 }
354
355 static gboolean
356 gst_ghost_pad_activate_push_default (GstPad * pad, GstObject * parent,
357     gboolean active)
358 {
359   gboolean ret;
360   GstPad *other;
361
362   g_return_val_if_fail (GST_IS_GHOST_PAD (pad), FALSE);
363
364   GST_LOG_OBJECT (pad, "%sactivate push on %s:%s, proxy internal",
365       (active ? "" : "de"), GST_DEBUG_PAD_NAME (pad));
366
367   /* just activate the internal pad */
368   other = GST_PROXY_PAD_INTERNAL (pad);
369   ret = gst_pad_activate_mode (other, GST_PAD_MODE_PUSH, active);
370
371   return ret;
372 }
373
374 static gboolean
375 gst_ghost_pad_activate_pull_default (GstPad * pad, GstObject * parent,
376     gboolean active)
377 {
378   gboolean ret;
379   GstPad *other;
380
381   GST_LOG_OBJECT (pad, "%sactivate pull on %s:%s", (active ? "" : "de"),
382       GST_DEBUG_PAD_NAME (pad));
383
384   if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC) {
385     /* the ghostpad is SRC and activated in pull mode by its peer, call the
386      * activation function of the internal pad to propagate the activation
387      * upstream */
388     GST_LOG_OBJECT (pad, "pad is src, activate internal");
389     other = GST_PROXY_PAD_INTERNAL (pad);
390     ret = gst_pad_activate_mode (other, GST_PAD_MODE_PULL, active);
391   } else if (G_LIKELY ((other = gst_pad_get_peer (pad)))) {
392     /* We are SINK and activated by the internal pad, propagate activation
393      * upstream because we hold a ref to the upstream peer */
394     GST_LOG_OBJECT (pad, "activating peer");
395     ret = gst_pad_activate_mode (other, GST_PAD_MODE_PULL, active);
396     gst_object_unref (other);
397   } else {
398     /* no peer, we fail */
399     GST_LOG_OBJECT (pad, "pad not src and no peer, failing");
400     ret = FALSE;
401   }
402
403   return ret;
404 }
405
406 /**
407  * gst_ghost_pad_activate_mode_default:
408  * @pad: the #GstPad to activate or deactivate.
409  * @parent: the parent of @pad or NULL
410  * @mode: the requested activation mode
411  * @active: whether the pad should be active or not.
412  *
413  * Invoke the default activate mode function of a ghost pad.
414  *
415  * Returns: %TRUE if the operation was successful.
416  */
417 gboolean
418 gst_ghost_pad_activate_mode_default (GstPad * pad, GstObject * parent,
419     GstPadMode mode, gboolean active)
420 {
421   gboolean res;
422
423   g_return_val_if_fail (GST_IS_GHOST_PAD (pad), FALSE);
424
425   switch (mode) {
426     case GST_PAD_MODE_PULL:
427       res = gst_ghost_pad_activate_pull_default (pad, parent, active);
428       break;
429     case GST_PAD_MODE_PUSH:
430       res = gst_ghost_pad_activate_push_default (pad, parent, active);
431       break;
432     default:
433       GST_LOG_OBJECT (pad, "unknown activation mode %d", mode);
434       res = FALSE;
435       break;
436   }
437   return res;
438 }
439
440 static void
441 gst_ghost_pad_class_init (GstGhostPadClass * klass)
442 {
443   GObjectClass *gobject_class = (GObjectClass *) klass;
444
445   g_type_class_add_private (klass, sizeof (GstGhostPadPrivate));
446
447   gobject_class->dispose = gst_ghost_pad_dispose;
448
449   GST_DEBUG_REGISTER_FUNCPTR (gst_ghost_pad_activate_pull_default);
450   GST_DEBUG_REGISTER_FUNCPTR (gst_ghost_pad_activate_push_default);
451 }
452
453 static void
454 gst_ghost_pad_init (GstGhostPad * pad)
455 {
456   GST_GHOST_PAD_PRIVATE (pad) = G_TYPE_INSTANCE_GET_PRIVATE (pad,
457       GST_TYPE_GHOST_PAD, GstGhostPadPrivate);
458
459   gst_pad_set_activatemode_function (GST_PAD_CAST (pad),
460       gst_ghost_pad_activate_mode_default);
461 }
462
463 static void
464 gst_ghost_pad_dispose (GObject * object)
465 {
466   GstPad *pad;
467   GstPad *internal;
468   GstPad *peer;
469
470   pad = GST_PAD (object);
471
472   GST_DEBUG_OBJECT (pad, "dispose");
473
474   gst_ghost_pad_set_target (GST_GHOST_PAD (pad), NULL);
475
476   /* Unlink here so that gst_pad_dispose doesn't. That would lead to a call to
477    * gst_ghost_pad_unlink_default when the ghost pad is in an inconsistent state */
478   peer = gst_pad_get_peer (pad);
479   if (peer) {
480     if (GST_PAD_IS_SRC (pad))
481       gst_pad_unlink (pad, peer);
482     else
483       gst_pad_unlink (peer, pad);
484
485     gst_object_unref (peer);
486   }
487
488   GST_OBJECT_LOCK (pad);
489   internal = GST_PROXY_PAD_INTERNAL (pad);
490
491   gst_pad_set_activatemode_function (internal, NULL);
492
493   /* disposes of the internal pad, since the ghostpad is the only possible object
494    * that has a refcount on the internal pad. */
495   gst_object_unparent (GST_OBJECT_CAST (internal));
496   GST_PROXY_PAD_INTERNAL (pad) = NULL;
497
498   GST_OBJECT_UNLOCK (pad);
499
500   G_OBJECT_CLASS (gst_ghost_pad_parent_class)->dispose (object);
501 }
502
503 /**
504  * gst_ghost_pad_construct:
505  * @gpad: the newly allocated ghost pad
506  *
507  * Finish initialization of a newly allocated ghost pad.
508  *
509  * This function is most useful in language bindings and when subclassing
510  * #GstGhostPad; plugin and application developers normally will not call this
511  * function. Call this function directly after a call to g_object_new
512  * (GST_TYPE_GHOST_PAD, "direction", @dir, ..., NULL).
513  *
514  * Returns: %TRUE if the construction succeeds, %FALSE otherwise.
515  */
516 gboolean
517 gst_ghost_pad_construct (GstGhostPad * gpad)
518 {
519   GstPadDirection dir, otherdir;
520   GstPadTemplate *templ;
521   GstPad *pad, *internal;
522
523   g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), FALSE);
524   g_return_val_if_fail (GST_GHOST_PAD_PRIVATE (gpad)->constructed == FALSE,
525       FALSE);
526
527   g_object_get (gpad, "direction", &dir, "template", &templ, NULL);
528
529   g_return_val_if_fail (dir != GST_PAD_UNKNOWN, FALSE);
530
531   pad = GST_PAD (gpad);
532
533   /* Set directional padfunctions for ghostpad */
534   if (dir == GST_PAD_SINK) {
535     gst_pad_set_chain_function (pad, gst_proxy_pad_chain_default);
536     gst_pad_set_chain_list_function (pad, gst_proxy_pad_chain_list_default);
537   } else {
538     gst_pad_set_getrange_function (pad, gst_proxy_pad_getrange_default);
539   }
540
541   /* INTERNAL PAD, it always exists and is child of the ghostpad */
542   otherdir = (dir == GST_PAD_SRC) ? GST_PAD_SINK : GST_PAD_SRC;
543   if (templ) {
544     internal =
545         g_object_new (GST_TYPE_PROXY_PAD, "name", NULL,
546         "direction", otherdir, "template", templ, NULL);
547     /* release ref obtained via g_object_get */
548     gst_object_unref (templ);
549   } else {
550     internal =
551         g_object_new (GST_TYPE_PROXY_PAD, "name", NULL,
552         "direction", otherdir, NULL);
553   }
554   GST_PAD_UNSET_FLUSHING (internal);
555
556   /* Set directional padfunctions for internal pad */
557   if (dir == GST_PAD_SRC) {
558     gst_pad_set_chain_function (internal, gst_proxy_pad_chain_default);
559     gst_pad_set_chain_list_function (internal,
560         gst_proxy_pad_chain_list_default);
561   } else {
562     gst_pad_set_getrange_function (internal, gst_proxy_pad_getrange_default);
563   }
564
565   GST_OBJECT_LOCK (pad);
566
567   /* now make the ghostpad a parent of the internal pad */
568   if (!gst_object_set_parent (GST_OBJECT_CAST (internal),
569           GST_OBJECT_CAST (pad)))
570     goto parent_failed;
571
572   /* The ghostpad is the parent of the internal pad and is the only object that
573    * can have a refcount on the internal pad.
574    * At this point, the GstGhostPad has a refcount of 1, and the internal pad has
575    * a refcount of 1.
576    * When the refcount of the GstGhostPad drops to 0, the ghostpad will dispose
577    * its refcount on the internal pad in the dispose method by un-parenting it.
578    * This is why we don't take extra refcounts in the assignments below
579    */
580   GST_PROXY_PAD_INTERNAL (pad) = internal;
581   GST_PROXY_PAD_INTERNAL (internal) = pad;
582
583   /* special activation functions for the internal pad */
584   gst_pad_set_activatemode_function (internal,
585       gst_ghost_pad_internal_activate_mode_default);
586
587   GST_OBJECT_UNLOCK (pad);
588
589   GST_GHOST_PAD_PRIVATE (gpad)->constructed = TRUE;
590   return TRUE;
591
592   /* ERRORS */
593 parent_failed:
594   {
595     GST_WARNING_OBJECT (gpad, "Could not set internal pad %s:%s",
596         GST_DEBUG_PAD_NAME (internal));
597     g_critical ("Could not set internal pad %s:%s",
598         GST_DEBUG_PAD_NAME (internal));
599     GST_OBJECT_UNLOCK (pad);
600     gst_object_unref (internal);
601     return FALSE;
602   }
603 }
604
605 static GstPad *
606 gst_ghost_pad_new_full (const gchar * name, GstPadDirection dir,
607     GstPadTemplate * templ)
608 {
609   GstGhostPad *ret;
610
611   g_return_val_if_fail (dir != GST_PAD_UNKNOWN, NULL);
612
613   /* OBJECT CREATION */
614   if (templ) {
615     ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name,
616         "direction", dir, "template", templ, NULL);
617   } else {
618     ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name,
619         "direction", dir, NULL);
620   }
621
622   if (!gst_ghost_pad_construct (ret))
623     goto construct_failed;
624
625   return GST_PAD_CAST (ret);
626
627 construct_failed:
628   /* already logged */
629   gst_object_unref (ret);
630   return NULL;
631 }
632
633 /**
634  * gst_ghost_pad_new_no_target:
635  * @name: (allow-none): the name of the new pad, or NULL to assign a default name.
636  * @dir: the direction of the ghostpad
637  *
638  * Create a new ghostpad without a target with the given direction.
639  * A target can be set on the ghostpad later with the
640  * gst_ghost_pad_set_target() function.
641  *
642  * The created ghostpad will not have a padtemplate.
643  *
644  * Returns: (transfer full): a new #GstPad, or NULL in case of an error.
645  */
646 GstPad *
647 gst_ghost_pad_new_no_target (const gchar * name, GstPadDirection dir)
648 {
649   GstPad *ret;
650
651   g_return_val_if_fail (dir != GST_PAD_UNKNOWN, NULL);
652
653   GST_LOG ("name:%s, direction:%d", GST_STR_NULL (name), dir);
654
655   ret = gst_ghost_pad_new_full (name, dir, NULL);
656
657   return ret;
658 }
659
660 /**
661  * gst_ghost_pad_new:
662  * @name: (allow-none): the name of the new pad, or NULL to assign a default name
663  * @target: (transfer none): the pad to ghost.
664  *
665  * Create a new ghostpad with @target as the target. The direction will be taken
666  * from the target pad. @target must be unlinked.
667  *
668  * Will ref the target.
669  *
670  * Returns: (transfer floating): a new #GstPad, or NULL in case of an error.
671  */
672 GstPad *
673 gst_ghost_pad_new (const gchar * name, GstPad * target)
674 {
675   GstPad *ret;
676
677   g_return_val_if_fail (GST_IS_PAD (target), NULL);
678   g_return_val_if_fail (!gst_pad_is_linked (target), NULL);
679
680   GST_LOG ("name:%s, target:%s:%s", GST_STR_NULL (name),
681       GST_DEBUG_PAD_NAME (target));
682
683   if ((ret = gst_ghost_pad_new_no_target (name, GST_PAD_DIRECTION (target))))
684     if (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (ret), target))
685       goto set_target_failed;
686
687   return ret;
688
689   /* ERRORS */
690 set_target_failed:
691   {
692     GST_WARNING_OBJECT (ret, "failed to set target %s:%s",
693         GST_DEBUG_PAD_NAME (target));
694     gst_object_unref (ret);
695     return NULL;
696   }
697 }
698
699 /**
700  * gst_ghost_pad_new_from_template:
701  * @name: (allow-none): the name of the new pad, or NULL to assign a default name.
702  * @target: (transfer none): the pad to ghost.
703  * @templ: (transfer none): the #GstPadTemplate to use on the ghostpad.
704  *
705  * Create a new ghostpad with @target as the target. The direction will be taken
706  * from the target pad. The template used on the ghostpad will be @template.
707  *
708  * Will ref the target.
709  *
710  * Returns: (transfer full): a new #GstPad, or NULL in case of an error.
711  */
712
713 GstPad *
714 gst_ghost_pad_new_from_template (const gchar * name, GstPad * target,
715     GstPadTemplate * templ)
716 {
717   GstPad *ret;
718
719   g_return_val_if_fail (GST_IS_PAD (target), NULL);
720   g_return_val_if_fail (!gst_pad_is_linked (target), NULL);
721   g_return_val_if_fail (templ != NULL, NULL);
722   g_return_val_if_fail (GST_PAD_TEMPLATE_DIRECTION (templ) ==
723       GST_PAD_DIRECTION (target), NULL);
724
725   GST_LOG ("name:%s, target:%s:%s, templ:%p", GST_STR_NULL (name),
726       GST_DEBUG_PAD_NAME (target), templ);
727
728   if ((ret = gst_ghost_pad_new_full (name, GST_PAD_DIRECTION (target), templ)))
729     if (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (ret), target))
730       goto set_target_failed;
731
732   return ret;
733
734   /* ERRORS */
735 set_target_failed:
736   {
737     GST_WARNING_OBJECT (ret, "failed to set target %s:%s",
738         GST_DEBUG_PAD_NAME (target));
739     gst_object_unref (ret);
740     return NULL;
741   }
742 }
743
744 /**
745  * gst_ghost_pad_new_no_target_from_template:
746  * @name: (allow-none): the name of the new pad, or NULL to assign a default name
747  * @templ: (transfer none): the #GstPadTemplate to create the ghostpad from.
748  *
749  * Create a new ghostpad based on @templ, without setting a target. The
750  * direction will be taken from the @templ.
751  *
752  * Returns: (transfer full): a new #GstPad, or NULL in case of an error.
753  */
754 GstPad *
755 gst_ghost_pad_new_no_target_from_template (const gchar * name,
756     GstPadTemplate * templ)
757 {
758   GstPad *ret;
759
760   g_return_val_if_fail (templ != NULL, NULL);
761
762   ret =
763       gst_ghost_pad_new_full (name, GST_PAD_TEMPLATE_DIRECTION (templ), templ);
764
765   return ret;
766 }
767
768 /**
769  * gst_ghost_pad_get_target:
770  * @gpad: the #GstGhostPad
771  *
772  * Get the target pad of @gpad. Unref target pad after usage.
773  *
774  * Returns: (transfer full): the target #GstPad, can be NULL if the ghostpad
775  * has no target set. Unref target pad after usage.
776  */
777 GstPad *
778 gst_ghost_pad_get_target (GstGhostPad * gpad)
779 {
780   GstPad *ret;
781
782   g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), NULL);
783
784   ret = gst_proxy_pad_get_target (GST_PAD_CAST (gpad));
785
786   GST_DEBUG_OBJECT (gpad, "get target %s:%s", GST_DEBUG_PAD_NAME (ret));
787
788   return ret;
789 }
790
791 /**
792  * gst_ghost_pad_set_target:
793  * @gpad: the #GstGhostPad
794  * @newtarget: (transfer none) (allow-none): the new pad target
795  *
796  * Set the new target of the ghostpad @gpad. Any existing target
797  * is unlinked and links to the new target are established. if @newtarget is
798  * NULL the target will be cleared.
799  *
800  * Returns: (transfer full): TRUE if the new target could be set. This function
801  *     can return FALSE when the internal pads could not be linked.
802  */
803 gboolean
804 gst_ghost_pad_set_target (GstGhostPad * gpad, GstPad * newtarget)
805 {
806   GstPad *internal;
807   GstPad *oldtarget;
808   GstPadLinkReturn lret;
809
810   g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), FALSE);
811   g_return_val_if_fail (GST_PAD_CAST (gpad) != newtarget, FALSE);
812   g_return_val_if_fail (newtarget != GST_PROXY_PAD_INTERNAL (gpad), FALSE);
813
814   /* no need for locking, the internal pad's lifecycle is directly linked to the
815    * ghostpad's */
816   internal = GST_PROXY_PAD_INTERNAL (gpad);
817
818   if (newtarget)
819     GST_DEBUG_OBJECT (gpad, "set target %s:%s", GST_DEBUG_PAD_NAME (newtarget));
820   else
821     GST_DEBUG_OBJECT (gpad, "clearing target");
822
823   /* clear old target */
824   GST_OBJECT_LOCK (gpad);
825   if ((oldtarget = GST_PROXY_PAD_TARGET (gpad))) {
826     GST_OBJECT_UNLOCK (gpad);
827
828     /* unlink internal pad */
829     if (GST_PAD_IS_SRC (internal))
830       gst_pad_unlink (internal, oldtarget);
831     else
832       gst_pad_unlink (oldtarget, internal);
833   } else {
834     GST_OBJECT_UNLOCK (gpad);
835   }
836
837   if (newtarget) {
838     /* and link to internal pad without any checks */
839     GST_DEBUG_OBJECT (gpad, "connecting internal pad to target");
840
841     if (GST_PAD_IS_SRC (internal))
842       lret =
843           gst_pad_link_full (internal, newtarget, GST_PAD_LINK_CHECK_NOTHING);
844     else
845       lret =
846           gst_pad_link_full (newtarget, internal, GST_PAD_LINK_CHECK_NOTHING);
847
848     if (lret != GST_PAD_LINK_OK)
849       goto link_failed;
850   }
851
852   return TRUE;
853
854   /* ERRORS */
855 link_failed:
856   {
857     GST_WARNING_OBJECT (gpad, "could not link internal and target, reason:%d",
858         lret);
859     return FALSE;
860   }
861 }