return set_layer_priority (element, data);
}
+static gboolean
+set_edit_trim_start_inpoint_value (GESTimelineElement * element,
+ EditData * data)
+{
+ GstClockTime new_inpoint = _clock_time_minus_diff (element->inpoint,
+ data->offset, NULL);
+ if (!GST_CLOCK_TIME_IS_VALID (new_inpoint)) {
+ GST_INFO_OBJECT (element, "Cannot trim start of %" GES_FORMAT
+ " with offset %" G_GINT64_FORMAT " because it would result in an "
+ "invalid in-point", GES_ARGS (element), data->offset);
+ return FALSE;
+ }
+ data->inpoint = new_inpoint;
+ return TRUE;
+}
+
+static gboolean
+set_edit_trim_start_non_core_children (GESTimelineElement * clip,
+ GstClockTimeDiff offset, GHashTable * edit_table)
+{
+ GList *tmp;
+ GESTimelineElement *child;
+ GESTrackElement *el;
+ EditData *data;
+
+ /* need to set in-point of active non-core children to keep their
+ * internal content at the same timeline position. This also ensures
+ * the duration-limit will not be broken */
+ for (tmp = GES_CONTAINER_CHILDREN (clip); tmp; tmp = tmp->next) {
+ child = tmp->data;
+ el = tmp->data;
+ if (ges_track_element_has_internal_source (el)
+ && ges_track_element_is_active (el)
+ && !GES_TRACK_ELEMENT_IS_CORE (child)) {
+
+ GST_INFO_OBJECT (child, "Setting track element %s to trim in-point "
+ "with offset %" G_GINT64_FORMAT " since the parent clip %"
+ GES_FORMAT " is being trimmed at its start", child->name, offset,
+ GES_ARGS (clip));
+
+ if (g_hash_table_contains (edit_table, child)) {
+ GST_ERROR_OBJECT (child, "Already set to be edited");
+ return FALSE;
+ }
+
+ data = new_edit_data (EDIT_TRIM_START, offset, 0);
+ g_hash_table_insert (edit_table, child, data);
+ if (!set_edit_trim_start_inpoint_value (child, data))
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
/* trim the start of a clip or a track element */
static gboolean
-set_edit_trim_start_values (GESTimelineElement * element, EditData * data)
+set_edit_trim_start_values (GESTimelineElement * element, EditData * data,
+ GHashTable * edit_table)
{
GstClockTime new_start =
_clock_time_minus_diff (element->start, data->offset, NULL);
}
_CHECK_END (element, new_start, new_duration);
- if (!GES_IS_TRACK_ELEMENT (element)
- || ges_track_element_has_internal_source (GES_TRACK_ELEMENT (element))) {
- GstClockTime new_inpoint =
- _clock_time_minus_diff (element->inpoint, data->offset, NULL);
- if (!GST_CLOCK_TIME_IS_VALID (new_inpoint)) {
- GST_INFO_OBJECT (element, "Cannot trim start of %" GES_FORMAT
- " with offset %" G_GINT64_FORMAT " because it would result in an "
- "invalid in-point", GES_ARGS (element), data->offset);
+ if (GES_IS_CLIP (element)) {
+ if (!set_edit_trim_start_inpoint_value (element, data))
+ return FALSE;
+ if (!set_edit_trim_start_non_core_children (element, data->offset,
+ edit_table))
+ return FALSE;
+ } else if (GES_IS_TRACK_ELEMENT (element)
+ && ges_track_element_has_internal_source (GES_TRACK_ELEMENT (element))) {
+ if (!set_edit_trim_start_inpoint_value (element, data))
return FALSE;
- }
-
- data->inpoint = new_inpoint;
}
data->start = new_start;
data->duration = new_duration;
/* handles clips and track elements with no parents */
static gboolean
-set_clip_edit_values (GESTimelineElement * element, EditData * data)
+set_clip_edit_values (GESTimelineElement * element, EditData * data,
+ GHashTable * edit_table)
{
switch (data->mode) {
case EDIT_MOVE:
return set_edit_move_values (element, data);
case EDIT_TRIM_START:
- return set_edit_trim_start_values (element, data);
+ return set_edit_trim_start_values (element, data, edit_table);
case EDIT_TRIM_END:
return set_edit_trim_end_values (element, data);
}
}
clip_data = new_edit_data (clip_mode, offset, layer_offset);
g_hash_table_insert (edit_table, clip, clip_data);
- if (!set_clip_edit_values (clip, clip_data))
+ if (!set_clip_edit_values (clip, clip_data, edit_table))
goto error;
}
}
if (GES_IS_GROUP (element))
res = replace_group_with_clip_edits (root, element, edits);
else
- res = set_clip_edit_values (element, edit_data);
+ res = set_clip_edit_values (element, edit_data, edits);
if (!res)
goto error;
}
]
])
+ def test_trim_non_core(self):
+ clip = self.append_clip()
+ self.assertTrue(clip.set_inpoint(12))
+ self.assertTrue(clip.set_max_duration(30))
+ self.assertEqual(clip.get_duration_limit(), 18)
+ for child in clip.get_children(False):
+ self.assertEqual(child.get_inpoint(), 12)
+ self.assertEqual(child.get_max_duration(), 30)
+
+ effect0 = GES.Effect.new("textoverlay")
+ effect0.set_has_internal_source(True)
+ self.assertTrue(effect0.set_inpoint(5))
+ self.assertTrue(effect0.set_max_duration(20))
+ self.assertTrue(clip.add(effect0))
+ self.assertEqual(clip.get_duration_limit(), 15)
+
+ effect1 = GES.Effect.new("agingtv")
+ effect1.set_has_internal_source(False)
+ self.assertTrue(clip.add(effect1))
+
+ effect2 = GES.Effect.new("textoverlay")
+ effect2.set_has_internal_source(True)
+ self.assertTrue(effect2.set_inpoint(8))
+ self.assertTrue(effect2.set_max_duration(18))
+ self.assertTrue(clip.add(effect2))
+ self.assertEqual(clip.get_duration_limit(), 10)
+
+ effect3 = GES.Effect.new("textoverlay")
+ effect3.set_has_internal_source(True)
+ self.assertTrue(effect3.set_inpoint(20))
+ self.assertTrue(effect3.set_max_duration(22))
+ self.assertTrue(effect3.set_active(False))
+ self.assertTrue(clip.add(effect3))
+ self.assertEqual(clip.get_duration_limit(), 10)
+
+ self.assertTrue(clip.set_start(10))
+ self.assertTrue(clip.set_duration(10))
+
+ # cannot trim to a 0 because effect0 would have a negative in-point
+ self.assertFalse(
+ clip.edit([], -1, GES.EditMode.EDIT_TRIM, GES.Edge.EDGE_START, 0))
+
+ self.assertEqual(clip.start, 10)
+ self.assertEqual(clip.inpoint, 12)
+ self.assertEqual(effect0.inpoint, 5)
+ self.assertEqual(effect1.inpoint, 0)
+ self.assertEqual(effect2.inpoint, 8)
+ self.assertEqual(effect3.inpoint, 20)
+
+ self.assertTrue(
+ clip.edit([], -1, GES.EditMode.EDIT_TRIM, GES.Edge.EDGE_START, 5))
+
+ self.assertEqual(clip.start, 5)
+ self.assertEqual(clip.duration, 15)
+ self.assertEqual(clip.get_duration_limit(), 15)
+
+ for child in clip.get_children(False):
+ self.assertEqual(child.start, 5)
+ self.assertEqual(child.duration, 15)
+
+ self.assertEqual(clip.inpoint, 7)
+ self.assertEqual(effect0.inpoint, 0)
+ self.assertEqual(effect1.inpoint, 0)
+ self.assertEqual(effect2.inpoint, 3)
+ self.assertEqual(effect3.inpoint, 20)
+
+ self.assertTrue(
+ clip.edit([], -1, GES.EditMode.EDIT_TRIM, GES.Edge.EDGE_START, 15))
+
+ self.assertEqual(clip.start, 15)
+ self.assertEqual(clip.duration, 5)
+ self.assertEqual(clip.get_duration_limit(), 5)
+
+ for child in clip.get_children(False):
+ self.assertEqual(child.start, 15)
+ self.assertEqual(child.duration, 5)
+
+ self.assertEqual(clip.inpoint, 17)
+ self.assertEqual(effect0.inpoint, 10)
+ self.assertEqual(effect1.inpoint, 0)
+ self.assertEqual(effect2.inpoint, 13)
+ self.assertEqual(effect3.inpoint, 20)
+
def test_ripple_end(self):
clip = self.append_clip()
clip.set_max_duration(20)