}
self->positioning = TRUE;
+ ELEMENT_SET_FLAG (self->transition_clip, GES_TIMELINE_ELEMENT_SET_SIMPLE);
_set_start0 (GES_TIMELINE_ELEMENT (self->transition_clip),
_START (self->next_source));
_set_duration0 (GES_TIMELINE_ELEMENT (self->transition_clip), new_duration);
+ ELEMENT_SET_FLAG (self->transition_clip, GES_TIMELINE_ELEMENT_SET_SIMPLE);
self->positioning = FALSE;
}
for (tmp = container->children; tmp; tmp = g_list_next (tmp)) {
GESTimelineElement *child = (GESTimelineElement *) tmp->data;
- if (child != container->initiated_move)
+ if (child != container->initiated_move) {
+ ELEMENT_SET_FLAG (child, GES_TIMELINE_ELEMENT_SET_SIMPLE);
_set_duration0 (GES_TIMELINE_ELEMENT (child), duration);
+ ELEMENT_UNSET_FLAG (child, GES_TIMELINE_ELEMENT_SET_SIMPLE);
+ }
}
container->children_control_mode = GES_CHILDREN_UPDATE;
G_DEFINE_TYPE_WITH_PRIVATE (GESSourceClip, ges_source_clip, GES_TYPE_CLIP);
-static gboolean
-_set_start (GESTimelineElement * element, GstClockTime start)
-{
- 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)) {
- if (!ges_timeline_move_object_simple (element->timeline, element, NULL,
- GES_EDGE_NONE, start))
- return FALSE;
- return -1;
- }
-
- return
- GES_TIMELINE_ELEMENT_CLASS (ges_source_clip_parent_class)->set_start
- (element, start);
-}
-
-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)) {
- if (!timeline_trim_object (element->timeline, element,
- GES_TIMELINE_ELEMENT_LAYER_PRIORITY (element), NULL, GES_EDGE_END,
- element->start + duration))
- return FALSE;
- return -1;
- }
-
- return
- GES_TIMELINE_ELEMENT_CLASS (ges_source_clip_parent_class)->set_duration
- (element, duration);
-}
-
static void
ges_source_clip_get_property (GObject * object, guint property_id,
GValue * value, GParamSpec * pspec)
ges_source_clip_class_init (GESSourceClipClass * klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
- GESTimelineElementClass *element_class = GES_TIMELINE_ELEMENT_CLASS (klass);
object_class->get_property = ges_source_clip_get_property;
object_class->set_property = ges_source_clip_set_property;
object_class->finalize = ges_source_clip_finalize;
-
- element_class->set_start = _set_start;
- element_class->set_duration = _set_duration;
}
static void
gboolean
ges_timeline_element_set_start (GESTimelineElement * self, GstClockTime start)
{
+ gboolean emit_notify = TRUE;
GESTimelineElementClass *klass;
GESTimelineElement *toplevel_container, *parent;
if (self->start == start)
return TRUE;
- klass = GES_TIMELINE_ELEMENT_GET_CLASS (self);
-
GST_DEBUG_OBJECT (self, "current start: %" GST_TIME_FORMAT
" new start: %" GST_TIME_FORMAT,
GST_TIME_ARGS (GES_TIMELINE_ELEMENT_START (self)), GST_TIME_ARGS (start));
toplevel_container = ges_timeline_element_get_toplevel_parent (self);
+
+ if (self->timeline
+ && !ELEMENT_FLAG_IS_SET (self, GES_TIMELINE_ELEMENT_SET_SIMPLE)
+ && !ELEMENT_FLAG_IS_SET (toplevel_container,
+ GES_TIMELINE_ELEMENT_SET_SIMPLE)) {
+ if (!ges_timeline_move_object_simple (self->timeline, self, NULL,
+ GES_EDGE_NONE, start)) {
+ gst_object_unref (toplevel_container);
+ return FALSE;
+ }
+
+ emit_notify = FALSE;
+ }
parent = self->parent;
/* FIXME This should not belong to GESTimelineElement */
}
gst_object_unref (toplevel_container);
+ klass = GES_TIMELINE_ELEMENT_GET_CLASS (self);
if (klass->set_start) {
gint res = klass->set_start (self, start);
- if (res == TRUE) {
+ if (res == TRUE && emit_notify) {
self->start = start;
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_START]);
}
GstClockTime duration)
{
GESTimelineElementClass *klass;
+ gboolean emit_notify = TRUE;
+ GESTimelineElement *toplevel;
g_return_val_if_fail (GES_IS_TIMELINE_ELEMENT (self), FALSE);
- klass = GES_TIMELINE_ELEMENT_GET_CLASS (self);
+ toplevel = ges_timeline_element_get_toplevel_parent (self);
+ if (self->timeline &&
+ !ELEMENT_FLAG_IS_SET (self, GES_TIMELINE_ELEMENT_SET_SIMPLE) &&
+ !ELEMENT_FLAG_IS_SET (toplevel, GES_TIMELINE_ELEMENT_SET_SIMPLE)) {
+ gboolean res;
+
+ res = timeline_trim_object (self->timeline, self,
+ GES_TIMELINE_ELEMENT_LAYER_PRIORITY (self), NULL,
+ GES_EDGE_END, self->start + duration);
+
+ if (!res) {
+ gst_object_unref (toplevel);
+
+ return FALSE;
+ }
+
+ emit_notify = res == -1;
+ }
+ gst_object_unref (toplevel);
GST_DEBUG_OBJECT (self, "current duration: %" GST_TIME_FORMAT
" new duration: %" GST_TIME_FORMAT,
GST_TIME_ARGS (GES_TIMELINE_ELEMENT_DURATION (self)),
GST_TIME_ARGS (duration));
+ klass = GES_TIMELINE_ELEMENT_GET_CLASS (self);
if (klass->set_duration) {
gint res = klass->set_duration (self, duration);
- if (res == TRUE) {
+ if (res == TRUE && emit_notify) {
self->duration = duration;
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DURATION]);
}
GHashTable *moved_clips;
GList *neighbours;
+
+ /* Data related to trimming groups */
+ GstClockTime trim_group_start;
+ GstClockTime trim_group_end;
} tree_iteration_data_init = {
.root = NULL,
.res = TRUE,
.edge = GES_EDGE_NONE,
.moved_clips = NULL,
.neighbours = NULL,
+ .trim_group_start = GST_CLOCK_TIME_NONE,
+ .trim_group_end = GST_CLOCK_TIME_NONE,
};
/* *INDENT-ON* */
goto done;
}
+static gboolean
+trim_group_get_vals (TreeIterationData * data, GESTimelineElement * e,
+ GstClockTimeDiff * n_start, GstClockTimeDiff * n_inpoint,
+ GstClockTimeDiff * n_duration)
+{
+ GstClockTimeDiff offset;
+ GstClockTimeDiff group_nstart =
+ GST_CLOCK_DIFF (data->start_diff, data->trim_group_start);
+ GstClockTimeDiff group_nend =
+ GST_CLOCK_DIFF (data->duration_diff, data->trim_group_end);
+
+ if (data->edge == GES_EDGE_START &&
+ ((group_nstart >= e->start) || (e->start == data->trim_group_start))) {
+
+ offset = GST_CLOCK_DIFF (group_nstart, e->start);
+ *n_start = group_nstart;
+ *n_inpoint = GST_CLOCK_DIFF (offset, e->inpoint);
+ *n_duration =
+ GST_CLOCK_DIFF (*n_start, (GstClockTimeDiff) e->start + e->duration);
+
+ GST_DEBUG_OBJECT (data->element, "Trimming %" GES_FORMAT " start",
+ GES_ARGS (e));
+ return TRUE;
+ } else if (data->edge == GES_EDGE_END &&
+ ((group_nend <= _END (e)) || (_END (e) == data->trim_group_end))) {
+
+ offset = GST_CLOCK_DIFF (group_nend, _END (e));
+ *n_start = e->start;
+ *n_inpoint = e->inpoint;
+ *n_duration = GST_CLOCK_DIFF (offset, e->duration);
+
+ GST_DEBUG_OBJECT (data->element, "Trimming %" GES_FORMAT " end",
+ GES_ARGS (e));
+
+ return TRUE;
+ }
+
+ /* Ignoring child */
+ return FALSE;
+}
+
static gboolean
check_trim_child (GNode * node, TreeIterationData * data)
{
GST_CLOCK_DIFF (data->duration_diff, e->duration) :
GST_CLOCK_DIFF (n_start, (GstClockTimeDiff) e->start + e->duration);
+ if (GST_CLOCK_TIME_IS_VALID (data->trim_group_start)
+ && !trim_group_get_vals (data, e, &n_start, &n_inpoint, &n_duration)) {
+ GST_DEBUG_OBJECT (data->element, "Not trimming");
+ return FALSE;
+ }
+
if (!timeline_tree_can_move_element_internal (data->root, e,
(gint64) ges_timeline_element_get_layer_priority (e) -
data->priority_diff, n_start, n_inpoint, n_duration, NULL,
static void
trim_simple (GESTimelineElement * element, GstClockTimeDiff offset,
- GESEdge edge)
+ GESEdge edge, TreeIterationData * data)
{
+ GESTimelineElement *toplevel =
+ ges_timeline_element_get_toplevel_parent (element);
+
+ GstClockTimeDiff n_start = GST_CLOCK_DIFF (offset, element->start);
+ GstClockTimeDiff n_inpoint = GST_CLOCK_DIFF (offset, element->inpoint);
+ GstClockTimeDiff n_duration = edge == GES_EDGE_END
+ ? GST_CLOCK_DIFF (offset, element->duration)
+ : element->duration + offset;
+
+ if (data && GST_CLOCK_TIME_IS_VALID (data->trim_group_start))
+ g_assert (trim_group_get_vals (data, element, &n_start, &n_inpoint,
+ &n_duration));
+
ELEMENT_SET_FLAG (element, GES_TIMELINE_ELEMENT_SET_SIMPLE);
- if (edge == GES_EDGE_END) {
- ges_timeline_element_set_duration (element, GST_CLOCK_DIFF (offset,
- element->duration));
- } else {
- ges_timeline_element_set_start (element, GST_CLOCK_DIFF (offset,
- element->start));
- ges_timeline_element_set_inpoint (element, GST_CLOCK_DIFF (offset,
- element->inpoint));
- ges_timeline_element_set_duration (element, element->duration + offset);
+ ELEMENT_SET_FLAG (toplevel, GES_TIMELINE_ELEMENT_SET_SIMPLE);
+ if (edge != GES_EDGE_END) {
+ ges_timeline_element_set_start (element, n_start);
+ ges_timeline_element_set_inpoint (element, n_inpoint);
}
+ ges_timeline_element_set_duration (element, n_duration);
+
GST_LOG ("Trimmed %" GES_FORMAT, GES_ARGS (element));
ELEMENT_UNSET_FLAG (element, GES_TIMELINE_ELEMENT_SET_SIMPLE);
+ ELEMENT_UNSET_FLAG (toplevel, GES_TIMELINE_ELEMENT_SET_SIMPLE);
+ gst_object_unref (toplevel);
}
#define SET_TRIMMING_DATA(data, _edge, offset) G_STMT_START { \
data.start_diff = (_edge) == GES_EDGE_END ? 0 : (offset); \
data.inpoint_diff = (_edge) == GES_EDGE_END ? 0 : (offset); \
data.duration_diff = (_edge) == GES_EDGE_END ? (offset) : -(offset); \
+ if (GES_IS_GROUP (data.element)) {\
+ data.trim_group_start = data.element->start;\
+ data.trim_group_end = _END (data.element); \
+ } \
} G_STMT_END
};
TreeIterationData data = tree_iteration_data_init;
+ /* Make sure to check all children of clips */
+ if (GES_IS_TRACK_ELEMENT (element) && element->parent)
+ element = element->parent;
+
data.root = root;
data.element = element;
data.priority_diff =
new_layer_priority;
data.snapping = snapping_distance ? &snapping : NULL;
data.moved_clips = g_hash_table_new (g_direct_hash, g_direct_equal);
-
SET_TRIMMING_DATA (data, edge, offset);
GST_INFO ("%" GES_FORMAT " trimming %s with offset %" G_GINT64_FORMAT "",
GES_ARGS (element), edge == GES_EDGE_END ? "end" : "start", offset);
- g_node_traverse (find_node (root, element), G_IN_ORDER,
- G_TRAVERSE_LEAVES, -1, (GNodeTraverseFunc) add_element_to_list,
- &data.movings);
+ g_node_traverse (find_node (root, get_toplevel_container (element)),
+ G_IN_ORDER, G_TRAVERSE_LEAVES, -1,
+ (GNodeTraverseFunc) add_element_to_list, &data.movings);
if (!timeline_tree_can_trim_element_internal (root, &data)) {
GST_INFO ("Can not trim object.");
g_hash_table_iter_init (&iter, data.moved_clips);
while (g_hash_table_iter_next (&iter, (gpointer *) & elem, NULL))
- trim_simple (elem, offset, edge);
+ trim_simple (elem, offset, edge, &data);
timeline_tree_create_transitions (root, ges_timeline_find_auto_transition);
timeline_update_transition (root->data);
}
}
- trim_simple (element, offset, edge);
+ trim_simple (element, offset, edge, NULL);
for (tmp = data.neighbours; tmp; tmp = tmp->next)
- trim_simple (tmp->data, offset, data.edge);
+ trim_simple (tmp->data, offset, data.edge, NULL);
done:
timeline_update_duration (root->data);
GESLayer *layer = ges_timeline_get_layer (timeline,
GES_TIMELINE_ELEMENT_LAYER_PRIORITY (element));
- if (!ges_layer_get_auto_transition (layer))
- goto fail;
+ if (!ges_layer_get_auto_transition (layer)) {
+ gst_object_unref (layer);
+ return -1;
+ }
gst_object_unref (layer);
for (tmp = timeline->priv->auto_transitions; tmp; tmp = tmp->next) {
}
return FALSE;
-
-fail:
- gst_object_unref (layer);
- return FALSE;
}
* |----------------------------------|
* | 7--------- 2----------|
* layer1: | | clip1 | | clip2 |
- * | 22--------30 62----------|
+ * | 20--------30 60----------|
* |----------------------------------|
*/
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 (clip1, 20, 5, 10);
+ CHECK_OBJECT_PROPS (clip2, 60, 0, 50);
CHECK_OBJECT_PROPS (group, 12, 0, 98);
ASSERT_OBJECT_REFCOUNT (group, "2 ref for the timeline", 2);
/* Setting the duration would lead to overlaps */
- ges_timeline_element_set_duration (GES_TIMELINE_ELEMENT (group), 10);
+ fail_if (ges_timeline_element_set_duration (GES_TIMELINE_ELEMENT (group),
+ 10));
CHECK_OBJECT_PROPS (clip, 12, 2, 3);
- CHECK_OBJECT_PROPS (clip1, 22, 7, 8);
- CHECK_OBJECT_PROPS (clip2, 62, 2, 48);
+ CHECK_OBJECT_PROPS (clip1, 20, 5, 10);
+ CHECK_OBJECT_PROPS (clip2, 60, 0, 50);
CHECK_OBJECT_PROPS (group, 12, 0, 98);
ges_timeline_element_set_duration (GES_TIMELINE_ELEMENT (group), 100);
CHECK_OBJECT_PROPS (clip, 12, 2, 3);
- CHECK_OBJECT_PROPS (clip1, 22, 7, 8);
- CHECK_OBJECT_PROPS (clip2, 62, 2, 50);
+ CHECK_OBJECT_PROPS (clip1, 20, 5, 10);
+ CHECK_OBJECT_PROPS (clip2, 60, 0, 52);
CHECK_OBJECT_PROPS (group, 12, 0, 100);
ges_timeline_element_set_start (GES_TIMELINE_ELEMENT (group), 20);
CHECK_OBJECT_PROPS (clip, 20, 2, 3);
- CHECK_OBJECT_PROPS (clip1, 30, 7, 8);
- CHECK_OBJECT_PROPS (clip2, 70, 2, 50);
+ CHECK_OBJECT_PROPS (clip1, 28, 5, 10);
+ CHECK_OBJECT_PROPS (clip2, 68, 0, 52);
CHECK_OBJECT_PROPS (group, 20, 0, 100);
+ /* Trim fails because clip inpoint would become negative */
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 (clip1, 28, 5, 10);
+ CHECK_OBJECT_PROPS (clip2, 68, 0, 52);
CHECK_OBJECT_PROPS (group, 20, 0, 100);
+ fail_unless (ges_timeline_element_trim (GES_TIMELINE_ELEMENT (group), 18));
+ CHECK_OBJECT_PROPS (clip, 18, 0, 5);
+ CHECK_OBJECT_PROPS (clip1, 28, 5, 10);
+ CHECK_OBJECT_PROPS (clip2, 68, 0, 52);
+ CHECK_OBJECT_PROPS (group, 18, 0, 102);
+
+ fail_unless (ges_timeline_element_set_duration (GES_TIMELINE_ELEMENT (clip),
+ 17));
+ CHECK_OBJECT_PROPS (clip, 18, 0, 17);
+ CHECK_OBJECT_PROPS (clip1, 28, 5, 10);
+ CHECK_OBJECT_PROPS (clip2, 68, 0, 52);
+ CHECK_OBJECT_PROPS (group, 18, 0, 102);
+
+ fail_unless (ges_timeline_element_trim (GES_TIMELINE_ELEMENT (group), 30));
+ CHECK_OBJECT_PROPS (clip, 30, 12, 5);
+ CHECK_OBJECT_PROPS (clip1, 30, 7, 8);
+ CHECK_OBJECT_PROPS (clip2, 68, 0, 52);
+ CHECK_OBJECT_PROPS (group, 30, 0, 90);
+
+ fail_unless (ges_timeline_element_trim (GES_TIMELINE_ELEMENT (group), 25));
+ CHECK_OBJECT_PROPS (clip, 25, 7, 10);
+ CHECK_OBJECT_PROPS (clip1, 25, 2, 13);
+ CHECK_OBJECT_PROPS (clip2, 68, 0, 52);
+ CHECK_OBJECT_PROPS (group, 25, 0, 95);
+
ASSERT_OBJECT_REFCOUNT (group, "2 ref for the timeline", 2);
check_destroyed (G_OBJECT (timeline), G_OBJECT (group), NULL);
gst_object_unref (asset);
len(self.track_types))
self.layer = self.timeline.append_layer()
- def add_clip(self, start, in_point, duration):
- clip = GES.TestClip()
+ def add_clip(self, start, in_point, duration, asset_type=GES.TestClip):
+ clip = GES.Asset.request(asset_type, None).extract()
clip.props.start = start
clip.props.in_point = in_point
clip.props.duration = duration
return clip
- def append_clip(self, layer=0):
+ def append_clip(self, layer=0, asset_type=GES.TestClip):
while len(self.timeline.get_layers()) < layer + 1:
self.timeline.append_layer()
layer = self.timeline.get_layers()[layer]
- clip = GES.TestClip()
+ clip = GES.Asset.request(asset_type, None).extract()
clip.props.start = layer.get_duration()
clip.props.duration = 10
self.assertTrue(layer.add_clip(clip))
for clip in layer.get_clips():
layer_timings.append(
(type(clip), clip.props.start, clip.props.duration))
+ for child in clip.get_children(True):
+ self.assertEqual(child.props.start, clip.props.start)
+ self.assertEqual(child.props.duration, clip.props.duration)
res.append(layer_timings)
if topology != res:
]
])
+ def test_illegal_effect_move(self):
+ c0 = self.append_clip()
+ self.append_clip()
+ self.assertTimelineTopology([
+ [
+ (GES.TestClip, 0, 10),
+ (GES.TestClip, 10, 10),
+ ]
+ ])
+
+ effect = GES.Effect.new("agingtv")
+ c0.add(effect)
+ self.assertTimelineTopology([
+ [
+ (GES.TestClip, 0, 10),
+ (GES.TestClip, 10, 10),
+ ]
+ ])
+
+ self.assertFalse(effect.set_start(10))
+ self.assertEqual(effect.props.start, 0)
+ self.assertTimelineTopology([
+ [
+ (GES.TestClip, 0, 10),
+ (GES.TestClip, 10, 10),
+ ]
+ ])
+
+
+ self.assertFalse(effect.set_duration(20))
+ self.assertEqual(effect.props.duration, 10)
+ self.assertTimelineTopology([
+ [
+ (GES.TestClip, 0, 10),
+ (GES.TestClip, 10, 10),
+ ]
+ ])
+
+ def test_moving_overlay_clip_in_group(self):
+ c0 = self.append_clip()
+ overlay = self.append_clip(asset_type=GES.TextOverlayClip)
+ group = GES.Group.new()
+ group.add(c0)
+ group.add(overlay)
+
+ self.assertTimelineTopology([
+ [
+ (GES.TestClip, 0, 10),
+ (GES.TextOverlayClip, 10, 10),
+ ]
+ ], groups=[(c0, overlay)])
+
+ self.assertTrue(overlay.set_start(20))
+ self.assertTimelineTopology([
+ [
+ (GES.TestClip, 10, 10),
+ (GES.TextOverlayClip, 20, 10),
+ ]
+ ], groups=[(c0, overlay)])
+
+ def test_moving_group_in_group(self):
+ c0 = self.append_clip()
+ overlay = self.append_clip(asset_type=GES.TextOverlayClip)
+ group0 = GES.Group.new()
+ group0.add(c0)
+ group0.add(overlay)
+
+ c1 = self.append_clip()
+ group1 = GES.Group.new()
+ group1.add(group0)
+ group1.add(c1)
+
+ self.assertTimelineTopology([
+ [
+ (GES.TestClip, 0, 10),
+ (GES.TextOverlayClip, 10, 10),
+ (GES.TestClip, 20, 10),
+ ]
+ ], groups=[(c1, group0), (c0, overlay)])
+
+ self.assertTrue(group0.set_start(10))
+ self.assertTimelineTopology([
+ [
+ (GES.TestClip, 10, 10),
+ (GES.TextOverlayClip, 20, 10),
+ (GES.TestClip, 30, 10),
+ ]
+ ], groups=[(c1, group0), (c0, overlay)])
+ self.check_element_values(group0, 10, 0, 20)
+ self.check_element_values(group1, 10, 0, 30)
+
+ def test_illegal_group_child_move(self):
+ clip0 = self.append_clip()
+ _clip1 = self.add_clip(20, 0, 10)
+ overlay = self.add_clip(20, 0, 10, asset_type=GES.TextOverlayClip)
+
+ group = GES.Group.new()
+ group.add(clip0)
+ group.add(overlay)
+
+ self.assertTimelineTopology([
+ [
+ (GES.TestClip, 0, 10),
+ (GES.TextOverlayClip, 20, 10),
+ (GES.TestClip, 20, 10),
+ ]
+ ], groups=[(clip0, overlay),])
+
+ # Can't move as clip0 and clip1 would fully overlap
+ self.assertFalse(overlay.set_start(40))
+ self.assertTimelineTopology([
+ [
+ (GES.TestClip, 0, 10),
+ (GES.TextOverlayClip, 20, 10),
+ (GES.TestClip, 20, 10),
+ ]
+ ], groups=[(clip0, overlay)])
+
+ def test_child_duration_change(self):
+ c0 = self.append_clip()
+
+ self.assertTimelineTopology([
+ [
+ (GES.TestClip, 0, 10),
+ ]
+ ])
+ self.assertTrue(c0.set_duration(40))
+ self.assertTimelineTopology([
+ [
+ (GES.TestClip, 0, 40),
+ ]
+ ])
+
+ c0.children[0].set_duration(10)
+ self.assertTimelineTopology([
+ [
+ (GES.TestClip, 0, 10),
+ ]
+ ])
+
+ self.assertTrue(c0.set_start(40))
+ self.assertTimelineTopology([
+ [
+ (GES.TestClip, 40, 10),
+ ]
+ ])
+
+ c0.children[0].set_start(10)
+ self.assertTimelineTopology([
+ [
+ (GES.TestClip, 10, 10),
+ ]
+ ])
+
class TestInvalidOverlaps(common.GESSimpleTimelineTest):