summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Kost <ensonic@users.sourceforge.net>2005-04-21 17:10:09 +0000
committerStefan Kost <ensonic@users.sourceforge.net>2005-04-21 17:10:09 +0000
commit2aa179d5ecae6bc723a97ad5b814e0a01d056d47 (patch)
tree8d3ad57f9f27ef319c32c2991869935e06f15da5
parent7e76da9dafdb59abe43ccb45895cf4b5622204f7 (diff)
downloadgstreamer-2aa179d5ecae6bc723a97ad5b814e0a01d056d47.tar.gz
new iface to uniformly access elements children and their properties
Original commit message from CVS: new iface to uniformly access elements children and their properties
-rw-r--r--configure.ac1
-rw-r--r--docs/gst/gstreamer-sections.txt26
-rw-r--r--docs/gst/tmpl/gstchildproxy.sgml140
-rw-r--r--gst/Makefile.am2
-rw-r--r--gst/gst.h1
-rw-r--r--gst/gstbin.c35
-rw-r--r--gst/gstchildproxy.c407
-rw-r--r--gst/gstchildproxy.h76
-rw-r--r--gst/parse/grammar.y6
-rw-r--r--tests/old/testsuite/Makefile.am4
-rw-r--r--tests/old/testsuite/childproxy/Makefile.am6
-rw-r--r--tests/old/testsuite/childproxy/childproxy.c114
-rw-r--r--testsuite/Makefile.am4
-rw-r--r--testsuite/childproxy/Makefile.am6
-rw-r--r--testsuite/childproxy/childproxy.c114
15 files changed, 936 insertions, 6 deletions
diff --git a/configure.ac b/configure.ac
index 2844e0fe12..a1a00388c7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -676,6 +676,7 @@ testsuite/Makefile
testsuite/bins/Makefile
testsuite/bytestream/Makefile
testsuite/caps/Makefile
+testsuite/childproxy/Makefile
testsuite/cleanup/Makefile
testsuite/clock/Makefile
testsuite/debug/Makefile
diff --git a/docs/gst/gstreamer-sections.txt b/docs/gst/gstreamer-sections.txt
index 26af6f0c23..fe897d4d9e 100644
--- a/docs/gst/gstreamer-sections.txt
+++ b/docs/gst/gstreamer-sections.txt
@@ -1114,6 +1114,32 @@ gst_pad_template_flags_get_type
</SECTION>
<SECTION>
+<FILE>gstchildproxy</FILE>
+<TITLE>GstChildProxy</TITLE>
+gst_child_proxy_get_children_count
+gst_child_proxy_get_child_by_name
+gst_child_proxy_get_child_by_index
+gst_child_proxy_lookup
+gst_child_proxy_get_property
+gst_child_proxy_get_valist
+gst_child_proxy_get
+gst_child_proxy_set_property
+gst_child_proxy_set_valist
+gst_child_proxy_set
+gst_child_proxy_child_added
+gst_child_proxy_child_removed
+<SUBSECTION Standard>
+GstChildProxy
+GstChildProxyInterface
+GST_CHILD_PROXY
+GST_IS_CHILD_PROXY
+GST_CHILD_PROXY_GET_INTERFACE
+GST_TYPE_CHILD_PROXY
+<SUBSECTION Private>
+gst_child_proxy_get_type
+</SECTION>
+
+<SECTION>
<FILE>gstparse</FILE>
<TITLE>GstParse</TITLE>
gst_parse_error_quark
diff --git a/docs/gst/tmpl/gstchildproxy.sgml b/docs/gst/tmpl/gstchildproxy.sgml
new file mode 100644
index 0000000000..a8185b119e
--- /dev/null
+++ b/docs/gst/tmpl/gstchildproxy.sgml
@@ -0,0 +1,140 @@
+<!-- ##### SECTION Title ##### -->
+GstChildProxy
+
+<!-- ##### SECTION Short_Description ##### -->
+interface for multi child element property access
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+This interface provides a uniform way to access child objects of elements.
+There are methods to get the children and methods to (recursivly) set and get
+their properties.
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### FUNCTION gst_child_proxy_get_children_count ##### -->
+<para>
+
+</para>
+
+@parent:
+@Returns:
+
+
+<!-- ##### FUNCTION gst_child_proxy_get_child_by_name ##### -->
+<para>
+
+</para>
+
+@parent:
+@name:
+@Returns:
+
+
+<!-- ##### FUNCTION gst_child_proxy_get_child_by_index ##### -->
+<para>
+
+</para>
+
+@parent:
+@index:
+@Returns:
+
+
+<!-- ##### FUNCTION gst_child_proxy_lookup ##### -->
+<para>
+
+</para>
+
+@object:
+@name:
+@target:
+@pspec:
+@Returns:
+
+
+<!-- ##### FUNCTION gst_child_proxy_get_property ##### -->
+<para>
+
+</para>
+
+@object:
+@name:
+@value:
+
+
+<!-- ##### FUNCTION gst_child_proxy_get_valist ##### -->
+<para>
+
+</para>
+
+@object:
+@first_property_name:
+@var_args:
+
+
+<!-- ##### FUNCTION gst_child_proxy_get ##### -->
+<para>
+
+</para>
+
+@object:
+@first_property_name:
+@Varargs:
+
+
+<!-- ##### FUNCTION gst_child_proxy_set_property ##### -->
+<para>
+
+</para>
+
+@object:
+@name:
+@value:
+
+
+<!-- ##### FUNCTION gst_child_proxy_set_valist ##### -->
+<para>
+
+</para>
+
+@object:
+@first_property_name:
+@var_args:
+
+
+<!-- ##### FUNCTION gst_child_proxy_set ##### -->
+<para>
+
+</para>
+
+@object:
+@first_property_name:
+@Varargs:
+
+
+<!-- ##### FUNCTION gst_child_proxy_child_added ##### -->
+<para>
+
+</para>
+
+@object:
+@child:
+
+
+<!-- ##### FUNCTION gst_child_proxy_child_removed ##### -->
+<para>
+
+</para>
+
+@object:
+@child:
+
+
diff --git a/gst/Makefile.am b/gst/Makefile.am
index 644b780f3d..b609eb401d 100644
--- a/gst/Makefile.am
+++ b/gst/Makefile.am
@@ -100,6 +100,7 @@ libgstreamer_@GST_MAJORMINOR@_la_SOURCES = \
gstinterface.c \
gstmemchunk.c \
gstpad.c \
+ gstchildproxy.c \
gstpipeline.c \
gstplugin.c \
gstpluginfeature.c \
@@ -174,6 +175,7 @@ gst_headers = \
gstmacros.h \
gstmemchunk.h \
gstpad.h \
+ gstchildproxy.h \
gstpipeline.h \
gstplugin.h \
gstpluginfeature.h \
diff --git a/gst/gst.h b/gst/gst.h
index 2f25b2eb68..126448fece 100644
--- a/gst/gst.h
+++ b/gst/gst.h
@@ -45,6 +45,7 @@
#include <gst/gstmarshal.h>
#include <gst/gstobject.h>
#include <gst/gstpad.h>
+#include <gst/gstchildproxy.h>
#include <gst/gstpipeline.h>
#include <gst/gstplugin.h>
#include <gst/gstscheduler.h>
diff --git a/gst/gstbin.c b/gst/gstbin.c
index 438ccef5da..579052966c 100644
--- a/gst/gstbin.c
+++ b/gst/gstbin.c
@@ -33,6 +33,7 @@
#include "gstscheduler.h"
#include "gstindex.h"
#include "gstutils.h"
+#include "gstchildproxy.h"
GST_DEBUG_CATEGORY_STATIC (bin_debug);
#define GST_CAT_DEFAULT bin_debug
@@ -97,6 +98,7 @@ enum
static void gst_bin_base_init (gpointer g_class);
static void gst_bin_class_init (GstBinClass * klass);
static void gst_bin_init (GstBin * bin);
+static void gst_bin_child_proxy_init (gpointer g_iface, gpointer iface_data);
static GstElementClass *parent_class = NULL;
static guint gst_bin_signals[LAST_SIGNAL] = { 0 };
@@ -123,9 +125,18 @@ gst_bin_get_type (void)
NULL
};
+ static const GInterfaceInfo child_proxy_info = {
+ gst_bin_child_proxy_init,
+ NULL,
+ NULL
+ };
+
_gst_bin_type =
g_type_register_static (GST_TYPE_ELEMENT, "GstBin", &bin_info, 0);
+ g_type_add_interface_static (_gst_bin_type, GST_TYPE_CHILD_PROXY,
+ &child_proxy_info);
+
GST_DEBUG_CATEGORY_INIT (bin_debug, "bin", GST_DEBUG_BOLD,
"debugging info for the 'bin' container element");
}
@@ -213,6 +224,28 @@ gst_bin_init (GstBin * bin)
bin->children = NULL;
}
+static GstObject *
+gst_bin_child_proxy_get_child_by_index (GstChildProxy * child_proxy,
+ guint index)
+{
+ return g_list_nth_data (GST_BIN (child_proxy)->children, index);
+}
+
+guint
+gst_bin_child_proxy_get_children_count (GstChildProxy * child_proxy)
+{
+ return GST_BIN (child_proxy)->numchildren;
+}
+
+static void
+gst_bin_child_proxy_init (gpointer g_iface, gpointer iface_data)
+{
+ GstChildProxyInterface *iface = g_iface;
+
+ iface->get_children_count = gst_bin_child_proxy_get_children_count;
+ iface->get_child_by_index = gst_bin_child_proxy_get_child_by_index;
+}
+
/**
* gst_bin_new:
* @name: name of new bin
@@ -529,6 +562,7 @@ gst_bin_add (GstBin * bin, GstElement * element)
if (bclass->add_element) {
bclass->add_element (bin, element);
+ gst_child_proxy_child_added (GST_OBJECT (bin), GST_OBJECT (element));
} else {
GST_ELEMENT_ERROR (bin, CORE, FAILED, (NULL),
("cannot add element %s to bin %s",
@@ -620,6 +654,7 @@ gst_bin_remove (GstBin * bin, GstElement * element)
bclass = GST_BIN_GET_CLASS (bin);
if (bclass->remove_element) {
+ gst_child_proxy_child_removed (GST_OBJECT (bin), GST_OBJECT (element));
bclass->remove_element (bin, element);
} else {
g_warning ("cannot remove elements from bin %s\n", GST_ELEMENT_NAME (bin));
diff --git a/gst/gstchildproxy.c b/gst/gstchildproxy.c
new file mode 100644
index 0000000000..1e97194e53
--- /dev/null
+++ b/gst/gstchildproxy.c
@@ -0,0 +1,407 @@
+/* GStreamer
+ * Copyright (C) 2005 Stefan Kost <ensonic@users.sf.net>
+ *
+ * gstchildproxy.c: interface for multi child elements
+ *
+ * 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_private.h"
+
+#include "gstchildproxy.h"
+#include <gobject/gvaluecollector.h>
+
+/* signals */
+enum
+{
+ CHILD_ADDED,
+ CHILD_REMOVED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+/**
+ * gst_child_proxy_get_child_by_name:
+ * @parent: the parent object to get the child from
+ * @name: the childs name
+ *
+ * Looks up a child element by the given name.
+ *
+ * Implementors can use #GstObject together with gst_object_get_name()
+ *
+ * Returns: the child object or %NULL if not found
+ */
+GstObject *
+gst_child_proxy_get_child_by_name (GstChildProxy * parent, const gchar * name)
+{
+ guint count, i;
+ GstObject *object;
+ const gchar *object_name;
+
+ g_return_val_if_fail (GST_IS_CHILD_PROXY (parent), NULL);
+ g_return_val_if_fail (name != NULL, NULL);
+
+ count = gst_child_proxy_get_children_count (parent);
+ for (i = 0; i < count; i++) {
+ object = gst_child_proxy_get_child_by_index (parent, i);
+ object_name = gst_object_get_name (object);
+ if (object_name == NULL) {
+ g_warning ("child %u of parent %s has no name", i,
+ GST_OBJECT_NAME (parent));
+ continue;
+ }
+ if (g_str_equal (object_name, name))
+ return object;
+ }
+ return NULL;
+}
+
+/**
+ * gst_child_proxy_get_child_by_index:
+ * @parent: the parent object to get the child from
+ * @index: the childs position in the child list
+ *
+ * Fetches a child by its number.
+ *
+ * Returns: the child object or %NULL if not found (index too high)
+ */
+GstObject *
+gst_child_proxy_get_child_by_index (GstChildProxy * parent, guint index)
+{
+ g_return_val_if_fail (GST_IS_CHILD_PROXY (parent), NULL);
+
+ return (GST_CHILD_PROXY_GET_INTERFACE (parent)->get_child_by_index (parent,
+ index));
+}
+
+/**
+ * gst_child_proxy_get_children_count:
+ * @parent: the parent object
+ *
+ * Gets the number of child objects this parent contains.
+ *
+ * Returns: the number of child objects
+ */
+guint
+gst_child_proxy_get_children_count (GstChildProxy * parent)
+{
+ g_return_val_if_fail (GST_IS_CHILD_PROXY (parent), 0);
+
+ return (GST_CHILD_PROXY_GET_INTERFACE (parent)->get_children_count (parent));
+}
+
+/**
+ * gst_child_proxy_lookup:
+ * @object: object to lookup the property in
+ * @name: name of the property to look up
+ * @target: pointer to a #GstObject that takes the real object to set property on
+ * @pspec: pointer to take the #GParamSpec describing the property
+ *
+ * Looks up which object and #GParamSpec would be effected by the given @name.
+ *
+ * Returns: TRUE if @target and @pspec could be found. FALSE otherwise. In that
+ * case the values for @pspec and @target are not modified
+ */
+gboolean
+gst_child_proxy_lookup (GstObject * object, const gchar * name,
+ GstObject ** target, GParamSpec ** pspec)
+{
+ gboolean res = FALSE;
+ gchar **names, **current;
+
+ g_return_val_if_fail (GST_IS_OBJECT (object), FALSE);
+ g_return_val_if_fail (name != NULL, FALSE);
+
+ current = names = g_strsplit (name, "::", -1);
+ while (current[1]) {
+ if (!GST_IS_CHILD_PROXY (object)) {
+ GST_INFO
+ ("object %s is not a parent, so you cannot request a child by name %s",
+ GST_OBJECT_NAME (object), current[0]);
+ break;
+ }
+ object =
+ gst_child_proxy_get_child_by_name (GST_CHILD_PROXY (object),
+ current[0]);
+ if (!object) {
+ GST_INFO ("no such object %s", current[0]);
+ break;
+ }
+ current++;
+ };
+ if (current[1] == NULL) {
+ GParamSpec *spec =
+ g_object_class_find_property (G_OBJECT_GET_CLASS (object), current[0]);
+ if (spec == NULL) {
+ GST_INFO ("no param spec named %s", current[0]);
+ } else {
+ if (pspec)
+ *pspec = spec;
+ if (target)
+ *target = object;
+ res = TRUE;
+ }
+ }
+ g_strfreev (names);
+ return res;
+}
+
+/**
+ * gst_child_proxy_get_property:
+ * @object: object to query
+ * @name: name of the property
+ * @value: an uninitialized GValue that should take the result.
+ *
+ * You are responsible for for freeing it by calling g_value_unset()
+ * Gets a single property using the GstChildProxy mechanism.
+ */
+void
+gst_child_proxy_get_property (GstObject * object, const gchar * name,
+ GValue * value)
+{
+ GParamSpec *pspec;
+ GstObject *target;
+
+ g_return_if_fail (GST_IS_OBJECT (object));
+ g_return_if_fail (name != NULL);
+ g_return_if_fail (!G_IS_VALUE (value));
+
+ if (!gst_child_proxy_lookup (object, name, &target, &pspec)) {
+ g_warning ("cannot get property %s from object %s", name,
+ GST_OBJECT_NAME (object));
+ return;
+ }
+ g_object_get_property (G_OBJECT (target), pspec->name, value);
+}
+
+/**
+ * gst_child_proxy_get_valist:
+ * @object: the object to query
+ * @first_property_name: name of the first property to get
+ * @var_args: return location for the first property, followed optionally by more name/return location pairs, followed by NULL
+ *
+ * Gets properties of the parent object and its children.
+ */
+void
+gst_child_proxy_get_valist (GstObject * object,
+ const gchar * first_property_name, va_list var_args)
+{
+ const gchar *name;
+ gchar *error = NULL;
+ GValue value = { 0, };
+
+ g_return_if_fail (G_IS_OBJECT (object));
+
+ g_object_ref (object);
+
+ name = first_property_name;
+
+ /* iterate over pairs */
+ while (name) {
+ gst_child_proxy_get_property (object, name, &value);
+ G_VALUE_LCOPY (&value, var_args, 0, &error);
+ if (error) {
+ g_warning ("error copying value: %s", error);
+ return;
+ }
+ g_value_unset (&value);
+ name = va_arg (var_args, gchar *);
+ }
+
+ g_object_unref (object);
+}
+
+/**
+ * gst_child_proxy_get:
+ * @object: the parent object
+ * @first_property_name: name of the first property to get
+ * @...: return location for the first property, followed optionally by more name/return location pairs, followed by NULL
+ *
+ * Gets properties of the parent object and its children.
+ */
+void
+gst_child_proxy_get (GstObject * object, const gchar * first_property_name, ...)
+{
+ va_list var_args;
+
+ g_return_if_fail (GST_IS_OBJECT (object));
+
+ va_start (var_args, first_property_name);
+ gst_child_proxy_get_valist (object, first_property_name, var_args);
+ va_end (var_args);
+}
+
+void
+gst_child_proxy_set_property (GstObject * object, const gchar * name,
+ const GValue * value)
+{
+ GParamSpec *pspec;
+ GstObject *target;
+
+ g_return_if_fail (GST_IS_OBJECT (object));
+ g_return_if_fail (name != NULL);
+ g_return_if_fail (!G_IS_VALUE (value));
+
+ if (!gst_child_proxy_lookup (object, name, &target, &pspec)) {
+ g_warning ("cannot set property %s on object %s", name,
+ GST_OBJECT_NAME (object));
+ return;
+ }
+ g_object_set_property (G_OBJECT (target), pspec->name, value);
+}
+
+/**
+ * gst_child_proxy_set_valist:
+ * @object: the parent object
+ * @first_property_name: name of the first property to set
+ * @var_args: value for the first property, followed optionally by more name/value pairs, followed by NULL
+ *
+ * Sets properties of the parent object and its children.
+ */
+void
+gst_child_proxy_set_valist (GstObject * object,
+ const gchar * first_property_name, va_list var_args)
+{
+ const gchar *name;
+ gchar *error = NULL;
+ GValue value = { 0, };
+
+ g_return_if_fail (G_IS_OBJECT (object));
+
+ g_object_ref (object);
+
+ name = first_property_name;
+
+ /* iterate over pairs */
+ while (name) {
+ GParamSpec *pspec;
+ GstObject *target;
+
+ if (!gst_child_proxy_lookup (object, name, &target, &pspec)) {
+ g_warning ("no such property %s in object %s", name,
+ GST_OBJECT_NAME (object));
+ g_object_unref (object);
+ }
+ g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
+ G_VALUE_COLLECT (&value, var_args, G_VALUE_NOCOPY_CONTENTS, &error);
+ if (error) {
+ g_warning ("error copying value: %s", error);
+ g_object_unref (object);
+ return;
+ }
+ g_object_set_property (G_OBJECT (target), pspec->name, &value);
+ g_value_unset (&value);
+ name = va_arg (var_args, gchar *);
+ }
+
+ g_object_unref (object);
+}
+
+/**
+ * gst_child_proxy_set:
+ * @object: the parent object
+ * @first_property_name: name of the first property to set
+ * @...: value for the first property, followed optionally by more name/value pairs, followed by NULL
+ *
+ * Sets properties of the parent object and its children.
+ */
+void
+gst_child_proxy_set (GstObject * object, const gchar * first_property_name, ...)
+{
+ va_list var_args;
+
+ g_return_if_fail (GST_IS_OBJECT (object));
+
+ va_start (var_args, first_property_name);
+ gst_child_proxy_set_valist (object, first_property_name, var_args);
+ va_end (var_args);
+}
+
+/**
+ * gst_child_proxy_child_added:
+ * @object: the parent object
+ * @child: the newly added child
+ *
+ * Emits the "child-added" signal.
+ */
+void
+gst_child_proxy_child_added (GstObject * object, GstObject * child)
+{
+ g_signal_emit (G_OBJECT (object), signals[CHILD_ADDED], 0, child);
+}
+
+/**
+ * gst_child_proxy_child_removed:
+ * @object: the parent object
+ * @child: the newly added child
+ *
+ * Emits the "child-removed" signal.
+ */
+void
+gst_child_proxy_child_removed (GstObject * object, GstObject * child)
+{
+ g_signal_emit (G_OBJECT (object), signals[CHILD_REMOVED], 0, child);
+}
+
+/* gobject methods */
+
+static void
+gst_child_proxy_base_init (gpointer g_class)
+{
+ static gboolean initialized = FALSE;
+
+ if (!initialized) {
+ /* create interface signals and properties here. */
+ signals[CHILD_ADDED] =
+ g_signal_new ("child-added", G_TYPE_FROM_CLASS (g_class),
+ G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstChildProxyInterface,
+ child_added), NULL, NULL, gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
+ G_TYPE_OBJECT);
+
+ signals[CHILD_REMOVED] =
+ g_signal_new ("child-removed", G_TYPE_FROM_CLASS (g_class),
+ G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstChildProxyInterface,
+ child_removed), NULL, NULL, gst_marshal_VOID__OBJECT, G_TYPE_NONE,
+ 1, G_TYPE_OBJECT);
+
+ initialized = TRUE;
+ }
+}
+
+GType
+gst_child_proxy_get_type (void)
+{
+ static GType type = 0;
+
+ if (type == 0) {
+ static const GTypeInfo info = {
+ sizeof (GstChildProxyInterface),
+ gst_child_proxy_base_init, /* base_init */
+ NULL, /* base_finalize */
+ NULL, /* class_init */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ 0,
+ 0, /* n_preallocs */
+ NULL /* instance_init */
+ };
+ type = g_type_register_static (G_TYPE_INTERFACE, "GstChildProxy", &info, 0);
+
+ g_type_interface_add_prerequisite (type, GST_TYPE_OBJECT);
+ }
+ return type;
+}
diff --git a/gst/gstchildproxy.h b/gst/gstchildproxy.h
new file mode 100644
index 0000000000..5f5580cb78
--- /dev/null
+++ b/gst/gstchildproxy.h
@@ -0,0 +1,76 @@
+/* GStreamer
+ * Copyright (C) 2005 Stefan Kost <ensonic@users.sf.net>
+ *
+ * gstchildproxy.h: interface header for multi child elements
+ *
+ * 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.
+ */
+
+#ifndef __GST_CHILD_PROXY_H__
+#define __GST_CHILD_PROXY_H__
+
+#include <glib-object.h>
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+
+#define GST_TYPE_CHILD_PROXY (gst_child_proxy_get_type ())
+#define GST_CHILD_PROXY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_CHILD_PROXY, GstChildProxy))
+#define GST_IS_CHILD_PROXY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_CHILD_PROXY))
+#define GST_CHILD_PROXY_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GST_TYPE_CHILD_PROXY, GstChildProxyInterface))
+
+typedef struct _GstChildProxy GstChildProxy; /* dummy object */
+typedef struct _GstChildProxyInterface GstChildProxyInterface;
+
+struct _GstChildProxyInterface
+{
+ GTypeInterface parent;
+
+ /* methods */
+ GstObject *(*get_child_by_index) (GstChildProxy * parent, guint index);
+ guint (*get_children_count) (GstChildProxy * parent);
+ /* signals */
+ void (*child_added) (GstChildProxy * parent, GstObject * child);
+ void (*child_removed) (GstChildProxy * parent, GstObject * child);
+
+ gpointer _gst_reserved[GST_PADDING];
+};
+
+GType gst_child_proxy_get_type (void);
+
+GstObject *gst_child_proxy_get_child_by_name (GstChildProxy * parent, const gchar * name);
+GstObject *gst_child_proxy_get_child_by_index (GstChildProxy * parent, guint index);
+guint gst_child_proxy_get_children_count (GstChildProxy * parent);
+
+gboolean gst_child_proxy_lookup (GstObject *object, const gchar *name,
+ GstObject **target, GParamSpec **pspec);
+void gst_child_proxy_get_property (GstObject * object, const gchar *name, GValue *value);
+void gst_child_proxy_get_valist (GstObject * object,
+ const gchar * first_property_name, va_list var_args);
+void gst_child_proxy_get (GstObject * object, const gchar * first_property_name,
+ ...);
+void gst_child_proxy_set_property (GstObject * object, const gchar *name, const GValue *value);
+void gst_child_proxy_set_valist (GstObject* object,
+ const gchar * first_property_name, va_list var_args);
+void gst_child_proxy_set (GstObject * object, const gchar * first_property_name,
+ ...);
+void gst_child_proxy_child_added (GstObject * object, GstObject * child);
+void gst_child_proxy_child_removed (GstObject * object, GstObject * child);
+
+G_END_DECLS
+
+#endif /* __GST_CHILD_PROXY_H__ */
diff --git a/gst/parse/grammar.y b/gst/parse/grammar.y
index 05b8033190..c425d2de8f 100644
--- a/gst/parse/grammar.y
+++ b/gst/parse/grammar.y
@@ -14,6 +14,7 @@
#include "../gsterror.h"
#include "../gsturi.h"
#include "../gstvalue.h"
+#include "../gstchildproxy.h"
#include "types.h"
/* All error messages in this file are user-visible and need to be translated.
@@ -236,6 +237,7 @@ gst_parse_element_set (gchar *value, GstElement *element, graph_t *graph)
gchar *pos = value;
GValue v = { 0, };
GValue v2 = { 0, };
+ GstObject *target;
/* parse the string, so the property name is null-terminated an pos points
to the beginning of the value */
while (!g_ascii_isspace (*pos) && (*pos != '=')) pos++;
@@ -253,11 +255,11 @@ gst_parse_element_set (gchar *value, GstElement *element, graph_t *graph)
pos[strlen (pos) - 1] = '\0';
}
gst_parse_unescape (pos);
- if ((pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (element), value))) {
+ if (gst_child_proxy_lookup (GST_OBJECT (element), value, &target, &pspec)) {
g_value_init (&v, G_PARAM_SPEC_VALUE_TYPE(pspec));
if (!gst_value_deserialize (&v, pos))
goto error;
- g_object_set_property (G_OBJECT (element), value, &v);
+ g_object_set_property (G_OBJECT (target), pspec->name, &v);
} else {
SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_NO_SUCH_PROPERTY, _("no property \"%s\" in element \"%s\""), value, GST_ELEMENT_NAME (element));
}
diff --git a/tests/old/testsuite/Makefile.am b/tests/old/testsuite/Makefile.am
index 54507be990..df8249a062 100644
--- a/tests/old/testsuite/Makefile.am
+++ b/tests/old/testsuite/Makefile.am
@@ -14,7 +14,7 @@ GST_DEBUG_DIRS = debug
endif
SUBDIRS = \
- bins bytestream caps cleanup clock \
+ bins bytestream caps childproxy cleanup clock \
$(GST_DEBUG_DIRS) \
dlopen dynparams \
elements ghostpads indexers negotiation pad \
@@ -22,7 +22,7 @@ SUBDIRS = \
plugin refcounting schedulers states tags threads
DIST_SUBDIRS = \
- bins bytestream caps cleanup clock \
+ bins bytestream caps childproxy cleanup clock \
debug \
dlopen dynparams \
elements ghostpads indexers negotiation pad \
diff --git a/tests/old/testsuite/childproxy/Makefile.am b/tests/old/testsuite/childproxy/Makefile.am
new file mode 100644
index 0000000000..f2324c8a9f
--- /dev/null
+++ b/tests/old/testsuite/childproxy/Makefile.am
@@ -0,0 +1,6 @@
+include ../Rules
+
+tests_pass = childproxy
+tests_fail =
+tests_ignore =
+
diff --git a/tests/old/testsuite/childproxy/childproxy.c b/tests/old/testsuite/childproxy/childproxy.c
new file mode 100644
index 0000000000..07f5f100fc
--- /dev/null
+++ b/tests/old/testsuite/childproxy/childproxy.c
@@ -0,0 +1,114 @@
+/* GStreamer
+ * Copyright (C) 2005 Stefan Kost <ensonic@users.sf.net>
+ *
+ * childproxy.c: test for GstChildProxy iface
+ *
+ * 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>
+
+gboolean added = FALSE;
+gboolean removed = FALSE;
+
+static void
+my_child_added (GstChildProxy * parent, GstObject * child, gpointer user_data)
+{
+ if (child == GST_OBJECT (user_data)) {
+ added = TRUE;
+ }
+}
+
+static void
+my_child_removed (GstChildProxy * parent, GstObject * child, gpointer user_data)
+{
+ if (child == GST_OBJECT (user_data)) {
+ removed = TRUE;
+ }
+}
+
+int
+main (int argc, char *argv[])
+{
+ GstBin *bin;
+ GstElement *child1, *child2;
+ gboolean state;
+
+ gst_init (&argc, &argv);
+
+ if ((bin = GST_BIN (gst_bin_new ("bin"))) == NULL) {
+ g_print ("Could not create a bin element!\n");
+ return 1;
+ }
+
+ if ((child1 = gst_element_factory_make ("identity", "filter")) == NULL) {
+ g_print ("Could not create a identity element!\n");
+ return 1;
+ }
+
+ g_signal_connect (G_OBJECT (bin), "child-added", G_CALLBACK (my_child_added),
+ child1);
+ g_signal_connect (G_OBJECT (bin), "child-removed",
+ G_CALLBACK (my_child_removed), child1);
+
+ gst_bin_add (bin, child1);
+
+ if (!added) {
+ g_print ("ChildProxy::child-added has not been caught!\n");
+ return 1;
+ }
+
+ if (gst_child_proxy_get_children_count (GST_CHILD_PROXY (bin)) != 1) {
+ g_print ("ChildProxy should manage exactly one child now!\n");
+ return 1;
+ }
+
+ child2 =
+ GST_ELEMENT (gst_child_proxy_get_child_by_index (GST_CHILD_PROXY (bin),
+ 0));
+ if (child2 != child1) {
+ g_print ("ChildProxy's first child is not what we have added!\n");
+ return 1;
+ }
+
+ gst_child_proxy_set (GST_OBJECT (bin), "filter::silent", TRUE, NULL);
+
+ g_object_get (G_OBJECT (child1), "silent", &state, NULL);
+ if (!state) {
+ g_print ("ChildProxy's child property access failed !\n");
+ return 1;
+ }
+
+ gst_child_proxy_set (GST_OBJECT (bin), "filter::silent", FALSE, NULL);
+
+ g_object_get (G_OBJECT (child1), "silent", &state, NULL);
+ if (state) {
+ g_print ("ChildProxy's child property access failed !\n");
+ return 1;
+ }
+
+ gst_bin_remove (bin, child1);
+
+ if (!removed) {
+ g_print ("ChildProxy::child-added has not been caught!\n");
+ return 1;
+ }
+
+ g_object_unref (G_OBJECT (bin));
+
+ /* success */
+ return 0;
+}
diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am
index 54507be990..df8249a062 100644
--- a/testsuite/Makefile.am
+++ b/testsuite/Makefile.am
@@ -14,7 +14,7 @@ GST_DEBUG_DIRS = debug
endif
SUBDIRS = \
- bins bytestream caps cleanup clock \
+ bins bytestream caps childproxy cleanup clock \
$(GST_DEBUG_DIRS) \
dlopen dynparams \
elements ghostpads indexers negotiation pad \
@@ -22,7 +22,7 @@ SUBDIRS = \
plugin refcounting schedulers states tags threads
DIST_SUBDIRS = \
- bins bytestream caps cleanup clock \
+ bins bytestream caps childproxy cleanup clock \
debug \
dlopen dynparams \
elements ghostpads indexers negotiation pad \
diff --git a/testsuite/childproxy/Makefile.am b/testsuite/childproxy/Makefile.am
new file mode 100644
index 0000000000..f2324c8a9f
--- /dev/null
+++ b/testsuite/childproxy/Makefile.am
@@ -0,0 +1,6 @@
+include ../Rules
+
+tests_pass = childproxy
+tests_fail =
+tests_ignore =
+
diff --git a/testsuite/childproxy/childproxy.c b/testsuite/childproxy/childproxy.c
new file mode 100644
index 0000000000..07f5f100fc
--- /dev/null
+++ b/testsuite/childproxy/childproxy.c
@@ -0,0 +1,114 @@
+/* GStreamer
+ * Copyright (C) 2005 Stefan Kost <ensonic@users.sf.net>
+ *
+ * childproxy.c: test for GstChildProxy iface
+ *
+ * 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>
+
+gboolean added = FALSE;
+gboolean removed = FALSE;
+
+static void
+my_child_added (GstChildProxy * parent, GstObject * child, gpointer user_data)
+{
+ if (child == GST_OBJECT (user_data)) {
+ added = TRUE;
+ }
+}
+
+static void
+my_child_removed (GstChildProxy * parent, GstObject * child, gpointer user_data)
+{
+ if (child == GST_OBJECT (user_data)) {
+ removed = TRUE;
+ }
+}
+
+int
+main (int argc, char *argv[])
+{
+ GstBin *bin;
+ GstElement *child1, *child2;
+ gboolean state;
+
+ gst_init (&argc, &argv);
+
+ if ((bin = GST_BIN (gst_bin_new ("bin"))) == NULL) {
+ g_print ("Could not create a bin element!\n");
+ return 1;
+ }
+
+ if ((child1 = gst_element_factory_make ("identity", "filter")) == NULL) {
+ g_print ("Could not create a identity element!\n");
+ return 1;
+ }
+
+ g_signal_connect (G_OBJECT (bin), "child-added", G_CALLBACK (my_child_added),
+ child1);
+ g_signal_connect (G_OBJECT (bin), "child-removed",
+ G_CALLBACK (my_child_removed), child1);
+
+ gst_bin_add (bin, child1);
+
+ if (!added) {
+ g_print ("ChildProxy::child-added has not been caught!\n");
+ return 1;
+ }
+
+ if (gst_child_proxy_get_children_count (GST_CHILD_PROXY (bin)) != 1) {
+ g_print ("ChildProxy should manage exactly one child now!\n");
+ return 1;
+ }
+
+ child2 =
+ GST_ELEMENT (gst_child_proxy_get_child_by_index (GST_CHILD_PROXY (bin),
+ 0));
+ if (child2 != child1) {
+ g_print ("ChildProxy's first child is not what we have added!\n");
+ return 1;
+ }
+
+ gst_child_proxy_set (GST_OBJECT (bin), "filter::silent", TRUE, NULL);
+
+ g_object_get (G_OBJECT (child1), "silent", &state, NULL);
+ if (!state) {
+ g_print ("ChildProxy's child property access failed !\n");
+ return 1;
+ }
+
+ gst_child_proxy_set (GST_OBJECT (bin), "filter::silent", FALSE, NULL);
+
+ g_object_get (G_OBJECT (child1), "silent", &state, NULL);
+ if (state) {
+ g_print ("ChildProxy's child property access failed !\n");
+ return 1;
+ }
+
+ gst_bin_remove (bin, child1);
+
+ if (!removed) {
+ g_print ("ChildProxy::child-added has not been caught!\n");
+ return 1;
+ }
+
+ g_object_unref (G_OBJECT (bin));
+
+ /* success */
+ return 0;
+}