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