54 #include <glib_global.h> |
54 #include <glib_global.h> |
55 #endif |
55 #endif |
56 |
56 |
57 #define GST_CAT_DEFAULT GST_CAT_PADS |
57 #define GST_CAT_DEFAULT GST_CAT_PADS |
58 |
58 |
59 #define GST_TYPE_PROXY_PAD (gst_proxy_pad_get_type ()) |
|
60 #define GST_IS_PROXY_PAD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_PROXY_PAD)) |
|
61 #define GST_IS_PROXY_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_PROXY_PAD)) |
|
62 #define GST_PROXY_PAD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_PROXY_PAD, GstProxyPad)) |
|
63 #define GST_PROXY_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_PROXY_PAD, GstProxyPadClass)) |
|
64 #define GST_PROXY_PAD_CAST(obj) ((GstProxyPad *)obj) |
59 #define GST_PROXY_PAD_CAST(obj) ((GstProxyPad *)obj) |
65 |
60 #define GST_PROXY_PAD_PRIVATE(obj) (GST_PROXY_PAD_CAST (obj)->priv) |
66 #define GST_PROXY_PAD_TARGET(pad) (GST_PROXY_PAD_CAST (pad)->target) |
61 #define GST_PROXY_PAD_TARGET(pad) (GST_PROXY_PAD_PRIVATE (pad)->target) |
67 #define GST_PROXY_PAD_INTERNAL(pad) (GST_PROXY_PAD_CAST (pad)->internal) |
62 #define GST_PROXY_PAD_INTERNAL(pad) (GST_PROXY_PAD_PRIVATE (pad)->internal) |
68 |
63 #define GST_PROXY_PAD_RETARGET(pad) (GST_PROXY_PAD_PRIVATE (pad)->retarget) |
69 typedef struct _GstProxyPad GstProxyPad; |
64 #define GST_PROXY_GET_LOCK(pad) (GST_PROXY_PAD_PRIVATE (pad)->proxy_lock) |
70 typedef struct _GstProxyPadClass GstProxyPadClass; |
|
71 |
|
72 #define GST_PROXY_GET_LOCK(pad) (GST_PROXY_PAD_CAST (pad)->proxy_lock) |
|
73 #define GST_PROXY_LOCK(pad) (g_mutex_lock (GST_PROXY_GET_LOCK (pad))) |
65 #define GST_PROXY_LOCK(pad) (g_mutex_lock (GST_PROXY_GET_LOCK (pad))) |
74 #define GST_PROXY_UNLOCK(pad) (g_mutex_unlock (GST_PROXY_GET_LOCK (pad))) |
66 #define GST_PROXY_UNLOCK(pad) (g_mutex_unlock (GST_PROXY_GET_LOCK (pad))) |
75 |
67 |
76 struct _GstProxyPad |
68 struct _GstProxyPadPrivate |
77 { |
69 { |
78 GstPad pad; |
|
79 |
|
80 /* with PROXY_LOCK */ |
70 /* with PROXY_LOCK */ |
81 GMutex *proxy_lock; |
71 GMutex *proxy_lock; |
82 GstPad *target; |
72 GstPad *target; |
83 GstPad *internal; |
73 GstPad *internal; |
|
74 gboolean retarget; |
84 }; |
75 }; |
85 |
|
86 struct _GstProxyPadClass |
|
87 { |
|
88 GstPadClass parent_class; |
|
89 |
|
90 /*< private > */ |
|
91 gpointer _gst_reserved[1]; |
|
92 }; |
|
93 |
|
94 static GType gst_proxy_pad_get_type (void); |
|
95 |
76 |
96 G_DEFINE_TYPE (GstProxyPad, gst_proxy_pad, GST_TYPE_PAD); |
77 G_DEFINE_TYPE (GstProxyPad, gst_proxy_pad, GST_TYPE_PAD); |
97 |
78 |
98 static GstPad *gst_proxy_pad_get_target (GstPad * pad); |
79 static GstPad *gst_proxy_pad_get_target (GstPad * pad); |
99 |
80 |
398 static void |
414 static void |
399 gst_proxy_pad_finalize (GObject * object) |
415 gst_proxy_pad_finalize (GObject * object) |
400 { |
416 { |
401 GstProxyPad *pad = GST_PROXY_PAD (object); |
417 GstProxyPad *pad = GST_PROXY_PAD (object); |
402 |
418 |
403 g_mutex_free (pad->proxy_lock); |
419 g_mutex_free (GST_PROXY_GET_LOCK (pad)); |
404 pad->proxy_lock = NULL; |
420 GST_PROXY_GET_LOCK (pad) = NULL; |
405 |
421 |
406 G_OBJECT_CLASS (gst_proxy_pad_parent_class)->finalize (object); |
422 G_OBJECT_CLASS (gst_proxy_pad_parent_class)->finalize (object); |
407 } |
423 } |
408 |
424 |
409 static void |
425 static void |
410 gst_proxy_pad_init (GstProxyPad * ppad) |
426 gst_proxy_pad_init (GstProxyPad * ppad) |
411 { |
427 { |
412 GstPad *pad = (GstPad *) ppad; |
428 GstPad *pad = (GstPad *) ppad; |
413 |
429 |
414 ppad->proxy_lock = g_mutex_new (); |
430 GST_PROXY_PAD_PRIVATE (ppad) = G_TYPE_INSTANCE_GET_PRIVATE (ppad, |
|
431 GST_TYPE_PROXY_PAD, GstProxyPadPrivate); |
|
432 GST_PROXY_GET_LOCK (pad) = g_mutex_new (); |
415 |
433 |
416 gst_pad_set_query_type_function (pad, |
434 gst_pad_set_query_type_function (pad, |
417 GST_DEBUG_FUNCPTR (gst_proxy_pad_do_query_type)); |
435 GST_DEBUG_FUNCPTR (gst_proxy_pad_do_query_type)); |
418 gst_pad_set_event_function (pad, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_event)); |
436 gst_pad_set_event_function (pad, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_event)); |
419 gst_pad_set_query_function (pad, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_query)); |
437 gst_pad_set_query_function (pad, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_query)); |
420 gst_pad_set_internal_link_function (pad, |
438 gst_pad_set_iterate_internal_links_function (pad, |
421 GST_DEBUG_FUNCPTR (gst_proxy_pad_do_internal_link)); |
439 GST_DEBUG_FUNCPTR (gst_proxy_pad_do_iterate_internal_links)); |
422 |
440 |
423 gst_pad_set_getcaps_function (pad, |
441 gst_pad_set_getcaps_function (pad, |
424 GST_DEBUG_FUNCPTR (gst_proxy_pad_do_getcaps)); |
442 GST_DEBUG_FUNCPTR (gst_proxy_pad_do_getcaps)); |
425 gst_pad_set_acceptcaps_function (pad, |
443 gst_pad_set_acceptcaps_function (pad, |
426 GST_DEBUG_FUNCPTR (gst_proxy_pad_do_acceptcaps)); |
444 GST_DEBUG_FUNCPTR (gst_proxy_pad_do_acceptcaps)); |
427 gst_pad_set_fixatecaps_function (pad, |
445 gst_pad_set_fixatecaps_function (pad, |
428 GST_DEBUG_FUNCPTR (gst_proxy_pad_do_fixatecaps)); |
446 GST_DEBUG_FUNCPTR (gst_proxy_pad_do_fixatecaps)); |
429 gst_pad_set_setcaps_function (pad, |
447 gst_pad_set_setcaps_function (pad, |
430 GST_DEBUG_FUNCPTR (gst_proxy_pad_do_setcaps)); |
448 GST_DEBUG_FUNCPTR (gst_proxy_pad_do_setcaps)); |
|
449 gst_pad_set_unlink_function (pad, |
|
450 GST_DEBUG_FUNCPTR (gst_proxy_pad_do_unlink)); |
431 } |
451 } |
432 |
452 |
433 #ifndef GST_DISABLE_LOADSAVE |
453 #ifndef GST_DISABLE_LOADSAVE |
434 /** |
454 /** |
435 * gst_proxy_pad_save_thyself: |
455 * gst_proxy_pad_save_thyself: |
660 } |
672 } |
661 |
673 |
662 static void |
674 static void |
663 gst_ghost_pad_do_unlink (GstPad * pad) |
675 gst_ghost_pad_do_unlink (GstPad * pad) |
664 { |
676 { |
665 GstPad *target; |
|
666 GstPad *internal; |
677 GstPad *internal; |
667 |
678 |
668 target = gst_proxy_pad_get_target (pad); |
|
669 internal = GST_PROXY_PAD_INTERNAL (pad); |
679 internal = GST_PROXY_PAD_INTERNAL (pad); |
670 |
680 |
671 GST_DEBUG_OBJECT (pad, "unlinking ghostpad"); |
681 GST_DEBUG_OBJECT (pad, "unlinking ghostpad"); |
672 |
682 |
673 /* The target of the internal pad is no longer valid */ |
683 /* The target of the internal pad is no longer valid */ |
674 gst_proxy_pad_set_target (internal, NULL); |
684 gst_proxy_pad_set_target (internal, NULL); |
675 |
|
676 if (target) { |
|
677 if (GST_PAD_UNLINKFUNC (target)) |
|
678 GST_PAD_UNLINKFUNC (target) (target); |
|
679 |
|
680 gst_object_unref (target); |
|
681 } |
|
682 } |
685 } |
683 |
686 |
684 static void |
687 static void |
685 on_int_notify (GstPad * internal, GParamSpec * unused, GstGhostPad * pad) |
688 on_int_notify (GstPad * internal, GParamSpec * unused, GstGhostPad * pad) |
686 { |
689 { |
687 GstCaps *caps; |
690 GstCaps *caps; |
|
691 gboolean changed; |
688 |
692 |
689 g_object_get (internal, "caps", &caps, NULL); |
693 g_object_get (internal, "caps", &caps, NULL); |
690 |
694 |
691 GST_OBJECT_LOCK (pad); |
695 GST_OBJECT_LOCK (pad); |
|
696 changed = (GST_PAD_CAPS (pad) != caps); |
|
697 if (changed) |
|
698 gst_caps_replace (&(GST_PAD_CAPS (pad)), caps); |
|
699 GST_OBJECT_UNLOCK (pad); |
|
700 |
|
701 if (changed) |
|
702 g_object_notify (G_OBJECT (pad), "caps"); |
|
703 |
|
704 if (caps) |
|
705 gst_caps_unref (caps); |
|
706 } |
|
707 |
|
708 static void |
|
709 on_src_target_notify (GstPad * target, GParamSpec * unused, GstGhostPad * pad) |
|
710 { |
|
711 GstCaps *caps; |
|
712 gboolean changed; |
|
713 |
|
714 g_object_get (target, "caps", &caps, NULL); |
|
715 |
|
716 GST_OBJECT_LOCK (pad); |
|
717 changed = (GST_PAD_CAPS (pad) != caps); |
692 gst_caps_replace (&(GST_PAD_CAPS (pad)), caps); |
718 gst_caps_replace (&(GST_PAD_CAPS (pad)), caps); |
693 GST_OBJECT_UNLOCK (pad); |
719 GST_OBJECT_UNLOCK (pad); |
694 |
720 |
695 g_object_notify (G_OBJECT (pad), "caps"); |
721 if (changed) |
|
722 g_object_notify (G_OBJECT (pad), "caps"); |
|
723 |
696 if (caps) |
724 if (caps) |
697 gst_caps_unref (caps); |
725 gst_caps_unref (caps); |
698 } |
726 } |
699 |
727 |
|
728 static gboolean |
|
729 gst_ghost_pad_do_setcaps (GstPad * pad, GstCaps * caps) |
|
730 { |
|
731 if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC) |
|
732 return TRUE; |
|
733 |
|
734 return gst_proxy_pad_do_setcaps (pad, caps); |
|
735 } |
|
736 |
700 static void |
737 static void |
701 gst_ghost_pad_init (GstGhostPad * pad) |
738 gst_ghost_pad_init (GstGhostPad * pad) |
702 { |
739 { |
|
740 GST_GHOST_PAD_PRIVATE (pad) = G_TYPE_INSTANCE_GET_PRIVATE (pad, |
|
741 GST_TYPE_GHOST_PAD, GstGhostPadPrivate); |
|
742 |
|
743 gst_pad_set_setcaps_function (GST_PAD_CAST (pad), |
|
744 GST_DEBUG_FUNCPTR (gst_ghost_pad_do_setcaps)); |
703 gst_pad_set_activatepull_function (GST_PAD_CAST (pad), |
745 gst_pad_set_activatepull_function (GST_PAD_CAST (pad), |
704 GST_DEBUG_FUNCPTR (gst_ghost_pad_do_activate_pull)); |
746 GST_DEBUG_FUNCPTR (gst_ghost_pad_do_activate_pull)); |
705 gst_pad_set_activatepush_function (GST_PAD_CAST (pad), |
747 gst_pad_set_activatepush_function (GST_PAD_CAST (pad), |
706 GST_DEBUG_FUNCPTR (gst_ghost_pad_do_activate_push)); |
748 GST_DEBUG_FUNCPTR (gst_ghost_pad_do_activate_push)); |
707 } |
749 } |
709 static void |
751 static void |
710 gst_ghost_pad_dispose (GObject * object) |
752 gst_ghost_pad_dispose (GObject * object) |
711 { |
753 { |
712 GstPad *pad; |
754 GstPad *pad; |
713 GstPad *internal; |
755 GstPad *internal; |
714 GstPad *intpeer; |
756 GstPad *peer; |
715 |
757 |
716 pad = GST_PAD (object); |
758 pad = GST_PAD (object); |
717 |
759 |
718 GST_DEBUG_OBJECT (pad, "dispose"); |
760 GST_DEBUG_OBJECT (pad, "dispose"); |
|
761 |
|
762 gst_ghost_pad_set_target (GST_GHOST_PAD (pad), NULL); |
|
763 |
|
764 /* Unlink here so that gst_pad_dispose doesn't. That would lead to a call to |
|
765 * gst_ghost_pad_do_unlink when the ghost pad is in an inconsistent state */ |
|
766 peer = gst_pad_get_peer (pad); |
|
767 if (peer) { |
|
768 if (GST_PAD_IS_SRC (pad)) |
|
769 gst_pad_unlink (pad, peer); |
|
770 else |
|
771 gst_pad_unlink (peer, pad); |
|
772 |
|
773 gst_object_unref (peer); |
|
774 } |
719 |
775 |
720 GST_PROXY_LOCK (pad); |
776 GST_PROXY_LOCK (pad); |
721 internal = GST_PROXY_PAD_INTERNAL (pad); |
777 internal = GST_PROXY_PAD_INTERNAL (pad); |
722 |
778 |
723 gst_pad_set_activatepull_function (internal, NULL); |
779 gst_pad_set_activatepull_function (internal, NULL); |
724 gst_pad_set_activatepush_function (internal, NULL); |
780 gst_pad_set_activatepush_function (internal, NULL); |
725 |
781 |
726 g_signal_handler_disconnect (internal, GST_GHOST_PAD_CAST (pad)->notify_id); |
782 g_signal_handler_disconnect (internal, |
727 |
783 GST_GHOST_PAD_PRIVATE (pad)->notify_id); |
728 intpeer = gst_pad_get_peer (internal); |
|
729 if (intpeer) { |
|
730 if (GST_PAD_IS_SRC (internal)) |
|
731 gst_pad_unlink (internal, intpeer); |
|
732 else |
|
733 gst_pad_unlink (intpeer, internal); |
|
734 |
|
735 gst_object_unref (intpeer); |
|
736 } |
|
737 |
|
738 GST_PROXY_PAD_INTERNAL (internal) = NULL; |
|
739 |
784 |
740 /* disposes of the internal pad, since the ghostpad is the only possible object |
785 /* disposes of the internal pad, since the ghostpad is the only possible object |
741 * that has a refcount on the internal pad. */ |
786 * that has a refcount on the internal pad. */ |
742 gst_object_unparent (GST_OBJECT_CAST (internal)); |
787 gst_object_unparent (GST_OBJECT_CAST (internal)); |
|
788 GST_PROXY_PAD_INTERNAL (pad) = NULL; |
743 |
789 |
744 GST_PROXY_UNLOCK (pad); |
790 GST_PROXY_UNLOCK (pad); |
745 |
791 |
746 G_OBJECT_CLASS (gst_ghost_pad_parent_class)->dispose (object); |
792 G_OBJECT_CLASS (gst_ghost_pad_parent_class)->dispose (object); |
747 } |
793 } |
748 |
794 |
749 static GstPad * |
795 /** |
750 gst_ghost_pad_new_full (const gchar * name, GstPadDirection dir, |
796 * gst_ghost_pad_construct: |
751 GstPadTemplate * templ) |
797 * @gpad: the newly allocated ghost pad |
752 { |
798 * |
753 GstPad *ret; |
799 * Finish initialization of a newly allocated ghost pad. |
754 GstPad *internal; |
800 * |
755 GstPadDirection otherdir; |
801 * This function is most useful in language bindings and when subclassing |
756 |
802 * #GstGhostPad; plugin and application developers normally will not call this |
757 g_return_val_if_fail (dir != GST_PAD_UNKNOWN, NULL); |
803 * function. Call this function directly after a call to g_object_new |
758 |
804 * (GST_TYPE_GHOST_PAD, "direction", @dir, ..., NULL). |
759 /* OBJECT CREATION */ |
805 * |
760 if (templ) { |
806 * Returns: %TRUE if the construction succeeds, %FALSE otherwise. |
761 ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name, |
807 * |
762 "direction", dir, "template", templ, NULL); |
808 * Since: 0.10.22 |
763 } else { |
809 */ |
764 ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name, |
810 #ifdef __SYMBIAN32__ |
765 "direction", dir, NULL); |
811 EXPORT_C |
766 } |
812 #endif |
|
813 |
|
814 gboolean |
|
815 gst_ghost_pad_construct (GstGhostPad * gpad) |
|
816 { |
|
817 GstPadDirection dir, otherdir; |
|
818 GstPadTemplate *templ; |
|
819 GstPad *pad, *internal; |
|
820 |
|
821 g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), FALSE); |
|
822 g_return_val_if_fail (GST_GHOST_PAD_PRIVATE (gpad)->constructed == FALSE, |
|
823 FALSE); |
|
824 |
|
825 g_object_get (gpad, "direction", &dir, "template", &templ, NULL); |
|
826 |
|
827 g_return_val_if_fail (dir != GST_PAD_UNKNOWN, FALSE); |
|
828 |
|
829 pad = GST_PAD (gpad); |
767 |
830 |
768 /* Set directional padfunctions for ghostpad */ |
831 /* Set directional padfunctions for ghostpad */ |
769 if (dir == GST_PAD_SINK) { |
832 if (dir == GST_PAD_SINK) { |
770 gst_pad_set_bufferalloc_function (ret, |
833 gst_pad_set_bufferalloc_function (pad, |
771 GST_DEBUG_FUNCPTR (gst_proxy_pad_do_bufferalloc)); |
834 GST_DEBUG_FUNCPTR (gst_proxy_pad_do_bufferalloc)); |
772 gst_pad_set_chain_function (ret, |
835 gst_pad_set_chain_function (pad, |
773 GST_DEBUG_FUNCPTR (gst_proxy_pad_do_chain)); |
836 GST_DEBUG_FUNCPTR (gst_proxy_pad_do_chain)); |
|
837 gst_pad_set_chain_list_function (pad, |
|
838 GST_DEBUG_FUNCPTR (gst_proxy_pad_do_chain_list)); |
774 } else { |
839 } else { |
775 gst_pad_set_getrange_function (ret, |
840 gst_pad_set_getrange_function (pad, |
776 GST_DEBUG_FUNCPTR (gst_proxy_pad_do_getrange)); |
841 GST_DEBUG_FUNCPTR (gst_proxy_pad_do_getrange)); |
777 gst_pad_set_checkgetrange_function (ret, |
842 gst_pad_set_checkgetrange_function (pad, |
778 GST_DEBUG_FUNCPTR (gst_proxy_pad_do_checkgetrange)); |
843 GST_DEBUG_FUNCPTR (gst_proxy_pad_do_checkgetrange)); |
779 } |
844 } |
780 |
845 |
781 /* link/unlink functions */ |
846 /* link/unlink functions */ |
782 gst_pad_set_link_function (ret, GST_DEBUG_FUNCPTR (gst_ghost_pad_do_link)); |
847 gst_pad_set_link_function (pad, GST_DEBUG_FUNCPTR (gst_ghost_pad_do_link)); |
783 gst_pad_set_unlink_function (ret, |
848 gst_pad_set_unlink_function (pad, |
784 GST_DEBUG_FUNCPTR (gst_ghost_pad_do_unlink)); |
849 GST_DEBUG_FUNCPTR (gst_ghost_pad_do_unlink)); |
785 |
|
786 |
850 |
787 /* INTERNAL PAD, it always exists and is child of the ghostpad */ |
851 /* INTERNAL PAD, it always exists and is child of the ghostpad */ |
788 otherdir = (dir == GST_PAD_SRC) ? GST_PAD_SINK : GST_PAD_SRC; |
852 otherdir = (dir == GST_PAD_SRC) ? GST_PAD_SINK : GST_PAD_SRC; |
789 if (templ) { |
853 if (templ) { |
790 internal = |
854 internal = |
791 g_object_new (GST_TYPE_PROXY_PAD, "name", NULL, |
855 g_object_new (GST_TYPE_PROXY_PAD, "name", NULL, |
792 "direction", otherdir, "template", templ, NULL); |
856 "direction", otherdir, "template", templ, NULL); |
|
857 /* release ref obtained via g_object_get */ |
|
858 gst_object_unref (templ); |
793 } else { |
859 } else { |
794 internal = |
860 internal = |
795 g_object_new (GST_TYPE_PROXY_PAD, "name", NULL, |
861 g_object_new (GST_TYPE_PROXY_PAD, "name", NULL, |
796 "direction", otherdir, NULL); |
862 "direction", otherdir, NULL); |
797 } |
863 } |
801 if (dir == GST_PAD_SRC) { |
867 if (dir == GST_PAD_SRC) { |
802 gst_pad_set_bufferalloc_function (internal, |
868 gst_pad_set_bufferalloc_function (internal, |
803 GST_DEBUG_FUNCPTR (gst_proxy_pad_do_bufferalloc)); |
869 GST_DEBUG_FUNCPTR (gst_proxy_pad_do_bufferalloc)); |
804 gst_pad_set_chain_function (internal, |
870 gst_pad_set_chain_function (internal, |
805 GST_DEBUG_FUNCPTR (gst_proxy_pad_do_chain)); |
871 GST_DEBUG_FUNCPTR (gst_proxy_pad_do_chain)); |
|
872 gst_pad_set_chain_list_function (internal, |
|
873 GST_DEBUG_FUNCPTR (gst_proxy_pad_do_chain_list)); |
806 } else { |
874 } else { |
807 gst_pad_set_getrange_function (internal, |
875 gst_pad_set_getrange_function (internal, |
808 GST_DEBUG_FUNCPTR (gst_proxy_pad_do_getrange)); |
876 GST_DEBUG_FUNCPTR (gst_proxy_pad_do_getrange)); |
809 gst_pad_set_checkgetrange_function (internal, |
877 gst_pad_set_checkgetrange_function (internal, |
810 GST_DEBUG_FUNCPTR (gst_proxy_pad_do_checkgetrange)); |
878 GST_DEBUG_FUNCPTR (gst_proxy_pad_do_checkgetrange)); |
811 } |
879 } |
812 |
880 |
813 GST_PROXY_LOCK (ret); |
881 GST_PROXY_LOCK (pad); |
814 |
882 |
815 /* now make the ghostpad a parent of the internal pad */ |
883 /* now make the ghostpad a parent of the internal pad */ |
816 if (!gst_object_set_parent (GST_OBJECT_CAST (internal), |
884 if (!gst_object_set_parent (GST_OBJECT_CAST (internal), |
817 GST_OBJECT_CAST (ret))) |
885 GST_OBJECT_CAST (pad))) |
818 goto parent_failed; |
886 goto parent_failed; |
819 |
887 |
820 /* The ghostpad is the parent of the internal pad and is the only object that |
888 /* The ghostpad is the parent of the internal pad and is the only object that |
821 * can have a refcount on the internal pad. |
889 * can have a refcount on the internal pad. |
822 * At this point, the GstGhostPad has a refcount of 1, and the internal pad has |
890 * At this point, the GstGhostPad has a refcount of 1, and the internal pad has |
823 * a refcount of 1. |
891 * a refcount of 1. |
824 * When the refcount of the GstGhostPad drops to 0, the ghostpad will dispose |
892 * When the refcount of the GstGhostPad drops to 0, the ghostpad will dispose |
825 * it's refcount on the internal pad in the dispose method by un-parenting it. |
893 * it's refcount on the internal pad in the dispose method by un-parenting it. |
826 * This is why we don't take extra refcounts in the assignments below |
894 * This is why we don't take extra refcounts in the assignments below |
827 */ |
895 */ |
828 GST_PROXY_PAD_INTERNAL (ret) = internal; |
896 GST_PROXY_PAD_INTERNAL (pad) = internal; |
829 GST_PROXY_PAD_INTERNAL (internal) = ret; |
897 GST_PROXY_PAD_INTERNAL (internal) = pad; |
830 |
898 |
831 /* could be more general here, iterating over all writable properties... |
899 /* could be more general here, iterating over all writable properties... |
832 * taking the short road for now tho */ |
900 * taking the short road for now tho */ |
833 GST_GHOST_PAD_CAST (ret)->notify_id = |
901 GST_GHOST_PAD_PRIVATE (pad)->notify_id = |
834 g_signal_connect (internal, "notify::caps", G_CALLBACK (on_int_notify), |
902 g_signal_connect (internal, "notify::caps", G_CALLBACK (on_int_notify), |
835 ret); |
903 pad); |
836 |
904 |
837 /* call function to init values of the pad caps */ |
905 /* call function to init values of the pad caps */ |
838 on_int_notify (internal, NULL, GST_GHOST_PAD_CAST (ret)); |
906 on_int_notify (internal, NULL, GST_GHOST_PAD_CAST (pad)); |
839 |
907 |
840 /* special activation functions for the internal pad */ |
908 /* special activation functions for the internal pad */ |
841 gst_pad_set_activatepull_function (internal, |
909 gst_pad_set_activatepull_function (internal, |
842 GST_DEBUG_FUNCPTR (gst_ghost_pad_internal_do_activate_pull)); |
910 GST_DEBUG_FUNCPTR (gst_ghost_pad_internal_do_activate_pull)); |
843 gst_pad_set_activatepush_function (internal, |
911 gst_pad_set_activatepush_function (internal, |
844 GST_DEBUG_FUNCPTR (gst_ghost_pad_internal_do_activate_push)); |
912 GST_DEBUG_FUNCPTR (gst_ghost_pad_internal_do_activate_push)); |
845 |
913 |
846 GST_PROXY_UNLOCK (ret); |
914 GST_PROXY_UNLOCK (pad); |
847 |
915 |
848 return ret; |
916 GST_GHOST_PAD_PRIVATE (gpad)->constructed = TRUE; |
|
917 return TRUE; |
849 |
918 |
850 /* ERRORS */ |
919 /* ERRORS */ |
851 parent_failed: |
920 parent_failed: |
852 { |
921 { |
853 GST_WARNING_OBJECT (ret, "Could not set internal pad %s:%s", |
922 GST_WARNING_OBJECT (gpad, "Could not set internal pad %s:%s", |
854 GST_DEBUG_PAD_NAME (internal)); |
923 GST_DEBUG_PAD_NAME (internal)); |
855 g_critical ("Could not set internal pad %s:%s", |
924 g_critical ("Could not set internal pad %s:%s", |
856 GST_DEBUG_PAD_NAME (internal)); |
925 GST_DEBUG_PAD_NAME (internal)); |
857 GST_PROXY_UNLOCK (ret); |
926 GST_PROXY_UNLOCK (pad); |
858 gst_object_unref (ret); |
|
859 gst_object_unref (internal); |
927 gst_object_unref (internal); |
860 return NULL; |
928 return FALSE; |
861 } |
929 } |
|
930 } |
|
931 |
|
932 static GstPad * |
|
933 gst_ghost_pad_new_full (const gchar * name, GstPadDirection dir, |
|
934 GstPadTemplate * templ) |
|
935 { |
|
936 GstGhostPad *ret; |
|
937 |
|
938 g_return_val_if_fail (dir != GST_PAD_UNKNOWN, NULL); |
|
939 |
|
940 /* OBJECT CREATION */ |
|
941 if (templ) { |
|
942 ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name, |
|
943 "direction", dir, "template", templ, NULL); |
|
944 } else { |
|
945 ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name, |
|
946 "direction", dir, NULL); |
|
947 } |
|
948 |
|
949 if (!gst_ghost_pad_construct (ret)) |
|
950 goto construct_failed; |
|
951 |
|
952 return GST_PAD (ret); |
|
953 |
|
954 construct_failed: |
|
955 /* already logged */ |
|
956 gst_object_unref (ret); |
|
957 return NULL; |
862 } |
958 } |
863 |
959 |
864 /** |
960 /** |
865 * gst_ghost_pad_new_no_target: |
961 * gst_ghost_pad_new_no_target: |
866 * @name: the name of the new pad, or NULL to assign a default name. |
962 * @name: the name of the new pad, or NULL to assign a default name. |
1068 |
1165 |
1069 g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), FALSE); |
1166 g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), FALSE); |
1070 |
1167 |
1071 GST_PROXY_LOCK (gpad); |
1168 GST_PROXY_LOCK (gpad); |
1072 internal = GST_PROXY_PAD_INTERNAL (gpad); |
1169 internal = GST_PROXY_PAD_INTERNAL (gpad); |
1073 |
1170 g_assert (internal); |
1074 GST_DEBUG_OBJECT (gpad, "set target %s:%s", GST_DEBUG_PAD_NAME (newtarget)); |
1171 |
|
1172 if (newtarget) |
|
1173 GST_DEBUG_OBJECT (gpad, "set target %s:%s", GST_DEBUG_PAD_NAME (newtarget)); |
|
1174 else |
|
1175 GST_DEBUG_OBJECT (gpad, "clearing target"); |
1075 |
1176 |
1076 /* clear old target */ |
1177 /* clear old target */ |
1077 if ((oldtarget = GST_PROXY_PAD_TARGET (gpad))) { |
1178 if ((oldtarget = GST_PROXY_PAD_TARGET (gpad))) { |
1078 /* if we have an internal pad, unlink */ |
1179 if (GST_PAD_IS_SRC (oldtarget)) { |
1079 if (internal) { |
1180 g_signal_handlers_disconnect_by_func (oldtarget, |
1080 if (GST_PAD_IS_SRC (internal)) |
1181 (gpointer) on_src_target_notify, gpad); |
1081 gst_pad_unlink (internal, oldtarget); |
|
1082 else |
|
1083 gst_pad_unlink (oldtarget, internal); |
|
1084 } |
1182 } |
|
1183 |
|
1184 GST_PROXY_PAD_RETARGET (internal) = TRUE; |
|
1185 |
|
1186 /* unlink internal pad */ |
|
1187 if (GST_PAD_IS_SRC (internal)) |
|
1188 gst_pad_unlink (internal, oldtarget); |
|
1189 else |
|
1190 gst_pad_unlink (oldtarget, internal); |
|
1191 |
|
1192 GST_PROXY_PAD_RETARGET (internal) = FALSE; |
1085 } |
1193 } |
1086 |
1194 |
1087 result = gst_proxy_pad_set_target_unlocked (GST_PAD_CAST (gpad), newtarget); |
1195 result = gst_proxy_pad_set_target_unlocked (GST_PAD_CAST (gpad), newtarget); |
1088 |
1196 |
1089 if (result && newtarget) { |
1197 if (result && newtarget) { |
|
1198 if (GST_PAD_IS_SRC (newtarget)) { |
|
1199 g_signal_connect (newtarget, "notify::caps", |
|
1200 G_CALLBACK (on_src_target_notify), gpad); |
|
1201 } |
|
1202 |
1090 /* and link to internal pad */ |
1203 /* and link to internal pad */ |
1091 GST_DEBUG_OBJECT (gpad, "connecting internal pad to target"); |
1204 GST_DEBUG_OBJECT (gpad, "connecting internal pad to target"); |
1092 |
1205 |
1093 if (GST_PAD_IS_SRC (internal)) |
1206 if (GST_PAD_IS_SRC (internal)) |
1094 lret = gst_pad_link (internal, newtarget); |
1207 lret = gst_pad_link (internal, newtarget); |