mirror of
https://github.com/storytold/soundcraft.git
synced 2026-10-24 10:36:46 -06:00
Merge pull request #494 from Jafz2001/fix/remove-folder-bus
fix(routing): remove folder bus on delete
This commit is contained in:
@@ -543,6 +543,15 @@ fn folder_bus(s: &Session, folder: TrackId) -> Option<Route> {
|
||||
s.track(folder).map(|folder| folder.mixer.input.clone()).filter(|route| matches!(route, Route::Bus(_)))
|
||||
}
|
||||
|
||||
/// The summing bus owned by a routing folder.
|
||||
fn owned_folder_bus(s: &Session, folder: TrackId) -> Option<soundcraft_model::BusId> {
|
||||
let folder = s.track(folder).filter(|track| track.kind == TrackKind::Folder)?;
|
||||
match folder.mixer.input {
|
||||
Route::Bus(id) => Some(id),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Keep only the selected roots so selecting a folder and one of its children preserves the subtree.
|
||||
fn root_tracks(s: &Session, tracks: Vec<TrackId>) -> Vec<TrackId> {
|
||||
tracks.iter().copied().filter(|track| !tracks.iter().any(|root| root != track && in_folder(s, *track, *root))).collect()
|
||||
@@ -627,6 +636,20 @@ fn change_width(e: &mut Engine, p: &Value) -> Result<Value> {
|
||||
fn delete(e: &mut Engine, p: &Value) -> Result<Value> {
|
||||
let tracks = tracks_required(e, "track.delete", p)?;
|
||||
let s = e.session_mut();
|
||||
let removed_busses: Vec<_> = tracks
|
||||
.iter()
|
||||
.filter_map(|folder| {
|
||||
let bus = owned_folder_bus(s, *folder)?;
|
||||
let mut parent = s.track(*folder).and_then(|folder| folder.folder);
|
||||
for _ in 0..64 {
|
||||
match parent {
|
||||
Some(candidate) if tracks.contains(&candidate) => parent = s.track(candidate).and_then(|folder| folder.folder),
|
||||
_ => break,
|
||||
}
|
||||
}
|
||||
Some((bus, parent.and_then(|parent| folder_bus(s, parent)).unwrap_or(Route::Main)))
|
||||
})
|
||||
.collect();
|
||||
// Promote children of deleted folders and repair only routes that used the deleted
|
||||
// folder's own bus. Custom outputs remain untouched.
|
||||
let mut promoted = Vec::new();
|
||||
@@ -657,6 +680,22 @@ fn delete(e: &mut Engine, p: &Value) -> Result<Value> {
|
||||
for g in &mut s.groups {
|
||||
g.members.retain(|t| !tracks.contains(t));
|
||||
}
|
||||
for (bus, replacement) in removed_busses {
|
||||
s.busses.retain(|candidate| candidate.id != bus);
|
||||
for track in &mut s.tracks {
|
||||
if track.mixer.input == Route::Bus(bus) {
|
||||
track.mixer.input = Route::None;
|
||||
}
|
||||
if track.mixer.output == Route::Bus(bus) {
|
||||
track.mixer.output = replacement.clone();
|
||||
}
|
||||
for send in &mut track.mixer.sends {
|
||||
if send.as_ref().is_some_and(|send| send.target == Route::Bus(bus)) {
|
||||
*send = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(json!({"deleted": tracks.len()}))
|
||||
}
|
||||
|
||||
@@ -999,6 +1038,14 @@ mod tests {
|
||||
|
||||
e.execute("track.move_to_folder", &json!({"tracks": ["Kick"], "folder": inner.0})).unwrap();
|
||||
e.execute("track.move_to_folder", &json!({"tracks": [inner.0], "folder": outer.0})).unwrap();
|
||||
let inner_bus = match e.session().track(inner).unwrap().mixer.input {
|
||||
Route::Bus(bus) => bus,
|
||||
_ => panic!("folder did not receive a bus"),
|
||||
};
|
||||
let outer_bus = match e.session().track(outer).unwrap().mixer.input {
|
||||
Route::Bus(bus) => bus,
|
||||
_ => panic!("folder did not receive a bus"),
|
||||
};
|
||||
assert!(e.execute("track.move_to_folder", &json!({"tracks": [outer.0], "folder": inner.0})).is_err());
|
||||
|
||||
let kick = e.session().track_by_name("Kick").unwrap();
|
||||
@@ -1025,6 +1072,8 @@ mod tests {
|
||||
let kick = e.session().track_by_name("Kick").unwrap();
|
||||
assert_eq!(kick.folder, None);
|
||||
assert_eq!(kick.mixer.output, Route::Main);
|
||||
assert!(e.session().bus(inner_bus).is_none(), "the deleted folder's owned bus must be removed");
|
||||
assert!(e.session().bus(outer_bus).is_some(), "the surviving parent folder's bus must remain");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user