mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 08:46:40 +00:00
timeline-tree: freeze auto-transitions whilst editing
Freeze the auto-tranistions so they do not destroy themselves during an edit. Once complete the auto-transitions can move themselves back into position, or remove themselves if their sources are no longer overlapping. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-editing-services/-/merge_requests/169>
This commit is contained in:
parent
30a821e136
commit
343e8581f2
5 changed files with 62 additions and 45 deletions
|
@ -43,33 +43,25 @@ neighbour_changed_cb (GESClip * clip, GParamSpec * arg G_GNUC_UNUSED,
|
|||
GESAutoTransition * self)
|
||||
{
|
||||
gint64 new_duration;
|
||||
GESTimelineElement *parent =
|
||||
ges_timeline_element_peak_toplevel (GES_TIMELINE_ELEMENT (clip));
|
||||
guint32 layer_prio;
|
||||
GESLayer *layer;
|
||||
GESTimeline *timeline;
|
||||
|
||||
if (GES_TIMELINE_ELEMENT_BEING_EDITED (parent))
|
||||
if (self->frozen) {
|
||||
GST_LOG_OBJECT (self, "Not updating because frozen");
|
||||
return;
|
||||
|
||||
if (parent) {
|
||||
GESTimelineElement *prev_topparent =
|
||||
ges_timeline_element_peak_toplevel (GES_TIMELINE_ELEMENT
|
||||
(self->next_source));
|
||||
GESTimelineElement *next_topparent =
|
||||
ges_timeline_element_peak_toplevel (GES_TIMELINE_ELEMENT
|
||||
(self->previous_source));
|
||||
|
||||
if (GES_TIMELINE_ELEMENT_BEING_EDITED (prev_topparent) ||
|
||||
GES_TIMELINE_ELEMENT_BEING_EDITED (next_topparent))
|
||||
return;
|
||||
|
||||
if (parent == prev_topparent && parent == next_topparent) {
|
||||
GST_DEBUG_OBJECT (self,
|
||||
"Moving all inside the same group, nothing to do");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (GES_TIMELINE_ELEMENT_LAYER_PRIORITY (self->next_source) !=
|
||||
GES_TIMELINE_ELEMENT_LAYER_PRIORITY (self->previous_source)) {
|
||||
if (self->positioning) {
|
||||
/* this can happen when the transition is moved layers as the layer
|
||||
* may resync its priorities */
|
||||
GST_LOG_OBJECT (self, "Not updating because positioning");
|
||||
return;
|
||||
}
|
||||
|
||||
layer_prio = GES_TIMELINE_ELEMENT_LAYER_PRIORITY (self->next_source);
|
||||
|
||||
if (layer_prio != GES_TIMELINE_ELEMENT_LAYER_PRIORITY (self->previous_source)) {
|
||||
GST_DEBUG_OBJECT (self, "Destroy changed layer");
|
||||
g_signal_emit (self, auto_transition_signals[DESTROY_ME], 0);
|
||||
return;
|
||||
|
@ -88,13 +80,24 @@ neighbour_changed_cb (GESClip * clip, GParamSpec * arg G_GNUC_UNUSED,
|
|||
return;
|
||||
}
|
||||
|
||||
timeline = GES_TIMELINE_ELEMENT_TIMELINE (self->transition_clip);
|
||||
layer = timeline ? ges_timeline_get_layer (timeline, layer_prio) : NULL;
|
||||
if (!layer) {
|
||||
GST_DEBUG_OBJECT (self, "Destroy no layer");
|
||||
g_signal_emit (self, auto_transition_signals[DESTROY_ME], 0);
|
||||
return;
|
||||
}
|
||||
|
||||
self->positioning = TRUE;
|
||||
GES_TIMELINE_ELEMENT_SET_BEING_EDITED (self->transition_clip);
|
||||
_set_start0 (GES_TIMELINE_ELEMENT (self->transition_clip),
|
||||
_START (self->next_source));
|
||||
_set_duration0 (GES_TIMELINE_ELEMENT (self->transition_clip), new_duration);
|
||||
ges_clip_move_to_layer (self->transition_clip, layer);
|
||||
GES_TIMELINE_ELEMENT_UNSET_BEING_EDITED (self->transition_clip);
|
||||
self->positioning = FALSE;
|
||||
|
||||
gst_object_unref (layer);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -153,6 +156,7 @@ ges_auto_transition_new (GESTrackElement * transition,
|
|||
{
|
||||
GESAutoTransition *self = g_object_new (GES_TYPE_AUTO_TRANSITION, NULL);
|
||||
|
||||
self->frozen = FALSE;
|
||||
self->previous_source = previous_source;
|
||||
self->next_source = next_source;
|
||||
self->transition = transition;
|
||||
|
|
|
@ -58,6 +58,8 @@ struct _GESAutoTransition
|
|||
|
||||
gchar *key;
|
||||
|
||||
gboolean frozen;
|
||||
|
||||
/* Padding for API extension */
|
||||
gpointer _ges_reserved[GES_PADDING];
|
||||
};
|
||||
|
@ -67,4 +69,4 @@ G_GNUC_INTERNAL GESAutoTransition * ges_auto_transition_new (GESTrackElement * t
|
|||
GESTrackElement * previous_source,
|
||||
GESTrackElement * next_source);
|
||||
|
||||
G_END_DECLS
|
||||
G_END_DECLS
|
||||
|
|
|
@ -103,6 +103,8 @@ GstDebugCategory * _ges_debug (void);
|
|||
|
||||
#define SUPRESS_UNUSED_WARNING(a) (void)a
|
||||
|
||||
G_GNUC_INTERNAL void
|
||||
ges_timeline_freeze_auto_transitions (GESTimeline * timeline, gboolean freeze);
|
||||
|
||||
G_GNUC_INTERNAL gboolean
|
||||
ges_timeline_edit (GESTimeline * timeline, GESTimelineElement * element,
|
||||
|
@ -135,10 +137,6 @@ 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);
|
||||
|
|
|
@ -1541,6 +1541,9 @@ timeline_tree_perform_edits (GNode * root, GHashTable * edits)
|
|||
GHashTableIter iter;
|
||||
gpointer key, value;
|
||||
|
||||
/* freeze the auto-transitions whilst we edit */
|
||||
ges_timeline_freeze_auto_transitions (root->data, TRUE);
|
||||
|
||||
g_hash_table_iter_init (&iter, edits);
|
||||
while (g_hash_table_iter_next (&iter, &key, &value)) {
|
||||
GESTimelineElement *element = key;
|
||||
|
@ -1548,9 +1551,10 @@ timeline_tree_perform_edits (GNode * root, GHashTable * edits)
|
|||
if (!perform_element_edit (element, edit_data))
|
||||
no_errors = FALSE;
|
||||
}
|
||||
/* allow the transitions to update if they can */
|
||||
ges_timeline_freeze_auto_transitions (root->data, FALSE);
|
||||
|
||||
timeline_tree_create_transitions (root, ges_timeline_find_auto_transition);
|
||||
timeline_update_transition (root->data);
|
||||
timeline_update_duration (root->data);
|
||||
|
||||
return no_errors;
|
||||
|
@ -2032,6 +2036,10 @@ create_transition_if_needed (GESTimeline * timeline, GESTrackElement * prev,
|
|||
"]", _START (next), duration);
|
||||
ges_timeline_create_transition (timeline, prev, next, NULL, layer,
|
||||
_START (next), duration);
|
||||
} else {
|
||||
GST_INFO ("Already have transition %" GES_FORMAT " between %" GES_FORMAT
|
||||
" and %" GES_FORMAT, GES_ARGS (trans), GES_ARGS (prev),
|
||||
GES_ARGS (next));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2043,12 +2051,10 @@ create_transitions (GNode * node,
|
|||
GESTimeline *timeline;
|
||||
GESLayer *layer;
|
||||
|
||||
if (G_NODE_IS_ROOT (node))
|
||||
if (!GES_IS_SOURCE (node->data))
|
||||
return FALSE;
|
||||
|
||||
timeline = GES_TIMELINE_ELEMENT_TIMELINE (node->data);
|
||||
if (!GES_IS_SOURCE (node->data))
|
||||
return FALSE;
|
||||
|
||||
if (!timeline) {
|
||||
GST_INFO ("%" GES_FORMAT " not in timeline yet", GES_ARGS (node->data));
|
||||
|
@ -2064,6 +2070,7 @@ create_transitions (GNode * node,
|
|||
if (!ges_layer_get_auto_transition (layer))
|
||||
return FALSE;
|
||||
|
||||
GST_LOG (node->data, "Checking for overlaps");
|
||||
data.root = g_node_get_root (node);
|
||||
check_all_overlaps_with_element (node, &data);
|
||||
|
||||
|
|
|
@ -1110,6 +1110,24 @@ done:
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
ges_timeline_freeze_auto_transitions (GESTimeline * timeline, gboolean freeze)
|
||||
{
|
||||
GList *tmp, *trans = g_list_copy (timeline->priv->auto_transitions);
|
||||
for (tmp = trans; tmp; tmp = tmp->next) {
|
||||
GESAutoTransition *auto_transition = tmp->data;
|
||||
auto_transition->frozen = freeze;
|
||||
if (freeze == FALSE) {
|
||||
GST_LOG_OBJECT (timeline, "Un-Freezing %" GES_FORMAT,
|
||||
GES_ARGS (auto_transition->transition_clip));
|
||||
ges_auto_transition_update (auto_transition);
|
||||
} else {
|
||||
GST_LOG_OBJECT (timeline, "Freezing %" GES_FORMAT,
|
||||
GES_ARGS (auto_transition->transition_clip));
|
||||
}
|
||||
}
|
||||
g_list_free (trans);
|
||||
}
|
||||
|
||||
static gint
|
||||
_edit_auto_transition (GESTimeline * timeline, GESTimelineElement * element,
|
||||
|
@ -1217,17 +1235,6 @@ timeline_add_group (GESTimeline * timeline, GESGroup * group)
|
|||
ges_timeline_element_set_timeline (GES_TIMELINE_ELEMENT (group), timeline);
|
||||
}
|
||||
|
||||
void
|
||||
timeline_update_transition (GESTimeline * timeline)
|
||||
{
|
||||
GList *tmp, *auto_transs;
|
||||
|
||||
auto_transs = g_list_copy (timeline->priv->auto_transitions);
|
||||
for (tmp = auto_transs; tmp; tmp = tmp->next)
|
||||
ges_auto_transition_update (tmp->data);
|
||||
g_list_free (auto_transs);
|
||||
}
|
||||
|
||||
/**
|
||||
* timeline_emit_group_added:
|
||||
* @timeline: The #GESTimeline
|
||||
|
@ -1689,8 +1696,7 @@ ges_timeline_add_clip (GESTimeline * timeline, GESClip * clip)
|
|||
if (ges_clip_is_moving_from_layer (clip)) {
|
||||
GST_DEBUG ("Clip %p moving from one layer to another, not creating "
|
||||
"TrackElement", clip);
|
||||
timeline_tree_create_transitions (timeline->priv->tree,
|
||||
ges_timeline_find_auto_transition);
|
||||
/* timeline-tree handles creation of auto-transitions */
|
||||
ret = TRUE;
|
||||
} else {
|
||||
ret = add_object_to_tracks (timeline, clip, NULL);
|
||||
|
|
Loading…
Reference in a new issue