collective

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

diff --git a/crates/engine/src/cmd/transport.rs b/crates/engine/src/cmd/transport.rs--- a/crates/engine/src/cmd/transport.rs+++ b/crates/engine/src/cmd/transport.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!({})) }),diff --git a/crates/engine/src/lib.rs b/crates/engine/src/lib.rs--- a/crates/engine/src/lib.rs+++ b/crates/engine/src/lib.rs@@ -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,diff --git a/crates/ui-egui/src/lib.rs b/crates/ui-egui/src/lib.rs--- a/crates/ui-egui/src/lib.rs+++ b/crates/ui-egui/src/lib.rs@@ -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());