ported gstchildproxy over from 0.8 ported gst-inspect fixes and enhancements over...
authorStefan Kost <ensonic@users.sourceforge.net>
Mon, 22 Aug 2005 21:03:33 +0000 (21:03 +0000)
committerStefan Kost <ensonic@users.sourceforge.net>
Mon, 22 Aug 2005 21:03:33 +0000 (21:03 +0000)
Original commit message from CVS:
* docs/gst/gstreamer-docs.sgml:
* docs/gst/gstreamer-sections.txt:
* gst/Makefile.am:
* gst/gstbin.c: (gst_bin_get_type),
(gst_bin_child_proxy_get_child_by_index),
(gst_bin_child_proxy_get_children_count),
(gst_bin_child_proxy_init):
* gst/gstchildproxy.c: (gst_child_proxy_get_child_by_name),
(gst_child_proxy_get_child_by_index),
(gst_child_proxy_get_children_count), (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),
(gst_child_proxy_base_init), (gst_child_proxy_get_type):
* gst/gstchildproxy.h:
* gst/parse/grammar.y:
* tools/gst-inspect.c: (print_interfaces),
(print_element_properties_info), (print_element_info):
ported gstchildproxy over from 0.8
ported gst-inspect fixes and enhancements over from 0.8

ChangeLog
docs/gst/gstreamer-docs.sgml
docs/gst/gstreamer-sections.txt
gst/Makefile.am
gst/gstbin.c
gst/gstchildproxy.c [new file with mode: 0644]
gst/gstchildproxy.h [new file with mode: 0644]
gst/parse/grammar.y
tools/gst-inspect.c

index e2e8c32..1494253 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,27 @@
+2005-08-23  Stefan Kost  <ensonic@users.sf.net>
+
+       * docs/gst/gstreamer-docs.sgml:
+       * docs/gst/gstreamer-sections.txt:
+       * gst/Makefile.am:
+       * gst/gstbin.c: (gst_bin_get_type),
+       (gst_bin_child_proxy_get_child_by_index),
+       (gst_bin_child_proxy_get_children_count),
+       (gst_bin_child_proxy_init):
+       * gst/gstchildproxy.c: (gst_child_proxy_get_child_by_name),
+       (gst_child_proxy_get_child_by_index),
+       (gst_child_proxy_get_children_count), (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),
+       (gst_child_proxy_base_init), (gst_child_proxy_get_type):
+       * gst/gstchildproxy.h:
+       * gst/parse/grammar.y:
+       * tools/gst-inspect.c: (print_interfaces),
+       (print_element_properties_info), (print_element_info):
+         ported gstchildproxy over from 0.8
+         ported gst-inspect fixes and enhancements over from 0.8
+
 2005-08-22  Wim Taymans  <wim@fluendo.com>
 
        * gst/base/gstbasetransform.c: (gst_base_transform_transform_caps),
index 140bfbe..f42db7a 100644 (file)
@@ -7,6 +7,7 @@
 <!ENTITY GstBin SYSTEM "xml/gstbin.xml">
 <!ENTITY GstBuffer SYSTEM "xml/gstbuffer.xml">
 <!ENTITY GstCaps SYSTEM "xml/gstcaps.xml">
+<!ENTITY GstChildProxy SYSTEM "xml/gstchildproxy.xml">
 <!ENTITY GstClock SYSTEM "xml/gstclock.xml">
 <!--
 <!ENTITY GstCompat SYSTEM "xml/gstcompat.xml">
     &GstBin;
     &GstBuffer;
     &GstCaps;
+    &GstChildProxy;
     &GstClock;
     &GstConfig;
     &GstElement;
   <chapter id="gstreamer-base">
     <title>GStreamer Base Classes</title>
     <para>
-      These base classes are provided to be extended by elements.
+      libgstbase-&GST_MAJORMINOR;.so provides some base classes to be extended
+      by elements.
     </para>
 
     &GstAdapter;
index 5c4f000..a5be2f6 100644 (file)
@@ -177,6 +177,32 @@ gst_caps_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>gstclock</FILE>
 <TITLE>GstClock</TITLE>
 GstClock
index e4630d5..d17de8c 100644 (file)
@@ -84,6 +84,7 @@ libgstreamer_@GST_MAJORMINOR@_la_SOURCES = \
        gstbuffer.c             \
        gstbus.c                \
        gstcaps.c               \
