Keep overlapping clips of a clip group when importing it (#452)

This commit is contained in:
MarekSpodBiedry
2026-10-13 17:52:12 +02:00
parent c0cb993408
commit df0e8928d7
+31 -1
View File
@@ -149,6 +149,7 @@ pub fn import(e: &mut Engine, path: &str, first: Option<TrackId>, at: Samples) -
s.add_track(kind, fmt, Some("Clip Group"))
}
};
let mut prepared = Vec::new();
for mut c in lane {
if let ClipContent::Audio { source, offset } = &mut c.content {
let Some(n) = map.get(&source.0) else { continue };
@@ -163,7 +164,16 @@ pub fn import(e: &mut Engine, path: &str, first: Option<TrackId>, at: Samples) -
c.group = Some(group_id);
c.sanitize();
placed.push(c.id);
crate::edit::place_clip(s, target, c);
prepared.push(c);
}
// Clear what was already on the track first, then add the whole lane at once, so clips of
// the group that overlap each other (crossfades) keep their overlap.
for c in &prepared {
crate::edit::clear_range(s, target, c.range(), false);
}
if let Some(pl) = s.track_mut(target).and_then(|t| t.playlist_mut()) {
pl.clips.extend(prepared);
pl.sort();
}
}
Ok(placed)
@@ -229,6 +239,26 @@ mod tests {
let _ = std::fs::remove_dir_all(&dir);
}
#[test]
fn overlapping_clips_of_a_group_keep_their_overlap_on_import() {
let dir = std::env::temp_dir().join(format!("sc-grp-overlap-{}", std::process::id()));
let _ = std::fs::create_dir_all(&dir);
let p = dir.join("overlap.scgrp");
let note = json!({"pitch": 60, "velocity": 100, "release_velocity": 64, "channel": 0, "start": 0, "length": 100});
let content = json!({"Midi": {"sequence": {"notes": [note], "ctrls": []}}});
let a = json!({"id": 1, "name": "a", "start": 0, "length": 1000, "content": content});
let b = json!({"id": 2, "name": "b", "start": 600, "length": 1000, "content": content});
let file = json!({"format": "soundcraft.clipgroup", "version": 1, "sample_rate": 48000, "length": 1600, "lanes": [[a, b]], "audio": {}});
std::fs::write(&p, file.to_string()).unwrap();
let mut e = crate::demo::demo_engine();
let r = e.execute("file.import_clip_groups", &json!({"path": p.to_string_lossy()})).unwrap();
let ids: Vec<_> = r["clips"].as_array().unwrap().iter().filter_map(serde_json::Value::as_u64).collect();
assert_eq!(ids.len(), 2);
let spans: Vec<_> = ids.iter().map(|id| e.session().find_clip(soundcraft_model::ClipId(*id)).map(|(_, c)| (c.start, c.length))).collect();
assert_eq!(spans, vec![Some((0, 1000)), Some((600, 1000))]);
let _ = std::fs::remove_dir_all(&dir);
}
#[test]
fn a_file_named_by_many_ids_becomes_one_source() {
let dir = std::env::temp_dir().join(format!("sc-grp-shared-{}", std::process::id()));