Old 04-02-2020, 04:19 PM   #1001
Sexan
Human being with feelings
 
Sexan's Avatar
 
Join Date: Jun 2009
Location: Croatia
Posts: 4,591
Default

Have IDE opened, drag from inside of IDE to track view, osx crashes there. Will upload code in the morning, just left my studio.

Edit: sorry I was not clear enough, its not api that crashes but my script, since when other window is in focus it loses track under mouse for some reason. That is not happening on windows.

So I replaced forground api with code above and for now it works without issue on osx

Last edited by Sexan; 04-02-2020 at 04:33 PM.
Sexan is online now   Reply With Quote
Old 04-03-2020, 12:02 AM   #1002
Sexan
Human being with feelings
 
Sexan's Avatar
 
Join Date: Jun 2009
Location: Croatia
Posts: 4,591
Default

Julian so here is the script with modifications because its not working on osx with the original (which works with windows)

In the class script:
Code:
230 :   if not Get_window_under_mouse() then return end
Code:
function Get_window_under_mouse()
   if mouse.l_down then
      local windowUnderMouse = reaper.JS_Window_FromPoint(mouse.x, mouse.y)
      if windowUnderMouse and windowUnderMouse ~= track_window then
         --local parentWindow = reaper.JS_Window_GetParent(windowUnderMouse)
         return false
      end
   end
   return true
end
WINDOWS:


OSX:


This additional check does not crash
Code:
function Get_window_under_mouse()
   if mouse.l_down then
      local windowUnderMouse = reaper.JS_Window_FromPoint(mouse.x, mouse.y)
      local old_windowUnderMouse = reaper.JS_Window_FromPoint(mouse.ox, mouse.oy)
      if windowUnderMouse then
         if windowUnderMouse ~= track_window then
            return true
         elseif old_windowUnderMouse then
            if old_windowUnderMouse ~= track_window then
               return true
            end
         end
      end
   end
   return false
end
Original code is commented out
Code:
40: --if reaper.JS_Window_GetForeground() ~= main_wnd then
41:  --  return
42--end
This works well on Windows, but cannot be used on OSX since if any window is opened it would trigger that API as TRUE. It sees any window that is opened as focused.

Anyway in the attachment is the old_version that is crashing on OSX, you can check the original behavior by commenting out line 230, and uncommenting lines 40-41-42 in the CLASS script.

The issue is only OSX

Last edited by Sexan; 02-13-2023 at 08:15 AM.
Sexan is online now   Reply With Quote
Old 04-03-2020, 12:54 AM   #1003
Sexan
Human being with feelings
 
Sexan's Avatar
 
Join Date: Jun 2009
Location: Croatia
Posts: 4,591
Default

