Play preview through the edited track's instrument

StuffMIDIMessage feeds the virtual MIDI keyboard, which only reaches
tracks that are armed and monitoring -- normally not the track whose
item you are editing. Opening an item in grid mode therefore sounded
every preview through whatever instrument happened to be armed, which
is confusing when the notes you are writing come back in the wrong
voice.

Grid mode now borrows the record routing: the edited take's track is
armed and monitoring with all MIDI inputs (anything narrower can
exclude the virtual keyboard), and every other armed track is stood
down so it cannot answer as well. The prior arm, monitor and input of
each track touched is saved by GUID in transient ExtState.

routePreview re-points lazily, so moving the editor to an item on
another track costs nothing until the target actually changes. The
daemon hands the routing back when grid mode goes off, when the editor
closes, or on exit -- the same way it already restores the loop and
repeat state the loop-bar action borrows -- so the project is put back
even if grid mode is never toggled off.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-24 00:55:25 +02:00
co-authored by Claude Opus 5
parent 2fe9fa75b2
commit 0acb7d58f6
7 changed files with 180 additions and 8 deletions
+18 -3
View File
@@ -374,6 +374,19 @@ daemon releases everything on `atexit`, so notes cannot hang.
Preview requests use **non-persisted** `ExtState` — persisting them would write
to `reaper.ini` on every keypress.
**Preview routing.** Preview notes go out through `StuffMIDIMessage`, i.e.
REAPER's virtual MIDI keyboard, which is only heard by tracks that are armed
and monitoring — normally not the track you are editing, so notes would sound
through whatever unrelated instrument happened to be armed. Grid mode therefore
borrows the record routing: on entering grid mode, and again whenever the
editor moves to an item on a different track, the edited take's track is armed
and monitoring with MIDI input, and every other armed track is stood down so it
cannot answer as well. The previous arm, monitor and input setting of every
track touched is remembered and handed straight back when grid mode is switched
off, when the MIDI editor closes, or when REAPER exits — the daemon does the
restoring, in the same way it restores the loop and repeat state the loop-bar
action borrows.
## Tunables
In `ExtState` section `midigrid`:
@@ -400,9 +413,11 @@ itself.
## Limitations
- Preview uses `StuffMIDIMessage`, which plays through the track's instrument
via the virtual-keyboard input, so the track must be armed / monitored —
exactly as with REAPER's own MIDI preview.
- While grid mode is on, the edited track is held record-armed and monitoring
with MIDI input so that preview can reach its instrument (see *Preview
routing* above), and any other armed track is stood down. Both are handed
back when grid mode ends, but a REAPER crash mid-session would lose that
arm state.
- The grid aligns to the project timeline (bar lines), not the item start. For
an item starting off-grid, the first cell will be partial.
- Note octave naming follows the `midioctoffs` preference; with the default,