From 20f76fe86f941fae124e2db78c2d63a0e173592d Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Wed, 29 Oct 2014 13:40:55 +0100 Subject: [PATCH] trackelement: Add a lookup_child vmethod This method can be used for subclass to override the default behaviour for child lookup. This vmethod can be used for example in the case where you want the name of a child property to be 'overridden'. As an example in the GESTitleSource where we have a videotestsrc which has a 'foreground-color' property that is used in the TitleSource to set the background color of the title, this vmethod is now used to tweak the name passed as parameter to rename "background" to "foreground-backend" making our API understandable. API: GESTrackElement::lookup_child https://bugzilla.gnome.org/show_bug.cgi?id=727880 --- ges/ges-title-source.c | 22 +++++++++++ ges/ges-title-source.h | 3 +- ges/ges-track-element.c | 81 +++++++++++++++++++++++------------------ ges/ges-track-element.h | 16 ++++++++ 4 files changed, 86 insertions(+), 36 deletions(-) diff --git a/ges/ges-title-source.c b/ges/ges-title-source.c index dea978165e..16c6e0c6bd 100644 --- a/ges/ges-title-source.c +++ b/ges/ges-title-source.c @@ -60,19 +60,41 @@ static void ges_title_source_set_property (GObject * object, guint static GstElement *ges_title_source_create_source (GESTrackElement * self); +static gboolean +_lookup_child (GESTrackElement * object, + const gchar * prop_name, GstElement ** element, GParamSpec ** pspec) +{ + gboolean res; + GESTitleSourceClass *c = GES_TITLE_SOURCE_GET_CLASS (object); + gchar *clean_name = g_regex_replace (c->cleanup_children_prop_names, + prop_name, -1, 0, "foreground-color", 0, NULL); + + res = + GES_TRACK_ELEMENT_CLASS (ges_title_source_parent_class)->lookup_child + (object, clean_name, element, pspec); + + g_free (clean_name); + + return res; +} + static void ges_title_source_class_init (GESTitleSourceClass * klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GESVideoSourceClass *source_class = GES_VIDEO_SOURCE_CLASS (klass); + GESTrackElementClass *track_element_class = GES_TRACK_ELEMENT_CLASS (klass); g_type_class_add_private (klass, sizeof (GESTitleSourcePrivate)); object_class->get_property = ges_title_source_get_property; object_class->set_property = ges_title_source_set_property; object_class->dispose = ges_title_source_dispose; + track_element_class->lookup_child = _lookup_child; source_class->create_source = ges_title_source_create_source; + klass->cleanup_children_prop_names = g_regex_new ("background", + G_REGEX_EXTENDED, 0, NULL); } static void diff --git a/ges/ges-title-source.h b/ges/ges-title-source.h index fa54f028c5..9ef5a580e7 100644 --- a/ges/ges-title-source.h +++ b/ges/ges-title-source.h @@ -69,9 +69,10 @@ struct _GESTitleSourceClass { GESVideoSourceClass parent_class; /*< private >*/ + GRegex * cleanup_children_prop_names; /* Padding for API extension */ - gpointer _ges_reserved[GES_PADDING]; + gpointer _ges_reserved[GES_PADDING - 1]; }; GType ges_title_source_get_type (void); diff --git a/ges/ges-track-element.c b/ges/ges-track-element.c index 87ce2007d9..fdeaa8ac03 100644 --- a/ges/ges-track-element.c +++ b/ges/ges-track-element.c @@ -121,6 +121,46 @@ static void _update_control_bindings (GESTimelineElement * element, GstClockTime inpoint, GstClockTime duration); +static gboolean +_lookup_child (GESTrackElement * object, + const gchar * prop_name, GstElement ** element, GParamSpec ** pspec) +{ + GHashTableIter iter; + gpointer key, value; + gchar **names, *name, *classename; + gboolean res; + + classename = NULL; + res = FALSE; + + names = g_strsplit (prop_name, "::", 2); + if (names[1] != NULL) { + classename = names[0]; + name = names[1]; + } else + name = names[0]; + + g_hash_table_iter_init (&iter, object->priv->children_props); + while (g_hash_table_iter_next (&iter, &key, &value)) { + if (g_strcmp0 (G_PARAM_SPEC (key)->name, name) == 0) { + if (classename == NULL || + g_strcmp0 (G_OBJECT_TYPE_NAME (G_OBJECT (value)), classename) == 0) { + GST_DEBUG ("The %s property from %s has been found", name, classename); + if (element) + *element = gst_object_ref (value); + + *pspec = g_param_spec_ref (key); + res = TRUE; + break; + } + } + } + g_strfreev (names); + + return res; +} + + static void ges_track_element_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec) @@ -273,6 +313,7 @@ ges_track_element_class_init (GESTrackElementClass * klass) klass->create_nle_object = ges_track_element_create_nle_object_func; klass->list_children_properties = default_list_children_properties; + klass->lookup_child = _lookup_child; } static void @@ -1044,41 +1085,13 @@ gboolean ges_track_element_lookup_child (GESTrackElement * object, const gchar * prop_name, GstElement ** element, GParamSpec ** pspec) { - GHashTableIter iter; - gpointer key, value; - gchar **names, *name, *classename; - gboolean res; + GESTrackElementClass *class; g_return_val_if_fail (GES_IS_TRACK_ELEMENT (object), FALSE); + class = GES_TRACK_ELEMENT_GET_CLASS (object); + g_return_val_if_fail (class->lookup_child, FALSE); - classename = NULL; - res = FALSE; - - names = g_strsplit (prop_name, "::", 2); - if (names[1] != NULL) { - classename = names[0]; - name = names[1]; - } else - name = names[0]; - - g_hash_table_iter_init (&iter, object->priv->children_props); - while (g_hash_table_iter_next (&iter, &key, &value)) { - if (g_strcmp0 (G_PARAM_SPEC (key)->name, name) == 0) { - if (classename == NULL || - g_strcmp0 (G_OBJECT_TYPE_NAME (G_OBJECT (value)), classename) == 0) { - GST_DEBUG ("The %s property from %s has been found", name, classename); - if (element) - *element = gst_object_ref (value); - - *pspec = g_param_spec_ref (key); - res = TRUE; - break; - } - } - } - g_strfreev (names); - - return res; + return class->lookup_child (object, prop_name, element, pspec); } /** @@ -1096,9 +1109,7 @@ ges_track_element_set_child_property_by_pspec (GESTrackElement * object, GstElement *element; g_return_if_fail (GES_IS_TRACK_ELEMENT (object)); - - element = g_hash_table_lookup (object->priv->children_props, pspec); - if (!element) + if (!ges_track_element_lookup_child (object, pspec->name, &element, &pspec)) goto not_found; g_object_set_property (G_OBJECT (element), pspec->name, value); diff --git a/ges/ges-track-element.h b/ges/ges-track-element.h index 17409e71f6..67249ec313 100644 --- a/ges/ges-track-element.h +++ b/ges/ges-track-element.h @@ -80,6 +80,16 @@ struct _GESTrackElement { * The default implementation will create an object * of type @nleobject_factorytype and call * @create_element. + * @lookup_child: method letting subclasses look for a child, overriding the + * simple standard behaviour. This vmethod can be used for example + * in the case where you want the name of a child property to be + * 'overriden'. A good example of where it is usefull is the + * GESTitleSource where we have a videotestsrc which has a + * 'foreground-color' property that is used in the TitleSource to + * set the background color of the title, in that case, this method + * has been overriden so that we tweak the name passed has parametter + * to rename "background" to "foreground-backend" making our API + * understandable. * * Subclasses can override the @create_nle_object method to override what type * of GNonLin object will be created. @@ -104,6 +114,12 @@ struct _GESTrackElementClass { /* virtual methods for subclasses */ GParamSpec** (*list_children_properties) (GESTrackElement * object, guint *n_properties); + + + gboolean (*lookup_child) (GESTrackElement *object, + const gchar *prop_name, + GstElement **element, + GParamSpec **pspec); /*< private >*/ /* Padding for API extension */ gpointer _ges_reserved[GES_PADDING_LARGE];