Also wanted to ask... what would be best way to optimize drawing ?
Drawing areas is pretty optimized, it only draws the latest area when creating and rest (if you have multiple areas on screen) are updated only on project change (if zoomed, scrolled, rezized etc etc.

But I want to optimize how GHOST items draw, since they can be in large numbers and that hits cpu bad (if you have over 100 items or envelopes selected but no one will do that in real use case scenarios.

Right now there is most standard check

Code:
if last_x ~= x or last_y ~= y then DRAW
Is there something else (advance??) that can be done?
Sexan is online now   Reply With Quote
Old 04-03-2020, 07:52 AM   #1004
amagalma
Human being with feelings
 
amagalma's Avatar
 
Join Date: Apr 2011
Posts: 3,451
Default

Quote:
Originally Posted by _Stevie_ View Post
I messed around a bit and I could get it working by putting the reaper.UpdateArrange()
just below first_x = x. But it's doing a lot of flickering here in Windows.

Thanks! I had tried this too and noticed the flickering.



Quote:
Originally Posted by juliansader View Post
You can use JS_Window_InvalidateRect to ask REAPER to re-draw part of a window, which will cover up the previous cycle's line.

For example, try adding this directly after the ReleaseDC line:
Code:
if prev_x and prev_x ~= x then reaper.JS_Window_InvalidateRect(trackview, prev_x, prev_top_y, prev_x+1, prev_bottom_y, true)
prev_x, prev_top_y, prev_bottom_y = x, y+1, y+height-1
Here on my system, this works without any flickering.

Thanks! It works!


Another question:
How can one intercept left mouse clicks on the trackview window? This doesn't work:
Code:
reaper.JS_VKeys_Intercept( 0x01, 1 )
This worked:
Code:
 reaper.JS_WindowMessage_Intercept( trackview, "WM_LBUTTONDOWN", false )
But how can I stop the interception after the script finishes? Because I am left with a non-working left-click!
__________________
Most of my scripts can be found in ReaPack.
If you find them useful, a donation would be greatly appreciated! Thank you! :)

Last edited by amagalma; 04-03-2020 at 07:59 AM.
amagalma is offline   Reply With Quote
Old 04-03-2020, 09:39 AM   #1005
Edgemeal
Human being with feelings
 
Edgemeal's Avatar
 
Join Date: Apr 2016
Location: ASU`ogacihC
Posts: 3,913
Default

Quote:
Originally Posted by amagalma View Post
But how can I stop the interception after the script finishes? Because I am left with a non-working left-click!
I think you just need to release it,..
Code:
reaper.JS_WindowMessage_Release(trackview, "WM_LBUTTONDOWN")
Edgemeal is offline   Reply With Quote
Old 04-03-2020, 09:50 AM   #1006
amagalma
Human being with feelings
 
amagalma's Avatar
 
Join Date: Apr 2011
Posts: 3,451
Default

Quote:
Originally Posted by Edgemeal View Post
I think you just need to release it,..
Code:
reaper.JS_WindowMessage_Release(trackview, "WM_LBUTTONDOWN")

Thanks!


I just found that this works too:
Code:
reaper.JS_WindowMessage_PassThrough( trackview, "WM_LBUTTONDOWN", true )
__________________
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 04-03-2020, 03:29 PM   #1007
amagalma
Human being with feelings
 
amagalma's Avatar
 
Join Date: Apr 2011
Posts: 3,451
Default

What kind of objects should be deleted with JS_GDI_DeleteObject when exiting the script? Created by which APIs? If not deleted, does that mean a memory leak?
__________________
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 04-03-2020, 04:52 PM   #1008
_Stevie_
Human being with feelings
 
_Stevie_'s Avatar
 
Join Date: Oct 2017
Location: Black Forest
Posts: 5,054
Default

Just checking amagalma, are you planning to code some kind of scissors tool for REAPER?
__________________
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-03-2020, 05:43 PM   #1009
Meo-Ada Mespotine
Human being with feelings
 
Meo-Ada Mespotine's Avatar
 
Join Date: May 2017
Location: Leipzig
Posts: 6,621
Default

Quote:
Originally Posted by amagalma View Post
What kind of objects should be deleted with JS_GDI_DeleteObject when exiting the script? Created by which APIs? If not deleted, does that mean a memory leak?
I would release it anyway, as these functions are made for C/C++ and I remember, when toying around with them, that they seem to leave stuff behind quite often, even after finishing the script. So Lua's garbage-collector seems to not clear up everything sometimes.

I suppose(but don't know), that API-functions exposed to ReaScript by the devs officially, are written to take care of cleaning up behind them, unless it's documented otherwise, but it's just a wild guess by me.
__________________
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 04-04-2020, 05:46 AM   #1010
amagalma
Human being with feelings
 
amagalma's Avatar
 
Join Date: Apr 2011
Posts: 3,451
Default

Quote:
Originally Posted by _Stevie_ View Post
Just checking amagalma, are you planning to code some kind of scissors tool for REAPER?

Yes.. Just for fun


Code:
-- Check if JS_ReaScriptAPI is installed
if not reaper.APIExists("JS_GDI_CreatePen") then
  local answer = reaper.MB( "You have to install JS_ReaScriptAPI for this script to work. Would you like to open the relative web page in your browser?", "JS_ReaScriptAPI not installed", 4 )
  if answer == 6 then
    local url = "https://forum.cockos.com/showthread.php?t=212174"
     reaper.CF_ShellExecute( url )
  end
  return
end


local reaper = reaper
local start = reaper.time_precise()
local trackview = reaper.JS_Window_FindChildByID(reaper.GetMainHwnd(), 1000)
local pen = reaper.JS_GDI_CreatePen( 1, 16777215 )
local height, prev_x, prev_top_y, prev_bottom_y, x, y = 0
local lm_state, quitting, tooltip = 0, false, false
reaper.JS_WindowMessage_InterceptList( trackview, "WM_LBUTTONDOWN:block,WM_SETCURSOR:block,0x4F:block" )
local cursor = reaper.JS_Mouse_LoadCursor( 32516 )
local split = true
local change = start
-- Refresh toolbar
local _, _, section, cmdID = reaper.get_action_context()  
reaper.SetToggleCommandState( section, cmdID, 1 ) -- Set ON
reaper.RefreshToolbar2( section, cmdID )


function main()
  x, y = reaper.GetMousePosition() -- screen
  
  if quitting then -- release intercepts and delete objects
    
    reaper.JS_GDI_DeleteObject( pen )
    reaper.JS_GDI_DeleteObject( cursor )
    reaper.UpdateArrange()
    reaper.JS_WindowMessage_ReleaseAll()
    reaper.SetToggleCommandState( section, cmdID, 0 ) -- Set OFF
    reaper.RefreshToolbar2( section, cmdID )
    tooltip = quitting
    quitting = false
  
  elseif tooltip then -- show tooltip while exiting
    
    reaper.TrackCtl_SetToolTip( "Quitting script", x-40, y+20, true )
    if reaper.time_precise() - tooltip >= 0.7 then
      reaper.TrackCtl_SetToolTip( "", 0, 0, true )
      return
    end
  
  else -- main
    
    reaper.JS_Mouse_SetCursor( cursor )
    local item, take = reaper.GetItemFromPoint( x, y, true )    
    if item then
      if split then
        reaper.TrackCtl_SetToolTip( "L-click to split\nO change mode\nESC quit", x-42, y+50, true )
      else
        reaper.TrackCtl_SetToolTip( "L-click to add stretch marker\nO change mode\nESC quit", x-85, y+50, true )
      end
      y = reaper.GetMediaTrackInfo_Value( reaper.GetMediaItem_Track( item ), "I_TCPY" ) + 
                reaper.GetMediaItemInfo_Value( item, "I_LASTY" ) -- client
      height = reaper.GetMediaItemInfo_Value( item, "I_LASTH" )
      x = reaper.JS_Window_ScreenToClient( trackview, x, 0 )
      local hdc = reaper.JS_GDI_GetClientDC( trackview )
      reaper.JS_GDI_SelectObject( hdc, pen ) 
      reaper.JS_GDI_Line( hdc, x, y + 1, x, y + height - 2 )
      reaper.JS_GDI_ReleaseDC( trackview, hdc )
      -- left-click
      local current_lm = reaper.JS_Mouse_GetState(1)
      if current_lm == 1 and lm_state == 0 then
        local position = reaper.BR_PositionAtMouseCursor( false )
        if split then
          reaper.SplitMediaItem( item, position )
          reaper.Undo_OnStateChange_Item( 0, "Split under mouse cursor", item )
        elseif take then
          local item_pos = reaper.GetMediaItemInfo_Value( item, "D_POSITION" )
          reaper.SetTakeStretchMarker( take, -1, position-item_pos, nil )
          reaper.Undo_OnStateChange_Item( 0, "Add stretch marker", item )
        end
        lm_state = 1
        reaper.UpdateItemInProject( item )
      elseif current_lm == 0 then
        lm_state = 0
      end
    end
    if prev_x and prev_x ~= x then
      reaper.JS_Window_InvalidateRect(trackview, prev_x, prev_top_y, prev_x+1, prev_bottom_y, true)
    end
    prev_x, prev_top_y, prev_bottom_y = x, y+1, y+height-1
    -- if ESC then terminate script
    if reaper.JS_VKeys_GetState(start):byte("0x1B") ~= 0 then
      quitting = reaper.time_precise()
    -- change mode with O key
    elseif reaper.JS_VKeys_GetState(start):byte("0x4F") ~= 0 then
      if reaper.time_precise() - change >= 0.2 then
        split = not split
        change = reaper.time_precise()
      end
    end
  
  end
  
  reaper.defer(main)
  
end


main()
__________________
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 04-04-2020, 05:52 AM   #1011
_Stevie_
Human being with feelings
 
_Stevie_'s Avatar
 
Join Date: Oct 2017
Location: Black Forest
Posts: 5,054
Default

Goodness, I was just about to do the same, when I saw your code, because that was the missing link

I think I'm gonna refrain from it then
I started a glue tool some time ago and need to finish it.

Which leads me to the next idea...

- Sexan is doing area selection
- You are doing a scissors tool
- I have a half finished glue tool

Should we maybe team up and create a tool collection for REAPER?
Of course this could also be extended to more tools and everyone could jump in.
__________________
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-04-2020, 05:52 AM   #1012
amagalma
Human being with feelings
 
amagalma's Avatar
 
Join Date: Apr 2011
Posts: 3,451
Default

Quote:
Originally Posted by mespotine View Post
I would release it anyway, as these functions are made for C/C++ and I remember, when toying around with them, that they seem to leave stuff behind quite often, even after finishing the script. So Lua's garbage-collector seems to not clear up everything sometimes.

I suppose(but don't know), that API-functions exposed to ReaScript by the devs officially, are written to take care of cleaning up behind them, unless it's documented otherwise, but it's just a wild guess by me.

So, for example, in the code I posted above I delete the Pen and the Mouse Cursor when exiting. Is there anything else I should delete?
__________________
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 04-04-2020, 05:59 AM   #1013
amagalma
Human being with feelings
 
amagalma's Avatar
 
Join Date: Apr 2011
Posts: 3,451
Default

Quote:
Originally Posted by _Stevie_ View Post
Goodness, I was just about to do the same, when I saw your code, because that was the missing link

I think I'm gonna refrain from it then
I started a glue tool some time ago and need to finish it.

Which leads me to the next idea...

- Sexan is doing area selection
- You are doing a scissors tool
- I have a half finished glue tool

Should we maybe team up and create a tool collection for REAPER?
Of course this could also be extended to more tools and everyone could jump in.

Actually, I just wanted to make a script that shows a vertical line on the items that are below the mouse cursor.. but I got carried away! :P .. To be honest, I'll use my first idea and stick to the various editing tools offered natively by Reaper and by scripts. No need to re-invent the wheel.. I don't know about your glue tool so I can't say, but what Sexan is doing is magic and is really needed and missing from Reaper...
__________________
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 04-04-2020, 06:05 AM   #1014
_Stevie_
Human being with feelings
 
_Stevie_'s Avatar
 
Join Date: Oct 2017
Location: Black Forest
Posts: 5,054
Default

Okay then, was just an idea
__________________
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-04-2020, 06:52 AM   #1015
amagalma
Human being with feelings
 
amagalma's Avatar
 
Join Date: Apr 2011
Posts: 3,451
Default

Quote:
Originally Posted by _Stevie_ View Post
Okay then, was just an idea

I hope you didn't get me wrong! It IS a nice idea, but for those who want tools like in Cubase for example. I am fine with the tools we have natively and those added by scripts already. The only thing I miss is area selection.. (ok.. and playlists and track editing groups :P)
__________________
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 04-04-2020, 07:01 AM   #1016
Klangfarben
Human being with feelings
 
Join Date: Jul 2016
Location: Los Angeles, CA
Posts: 1,701
Default

Quote:
Originally Posted by amagalma View Post
(ok.. and playlists and track editing groups :P)
Same. Well, the more help Sexan gets, the faster he can revisit his PT Playlist/Track Versions script
Klangfarben is offline   Reply With Quote
Old 04-04-2020, 07:07 AM   #1017
_Stevie_
Human being with feelings
 
_Stevie_'s Avatar
 
Join Date: Oct 2017
Location: Black Forest
Posts: 5,054
Default

Quote:
Originally Posted by amagalma View Post
I hope you didn't get me wrong! It IS a nice idea, but for those who want tools like in Cubase for example. I am fine with the tools we have natively and those added by scripts already. The only thing I miss is area selection.. (ok.. and playlists and track editing groups :P)
All good man, I will give it another thought how this could be done.
__________________
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-04-2020, 10:10 AM   #1018
Neutronic
Human being with feelings
 
Neutronic's Avatar
 
Join Date: Sep 2013
Posts: 657
Default

Julian, your API extension is full of really handy gems. Thank you for starting this project and keeping it up to date!
Neutronic is offline   Reply With Quote
Old 04-04-2020, 11:06 AM   #1019
Thonex
Human being with feelings
 
Join Date: May 2018
Location: Los Angeles
Posts: 1,719
Default

Quote:
Originally Posted by _Stevie_ View Post
Goodness, I was just about to do the same, when I saw your code, because that was the missing link

I think I'm gonna refrain from it then
I started a glue tool some time ago and need to finish it.

Which leads me to the next idea...

- Sexan is doing area selection
- You are doing a scissors tool
- I have a half finished glue tool

Should we maybe team up and create a tool collection for REAPER?
Of course this could also be extended to more tools and everyone could jump in.
A cohesive toolkit would be very sweet!

+1 from me

Cheers,

Andrew K
__________________
Cheers... Andrew K
Reaper v6.80+dev0621 - June 21 2023 • Catalina • Mac Mini 2020 6 core i7 • 64GB RAM • OS: Catalina • 4K monitor • RME RayDAT card with Sync Card and extended Light Pipe.
Thonex is offline   Reply With Quote
Old 04-05-2020, 05:54 AM   #1020
_Stevie_
Human being with feelings
 
_Stevie_'s Avatar
 
Join Date: Oct 2017
Location: Black Forest
Posts: 5,054
Default

Thanks Andrew! Will try to work something out
__________________
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-05-2020, 09:13 AM   #1021
Sexan
Human being with feelings
 
Sexan's Avatar
 
Join Date: Jun 2009
Location: Croatia
Posts: 4,591
Default

Julian is this correct way to intercept mouse cursors?

Code:
local reaper_cursors_list = {
   {187, "C"}, -- MOVE
   {185, "DRAW"}, -- DRAW
   {462, "L"}, -- LEFT EDGE
   {462, "R"}, -- RIGHT EDGE
   {530, "T"}, -- FADE RIGHT
   {530, "B"} -- FADE LEFT
}

function Change_cursor(zone)
   if zone then
      if not ICON_INT then
         reaper.JS_WindowMessage_Intercept(track_window, "WM_SETCURSOR", false)
         ICON_INT = true
      end
      for i = 1, #reaper_cursors_list do
         if zone == reaper_cursors_list[i][2] then
            local cursor = reaper.JS_Mouse_LoadCursor(reaper_cursors_list[i][1])
            reaper.JS_Mouse_SetCursor(cursor)
         end
      end
   else
      if ICON_INT then
         reaper.JS_WindowMessage_Release(track_window, "WM_SETCURSOR")
         ICON_INT = false
      end
   end
end
If mouse is over area it sends which zone is over

Last edited by Sexan; 04-05-2020 at 11:12 AM.
Sexan is online now   Reply With Quote
Old 04-06-2020, 04:49 PM   #1022
juliansader
Human being with feelings
 
Join Date: Jul 2009
Posts: 3,714
Default

I've uploaded v1.000 of the extension:
* Composite, Composite_Unlink and DestroyBitmap automatically update and re-draw window.
* Slightly less flickering on WindowsOS.
* Composite_Unlink can optionally unlink all bitmaps from window.
* JS_LICE_List/ArrayAllBitmaps.
* JS_Window_EnableMetal to check Metal mode on macOS.

The improved Composite functions are helpful for bitmaps that move across the screen without changing their content, such as the script by Sexan and amagalma, since the script doesn't need to calculate and call InvalidateRect.

I'm not sure if the Metal function actually works -- please let me know.

Last edited by juliansader; 04-06-2020 at 05:23 PM.
juliansader is offline   Reply With Quote
Old 04-06-2020, 05:46 PM   #1023
_Stevie_
Human being with feelings
 
_Stevie_'s Avatar
 
Join Date: Oct 2017
Location: Black Forest
Posts: 5,054
Default

Will let you know about Metal!
__________________
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-06-2020, 11:29 PM   #1024
Sexan
Human being with feelings
 
Sexan's Avatar
 
Join Date: Jun 2009
Location: Croatia
Posts: 4,591
Default

So I do not need to call Invalidate anymore?

EDIT: Do I need to make any modification to the script?

Code:
function Element:draw(w,h)
    reaper.JS_Composite(track_window, self.x, self.y, self.w, self.h, self.bm, 0, 0, w, h)
    Refresh_reaper()
end
Refresh calls Invalidate. I guess I should remove that ?

Not sure if I wrote ghosts drawing rights, it hits CPU hard when lots of ghosts:

Code:
function Element:ghosts(off_time, off_tr)
  for i = 1, #self.sel_info do
    if self.sel_info[i].ghosts then
      for j = 1, #self.sel_info[i].ghosts do
        local tr = off_tr and off_tr or self.sel_info[i].track
        local ghost = self.sel_info[i].ghosts[j]
        local ghost_start = off_time and (off_time + ghost.time_start) or ghost.time_start
        ghost.x, ghost.w = Convert_time_to_pixel(ghost_start,  ghost.time_dur)
        ghost.y, ghost.h = Get_tr_TBH(tr)
        ghost:draw(ghost.info[1], ghost.info[2]) -- STORED GHOST W AND H
      end
    end
  end
end
I'm pretty sure I did not have this issue before (not related to this update!). Maybe during rewrite I wrote some functions wrong



(this is about 250 items selected)

EDIT2:

Hmm... yeah need to figure out where to refresh the screen, if I remove refresh() from draw method and put it at the end of ghost function, cpu is way less used


(peaks at 2% sometimes)

Last edited by Sexan; 04-07-2020 at 02:27 AM.
Sexan is online now   Reply With Quote
Old 04-07-2020, 12:14 AM   #1025
Sexan
Human being with feelings
 
Sexan's Avatar
 
Join Date: Jun 2009
Location: Croatia
Posts: 4,591
Default

Quote:
Originally Posted by juliansader View Post
* Composite_Unlink can optionally unlink all bitmaps from window.
How do I do this?

I have 3 functions that loop all the tables to unlink or delete bitmaps
Sexan is online now   Reply With Quote
Old 04-07-2020, 02:40 AM   #1026
Sexan
Human being with feelings
 
Sexan's Avatar
 
Join Date: Jun 2009
Location: Croatia
Posts: 4,591
Default

Will get back to you soon, done some extreme optimizations regarding drawing.

Forget all above I've said, horrible code, found a lot of issues
Sexan is online now   Reply With Quote
Old 04-07-2020, 05:39 AM   #1027
X-Raym
Human being with feelings
 
X-Raym's Avatar
 
Join Date: Apr 2013
Location: France
Posts: 9,875
Default

Quote:
I've uploaded v1.000 of the extension:

v1.0 ? Well done !!
X-Raym is offline   Reply With Quote
Old 04-07-2020, 06:12 AM   #1028
amagalma
Human being with feelings
 
amagalma's Avatar
 
Join Date: Apr 2011
Posts: 3,451
Default

Quote:
Originally Posted by juliansader View Post
The improved Composite functions are helpful for bitmaps that move across the screen without changing their content, such as the script by Sexan and amagalma, since the script doesn't need to calculate and call InvalidateRect.

So, I could use another better way to draw the line? The current is this:
Code:
function main()
  x, y = reaper.GetMousePosition() -- screen
  local item = reaper.GetItemFromPoint( x, y, true )
  if item then
    y = reaper.GetMediaTrackInfo_Value( reaper.GetMediaItem_Track( item ), "I_TCPY" ) + 
              reaper.GetMediaItemInfo_Value( item, "I_LASTY" ) -- client
    height = reaper.GetMediaItemInfo_Value( item, "I_LASTH" )
    x = reaper.JS_Window_ScreenToClient( trackview, x, 0 )
    local hdc = reaper.JS_GDI_GetClientDC( trackview )
    reaper.JS_GDI_SelectObject( hdc, pen ) 
    reaper.JS_GDI_Line( hdc, x, y + 1, x, y + height - 2 )
    reaper.JS_GDI_ReleaseDC( trackview, hdc )
  end
  if prev_x and (prev_x ~= x or prev_top_y ~= y + 1) then
    reaper.JS_Window_InvalidateRect(trackview, prev_x, prev_top_y, prev_x + 1, prev_bottom_y, true)
  end
  prev_x, prev_top_y, prev_bottom_y = x, y + 1, y + height - 2
  reaper.defer(main)
end
__________________
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 04-07-2020, 07:18 AM   #1029
Meo-Ada Mespotine
Human being with feelings
 
Meo-Ada Mespotine's Avatar
 
Join Date: May 2017
Location: Leipzig
Posts: 6,621
Default

Quote:
Originally Posted by X-Raym View Post
v1.0 ? Well done !!
Time to update my docs
__________________
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 04-07-2020, 09:43 AM   #1030
Sexan
Human being with feelings
 
Sexan's Avatar
 
Join Date: Jun 2009
Location: Croatia
Posts: 4,591
Default

I have some weirdness with 1.0:

Code:
v0.999

This one is fine

Code:
v1.0

This one stucks somewhere with redrawing/refreshing

The only difference in the code is Refresh_reaper(), on v1.0 is commented out since V1.0 has internal invalidate

Code:
Class script Line 103-106

function Element:draw(w,h)
    reaper.JS_Composite(track_window, self.x, self.y, self.w, self.h, self.bm, 0, 0, w, h)
    --Refresh_reaper()
end
Steps to reproduce:
1.Create multiple items like in gif
2. Create multiple selections (CTRL + SHIFT + DRAG)
3. Activate copy mode CRTL + C
4. Move items around

Last edited by Sexan; 02-13-2023 at 08:15 AM.
Sexan is online now   Reply With Quote
Old 04-07-2020, 12:11 PM   #1031
juliansader
Human being with feelings
 
Join Date: Jul 2009
Posts: 3,714
Default

Quote:
Originally Posted by amagalma View Post
So, I could use another better way to draw the line?
I would recommend that you use the Composite functions, since they work better on Linux and macOS (except for that Metal issue -- which is probably not relevant to your script), and you don't have to bother with DCs and GDI objects. Simply create a bitmap of any color at the start of the script, use JS_Composite to link and move the image, and destroy the bitmap when the script terminates.

For example:
Code:
bm = reaper.JS_LICE_CreateBitmap(true, 1, 1)
reaper.JS_LICE_Clear(bm, 0xFFFF0000)

trackview = reaper.JS_Window_FindChildByID(reaper.GetMainHwnd(), 1000)

function loop()
    x, y = reaper.GetMousePosition() -- screen
    if x ~= prev_x or y ~= prev_y then
        prev_x, prev_y = x, y
        item = reaper.GetItemFromPoint( x, y, true )
        if item then
            if item ~= prev_item then
                prev_item = item
                track_y = reaper.GetMediaTrackInfo_Value( reaper.GetMediaItem_Track( item ), "I_TCPY" ) + 
                          reaper.GetMediaItemInfo_Value( item, "I_LASTY" ) -- client
                item_h = reaper.GetMediaItemInfo_Value( item, "I_LASTH" )
            end
            x, y = reaper.JS_Window_ScreenToClient(trackview, x, y)
            reaper.JS_Composite(trackview, x, track_y, 1, item_h, bm, 0, 0, 1, 1)
        end
    end
    reaper.defer(loop)
end

reaper.atexit(function() if bm then reaper.JS_LICE_DestroyBitmap(bm) end end)
loop()
juliansader is offline   Reply With Quote
Old 04-07-2020, 07:11 PM   #1032
juliansader
Human being with feelings
 
Join Date: Jul 2009
Posts: 3,714
Default

Quote:
Originally Posted by amagalma View Post
What kind of objects should be deleted with JS_GDI_DeleteObject when exiting the script? Created by which APIs? If not deleted, does that mean a memory leak?
Any object, DC, bitmap or malloc-allocated memory that is not deleted, will accumulate during the session. However, the extension keeps track of all resources and automatically destroys them when REAPER closes. (REAPER and/or the OS would probably do it as well, but just to make doubly sure there are no memory leaks, the extension does it explicitly.)

Speaking of which... I realized today that, if REAPER is closed while deferred scripts are running, REAPER calls the extension's equivalent of the "atexit" function (which cleans up resources) *before* calling scripts' atexits. This is quite unexpected. The extension must therefore be careful to prevent scripts from trying to access resources that have already been destroyed. I have uploaded v1.001 that does so.
juliansader is offline   Reply With Quote
Old 04-07-2020, 07:20 PM   #1033
juliansader
Human being with feelings
 
Join Date: Jul 2009
Posts: 3,714
Default

Quote:
Originally Posted by _Stevie_ View Post
Sexan's work is coming along nicely. He is just fixing all the coordinates stuff for OS X. For the drawing (done via JS API) you need to switch the GUI mode from Metal to classic mode. You need to restart REAPER in order to apply the changes.

Bad news regarding macOS: In my own tests, I noticed lots of graphics glitches when using WDL/swell functions in "Force classic (10.5-10.9) drawing mode" too.

The only display mode that seems safe is "Disable all optimized drawing (reduces GPU usage)".

However... for some strange reason the glitches in classic mode can be suppressed by calling InvalidateRect over the entire window in every defer cycle. I have no idea why that is.

Last edited by juliansader; 04-07-2020 at 07:28 PM.
juliansader is offline   Reply With Quote
Old 04-07-2020, 07:48 PM   #1034
juliansader
Human being with feelings
 
Join Date: Jul 2009
Posts: 3,714
Default

Quote:
Originally Posted by Sexan View Post
I have some weirdness with 1.0:
...
This one stucks somewhere with redrawing/refreshing

The only difference in the code is Refresh_reaper(), on v1.0 is commented out since V1.0 has internal invalidate

Code:
Class script Line 103-106

function Element:draw(w,h)
    reaper.JS_Composite(track_window, self.x, self.y, self.w, self.h, self.bm, 0, 0, w, h)
    --Refresh_reaper()
end
Steps to reproduce:
1.Create multiple items like in gif
2. Create multiple selections (CTRL + SHIFT + DRAG)
3. Activate copy mode CRTL + C
4. Move items around
I could not replicate the problem on Windows or macOS, even with dozens of area selections. Which OS and display mode are you using? Does it always happen when you follow these steps, or only sometimes?
juliansader is offline   Reply With Quote
Old 04-07-2020, 10:00 PM   #1035
Sexan
Human being with feelings
 
Sexan's Avatar
 
Join Date: Jun 2009
Location: Croatia
Posts: 4,591
Default

Windows 10 x64, can replicate it every time. It only appears onmultiple selection but it seems to happenwhen cursor is over track 1 or above it.
Sexan is online now   Reply With Quote
Old 04-07-2020, 10:23 PM   #1036
Sexan
Human being with feelings
 
Sexan's Avatar
 
Join Date: Jun 2009
Location: Croatia
Posts: 4,591
Default



Here is the latest WIP (this is not on git) along with sample project in attachment.

Tested also with git version which does not include ghost optimizations I made in this version to eliminate problems in the new ghost code (even the ghost bitmaps are ok, areas bitmaps get corrupted)


How drawing code works:

Areas are only update when drawing (updates only latest one), and when there is a project change it updates all.

1. Ghosts - (git version) COPY MODE IS ON and are drawn all the time.
2. Ghosts - (this version) COPY MODE IS ON update all ghosts only one time per loop if there is project change or mouse change.

While ghosts are activated areas are not updated

The only difference between ghost and area drawing is W and H in Composite call:
Code:
area:draw(1,1) -- areas stretch 1 pixel
ghost:draw(ghost.info[1], ghost.info[2]) -- ghost use full bitmap W H

function Element:draw(w,h)
    reaper.JS_Composite(track_window, self.x, self.y, self.w, self.h, self.bm, 0, 0, w, h)
    --Refresh_reaper()
end
EDIT:
The problem goes away if I manually call Invalidate (only one time) after all drawing is done

Code:
function Draw(tbl)
  local is_view_changed = Arrange_view_info()
  if (copy or move) and check_mouse_change() then
    GHOST_UPDATE = true
  end
  if is_view_changed and not DRAWING then -- PROJECT UPDATED
    AREA_UPDATE = true
    GHOST_UPDATE = copy and true

    for i = #tbl, 1, -1 do
      if AREA_UPDATE then
        tbl[i]:update_xywh()
      end
    end
  elseif DRAWING and #tbl ~= 0 then -- UPDATE ONLY AS THAT IS DRAWING (LAST CREATED)
    tbl[#tbl]:draw(1,1)
  end
  Track(tbl)
 if AREA_UPDATE or GHOST_UPDATE then
  Refresh_reaper() <------ THIS GETS CALLED ONLY 1 TIME PER LOOP IF THERE IS A NEED FOR UPDATE
 end
  AREA_UPDATE = false
  GHOST_UPDATE = false
end

Btw my Invalidate refreshes the whole screen, I assume new composite function refreshes only the part where the bitmap is (since areas bitmap gets corrupted)?
Code:
function Refresh_reaper()
  reaper.JS_Window_InvalidateRect(track_window, 0, 0, 5000, 5000, false)
end
Class script, at the end of the script

Last edited by Sexan; 02-13-2023 at 08:15 AM.
Sexan is online now   Reply With Quote
Old 04-08-2020, 12:26 AM   #1037
Sexan
Human being with feelings
 
Sexan's Avatar
 
Join Date: Jun 2009
Location: Croatia
Posts: 4,591
Default

BTW regarding optimization I think this is pretty much it that can be done ?

Even making ghosts for unreal amount of items (700 items) takes 0% if they do not need any update and 7-8% CPU if you move them constantly around, and that is still well under than doing anything in Reaper.

For example empty project Reaper redraw CPU usage:
hand scroll arrange -> 12-15% CPU usage
Resize TCP area -> 12-20% CPU

Anything that needs reaper to redraw takes 10-20% CPU

Ryzen 1800x

Last edited by Sexan; 04-08-2020 at 12:31 AM.
Sexan is online now   Reply With Quote
Old 04-08-2020, 10:00 AM   #1038
Sexan
Human being with feelings
 
Sexan's Avatar
 
Join Date: Jun 2009
Location: Croatia
Posts: 4,591
Default

Julian is there a API to draw non filled rectangle or I need to do it manually with lines or rects?
Sexan is online now   Reply With Quote
Old 04-08-2020, 11:35 AM   #1039
juliansader
Human being with feelings
 
Join Date: Jul 2009
Posts: 3,714
Default

Quote:
Originally Posted by Sexan View Post
BTW regarding optimization I think this is pretty much it that can be done ?
I notice that the check_mouse_change function returns true whenever the mouse y position changes, which causes lots up extra updates. Perhaps the updates can be limited to when the y position moves into another media or envelope lane?


Quote:
Originally Posted by Sexan View Post
Julian is there a API to draw non filled rectangle or I need to do it manually with lines or rects?
RoundRect with radius = 0 will draw a non-filled rectangle.

Would you prefer if I make the new behaviour optional? I can add an optional boolean parameter to JS_Composite.
juliansader is offline   Reply With Quote
Old 04-08-2020, 11:42 AM   #1040
_Stevie_
Human being with feelings
 
_Stevie_'s Avatar
 
Join Date: Oct 2017
Location: Black Forest
Posts: 5,054
Default

@Julian

Sexan and I are pulling out our hair because of this refresh issue (flickering) which is only happening on Windows. Do you know if this is caused by REAPER itself or JS_API? And if you don't know: how could we find out?
__________________
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 06:38 AM.


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