Reimplement the timeline editing API

This is implemented on top of a Tree that represents the whole timeline.

SourceClips can not fully overlap anymore and the tests have been
updated to take that into account. Some new tests were added to verify
that behaviour in greater details
This commit is contained in:
Thibault Saunier 2019-03-01 19:32:19 -03:00 committed by Thibault Saunier
parent 7261f714fc
commit a46390ff56
27 changed files with 2814 additions and 2560 deletions

View file

@ -46,6 +46,10 @@ neighbour_changed_cb (GESClip * clip, GParamSpec * arg G_GNUC_UNUSED,
GESTimelineElement *parent =
ges_timeline_element_get_toplevel_parent (GES_TIMELINE_ELEMENT (clip));
if (ELEMENT_FLAG_IS_SET (parent, GES_TIMELINE_ELEMENT_SET_SIMPLE)) {
return;
}
if (parent) {
GESTimelineElement *prev_topparent =
ges_timeline_element_get_toplevel_parent (GES_TIMELINE_ELEMENT
@ -54,6 +58,11 @@ neighbour_changed_cb (GESClip * clip, GParamSpec * arg G_GNUC_UNUSED,
ges_timeline_element_get_toplevel_parent (GES_TIMELINE_ELEMENT
(self->previous_source));
if (ELEMENT_FLAG_IS_SET (prev_topparent, GES_TIMELINE_ELEMENT_SET_SIMPLE) ||
ELEMENT_FLAG_IS_SET (next_topparent, GES_TIMELINE_ELEMENT_SET_SIMPLE)) {
return;
}
if (parent == prev_topparent && parent == next_topparent) {
GST_DEBUG_OBJECT (self,
"Moving all inside the same group, nothing to do");
@ -192,3 +201,11 @@ ges_auto_transition_new (GESTrackElement * transition,
return self;
}
void
ges_auto_transition_update (GESAutoTransition * self)
{
GST_INFO ("Updating info %s",
GES_TIMELINE_ELEMENT_NAME (self->transition_clip));
neighbour_changed_cb (self->previous_clip, NULL, self);
}

View file

@ -71,6 +71,7 @@ struct _GESAutoTransition
G_GNUC_INTERNAL GType ges_auto_transition_get_type (void) G_GNUC_CONST;
G_GNUC_INTERNAL void ges_auto_transition_update (GESAutoTransition *self);
G_GNUC_INTERNAL GESAutoTransition * ges_auto_transition_new (GESTrackElement * transition,
GESTrackElement * previous_source,
GESTrackElement * next_source);

View file

@ -175,7 +175,6 @@ static gboolean
_set_duration (GESTimelineElement * element, GstClockTime duration)
{
GList *tmp;
GESTimeline *timeline;
GESContainer *container = GES_CONTAINER (element);
@ -183,16 +182,8 @@ _set_duration (GESTimelineElement * element, GstClockTime duration)
for (tmp = container->children; tmp; tmp = g_list_next (tmp)) {
GESTimelineElement *child = (GESTimelineElement *) tmp->data;
if (child != container->initiated_move) {
/* Make the snapping happen if in a timeline */
timeline = GES_TIMELINE_ELEMENT_TIMELINE (child);
if (timeline == NULL
|| ELEMENT_FLAG_IS_SET (element, GES_CLIP_IS_SPLITTING)
|| (ges_timeline_trim_object_simple (timeline, child, NULL,
GES_EDGE_END, _START (child) + duration, TRUE) == FALSE)) {
_set_duration0 (GES_TIMELINE_ELEMENT (child), duration);
}
}
if (child != container->initiated_move)
_set_duration0 (GES_TIMELINE_ELEMENT (child), duration);
}
container->children_control_mode = GES_CHILDREN_UPDATE;
@ -628,9 +619,8 @@ static gboolean
_edit (GESContainer * container, GList * layers,
gint new_layer_priority, GESEditMode mode, GESEdge edge, guint64 position)
{
GList *tmp;
gboolean ret = TRUE;
GESLayer *layer;
GESTimeline *timeline = GES_TIMELINE_ELEMENT_TIMELINE (container);
GESTimelineElement *element = GES_TIMELINE_ELEMENT (container);
if (!G_UNLIKELY (GES_CONTAINER_CHILDREN (container))) {
GST_WARNING_OBJECT (container, "Trying to edit, but not containing"
@ -638,31 +628,35 @@ _edit (GESContainer * container, GList * layers,
return FALSE;
}
for (tmp = GES_CONTAINER_CHILDREN (container); tmp; tmp = g_list_next (tmp)) {
if (GES_IS_SOURCE (tmp->data) || GES_IS_TRANSITION (tmp->data)) {
ret &= ges_track_element_edit (tmp->data, layers, mode, edge, position);
break;
}
if (!timeline) {
GST_WARNING_OBJECT (container, "Trying to edit, but not in any"
"timeline.");
return FALSE;
}
/* Moving to layer */
if (new_layer_priority == -1) {
GST_DEBUG_OBJECT (container, "Not moving new prio %d", new_layer_priority);
} else {
gint priority_offset;
layer = GES_CLIP (container)->priv->layer;
if (layer == NULL) {
GST_WARNING_OBJECT (container, "Not in any layer yet, not moving");
switch (mode) {
case GES_EDIT_MODE_RIPPLE:
return timeline_ripple_object (timeline, element,
new_layer_priority <
0 ? GES_TIMELINE_ELEMENT_LAYER_PRIORITY (container) :
new_layer_priority, layers, edge, position);
case GES_EDIT_MODE_TRIM:
return timeline_trim_object (timeline, element,
new_layer_priority <
0 ? GES_TIMELINE_ELEMENT_LAYER_PRIORITY (container) :
new_layer_priority, layers, edge, position);
case GES_EDIT_MODE_NORMAL:
return timeline_move_object (timeline, element,
new_layer_priority <
0 ? GES_TIMELINE_ELEMENT_LAYER_PRIORITY (container) :
new_layer_priority, layers, edge, position);
case GES_EDIT_MODE_ROLL:
return timeline_roll_object (timeline, element, layers, edge, position);
case GES_EDIT_MODE_SLIDE:
GST_ERROR ("Sliding not implemented.");
return FALSE;
}
priority_offset = new_layer_priority - ges_layer_get_priority (layer);
ret &= timeline_context_to_layer (layer->timeline, priority_offset);
}
return ret;
return FALSE;
}
static void
@ -1012,23 +1006,6 @@ ges_clip_set_layer (GESClip * clip, GESLayer * layer)
g_object_notify_by_pspec (G_OBJECT (clip), properties[PROP_LAYER]);
}
/**
* ges_clip_get_layer_priority:
* @clip: The clip to get the layer priority from
*
* Returns: The priority of the layer @clip is in, -1 if not in a layer.
*/
guint32
ges_clip_get_layer_priority (GESClip * clip)
{
g_return_val_if_fail (GES_IS_CLIP (clip), -1);
if (clip->priv->layer == NULL)
return -1;
return ges_layer_get_priority (clip->priv->layer);
}
/**
* ges_clip_set_moving_from_layer:
* @clip: a #GESClip
@ -1088,6 +1065,19 @@ ges_clip_move_to_layer (GESClip * clip, GESLayer * layer)
g_return_val_if_fail (GES_IS_CLIP (clip), FALSE);
g_return_val_if_fail (GES_IS_LAYER (layer), FALSE);
ELEMENT_SET_FLAG (clip, GES_CLIP_IS_MOVING);
if (layer->timeline
&& !timeline_tree_can_move_element (timeline_get_tree (layer->timeline),
GES_TIMELINE_ELEMENT (clip),
ges_layer_get_priority (layer),
GES_TIMELINE_ELEMENT_START (clip),
GES_TIMELINE_ELEMENT_DURATION (clip), NULL)) {
GST_INFO_OBJECT (layer, "Clip %" GES_FORMAT " can't move to layer %d",
GES_ARGS (clip), ges_layer_get_priority (layer));
ELEMENT_UNSET_FLAG (clip, GES_CLIP_IS_MOVING);
return FALSE;
}
current_layer = clip->priv->layer;
if (current_layer == NULL) {
@ -1099,11 +1089,11 @@ ges_clip_move_to_layer (GESClip * clip, GESLayer * layer)
GST_DEBUG_OBJECT (clip, "moving to layer %p, priority: %d", layer,
ges_layer_get_priority (layer));
ELEMENT_SET_FLAG (clip, GES_CLIP_IS_MOVING);
gst_object_ref (clip);
ret = ges_layer_remove_clip (current_layer, clip);
if (!ret) {
ELEMENT_UNSET_FLAG (clip, GES_CLIP_IS_MOVING);
gst_object_unref (clip);
return FALSE;
}
@ -1418,16 +1408,9 @@ ges_clip_split (GESClip * clip, guint64 position)
position - start + inpoint);
}
ELEMENT_SET_FLAG (clip, GES_CLIP_IS_SPLITTING);
ELEMENT_SET_FLAG (clip, GES_TIMELINE_ELEMENT_SET_SIMPLE);
_set_duration0 (GES_TIMELINE_ELEMENT (clip), old_duration);
ELEMENT_UNSET_FLAG (clip, GES_CLIP_IS_SPLITTING);
if (GES_TIMELINE_ELEMENT_TIMELINE (clip)) {
for (tmp = GES_CONTAINER_CHILDREN (new_object); tmp; tmp = tmp->next) {
timeline_create_transitions (GES_TIMELINE_ELEMENT_TIMELINE (tmp->data),
tmp->data);
}
}
ELEMENT_UNSET_FLAG (clip, GES_TIMELINE_ELEMENT_SET_SIMPLE);
return new_object;
}
@ -1466,134 +1449,40 @@ ges_clip_get_supported_formats (GESClip * clip)
gboolean
_ripple (GESTimelineElement * element, GstClockTime start)
{
gboolean ret = TRUE;
GESTimeline *timeline;
GESClip *clip = GES_CLIP (element);
timeline = ges_layer_get_timeline (clip->priv->layer);
if (timeline == NULL) {
GST_DEBUG ("Not in a timeline yet");
return FALSE;
}
if (start > _END (element))
start = _END (element);
if (GES_CONTAINER_CHILDREN (element)) {
GESTrackElement *track_element =
GES_TRACK_ELEMENT (GES_CONTAINER_CHILDREN (element)->data);
ret = timeline_ripple_object (timeline, track_element, NULL, GES_EDGE_NONE,
start);
}
return ret;
return ges_container_edit (GES_CONTAINER (element), NULL,
ges_timeline_element_get_layer_priority (element),
GES_EDIT_MODE_RIPPLE, GES_EDGE_NONE, start);
}
static gboolean
_ripple_end (GESTimelineElement * element, GstClockTime end)
{
gboolean ret = TRUE;
GESTimeline *timeline;
GESClip *clip = GES_CLIP (element);
timeline = ges_layer_get_timeline (clip->priv->layer);
if (timeline == NULL) {
GST_DEBUG ("Not in a timeline yet");
return FALSE;
}
if (GES_CONTAINER_CHILDREN (element)) {
GESTrackElement *track_element =
GES_TRACK_ELEMENT (GES_CONTAINER_CHILDREN (element)->data);
ret = timeline_ripple_object (timeline, track_element, NULL, GES_EDGE_END,
end);
}
return ret;
return ges_container_edit (GES_CONTAINER (element), NULL,
ges_timeline_element_get_layer_priority (element),
GES_EDIT_MODE_RIPPLE, GES_EDGE_END, end);
}
gboolean
_roll_start (GESTimelineElement * element, GstClockTime start)
{
gboolean ret = TRUE;
GESTimeline *timeline;
GESClip *clip = GES_CLIP (element);
timeline = ges_layer_get_timeline (clip->priv->layer);
if (timeline == NULL) {
GST_DEBUG ("Not in a timeline yet");
return FALSE;
}
if (GES_CONTAINER_CHILDREN (element)) {
GESTrackElement *track_element =
GES_TRACK_ELEMENT (GES_CONTAINER_CHILDREN (element)->data);
ret = timeline_roll_object (timeline, track_element, NULL, GES_EDGE_START,
start);
}
return ret;
return ges_container_edit (GES_CONTAINER (element), NULL,
ges_timeline_element_get_layer_priority (element),
GES_EDIT_MODE_ROLL, GES_EDGE_START, start);
}
gboolean
_roll_end (GESTimelineElement * element, GstClockTime end)
{
gboolean ret = TRUE;
GESTimeline *timeline;
GESClip *clip = GES_CLIP (element);
timeline = ges_layer_get_timeline (clip->priv->layer);
if (timeline == NULL) {
GST_DEBUG ("Not in a timeline yet");
return FALSE;
}
if (GES_CONTAINER_CHILDREN (element)) {
GESTrackElement *track_element =
GES_TRACK_ELEMENT (GES_CONTAINER_CHILDREN (element)->data);
ret = timeline_roll_object (timeline, track_element,
NULL, GES_EDGE_END, end);
}
return ret;
return ges_container_edit (GES_CONTAINER (element), NULL,
ges_timeline_element_get_layer_priority (element),
GES_EDIT_MODE_ROLL, GES_EDGE_END, end);
}
gboolean
_trim (GESTimelineElement * element, GstClockTime start)
{
gboolean ret = TRUE;
GESTimeline *timeline;
GESClip *clip = GES_CLIP (element);
timeline = ges_layer_get_timeline (clip->priv->layer);
if (timeline == NULL) {
GST_DEBUG ("Not in a timeline yet");
return FALSE;
}
if (GES_CONTAINER_CHILDREN (element)) {
GESTrackElement *track_element =
GES_TRACK_ELEMENT (GES_CONTAINER_CHILDREN (element)->data);
GST_DEBUG_OBJECT (element, "Trimming child: %" GST_PTR_FORMAT,
track_element);
ret = timeline_trim_object (timeline, track_element, NULL, GES_EDGE_START,
start);
}
return ret;
return ges_container_edit (GES_CONTAINER (element), NULL, -1,
GES_EDIT_MODE_TRIM, GES_EDGE_START, start);
}
/**

View file

@ -163,8 +163,6 @@ GES_API
GESLayer* ges_clip_get_layer (GESClip *clip);
GES_API
gboolean ges_clip_move_to_layer (GESClip *clip, GESLayer *layer);
GES_API
guint32 ges_clip_get_layer_priority (GESClip * clip);
/****************************************************
* Effects *

View file

@ -524,10 +524,14 @@ _child_start_changed_cb (GESTimelineElement * child,
GESContainerPrivate *priv = container->priv;
GESTimelineElement *element = GES_TIMELINE_ELEMENT (container);
GESChildrenControlMode pmode = container->children_control_mode;
map = g_hash_table_lookup (priv->mappings, child);
g_assert (map);
if (ELEMENT_FLAG_IS_SET (child, GES_TIMELINE_ELEMENT_SET_SIMPLE))
container->children_control_mode = GES_CHILDREN_UPDATE_ALL_VALUES;
switch (container->children_control_mode) {
case GES_CHILDREN_IGNORE_NOTIFIES:
return;
@ -540,8 +544,8 @@ _child_start_changed_cb (GESTimelineElement * child,
_DURATION (container) = _END (container) - start;
_START (container) = start;
GST_DEBUG_OBJECT (container, "Child move made us "
"move to %" GST_TIME_FORMAT, GST_TIME_ARGS (_START (container)));
GST_DEBUG_OBJECT (container, "Child move made us move %" GES_FORMAT,
GES_ARGS (container));
g_object_notify (G_OBJECT (container), "start");
}
@ -560,6 +564,9 @@ _child_start_changed_cb (GESTimelineElement * child,
default:
break;
}
if (ELEMENT_FLAG_IS_SET (child, GES_TIMELINE_ELEMENT_SET_SIMPLE))
container->children_control_mode = pmode;
}
static void
@ -577,7 +584,8 @@ _child_inpoint_changed_cb (GESTimelineElement * child,
map = g_hash_table_lookup (priv->mappings, child);
g_assert (map);
if (container->children_control_mode == GES_CHILDREN_UPDATE_OFFSETS) {
if (container->children_control_mode == GES_CHILDREN_UPDATE_OFFSETS
|| ELEMENT_FLAG_IS_SET (child, GES_TIMELINE_ELEMENT_SET_SIMPLE)) {
map->inpoint_offset = _START (container) - _START (child);
return;
@ -599,10 +607,14 @@ _child_duration_changed_cb (GESTimelineElement * child,
GstClockTime end = 0;
GESContainerPrivate *priv = container->priv;
GESTimelineElement *element = GES_TIMELINE_ELEMENT (container);
GESChildrenControlMode pmode = container->children_control_mode;
if (container->children_control_mode == GES_CHILDREN_IGNORE_NOTIFIES)
return;
if (ELEMENT_FLAG_IS_SET (child, GES_TIMELINE_ELEMENT_SET_SIMPLE))
container->children_control_mode = GES_CHILDREN_UPDATE_ALL_VALUES;
map = g_hash_table_lookup (priv->mappings, child);
g_assert (map);
@ -632,6 +644,9 @@ _child_duration_changed_cb (GESTimelineElement * child,
default:
break;
}
if (ELEMENT_FLAG_IS_SET (child, GES_TIMELINE_ELEMENT_SET_SIMPLE))
container->children_control_mode = pmode;
}
/****************************************************

View file

@ -255,11 +255,7 @@ _child_group_priority_changed (GESTimelineElement * child,
static gboolean
_trim (GESTimelineElement * group, GstClockTime start)
{
GList *tmp;
GstClockTime last_child_end = 0, oldstart = _START (group);
GESContainer *container = GES_CONTAINER (group);
GESTimeline *timeline = GES_TIMELINE_ELEMENT_TIMELINE (group);
gboolean ret = TRUE, expending = (start < _START (group));
if (timeline == NULL) {
GST_DEBUG ("Not in a timeline yet");
@ -267,40 +263,9 @@ _trim (GESTimelineElement * group, GstClockTime start)
return FALSE;
}
container->children_control_mode = GES_CHILDREN_IGNORE_NOTIFIES;
for (tmp = GES_CONTAINER_CHILDREN (group); tmp; tmp = tmp->next) {
GESTimelineElement *child = tmp->data;
if (expending) {
/* If the start is bigger, we do not touch it (in case we are expending) */
if (_START (child) > oldstart) {
GST_DEBUG_OBJECT (child, "Skipping as not at begining of the group");
continue;
}
ret &= ges_timeline_element_trim (child, start);
} else {
if (start > _END (child))
ret &= ges_timeline_element_trim (child, _END (child));
else if (_START (child) < start && _DURATION (child))
ret &= ges_timeline_element_trim (child, start);
}
}
for (tmp = GES_CONTAINER_CHILDREN (group); tmp; tmp = tmp->next) {
if (_DURATION (tmp->data))
last_child_end =
MAX (GES_TIMELINE_ELEMENT_END (tmp->data), last_child_end);
}
GES_GROUP (group)->priv->setting_value = TRUE;
_set_start0 (group, start);
_set_duration0 (group, last_child_end - start);
GES_GROUP (group)->priv->setting_value = FALSE;
container->children_control_mode = GES_CHILDREN_UPDATE;
return ret;
return timeline_tree_trim (timeline_get_tree (timeline), group,
0, GST_CLOCK_DIFF (start, _START (group)), GES_EDGE_START,
ges_timeline_get_snapping_distance (timeline));
}
static gboolean
@ -309,38 +274,44 @@ _set_priority (GESTimelineElement * element, guint32 priority)
GList *tmp, *layers;
gint diff = priority - _PRIORITY (element);
GESContainer *container = GES_CONTAINER (element);
GESTimeline *timeline = GES_TIMELINE_ELEMENT_TIMELINE (element);
if (GES_GROUP (element)->priv->setting_value == TRUE)
return TRUE;
container->children_control_mode = GES_CHILDREN_IGNORE_NOTIFIES;
layers = GES_TIMELINE_ELEMENT_TIMELINE (element) ?
GES_TIMELINE_ELEMENT_TIMELINE (element)->layers : NULL;
if (layers == NULL) {
GST_WARNING_OBJECT (element, "Not any layer in the timeline, not doing"
"anything, timeline: %" GST_PTR_FORMAT,
GES_TIMELINE_ELEMENT_TIMELINE (element));
return FALSE;
} else if (priority + GES_CONTAINER_HEIGHT (container) - 1 >
g_list_length (layers)) {
GST_WARNING_OBJECT (container, "Trying to move to a layer outside of"
"the timeline layers");
return FALSE;
}
for (tmp = GES_CONTAINER_CHILDREN (element); tmp; tmp = tmp->next) {
GESTimelineElement *child = tmp->data;
if (child != container->initiated_move) {
if (child != container->initiated_move
|| ELEMENT_FLAG_IS_SET (container, GES_TIMELINE_ELEMENT_SET_SIMPLE)) {
if (GES_IS_CLIP (child)) {
guint32 layer_prio = GES_TIMELINE_ELEMENT_LAYER_PRIORITY (child) + diff;
GESLayer *layer =
g_list_nth_data (GES_TIMELINE_GET_LAYERS (timeline), layer_prio);
GST_DEBUG_OBJECT (child, "moving from layer: %i to %i",
GES_TIMELINE_ELEMENT_LAYER_PRIORITY (child), layer_prio);
ges_clip_move_to_layer (GES_CLIP (child),
g_list_nth_data (layers, layer_prio));
if (layer == NULL) {
do {
layer = ges_timeline_append_layer (timeline);
} while (ges_layer_get_priority (layer) < layer_prio);
}
GST_DEBUG ("%" GES_FORMAT "moving from layer: %i to %i",
GES_ARGS (child), GES_TIMELINE_ELEMENT_LAYER_PRIORITY (child),
layer_prio);
ges_clip_move_to_layer (GES_CLIP (child), g_list_nth_data (layers,
layer_prio));
} else if (GES_IS_GROUP (child)) {
GST_DEBUG_OBJECT (child, "moving from %i to %i",
_PRIORITY (child), diff + _PRIORITY (child));
@ -358,24 +329,31 @@ _set_start (GESTimelineElement * element, GstClockTime start)
{
GList *tmp;
gint64 diff = start - _START (element);
GESTimeline *timeline;
GESContainer *container = GES_CONTAINER (element);
GESTimelineElement *toplevel =
ges_timeline_element_get_toplevel_parent (element);;
gst_object_unref (toplevel);
if (GES_GROUP (element)->priv->setting_value == TRUE)
/* Let GESContainer update itself */
return GES_TIMELINE_ELEMENT_CLASS (parent_class)->set_start (element,
start);
if (ELEMENT_FLAG_IS_SET (element, GES_TIMELINE_ELEMENT_SET_SIMPLE) ||
ELEMENT_FLAG_IS_SET (toplevel, GES_TIMELINE_ELEMENT_SET_SIMPLE)) {
container->children_control_mode = GES_CHILDREN_IGNORE_NOTIFIES;
for (tmp = GES_CONTAINER_CHILDREN (element); tmp; tmp = tmp->next)
_set_start0 (tmp->data, _START (tmp->data) + diff);
container->children_control_mode = GES_CHILDREN_UPDATE;
container->children_control_mode = GES_CHILDREN_IGNORE_NOTIFIES;
for (tmp = GES_CONTAINER_CHILDREN (element); tmp; tmp = tmp->next) {
GESTimelineElement *child = (GESTimelineElement *) tmp->data;
if (child != container->initiated_move &&
(_END (child) > _START (element) || _END (child) > start)) {
_set_start0 (child, _START (child) + diff);
}
return TRUE;
}
container->children_control_mode = GES_CHILDREN_UPDATE;
timeline = GES_TIMELINE_ELEMENT_TIMELINE (element);
if (timeline)
return ges_timeline_move_object_simple (timeline, element, NULL,
GES_EDGE_NONE, start);
return TRUE;
}
@ -399,6 +377,12 @@ _set_duration (GESTimelineElement * element, GstClockTime duration)
return GES_TIMELINE_ELEMENT_CLASS (parent_class)->set_duration (element,
duration);
if (element->timeline
&& !timeline_tree_can_move_element (timeline_get_tree (element->timeline),
element, _PRIORITY (element), element->start, duration, NULL)) {
return FALSE;
}
if (container->initiated_move == NULL) {
gboolean expending = (_DURATION (element) < duration);
@ -471,6 +455,7 @@ _child_added (GESContainer * group, GESTimelineElement * child)
}
priv->setting_value = TRUE;
ELEMENT_SET_FLAG (group, GES_TIMELINE_ELEMENT_SET_SIMPLE);
if (first_child_start != GES_TIMELINE_ELEMENT_START (group)) {
group->children_control_mode = GES_CHILDREN_IGNORE_NOTIFIES;
_set_start0 (GES_TIMELINE_ELEMENT (group), first_child_start);
@ -480,6 +465,7 @@ _child_added (GESContainer * group, GESTimelineElement * child)
_set_duration0 (GES_TIMELINE_ELEMENT (group),
last_child_end - first_child_start);
}
ELEMENT_UNSET_FLAG (group, GES_TIMELINE_ELEMENT_SET_SIMPLE);
priv->setting_value = FALSE;
group->children_control_mode = GES_CHILDREN_UPDATE;
@ -561,12 +547,14 @@ _child_removed (GESContainer * group, GESTimelineElement * child)
}
priv->setting_value = TRUE;
ELEMENT_SET_FLAG (group, GES_TIMELINE_ELEMENT_SET_SIMPLE);
first_child_start = GES_TIMELINE_ELEMENT_START (children->data);
if (first_child_start > GES_TIMELINE_ELEMENT_START (group)) {
group->children_control_mode = GES_CHILDREN_IGNORE_NOTIFIES;
_set_start0 (GES_TIMELINE_ELEMENT (group), first_child_start);
group->children_control_mode = GES_CHILDREN_UPDATE;
}
ELEMENT_UNSET_FLAG (group, GES_TIMELINE_ELEMENT_SET_SIMPLE);
priv->setting_value = FALSE;
}

View file

@ -30,6 +30,7 @@
#include "ges-asset.h"
#include "ges-base-xml-formatter.h"
#include "ges-timeline-tree.h"
G_BEGIN_DECLS
@ -50,7 +51,9 @@ GST_DEBUG_CATEGORY_EXTERN (_ges_debug);
#define _DURATION(obj) GES_TIMELINE_ELEMENT_DURATION (obj)
#define _MAXDURATION(obj) GES_TIMELINE_ELEMENT_MAX_DURATION (obj)
#define _PRIORITY(obj) GES_TIMELINE_ELEMENT_PRIORITY (obj)
#ifndef _END
#define _END(obj) (_START (obj) + _DURATION (obj))
#endif
#define _set_start0 ges_timeline_element_set_start
#define _set_inpoint0 ges_timeline_element_set_inpoint
#define _set_duration0 ges_timeline_element_set_duration
@ -60,44 +63,50 @@ GST_DEBUG_CATEGORY_EXTERN (_ges_debug);
"s<%p>" \
" [ %" GST_TIME_FORMAT \
" (%" GST_TIME_FORMAT \
") - %" GST_TIME_FORMAT "]"
") - %" GST_TIME_FORMAT "(%" GST_TIME_FORMAT") layer: %" G_GINT32_FORMAT "] "
#define GES_TIMELINE_ELEMENT_ARGS(element) \
GES_TIMELINE_ELEMENT_NAME(element), element, \
GST_TIME_ARGS(GES_TIMELINE_ELEMENT_START(element)), \
GST_TIME_ARGS(GES_TIMELINE_ELEMENT_INPOINT(element)), \
GST_TIME_ARGS(GES_TIMELINE_ELEMENT_DURATION(element))
GST_TIME_ARGS(GES_TIMELINE_ELEMENT_DURATION(element)), \
GST_TIME_ARGS(GES_TIMELINE_ELEMENT_MAX_DURATION(element)), \
GES_TIMELINE_ELEMENT_LAYER_PRIORITY(element)
#define GES_FORMAT GES_TIMELINE_ELEMENT_FORMAT
#define GES_ARGS GES_TIMELINE_ELEMENT_ARGS
G_GNUC_INTERNAL gboolean
timeline_ripple_object (GESTimeline *timeline, GESTrackElement *obj,
GList * layers, GESEdge edge,
guint64 position);
timeline_ripple_object (GESTimeline *timeline, GESTimelineElement *obj,
gint new_layer_priority,
GList * layers, GESEdge edge,
guint64 position);
G_GNUC_INTERNAL gboolean
timeline_slide_object (GESTimeline *timeline, GESTrackElement *obj,
GList * layers, GESEdge edge, guint64 position);
G_GNUC_INTERNAL gboolean
timeline_roll_object (GESTimeline *timeline, GESTrackElement *obj,
GList * layers, GESEdge edge, guint64 position);
timeline_roll_object (GESTimeline *timeline, GESTimelineElement *obj,
GList * layers, GESEdge edge, guint64 position);
G_GNUC_INTERNAL gboolean
timeline_trim_object (GESTimeline *timeline, GESTrackElement * object,
GList * layers, GESEdge edge, guint64 position);
timeline_trim_object (GESTimeline *timeline, GESTimelineElement * object,
guint32 new_layer_priority, GList * layers, GESEdge edge,
guint64 position);
G_GNUC_INTERNAL gboolean
ges_timeline_trim_object_simple (GESTimeline * timeline, GESTimelineElement * obj,
GList * layers, GESEdge edge, guint64 position, gboolean snapping);
guint32 new_layer_priority, GList * layers, GESEdge edge,
guint64 position, gboolean snapping);
G_GNUC_INTERNAL gboolean
ges_timeline_move_object_simple (GESTimeline * timeline, GESTimelineElement * object,
GList * layers, GESEdge edge, guint64 position);
G_GNUC_INTERNAL gboolean
timeline_move_object (GESTimeline *timeline, GESTrackElement * object,
GList * layers, GESEdge edge, guint64 position);
G_GNUC_INTERNAL gboolean
timeline_context_to_layer (GESTimeline *timeline, gint offset);
timeline_move_object (GESTimeline *timeline, GESTimelineElement * object,
guint32 new_layer_priority, GList * layers, GESEdge edge,
guint64 position);
G_GNUC_INTERNAL void
timeline_add_group (GESTimeline *timeline,
@ -121,6 +130,14 @@ gboolean
timeline_remove_element (GESTimeline *timeline,
GESTimelineElement *element);
G_GNUC_INTERNAL
GNode *
timeline_get_tree (GESTimeline *timeline);
G_GNUC_INTERNAL
void
timeline_update_transition (GESTimeline *timeline);
G_GNUC_INTERNAL
void
timeline_fill_gaps (GESTimeline *timeline);
@ -396,9 +413,8 @@ G_GNUC_INTERNAL GESVideoTestSource * ges_video_test_source_new (void);
****************************************************/
typedef enum
{
GES_CLIP_IS_SPLITTING = (1 << 0),
GES_CLIP_IS_MOVING = (1 << 1),
GES_TIMELINE_ELEMENT_SET_SIMPLE = (1 << 2),
GES_CLIP_IS_MOVING = (1 << 0),
GES_TIMELINE_ELEMENT_SET_SIMPLE = (1 << 1),
} GESTimelineElementFlags;
G_GNUC_INTERNAL gdouble ges_timeline_element_get_media_duration_factor(GESTimelineElement *self);
@ -406,9 +422,6 @@ G_GNUC_INTERNAL GESTimelineElement * ges_timeline_element_get_copied_from (GESTi
G_GNUC_INTERNAL GESTimelineElementFlags ges_timeline_element_flags (GESTimelineElement *self);
G_GNUC_INTERNAL void ges_timeline_element_set_flags (GESTimelineElement *self, GESTimelineElementFlags flags);
/* FIXME: Provide a clean way to get layer prio generically */
G_GNUC_INTERNAL gint32 _layer_priority (GESTimelineElement * element);
#define ELEMENT_FLAGS(obj) (ges_timeline_element_flags (GES_TIMELINE_ELEMENT(obj)))
#define ELEMENT_SET_FLAG(obj,flag) (ges_timeline_element_set_flags(GES_TIMELINE_ELEMENT(obj), (ELEMENT_FLAGS(obj) | (flag))))
#define ELEMENT_UNSET_FLAG(obj,flag) (ges_timeline_element_set_flags(GES_TIMELINE_ELEMENT(obj), (ELEMENT_FLAGS(obj) & ~(flag))))

View file

@ -666,6 +666,17 @@ ges_layer_add_clip (GESLayer * layer, GESClip * clip)
/* emit 'clip-added' */
g_signal_emit (layer, ges_layer_signals[OBJECT_ADDED], 0, clip);
if (!ELEMENT_FLAG_IS_SET (clip, GES_CLIP_IS_MOVING) && layer->timeline
&& !timeline_tree_can_move_element (timeline_get_tree (layer->timeline),
GES_TIMELINE_ELEMENT (clip),
GES_TIMELINE_ELEMENT_LAYER_PRIORITY (clip),
GES_TIMELINE_ELEMENT_START (clip),
GES_TIMELINE_ELEMENT_DURATION (clip), NULL)) {
GST_INFO_OBJECT (layer, "Clip %" GES_FORMAT, GES_ARGS (clip));
ges_layer_remove_clip_internal (layer, clip, TRUE);
return FALSE;
}
return TRUE;
}

View file

@ -49,43 +49,41 @@ G_DEFINE_TYPE_WITH_PRIVATE (GESSourceClip, ges_source_clip, GES_TYPE_CLIP);
static gboolean
_set_start (GESTimelineElement * element, GstClockTime start)
{
GList *tmp;
GESTimeline *timeline;
GESContainer *container = GES_CONTAINER (element);
GstClockTime rollback_start = GES_TIMELINE_ELEMENT_START (element);
GESTimelineElement *toplevel =
ges_timeline_element_get_toplevel_parent (element);
GST_DEBUG_OBJECT (element, "Setting children start, (initiated_move: %"
GST_PTR_FORMAT ")", container->initiated_move);
element->start = start;
g_object_notify (G_OBJECT (element), "start");
container->children_control_mode = GES_CHILDREN_IGNORE_NOTIFIES;
for (tmp = container->children; tmp; tmp = g_list_next (tmp)) {
GESTimelineElement *child = (GESTimelineElement *) tmp->data;
if (child != container->initiated_move) {
/* Make the snapping happen if in a timeline */
timeline = GES_TIMELINE_ELEMENT_TIMELINE (child);
if (timeline && !container->initiated_move) {
if (!ges_timeline_move_object_simple (timeline, child, NULL,
GES_EDGE_NONE, start)) {
for (tmp = container->children; tmp; tmp = g_list_next (tmp))
ges_timeline_element_set_start (tmp->data, rollback_start);
element->start = rollback_start;
g_object_notify (G_OBJECT (element), "start");
container->children_control_mode = GES_CHILDREN_UPDATE;
return FALSE;
}
}
_set_start0 (GES_TIMELINE_ELEMENT (child), start);
}
gst_object_unref (toplevel);
if (element->timeline
&& !ELEMENT_FLAG_IS_SET (element, GES_TIMELINE_ELEMENT_SET_SIMPLE)
&& !ELEMENT_FLAG_IS_SET (toplevel, GES_TIMELINE_ELEMENT_SET_SIMPLE)) {
ges_timeline_move_object_simple (element->timeline, element, NULL,
GES_EDGE_NONE, start);
return FALSE;
}
container->children_control_mode = GES_CHILDREN_UPDATE;
return
GES_TIMELINE_ELEMENT_CLASS (ges_source_clip_parent_class)->set_start
(element, start);
}
return FALSE;
static gboolean
_set_duration (GESTimelineElement * element, GstClockTime duration)
{
GESTimelineElement *toplevel =
ges_timeline_element_get_toplevel_parent (element);
gst_object_unref (toplevel);
if (element->timeline
&& !ELEMENT_FLAG_IS_SET (element, GES_TIMELINE_ELEMENT_SET_SIMPLE)
&& !ELEMENT_FLAG_IS_SET (toplevel, GES_TIMELINE_ELEMENT_SET_SIMPLE)) {
return !timeline_trim_object (element->timeline, element,
GES_TIMELINE_ELEMENT_LAYER_PRIORITY (element), NULL, GES_EDGE_END,
element->start + duration);
}
return
GES_TIMELINE_ELEMENT_CLASS (ges_source_clip_parent_class)->set_duration
(element, duration);
}
static void
@ -125,6 +123,7 @@ ges_source_clip_class_init (GESSourceClipClass * klass)
object_class->finalize = ges_source_clip_finalize;
element_class->set_start = _set_start;
element_class->set_duration = _set_duration;
}
static void

View file

@ -694,6 +694,9 @@ ges_timeline_element_set_start (GESTimelineElement * self, GstClockTime start)
g_return_val_if_fail (GES_IS_TIMELINE_ELEMENT (self), FALSE);
if (self->start == start)
return TRUE;
klass = GES_TIMELINE_ELEMENT_GET_CLASS (self);
GST_DEBUG_OBJECT (self, "current start: %" GST_TIME_FORMAT

1256
ges/ges-timeline-tree.c Normal file

File diff suppressed because it is too large Load diff

79
ges/ges-timeline-tree.h Normal file
View file

@ -0,0 +1,79 @@
#ifndef __GES_TIMELINE_TREE__
#define __GES_TIMELINE_TREE__
#include <ges/ges.h>
#include "ges-auto-transition.h"
void timeline_tree_track_element (GNode *root,
GESTimelineElement *element);
void timeline_tree_stop_tracking_element (GNode *root,
GESTimelineElement *element);
gboolean timeline_tree_can_move_element (GNode *root,
GESTimelineElement *element,
guint32 priority,
GstClockTime start,
GstClockTime duration,
GList *moving_track_elements);
gboolean timeline_tree_ripple (GNode *root,
gint64 layer_priority_offset,
GstClockTimeDiff offset,
GESTimelineElement *rippled_element,
GESEdge moving_edge,
GstClockTime snapping_distance);
void ges_timeline_emit_snapping (GESTimeline * timeline,
GESTimelineElement * elem1,
GESTimelineElement * elem2,
GstClockTime snap_time);
gboolean timeline_tree_trim (GNode *root,
GESTimelineElement *element,
gint64 layer_priority_offset,
GstClockTimeDiff offset,
GESEdge edge,
GstClockTime snapping_distance);
gboolean timeline_tree_move (GNode *root,
GESTimelineElement *element,
gint64 layer_priority_offset,
GstClockTimeDiff offset,
GESEdge edge,
GstClockTime snapping_distance);
gboolean timeline_tree_roll (GNode * root,
GESTimelineElement * element,
GstClockTimeDiff offset,
GESEdge edge,
GstClockTime snapping_distance);
typedef GESAutoTransition *
(*GESTreeGetAutoTransitionFunc) (GESTimeline * timeline,
GESTrackElement * previous,
GESTrackElement * next,
GstClockTime transition_duration);
void timeline_tree_create_transitions (GNode *root,
GESTreeGetAutoTransitionFunc get_auto_transition);
GstClockTime timeline_tree_get_duration (GNode *root);
void timeline_tree_debug (GNode * root);
GESAutoTransition *
ges_timeline_create_transition (GESTimeline * timeline, GESTrackElement * previous,
GESTrackElement * next, GESClip * transition,
GESLayer * layer, guint64 start, guint64 duration);
GESAutoTransition *
ges_timeline_find_auto_transition (GESTimeline * timeline, GESTrackElement * prev,
GESTrackElement * next, GstClockTime transition_duration);
void
timeline_update_duration (GESTimeline * timeline);
void timeline_tree_init_debug (void);
#endif // __GES_TIMELINE_TREE__

File diff suppressed because it is too large Load diff

View file

@ -1364,16 +1364,21 @@ ges_track_element_edit (GESTrackElement * object,
switch (mode) {
case GES_EDIT_MODE_NORMAL:
return timeline_move_object (timeline, object, layers, edge, position);
return timeline_move_object (timeline, GES_TIMELINE_ELEMENT (object), -1,
layers, edge, position);
break;
case GES_EDIT_MODE_TRIM:
return timeline_trim_object (timeline, object, layers, edge, position);
return timeline_trim_object (timeline, GES_TIMELINE_ELEMENT (object), -1,
layers, edge, position);
break;
case GES_EDIT_MODE_RIPPLE:
return timeline_ripple_object (timeline, object, layers, edge, position);
return timeline_ripple_object (timeline, GES_TIMELINE_ELEMENT (object),
GES_TIMELINE_ELEMENT_PRIORITY (object) / LAYER_HEIGHT,
layers, edge, position);
break;
case GES_EDIT_MODE_ROLL:
return timeline_roll_object (timeline, object, layers, edge, position);
return timeline_roll_object (timeline, GES_TIMELINE_ELEMENT (object),
layers, edge, position);
break;
case GES_EDIT_MODE_SLIDE:
return timeline_slide_object (timeline, object, layers, edge, position);

View file

@ -276,6 +276,24 @@ extractable_set_asset (GESExtractable * self, GESAsset * asset)
g_return_val_if_fail (GES_IS_URI_CLIP_ASSET (asset), FALSE);
uri_clip_asset = GES_URI_CLIP_ASSET (asset);
if (GST_CLOCK_TIME_IS_VALID (GES_TIMELINE_ELEMENT_DURATION (self)) &&
ges_uri_clip_asset_get_duration (uri_clip_asset) <
GES_TIMELINE_ELEMENT_INPOINT (self) +
GES_TIMELINE_ELEMENT_DURATION (self)) {
GST_INFO_OBJECT (self,
"Can not set asset to %p as its duration is %" GST_TIME_FORMAT
" < to inpoint %" GST_TIME_FORMAT " + %" GST_TIME_FORMAT " = %"
GST_TIME_FORMAT, asset,
GST_TIME_ARGS (ges_uri_clip_asset_get_duration (uri_clip_asset)),
GST_TIME_ARGS (GES_TIMELINE_ELEMENT_INPOINT (self)),
GST_TIME_ARGS (GES_TIMELINE_ELEMENT_DURATION (self)),
GST_TIME_ARGS (GES_TIMELINE_ELEMENT_INPOINT (self) +
GES_TIMELINE_ELEMENT_DURATION (self)));
return FALSE;
}
if (GST_CLOCK_TIME_IS_VALID (GES_TIMELINE_ELEMENT_DURATION (clip)) == FALSE)
_set_duration0 (GES_TIMELINE_ELEMENT (uriclip),
ges_uri_clip_asset_get_duration (uri_clip_asset));

View file

@ -51,6 +51,7 @@ ges_sources = [
'ges-command-line-formatter.c',
'ges-auto-transition.c',
'ges-timeline-element.c',
'ges-timeline-tree.c',
'ges-container.c',
'ges-effect-asset.c',
'ges-smart-adder.c',

View file

@ -227,6 +227,9 @@ GST_START_TEST (test_uri_clip_change_asset)
asset1 = GES_ASSET (ges_uri_clip_asset_request_sync (uri1, NULL));
fail_unless_equals_int (g_list_length (GES_CONTAINER_CHILDREN (extractable)),
2);
fail_if (ges_extractable_set_asset (extractable, asset1));
ges_timeline_element_set_duration (GES_TIMELINE_ELEMENT (extractable),
ges_uri_clip_asset_get_duration (GES_URI_CLIP_ASSET (asset1)));
fail_unless (ges_extractable_set_asset (extractable, asset1));
fail_unless_equals_int (g_list_length (GES_CONTAINER_CHILDREN (extractable)),
1);

View file

@ -94,13 +94,13 @@ GST_START_TEST (test_ges_scenario)
/* There are 3 references:
* 1 by the clip
* 1 by the track
* 2 by the timeline */
ASSERT_OBJECT_REFCOUNT (trackelement, "trackelement", 4);
* 1 by the timeline */
ASSERT_OBJECT_REFCOUNT (trackelement, "trackelement", 3);
/* There are 3 references:
* 1 by the clip
* 2 by the timeline
* 3 by the timeline
* 1 by the track */
ASSERT_OBJECT_REFCOUNT (trackelement, "trackelement", 4);
ASSERT_OBJECT_REFCOUNT (trackelement, "trackelement", 3);
GST_DEBUG ("Remove the Clip from the layer");
@ -225,13 +225,13 @@ GST_START_TEST (test_ges_timeline_add_layer)
/* There are 3 references:
* 1 by the clip
* 1 by the trackelement
* 2 by the timeline */
ASSERT_OBJECT_REFCOUNT (trackelement, "trackelement", 4);
* 1 by the timeline */
ASSERT_OBJECT_REFCOUNT (trackelement, "trackelement", 3);
/* There are 3 references:
* 1 by the clip
* 1 by the timeline
* 2 by the trackelement */
ASSERT_OBJECT_REFCOUNT (trackelement, "trackelement", 4);
* 1 by the trackelement */
ASSERT_OBJECT_REFCOUNT (trackelement, "trackelement", 3);
trackelements = GES_CONTAINER_CHILDREN (s2);
trackelement = GES_TRACK_ELEMENT (trackelements->data);
@ -240,8 +240,8 @@ GST_START_TEST (test_ges_timeline_add_layer)
/* There are 3 references:
* 1 by the clip
* 1 by the timeline
* 2 by the trackelement */
ASSERT_OBJECT_REFCOUNT (GES_TRACK_ELEMENT (trackelement), "trackelement", 4);
* 1 by the trackelement */
ASSERT_OBJECT_REFCOUNT (GES_TRACK_ELEMENT (trackelement), "trackelement", 3);
trackelements = GES_CONTAINER_CHILDREN (s3);
trackelement = GES_TRACK_ELEMENT (trackelements->data);
@ -251,7 +251,7 @@ GST_START_TEST (test_ges_timeline_add_layer)
* 1 by the clip
* 1 by the timeline
* 2 by the trackelement */
ASSERT_OBJECT_REFCOUNT (trackelement, "trackelement", 4);
ASSERT_OBJECT_REFCOUNT (trackelement, "trackelement", 3);
/* theoretically this is all we need to do to ensure cleanup */
gst_object_unref (timeline);
@ -334,8 +334,8 @@ GST_START_TEST (test_ges_timeline_add_layer_first)
/* Each object has 3 references:
* 1 by the clip
* 1 by the track
* 2 by the timeline */
ASSERT_OBJECT_REFCOUNT (GES_TRACK_ELEMENT (tmp->data), "trackelement", 4);
* 1 by the timeline */
ASSERT_OBJECT_REFCOUNT (GES_TRACK_ELEMENT (tmp->data), "trackelement", 3);
}
trackelements = GES_CONTAINER_CHILDREN (s2);
@ -344,8 +344,8 @@ GST_START_TEST (test_ges_timeline_add_layer_first)
/* Each object has 3 references:
* 1 by the clip
* 1 by the track
* 2 by the timeline */
ASSERT_OBJECT_REFCOUNT (GES_TRACK_ELEMENT (tmp->data), "trackelement", 4);
* 1 by the timeline */
ASSERT_OBJECT_REFCOUNT (GES_TRACK_ELEMENT (tmp->data), "trackelement", 3);
}
trackelements = GES_CONTAINER_CHILDREN (s3);
@ -354,8 +354,8 @@ GST_START_TEST (test_ges_timeline_add_layer_first)
/* Each object has 3 references:
* 1 by the clip
* 1 by the track
* 2 by the timeline */
ASSERT_OBJECT_REFCOUNT (GES_TRACK_ELEMENT (tmp->data), "trackelement", 4);
* 1 by the timeline */
ASSERT_OBJECT_REFCOUNT (GES_TRACK_ELEMENT (tmp->data), "trackelement", 3);
}
/* theoretically this is all we need to do to ensure cleanup */
@ -444,14 +444,14 @@ GST_START_TEST (test_ges_timeline_remove_track)
/* There are 3 references held:
* 1 by the clip
* 1 by the track
* 2 by the timeline */
ASSERT_OBJECT_REFCOUNT (GES_TRACK_ELEMENT (tmp->data), "trackelement", 4);
* 1 by the timeline */
ASSERT_OBJECT_REFCOUNT (GES_TRACK_ELEMENT (tmp->data), "trackelement", 3);
}
/* There are 3 references held:
* 1 by the container
* 1 by the track
* 2 by the timeline */
ASSERT_OBJECT_REFCOUNT (t1, "trackelement", 4);
* 1 by the timeline */
ASSERT_OBJECT_REFCOUNT (t1, "trackelement", 3);
trackelements = GES_CONTAINER_CHILDREN (s2);
fail_unless (trackelements != NULL);
@ -460,14 +460,14 @@ GST_START_TEST (test_ges_timeline_remove_track)
/* There are 3 references held:
* 1 by the clip
* 1 by the track
* 2 by the timeline */
ASSERT_OBJECT_REFCOUNT (GES_TRACK_ELEMENT (tmp->data), "trackelement", 4);
* 1 by the timeline */
ASSERT_OBJECT_REFCOUNT (GES_TRACK_ELEMENT (tmp->data), "trackelement", 3);
}
/* There are 3 references held:
* 1 by the container
* 1 by the track
* 2 by the timeline */
ASSERT_OBJECT_REFCOUNT (t2, "t2", 4);
* 1 by the timeline */
ASSERT_OBJECT_REFCOUNT (t2, "t2", 3);
trackelements = GES_CONTAINER_CHILDREN (s3);
fail_unless (trackelements != NULL);
@ -476,21 +476,21 @@ GST_START_TEST (test_ges_timeline_remove_track)
/* There are 3 references held:
* 1 by the clip
* 1 by the track
* 2 by the timeline */
ASSERT_OBJECT_REFCOUNT (GES_TRACK_ELEMENT (tmp->data), "trackelement", 4);
* 1 by the timeline */
ASSERT_OBJECT_REFCOUNT (GES_TRACK_ELEMENT (tmp->data), "trackelement", 3);
}
/* There are 3 references held:
* 1 by the container
* 1 by the track
* 2 by the timeline */
ASSERT_OBJECT_REFCOUNT (t3, "t3", 4);
* 1 by the timeline */
ASSERT_OBJECT_REFCOUNT (t3, "t3", 3);
/* remove the track and check that the track elements have been released */
fail_unless (ges_timeline_remove_track (timeline, track));
ASSERT_OBJECT_REFCOUNT (t1, "trackelement", 2);
ASSERT_OBJECT_REFCOUNT (t2, "trackelement", 2);
ASSERT_OBJECT_REFCOUNT (t3, "trackelement", 2);
ASSERT_OBJECT_REFCOUNT (t1, "trackelement", 1);
ASSERT_OBJECT_REFCOUNT (t2, "trackelement", 1);
ASSERT_OBJECT_REFCOUNT (t3, "trackelement", 1);
ASSERT_OBJECT_REFCOUNT (layer, "1 for the timeline", 1);
ASSERT_OBJECT_REFCOUNT (timeline, "1 for the us", 1);
tmp = ges_layer_get_clips (layer);
@ -614,17 +614,17 @@ GST_START_TEST (test_ges_timeline_multiple_tracks)
/* There are 3 references held:
* 1 by the clip
* 1 by the track
* 2 by the timeline */
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);
}
gst_object_ref (t1);
/* There are 3 references held:
* 1 by the container
* 1 by the track
* 2 by the timeline
* 1 by the timeline
* 1 added by ourselves above (gst_object_ref (t1)) */
ASSERT_OBJECT_REFCOUNT (t1, "trackelement", 5);
ASSERT_OBJECT_REFCOUNT (t1, "trackelement", 4);
trackelements = GES_CONTAINER_CHILDREN (s2);
fail_unless (trackelements != NULL);
@ -633,17 +633,17 @@ GST_START_TEST (test_ges_timeline_multiple_tracks)
/* There are 3 references held:
* 1 by the clip
* 1 by the track
* 2 by the timeline */
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);
}
gst_object_ref (t2);
/* There are 3 references held:
* 1 by the container
* 1 by the track
* 2 by the timeline
* 1 by the timeline
* 1 added by ourselves above (gst_object_ref (t2)) */
ASSERT_OBJECT_REFCOUNT (t2, "t2", 5);
ASSERT_OBJECT_REFCOUNT (t2, "t2", 4);
trackelements = GES_CONTAINER_CHILDREN (s3);
fail_unless (trackelements != NULL);
@ -652,17 +652,17 @@ GST_START_TEST (test_ges_timeline_multiple_tracks)
/* There are 3 references held:
* 1 by the clip
* 1 by the track
* 2 by the timeline */
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);
}
gst_object_ref (t3);
/* There are 3 references held:
* 1 by the container
* 1 by the track
* 2 by the timeline
* 1 by the timeline
* 1 added by ourselves above (gst_object_ref (t3)) */
ASSERT_OBJECT_REFCOUNT (t3, "t3", 5);
ASSERT_OBJECT_REFCOUNT (t3, "t3", 4);
gst_object_unref (t1);
gst_object_unref (t2);

View file

@ -365,7 +365,7 @@ GST_START_TEST (test_split_object)
/* 1 ref for the Clip, 1 ref for the Track and 2 ref for the timeline
* (1 for the "all_element" hashtable, another for the sequence of TrackElement*/
ASSERT_OBJECT_REFCOUNT (splittrackelement,
"1 ref for the Clip, 1 ref for the Track and 2 ref for the timeline", 4);
"1 ref for the Clip, 1 ref for the Track and 1 ref for the timeline", 3);
check_destroyed (G_OBJECT (timeline), G_OBJECT (splitclip), clip,
splittrackelement, NULL);
@ -429,7 +429,7 @@ GST_START_TEST (test_clip_group_ungroup)
tmp = ges_track_get_elements (audio_track);
assert_equals_int (g_list_length (tmp), 1);
ASSERT_OBJECT_REFCOUNT (tmp->data, "1 for the track + 1 for the container "
"+ 2 for the timeline + 1 in tmp list", 5);
"+ 1 for the timeline + 1 in tmp list", 4);
assert_equals_int (ges_track_element_get_track_type (tmp->data),
GES_TRACK_TYPE_AUDIO);
assert_equals_int (ges_clip_get_supported_formats (GES_CLIP
@ -438,7 +438,7 @@ GST_START_TEST (test_clip_group_ungroup)
tmp = ges_track_get_elements (video_track);
assert_equals_int (g_list_length (tmp), 1);
ASSERT_OBJECT_REFCOUNT (tmp->data, "1 for the track + 1 for the container "
"+ 2 for the timeline + 1 in tmp list", 5);
"+ 1 for the timeline + 1 in tmp list", 4);
assert_equals_int (ges_track_element_get_track_type (tmp->data),
GES_TRACK_TYPE_VIDEO);
assert_equals_int (ges_clip_get_supported_formats (GES_CLIP
@ -489,7 +489,7 @@ GST_START_TEST (test_clip_group_ungroup)
tmp = ges_track_get_elements (video_track);
assert_equals_int (g_list_length (tmp), 1);
ASSERT_OBJECT_REFCOUNT (tmp->data, "1 for the track + 1 for the container "
"+ 2 for the timeline + 1 in tmp list", 5);
"+ 1 for the timeline + 1 in tmp list", 4);
assert_equals_int (ges_track_element_get_track_type (tmp->data),
GES_TRACK_TYPE_VIDEO);
fail_unless (GES_CONTAINER (ges_timeline_element_get_parent (tmp->data)) ==

View file

@ -165,147 +165,69 @@ GST_START_TEST (test_move_group)
CHECK_OBJECT_PROPS (clip2, 60, 0, 50);
CHECK_OBJECT_PROPS (group, 10, 0, 100);
ASSERT_OBJECT_REFCOUNT (group, "2 ref for the timeline", 2);
/*
* 0 20---Group1---------------110
* | |
* layer: | |
* | |
* |--------------------------|
* 5--------- 0------------|
* layer1: | clip1 | | clip2 |
* 20--------30 60----------|
* |--------------------------|
*/
ges_timeline_element_trim (GES_TIMELINE_ELEMENT (group), 20);
CHECK_OBJECT_PROPS (clip, 15, 5, 0);
fail_if (ges_timeline_element_trim (GES_TIMELINE_ELEMENT (group), 20));
CHECK_OBJECT_PROPS (clip, 10, 0, 5);
CHECK_OBJECT_PROPS (clip1, 20, 5, 10);
CHECK_OBJECT_PROPS (clip2, 60, 0, 50);
CHECK_OBJECT_PROPS (group, 20, 0, 90);
/*
* 0 25---Group1---------------110
* | |
* layer: | |
* | |
* |--------------------------|
* 10------ 0------------|
* layer1: | clip1 | | clip2 |
* 25------30 60----------|
* |--------------------------|
*/
ges_timeline_element_trim (GES_TIMELINE_ELEMENT (group), 25);
CHECK_OBJECT_PROPS (clip, 15, 5, 0);
CHECK_OBJECT_PROPS (clip1, 25, 10, 5);
CHECK_OBJECT_PROPS (clip2, 60, 0, 50);
CHECK_OBJECT_PROPS (group, 25, 0, 85);
CHECK_OBJECT_PROPS (group, 10, 0, 100);
ASSERT_OBJECT_REFCOUNT (group, "2 ref for the timeline", 2);
/*
* 0 10------------Group1------------------110
* |------ |
* layer: |clip | |
* |-----15 |
* |-------------------------------------|
* | 10------ 0------------|
* layer1: | | clip1 | | clip2 |
* | 25------30 60----------|
* | |--------------------------|
* |-------------------------------------|
*/
fail_if (ges_timeline_element_trim (GES_TIMELINE_ELEMENT (group), 25));
CHECK_OBJECT_PROPS (clip, 10, 0, 5);
CHECK_OBJECT_PROPS (clip1, 20, 5, 10);
CHECK_OBJECT_PROPS (clip2, 60, 0, 50);
CHECK_OBJECT_PROPS (group, 10, 0, 100);
ASSERT_OBJECT_REFCOUNT (group, "2 ref for the timeline", 2);
/* Same thing in the end... */
ges_timeline_element_trim (GES_TIMELINE_ELEMENT (group), 10);
CHECK_OBJECT_PROPS (clip, 10, 0, 5);
CHECK_OBJECT_PROPS (clip1, 25, 10, 5);
CHECK_OBJECT_PROPS (clip1, 20, 5, 10);
CHECK_OBJECT_PROPS (clip2, 60, 0, 50);
CHECK_OBJECT_PROPS (group, 10, 0, 100);
ASSERT_OBJECT_REFCOUNT (group, "2 ref for the timeline", 2);
/*
* 0 25---Group1---------------110
* | |
* layer: 15 | |
* |clip | |
* - |--------------------------|
* 10------ 0------------|
* layer1: | clip1 | | clip2 |
* 25------30 60----------|
* |--------------------------|
* 0 12------------Group1---------------110
* 2------ |
* layer: |clip | |
* |-----15 |
* |----------------------------------|
* | 7--------- 2----------|
* layer1: | | clip1 | | clip2 |
* | 22--------30 62----------|
* |----------------------------------|
*/
ges_timeline_element_trim (GES_TIMELINE_ELEMENT (group), 25);
CHECK_OBJECT_PROPS (clip, 15, 5, 0);
CHECK_OBJECT_PROPS (clip1, 25, 10, 5);
CHECK_OBJECT_PROPS (clip2, 60, 0, 50);
CHECK_OBJECT_PROPS (group, 25, 0, 85);
ges_timeline_element_trim (GES_TIMELINE_ELEMENT (group), 12);
CHECK_OBJECT_PROPS (clip, 12, 2, 3);
CHECK_OBJECT_PROPS (clip1, 22, 7, 8);
CHECK_OBJECT_PROPS (clip2, 62, 2, 48);
CHECK_OBJECT_PROPS (group, 12, 0, 98);
ASSERT_OBJECT_REFCOUNT (group, "2 ref for the timeline", 2);
/*
* 0 25---Group1--30
* | |
* layer: 15 | |
* |clip | |
* - |------------
* 15-----------| 60
* layer1: | clip1 | |clip2
* 25------------| -
* |------------|
*/
/* Setting the duration would lead to overlaps */
ges_timeline_element_set_duration (GES_TIMELINE_ELEMENT (group), 10);
CHECK_OBJECT_PROPS (clip, 15, 5, 0);
CHECK_OBJECT_PROPS (clip1, 25, 10, 5);
CHECK_OBJECT_PROPS (clip2, 60, 0, 0);
CHECK_OBJECT_PROPS (group, 25, 0, 5);
/*
* 0 25---Group1---------------125
* | |
* layer: 15 | |
* |clip | |
* - |--------------------------|
* 10-------------------------|
* layer1: | clip1 | clip2 |
* 25--------------60----------|
* |--------------------------|
*/
CHECK_OBJECT_PROPS (clip, 12, 2, 3);
CHECK_OBJECT_PROPS (clip1, 22, 7, 8);
CHECK_OBJECT_PROPS (clip2, 62, 2, 48);
CHECK_OBJECT_PROPS (group, 12, 0, 98);
ges_timeline_element_set_duration (GES_TIMELINE_ELEMENT (group), 100);
CHECK_OBJECT_PROPS (clip, 15, 5, 0);
CHECK_OBJECT_PROPS (clip1, 25, 10, 100);
CHECK_OBJECT_PROPS (clip2, 60, 0, 65);
CHECK_OBJECT_PROPS (group, 25, 0, 100);
ASSERT_OBJECT_REFCOUNT (group, "2 ref for the timeline", 2);
CHECK_OBJECT_PROPS (clip, 12, 2, 3);
CHECK_OBJECT_PROPS (clip1, 22, 7, 8);
CHECK_OBJECT_PROPS (clip2, 62, 2, 50);
CHECK_OBJECT_PROPS (group, 12, 0, 100);
/*
* 0 20---Group1---------------120
* | |
* layer: 15 | |
* |clip| |
* - |--------------------------|
* 10-------------------------|
* layer1: | clip1 | clip2 |
* 20-------------55----------|
* |--------------------------|
*/
ges_timeline_element_set_start (GES_TIMELINE_ELEMENT (group), 20);
CHECK_OBJECT_PROPS (clip, 15, 5, 0);
CHECK_OBJECT_PROPS (clip1, 20, 10, 100);
CHECK_OBJECT_PROPS (clip2, 55, 0, 65);
CHECK_OBJECT_PROPS (clip, 20, 2, 3);
CHECK_OBJECT_PROPS (clip1, 30, 7, 8);
CHECK_OBJECT_PROPS (clip2, 70, 2, 50);
CHECK_OBJECT_PROPS (group, 20, 0, 100);
/*
* 0 10---Group1---------------120
* |-----15 |
* layer: | clip| |
* |------ |
* |--------------------------|
* 5--------------------------|
* layer1: | clip1 | clip2 |
* 10-------------55----------|
* |--------------------------|
*/
ges_timeline_element_trim (GES_TIMELINE_ELEMENT (group), 10);
CHECK_OBJECT_PROPS (clip, 10, 0, 5);
CHECK_OBJECT_PROPS (clip1, 10, 0, 110);
CHECK_OBJECT_PROPS (clip2, 55, 0, 65);
CHECK_OBJECT_PROPS (group, 10, 0, 110);
fail_if (ges_timeline_element_trim (GES_TIMELINE_ELEMENT (group), 10));
CHECK_OBJECT_PROPS (clip, 20, 2, 3);
CHECK_OBJECT_PROPS (clip1, 30, 7, 8);
CHECK_OBJECT_PROPS (clip2, 70, 2, 50);
CHECK_OBJECT_PROPS (group, 20, 0, 100);
ASSERT_OBJECT_REFCOUNT (group, "2 ref for the timeline", 2);
check_destroyed (G_OBJECT (timeline), G_OBJECT (group), NULL);

View file

@ -308,7 +308,7 @@ GST_START_TEST (test_single_layer_automatic_transition)
{
GESAsset *asset;
GESTimeline *timeline;
GList *objects, *current;
GList *objects;
GESClip *transition;
GESLayer *layer;
GESTimelineElement *src, *src1, *src2;
@ -379,24 +379,19 @@ GST_START_TEST (test_single_layer_automatic_transition)
ges_timeline_element_set_start (src, 250);
/*
* 500_____transition____1250
* 250___________src_________1250
* 600_____transition______1500
* 600___________src_________1600
* 500___________src1_________1500
*/
GST_DEBUG ("Checking src timing values");
assert_equals_uint64 (_START (src), 250);
assert_equals_uint64 (_DURATION (src), 1250 - 250);
assert_equals_uint64 (_START (src1), 500);
assert_equals_uint64 (_DURATION (src1), 1500 - 500);
CHECK_OBJECT_PROPS (src, 250, 0, 1000);
CHECK_OBJECT_PROPS (src1, 500, 0, 1000);
objects = ges_layer_get_clips (layer);
assert_equals_int (g_list_length (objects), 4);
assert_is_type (objects->data, GES_TYPE_TEST_CLIP);
transition = objects->next->data;
assert_is_type (transition, GES_TYPE_TRANSITION_CLIP);
assert_equals_uint64 (_START (transition), 500);
assert_equals_uint64 (_DURATION (transition), 750);
CHECK_OBJECT_PROPS (transition, 500, 0, 750);
transition = objects->next->next->data;
assert_is_type (transition, GES_TYPE_TRANSITION_CLIP);
@ -404,295 +399,65 @@ GST_START_TEST (test_single_layer_automatic_transition)
assert_equals_uint64 (_DURATION (transition), 750);
g_list_free_full (objects, gst_object_unref);
GST_DEBUG ("Moving second source to 250, the transitions should be removed");
ges_timeline_element_set_start (src1, 250);
fail_if (ges_timeline_element_set_start (src1, 250));
/* The transition should be removed
* 250___________src_________1250
* 250___________src1________1250
fail_if (ges_container_edit (GES_CONTAINER (src), NULL, -1,
GES_EDIT_MODE_TRIM, GES_EDGE_START, 500));
CHECK_OBJECT_PROPS (src, 250, 0, 1000);
CHECK_OBJECT_PROPS (src1, 500, 0, 1000);
fail_if (ges_timeline_element_trim (src, 500));
CHECK_OBJECT_PROPS (src, 250, 0, 1000);
CHECK_OBJECT_PROPS (src1, 500, 0, 1000);
fail_if (ges_timeline_element_trim (src, 750));
CHECK_OBJECT_PROPS (src, 250, 0, 1000);
CHECK_OBJECT_PROPS (src1, 500, 0, 1000);
fail_if (ges_timeline_element_set_start (src, 500));
CHECK_OBJECT_PROPS (src, 250, 0, 1000);
CHECK_OBJECT_PROPS (src1, 500, 0, 1000);
/*
* 600_____transition______1500
* 600___________src_________1600
* 500___________src1_________1500
*/
GST_DEBUG ("Checking src timing values");
assert_equals_uint64 (_START (src), 250);
assert_equals_uint64 (_DURATION (src), 1250 - 250);
assert_equals_uint64 (_START (src1), 250);
assert_equals_uint64 (_DURATION (src1), 1250 - 250);
objects = ges_layer_get_clips (layer);
assert_equals_int (g_list_length (objects), 2);
g_list_free_full (objects, gst_object_unref);
GST_DEBUG ("Trimming second source to 500 no transition should be created "
"as they have the same end");
ges_container_edit (GES_CONTAINER (src1), NULL, -1,
GES_EDIT_MODE_TRIM, GES_EDGE_START, 500);
/* 250___________src_________1250
* 500______src1_______1250
*/
GST_DEBUG ("Checking src timing values");
assert_equals_uint64 (_START (src), 250);
assert_equals_uint64 (_DURATION (src), 1250 - 250);
assert_equals_uint64 (_START (src1), 500);
assert_equals_uint64 (_DURATION (src1), 1250 - 500);
objects = ges_layer_get_clips (layer);
assert_equals_int (g_list_length (objects), 2);
g_list_free_full (objects, gst_object_unref);
GST_DEBUG ("Trimming second source to 500, no transition should be created");
ges_timeline_element_trim (src, 500);
/* 500___________src_________1250
* 500___________src1________1250
*/
GST_DEBUG ("Checking src timing values");
assert_equals_uint64 (_START (src), 500);
assert_equals_uint64 (_DURATION (src), 1250 - 500);
assert_equals_uint64 (_START (src1), 500);
assert_equals_uint64 (_DURATION (src1), 1250 - 500);
GST_DEBUG ("Trimming first source to 750, no transition should be created");
ges_timeline_element_trim (src, 750);
/* 750_______src_______1250
* 500___________src1________1250
*/
GST_DEBUG ("Checking src timing values");
assert_equals_uint64 (_START (src), 750);
assert_equals_uint64 (_DURATION (src), 1250 - 750);
assert_equals_uint64 (_START (src1), 500);
assert_equals_uint64 (_DURATION (src1), 1250 - 500);
objects = ges_layer_get_clips (layer);
assert_equals_int (g_list_length (objects), 2);
g_list_free_full (objects, gst_object_unref);
objects = ges_layer_get_clips (layer);
assert_equals_int (g_list_length (objects), 2);
g_list_free_full (objects, gst_object_unref);
GST_DEBUG ("Moving first source to 500, no transition should be created");
ges_timeline_element_set_start (src, 500);
/* 500________src______1000
* 500___________src1________1250
*/
GST_DEBUG ("Checking src timing values");
assert_equals_uint64 (_START (src), 500);
assert_equals_uint64 (_DURATION (src), 1000 - 500);
assert_equals_uint64 (_START (src1), 500);
assert_equals_uint64 (_DURATION (src1), 1250 - 500);
objects = ges_layer_get_clips (layer);
assert_equals_int (g_list_length (objects), 2);
g_list_free_full (objects, gst_object_unref);
objects = ges_layer_get_clips (layer);
assert_equals_int (g_list_length (objects), 2);
g_list_free_full (objects, gst_object_unref);
GST_DEBUG ("Moving first source to 600, no transition should be created");
ges_timeline_element_set_start (src, 600);
/* 600____src___1100
* 500___________src1________1250
*/
GST_DEBUG ("Checking src timing values");
assert_equals_uint64 (_START (src), 600);
assert_equals_uint64 (_DURATION (src), 1100 - 600);
assert_equals_uint64 (_START (src1), 500);
assert_equals_uint64 (_DURATION (src1), 1250 - 500);
CHECK_OBJECT_PROPS (src, 600, 0, 1000);
CHECK_OBJECT_PROPS (src1, 500, 0, 1000);
objects = ges_layer_get_clips (layer);
assert_equals_int (g_list_length (objects), 2);
g_list_free_full (objects, gst_object_unref);
objects = ges_layer_get_clips (layer);
assert_equals_int (g_list_length (objects), 2);
assert_equals_int (g_list_length (objects), 4);
transition = objects->next->data;
assert_is_type (transition, GES_TYPE_TRANSITION_CLIP);
CHECK_OBJECT_PROPS (transition, 600, 0, 900);
g_list_free_full (objects, gst_object_unref);
GST_DEBUG ("Adding asset to first layer");
GST_DEBUG ("Adding clip from 1250 -- 1000 to first layer");
src2 =
GES_TIMELINE_ELEMENT (ges_layer_add_asset (layer, asset, 1250, 0,
fail_if (ges_layer_add_asset (layer, asset, 1250, 0,
1000, GES_TRACK_TYPE_UNKNOWN));
/*
* 1500___________src2________2000
* 1500_trans_1600
* 600______________src________________1600
* 600_____transition______1500
* 500___________src1_________1500
*/
src2 = GES_TIMELINE_ELEMENT (ges_layer_add_asset (layer, asset, 1500, 0,
500, GES_TRACK_TYPE_UNKNOWN));
assert_is_type (src2, GES_TYPE_TEST_CLIP);
/* 600____src___1100
* 500___________src1________1250
* 1250___________src2________2250
*/
assert_equals_uint64 (_START (src), 600);
assert_equals_uint64 (_DURATION (src), 1100 - 600);
assert_equals_uint64 (_START (src1), 500);
assert_equals_uint64 (_DURATION (src1), 1250 - 500);
assert_equals_uint64 (_START (src2), 1250);
assert_equals_uint64 (_DURATION (src2), 1000);
CHECK_OBJECT_PROPS (src, 600, 0, 1000);
CHECK_OBJECT_PROPS (src1, 500, 0, 1000);
CHECK_OBJECT_PROPS (src2, 1500, 0, 500);
objects = ges_layer_get_clips (layer);
assert_equals_int (g_list_length (objects), 3);
g_list_free_full (objects, gst_object_unref);
GST_DEBUG
("Changig first source duration to 800 2 transitions should be created");
ges_timeline_element_set_duration (src, 800);
ges_timeline_commit (timeline);
/* 600__________________src_____________1400
* 500___________src1________1250
* 1250___________src2________2250
* 600_____trans1_______1250
* 1250___trans2___1400
*/
GST_DEBUG ("Checking src timing values");
assert_equals_uint64 (_START (src), 600);
assert_equals_uint64 (_DURATION (src), 1400 - 600);
assert_equals_uint64 (_START (src1), 500);
assert_equals_uint64 (_DURATION (src1), 1250 - 500);
current = objects = ges_layer_get_clips (layer);
transition = objects->next->next->data;
assert_equals_int (g_list_length (objects), 7);
assert_is_type (objects->data, GES_TYPE_TEST_CLIP);
fail_unless (objects->data == src1);
current = current->next;
transition = current->data;
assert_is_type (transition, GES_TYPE_TRANSITION_CLIP);
assert_equals_uint64 (_START (transition), 600);
assert_equals_uint64 (_DURATION (transition), 1250 - 600);
ASSERT_OBJECT_REFCOUNT (transition, "layer + timeline + ourself", 3);
current = current->next;
transition = current->data;
CHECK_OBJECT_PROPS (transition, 600, 0, 900);
transition = objects->next->next->next->next->data;
assert_is_type (transition, GES_TYPE_TRANSITION_CLIP);
assert_equals_uint64 (_START (transition), 600);
assert_equals_uint64 (_DURATION (transition), 1250 - 600);
ASSERT_OBJECT_REFCOUNT (transition, "layer + timeline + ourself", 3);
CHECK_OBJECT_PROPS (transition, 1500, 0, 100);
current = current->next;
fail_unless (current->data == src);
current = current->next;
transition = current->data;
assert_is_type (transition, GES_TYPE_TRANSITION_CLIP);
assert_equals_uint64 (_START (transition), 1250);
assert_equals_uint64 (_DURATION (transition), 1400 - 1250);
ASSERT_OBJECT_REFCOUNT (transition, "layer + timeline + ourself", 3);
current = current->next;
transition = current->data;
assert_is_type (transition, GES_TYPE_TRANSITION_CLIP);
assert_equals_uint64 (_START (transition), 1250);
assert_equals_uint64 (_DURATION (transition), 1400 - 1250);
ASSERT_OBJECT_REFCOUNT (transition, "layer + timeline + ourself", 3);
current = current->next;
fail_unless (current->data == src2);
g_list_free_full (objects, gst_object_unref);
GST_DEBUG ("Back to previous state");
/* Make sure to keep 1 ref so we can check_destroyed afterward */
gst_object_ref (transition);
ges_timeline_element_set_duration (src, 1100 - 600);
/* 600____src___1100
* 500___________src1________1250
* 1250___________src2________2250
*/
assert_equals_uint64 (_START (src), 600);
assert_equals_uint64 (_DURATION (src), 1100 - 600);
assert_equals_uint64 (_START (src1), 500);
assert_equals_uint64 (_DURATION (src1), 1250 - 500);
assert_equals_uint64 (_START (src2), 1250);
assert_equals_uint64 (_DURATION (src2), 1000);
/* We check that the transition as actually been freed */
check_destroyed (G_OBJECT (transition), NULL, NULL);
objects = ges_layer_get_clips (layer);
assert_equals_int (g_list_length (objects), 3);
g_list_free_full (objects, gst_object_unref);
GST_DEBUG
("Set third clip start to 1100, 1 new transition should be created");
ges_timeline_element_set_start (src2, 1100);
ges_timeline_commit (timeline);
/* 600____src___1100
* 500___________src1________1250
* 1100___________src2________2100
* ^__trans___^
*/
assert_equals_uint64 (_START (src), 600);
assert_equals_uint64 (_DURATION (src), 1100 - 600);
assert_equals_uint64 (_START (src1), 500);
assert_equals_uint64 (_DURATION (src1), 1250 - 500);
assert_equals_uint64 (_START (src2), 1100);
assert_equals_uint64 (_DURATION (src2), 1000);
current = objects = ges_layer_get_clips (layer);
assert_equals_int (g_list_length (objects), 5);
assert_is_type (objects->data, GES_TYPE_TEST_CLIP);
fail_unless (current->data == src1);
current = current->next;
fail_unless (current->data == src);
current = current->next;
transition = current->data;
assert_is_type (transition, GES_TYPE_TRANSITION_CLIP);
assert_equals_uint64 (_START (transition), 1100);
assert_equals_uint64 (_DURATION (transition), 1250 - 1100);
current = current->next;
transition = current->data;
assert_is_type (transition, GES_TYPE_TRANSITION_CLIP);
assert_equals_uint64 (_START (transition), 1100);
assert_equals_uint64 (_DURATION (transition), 1250 - 1100);
current = current->next;
fail_unless (current->data == src2);
g_list_free_full (objects, gst_object_unref);
GST_DEBUG ("Check that we can not create 2 transitions at the same place");
fail_if (ges_container_edit (GES_CONTAINER (src2), NULL, -1,
GES_EDIT_MODE_NORMAL, GES_EDGE_START, 1000));
/*
* 500___________src1________1250
* 1000___________src2________2000
* ^____trans____^
*/
ges_layer_remove_clip (layer, GES_CLIP (src));
fail_unless (ges_container_edit (GES_CONTAINER (src2), NULL, -1,
GES_EDIT_MODE_NORMAL, GES_EDGE_START, 1000));
assert_equals_uint64 (_START (src1), 500);
assert_equals_uint64 (_DURATION (src1), 1250 - 500);
assert_equals_uint64 (_START (src2), 1000);
assert_equals_uint64 (_DURATION (src2), 1000);
current = objects = ges_layer_get_clips (layer);
current = objects;
assert_equals_int (g_list_length (objects), 4);
assert_is_type (objects->data, GES_TYPE_TEST_CLIP);
transition = objects->next->data;
assert_is_type (transition, GES_TYPE_TRANSITION_CLIP);
fail_unless (current->data == src1);
g_list_free_full (objects, gst_object_unref);
/*
* 500___________src1________1250
* ^____trans____^
* 1100___________src2________2000
*/
ges_container_edit (GES_CONTAINER (transition),
NULL, -1, GES_EDIT_MODE_TRIM, GES_EDGE_START, 1100);
assert_equals_uint64 (_START (src1), 500);
assert_equals_uint64 (_DURATION (src1), 1250 - 500);
assert_equals_uint64 (_START (src2), 1100);
assert_equals_uint64 (_DURATION (src2), 2000 - 1100);
current = objects = ges_layer_get_clips (layer);
current = objects;
assert_equals_int (g_list_length (objects), 4);
assert_is_type (objects->data, GES_TYPE_TEST_CLIP);
fail_unless (current->data == src1);
g_list_free_full (objects, gst_object_unref);
gst_object_unref (timeline);
@ -1006,7 +771,7 @@ GST_START_TEST (test_multi_layer_automatic_transition)
GST_DEBUG
("Moving src to second layer, should remove first transition on first layer");
ges_clip_move_to_layer (GES_CLIP (src), layer1);
fail_if (ges_clip_move_to_layer (GES_CLIP (src), layer1));
/* 500___________src1_________1500
* 1000___________src3_________2000 Layer
@ -1027,31 +792,8 @@ GST_START_TEST (test_multi_layer_automatic_transition)
GST_DEBUG ("Checking transitions on first layer");
current = objects = ges_layer_get_clips (layer);
assert_equals_int (g_list_length (objects), 4);
fail_unless (current->data == src1);
assert_equals_int (g_list_length (objects), 7);
current = current->next;
transition = current->data;
assert_is_type (transition, GES_TYPE_TRANSITION_CLIP);
assert_equals_uint64 (_START (transition), 1000);
assert_equals_uint64 (_DURATION (transition), 500);
current = current->next;
transition = current->data;
assert_is_type (transition, GES_TYPE_TRANSITION_CLIP);
assert_equals_uint64 (_START (transition), 1000);
assert_equals_uint64 (_DURATION (transition), 500);
current = current->next;
fail_unless (current->data == src3);
g_list_free_full (objects, gst_object_unref);
ASSERT_OBJECT_REFCOUNT (transition, "layer + timeline", 2);
GST_DEBUG ("Checking second layer");
current = objects = ges_layer_get_clips (layer1);
assert_equals_int (g_list_length (objects), 2);
assert_is_type (current->data, GES_TYPE_TEST_CLIP);
assert_is_type (current->next->data, GES_TYPE_TEST_CLIP);
g_list_free_full (objects, gst_object_unref);
ASSERT_OBJECT_REFCOUNT (transition, "layer + timeline", 2);

View file

@ -83,30 +83,37 @@ G_STMT_START { \
#define _DURATION(obj) GES_TIMELINE_ELEMENT_DURATION (obj)
#define _INPOINT(obj) GES_TIMELINE_ELEMENT_INPOINT (obj)
#define _PRIORITY(obj) GES_TIMELINE_ELEMENT_PRIORITY (obj)
#ifndef _END
#define _END(obj) (_START(obj) + _DURATION(obj))
#endif
#define CHECK_OBJECT_PROPS(obj, start, inpoint, duration) {\
assert_equals_uint64 (_START (obj), start);\
assert_equals_uint64 (_INPOINT (obj), inpoint);\
assert_equals_uint64 (_DURATION (obj), duration);\
fail_unless (_START (obj) == start, "%s start is %" GST_TIME_FORMAT " != %" GST_TIME_FORMAT, GES_TIMELINE_ELEMENT_NAME(obj), GST_TIME_ARGS (_START(obj)), GST_TIME_ARGS (start));\
fail_unless (_INPOINT (obj) == inpoint, "%s inpoint is %" GST_TIME_FORMAT " != %" GST_TIME_FORMAT, GES_TIMELINE_ELEMENT_NAME(obj), GST_TIME_ARGS (_INPOINT(obj)), GST_TIME_ARGS (inpoint));\
fail_unless (_DURATION (obj) == duration, "%s duration is %" GST_TIME_FORMAT " != %" GST_TIME_FORMAT, GES_TIMELINE_ELEMENT_NAME(obj), GST_TIME_ARGS (_DURATION(obj)), GST_TIME_ARGS (duration));\
}
#define check_layer(clip, layer_prio) { \
GESLayer *tmplayer = ges_clip_get_layer ((clip)); \
assert_equals_int (ges_layer_get_priority (tmplayer), (layer_prio)); \
gst_object_unref (tmplayer); \
#define check_layer(clip, layer_prio) { \
fail_unless (GES_TIMELINE_ELEMENT_LAYER_PRIORITY (clip) == (layer_prio), \
"%s in layer %d instead of %d", GES_TIMELINE_ELEMENT_NAME (clip), \
GES_TIMELINE_ELEMENT_LAYER_PRIORITY (clip), layer_prio); \
}
#define GES_TIMELINE_ELEMENT_FORMAT \
"s<%p>" \
" [ %" GST_TIME_FORMAT \
" (%" GST_TIME_FORMAT \
") - %" GST_TIME_FORMAT "]"
") - %" GST_TIME_FORMAT "(%" GST_TIME_FORMAT") layer: %" G_GINT32_FORMAT "] "
#define GES_TIMELINE_ELEMENT_ARGS(element) \
GES_TIMELINE_ELEMENT_NAME(element), element, \
GST_TIME_ARGS(GES_TIMELINE_ELEMENT_START(element)), \
GST_TIME_ARGS(GES_TIMELINE_ELEMENT_INPOINT(element)), \
GST_TIME_ARGS(GES_TIMELINE_ELEMENT_DURATION(element))
GST_TIME_ARGS(GES_TIMELINE_ELEMENT_DURATION(element)), \
GST_TIME_ARGS(GES_TIMELINE_ELEMENT_MAX_DURATION(element)), \
GES_TIMELINE_ELEMENT_LAYER_PRIORITY(element)
#define GES_ARGS GES_TIMELINE_ELEMENT_ARGS
#define GES_FORMAT GES_TIMELINE_ELEMENT_FORMAT
void print_timeline(GESTimeline *timeline);

View file

@ -25,19 +25,21 @@
#define DEEP_CHECK(element, start, inpoint, duration) \
{ \
GList *track_elements, *tmp; \
\
assert_equals_uint64 (_START (element), start); \
assert_equals_uint64 (_INPOINT (element), inpoint); \
assert_equals_uint64 (_DURATION (element), duration); \
CHECK_OBJECT_PROPS (element, start, inpoint, duration) \
\
track_elements = GES_CONTAINER_CHILDREN (element); \
for (tmp = track_elements; tmp; tmp = tmp->next) { \
assert_equals_uint64 (_START (tmp->data), start); \
assert_equals_uint64 (_INPOINT (tmp->data), inpoint); \
assert_equals_uint64 (_DURATION (tmp->data), duration); \
CHECK_OBJECT_PROPS (tmp->data, start, inpoint, duration) \
} \
}
#define CHECK_CLIP(element, start, inpoint, duration, layer_prio) \
{ \
DEEP_CHECK(element, start, inpoint, duration);\
check_layer (element, layer_prio); \
}\
GST_START_TEST (test_basic_timeline_edition)
{
GESAsset *asset;
@ -288,7 +290,7 @@ GST_START_TEST (test_snapping)
fail_unless (ges_track_element_get_track (trackelement) == track);
assert_equals_uint64 (_DURATION (trackelement), 37);
ASSERT_OBJECT_REFCOUNT (trackelement, "track + timeline + clip", 4);
ASSERT_OBJECT_REFCOUNT (trackelement, "track + timeline + clip", 3);
ASSERT_OBJECT_REFCOUNT (clip, "layer + timeline", 2);
fail_unless (ges_layer_add_clip (layer, GES_CLIP (clip1)));
@ -299,7 +301,7 @@ GST_START_TEST (test_snapping)
assert_equals_uint64 (_DURATION (trackelement1), 15);
/* Same ref logic */
ASSERT_OBJECT_REFCOUNT (trackelement1, "First trackelement", 4);
ASSERT_OBJECT_REFCOUNT (trackelement1, "First trackelement", 3);
ASSERT_OBJECT_REFCOUNT (clip1, "First clip", 2);
fail_unless (ges_layer_add_clip (layer, GES_CLIP (clip2)));
@ -310,7 +312,7 @@ GST_START_TEST (test_snapping)
assert_equals_uint64 (_DURATION (trackelement2), 60);
/* Same ref logic */
ASSERT_OBJECT_REFCOUNT (trackelement2, "First trackelement", 4);
ASSERT_OBJECT_REFCOUNT (trackelement2, "First trackelement", 3);
ASSERT_OBJECT_REFCOUNT (clip2, "First clip", 2);
/* Snaping to edge, so no move */
@ -322,8 +324,7 @@ GST_START_TEST (test_snapping)
CHECK_OBJECT_PROPS (trackelement2, 62, 0, 60);
/* Snaping to edge, so no move */
fail_if (ges_container_edit (clip1, NULL, -1, GES_EDIT_MODE_TRIM,
GES_EDGE_END, 27));
ges_container_edit (clip1, NULL, -1, GES_EDIT_MODE_TRIM, GES_EDGE_END, 27);
CHECK_OBJECT_PROPS (trackelement, 25, 0, 37);
CHECK_OBJECT_PROPS (trackelement1, 20, 0, 5);
CHECK_OBJECT_PROPS (trackelement2, 62, 0, 60);
@ -338,144 +339,78 @@ GST_START_TEST (test_snapping)
*/
g_object_set (timeline, "snapping-distance", (guint64) 0, NULL);
ges_timeline_element_set_duration (GES_TIMELINE_ELEMENT (clip1), 10);
CHECK_OBJECT_PROPS (trackelement, 25, 0, 37);
CHECK_OBJECT_PROPS (trackelement1, 20, 0, 10);
CHECK_OBJECT_PROPS (trackelement2, 62, 0, 60);
DEEP_CHECK (clip, 25, 0, 37);
DEEP_CHECK (clip1, 20, 0, 10);
DEEP_CHECK (clip2, 62, 0, 60);
/**
* New timeline(the "layers" are just to help reading diagram, nothing else):
* ------------
* 0----------
* | clip |
* 25---------62
* inpoints 0----------------------- 10--------
* | clip1 || clip2 |
* time 20---------------------- 72 --------122
*/
/* Rolling involves only neighbour that are currently snapping */
fail_unless (ges_timeline_element_roll_end (GES_TIMELINE_ELEMENT (clip1),
62));
fail_unless (ges_timeline_element_roll_end (GES_TIMELINE_ELEMENT (clip1),
/* clip and clip1 would fully overlap ... forbiden */
fail_if (ges_timeline_element_roll_end (GES_TIMELINE_ELEMENT (clip1), 62));
DEEP_CHECK (clip, 25, 0, 37);
DEEP_CHECK (clip1, 20, 0, 10);
DEEP_CHECK (clip2, 62, 0, 60);
fail_if (ges_timeline_element_roll_end (GES_TIMELINE_ELEMENT (clip1),
72) == TRUE);
CHECK_OBJECT_PROPS (trackelement, 25, 0, 37);
CHECK_OBJECT_PROPS (trackelement1, 20, 0, 52);
CHECK_OBJECT_PROPS (trackelement2, 72, 10, 50);
DEEP_CHECK (clip, 25, 0, 37);
DEEP_CHECK (clip1, 20, 0, 10);
DEEP_CHECK (clip2, 62, 0, 60);
/**
* 0----------
* | clip |
* 25---------62
* inpoints 5--------------- 10--------
* | clip1 || clip2 |
* time 25------------- 72 --------122
* 30-------+0-------------+
* inpoints 0-----------5 clip || clip2 |
* | clip1 |------- 62 -----------122
* time 20----------30
*/
g_object_set (timeline, "snapping-distance", (guint64) 4, NULL);
fail_unless (ges_timeline_element_trim (GES_TIMELINE_ELEMENT (clip1),
fail_unless (ges_timeline_element_trim (GES_TIMELINE_ELEMENT (clip),
28) == TRUE);
CHECK_OBJECT_PROPS (trackelement, 25, 0, 37);
CHECK_OBJECT_PROPS (trackelement1, 25, 5, 47);
CHECK_OBJECT_PROPS (trackelement2, 72, 10, 50);
DEEP_CHECK (clip, 30, 5, 32);
DEEP_CHECK (clip1, 20, 0, 10);
DEEP_CHECK (clip2, 62, 0, 60);
/**
* 0----------
* | clip |
* 25---------62
* inpoints 5---------- 0---------
* | clip1 || clip2 |
* time 25-------- 62 --------122
* 30-------+0-------------+
* inpoints 0-----------5 clip || clip2 |
* | clip1 |------- 62 -----------122
* time 20----------30
*/
fail_unless (ges_timeline_element_set_inpoint (GES_TIMELINE_ELEMENT (clip2),
5));
fail_unless (ges_timeline_element_roll_start (GES_TIMELINE_ELEMENT (clip2),
59) == TRUE);
CHECK_OBJECT_PROPS (trackelement, 25, 0, 37);
CHECK_OBJECT_PROPS (trackelement1, 25, 5, 37);
CHECK_OBJECT_PROPS (trackelement2, 62, 0, 60);
60));
DEEP_CHECK (clip, 30, 5, 32);
DEEP_CHECK (clip1, 20, 0, 10);
DEEP_CHECK (clip2, 62, 5, 60);
/**
* 0----------
* | clip |
* 25--------62
* inpoints 5-----------------------+
* | clip1 || clip2 |
* time 30------------]--------122
* 67
* 30-------+0-------------+
* inpoints 0-----------5 clip || clip2 |
* | clip1 |------- 62 -----------122
* time 20----------30
*/
ges_container_edit (clip1, NULL, -1, GES_EDIT_MODE_NORMAL, GES_EDGE_NONE, 30);
CHECK_OBJECT_PROPS (trackelement, 25, 0, 37);
CHECK_OBJECT_PROPS (trackelement1, 30, 5, 37);
CHECK_OBJECT_PROPS (trackelement2, 62, 0, 60);
/* Moving clip1 to 26 would lead to snapping to 30, and clip1 and clip
* would fully overlap */
fail_if (ges_container_edit (clip1, NULL, -1, GES_EDIT_MODE_NORMAL,
GES_EDGE_NONE, 26) == TRUE);
DEEP_CHECK (clip, 30, 5, 32);
DEEP_CHECK (clip1, 20, 0, 10);
DEEP_CHECK (clip2, 62, 5, 60);
/**
* inpoints 0----------5--------------
* | clip || clip1 |
* time 25----------62----------99
* 0-----------
* | clip2 |
* 98--------168
* Check that clip1 snaps with the end of clip */
fail_unless (ges_timeline_element_ripple (GES_TIMELINE_ELEMENT (clip1),
58) == TRUE);
CHECK_OBJECT_PROPS (trackelement, 25, 0, 37);
CHECK_OBJECT_PROPS (trackelement1, 62, 5, 37);
CHECK_OBJECT_PROPS (trackelement2, 94, 0, 60);
/**
* inpoints 0----------- 5------------ 0-----------
* | clip || clip1 | | clip2 |
* time 25----------62----------99 110--------170
*/
ges_container_edit (clip2, NULL, -1, GES_EDIT_MODE_NORMAL, GES_EDGE_NONE,
110);
CHECK_OBJECT_PROPS (trackelement, 25, 0, 37);
CHECK_OBJECT_PROPS (trackelement1, 62, 5, 37);
CHECK_OBJECT_PROPS (trackelement2, 110, 0, 60);
/**
* inpoints 0----------5 5 --------- 0----------
* | clip | | clip1 || clip2 |
* time 25---------62 73---------110--------170
*/
* 30-------+0-------------+
* inpoints 5 clip || clip2 |-------------+
* +------- 62 -----------122 clip1 |
* time +------------132
* Check that clip1 snaps with the end of clip2 */
fail_unless (ges_container_edit (clip1, NULL, -1, GES_EDIT_MODE_NORMAL,
GES_EDGE_NONE, 72) == TRUE);
CHECK_OBJECT_PROPS (trackelement, 25, 0, 37);
CHECK_OBJECT_PROPS (trackelement1, 73, 5, 37);
CHECK_OBJECT_PROPS (trackelement2, 110, 0, 60);
/**
* inpoints 0----------5---------- 0----------
* | clip || clip1 | | clip2 |
* time 25---------62-------- 99 110--------170
*/
fail_unless (ges_container_edit (clip1, NULL, -1, GES_EDIT_MODE_NORMAL,
GES_EDGE_NONE, 58) == TRUE);
CHECK_OBJECT_PROPS (trackelement, 25, 0, 37);
CHECK_OBJECT_PROPS (trackelement1, 62, 5, 37);
CHECK_OBJECT_PROPS (trackelement2, 110, 0, 60);
/**
* inpoints 0----------5---------- 0----------
* | clip || clip1 || clip2 |
* time 25---------62--------110--------170
*/
g_object_set (clip1, "duration", (guint64) 46, NULL);
CHECK_OBJECT_PROPS (trackelement, 25, 0, 37);
CHECK_OBJECT_PROPS (trackelement1, 62, 5, 48);
CHECK_OBJECT_PROPS (trackelement2, 110, 0, 60);
/**
* inpoints 5----------- 0--------- 0----------
* | clip1 || clip2 || clip |
* time 62---------110--------170--------207
*/
ges_container_edit (clip, NULL, -1, GES_EDIT_MODE_NORMAL, GES_EDGE_NONE, 168);
CHECK_OBJECT_PROPS (trackelement, 170, 0, 37);
CHECK_OBJECT_PROPS (trackelement1, 62, 5, 48);
CHECK_OBJECT_PROPS (trackelement2, 110, 0, 60);
GES_EDGE_NONE, 125) == TRUE);
DEEP_CHECK (clip, 30, 5, 32);
DEEP_CHECK (clip1, 122, 0, 10);
DEEP_CHECK (clip2, 62, 5, 60);
/* Check we didn't lose/screwed any references */
ASSERT_OBJECT_REFCOUNT (trackelement, "First trackelement", 4);
ASSERT_OBJECT_REFCOUNT (trackelement1, "Second trackelement", 4);
ASSERT_OBJECT_REFCOUNT (trackelement2, "Third trackelement", 4);
ASSERT_OBJECT_REFCOUNT (trackelement, "First trackelement", 3);
ASSERT_OBJECT_REFCOUNT (trackelement1, "Second trackelement", 3);
ASSERT_OBJECT_REFCOUNT (trackelement2, "Third trackelement", 3);
ASSERT_OBJECT_REFCOUNT (clip, "First clip", 2);
ASSERT_OBJECT_REFCOUNT (clip1, "Second clip", 2);
ASSERT_OBJECT_REFCOUNT (clip2, "Third clip", 2);
@ -782,6 +717,15 @@ GST_START_TEST (test_timeline_edition_mode)
assert_equals_int (ges_layer_get_priority (layer), 2);
gst_object_unref (layer);
/* Roll end clip back to 35 */
/* Can not move to the first layer as clip2 should move to a layer with priority < 0 */
fail_if (ges_container_edit (clip, NULL, 0, GES_EDIT_MODE_RIPPLE,
GES_EDGE_END, 52));
CHECK_OBJECT_PROPS (trackelement, 32, 5, 3);
CHECK_OBJECT_PROPS (trackelement1, 20, 0, 10);
CHECK_OBJECT_PROPS (trackelement2, 35, 0, 60);
assert_equals_int (GES_TIMELINE_ELEMENT_LAYER_PRIORITY (clip), 2);
/* Ripple clip end to 52
* New timeline:
* ------------
@ -795,8 +739,7 @@ GST_START_TEST (test_timeline_edition_mode)
* 32------52
*
*/
/* Can not move to the first layer as clip2 should move to a layer with priority < 0 */
fail_unless (ges_container_edit (clip, NULL, 0, GES_EDIT_MODE_RIPPLE,
fail_unless (ges_container_edit (clip, NULL, -1, GES_EDIT_MODE_RIPPLE,
GES_EDGE_END, 52) == TRUE);
CHECK_OBJECT_PROPS (trackelement, 32, 5, 20);
CHECK_OBJECT_PROPS (trackelement1, 20, 0, 10);
@ -817,9 +760,9 @@ GST_START_TEST (test_timeline_edition_mode)
/* We have 3 references:
* track + timeline + clip
*/
ASSERT_OBJECT_REFCOUNT (trackelement, "First trackelement", 4);
ASSERT_OBJECT_REFCOUNT (trackelement1, "Second trackelement", 4);
ASSERT_OBJECT_REFCOUNT (trackelement2, "Third trackelement", 4);
ASSERT_OBJECT_REFCOUNT (trackelement, "First trackelement", 3);
ASSERT_OBJECT_REFCOUNT (trackelement1, "Second trackelement", 3);
ASSERT_OBJECT_REFCOUNT (trackelement2, "Third trackelement", 3);
ASSERT_OBJECT_REFCOUNT (clip, "First clip", 2);
ASSERT_OBJECT_REFCOUNT (clip1, "Second clip", 2);
ASSERT_OBJECT_REFCOUNT (clip2, "Third clip", 2);
@ -904,16 +847,13 @@ GST_START_TEST (test_timeline_edition_mode)
/* Snaping to edge, so no move */
g_object_set (timeline, "snapping-distance", (guint64) 3, NULL);
fail_if (ges_container_edit (clip1, NULL, -1, GES_EDIT_MODE_TRIM,
GES_EDGE_END, 27));
ges_container_edit (clip1, NULL, -1, GES_EDIT_MODE_TRIM, GES_EDGE_END, 27);
CHECK_OBJECT_PROPS (trackelement, 25, 0, 37);
CHECK_OBJECT_PROPS (trackelement1, 20, 0, 5);
CHECK_OBJECT_PROPS (trackelement2, 62, 0, 60);
/* Snaping to edge, so no move */
fail_if (ges_container_edit (clip1, NULL, -1, GES_EDIT_MODE_TRIM,
GES_EDGE_END, 27));
ges_container_edit (clip1, NULL, -1, GES_EDIT_MODE_TRIM, GES_EDGE_END, 27);
CHECK_OBJECT_PROPS (trackelement, 25, 0, 37);
CHECK_OBJECT_PROPS (trackelement1, 20, 0, 5);
CHECK_OBJECT_PROPS (trackelement2, 62, 0, 60);
@ -939,13 +879,13 @@ GST_START_TEST (test_timeline_edition_mode)
* 0----------
* | clip |
* 25---------62
* -------------------------------------------------
* inpoints 0----------------------- 10--------
* | clip1 || clip2 |
* time 20---------------------- 72 --------122
*/
/* Rolling involves only neighbours that are currently snapping */
fail_unless (ges_container_edit (clip1, NULL, -1, GES_EDIT_MODE_ROLL,
GES_EDGE_END, 62) == TRUE);
ges_container_edit (clip1, NULL, -1, GES_EDIT_MODE_ROLL, GES_EDGE_END, 62);
fail_unless (ges_container_edit (clip1, NULL, -1, GES_EDIT_MODE_ROLL,
GES_EDGE_END, 72) == TRUE);
CHECK_OBJECT_PROPS (trackelement, 25, 0, 37);
@ -968,19 +908,8 @@ GST_START_TEST (test_timeline_edition_mode)
CHECK_OBJECT_PROPS (trackelement1, 25, 5, 47);
CHECK_OBJECT_PROPS (trackelement2, 72, 10, 50);
/**
* 0----------
* | clip |
* 25---------62
* inpoints 5---------- 0---------
* | clip1 || clip2 |
* time 25-------- 62 --------122
*/
fail_unless (ges_container_edit (clip2, NULL, -1, GES_EDIT_MODE_ROLL,
GES_EDGE_START, 59) == TRUE);
CHECK_OBJECT_PROPS (trackelement, 25, 0, 37);
CHECK_OBJECT_PROPS (trackelement1, 25, 5, 37);
CHECK_OBJECT_PROPS (trackelement2, 62, 0, 60);
fail_if (ges_container_edit (clip2, NULL, -1, GES_EDIT_MODE_ROLL,
GES_EDGE_START, 59));
ges_deinit ();
}
@ -1040,131 +969,70 @@ GST_START_TEST (test_groups)
g_list_free (clips);
fail_unless (GES_IS_GROUP (group));
DEEP_CHECK (c, 0, 0, 10);
DEEP_CHECK (c1, 10, 0, 10);
DEEP_CHECK (c2, 20, 0, 10);
CHECK_CLIP (c, 0, 0, 10, 0);
CHECK_CLIP (c1, 10, 0, 10, 1);
CHECK_CLIP (c2, 20, 0, 10, 1);
CHECK_OBJECT_PROPS (group, 0, 0, 30);
c3 = ges_layer_add_asset (layer, asset, 30, 0, 20, GES_TRACK_TYPE_UNKNOWN);
c4 = ges_layer_add_asset (layer1, asset, 40, 0, 20, GES_TRACK_TYPE_UNKNOWN);
c5 = ges_layer_add_asset (layer2, asset, 50, 0, 20, GES_TRACK_TYPE_UNKNOWN);
DEEP_CHECK (c3, 30, 0, 20);
DEEP_CHECK (c4, 40, 0, 20);
DEEP_CHECK (c5, 50, 0, 20);
CHECK_CLIP (c3, 30, 0, 20, 0);
CHECK_CLIP (c4, 40, 0, 20, 1);
CHECK_CLIP (c5, 50, 0, 20, 2);
check_layer (c, 0);
check_layer (c1, 1);
check_layer (c2, 1);
check_layer (c3, 0);
check_layer (c4, 1);
check_layer (c5, 2);
fail_unless (ges_container_edit (GES_CONTAINER (c), NULL, -1,
GES_EDIT_MODE_RIPPLE, GES_EDGE_NONE, 10) == TRUE);
DEEP_CHECK (c, 10, 0, 10);
DEEP_CHECK (c1, 10, 0, 10);
DEEP_CHECK (c2, 30, 0, 10);
DEEP_CHECK (c3, 40, 0, 20);
DEEP_CHECK (c4, 50, 0, 20);
DEEP_CHECK (c5, 60, 0, 20);
check_layer (c, 0);
check_layer (c1, 1);
check_layer (c2, 1);
check_layer (c3, 0);
check_layer (c4, 1);
check_layer (c5, 2);
CHECK_CLIP (c, 10, 0, 10, 0);
CHECK_CLIP (c1, 20, 0, 10, 1);
CHECK_CLIP (c2, 30, 0, 10, 1);
CHECK_CLIP (c3, 40, 0, 20, 0);
CHECK_CLIP (c4, 50, 0, 20, 1);
CHECK_CLIP (c5, 60, 0, 20, 2);
fail_unless (ges_container_edit (GES_CONTAINER (c), NULL, 1,
GES_EDIT_MODE_RIPPLE, GES_EDGE_NONE, 10) == TRUE);
DEEP_CHECK (c, 10, 0, 10);
DEEP_CHECK (c1, 10, 0, 10);
DEEP_CHECK (c2, 30, 0, 10);
DEEP_CHECK (c3, 40, 0, 20);
DEEP_CHECK (c4, 50, 0, 20);
DEEP_CHECK (c5, 60, 0, 20);
check_layer (c, 1);
check_layer (c1, 2);
check_layer (c2, 2);
check_layer (c3, 1);
check_layer (c4, 2);
check_layer (c5, 3);
CHECK_CLIP (c, 10, 0, 10, 1);
CHECK_CLIP (c1, 20, 0, 10, 2);
CHECK_CLIP (c2, 30, 0, 10, 2);
CHECK_CLIP (c3, 40, 0, 20, 1);
CHECK_CLIP (c4, 50, 0, 20, 2);
CHECK_CLIP (c5, 60, 0, 20, 3);
fail_unless (ges_container_edit (GES_CONTAINER (c1), NULL, 2,
fail_if (ges_container_edit (GES_CONTAINER (c1), NULL, 2,
GES_EDIT_MODE_RIPPLE, GES_EDGE_END, 40) == TRUE);
DEEP_CHECK (c, 10, 0, 10);
DEEP_CHECK (c1, 10, 0, 30);
DEEP_CHECK (c2, 50, 0, 10);
DEEP_CHECK (c3, 60, 0, 20);
DEEP_CHECK (c4, 70, 0, 20);
DEEP_CHECK (c5, 80, 0, 20);
check_layer (c, 1);
check_layer (c1, 2);
check_layer (c2, 2);
check_layer (c3, 1);
check_layer (c4, 2);
check_layer (c5, 3);
fail_unless (ges_container_edit (GES_CONTAINER (c1), NULL, 2,
fail_if (ges_container_edit (GES_CONTAINER (c1), NULL, 2,
GES_EDIT_MODE_RIPPLE, GES_EDGE_END, 30) == TRUE);
DEEP_CHECK (c, 10, 0, 10);
DEEP_CHECK (c1, 10, 0, 20);
DEEP_CHECK (c2, 40, 0, 10);
DEEP_CHECK (c3, 50, 0, 20);
DEEP_CHECK (c4, 60, 0, 20);
DEEP_CHECK (c5, 70, 0, 20);
check_layer (c, 1);
check_layer (c1, 2);
check_layer (c2, 2);
check_layer (c3, 1);
check_layer (c4, 2);
check_layer (c5, 3);
CHECK_CLIP (c, 10, 0, 10, 1);
CHECK_CLIP (c1, 20, 0, 10, 2);
CHECK_CLIP (c2, 30, 0, 10, 2);
CHECK_CLIP (c3, 40, 0, 20, 1);
CHECK_CLIP (c4, 50, 0, 20, 2);
CHECK_CLIP (c5, 60, 0, 20, 3);
fail_unless (ges_container_edit (GES_CONTAINER (c), NULL, 0,
GES_EDIT_MODE_RIPPLE, GES_EDGE_NONE, 0) == TRUE);
DEEP_CHECK (c, 0, 0, 10);
DEEP_CHECK (c1, 10, 0, 20);
DEEP_CHECK (c2, 30, 0, 10);
DEEP_CHECK (c3, 40, 0, 20);
DEEP_CHECK (c4, 50, 0, 20);
DEEP_CHECK (c5, 60, 0, 20);
check_layer (c, 0);
check_layer (c1, 1);
check_layer (c2, 1);
check_layer (c3, 0);
check_layer (c4, 1);
check_layer (c5, 2);
fail_if (ges_container_edit (GES_CONTAINER (c2), NULL, -1,
GES_EDIT_MODE_ROLL, GES_EDGE_END, 40) == TRUE);
DEEP_CHECK (c, 0, 0, 10);
DEEP_CHECK (c1, 10, 0, 20);
DEEP_CHECK (c2, 30, 0, 10);
DEEP_CHECK (c3, 40, 0, 20);
DEEP_CHECK (c4, 50, 0, 20);
DEEP_CHECK (c5, 60, 0, 20);
check_layer (c, 0);
check_layer (c1, 1);
check_layer (c2, 1);
check_layer (c3, 0);
check_layer (c4, 1);
check_layer (c5, 2);
CHECK_CLIP (c, 0, 0, 10, 0);
CHECK_CLIP (c1, 10, 0, 10, 1);
CHECK_CLIP (c2, 20, 0, 10, 1);
CHECK_CLIP (c3, 30, 0, 20, 0);
CHECK_CLIP (c4, 40, 0, 20, 1);
CHECK_CLIP (c5, 50, 0, 20, 2);
CHECK_OBJECT_PROPS (group, 0, 0, 30);
fail_unless (ges_container_edit (GES_CONTAINER (c), NULL, 0,
GES_EDIT_MODE_TRIM, GES_EDGE_START, 5) == TRUE);
CHECK_OBJECT_PROPS (c, 5, 5, 5);
DEEP_CHECK (c1, 10, 0, 20);
DEEP_CHECK (c2, 30, 0, 10);
DEEP_CHECK (c3, 40, 0, 20);
DEEP_CHECK (c4, 50, 0, 20);
DEEP_CHECK (c5, 60, 0, 20);
CHECK_OBJECT_PROPS (group, 5, 0, 35);
check_layer (c, 0);
check_layer (c1, 1);
check_layer (c2, 1);
check_layer (c3, 0);
check_layer (c4, 1);
check_layer (c5, 2);
CHECK_CLIP (c, 5, 5, 5, 0);
CHECK_CLIP (c1, 10, 0, 10, 1);
CHECK_CLIP (c2, 20, 0, 10, 1);
CHECK_CLIP (c3, 30, 0, 20, 0);
CHECK_CLIP (c4, 40, 0, 20, 1);
CHECK_CLIP (c5, 50, 0, 20, 2);
CHECK_OBJECT_PROPS (group, 5, 0, 25);
gst_object_unref (timeline);
gst_object_unref (asset);

View file

@ -263,7 +263,7 @@ GST_START_TEST (test_filesource_images)
fail_unless (GES_IS_IMAGE_SOURCE (track_element));
ASSERT_OBJECT_REFCOUNT (track_element, "1 in track, 1 in clip 2 in timeline",
4);
3);
gst_object_unref (asset);
gst_object_unref (timeline);

View file

@ -194,7 +194,16 @@ class GESSimpleTimelineTest(GESTest):
return clip
def assertTimelineTopology(self, topology):
def append_clip(self, layer=0):
layer = self.timeline.get_layers()[layer]
clip = GES.TestClip()
clip.props.start = layer.get_duration()
clip.props.duration = 10
self.assertTrue(layer.add_clip(clip))
return clip
def assertTimelineTopology(self, topology, groups=[]):
res = []
for layer in self.timeline.get_layers():
layer_timings = []
@ -203,6 +212,14 @@ class GESSimpleTimelineTest(GESTest):
(type(clip), clip.props.start, clip.props.duration))
res.append(layer_timings)
if topology != res:
Gst.error(self.timeline_as_str())
self.assertEqual(topology, res)
self.assertEqual(topology, res)
return res
timeline_groups = self.timeline.get_groups()
if groups and timeline_groups:
for i, group in enumerate(groups):
self.assertEqual(set(group), set(timeline_groups[i].get_children(False)))
self.assertEqual(len(timeline_groups), i + 1)
return res

View file

@ -251,6 +251,8 @@ class TestGroup(common.GESSimpleTimelineTest):
self.assertEqual(audio_transition.props.duration, 10)
def test_moving_group_snapping_from_the_middle(self):
self.track_types = [GES.TrackType.AUDIO]
super().setUp()
snapped_positions = []
def snapping_started_cb(timeline, first_element, second_element,
position, snapped_positions):
@ -272,10 +274,88 @@ class TestGroup(common.GESSimpleTimelineTest):
group = GES.Container.group(clips[1:3])
self.assertIsNotNone(group)
self.assertTimelineTopology([
[
(GES.TestClip, 0, 5),
(GES.TestClip, 5, 5),
(GES.TestClip, 10, 5),
(GES.TestClip, 15, 5),
],
], groups=[clips[1:3]])
self.assertEqual(clips[1].props.start, 5)
self.assertEqual(clips[2].props.start, 10)
clips[2].edit([], 0, GES.EditMode.EDIT_NORMAL, GES.Edge.EDGE_NONE, 11)
self.assertEqual(snapped_positions[0], clips[2].start + clips[2].duration)
self.assertEqual(clips[1].props.start, 5)
self.assertEqual(clips[2].props.start, 10)
self.assertEqual(snapped_positions[0], 5)
self.assertTimelineTopology([
[
(GES.TestClip, 0, 5),
(GES.TestClip, 5, 5),
(GES.TestClip, 10, 5),
(GES.TestClip, 15, 5),
],
], groups=[clips[1:3]])
def test_rippling_with_group(self):
self.track_types = [GES.TrackType.AUDIO]
super().setUp()
for _ in range(4):
self.append_clip()
snapped_positions = []
def snapping_started_cb(timeline, first_element, second_element,
position, snapped_positions):
snapped_positions.append(position)
self.timeline.props.snapping_distance = 5
self.timeline.connect("snapping-started", snapping_started_cb,
snapped_positions)
clips = self.layer.get_clips()
self.assertEqual(len(clips), 4)
group_clips = clips[1:3]
GES.Container.group(group_clips)
self.assertTimelineTopology([
[
(GES.TestClip, 0, 10),
(GES.TestClip, 10, 10),
(GES.TestClip, 20, 10),
(GES.TestClip, 30, 10),
],
], groups=[group_clips])
self.assertFalse(clips[2].edit([], 0, GES.EditMode.EDIT_RIPPLE, GES.Edge.EDGE_NONE, 5))
self.assertTimelineTopology([
[
(GES.TestClip, 0, 10),
(GES.TestClip, 10, 10),
(GES.TestClip, 20, 10),
(GES.TestClip, 30, 10),
],
], groups=[group_clips])
# Negative start...
self.assertFalse(clips[2].edit([], 1, GES.EditMode.EDIT_RIPPLE, GES.Edge.EDGE_NONE, 1))
self.assertTimelineTopology([
[
(GES.TestClip, 0, 10),
(GES.TestClip, 10, 10),
(GES.TestClip, 20, 10),
(GES.TestClip, 30, 10),
],
], groups=[group_clips])
self.assertTrue(clips[2].edit([], 1, GES.EditMode.EDIT_RIPPLE, GES.Edge.EDGE_NONE, 20))
self.assertTimelineTopology([
[
(GES.TestClip, 0, 10),
],
[
(GES.TestClip, 10, 10),
(GES.TestClip, 20, 10),
(GES.TestClip, 30, 10),
],
], groups=[group_clips])

View file

@ -35,7 +35,7 @@ Gst.init(None)
GES.init()
class TestTimeline(unittest.TestCase):
class TestTimeline(common.GESSimpleTimelineTest):
def test_signals_not_emitted_when_loading(self):
mainloop = common.create_main_loop()
@ -63,13 +63,31 @@ class TestTimeline(unittest.TestCase):
self.assertTrue(loaded_called)
handle.assert_not_called()
def test_timeline_duration(self):
self.append_clip()
self.append_clip()
clips = self.layer.get_clips()
class TestSplitting(common.GESSimpleTimelineTest):
def setUp(self):
self.track_types = [GES.TrackType.AUDIO]
super(TestSplitting, self).setUp()
self.assertEqual(self.timeline.props.duration, 20)
self.layer.remove_clip(clips[1])
self.assertEqual(self.timeline.props.duration, 10)
self.append_clip()
self.append_clip()
clips = self.layer.get_clips()
self.assertEqual(self.timeline.props.duration, 30)
group = GES.Container.group(clips[1:])
self.assertEqual(self.timeline.props.duration, 30)
group1 = GES.Container.group([])
group1.add(group)
self.assertEqual(self.timeline.props.duration, 30)
def test_spliting_with_auto_transition_on_the_left(self):
self.track_types = [GES.TrackType.AUDIO]
super().setUp()
self.timeline.props.auto_transition = True
clip1 = self.add_clip(0, 0, 100)
clip2 = self.add_clip(50, 0, 100)
@ -117,6 +135,102 @@ class TestEditing(common.GESSimpleTimelineTest):
self.assertEqual(len(self.layer.get_clips()), 1)
self.assertEqual(len(layer2.get_clips()), 1)
def activate_snapping(self):
self.timeline.set_snapping_distance(5)
self.snapped_at = []
def _snapped_cb(timeline, elem1, elem2, position):
self.snapped_at.append(position)
Gst.error('%s' % position)
def _snapped_end_cb(timeline, elem1, elem2, position):
if self.snapped_at: # Ignoring first snap end.
self.snapped_at.append(Gst.CLOCK_TIME_NONE)
Gst.error('%s' % position)
self.timeline.connect("snapping-started", _snapped_cb)
self.timeline.connect("snapping-ended", _snapped_end_cb)
def test_snap_start_snap_end(self):
clip = self.append_clip()
self.append_clip()
self.activate_snapping()
self.assertTimelineTopology([
[ # Unique layer
(GES.TestClip, 0, 10),
(GES.TestClip, 10, 10),
]
])
clip.props.start = 18
self.assertTimelineTopology([
[ # Unique layer
(GES.TestClip, 10, 10),
(GES.TestClip, 20, 10),
]
])
self.assertEqual(self.snapped_at, [20])
clip.props.start = 30
self.assertTimelineTopology([
[ # Unique layer
(GES.TestClip, 10, 10),
(GES.TestClip, 30, 10),
]
])
self.assertEqual(self.snapped_at, [20, Gst.CLOCK_TIME_NONE])
clip.props.start = 18
self.assertTimelineTopology([
[ # Unique layer
(GES.TestClip, 10, 10),
(GES.TestClip, 20, 10),
]
])
self.assertEqual(self.snapped_at, [20, Gst.CLOCK_TIME_NONE,
Gst.CLOCK_TIME_NONE, 20])
clip.props.start = 19
self.assertTimelineTopology([
[ # Unique layer
(GES.TestClip, 10, 10),
(GES.TestClip, 20, 10),
]
])
self.assertEqual(self.snapped_at, [20, Gst.CLOCK_TIME_NONE,
Gst.CLOCK_TIME_NONE, 20])
def test_rippling_snaps(self):
self.timeline.props.auto_transition = True
self.append_clip()
clip = self.append_clip()
self.activate_snapping()
self.assertTimelineTopology([
[ # Unique layer
(GES.TestClip, 0, 10),
(GES.TestClip, 10, 10),
]
])
clip.edit([], 0, GES.EditMode.EDIT_RIPPLE, GES.Edge.EDGE_NONE, 15)
self.assertEqual(self.snapped_at, [10])
self.assertTimelineTopology([
[ # Unique layer
(GES.TestClip, 0, 10),
(GES.TestClip, 10, 10),
]
])
clip.edit([], 0, GES.EditMode.EDIT_RIPPLE, GES.Edge.EDGE_NONE, 20)
self.assertEqual(self.snapped_at, [10, Gst.CLOCK_TIME_NONE])
self.assertTimelineTopology([
[ # Unique layer
(GES.TestClip, 0, 10),
(GES.TestClip, 20, 10),
]
])
def test_transition_moves_when_rippling_to_another_layer(self):
self.timeline.props.auto_transition = True
clip1 = self.add_clip(0, 0, 100)
@ -160,6 +274,451 @@ class TestEditing(common.GESSimpleTimelineTest):
GES.EditMode.EDIT_RIPPLE, GES.Edge.EDGE_NONE, 35 * Gst.SECOND)
self.assertEqual(len(self.layer.get_clips()), 4)
def test_trim_transition(self):
self.track_types = [GES.TrackType.AUDIO]
super().setUp()
self.timeline.props.auto_transition = True
self.add_clip(0, 0, 10)
self.add_clip(5, 0, 10)
self.assertTimelineTopology([
[ # Unique layer
(GES.TestClip, 0, 10),
(GES.TransitionClip, 5, 5),
(GES.TestClip, 5, 10),
]
])
transition = self.layer.get_clips()[1]
self.assertTrue(transition.edit([], -1, GES.EditMode.EDIT_TRIM, GES.Edge.EDGE_START, 7))
self.assertTimelineTopology([
[ # Unique layer
(GES.TestClip, 0, 10),
(GES.TransitionClip, 7, 3),
(GES.TestClip, 7, 8),
]
])
def test_trim_start(self):
clip = self.append_clip()
self.assertTrue(clip.edit([], -1, GES.EditMode.EDIT_NORMAL, GES.Edge.EDGE_NONE, 10))
self.assertTimelineTopology([
[ # Unique layer
(GES.TestClip, 10, 10),
]
])
self.assertFalse(clip.edit([], -1, GES.EditMode.EDIT_TRIM, GES.Edge.EDGE_NONE, 0))
self.assertTimelineTopology([
[ # Unique layer
(GES.TestClip, 10, 10),
]
])
def test_ripple_end(self):
clip = self.append_clip()
clip.set_max_duration(20)
self.append_clip().set_max_duration(10)
self.append_clip().set_max_duration(10)
self.print_timeline()
self.assertTrue(clip.edit([], -1, GES.EditMode.EDIT_RIPPLE, GES.Edge.EDGE_END, 20))
self.assertTimelineTopology([
[ # Unique layer
(GES.TestClip, 0, 20),
(GES.TestClip, 20, 10),
(GES.TestClip, 30, 10),
]
])
self.assertTrue(clip.edit([], -1, GES.EditMode.EDIT_RIPPLE, GES.Edge.EDGE_END, 15))
self.assertTimelineTopology([
[ # Unique layer
(GES.TestClip, 0, 15),
(GES.TestClip, 15, 10),
(GES.TestClip, 25, 10),
]
])
def test_move_group_full_overlap(self):
self.track_types = [GES.TrackType.AUDIO]
super().setUp()
for _ in range(4):
self.append_clip()
clips = self.layer.get_clips()
self.assertTrue(clips[0].ripple(20))
self.assertTimelineTopology([
[
(GES.TestClip, 20, 10),
(GES.TestClip, 30, 10),
(GES.TestClip, 40, 10),
(GES.TestClip, 50, 10),
]
])
group = GES.Container.group(clips[1:])
self.print_timeline()
self.assertFalse(group.edit([], -1, GES.EditMode.EDIT_NORMAL, GES.Edge.EDGE_NONE, 0))
self.print_timeline()
self.assertTimelineTopology([
[
(GES.TestClip, 20, 10),
(GES.TestClip, 30, 10),
(GES.TestClip, 40, 10),
(GES.TestClip, 50, 10),
]
])
self.assertFalse(clips[1].edit([], -1, GES.EditMode.EDIT_NORMAL, GES.Edge.EDGE_NONE, 0))
self.print_timeline()
self.assertTimelineTopology([
[
(GES.TestClip, 20, 10),
(GES.TestClip, 30, 10),
(GES.TestClip, 40, 10),
(GES.TestClip, 50, 10),
]
])
def test_trim_inside_group(self):
self.track_types = [GES.TrackType.AUDIO]
super().setUp()
for _ in range(2):
self.append_clip()
clips = self.layer.get_clips()
group = GES.Container.group(clips)
self.assertTimelineTopology([
[ # Unique layer
(GES.TestClip, 0, 10),
(GES.TestClip, 10, 10),
]
])
self.assertEqual(group.props.start, 0)
self.assertEqual(group.props.duration, 20)
clips[0].trim(5)
self.assertTimelineTopology([
[ # Unique layer
(GES.TestClip, 5, 5),
(GES.TestClip, 10, 10),
]
])
self.assertEqual(group.props.start, 5)
self.assertEqual(group.props.duration, 15)
def test_trim_end_past_max_duration(self):
clip = self.append_clip()
max_duration = clip.props.duration
clip.set_max_duration(max_duration)
self.assertTrue(clip.edit([], -1, GES.EditMode.EDIT_TRIM, GES.Edge.EDGE_START, 5))
self.assertTimelineTopology([
[ # Unique layer
(GES.TestClip, 5, 5),
]
])
self.assertFalse(clip.edit([], -1, GES.EditMode.EDIT_TRIM, GES.Edge.EDGE_END, 15))
self.assertTimelineTopology([
[ # Unique layer
(GES.TestClip, 5, 5),
]
])
class TestInvalidOverlaps(common.GESSimpleTimelineTest):
def test_adding_or_moving(self):
clip1 = self.add_clip(start=10, in_point=0, duration=3)
self.assertIsNotNone(clip1)
def check_add_move_clip(start, duration):
self.timeline.props.auto_transition = True
self.layer.props.auto_transition = True
clip2 = GES.TestClip()
clip2.props.start = start
clip2.props.duration = duration
self.assertFalse(self.layer.add_clip(clip2))
self.assertEqual(len(self.layer.get_clips()), 1)
# Add the clip at a different position.
clip2.props.start = 25
self.assertTrue(self.layer.add_clip(clip2))
self.assertEqual(clip2.props.start, 25)
# Try to move the second clip by editing it.
self.assertFalse(clip2.edit([], -1, GES.EditMode.EDIT_NORMAL, GES.Edge.EDGE_NONE, start))
self.assertEqual(clip2.props.start, 25)
# Try to put it in a group and move the group.
clip3 = GES.TestClip()
clip3.props.start = 20
clip3.props.duration = 1
self.assertTrue(self.layer.add_clip(clip3))
group = GES.Container.group([clip3, clip2])
self.assertTrue(group.props.start, 20)
self.assertFalse(group.edit([], -1, GES.EditMode.EDIT_NORMAL, GES.Edge.EDGE_NONE, start - 5))
self.assertEqual(group.props.start, 20)
self.assertEqual(clip3.props.start, 20)
self.assertEqual(clip2.props.start, 25)
for clip in group.ungroup(False):
self.assertTrue(self.layer.remove_clip(clip))
# clip1 contains...
check_add_move_clip(start=10, duration=1)
check_add_move_clip(start=11, duration=1)
check_add_move_clip(start=12, duration=1)
def test_splitting(self):
clip1 = self.add_clip(start=9, in_point=0, duration=3)
clip2 = self.add_clip(start=10, in_point=0, duration=4)
clip3 = self.add_clip(start=12, in_point=0, duration=3)
self.assertIsNone(clip1.split(13))
self.assertIsNone(clip1.split(8))
self.assertIsNone(clip3.split(12))
self.assertIsNone(clip3.split(15))
def test_changing_duration(self):
clip1 = self.add_clip(start=9, in_point=0, duration=2)
clip2 = self.add_clip(start=10, in_point=0, duration=2)
self.assertFalse(clip1.set_start(10))
self.assertFalse(clip1.edit([], -1, GES.EditMode.EDIT_TRIM, GES.Edge.EDGE_END, clip2.props.start + clip2.props.duration))
self.assertFalse(clip1.ripple_end(clip2.props.start + clip2.props.duration))
self.assertFalse(clip1.roll_end(clip2.props.start + clip2.props.duration))
# clip2's end edge to the left, to decrease its duration.
self.assertFalse(clip2.edit([], -1, GES.EditMode.EDIT_TRIM, GES.Edge.EDGE_END, clip1.props.start + clip1.props.duration))
self.assertFalse(clip2.ripple_end(clip1.props.start + clip1.props.duration))
self.assertFalse(clip2.roll_end(clip1.props.start + clip1.props.duration))
# clip2's start edge to the left, to increase its duration.
self.assertFalse(clip2.edit([], -1, GES.EditMode.EDIT_TRIM, GES.Edge.EDGE_START, clip1.props.start))
self.assertFalse(clip2.trim(clip1.props.start))
# clip1's start edge to the right, to decrease its duration.
self.assertFalse(clip1.edit([], -1, GES.EditMode.EDIT_TRIM, GES.Edge.EDGE_START, clip2.props.start))
self.assertFalse(clip1.trim(clip2.props.start))
def test_rippling_backward(self):
self.track_types = [GES.TrackType.AUDIO]
super().setUp()
self.maxDiff = None
for i in range(4):
self.append_clip()
self.assertTimelineTopology([
[ # Unique layer
(GES.TestClip, 0, 10),
(GES.TestClip, 10, 10),
(GES.TestClip, 20, 10),
(GES.TestClip, 30, 10),
]
])
clip = self.layer.get_clips()[2]
self.assertFalse(clip.edit([], -1, GES.EditMode.EDIT_RIPPLE, GES.Edge.EDGE_NONE, clip.props.start - 20))
self.assertTimelineTopology([
[ # Unique layer
(GES.TestClip, 0, 10),
(GES.TestClip, 10, 10),
(GES.TestClip, 20, 10),
(GES.TestClip, 30, 10),
]
])
self.assertTrue(clip.edit([], -1, GES.EditMode.EDIT_RIPPLE, GES.Edge.EDGE_NONE, clip.props.start + 10))
self.assertTimelineTopology([
[ # Unique layer
(GES.TestClip, 0, 10),
(GES.TestClip, 10, 10),
(GES.TestClip, 30, 10),
(GES.TestClip, 40, 10),
]
])
self.assertFalse(clip.edit([], -1, GES.EditMode.EDIT_RIPPLE, GES.Edge.EDGE_NONE, clip.props.start -20))
self.assertTimelineTopology([
[ # Unique layer
(GES.TestClip, 0, 10),
(GES.TestClip, 10, 10),
(GES.TestClip, 30, 10),
(GES.TestClip, 40, 10),
]
])
def test_rolling(self):
clip1 = self.add_clip(start=9, in_point=0, duration=2)
clip2 = self.add_clip(start=10, in_point=0, duration=2)
clip3 = self.add_clip(start=11, in_point=0, duration=2)
# Rolling clip1's end -1 would lead to clip3 to overlap 100% with clip2.
self.assertTimelineTopology([
[ # Unique layer
(GES.TestClip, 9, 2),
(GES.TestClip, 10, 2),
(GES.TestClip, 11, 2)
]
])
self.assertFalse(clip1.edit([], -1, GES.EditMode.EDIT_ROLL, GES.Edge.EDGE_END, clip1.props.start + clip1.props.duration - 1))
self.assertFalse(clip1.roll_end(13))
self.assertTimelineTopology([
[ # Unique layer
(GES.TestClip, 9, 2),
(GES.TestClip, 10, 2),
(GES.TestClip, 11, 2)
]
])
# Rolling clip3's start +1 would lead to clip1 to overlap 100% with clip2.
self.assertFalse(clip3.edit([], -1, GES.EditMode.EDIT_ROLL, GES.Edge.EDGE_START, 12))
self.assertTimelineTopology([
[ # Unique layer
(GES.TestClip, 9, 2),
(GES.TestClip, 10, 2),
(GES.TestClip, 11, 2)
]
])
def test_layers(self):
self.track_types = [GES.TrackType.AUDIO]
super().setUp()
self.maxDiff = None
self.timeline.append_layer()
for i in range(2):
self.append_clip()
self.append_clip(1)
self.assertTimelineTopology([
[
(GES.TestClip, 0, 10),
(GES.TestClip, 10, 10),
],
[
(GES.TestClip, 0, 10),
(GES.TestClip, 10, 10),
]
])
clip = self.layer.get_clips()[0]
self.assertFalse(clip.edit([], 1, GES.EditMode.EDIT_NORMAL, GES.Edge.EDGE_NONE, 0))
self.assertTimelineTopology([
[
(GES.TestClip, 0, 10),
(GES.TestClip, 10, 10),
],
[
(GES.TestClip, 0, 10),
(GES.TestClip, 10, 10),
]
])
def test_rippling(self):
self.timeline.remove_track(self.timeline.get_tracks()[0])
clip1 = self.add_clip(start=9, in_point=0, duration=2)
clip2 = self.add_clip(start=10, in_point=0, duration=2)
clip3 = self.add_clip(start=11, in_point=0, duration=2)
# Rippling clip2's start -2 would bring clip3 exactly on top of clip1.
self.assertFalse(clip2.edit([], -1, GES.EditMode.EDIT_RIPPLE, GES.Edge.EDGE_NONE, 8))
self.assertFalse(clip2.ripple(8))
# Rippling clip1's end -1 would bring clip3 exactly on top of clip2.
self.assertFalse(clip1.edit([], -1, GES.EditMode.EDIT_RIPPLE, GES.Edge.EDGE_END, 8))
self.assertFalse(clip1.ripple_end(8))
def test_move_group_to_layer(self):
self.track_types = [GES.TrackType.AUDIO]
super().setUp()
self.append_clip()
self.append_clip()
self.append_clip()
clips = self.layer.get_clips()
clips[1].props.start += 2
group = GES.Container.group(clips[1:])
self.assertTrue(clips[1].edit([], 1, GES.EditMode.EDIT_NORMAL, GES.Edge.EDGE_NONE,
group.props.start))
self.assertTimelineTopology([
[
(GES.TestClip, 0, 10),
],
[
(GES.TestClip, 12, 10),
(GES.TestClip, 20, 10),
]
])
clips[0].props.start = 15
self.assertTimelineTopology([
[
(GES.TestClip, 15, 10),
],
[
(GES.TestClip, 12, 10),
(GES.TestClip, 20, 10),
]
])
self.assertFalse(clips[1].edit([], 0, GES.EditMode.EDIT_NORMAL,
GES.Edge.EDGE_NONE, group.props.start))
self.assertTimelineTopology([
[
(GES.TestClip, 15, 10),
],
[
(GES.TestClip, 12, 10),
(GES.TestClip, 20, 10),
]
])
def test_move_group_with_overlaping_clips(self):
self.track_types = [GES.TrackType.AUDIO]
super().setUp()
self.append_clip()
self.append_clip()
self.append_clip()
self.timeline.props.auto_transition = True
clips = self.layer.get_clips()
clips[1].props.start += 5
group = GES.Container.group(clips[1:])
self.assertTimelineTopology([
[
(GES.TestClip, 0, 10),
(GES.TestClip, 15, 10),
(GES.TransitionClip, 20, 5),
(GES.TestClip, 20, 10),
]
])
clips[0].props.start = 30
self.assertTimelineTopology([
[
(GES.TestClip, 15, 10),
(GES.TransitionClip, 20, 5),
(GES.TestClip, 20, 10),
(GES.TestClip, 30, 10),
]
])
# the 3 clips would overlap
self.assertFalse(clips[1].edit([], 0, GES.EditMode.EDIT_NORMAL, GES.Edge.EDGE_NONE, 25))
self.assertTimelineTopology([
[
(GES.TestClip, 15, 10),
(GES.TransitionClip, 20, 5),
(GES.TestClip, 20, 10),
(GES.TestClip, 30, 10),
]
])
class TestSnapping(common.GESSimpleTimelineTest):
@ -180,14 +739,77 @@ class TestSnapping(common.GESSimpleTimelineTest):
clip2.props.start - 1)
self.assertEqual(clip2.props.start, split_position)
def test_trim_snapps_inside_group(self):
self.track_types = [GES.TrackType.AUDIO]
super().setUp()
self.timeline.props.auto_transition = True
self.timeline.set_snapping_distance(5)
snaps = []
def snapping_started_cb(timeline, element1, element2, dist, self):
snaps.append(set([element1, element2]))
self.timeline.connect('snapping-started', snapping_started_cb, self)
clip = self.append_clip()
clip1 = self.append_clip()
self.assertTimelineTopology([
[ # Unique layer
(GES.TestClip, 0, 10),
(GES.TestClip, 10, 10),
]
])
clip1.edit([], self.layer.get_priority(), GES.EditMode.EDIT_TRIM, GES.Edge.EDGE_START, 15)
self.assertTimelineTopology([
[ # Unique layer
(GES.TestClip, 0, 10),
(GES.TestClip, 10, 10),
]
])
self.assertEqual(snaps[0], set([clip.get_children(False)[0], clip1.get_children(False)[0]]))
clip1.edit([], self.layer.get_priority(), GES.EditMode.EDIT_TRIM, GES.Edge.EDGE_START, 16)
self.assertTimelineTopology([
[ # Unique layer
(GES.TestClip, 0, 10),
(GES.TestClip, 16, 4),
]
])
def test_trim_no_snapping_on_same_clip(self):
self.timeline.props.auto_transition = True
self.timeline.set_snapping_distance(1)
not_called = []
def snapping_started_cb(timeline, element1, element2, dist, self):
not_called.append("No snapping should happen")
self.timeline.connect('snapping-started', snapping_started_cb, self)
clip = self.append_clip()
clip.edit([], self.layer.get_priority(), GES.EditMode.EDIT_TRIM, GES.Edge.EDGE_START, 5)
self.assertEqual(not_called, [])
self.assertTimelineTopology([
[ # Unique layer
(GES.TestClip, 5, 5),
]
])
clip.edit([], self.layer.get_priority(), GES.EditMode.EDIT_TRIM, GES.Edge.EDGE_START, 4)
self.assertEqual(not_called, [])
self.assertTimelineTopology([
[ # Unique layer
(GES.TestClip, 4, 6),
]
])
def test_no_snapping_on_split(self):
self.timeline.props.auto_transition = True
self.timeline.set_snapping_distance(1)
not_called = []
def snapping_started_cb(timeline, element1, element2, dist, self):
Gst.error("Here %s %s" % (Gst.TIME_ARGS(element1.props.start + element1.props.duration),
Gst.TIME_ARGS(element2.props.start)))
not_called.append("No snapping should happen")
self.timeline.connect('snapping-started', snapping_started_cb, self)
@ -296,9 +918,9 @@ class TestTransitions(common.GESSimpleTimelineTest):
self.assertLess(clip1.props.start + clip1.props.duration, clip2.props.start + clip2.props.duration)
self.assertEqual(len(clips), 3)
# Even though 3 clips overlap 1 transition will be created
# 3 clips would be overlapping, 1 of them wasn't added!
clips = layers[1].get_clips()
self.assertEqual(len(clips), 4)
self.assertEqual(len(clips), 3)
class TestPriorities(common.GESSimpleTimelineTest):