ges: Move the notion of children properties to GESTimelineElement

Summary:
Deprecate the old GESTrackElement children property handling API.

New APIs:
  * ges_timeline_element_list_children_properties
  * ges_timeline_element_lookup_child
  * ges_timeline_element_get_child_property_by_pspec
  * ges_timeline_element_get_child_property_valist
  * ges_timeline_element_get_child_properties
  * ges_timeline_element_set_child_property_valist
  * ges_timeline_element_set_child_property_by_pspec
  * ges_timeline_element_set_child_properties
  * ges_timeline_element_set_child_property
  * ges_timeline_element_get_child_property
  * ges_timeline_element_add_child_property
  * ges_timeline_element_remove_child_property

Deprecated APIs:
  * ges_track_element_list_children_properties
  * ges_track_element_lookup_child
  * ges_track_element_get_child_property_by_pspec
  * ges_track_element_get_child_property_valist
  * ges_track_element_get_child_properties
  * ges_track_element_set_child_property_valist
  * ges_track_element_set_child_property_by_pspec
  * ges_track_element_set_child_properties
  * ges_track_element_set_child_property
  * ges_track_element_get_child_property
  * ges_track_element_add_child_property

Reviewers: Mathieu_Du

Differential Revision: http://phabricator.freedesktop.org/D40
This commit is contained in:
Thibault Saunier 2015-02-19 16:30:18 +01:00
parent 3e49850e6d
commit 42477a5ec3
8 changed files with 717 additions and 368 deletions

View file

@ -452,6 +452,18 @@ ges_timeline_element_get_toplevel_parent
ges_timeline_element_copy
ges_timeline_element_get_name
ges_timeline_element_set_name
ges_timeline_element_list_children_properties
ges_timeline_element_lookup_child
ges_timeline_element_get_child_property_by_pspec
ges_timeline_element_get_child_property_valist
ges_timeline_element_get_child_properties
ges_timeline_element_set_child_property_valist
ges_timeline_element_set_child_property_by_pspec
ges_timeline_element_set_child_properties
ges_timeline_element_set_child_property
ges_timeline_element_get_child_property
ges_timeline_element_add_child_property
ges_timeline_element_remove_child_property
GES_TIMELINE_ELEMENT_PARENT
GES_TIMELINE_ELEMENT_TIMELINE
GES_TIMELINE_ELEMENT_START

View file

