/** * gst_child_proxy_lookup: * @childproxy: child proxy object to lookup the property in * @name: name of the property to look up * @target: (out) (allow-none) (transfer full): pointer to a #GObject that * takes the real object to set property on * @pspec: (out) (allow-none) (transfer none): pointer to take the #GParamSpec * describing the property * * Looks up which object and #GParamSpec would be effected by the given @name. * * MT safe. * * Returns: TRUE if @target and @pspec could be found. FALSE otherwise. In that * case the values for @pspec and @target are not modified. Unref @target after * usage. For plain GObjects @target is the same as @object. */ gboolean gst_child_proxy_lookup (GstChildProxy * childproxy, const gchar * name, GObject ** target, GParamSpec ** pspec) { GObject *object; gboolean res = FALSE; gchar **names, **current; g_return_val_if_fail (GST_IS_CHILD_PROXY (childproxy), FALSE); g_return_val_if_fail (name != NULL, FALSE); object = g_object_ref (childproxy); current = names = g_strsplit (name, "::", -1); /* find the owner of the property */ while (current[1]) { GObject *next; if (!GST_IS_CHILD_PROXY (object)) { GST_INFO ("object %s is not a parent, so you cannot request a child by name %s", (GST_IS_OBJECT (object) ? GST_OBJECT_NAME (object) : ""), current[0]); break; } next = gst_child_proxy_get_child_by_name (GST_CHILD_PROXY (object), current[0]); if (!next) { GST_INFO ("no such object %s", current[0]); break; } g_object_unref (object); object = next; current++; } /* look for psec */ 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) { g_object_ref (object); *target = object; } res = TRUE; } } g_object_unref (object); g_strfreev (names); return res; }
/** * 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 (GstChildProxy * object, const gchar * name, const GValue * value) { GParamSpec *pspec; GObject *target; g_return_if_fail (GST_IS_CHILD_PROXY (object)); g_return_if_fail (name != NULL); g_return_if_fail (G_IS_VALUE (value)); if (!gst_child_proxy_lookup (object, name, &target, &pspec)) goto not_found; g_object_set_property (target, pspec->name, value); g_object_unref (target); return; not_found: { g_warning ("cannot set property %s on object %s", name, (GST_IS_OBJECT (object) ? GST_OBJECT_NAME (object) : "")); return; } }
/** * 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 * * MT safe. */ 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_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: (transfer full): the child object or %NULL if not found (index * too high). Unref after usage. * * MT safe. */ GObject * 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_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. * * This virtual method has a default implementation that uses #GstObject * together with gst_object_get_name(). If the interface is to be used with * #GObjects, this methods needs to be overridden. * * Returns: (transfer full): the child object or %NULL if not found. Unref * after usage. * * MT safe. */ GObject * gst_child_proxy_get_child_by_name (GstChildProxy * parent, const gchar * name) { g_return_val_if_fail (GST_IS_CHILD_PROXY (parent), 0); return (GST_CHILD_PROXY_GET_INTERFACE (parent)->get_child_by_name (parent, name)); }
/** * 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 (GstChildProxy * object, const gchar * first_property_name, ...) { va_list var_args; g_return_if_fail (GST_IS_CHILD_PROXY (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_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 (GstChildProxy * object, const gchar * first_property_name, va_list var_args) { const gchar *name; gchar *error = NULL; GValue value = { 0, }; GParamSpec *pspec; GObject *target; g_return_if_fail (GST_IS_CHILD_PROXY (object)); name = first_property_name; /* iterate over pairs */ while (name) { if (!gst_child_proxy_lookup (object, name, &target, &pspec)) goto not_found; G_VALUE_COLLECT_INIT (&value, pspec->value_type, var_args, G_VALUE_NOCOPY_CONTENTS, &error); if (error) goto cant_copy; g_object_set_property (target, pspec->name, &value); g_object_unref (target); g_value_unset (&value); name = va_arg (var_args, gchar *); } return; not_found: { g_warning ("no property %s in object %s", name, (GST_IS_OBJECT (object) ? GST_OBJECT_NAME (object) : "")); return; } cant_copy: { g_warning ("error copying value %s in object %s: %s", pspec->name, (GST_IS_OBJECT (object) ? GST_OBJECT_NAME (object) : ""), error); g_value_unset (&value); g_object_unref (target); return; } }
static GObject * gst_child_proxy_default_get_child_by_name (GstChildProxy * parent, const gchar * name) { guint count, i; GObject *object, *result; gchar *object_name; g_return_val_if_fail (GST_IS_CHILD_PROXY (parent), NULL); g_return_val_if_fail (name != NULL, NULL); result = NULL; count = gst_child_proxy_get_children_count (parent); for (i = 0; i < count; i++) { gboolean eq; if (!(object = gst_child_proxy_get_child_by_index (parent, i))) continue; if (!GST_IS_OBJECT (object)) { goto next; } object_name = gst_object_get_name (GST_OBJECT_CAST (object)); if (object_name == NULL) { g_warning ("child %u of parent %s has no name", i, GST_OBJECT_NAME (parent)); goto next; } eq = g_str_equal (object_name, name); g_free (object_name); if (eq) { result = object; break; } next: g_object_unref (object); } return result; }
/* save the preset with the given name */ static gboolean gst_preset_default_save_preset (GstPreset * preset, const gchar * name) { GKeyFile *presets; gchar **props; guint i; GObjectClass *gclass; gboolean is_child_proxy; GST_INFO_OBJECT (preset, "saving new preset: %s", name); /* get the presets from the type */ if (!(presets = preset_get_keyfile (preset))) goto no_presets; /* take copies of current gobject properties from preset */ if (!(props = gst_preset_get_property_names (preset))) goto no_properties; gclass = G_OBJECT_CLASS (GST_ELEMENT_GET_CLASS (preset)); is_child_proxy = GST_IS_CHILD_PROXY (preset); /* loop over the object properties and store the property value in the * keyfile */ for (i = 0; props[i]; i++) { GValue gvalue = { 0, }; gchar *str; GParamSpec *property = NULL; if (is_child_proxy) { gst_child_proxy_lookup ((GstChildProxy *) preset, props[i], NULL, &property); } else { property = g_object_class_find_property (gclass, props[i]); } if (!property) { /* the element said it supported the property but then it does not have * that property. This should not happen. */ GST_WARNING_OBJECT (preset, "property '%s' not in object", props[i]); continue; } g_value_init (&gvalue, property->value_type); if (is_child_proxy) { gst_child_proxy_get_property ((GstChildProxy *) preset, props[i], &gvalue); } else { g_object_get_property ((GObject *) preset, props[i], &gvalue); } if ((str = gst_value_serialize (&gvalue))) { g_key_file_set_string (presets, name, props[i], (gpointer) str); g_free (str); } else { GST_WARNING_OBJECT (preset, "serialization for property '%s' failed", props[i]); } g_value_unset (&gvalue); } GST_INFO_OBJECT (preset, " saved"); g_strfreev (props); /* save updated version */ return gst_preset_default_save_presets_file (preset); /* ERRORS */ no_presets: { GST_WARNING_OBJECT (preset, "no presets"); return FALSE; } no_properties: { GST_INFO_OBJECT (preset, "no properties"); return FALSE; } }
/* load the presets of @name for the instance @preset. Returns %FALSE if something * failed. */ static gboolean gst_preset_default_load_preset (GstPreset * preset, const gchar * name) { GKeyFile *presets; gchar **props; guint i; GObjectClass *gclass; gboolean is_child_proxy; /* get the presets from the type */ if (!(presets = preset_get_keyfile (preset))) goto no_presets; /* get the preset name */ if (!g_key_file_has_group (presets, name)) goto no_group; GST_DEBUG_OBJECT (preset, "loading preset : '%s'", name); /* get the properties that we can configure in this element */ if (!(props = gst_preset_get_property_names (preset))) goto no_properties; gclass = G_OBJECT_CLASS (GST_ELEMENT_GET_CLASS (preset)); is_child_proxy = GST_IS_CHILD_PROXY (preset); /* for each of the property names, find the preset parameter and try to * configure the property with its value */ for (i = 0; props[i]; i++) { gchar *str; GValue gvalue = { 0, }; GParamSpec *property = NULL; /* check if we have a settings for this element property */ if (!(str = g_key_file_get_value (presets, name, props[i], NULL))) { /* the element has a property but the parameter is not in the keyfile */ GST_WARNING_OBJECT (preset, "parameter '%s' not in preset", props[i]); continue; } GST_DEBUG_OBJECT (preset, "setting value '%s' for property '%s'", str, props[i]); if (is_child_proxy) { gst_child_proxy_lookup ((GstChildProxy *) preset, props[i], NULL, &property); } else { property = g_object_class_find_property (gclass, props[i]); } if (!property) { /* the parameter was in the keyfile, the element said it supported it but * then the property was not found in the element. This should not happen. */ GST_WARNING_OBJECT (preset, "property '%s' not in object", props[i]); g_free (str); continue; } /* try to deserialize the property value from the keyfile and set it as * the object property */ g_value_init (&gvalue, property->value_type); if (gst_value_deserialize (&gvalue, str)) { if (is_child_proxy) { gst_child_proxy_set_property ((GstChildProxy *) preset, props[i], &gvalue); } else { g_object_set_property ((GObject *) preset, props[i], &gvalue); } } else { GST_WARNING_OBJECT (preset, "deserialization of value '%s' for property '%s' failed", str, props[i]); } g_value_unset (&gvalue); g_free (str); } g_strfreev (props); return TRUE; /* ERRORS */ no_presets: { GST_WARNING_OBJECT (preset, "no presets"); return FALSE; } no_group: { GST_WARNING_OBJECT (preset, "no preset named '%s'", name); return FALSE; } no_properties: { GST_INFO_OBJECT (preset, "no properties"); return FALSE; } }