Go Back   Cockos Incorporated Forums > REAPER Forums > REAPER Feature Requests

Reply
 
Thread Tools Display Modes
Old 06-18-2017, 01:59 PM   #1
juliansader
Human being with feelings
 
Join Date: Jul 2009
Posts: 3,714
Default Reascript: new function MIDIEditor_Update for faster MIDI scripts

REAPER's API includes functions to either prevent the arrange view from updating while a script is running (PreventUIRefresh), or to force the arrange view to update (UpdateArrange and UpdateTimeline).

The MIDI editor does not currently enjoy similar functionality as UpdateArrange and UpdateTimeline:

By default, REAPER does not update the MIDI editor UI while scripts are running -- which is very good, since it makes execution of scripts much faster.

However, it would be useful in some cases to be able to force a MIDI editor to update its UI even before a script ends -- *without* updating the arrange view too. In particular, MIDI editing scripts (that track mouse movements and update the MIDI editor in realtime) currently have to use deferred loops instead of a plain while-loops, since the MIDI editor cannot be updated inside such while-loops.

I expect that while-loops would execute much faster than deferred loops, since while-loops can skip updating of the arrange view and all the other background stuff. (Note that REAPER's native MIDI editing mouse modifier actions do not update the arrange window while the action is running, either.)

I therefore propose a new API function:
Code:
Lua: reaper.MIDIEditor_Update(HWND midieditor)

Redraw the MIDI editor, without updating the arrange view and ruler

Last edited by juliansader; 06-18-2017 at 02:25 PM.
juliansader is offline   Reply With Quote
Old 06-23-2017, 11:22 AM   #2
Ulf3000
Human being with feelings
 
Join Date: May 2016
Posts: 369
Default

as a little hack you could do

reaper.MIDIEditor_LastFocused_OnCommand(40501,0) --Invert Selection x2 ... little hack to activate the new notes ...
reaper.MIDIEditor_LastFocused_OnCommand(40501,0) --... reaper.MIDI_Sort(MidiTake) is messing up the notes

yes i just used that yesterday as reaper.MIDI_Sort(MidiTake) messes up overlapping notes
it also seems to update the arrange view and midiplayback (updates the midi editor)

every selection action does that .. i haven´t tried any more .. maybe theres an action with even less impact to trigger the update
Ulf3000 is offline   Reply With Quote
Old 06-23-2017, 01:21 PM   #3
juliansader
Human being with feelings
 
Join Date: Jul 2009
Posts: 3,714
Default

Thanks for the reply!

Unfortunately (if I am not mistaken?), the OnCommand actions are only visibly drawn in the MIDI editor once a script exits, or starts a new defer cycle. What I would like to achieve, is to force the MIDI editor to immediately redraw itself on the screen while a script is still running -- without having to exit the script, and without redrawing the arrange view (and without doing anything else that is time-consuming). Hopefully this will speed up deferred scripts.
juliansader is offline   Reply With Quote
Old 10-10-2017, 01:18 PM   #4
juliansader
Human being with feelings
 
Join Date: Jul 2009
Posts: 3,714
Default

BTW, this new function is intended as a possible alternative to the FR Reascript: Restore original behavior of PreventUIRefresh to make actions faster, both of which aim to make MIDI editing scripts run faster.
juliansader is offline   Reply With Quote
Old 12-15-2017, 08:58 PM   #5
_Stevie_
Human being with feelings
 
_Stevie_'s Avatar
 
Join Date: Oct 2017
Location: Black Forest
Posts: 5,054
Default

I just stumbled across the same problem. I have a script that will add +12 semitones to a MIDI take. The script can be run in the arrangement. However, the item does not update itself and the added notes are not visible.
Adding invert selection only works, if the MIDI Editor is open.
Is there any other solution to update the take in the arrangement?
_Stevie_ is offline   Reply With Quote
Old 12-16-2017, 02:50 AM   #6
juliansader
Human being with feelings
 
Join Date: Jul 2009
Posts: 3,714
Default

Quote:
Originally Posted by _Stevie_ View Post
I just stumbled across the same problem. I have a script that will add +12 semitones to a MIDI take. The script can be run in the arrangement. However, the item does not update itself and the added notes are not visible.
Adding invert selection only works, if the MIDI Editor is open.
Is there any other solution to update the take in the arrangement?
Some API functions that change an item's appearance don't automatically trigger a redraw of the item. So if a script is run in the arrange view, it is often safer to include one of the "Update" functions at the end of the script to ensure that the graphics are updated:

UpdateItemInProject() updates only one item (probably the fastest option)
UpdateArrange() updates all items but not the ruler.
UpdateTimeLine() updates everything.
juliansader is offline   Reply With Quote
Old 12-16-2017, 05:08 AM   #7
_Stevie_
Human being with feelings
 
_Stevie_'s Avatar
 
Join Date: Oct 2017
Location: Black Forest
Posts: 5,054
Default

I already tried all 3 of these and it doesn't work :/
The only thing that seems to work is a selection of the notes in the midi editor, then a redraw happens.
_Stevie_ is offline   Reply With Quote
Old 12-16-2017, 05:39 AM   #8
juliansader
Human being with feelings
 
Join Date: Jul 2009
Posts: 3,714
Default

Could you post the script here?
juliansader is offline   Reply With Quote
Old 12-16-2017, 05:41 AM   #9
_Stevie_
Human being with feelings
 
_Stevie_'s Avatar
 
Join Date: Oct 2017
Location: Black Forest
Posts: 5,054
Default

Sure!

Code:
interval = 12 -- semitones

function add_notes(interval)
	for i = 0, reaper.CountSelectedMediaItems(0)-1 do -- loop through all selected items
		item = reaper.GetSelectedMediaItem(0, i)
		for t = 0, reaper.CountTakes(item)-1 do -- Loop through all takes within each selected item
			take = reaper.GetTake(item, t)
			if reaper.TakeIsMIDI(take) then -- make sure, that take is MIDI
				notes = reaper.MIDI_CountEvts(take) -- count notes and save amount to "notes"
				for n = 0, notes - 1 do -- loop thru all notes
					_, selectedOut, _, _, _, _, _, _ = reaper.MIDI_GetNote(take, n) -- get selection status
					if selectedOut == true then -- if at least note is selected
						notes_selected = true -- set notes_selected to true
						break -- break the for loop, because at least one selected note was found
					end
				end
				for n = 0, notes - 1 do -- loop thru all notes
					_, selectedOut, _, startppqposOut, endppqposOut, chanOut, pitchOut, velOut = reaper.MIDI_GetNote(take, n) -- get selection status and pitch
					if notes_selected == true then -- if there is a note selection
						if selectedOut == true then -- filter out selected notes to add notes
							reaper.MIDI_InsertNote(take, false, false, startppqposOut, endppqposOut, chanOut, pitchOut+interval, velOut, true) -- add notes by interval to selected notes
						end
					else
						reaper.MIDI_InsertNote(take, false, false, startppqposOut, endppqposOut, chanOut, pitchOut+interval, velOut, true) -- add notes by interval to all notes
					end
				end
			end
		end
	end
end


add_notes(interval) -- call function
reaper.Undo_OnStateChange2(proj, "Add notes +12")
_Stevie_ is offline   Reply With Quote
Old 12-16-2017, 06:07 AM   #10
juliansader
Human being with feelings
 
Join Date: Jul 2009
Posts: 3,714
Default

Ah, the problem is that you need to run reaper.MIDI_Sort(take) for each take, after inserting all the notes into the take.

If you use the option noSort=true when inserting notes with MIDI_InsertNote, the note data is temporarily placed in incorrect order at the end of the take, *after* the end-of-take signal.

* You can also use MIDI_EnumSelNotes to find selected notes.
juliansader is offline   Reply With Quote
Old 12-16-2017, 06:10 AM   #11
mpl
Human being with feelings
 
mpl's Avatar
 
Join Date: Oct 2013
Location: Moscow, Russia
Posts: 3,960
Default

Quote:
*without* updating the arrange view too
How do you expect MIDI items view will be refreshed without updating arrange (or at least updating local item)?

Isn`t GetProjectStateChangeCount solve often refresh issue?
mpl is offline   Reply With Quote
Old 12-16-2017, 06:54 AM   #12
_Stevie_
Human being with feelings
 
_Stevie_'s Avatar
 
Join Date: Oct 2017
Location: Black Forest
Posts: 5,054
Default

Quote:
Originally Posted by juliansader View Post
Ah, the problem is that you need to run reaper.MIDI_Sort(take) for each take, after inserting all the notes into the take.

If you use the option noSort=true when inserting notes with MIDI_InsertNote, the note data is temporarily placed in incorrect order at the end of the take, *after* the end-of-take signal.

* You can also use MIDI_EnumSelNotes to find selected notes.
Julian, you are my hero! I just fixed it *joy*. This is so awesome
Will take a look into MIDI_EnumSelNotes, it seems I could delete some unnecessary lines of code
_Stevie_ is offline   Reply With Quote
Old 05-27-2018, 02:54 AM   #13
juliansader
Human being with feelings
 
Join Date: Jul 2009
Posts: 3,714
Default

Given that one of the MIDI editor slowdown bugs received attention in v5.90, I hope that this is a good time to bump this thread.

Quote:
Originally Posted by Edgemeal View Post
v5.90 - May 24 2018
+ MIDI editor: avoid double-drawing many updates
+ MIDI editor: faster updating when using hand scrolling
Other threads related to deferred scripts and MIDI editor sluggishness:
* Bug report: MIDI editor: Recent versions get unnecessarily bogged down if multiple takes visible
* Feature request: Reascript: Restore original behavior of PreventUIRefresh to make deferred scripts run faster
juliansader is offline   Reply With Quote
Old 05-27-2018, 05:54 AM   #14
_Stevie_
Human being with feelings
 
_Stevie_'s Avatar
 
Join Date: Oct 2017
Location: Black Forest
Posts: 5,054
Default

Absolutely agreed, would be awesome!
__________________
My Reascripts forum thread | My Reascripts on GitHub
If you like or use my scripts, please support the Ukraine: Ukraine Crisis Relief Fund | DirectRelief | Save The Children | Razom
_Stevie_ is offline   Reply With Quote
Old 07-03-2018, 06:27 AM   #15
juliansader
Human being with feelings
 
Join Date: Jul 2009
Posts: 3,714
Default

A function MIDIEditor_Update that can be used in a "while" loop (thereby avoiding "defer" loops), will have another advantage: scripts would be able to change the mouse cursor.

If a script tries to change the mouse cursor during a defer loop, REAPER restores the mouse cursor during each cycle, resulting in a cursor that flashes between two images.

If a script uses a while loop, REAPER doesn't change the custom cursor until the script is terminated.
juliansader is offline   Reply With Quote
Old 04-14-2019, 05:55 PM   #16
_Stevie_
Human being with feelings
 
_Stevie_'s Avatar
 
Join Date: Oct 2017
Location: Black Forest
Posts: 5,054
Default

I noticed that undoing changes in the MIDI editor is extremely slow.
Whereas applying the scripts (my nudge notes script based on Set_AllEvts)
executes extremely fast. Even when pressing and holding the shortcut for the script,
visual updates are drawn very fast. But when undoing all these changes, the MIDI editor really struggles. Could this be related somehow?
__________________
My Reascripts forum thread | My Reascripts on GitHub
If you like or use my scripts, please support the Ukraine: Ukraine Crisis Relief Fund | DirectRelief | Save The Children | Razom
_Stevie_ is offline   Reply With Quote
Old 09-19-2022, 01:22 PM   #17
_Stevie_
Human being with feelings
 
_Stevie_'s Avatar
 
Join Date: Oct 2017
Location: Black Forest
Posts: 5,054
Default

Bumping this FR
__________________
My Reascripts forum thread | My Reascripts on GitHub
If you like or use my scripts, please support the Ukraine: Ukraine Crisis Relief Fund | DirectRelief | Save The Children | Razom
_Stevie_ is offline   Reply With Quote
Old 09-22-2022, 07:36 AM   #18
_Stevie_
Human being with feelings
 
_Stevie_'s Avatar
 
Join Date: Oct 2017
Location: Black Forest
Posts: 5,054
Default

Well, apparently, again Julian Sader had to come to the rescue and (unconsciously?) solve this issue. Read further...

This whole MIDI Editor refresh issue is what hinders ALL midi scripts, that need to be refreshed regularly to function properly.
In my experience, this mostly affects Windows machines. Macs don't suffer from this.

Now to the solution. You need to add this in your scripts, after your MIDI has been changed by your script:
Code:
reaper.JS_Window_Update(windowHWND)
Where windowHWND should be the hwnd of your MIDI Editor.

I'm literally speechless, that this issue had to be solved with a 3rd party library and not with a native REAPER solution.
__________________
My Reascripts forum thread | My Reascripts on GitHub
If you like or use my scripts, please support the Ukraine: Ukraine Crisis Relief Fund | DirectRelief | Save The Children | Razom
_Stevie_ is offline   Reply With Quote
Old 09-26-2022, 10:59 AM   #19
juliansader
Human being with feelings
 
Join Date: Jul 2009
Posts: 3,714
Default

Wow, this is a wonderful discovery!!!

I can update the MIDI editor within a for- or while-loop, without waiting for defer!

In my experiments, it seems that updating will only work if MIDI_Sort has been called (including if SetCC/Note is called with the no-sort option = false).

One potential problem: the script will terminate after the timeout period set in Preferences -> ReaScript -> Timeout limit for Lua ReaScripts, and it does so without calling the atexit function.

EDIT: It seems that the termination is handled like a normal script error, so if the script is protected within a pcall, it can continue to its atexit.

Last edited by juliansader; 09-26-2022 at 11:11 AM.
juliansader is offline   Reply With Quote
Old 09-26-2022, 11:06 AM   #20
_Stevie_
Human being with feelings
 
_Stevie_'s Avatar
 
Join Date: Oct 2017
Location: Black Forest
Posts: 5,054
Default

I discovered this thanks to sockmonkey72, because we were trying to find a way to refresh the ME

But I still find it crazy, that we have to jump through hoops in order to get MIDI scripts refresh often enough.
__________________
My Reascripts forum thread | My Reascripts on GitHub
If you like or use my scripts, please support the Ukraine: Ukraine Crisis Relief Fund | DirectRelief | Save The Children | Razom
_Stevie_ is offline   Reply With Quote
Old 02-26-2023, 04:37 PM   #21
_Stevie_
Human being with feelings
 
_Stevie_'s Avatar
 
Join Date: Oct 2017
Location: Black Forest
Posts: 5,054
Default

Quote:
Originally Posted by juliansader View Post
Wow, this is a wonderful discovery!!!

I can update the MIDI editor within a for- or while-loop, without waiting for defer!
But will this also work, if the executed script is a defer script?
Or did I misunderstand?
__________________
My Reascripts forum thread | My Reascripts on GitHub
If you like or use my scripts, please support the Ukraine: Ukraine Crisis Relief Fund | DirectRelief | Save The Children | Razom
_Stevie_ is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 03:04 AM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.