2 * Copyright (C) 2005 Stefan Kost <ensonic@users.sf.net>
4 * gstchildproxy.c: interface for multi child elements
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
23 * SECTION:gstchildproxy
24 * @short_description: Interface for multi child elements.
27 * This interface abstracts handling of property sets for child elements.
28 * Imagine elements such as mixers or polyphonic generators. They all have
29 * multiple #GstPads or some kind of voice objects. The element acts as a
30 * parent for those child objects. Each child has the same properties.
32 * By implementing this interface the child properties can be accessed from the
33 * parent element by using gst_child_proxy_get() and gst_child_proxy_set().
35 * Property names are written as "child-name::property-name". The whole naming
36 * scheme is recursive. Thus "child1::child2::property" is valid too, if
37 * "child1" also implements the #GstChildProxy interface.
40 #include "gst_private.h"
42 #include "gstchildproxy.h"
43 #include "gstmarshal.h"
44 #include <gobject/gvaluecollector.h>
54 static guint signals[LAST_SIGNAL] = { 0 };
57 * gst_child_proxy_get_child_by_name:
58 * @parent: the parent object to get the child from
59 * @name: the childs name
61 * Looks up a child element by the given name.
63 * Implementors can use #GstObject together with gst_object_get_name()
65 * Returns: the child object or %NULL if not found. Unref after usage.
70 gst_child_proxy_get_child_by_name (GstChildProxy * parent, const gchar * name)
73 GstObject *object, *result;
76 g_return_val_if_fail (GST_IS_CHILD_PROXY (parent), NULL);
77 g_return_val_if_fail (name != NULL, NULL);
81 count = gst_child_proxy_get_children_count (parent);
82 for (i = 0; i < count; i++) {
85 if (!(object = gst_child_proxy_get_child_by_index (parent, i)))
88 object_name = gst_object_get_name (object);
89 if (object_name == NULL) {
90 g_warning ("child %u of parent %s has no name", i,
91 GST_OBJECT_NAME (parent));
94 eq = g_str_equal (object_name, name);
102 gst_object_unref (object);
108 * gst_child_proxy_get_child_by_index:
109 * @parent: the parent object to get the child from
110 * @index: the childs position in the child list
112 * Fetches a child by its number.
114 * Returns: the child object or %NULL if not found (index too high). Unref
120 gst_child_proxy_get_child_by_index (GstChildProxy * parent, guint index)
122 g_return_val_if_fail (GST_IS_CHILD_PROXY (parent), NULL);
124 return (GST_CHILD_PROXY_GET_INTERFACE (parent)->get_child_by_index (parent,
129 * gst_child_proxy_get_children_count:
130 * @parent: the parent object
132 * Gets the number of child objects this parent contains.
134 * Returns: the number of child objects
139 gst_child_proxy_get_children_count (GstChildProxy * parent)
141 g_return_val_if_fail (GST_IS_CHILD_PROXY (parent), 0);
143 return (GST_CHILD_PROXY_GET_INTERFACE (parent)->get_children_count (parent));
147 * gst_child_proxy_lookup:
148 * @object: object to lookup the property in
149 * @name: name of the property to look up
150 * @target: pointer to a #GstObject that takes the real object to set property on
151 * @pspec: pointer to take the #GParamSpec describing the property
153 * Looks up which object and #GParamSpec would be effected by the given @name.
155 * Returns: TRUE if @target and @pspec could be found. FALSE otherwise. In that
156 * case the values for @pspec and @target are not modified. Unref @target after
162 gst_child_proxy_lookup (GstObject * object, const gchar * name,
163 GstObject ** target, GParamSpec ** pspec)
165 gboolean res = FALSE;
166 gchar **names, **current;
168 g_return_val_if_fail (GST_IS_OBJECT (object), FALSE);
169 g_return_val_if_fail (name != NULL, FALSE);
171 gst_object_ref (object);
173 current = names = g_strsplit (name, "::", -1);
177 if (!GST_IS_CHILD_PROXY (object)) {
179 ("object %s is not a parent, so you cannot request a child by name %s",
180 GST_OBJECT_NAME (object), current[0]);
183 next = gst_child_proxy_get_child_by_name (GST_CHILD_PROXY (object),
186 GST_INFO ("no such object %s", current[0]);
189 gst_object_unref (object);
193 if (current[1] == NULL) {
195 g_object_class_find_property (G_OBJECT_GET_CLASS (object), current[0]);
197 GST_INFO ("no param spec named %s", current[0]);
202 gst_object_ref (object);
208 gst_object_unref (object);
214 * gst_child_proxy_get_property:
215 * @object: object to query
216 * @name: name of the property
217 * @value: an uninitialized #GValue that should take the result.
219 * Gets a single property using the GstChildProxy mechanism.
220 * You are responsible for for freeing it by calling g_value_unset()
223 gst_child_proxy_get_property (GstObject * object, const gchar * name,
229 g_return_if_fail (GST_IS_OBJECT (object));
230 g_return_if_fail (name != NULL);
231 g_return_if_fail (!G_IS_VALUE (value));
233 if (!gst_child_proxy_lookup (object, name, &target, &pspec))
236 g_object_get_property (G_OBJECT (target), pspec->name, value);
237 gst_object_unref (target);
243 g_warning ("cannot get property %s from object %s", name,
244 GST_OBJECT_NAME (object));
250 * gst_child_proxy_get_valist:
251 * @object: the object to query
252 * @first_property_name: name of the first property to get
253 * @var_args: return location for the first property, followed optionally by more name/return location pairs, followed by NULL
255 * Gets properties of the parent object and its children.
258 gst_child_proxy_get_valist (GstObject * object,
259 const gchar * first_property_name, va_list var_args)
263 GValue value = { 0, };
265 g_return_if_fail (G_IS_OBJECT (object));
267 name = first_property_name;
269 /* iterate over pairs */
271 gst_child_proxy_get_property (object, name, &value);
272 G_VALUE_LCOPY (&value, var_args, 0, &error);
274 g_warning ("error copying value: %s", error);
277 g_value_unset (&value);
278 name = va_arg (var_args, gchar *);
283 * gst_child_proxy_get:
284 * @object: the parent object
285 * @first_property_name: name of the first property to get
286 * @...: return location for the first property, followed optionally by more name/return location pairs, followed by NULL
288 * Gets properties of the parent object and its children.
291 gst_child_proxy_get (GstObject * object, const gchar * first_property_name, ...)
295 g_return_if_fail (GST_IS_OBJECT (object));
297 va_start (var_args, first_property_name);
298 gst_child_proxy_get_valist (object, first_property_name, var_args);
303 * gst_child_proxy_set_property:
304 * @object: the parent object
305 * @name: name of the property to set
306 * @value: new #GValue for the property
308 * Sets a single property using the GstChildProxy mechanism.
311 gst_child_proxy_set_property (GstObject * object, const gchar * name,
312 const GValue * value)
317 g_return_if_fail (GST_IS_OBJECT (object));
318 g_return_if_fail (name != NULL);
319 g_return_if_fail (!G_IS_VALUE (value));
321 if (!gst_child_proxy_lookup (object, name, &target, &pspec))
324 g_object_set_property (G_OBJECT (target), pspec->name, value);
325 gst_object_unref (target);
330 g_warning ("cannot set property %s on object %s", name,
331 GST_OBJECT_NAME (object));
337 * gst_child_proxy_set_valist:
338 * @object: the parent object
339 * @first_property_name: name of the first property to set
340 * @var_args: value for the first property, followed optionally by more name/value pairs, followed by NULL
342 * Sets properties of the parent object and its children.
345 gst_child_proxy_set_valist (GstObject * object,
346 const gchar * first_property_name, va_list var_args)
350 GValue value = { 0, };
352 g_return_if_fail (G_IS_OBJECT (object));
354 name = first_property_name;
356 /* iterate over pairs */
361 if (!gst_child_proxy_lookup (object, name, &target, &pspec)) {
362 g_warning ("no such property %s in object %s", name,
363 GST_OBJECT_NAME (object));
366 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
367 G_VALUE_COLLECT (&value, var_args, G_VALUE_NOCOPY_CONTENTS, &error);
369 g_warning ("error copying value: %s", error);
370 gst_object_unref (target);
373 g_object_set_property (G_OBJECT (target), pspec->name, &value);
374 gst_object_unref (target);
376 g_value_unset (&value);
377 name = va_arg (var_args, gchar *);
382 * gst_child_proxy_set:
383 * @object: the parent object
384 * @first_property_name: name of the first property to set
385 * @...: value for the first property, followed optionally by more name/value pairs, followed by NULL
387 * Sets properties of the parent object and its children.
390 gst_child_proxy_set (GstObject * object, const gchar * first_property_name, ...)
394 g_return_if_fail (GST_IS_OBJECT (object));
396 va_start (var_args, first_property_name);
397 gst_child_proxy_set_valist (object, first_property_name, var_args);
402 * gst_child_proxy_child_added:
403 * @object: the parent object
404 * @child: the newly added child
406 * Emits the "child-added" signal.
409 gst_child_proxy_child_added (GstObject * object, GstObject * child)
411 g_signal_emit (G_OBJECT (object), signals[CHILD_ADDED], 0, child);
415 * gst_child_proxy_child_removed:
416 * @object: the parent object
417 * @child: the newly added child
419 * Emits the "child-removed" signal.
422 gst_child_proxy_child_removed (GstObject * object, GstObject * child)
424 g_signal_emit (G_OBJECT (object), signals[CHILD_REMOVED], 0, child);
427 /* gobject methods */
430 gst_child_proxy_base_init (gpointer g_class)
432 static gboolean initialized = FALSE;
435 /* create interface signals and properties here. */
436 signals[CHILD_ADDED] =
437 g_signal_new ("child-added", G_TYPE_FROM_CLASS (g_class),
438 G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstChildProxyInterface,
439 child_added), NULL, NULL, gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
442 signals[CHILD_REMOVED] =
443 g_signal_new ("child-removed", G_TYPE_FROM_CLASS (g_class),
444 G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstChildProxyInterface,
445 child_removed), NULL, NULL, gst_marshal_VOID__OBJECT, G_TYPE_NONE,
453 gst_child_proxy_get_type (void)
455 static GType type = 0;
458 static const GTypeInfo info = {
459 sizeof (GstChildProxyInterface),
460 gst_child_proxy_base_init, /* base_init */
461 NULL, /* base_finalize */
462 NULL, /* class_init */
463 NULL, /* class_finalize */
464 NULL, /* class_data */
467 NULL /* instance_init */
469 type = g_type_register_static (G_TYPE_INTERFACE, "GstChildProxy", &info, 0);
471 g_type_interface_add_prerequisite (type, GST_TYPE_OBJECT);