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

Reply
 
Thread Tools Display Modes
Old 11-17-2018, 02:21 AM   #1
juliansader
Human being with feelings
 
Join Date: Jul 2009
Posts: 3,714
Default ReaScript API: Get MIDI editor on-screen layout via MIDIEditor_GetSetting_Int()

Scripts need access to the on-screen layout of the MIDI editor, in order to 1) accurately position transparent script GUIs over the editor, and to 2) quickly and accurately calculate the CC value, etc at the mouse position.

Unfortunately, REAPER's MIDI editor is secretive about its on-screen layout, with no native API functions to get information such as
* screen coordinates,
* CC lane heights,
* note vertical zoom, or
* leftmost scroll position, etc

Some of this information is supposed to be encoded in the item state chunk of the MIDI editor's active take, but it is unreliable:

* Screen coordinates are encoded in the CFGEDIT field, but it only gives the coordinates of the last-used UNmaximized size and position (and also includes the window frame).

* CC lane heights are encoded in VELLANE fields, but if two or more lanes are of the same type in the MIDI editor (for example, if two or more lanes are Pitch), only one lane is recorded in a VELLANE field. Scripts and SWS actions that try to calculate the CC lane under the mouse will fail in such situations.

Moreover, loading the item state chunk with GetItemStateChunk() is slow, which limits the responsiveness of scripts. Deferred scripts that try to load large state chunks in each defer cycle become jerky and can even slow REAPER down.

It would make scripts faster and more reliable -- and easier to code -- if REAPER could return reliable and up-to-date information about the MIDI editor's structure.

The existing API function MIDIEditor_GetSetting_Int can easily be expanded to return values such as:
* "note_zoom",
* "leftmost_pixel",
etc, and MIDIEditor_GetSetting_Str(editor, "cc_lanes", "") can return all the visible CC lanes as a single packed string.
juliansader is offline   Reply With Quote
Old 11-18-2018, 08:06 AM   #2
nappies
Human being with feelings
 
nappies's Avatar
 
Join Date: Dec 2017
Posts: 302
Default

+1 for this additional function!

I wanted to do something like a "smart grid" for the midi editor(Ableton style). grid snap setting follow grid visibility for midi editor.

It was cool, to have horizontal and vertical zoom data for midi editor window too.
nappies is offline   Reply With Quote
Old 11-26-2018, 11:12 AM   #3
MIP
Human being with feelings
 
Join Date: Sep 2017
Posts: 1
Default

Quote:
Originally Posted by nappies View Post
+1 for this additional function!

I wanted to do something like a "smart grid" for the midi editor(Ableton style). grid snap setting follow grid visibility for midi editor.

It was cool, to have horizontal and vertical zoom data for midi editor window too.
+1
Great feature
MIP is offline   Reply With Quote
Old 12-09-2018, 08:28 AM   #4
nappies
Human being with feelings
 
nappies's Avatar
 
Join Date: Dec 2017
Posts: 302
Default

I made cpu save "smart" grid using JS_Mouse_GetState it works only when you zoom



by the way Ableton take much more CPU then zooming in midi editor


Last edited by nappies; 12-09-2018 at 08:58 AM.
nappies is offline   Reply With Quote
Old 12-10-2018, 08:13 AM   #5
Meo-Ada Mespotine
Human being with feelings
 
Meo-Ada Mespotine's Avatar
 
Join Date: May 2017
Location: Leipzig
Posts: 6,612
Default

+1
Everything that helps making programming the MIDI-Editor as versatile as the ArrangeView is a good thing.
__________________
Use you/she/her.Ultraschall-Api Lua Api4Reaper - Donate, if you wish

On vacation for the time being...
Meo-Ada Mespotine is offline   Reply With Quote
Old 01-03-2019, 10:17 PM   #6
amagalma
Human being with feelings
 
amagalma's Avatar
 
Join Date: Apr 2011
Posts: 3,450
Default

Yes please! And a GetSetArrangeView equivalent for the Midi Editor.
__________________
Most of my scripts can be found in ReaPack.
If you find them useful, a donation would be greatly appreciated! Thank you! :)
amagalma is offline   Reply With Quote
Old 01-24-2019, 12:35 PM   #7
_Stevie_
Human being with feelings
 
_Stevie_'s Avatar
 
Join Date: Oct 2017
Location: Black Forest
Posts: 5,048
Default

Quote:
Originally Posted by juliansader View Post
The existing API function MIDIEditor_GetSetting_Int can easily be expanded to return values such as:
* "note_zoom",
* "leftmost_pixel",
etc, and MIDIEditor_GetSetting_Str(editor, "cc_lanes", "") can return all the visible CC lanes as a single packed string.

