58 lines
1.6 KiB
Lua
58 lines
1.6 KiB
Lua
--[[
|
|||
|
|
MIDI Grid: preview daemon.
|
||
|
|
|
||
|
|
Runs quietly in the background and owns every preview note-on/note-off.
|
||
|
|
The action scripts never defer, so they always exit instantly and Reaper
|
||
|
|
never shows its "already running" prompt no matter how fast keys repeat.
|
||
|
|
|
||
|
|
Started automatically by the action scripts; you never need to run it.
|
||
|
|
]]
|
||
|
|
local dir = ({ reaper.get_action_context() })[2]:match("@?(.*[\\/])")
|
||
|
|
local G = dofile(dir .. "midigrid_lib.lua")
|
||
|
|
|
||
|
|
-- Refuse to start a second copy.
|
||
|
|
local hb = tonumber(G.getTemp("hb", "0")) or 0
|
||
|
|
if os.time() - hb <= 3 then return end
|
||
|
|
|
||
|
|
local sounding = {}
|
||
|
|
local releaseAt = 0
|
||
|
|
local lastSeq = tonumber(G.getTemp("seq", "0")) or 0
|
||
|
|
|
||
|
|
local function allOff()
|
||
|
|
for _, p in ipairs(sounding) do
|
||
|
|
reaper.StuffMIDIMessage(0, 0x80, p, 0)
|
||
|
|
end
|
||
|
|
sounding = {}
|
||
|
|
end
|
||
|
|
|
||
|
|
local function loop()
|
||
|
|
G.setTemp("hb", os.time())
|
||
|
|
|
||
|
|
local seq = tonumber(G.getTemp("seq", "0")) or 0
|
||
|
|
if seq ~= lastSeq then
|
||
|
|
lastSeq = seq
|
||
|
|
-- A new request cuts whatever is still sounding, so fast arrowing
|
||
|
|
-- retriggers cleanly instead of piling notes up.
|
||
|
|
allOff()
|
||
|
|
local vel = math.floor(G.getNum("vel", 96))
|
||
|
|
for s in tostring(G.getTemp("pitches", "")):gmatch("%d+") do
|
||
|
|
local p = tonumber(s)
|
||
|
|
if p and p >= 0 and p <= 127 then
|
||
|
|
sounding[#sounding + 1] = p
|
||
|
|
reaper.StuffMIDIMessage(0, 0x90, p, vel)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
releaseAt = reaper.time_precise() + (tonumber(G.getTemp("dur", "0.4")) or 0.4)
|
||
|
|
end
|
||
|
|
|
||
|
|
if #sounding > 0 and reaper.time_precise() >= releaseAt then
|
||
|
|
allOff()
|
||
|
|
end
|
||
|
|
|
||
|
|
reaper.defer(loop)
|
||
|
|
end
|
||
|
|
|
||
|
|
-- Never leave a note hanging if the daemon is terminated or Reaper quits.
|
||
|
|
reaper.atexit(allOff)
|
||
|
|
loop()
|