testsuite/debug/Makefile
testsuite/dynparams/Makefile
testsuite/elements/Makefile
+testsuite/ghostpads/Makefile
testsuite/indexers/Makefile
testsuite/parse/Makefile
testsuite/plugin/Makefile
* 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;
* 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;
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);
#endif
#include <string.h>
+#include <gobject/gvaluecollector.h>
#include <gst/gst.h>
#define CAPS_POISON(caps) G_STMT_START{ \
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);
_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,
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)
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,
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 */
/* 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)
}
/**
+ * 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.
* @pad: the #GstPad to remove from the element.
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_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)
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));
}
BOOLEAN:VOID
BOOLEAN:POINTER
POINTER:POINTER
+BOXED:BOXED
+VOID:BOXED
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,
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));
_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;
{
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;
}
/**
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.
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;
}
*
* 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)
*
* 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)
* 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)
/* 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));
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))) {
*
* 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)
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)
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
{
/* 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.
*
* 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);
-
- realpad = (GstRealPad *) 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... ? */
+ gpad = g_object_new (GST_TYPE_GHOST_PAD,
+ "name", name,
+ "real-pad", pad,
+ NULL);
- GST_CAT_DEBUG (GST_CAT_PADS, "created ghost pad \"%s\"",
- gst_pad_get_name (GST_PAD (ghostpad)));
+ GST_CAT_DEBUG (GST_CAT_PADS, "created ghost pad \"%s\" for pad %s:%s",
+ GST_OBJECT_NAME (gpad),
+ GST_DEBUG_PAD_NAME (pad));
- return GST_PAD (ghostpad);
+ return gpad;
}
/**
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 =
--- /dev/null
+include ../Rules
+
+tests_pass = ghostpads
+tests_fail =
+
+ghostpads_SOURCES = ghostpads.c
+
--- /dev/null
+/* GStreamer
+ * Copyright (C) 2004 Andy Wingo <wingo at pobox.com>
+ *
+ * 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 <gst/gst.h>
+
+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;
+}
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 =
--- /dev/null
+include ../Rules
+
+tests_pass = ghostpads
+tests_fail =
+
+ghostpads_SOURCES = ghostpads.c
+
--- /dev/null
+/* GStreamer
+ * Copyright (C) 2004 Andy Wingo <wingo at pobox.com>
+ *
+ * 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 <gst/gst.h>
+
+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;
+}