childproxy: Implement a new ::get_child_by_name_recurse() API

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2908>
This commit is contained in:
Michael Gruner 2022-10-18 18:15:12 +02:00 committed by GStreamer Marge Bot
parent 60f7467dfe
commit ded2fed3b9
2 changed files with 105 additions and 39 deletions

View file

@ -55,6 +55,69 @@ enum
static guint signals[LAST_SIGNAL] = { 0 };
/**
* gst_child_proxy_get_child_by_name_recurse:
* @parent: the parent object to get the child from
* @name: the full-path child's name
*
* Looks up a child element by the given full-path name.
*
* Similar to gst_child_proxy_get_child_by_name(), this method
* searches and returns a child given a name. The difference is that
* this method allows a hierarchical path in the form of
* child1::child2::child3. In the later example this method would
* return a reference to child3, if found. The name should be made of
* element names only and should not contain any property names.
*
* Returns: (transfer full) (nullable): the child object or %NULL if
* not found.
*
* Since: 1.22
*/
GObject *
gst_child_proxy_get_child_by_name_recurse (GstChildProxy * child_proxy,
const gchar * name)
{
gchar **names = NULL, **current = NULL;
GObject *obj = NULL, *next = NULL;
g_return_val_if_fail (child_proxy != NULL, NULL);
g_return_val_if_fail (name != NULL, NULL);
current = names = g_strsplit (name, "::", -1);
if (current[0]) {
obj = G_OBJECT (g_object_ref (child_proxy));
}
/* walk through the children hierarchy until the requested one is found */
while (current[0]) {
/* Cannot ask for the child of a non-childproxy */
if (!GST_IS_CHILD_PROXY (obj)) {
gst_object_unref (obj);
next = NULL;
break;
}
next = gst_child_proxy_get_child_by_name (GST_CHILD_PROXY (obj),
current[0]);
gst_object_unref (obj);
/* The child does not exist */
if (!next) {
GST_INFO ("Unable to find child %s", current[0]);
break;
}
obj = next;
current++;
}
g_strfreev (names);
return next;
}
static GObject *
gst_child_proxy_default_get_child_by_name (GstChildProxy * parent,
const gchar * name)
@ -194,55 +257,54 @@ gboolean
gst_child_proxy_lookup (GstChildProxy * object, const gchar * name,
GObject ** target, GParamSpec ** pspec)
{
GObject *obj;
gboolean res = FALSE;
gchar **names, **current;
gchar *children = NULL;
const gchar *prop = NULL;
GObject *child = NULL;
static const gchar *separator = "::";
g_return_val_if_fail (GST_IS_CHILD_PROXY (object), FALSE);
g_return_val_if_fail (name != NULL, FALSE);
obj = G_OBJECT (g_object_ref (object));
/* If the requested name does not include a "::" then it is not a
child proxy path, but the property name directly */
prop = g_strrstr (name, separator);
if (!prop) {
child = gst_object_ref (G_OBJECT (object));
prop = name;
} else {
/* Skip "::" */
prop += 2;
current = names = g_strsplit (name, "::", -1);
/* find the owner of the property */
while (current[1]) {
GObject *next;
/* Extract "child1::child2" from "child1::child2::prop" */
children = g_strndup (name, prop - name - 2);
GST_INFO ("Looking for property %s in %s", prop, children);
if (!GST_IS_CHILD_PROXY (obj)) {
GST_INFO
("object %s is not a parent, so you cannot request a child by name %s",
(GST_IS_OBJECT (obj) ? GST_OBJECT_NAME (obj) : ""), current[0]);
break;
}
next = gst_child_proxy_get_child_by_name (GST_CHILD_PROXY (obj),
current[0]);
if (!next) {
GST_INFO ("no such object %s", current[0]);
break;
}
gst_object_unref (obj);
obj = next;
current++;
}
child = gst_child_proxy_get_child_by_name_recurse (object, children);
g_free (children);
/* look for psec */
if (current[1] == NULL) {
GParamSpec *spec =
g_object_class_find_property (G_OBJECT_GET_CLASS (obj), current[0]);
if (spec == NULL) {
GST_INFO ("no param spec named %s", current[0]);
} else {
if (pspec)
*pspec = spec;
if (target) {
g_object_ref (obj);
*target = obj;
}
res = TRUE;
if (!child) {
GST_INFO ("Child not found");
goto out;
}
}
gst_object_unref (obj);
g_strfreev (names);
GParamSpec *spec =
g_object_class_find_property (G_OBJECT_GET_CLASS (child), prop);
if (spec == NULL) {
GST_INFO ("no param spec named %s", prop);
} else {
if (pspec)
*pspec = spec;
if (target) {
g_object_ref (child);
*target = child;
}
res = TRUE;
}
gst_object_unref (child);
out:
return res;
}

View file

@ -118,6 +118,10 @@ GType gst_child_proxy_get_type (void);
GST_API
GObject * gst_child_proxy_get_child_by_name (GstChildProxy * parent, const gchar * name);
GST_API
GObject * gst_child_proxy_get_child_by_name_recurse (GstChildProxy * child_proxy,
const gchar *name);
GST_API
guint gst_child_proxy_get_children_count (GstChildProxy * parent);