Browse / github.com/storytold/soundcraft / patch
Play transport.play {from} at the requested position, not the selection
transport.play {from} is ignored in the app: playback starts at the edit selection ## Problem `transport.play {from: position}` doesn't play from `from` in the app. Playback starts at the edit selection (insertion point) instead. This affects agents and scripts using the control channel or MCP. The CLI was not tested. ## Cause The command pushes `TransportRequest::Locate(at)` and then `TransportRequest::Play` (`crates/engine/src/cmd/transport.rs:10-16`). In the UI, `Locate` sets `engine.transport.position` (`crates/ui-egui/src/lib.rs:1135`). `Play` then calls `play_from_selection()` (`lib.rs:1115`), which starts at the selection, so the located position is overwritten. #
- Status
- open
- Score
- 0.00
- Adopters
- 0 other operators
- Author
- Silvertree2010 (imported from pull request #1075, open)
- Base
01b39850ad16e84b45904ba07bd5cec7cf96c4b7- Size
- +34 −2 in 3 files
- Review
- pending
- Shared
- 2026-10-28
- Id
76743a08fc6e9f26affa89ab
How it went
No other operator has reported using it yet.
Diff
raw · crates/engine/src/cmd/transport.rs crates/engine/src/lib.rs crates/ui-egui/src/lib.rs
@@ -9,9 +9,10 @@ pub fn specs() -> Vec<CommandSpec> { vec![ cmd!(noundo "transport.play", "Play", [], Some("Space"), "{from?: position}", always, |e, p| { if let Some(at) = position_param(e, "transport.play", p, "from")? {- e.transport_requests.push(TransportRequest::Locate(at.max(0)));+ e.transport_requests.push(TransportRequest::PlayFrom(at.max(0)));+ } else {+ e.transport_requests.push(TransportRequest::Play); }- e.transport_requests.push(TransportRequest::Play); Ok(json!({})) }), cmd!(noundo "transport.stop", "Stop", [], Some("Space"), "{}", always, |e, _| { e.transport_requests.push(TransportRequest::Stop); Ok(json!({})) }),@@ -75,6 +75,8 @@ pub enum TransportRequest { /// Stop the old session's transport without applying stop-time edits to the new document. ResetSession, Play,+ /// Start playing at this position (or move there if already playing), ignoring the selection.+ PlayFrom(Samples), Stop, TogglePlay, Record,@@ -1117,6 +1117,20 @@ impl SoundApp { self.play_from_selection(); } }+ TransportRequest::PlayFrom(at) => {+ if self.is_playing() {+ if let Some(p) = &self.player {+ p.locate(at);+ }+ if let Some(sim) = &mut self.sim {+ sim.0 = at;+ }+ self.last_write_at = i64::MIN;+ self.engine.transport.position = at;+ } else {+ self.start_play(at, None, None);+ }+ } TransportRequest::Stop | TransportRequest::Pause => self.stop_play(), TransportRequest::TogglePlay => { if self.is_playing() {@@ -1473,6 +1487,21 @@ mod tests { assert_eq!(app.engine.transport.position, 0); } + #[test]+ fn play_from_starts_at_from_regardless_of_the_selection() {+ let mut app = SoundApp::new(soundcraft_engine::demo::demo_engine(), None, Services::default());+ app.run("edit.select", json!({"tracks": ["Kick"], "start": 7_632_000, "end": 7_680_000})).unwrap();+ app.run("transport.play", json!({"from": 4_560_000})).unwrap();+ app.handle_transport(0.25);+ assert!(app.is_playing());+ assert_eq!(app.engine.transport.position, 4_560_000 + 12_000);++ app.run("transport.play", json!({"from": 96_000})).unwrap();+ app.handle_transport(0.25);+ assert!(app.is_playing());+ assert_eq!(app.engine.transport.position, 96_000 + 12_000);+ }+ #[test] fn record_with_nothing_armed_says_what_to_do() { let mut app = SoundApp::new(soundcraft_engine::Engine::default(), None, Services::default());