From 712bda84db2d1093aa29687b6e583f8c194d4286 Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Tue, 25 Oct 2022 23:12:00 -0300 Subject: [PATCH] ges: Add API to disable timeline coherence checks There are cases where user might want to be in full control of the timeline and not be limited by the checks that are being done by GES to go from one timeline layout to another, this should be doable as it is a valid use case. Part-of: --- .../ges/ges-timeline-tree.c | 9 +++ .../gst-editing-services/ges/ges-timeline.c | 69 ++++++++++++++++++- .../gst-editing-services/ges/ges-timeline.h | 5 ++ .../tests/check/python/test_timeline.py | 16 +++++ 4 files changed, 98 insertions(+), 1 deletion(-) diff --git a/subprojects/gst-editing-services/ges/ges-timeline-tree.c b/subprojects/gst-editing-services/ges/ges-timeline-tree.c index ed44884ed2..d4672c1238 100644 --- a/subprojects/gst-editing-services/ges/ges-timeline-tree.c +++ b/subprojects/gst-editing-services/ges/ges-timeline-tree.c @@ -929,6 +929,11 @@ timeline_tree_can_move_elements (GNode * root, GHashTable * moving, GError ** error) { TreeIterationData data = tree_iteration_data_init; + + if (ges_timeline_get_edit_apis_disabled (root->data)) { + return TRUE; + } + data.moving = moving; data.root = root; data.res = TRUE; @@ -1703,6 +1708,10 @@ timeline_tree_can_move_element (GNode * root, GHashTableIter iter; gpointer key, value; + if (ges_timeline_get_edit_apis_disabled (root->data)) { + return TRUE; + } + if (layer_prio == GES_TIMELINE_ELEMENT_NO_LAYER_PRIORITY && priority != layer_prio) { GST_INFO_OBJECT (element, "Cannot move to a layer when no layer " diff --git a/subprojects/gst-editing-services/ges/ges-timeline.c b/subprojects/gst-editing-services/ges/ges-timeline.c index 045282565d..eb6f1092bf 100644 --- a/subprojects/gst-editing-services/ges/ges-timeline.c +++ b/subprojects/gst-editing-services/ges/ges-timeline.c @@ -115,6 +115,10 @@ * transition object will be kept, but with its timing and layer adjusted * accordingly. * + * NOTE: if you know what you are doing and want to be in full control of the + * timeline layout, you can disable the edit APIs with + * #ges_timeline_disable_edit_apis. + * * ## Saving * * To save/load a timeline, you can use the ges_timeline_load_from_uri() @@ -234,6 +238,7 @@ struct _GESTimelinePrivate GstStreamCollection *stream_collection; gboolean rendering_smartly; + gboolean disable_edit_apis; }; /* private structure to contain our track-related information */ @@ -2947,7 +2952,7 @@ ges_timeline_commit_sync (GESTimeline * timeline) * Freezes the timeline from being committed. This is usually needed while the * timeline is being rendered to ensure that not change to the timeline are * taken into account during that moment. Once the rendering is done, you - * should call #ges_timeline_thaw_commit so that comiting becomes possible + * should call #ges_timeline_thaw_commit so that committing becomes possible * again and any call to `commit()` that happened during the rendering is * actually taken into account. * @@ -3038,6 +3043,7 @@ ges_timeline_set_auto_transition (GESTimeline * timeline, GESLayer *layer; g_return_if_fail (GES_IS_TIMELINE (timeline)); + g_return_if_fail (!timeline->priv->disable_edit_apis); CHECK_THREAD (timeline); timeline->priv->auto_transition = auto_transition; @@ -3387,3 +3393,64 @@ ges_timeline_get_frame_at (GESTimeline * self, GstClockTime timestamp) return gst_util_uint64_scale (timestamp, fps_n, fps_d * GST_SECOND); } + +/** + * ges_timeline_disable_edit_apis: + * @self: A #GESTimeline + * @disable_edit_apis: %TRUE to disable all the edit APIs so the user is in full + * control of ensuring timeline state validity %FALSE otherwise. + * + * WARNING: When using that mode, GES won't guarantee the coherence of the + * timeline. You need to ensure that the rules described in the [Overlaps and + * auto transitions](#overlaps-and-autotransitions) section are respected any time + * the timeline is [commited](ges_timeline_commit) (otherwise playback will most + * probably fail in different ways). + * + * When disabling editing APIs, GES won't be able to enforce the rules that + * makes the timeline overall state to be valid but some feature won't be + * usable: + * * #GESTimeline:snapping-distance + * * #GESTimeline:auto-transition + * + * Since: 1.22 + */ +void +ges_timeline_disable_edit_apis (GESTimeline * self, gboolean disable_edit_apis) +{ + CHECK_THREAD (self); + g_return_if_fail (GES_IS_TIMELINE (self)); + + if (disable_edit_apis) { + if (self->priv->snapping_distance > 0) { + GST_INFO_OBJECT (self, + "Disabling snapping as we are disabling edit APIs"); + + ges_timeline_set_snapping_distance (self, 0); + } + + if (self->priv->auto_transition || self->priv->auto_transitions) { + GST_INFO_OBJECT (self, + "Disabling auto transitions as we are disabling auto edit APIs"); + ges_timeline_set_auto_transition (self, FALSE); + } + } + + self->priv->disable_edit_apis = disable_edit_apis; +} + +/** + * ges_timeline_get_edit_apis_disabled: + * @self: A #GESTimeline + * + * Returns: %TRUE if edit APIs are disabled, %FALSE otherwise. + * + * Since: 1.22 + */ +gboolean +ges_timeline_get_edit_apis_disabled (GESTimeline * self) +{ + CHECK_THREAD (self); + g_return_val_if_fail (GES_IS_TIMELINE (self), FALSE); + + return self->priv->disable_edit_apis; +} diff --git a/subprojects/gst-editing-services/ges/ges-timeline.h b/subprojects/gst-editing-services/ges/ges-timeline.h index 00947d8ba6..92cb496c27 100644 --- a/subprojects/gst-editing-services/ges/ges-timeline.h +++ b/subprojects/gst-editing-services/ges/ges-timeline.h @@ -160,4 +160,9 @@ GES_API GESFrameNumber ges_timeline_get_frame_at (GESTimeline *self, GstClockTime timestamp); +GES_API +void ges_timeline_disable_edit_apis (GESTimeline * self, gboolean disable_edit_apis); +GES_API +gboolean ges_timeline_get_edit_apis_disabled (GESTimeline * self); + G_END_DECLS diff --git a/subprojects/gst-editing-services/tests/check/python/test_timeline.py b/subprojects/gst-editing-services/tests/check/python/test_timeline.py index e28607bcf5..c648fc86c0 100644 --- a/subprojects/gst-editing-services/tests/check/python/test_timeline.py +++ b/subprojects/gst-editing-services/tests/check/python/test_timeline.py @@ -3651,6 +3651,22 @@ class TestComplexEditing(common.GESTimelineConfigTest): c0, 0, GES.EditMode.EDIT_NORMAL, GES.Edge.EDGE_NONE, 10, 30, [c0], [c1], {c0 : {"start": 27}}, [], []) + def test_disable_timeline_editing_apis(self): + track = self.add_video_track() + self.assertEqual(self.timeline.props.auto_transition, True) + self.timeline.disable_edit_apis(True) + self.assertEqual(self.timeline.props.auto_transition, False) + + c0 = self.add_clip("c0", 0, [track], 0, 10) + # Without disabling edit API adding clip would fail + c1 = self.add_clip("c1", 0, [track], 0, 10) + self.assertTimelineConfig() + + c1.set_start(1) + c1.set_duration(1) + self.assertEqual(c1.get_start(), 1) + self.assertEqual(c1.get_duration(), 1) + class TestTransitions(common.GESSimpleTimelineTest):