[EDIT: Fixed in v5.23]
I have encountered a strange problem:
There appears to be a discoordination between:
* ReaScript functions that de/select notes, such as MIDI_SetNote and MIDI_SelectAll, and
* Notation actions that are called through MIDIEditor_OnCommand, such as "Beam selected notes together" or "Nudge length display offset".
If the notation action is called too soon after the ReaScript function, the action is sometimes skipped or applied to the wrong note. My impression is that scripts are executed faster than the MIDI editor can update after a ReaScript function.
If a pause step is inserted in-between, using for example "reaper.GetUserInputs", the notation actions are applied correctly.
As an example, here is a script that I am working on. It is intended to change the displayed length of notes in the notation editor to a user-specified length. (EDIT: This is an old version of the script - it has since been rewritten to write directly to notation text events, which works much better than trying to use OnCommand to call actions.)
Code:
editor = reaper.MIDIEditor_GetActive()
if editor ~= nil then
take = reaper.MIDIEditor_GetTake(editor)
if reaper.ValidatePtr2(0, take, "MediaItem_Take*") then
-- Get user-specified displayed note length
repeat
retval, input = reaper.GetUserInputs("Set displayed note length",
1,
"Note length (4=quarter note)",
"8")
input = tonumber(input)
until retval == false or (type(input) == "number" and input>0)
if retval == false then
return(0)
else
reaper.Undo_BeginBlock2(0)
reaper.MIDI_Sort(take)
-- It seems that the "Notation: Nudge note display length" actions work in
-- steps of 1/64 notes.
-- Weird, sometimes REAPER's PPQ is not 960. So first get PPQ of take.
local QNstart = reaper.MIDI_GetProjQNFromPPQPos(take, 0)
PPQ = reaper.MIDI_GetPPQPosFromProjQN(take, QNstart + 1) - QNstart
PP64 = PPQ/16
userLength = (4.0/input)*PPQ -- Desired length of displayed notes in ticks
reaper.MIDIEditor_OnCommand(editor, 41759) -- Notation: Clear display offset
-- Store indices of selected notes so that they can be reselected after deselection
tableSelIndices = {}
i = -1
repeat
i = reaper.MIDI_EnumSelNotes(take, i)
if i >= 0 then table.insert(tableSelIndices, i) end
until i == -1
-- The notes will now all be deselected, and then REselected one by one
-- so that the notation actions can be applied to each note separately.
reaper.MIDI_SelectAll(take, false)
reaper.GetUserInputs("Pause step...",1,"","")
for _, index in ipairs(tableSelIndices) do
local noteOK, _, _, startppq, endppq, _, _, _ = reaper.MIDI_GetNote(take, index)
if noteOK then
local noteLength = endppq-startppq
reaper.MIDI_SetNote(take, index, true, nil, nil, nil, nil, nil, nil, false)
reaper.GetUserInputs("Pause step...",1,"","")
if noteLength < userLength then
-- In REAPER v5.22, can only increase or decrease display length by up to eight 64th notes
local numSteps = math.min(8, math.floor(0.5 + (userLength-noteLength)/PP64)) -- PP64 = length of nudge = 64th note)
for i = 1, numSteps do
reaper.MIDIEditor_OnCommand(editor, 41763) -- Notation: Nudge length display offset RIGHT
end
elseif noteLength > userLength then
local numSteps = math.min(8, math.floor(0.5 + (noteLength-userLength)/PP64)) -- PP64 = length of nudge = 64th note
for i = 1, numSteps do
reaper.MIDIEditor_OnCommand(editor, 41762) -- Notation: Nudge length display offset LEFT
end
end
end
-- Deselect note again, so that next note can be reselected
reaper.MIDI_SetNote(take, index, false, nil, nil, nil, nil, nil, nil, false)
reaper.GetUserInputs("Pause step...",1,"","")
end
-- Reselect all the notes that were originally selected
for _, index in ipairs(tableSelIndices) do
reaper.MIDI_SetNote(take, index, true, nil, nil, nil, nil, nil, nil, false)
end
reaper.Undo_EndBlock2(0, "Notation: Set displayed note length", -1)
end
end
end
I have inserted several pause steps using "reaper.GetUserInputs("Pause step...",1,"","")".
By removing these pause steps one at a time and running the script with several notes selected, one can see the different effects.
So... Has anyone else encountered this strange behavior? Is this a bug that I have discovered, or am I overlooking my own coding error?