diff options
author | Thibault Saunier <tsaunier@gnome.org> | 2015-02-20 12:24:49 +0100 |
---|---|---|
committer | Thibault Saunier <tsaunier@gnome.org> | 2015-03-18 20:33:48 +0100 |
commit | f470222f3db8a9042818103a232f7b84320539b7 (patch) | |
tree | ab2031ad7c157dd56276842a98a2ddcb9b4e9e09 /ges | |
parent | 9fe15ef4354dc1d878dbdec80908ac8541bc6131 (diff) |
Revert "ges: Move the notion of children properties to GESTimelineElement"
I got some trouble with
arc land
and I wanted to push the 3 commit coming after this revert as 3
different commits but they ended up being all squash into one single
commit, which is clearly not cool for later bisecting and blaming.
Reverting that commit and re pushing those 3 commits as they were
supposed to be.
This reverts commit 9fe15ef4354dc1d878dbdec80908ac8541bc6131.
Diffstat (limited to 'ges')
-rw-r--r-- | ges/ges-container.c | 86 | ||||
-rw-r--r-- | ges/ges-timeline-element.c | 539 | ||||
-rw-r--r-- | ges/ges-timeline-element.h | 59 | ||||
-rw-r--r-- | ges/ges-timeline.c | 31 | ||||
-rw-r--r-- | ges/ges-timeline.h | 1 | ||||
-rw-r--r-- | ges/ges-track-element.c | 418 | ||||
-rw-r--r-- | ges/ges-track-element.h | 4 |
7 files changed, 343 insertions, 795 deletions
diff --git a/ges/ges-container.c b/ges/ges-container.c index 7b26f89e..c4010591 100644 --- a/ges/ges-container.c +++ b/ges/ges-container.c @@ -185,86 +185,6 @@ _set_duration (GESTimelineElement * element, GstClockTime duration) return TRUE; } -static void -_ges_container_add_child_properties (GESContainer * container, - GESTimelineElement * child) -{ - guint n_props, i; - - GParamSpec **child_props = - ges_timeline_element_list_children_properties (child, - &n_props); - - for (i = 0; i < n_props; i++) { - GObject *prop_child; - - if (ges_timeline_element_lookup_child (child, child_props[i]->name, - &prop_child, NULL)) { - ges_timeline_element_add_child_property (GES_TIMELINE_ELEMENT (container), - child_props[i], prop_child); - - } - - g_param_spec_unref (child_props[i]); - } - - g_free (child_props); -} - -static void -_ges_container_remove_child_properties (GESContainer * container, - GESTimelineElement * child) -{ - guint n_props, i; - - GParamSpec **child_props = - ges_timeline_element_list_children_properties (child, - &n_props); - - for (i = 0; i < n_props; i++) { - GObject *prop_child; - - if (ges_timeline_element_lookup_child (child, child_props[i]->name, - &prop_child, NULL)) { - ges_timeline_element_remove_child_property (GES_TIMELINE_ELEMENT - (container), child_props[i]); - - } - - g_param_spec_unref (child_props[i]); - } - - g_free (child_props); -} - -static GParamSpec ** -_list_children_properties (GESTimelineElement * self, guint * n_properties) -{ - GList *tmp; - - for (tmp = GES_CONTAINER_CHILDREN (self); tmp; tmp = tmp->next) - _ges_container_add_child_properties (GES_CONTAINER (self), tmp->data); - - return - GES_TIMELINE_ELEMENT_CLASS - (ges_container_parent_class)->list_children_properties (self, - n_properties); -} - -static gboolean -_lookup_child (GESTimelineElement * self, const gchar * prop_name, - GObject ** child, GParamSpec ** pspec) -{ - GList *tmp; - - for (tmp = GES_CONTAINER_CHILDREN (self); tmp; tmp = tmp->next) - _ges_container_add_child_properties (GES_CONTAINER (self), tmp->data); - - return - GES_TIMELINE_ELEMENT_CLASS (ges_container_parent_class)->lookup_child - (self, prop_name, child, pspec); -} - /****************************************** * * * GObject virtual methods implementation * @@ -361,8 +281,6 @@ ges_container_class_init (GESContainerClass * klass) element_class->set_start = _set_start; element_class->set_duration = _set_duration; element_class->set_inpoint = _set_inpoint; - element_class->list_children_properties = _list_children_properties; - element_class->lookup_child = _lookup_child; /* No default implementations */ klass->remove_child = NULL; @@ -640,8 +558,6 @@ ges_container_add (GESContainer * container, GESTimelineElement * child) return FALSE; } - _ges_container_add_child_properties (container, child); - g_signal_emit (container, ges_container_signals[CHILD_ADDED_SIGNAL], 0, child); @@ -686,8 +602,6 @@ ges_container_remove (GESContainer * container, GESTimelineElement * child) /* Let it live removing from our mappings */ g_hash_table_remove (priv->mappings, child); - _ges_container_remove_child_properties (container, child); - g_signal_emit (container, ges_container_signals[CHILD_REMOVED_SIGNAL], 0, child); gst_object_unref (child); diff --git a/ges/ges-timeline-element.c b/ges/ges-timeline-element.c index 0ddd28d9..3ace821a 100644 --- a/ges/ges-timeline-element.c +++ b/ges/ges-timeline-element.c @@ -26,14 +26,11 @@ * 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; @@ -70,90 +67,13 @@ 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) @@ -249,10 +169,6 @@ 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 @@ -352,21 +268,6 @@ 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; @@ -381,9 +282,6 @@ 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 @@ -1184,440 +1082,3 @@ 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); -} diff --git a/ges/ges-timeline-element.h b/ges/ges-timeline-element.h index ba0d5615..d787d668 100644 --- a/ges/ges-timeline-element.h +++ b/ges/ges-timeline-element.h @@ -185,15 +185,11 @@ struct _GESTimelineElementClass gboolean (*roll_start) (GESTimelineElement *self, guint64 start); gboolean (*roll_end) (GESTimelineElement *self, guint64 end); 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); + void (*deep_copy) (GESTimelineElement *self, GESTimelineElement *copy); /*< private > */ /* Padding for API extension */ - gpointer _ges_reserved[GES_PADDING_LARGE - 2]; + gpointer _ges_reserved[GES_PADDING_LARGE]; }; GType ges_timeline_element_get_type (void) G_GNUC_CONST; @@ -224,57 +220,6 @@ 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 diff --git a/ges/ges-timeline.c b/ges/ges-timeline.c index 5b67253a..b753f9e2 100644 --- a/ges/ges-timeline.c +++ b/ges/ges-timeline.c @@ -3214,34 +3214,3 @@ ges_timeline_is_empty (GESTimeline * timeline) return TRUE; } - -/** - * ges_timeline_get_layer: - * @timeline: The #GESTimeline to retrive a layer from - * @priority: The priority of the layer to find - * - * Retrieve the layer with @priority as a priority - * - * Returns: A #GESLayer or %NULL if no layer with @priority was found - * - * Since 1.6 - */ -GESLayer * -ges_timeline_get_layer (GESTimeline * timeline, guint priority) -{ - GList *tmp; - GESLayer *layer = NULL; - - for (tmp = timeline->layers; tmp; tmp = tmp->next) { - GESLayer *tmp_layer = GES_LAYER (tmp->data); - guint tmp_priority; - - g_object_get (tmp_layer, "priority", &tmp_priority, NULL); - if (tmp_priority == priority) { - layer = gst_object_ref (tmp_layer); - break; - } - } - - return layer; -} diff --git a/ges/ges-timeline.h b/ges/ges-timeline.h index fd5e6ec2..bbcc83aa 100644 --- a/ges/ges-timeline.h +++ b/ges/ges-timeline.h @@ -109,7 +109,6 @@ gboolean ges_timeline_add_layer (GESTimeline *timeline, GESLayer *layer); GESLayer * ges_timeline_append_layer (GESTimeline * timeline); gboolean ges_timeline_remove_layer (GESTimeline *timeline, GESLayer *layer); GList* ges_timeline_get_layers (GESTimeline *timeline); -GESLayer* ges_timeline_get_layer (GESTimeline *timeline, guint priority); gboolean ges_timeline_add_track (GESTimeline *timeline, GESTrack *track); gboolean ges_timeline_remove_track (GESTimeline *timeline, GESTrack *track); diff --git a/ges/ges-track-element.c b/ges/ges-track-element.c index dab9a7ef..fdeaa8ac 100644 --- a/ges/ges-track-element.c +++ b/ges/ges-track-element.c @@ -29,11 +29,13 @@ * 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); @@ -52,6 +54,11 @@ 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; @@ -85,6 +92,7 @@ static GParamSpec *properties[PROP_LAST]; enum { + DEEP_NOTIFY, CONTROL_BINDING_ADDED, LAST_SIGNAL }; @@ -94,6 +102,11 @@ 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); @@ -112,27 +125,42 @@ static gboolean _lookup_child (GESTrackElement * object, const gchar * prop_name, GstElement ** element, GParamSpec ** pspec) { - 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; + 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 FALSE; + return res; } + static void ges_track_element_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec) @@ -178,6 +206,7 @@ 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); @@ -249,6 +278,21 @@ ges_track_element_class_init (GESTrackElementClass * klass) 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 * @control_binding: the #GstControlBinding that has been added @@ -286,6 +330,16 @@ 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 @@ -537,6 +591,33 @@ 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) @@ -687,6 +768,22 @@ 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 @@ -733,8 +830,8 @@ ges_track_element_add_children_props (GESTrackElement * self, } if (pspec->flags & G_PARAM_WRITABLE) { - ges_timeline_element_add_child_property (GES_TIMELINE_ELEMENT (self), - pspec, G_OBJECT (element)); + g_hash_table_insert (self->priv->children_props, + g_param_spec_ref (pspec), gst_object_ref (element)); GST_LOG_OBJECT (self, "added property %s to controllable properties successfully !", whitelist[i]); @@ -744,6 +841,8 @@ ges_track_element_add_children_props (GESTrackElement * self, whitelist[i], gst_element_get_name (element)); } + + connect_properties_signals (self); return; } @@ -782,8 +881,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))) { - ges_timeline_element_add_child_property (GES_TIMELINE_ELEMENT - (self), parray[i], G_OBJECT (child)); + g_hash_table_insert (self->priv->children_props, + g_param_spec_ref (parray[i]), gst_object_ref (child)); } } g_free (parray); @@ -816,6 +915,8 @@ ges_track_element_add_children_props (GESTrackElement * self, g_value_unset (&item); } gst_iterator_free (it); + + connect_properties_signals (self); } /* INTERNAL USAGE */ @@ -979,15 +1080,18 @@ 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) { - return ges_timeline_element_lookup_child (GES_TIMELINE_ELEMENT (object), - prop_name, ((GObject **) element), 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); } /** @@ -997,19 +1101,26 @@ 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)); - ges_timeline_element_set_child_property_by_pspec (GES_TIMELINE_ELEMENT - (object), pspec, value); + if (!ges_track_element_lookup_child (object, pspec->name, &element, &pspec)) + goto not_found; + + g_object_set_property (G_OBJECT (element), pspec->name, value); return; + +not_found: + { + GST_ERROR ("The %s property doesn't exist", pspec->name); + return; + } } /** @@ -1023,15 +1134,62 @@ ges_track_element_set_child_property_by_pspec (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_set_child_property_valist */ void ges_track_element_set_child_property_valist (GESTrackElement * object, const gchar * first_property_name, va_list var_args) { - ges_timeline_element_set_child_property_valist (GES_TIMELINE_ELEMENT (object), - first_property_name, 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; + } } /** @@ -1045,8 +1203,6 @@ ges_track_element_set_child_property_valist (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_set_child_properties */ void ges_track_element_set_child_properties (GESTrackElement * object, @@ -1073,15 +1229,50 @@ 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) { - ges_timeline_element_get_child_property_valist (GES_TIMELINE_ELEMENT (object), - first_property_name, 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; + } } /** @@ -1094,16 +1285,23 @@ ges_track_element_get_child_property_valist (GESTrackElement * object, * * 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) { - return - ges_timeline_element_list_children_properties (GES_TIMELINE_ELEMENT - (object), 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; } /** @@ -1114,8 +1312,6 @@ 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, @@ -1138,15 +1334,28 @@ 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) { - ges_timeline_element_get_child_property_by_pspec (GES_TIMELINE_ELEMENT - (object), pspec, 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; + } } /** @@ -1162,53 +1371,104 @@ ges_track_element_get_child_property_by_pspec (GESTrackElement * object, * 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) { - return ges_timeline_element_set_child_property (GES_TIMELINE_ELEMENT (object), - property_name, 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; + } } /** - * 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 - */ +* 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 +*/ gboolean ges_track_element_get_child_property (GESTrackElement * object, const gchar * property_name, GValue * value) { - return ges_timeline_element_get_child_property (GES_TIMELINE_ELEMENT (object), - property_name, 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; + } } static GParamSpec ** default_list_children_properties (GESTrackElement * object, guint * n_properties) { - return - GES_TIMELINE_ELEMENT_GET_CLASS (object)->list_children_properties - (GES_TIMELINE_ELEMENT (object), 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; } void diff --git a/ges/ges-track-element.h b/ges/ges-track-element.h index 370a0831..67249ec3 100644 --- a/ges/ges-track-element.h +++ b/ges/ges-track-element.h @@ -80,7 +80,6 @@ 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 @@ -91,7 +90,6 @@ 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. @@ -116,6 +114,8 @@ 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, |