From 805af0dffce16ee9109f375e50884ca3bc0bb551 Mon Sep 17 00:00:00 2001 From: Jonathan Thomas Date: Sat, 7 Jun 2025 16:03:55 -0500 Subject: [PATCH] Fix Timeline::ApplyJsonDiff to make changes to our data first, and then clear cache afterwards (potential race condition) --- src/Timeline.cpp | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/Timeline.cpp b/src/Timeline.cpp index eb8031b2..9f8efb58 100644 --- a/src/Timeline.cpp +++ b/src/Timeline.cpp @@ -1412,13 +1412,6 @@ void Timeline::apply_json_to_clips(Json::Value change) { } } - // Calculate start and end frames that this impacts, and remove those frames from the cache - if (!change["value"].isArray() && !change["value"]["position"].isNull()) { - int64_t new_starting_frame = (change["value"]["position"].asDouble() * info.fps.ToDouble()) + 1; - int64_t new_ending_frame = ((change["value"]["position"].asDouble() + change["value"]["end"].asDouble() - change["value"]["start"].asDouble()) * info.fps.ToDouble()) + 1; - final_cache->Remove(new_starting_frame - 8, new_ending_frame + 8); - } - // Determine type of change operation if (change_type == "insert") { @@ -1438,6 +1431,8 @@ void Timeline::apply_json_to_clips(Json::Value change) { // Update existing clip if (existing_clip) { + // Update clip properties from JSON + existing_clip->SetJsonValue(change["value"]); // Calculate start and end frames that this impacts, and remove those frames from the cache int64_t old_starting_frame = (existing_clip->Position() * info.fps.ToDouble()) + 1; @@ -1448,9 +1443,6 @@ void Timeline::apply_json_to_clips(Json::Value change) { if (existing_clip->Reader() && existing_clip->Reader()->GetCache()) existing_clip->Reader()->GetCache()->Remove(old_starting_frame - 8, old_ending_frame + 8); - // Update clip properties from JSON - existing_clip->SetJsonValue(change["value"]); - // Apply framemapper (or update existing framemapper) if (auto_map_clips) { apply_mapper_to_clip(existing_clip); @@ -1461,18 +1453,24 @@ void Timeline::apply_json_to_clips(Json::Value change) { // Remove existing clip if (existing_clip) { + // Remove clip from timeline + RemoveClip(existing_clip); // Calculate start and end frames that this impacts, and remove those frames from the cache int64_t old_starting_frame = (existing_clip->Position() * info.fps.ToDouble()) + 1; int64_t old_ending_frame = ((existing_clip->Position() + existing_clip->Duration()) * info.fps.ToDouble()) + 1; final_cache->Remove(old_starting_frame - 8, old_ending_frame + 8); - - // Remove clip from timeline - RemoveClip(existing_clip); } } + // Calculate start and end frames that this impacts, and remove those frames from the cache + if (!change["value"].isArray() && !change["value"]["position"].isNull()) { + int64_t new_starting_frame = (change["value"]["position"].asDouble() * info.fps.ToDouble()) + 1; + int64_t new_ending_frame = ((change["value"]["position"].asDouble() + change["value"]["end"].asDouble() - change["value"]["start"].asDouble()) * info.fps.ToDouble()) + 1; + final_cache->Remove(new_starting_frame - 8, new_ending_frame + 8); + } + // Re-Sort Clips (since they likely changed) sort_clips(); }