Commit Graph
484 Commits
Author SHA1 Message Date
SlyLaM e66a5e7c67 feat(ui): add complete Preferences window and live settings (#819)
* feat(ui): add complete Preferences window shell

* fix(ui): refine Preferences layout and live settings

* fix(ui): remove Preferences page scrolling

* fix(ui): keep Preferences window size constant

* feat(ui): add Preferences to the SoundCraft menu

* fix(ui): address Preferences review feedback

* docs(ui): document Preferences behavior

* fix(macOS): add Preferences to the application menu

* fix(ui): make Preferences menu behavior modal

* fix(ui): preserve live Preferences updates

* fix(ui): address latest Preferences review findings

* fix(ui): preserve Preferences button actions
2026-11-06 11:34:43 +01:00
FredApps 87f46cf23b Merge pull request #782 from SlyLaM/fix/transient-record-monitor-states
fix(engine): keep live input states transient
2026-11-06 07:26:56 +01:00
Sly LaMenace d393730b02 Merge upstream/main and adapt transient live input states 2026-11-05 07:51:42 +00:00
Zinadin ZidanandClaude Opus 5.5 4240ffda42 fix(engine): cap sessions at 256 MiB and parse them without a Value tree (#892)
A session was parsed into a serde_json Value and then converted, which takes
many times the file's size in memory, and nothing limited how big a session
file could be.

Session::from_json now reads only format_version first (every other field is
skipped) and then parses the text straight into the session. A missing
format_version and a newer version give the errors they gave before. Other
type errors now end with the place they were found ("at line L column C").
A field of the document given twice in one object, which used to load with
the last value winning, is now refused with "duplicate field `key`" (a
twice-given format_version too, not "missing format_version"): keeping the
old leniency would need the tree this change removes, and no writer repeats
a field. Keys of maps (plugin params, edit values and the like) and unknown
keys still keep the last value given, as before.

A track's height was read through an untagged enum, which buffers the whole
value before it looks at it; a huge array there took about 27 times its size.
It now has its own reader that takes exactly the forms that loaded before
("Micro" to "Extreme", also as {"Micro": null}, {"Custom": n}, {"Fit": n},
and the old bare "Fit" or {"Fit": null}) and refuses anything else at its
first token.

Opening a session (a .scraft file, the browser's bytes, the session in a
bundle) and Import Session Data refuse one over 256 MiB by its size, before
reading it. Save, Save Copy In, Save As Template, autosave and the browser's
bundle refuse to write a session over that size, so SoundCraft never saves
one it then won't open. Save and autosave check before they write any audio,
so a refused save leaves nothing behind and a refused autosave keeps the last
one and its audio copies as they were; the refusal is reported like any
other autosave failure. Save checks against the longest name each new audio
file can get, so it may refuse a session within a few bytes per new file of
the limit. Crash recovery reads only the name of a leftover autosave, and
none from one over the cap. Audio files are read without that cap, as
before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 12:47:13 +06:00
Sly LaMenace 92e6973640 Merge upstream/main and fix frame-origin grid snapping 2026-11-04 22:54:15 +00:00
Dylan M. Taylor fa34e0c182 fix(engine): dedupe clip ids, clamp score bars per system, share autosave copies (#1333) 2026-11-03 23:02:33 -05:00
Brandon Thomas 6492b5f27e Merge pull request #1286 from Silvertree2010/fix/1260-zoom-in-t-doesn-t-use-the-edit-c
Keep the edit cursor as the zoom reference when it is off-screen
2026-11-03 10:04:56 -05:00
Brandon Thomas c15682a088 Merge pull request #1302 from JonRC/fix/1301-audiosuite-hosted-ids
audiosuite.process: say it takes built-in plugin ids, and why hosted ones are refused
2026-11-03 10:04:28 -05:00
Brandon Thomas 0d253b6d8c Merge pull request #1300 from JonRC/fix/1296-bounce-bext
Stamp WAV bounces with their timecode position (BWF bext TimeReference)
2026-11-03 10:04:22 -05:00
Brandon ThomasandClaude Opus 5.5 f86b077cdf Test that an off-screen edit cursor lands on its fixed column
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 09:53:19 -05:00
Dylan M. Taylor aa250cc1d7 Clip gain to volume: index envelope lookups (#1309)
Converting clip gain to volume (and baking volume into clip gain)
evaluated the clip's gain envelope by walking it from the start for
every breakpoint being converted, so a large envelope in an opened or
imported session cost envelope points squared and blocked the engine.

Build a running-maximum index over the envelope once per clip and
binary-search it. It returns exactly what the walk returned, including
for envelopes stored out of order.
2026-11-03 07:44:31 -05:00
Sly LaMenace dbcbcbac00 Merge upstream/main into feat/grid-nudge-time-scales 2026-11-03 11:52:00 +00:00
Dylan M. Taylor da02c19fcc Bundles: refuse entries that share their data (#1303)
Bundle entries are stored, so the files read out of one can only
outgrow the bundle when several entries point at the same bytes. A
small bundle naming one payload thousands of times was copied out once
per name, up to the 1 GiB total limit, in the browser. Check the
archive for overlapping entry data before reading any entry.
2026-11-02 23:33:19 -05:00
JonRC 1403bbc4d3 audiosuite.process: say it takes built-in plugin ids
Its help said `<plugin id>`, but it only runs built-in plugins, and a
hosted id (clap:, vst3:, au:) failed as "unknown process". The help now
says built-in plugin id, and a hosted id gets an error saying AudioSuite
runs built-in plugins only.

Fixes #1301.
2026-11-02 23:42:08 -03:00
JonRC b0793ca875 Stamp WAV bounces with their timecode position (BWF bext)
Bounces passed no bwf to the encoder, so mix and stem WAVs had no bext
chunk and post tools placed them at zero. Bounce::new now stamps them
with TimeReference = the session's timecode start plus the bounce start,
in samples since midnight, as other DAWs do. A caller's own bwf wins;
AIFF and FLAC have no bext and are unchanged.

Fixes #1296.
2026-11-02 23:36:15 -03:00
Sly LaMenace 087978a4a0 fix(edit): preserve overlaps in stationary nudge and quantize 2026-11-02 23:42:44 +00:00
Sly LaMenace 9b5554e312 Merge upstream/main into feat/grid-nudge-time-scales 2026-11-02 23:42:44 +00:00
FredApps 1dbc185e01 Merge pull request #559 from SlyLaM/fix/new-tracks-keyboard-ux
feat(ui): improve the New Tracks creation workflow
2026-11-02 18:23:48 +01:00
NetterSilverandClaude Haiku 5.5 4b06407dae Keep the edit cursor as the zoom reference when it is off-screen
Fixes #1260

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-02 15:57:40 +01:00
Brandon Thomas 98cda6ecaf Merge pull request #1032 from Silvertree2010/fix/h2086-midi-export-writes-notes-that-a
Export only the MIDI notes a trimmed clip still plays
2026-11-01 23:06:40 -05:00
Brandon ThomasandClaude Opus 5.5 5e8898976e Test a grid of 1/16, 1/32 and 1/64 bars in a row
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 23:06:02 -05:00
Brandon ThomasandClaude Opus 5.5 c426b889bb Test MIDI export of a clip trimmed at both ends
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 23:05:08 -05:00
Sly LaMenace e1f10ccdc8 fix(edit): preserve cross-track grid snapping 2026-11-01 23:03:35 +00:00
Sly LaMenace 627bbbf9cc fix(edit): keep zero-distance moves lossless 2026-11-01 22:49:21 +00:00
Sly LaMenace 84baa5debc fix(edit): preserve drag origins while snapping 2026-11-01 22:39:15 +00:00
Sly LaMenace 71f899baac fix(edit): align grid snapping across time scales 2026-11-01 14:47:41 +00:00
Sly LaMenace d2298ff974 Merge remote-tracking branch 'upstream/main' into fix/new-tracks-keyboard-ux
# Conflicts:
#	crates/ui-egui/src/dialogs.rs
#	crates/ui-egui/src/lib.rs
2026-11-01 11:32:53 +00:00
Sly LaMenace 381832447c Merge remote-tracking branch 'upstream/main' into feat/grid-nudge-time-scales 2026-11-01 00:09:45 +00:00
NetterSilverandClaude Opus 5.5 b32065a109 Keep score export notes when bars are shorter than a sixteenth
Found while testing crates/engine/src/score.rs:~150 (measure_grid, `if ub <= ua { break; }`), used by layout()

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-01 00:34:16 +01:00
NetterSilverandClaude Sonnet 5.5 97e2603683 fix: release a held sustain at the end of a trimmed MIDI clip on export
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-31 16:48:51 +00:00
Brandon Thomas 54d36c2fcc Merge pull request #1075 from Silvertree2010/fix/1069-transport-play-from-is-ignored-i
Play transport.play {from} at the requested position, not the selection
2026-10-31 10:54:18 -04:00
Brandon Thomas 382965153a Merge pull request #1214 from Silvertree2010/fix/h4142-range-param-ignores-end-length-w
Default range start to the selection start in range_param
2026-10-31 10:54:15 -04:00
Brandon Thomas e60a559596 Merge pull request #1212 from kk376/fix/890-smf-tempo-track-floods
fix(engine): bound MIDI import tempo and track floods (#890)
2026-10-31 10:54:02 -04:00
Brandon Thomas a4e4a44bab Merge pull request #1126 from SusieeTheLinuxUser/fix/clamp-clip-fx-gain-send-level
Mix: clamp clip-FX gain and send-level automation (fixes #884)
2026-10-31 10:53:27 -04:00
Brandon Thomas 99895de2c7 Merge pull request #1101 from dotCooCoo/feat/zoom-toggle-cancel
Zoom Toggle: Alt+Shift+E and Alt-click cancel it and keep the current view
2026-10-31 10:53:23 -04:00
Brandon ThomasandClaude Opus 5.5 13b2488e95 Set an empty-range constant tempo at the range start
With start now optional, {end} alone resolves the start from the
selection; the empty-range fallback still went through event.tempo,
which put the tempo at tick 0. CodeRabbit flagged this.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 10:42:37 -04:00
NetterSilverandClaude Haiku 5.5 331b1820db Default range start to the selection start in range_param
Found while testing crates/engine/src/cmd.rs:326-336 (range_param), used by crates/engine/src/cmd/event.rs:148 (insert_time) and :172 (cut_time)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-31 02:29:44 +00:00
Kushagra Kumar 966e253873 fix(engine): skip duplicate MIDI tempos only when session tempo matches
Collapse consecutive duplicate SMF tempos only if the session tempo at
the event tick already matches, so existing session tempo markers are
overridden as expected.
2026-10-31 05:50:50 +05:30
Kushagra Kumar f7b0805de6 fix(engine): bound MIDI import tempo and track floods (#890)
import_midi_bytes capped meter changes at MAX_MIDI_METERS (10,000), but
left imported tempo events and synth tracks unbounded. Dense MIDI files
inserted unlimited tempo markers into the session tempo map, degrading
linear tick-to-sample conversions across playback and audio processing,
and instantiated up to 4,096 synth tracks for controller-only tracks.

Add MAX_MIDI_TEMPOS (10,000) and MAX_MIDI_TRACKS (512) caps checked
before session mutation, and collapse consecutive equal tempo events.
2026-10-31 05:35:09 +05:30
ydking0911 5a1324b8bc Clear: lift clips removed by id in Shuffle so crossfade partners don't overlap 2026-10-30 16:13:42 +09:00
SusieeTheFemboyandClaude Opus 5.5 552607cbee Merge main into fix/clamp-clip-fx-gain-send-level
main split crates/mix/src/lib.rs: the clip-FX gain clamp now lives in
clips.rs and the send-level automation clamp in automation.rs (via
crate::SEND_LEVEL_MAX_DB). Adds tests for the send-automation clamp and
the load-time sanitize clamp (#884).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 06:40:00 +01:00
ydking0911 9f5f312051 Clear: close the gaps of clips removed by id in Shuffle 2026-10-30 14:30:58 +09:00
NetterSilverandClaude Haiku 5.5 440999a51f Play transport.play {from} at the requested position, not the selection
Fixes #1069

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-30 05:29:09 +01:00
NetterSilverandClaude Haiku 5.5 4740e8d4c4 Export only the MIDI notes a trimmed clip still plays
Found while testing crates/engine/src/io.rs:350-362 (export_midi)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-30 05:24:39 +01:00
Brandon Thomas d2079bf09d Merge pull request #1194 from storytold/m/land-995
Bound the command journal (#995, rebased)
2026-10-29 22:04:22 -04:00
Brandon Thomas 5447c94cb6 Merge pull request #1193 from storytold/m/land-993
Bound Print Score and MusicXML output size (#993, rebased)
2026-10-29 22:04:18 -04:00
Brandon Thomas b4412929a7 Merge pull request #1109 from Silvertree2010/fix/h2757-audiosuite-processes-that-shorte
Clamp clip fades after AudioSuite processes that shorten a clip
2026-10-29 22:03:21 -04:00
Brandon Thomas ca27f0f8b4 Merge pull request #1057 from Silvertree2010/fix/h2373-trim-tool-lets-a-stretched-clip
Scale trim_clip file bounds by clip stretch
2026-10-29 22:03:18 -04:00
Brandon Thomas 5075da2f3e Merge remote-tracking branch 'origin/main' into land-993
# Conflicts:
#	crates/engine/src/score.rs
2026-10-29 21:59:42 -04:00
Brandon Thomas a62d955a39 Merge remote-tracking branch 'origin/main' into land-995 2026-10-29 21:59:42 -04:00