+       gstchildproxy.c         \
        gstclock.c              \
        gstelement.c            \
        gstelementfactory.c     \
@@ -157,6 +158,7 @@ gst_headers =                       \
        gstbuffer.h             \
        gstbus.h                \
        gstcaps.h               \
+       gstchildproxy.h         \
        gstclock.h              \
        gstcompat.h             \
        gstelement.h            \
index 3d6fe2c..7a5bc86 100644 (file)
@@ -34,6 +34,7 @@
 
 #include "gstindex.h"
 #include "gstutils.h"
+#include "gstchildproxy.h"
 
 GST_DEBUG_CATEGORY_STATIC (bin_debug);
 #define GST_CAT_DEFAULT bin_debug
@@ -95,6 +96,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 };
@@ -120,10 +122,18 @@ gst_bin_get_type (void)
       (GInstanceInitFunc) gst_bin_init,
       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");
   }
@@ -138,6 +148,28 @@ gst_bin_base_init (gpointer g_class)
   gst_element_class_set_details (gstelement_class, &gst_bin_details);
 }
 
+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;
+}
+
 static void
 gst_bin_class_init (GstBinClass * klass)
 {
diff --git a/gst/gstchildproxy.c b/gst/gstchildproxy.c
new file mode 100644 (file)
index 0000000..96058cb
--- /dev/null
@@ -0,0 +1,432 @@
+/* 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.
+ */
+/**
+ * SECTION:gstchildproxy
+ * @short_description: Interface for multi child elements.
+ * @see_also: #GstBin
+ *
+ * This interface abstracts handling of property sets for child elements.
+ * Imagine elements such as mixers or polyphonic generators. They all have
+ * multiple #GstPads or some kind of voice objects. The element acts as a parent
+ * for those child objects. Each child has the same properties.
+ *
+ * By implementing this interface the child properties can be accessed from the
+ * parent element by using gst_child_proxy_get() and gst_child_proxy_set().
+ *
+ * Property names are written as "child-name::property-name". The whole naming
+ * scheme is recursive. Thus "child1::child2::property" is valid too, if
+ * "child1" also implements the #GstChildProxy interface.
+ */
+
+#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. 
+ *
+ * Gets a single property using the GstChildProxy mechanism.
+ * You are responsible for for freeing it by calling g_value_unset()
+ */
+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);
+}
+
+/**
+ * gst_child_proxy_set_property:
+ * @object: the parent object
+ * @name: name of the property to set
+ * @value: new #GValue for the property
+ *
+ * Sets a single property using the GstChildProxy mechanism.
+ */
+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 (file)
index 0000000..5f5580c
--- /dev/null
@@ -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__ */
index 2809a6f..e6bf0e0 100644 (file)
@@ -15,6 +15,7 @@
 #include "../gsturi.h"
 #include "../gstutils.h"
 #include "../gstvalue.h"
