From 795b8df1b6a17b888b21ebea7a54a57482e34655 Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Thu, 28 Feb 2013 22:27:50 -0300 Subject: [PATCH] Implement GESContainer + Fix unit tests + Minor enhancement in unit tests API changes: ----------- * ges_track_element_get_clip -> ges_timeline_element_get_parent * ges_clip_add_track_element -> ges_container_add * ges_clip_release_track_element -> ges_container_remove * ges_clip_get_track_elements -> ges_container_get_children (or GES_CONTAINER_CHILDREN) --- docs/libs/ges-docs.sgml | 1 + docs/libs/ges-sections.txt | 26 +- ges/Makefile.am | 2 + ges/ges-auto-transition.c | 10 +- ges/ges-base-xml-formatter.c | 2 +- ges/ges-clip.c | 987 +++++------------------------ ges/ges-clip.h | 51 +- ges/ges-container.c | 671 ++++++++++++++++++++ ges/ges-container.h | 119 ++++ ges/ges-internal.h | 11 +- ges/ges-pitivi-formatter.c | 17 +- ges/ges-simple-timeline-layer.c | 2 +- ges/ges-source-clip.c | 3 - ges/ges-test-clip.c | 36 +- ges/ges-text-overlay-clip.c | 63 +- ges/ges-timeline.c | 150 +++-- ges/ges-title-clip.c | 43 +- ges/ges-track-element.c | 68 +- ges/ges-track-element.h | 5 - ges/ges-track.c | 7 +- ges/ges-transition-clip.c | 40 +- ges/ges-types.h | 3 + ges/ges-uri-clip.c | 16 +- tests/check/ges/backgroundsource.c | 20 +- tests/check/ges/basic.c | 177 ++---- tests/check/ges/clip.c | 88 +-- tests/check/ges/effects.c | 208 +++--- tests/check/ges/layer.c | 7 +- tests/check/ges/overlays.c | 5 +- tests/check/ges/simplelayer.c | 6 +- tests/check/ges/timelineedition.c | 28 +- tests/check/ges/titles.c | 5 +- tests/check/ges/transition.c | 16 +- tests/check/ges/uriclip.c | 21 +- tests/examples/ges-ui.c | 3 +- tests/examples/transition.c | 10 +- 36 files changed, 1407 insertions(+), 1520 deletions(-) create mode 100644 ges/ges-container.c create mode 100644 ges/ges-container.h diff --git a/docs/libs/ges-docs.sgml b/docs/libs/ges-docs.sgml index c871945e37..0673ffb435 100644 --- a/docs/libs/ges-docs.sgml +++ b/docs/libs/ges-docs.sgml @@ -37,6 +37,7 @@ platform as well as Windows. It is released under the GNU Library General Public + diff --git a/docs/libs/ges-sections.txt b/docs/libs/ges-sections.txt index feba8dc375..c8e46dee92 100644 --- a/docs/libs/ges-sections.txt +++ b/docs/libs/ges-sections.txt @@ -98,7 +98,6 @@ ges_track_element_set_active ges_track_element_set_locked ges_track_element_is_locked ges_track_element_get_track -ges_track_element_get_clip ges_track_element_get_gnlobject ges_track_element_get_element ges_track_element_get_max_duration @@ -117,7 +116,6 @@ ges_track_element_edit ges_track_element_copy GESTrackElementPrivate -ges_track_element_set_clip ges_track_element_set_track ges_track_element_get_type GES_IS_TRACK_ELEMENT @@ -359,6 +357,27 @@ GES_IS_TIMELINE_ELEMENT_CLASS GES_TIMELINE_ELEMENT_GET_CLASS +
+ges-container +GESContainer +GESContainer +GESContainerClass +GES_CONTAINER_CHILDREN +GES_CONTAINER_HEIGHT +ges_container_get_children +ges_container_add +ges_container_remove + +GESContainerPrivate +ges_container_get_type +GES_TYPE_CONTAINER +GES_CONTAINER +GES_CONTAINER_CLASS +GES_IS_CONTAINER +GES_IS_CONTAINER_CLASS +GES_CONTAINER_GET_CLASS +
+
ges-clip GESClip @@ -369,7 +388,6 @@ GESCreateTrackElementsFunc GESFillTrackElementFunc ges_clip_get_layer ges_clip_find_track_element -ges_clip_add_track_element ges_clip_add_asset ges_clip_get_top_effects ges_clip_get_top_effect_position @@ -388,8 +406,6 @@ ges_clip_create_track_elements ges_clip_create_track_element ges_clip_fill_track_element ges_clip_is_moving_from_layer -ges_clip_release_track_element -ges_clip_get_track_elements ges_clip_set_layer ges_clip_set_moving_from_layer GESClipPrivate diff --git a/ges/Makefile.am b/ges/Makefile.am index 87bae5cccb..cca8129aaa 100644 --- a/ges/Makefile.am +++ b/ges/Makefile.am @@ -57,6 +57,7 @@ libges_@GST_API_VERSION@_la_SOURCES = \ ges-xml-formatter.c \ ges-auto-transition.c \ ges-timeline-element.c \ + ges-container.c \ ges-utils.c libges_@GST_API_VERSION@includedir = $(includedir)/gstreamer-@GST_API_VERSION@/ges/ @@ -110,6 +111,7 @@ libges_@GST_API_VERSION@include_HEADERS = \ ges-base-xml-formatter.h \ ges-xml-formatter.h \ ges-timeline-element.h \ + ges-container.h \ ges-utils.h noinst_HEADERS = \ diff --git a/ges/ges-auto-transition.c b/ges/ges-auto-transition.c index 22f3c89c22..88dafb68fd 100644 --- a/ges/ges-auto-transition.c +++ b/ges/ges-auto-transition.c @@ -73,7 +73,8 @@ _height_changed_cb (GESClip * clip, GParamSpec * arg G_GNUC_UNUSED, /* FIXME This is really not smart and we should properly implement clip * priority management at the TimelineLayer level */ _set_priority0 (GES_TIMELINE_ELEMENT (self->next_clip), - _PRIORITY (self->previous_clip) + self->previous_clip->height); + _PRIORITY (self->previous_clip) + + GES_CONTAINER_HEIGHT (self->previous_clip)); } static void @@ -138,9 +139,10 @@ ges_auto_transition_new (GESTrackElement * transition, self->next_source = next_source; self->transition = transition; - self->previous_clip = ges_track_element_get_clip (previous_source); - self->next_clip = ges_track_element_get_clip (next_source); - self->transition_clip = ges_track_element_get_clip (transition); + self->previous_clip = + GES_CLIP (GES_TIMELINE_ELEMENT_PARENT (previous_source)); + self->next_clip = GES_CLIP (GES_TIMELINE_ELEMENT_PARENT (next_source)); + self->transition_clip = GES_CLIP (GES_TIMELINE_ELEMENT_PARENT (transition)); g_signal_connect (previous_source, "notify::start", G_CALLBACK (neighbour_changed_cb), self); diff --git a/ges/ges-base-xml-formatter.c b/ges/ges-base-xml-formatter.c index 37ecd57750..a8b9f6aa4d 100644 --- a/ges/ges-base-xml-formatter.c +++ b/ges/ges-base-xml-formatter.c @@ -452,7 +452,7 @@ _add_track_element (GESFormatter * self, GESClip * clip, GST_DEBUG_OBJECT (self, "Adding track_element: %" GST_PTR_FORMAT " To : %" GST_PTR_FORMAT, trackelement, clip); - ges_clip_add_track_element (clip, trackelement); + ges_container_add (GES_CONTAINER (clip), GES_TIMELINE_ELEMENT (trackelement)); ges_track_add_element (track, trackelement); gst_structure_foreach (children_properties, (GstStructureForeachFunc) _set_child_property, trackelement); diff --git a/ges/ges-clip.c b/ges/ges-clip.c index 539cb8c8c7..3c755a5cca 100644 --- a/ges/ges-clip.c +++ b/ges/ges-clip.c @@ -42,75 +42,13 @@ ges_clip_fill_track_element_func (GESClip * clip, GESTrackElement * trackelement, GstElement * gnlobj); GList *ges_clip_create_track_elements_func (GESClip * clip, GESTrackType type); - -static gboolean _set_max_duration (GESTimelineElement * element, - GstClockTime maxduration); - -static void -track_element_start_changed_cb (GESTrackElement * child, - GParamSpec * arg G_GNUC_UNUSED, GESClip * clip); -static void -track_element_inpoint_changed_cb (GESTrackElement * child, - GParamSpec * arg G_GNUC_UNUSED, GESClip * clip); -static void -track_element_duration_changed_cb (GESTrackElement * child, - GParamSpec * arg G_GNUC_UNUSED, GESClip * clip); -static void -track_element_priority_changed_cb (GESTrackElement * child, - GParamSpec * arg G_GNUC_UNUSED, GESClip * clip); -static void update_height (GESClip * clip); - -static gint sort_base_effects (gpointer a, gpointer b, GESClip * clip); -static void -get_layer_priorities (GESTimelineLayer * layer, guint32 * layer_min_gnl_prio, - guint32 * layer_max_gnl_prio); - -static gboolean _set_start (GESTimelineElement * element, GstClockTime start); -static gboolean _set_inpoint (GESTimelineElement * element, - GstClockTime inpoint); -static gboolean _set_duration (GESTimelineElement * element, - GstClockTime duration); -static gboolean _set_priority (GESTimelineElement * element, guint32 priority); - static gboolean _ripple (GESTimelineElement * element, GstClockTime start); static gboolean _ripple_end (GESTimelineElement * element, GstClockTime end); static gboolean _roll_start (GESTimelineElement * element, GstClockTime start); static gboolean _roll_end (GESTimelineElement * element, GstClockTime end); static gboolean _trim (GESTimelineElement * element, GstClockTime start); -G_DEFINE_ABSTRACT_TYPE (GESClip, ges_clip, GES_TYPE_TIMELINE_ELEMENT); - -/* Mapping of relationship between a Clip and the TrackElements - * it controls - * - * NOTE : how do we make this public in the future ? - */ -typedef struct -{ - GESTrackElement *track_element; - gint64 start_offset; - gint64 duration_offset; - gint64 inpoint_offset; - gint32 priority_offset; - - guint start_notifyid; - guint duration_notifyid; - guint inpoint_notifyid; - guint priority_notifyid; - - /* track mapping ?? */ -} ObjectMapping; - -enum -{ - EFFECT_ADDED, - EFFECT_REMOVED, - TRACK_ELEMENT_ADDED, - TRACK_ELEMENT_REMOVED, - LAST_SIGNAL -}; - -static guint ges_clip_signals[LAST_SIGNAL] = { 0 }; +G_DEFINE_ABSTRACT_TYPE (GESClip, ges_clip, GES_TYPE_CONTAINER); struct _GESClipPrivate { @@ -122,25 +60,17 @@ struct _GESClipPrivate /* Set to TRUE when the clip is doing updates of track element * properties so we don't end up in infinite property update loops */ - gboolean ignore_notifies; gboolean is_moving; - GList *mappings; - guint nb_effects; - GESTrackElement *initiated_move; - /* The formats supported by this Clip */ GESTrackType supportedformats; - - GESAsset *asset; }; enum { PROP_0, - PROP_HEIGHT, PROP_LAYER, PROP_SUPPORTED_FORMATS, PROP_LAST @@ -148,6 +78,86 @@ enum static GParamSpec *properties[PROP_LAST]; +/**************************************************** + * * + * GESContainer virtual methods implementation * + * * + ****************************************************/ + +static void +_get_priorty_range (GESContainer * container, guint32 * min_priority, + guint32 * max_priority) +{ + GESTimelineLayer *layer = GES_CLIP (container)->priv->layer; + + if (layer) { + *min_priority = layer->min_gnl_priority; + *max_priority = layer->max_gnl_priority; + } else { + *min_priority = 0; + *max_priority = G_MAXUINT32; + } +} + +static gboolean +_add_child (GESContainer * container, GESTimelineElement * element) +{ + GList *tmp; + guint max_prio, min_prio; + GESClipPrivate *priv = GES_CLIP (container)->priv; + + /* First make sure we work with a sorted list of GESTimelineElement-s */ + _ges_container_sort_children (container); + + /* If the TrackElement is an effect: + * - We add it on top of the list of TrackEffect + * - We put all TrackObject present in the TimelineObject + * which are not BaseEffect on top of them + * FIXME: Let the full control over priorities to the user + */ + _get_priorty_range (container, &min_prio, &max_prio); + if (GES_IS_BASE_EFFECT (element)) { + + GST_DEBUG_OBJECT (container, "Adding %ith effect: %" GST_PTR_FORMAT + " Priority %i", priv->nb_effects + 1, element, + GES_TIMELINE_ELEMENT_PRIORITY (container) + priv->nb_effects); + + tmp = g_list_nth (GES_CONTAINER_CHILDREN (container), priv->nb_effects); + for (; tmp; tmp = tmp->next) + ges_timeline_element_set_priority (GES_TIMELINE_ELEMENT (tmp->data), + GES_TIMELINE_ELEMENT_PRIORITY (tmp->data) + 1); + + _set_priority0 (element, min_prio + + GES_TIMELINE_ELEMENT_PRIORITY (container) + priv->nb_effects); + priv->nb_effects++; + } else { + /* We add the track element on top of the effect list */ + _set_priority0 (element, min_prio + + GES_TIMELINE_ELEMENT_PRIORITY (container) + priv->nb_effects); + } + + /* We set the timing value of the child to ours, we avoid infinite loop + * making sure the container ignore notifies from the child */ + _ges_container_set_ignore_notifies (container, TRUE); + _set_start0 (element, GES_TIMELINE_ELEMENT_START (container)); + _set_inpoint0 (element, GES_TIMELINE_ELEMENT_INPOINT (container)); + _set_duration0 (element, GES_TIMELINE_ELEMENT_DURATION (container)); + _ges_container_set_ignore_notifies (container, FALSE); + + return TRUE; +} + +static gboolean +_remove_child (GESContainer * container, GESTimelineElement * element) +{ + if (GES_IS_BASE_EFFECT (element)) + GES_CLIP (container)->priv->nb_effects--; + + GST_FIXME_OBJECT (container, "We should set other children prios"); + + return TRUE; +} + static void ges_clip_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec) @@ -155,9 +165,6 @@ ges_clip_get_property (GObject * object, guint property_id, GESClip *clip = GES_CLIP (object); switch (property_id) { - case PROP_HEIGHT: - g_value_set_uint (value, clip->height); - break; case PROP_LAYER: g_value_set_object (value, clip->priv->layer); break; @@ -188,6 +195,7 @@ static void ges_clip_class_init (GESClipClass * klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); + GESContainerClass *container_class = GES_CONTAINER_CLASS (klass); GESTimelineElementClass *element_class = GES_TIMELINE_ELEMENT_CLASS (klass); g_type_class_add_private (klass, sizeof (GESClipPrivate)); @@ -196,19 +204,6 @@ ges_clip_class_init (GESClipClass * klass) object_class->set_property = ges_clip_set_property; klass->create_track_elements = ges_clip_create_track_elements_func; klass->create_track_element = NULL; - klass->track_element_added = NULL; - klass->track_element_released = NULL; - - /** - * GESClip:height: - * - * The span of layer priorities which this clip occupies. - */ - properties[PROP_HEIGHT] = g_param_spec_uint ("height", "Height", - "The span of priorities this clip occupies", 0, G_MAXUINT, 1, - G_PARAM_READABLE); - g_object_class_install_property (object_class, PROP_HEIGHT, - properties[PROP_HEIGHT]); /** * GESClip:supported-formats: @@ -236,78 +231,18 @@ ges_clip_class_init (GESClipClass * klass) g_object_class_install_property (object_class, PROP_LAYER, properties[PROP_LAYER]); - /** - * GESClip::effect-added: - * @clip: the #GESClip - * @effect: the #GESBaseEffect that was added. - * - * Will be emitted after an effect was added to the clip. - * - * Since: 0.10.2 - */ - ges_clip_signals[EFFECT_ADDED] = - g_signal_new ("effect-added", G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_generic, - G_TYPE_NONE, 1, GES_TYPE_BASE_EFFECT); - - /** - * GESClip::effect-removed: - * @clip: the #GESClip - * @effect: the #GESBaseEffect that was added. - * - * Will be emitted after an effect was remove from the clip. - * - * Since: 0.10.2 - */ - ges_clip_signals[EFFECT_REMOVED] = - g_signal_new ("effect-removed", G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_generic, - G_TYPE_NONE, 1, GES_TYPE_BASE_EFFECT); - - /** - * GESClip::track-element-added: - * @clip: the #GESClip - * @trackelement: the #GESTrackElement that was added. - * - * Will be emitted after a track element was added to the clip. - * - * Since: 0.10.2 - */ - ges_clip_signals[TRACK_ELEMENT_ADDED] = - g_signal_new ("track-element-added", G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_generic, - G_TYPE_NONE, 1, GES_TYPE_TRACK_ELEMENT); - - /** - * GESClip::track-element-removed: - * @clip: the #GESClip - * @trackelement: the #GESTrackElement that was removed. - * - * Will be emitted after a track element was removed from @clip. - * - * Since: 0.10.2 - */ - ges_clip_signals[TRACK_ELEMENT_REMOVED] = - g_signal_new ("track-element-removed", G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_generic, - G_TYPE_NONE, 1, GES_TYPE_TRACK_ELEMENT); - - - element_class->set_start = _set_start; - element_class->set_duration = _set_duration; - element_class->set_inpoint = _set_inpoint; - element_class->set_priority = _set_priority; - element_class->ripple = _ripple; element_class->ripple_end = _ripple_end; element_class->roll_start = _roll_start; element_class->roll_end = _roll_end; element_class->trim = _trim; - element_class->set_max_duration = _set_max_duration; -/* TODO implement the deep_copy Virtual method */ + /* TODO implement the deep_copy Virtual method */ + + container_class->get_priorty_range = _get_priorty_range; + container_class->add_child = _add_child; + container_class->remove_child = _remove_child; klass->need_fill_track = TRUE; - klass->snaps = FALSE; } static void @@ -316,8 +251,6 @@ ges_clip_init (GESClip * self) self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GES_TYPE_CLIP, GESClipPrivate); /* FIXME, check why it was done this way _DURATION (self) = GST_SECOND; */ - self->height = 1; - self->trackelements = NULL; self->priv->layer = NULL; self->priv->nb_effects = 0; self->priv->is_moving = FALSE; @@ -330,7 +263,7 @@ ges_clip_init (GESClip * self) * * Creates a #GESTrackElement for the provided @type. The clip * keep a reference to the newly created trackelement, you therefore need to - * call @ges_clip_release_track_element when you are done with it. + * call @ges_container_remove when you are done with it. * * Returns: (transfer none): A #GESTrackElement. Returns NULL if the #GESTrackElement could not * be created. @@ -377,7 +310,9 @@ ges_clip_create_track_element (GESClip * clip, GESTrackType type) GList * ges_clip_create_track_elements (GESClip * clip, GESTrackType type) { + GList *result, *tmp; GESClipClass *klass; + guint max_prio, min_prio; g_return_val_if_fail (GES_IS_CLIP (clip), NULL); @@ -390,19 +325,25 @@ ges_clip_create_track_elements (GESClip * clip, GESTrackType type) GST_DEBUG_OBJECT (clip, "Creating TrackElements for type: %s", ges_track_type_name (type)); - return klass->create_track_elements (clip, type); -} + result = klass->create_track_elements (clip, type); -gboolean -_set_max_duration (GESTimelineElement * element, GstClockTime maxduration) -{ - GList *tmp; + _get_priorty_range (GES_CONTAINER (clip), &min_prio, &max_prio); + for (tmp = result; tmp; tmp = tmp->next) { + GESTimelineElement *elem = tmp->data; - for (tmp = GES_CLIP (element)->trackelements; tmp; tmp = g_list_next (tmp)) - ges_timeline_element_set_max_duration (GES_TIMELINE_ELEMENT (tmp->data), - maxduration); + _set_start0 (elem, GES_TIMELINE_ELEMENT_START (clip)); + _set_inpoint0 (elem, GES_TIMELINE_ELEMENT_INPOINT (clip)); + _set_duration0 (elem, GES_TIMELINE_ELEMENT_DURATION (clip)); - return TRUE; + if (GST_CLOCK_TIME_IS_VALID (GES_TIMELINE_ELEMENT_MAX_DURATION (clip))) + ges_timeline_element_set_max_duration (GES_TIMELINE_ELEMENT (elem), + GES_TIMELINE_ELEMENT_MAX_DURATION (clip)); + + _set_priority0 (elem, min_prio + GES_TIMELINE_ELEMENT_PRIORITY (clip) + + clip->priv->nb_effects); + } + + return result; } /* @@ -424,203 +365,6 @@ ges_clip_create_track_elements_func (GESClip * clip, GESTrackType type) return g_list_append (NULL, result); } -/** - * ges_clip_add_track_element: - * @clip: a #GESClip - * @track_element: the GESTrackElement - * - * Add a track element to the clip. Should only be called by - * subclasses implementing the create_track_elements (plural) vmethod. - * - * Takes a reference on @track_element. - * - * Returns: %TRUE on success, %FALSE on failure. - */ - -gboolean -ges_clip_add_track_element (GESClip * clip, GESTrackElement * track_element) -{ - GList *tmp; - gboolean is_effect; - ObjectMapping *mapping; - guint max_prio, min_prio; - GESClipClass *klass; - GESClipPrivate *priv; - - g_return_val_if_fail (GES_IS_CLIP (clip), FALSE); - g_return_val_if_fail (GES_IS_TRACK_ELEMENT (track_element), FALSE); - - priv = clip->priv; - is_effect = GES_IS_BASE_EFFECT (track_element); - - GST_LOG ("Got a TrackElement : %p , setting the clip as its" - "creator. Is a BaseEffect %i", track_element, is_effect); - - if (!track_element) - return FALSE; - - ges_track_element_set_clip (track_element, clip); - - g_object_ref (track_element); - - mapping = g_slice_new0 (ObjectMapping); - mapping->track_element = track_element; - priv->mappings = g_list_append (priv->mappings, mapping); - - GST_DEBUG ("Adding TrackElement to the list of controlled track elements"); - /* We steal the initial reference */ - - GST_DEBUG ("Setting properties on newly created TrackElement"); - - mapping->priority_offset = priv->nb_effects; - - /* If the trackelement is an effect: - * - We add it on top of the list of BaseEffect - * - We put all TrackElement present in the Clip - * which are not BaseEffect on top of them - * - * FIXME: Let the full control over priorities to the user - */ - if (is_effect) { - GST_DEBUG - ("Moving non on top effect under other TrackElement-s, nb effects %i", - priv->nb_effects); - for (tmp = g_list_nth (clip->trackelements, priv->nb_effects); tmp; - tmp = tmp->next) { - GESTrackElement *tmpo = GES_TRACK_ELEMENT (tmp->data); - - /* We make sure not to move the entire #Clip */ - ges_track_element_set_locked (tmpo, FALSE); - _set_priority0 (GES_TIMELINE_ELEMENT (tmpo), _PRIORITY (tmpo) + 1); - ges_track_element_set_locked (tmpo, TRUE); - } - - priv->nb_effects++; - } - - clip->trackelements = - g_list_insert_sorted_with_data (clip->trackelements, track_element, - (GCompareDataFunc) sort_base_effects, clip); - - _set_start0 (GES_TIMELINE_ELEMENT (track_element), _START (clip)); - _set_duration0 (GES_TIMELINE_ELEMENT (track_element), _DURATION (clip)); - _set_inpoint0 (GES_TIMELINE_ELEMENT (track_element), _INPOINT (clip)); - ges_timeline_element_set_max_duration (GES_TIMELINE_ELEMENT (track_element), - _MAXDURATION (clip)); - - klass = GES_CLIP_GET_CLASS (clip); - if (klass->track_element_added) { - GST_DEBUG ("Calling track_element_added subclass method"); - klass->track_element_added (clip, track_element); - } else { - GST_DEBUG ("%s doesn't have any track_element_added vfunc implementation", - G_OBJECT_CLASS_NAME (klass)); - } - - /* Listen to all property changes */ - mapping->start_notifyid = - g_signal_connect (G_OBJECT (track_element), "notify::start", - G_CALLBACK (track_element_start_changed_cb), clip); - mapping->duration_notifyid = - g_signal_connect (G_OBJECT (track_element), "notify::duration", - G_CALLBACK (track_element_duration_changed_cb), clip); - mapping->inpoint_notifyid = - g_signal_connect (G_OBJECT (track_element), "notify::inpoint", - G_CALLBACK (track_element_inpoint_changed_cb), clip); - mapping->priority_notifyid = - g_signal_connect (G_OBJECT (track_element), "notify::priority", - G_CALLBACK (track_element_priority_changed_cb), clip); - - get_layer_priorities (priv->layer, &min_prio, &max_prio); - _set_priority0 (GES_TIMELINE_ELEMENT (track_element), min_prio + - _PRIORITY (clip) + mapping->priority_offset); - - GST_DEBUG ("Returning track_element:%p", track_element); - if (!GES_IS_BASE_EFFECT (track_element)) { - g_signal_emit (clip, ges_clip_signals[TRACK_ELEMENT_ADDED], 0, - GES_TRACK_ELEMENT (track_element)); - } else { - /* emit 'effect-added' */ - g_signal_emit (clip, ges_clip_signals[EFFECT_ADDED], 0, - GES_BASE_EFFECT (track_element)); - } - - return TRUE; -} - -/** - * ges_clip_release_track_element: - * @clip: a #GESClip - * @trackelement: the #GESTrackElement to release - * - * Release the @trackelement from the control of @clip. - * - * Returns: %TRUE if the @trackelement was properly released, else %FALSE. - */ -gboolean -ges_clip_release_track_element (GESClip * clip, GESTrackElement * trackelement) -{ - GList *tmp; - ObjectMapping *mapping = NULL; - GESClipClass *klass; - - g_return_val_if_fail (GES_IS_CLIP (clip), FALSE); - g_return_val_if_fail (GES_IS_TRACK_ELEMENT (trackelement), FALSE); - - GST_DEBUG ("clip:%p, trackelement:%p", clip, trackelement); - klass = GES_CLIP_GET_CLASS (clip); - - if (!(g_list_find (clip->trackelements, trackelement))) { - GST_WARNING ("TrackElement isn't controlled by this clip"); - return FALSE; - } - - for (tmp = clip->priv->mappings; tmp; tmp = tmp->next) { - mapping = (ObjectMapping *) tmp->data; - if (mapping->track_element == trackelement) - break; - } - - if (tmp && mapping) { - - /* Disconnect all notify listeners */ - g_signal_handler_disconnect (trackelement, mapping->start_notifyid); - g_signal_handler_disconnect (trackelement, mapping->duration_notifyid); - g_signal_handler_disconnect (trackelement, mapping->inpoint_notifyid); - g_signal_handler_disconnect (trackelement, mapping->priority_notifyid); - - g_slice_free (ObjectMapping, mapping); - - clip->priv->mappings = g_list_delete_link (clip->priv->mappings, tmp); - } - - clip->trackelements = g_list_remove (clip->trackelements, trackelement); - - if (GES_IS_BASE_EFFECT (trackelement)) { - /* emit 'clip-removed' */ - clip->priv->nb_effects--; - g_signal_emit (clip, ges_clip_signals[EFFECT_REMOVED], 0, - GES_BASE_EFFECT (trackelement)); - } else - g_signal_emit (clip, ges_clip_signals[TRACK_ELEMENT_REMOVED], 0, - GES_TRACK_ELEMENT (trackelement)); - - ges_track_element_set_clip (trackelement, NULL); - - GST_DEBUG ("Removing reference to track element %p", trackelement); - - if (klass->track_element_released) { - GST_DEBUG ("Calling track_element_released subclass method"); - klass->track_element_released (clip, trackelement); - } - - g_object_unref (trackelement); - - /* FIXME : resync properties ? */ - - return TRUE; -} - void ges_clip_set_layer (GESClip * clip, GESTimelineLayer * layer) { @@ -664,176 +408,6 @@ ges_clip_fill_track_element_func (GESClip * clip, return FALSE; } -static ObjectMapping * -find_object_mapping (GESClip * clip, GESTrackElement * child) -{ - GList *tmp; - - for (tmp = clip->priv->mappings; tmp; tmp = tmp->next) { - ObjectMapping *map = (ObjectMapping *) tmp->data; - if (map->track_element == child) - return map; - } - - return NULL; -} - -static gboolean -_set_start (GESTimelineElement * element, GstClockTime start) -{ - GList *tmp; - GESTrackElement *tr; - ObjectMapping *map; - gboolean snap = FALSE; - GESTimeline *timeline = NULL; - - GESClip *clip = GES_CLIP (element); - GESClipPrivate *priv = clip->priv; - - /* If the class has snapping enabled and the clip is in a timeline, - * we snap */ - if (priv->layer && GES_CLIP_GET_CLASS (clip)->snaps) - timeline = ges_timeline_layer_get_timeline (clip->priv->layer); - snap = timeline && priv->initiated_move == NULL ? TRUE : FALSE; - - clip->priv->ignore_notifies = TRUE; - - for (tmp = clip->trackelements; tmp; tmp = g_list_next (tmp)) { - tr = (GESTrackElement *) tmp->data; - map = find_object_mapping (clip, tr); - - if (ges_track_element_is_locked (tr) && tr != clip->priv->initiated_move) { - gint64 new_start = start - map->start_offset; - - /* Move the child... */ - if (new_start < 0) { - GST_ERROR ("Trying to set start to a negative value %" GST_TIME_FORMAT, - GST_TIME_ARGS (-(start + map->start_offset))); - continue; - } - - /* Make the snapping happen if in a timeline */ - if (snap) - ges_timeline_move_object_simple (timeline, tr, NULL, GES_EDGE_NONE, - start); - else - _set_start0 (GES_TIMELINE_ELEMENT (tr), start); - } else { - /* ... or update the offset */ - map->start_offset = start - _START (tr); - } - } - - clip->priv->ignore_notifies = FALSE; - - return TRUE; -} - -static gboolean -_set_inpoint (GESTimelineElement * element, GstClockTime inpoint) -{ - GList *tmp; - GESTrackElement *tr; - - GESClip *clip = GES_CLIP (element); - - for (tmp = clip->trackelements; tmp; tmp = g_list_next (tmp)) { - tr = (GESTrackElement *) tmp->data; - - if (ges_track_element_is_locked (tr)) - /* call set_inpoint on each trackelement */ - _set_inpoint0 (GES_TIMELINE_ELEMENT (tr), inpoint); - } - - return TRUE; -} - -static gboolean -_set_duration (GESTimelineElement * element, GstClockTime duration) -{ - GList *tmp; - GESTrackElement *tr; - GESTimeline *timeline = NULL; - gboolean snap = FALSE; - - GESClip *clip = GES_CLIP (element); - GESClipPrivate *priv = clip->priv; - - if (priv->layer && GES_CLIP_GET_CLASS (clip)->snaps) - timeline = ges_timeline_layer_get_timeline (clip->priv->layer); - - /* If the class has snapping enabled, the clip is in a timeline, - * and we are not following a moved TrackElement, we snap */ - snap = timeline && priv->initiated_move == NULL ? TRUE : FALSE; - - clip->priv->ignore_notifies = TRUE; - for (tmp = clip->trackelements; tmp; tmp = g_list_next (tmp)) { - tr = (GESTrackElement *) tmp->data; - - if (ges_track_element_is_locked (tr)) { - /* call set_duration on each trackelement - * and make the snapping happen if in a timeline */ - if (G_LIKELY (snap)) - ges_timeline_trim_object_simple (timeline, tr, NULL, GES_EDGE_END, - _START (tr) + duration, TRUE); - else - _set_duration0 (GES_TIMELINE_ELEMENT (tr), duration); - } - } - clip->priv->ignore_notifies = FALSE; - - return TRUE; -} - -static gboolean -_set_priority (GESTimelineElement * element, guint32 priority) -{ - GList *tmp; - GESTrackElement *tr; - ObjectMapping *map; - GESClipPrivate *priv; - guint32 layer_min_gnl_prio, layer_max_gnl_prio; - - GESClip *clip = GES_CLIP (element); - - priv = clip->priv; - - get_layer_priorities (priv->layer, &layer_min_gnl_prio, &layer_max_gnl_prio); - - priv->ignore_notifies = TRUE; - for (tmp = clip->trackelements; tmp; tmp = g_list_next (tmp)) { - tr = (GESTrackElement *) tmp->data; - map = find_object_mapping (clip, tr); - - if (ges_track_element_is_locked (tr)) { - guint32 real_tck_prio; - - /* Move the child... */ - real_tck_prio = layer_min_gnl_prio + priority + map->priority_offset; - - if (real_tck_prio > layer_max_gnl_prio) { - GST_WARNING ("%p priority of %i, is outside of the its containing " - "layer space. (%d/%d) setting it to the maximum it can be", clip, - priority, layer_min_gnl_prio, layer_max_gnl_prio); - - real_tck_prio = layer_max_gnl_prio; - } - - _set_priority0 (GES_TIMELINE_ELEMENT (tr), real_tck_prio); - - } else { - /* ... or update the offset */ - map->priority_offset = _PRIORITY (tr) - layer_min_gnl_prio + priority; - } - } - - clip->trackelements = g_list_sort_with_data (clip->trackelements, - (GCompareDataFunc) sort_base_effects, clip); - priv->ignore_notifies = FALSE; - - return TRUE; -} - /** * ges_clip_set_moving_from_layer: * @clip: a #GESClip @@ -946,7 +520,7 @@ ges_clip_find_track_element (GESClip * clip, GESTrack * track, GType type) g_return_val_if_fail (GES_IS_CLIP (clip), NULL); g_return_val_if_fail (GES_IS_TRACK (track), NULL); - for (tmp = clip->trackelements; tmp; tmp = g_list_next (tmp)) { + for (tmp = GES_CONTAINER_CHILDREN (clip); tmp; tmp = g_list_next (tmp)) { otmp = (GESTrackElement *) tmp->data; if (ges_track_element_get_track (otmp) == track) { @@ -984,58 +558,6 @@ ges_clip_get_layer (GESClip * clip) return clip->priv->layer; } -/** - * ges_clip_get_track_elements: - * @clip: a #GESClip - * - * Get the list of #GESTrackElement contained in @clip - * - * Returns: (transfer full) (element-type GESTrackElement): The list of - * trackelement contained in @clip. - * The user is responsible for unreffing the contained objects - * and freeing the list. - */ -GList * -ges_clip_get_track_elements (GESClip * clip) -{ - GList *ret; - GList *tmp; - - g_return_val_if_fail (GES_IS_CLIP (clip), NULL); - - ret = g_list_copy (clip->trackelements); - - for (tmp = ret; tmp; tmp = tmp->next) { - g_object_ref (tmp->data); - } - - return ret; -} - -static gint -sort_base_effects (gpointer a, gpointer b, GESClip * clip) -{ - guint prio_offset_a, prio_offset_b; - ObjectMapping *map_a, *map_b; - GESTrackElement *track_element_a, *track_element_b; - - track_element_a = GES_TRACK_ELEMENT (a); - track_element_b = GES_TRACK_ELEMENT (b); - - map_a = find_object_mapping (clip, track_element_a); - map_b = find_object_mapping (clip, track_element_b); - - prio_offset_a = map_a->priority_offset; - prio_offset_b = map_b->priority_offset; - - if ((gint) prio_offset_a > (guint) prio_offset_b) - return 1; - if ((guint) prio_offset_a < (guint) prio_offset_b) - return -1; - - return 0; -} - /** * ges_clip_get_top_effects: * @clip: The origin #GESClip @@ -1060,12 +582,12 @@ ges_clip_get_top_effects (GESClip * clip) GST_DEBUG_OBJECT (clip, "Getting the %i top effects", clip->priv->nb_effects); ret = NULL; - for (tmp = clip->trackelements, i = 0; i < clip->priv->nb_effects; - tmp = tmp->next, i++) { + for (tmp = GES_CONTAINER_CHILDREN (clip), i = 0; + i < clip->priv->nb_effects; tmp = tmp->next, i++) { ret = g_list_append (ret, g_object_ref (tmp->data)); } - return ret; + return g_list_sort (ret, (GCompareFunc) element_start_compare); } /** @@ -1082,10 +604,15 @@ ges_clip_get_top_effects (GESClip * clip) gint ges_clip_get_top_effect_position (GESClip * clip, GESBaseEffect * effect) { - g_return_val_if_fail (GES_IS_CLIP (clip), -1); + guint max_prio, min_prio; - return find_object_mapping (clip, - GES_TRACK_ELEMENT (effect))->priority_offset; + g_return_val_if_fail (GES_IS_CLIP (clip), -1); + g_return_val_if_fail (GES_IS_BASE_EFFECT (effect), -1); + + _get_priorty_range (GES_CONTAINER (clip), &min_prio, &max_prio); + + return GES_TIMELINE_ELEMENT_PRIORITY (effect) - min_prio + + GES_TIMELINE_ELEMENT_PRIORITY (clip); } /** @@ -1117,7 +644,8 @@ ges_clip_set_top_effect_priority (GESClip * clip, /* We don't change the priority */ if (current_prio == newpriority || - (G_UNLIKELY (ges_track_element_get_clip (track_element) != clip))) + (G_UNLIKELY (GES_CLIP (GES_TIMELINE_ELEMENT_PARENT (track_element)) != + clip))) return FALSE; if (newpriority > (clip->priv->nb_effects - 1)) { @@ -1130,24 +658,28 @@ ges_clip_set_top_effect_priority (GESClip * clip, return FALSE; } + _ges_container_sort_children (GES_CONTAINER (clip)); if (_PRIORITY (track_element) < newpriority) inc = -1; else inc = +1; - _set_priority0 (GES_TIMELINE_ELEMENT (track_element), newpriority); - for (tmp = clip->trackelements; tmp; tmp = tmp->next) { + GST_DEBUG_OBJECT (clip, "Setting top effect %" GST_PTR_FORMAT "priority: %i", + effect, newpriority); + + for (tmp = GES_CONTAINER_CHILDREN (clip); tmp; tmp = tmp->next) { GESTrackElement *tmpo = GES_TRACK_ELEMENT (tmp->data); guint tck_priority = _PRIORITY (tmpo); + if (tmpo == track_element) + continue; + if ((inc == +1 && tck_priority >= newpriority) || (inc == -1 && tck_priority <= newpriority)) { _set_priority0 (GES_TIMELINE_ELEMENT (tmpo), tck_priority + inc); } } - - clip->trackelements = g_list_sort_with_data (clip->trackelements, - (GCompareDataFunc) sort_base_effects, clip); + _set_priority0 (GES_TIMELINE_ELEMENT (track_element), newpriority); return TRUE; } @@ -1183,13 +715,13 @@ ges_clip_edit (GESClip * clip, GList * layers, g_return_val_if_fail (GES_IS_CLIP (clip), FALSE); - if (!G_UNLIKELY (clip->trackelements)) { + if (!G_UNLIKELY (GES_CONTAINER_CHILDREN (clip))) { GST_WARNING_OBJECT (clip, "Trying to edit, but not containing" "any TrackElement yet."); return FALSE; } - for (tmp = clip->trackelements; tmp; tmp = g_list_next (tmp)) { + for (tmp = GES_CONTAINER_CHILDREN (clip); tmp; tmp = g_list_next (tmp)) { if (ges_track_element_is_locked (tmp->data) && GES_IS_SOURCE (tmp->data)) { ret &= ges_track_element_edit (tmp->data, layers, mode, edge, position); @@ -1232,7 +764,6 @@ GESClip * ges_clip_split (GESClip * clip, guint64 position) { GList *tmp; - gboolean locked; GESClip *new_object; GstClockTime start, inpoint, duration; @@ -1254,9 +785,10 @@ ges_clip_split (GESClip * clip, guint64 position) GST_TIME_ARGS (position)); /* Create the new Clip */ - new_object = - GES_CLIP (ges_timeline_element_copy (GES_TIMELINE_ELEMENT (clip), FALSE)); + new_object = GES_CLIP (ges_timeline_element_copy (GES_TIMELINE_ELEMENT (clip), + FALSE)); + GST_DEBUG_OBJECT (new_object, "New 'splitted' clip"); /* Set new timing properties on the Clip */ _set_start0 (GES_TIMELINE_ELEMENT (new_object), position); _set_inpoint0 (GES_TIMELINE_ELEMENT (new_object), @@ -1275,7 +807,7 @@ ges_clip_split (GESClip * clip, guint64 position) * properly in the following loop * FIXME: Avoid setting it oureself reworking the API */ GES_TIMELINE_ELEMENT (clip)->duration = position - _START (clip); - for (tmp = clip->trackelements; tmp; tmp = tmp->next) { + for (tmp = GES_CONTAINER_CHILDREN (clip); tmp; tmp = tmp->next) { GESTrack *track; GESTrackElement *new_trackelement, *trackelement = @@ -1302,8 +834,6 @@ ges_clip_split (GESClip * clip, guint64 position) continue; } - ges_clip_add_track_element (new_object, new_trackelement); - track = ges_track_element_get_track (trackelement); if (track == NULL) GST_DEBUG_OBJECT (trackelement, "Was not in a track, not adding %p to" @@ -1311,12 +841,6 @@ ges_clip_split (GESClip * clip, guint64 position) else ges_track_add_element (track, new_trackelement); - /* Unlock TrackElement-s as we do not want the container to move - * syncronously */ - locked = ges_track_element_is_locked (trackelement); - ges_track_element_set_locked (new_trackelement, FALSE); - ges_track_element_set_locked (trackelement, FALSE); - /* Set 'new' track element timing propeties */ _set_start0 (GES_TIMELINE_ELEMENT (new_trackelement), position); _set_inpoint0 (GES_TIMELINE_ELEMENT (new_trackelement), @@ -1327,9 +851,8 @@ ges_clip_split (GESClip * clip, guint64 position) /* Set 'old' track element duration */ _set_duration0 (GES_TIMELINE_ELEMENT (trackelement), position - start); - /* And let track elements in the same locking state as before. */ - ges_track_element_set_locked (trackelement, locked); - ges_track_element_set_locked (new_trackelement, locked); + ges_container_add (GES_CONTAINER (new_object), + GES_TIMELINE_ELEMENT (new_trackelement)); } return new_object; @@ -1370,33 +893,10 @@ ges_clip_get_supported_formats (GESClip * clip) return clip->priv->supportedformats; } -/** - * ges_clip_objects_set_locked: - * @clip: the #GESClip - * @locked: whether the #GESTrackElement contained in @clip are locked to it. - * - * Set the locking status of all the #GESTrackElement contained in @clip to @locked. - * See the ges_track_element_set_locked documentation for more details. - * - * Since: 0.10.XX - */ -void -ges_clip_objects_set_locked (GESClip * clip, gboolean locked) -{ - GList *tmp; - - g_return_if_fail (GES_IS_CLIP (clip)); - - for (tmp = clip->priv->mappings; tmp; tmp = g_list_next (tmp)) { - ges_track_element_set_locked (((ObjectMapping *) tmp->data)->track_element, - locked); - } -} - gboolean _ripple (GESTimelineElement * element, GstClockTime start) { - GList *tmp, *trackelements; + GList *tmp; gboolean ret = TRUE; GESTimeline *timeline; GESClip *clip = GES_CLIP (element); @@ -1408,8 +908,7 @@ _ripple (GESTimelineElement * element, GstClockTime start) return FALSE; } - trackelements = ges_clip_get_track_elements (clip); - for (tmp = trackelements; tmp; tmp = g_list_next (tmp)) { + for (tmp = GES_CONTAINER_CHILDREN (element); tmp; tmp = g_list_next (tmp)) { if (ges_track_element_is_locked (tmp->data)) { ret = timeline_ripple_object (timeline, GES_TRACK_ELEMENT (tmp->data), NULL, GES_EDGE_NONE, start); @@ -1418,7 +917,6 @@ _ripple (GESTimelineElement * element, GstClockTime start) break; } } - g_list_free_full (trackelements, g_object_unref); return ret; } @@ -1426,7 +924,7 @@ _ripple (GESTimelineElement * element, GstClockTime start) static gboolean _ripple_end (GESTimelineElement * element, GstClockTime end) { - GList *tmp, *trackelements; + GList *tmp; gboolean ret = TRUE; GESTimeline *timeline; GESClip *clip = GES_CLIP (element); @@ -1438,8 +936,7 @@ _ripple_end (GESTimelineElement * element, GstClockTime end) return FALSE; } - trackelements = ges_clip_get_track_elements (clip); - for (tmp = trackelements; tmp; tmp = g_list_next (tmp)) { + for (tmp = GES_CONTAINER_CHILDREN (element); tmp; tmp = g_list_next (tmp)) { if (ges_track_element_is_locked (tmp->data)) { ret = timeline_ripple_object (timeline, GES_TRACK_ELEMENT (tmp->data), NULL, GES_EDGE_END, end); @@ -1448,7 +945,6 @@ _ripple_end (GESTimelineElement * element, GstClockTime end) break; } } - g_list_free_full (trackelements, g_object_unref); return ret; } @@ -1456,7 +952,7 @@ _ripple_end (GESTimelineElement * element, GstClockTime end) gboolean _roll_start (GESTimelineElement * element, GstClockTime start) { - GList *tmp, *trackelements; + GList *tmp; gboolean ret = TRUE; GESTimeline *timeline; @@ -1469,8 +965,7 @@ _roll_start (GESTimelineElement * element, GstClockTime start) return FALSE; } - trackelements = ges_clip_get_track_elements (clip); - for (tmp = trackelements; tmp; tmp = g_list_next (tmp)) { + for (tmp = GES_CONTAINER_CHILDREN (element); tmp; tmp = g_list_next (tmp)) { if (ges_track_element_is_locked (tmp->data)) { ret = timeline_roll_object (timeline, GES_TRACK_ELEMENT (tmp->data), NULL, GES_EDGE_START, start); @@ -1479,7 +974,6 @@ _roll_start (GESTimelineElement * element, GstClockTime start) break; } } - g_list_free_full (trackelements, g_object_unref); return ret; } @@ -1487,7 +981,7 @@ _roll_start (GESTimelineElement * element, GstClockTime start) gboolean _roll_end (GESTimelineElement * element, GstClockTime end) { - GList *tmp, *trackelements; + GList *tmp; gboolean ret = TRUE; GESTimeline *timeline; @@ -1500,8 +994,7 @@ _roll_end (GESTimelineElement * element, GstClockTime end) } - trackelements = ges_clip_get_track_elements (clip); - for (tmp = trackelements; tmp; tmp = g_list_next (tmp)) { + for (tmp = GES_CONTAINER_CHILDREN (element); tmp; tmp = g_list_next (tmp)) { if (ges_track_element_is_locked (tmp->data)) { ret = timeline_roll_object (timeline, GES_TRACK_ELEMENT (tmp->data), NULL, GES_EDGE_END, end); @@ -1510,7 +1003,6 @@ _roll_end (GESTimelineElement * element, GstClockTime end) break; } } - g_list_free_full (trackelements, g_object_unref); return ret; } @@ -1518,7 +1010,7 @@ _roll_end (GESTimelineElement * element, GstClockTime end) gboolean _trim (GESTimelineElement * element, GstClockTime start) { - GList *tmp, *trackelements; + GList *tmp; gboolean ret = TRUE; GESTimeline *timeline; @@ -1531,15 +1023,13 @@ _trim (GESTimelineElement * element, GstClockTime start) return FALSE; } - trackelements = ges_clip_get_track_elements (clip); - for (tmp = trackelements; tmp; tmp = g_list_next (tmp)) { + for (tmp = GES_CONTAINER_CHILDREN (element); tmp; tmp = g_list_next (tmp)) { if (ges_track_element_is_locked (tmp->data)) { ret = timeline_trim_object (timeline, GES_TRACK_ELEMENT (tmp->data), NULL, GES_EDGE_START, start); break; } } - g_list_free_full (trackelements, g_object_unref); return ret; } @@ -1567,185 +1057,6 @@ ges_clip_add_asset (GESClip * clip, GESAsset * asset) g_return_val_if_fail (g_type_is_a (ges_asset_get_extractable_type (asset), GES_TYPE_TRACK_ELEMENT), FALSE); - return ges_clip_add_track_element (clip, - GES_TRACK_ELEMENT (ges_asset_extract (asset, NULL))); -} - -static void -update_height (GESClip * clip) -{ - GList *tmp; - guint32 min_prio = G_MAXUINT32, max_prio = 0; - - /* Go over all childs and check if height has changed */ - for (tmp = clip->trackelements; tmp; tmp = tmp->next) { - guint tck_priority = _PRIORITY (tmp->data); - - if (tck_priority < min_prio) - min_prio = tck_priority; - if (tck_priority > max_prio) - max_prio = tck_priority; - } - - /* FIXME : We only grow the height */ - if (clip->height < (max_prio - min_prio + 1)) { - clip->height = max_prio - min_prio + 1; - GST_DEBUG ("Updating height %i", clip->height); -#if GLIB_CHECK_VERSION(2,26,0) - g_object_notify_by_pspec (G_OBJECT (clip), properties[PROP_HEIGHT]); -#else - g_object_notify (G_OBJECT (clip), "height"); -#endif - } -} - -/* - * PROPERTY NOTIFICATIONS FROM TRACK ELEMENTS - */ - -static void -track_element_start_changed_cb (GESTrackElement * child, - GParamSpec * arg G_GNUC_UNUSED, GESClip * clip) -{ - ObjectMapping *map; - GESTimelineElement *element = GES_TIMELINE_ELEMENT (clip); - - if (clip->priv->ignore_notifies) - return; - - map = find_object_mapping (clip, child); - if (G_UNLIKELY (map == NULL)) - /* something massively screwed up if we get this */ - return; - - if (!ges_track_element_is_locked (child)) { - /* Update the internal start_offset */ - map->start_offset = _START (element) - _START (child); - } else { - /* Or update the parent start */ - clip->priv->initiated_move = child; - _set_start0 (element, _START (child) + map->start_offset); - clip->priv->initiated_move = NULL; - } -} - -static void -track_element_inpoint_changed_cb (GESTrackElement * child, - GParamSpec * arg G_GNUC_UNUSED, GESClip * clip) -{ - ObjectMapping *map; - GESTimelineElement *element = GES_TIMELINE_ELEMENT (clip); - - if (clip->priv->ignore_notifies) - return; - - map = find_object_mapping (GES_CLIP (element), child); - if (G_UNLIKELY (map == NULL)) - /* something massively screwed up if we get this */ - return; - - if (!ges_track_element_is_locked (child)) { - /* Update the internal start_offset */ - map->inpoint_offset = _INPOINT (element) - _INPOINT (child); - } else { - /* Or update the parent start */ - clip->priv->initiated_move = child; - _set_inpoint0 (element, _INPOINT (child) + map->inpoint_offset); - clip->priv->initiated_move = NULL; - } - -} - -static void -track_element_duration_changed_cb (GESTrackElement * child, - GParamSpec * arg G_GNUC_UNUSED, GESClip * clip) -{ - ObjectMapping *map; - GESTimelineElement *element = GES_TIMELINE_ELEMENT (clip); - - if (clip->priv->ignore_notifies) - return; - - map = find_object_mapping (clip, child); - if (G_UNLIKELY (map == NULL)) - /* something massively screwed up if we get this */ - return; - - if (!ges_track_element_is_locked (child)) { - /* Update the internal start_offset */ - map->duration_offset = _DURATION (element) - _DURATION (child); - } else { - /* Or update the parent start */ - clip->priv->initiated_move = child; - _set_duration0 (element, _DURATION (child) + map->duration_offset); - clip->priv->initiated_move = NULL; - } - -} - -static void -track_element_priority_changed_cb (GESTrackElement * child, - GParamSpec * arg G_GNUC_UNUSED, GESClip * clip) -{ - ObjectMapping *map; - GESTimelineElement *element = GES_TIMELINE_ELEMENT (clip); - guint32 layer_min_gnl_prio, layer_max_gnl_prio; - - guint tck_priority = _PRIORITY (child); - - GST_DEBUG ("TrackElement %p priority changed to %i", child, - _PRIORITY (child)); - - if (clip->priv->ignore_notifies) - return; - - update_height (clip); - map = find_object_mapping (clip, child); - get_layer_priorities (clip->priv->layer, &layer_min_gnl_prio, - &layer_max_gnl_prio); - - if (G_UNLIKELY (map == NULL)) - /* something massively screwed up if we get this */ - return; - - if (!ges_track_element_is_locked (child)) { - if (tck_priority < layer_min_gnl_prio || tck_priority > layer_max_gnl_prio) { - GST_WARNING ("%p priority of %i, is outside of its containing " - "layer space. (%d/%d). This is a bug in the program.", element, - tck_priority, layer_min_gnl_prio, layer_max_gnl_prio); - } - - /* Update the internal priority_offset */ - map->priority_offset = tck_priority - (layer_min_gnl_prio + - _PRIORITY (element)); - - } else if (tck_priority < layer_min_gnl_prio + _PRIORITY (element)) { - /* Or update the parent priority, the element priority is always the - * highest priority (smaller number) */ - if (tck_priority < layer_min_gnl_prio || layer_max_gnl_prio < tck_priority) { - - GST_WARNING ("%p priority of %i, is outside of its containing " - "layer space. (%d/%d). This is a bug in the program.", element, - tck_priority, layer_min_gnl_prio, layer_max_gnl_prio); - return; - } - - _set_priority0 (element, tck_priority - layer_min_gnl_prio); - } - - GST_DEBUG_OBJECT (element, "priority %d child %p priority %d", - _PRIORITY (element), child, _PRIORITY (child)); -} - -static void -get_layer_priorities (GESTimelineLayer * layer, guint32 * layer_min_gnl_prio, - guint32 * layer_max_gnl_prio) -{ - if (layer) { - *layer_min_gnl_prio = layer->min_gnl_priority; - *layer_max_gnl_prio = layer->max_gnl_priority; - } else { - *layer_min_gnl_prio = 0; - *layer_max_gnl_prio = G_MAXUINT32; - } + return ges_container_add (GES_CONTAINER (clip), + GES_TIMELINE_ELEMENT (ges_asset_extract (asset, NULL))); } diff --git a/ges/ges-clip.h b/ges/ges-clip.h index 48dc487652..07fd6aa5ce 100644 --- a/ges/ges-clip.h +++ b/ges/ges-clip.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -92,41 +93,19 @@ typedef GESTrackElement *(*GESCreateTrackElementFunc) (GESClip * clip, * Subclasses should implement this method if they potentially need to * return more than one #GESTrackElement(s) for a given #GESTrack. * - * For each clip created, the subclass must call - * ges_clip_add_track_element() with the newly created clip - * and provided @type. - * * Returns: %TRUE on success %FALSE on failure. */ typedef GList * (*GESCreateTrackElementsFunc) (GESClip * clip, GESTrackType type); -/** - * GES_CLIP_HEIGHT: - * @obj: a #GESClip - * - * The span of priorities this clip occupies. - */ -#define GES_CLIP_HEIGHT(obj) (((GESClip*)obj)->height) - /** * GESClip: - * @trackelements: (element-type GES.TrackElement): A list of TrackElement - * controlled by this Clip sorted by priority. NOTE: Do not modify. * * The #GESClip base class. */ struct _GESClip { - GESTimelineElement parent; - - /*< readonly >*/ - GList *trackelements; - - /* We don't add those properties to the priv struct for optimization purposes - * start, inpoint, duration and fullduration are in nanoseconds */ - guint32 height; /* the span of priorities this clip needs */ - guint64 fullduration; /* Full usable duration of the clip (-1: no duration) */ + GESContainer parent; /*< private >*/ GESClipPrivate *priv; @@ -142,20 +121,13 @@ struct _GESClip * #GESTrack. * @fill_track_element: method to fill an associated #GESTrackElement. * @need_fill_track: Set to TRUE if @fill_track_element needs to be called. - * @snaps: Set to %TRUE if the objects of this type snap with - * other objects in a timeline %FALSE otherwise (default is %FALSE). Basically only - * sources snap. - * @track_element_added: Should be overridden by subclasses if they need to perform an - * operation when a #GESTrackElement is added. Since: 0.10.2 - * @track_element_released: Should be overridden by subclasses if they need to perform - * action when a #GESTrackElement is released. Since: 0.10.2 * * Subclasses can override the @create_track_element and @fill_track_element methods. */ struct _GESClipClass { /*< private > */ - GESTimelineElementClass parent_class; + GESContainerClass parent_class; /*< public > */ GESCreateTrackElementFunc create_track_element; @@ -164,12 +136,6 @@ struct _GESClipClass /* FIXME : might need a release_track_element */ GESFillTrackElementFunc fill_track_element; gboolean need_fill_track; - gboolean snaps; - - void (*track_element_added) (GESClip *clip, - GESTrackElement *track_element); - void (*track_element_released) (GESClip *clip, - GESTrackElement *track_element); /*< private >*/ /* Padding for API extension */ @@ -183,14 +149,12 @@ void ges_clip_set_layer (GESClip *clip, GESTimelineLayer *layer); /* TrackElement handling */ -GList* ges_clip_get_track_elements (GESClip *clip); -GESTrackType ges_clip_get_supported_formats (GESClip *clip); +GESTrackType ges_clip_get_supported_formats (GESClip *clip); GESTrackElement *ges_clip_create_track_element (GESClip *clip, GESTrackType type); -GList * ges_clip_create_track_elements (GESClip *clip, GESTrackType type); -gboolean ges_clip_release_track_element (GESClip *clip, GESTrackElement *trackelement); -void ges_clip_set_supported_formats (GESClip *clip, GESTrackType supportedformats); +GList * ges_clip_create_track_elements (GESClip *clip, GESTrackType type); +void ges_clip_set_supported_formats (GESClip *clip, GESTrackType supportedformats); + gboolean ges_clip_add_asset (GESClip *clip, GESAsset *asset); -gboolean ges_clip_add_track_element (GESClip *clip, GESTrackElement *track_element); gboolean ges_clip_fill_track_element (GESClip *clip, GESTrackElement *trackelement, GstElement *gnlobj); GESTrackElement *ges_clip_find_track_element (GESClip *clip, GESTrack *track, GType type); @@ -207,7 +171,6 @@ gboolean ges_clip_set_top_effect_priority (GESClip *clip, GESBaseEffect *effect, /* Editing */ GESClip *ges_clip_split (GESClip *clip, guint64 position); -void ges_clip_objects_set_locked (GESClip *clip, gboolean locked); gboolean ges_clip_edit (GESClip *clip, GList *layers, gint new_layer_priority, GESEditMode mode, diff --git a/ges/ges-container.c b/ges/ges-container.c new file mode 100644 index 0000000000..58e2aa65d8 --- /dev/null +++ b/ges/ges-container.c @@ -0,0 +1,671 @@ +/* GStreamer Editing Services + * Copyright (C) <2013> Thibault Saunier + * <2013> Collabora Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:ges-container + * @short_description: Base Class for objects responsible for controlling other + * GESTimelineElement-s + */ + +#include "ges-container.h" +#include "ges.h" +#include "ges-internal.h" + +#include + +#define _GET_PRIV(o) (G_TYPE_INSTANCE_GET_PRIVATE (self, GES_TYPE_CONTAINER, GESContainerPrivate)) + +G_DEFINE_ABSTRACT_TYPE (GESContainer, ges_container, GES_TYPE_TIMELINE_ELEMENT); + +GST_DEBUG_CATEGORY_STATIC (ges_container_debug); +#undef GST_CAT_DEFAULT +#define GST_CAT_DEFAULT ges_container_debug + +/* Mapping of relationship between a Container and the TimelineElements + * it controls + * + * NOTE : Does it make sense to make it public in the future ? + */ +typedef struct +{ + GESTimelineElement *child; + + GstClockTime start_offset; + GstClockTime duration_offset; + GstClockTime inpoint_offset; + gint32 priority_offset; + + guint start_notifyid; + guint duration_notifyid; + guint inpoint_notifyid; + guint priority_notifyid; +} ChildMapping; + +enum +{ + CHILD_ADDED_SIGNAL, + CHILD_REMOVED_SIGNAL, + LAST_SIGNAL +}; + +static guint ges_container_signals[LAST_SIGNAL] = { 0 }; + +struct _GESContainerPrivate +{ + /*< public > */ + GESTimelineLayer *layer; + + /*< private > */ + /* Set to TRUE when the container is doing updates of track object + * properties so we don't end up in infinite property update loops + */ + gboolean ignore_notifies; + GHashTable *mappings; + guint nb_effects; + GESTimelineElement *initiated_move; +}; + +enum +{ + PROP_0, + PROP_HEIGHT, + PROP_LAST +}; + +static GParamSpec *properties[PROP_LAST]; + +/************************ + * * + * Private methods * + * * + ************************/ +static void +update_height (GESContainer * container) +{ + GList *tmp; + guint32 min_prio = G_MAXUINT32, max_prio = 0; + + GST_FIXME_OBJECT (container, "No children, we should reset our height to 0"); + if (container->children == NULL) + return; + + /* Go over all childs and check if height has changed */ + for (tmp = container->children; tmp; tmp = tmp->next) { + guint tck_priority = _PRIORITY (tmp->data); + + if (tck_priority < min_prio) + min_prio = tck_priority; + if (tck_priority > max_prio) + max_prio = tck_priority; + } + + if (container->height < (max_prio - min_prio + 1)) { + container->height = max_prio - min_prio + 1; + GST_DEBUG_OBJECT (container, "Updating height %i", container->height); + g_object_notify (G_OBJECT (container), "height"); + } else + GST_FIXME_OBJECT (container, "We only grow the height!"); +} + +static void +_free_mapping (ChildMapping * mapping) +{ + GESTimelineElement *child = mapping->child; + + /* Disconnect all notify listeners */ + g_signal_handler_disconnect (child, mapping->start_notifyid); + g_signal_handler_disconnect (child, mapping->duration_notifyid); + g_signal_handler_disconnect (child, mapping->inpoint_notifyid); + g_signal_handler_disconnect (child, mapping->priority_notifyid); + + ges_timeline_element_set_parent (child, NULL); + g_object_unref (child); + g_slice_free (ChildMapping, mapping); +} + +/***************************************************** + * * + * GESTimelineElement virtual methods implementation * + * * + *****************************************************/ +static gboolean +_set_start (GESTimelineElement * element, GstClockTime start) +{ + GList *tmp; + ChildMapping *map; + GESTimeline *timeline; + GESContainer *container = GES_CONTAINER (element); + GESContainerPrivate *priv = container->priv; + + GST_DEBUG_OBJECT (element, "Setting children start, (initiated_move: %" + GST_PTR_FORMAT ")", container->priv->initiated_move); + + container->priv->ignore_notifies = TRUE; + for (tmp = container->children; tmp; tmp = g_list_next (tmp)) { + GESTimelineElement *child = (GESTimelineElement *) tmp->data; + + map = g_hash_table_lookup (priv->mappings, child); + if (child != container->priv->initiated_move) { + gint64 new_start = start - map->start_offset; + + /* Move the child... */ + if (new_start < 0) { + GST_ERROR ("Trying to set start to a negative value -%" GST_TIME_FORMAT, + GST_TIME_ARGS (-(start + map->start_offset))); + continue; + } + + /* Make the snapping happen if in a timeline */ + timeline = GES_TIMELINE_ELEMENT_TIMELINE (child); + if (timeline == NULL || ges_timeline_move_object_simple (timeline, child, + NULL, GES_EDGE_NONE, start) == FALSE) + _set_start0 (GES_TIMELINE_ELEMENT (child), start); + + } else { + /* ... update the offset for the child that initiated the move */ + map->start_offset = start - _START (child); + } + } + container->priv->ignore_notifies = FALSE; + + return TRUE; +} + +static gboolean +_set_inpoint (GESTimelineElement * element, GstClockTime inpoint) +{ + GList *tmp; + GESContainer *container = GES_CONTAINER (element); + + container->priv->ignore_notifies = TRUE; + for (tmp = container->children; tmp; tmp = g_list_next (tmp)) { + GESTimelineElement *child = (GESTimelineElement *) tmp->data; + ChildMapping *map = g_hash_table_lookup (container->priv->mappings, child); + + if (child == container->priv->initiated_move) { + map->inpoint_offset = inpoint - _INPOINT (child); + continue; + } + + _set_inpoint0 (child, inpoint); + } + container->priv->ignore_notifies = FALSE; + + return TRUE; +} + +static gboolean +_set_duration (GESTimelineElement * element, GstClockTime duration) +{ + GList *tmp; + GESTimeline *timeline; + + GESContainer *container = GES_CONTAINER (element); + GESContainerPrivate *priv = container->priv; + + priv->ignore_notifies = TRUE; + for (tmp = container->children; tmp; tmp = g_list_next (tmp)) { + GESTimelineElement *child = (GESTimelineElement *) tmp->data; + ChildMapping *map = g_hash_table_lookup (priv->mappings, child); + + if (child == container->priv->initiated_move) { + map->duration_offset = duration - _DURATION (child); + continue; + } + + /* Make the snapping happen if in a timeline */ + timeline = GES_TIMELINE_ELEMENT_TIMELINE (child); + if (timeline == NULL || ges_timeline_trim_object_simple (timeline, child, + NULL, GES_EDGE_END, _START (child) + duration, TRUE) == FALSE) + _set_duration0 (GES_TIMELINE_ELEMENT (child), duration); + } + priv->ignore_notifies = FALSE; + + return TRUE; +} + +static gboolean +_set_max_duration (GESTimelineElement * element, GstClockTime maxduration) +{ + GList *tmp; + + for (tmp = GES_CONTAINER (element)->children; tmp; tmp = g_list_next (tmp)) + ges_timeline_element_set_max_duration (GES_TIMELINE_ELEMENT (tmp->data), + maxduration); + + return TRUE; +} + +static gboolean +_set_priority (GESTimelineElement * element, guint32 priority) +{ + GList *tmp; + GESContainerPrivate *priv; + guint32 min_prio, max_prio; + + GESContainer *container = GES_CONTAINER (element); + + priv = container->priv; + + GES_CONTAINER_GET_CLASS (element)->get_priorty_range (container, &min_prio, + &max_prio); + + priv->ignore_notifies = TRUE; /* */ + for (tmp = container->children; tmp; tmp = g_list_next (tmp)) { + GESTimelineElement *child = (GESTimelineElement *) tmp->data; + ChildMapping *map = g_hash_table_lookup (priv->mappings, child); + guint32 real_tck_prio = min_prio + priority + map->priority_offset; + + if (real_tck_prio > max_prio) { + GST_WARNING ("%p priority of %i, is outside of the its containing " + "layer space. (%d/%d) setting it to the maximum it can be", + container, priority, min_prio, max_prio); + + real_tck_prio = max_prio; + } + _set_priority0 (child, real_tck_prio); + } + priv->ignore_notifies = FALSE; + + update_height (container); + + return TRUE; +} + +/****************************************** + * * + * GObject virtual methods implementation * + * * + ******************************************/ +static void +_dispose (GObject * object) +{ + GESContainer *self = GES_CONTAINER (object); + + g_hash_table_unref (self->priv->mappings); +} + +static void +_get_property (GObject * container, guint property_id, + GValue * value, GParamSpec * pspec) +{ + GESContainer *tobj = GES_CONTAINER (container); + + switch (property_id) { + case PROP_HEIGHT: + g_value_set_uint (value, tobj->height); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (container, property_id, pspec); + } +} + +static void +_set_property (GObject * container, guint property_id, + const GValue * value, GParamSpec * pspec) +{ + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (container, property_id, pspec); + } +} + +static void +ges_container_class_init (GESContainerClass * klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GESTimelineElementClass *element_class = GES_TIMELINE_ELEMENT_CLASS (klass); + + GST_DEBUG_CATEGORY_INIT (ges_container_debug, "gescontainer", + GST_DEBUG_FG_YELLOW, "ges container"); + + g_type_class_add_private (klass, sizeof (GESContainerPrivate)); + + object_class->get_property = _get_property; + object_class->set_property = _set_property; + object_class->dispose = _dispose; + + /** + * GESContainer:height: + * + * The span of priorities which this container occupies. + */ + properties[PROP_HEIGHT] = g_param_spec_uint ("height", "Height", + "The span of priorities this container occupies", 0, G_MAXUINT, 1, + G_PARAM_READABLE); + g_object_class_install_property (object_class, PROP_HEIGHT, + properties[PROP_HEIGHT]); + + /** + * GESContainer::child-added: + * @container: the #GESContainer + * @element: the #GESTimelineElement that was added. + * + * Will be emitted after a child was added to @container. + */ + ges_container_signals[CHILD_ADDED_SIGNAL] = + g_signal_new ("child-added", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GESContainerClass, child_added), + NULL, NULL, g_cclosure_marshal_generic, + G_TYPE_NONE, 1, GES_TYPE_TIMELINE_ELEMENT); + + /** + * GESContainer::child-removed: + * @container: the #GESContainer + * @element: the #GESTimelineElement that was removed. + * + * Will be emitted after a child was removed from @container. + */ + ges_container_signals[CHILD_REMOVED_SIGNAL] = + g_signal_new ("child-removed", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GESContainerClass, child_removed), + NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, + GES_TYPE_TIMELINE_ELEMENT); + + + element_class->set_start = _set_start; + element_class->set_duration = _set_duration; + element_class->set_inpoint = _set_inpoint; + element_class->set_priority = _set_priority; + element_class->set_max_duration = _set_max_duration; + + /* No default implementations */ + klass->remove_child = NULL; + klass->add_child = NULL; +} + +static void +ges_container_init (GESContainer * self) +{ + self->priv = _GET_PRIV (self); + + /* FIXME, check why default was GST_SECOND? (before the existend of + * ges-container) + * + * _DURATION (self) = GST_SECOND; */ + self->height = 1; /* FIXME Why 1 and not 0? */ + self->children = NULL; + + self->priv->mappings = g_hash_table_new_full (g_direct_hash, g_direct_equal, + NULL, (GDestroyNotify) _free_mapping); +} + +/********************************************** + * * + * Property notifications from Children * + * * + **********************************************/ +static void +_child_start_changed_cb (GESTimelineElement * child, + GParamSpec * arg G_GNUC_UNUSED, GESContainer * container) +{ + ChildMapping *map; + + GESContainerPrivate *priv = container->priv; + GESTimelineElement *element = GES_TIMELINE_ELEMENT (container); + + if (priv->ignore_notifies) + return; + + map = g_hash_table_lookup (priv->mappings, child); + g_assert (map); + + GST_FIXME_OBJECT (container, "We should make sure that our child does not" + "involve our start becoming < 0. In that case, undo the child move."); + + /* We update all the children calling our set_start method */ + container->priv->initiated_move = child; + _set_start0 (element, _START (child) + map->start_offset); + container->priv->initiated_move = NULL; +} + +static void +_child_inpoint_changed_cb (GESTimelineElement * child, + GParamSpec * arg G_GNUC_UNUSED, GESContainer * container) +{ + ChildMapping *map; + + GESContainerPrivate *priv = container->priv; + GESTimelineElement *element = GES_TIMELINE_ELEMENT (container); + + if (priv->ignore_notifies) + return; + + map = g_hash_table_lookup (priv->mappings, child); + g_assert (map); + + /* We update all the children calling our set_inpoint method */ + container->priv->initiated_move = child; + _set_inpoint0 (element, _INPOINT (child) + map->inpoint_offset); + container->priv->initiated_move = NULL; +} + +static void +_child_duration_changed_cb (GESTimelineElement * child, + GParamSpec * arg G_GNUC_UNUSED, GESContainer * container) +{ + ChildMapping *map; + + GESContainerPrivate *priv = container->priv; + GESTimelineElement *element = GES_TIMELINE_ELEMENT (container); + + if (priv->ignore_notifies) + return; + + map = g_hash_table_lookup (priv->mappings, child); + g_assert (map); + + /* We update all the children calling our set_duration method */ + container->priv->initiated_move = child; + _set_duration0 (element, _DURATION (child) + map->duration_offset); + container->priv->initiated_move = NULL; +} + +static void +_child_priority_changed_cb (GESTimelineElement * child, + GParamSpec * arg G_GNUC_UNUSED, GESContainer * container) +{ + ChildMapping *map; + guint32 min_prio, max_prio; + GESContainerPrivate *priv = container->priv; + + GST_DEBUG_OBJECT (container, "TimelineElement %p priority changed to %i", + child, _PRIORITY (child)); + + if (priv->ignore_notifies) + return; + + update_height (container); + + /* Update mapping */ + map = g_hash_table_lookup (priv->mappings, child); + g_assert (map); + + GES_CONTAINER_GET_CLASS (container)->get_priorty_range (container, &min_prio, + &max_prio); + + map->priority_offset = min_prio + _PRIORITY (container) - _PRIORITY (child); +} + +/**************************************************** + * * + * Internal methods implementation * + * * + ****************************************************/ + +void +_ges_container_sort_children (GESContainer * container) +{ + container->children = g_list_sort (container->children, + (GCompareFunc) element_start_compare); +} + +void +_ges_container_set_ignore_notifies (GESContainer * container, + gboolean ignore_notifies) +{ + container->priv->ignore_notifies = ignore_notifies; +} + +/********************************************** + * * + * API implementation * + * * + **********************************************/ + +/** + * ges_container_add: + * @container: a #GESContainer + * @child: the #GESTimelineElement + * + * Add the #GESTimelineElement to the container. + * + * Returns: %TRUE on success, %FALSE on failure. + */ +gboolean +ges_container_add (GESContainer * container, GESTimelineElement * child) +{ + ChildMapping *mapping; + GESContainerClass *class; + GESContainerPrivate *priv; + guint32 min_prio, max_prio; + + g_return_val_if_fail (GES_IS_CONTAINER (container), FALSE); + g_return_val_if_fail (GES_IS_TIMELINE_ELEMENT (child), FALSE); + + class = GES_CONTAINER_GET_CLASS (container); + priv = container->priv; + + GST_DEBUG_OBJECT (container, "adding timeline element %" GST_PTR_FORMAT, + child); + + priv->ignore_notifies = TRUE; + if (class->add_child) { + if (class->add_child (container, child) == FALSE) + return FALSE; + } + priv->ignore_notifies = FALSE; + + mapping = g_slice_new0 (ChildMapping); + mapping->child = g_object_ref (child); + mapping->start_offset = _START (container) - _START (child); + mapping->duration_offset = _DURATION (container) - _DURATION (child); + mapping->inpoint_offset = _INPOINT (container) - _INPOINT (child); + GES_CONTAINER_GET_CLASS (container)->get_priorty_range (container, + &min_prio, &max_prio); + mapping->priority_offset = + min_prio + _PRIORITY (container) - _PRIORITY (child); + + g_hash_table_insert (priv->mappings, child, mapping); + + container->children = g_list_prepend (container->children, child); + + /* Listen to all property changes */ + mapping->start_notifyid = + g_signal_connect (G_OBJECT (child), "notify::start", + G_CALLBACK (_child_start_changed_cb), container); + mapping->duration_notifyid = + g_signal_connect (G_OBJECT (child), "notify::duration", + G_CALLBACK (_child_duration_changed_cb), container); + mapping->inpoint_notifyid = + g_signal_connect (G_OBJECT (child), "notify::inpoint", + G_CALLBACK (_child_inpoint_changed_cb), container); + mapping->priority_notifyid = + g_signal_connect (G_OBJECT (child), "notify::priority", + G_CALLBACK (_child_priority_changed_cb), container); + update_height (container); + + + if (ges_timeline_element_set_parent (child, GES_TIMELINE_ELEMENT (container)) + == FALSE) { + GST_FIXME_OBJECT (container, "Revert everything that was done before!"); + + return FALSE; + } + + g_signal_emit (container, ges_container_signals[CHILD_ADDED_SIGNAL], 0, + child); + + return TRUE; +} + +/** + * ges_container_remove: + * @container: a #GESContainer + * @element: the #GESTimelineElement to release + * + * Release the @element from the control of @container. + * + * Returns: %TRUE if the @element was properly released, else %FALSE. + */ +gboolean +ges_container_remove (GESContainer * container, GESTimelineElement * element) +{ + GESContainerClass *klass; + GESContainerPrivate *priv; + + g_return_val_if_fail (GES_IS_CONTAINER (container), FALSE); + g_return_val_if_fail (GES_IS_TIMELINE_ELEMENT (element), FALSE); + + GST_DEBUG_OBJECT (container, "removing element: %" GST_PTR_FORMAT, element); + + klass = GES_CONTAINER_GET_CLASS (container); + priv = container->priv; + + if (!(g_hash_table_lookup (priv->mappings, element))) { + GST_WARNING_OBJECT (container, "Element isn't controlled by this " + "container"); + return FALSE; + } + + if (klass->remove_child) { + if (klass->remove_child (container, element) == FALSE) + return FALSE; + } + + container->children = g_list_remove (container->children, element); + /* Let it live removing from our mappings */ + g_hash_table_remove (priv->mappings, element); + + g_signal_emit (container, ges_container_signals[CHILD_REMOVED_SIGNAL], 0, + element); + + return TRUE; +} + +/** + * ges_container_get_children: + * @container: a #GESContainer + * + * Get the list of #GESTimelineElement contained in @container + * The user is responsible for unreffing the contained objects + * and freeing the list. + * + * Returns: (transfer full) (element-type GESTimelineElement): The list of + * timeline element contained in @container. + */ +GList * +ges_container_get_children (GESContainer * container) +{ + g_return_val_if_fail (GES_IS_CONTAINER (container), NULL); + + return g_list_copy_deep (container->children, (GCopyFunc) gst_object_ref, + NULL); +} diff --git a/ges/ges-container.h b/ges/ges-container.h new file mode 100644 index 0000000000..d39121ddd2 --- /dev/null +++ b/ges/ges-container.h @@ -0,0 +1,119 @@ +/* GStreamer Editing Services + * Copyright (C) 2009 Edward Hervey + * 2009 Nokia Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef _GES_CONTAINER +#define _GES_CONTAINER + +#include +#include +#include +#include +#include + +G_BEGIN_DECLS + +#define GES_TYPE_CONTAINER ges_container_get_type() +#define GES_CONTAINER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GES_TYPE_CONTAINER, GESContainer)) +#define GES_CONTAINER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GES_TYPE_CONTAINER, GESContainerClass)) +#define GES_IS_CONTAINER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GES_TYPE_CONTAINER)) +#define GES_IS_CONTAINER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GES_TYPE_CONTAINER)) +#define GES_CONTAINER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GES_TYPE_CONTAINER, GESContainerClass)) + +typedef struct _GESContainerPrivate GESContainerPrivate; + +/** + * GES_CONTAINER_HEIGHT: + * @obj: a #GESContainer + * + * The span of priorities this object occupies. + */ +#define GES_CONTAINER_HEIGHT(obj) (((GESContainer*)obj)->height) + +/** + * GES_CONTAINER_CHILDREN: + * @obj: a #GESContainer + * + * A #GList containing the children of @object + */ +#define GES_CONTAINER_CHILDREN(obj) (((GESContainer*)obj)->children) + +/** + * GESContainer: + * @children: (element-type GES.TimelineElement): A list of TimelineElement + * controlled by this Container. NOTE: Do not modify. + * + * The #GESContainer base class. + */ +struct _GESContainer +{ + GESTimelineElement parent; + + /*< readonly >*/ + GList *children; + + /* We don't add those properties to the priv struct for optimization purposes + * start, inpoint, duration and fullduration are in nanoseconds */ + guint32 height; /* the span of priorities this object needs */ + guint64 fullduration; /* Full usable duration of the object (-1: no duration) */ + + /*< private >*/ + GESContainerPrivate *priv; + + /* Padding for API extension */ + gpointer _ges_reserved[GES_PADDING_LARGE]; +}; + +/** + * GESContainerClass: + * @child_added: Virtual method that is called right after a #GESTimelineElement is added + * @child_removed: Virtual method that is called right after a #GESTimelineElement is removed + * @remove_child: Virtual method to remove a child + * @add_child: Virtual method to add a child + * @get_priorty_range: Returns the range of possible priority in which the children can be in. + */ +struct _GESContainerClass +{ + /*< private > */ + GESTimelineElementClass parent_class; + + /* signals */ + void (*child_added) (GESContainer *container, GESTimelineElement *element); + void (*child_removed) (GESContainer *container, GESTimelineElement *element); + + /*< public > */ + gboolean (*add_child) (GESContainer *container, GESTimelineElement *element); + gboolean (*remove_child) (GESContainer *container, GESTimelineElement *element); + void (*get_priorty_range) (GESContainer *container, guint32 *min_prio, guint32 *max_prio); + + + /*< private >*/ + /* Padding for API extension */ + gpointer _ges_reserved[GES_PADDING_LARGE]; +}; + +GType ges_container_get_type (void); + +/* Children handling */ +GList* ges_container_get_children (GESContainer *container); +gboolean ges_container_add (GESContainer *container, GESTimelineElement *child); +gboolean ges_container_remove (GESContainer *container, GESTimelineElement *child); + +G_END_DECLS +#endif /* _GES_CONTAINER */ diff --git a/ges/ges-internal.h b/ges/ges-internal.h index 9b8a5523c3..5de1648d2c 100644 --- a/ges/ges-internal.h +++ b/ges/ges-internal.h @@ -63,11 +63,11 @@ G_GNUC_INTERNAL gboolean timeline_trim_object (GESTimeline *timeline, GESTrackElement * object, GList * layers, GESEdge edge, guint64 position); G_GNUC_INTERNAL gboolean -ges_timeline_trim_object_simple (GESTimeline * timeline, GESTrackElement * obj, +ges_timeline_trim_object_simple (GESTimeline * timeline, GESTimelineElement * obj, GList * layers, GESEdge edge, guint64 position, gboolean snapping); G_GNUC_INTERNAL gboolean -ges_timeline_move_object_simple (GESTimeline * timeline, GESTrackElement * object, +ges_timeline_move_object_simple (GESTimeline * timeline, GESTimelineElement * object, GList * layers, GESEdge edge, guint64 position); G_GNUC_INTERNAL gboolean @@ -225,5 +225,12 @@ G_GNUC_INTERNAL void _init_formatter_assets (void); /* Utilities */ G_GNUC_INTERNAL gint element_start_compare (GESTimelineElement * a, GESTimelineElement * b); +/**************************************************** + * GESContainer * + ****************************************************/ +G_GNUC_INTERNAL void _ges_container_sort_children (GESContainer *container); +G_GNUC_INTERNAL void _ges_container_set_ignore_notifies (GESContainer *container, + gboolean ignore_notifies); + #endif /* __GES_INTERNAL_H__ */ diff --git a/ges/ges-pitivi-formatter.c b/ges/ges-pitivi-formatter.c index eef61061ab..20932a30e1 100644 --- a/ges/ges-pitivi-formatter.c +++ b/ges/ges-pitivi-formatter.c @@ -151,7 +151,7 @@ static void save_track_elements (xmlTextWriterPtr writer, GList * source_list, GESTrackType type, gint * id) { - GList *tmp, *track_elements, *tmp_tck; + GList *tmp, *tmp_tck; gchar *bin_desc; xmlTextWriterStartElement (writer, BAD_CAST "track-objects"); @@ -166,8 +166,8 @@ save_track_elements (xmlTextWriterPtr writer, GList * source_list, clip = srcmap->clip; /* Save track associated objects */ - track_elements = ges_clip_get_track_elements (clip); - for (tmp_tck = track_elements; tmp_tck; tmp_tck = tmp_tck->next) { + for (tmp_tck = GES_CONTAINER_CHILDREN (clip); tmp_tck; + tmp_tck = tmp_tck->next) { xmlChar *cast; GESTrackElement *trackelement = GES_TRACK_ELEMENT (tmp_tck->data); GESTrack *track = ges_track_element_get_track (trackelement); @@ -752,14 +752,13 @@ track_element_added_cb (GESClip * clip, GESTrackElement * track_element, GHashTable * props_table) { gchar *media_type = NULL, *lockedstr; - GList *track_elements = NULL, *tmp = NULL; + GList *tmp = NULL; GESTrack *track; gint64 start, duration; gboolean has_effect = FALSE, locked = TRUE; gint type = 0; GESPitiviFormatter *formatter; - track_elements = ges_clip_get_track_elements (clip); media_type = (gchar *) g_hash_table_lookup (props_table, "media_type"); lockedstr = (gchar *) g_hash_table_lookup (props_table, "locked"); @@ -782,8 +781,7 @@ track_element_added_cb (GESClip * clip, if (lockedstr && !g_strcmp0 (lockedstr, "(bool)False")) locked = FALSE; - for (tmp = track_elements; tmp; tmp = tmp->next) { - + for (tmp = GES_CONTAINER_CHILDREN (clip); tmp; tmp = tmp->next) { if (!GES_IS_TRACK_ELEMENT (tmp->data)) { /* If we arrive here something massively screwed */ GST_ERROR ("Not a TrackElement, this is a bug"); @@ -819,13 +817,12 @@ track_element_added_cb (GESClip * clip, } if (has_effect) { - track_elements = ges_clip_get_track_elements (clip); /* FIXME make sure this is the way we want to handle that * ie: set duration and start as the other trackelement * and no let full control to the user. */ - for (tmp = track_elements; tmp; tmp = tmp->next) { + for (tmp = GES_CONTAINER_CHILDREN (clip); tmp; tmp = tmp->next) { /* We set the effects start and duration */ track = ges_track_element_get_track (tmp->data); @@ -939,7 +936,7 @@ make_source (GESFormatter * self, GList * reflist, GHashTable * source_table) effect_table = g_hash_table_lookup (props_table, (gchar *) "effect_props"); - ges_clip_add_track_element (GES_CLIP (src), GES_TRACK_ELEMENT (effect)); + ges_container_add (GES_CONTAINER (src), GES_TIMELINE_ELEMENT (effect)); if (!g_strcmp0 (active, (gchar *) "(bool)False")) ges_track_element_set_active (GES_TRACK_ELEMENT (effect), FALSE); diff --git a/ges/ges-simple-timeline-layer.c b/ges/ges-simple-timeline-layer.c index 07d1cd9f05..4a458ca974 100644 --- a/ges/ges-simple-timeline-layer.c +++ b/ges/ges-simple-timeline-layer.c @@ -185,7 +185,7 @@ gstl_recalculate (GESSimpleTimelineLayer * self) clip = (GESClip *) tmp->data; dur = _DURATION (clip); - height = GES_CLIP_HEIGHT (clip); + height = GES_CONTAINER_HEIGHT (clip); if (GES_IS_SOURCE_CLIP (clip)) { diff --git a/ges/ges-source-clip.c b/ges/ges-source-clip.c index 9456d6b98e..258f5ea456 100644 --- a/ges/ges-source-clip.c +++ b/ges/ges-source-clip.c @@ -78,9 +78,6 @@ ges_source_clip_class_init (GESSourceClipClass * klass) object_class->get_property = ges_source_clip_get_property; object_class->set_property = ges_source_clip_set_property; object_class->finalize = ges_source_clip_finalize; - - /* All subclasses should have snapping enabled */ - GES_CLIP_CLASS (klass)->snaps = TRUE; } static void diff --git a/ges/ges-test-clip.c b/ges/ges-test-clip.c index 912fc861c5..5f70128713 100644 --- a/ges/ges-test-clip.c +++ b/ges/ges-test-clip.c @@ -185,25 +185,20 @@ ges_test_clip_init (GESTestClip * self) void ges_test_clip_set_mute (GESTestClip * self, gboolean mute) { - GList *tmp, *trackelements; - GESClip *clip = (GESClip *) self; + GList *tmp; GST_DEBUG ("self:%p, mute:%d", self, mute); self->priv->mute = mute; /* Go over tracked objects, and update 'active' status on all audio objects */ - trackelements = ges_clip_get_track_elements (clip); - for (tmp = trackelements; tmp; tmp = tmp->next) { + for (tmp = GES_CONTAINER_CHILDREN (self); tmp; tmp = tmp->next) { GESTrackElement *trackelement = (GESTrackElement *) tmp->data; if (ges_track_element_get_track (trackelement)->type == GES_TRACK_TYPE_AUDIO) ges_track_element_set_active (trackelement, !mute); - - g_object_unref (GES_TRACK_ELEMENT (tmp->data)); } - g_list_free (trackelements); } /** @@ -217,21 +212,16 @@ ges_test_clip_set_mute (GESTestClip * self, gboolean mute) void ges_test_clip_set_vpattern (GESTestClip * self, GESVideoTestPattern vpattern) { - GList *tmp, *trackelements; - GESClip *clip = (GESClip *) self; + GList *tmp; self->priv->vpattern = vpattern; - trackelements = ges_clip_get_track_elements (clip); - for (tmp = trackelements; tmp; tmp = tmp->next) { + for (tmp = GES_CONTAINER_CHILDREN (self); tmp; tmp = tmp->next) { GESTrackElement *trackelement = (GESTrackElement *) tmp->data; if (GES_IS_VIDEO_TEST_SOURCE (trackelement)) ges_video_test_source_set_pattern ( (GESVideoTestSource *) trackelement, vpattern); - - g_object_unref (GES_TRACK_ELEMENT (tmp->data)); } - g_list_free (trackelements); } /** @@ -245,21 +235,16 @@ ges_test_clip_set_vpattern (GESTestClip * self, GESVideoTestPattern vpattern) void ges_test_clip_set_frequency (GESTestClip * self, gdouble freq) { - GList *tmp, *trackelements; - GESClip *clip = (GESClip *) self; + GList *tmp; self->priv->freq = freq; - trackelements = ges_clip_get_track_elements (clip); - for (tmp = trackelements; tmp; tmp = tmp->next) { + for (tmp = GES_CONTAINER_CHILDREN (self); tmp; tmp = tmp->next) { GESTrackElement *trackelement = (GESTrackElement *) tmp->data; if (GES_IS_AUDIO_TEST_SOURCE (trackelement)) ges_audio_test_source_set_freq ( (GESAudioTestSource *) trackelement, freq); - - g_object_unref (GES_TRACK_ELEMENT (tmp->data)); } - g_list_free (trackelements); } /** @@ -273,21 +258,16 @@ ges_test_clip_set_frequency (GESTestClip * self, gdouble freq) void ges_test_clip_set_volume (GESTestClip * self, gdouble volume) { - GList *tmp, *trackelements; - GESClip *clip = (GESClip *) self; + GList *tmp; self->priv->volume = volume; - trackelements = ges_clip_get_track_elements (clip); - for (tmp = trackelements; tmp; tmp = tmp->next) { + for (tmp = GES_CONTAINER_CHILDREN (self); tmp; tmp = tmp->next) { GESTrackElement *trackelement = (GESTrackElement *) tmp->data; if (GES_IS_AUDIO_TEST_SOURCE (trackelement)) ges_audio_test_source_set_volume ( (GESAudioTestSource *) trackelement, volume); - - g_object_unref (GES_TRACK_ELEMENT (tmp->data)); } - g_list_free (trackelements); } /** diff --git a/ges/ges-text-overlay-clip.c b/ges/ges-text-overlay-clip.c index 92aa645cc2..91c291554a 100644 --- a/ges/ges-text-overlay-clip.c +++ b/ges/ges-text-overlay-clip.c @@ -266,8 +266,7 @@ ges_text_overlay_clip_init (GESTextOverlayClip * self) void ges_text_overlay_clip_set_text (GESTextOverlayClip * self, const gchar * text) { - GList *tmp, *trackelements; - GESClip *clip = (GESClip *) self; + GList *tmp; GST_DEBUG ("self:%p, text:%s", self, text); @@ -276,18 +275,14 @@ ges_text_overlay_clip_set_text (GESTextOverlayClip * self, const gchar * text) self->priv->text = g_strdup (text); - trackelements = ges_clip_get_track_elements (clip); - for (tmp = trackelements; tmp; tmp = tmp->next) { + for (tmp = GES_CONTAINER_CHILDREN (self); tmp; tmp = tmp->next) { GESTrackElement *trackelement = (GESTrackElement *) tmp->data; if (ges_track_element_get_track (trackelement)->type == GES_TRACK_TYPE_VIDEO) ges_text_overlay_set_text (GES_TEXT_OVERLAY (trackelement), self->priv->text); - - g_object_unref (GES_TRACK_ELEMENT (tmp->data)); } - g_list_free (trackelements); } /** @@ -302,8 +297,7 @@ void ges_text_overlay_clip_set_font_desc (GESTextOverlayClip * self, const gchar * font_desc) { - GList *tmp, *trackelements; - GESClip *clip = (GESClip *) self; + GList *tmp; GST_DEBUG ("self:%p, font_desc:%s", self, font_desc); @@ -312,18 +306,14 @@ ges_text_overlay_clip_set_font_desc (GESTextOverlayClip * self, self->priv->font_desc = g_strdup (font_desc); - trackelements = ges_clip_get_track_elements (clip); - for (tmp = trackelements; tmp; tmp = tmp->next) { + for (tmp = GES_CONTAINER_CHILDREN (self); tmp; tmp = tmp->next) { GESTrackElement *trackelement = (GESTrackElement *) tmp->data; if (ges_track_element_get_track (trackelement)->type == GES_TRACK_TYPE_VIDEO) ges_text_overlay_set_font_desc (GES_TEXT_OVERLAY (trackelement), self->priv->font_desc); - - g_object_unref (GES_TRACK_ELEMENT (tmp->data)); } - g_list_free (trackelements); } @@ -339,25 +329,20 @@ void ges_text_overlay_clip_set_halign (GESTextOverlayClip * self, GESTextHAlign halign) { - GList *tmp, *trackelements; - GESClip *clip = (GESClip *) self; + GList *tmp; GST_DEBUG ("self:%p, halign:%d", self, halign); self->priv->halign = halign; - trackelements = ges_clip_get_track_elements (clip); - for (tmp = trackelements; tmp; tmp = tmp->next) { + for (tmp = GES_CONTAINER_CHILDREN (self); tmp; tmp = tmp->next) { GESTrackElement *trackelement = (GESTrackElement *) tmp->data; if (ges_track_element_get_track (trackelement)->type == GES_TRACK_TYPE_VIDEO) ges_text_overlay_set_halignment (GES_TEXT_OVERLAY (trackelement), self->priv->halign); - - g_object_unref (GES_TRACK_ELEMENT (tmp->data)); } - g_list_free (trackelements); } @@ -373,25 +358,20 @@ void ges_text_overlay_clip_set_valign (GESTextOverlayClip * self, GESTextVAlign valign) { - GList *tmp, *trackelements; - GESClip *clip = (GESClip *) self; + GList *tmp; GST_DEBUG ("self:%p, valign:%d", self, valign); self->priv->valign = valign; - trackelements = ges_clip_get_track_elements (clip); - for (tmp = trackelements; tmp; tmp = tmp->next) { + for (tmp = GES_CONTAINER_CHILDREN (self); tmp; tmp = tmp->next) { GESTrackElement *trackelement = (GESTrackElement *) tmp->data; if (ges_track_element_get_track (trackelement)->type == GES_TRACK_TYPE_VIDEO) ges_text_overlay_set_valignment (GES_TEXT_OVERLAY (trackelement), self->priv->valign); - - g_object_unref (GES_TRACK_ELEMENT (tmp->data)); } - g_list_free (trackelements); } @@ -407,25 +387,20 @@ ges_text_overlay_clip_set_valign (GESTextOverlayClip * self, void ges_text_overlay_clip_set_color (GESTextOverlayClip * self, guint32 color) { - GList *tmp, *trackelements; - GESClip *clip = (GESClip *) self; + GList *tmp; GST_DEBUG ("self:%p, color:%d", self, color); self->priv->color = color; - trackelements = ges_clip_get_track_elements (clip); - for (tmp = trackelements; tmp; tmp = tmp->next) { + for (tmp = GES_CONTAINER_CHILDREN (self); tmp; tmp = tmp->next) { GESTrackElement *trackelement = (GESTrackElement *) tmp->data; if (ges_track_element_get_track (trackelement)->type == GES_TRACK_TYPE_VIDEO) ges_text_overlay_set_color (GES_TEXT_OVERLAY (trackelement), self->priv->color); - - g_object_unref (GES_TRACK_ELEMENT (tmp->data)); } - g_list_free (trackelements); } /** @@ -440,25 +415,20 @@ ges_text_overlay_clip_set_color (GESTextOverlayClip * self, guint32 color) void ges_text_overlay_clip_set_xpos (GESTextOverlayClip * self, gdouble position) { - GList *tmp, *trackelements; - GESClip *clip = (GESClip *) self; + GList *tmp; GST_DEBUG ("self:%p, xpos:%f", self, position); self->priv->xpos = position; - trackelements = ges_clip_get_track_elements (clip); - for (tmp = trackelements; tmp; tmp = tmp->next) { + for (tmp = GES_CONTAINER_CHILDREN (self); tmp; tmp = tmp->next) { GESTrackElement *trackelement = (GESTrackElement *) tmp->data; if (ges_track_element_get_track (trackelement)->type == GES_TRACK_TYPE_VIDEO) ges_text_overlay_set_xpos (GES_TEXT_OVERLAY (trackelement), self->priv->xpos); - - g_object_unref (GES_TRACK_ELEMENT (tmp->data)); } - g_list_free (trackelements); } /** @@ -473,25 +443,20 @@ ges_text_overlay_clip_set_xpos (GESTextOverlayClip * self, gdouble position) void ges_text_overlay_clip_set_ypos (GESTextOverlayClip * self, gdouble position) { - GList *tmp, *trackelements; - GESClip *clip = (GESClip *) self; + GList *tmp; GST_DEBUG ("self:%p, ypos:%f", self, position); self->priv->ypos = position; - trackelements = ges_clip_get_track_elements (clip); - for (tmp = trackelements; tmp; tmp = tmp->next) { + for (tmp = GES_CONTAINER_CHILDREN (self); tmp; tmp = tmp->next) { GESTrackElement *trackelement = (GESTrackElement *) tmp->data; if (ges_track_element_get_track (trackelement)->type == GES_TRACK_TYPE_VIDEO) ges_text_overlay_set_ypos (GES_TEXT_OVERLAY (trackelement), self->priv->ypos); - - g_object_unref (GES_TRACK_ELEMENT (tmp->data)); } - g_list_free (trackelements); } /** diff --git a/ges/ges-timeline.c b/ges/ges-timeline.c index 0849facd55..66eae95162 100644 --- a/ges/ges-timeline.c +++ b/ges/ges-timeline.c @@ -39,6 +39,7 @@ #include "ges-internal.h" #include "ges-project.h" +#include "ges-container.h" #include "ges-timeline.h" #include "ges-track.h" #include "ges-timeline-layer.h" @@ -670,7 +671,6 @@ create_transition (GESTimeline * timeline, GESTrackElement * previous, GESTrackElement * next, GESClip * transition, GESTimelineLayer * layer, guint64 start, guint64 duration) { - GList *trackelements; GESAsset *asset; GESAutoTransition *auto_transition; @@ -686,10 +686,9 @@ create_transition (GESTimeline * timeline, GESTrackElement * previous, } /* We know there is only 1 TrackElement */ - trackelements = ges_clip_get_track_elements (transition); auto_transition = - ges_auto_transition_new (trackelements->data, previous, next); - g_list_free_full (trackelements, gst_object_unref); + ges_auto_transition_new (GES_CONTAINER_CHILDREN (transition)->data, + previous, next); g_signal_connect (auto_transition, "destroy-me", G_CALLBACK (_destroy_auto_transition_cb), timeline); @@ -760,7 +759,7 @@ _create_auto_transition_from_transitions (GESTimeline * timeline, * TrackElement-s in @track and if it is not the case properly unlink the * object to use it */ return create_transition (timeline, prev, next, - ges_track_element_get_clip (maybe_transition), layer, + GES_CLIP (GES_TIMELINE_ELEMENT_PARENT (maybe_transition)), layer, _START (next), transition_duration); } @@ -1070,7 +1069,7 @@ ges_timeline_snap_position (GESTimeline * timeline, } } - clip = ges_track_element_get_clip (trackelement); + clip = GES_CLIP (GES_TIMELINE_ELEMENT_PARENT (trackelement)); iter = g_sequence_search (priv->starts_ends, &timecode, (GCompareDataFunc) compare_uint64, NULL); @@ -1081,7 +1080,7 @@ ges_timeline_snap_position (GESTimeline * timeline, while (!g_sequence_iter_is_end (nxt_iter)) { next_tc = g_sequence_get (iter); tmp_trackelement = g_hash_table_lookup (timeline->priv->by_object, next_tc); - tmp_clip = ges_track_element_get_clip (tmp_trackelement); + tmp_clip = GES_CLIP (GES_TIMELINE_ELEMENT_PARENT (tmp_trackelement)); off = timecode > *next_tc ? timecode - *next_tc : *next_tc - timecode; if (next_tc != current && off <= snap_distance && clip != tmp_clip) { @@ -1100,7 +1099,7 @@ ges_timeline_snap_position (GESTimeline * timeline, while (!g_sequence_iter_is_begin (prev_iter)) { prev_tc = g_sequence_get (prev_iter); tmp_trackelement = g_hash_table_lookup (timeline->priv->by_object, prev_tc); - tmp_clip = ges_track_element_get_clip (tmp_trackelement); + tmp_clip = GES_CLIP (GES_TIMELINE_ELEMENT_PARENT (tmp_trackelement)); off1 = timecode > *prev_tc ? timecode - *prev_tc : *prev_tc - timecode; if (prev_tc != current && off1 < off && off1 <= snap_distance && @@ -1135,7 +1134,7 @@ add_moving_clip (MoveContext * mv_ctx, GESTrackElement * trackelement) GESTimelineLayer *layer; guint layer_prio; - clip = ges_track_element_get_clip (trackelement); + clip = GES_CLIP (GES_TIMELINE_ELEMENT_PARENT (trackelement)); /* Avoid recalculating */ if (!g_hash_table_lookup (mv_ctx->moving_clips, clip)) { @@ -1235,7 +1234,7 @@ ges_timeline_set_moving_context (GESTimeline * timeline, GESTrackElement * obj, /* A TrackElement that could initiate movement for other object */ GESTrackElement *editor_trackelement = NULL; MoveContext *mv_ctx = &timeline->priv->movecontext; - GESClip *clip = ges_track_element_get_clip (obj); + GESClip *clip = GES_CLIP (GES_TIMELINE_ELEMENT_PARENT (obj)); /* Still in the same mv_ctx */ if ((mv_ctx->clip == clip && mv_ctx->mode == mode && @@ -1261,7 +1260,7 @@ ges_timeline_set_moving_context (GESTimeline * timeline, GESTrackElement * obj, if (GES_IS_SOURCE (obj) == FALSE) { GList *tmp; - for (tmp = clip->trackelements; tmp; tmp = tmp->next) { + for (tmp = GES_CONTAINER_CHILDREN (clip); tmp; tmp = tmp->next) { if (GES_IS_SOURCE (tmp->data)) { editor_trackelement = tmp->data; break; @@ -1292,29 +1291,37 @@ ges_timeline_set_moving_context (GESTimeline * timeline, GESTrackElement * obj, } gboolean -ges_timeline_trim_object_simple (GESTimeline * timeline, GESTrackElement * obj, - GList * layers, GESEdge edge, guint64 position, gboolean snapping) +ges_timeline_trim_object_simple (GESTimeline * timeline, + GESTimelineElement * element, GList * layers, GESEdge edge, + guint64 position, gboolean snapping) { guint64 nstart, start, inpoint, duration, max_duration, *snapped, *cur; gboolean ret = TRUE; gint64 real_dur; + GESTrackElement *track_element; - GST_DEBUG_OBJECT (obj, "Trimming to %" GST_TIME_FORMAT " %s snaping, edge %i", - GST_TIME_ARGS (position), snapping ? "Is" : "Not", edge); + /* We only work with GESSource-s */ + if (GES_IS_SOURCE (element) == FALSE) + return FALSE; - start = _START (obj); - g_object_get (obj, "max-duration", &max_duration, NULL); + track_element = GES_TRACK_ELEMENT (element); + GST_DEBUG_OBJECT (track_element, "Trimming to %" GST_TIME_FORMAT + " %s snaping, edge %i", GST_TIME_ARGS (position), + snapping ? "Is" : "Not", edge); + + start = _START (track_element); + g_object_get (track_element, "max-duration", &max_duration, NULL); switch (edge) { case GES_EDGE_START: - inpoint = _INPOINT (obj); - duration = _DURATION (obj); + inpoint = _INPOINT (track_element); + duration = _DURATION (track_element); if (snapping) { - cur = g_hash_table_lookup (timeline->priv->by_start, obj); + cur = g_hash_table_lookup (timeline->priv->by_start, track_element); - snapped = ges_timeline_snap_position (timeline, obj, cur, position, - TRUE); + snapped = ges_timeline_snap_position (timeline, track_element, cur, + position, TRUE); if (snapped) position = *snapped; } @@ -1329,28 +1336,29 @@ ges_timeline_trim_object_simple (GESTimeline * timeline, GESTrackElement * obj, real_dur = start + duration - nstart; /* FIXME: Why CLAMP (0, real_dur, max_duration) doesn't work? */ duration = MAX (0, real_dur); - duration = MIN (duration, max_duration - _INPOINT (obj)); + duration = MIN (duration, max_duration - _INPOINT (track_element)); timeline->priv->needs_transitions_update = FALSE; - _set_start0 (GES_TIMELINE_ELEMENT (obj), nstart); - _set_inpoint0 (GES_TIMELINE_ELEMENT (obj), inpoint); + _set_start0 (GES_TIMELINE_ELEMENT (track_element), nstart); + _set_inpoint0 (GES_TIMELINE_ELEMENT (track_element), inpoint); timeline->priv->needs_transitions_update = TRUE; - _set_duration0 (GES_TIMELINE_ELEMENT (obj), duration); + _set_duration0 (GES_TIMELINE_ELEMENT (track_element), duration); break; case GES_EDGE_END: { - cur = g_hash_table_lookup (timeline->priv->by_end, obj); - snapped = ges_timeline_snap_position (timeline, obj, cur, position, TRUE); + cur = g_hash_table_lookup (timeline->priv->by_end, track_element); + snapped = ges_timeline_snap_position (timeline, track_element, cur, + position, TRUE); if (snapped) position = *snapped; /* Calculate new values */ real_dur = position - start; duration = MAX (0, real_dur); - duration = MIN (duration, max_duration - _INPOINT (obj)); + duration = MIN (duration, max_duration - _INPOINT (track_element)); - _set_duration0 (GES_TIMELINE_ELEMENT (obj), duration); + _set_duration0 (GES_TIMELINE_ELEMENT (track_element), duration); break; } default: @@ -1494,9 +1502,8 @@ timeline_trim_object (GESTimeline * timeline, GESTrackElement * object, edge, layers)) goto end; - ret = - ges_timeline_trim_object_simple (timeline, object, layers, edge, position, - TRUE); + ret = ges_timeline_trim_object_simple (timeline, + GES_TIMELINE_ELEMENT (object), layers, edge, position, TRUE); end: mv_ctx->ignore_needs_ctx = FALSE; @@ -1539,9 +1546,8 @@ timeline_roll_object (GESTimeline * timeline, GESTrackElement * obj, if (snapped) position = *snapped; - ret &= - ges_timeline_trim_object_simple (timeline, obj, layers, - GES_EDGE_START, position, FALSE); + ret &= ges_timeline_trim_object_simple (timeline, + GES_TIMELINE_ELEMENT (obj), layers, GES_EDGE_START, position, FALSE); /* In the case we reached max_duration we just make sure to roll * everything to the real new position */ @@ -1549,17 +1555,16 @@ timeline_roll_object (GESTimeline * timeline, GESTrackElement * obj, /* Send back changes to the neighbourhood */ for (tmp = mv_ctx->moving_trackelements; tmp; tmp = tmp->next) { - GESTrackElement *tmptrackelement = GES_TRACK_ELEMENT (tmp->data); + GESTimelineElement *tmpelement = GES_TIMELINE_ELEMENT (tmp->data); - tmpstart = _START (tmptrackelement); - tmpduration = _DURATION (tmptrackelement); + tmpstart = _START (tmpelement); + tmpduration = _DURATION (tmpelement); tmpend = tmpstart + tmpduration; /* Check that the object should be resized at this position * even if an error accurs, we keep doing our job */ if (tmpend == start) { - ret &= - ges_timeline_trim_object_simple (timeline, tmptrackelement, NULL, + ret &= ges_timeline_trim_object_simple (timeline, tmpelement, NULL, GES_EDGE_END, position, FALSE); break; } @@ -1578,8 +1583,8 @@ timeline_roll_object (GESTimeline * timeline, GESTrackElement * obj, if (snapped) position = *snapped; - ret &= ges_timeline_trim_object_simple (timeline, obj, NULL, GES_EDGE_END, - position, FALSE); + ret &= ges_timeline_trim_object_simple (timeline, + GES_TIMELINE_ELEMENT (obj), NULL, GES_EDGE_END, position, FALSE); /* In the case we reached max_duration we just make sure to roll * everything to the real new position */ @@ -1587,17 +1592,16 @@ timeline_roll_object (GESTimeline * timeline, GESTrackElement * obj, /* Send back changes to the neighbourhood */ for (tmp = mv_ctx->moving_trackelements; tmp; tmp = tmp->next) { - GESTrackElement *tmptrackelement = GES_TRACK_ELEMENT (tmp->data); + GESTimelineElement *tmpelement = GES_TIMELINE_ELEMENT (tmp->data); - tmpstart = _START (tmptrackelement); - tmpduration = _DURATION (tmptrackelement); + tmpstart = _START (tmpelement); + tmpduration = _DURATION (tmpelement); tmpend = tmpstart + tmpduration; /* Check that the object should be resized at this position * even if an error accure, we keep doing our job */ if (end == tmpstart) { - ret &= - ges_timeline_trim_object_simple (timeline, tmptrackelement, NULL, + ret &= ges_timeline_trim_object_simple (timeline, tmpelement, NULL, GES_EDGE_START, position, FALSE); } } @@ -1633,30 +1637,41 @@ timeline_move_object (GESTimeline * timeline, GESTrackElement * object, return FALSE; } - return ges_timeline_move_object_simple (timeline, object, layers, edge, - position); + return ges_timeline_move_object_simple (timeline, + GES_TIMELINE_ELEMENT (object), layers, edge, position); } gboolean ges_timeline_move_object_simple (GESTimeline * timeline, - GESTrackElement * object, GList * layers, GESEdge edge, guint64 position) + GESTimelineElement * element, GList * layers, GESEdge edge, + guint64 position) { guint64 *snap_end, *snap_st, *cur, off1, off2, end; + GESTrackElement *track_element; - end = position + _DURATION (object); - cur = g_hash_table_lookup (timeline->priv->by_end, object); + /* We only work with GESSource-s and we check that we are not already moving + * element ourself*/ + if (GES_IS_SOURCE (element) == FALSE || + g_list_find (timeline->priv->movecontext.moving_trackelements, element)) + return FALSE; + + track_element = GES_TRACK_ELEMENT (element); + end = position + _DURATION (track_element); + cur = g_hash_table_lookup (timeline->priv->by_end, track_element); GST_DEBUG_OBJECT (timeline, "Moving to %" GST_TIME_FORMAT " (end %" GST_TIME_FORMAT ")", GST_TIME_ARGS (position), GST_TIME_ARGS (end)); - snap_end = ges_timeline_snap_position (timeline, object, cur, end, FALSE); + snap_end = ges_timeline_snap_position (timeline, track_element, cur, end, + FALSE); if (snap_end) off1 = end > *snap_end ? end - *snap_end : *snap_end - end; else off1 = G_MAXUINT64; - cur = g_hash_table_lookup (timeline->priv->by_start, object); - snap_st = ges_timeline_snap_position (timeline, object, cur, position, FALSE); + cur = g_hash_table_lookup (timeline->priv->by_start, track_element); + snap_st = ges_timeline_snap_position (timeline, track_element, cur, position, + FALSE); if (snap_st) off2 = position > *snap_st ? position - *snap_st : *snap_st - position; else @@ -1665,15 +1680,15 @@ ges_timeline_move_object_simple (GESTimeline * timeline, /* In the case we could snap on both sides, we snap on the end */ if (snap_end && off1 <= off2) { position = position + *snap_end - end; - ges_timeline_emit_snappig (timeline, object, snap_end); + ges_timeline_emit_snappig (timeline, track_element, snap_end); } else if (snap_st) { position = position + *snap_st - position; - ges_timeline_emit_snappig (timeline, object, snap_st); + ges_timeline_emit_snappig (timeline, track_element, snap_st); } else - ges_timeline_emit_snappig (timeline, object, NULL); + ges_timeline_emit_snappig (timeline, track_element, NULL); - _set_start0 (GES_TIMELINE_ELEMENT (object), position); + _set_start0 (GES_TIMELINE_ELEMENT (track_element), position); return TRUE; } @@ -1732,7 +1747,8 @@ static void add_object_to_track (GESClip * clip, GESTrackElement * track_element, GESTrack * track) { - if (!ges_clip_add_track_element (clip, track_element)) { + if (!ges_container_add (GES_CONTAINER (clip), + GES_TIMELINE_ELEMENT (track_element))) { GST_WARNING_OBJECT (clip, "Failed to add track element to clip"); gst_object_unref (track_element); return; @@ -1740,7 +1756,8 @@ add_object_to_track (GESClip * clip, GESTrackElement * track_element, if (!ges_track_add_element (track, track_element)) { GST_WARNING_OBJECT (clip, "Failed to add track element to track"); - ges_clip_release_track_element (clip, track_element); + ges_container_remove (GES_CONTAINER (clip), + GES_TIMELINE_ELEMENT (track_element)); gst_object_unref (track_element); return; } @@ -1896,7 +1913,7 @@ layer_object_removed_cb (GESTimelineLayer * layer, GESClip * clip, /* Go over the clip's track element and figure out which one belongs to * the list of tracks we control */ - trackelements = ges_clip_get_track_elements (clip); + trackelements = ges_container_get_children (GES_CONTAINER (clip)); for (tmp = trackelements; tmp; tmp = tmp->next) { GESTrackElement *track_element = (GESTrackElement *) tmp->data; @@ -1909,13 +1926,12 @@ layer_object_removed_cb (GESTimelineLayer * layer, GESClip * clip, ges_track_remove_element (ges_track_element_get_track (track_element), track_element); - ges_clip_release_track_element (clip, track_element); + ges_container_remove (GES_CONTAINER (clip), + GES_TIMELINE_ELEMENT (track_element)); } - /* removing the reference added by _get_track_elements() */ - g_object_unref (track_element); } - g_list_free (trackelements); + g_list_free_full (trackelements, gst_object_unref); GST_DEBUG ("Done"); } diff --git a/ges/ges-title-clip.c b/ges/ges-title-clip.c index 28e01268e6..e9ee8e39ff 100644 --- a/ges/ges-title-clip.c +++ b/ges/ges-title-clip.c @@ -69,11 +69,10 @@ enum static GESTrackElement * ges_title_clip_create_track_element (GESClip * clip, GESTrackType type); -static void -ges_title_clip_track_element_added (GESClip * clip, - GESTrackElement * trackelement); -static void ges_title_clip_track_element_released (GESClip * clip, - GESTrackElement * trackelement); +static void _child_added (GESContainer * container, + GESTimelineElement * element); +static void _child_removed (GESContainer * container, + GESTimelineElement * element); static void ges_title_clip_get_property (GObject * object, guint property_id, @@ -165,6 +164,7 @@ ges_title_clip_class_init (GESTitleClipClass * klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GESClipClass *timobj_class = GES_CLIP_CLASS (klass); + GESContainerClass *container_class = GES_CONTAINER_CLASS (klass); g_type_class_add_private (klass, sizeof (GESTitleClipPrivate)); @@ -216,8 +216,9 @@ ges_title_clip_class_init (GESTitleClipClass * klass) timobj_class->create_track_element = ges_title_clip_create_track_element; timobj_class->need_fill_track = FALSE; - timobj_class->track_element_added = ges_title_clip_track_element_added; - timobj_class->track_element_released = ges_title_clip_track_element_released; + + container_class->child_added = _child_added; + container_class->child_removed = _child_removed; /** * GESTitleClip:color: @@ -593,29 +594,27 @@ ges_title_clip_get_ypos (GESTitleClip * self) } static void -ges_title_clip_track_element_released (GESClip * clip, - GESTrackElement * trackelement) +_child_removed (GESContainer * container, GESTimelineElement * element) { - GESTitleClipPrivate *priv = GES_TITLE_CLIP (clip)->priv; + GESTitleClipPrivate *priv = GES_TITLE_CLIP (container)->priv; - /* If this is called, we should be sure the trackelement exists */ - if (GES_IS_TITLE_SOURCE (trackelement)) { - GST_DEBUG_OBJECT (clip, "%p released from %p", trackelement, clip); - priv->track_titles = g_slist_remove (priv->track_titles, trackelement); - g_object_unref (trackelement); + /* If this is called, we should be sure the element exists */ + if (GES_IS_TITLE_SOURCE (element)) { + GST_DEBUG_OBJECT (container, "%" GST_PTR_FORMAT " removed", element); + priv->track_titles = g_slist_remove (priv->track_titles, element); + g_object_unref (element); } } static void -ges_title_clip_track_element_added (GESClip * clip, - GESTrackElement * trackelement) +_child_added (GESContainer * container, GESTimelineElement * element) { - GESTitleClipPrivate *priv = GES_TITLE_CLIP (clip)->priv; + GESTitleClipPrivate *priv = GES_TITLE_CLIP (container)->priv; - if (GES_IS_TITLE_SOURCE (trackelement)) { - GST_DEBUG_OBJECT (clip, "%p added to %p", trackelement, clip); - priv->track_titles = - g_slist_prepend (priv->track_titles, g_object_ref (trackelement)); + if (GES_IS_TITLE_SOURCE (element)) { + GST_DEBUG_OBJECT (container, "%" GST_PTR_FORMAT " added", element); + priv->track_titles = g_slist_prepend (priv->track_titles, + g_object_ref (element)); } } diff --git a/ges/ges-track-element.c b/ges/ges-track-element.c index ded021b037..0251967662 100644 --- a/ges/ges-track-element.c +++ b/ges/ges-track-element.c @@ -185,7 +185,7 @@ ges_track_element_dispose (GObject * object) GstState cstate; if (priv->track != NULL) { - GST_ERROR_OBJECT (object, "Still in %p, this means that you forgot" + g_error ("Still in %p, this means that you forgot" " to remove it from the GESTrack it is contained in. You always need" " to remove a GESTrackElement from its track before dropping the last" " reference\n" @@ -308,9 +308,6 @@ _set_start (GESTimelineElement * element, GstClockTime start) { GESTrackElement *object = GES_TRACK_ELEMENT (element); - GST_DEBUG ("object:%p, start:%" GST_TIME_FORMAT, - object, GST_TIME_ARGS (start)); - if (object->priv->gnlobject != NULL) { if (G_UNLIKELY (start == _START (object))) return FALSE; @@ -327,9 +324,6 @@ _set_inpoint (GESTimelineElement * element, GstClockTime inpoint) { GESTrackElement *object = GES_TRACK_ELEMENT (element); - GST_DEBUG ("object:%p, inpoint:%" GST_TIME_FORMAT, - object, GST_TIME_ARGS (inpoint)); - if (object->priv->gnlobject != NULL) { if (G_UNLIKELY (inpoint == _INPOINT (object))) @@ -348,9 +342,6 @@ _set_duration (GESTimelineElement * element, GstClockTime duration) GESTrackElement *object = GES_TRACK_ELEMENT (element); GESTrackElementPrivate *priv = object->priv; - GST_DEBUG ("object:%p, duration:%" GST_TIME_FORMAT, - object, GST_TIME_ARGS (duration)); - if (GST_CLOCK_TIME_IS_VALID (_MAXDURATION (element)) && duration > _INPOINT (object) + _MAXDURATION (element)) duration = _MAXDURATION (element) - _INPOINT (object); @@ -440,13 +431,13 @@ gnlobject_start_cb (GstElement * gnlobject, GParamSpec * arg G_GNUC_UNUSED, g_object_get (gnlobject, "start", &start, NULL); - GST_DEBUG ("gnlobject start : %" GST_TIME_FORMAT " current : %" + GST_DEBUG_OBJECT (gnlobject, "start : %" GST_TIME_FORMAT " current : %" GST_TIME_FORMAT, GST_TIME_ARGS (start), GST_TIME_ARGS (_START (track_element))); if (start != _START (track_element)) { - _START (track_element) = start; - g_object_notify (G_OBJECT (track_element), "start"); + ges_timeline_element_set_start (GES_TIMELINE_ELEMENT (track_element), + start); } } @@ -492,13 +483,13 @@ gnlobject_media_start_cb (GstElement * gnlobject, g_object_get (gnlobject, "media-start", &inpoint, NULL); - GST_DEBUG ("gnlobject in-point : %" GST_TIME_FORMAT " current : %" + GST_DEBUG_OBJECT (gnlobject, "in-point : %" GST_TIME_FORMAT " current : %" GST_TIME_FORMAT, GST_TIME_ARGS (inpoint), GST_TIME_ARGS (_INPOINT (track_element))); if (inpoint != _INPOINT (track_element)) { - _INPOINT (track_element) = inpoint; - g_object_notify (G_OBJECT (track_element), "in-point"); + ges_timeline_element_set_inpoint (GES_TIMELINE_ELEMENT (track_element), + inpoint); } } @@ -514,8 +505,8 @@ gnlobject_priority_cb (GstElement * gnlobject, GParamSpec * arg G_GNUC_UNUSED, _PRIORITY (track_element)); if (priority != _PRIORITY (track_element)) { - _PRIORITY (track_element) = priority; - g_object_notify (G_OBJECT (track_element), "priority"); + ges_timeline_element_set_priority (GES_TIMELINE_ELEMENT (track_element), + priority); } } @@ -524,9 +515,6 @@ gnlobject_duration_cb (GstElement * gnlobject, GParamSpec * arg G_GNUC_UNUSED, GESTrackElement * track_element) { guint64 duration; - GESTrackElementClass *klass; - - klass = GES_TRACK_ELEMENT_GET_CLASS (track_element); g_object_get (gnlobject, "duration", &duration, NULL); @@ -535,10 +523,8 @@ gnlobject_duration_cb (GstElement * gnlobject, GParamSpec * arg G_GNUC_UNUSED, GST_TIME_ARGS (_DURATION (track_element))); if (duration != _DURATION (track_element)) { - _DURATION (track_element) = duration; - if (klass->duration_changed) - klass->duration_changed (track_element, duration); - g_object_notify (G_OBJECT (track_element), "duration"); + ges_timeline_element_set_duration (GES_TIMELINE_ELEMENT (track_element), + duration); } } @@ -779,38 +765,6 @@ ges_track_element_get_track (GESTrackElement * object) return object->priv->track; } -/** - * ges_track_element_set_clip: - * @object: The #GESTrackElement to set the parent to - * @clipect: The #GESClip, parent of @clip or %NULL - * - * Set the #GESClip to which @object belongs. - */ -void -ges_track_element_set_clip (GESTrackElement * object, GESClip * clipect) -{ - GST_DEBUG ("object:%p, clip:%p", object, clipect); - - object->priv->timelineobj = clipect; -} - -/** - * ges_track_element_get_clip: - * @object: a #GESTrackElement - * - * Get the #GESClip which is controlling this track element - * - * Returns: (transfer none): the #GESClip which is controlling - * this track element - */ -GESClip * -ges_track_element_get_clip (GESTrackElement * object) -{ - g_return_val_if_fail (GES_IS_TRACK_ELEMENT (object), NULL); - - return object->priv->timelineobj; -} - /** * ges_track_element_get_gnlobject: * @object: a #GESTrackElement diff --git a/ges/ges-track-element.h b/ges/ges-track-element.h index ffcc059e83..ac4231552a 100644 --- a/ges/ges-track-element.h +++ b/ges/ges-track-element.h @@ -122,11 +122,6 @@ GESTrackType ges_track_element_get_track_type (GESTrackElement * object); void ges_track_element_set_track_type (GESTrackElement * object, GESTrackType type); -void ges_track_element_set_clip (GESTrackElement * object, - GESClip * clipect); -GESClip * -ges_track_element_get_clip (GESTrackElement* object); - GstElement * ges_track_element_get_gnlobject (GESTrackElement * object); GstElement * ges_track_element_get_element (GESTrackElement * object); diff --git a/ges/ges-track.c b/ges/ges-track.c index 492c32b71a..c128dda939 100644 --- a/ges/ges-track.c +++ b/ges/ges-track.c @@ -382,10 +382,11 @@ dispose_trackelements_foreach (GESTrackElement * trackelement, GESTrack * track) { GESClip *clip; - clip = ges_track_element_get_clip (trackelement); + clip = GES_CLIP (GES_TIMELINE_ELEMENT_PARENT (trackelement)); + ges_container_remove (GES_CONTAINER (clip), + GES_TIMELINE_ELEMENT (trackelement)); remove_object_internal (track, trackelement); - ges_clip_release_track_element (clip, trackelement); } /* GObject virtual methods */ @@ -819,6 +820,8 @@ ges_track_remove_element (GESTrack * track, GESTrackElement * object) priv = track->priv; + GST_DEBUG_OBJECT (track, "Removing %" GST_PTR_FORMAT, object); + if (remove_object_internal (track, object) == TRUE) { it = g_hash_table_lookup (priv->trackelements_iter, object); g_sequence_remove (it); diff --git a/ges/ges-transition-clip.c b/ges/ges-transition-clip.c index 345316daeb..304d7a6c9e 100644 --- a/ges/ges-transition-clip.c +++ b/ges/ges-transition-clip.c @@ -58,11 +58,10 @@ enum static GESTrackElement *_create_track_element (GESClip * self, GESTrackType type); -static void -ges_transition_clip_track_element_added (GESClip * clip, - GESTrackElement * trackelement); -static void ges_transition_clip_track_element_released (GESClip * clip, - GESTrackElement * trackelement); +static void _child_added (GESContainer * container, + GESTimelineElement * element); +static void _child_removed (GESContainer * container, + GESTimelineElement * element); /* Internal methods */ static void @@ -230,6 +229,7 @@ ges_transition_clip_class_init (GESTransitionClipClass * klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GESClipClass *timobj_class = GES_CLIP_CLASS (klass); + GESContainerClass *container_class = GES_CONTAINER_CLASS (klass); g_type_class_add_private (klass, sizeof (GESTransitionClipPrivate)); @@ -248,12 +248,11 @@ ges_transition_clip_class_init (GESTransitionClipClass * klass) GES_VIDEO_STANDARD_TRANSITION_TYPE_CROSSFADE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + container_class->child_added = _child_added; + container_class->child_removed = _child_removed; timobj_class->create_track_element = _create_track_element; timobj_class->need_fill_track = FALSE; - timobj_class->track_element_added = ges_transition_clip_track_element_added; - timobj_class->track_element_released = - ges_transition_clip_track_element_released; } static void @@ -268,30 +267,27 @@ ges_transition_clip_init (GESTransitionClip * self) } static void -ges_transition_clip_track_element_released (GESClip * clip, - GESTrackElement * trackelement) +_child_removed (GESContainer * container, GESTimelineElement * element) { - GESTransitionClipPrivate *priv = GES_TRANSITION_CLIP (clip)->priv; + GESTransitionClipPrivate *priv = GES_TRANSITION_CLIP (container)->priv; /* If this is called, we should be sure the trackelement exists */ - if (GES_IS_VIDEO_TRANSITION (trackelement)) { - GST_DEBUG ("GESVideoTransition %p released from %p", trackelement, clip); - priv->video_transitions = - g_slist_remove (priv->video_transitions, trackelement); - g_object_unref (trackelement); + if (GES_IS_VIDEO_TRANSITION (element)) { + GST_DEBUG_OBJECT (container, "%" GST_PTR_FORMAT " removed", element); + priv->video_transitions = g_slist_remove (priv->video_transitions, element); + g_object_unref (element); } } static void -ges_transition_clip_track_element_added (GESClip * clip, - GESTrackElement * trackelement) +_child_added (GESContainer * container, GESTimelineElement * element) { - GESTransitionClipPrivate *priv = GES_TRANSITION_CLIP (clip)->priv; + GESTransitionClipPrivate *priv = GES_TRANSITION_CLIP (container)->priv; - if (GES_IS_VIDEO_TRANSITION (trackelement)) { - GST_DEBUG ("GESVideoTransition %p added to %p", trackelement, clip); + if (GES_IS_VIDEO_TRANSITION (element)) { + GST_DEBUG_OBJECT (container, "%" GST_PTR_FORMAT " added", element); priv->video_transitions = - g_slist_prepend (priv->video_transitions, g_object_ref (trackelement)); + g_slist_prepend (priv->video_transitions, g_object_ref (element)); } } diff --git a/ges/ges-types.h b/ges/ges-types.h index 8b1f49ea8f..988c8200fd 100644 --- a/ges/ges-types.h +++ b/ges/ges-types.h @@ -44,6 +44,9 @@ typedef struct _GESTimelineLayerClass GESTimelineLayerClass; typedef struct _GESTimelineElementClass GESTimelineElementClass; typedef struct _GESTimelineElement GESTimelineElement; +typedef struct _GESContainer GESContainer; +typedef struct _GESContainerClass GESContainerClass; + typedef struct _GESClip GESClip; typedef struct _GESClipClass GESClipClass; diff --git a/ges/ges-uri-clip.c b/ges/ges-uri-clip.c index 19dcab8b88..b3be330923 100644 --- a/ges/ges-uri-clip.c +++ b/ges/ges-uri-clip.c @@ -280,25 +280,20 @@ ges_uri_clip_init (GESUriClip * self) void ges_uri_clip_set_mute (GESUriClip * self, gboolean mute) { - GList *tmp, *trackelements; - GESClip *clip = (GESClip *) self; + GList *tmp; GST_DEBUG ("self:%p, mute:%d", self, mute); self->priv->mute = mute; /* Go over tracked objects, and update 'active' status on all audio objects */ - trackelements = ges_clip_get_track_elements (clip); - for (tmp = trackelements; tmp; tmp = tmp->next) { + for (tmp = GES_CONTAINER_CHILDREN (self); tmp; tmp = g_list_next (tmp)) { GESTrackElement *trackelement = (GESTrackElement *) tmp->data; if (ges_track_element_get_track (trackelement)->type == GES_TRACK_TYPE_AUDIO) ges_track_element_set_active (trackelement, !mute); - - g_object_unref (GES_TRACK_ELEMENT (tmp->data)); } - g_list_free (trackelements); } gboolean @@ -445,12 +440,9 @@ ges_uri_clip_new (gchar * uri) void ges_uri_clip_set_uri (GESUriClip * self, gchar * uri) { - GESClip *clip = GES_CLIP (self); - GList *trackelements = ges_clip_get_track_elements (clip); - - if (trackelements) { + if (GES_CONTAINER_CHILDREN (self)) { /* FIXME handle this case properly */ - GST_WARNING_OBJECT (clip, "Can not change uri when already" + GST_WARNING_OBJECT (self, "Can not change uri when already" "containing TrackElements"); return; diff --git a/tests/check/ges/backgroundsource.c b/tests/check/ges/backgroundsource.c index d25cddfd6a..c4877f0710 100644 --- a/tests/check/ges/backgroundsource.c +++ b/tests/check/ges/backgroundsource.c @@ -46,11 +46,11 @@ GST_START_TEST (test_test_source_properties) track = ges_track_new (GES_TRACK_TYPE_AUDIO, gst_caps_ref (GST_CAPS_ANY)); fail_unless (track != NULL); - clip = (GESClip *) - ges_test_clip_new (); + clip = (GESClip *) ges_test_clip_new (); fail_unless (clip != NULL); /* Set some properties */ + GST_DEBUG ("Setting start duration and inpoint to %" GST_PTR_FORMAT, clip); g_object_set (clip, "start", (guint64) 42, "duration", (guint64) 51, "in-point", (guint64) 12, NULL); assert_equals_uint64 (_START (clip), 42); @@ -58,8 +58,11 @@ GST_START_TEST (test_test_source_properties) assert_equals_uint64 (_INPOINT (clip), 12); trackelement = ges_clip_create_track_element (clip, track->type); - ges_clip_add_track_element (clip, trackelement); + ges_container_add (GES_CONTAINER (clip), GES_TIMELINE_ELEMENT (trackelement)); fail_unless (trackelement != NULL); + fail_unless (GES_TIMELINE_ELEMENT_PARENT (trackelement) == + GES_TIMELINE_ELEMENT (clip)); + fail_unless (ges_track_element_set_track (trackelement, track)); /* Check that trackelement has the same properties */ @@ -93,7 +96,8 @@ GST_START_TEST (test_test_source_properties) gnl_object_check (ges_track_element_get_gnlobject (trackelement), 420, 510, 120, 510, 0, TRUE); - ges_clip_release_track_element (clip, trackelement); + ges_container_remove (GES_CONTAINER (clip), + GES_TIMELINE_ELEMENT (trackelement)); g_object_unref (clip); } @@ -254,7 +258,7 @@ GST_START_TEST (test_gap_filling_basic) assert_equals_uint64 (_DURATION (clip), 5); trackelement = ges_clip_create_track_element (clip, track->type); - ges_clip_add_track_element (clip, trackelement); + ges_container_add (GES_CONTAINER (clip), GES_TIMELINE_ELEMENT (trackelement)); fail_unless (ges_track_add_element (track, trackelement)); fail_unless (trackelement != NULL); @@ -276,7 +280,8 @@ GST_START_TEST (test_gap_filling_basic) assert_equals_uint64 (_DURATION (clip1), 5); trackelement1 = ges_clip_create_track_element (clip1, track->type); - ges_clip_add_track_element (clip1, trackelement1); + ges_container_add (GES_CONTAINER (clip1), + GES_TIMELINE_ELEMENT (trackelement1)); fail_unless (ges_track_add_element (track, trackelement1)); fail_unless (trackelement1 != NULL); gnlsrc1 = ges_track_element_get_gnlobject (trackelement1); @@ -303,7 +308,8 @@ GST_START_TEST (test_gap_filling_basic) fail_unless (clip2 != NULL); g_object_set (clip2, "start", (guint64) 35, "duration", (guint64) 5, NULL); trackelement2 = ges_clip_create_track_element (clip2, track->type); - ges_clip_add_track_element (clip2, trackelement2); + ges_container_add (GES_CONTAINER (clip2), + GES_TIMELINE_ELEMENT (trackelement2)); fail_unless (ges_track_add_element (track, trackelement2)); fail_unless (trackelement2 != NULL); assert_equals_uint64 (_START (trackelement2), 35); diff --git a/tests/check/ges/basic.c b/tests/check/ges/basic.c index 2a43eca991..f0e78b1609 100644 --- a/tests/check/ges/basic.c +++ b/tests/check/ges/basic.c @@ -56,7 +56,7 @@ GST_START_TEST (test_ges_scenario) GESTrack *track; GESCustomSourceClip *source; GESTrackElement *trackelement; - GList *trackelements, *tmp, *layers, *tracks; + GList *trackelements, *layers, *tracks; ges_init (); /* This is the simplest scenario ever */ @@ -112,19 +112,14 @@ GST_START_TEST (test_ges_scenario) ASSERT_OBJECT_REFCOUNT (layer, "layer", 1); /* Make sure the associated TrackElement is in the Track */ - trackelements = ges_clip_get_track_elements (GES_CLIP (source)); + trackelements = GES_CONTAINER_CHILDREN (source); fail_unless (trackelements != NULL); trackelement = GES_TRACK_ELEMENT (trackelements->data); - /* There are 4 references: + /* There are 3 references: * 1 by the clip * 1 by the track - * 1 by the timeline - * 1 added by the call to _get_track_elements() above */ - ASSERT_OBJECT_REFCOUNT (trackelement, "trackelement", 4); - for (tmp = trackelements; tmp; tmp = tmp->next) { - g_object_unref (GES_TRACK_ELEMENT (tmp->data)); - } - g_list_free (trackelements); + * 1 by the timeline */ + ASSERT_OBJECT_REFCOUNT (trackelement, "trackelement", 3); /* There are 3 references: * 1 by the clip * 1 by the timeline @@ -141,7 +136,7 @@ GST_START_TEST (test_ges_scenario) ASSERT_OBJECT_REFCOUNT (layer, "layer", 1); tmp_layer = ges_clip_get_layer (GES_CLIP (source)); fail_unless (tmp_layer == NULL); - trackelements = ges_clip_get_track_elements (GES_CLIP (source)); + trackelements = GES_CONTAINER_CHILDREN (source); fail_unless (trackelements == NULL); /* No unreffing then */ g_object_unref (source); @@ -184,7 +179,7 @@ GST_START_TEST (test_ges_timeline_add_layer) GESTimelineLayer *layer, *tmp_layer; GESTrack *track; GESCustomSourceClip *s1, *s2, *s3; - GList *trackelements, *tmp, *layers; + GList *trackelements, *layers; GESTrackElement *trackelement; ges_init (); @@ -248,45 +243,34 @@ GST_START_TEST (test_ges_timeline_add_layer) g_list_free (layers); /* Make sure the associated TrackElements are in the Track */ - trackelements = ges_clip_get_track_elements (GES_CLIP (s1)); + trackelements = GES_CONTAINER_CHILDREN (s1); fail_unless (trackelements != NULL); trackelement = GES_TRACK_ELEMENT (trackelements->data); - /* There are 4 references: + /* There are 3 references: * 1 by the clip * 1 by the trackelement - * 1 by the timeline - * 1 added by the call to _get_track_elements() above */ - ASSERT_OBJECT_REFCOUNT (trackelement, "trackelement", 4); - for (tmp = trackelements; tmp; tmp = tmp->next) { - g_object_unref (GES_TRACK_ELEMENT (tmp->data)); - } - g_list_free (trackelements); + * 1 by the timeline */ + ASSERT_OBJECT_REFCOUNT (trackelement, "trackelement", 3); /* There are 3 references: * 1 by the clip * 1 by the timeline * 1 by the trackelement */ ASSERT_OBJECT_REFCOUNT (trackelement, "trackelement", 3); - trackelements = ges_clip_get_track_elements (GES_CLIP (s2)); + trackelements = GES_CONTAINER_CHILDREN (s2); trackelement = GES_TRACK_ELEMENT (trackelements->data); fail_unless (trackelements != NULL); - for (tmp = trackelements; tmp; tmp = tmp->next) { - g_object_unref (GES_TRACK_ELEMENT (tmp->data)); - } - g_list_free (trackelements); + /* There are 3 references: * 1 by the clip * 1 by the timeline * 1 by the trackelement */ ASSERT_OBJECT_REFCOUNT (GES_TRACK_ELEMENT (trackelement), "trackelement", 3); - trackelements = ges_clip_get_track_elements (GES_CLIP (s3)); + trackelements = GES_CONTAINER_CHILDREN (s3); trackelement = GES_TRACK_ELEMENT (trackelements->data); fail_unless (trackelements != NULL); - for (tmp = trackelements; tmp; tmp = tmp->next) { - g_object_unref (GES_TRACK_ELEMENT (tmp->data)); - } - g_list_free (trackelements); + /* There are 3 references: * 1 by the clip * 1 by the timeline @@ -366,44 +350,35 @@ GST_START_TEST (test_ges_timeline_add_layer_first) fail_unless ((gpointer) GST_ELEMENT_PARENT (track) == (gpointer) timeline); /* Make sure the associated TrackElements are in the Track */ - trackelements = ges_clip_get_track_elements (GES_CLIP (s1)); + trackelements = GES_CONTAINER_CHILDREN (s1); fail_unless (trackelements != NULL); for (tmp = trackelements; tmp; tmp = tmp->next) { - /* Each object has 4 references: + /* Each object has 3 references: * 1 by the clip * 1 by the track - * 1 by the timeline - * 1 added by _get_track_element() above */ - ASSERT_OBJECT_REFCOUNT (GES_TRACK_ELEMENT (tmp->data), "trackelement", 4); - g_object_unref (GES_TRACK_ELEMENT (tmp->data)); + * 1 by the timeline */ + ASSERT_OBJECT_REFCOUNT (GES_TRACK_ELEMENT (tmp->data), "trackelement", 3); } - g_list_free (trackelements); - trackelements = ges_clip_get_track_elements (GES_CLIP (s2)); + trackelements = GES_CONTAINER_CHILDREN (s2); fail_unless (trackelements != NULL); for (tmp = trackelements; tmp; tmp = tmp->next) { - /* Each object has 4 references: + /* Each object has 3 references: * 1 by the clip * 1 by the track - * 1 by the timeline - * 1 added by _get_track_element() above */ - ASSERT_OBJECT_REFCOUNT (GES_TRACK_ELEMENT (tmp->data), "trackelement", 4); - g_object_unref (GES_TRACK_ELEMENT (tmp->data)); + * 1 by the timeline */ + ASSERT_OBJECT_REFCOUNT (GES_TRACK_ELEMENT (tmp->data), "trackelement", 3); } - g_list_free (trackelements); - trackelements = ges_clip_get_track_elements (GES_CLIP (s3)); + trackelements = GES_CONTAINER_CHILDREN (s3); fail_unless (trackelements != NULL); for (tmp = trackelements; tmp; tmp = tmp->next) { - /* Each object has 4 references: + /* Each object has 3 references: * 1 by the clip * 1 by the track - * 1 by the timeline - * 1 added by _get_track_element() above */ - ASSERT_OBJECT_REFCOUNT (GES_TRACK_ELEMENT (tmp->data), "trackelement", 4); - g_object_unref (GES_TRACK_ELEMENT (tmp->data)); + * 1 by the timeline */ + ASSERT_OBJECT_REFCOUNT (GES_TRACK_ELEMENT (tmp->data), "trackelement", 3); } - g_list_free (trackelements); /* theoretically this is all we need to do to ensure cleanup */ g_object_unref (timeline); @@ -478,67 +453,58 @@ GST_START_TEST (test_ges_timeline_remove_track) fail_unless ((gpointer) GST_ELEMENT_PARENT (track) == (gpointer) timeline); /* Make sure the associated TrackElements are in the Track */ - trackelements = ges_clip_get_track_elements (GES_CLIP (s1)); + trackelements = GES_CONTAINER_CHILDREN (s1); fail_unless (trackelements != NULL); t1 = GES_TRACK_ELEMENT ((trackelements)->data); for (tmp = trackelements; tmp; tmp = tmp->next) { - /* There are 4 references held: + /* There are 3 references held: * 1 by the clip * 1 by the track - * 1 by the timeline - * 1 added by the call to _get_track_elements() above */ - ASSERT_OBJECT_REFCOUNT (GES_TRACK_ELEMENT (tmp->data), "trackelement", 4); - g_object_unref (GES_TRACK_ELEMENT (tmp->data)); + * 1 by the timeline */ + ASSERT_OBJECT_REFCOUNT (GES_TRACK_ELEMENT (tmp->data), "trackelement", 3); } g_object_ref (t1); - g_list_free (trackelements); - /* There are 4 references held: - * 1 by the timelinobject + /* There are 3 references held: + * 1 by the container * 1 by the track * 1 by the timeline * 1 added by ourselves above (g_object_ref (t1)) */ ASSERT_OBJECT_REFCOUNT (t1, "trackelement", 4); - trackelements = ges_clip_get_track_elements (GES_CLIP (s2)); + trackelements = GES_CONTAINER_CHILDREN (s2); fail_unless (trackelements != NULL); t2 = GES_TRACK_ELEMENT (trackelements->data); for (tmp = trackelements; tmp; tmp = tmp->next) { - /* There are 4 references held: + /* There are 3 references held: * 1 by the clip * 1 by the track - * 1 by the timeline - * 1 added by the call to _get_track_elements() above */ - ASSERT_OBJECT_REFCOUNT (GES_TRACK_ELEMENT (tmp->data), "trackelement", 4); - g_object_unref (GES_TRACK_ELEMENT (tmp->data)); + * 1 by the timeline */ + ASSERT_OBJECT_REFCOUNT (GES_TRACK_ELEMENT (tmp->data), "trackelement", 3); } g_object_ref (t2); - g_list_free (trackelements); - /* There are 4 references held: - * 1 by the timelinobject + /* There are 3 references held: + * 1 by the container * 1 by the track * 1 by the timeline - * 1 added by ourselves above (g_object_ref (t1)) */ + * 1 added by ourselves above (g_object_ref (t2)) */ ASSERT_OBJECT_REFCOUNT (t2, "t2", 4); - trackelements = ges_clip_get_track_elements (GES_CLIP (s3)); + trackelements = GES_CONTAINER_CHILDREN (s3); fail_unless (trackelements != NULL); t3 = GES_TRACK_ELEMENT (trackelements->data); for (tmp = trackelements; tmp; tmp = tmp->next) { - /* There are 4 references held: + /* There are 3 references held: * 1 by the clip * 1 by the track - * 1 by the timeline - * 1 added by the call to _get_track_elements() above */ - ASSERT_OBJECT_REFCOUNT (GES_TRACK_ELEMENT (tmp->data), "trackelement", 4); - g_object_unref (GES_TRACK_ELEMENT (tmp->data)); + * 1 by the timeline */ + ASSERT_OBJECT_REFCOUNT (GES_TRACK_ELEMENT (tmp->data), "trackelement", 3); } g_object_ref (t3); - g_list_free (trackelements); - /* There are 4 references held: - * 1 by the timelinobject + /* There are 3 references held: + * 1 by the container * 1 by the track * 1 by the timeline - * 1 added by ourselves above (g_object_ref (t1)) */ + * 1 added by ourselves above (g_object_ref (t3)) */ ASSERT_OBJECT_REFCOUNT (t3, "t3", 4); /* remove the track and check that the track elements have been released */ @@ -659,70 +625,61 @@ GST_START_TEST (test_ges_timeline_multiple_tracks) g_list_free (layers); /* Make sure the associated TrackElements are in the Track */ - trackelements = ges_clip_get_track_elements (GES_CLIP (s1)); + trackelements = GES_CONTAINER_CHILDREN (s1); fail_unless (trackelements != NULL); t1 = GES_TRACK_ELEMENT ((trackelements)->data); for (tmp = trackelements; tmp; tmp = tmp->next) { - /* There are 4 references held: + /* There are 3 references held: * 1 by the clip * 1 by the track - * 1 by the timeline - * 1 added by the call to _get_track_elements() above */ - ASSERT_OBJECT_REFCOUNT (GES_TRACK_ELEMENT (tmp->data), "trackelement", 4); + * 1 by the timeline */ + ASSERT_OBJECT_REFCOUNT (GES_TRACK_ELEMENT (tmp->data), "trackelement", 3); fail_unless (ges_track_element_get_track (tmp->data) == track1); - g_object_unref (GES_TRACK_ELEMENT (tmp->data)); } g_object_ref (t1); - g_list_free (trackelements); - /* There are 4 references held: - * 1 by the timelinobject + /* There are 3 references held: + * 1 by the container * 1 by the track * 1 by the timeline * 1 added by ourselves above (g_object_ref (t1)) */ ASSERT_OBJECT_REFCOUNT (t1, "trackelement", 4); - trackelements = ges_clip_get_track_elements (GES_CLIP (s2)); + trackelements = GES_CONTAINER_CHILDREN (s2); fail_unless (trackelements != NULL); t2 = GES_TRACK_ELEMENT (trackelements->data); for (tmp = trackelements; tmp; tmp = tmp->next) { - /* There are 4 references held: + /* There are 3 references held: * 1 by the clip * 1 by the track - * 1 by the timeline - * 1 added by the call to _get_track_elements() above */ - ASSERT_OBJECT_REFCOUNT (GES_TRACK_ELEMENT (tmp->data), "trackelement", 4); + * 1 by the timeline */ + ASSERT_OBJECT_REFCOUNT (GES_TRACK_ELEMENT (tmp->data), "trackelement", 3); fail_unless (ges_track_element_get_track (tmp->data) == track2); - g_object_unref (GES_TRACK_ELEMENT (tmp->data)); } g_object_ref (t2); - g_list_free (trackelements); - /* There are 4 references held: - * 1 by the timelinobject + /* There are 3 references held: + * 1 by the container * 1 by the track * 1 by the timeline - * 1 added by ourselves above (g_object_ref (t1)) */ + * 1 added by ourselves above (g_object_ref (t2)) */ ASSERT_OBJECT_REFCOUNT (t2, "t2", 4); - trackelements = ges_clip_get_track_elements (GES_CLIP (s3)); + trackelements = GES_CONTAINER_CHILDREN (s3); fail_unless (trackelements != NULL); t3 = GES_TRACK_ELEMENT (trackelements->data); for (tmp = trackelements; tmp; tmp = tmp->next) { - /* There are 4 references held: + /* There are 3 references held: * 1 by the clip * 1 by the track - * 1 by the timeline - * 1 added by the call to _get_track_elements() above */ - ASSERT_OBJECT_REFCOUNT (GES_TRACK_ELEMENT (tmp->data), "trackelement", 4); + * 1 by the timeline */ + ASSERT_OBJECT_REFCOUNT (GES_TRACK_ELEMENT (tmp->data), "trackelement", 3); fail_unless (ges_track_element_get_track (tmp->data) == track1); - g_object_unref (GES_TRACK_ELEMENT (tmp->data)); } g_object_ref (t3); - g_list_free (trackelements); - /* There are 4 references held: - * 1 by the timelinobject + /* There are 3 references held: + * 1 by the container * 1 by the track * 1 by the timeline - * 1 added by ourselves above (g_object_ref (t1)) */ + * 1 added by ourselves above (g_object_ref (t3)) */ ASSERT_OBJECT_REFCOUNT (t3, "t3", 4); g_object_unref (t1); diff --git a/tests/check/ges/clip.c b/tests/check/ges/clip.c index a46ff67609..41449ea61f 100644 --- a/tests/check/ges/clip.c +++ b/tests/check/ges/clip.c @@ -61,7 +61,7 @@ GST_START_TEST (test_object_properties) assert_equals_uint64 (_INPOINT (clip), 12); trackelement = ges_clip_create_track_element (clip, track->type); - ges_clip_add_track_element (clip, trackelement); + ges_container_add (GES_CONTAINER (clip), GES_TIMELINE_ELEMENT (trackelement)); fail_unless (trackelement != NULL); fail_unless (ges_track_element_set_track (trackelement, track)); @@ -97,78 +97,8 @@ GST_START_TEST (test_object_properties) gnl_object_check (ges_track_element_get_gnlobject (trackelement), 400, 510, 120, 510, 0, TRUE); - ges_clip_release_track_element (clip, trackelement); - - g_object_unref (clip); - g_object_unref (track); -} - -GST_END_TEST; - -GST_START_TEST (test_object_properties_unlocked) -{ - GESTrack *track; - GESTrackElement *trackelement; - GESClip *clip; - - ges_init (); - - track = ges_track_new (GES_TRACK_TYPE_CUSTOM, gst_caps_ref (GST_CAPS_ANY)); - fail_unless (track != NULL); - - clip = (GESClip *) ges_custom_source_clip_new (my_fill_track_func, NULL); - fail_unless (clip != NULL); - - /* Set some properties */ - g_object_set (clip, "start", (guint64) 42, "duration", (guint64) 51, - "in-point", (guint64) 12, NULL); - assert_equals_uint64 (_START (clip), 42); - assert_equals_uint64 (_DURATION (clip), 51); - assert_equals_uint64 (_INPOINT (clip), 12); - - trackelement = ges_clip_create_track_element (clip, track->type); - ges_clip_add_track_element (clip, trackelement); - fail_unless (trackelement != NULL); - fail_unless (ges_track_element_set_track (trackelement, track)); - - /* Check that trackelement has the same properties */ - assert_equals_uint64 (_START (trackelement), 42); - assert_equals_uint64 (_DURATION (trackelement), 51); - assert_equals_uint64 (_INPOINT (trackelement), 12); - - /* And let's also check that it propagated correctly to GNonLin */ - gnl_object_check (ges_track_element_get_gnlobject (trackelement), 42, 51, 12, - 51, 0, TRUE); - - /* This time we unlock the trackelement and make sure it doesn't propagate */ - ges_track_element_set_locked (trackelement, FALSE); - - /* Change more properties, they will be set on the GESClip */ - g_object_set (clip, "start", (guint64) 420, "duration", (guint64) 510, - "in-point", (guint64) 120, NULL); - assert_equals_uint64 (_START (clip), 420); - assert_equals_uint64 (_DURATION (clip), 510); - assert_equals_uint64 (_INPOINT (clip), 120); - /* ... but not on the GESTrackElement since it was unlocked... */ - assert_equals_uint64 (_START (trackelement), 42); - assert_equals_uint64 (_DURATION (trackelement), 51); - assert_equals_uint64 (_INPOINT (trackelement), 12); - /* ... and neither on the GNonLin clip */ - gnl_object_check (ges_track_element_get_gnlobject (trackelement), 42, 51, 12, - 51, 0, TRUE); - - /* When unlocked, moving the GESTrackElement won't move the GESClip - * either */ - /* This time, we move the trackelement to see if the changes move - * along to the parent and the gnonlin clip */ - g_object_set (trackelement, "start", (guint64) 400, NULL); - assert_equals_uint64 (_START (clip), 420); - assert_equals_uint64 (_START (trackelement), 400); - gnl_object_check (ges_track_element_get_gnlobject (trackelement), 400, 51, 12, - 51, 0, TRUE); - - - ges_clip_release_track_element (clip, trackelement); + ges_container_remove (GES_CONTAINER (clip), + GES_TIMELINE_ELEMENT (trackelement)); g_object_unref (clip); g_object_unref (track); @@ -199,7 +129,7 @@ GST_START_TEST (test_split_object) assert_equals_uint64 (_INPOINT (clip), 12); trackelement = ges_clip_create_track_element (clip, track->type); - ges_clip_add_track_element (clip, trackelement); + ges_container_add (GES_CONTAINER (clip), GES_TIMELINE_ELEMENT (trackelement)); fail_unless (trackelement != NULL); fail_unless (ges_track_element_set_track (trackelement, track)); @@ -223,7 +153,7 @@ GST_START_TEST (test_split_object) assert_equals_uint64 (_DURATION (splitclip), 25); assert_equals_uint64 (_INPOINT (splitclip), 37); - splittrackelements = ges_clip_get_track_elements (splitclip); + splittrackelements = GES_CONTAINER_CHILDREN (splitclip); fail_unless_equals_int (g_list_length (splittrackelements), 1); splittrackelement = GES_TRACK_ELEMENT (splittrackelements->data); @@ -237,15 +167,12 @@ GST_START_TEST (test_split_object) /* We own the only ref */ ASSERT_OBJECT_REFCOUNT (splitclip, "splitclip", 1); - /* 1 ref for the Clip, 1 ref for the Track and 1 in splittrackelements */ - ASSERT_OBJECT_REFCOUNT (splittrackelement, "splittrackelement", 3); + /* 1 ref for the Clip and 1 ref for the Track */ + ASSERT_OBJECT_REFCOUNT (splittrackelement, "splittrackelement", 2); g_object_unref (track); g_object_unref (splitclip); g_object_unref (clip); - - ASSERT_OBJECT_REFCOUNT (splittrackelement, "splittrackelement", 1); - g_list_free_full (splittrackelements, g_object_unref); } GST_END_TEST; @@ -259,7 +186,6 @@ ges_suite (void) suite_add_tcase (s, tc_chain); tcase_add_test (tc_chain, test_object_properties); - tcase_add_test (tc_chain, test_object_properties_unlocked); tcase_add_test (tc_chain, test_split_object); return s; diff --git a/tests/check/ges/effects.c b/tests/check/ges/effects.c index a1ae2bb1da..ddd43d3ea2 100644 --- a/tests/check/ges/effects.c +++ b/tests/check/ges/effects.c @@ -21,7 +21,6 @@ #include #include -void effect_added_cb (GESClip * clip, GESBaseEffect * trop, gpointer data); void deep_prop_changed_cb (GESTrackElement * track_element, GstElement * element, GParamSpec * spec); @@ -44,7 +43,7 @@ GST_START_TEST (test_add_effect_to_clip) GESTimeline *timeline; GESTimelineLayer *layer; GESTrack *track_audio, *track_video; - GESEffect *base_effect; + GESEffect *effect; GESTestClip *source; ges_init (); @@ -67,17 +66,14 @@ GST_START_TEST (test_add_effect_to_clip) GST_DEBUG ("Create effect"); - base_effect = ges_effect_new ("agingtv"); + effect = ges_effect_new ("agingtv"); - fail_unless (GES_IS_BASE_EFFECT (base_effect)); + fail_unless (GES_IS_EFFECT (effect)); + fail_unless (ges_container_add (GES_CONTAINER (source), + GES_TIMELINE_ELEMENT (effect))); + fail_unless (ges_track_add_element (track_video, GES_TRACK_ELEMENT (effect))); - - fail_unless (ges_clip_add_track_element (GES_CLIP - (source), GES_TRACK_ELEMENT (base_effect))); - fail_unless (ges_track_add_element (track_video, - GES_TRACK_ELEMENT (base_effect))); - - assert_equals_int (GES_TRACK_ELEMENT (base_effect)->active, TRUE); + assert_equals_int (GES_TRACK_ELEMENT (effect)->active, TRUE); ges_timeline_layer_remove_clip (layer, (GESClip *) source); @@ -91,11 +87,10 @@ GST_START_TEST (test_get_effects_from_tl) GESTimeline *timeline; GESTimelineLayer *layer; GESTrack *track_video; - GESEffect *base_effect, *base_effect1, *base_effect2; + GESEffect *effect, *effect1, *effect2; GESTestClip *source; GList *effects, *tmp = NULL; gint effect_prio = -1; - guint clip_height = 0; ges_init (); @@ -115,31 +110,28 @@ GST_START_TEST (test_get_effects_from_tl) GST_DEBUG ("Create effect"); - base_effect = ges_effect_new ("agingtv"); - base_effect1 = ges_effect_new ("agingtv"); - base_effect2 = ges_effect_new ("agingtv"); + effect = ges_effect_new ("agingtv"); + effect1 = ges_effect_new ("agingtv"); + effect2 = ges_effect_new ("agingtv"); - fail_unless (GES_IS_BASE_EFFECT (base_effect)); - fail_unless (GES_IS_BASE_EFFECT (base_effect1)); - fail_unless (GES_IS_BASE_EFFECT (base_effect2)); + fail_unless (GES_IS_EFFECT (effect)); + fail_unless (GES_IS_EFFECT (effect1)); + fail_unless (GES_IS_EFFECT (effect2)); - fail_unless (ges_clip_add_track_element (GES_CLIP - (source), GES_TRACK_ELEMENT (base_effect))); + fail_unless (ges_container_add (GES_CONTAINER (source), + GES_TIMELINE_ELEMENT (effect))); + fail_unless (ges_track_add_element (track_video, GES_TRACK_ELEMENT (effect))); + + fail_unless (ges_container_add (GES_CONTAINER (source), + GES_TIMELINE_ELEMENT (effect1))); fail_unless (ges_track_add_element (track_video, - GES_TRACK_ELEMENT (base_effect))); + GES_TRACK_ELEMENT (effect1))); - fail_unless (ges_clip_add_track_element (GES_CLIP - (source), GES_TRACK_ELEMENT (base_effect1))); + fail_unless (ges_container_add (GES_CONTAINER (source), + GES_TIMELINE_ELEMENT (effect2))); fail_unless (ges_track_add_element (track_video, - GES_TRACK_ELEMENT (base_effect1))); - - fail_unless (ges_clip_add_track_element (GES_CLIP - (source), GES_TRACK_ELEMENT (base_effect2))); - fail_unless (ges_track_add_element (track_video, - GES_TRACK_ELEMENT (base_effect2))); - - g_object_get (G_OBJECT (source), "height", &clip_height, NULL); - fail_unless (clip_height == 4); + GES_TRACK_ELEMENT (effect2))); + assert_equals_int (GES_CONTAINER_HEIGHT (source), 4); effects = ges_clip_get_top_effects (GES_CLIP (source)); fail_unless (g_list_length (effects) == 3); @@ -147,7 +139,7 @@ GST_START_TEST (test_get_effects_from_tl) gint priority = ges_clip_get_top_effect_position (GES_CLIP (source), GES_BASE_EFFECT (tmp->data)); fail_unless (priority > effect_prio); - fail_unless (GES_IS_BASE_EFFECT (tmp->data)); + fail_unless (GES_IS_EFFECT (tmp->data)); effect_prio = priority; g_object_unref (tmp->data); @@ -167,7 +159,7 @@ GST_START_TEST (test_effect_clip) GESTimelineLayer *layer; GESTrack *track_audio, *track_video; GESEffectClip *effect_clip; - GESEffect *tck_effect, *tck_effect1; + GESEffect *effect, *effect1; GList *effects, *tmp; gint i, clip_height; gint effect_prio = -1; @@ -196,20 +188,19 @@ GST_START_TEST (test_effect_clip) ges_simple_timeline_layer_add_object ((GESSimpleTimelineLayer *) (layer), (GESClip *) effect_clip, 0); - tck_effect = ges_effect_new ("identity"); - fail_unless (ges_clip_add_track_element (GES_CLIP - (effect_clip), GES_TRACK_ELEMENT (tck_effect))); - fail_unless (ges_track_add_element (track_video, - GES_TRACK_ELEMENT (tck_effect))); + effect = ges_effect_new ("identity"); + fail_unless (ges_container_add (GES_CONTAINER (effect_clip), + GES_TIMELINE_ELEMENT (effect))); + fail_unless (ges_track_add_element (track_video, GES_TRACK_ELEMENT (effect))); g_object_get (effect_clip, "height", &clip_height, NULL); assert_equals_int (clip_height, 3); - tck_effect1 = ges_effect_new ("identity"); - fail_unless (ges_clip_add_track_element (GES_CLIP - (effect_clip), GES_TRACK_ELEMENT (tck_effect1))); + effect1 = ges_effect_new ("identity"); + fail_unless (ges_container_add (GES_CONTAINER (effect_clip), + GES_TIMELINE_ELEMENT (effect1))); fail_unless (ges_track_add_element (track_audio, - GES_TRACK_ELEMENT (tck_effect1))); + GES_TRACK_ELEMENT (effect1))); g_object_get (effect_clip, "height", &clip_height, NULL); assert_equals_int (clip_height, 4); @@ -219,7 +210,7 @@ GST_START_TEST (test_effect_clip) gint priority = ges_clip_get_top_effect_position (GES_CLIP (effect_clip), GES_BASE_EFFECT (tmp->data)); fail_unless (priority > effect_prio); - fail_unless (GES_IS_BASE_EFFECT (tmp->data)); + fail_unless (GES_IS_EFFECT (tmp->data)); fail_unless (ges_track_element_get_track (GES_TRACK_ELEMENT (tmp-> data))->type == track_type[i]); effect_prio = priority; @@ -237,13 +228,14 @@ GST_END_TEST; GST_START_TEST (test_priorities_clip) { + gint i; + GList *effects, *tmp; GESTimeline *timeline; GESTimelineLayer *layer; - GESTrack *track_audio, *track_video; GESEffectClip *effect_clip; - GESEffect *tck_effect, *tck_effect1; - GList *effects, *tmp; - gint i, clip_height; + GESTrack *track_audio, *track_video; + GESEffect *effect, *effect1, *audio_effect = NULL, *video_effect = NULL; + gint effect_prio = -1; ges_init (); @@ -265,39 +257,56 @@ GST_START_TEST (test_priorities_clip) ges_simple_timeline_layer_add_object ((GESSimpleTimelineLayer *) (layer), (GESClip *) effect_clip, 0); - tck_effect = ges_effect_new ("identity"); - fail_unless (ges_clip_add_track_element (GES_CLIP - (effect_clip), GES_TRACK_ELEMENT (tck_effect))); - fail_unless (ges_track_add_element (track_video, - GES_TRACK_ELEMENT (tck_effect))); + for (tmp = GES_CONTAINER_CHILDREN (effect_clip); tmp; tmp = tmp->next) { + if (ges_track_element_get_track_type (GES_TRACK_ELEMENT (tmp->data)) == + GES_TRACK_TYPE_AUDIO) + audio_effect = tmp->data; + else if (ges_track_element_get_track_type (GES_TRACK_ELEMENT (tmp->data)) == + GES_TRACK_TYPE_VIDEO) + video_effect = tmp->data; + else + g_assert (0); + } + fail_unless (GES_IS_EFFECT (audio_effect)); + fail_unless (GES_IS_EFFECT (video_effect)); - g_object_get (effect_clip, "height", &clip_height, NULL); - fail_unless (clip_height == 3); + /* FIXME This is ridiculus, both effects should have the same priority (0) */ + assert_equals_int (_PRIORITY (audio_effect), 0); + assert_equals_int (_PRIORITY (video_effect), 1); + assert_equals_int (GES_CONTAINER_HEIGHT (effect_clip), 2); - tck_effect1 = ges_effect_new ("identity"); - fail_unless (ges_clip_add_track_element (GES_CLIP - (effect_clip), GES_TRACK_ELEMENT (tck_effect1))); + effect = ges_effect_new ("identity"); + GST_DEBUG ("Adding effect to the effect clip %" GST_PTR_FORMAT, effect); + fail_unless (ges_container_add (GES_CONTAINER (effect_clip), + GES_TIMELINE_ELEMENT (effect))); + fail_unless (ges_track_add_element (track_video, GES_TRACK_ELEMENT (effect))); + assert_equals_int (GES_CONTAINER_HEIGHT (effect_clip), 3); + + effect1 = ges_effect_new ("identity"); + GST_DEBUG ("Adding effect1 to the effect clip %" GST_PTR_FORMAT, effect1); + fail_unless (ges_container_add (GES_CONTAINER (effect_clip), + GES_TIMELINE_ELEMENT (effect1))); fail_unless (ges_track_add_element (track_audio, - GES_TRACK_ELEMENT (tck_effect1))); + GES_TRACK_ELEMENT (effect1))); - fail_unless (ges_clip_set_top_effect_priority (GES_CLIP - (effect_clip), GES_BASE_EFFECT (tck_effect1), 0)); + fail_unless (ges_clip_set_top_effect_priority (GES_CLIP (effect_clip), + GES_BASE_EFFECT (effect1), 0)); + assert_equals_int (_PRIORITY (effect), 3); + assert_equals_int (_PRIORITY (effect1), 0); + assert_equals_int (GES_CONTAINER_HEIGHT (effect_clip), 4); - fail_unless (_PRIORITY (tck_effect), 3); - - fail_unless (ges_clip_set_top_effect_priority (GES_CLIP - (effect_clip), GES_BASE_EFFECT (tck_effect1), 3)); - fail_unless (_PRIORITY (tck_effect) == 2); - - g_object_get (effect_clip, "height", &clip_height, NULL); - fail_unless (clip_height == 4); + fail_unless (ges_clip_set_top_effect_priority (GES_CLIP (effect_clip), + GES_BASE_EFFECT (effect1), 3)); + assert_equals_int (_PRIORITY (effect), 2); + assert_equals_int (_PRIORITY (effect1), 3); + assert_equals_int (GES_CONTAINER_HEIGHT (effect_clip), 4); effects = ges_clip_get_top_effects (GES_CLIP (effect_clip)); for (tmp = effects, i = 0; tmp; tmp = tmp->next, i++) { gint priority = ges_clip_get_top_effect_position (GES_CLIP (effect_clip), GES_BASE_EFFECT (tmp->data)); fail_unless (priority > effect_prio); - fail_unless (GES_IS_BASE_EFFECT (tmp->data)); + fail_unless (GES_IS_EFFECT (tmp->data)); effect_prio = priority; g_object_unref (tmp->data); @@ -311,13 +320,13 @@ GST_START_TEST (test_priorities_clip) GST_END_TEST; -GST_START_TEST (test_base_effect_set_properties) +GST_START_TEST (test_effect_set_properties) { GESTimeline *timeline; GESTimelineLayer *layer; GESTrack *track_video; GESEffectClip *effect_clip; - GESTrackElement *tck_effect; + GESTrackElement *effect; guint scratch_line, n_props, i; gboolean color_aging; GParamSpec **pspecs, *spec; @@ -341,19 +350,20 @@ GST_START_TEST (test_base_effect_set_properties) ges_simple_timeline_layer_add_object ((GESSimpleTimelineLayer *) (layer), (GESClip *) effect_clip, 0); - tck_effect = GES_TRACK_ELEMENT (ges_effect_new ("agingtv")); - fail_unless (ges_clip_add_track_element (GES_CLIP (effect_clip), tck_effect)); - fail_unless (ges_track_add_element (track_video, tck_effect)); + effect = GES_TRACK_ELEMENT (ges_effect_new ("agingtv")); + fail_unless (ges_container_add (GES_CONTAINER (effect_clip), + GES_TIMELINE_ELEMENT (effect))); + fail_unless (ges_track_add_element (track_video, effect)); - ges_track_element_set_child_properties (tck_effect, + ges_track_element_set_child_properties (effect, "GstAgingTV::scratch-lines", 17, "color-aging", FALSE, NULL); - ges_track_element_get_child_properties (tck_effect, + ges_track_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 (tck_effect, &n_props); + pspecs = ges_track_element_list_children_properties (effect, &n_props); fail_unless (n_props == 7); spec = pspecs[0]; @@ -366,8 +376,8 @@ GST_START_TEST (test_base_effect_set_properties) g_value_init (&nval, G_TYPE_UINT); g_value_set_uint (&val, 10); - ges_track_element_set_child_property_by_pspec (tck_effect, spec, &val); - ges_track_element_get_child_property_by_pspec (tck_effect, spec, &nval); + ges_track_element_set_child_property_by_pspec (effect, spec, &val); + ges_track_element_get_child_property_by_pspec (effect, spec, &nval); fail_unless (g_value_get_uint (&nval) == 10); for (i = 0; i < n_props; i++) { @@ -382,12 +392,13 @@ GST_START_TEST (test_base_effect_set_properties) GST_END_TEST; -void -effect_added_cb (GESClip * clip, GESBaseEffect * trop, gpointer data) +static void +effect_added_cb (GESClip * clip, GESBaseEffect * trop, gboolean * effect_added) { GST_DEBUG ("Effect added"); fail_unless (GES_IS_CLIP (clip)); - fail_unless (GES_IS_BASE_EFFECT (trop)); + fail_unless (GES_IS_EFFECT (trop)); + *effect_added = TRUE; } void @@ -405,8 +416,9 @@ GST_START_TEST (test_clip_signals) GESTimelineLayer *layer; GESTrack *track_video; GESEffectClip *effect_clip; - GESEffect *tck_effect; + GESEffect *effect; GValue val = { 0, }; + gboolean effect_added = FALSE; ges_init (); @@ -419,27 +431,29 @@ GST_START_TEST (test_clip_signals) GST_DEBUG ("Create effect"); effect_clip = ges_effect_clip_new ("agingtv", NULL); - g_signal_connect (effect_clip, "effect-added", (GCallback) effect_added_cb, - effect_clip); + g_signal_connect (effect_clip, "child-added", (GCallback) effect_added_cb, + &effect_added); g_object_set (effect_clip, "duration", 25 * GST_SECOND, NULL); ges_simple_timeline_layer_add_object ((GESSimpleTimelineLayer *) (layer), (GESClip *) effect_clip, 0); - tck_effect = ges_effect_new ("agingtv"); - fail_unless (ges_clip_add_track_element (GES_CLIP - (effect_clip), GES_TRACK_ELEMENT (tck_effect))); - fail_unless (ges_track_add_element (track_video, - GES_TRACK_ELEMENT (tck_effect))); - g_signal_connect (tck_effect, "deep-notify", (GCallback) deep_prop_changed_cb, - tck_effect); + effect = ges_effect_new ("agingtv"); + fail_unless (ges_container_add (GES_CONTAINER (effect_clip), + GES_TIMELINE_ELEMENT (effect))); + fail_unless (effect_added); + g_signal_handlers_disconnect_by_func (effect_clip, effect_added_cb, + &effect_added); + fail_unless (ges_track_add_element (track_video, GES_TRACK_ELEMENT (effect))); + g_signal_connect (effect, "deep-notify", (GCallback) deep_prop_changed_cb, + effect); - ges_track_element_set_child_properties (GES_TRACK_ELEMENT (tck_effect), + ges_track_element_set_child_properties (GES_TRACK_ELEMENT (effect), "GstAgingTV::scratch-lines", 17, NULL); g_value_init (&val, G_TYPE_UINT); - ges_track_element_get_child_property (GES_TRACK_ELEMENT (tck_effect), + ges_track_element_get_child_property (GES_TRACK_ELEMENT (effect), "GstAgingTV::scratch-lines", &val); fail_unless (G_VALUE_HOLDS_UINT (&val)); g_value_unset (&val); @@ -463,7 +477,7 @@ ges_suite (void) tcase_add_test (tc_chain, test_get_effects_from_tl); tcase_add_test (tc_chain, test_effect_clip); tcase_add_test (tc_chain, test_priorities_clip); - tcase_add_test (tc_chain, test_base_effect_set_properties); + tcase_add_test (tc_chain, test_effect_set_properties); tcase_add_test (tc_chain, test_clip_signals); return s; diff --git a/tests/check/ges/layer.c b/tests/check/ges/layer.c index ed64c01684..e827be6703 100644 --- a/tests/check/ges/layer.c +++ b/tests/check/ges/layer.c @@ -257,13 +257,13 @@ GST_START_TEST (test_layer_priorities) assert_equals_int (prio2, 2 * LAYER_HEIGHT + 1); assert_equals_int (prio3, LAYER_HEIGHT * 3 - 1); - /* And change TrackElement-s priorities and check that changes are well + /* And change TrackElement-s priorities and check that changes are not * refected on it containing Clip */ ges_timeline_element_set_priority (GES_TIMELINE_ELEMENT (trackelement3), LAYER_HEIGHT * 2); g_object_get (gnlobj3, "priority", &prio3, NULL); assert_equals_int (prio3, 2 * LAYER_HEIGHT); - assert_equals_int (_PRIORITY (clip3), 0); + assert_equals_int (_PRIORITY (clip3), LAYER_HEIGHT - 1); g_object_unref (trackelement1); g_object_unref (trackelement2); @@ -1230,9 +1230,8 @@ GST_START_TEST (test_layer_activate_automatic_transition) GES_CLIP (ges_timeline_layer_add_asset (layer, transition_asset, 1000, 0, 500, 1, GES_TRACK_TYPE_VIDEO)); fail_unless (GES_IS_TRANSITION_CLIP (transition)); - objects = ges_clip_get_track_elements (transition); + objects = GES_CONTAINER_CHILDREN (transition); assert_equals_int (g_list_length (objects), 1); - g_list_free_full (objects, gst_object_unref); GST_DEBUG ("Checking the transitions"); /* diff --git a/tests/check/ges/overlays.c b/tests/check/ges/overlays.c index b96d2e9b97..aaa07ce35c 100644 --- a/tests/check/ges/overlays.c +++ b/tests/check/ges/overlays.c @@ -57,7 +57,7 @@ GST_START_TEST (test_overlay_properties) assert_equals_uint64 (_INPOINT (clip), 12); trackelement = ges_clip_create_track_element (clip, track->type); - ges_clip_add_track_element (clip, trackelement); + ges_container_add (GES_CONTAINER (clip), GES_TIMELINE_ELEMENT (trackelement)); fail_unless (trackelement != NULL); fail_unless (ges_track_element_set_track (trackelement, track)); @@ -84,7 +84,8 @@ GST_START_TEST (test_overlay_properties) gnl_object_check (ges_track_element_get_gnlobject (trackelement), 420, 510, 120, 510, 0, TRUE); - ges_clip_release_track_element (clip, trackelement); + ges_container_remove (GES_CONTAINER (clip), + GES_TIMELINE_ELEMENT (trackelement)); g_object_unref (clip); } diff --git a/tests/check/ges/simplelayer.c b/tests/check/ges/simplelayer.c index eac14c78a0..bc1003a03a 100644 --- a/tests/check/ges/simplelayer.c +++ b/tests/check/ges/simplelayer.c @@ -274,7 +274,8 @@ GST_START_TEST (test_gsl_with_transitions) source2 = ges_custom_source_clip_new (arbitrary_fill_track_func, (gpointer) ELEMENT); g_object_set (source2, "duration", GST_SECOND, "start", (guint64) 42, NULL); - GES_CLIP (source2)->height = 4; + GES_CONTAINER_HEIGHT (source2) = 4; + fail_unless_equals_uint64 (_DURATION (source2), GST_SECOND); source3 = ges_custom_source_clip_new (arbitrary_fill_track_func, @@ -330,7 +331,6 @@ GST_START_TEST (test_gsl_with_transitions) /* add objects in sequence */ GST_DEBUG ("Adding source1"); - fail_unless (ges_simple_timeline_layer_add_object (gstl, GES_CLIP (source1), -1)); fail_unless_equals_uint64 (_DURATION (source1), GST_SECOND); @@ -338,7 +338,6 @@ GST_START_TEST (test_gsl_with_transitions) fail_unless_equals_uint64 (_PRIORITY (source1), 2); GST_DEBUG ("Adding tr1"); - fail_unless (ges_simple_timeline_layer_add_object (gstl, GES_CLIP (tr1), -1)); fail_unless_equals_uint64 (_DURATION (source1), GST_SECOND); fail_unless_equals_uint64 (_START (source1), 0); @@ -348,7 +347,6 @@ GST_START_TEST (test_gsl_with_transitions) fail_unless_equals_uint64 (_PRIORITY (tr1), 1); GST_DEBUG ("Adding source2"); - fail_unless (ges_simple_timeline_layer_add_object (gstl, GES_CLIP (source2), -1)); fail_unless_equals_uint64 (_DURATION (source1), GST_SECOND); diff --git a/tests/check/ges/timelineedition.c b/tests/check/ges/timelineedition.c index b7bb7e5857..ed11915944 100644 --- a/tests/check/ges/timelineedition.c +++ b/tests/check/ges/timelineedition.c @@ -92,18 +92,21 @@ GST_START_TEST (test_basic_timeline_edition) trackelement = ges_clip_create_track_element (clip, track->type); fail_unless (trackelement != NULL); - fail_unless (ges_clip_add_track_element (clip, trackelement)); + fail_unless (ges_container_add (GES_CONTAINER (clip), + GES_TIMELINE_ELEMENT (trackelement))); fail_unless (ges_track_add_element (track, trackelement)); assert_equals_uint64 (_DURATION (trackelement), 10); trackelement1 = ges_clip_create_track_element (clip1, track->type); fail_unless (trackelement1 != NULL); - fail_unless (ges_clip_add_track_element (clip1, trackelement1)); + fail_unless (ges_container_add (GES_CONTAINER (clip1), + GES_TIMELINE_ELEMENT (trackelement1))); fail_unless (ges_track_add_element (track, trackelement1)); assert_equals_uint64 (_DURATION (trackelement1), 10); trackelement2 = ges_clip_create_track_element (clip2, track->type); - fail_unless (ges_clip_add_track_element (clip2, trackelement2)); + fail_unless (ges_container_add (GES_CONTAINER (clip2), + GES_TIMELINE_ELEMENT (trackelement2))); fail_unless (trackelement2 != NULL); fail_unless (ges_track_add_element (track, trackelement2)); assert_equals_uint64 (_DURATION (trackelement2), 60); @@ -294,12 +297,11 @@ GST_START_TEST (test_snapping) fail_unless (ges_timeline_layer_add_clip (layer, clip)); - fail_unless ((trackelements = ges_clip_get_track_elements (clip)) != NULL); + fail_unless ((trackelements = GES_CONTAINER_CHILDREN (clip)) != NULL); fail_unless ((trackelement = GES_TRACK_ELEMENT (trackelements->data)) != NULL); fail_unless (ges_track_element_get_track (trackelement) == track); assert_equals_uint64 (_DURATION (trackelement), 37); - g_list_free_full (trackelements, g_object_unref); /* We have 3 references to trackelement from: * track + timeline + clip */ @@ -309,24 +311,22 @@ GST_START_TEST (test_snapping) ASSERT_OBJECT_REFCOUNT (clip, "First clip", 1); fail_unless (ges_timeline_layer_add_clip (layer, clip1)); - fail_unless ((trackelements = ges_clip_get_track_elements (clip1)) != NULL); + fail_unless ((trackelements = GES_CONTAINER_CHILDREN (clip1)) != NULL); fail_unless ((trackelement1 = GES_TRACK_ELEMENT (trackelements->data)) != NULL); fail_unless (ges_track_element_get_track (trackelement1) == track); assert_equals_uint64 (_DURATION (trackelement1), 15); - g_list_free_full (trackelements, g_object_unref); /* Same ref logic */ ASSERT_OBJECT_REFCOUNT (trackelement1, "First trackelement", 3); ASSERT_OBJECT_REFCOUNT (clip1, "First clip", 1); fail_unless (ges_timeline_layer_add_clip (layer, clip2)); - fail_unless ((trackelements = ges_clip_get_track_elements (clip2)) != NULL); + fail_unless ((trackelements = GES_CONTAINER_CHILDREN (clip2)) != NULL); fail_unless ((trackelement2 = GES_TRACK_ELEMENT (trackelements->data)) != NULL); fail_unless (ges_track_element_get_track (trackelement2) == track); assert_equals_uint64 (_DURATION (trackelement2), 60); - g_list_free_full (trackelements, g_object_unref); /* Same ref logic */ ASSERT_OBJECT_REFCOUNT (trackelement2, "First trackelement", 3); @@ -484,6 +484,7 @@ GST_START_TEST (test_snapping) g_object_unref (timeline); /* Check we destroyed everything */ + fail_if (G_IS_OBJECT (timeline)); fail_if (G_IS_OBJECT (trackelement)); fail_if (G_IS_OBJECT (trackelement1)); fail_if (G_IS_OBJECT (trackelement2)); @@ -544,12 +545,11 @@ GST_START_TEST (test_timeline_edition_mode) fail_unless (ges_timeline_layer_add_clip (layer, clip)); - fail_unless ((trackelements = ges_clip_get_track_elements (clip)) != NULL); + fail_unless ((trackelements = GES_CONTAINER_CHILDREN (clip)) != NULL); fail_unless ((trackelement = GES_TRACK_ELEMENT (trackelements->data)) != NULL); fail_unless (ges_track_element_get_track (trackelement) == track); assert_equals_uint64 (_DURATION (trackelement), 10); - g_list_free_full (trackelements, g_object_unref); /* Add a new layer and add clipects to it */ fail_unless ((layer1 = ges_timeline_append_layer (timeline)) != NULL); @@ -557,20 +557,18 @@ GST_START_TEST (test_timeline_edition_mode) assert_equals_int (ges_timeline_layer_get_priority (layer1), 1); fail_unless (ges_timeline_layer_add_clip (layer1, clip1)); - fail_unless ((trackelements = ges_clip_get_track_elements (clip1)) != NULL); + fail_unless ((trackelements = GES_CONTAINER_CHILDREN (clip1)) != NULL); fail_unless ((trackelement1 = GES_TRACK_ELEMENT (trackelements->data)) != NULL); fail_unless (ges_track_element_get_track (trackelement1) == track); assert_equals_uint64 (_DURATION (trackelement1), 10); - g_list_free_full (trackelements, g_object_unref); fail_unless (ges_timeline_layer_add_clip (layer1, clip2)); - fail_unless ((trackelements = ges_clip_get_track_elements (clip2)) != NULL); + fail_unless ((trackelements = GES_CONTAINER_CHILDREN (clip2)) != NULL); fail_unless ((trackelement2 = GES_TRACK_ELEMENT (trackelements->data)) != NULL); fail_unless (ges_track_element_get_track (trackelement2) == track); assert_equals_uint64 (_DURATION (trackelement2), 60); - g_list_free_full (trackelements, g_object_unref); /** * Simple rippling clip to: 10 diff --git a/tests/check/ges/titles.c b/tests/check/ges/titles.c index 66c215bd73..c58482b48c 100644 --- a/tests/check/ges/titles.c +++ b/tests/check/ges/titles.c @@ -58,7 +58,7 @@ GST_START_TEST (test_title_source_properties) assert_equals_uint64 (_INPOINT (clip), 12); trackelement = ges_clip_create_track_element (clip, track->type); - ges_clip_add_track_element (clip, trackelement); + ges_container_add (GES_CONTAINER (clip), GES_TIMELINE_ELEMENT (trackelement)); fail_unless (trackelement != NULL); fail_unless (ges_track_element_set_track (trackelement, track)); @@ -85,7 +85,8 @@ GST_START_TEST (test_title_source_properties) gnl_object_check (ges_track_element_get_gnlobject (trackelement), 420, 510, 120, 510, 0, TRUE); - ges_clip_release_track_element (clip, trackelement); + ges_container_remove (GES_CONTAINER (clip), + GES_TIMELINE_ELEMENT (trackelement)); g_object_unref (clip); } diff --git a/tests/check/ges/transition.c b/tests/check/ges/transition.c index f7cb7e6c0d..5c8951a9f0 100644 --- a/tests/check/ges/transition.c +++ b/tests/check/ges/transition.c @@ -46,14 +46,14 @@ GST_START_TEST (test_transition_basic) /* Make sure track element is created and vtype is set */ trackelement = ges_clip_create_track_element (GES_CLIP (tr2), track->type); - ges_clip_add_track_element (GES_CLIP (tr2), trackelement); + ges_container_add (GES_CONTAINER (tr2), GES_TIMELINE_ELEMENT (trackelement)); fail_unless (trackelement != NULL); fail_unless (ges_video_transition_get_transition_type (GES_VIDEO_TRANSITION (trackelement)) == 1); - fail_unless (ges_clip_release_track_element (GES_CLIP - (tr2), trackelement) == TRUE); + fail_unless (ges_container_remove (GES_CONTAINER (tr2), + GES_TIMELINE_ELEMENT (trackelement)) == TRUE); g_object_unref (track); g_object_unref (tr1); @@ -86,7 +86,7 @@ GST_START_TEST (test_transition_properties) assert_equals_uint64 (_INPOINT (clip), 12); trackelement = ges_clip_create_track_element (clip, track->type); - ges_clip_add_track_element (clip, trackelement); + ges_container_add (GES_CONTAINER (clip), GES_TIMELINE_ELEMENT (trackelement)); fail_unless (trackelement != NULL); fail_unless (ges_track_element_set_track (trackelement, track)); @@ -133,13 +133,14 @@ GST_START_TEST (test_transition_properties) (GES_VIDEO_TRANSITION (trackelement)), 1); GST_DEBUG ("Releasing track element"); - ges_clip_release_track_element (clip, trackelement); + ges_container_remove (GES_CONTAINER (clip), + GES_TIMELINE_ELEMENT (trackelement)); g_object_set (clip, "vtype", 1, NULL); GST_DEBUG ("creating track element"); trackelement = ges_clip_create_track_element (clip, track->type); - ges_clip_add_track_element (clip, trackelement); + ges_container_add (GES_CONTAINER (clip), GES_TIMELINE_ELEMENT (trackelement)); fail_unless (trackelement != NULL); fail_unless (ges_track_element_set_track (trackelement, track)); @@ -150,7 +151,8 @@ GST_START_TEST (test_transition_properties) (GES_VIDEO_TRANSITION (trackelement)), 1); assert_equals_int (GES_TRANSITION_CLIP (clip)->vtype, 1); - ges_clip_release_track_element (clip, trackelement); + ges_container_remove (GES_CONTAINER (clip), + GES_TIMELINE_ELEMENT (trackelement)); g_object_unref (clip); g_object_unref (track); } diff --git a/tests/check/ges/uriclip.c b/tests/check/ges/uriclip.c index d539e578a7..acd5e260c8 100644 --- a/tests/check/ges/uriclip.c +++ b/tests/check/ges/uriclip.c @@ -121,10 +121,9 @@ GST_START_TEST (test_filesource_properties) track = ges_track_new (GES_TRACK_TYPE_AUDIO, GST_CAPS_ANY); fail_unless (track != NULL); - clip = (GESClip *) - ges_uri_clip_new ((gchar *) + clip = (GESClip *) ges_uri_clip_new ((gchar *) "crack:///there/is/no/way/this/exists"); - fail_unless (clip != NULL); + assert_is_type (clip, GES_TYPE_URI_CLIP); /* Set some properties */ g_object_set (clip, "start", (guint64) 42, "duration", (guint64) 51, @@ -135,9 +134,9 @@ GST_START_TEST (test_filesource_properties) assert_equals_uint64 (_INPOINT (clip), 12); trackelement = ges_clip_create_track_element (clip, track->type); - ges_clip_add_track_element (clip, trackelement); - fail_unless (trackelement != NULL); - fail_unless (ges_track_element_set_track (trackelement, track)); + ges_container_add (GES_CONTAINER (clip), GES_TIMELINE_ELEMENT (trackelement)); + assert_is_type (trackelement, GES_TYPE_TRACK_FILESOURCE); + fail_unless (ges_track_add_element (track, trackelement)); /* Check that trackelement has the same properties */ assert_equals_uint64 (_START (trackelement), 42); @@ -170,9 +169,9 @@ GST_START_TEST (test_filesource_properties) gnl_object_check (ges_track_element_get_gnlobject (trackelement), 420, 510, 120, 510, 0, TRUE); - ges_clip_release_track_element (clip, trackelement); + ges_container_remove (GES_CONTAINER (clip), + GES_TIMELINE_ELEMENT (trackelement)); - g_object_unref (clip); g_object_unref (track); } @@ -200,7 +199,8 @@ GST_START_TEST (test_filesource_images) /* the returned track element should be an image source */ track_element = ges_clip_create_track_element (clip, v->type); - ges_clip_add_track_element (clip, track_element); + ges_container_add (GES_CONTAINER (clip), + GES_TIMELINE_ELEMENT (track_element)); fail_unless (GES_IS_IMAGE_SOURCE (track_element)); /* The track holds a reference to the clip @@ -208,7 +208,8 @@ GST_START_TEST (test_filesource_images) ASSERT_OBJECT_REFCOUNT (track_element, "Video Track Element", 2); ges_track_remove_element (v, track_element); - ges_clip_release_track_element (clip, track_element); + ges_container_remove (GES_CONTAINER (clip), + GES_TIMELINE_ELEMENT (track_element)); /* the clip should not create any TrackElement in the audio track */ track_element = ges_clip_create_track_element (clip, a->type); diff --git a/tests/examples/ges-ui.c b/tests/examples/ges-ui.c index 84c6c554bc..aa1c63e925 100644 --- a/tests/examples/ges-ui.c +++ b/tests/examples/ges-ui.c @@ -1081,7 +1081,8 @@ app_add_effect_on_selected_clips (App * app, const gchar * bin_desc, for (tmp = objects; tmp; tmp = tmp->next) { effect = GES_TRACK_ELEMENT (ges_effect_new (bin_desc)); - ges_clip_add_track_element (GES_CLIP (tmp->data), effect); + ges_container_add (GES_CONTAINER (tmp->data), + GES_TIMELINE_ELEMENT (effect)); if (type == GES_TRACK_TYPE_VIDEO) ges_track_add_element (app->video_track, effect); diff --git a/tests/examples/transition.c b/tests/examples/transition.c index 4c89ab8945..32732e3f9a 100644 --- a/tests/examples/transition.c +++ b/tests/examples/transition.c @@ -62,12 +62,12 @@ print_transition_data (GESClip * tr) guint64 start, duration; gint priority; char *name; - GList *trackelements, *tmp; + GList *trackelements; if (!tr) return FALSE; - if (!(trackelements = ges_clip_get_track_elements (tr))) + if (!(trackelements = GES_CONTAINER_CHILDREN (tr))) return FALSE; if (!(trackelement = GES_TRACK_ELEMENT (trackelements->data))) return FALSE; @@ -80,12 +80,6 @@ print_transition_data (GESClip * tr) ((gfloat) start) / GST_SECOND, ((gfloat) duration) / GST_SECOND, priority); - for (tmp = trackelements; tmp; tmp = tmp->next) { - g_object_unref (GES_TRACK_ELEMENT (tmp->data)); - } - - g_list_free (trackelements); - return FALSE; }