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