+#include "../gstchildproxy.h"
 #include "types.h"
 
 /* All error messages in this file are user-visible and need to be translated.
@@ -237,6 +238,7 @@ gst_parse_element_set (gchar *value, GstElement *element, graph_t *graph)
   gchar *pos = value;
   GValue v = { 0, }; 
   GValue v2 = { 0, };
+  GstObject *target;
   GType value_type;
 
   /* parse the string, so the property name is null-terminated an pos points
@@ -255,16 +257,16 @@ gst_parse_element_set (gchar *value, GstElement *element, graph_t *graph)
     pos++;
     pos[strlen (pos) - 1] = '\0';
   }
-  gst_parse_unescape (pos); 
-  pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (element), value);
-  if (pspec) {
-      value_type = G_PARAM_SPEC_VALUE_TYPE (pspec);
-      GST_LOG ("parsing property %s as a %s", pspec->name,
-        g_type_name (value_type));
+  gst_parse_unescape (pos);
+
+  if (gst_child_proxy_lookup (GST_OBJECT (element), value, &target, &pspec)) { 
+    value_type = G_PARAM_SPEC_VALUE_TYPE (pspec); 
+    GST_LOG ("parsing property %s as a %s", pspec->name,
+      g_type_name (value_type));
     g_value_init (&v, value_type);
     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)); 
   }
index 5741e92..83f9a6a 100644 (file)
@@ -239,13 +239,31 @@ print_hierarchy (GType type, gint level, gint * maxlevel)
 }
 
 static void
+print_interfaces (GType type)
+{
+  guint n_ifaces;
+  GType *iface, *ifaces = g_type_interfaces (type, &n_ifaces);
+
+  if (ifaces) {
+    if (n_ifaces) {
+      g_print ("Implemented Interfaces:\n");
+      iface = ifaces;
+      while (*iface) {
+        g_print ("  %s\n", g_type_name (*iface));
+        iface++;
+      }
+      g_print ("\n");
+      g_free (ifaces);
+    }
+  }
+}
+
+static void
 print_element_properties_info (GstElement * element)
 {
   GParamSpec **property_specs;
-  guint num_properties;
-  gint i;
+  guint num_properties, i;
   gboolean readable;
-  const char *string_val;
 
   property_specs = g_object_class_list_properties
       (G_OBJECT_GET_CLASS (element), &num_properties);
@@ -269,29 +287,41 @@ print_element_properties_info (GstElement * element)
 
     switch (G_VALUE_TYPE (&value)) {
       case G_TYPE_STRING:
-        string_val = g_value_get_string (&value);
+      {
+        GParamSpecString *pstring = G_PARAM_SPEC_STRING (param);
+
         n_print ("%-23.23s String. ", "");
+        g_print ("Default: \"%s\" ", pstring->default_value);
         if (readable) {
+          const char *string_val = g_value_get_string (&value);
+
           if (string_val == NULL)
-            g_print ("(Default \"\")");
+            g_print ("Current: \"\"");
           else
-            g_print ("(Default \"%s\")", g_value_get_string (&value));
+            g_print ("Current: \"%s\"", string_val);
         }
         break;
+      }
       case G_TYPE_BOOLEAN:
+      {
+        GParamSpecBoolean *pboolean = G_PARAM_SPEC_BOOLEAN (param);
+
         n_print ("%-23.23s Boolean. ", "");
+        g_print ("Default: %s ", (pboolean->default_value ? "true" : "false"));
         if (readable)
-          g_print ("(Default %s)",
+          g_print ("Current: %s",
               (g_value_get_boolean (&value) ? "true" : "false"));
         break;
+      }
       case G_TYPE_ULONG:
       {
         GParamSpecULong *pulong = G_PARAM_SPEC_ULONG (param);
 
         n_print ("%-23.23s Unsigned Long. ", "");
+        g_print ("Range: %lu - %lu Default: %lu ",
+            pulong->minimum, pulong->maximum, pulong->default_value);
         if (readable)
-          g_print ("Range: %lu - %lu (Default %lu)",
-              pulong->minimum, pulong->maximum, g_value_get_ulong (&value));
+          g_print ("Current: %lu", g_value_get_ulong (&value));
         break;
       }
       case G_TYPE_LONG:
@@ -299,9 +329,10 @@ print_element_properties_info (GstElement * element)
         GParamSpecLong *plong = G_PARAM_SPEC_LONG (param);
 
         n_print ("%-23.23s Long. ", "");
+        g_print ("Range: %ld - %ld Default: %ld ",
+            plong->minimum, plong->maximum, plong->default_value);
         if (readable)
-          g_print ("Range: %ld - %ld (Default %ld)",
-              plong->minimum, plong->maximum, g_value_get_long (&value));
+          g_print ("Current: %ld", g_value_get_long (&value));
         break;
       }
       case G_TYPE_UINT:
@@ -309,9 +340,10 @@ print_element_properties_info (GstElement * element)
         GParamSpecUInt *puint = G_PARAM_SPEC_UINT (param);
 
         n_print ("%-23.23s Unsigned Integer. ", "");
+        g_print ("Range: %u - %u Default: %u ",
+            puint->minimum, puint->maximum, puint->default_value);
         if (readable)
-          g_print ("Range: %u - %u (Default %u)",
-              puint->minimum, puint->maximum, g_value_get_uint (&value));
+          g_print ("Current: %u", g_value_get_uint (&value));
         break;
       }
       case G_TYPE_INT:
@@ -319,9 +351,10 @@ print_element_properties_info (GstElement * element)
         GParamSpecInt *pint = G_PARAM_SPEC_INT (param);
 
         n_print ("%-23.23s Integer. ", "");
+        g_print ("Range: %d - %d Default: %d ",
+            pint->minimum, pint->maximum, pint->default_value);
         if (readable)
-          g_print ("Range: %d - %d (Default %d)",
-              pint->minimum, pint->maximum, g_value_get_int (&value));
+          g_print ("Current: %d", g_value_get_int (&value));
         break;
       }
       case G_TYPE_UINT64:
@@ -329,10 +362,11 @@ print_element_properties_info (GstElement * element)
         GParamSpecUInt64 *puint64 = G_PARAM_SPEC_UINT64 (param);
 
         n_print ("%-23.23s Unsigned Integer64. ", "");
+        g_print ("Range: %" G_GUINT64_FORMAT " - %" G_GUINT64_FORMAT
+            " Default: %" G_GUINT64_FORMAT " ",
+            puint64->minimum, puint64->maximum, puint64->default_value);
         if (readable)
-          g_print ("Range: %" G_GUINT64_FORMAT " - %"
-              G_GUINT64_FORMAT " (Default %" G_GUINT64_FORMAT ")",
-              puint64->minimum, puint64->maximum, g_value_get_uint64 (&value));
+          g_print ("Current: %" G_GUINT64_FORMAT, g_value_get_uint64 (&value));
         break;
       }
       case G_TYPE_INT64:
@@ -340,30 +374,33 @@ print_element_properties_info (GstElement * element)
         GParamSpecInt64 *pint64 = G_PARAM_SPEC_INT64 (param);
 
         n_print ("%-23.23s Integer64. ", "");
+        g_print ("Range: %" G_GINT64_FORMAT " - %" G_GINT64_FORMAT
+            " Default: %" G_GINT64_FORMAT " ",
+            pint64->minimum, pint64->maximum, pint64->default_value);
         if (readable)
-          g_print ("Range: %" G_GINT64_FORMAT " - %" G_GINT64_FORMAT
-              " (Default %" G_GINT64_FORMAT ")", pint64->minimum,
-              pint64->maximum, g_value_get_int64 (&value));
+          g_print ("Current: %" G_GINT64_FORMAT, g_value_get_int64 (&value));
         break;
       }
       case G_TYPE_FLOAT:
       {
         GParamSpecFloat *pfloat = G_PARAM_SPEC_FLOAT (param);
 
-        n_print ("%-23.23s Float. Default: %-8.8s %15.7g\n", "", "",
-            g_value_get_float (&value));
-        n_print ("%-23.23s Range: %15.7g - %15.7g", "",
-            pfloat->minimum, pfloat->maximum);
+        n_print ("%-23.23s Float. ", "");
+        g_print ("Range: %15.7g - %15.7g Default: %15.7g ",
+            pfloat->minimum, pfloat->maximum, pfloat->default_value);
+        if (readable)
+          g_print ("Current: %15.7g\n", g_value_get_float (&value));
         break;
       }
       case G_TYPE_DOUBLE:
       {
         GParamSpecDouble *pdouble = G_PARAM_SPEC_DOUBLE (param);
 
-        n_print ("%-23.23s Double. Default: %-8.8s %15.7g\n", "", "",
-            g_value_get_double (&value));
-        n_print ("%-23.23s Range: %15.7g - %15.7g", "",
-            pdouble->minimum, pdouble->maximum);
+        n_print ("%-23.23s Double. ", "");
+        g_print ("Range: %15.7g - %15.7g Default: %15.7g ",
+            pdouble->minimum, pdouble->maximum, pdouble->default_value);
+        if (readable)
+          g_print ("Current: %15.7g\n", g_value_get_double (&value));
         break;
       }
       default:
@@ -392,7 +429,7 @@ print_element_properties_info (GstElement * element)
             j++;
           }
 
-          n_print ("%-23.23s Enum \"%s\" (default %d, \"%s\")", "",
+          n_print ("%-23.23s Enum \"%s\" Current: %d, \"%s\"", "",
               g_type_name (G_VALUE_TYPE (&value)),
               enum_value, values[j].value_nick);
 
@@ -423,7 +460,7 @@ print_element_properties_info (GstElement * element)
             j++;
           }
 
-          n_print ("%-23.23s Flags \"%s\" (default %d, \"%s\")", "",
+          n_print ("%-23.23s Flags \"%s\" Current: %d, \"%s\"", "",
               g_type_name (G_VALUE_TYPE (&value)),
               flags_value, (flags ? flags->str : "(none)"));
 
@@ -982,6 +1019,7 @@ print_element_info (GstElementFactory * factory, gboolean print_names)
   }
 
   print_hierarchy (G_OBJECT_TYPE (element), 0, &maxlevel);
+  print_interfaces (G_OBJECT_TYPE (element));
 
   print_pad_templates_info (element, factory);
   print_element_flag_info (element);