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
This commit is contained in:
Thibault Saunier 2014-10-29 13:40:55 +01:00
parent 190643508f
commit 20f76fe86f
4 changed files with 86 additions and 36 deletions

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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];