@ -26,11 +26,14 @@
* responsible for controlling its timing properties.
*/
#include "ges-utils.h"
#include "ges-timeline-element.h"
#include "ges-extractable.h"
#include "ges-meta-container.h"
#include "ges-internal.h"
#include <string.h>
#include <gobject/gvaluecollector.h>
/* maps type name quark => count */
static GData *object_name_counts = NULL;
@ -67,13 +70,90 @@ enum
PROP_LAST
};
enum
{
DEEP_NOTIFY,
LAST_SIGNAL
};
static guint ges_timeline_element_signals[LAST_SIGNAL] = { 0 };
static GParamSpec *properties[PROP_LAST] = { NULL, };
struct _GESTimelineElementPrivate
{
gboolean serialize;
/* We keep a link between properties name and elements internally
* The hashtable should look like
* {GParamaSpec ---> child}*/
GHashTable *children_props;
};
static gboolean
_lookup_child (GESTimelineElement * self, const gchar * prop_name,
GObject ** child, 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, self->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_OBJECT (self, "The %s property from %s has been found", name,
classename);
if (child)
*child = gst_object_ref (value);
if (pspec)
*pspec = g_param_spec_ref (key);
res = TRUE;
break;
}
}
}
g_strfreev (names);
return res;
}
static GParamSpec **
default_list_children_properties (GESTimelineElement * self,
guint * n_properties)
{
GParamSpec **pspec, *spec;
GHashTableIter iter;
gpointer key, value;
guint i = 0;
*n_properties = g_hash_table_size (self->priv->children_props);
pspec = g_new (GParamSpec *, *n_properties);
g_hash_table_iter_init (&iter, self->priv->children_props);
while (g_hash_table_iter_next (&iter, &key, &value)) {
spec = G_PARAM_SPEC (key);
pspec[i] = g_param_spec_ref (spec);
i++;
}
return pspec;
}
static void
_get_property (GObject * object, guint property_id,
GValue * value, GParamSpec * pspec)
@ -169,6 +249,10 @@ ges_timeline_element_init (GESTimelineElement * self)
GES_TYPE_TIMELINE_ELEMENT, GESTimelineElementPrivate);
self->priv->serialize = TRUE;
self->priv->children_props =
g_hash_table_new_full ((GHashFunc) ges_pspec_hash, ges_pspec_equal,
(GDestroyNotify) g_param_spec_unref, gst_object_unref);
}
static void
@ -268,6 +352,21 @@ ges_timeline_element_class_init (GESTimelineElementClass * klass)
g_object_class_install_properties (object_class, PROP_LAST, properties);
/**
* GESTimelineElement::deep-notify:
* @timeline_element: a #GESTtimelineElement
* @prop_object: the object that originated the signal
* @prop: the property that changed
*
* The deep notify signal is used to be notified of property changes of all
* the childs of @timeline_element
*/
ges_timeline_element_signals[DEEP_NOTIFY] =
g_signal_new ("deep-notify", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_DETAILED |
G_SIGNAL_NO_HOOKS, 0, NULL, NULL, g_cclosure_marshal_generic,
G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_PARAM);
object_class->finalize = ges_timeline_element_finalize;
klass->set_parent = NULL;
@ -282,6 +381,9 @@ ges_timeline_element_class_init (GESTimelineElementClass * klass)
klass->roll_start = NULL;
klass->roll_end = NULL;
klass->trim = NULL;
klass->list_children_properties = default_list_children_properties;
klass->lookup_child = _lookup_child;
}
static void
@ -1082,3 +1184,440 @@ had_timeline:
return FALSE;
}
}
static void
child_prop_changed_cb (GObject * child, GParamSpec * arg
G_GNUC_UNUSED, GESTimelineElement * self)
{
g_signal_emit (self, ges_timeline_element_signals[DEEP_NOTIFY], 0,
child, arg);
}
gboolean
ges_timeline_element_add_child_property (GESTimelineElement * self,
GParamSpec * pspec, GObject * child)
{
GST_DEBUG_OBJECT (self, "Adding child property: %" GST_PTR_FORMAT "::%s",
child, pspec->name);
if (g_hash_table_insert (self->priv->children_props,
g_param_spec_ref (pspec), gst_object_ref (child))) {
gchar *signame = g_strconcat ("notify::", pspec->name, NULL);
g_signal_connect (child, signame, G_CALLBACK (child_prop_changed_cb), self);
g_free (signame);
return TRUE;
}
return FALSE;
}
/**
* ges_track_element_get_child_property_by_pspec:
* @self: a #GESTrackElement
* @pspec: The #GParamSpec that specifies the property you want to get
* @value: (out): return location for the value
*
* Gets a property of a child of @self.
*/
void
ges_timeline_element_get_child_property_by_pspec (GESTimelineElement * self,
GParamSpec * pspec, GValue * value)
{
GstElement *element;
g_return_if_fail (GES_IS_TIMELINE_ELEMENT (self));
element = g_hash_table_lookup (self->priv->children_props, pspec);
if (!element)
goto not_found;
g_object_get_property (G_OBJECT (element), pspec->name, value);
return;
not_found:
{
GST_ERROR_OBJECT (self, "The %s property doesn't exist", pspec->name);
return;
}
}
/**
* ges_timeline_element_set_child_property_by_pspec:
* @self: a #GESTimelineElement
* @pspec: The #GParamSpec that specifies the property you want to set
* @value: the value
*
* Sets a property of a child of @self.
*/
void
ges_timeline_element_set_child_property_by_pspec (GESTimelineElement * self,
GParamSpec * pspec, GValue * value)
{
GObject *child;
g_return_if_fail (GES_IS_TRACK_ELEMENT (self));
if (!ges_timeline_element_lookup_child (self, pspec->name, &child, &pspec))
goto not_found;
g_object_set_property (child, pspec->name, value);
return;
not_found:
{
GST_ERROR ("The %s property doesn't exist", pspec->name);
return;
}
}
/**
* ges_timeline_element_set_child_property:
* @self: The origin #GESTimelineElement
* @property_name: The name of the property
* @value: the value
*
* Sets a property of a child of @self
*
* Note that #ges_timeline_element_set_child_property is really
* intended for language bindings, #ges_timeline_element_set_child_properties
* is much more convenient for C programming.
*
* Returns: %TRUE if the property was set, %FALSE otherwize
*/
gboolean
ges_timeline_element_set_child_property (GESTimelineElement * self,
const gchar * property_name, GValue * value)
{
GParamSpec *pspec;
GObject *child;
g_return_val_if_fail (GES_IS_TIMELINE_ELEMENT (self), FALSE);
if (!ges_timeline_element_lookup_child (self, property_name, &child, &pspec))
goto not_found;
g_object_set_property (child, pspec->name, value);
gst_object_unref (child);
g_param_spec_unref (pspec);
return TRUE;
not_found:
{
GST_WARNING_OBJECT (self, "The %s property doesn't exist", property_name);
return FALSE;
}
}
/**
* ges_timeline_element_get_child_property:
* @object: The origin #GESTimelineElement
* @property_name: The name of the property
* @value: (out): return location for the property value, it will
* be initialized if it is initialized with 0
*
* In general, a copy is made of the property contents and
* the caller is responsible for freeing the memory by calling
* g_value_unset().
*
* Gets a property of a GstElement contained in @object.
*
* Note that #ges_timeline_element_get_child_property is really
* intended for language bindings, #ges_timeline_element_get_child_properties
* is much more convenient for C programming.
*
* Returns: %TRUE if the property was found, %FALSE otherwize
*/
gboolean
ges_timeline_element_get_child_property (GESTimelineElement * self,
const gchar * property_name, GValue * value)
{
GParamSpec *pspec;
GObject *child;
g_return_val_if_fail (GES_IS_TIMELINE_ELEMENT (self), FALSE);
if (!ges_timeline_element_lookup_child (self, property_name, &child, &pspec))
goto not_found;
if (G_VALUE_TYPE (value) == G_TYPE_INVALID)
g_value_init (value, pspec->value_type);
g_object_get_property (child, pspec->name, value);
gst_object_unref (child);
g_param_spec_unref (pspec);
return TRUE;
not_found:
{
GST_WARNING_OBJECT (self, "The %s property doesn't exist", property_name);
return FALSE;
}
}
/**
* ges_timeline_element_lookup_child:
* @self: object to lookup the property in
* @prop_name: name of the property to look up. You can specify the name of the
* class as such: "ClassName::property-name", to guarantee that you get the
* proper GParamSpec in case various GstElement-s contain the same property
* name. If you don't do so, you will get the first element found, having
* this property and the and the corresponding GParamSpec.
* @element: (out) (allow-none) (transfer full): pointer to a #GstElement that
* takes the real object to set property on
* @pspec: (out) (allow-none) (transfer full): pointer to take the #GParamSpec
* describing the property
*
* Looks up which @element and @pspec would be effected by the given @name. If various
* contained elements have this property name you will get the first one, unless you
* specify the class name in @name.
*
* Returns: TRUE if @element and @pspec could be found. FALSE otherwise. In that
* case the values for @pspec and @element are not modified. Unref @element after
* usage.
*/
gboolean
ges_timeline_element_lookup_child (GESTimelineElement * self,
const gchar * prop_name, GObject ** child, GParamSpec ** pspec)
{
GESTimelineElementClass *class;
g_return_val_if_fail (GES_IS_TIMELINE_ELEMENT (self), FALSE);
class = GES_TIMELINE_ELEMENT_GET_CLASS (self);
g_return_val_if_fail (class->lookup_child, FALSE);
return class->lookup_child (self, prop_name, child, pspec);
}
/**
* ges_timeline_element_set_child_property_valist:
* @self: The #GESTimelineElement parent object
* @first_property_name: The name of the first property to set
* @var_args: value for the first property, followed optionally by more
* name/return location pairs, followed by NULL
*
* Sets a property of a child of @self. If there are various child elements
* that have the same property name, you can distinguish them using the following
* syntax: 'ClasseName::property_name' as property name. If you don't, the
* corresponding property of the first element found will be set.
*/
void
ges_timeline_element_set_child_property_valist (GESTimelineElement * self,
const gchar * first_property_name, va_list var_args)
{
const gchar *name;
GParamSpec *pspec;
GObject *child;
gchar *error = NULL;
GValue value = { 0, };
g_return_if_fail (GES_IS_TIMELINE_ELEMENT (self));
name = first_property_name;
/* Note: This part is in big part copied from the gst_child_object_set_valist
* method. */
/* iterate over pairs */
while (name) {
if (!ges_timeline_element_lookup_child (self, name, &child, &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 (child, pspec->name, &value);
gst_object_unref (child);
g_value_unset (&value);
name = va_arg (var_args, gchar *);
}
return;
not_found:
{
GST_WARNING_OBJECT (self, "No property %s in OBJECT\n", name);
return;
}
cant_copy:
{
GST_WARNING_OBJECT (self, "error copying value %s in %p: %s", pspec->name,
self, error);
g_value_unset (&value);
return;
}
}
/**
* ges_timeline_element_set_child_properties:
* @self: The #GESTimelineElement parent object
* @first_property_name: The name of the first property to set
* @...: value for the first property, followed optionally by more
* name/return location pairs, followed by NULL
*
* Sets a property of a child of @self. If there are various child elements
* that have the same property name, you can distinguish them using the following
* syntax: 'ClasseName::property_name' as property name. If you don't, the
* corresponding property of the first element found will be set.
*/
void
ges_timeline_element_set_child_properties (GESTimelineElement * self,
const gchar * first_property_name, ...)
{
va_list var_args;
g_return_if_fail (GES_IS_TIMELINE_ELEMENT (self));
va_start (var_args, first_property_name);
ges_timeline_element_set_child_property_valist (self, first_property_name,
var_args);
va_end (var_args);
}
/**
* ges_timeline_element_get_child_property_valist:
* @self: The #GESTimelineElement parent object
* @first_property_name: The name of the first property to get
* @var_args: value for the first property, followed optionally by more
* name/return location pairs, followed by NULL
*
* Gets a property of a child of @self. If there are various child elements
* that have the same property name, you can distinguish them using the following
* syntax: 'ClasseName::property_name' as property name. If you don't, the
* corresponding property of the first element found will be set.
*/
void
ges_timeline_element_get_child_property_valist (GESTimelineElement * self,
const gchar * first_property_name, va_list var_args)
{
const gchar *name;
gchar *error = NULL;
GValue value = { 0, };
GParamSpec *pspec;
GObject *child;
g_return_if_fail (GES_IS_TIMELINE_ELEMENT (self));
name = first_property_name;
/* This part is in big part copied from the gst_child_object_get_valist method */
while (name) {
if (!ges_timeline_element_lookup_child (self, name, &child, &pspec))
goto not_found;
g_value_init (&value, pspec->value_type);
g_object_get_property (child, pspec->name, &value);
gst_object_unref (child);
G_VALUE_LCOPY (&value, var_args, 0, &error);
if (error)
goto cant_copy;
g_value_unset (&value);
name = va_arg (var_args, gchar *);
}
return;
not_found:
{
GST_WARNING_OBJECT (self, "no child property %s", name);
return;
}
cant_copy:
{
GST_WARNING_OBJECT (self, "error copying value %s in %s", pspec->name,
error);
g_value_unset (&value);
return;
}
}
static gint
compare_gparamspec (GParamSpec ** a, GParamSpec ** b, gpointer udata)
{
return g_strcmp0 ((*a)->name, (*b)->name);
}
/**
* ges_timeline_element_list_children_properties:
* @self: The #GESTimelineElement to get the list of children properties from
* @n_properties: (out): return location for the length of the returned array
*
* Gets an array of #GParamSpec* for all configurable properties of the
* children of @self.
*
* Returns: (transfer full) (array length=n_properties): an array of #GParamSpec* which should be freed after use or
* %NULL if something went wrong
*/
GParamSpec **
ges_timeline_element_list_children_properties (GESTimelineElement * self,
guint * n_properties)
{
GParamSpec **ret;
GESTimelineElementClass *class;
g_return_val_if_fail (GES_IS_TIMELINE_ELEMENT (self), NULL);
class = GES_TIMELINE_ELEMENT_GET_CLASS (self);
if (!class->list_children_properties) {
GST_INFO_OBJECT (self, "No %s->list_children_properties implementation",
G_OBJECT_TYPE_NAME (self));
*n_properties = 0;
return NULL;
}
ret = class->list_children_properties (self, n_properties);
g_qsort_with_data (ret, *n_properties, sizeof (GParamSpec *),
(GCompareDataFunc) compare_gparamspec, NULL);
return ret;
}
/**
* ges_timeline_element_get_child_properties:
* @self: The origin #GESTimelineElement
* @first_property_name: The name of the first property to get
* @...: return location for the first property, followed optionally by more
* name/return location pairs, followed by NULL
*
* Gets properties of a child of @self.
*/
void
ges_timeline_element_get_child_properties (GESTimelineElement * self,
const gchar * first_property_name, ...)
{
va_list var_args;
g_return_if_fail (GES_IS_TIMELINE_ELEMENT (self));
va_start (var_args, first_property_name);
ges_timeline_element_get_child_property_valist (self, first_property_name,
var_args);
va_end (var_args);
}
gboolean
ges_timeline_element_remove_child_property (GESTimelineElement * self,
GParamSpec * pspec)
{
return g_hash_table_remove (self->priv->children_props, pspec);
}

View file

@ -187,9 +187,13 @@ struct _GESTimelineElementClass
gboolean (*trim) (GESTimelineElement *self, guint64 start);
void (*deep_copy) (GESTimelineElement *self, GESTimelineElement *copy);
GParamSpec** (*list_children_properties) (GESTimelineElement * self, guint *n_properties);
gboolean (*lookup_child) (GESTimelineElement *self, const gchar *prop_name,
GObject **child, GParamSpec **pspec);
/*< private > */
/* Padding for API extension */
gpointer _ges_reserved[GES_PADDING_LARGE];
gpointer _ges_reserved[GES_PADDING_LARGE - 2];
};
GType ges_timeline_element_get_type (void) G_GNUC_CONST;
@ -220,6 +224,57 @@ gboolean ges_timeline_element_trim (GESTimelineElement *self,
GESTimelineElement * ges_timeline_element_copy (GESTimelineElement *self, gboolean deep);
gchar * ges_timeline_element_get_name (GESTimelineElement *self);
gboolean ges_timeline_element_set_name (GESTimelineElement *self, const gchar *name);
GParamSpec **
ges_timeline_element_list_children_properties (GESTimelineElement *self,
guint *n_properties);
gboolean ges_timeline_element_lookup_child (GESTimelineElement *self,
const gchar *prop_name,
GObject **child,
GParamSpec **pspec);
void
ges_timeline_element_get_child_property_by_pspec (GESTimelineElement * self,
GParamSpec * pspec,
GValue * value);
void
ges_timeline_element_get_child_property_valist (GESTimelineElement * self,
const gchar * first_property_name,
va_list var_args);
void ges_timeline_element_get_child_properties (GESTimelineElement *self,
const gchar * first_property_name,
...) G_GNUC_NULL_TERMINATED;
void
ges_timeline_element_set_child_property_valist (GESTimelineElement * self,
const gchar * first_property_name,
va_list var_args);
void
ges_timeline_element_set_child_property_by_pspec (GESTimelineElement * self,
GParamSpec * pspec,
GValue * value);
void ges_timeline_element_set_child_properties (GESTimelineElement * self,
const gchar * first_property_name,
...) G_GNUC_NULL_TERMINATED;
gboolean ges_timeline_element_set_child_property (GESTimelineElement *self,
const gchar *property_name,
GValue * value);
gboolean ges_timeline_element_get_child_property (GESTimelineElement *self,
const gchar *property_name,
GValue * value);
gboolean ges_timeline_element_add_child_property (GESTimelineElement * self,
GParamSpec *pspec,
GObject *child);
gboolean ges_timeline_element_remove_child_property(GESTimelineElement * self,
GParamSpec *pspec);
G_END_DECLS

View file

@ -29,13 +29,11 @@
* its container, like the start position, the inpoint, the duration and the
* priority.
*/
#include "ges-utils.h"
#include "ges-internal.h"
#include "ges-extractable.h"
#include "ges-track-element.h"
#include "ges-clip.h"
#include "ges-meta-container.h"
#include <gobject/gvaluecollector.h>
G_DEFINE_ABSTRACT_TYPE (GESTrackElement, ges_track_element,
GES_TYPE_TIMELINE_ELEMENT);
@ -54,11 +52,6 @@ struct _GESTrackElementPrivate
GstElement *nleobject; /* The NleObject */
GstElement *element; /* The element contained in the nleobject (can be NULL) */
/* We keep a link between properties name and elements internally
* The hashtable should look like
* {GParamaSpec ---> element,}*/
GHashTable *children_props;
GESTrack *track;
gboolean valid;
@ -92,7 +85,6 @@ static GParamSpec *properties[PROP_LAST];
enum
{
DEEP_NOTIFY,
CONTROL_BINDING_ADDED,
LAST_SIGNAL
};
@ -102,11 +94,6 @@ static guint ges_track_element_signals[LAST_SIGNAL] = { 0 };
static GstElement *ges_track_element_create_nle_object_func (GESTrackElement *
object);
static void connect_properties_signals (GESTrackElement * object);
static void connect_signal (gpointer key, gpointer value, gpointer user_data);
static void gst_element_prop_changed_cb (GstElement * element, GParamSpec * arg
G_GNUC_UNUSED, GESTrackElement * track_element);
static gboolean _set_start (GESTimelineElement * element, GstClockTime start);
static gboolean _set_inpoint (GESTimelineElement * element,
GstClockTime inpoint);
@ -125,41 +112,26 @@ 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;
return
GES_TIMELINE_ELEMENT_GET_CLASS (object)->lookup_child
(GES_TIMELINE_ELEMENT (object), prop_name, (GObject **) element, pspec);
}
static gboolean
strv_find_str (const gchar ** strv, const char *str)
{
guint i;
if (strv == NULL)
return FALSE;
for (i = 0; strv[i]; i++) {
if (g_strcmp0 (strv[i], str) == 0)
return TRUE;
}
return FALSE;
}
static void
ges_track_element_get_property (GObject * object, guint property_id,
@ -206,7 +178,6 @@ ges_track_element_dispose (GObject * object)
GESTrackElement *element = GES_TRACK_ELEMENT (object);
GESTrackElementPrivate *priv = element->priv;
g_hash_table_destroy (priv->children_props);
if (priv->bindings_hashtable)
g_hash_table_destroy (priv->bindings_hashtable);
@ -277,21 +248,6 @@ ges_track_element_class_init (GESTrackElementClass * klass)
g_object_class_install_property (object_class, PROP_TRACK,
properties[PROP_TRACK]);
/**
* GESTrackElement::deep-notify:
* @track_element: a #GESTrackElement
* @prop_object: the object that originated the signal
* @prop: the property that changed
*
* The deep notify signal is used to be notified of property changes of all
* the childs of @track_element
*/
ges_track_element_signals[DEEP_NOTIFY] =
g_signal_new ("deep-notify", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_DETAILED |
G_SIGNAL_NO_HOOKS, 0, NULL, NULL, g_cclosure_marshal_generic,
G_TYPE_NONE, 2, GST_TYPE_ELEMENT, G_TYPE_PARAM);
/**
* GESTrackElement::control-binding-added:
* @track_element: a #GESTrackElement
@ -330,16 +286,6 @@ ges_track_element_init (GESTrackElement * self)
priv->pending_active = TRUE;
priv->bindings_hashtable = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, NULL);
priv->children_props =
g_hash_table_new_full ((GHashFunc) ges_pspec_hash, ges_pspec_equal,
(GDestroyNotify) g_param_spec_unref, gst_object_unref);
}
static gint
compare_gparamspec (GParamSpec ** a, GParamSpec ** b, gpointer udata)
{
return g_strcmp0 ((*a)->name, (*b)->name);
}
static gfloat
@ -591,33 +537,6 @@ ges_track_element_get_track_type (GESTrackElement * object)
return object->priv->track_type;
}
static void
gst_element_prop_changed_cb (GstElement * element, GParamSpec * arg
G_GNUC_UNUSED, GESTrackElement * track_element)
{
g_signal_emit (track_element, ges_track_element_signals[DEEP_NOTIFY], 0,
GST_ELEMENT (element), arg);
}
static void
connect_signal (gpointer key, gpointer value, gpointer user_data)
{
gchar *signame = g_strconcat ("notify::", G_PARAM_SPEC (key)->name, NULL);
g_signal_connect (G_OBJECT (value),
signame, G_CALLBACK (gst_element_prop_changed_cb),
GES_TRACK_ELEMENT (user_data));
g_free (signame);
}
static void
connect_properties_signals (GESTrackElement * object)
{
g_hash_table_foreach (object->priv->children_props,
(GHFunc) connect_signal, object);
}
/* default 'create_nle_object' virtual method implementation */
static GstElement *
ges_track_element_create_nle_object_func (GESTrackElement * self)
@ -768,22 +687,6 @@ done:
return res;
}
static gboolean
strv_find_str (const gchar ** strv, const char *str)
{
guint i;
if (strv == NULL)
return FALSE;
for (i = 0; strv[i]; i++) {
if (g_strcmp0 (strv[i], str) == 0)
return TRUE;
}
return FALSE;
}
/**
* ges_track_element_add_children_props:
* @self: The #GESTrackElement to set chidlren props on
@ -830,8 +733,8 @@ ges_track_element_add_children_props (GESTrackElement * self,
}
if (pspec->flags & G_PARAM_WRITABLE) {
g_hash_table_insert (self->priv->children_props,
g_param_spec_ref (pspec), gst_object_ref (element));
ges_timeline_element_add_child_property (GES_TIMELINE_ELEMENT (self),
pspec, G_OBJECT (element));
GST_LOG_OBJECT (self,
"added property %s to controllable properties successfully !",
whitelist[i]);
@ -841,8 +744,6 @@ ges_track_element_add_children_props (GESTrackElement * self,
whitelist[i], gst_element_get_name (element));
}
connect_properties_signals (self);
return;
}
@ -881,8 +782,8 @@ ges_track_element_add_children_props (GESTrackElement * self,
for (i = 0; i < nb_specs; i++) {
if ((parray[i]->flags & G_PARAM_WRITABLE) &&
(!whitelist || strv_find_str (whitelist, parray[i]->name))) {
g_hash_table_insert (self->priv->children_props,
g_param_spec_ref (parray[i]), gst_object_ref (child));
ges_timeline_element_add_child_property (GES_TIMELINE_ELEMENT
(self), parray[i], G_OBJECT (child));
}
}
g_free (parray);
@ -915,8 +816,6 @@ ges_track_element_add_children_props (GESTrackElement * self,
g_value_unset (&item);
}
gst_iterator_free (it);
connect_properties_signals (self);
}
/* INTERNAL USAGE */
@ -1080,18 +979,15 @@ ges_track_element_is_active (GESTrackElement * object)
* Returns: TRUE if @element and @pspec could be found. FALSE otherwise. In that
* case the values for @pspec and @element are not modified. Unref @element after
* usage.
*
* Deprecated: Use #ges_timeline_element_lookup_child
*/
gboolean
ges_track_element_lookup_child (GESTrackElement * object,
const gchar * prop_name, GstElement ** element, GParamSpec ** pspec)
{
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);
return class->lookup_child (object, prop_name, element, pspec);
return ges_timeline_element_lookup_child (GES_TIMELINE_ELEMENT (object),
prop_name, ((GObject **) element), pspec);
}
/**
@ -1101,26 +997,19 @@ ges_track_element_lookup_child (GESTrackElement * object,
* @value: the value
*
* Sets a property of a child of @object.
*
* Deprecated: Use #ges_timeline_element_set_child_property_by_spec
*/
void
ges_track_element_set_child_property_by_pspec (GESTrackElement * object,
GParamSpec * pspec, GValue * value)
{
GstElement *element;
g_return_if_fail (GES_IS_TRACK_ELEMENT (object));
if (!ges_track_element_lookup_child (object, pspec->name, &element, &pspec))
goto not_found;
g_object_set_property (G_OBJECT (element), pspec->name, value);
ges_timeline_element_set_child_property_by_pspec (GES_TIMELINE_ELEMENT
(object), pspec, value);
return;
not_found:
{
GST_ERROR ("The %s property doesn't exist", pspec->name);
return;
}
}
/**
@ -1134,62 +1023,15 @@ not_found:
* that have the same property name, you can distinguish them using the following
* syntax: 'ClasseName::property_name' as property name. If you don't, the
* corresponding property of the first element found will be set.
*
* Deprecated: Use #ges_timeline_element_set_child_property_valist
*/
void
ges_track_element_set_child_property_valist (GESTrackElement * object,
const gchar * first_property_name, va_list var_args)
{
const gchar *name;
GParamSpec *pspec;
GstElement *element;
gchar *error = NULL;
GValue value = { 0, };
g_return_if_fail (GES_IS_TRACK_ELEMENT (object));
name = first_property_name;
/* Note: This part is in big part copied from the gst_child_object_set_valist
* method. */
/* iterate over pairs */
while (name) {
if (!ges_track_element_lookup_child (object, name, &element, &pspec))
goto not_found;
#if GLIB_CHECK_VERSION(2,23,3)
G_VALUE_COLLECT_INIT (&value, pspec->value_type, var_args,
G_VALUE_NOCOPY_CONTENTS, &error);
#else
g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
G_VALUE_COLLECT (&value, var_args, G_VALUE_NOCOPY_CONTENTS, &error);
#endif
if (error)
goto cant_copy;
g_object_set_property (G_OBJECT (element), pspec->name, &value);
gst_object_unref (element);
g_value_unset (&value);
name = va_arg (var_args, gchar *);
}
return;
not_found:
{
GST_WARNING ("No property %s in OBJECT\n", name);
return;
}
cant_copy:
{
GST_WARNING ("error copying value %s in object %p: %s", pspec->name, object,
error);
g_value_unset (&value);
return;
}
ges_timeline_element_set_child_property_valist (GES_TIMELINE_ELEMENT (object),
first_property_name, var_args);
}
/**
@ -1203,6 +1045,8 @@ cant_copy:
* that have the same property name, you can distinguish them using the following
* syntax: 'ClasseName::property_name' as property name. If you don't, the
* corresponding property of the first element found will be set.
*
* Deprecated: Use #ges_timeline_element_set_child_properties
*/
void
ges_track_element_set_child_properties (GESTrackElement * object,
@ -1229,50 +1073,15 @@ ges_track_element_set_child_properties (GESTrackElement * object,
* that have the same property name, you can distinguish them using the following
* syntax: 'ClasseName::property_name' as property name. If you don't, the
* corresponding property of the first element found will be set.
*
* Deprecated: Use #ges_timeline_element_get_child_property_valist
*/
void
ges_track_element_get_child_property_valist (GESTrackElement * object,
const gchar * first_property_name, va_list var_args)
{
const gchar *name;
gchar *error = NULL;
GValue value = { 0, };
GParamSpec *pspec;
GstElement *element;
g_return_if_fail (G_IS_OBJECT (object));
name = first_property_name;
/* This part is in big part copied from the gst_child_object_get_valist method */
while (name) {
if (!ges_track_element_lookup_child (object, name, &element, &pspec))
goto not_found;
g_value_init (&value, pspec->value_type);
g_object_get_property (G_OBJECT (element), pspec->name, &value);
gst_object_unref (element);
G_VALUE_LCOPY (&value, var_args, 0, &error);
if (error)
goto cant_copy;
g_value_unset (&value);
name = va_arg (var_args, gchar *);
}
return;
not_found:
{
GST_WARNING ("no property %s in object", name);
return;
}
cant_copy:
{
GST_WARNING ("error copying value %s in object %p: %s", pspec->name, object,
error);
g_value_unset (&value);
return;
}
ges_timeline_element_get_child_property_valist (GES_TIMELINE_ELEMENT (object),
first_property_name, var_args);
}
/**
@ -1285,23 +1094,16 @@ cant_copy:
*
* Returns: (transfer full) (array length=n_properties): an array of #GParamSpec* which should be freed after use or
* %NULL if something went wrong
*
* Deprecated: Use #ges_timeline_element_list_children_properties
*/
GParamSpec **
ges_track_element_list_children_properties (GESTrackElement * object,
guint * n_properties)
{
GParamSpec **ret;
GESTrackElementClass *class;
g_return_val_if_fail (GES_IS_TRACK_ELEMENT (object), NULL);
class = GES_TRACK_ELEMENT_GET_CLASS (object);
ret = class->list_children_properties (object, n_properties);
g_qsort_with_data (ret, *n_properties, sizeof (GParamSpec *),
(GCompareDataFunc) compare_gparamspec, NULL);
return ret;
return
ges_timeline_element_list_children_properties (GES_TIMELINE_ELEMENT
(object), n_properties);
}
/**
@ -1312,6 +1114,8 @@ ges_track_element_list_children_properties (GESTrackElement * object,
* name/return location pairs, followed by NULL
*
* Gets properties of a child of @object.
*
* Deprecated: Use #ges_timeline_element_get_child_properties
*/
void
ges_track_element_get_child_properties (GESTrackElement * object,
@ -1334,28 +1138,15 @@ ges_track_element_get_child_properties (GESTrackElement * object,
* @value: (out): return location for the value
*
* Gets a property of a child of @object.
*
* Deprecated: Use #ges_timeline_element_get_child_property_by_pspec
*/
void
ges_track_element_get_child_property_by_pspec (GESTrackElement * object,
GParamSpec * pspec, GValue * value)
{
GstElement *element;
g_return_if_fail (GES_IS_TRACK_ELEMENT (object));
element = g_hash_table_lookup (object->priv->children_props, pspec);
if (!element)
goto not_found;
g_object_get_property (G_OBJECT (element), pspec->name, value);
return;
not_found:
{
GST_ERROR ("The %s property doesn't exist", pspec->name);
return;
}
ges_timeline_element_get_child_property_by_pspec (GES_TIMELINE_ELEMENT
(object), pspec, value);
}
/**
@ -1371,104 +1162,53 @@ not_found:
* is much more convenient for C programming.
*
* Returns: %TRUE if the property was set, %FALSE otherwize
*
* Deprecated: use #ges_timeline_element_set_child_property instead
*/
gboolean
ges_track_element_set_child_property (GESTrackElement * object,
const gchar * property_name, GValue * value)
{
GParamSpec *pspec;
GstElement *element;
g_return_val_if_fail (GES_IS_TRACK_ELEMENT (object), FALSE);
if (!ges_track_element_lookup_child (object, property_name, &element, &pspec))
goto not_found;
g_object_set_property (G_OBJECT (element), pspec->name, value);
gst_object_unref (element);
g_param_spec_unref (pspec);
return TRUE;
not_found:
{
GST_WARNING_OBJECT (object, "The %s property doesn't exist", property_name);
return FALSE;
}
return ges_timeline_element_set_child_property (GES_TIMELINE_ELEMENT (object),
property_name, value);
}
/**
* ges_track_element_get_child_property:
* @object: The origin #GESTrackElement
* @property_name: The name of the property
* @value: (out): return location for the property value, it will
* be initialized if it is initialized with 0
*
* In general, a copy is made of the property contents and
* the caller is responsible for freeing the memory by calling
* g_value_unset().
*
* Gets a property of a GstElement contained in @object.
*
* Note that #ges_track_element_get_child_property is really
* intended for language bindings, #ges_track_element_get_child_properties
* is much more convenient for C programming.
*
* Returns: %TRUE if the property was found, %FALSE otherwize
*/
* ges_track_element_get_child_property:
* @object: The origin #GESTrackElement
* @property_name: The name of the property
* @value: (out): return location for the property value, it will
* be initialized if it is initialized with 0
*
* In general, a copy is made of the property contents and
* the caller is responsible for freeing the memory by calling
* g_value_unset().
*
* Gets a property of a GstElement contained in @object.
*
* Note that #ges_track_element_get_child_property is really
* intended for language bindings, #ges_track_element_get_child_properties
* is much more convenient for C programming.
*
* Returns: %TRUE if the property was found, %FALSE otherwize
*
* Deprecated: Use #ges_timeline_element_get_child_property
*/
gboolean
ges_track_element_get_child_property (GESTrackElement * object,
const gchar * property_name, GValue * value)
{
GParamSpec *pspec;
GstElement *element;
g_return_val_if_fail (GES_IS_TRACK_ELEMENT (object), FALSE);
if (!ges_track_element_lookup_child (object, property_name, &element, &pspec))
goto not_found;
if (G_VALUE_TYPE (value) == G_TYPE_INVALID)
g_value_init (value, pspec->value_type);
g_object_get_property (G_OBJECT (element), pspec->name, value);
gst_object_unref (element);
g_param_spec_unref (pspec);
return TRUE;
not_found:
{
GST_WARNING_OBJECT (object, "The %s property doesn't exist", property_name);
return FALSE;
}
return ges_timeline_element_get_child_property (GES_TIMELINE_ELEMENT (object),
property_name, value);
}
static GParamSpec **
default_list_children_properties (GESTrackElement * object,
guint * n_properties)
{
GParamSpec **pspec, *spec;
GHashTableIter iter;
gpointer key, value;
guint i = 0;
*n_properties = g_hash_table_size (object->priv->children_props);
pspec = g_new (GParamSpec *, *n_properties);
g_hash_table_iter_init (&iter, object->priv->children_props);
while (g_hash_table_iter_next (&iter, &key, &value)) {
spec = G_PARAM_SPEC (key);
pspec[i] = g_param_spec_ref (spec);
i++;
}
return pspec;
return
GES_TIMELINE_ELEMENT_GET_CLASS (object)->list_children_properties
(GES_TIMELINE_ELEMENT (object), n_properties);
}
void

View file

@ -80,6 +80,7 @@ struct _GESTrackElement {
* The default implementation will create an object
* of type @nleobject_factorytype and call
* @create_element.
* DeprecatedUse: GESTimelineElement.list_children_properties instead
* @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
@ -90,6 +91,7 @@ struct _GESTrackElement {
* has been overriden so that we tweak the name passed has parametter
* to rename "background" to "foreground-backend" making our API
* understandable.
* Deprecated: use GESTimelineElement.lookup_child instead
*
* Subclasses can override the @create_nle_object method to override what type
* of GNonLin object will be created.
@ -114,8 +116,6 @@ 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,

View file

@ -354,7 +354,7 @@ GST_START_TEST (test_effect_set_properties)
GESLayer *layer;
GESTrack *track_video;
GESEffectClip *effect_clip;
GESTrackElement *effect;
GESTimelineElement *effect;
guint scratch_line, n_props, i;
gboolean color_aging;
GParamSpec **pspecs, *spec;
@ -377,21 +377,21 @@ GST_START_TEST (test_effect_set_properties)
ges_layer_add_clip (layer, (GESClip *) effect_clip);
effect = GES_TRACK_ELEMENT (ges_effect_new ("agingtv"));
effect = GES_TIMELINE_ELEMENT (ges_effect_new ("agingtv"));
fail_unless (ges_container_add (GES_CONTAINER (effect_clip),
GES_TIMELINE_ELEMENT (effect)));
fail_unless (ges_track_element_get_track (GES_TRACK_ELEMENT (effect)) ==
track_video);
ges_track_element_set_child_properties (effect,
ges_timeline_element_set_child_properties (effect,
"GstAgingTV::scratch-lines", 17, "color-aging", FALSE, NULL);
ges_track_element_get_child_properties (effect,
ges_timeline_element_get_child_properties (effect,
"GstAgingTV::scratch-lines", &scratch_line,
"color-aging", &color_aging, NULL);
fail_unless (scratch_line == 17);
fail_unless (color_aging == FALSE);
pspecs = ges_track_element_list_children_properties (effect, &n_props);
pspecs = ges_timeline_element_list_children_properties (effect, &n_props);
fail_unless (n_props == 7);
spec = pspecs[0];
@ -404,8 +404,8 @@ GST_START_TEST (test_effect_set_properties)
g_value_init (&nval, G_TYPE_UINT);
g_value_set_uint (&val, 10);
ges_track_element_set_child_property_by_pspec (effect, spec, &val);
ges_track_element_get_child_property_by_pspec (effect, spec, &nval);
ges_timeline_element_set_child_property_by_pspec (effect, spec, &val);
ges_timeline_element_get_child_property_by_pspec (effect, spec, &nval);
fail_unless (g_value_get_uint (&nval) == 10);
for (i = 0; i < n_props; i++) {
@ -444,7 +444,7 @@ GST_START_TEST (test_clip_signals)
GESLayer *layer;
GESTrack *track_video;
GESEffectClip *effect_clip;
GESEffect *effect;
GESTimelineElement *effect;
GValue val = { 0, };
gboolean effect_added = FALSE;
@ -466,9 +466,8 @@ GST_START_TEST (test_clip_signals)
ges_layer_add_clip (layer, (GESClip *) effect_clip);
effect = ges_effect_new ("agingtv");
fail_unless (ges_container_add (GES_CONTAINER (effect_clip),
GES_TIMELINE_ELEMENT (effect)));
effect = GES_TIMELINE_ELEMENT (ges_effect_new ("agingtv"));
fail_unless (ges_container_add (GES_CONTAINER (effect_clip), effect));
fail_unless (effect_added);
g_signal_handlers_disconnect_by_func (effect_clip, effect_added_cb,
&effect_added);
@ -477,11 +476,11 @@ GST_START_TEST (test_clip_signals)
g_signal_connect (effect, "deep-notify", (GCallback) deep_prop_changed_cb,
effect);
ges_track_element_set_child_properties (GES_TRACK_ELEMENT (effect),
ges_timeline_element_set_child_properties (effect,
"GstAgingTV::scratch-lines", 17, NULL);
g_value_init (&val, G_TYPE_UINT);
ges_track_element_get_child_property (GES_TRACK_ELEMENT (effect),
ges_timeline_element_get_child_property (effect,
"GstAgingTV::scratch-lines", &val);
fail_unless (G_VALUE_HOLDS_UINT (&val));
g_value_unset (&val);

View file

@ -249,7 +249,7 @@ _test_project (GESProject * project, GESTimeline * timeline)
if (GES_IS_BASE_EFFECT (trackelement)) {
guint nb_scratch_lines;
ges_track_element_get_child_properties (trackelement,
ges_timeline_element_get_child_properties (tmptrackelement->data,
"scratch-lines", &nb_scratch_lines, NULL);
assert_equals_int (nb_scratch_lines, 12);
@ -339,10 +339,10 @@ _add_properties (GESTimeline * timeline)
/* Adding children properties */
else if (GES_IS_VIDEO_SOURCE (element)) {
gint64 posx = 42;
ges_track_element_set_child_properties (element, "posx", posx,
NULL);
ges_track_element_get_child_properties (element, "posx", &posx,
NULL);
ges_timeline_element_set_child_properties (GES_TIMELINE_ELEMENT
(element), "posx", posx, NULL);
ges_timeline_element_get_child_properties (GES_TIMELINE_ELEMENT
(element), "posx", &posx, NULL);
fail_unless_equals_int64 (posx, 42);
}
}
@ -406,8 +406,8 @@ _check_properties (GESTimeline * timeline)
else if (GES_IS_VIDEO_SOURCE (element)) {
/* Init 'posx' with a wrong value */
gint64 posx = 27;
ges_track_element_get_child_properties (element, "posx", &posx,
NULL);
ges_timeline_element_get_child_properties (GES_TIMELINE_ELEMENT
(element), "posx", &posx, NULL);
fail_unless_equals_int64 (posx, 42);
}
}

View file

@ -1265,9 +1265,11 @@ _set_track_element_width_height (GESTrackElement * trksrc, gint wvalue,
g_value_set_int (&width, wvalue);
g_value_set_int (&height, hvalue);
if (wvalue >= 0)
ges_track_element_set_child_property (trksrc, "width", &width);
ges_timeline_element_set_child_property (GES_TIMELINE_ELEMENT (trksrc),
"width", &width);
if (hvalue >= 0)
ges_track_element_set_child_property (trksrc, "height", &height);
ges_timeline_element_set_child_property (GES_TIMELINE_ELEMENT (trksrc),
"height", &height);
}
static gboolean
@ -1285,8 +1287,10 @@ check_frame_positionner_size (GESClip * clip, gint width, gint height)
g_value_init (&val_width, G_TYPE_INT);
g_value_init (&val_height, G_TYPE_INT);
ges_track_element_get_child_property (trksrc, "width", &val_width);
ges_track_element_get_child_property (trksrc, "height", &val_height);
ges_timeline_element_get_child_property (GES_TIMELINE_ELEMENT (trksrc),
"width", &val_width);
ges_timeline_element_get_child_property (GES_TIMELINE_ELEMENT (trksrc),
"height", &val_height);
real_width = g_value_get_int (&val_width);
real_height = g_value_get_int (&val_height);