diff --git a/configure.ac b/configure.ac index b75fed8363..bd5d061d5b 100644 --- a/configure.ac +++ b/configure.ac @@ -642,6 +642,7 @@ testsuite/clock/Makefile testsuite/debug/Makefile testsuite/dynparams/Makefile testsuite/elements/Makefile +testsuite/ghostpads/Makefile testsuite/indexers/Makefile testsuite/parse/Makefile testsuite/plugin/Makefile diff --git a/gst/gstbin.c b/gst/gstbin.c index c01778d544..c2a2012384 100644 --- a/gst/gstbin.c +++ b/gst/gstbin.c @@ -906,7 +906,7 @@ gst_bin_get_list (GstBin * bin) * Returns: An element inside the bin implementing the interface. */ GstElement * -gst_bin_get_by_interface (GstBin *bin, const GType interface) +gst_bin_get_by_interface (GstBin *bin, GType interface) { GList *walk; @@ -942,7 +942,7 @@ gst_bin_get_by_interface (GstBin *bin, const GType interface) * Returns: An element inside the bin implementing the interface. */ GList * -gst_bin_get_all_by_interface (GstBin *bin, const GType interface) +gst_bin_get_all_by_interface (GstBin *bin, GType interface) { GList *walk, *ret = NULL; diff --git a/gst/gstbin.h b/gst/gstbin.h index 2e08b75985..60cdbf6cf1 100644 --- a/gst/gstbin.h +++ b/gst/gstbin.h @@ -103,8 +103,8 @@ GstElement* gst_bin_get_by_name (GstBin *bin, const gchar *name); GstElement* gst_bin_get_by_name_recurse_up (GstBin *bin, const gchar *name); G_CONST_RETURN GList* gst_bin_get_list (GstBin *bin); -GstElement* gst_bin_get_by_interface (GstBin *bin, const GType interface); -GList * gst_bin_get_all_by_interface (GstBin *bin, const GType interface); +GstElement* gst_bin_get_by_interface (GstBin *bin, GType interface); +GList * gst_bin_get_all_by_interface (GstBin *bin, GType interface); gboolean gst_bin_iterate (GstBin *bin); diff --git a/gst/gstcaps.c b/gst/gstcaps.c index 676c835d73..3aa92c1830 100644 --- a/gst/gstcaps.c +++ b/gst/gstcaps.c @@ -22,6 +22,7 @@ #endif #include +#include #include #define CAPS_POISON(caps) G_STMT_START{ \ @@ -46,6 +47,14 @@ static void _gst_caps_value_init (GValue *value); static void _gst_caps_value_free (GValue *value); static void _gst_caps_value_copy (const GValue *src, GValue *dest); static gpointer _gst_caps_value_peek_pointer (const GValue *value); +static gchar* _gst_caps_collect_value (GValue *value, + guint n_collect_values, + GTypeCValue *collect_values, + guint collect_flags); +static gchar* _gst_caps_lcopy_value (const GValue *value, + guint n_collect_values, + GTypeCValue *collect_values, + guint collect_flags); static gboolean _gst_caps_from_string_inplace (GstCaps *caps, const gchar *string); @@ -59,10 +68,10 @@ void _gst_caps_initialize (void) _gst_caps_value_free, _gst_caps_value_copy, _gst_caps_value_peek_pointer, - NULL, - NULL, - NULL, - NULL, + "p", + _gst_caps_collect_value, + "p", + _gst_caps_lcopy_value, }; static const GTypeInfo caps2_info = { 0, @@ -1134,7 +1143,7 @@ static void _gst_caps_transform_to_string (const GValue *src_value, static void _gst_caps_value_init (GValue *value) { - value->data[0].v_pointer = gst_caps_new_empty(); + value->data[0].v_pointer = NULL; } static void _gst_caps_value_free (GValue *value) @@ -1159,6 +1168,49 @@ static gpointer _gst_caps_value_peek_pointer (const GValue *value) return value->data[0].v_pointer; } +/* adapted from gboxed.c */ +static gchar* +_gst_caps_collect_value (GValue *value, + guint n_collect_values, + GTypeCValue *collect_values, + guint collect_flags) +{ + if (!collect_values[0].v_pointer) + value->data[0].v_pointer = NULL; + else + if (collect_flags & G_VALUE_NOCOPY_CONTENTS) + { + value->data[0].v_pointer = collect_values[0].v_pointer; + value->data[1].v_uint = G_VALUE_NOCOPY_CONTENTS; + } + else + value->data[0].v_pointer = gst_caps_copy (collect_values[0].v_pointer); + + return NULL; +} + +static gchar* +_gst_caps_lcopy_value (const GValue *value, + guint n_collect_values, + GTypeCValue *collect_values, + guint collect_flags) +{ + GstCaps **boxed_p = collect_values[0].v_pointer; + + if (!boxed_p) + return g_strdup_printf ("value location for `%s' passed as NULL", + G_VALUE_TYPE_NAME (value)); + + if (!value->data[0].v_pointer) + *boxed_p = NULL; + else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) + *boxed_p = value->data[0].v_pointer; + else + *boxed_p = gst_caps_copy (value->data[0].v_pointer); + + return NULL; +} + /* fixate utility functions */ gboolean gst_caps_structure_fixate_field_nearest_int (GstStructure *structure, diff --git a/gst/gstelement.c b/gst/gstelement.c index f73ca65e77..e2918d1962 100644 --- a/gst/gstelement.c +++ b/gst/gstelement.c @@ -1056,7 +1056,8 @@ gst_element_add_pad (GstElement *element, GstPad *pad) g_return_if_fail (GST_IS_ELEMENT (element)); g_return_if_fail (GST_IS_PAD (pad)); - /* first check to make sure the pad's parent is already set */ + /* first check to make sure the pad hasn't already been added to another + * element */ g_return_if_fail (GST_PAD_PARENT (pad) == NULL); /* then check to see if there's already a pad by that name here */ @@ -1070,10 +1071,18 @@ gst_element_add_pad (GstElement *element, GstPad *pad) /* add it to the list */ element->pads = g_list_append (element->pads, pad); element->numpads++; - if (gst_pad_get_direction (pad) == GST_PAD_SRC) + + switch (gst_pad_get_direction (pad)) { + case GST_PAD_SRC: element->numsrcpads++; - else + break; + case GST_PAD_SINK: element->numsinkpads++; + break; + default: + /* can happen for ghost pads */ + break; + } /* activate element when we are playing */ if (GST_STATE (element) == GST_STATE_PLAYING) @@ -1083,6 +1092,36 @@ gst_element_add_pad (GstElement *element, GstPad *pad) g_signal_emit (G_OBJECT (element), gst_element_signals[NEW_PAD], 0, pad); } +/** + * gst_element_add_ghost_pad: + * @element: a #GstElement to add the ghost pad to. + * @pad: the #GstPad from which the new ghost pad will be created. + * @name: the name of the new ghost pad, or NULL to assign a unique name + * automatically. + * + * Creates a ghost pad from the given pad, and adds it to the list of pads + * for this element. + * + * Returns: the added ghost #GstPad, or NULL on error. + */ +GstPad * +gst_element_add_ghost_pad (GstElement *element, GstPad *pad, const gchar *name) +{ + GstPad *ghostpad; + + g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); + g_return_val_if_fail (GST_IS_PAD (pad), NULL); + + /* then check to see if there's already a pad by that name here */ + g_return_val_if_fail (gst_object_check_uniqueness (element->pads, name) == TRUE, NULL); + + ghostpad = gst_ghost_pad_new (name, pad); + + gst_element_add_pad (element, ghostpad); + + return ghostpad; +} + /** * gst_element_remove_pad: * @element: a #GstElement to remove pad from. @@ -1100,79 +1139,42 @@ gst_element_remove_pad (GstElement *element, GstPad *pad) g_return_if_fail (GST_PAD_PARENT (pad) == element); - /* check to see if the pad is still linked */ - /* FIXME: what if someone calls _remove_pad instead of - _remove_ghost_pad? */ if (GST_IS_REAL_PAD (pad)) { + /* unlink if necessary */ if (GST_RPAD_PEER (pad) != NULL) { gst_pad_unlink (pad, GST_PAD (GST_RPAD_PEER (pad))); } + } else if (GST_IS_GHOST_PAD (pad)) { + g_object_set (pad, "real-pad", NULL, NULL); } /* remove it from the list */ element->pads = g_list_remove (element->pads, pad); element->numpads--; - if (gst_pad_get_direction (pad) == GST_PAD_SRC) + switch (gst_pad_get_direction (pad)) { + case GST_PAD_SRC: element->numsrcpads--; - else + break; + case GST_PAD_SINK: element->numsinkpads--; + break; + default: + /* can happen for ghost pads */ + break; + } g_signal_emit (G_OBJECT (element), gst_element_signals[PAD_REMOVED], 0, pad); gst_object_unparent (GST_OBJECT (pad)); } -/** - * gst_element_add_ghost_pad: - * @element: a #GstElement to add the ghost pad to. - * @pad: the #GstPad from which the new ghost pad will be created. - * @name: the name of the new ghost pad. - * - * Creates a ghost pad from the given pad, and adds it to the list of pads - * for this element. - * - * Returns: the added ghost #GstPad, or NULL, if no ghost pad was created. - */ -GstPad * -gst_element_add_ghost_pad (GstElement *element, GstPad *pad, const gchar *name) -{ - GstPad *ghostpad; - - g_return_val_if_fail (element != NULL, NULL); - g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); - g_return_val_if_fail (pad != NULL, NULL); - g_return_val_if_fail (GST_IS_PAD (pad), NULL); - - /* then check to see if there's already a pad by that name here */ - g_return_val_if_fail (gst_object_check_uniqueness (element->pads, name) == TRUE, NULL); - - GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, - "creating new ghost pad called %s, from pad %s:%s", - name, GST_DEBUG_PAD_NAME(pad)); - ghostpad = gst_ghost_pad_new (name, pad); - - /* add it to the list */ - GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,"adding ghost pad %s to element %s", - name, GST_ELEMENT_NAME (element)); - element->pads = g_list_append (element->pads, ghostpad); - element->numpads++; - /* set the parent of the ghostpad */ - gst_object_set_parent (GST_OBJECT (ghostpad), GST_OBJECT (element)); - - GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,"added ghostpad %s:%s",GST_DEBUG_PAD_NAME(ghostpad)); - - /* emit the NEW_GHOST_PAD signal */ - g_signal_emit (G_OBJECT (element), gst_element_signals[NEW_PAD], 0, ghostpad); - - return ghostpad; -} - /** * gst_element_remove_ghost_pad: * @element: a #GstElement to remove the ghost pad from. * @pad: ghost #GstPad to remove. * - * Removes a ghost pad from an element. + * Removes a ghost pad from an element. Deprecated, use gst_element_remove_pad + * instead. */ void gst_element_remove_ghost_pad (GstElement *element, GstPad *pad) @@ -1180,15 +1182,10 @@ gst_element_remove_ghost_pad (GstElement *element, GstPad *pad) g_return_if_fail (GST_IS_ELEMENT (element)); g_return_if_fail (GST_IS_GHOST_PAD (pad)); - /* FIXME this is redundant? - * wingo 10-july-2001: I don't think so, you have to actually remove the pad - * from the element. gst_pad_remove_ghost_pad just removes the ghostpad from - * the real pad's ghost pad list - */ - gst_object_ref (GST_OBJECT (pad)); + g_warning ("gst_element_remove_ghost_pad is deprecated.\n" + "Use gst_element_remove_pad instead."); + gst_element_remove_pad (element, pad); - gst_pad_remove_ghost_pad (GST_PAD (GST_PAD_REALIZE (pad)), pad); - gst_object_unref (GST_OBJECT (pad)); } diff --git a/gst/gstmarshal.list b/gst/gstmarshal.list index 48fff87f28..0f033ad768 100644 --- a/gst/gstmarshal.list +++ b/gst/gstmarshal.list @@ -16,3 +16,5 @@ VOID:UINT,POINTER BOOLEAN:VOID BOOLEAN:POINTER POINTER:POINTER +BOXED:BOXED +VOID:BOXED diff --git a/gst/gstpad.c b/gst/gstpad.c index 0fb5331a74..2c21841d15 100644 --- a/gst/gstpad.c +++ b/gst/gstpad.c @@ -183,8 +183,8 @@ gst_real_pad_class_init (GstRealPadClass *klass) gst_real_pad_signals[REAL_CAPS_NEGO_FAILED] = g_signal_new ("caps_nego_failed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRealPadClass, caps_nego_failed), NULL, NULL, - gst_marshal_VOID__POINTER, G_TYPE_NONE, 1, - G_TYPE_POINTER); + gst_marshal_VOID__BOXED, G_TYPE_NONE, 1, + GST_TYPE_CAPS); gst_real_pad_signals[REAL_LINKED] = g_signal_new ("linked", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRealPadClass, linked), NULL, NULL, @@ -199,11 +199,9 @@ gst_real_pad_class_init (GstRealPadClass *klass) g_signal_new ("fixate", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRealPadClass, appfixatefunc), _gst_real_pad_fixate_accumulator, NULL, - gst_marshal_POINTER__POINTER, G_TYPE_POINTER, 1, - G_TYPE_POINTER); + gst_marshal_BOXED__BOXED, GST_TYPE_CAPS, 1, + GST_TYPE_CAPS); -/* gtk_object_add_arg_type ("GstRealPad::active", G_TYPE_BOOLEAN, */ -/* GTK_ARG_READWRITE, REAL_ARG_ACTIVE); */ g_object_class_install_property (G_OBJECT_CLASS (klass), REAL_ARG_ACTIVE, g_param_spec_boolean ("active", "Active", "Whether the pad is active.", TRUE, G_PARAM_READWRITE)); @@ -221,7 +219,7 @@ static gboolean _gst_real_pad_fixate_accumulator (GSignalInvocationHint *ihint, GValue *return_accu, const GValue *handler_return, gpointer dummy) { - if (g_value_get_pointer (handler_return)) { + if (g_value_get_boxed (handler_return)) { g_value_copy (handler_return, return_accu); /* stop emission if something was returned */ return FALSE; @@ -400,7 +398,10 @@ gst_pad_get_direction (GstPad *pad) { g_return_val_if_fail (GST_IS_PAD (pad), GST_PAD_UNKNOWN); - return GST_PAD_DIRECTION (pad); + if (GST_IS_REAL_PAD (pad)) + return GST_PAD_DIRECTION (pad); + else + return GST_PAD_UNKNOWN; } /** @@ -1837,12 +1838,18 @@ gst_pad_add_ghost_pad (GstPad *pad, g_return_if_fail (ghostpad != NULL); g_return_if_fail (GST_IS_GHOST_PAD (ghostpad)); - realpad = GST_PAD_REALIZE (pad); + /* if we're ghosting a ghost pad, drill down to find the real pad */ + realpad = (GstRealPad*)pad; + while (GST_IS_GHOST_PAD (realpad)) + realpad = GST_GPAD_REALPAD (realpad); + g_return_if_fail (GST_IS_REAL_PAD (realpad)); + /* will ref the pad template */ + GST_GPAD_REALPAD (ghostpad) = realpad; realpad->ghostpads = g_list_prepend (realpad->ghostpads, ghostpad); + gst_pad_set_pad_template (GST_PAD (ghostpad), GST_PAD_PAD_TEMPLATE (pad)); } - /** * gst_pad_remove_ghost_pad: * @pad: a #GstPad to remove the ghost pad from. @@ -1861,6 +1868,7 @@ gst_pad_remove_ghost_pad (GstPad *pad, realpad = GST_PAD_REALIZE (pad); g_return_if_fail (GST_GPAD_REALPAD (ghostpad) == realpad); + gst_pad_set_pad_template (GST_PAD (ghostpad), NULL); realpad->ghostpads = g_list_remove (realpad->ghostpads, ghostpad); GST_GPAD_REALPAD (ghostpad) = NULL; } @@ -2441,8 +2449,8 @@ gst_pad_get_caps (GstPad *pad) * * Gets the template capabilities of this pad. * - * Returns: the template #GstCaps of this pad, unref the caps - * if you no longer need it. + * Returns: the #GstCaps of this pad template. If you intend to keep a reference + * on the caps, make a copy (see gst_caps_copy ()). */ const GstCaps* gst_pad_get_pad_template_caps (GstPad *pad) @@ -2470,8 +2478,8 @@ gst_pad_get_pad_template_caps (GstPad *pad) * * Gets the capability with the given name from this pad template. * - * Returns: the #GstCaps, or NULL if not found or in case of an error. unref - * the caps if you no longer need it. + * Returns: the #GstCaps of this pad template, or NULL if not found. If you + * intend to keep a reference on the caps, make a copy (see gst_caps_copy ()). */ const GstCaps* gst_pad_template_get_caps_by_name (GstPadTemplate *templ, const gchar *name) @@ -2497,7 +2505,7 @@ gst_pad_template_get_caps_by_name (GstPadTemplate *templ, const gchar *name) * Checks if two pads have compatible capabilities. * * Returns: TRUE if they are compatible or if the capabilities - * could not be checked + * could not be checked. */ gboolean gst_pad_check_compatibility (GstPad *srcpad, GstPad *sinkpad) @@ -2684,6 +2692,9 @@ gst_real_pad_dispose (GObject *object) /* No linked pad can ever be disposed. * It has to have a parent to be linked * and a parent would hold a reference */ + /* FIXME: what about if g_object_dispose is explicitly called on the pad? Is + that legal? otherwise we could assert GST_OBJECT_PARENT (pad) == NULL as + well... */ g_assert (GST_PAD_PEER (pad) == NULL); GST_CAT_DEBUG (GST_CAT_REFCOUNTING, "dispose %s:%s", GST_DEBUG_PAD_NAME(pad)); @@ -2697,16 +2708,23 @@ gst_real_pad_dispose (GObject *object) while (ghostpads) { GstPad *ghostpad = GST_PAD (ghostpads->data); - if (GST_IS_ELEMENT (GST_OBJECT_PARENT (ghostpad))){ - GST_CAT_DEBUG (GST_CAT_REFCOUNTING, "removing ghost pad from element '%s'", - GST_OBJECT_NAME (GST_OBJECT_PARENT (ghostpad))); + if (GST_IS_ELEMENT (GST_OBJECT_PARENT (ghostpad))) { + GstElement *parent = GST_ELEMENT (GST_OBJECT_PARENT (ghostpad)); - gst_element_remove_ghost_pad (GST_ELEMENT (GST_OBJECT_PARENT (ghostpad)), GST_PAD (ghostpad)); + GST_CAT_DEBUG (GST_CAT_REFCOUNTING, "removing ghost pad from element '%s'", + GST_OBJECT_NAME (parent)); + gst_element_remove_pad (parent, ghostpad); + } else { + /* handle the case where we have some floating ghost pad that was never + added to an element */ + g_object_set (ghostpad, "real-pad", NULL, NULL); } ghostpads = g_list_next (ghostpads); } g_list_free (orig); - g_list_free (GST_REAL_PAD(pad)->ghostpads); + /* as the ghost pads are removed, they remove themselves from ->ghostpads. + So it should be empty now. Let's assert that. */ + g_assert (GST_REAL_PAD(pad)->ghostpads == NULL); } if (GST_IS_ELEMENT (GST_OBJECT_PARENT (pad))) { @@ -3239,8 +3257,8 @@ gst_pad_template_new (const gchar *name_template, * * Gets the capabilities of the pad template. * - * Returns: the #GstCaps of the pad template. unref the caps - * after use. + * Returns: the #GstCaps of the pad template. If you need to keep a reference to + * the caps, make a copy (see gst_caps_copy ()). */ const GstCaps* gst_pad_template_get_caps (GstPadTemplate *templ) @@ -3285,9 +3303,19 @@ GType _gst_ghost_pad_type = 0; static void gst_ghost_pad_class_init (GstGhostPadClass *klass); static void gst_ghost_pad_init (GstGhostPad *pad); static void gst_ghost_pad_dispose (GObject *object); +static void gst_ghost_pad_get_property (GObject* object, guint prop_id, + GValue* value, GParamSpec* pspec); +static void gst_ghost_pad_set_property (GObject* object, guint prop_id, + const GValue* value, GParamSpec* pspec); static GstPad *ghost_pad_parent_class = NULL; /* static guint gst_ghost_pad_signals[LAST_SIGNAL] = { 0 }; */ +enum +{ + GPAD_ARG_0, + GPAD_ARG_REAL_PAD + /* fill me */ +}; GType gst_ghost_pad_get_type (void) @@ -3317,6 +3345,12 @@ gst_ghost_pad_class_init (GstGhostPadClass *klass) ghost_pad_parent_class = g_type_class_ref (GST_TYPE_PAD); gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_ghost_pad_dispose); + gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_ghost_pad_set_property); + gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_ghost_pad_get_property); + + g_object_class_install_property (gobject_class, GPAD_ARG_REAL_PAD, + g_param_spec_object ("real-pad", "Real pad", "The real pad for the ghost pad", + GST_TYPE_PAD, G_PARAM_READWRITE)); } static void @@ -3324,17 +3358,59 @@ gst_ghost_pad_init (GstGhostPad *pad) { /* zeroed by glib */ } + static void gst_ghost_pad_dispose (GObject *object) { - GstGhostPad *pad = GST_GHOST_PAD (object); - - if (pad->realpad) - gst_pad_remove_ghost_pad((GstPad *) pad->realpad, (GstPad *) pad); + g_object_set (object, "real-pad", NULL, NULL); G_OBJECT_CLASS (ghost_pad_parent_class)->dispose (object); } +static void +gst_ghost_pad_set_property (GObject* object, guint prop_id, + const GValue* value, GParamSpec* pspec) +{ + GstPad *ghostpad = (GstPad*)object; + GstPad *oldrealpad = (GstPad*)GST_GPAD_REALPAD (ghostpad); + GstPad *realpad = NULL; + + switch (prop_id) { + case GPAD_ARG_REAL_PAD: + realpad = g_value_get_object (value); + + if (oldrealpad) { + if (realpad == oldrealpad) + return; + else + gst_pad_remove_ghost_pad (oldrealpad, ghostpad); + } + + if (realpad) + gst_pad_add_ghost_pad (realpad, ghostpad); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_ghost_pad_get_property (GObject* object, guint prop_id, + GValue* value, GParamSpec* pspec) +{ + switch (prop_id) { + case GPAD_ARG_REAL_PAD: + g_value_set_object (value, GST_GPAD_REALPAD (object)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + /** * gst_ghost_pad_new: * @name: the name of the new ghost pad. @@ -3342,40 +3418,28 @@ gst_ghost_pad_dispose (GObject *object) * * Creates a new ghost pad associated with the given pad, and names it with * the given name. If name is NULL, a guaranteed unique name (across all - * ghost pads) will be assigned (most likely of the form ghostpad%d). + * ghost pads) will be assigned. * * Returns: a new ghost #GstPad, or NULL in case of an error. */ - GstPad* gst_ghost_pad_new (const gchar *name, GstPad *pad) { - GstGhostPad *ghostpad; - GstRealPad *realpad; + GstPad *gpad; g_return_val_if_fail (GST_IS_PAD (pad), NULL); - ghostpad = g_object_new (gst_ghost_pad_get_type () ,NULL); - gst_pad_set_name (GST_PAD (ghostpad), name); + gpad = g_object_new (GST_TYPE_GHOST_PAD, + "name", name, + "real-pad", pad, + NULL); - realpad = (GstRealPad *) pad; + GST_CAT_DEBUG (GST_CAT_PADS, "created ghost pad \"%s\" for pad %s:%s", + GST_OBJECT_NAME (gpad), + GST_DEBUG_PAD_NAME (pad)); - while (!GST_IS_REAL_PAD (realpad)) { - realpad = GST_PAD_REALIZE (realpad); - } - GST_GPAD_REALPAD (ghostpad) = realpad; - gst_pad_set_pad_template (GST_PAD (ghostpad), GST_PAD_PAD_TEMPLATE (pad)); - - /* add ourselves to the real pad's list of ghostpads */ - gst_pad_add_ghost_pad (pad, GST_PAD (ghostpad)); - - /* FIXME need to ref the real pad here... ? */ - - GST_CAT_DEBUG (GST_CAT_PADS, "created ghost pad \"%s\"", - gst_pad_get_name (GST_PAD (ghostpad))); - - return GST_PAD (ghostpad); + return gpad; } /** diff --git a/tests/old/testsuite/Makefile.am b/tests/old/testsuite/Makefile.am index 0d0d2d37d5..75ddff7512 100644 --- a/tests/old/testsuite/Makefile.am +++ b/tests/old/testsuite/Makefile.am @@ -13,12 +13,12 @@ else GST_DEBUG_DIRS = debug endif -SUBDIRS = bins bytestream cleanup dynparams \ +SUBDIRS = bins bytestream cleanup dynparams ghostpads \ caps plugin elements clock refcounting tags threads \ indexers debug $(GST_PARSE_DIRS) $(GST_DEBUG_DIRS) DIST_SUBDIRS = bins bytestream caps cleanup clock dynparams elements indexers \ - plugin refcounting tags threads parse debug + plugin refcounting tags threads parse debug ghostpads tests_pass = test_gst_init tests_fail = diff --git a/tests/old/testsuite/ghostpads/Makefile.am b/tests/old/testsuite/ghostpads/Makefile.am new file mode 100644 index 0000000000..c66c40b24d --- /dev/null +++ b/tests/old/testsuite/ghostpads/Makefile.am @@ -0,0 +1,7 @@ +include ../Rules + +tests_pass = ghostpads +tests_fail = + +ghostpads_SOURCES = ghostpads.c + diff --git a/tests/old/testsuite/ghostpads/ghostpads.c b/tests/old/testsuite/ghostpads/ghostpads.c new file mode 100644 index 0000000000..27c0aff9a3 --- /dev/null +++ b/tests/old/testsuite/ghostpads/ghostpads.c @@ -0,0 +1,64 @@ +/* GStreamer + * Copyright (C) 2004 Andy Wingo + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +gint +main (gint argc, gchar *argv[]) +{ + GstElement *pipeline, *bin; + GstElement *fakesrc, *fakesink, *identity; + GstPad *sink, *src, *real = (GstPad*)0xdeadbeef; + + gst_init (&argc, &argv); + + pipeline = gst_element_factory_make ("pipeline", NULL); + bin = gst_element_factory_make ("bin", NULL); + fakesrc = gst_element_factory_make ("fakesrc", NULL); + fakesink = gst_element_factory_make ("fakesink", NULL); + identity = gst_element_factory_make ("identity", NULL); + + gst_bin_add_many (GST_BIN (pipeline), fakesrc, bin, fakesink, NULL); + gst_bin_add (GST_BIN (bin), identity); + + sink = gst_element_add_ghost_pad (bin, + gst_element_get_pad (identity, "sink"), + "sink"); + src = gst_element_add_ghost_pad (bin, + gst_element_get_pad (identity, "src"), + "src"); + + gst_element_link_many (fakesrc, bin, fakesink); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + if (!gst_bin_iterate (GST_BIN (pipeline))) + g_assert_not_reached (); + + gst_element_set_state (pipeline, GST_STATE_NULL); + + /* test the cleanup */ + gst_object_ref (GST_OBJECT (sink)); + gst_object_unref ((GstObject*)pipeline); + g_object_get (sink, "real-pad", &real, NULL); + g_assert (real == NULL); + g_assert (G_OBJECT (sink)->ref_count == 1); + gst_object_unref (GST_OBJECT (sink)); + + return 0; +} diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am index 0d0d2d37d5..75ddff7512 100644 --- a/testsuite/Makefile.am +++ b/testsuite/Makefile.am @@ -13,12 +13,12 @@ else GST_DEBUG_DIRS = debug endif -SUBDIRS = bins bytestream cleanup dynparams \ +SUBDIRS = bins bytestream cleanup dynparams ghostpads \ caps plugin elements clock refcounting tags threads \ indexers debug $(GST_PARSE_DIRS) $(GST_DEBUG_DIRS) DIST_SUBDIRS = bins bytestream caps cleanup clock dynparams elements indexers \ - plugin refcounting tags threads parse debug + plugin refcounting tags threads parse debug ghostpads tests_pass = test_gst_init tests_fail = diff --git a/testsuite/ghostpads/Makefile.am b/testsuite/ghostpads/Makefile.am new file mode 100644 index 0000000000..c66c40b24d --- /dev/null +++ b/testsuite/ghostpads/Makefile.am @@ -0,0 +1,7 @@ +include ../Rules + +tests_pass = ghostpads +tests_fail = + +ghostpads_SOURCES = ghostpads.c + diff --git a/testsuite/ghostpads/ghostpads.c b/testsuite/ghostpads/ghostpads.c new file mode 100644 index 0000000000..27c0aff9a3 --- /dev/null +++ b/testsuite/ghostpads/ghostpads.c @@ -0,0 +1,64 @@ +/* GStreamer + * Copyright (C) 2004 Andy Wingo + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +gint +main (gint argc, gchar *argv[]) +{ + GstElement *pipeline, *bin; + GstElement *fakesrc, *fakesink, *identity; + GstPad *sink, *src, *real = (GstPad*)0xdeadbeef; + + gst_init (&argc, &argv); + + pipeline = gst_element_factory_make ("pipeline", NULL); + bin = gst_element_factory_make ("bin", NULL); + fakesrc = gst_element_factory_make ("fakesrc", NULL); + fakesink = gst_element_factory_make ("fakesink", NULL); + identity = gst_element_factory_make ("identity", NULL); + + gst_bin_add_many (GST_BIN (pipeline), fakesrc, bin, fakesink, NULL); + gst_bin_add (GST_BIN (bin), identity); + + sink = gst_element_add_ghost_pad (bin, + gst_element_get_pad (identity, "sink"), + "sink"); + src = gst_element_add_ghost_pad (bin, + gst_element_get_pad (identity, "src"), + "src"); + + gst_element_link_many (fakesrc, bin, fakesink); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + if (!gst_bin_iterate (GST_BIN (pipeline))) + g_assert_not_reached (); + + gst_element_set_state (pipeline, GST_STATE_NULL); + + /* test the cleanup */ + gst_object_ref (GST_OBJECT (sink)); + gst_object_unref ((GstObject*)pipeline); + g_object_get (sink, "real-pad", &real, NULL); + g_assert (real == NULL); + g_assert (G_OBJECT (sink)->ref_count == 1); + gst_object_unref (GST_OBJECT (sink)); + + return 0; +}