Files
midigrid/MidiGrid_SetScale.lua
Talon 8fd6f947ed Accessible grid-based MIDI entry mode for REAPER
Keyboard- and speech-driven step entry for the MIDI editor, built for use
with OSARA. Arrows walk grid cells and scale degrees, Enter toggles notes,
and every position is spoken and auditioned.

Uses REAPER's own edit cursor and active_note_row rather than private cursor
state, so grid mode and OSARA editing stay in sync. Grid size comes from
MIDI_GetGrid(), so existing grid keybindings drive it. When grid mode is off,
every bound key forwards to its previous action.

Preview timing lives in a background daemon so the action scripts can exit
immediately -- a script still alive on the next keypress triggers REAPER's
"already running" prompt and breaks key repeat.
2026-08-14 18:13:45 +02:00

36 lines
1.2 KiB
Lua

-- MIDI Grid: choose the root and scale that up/down navigate by
local dir = ({ reaper.get_action_context() })[2]:match("@?(.*[\\/])")
local G = dofile(dir .. "midigrid_lib.lua")
local names = {}
for i, s in ipairs(G.SCALES) do names[#names + 1] = i .. "=" .. s.name end
local ok, csv = reaper.GetUserInputs(
"MIDI Grid scale", 2,
"Root note (C, F#, Bb...),Scale number (" .. table.concat(names, " ") .. "),extrawidth=320",
G.noteNamePc(G.scaleRoot()) .. "," .. G.scaleIndex())
if not ok then return end
local rootStr, scaleStr = csv:match("^([^,]*),(.*)$")
-- Parse a root spelled with either sharps or flats.
local BASE = { c = 0, d = 2, e = 4, f = 5, g = 7, a = 9, b = 11 }
local letter, accid = tostring(rootStr):match("^%s*(%a)([#b]?)")
if not letter or not BASE[letter:lower()] then
G.say("Unrecognised root note")
return
end
local pc = BASE[letter:lower()]
if accid == "#" then pc = pc + 1 elseif accid == "b" then pc = pc - 1 end
pc = pc % 12
local si = math.floor(tonumber(scaleStr) or 0)
if si < 1 or si > #G.SCALES then
G.say("Scale number must be 1 to " .. #G.SCALES)
return
end
G.set("root", pc)
G.set("scale", si)
G.say("Scale set to " .. G.scaleName())