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