diff --git a/crates/engine/src/edit.rs b/crates/engine/src/edit.rs index 5531953d..e7a8e977 100644 --- a/crates/engine/src/edit.rs +++ b/crates/engine/src/edit.rs @@ -835,6 +835,8 @@ pub fn delete_fades(s: &mut Session, track: TrackId, range: Range) -> usize { } } } + // Trimming can move a start past a later clip's start when one clip overlapped several. + pl.sort(); n } @@ -1041,4 +1043,18 @@ mod tests { s.find_clip_mut(id).unwrap().time_locked = true; assert_eq!(move_clips(&mut s, &[id], 500, &[]), 0); } + + #[test] + fn delete_fades_keeps_playlist_sorted_when_a_clip_overlaps_several() { + let (mut s, t) = session_with_clip(); + let pl = s.track_mut(t).and_then(|t| t.playlist_mut()).expect("track has a playlist"); + pl.clips.clear(); + pl.clips.push(Clip::audio(ClipId(901), "a", SourceId(500), 0, 0, 1000)); + pl.clips.push(Clip::audio(ClipId(902), "b", SourceId(500), 100, 100, 100)); + pl.clips.push(Clip::audio(ClipId(903), "c", SourceId(500), 150, 150, 750)); + delete_fades(&mut s, t, Range::new(0, 10_000)); + let got = clips(&s, t); + assert!(got.windows(2).all(|w| w[0].0 <= w[1].0), "playlist not sorted: {got:?}"); + assert!(got.iter().all(|c| c.1 > 0), "empty clip: {got:?}"); + } } diff --git a/crates/engine/tests/random_edits.proptest-regressions b/crates/engine/tests/random_edits.proptest-regressions index 3d338463..dc40fac6 100644 --- a/crates/engine/tests/random_edits.proptest-regressions +++ b/crates/engine/tests/random_edits.proptest-regressions @@ -5,3 +5,4 @@ # It is recommended to check this file in to source control so that # everyone who runs the test benefits from these saved cases. cc 1dc212f0026723d05bfcfbb29fcff476eda7f491e9bea9cd5d26dccf006a81f6 # shrinks to ops = [(9, 0, 2420494, 1), (3, 0, 2396495, 1)] +cc 87a0afb56f43d6ad377071e28bd6ba94c3d67485fc69dbefa9a2c7de3f698ed6 # shrinks to ops = [(10, 2215386, 0, 0), (0, 844227, 213110, 1), (3, 0, 443078, 0), (0, 443079, 443079, 0), (11, 0, 0, 0)]