Yes, that would really help! Trying to get all visible CCs fails because of these missing values.
__________________
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 04-12-2019, 05:17 PM   #8
juliansader
Human being with feelings
 
Join Date: Jul 2009
Posts: 3,714
Default

Bumping this since the devs are currently working on MIDIEditor settings.
juliansader is offline   Reply With Quote
Old 04-13-2019, 05:42 AM   #9
_Stevie_
Human being with feelings
 
_Stevie_'s Avatar
 
Join Date: Oct 2017
Location: Black Forest
Posts: 5,048
Default

Well, I might add another thing: get and set swing amount for grid in the MIDI editor.
__________________
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 06-22-2020, 01:58 PM   #10
reapero
Human being with feelings
 
Join Date: Aug 2011
Posts: 508
Default

+1! Please
reapero is offline   Reply With Quote
Old 06-23-2020, 01:57 AM   #11
mozart999uk
Human being with feelings
 
Join Date: Nov 2010
Posts: 1,710
Default

+1 please
mozart999uk is offline   Reply With Quote
Old 06-25-2020, 12:02 PM   #12
juliansader
Human being with feelings
 
Join Date: Jul 2009
Posts: 3,714
Default

Using the ReaScriptAPI extension, one can get the positions and sizes of the MIDI editor and its child windows.

In addition, the position and name of each CC lane can be derived from the CC lane selectors, each of which is a child window of the "midipianoview" window.

The zoom, scroll and timebase settings are still hidden, though.
juliansader is offline   Reply With Quote
Old 01-15-2021, 09:25 PM   #13
daniellumertz
Human being with feelings
 
daniellumertz's Avatar
 
Join Date: Dec 2017
Location: Brazil
Posts: 1,986
Default

+1

This would be gold for some projects of mine involving the piano roll !!!
daniellumertz is online now   Reply With Quote
Old 01-17-2021, 10:31 AM   #14
juliansader
Human being with feelings
 
Join Date: Jul 2009
Posts: 3,714
Default

Quote:
Originally Posted by juliansader View Post
In addition, the position and name of each CC lane can be derived from the CC lane selectors, each of which is a child window of the "midipianoview" window.
In recent versions of REAPER, the CC selection dropdowns aren't separate child windows any more, so this trick is out of the window too.
juliansader is offline   Reply With Quote
Old 04-20-2021, 10:17 PM   #15
Malfunction
Human being with feelings
 
Malfunction's Avatar
 
Join Date: Sep 2020
Posts: 149
Default

JS_Window_GetScrollInfo can provide some information about the scroll/zoom.
It can tell you if zoom/scroll info has changed, so that you can do chunk reading only when nessesary.
Code:
VERT = {reaper.JS_Window_GetScrollInfo(  midiview,"VERT")} 
HORZ = {reaper.JS_Window_GetScrollInfo(  midiview,"HORZ")} 

retval,  left,  top,  right,  bottom = reaper.JS_Window_GetClientRect(  midiview)
top_P= 127-VERT[2]/100 
pixeltop = top + 62

in my notegrid hightlighting script,-I was able to estimate horizontal pixel/grid by tracking mouse movement.
The measured pixel/QN ratio was unstable, but was stablized by gathering multiple measurements into a table, and voting the most "popular" result.

I tried to estimate pixel/pitch by tracking mouse movement, but failed royally. ( update... see next post)
You have alot more limiting info to work with.
You have the top visible pitch and its pixel position.
You gather mouse y position, and its noterow or pitch position.

There might be some clever tricks you can do.
Maybe building a pixel/height function by reading the reaper.JS_Window_GetScrollInfo data.

Last edited by Malfunction; 04-21-2021 at 03:54 AM.
Malfunction is offline   Reply With Quote
Old 04-22-2021, 03:36 PM   #16
Malfunction
Human being with feelings
 
Malfunction's Avatar
 
Join Date: Sep 2020
Posts: 149
Default

