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