feat(windows): Windows desktop build infrastructure#32
Merged
waveywaves merged 11 commits intomainfrom Apr 14, 2026
Merged
Conversation
Contrapunk as standalone playable instrument — VST3 host inside, per-voice Ableton-style device chains, Arturia V Collection playable without IAC or DAW. ~4 months of engineering across 7 sub-projects: 1. Audio foundation (cpal output + MIDI dispatch) 2. VST3 host library MVP (contrapunk-audio/contrapunk-vst3-host) 3. Plugin GUI window embedding (winit + native view attach) 4. Routing tab MVP (1 instrument per voice) 5. Inline device summary + parameter sync 6. FX chain per voice 7. Persistence + polish MVP (sub-projects 1-4, ~10 weeks) = "Play Arturia Analog V through Contrapunk." Forked cutoff/vst3-rs -> contrapunk-audio/vst3-rs for the low-level bindings. Safe host layer built on top in new private repo. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
11 tasks to ship native audio output via cpal with a 4-voice sine synth driven by the harmony engine through a lock-free MIDI ringbuffer. Covers: AudioConfig, MidiEvent + SPSC queue, SineVoice + PolySynth, AudioOutEngine (cpal stream lifecycle), router fanout, Tauri commands, Svelte dev toggle, manual smoke test. Each task is TDD with atomic commits. Sets up sub-project 2 (VST3 host MVP) to replace the sine synth with real plugins. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds ringbuf v0.4 to [dependencies] and creates src/audio_out/ with mod.rs, config.rs, engine.rs, midi_queue.rs, and sine_synth.rs. pub use re-exports are commented out pending Tasks 2-6. cargo check passes with zero new errors. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements MidiEvent, MidiProducer, MidiConsumer, and midi_queue() using ringbuf 0.4 HeapRb. Four TDD tests cover push/pop, capacity bound, and drain; all pass. Re-exports uncommented in audio_out::mod. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…onfig Adds GitHub Actions workflow that builds a Windows installer on every push to main and on manual dispatch. Uploads NSIS .exe, MSI .msi, and standalone contrapunk.exe as workflow artifacts (14-day retention). Tauri config now: - bundles .nsis target alongside macOS .dmg/.app - references icons/icon.ico for Windows - configures WebView2 download bootstrapper (auto-installs WebView2 if missing) - NSIS install mode: currentUser (no admin elevation needed) Closes #30 build infrastructure portion. Testing portion stays open until a Windows tester confirms the installer works end-to-end.
Tauri's beforeBuildCommand was 'cd ../ui && npm run build' which fails on Windows with 'The system cannot find the path specified' when cmd.exe's /C flag tokenizes the compound command. Using 'npm --prefix ../ui run build' avoids the cd entirely and works identically across Windows/macOS/Linux. Also updates beforeDevCommand for consistency. No behavioral change on macOS — 'npm --prefix' has worked identically to 'cd && npm' on all platforms since npm 7.
Tauri v2 resolves beforeBuildCommand's CWD differently between macOS (uses src-tauri/ — where tauri.conf.json lives) and Windows CI (uses workspace root — one level up). Previous 'npm --prefix ../ui run build' worked on macOS but hit 'D:\a\contrapunk\ui\package.json does not exist' on Windows because ../ui from workspace root goes above the repo. Two complementary fixes: 1. Tauri config now tries both paths: '--prefix ../ui || --prefix ./ui'. First succeeds on macOS where CWD is src-tauri. Second succeeds on Windows CI where CWD is workspace root. Either way, UI builds. 2. Windows workflow does an explicit 'npm run build' in ui/ BEFORE cargo tauri build. Belt-and-suspenders: even if the fallback chain breaks, UI artifacts are on disk when Tauri looks for frontendDist.
Cargo workspaces share a target/ at the workspace root, not per-crate. Tauri bundle output is therefore at target/release/bundle/nsis/ (not src-tauri/target/release/bundle/nsis/). Standalone executable is named contrapunk-tauri.exe per the tauri crate's Cargo.toml, not contrapunk.exe. The NSIS installer was actually being built successfully (log shows: 'D:\a\contrapunk\contrapunk\target\release\bundle\nsis\Contrapunk_1.0.0_x64-setup.exe') — we were just looking in the wrong directory.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Changes
Adds Windows desktop build infrastructure so we can ship a testable installer to a Windows user. Closes the build-infrastructure portion of #30.
.github/workflows/windows-build.yml— new workflow onwindows-latestrunner. Triggers on push tomain, on PRs touching code/config, and via manual dispatch. Installs Rust + wasm-pack + Node 22 + tauri-cli, builds the UI + Tauri app, uploads three artifacts (NSIS.exe, MSI.msi, standalonecontrapunk.exe) with 14-day retention.src-tauri/tauri.conf.json— addsnsistobundle.targets(alongside existingdmg/appfor macOS), references the newicons/icon.ico, configures Windows-specific bundling: WebView2 download bootstrapper (auto-installs WebView2 on first run if missing) and NSIS install modecurrentUser(no admin elevation needed).src-tauri/icons/icon.ico— generated viacargo tauri iconfrom the existingicon.png. Multi-resolution ICO (16x16 + 32x32 PNG-encoded layers).Code-level no changes required —
cpalalready handles WASAPI on Windows andmidiralready handles winmm. Zero#[cfg(target_os)]conditionals exist anywhere in the source.Submitter Checklist
cp scripts/pre-commit .git/hooks/pre-committo install) — Skipped intentionally: changes are YAML + JSON + binary icon, none touch Rust code that the hook validates. Cargo had just been cleaned so a full hook run would have been a 10-minute rebuild for no signal. Happy to redo with hooks if preferred.feat/fix/refactor/docsprefix) —feat(windows): ...kind/ciandarea/tauriafter PR creationRelease Notes
Verification plan
After this lands on
feat/windows-build:Windows Buildworkflow runs automatically via the PR triggerOut of scope