This one calculates leftmostQN, rightmostQN, Qn_perPixel, PixelPrPitch, TopMostPitch, BottomMost Pitch, just from tracking mouse movement. (update: even more solid)
Code:
function main()
  midiview = reaper.JS_Window_Find("midiview",false) 
  HORZ = {reaper.JS_Window_GetScrollInfo(midiview, "HORZ") } 
  VERT = {reaper.JS_Window_GetScrollInfo(midiview,"VERT")}
  x, y = reaper.GetMousePosition()
  X, Y = reaper.JS_Window_ScreenToClient(midiview,  x,   y) 
  retval_BR_Getmousecursorcontext , segment, details = reaper.BR_GetMouseCursorContext() 
  retval_BR_Getmousecursorcontext_MIDI,  inlineEditor,   noteRow,   ccLane, ccLaneVal,  ccLaneI = reaper.BR_GetMouseCursorContext_MIDI() 
  timepos = reaper.BR_GetMouseCursorContext_Position() 
  retval,  left,  top,  right,  bottom = reaper.JS_Window_GetClientRect(midiview)
  top_P= 127-VERT[2]/100 
  pixeltop = top + 62
  Y =Y - 62 
  if  segment == "notes" then 
    QN = reaper.TimeMap2_timeToQN(0,timepos) 
    if QN >0 then 
      if X>max_X then 
        max_X = X 
        max_Qn = QN 
      end 

      if X<min_X then
        min_X = X 
        min_Qn = QN 
      end
    end 
    ratio = (max_X - min_X)/(max_Qn - min_Qn)
    -------------------------------------------
    ME_Leftmost_Qn =  max_Qn - max_X /ratio 
    ME_Rightmost_Qn =  min_Qn + ( HORZ[3]- min_X)/ratio 
    ME_QnPerPixel = (max_Qn - min_Qn)/(max_X - min_X)
 
    H_zoom_ = H_zoom or 0
    H_zoom = HORZ[3] 
    H_zoom2_ = H_zoom2 or 0
    H_zoom2 = HORZ[5]
    H_scroll_ = H_scroll or 0
    H_scroll = HORZ[2] 

    if  H_zoom~=H_zoom_ or H_scroll~=H_scroll_ or H_zoom2~=H_zoom2_ then 
      min_X = 10000
      max_X = 0 
    end 
    
    if count<limit then 
      i = 4 
      upper_limit =100
      pd = top_P-noteRow 
      lower_limit = Y/(pd +1) 
      if pd > 1 then 
         upper_limit = Y/(pd -1) end 
      if pd == 1 then 
         upper_limit = Y 
      end
      i = math.floor(lower_limit-1)
      while (i<upper_limit) do
        if Y>=i*pd and Y<=(i*pd + i)  then 
          if height[i] then 
            height[i] = height[i] + 1     
          else 
            height[i]=1 
          end
        end 
        i=i+1 
      end  
      m = 0
      for u,v in pairs(height) do 
        if v>m then
          m=v 
          hg=u
        end 
      end 
      count = count +1 
    end
    
    ME_pixel_per_pitch =hg
    ME_topmostPitch = top_P 
    ME_bottommostPitch = top_P - VERT[3]/100
    
    V_zoom_ = V_zoom or 0
    V_zoom = VERT[3] 
    V_scroll_ = V_scroll or 0
    V_scroll = VERT[2] 

    if V_zoom~=V_zoom_ or V_scroll~=V_scroll_   then 
       count = 0
       height={} 
    end 
  end   
  reaper.defer(main)
end


min_X = 10000
max_X = 0 
height ={} 
limit = 100
count = 0

main()

Last edited by Malfunction; 04-23-2021 at 07:07 PM.
Malfunction is offline   Reply With Quote
Old 05-01-2021, 10:45 AM   #17
juliansader
Human being with feelings
 
Join Date: Jul 2009
Posts: 3,714
Default

Quote:
Originally Posted by Malfunction View Post
This one calculates leftmostQN, rightmostQN, Qn_perPixel, PixelPrPitch, TopMostPitch, BottomMost Pitch, just from tracking mouse movement. (update: even more solid)
This is an impressive function!

Unfortunately, it does not solve the problems mentioned in the OP, namely speed, reliability and ease of coding. Under the hood, the SWS function BR_GetMouseCursorContext_MIDI has to load the MIDI chunk too, so it about as slow as doing the same in a script, and it has the same limitations wrt reliability.
juliansader is offline   Reply With Quote
Old 05-28-2021, 10:37 AM   #18
bFooz
Human being with feelings
 
Join Date: Jul 2010
Location: Slovakia
Posts: 2,588
Default

Bump. Also applies for notation.
bFooz is offline   Reply With Quote
Old 06-23-2021, 04:45 AM   #19
Malfunction
Human being with feelings
 
Malfunction's Avatar
 
Join Date: Sep 2020
Posts: 149
Default

Quote:
Originally Posted by juliansader View Post
This is an impressive function!

Unfortunately, it does not solve the problems mentioned in the OP, namely speed, reliability and ease of coding. Under the hood, the SWS function BR_GetMouseCursorContext_MIDI has to load the MIDI chunk too, so it about as slow as doing the same in a script, and it has the same limitations wrt reliability.
Is there a list of which functions that read from the midi chunk (itemstatechunk)?
Malfunction is offline   Reply With Quote
Old 12-26-2021, 08:36 AM   #20
bFooz
Human being with feelings
 
Join Date: Jul 2010
Location: Slovakia
Posts: 2,588
Default

Bump.
bFooz 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 08:40 PM.


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