From a825f0aba3dbd9504a1cfe9747eed251b959d61c Mon Sep 17 00:00:00 2001 From: "prompt.ac/@jeffrey" Date: Wed, 27 May 2026 11:56:08 -0700 Subject: [PATCH] menuband: always restart engine after MIDISynth preload The `if engineWasRunning` guard left the engine paused when configureMIDISynth ran during a graph-reconfig window (engine.attach / engine.connect can transiently pause the engine), so the first noteOn after launch played MIDISynth's empty-state sine tone instead of the program the UI showed as selected. Co-Authored-By: Claude Opus 4.7 (1M context) --- slab/menuband/Sources/MenuBand/MenuBandSynth.swift | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/slab/menuband/Sources/MenuBand/MenuBandSynth.swift b/slab/menuband/Sources/MenuBand/MenuBandSynth.swift index 1648bc9927..cdf93e8c13 100644 --- a/slab/menuband/Sources/MenuBand/MenuBandSynth.swift +++ b/slab/menuband/Sources/MenuBand/MenuBandSynth.swift @@ -343,7 +343,17 @@ final class MenuBandSynth { if engineWasRunning { engine.pause() } preloadAllMelodicPrograms(au) preloadDrumKit(au) - if engineWasRunning { + // Always restart the engine after preload — selectMelodicProgram + // below (and every subsequent noteOn) needs the render thread + // alive to actually process the queued bank+PC MIDI events. + // The old `if engineWasRunning` guard stranded us in a paused + // state when configureMIDISynth happened during a graph-reconfig + // window (engine.attach/engine.connect can transiently pause the + // engine), with the symptom that the user's picked instrument + // never lands on the AU — first noteOn after launch plays + // MIDISynth's empty-state fallback (a sine tone) regardless of + // which program the UI shows as selected. + if !engine.isRunning { do { try engine.start() } catch { NSLog("MenuBand: engine restart after MIDISynth preload failed: \(error)") } -- 2.51.2