Commit Graph
82 Commits
Author SHA1 Message Date
Brandon ThomasandClaude Opus 5.5 3a3c447904 Merge origin/main into issue-57
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 20:30:26 -04:00
21f9b07074 Add a selectable Light theme (#32)
* Add a selectable Light theme

* Apply the active theme to the menu bar

* Use the system theme by default

* Expose Appearance in the Setup menu

* Add Light theme screenshot

* Remove the Light theme screenshot

Repo policy keeps large binary assets out of the tree, and the PNG had no
ATTRIBUTION row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Appearance: ui.theme command, Dark default, non-blocking system lookup

- ThemeMode derives Default with Dark as the default (fixes clippy's
  derivable_impls); System and Light are opt-in. LIGHT_THEME starts false.
- New UI command `ui.theme {"mode": "system|light|dark"}` (label
  "Appearance") in UI_COMMANDS; with no mode it reports the current one.
  The UI Customization combo box dispatches it instead of writing state.
- The choice lives in UiState.theme, so it persists with the existing UI
  prefs (ui.json) and is exposed through ui.set / ui.inspect. Restoring a
  window configuration keeps the current theme.
- dark_light::detect() is only called in System mode, on a background
  thread (an AtomicU8 holds the answer; dark until it arrives, then a
  repaint). On the web it is the synchronous matchMedia lookup.
- theme::apply runs only when the effective palette changes, not every
  frame.
- window.ui_customization keeps its catalog path (Window > UI
  Customization) so parity is unchanged; Setup > Appearance still opens
  it. The combo row is labelled "Theme" so it no longer repeats the title.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Light theme: move hard-coded colours to theme tokens

The Light palette left dark islands and unreadable text where colours
were Color32 literals. New tokens (Dark values are the old literals, so
the Dark theme renders pixel-identical to main):

- menu bar; toolbar group outline; edit-mode cells (no more dark block
  around Shuffle/Spot/Slip/Grid); counter panel outlines, dividers and
  off toggles; Smart-tool bracket
- selected rows in the Tracks/Groups/Clips lists, track-visible dot,
  selected Edit track header, selected Mix strip
- marker names, alternate-playlist lanes, Universe background/outline,
  Big Counter background
- meter background and clip lamp, pan knob body/ring/pointer, Mix insert
  and send slots, Mix section captions

In Light, clip bodies are a paler tint and waveforms a deep shade of the
clip colour instead of black.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Light theme: instrument slot and plugin window text use the current tokens

The instrument picker (#23) landed with Tokens::DARK literals.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: t <t@t>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-09 18:37:04 -04:00
Brandon Thomas 5f2ce943a6 Merge pull request #10 from reoniazx/fix/macos-native-menu-bar
macOS: move application menus to the system menu bar
2026-10-09 18:27:25 -04:00
Brandon ThomasandClaude Opus 5.5 a867f05177 Merge origin/main into feature/plugin-menus-instruments
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 18:23:33 -04:00
Brandon ThomasandClaude Opus 5.5 acf3237bed Merge origin/main into fix/macos-native-menu-bar
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 18:15:50 -04:00
Brandon ThomasandClaude Opus 5.5 2e2220c64d Merge origin/main into fix/vst3-module-exit
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 18:13:17 -04:00
Brandon ThomasandClaude Opus 5.5 5824042856 Merge origin/main into desktop-log-file
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 18:12:03 -04:00
Brandon Thomas 2c495aa473 Merge pull request #31 from vbasky/feat/fontconfig-system-fonts
Use fontconfig for Linux system fonts
2026-10-09 18:11:45 -04:00
Brandon Thomas 7083a58500 Merge pull request #29 from Garygunn94/claude/track-delete-menu-disappear-9456d6
Keep the clip context menu open while moving onto it
2026-10-09 18:11:39 -04:00
Brandon Thomas e9820fac30 Merge pull request #28 from Garygunn94/claude/recording-audio-playback-b2db9a
Fix input monitoring pitch and dropouts when input and session rates differ
2026-10-09 18:11:35 -04:00
Brandon Thomas 4bb041ad5c Merge pull request #26 from Garygunn94/feat/metronome-click
Make the Click option audible: metronome in live playback
2026-10-09 18:11:29 -04:00
Brandon Thomas d4a20130f0 Merge pull request #25 from Garygunn94/claude/tempo-value-not-saving-12cc98
Fix tempo change from the tempo ruler not saving
2026-10-09 18:11:16 -04:00
Brandon Thomas 30dd2c84d1 Merge pull request #36 from reoniazx/fix/timeline-follow-hold
Pause playhead follow when the timeline is moved away during playback
2026-10-09 18:11:11 -04:00
Brandon Thomas 286ac34e26 Merge pull request #20 from MarekSpodBiedry/issue-15
Fix keyboard shortcuts on Windows and Linux: Ctrl is the Cmd key (#15)
2026-10-09 18:11:06 -04:00
Brandon Thomas 886278fa21 Merge pull request #37 from reoniazx/fix/automation-first-pass-overflow
Fix debug overflow panic on the first automation-write pass
2026-10-09 18:10:56 -04:00
MarekSpodBiedry f8a156d255 Warn about missing media when opening a session (#57) 2026-10-09 20:28:46 +02:00
tandClaude Opus 5.5 d5f70bf09e dialogs: keep the Dialog enum rustfmt-clean
A doc comment on one variant made rustfmt expand every variant.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 11:05:24 -04:00
tandClaude Opus 5.5 c04e79714c fonts: fontconfig on FreeBSD too; accept only TrueType/OpenType results
egui panics on Type 1 or bitmap font bytes, which fc-match can return on
minimal systems, so check the sfnt magic first. Mask the variable-font
named instance out of %{index}. Fix the unused 'bold' warning on macOS
and Windows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 11:00:17 -04:00
tandClaude Opus 5.5 916f453690 mix: no click while only monitoring input with the transport stopped
The stopped position does not advance, so a beat at the stop point
re-rendered its first 30 ms every block: a ~94 Hz buzz whenever a track
was record-armed or monitoring input. Regression test included.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 10:58:38 -04:00
tandClaude Opus 5.5 6c3f2dbac8 After Playback: scroll via view.scroll, and only when the stop point is off-screen
Stop no longer writes the session's scroll directly (everything is a
command) and leaves the view alone when the stopped position is visible.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 10:57:18 -04:00
Brandon Thomas a4c371b18b Revert "Do not yank the view to the playhead on play start"
This reverts commit 0ffd2a1441.
2026-10-09 10:56:45 -04:00
tandClaude Opus 5.5 667e32152e shortcuts: keep Cmd+Ctrl apart from Cmd on macOS; detect the Mac at runtime
On macOS a held Cmd made the Ctrl state ignored, so Cmd+Ctrl+X ran Cut
instead of Cut Clip Gain. Ask egui for the OS so the web build in a Mac
browser uses Mac modifiers too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 10:55:42 -04:00
Brandon ThomasandClaude Opus 5.5 f0a0ac8318 vst3-host tests: expect editor 'unsupported' off macOS
VST3 editor windows are hosted on macOS only, but editor_main_thread and
fixture_e2e asserted a probed view size on every platform, failing the
FreeBSD job on every commit to main (and Linux locally). Gate only the
size assertion; the controller round trips still run everywhere.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 10:42:37 -04:00
reoniazx 0ffd2a1441 Do not yank the view to the playhead on play start 2026-10-09 13:28:58 +08:00
reoniazx da970b2490 Fix debug overflow panic on the first automation-write pass 2026-10-09 13:24:37 +08:00
reoniazx 5b7864c8f7 Pause playhead follow when the timeline is moved away during playback 2026-10-09 13:22:39 +08:00
Vikram Bhaskaran 983846a054 Use fontconfig for Linux system fonts 2026-10-09 11:12:26 +11:00
Gary GunnandClaude Haiku 5.5 4c7ffc5f03 Keep the clip context menu open while moving onto it
The clip menu was attached at the end of lane_interaction, which returns
early when the lane has no pointer position. Once the menu opened, the
pointer sat over the popup, the lane lost its hover, and the menu was
never drawn again, so it vanished before Delete could be clicked.

Attach the menu before the early return and remember the right-clicked
clip so it keeps its target. Stale clip ids are dropped if the clip no
longer exists. Adds a kittest regression test covering right-click,
move onto the menu, and Delete.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-08 22:25:48 +01:00
Gary GunnandClaude Haiku 5.5 b3669c767e Fix input monitoring pitch and dropouts when input and session rates differ
The monitor ring fed raw input-device samples to the output callback as if
they were at the session rate. A 16 kHz or 44.1 kHz input played back too
fast (higher pitch) and ran dry between bursts, so it sounded quiet.

InputRing now knows the input rate and converts to the session rate with
linear interpolation in pop_into, allocation-free and non-blocking. The
buffer cap is computed once in new(). Tests cover rate up-conversion,
down-conversion, equal rates and underrun.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-08 22:18:32 +01:00
Gary GunnandClaude Haiku 5.5 9701f8e9a5 Match tempo dialog limits to the engine and test its action
The tempo-change dialog clamped BPM to 1..=999, but the engine accepts
5..=1000. A 1000 BPM tempo was silently changed to 999 on OK, and values
below 5 were rejected after the dialog had closed.

Use the engine's limits, and move the OK action into tempo_change_action
so a test can check it runs a real command with the position. The test
would have caught the original bad command id.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-08 21:42:02 +01:00
Gary GunnandClaude Haiku 5.5 368c3df276 Make the Click option audible: metronome in live playback
Options > Click set a flag but nothing rendered sound, so a click track
was silent. The mix engine now synthesizes a short blip on every beat of
the tempo map (accent on beat 1), using the click.* settings from
Setup > Click/Countoff, and sums it after the master fader.

The metronome is opt-in per engine: only live playback enables it.
Offline renders (bounces, stems, exports) leave it off so the click is
never printed into a file.

Also: midi_to_hz moves from the engine demo into soundcraft-dsp so the
mix and demo share one tuning formula.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-08 21:26:40 +01:00
Gary GunnandClaude Haiku 5.5 c8437c5c61 Fix tempo change from the tempo ruler not saving
Double-clicking the tempo ruler opened a number dialog whose command was
built as "event.tempo@<position>". No such command exists, so OK failed
and nothing changed. The position was also never passed, so a change
would have landed at the session start.

Add a TempoChange dialog that carries the position and runs
event.tempo with bpm and at. Add an engine test that a tempo change at a
position is applied there.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-08 21:24:47 +01:00
ebbicottandClaude Opus 5.5 ed47ec0fbe Instrument picker: choose an instrument track's instrument and open it
There was no way in the app to choose a CLAP, VST3 or Audio Units instrument,
or to open an instrument's editor:
- the insert menus leave instruments out;
- an instrument was only set by track.new;
- the Mix window's INSTRUMENT row looked for instrument inserts rather than the
  track's instrument;
- plugin windows opened only for insert slots.

Changes:
- mix.instrument {track?, plugin} sets an instrument track's instrument, with
  the plugin's default parameters, and is undoable. It refuses effects and
  other track kinds.
- The INST label on an instrument track's header opens an instrument menu: the
  current instrument and its editor, then the built-in, CLAP, VST3 and Audio
  Units instruments, by vendor.
- The Mix window's INSTRUMENT row shows the track's instrument. A click opens a
  hosted instrument's plugin window, and a right-click changes it.
- Plugin windows open for the instrument slot, with only the editor button,
  because the bypass, preset and parameter commands address insert slots.
  They no longer derive a slot letter for the instrument slot.

Closes #22

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 15:40:37 -04:00
ebbicottandClaude Opus 5.5 2a8c60922f Plugin menus: hosted plugins by vendor in scrollable lists; Audio Units insert
The Mix window's insert menu listed each format's plugins as one flat column.
With many installed (53 VST3 and 95 Audio Units effects on a composer's Mac)
it ran past the bottom of the screen and egui menus don't scroll, so the lower
entries couldn't be reached. CLAP, VST3 and Audio Units now open one submenu
per vendor, as Pro Tools does when plug-in menus are organized by manufacturer,
and every list scrolls within the screen.

Choosing an Audio Unit did nothing: the engine's plugin lookup, which
mix.insert uses, covered built-in, CLAP and VST3 plugins only, so "au:" ids were
"unknown plugin" and the UI dropped the error. The lookup now includes Audio
Units (the engine depends on soundcraft-au-host, like the mixer and the UI), and
the menu shows a failed insert in the status bar.

Closes #21

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 15:39:23 -04:00
ebbicottandClaude Opus 5.5 ccd1f995bf Shut plugin hosting down at the end of main, not only from an exit handler
Testing on macOS showed that the exit-handler fallback comes too late for a
plugin that has been used: with HALion Sonic inserted on a track, its bundleExit
segfaults, and both the app (on quit) and soundcraft-cli (after a bounce) exited
with 139. A plain scan was fine. Exit handlers run in reverse order of
registration, so state the plugin set up while in use is presumably torn down
before the host's handler runs.

soundcraft_vst3_host::shutdown() runs the module exits up front, and
soundcraft_engine::shutdown_plugin_hosts() calls it. The app calls that once the
event loop has returned (the player and its plugin instances are gone by then),
and the CLI once its subcommand has. The exit handler stays as the fallback for
other exits, such as test binaries.

The fixture can now set up state lazily the way such plugins do
(VST3_FIXTURE_LATE_STATE), and module_exit_shutdown checks both sides in child
processes: with shutdown() the exit is clean, with only the exit handler the
fixture reports the late teardown. Contract violations now end the process with
status 3 instead of an abort, so that expected failure leaves no crash report.

Refs #16

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 14:28:27 -04:00
MarekSpodBiedry b919713ea7 Fix keyboard shortcuts on Windows and Linux: Ctrl is the Cmd key (#15)
egui reports a held Ctrl as both ctrl and command off macOS, so no Cmd+ shortcut matched and Ctrl+S opened Search (Cmd+Ctrl+S) instead of saving. Off macOS a held Ctrl now stands for the shortcut's Cmd, shortcuts that also need the Mac Control key stay off the keyboard there (Ctrl+X is Cut, not Cmd+Ctrl+X), and the Search chord is macOS only.
2026-10-08 20:06:42 +02:00
ebbicottandClaude Opus 5.5 527f555512 Fix the crash on quit after a VST3 scan: run module exits on the entry thread
vst3-host ran each module's entry (bundleEntry / InitDll / ModuleEntry) when it
loaded a .vst3 and cached the module for the life of the process, but never ran
the matching exit or released the cached factory. At exit() the module's static
destructors then ran on a module that was never shut down. Steinberg's HALion
Sonic segfaults there, so every process that had scanned VST3 plugins crashed on
exit: the app on quit, soundcraft-cli, and the engine, mix and vst3-host unit
tests.

At process exit each module now has its factory released and its exit run,
newest first, on the thread that ran its entry: Native Instruments' Massive X
crashes in bundleExit on any other thread. Loads asked for off the main thread
go to a long-lived module thread, which also runs their exits. Modules with a
live instance or a leaked editor view are left alone, later loads are refused,
and plugin code stays mapped. The exit handler is registered with atexit after
each new module, so it runs ahead of that module's static destructors; it uses
OS thread ids because std::thread::current() panics in exit handlers. A module
whose entry ran but that then fails to load now gets its exit too.

The fixture plugin now checks the module lifecycle and aborts the process when
it is broken. Three harness = false tests cover the exit after use, a live
instance at exit, and a load from a short-lived thread.

Fixes #16

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 13:45:32 -04:00
Brandon ThomasandClaude Opus 5.5 ef47ab59d0 Fix the Windows build of vst3-host; bump version to 0.2.1
The vst3 bindings' enum constants use the C default enum type, which is i32 on
Windows and u32 elsewhere. The bus helpers took u32 and the process-context
flags were assigned to a u32 field directly, so the release build failed on all
three Windows targets. Type the helpers with the bindings' own aliases and cast
the flags once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 08:39:10 -04:00
Gert Pellin 74926df527 Desktop: write log records to standard error and a rotating log file
The desktop app installed no logger, so every log::warn!/log::error! in
the workspace was discarded: the engine's panic report, audio devices
that failed to open or broke, plugins that refused their stored state or
failed to activate, CLAP plugins' own log messages, files that failed to
open. A launch from a desktop menu has no terminal either, so there was
nothing to attach to a bug report.

apps/soundcraft/src/logging.rs (no new dependency):
- standard error plus <settings dir>/logs/soundcraft.log (beside
  ui.json, Autosave/ and Presets/); each launch rotates the previous log
  to soundcraft.1.log and .2.log, so the log of a run that crashed
  survives the next start; the file is capped at 16 MiB
- records logged before the settings directory is known are buffered
  (bounded) and written once the file is attached
- default levels: info for soundcraft*, warn for everything else;
  RUST_LOG replaces them with env_logger-style directives
- never panics: an unusable directory or a failed write leaves standard
  error as the only sink; a poisoned lock is tolerated
- runs with SOUNDCRAFT_NO_PREFS (agents' test runs) log to standard
  error only, so they don't rotate away the user's own logs

Realtime audio: a record takes a lock and does I/O, which the audio
callback must never do, yet code on the audio thread logs (the cpal
error callbacks, the synth's full event queue, a hosted plugin's failed
process, a CLAP plugin calling the host's log, the panic hook). The cpal
callbacks now mark their thread (soundcraft_mix::mark_audio_thread,
re-exported by soundcraft_playback), and the mix engine carries the mark
into the rayon workers that render strips for it. A record from a marked
thread is not written there: the first is kept in a fixed buffer
(try_lock, no allocation, never waits), the rest are counted, and the UI
thread writes them every frame (any other thread before its own next
record).

The logger is installed first in main (before the engine's panic hook)
and the file is opened after argument parsing (--version leaves no
file). The settings directory moves out of prefs_path into config_dir.
The control server's eprintln!s go through the logger (the
SOUNDCRAFT_CONTROL_PORT line on standard output stays). Documented in
README.md (Getting started > Logs) and docs/architecture.md (Audio).
2026-10-08 12:25:49 +02:00
reoniazx b44aaade42 macOS: move application menus to the system menu bar 2026-10-08 14:10:03 +08:00
Brandon ThomasandClaude Opus 5.5 4627084956 About: contributor and model credits compiled in (grab bag + table, self-submitted names) (#8)
* About: contributors compiled in from contributors.json (grab bag + table, sortable, name toggle)

Adds the craftrules standard (standards/contributors.md) to SoundCraft: the About window gets
About · Contributors · Models tabs. contributors/contributors.json is generated by
craftrules/scripts/contributors.py and baked into the binary by crates/ui-egui/build.rs as
static tables. Each contributor line: @username, opt-in display/real name, PRs, commits,
lines +/−/Δ, binary assets +/−, first/last commit. Sortable by every column; alphabetical
ignores case and the leading @. Sort arrows use ⏶/⏷ (egui's icon font) since the system UI
font has no ▲/▼.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Contributors: self-submitted names in contributors/people.toml; AGENTS.md credit-yourself section

build.rs reads contributors/people.toml next to the generated contributors.json and shows a name only
for entries the generator verified as written by that person (craftrules standards/contributors.md).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Contributors: regenerate (verified people.toml entries)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 21:16:58 -04:00
Brandon ThomasandClaude Opus 5.5 cdefc57c91 Video track, Audio Unit hosting, plugin state and editors, Renderer and UI Customization
Video (new standalone crate soundcraft-video):
- Pure-Rust H.264 (Baseline/Main/High), ProRes (all flavours) and Motion JPEG decoding with
  ISO-BMFF demux, adapted from FilmCraft's crates; fuzzed with mutated/truncated movies
- TrackKind::Video with ClipContent::Video referencing Session.videos; file.import_video adds
  the picture track and the movie's audio; relinking on open; video.offset/online/list
- Video and Video Universe windows, thumbnails on the timeline, background decoding

Third-party plugins:
- Plugin state (CLAP state ext, VST3 component + controller state) saved in sessions
- Hosted instances created, state-loaded and dropped on the UI thread, never the audio thread
- Plugin editors: floating CLAP GUIs and VST3 views on macOS (verified with Melodyne)
- New isolated FFI crate soundcraft-au-host: Audio Units on macOS (effects and instruments,
  parameters, latency, MIDI, ClassInfo state), wired into the mixer and plugin browser

UI: Window > Renderer (speaker layout with live levels and object positions), Window > UI
Customization (interface scale, reduce motion), Window > Configurations > Auto-Update.

Fix: saturating sample-index math in clip rendering (hostile stretch values overflowed).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 01:41:05 -04:00
Brandon ThomasandClaude Opus 5.5 c125a79a47 Mix window views: Mic Preamps (input gain), Instruments, Object/Bed
Adds track.object for routing a track as an immersive object or to the bed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 01:24:05 -04:00
Brandon ThomasandClaude Opus 5.5 0751dd31f1 Score export and print, clip group files, Merge Markers, path dialogs for every file command
- File › Export › Sibelius and File › Send To › Sibelius write MusicXML 4.0 (quantized,
  chords, ties across bar lines, meter changes, treble or bass clef per part)
- File › Print Score engraves the MIDI tracks to a printable SVG page; File › Score Setup
  sets title, composer, bars per system and track names
- File › Import › Clip Groups and Export Clip Groups (.scgrp with its audio)
- Edit › Paste Special › Merge Markers: copy carries the markers in the copied range
- The UI opens a path prompt for any command that needs a path or folder

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 01:17:42 -04:00
Brandon ThomasandClaude Opus 5.5 0368d7f541 MIDI Editor: rubber-band selection, Cmd+A, arrow-key transpose and move, header toolbar
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 00:49:48 -04:00
Brandon ThomasandClaude Opus 5.5 18ea131c7e fmt
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 00:48:08 -04:00
Brandon ThomasandClaude Opus 5.5 c543c7a781 Search: a command palette over every command (Window › Search, Cmd+Ctrl+S)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 00:44:35 -04:00
Brandon ThomasandClaude Opus 5.5 856aae6871 Keyboard focus command and the a-z Commands Focus toolbar toggle
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 00:42:00 -04:00
Brandon ThomasandClaude Opus 5.5 cc86842abe Surround mixing, VST3 hosting, and hardening against hostile inputs
Surround:
- main and bus formats up to 9.1.6 and Ambisonics; pairwise constant-power
  surround panner (divergence, centre, LFE, height) per track and send;
  ITU fold-down; multichannel bounce with correct WAV channel masks;
  multichannel device output; surround panner and multichannel meters in the
  Mix window; setup.main_format, mix.surround_pan, mix.send_surround_pan

VST3:
- soundcraft-vst3-host: isolated unsafe crate (vst3 bindings, MIT), scans
  standard folders, hosts components/processors/controllers, params,
  latency, notes; VST3 menu; engine.vst3_plugins; e2e tests with a fixture

Hardening:
- positions from parameters clamped; offline renders capped and bounded to
  track material; loop/transport limits; hostile-parameter property test

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 00:39:59 -04:00
Brandon ThomasandClaude Opus 5.5 8269ca77f6 Property test: every command survives hostile parameters
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 00:15:26 -04:00