Old 05-12-2019, 06:03 AM   #481
Sexan
Human being with feelings
 
Sexan's Avatar
 
Join Date: Jun 2009
Location: Croatia
Posts: 2,819
Default

@Julian

Is something like this possible?

Code:
local merge_bm = reaper.JS_LICE_CreateBitmap(true, 5000, 5000)
function test()
   for i = 1, #items do
      local item_bm[i]= reaper.JS_LICE_CreateBitmap(true, 1, 1)
      reaper.JS_LICE_FillRect(item_bm[i], item.x , item.y, item.w, item.h, 0x66557788, 1, "COPY" ) -- MAKE ITEM RECTANGLE
      reaper.JS_LICE_Blit( merge_bm, 0, 0, item_bm[i], 0, 0, 5000, 5000, 1, "COPY") -- BLIT ITEM RECTANGLE TO MERGE IMG
   end 
   reaper.JS_Composite(track_window, cursor.x , cursor.y, W, H, merge_bm, 0, 0, 1, 1)
end
So far I did not succeed, it just draws one big rectangle, but if its not possible I will stop trying. My code ATM draws and composites for every item.

Wanted to make envelope shadow also which I have coded, but drawing and compositing for every LICE line would not be a best thing...

Last edited by Sexan; 05-12-2019 at 06:10 AM.
Sexan is offline   Reply With Quote
Old 05-12-2019, 08:00 AM   #482
juliansader
Human being with feelings
 
Join Date: Jul 2009
Posts: 3,219
Default

I am not quite sure what you are trying to do, but these lines may be problematic:

In these, only the tiny 1-pixel corner of merge_bm is composited and stretched onto trackview, so the (track_window, cursor.x , cursor.y, W, H, merge_bm, 0, 0, 1, 1) should probably be (track_window, cursor.x , cursor.y, 5000, 5000, merge_bm, 0, 0, 5000, 5000):
Code:
local merge_bm = reaper.JS_LICE_CreateBitmap(true, 5000, 5000)

   reaper.JS_Composite(track_window, cursor.x , cursor.y, W, H, merge_bm, 0, 0, 1, 1)
end
In these lines, the FillRect is drawn far outside the boundaries of the bitmap, which is only 1 pixel wide, so nothing will happen:
Code:
    local item_bm[i]= reaper.JS_LICE_CreateBitmap(true, 1, 1)
    reaper.JS_LICE_FillRect(item_bm[i], item.x , item.y, item.w, item.h, 0x66557788, 1, "COPY" ) -- MAKE ITEM RECTANGLE
juliansader is offline   Reply With Quote
Old 05-12-2019, 08:16 AM   #483
Sexan
Human being with feelings
 
Sexan's Avatar
 
Join Date: Jun 2009
Location: Croatia
Posts: 2,819
Default



Instead of calling JS_Composite for every item in AS for example:
If there are 16 items JS_Composite will be called 16 times in loop, so if there are more items it will call it X times.

What I want is to minimize that and cpu usage and flickering (more items it has the flickering get more noticeable since it is looping it x times):
Build all items rectangles into one single image and then compose ONLY that one:

this is what I do atm:
Code:
for i = 1, x do
 item_bm = reaper.JS_LICE_CreateBitmap() -- create bitmap for item
 reaper.JS_Composite(item_bm) -- draw what bitmap
end
what I want is:
Code:
final_image = reaper.JS_LICE_CreateBitmap() -- bitmap where all the rectangles of all items will be
for i = 1, x do
 item_bm = reaper.JS_LICE_CreateBitmap() -- create bitmap for item
 reaper.JS_LICE_FillRect(item_bg) --fill that bitmap with rectangle
 reaper.JS_LICE_Blit(final_bm, item_bm) -- copy item bitmap to final image 
end
reaper.JS_Composite(final_bg) -- draw the final bitmap with all rectangles of all items, CALL IT ONLY ONCE
Since I'm still pretty bad with blitting, code above copies item_bm to final_mb?

this is the code I'm using now
Code:
local i_y, i_h, i_b = A[tostring(atrack)].t + t_h, A[tostring(atrack)].h + t_h, A[tostring(atrack)].b + t_h
        if not items_bm[i] then items_bm[i] = {} end
        for j = 1, #active_as.tracks[i].items do
          local item = active_as.tracks[i].items[j]
          if items_bm[i][j] == nil then items_bm[i][j] = reaper.JS_LICE_CreateBitmap(true, 1, 1); reaper.JS_LICE_Clear(items_bm[i][j], 0x66557788) end
          local new_item_start, new_item_lenght = as_item_position(item, active_as.sel_start, active_as.sel_end, mouse_time_pos)
          reaper.JS_Composite(track_window, math.floor(new_item_start * zoom_lvl) - Arr_pixel, (i_y - y_view_start), math.floor(new_item_lenght * zoom_lvl), i_b - i_y, items_bm[i][j], 0, 0, 1, 1)
        end
The code is available on my git,WIP folder draw_item_shadow() function so you can see what it does, just make selection over items

Last edited by Sexan; 05-12-2019 at 08:23 AM.
Sexan is offline   Reply With Quote
Old 05-12-2019, 08:31 AM   #484
juliansader
Human being with feelings
 
Join Date: Jul 2009
Posts: 3,219
Default

Quote:
Originally Posted by Sexan View Post
Instead of calling JS_Composite for every item in AS for example:
If there are 16 items JS_Composite will be called 16 times in loop, so if there are more items it will call it X times.
This is indeed possible, and easy. Simply draw new FillRects on the large bitmap, instead of creating new bitmaps:
Code:
bitmap = reaper.JS_LICE_CreateBitmap(true, 5000, 5000) -- bitmap where all the rectangles of all items will be
reaper.JS_Composite(trackview, 0, 0, 5000, 5000, bitmap, 0, 0, 5000, 5000) -- CALL IT ONLY ONCE

-- Whenever the mouse cursor position changes:
reaper.JS_LICE_Clear(bitmap, 0) -- CLEAR PREVIOUS FILLRECTS
for i = 1, totalNumberOfAreas do
    reaper.JS_LICE_FillRect(bitmap, area[i].x, area[i].y, area[i].w, area[i].h, someColor, 1, "COPY")
    -- DRAW SHADOWS AND OTHER LINES
end
I'm not sure that there will be less flicker (on WindowsOS), unfortunately. Fewer blitting function calls, but more pixels blitted in total.
juliansader is offline   Reply With Quote
Old 05-12-2019, 08:47 AM   #485
Sexan
Human being with feelings
 
Sexan's Avatar
 
Join Date: Jun 2009
Location: Croatia
Posts: 2,819
Default

Thank you very much, as for capturing part of the screen (capture item real images from reapers screen) I need to use GDI and bitmap_dc?
Sexan is offline   Reply With Quote
Old 05-12-2019, 09:13 AM   #486
juliansader
Human being with feelings
 
Join Date: Jul 2009
Posts: 3,219
Default

Yes: GDI_Blit is the link between the screen and LICE *sys*bitmaps.

(Under the hood, the Composite functions also use GDI blitting to copy the bitmaps onto the screen.)

If you would like to display "ghosts" of the contents of the AS while the user is mouse-dragging, you can use GDI blit to save each of the AS areas as a LICE bitmap, and then LICE_ScaledBlit to copy them onto the large bitmap discussed above (scaled to the height of the target track or envelope lane), or Composite each individually to the trackview.
juliansader is offline   Reply With Quote
Old 05-12-2019, 09:32 AM   #487
Sexan
Human being with feelings
 
Sexan's Avatar
 
Join Date: Jun 2009
Location: Croatia
Posts: 2,819
Default

Can you give me please short code example.... I'm getting white color only ...sorry this gdi/blitting/lice stuff is too much for my brain
Sexan is offline   Reply With Quote
Old 05-12-2019, 11:42 AM   #488
X-Raym
Human being with feelings
 
X-Raym's Avatar
 
Join Date: Apr 2013
Location: France
Posts: 6,605
Default

Quote:
Originally Posted by sexan
sorry this gdi/blitting/lice stuff is too much for my brain
You are way ahead of any other scripter on this topic ^^
X-Raym is offline   Reply With Quote
Old 05-12-2019, 02:34 PM   #489
juliansader
Human being with feelings
 
Join Date: Jul 2009
Posts: 3,219
Default

Quote:
Originally Posted by Sexan View Post
Can you give me please short code example.... I'm getting white color only ...sorry this gdi/blitting/lice stuff is too much for my brain
Here are examples for both options that I mentioned above.

While writing the examples, I realized that REAPER's windows (on WindowsOS, at least) don't have alpha information, which causes weirdness when trying blit them to and from LICE bitmaps that do use alpha. However, if you *first* blit a transparent bitmap onto the window, then suddenly that area does gain alpha info.

I will update the extension with new functions to change the alpha values of LICE bitmaps.

In the meantime, this example uses GDI_Blit to first copy a transparent rectangle onto the Area Select area, before copying it to the mouse position. (In you Area51 code, the AS areas will in any case already have transparent overlays.)



Code:
main = reaper.GetMainHwnd()
trackview = reaper.JS_Window_FindChildByID(main, 1000)
tvDC = reaper.JS_GDI_GetWindowDC(trackview)

-- JUST A QUICK HACK TO GET ALL TRACK Y COORDINATES, TO DEMONSTRATE SCALED BLIT
sOK, topVisiblePixel, pageSize, min, max, trackPos = reaper.JS_Window_GetScrollInfo(trackview, "VERT")
tvOK, tvLeft, tvTop, tvRight, tvBottom = reaper.JS_Window_GetRect(trackview)
bottomPixel = -topVisiblePixel
tT = {} -- TABLE OF TRACK INFO
if reaper.GetMasterTrackVisibility()&1 == 1 then
    track = reaper.GetMasterTrack(0)
    tT[track] = {top = bottomPixel}
    bottomPixel = bottomPixel + reaper.GetMediaTrackInfo_Value(track, "I_WNDH") + 5
    tT[track].bottom = bottomPixel
end
for t = 0, reaper.CountTracks(0)-1 do
    track = reaper.GetTrack(0, t)
    tT[track] = {top = bottomPixel}
    bottomPixel = bottomPixel + reaper.GetMediaTrackInfo_Value(track, "I_WNDH")
    tT[track].bottom = bottomPixel
end

-- UNLINK PREVIOUS BITMAPS
OK, list = reaper.JS_Composite_ListBitmaps(trackview)
for a in list:gmatch("[^,]+") do
    reaper.JS_Composite_Unlink(trackview, reaper.JS_Window_HandleFromAddress(a))
end

-- LET'S ASSUME THERE IS ONE AREA SELECT ON TRACK 0, WITH WIDTH 200 PIXELS. DRAW THIS RECTANGLE ON SCREEN
-- !!! REAPER'S WINDOWS DON'T HAVE ALPHA INFO PER DEFAULT. THIS BLIT WILL PROVIDE THEM WITH ALPHA INFO !!!
bm1 = reaper.JS_LICE_CreateBitmap(true, 1, 1)
bm1DC = reaper.JS_LICE_GetDC(bm1)
reaper.JS_LICE_Clear(bm1, 0x40400000)
sourceTrack = reaper.GetTrack(0, 0)
sourceHeight = tT[sourceTrack].bottom-tT[sourceTrack].top
ASWidth = 200
reaper.JS_GDI_StretchBlit(tvDC, 0, tT[sourceTrack].top, ASWidth, sourceHeight, bm1DC, 0, 0, 1, 1, "ALPHA")


-- NOW FOR DEMONSTRATING COPYING GHOSTS TO MOUSE POSITION

-- COPY AREA SELECT CONTENTS TO A LICE BITMAP
ghost1 = reaper.JS_LICE_CreateBitmap(true, ASWidth, sourceHeight)
reaper.JS_LICE_Clear(ghost1, 0)
ghost1DC = reaper.JS_LICE_GetDC(ghost1)
reaper.JS_GDI_Blit(ghost1DC, 0, 0, tvDC, 0, tT[sourceTrack].top, ASWidth, sourceHeight)
--pix = string.format("%x", reaper.JS_LICE_GetPixel(ghost1, 20, 20)&0xffffffff)


-- OPTION 1: COMPOSITE EACH AREA SELECT SUB-AREA SEPARATELY
--[[
function loop()
    if reaper.JS_Mouse_GetState(1) ~= 1 then -- QUIT WHEN LEFT-CLICK
        x, y = reaper.GetMousePosition()
        if x ~= prevX or y ~= prevY then
            prevX, prevY = x, y
            track = reaper.GetTrackFromPoint(x, y)
            if track then
                x, y = x-tvLeft, y-tvRight -- CONVERT TO RELATIVE CLIENT COORDINATES
                reaper.JS_Composite(trackview, x, tT[track].top, ASWidth, tT[track].bottom-tT[track].top, ghost1, 0, 0, ASWidth, sourceHeight) -- STRETCH TO FIT TARGET TRACK
                reaper.JS_Window_InvalidateRect(trackview, 0, 0, 1, 1, true) -- INVALIDATE COORDINATES DON'T MATTER FOR COMPOSITE: COMPOSITE WILL UPDATE ENTIRE WINDOW
            end
        end
        reaper.defer(loop) 
    end
end
]]

-- OPTION 2: USE SINGLE LARGE CANVAS
--
canvas = reaper.JS_LICE_CreateBitmap(true, 5000, 5000) -- LARGE ENOUGH TO COVER ENTIRE TRACKVIEW
cOK = reaper.JS_Composite(trackview, 0, 0, 5000, 5000, canvas, 0, 0, 5000, 5000) -- I DON'T THINK IT MATTERS IF THE COMPOSITE SIZES ARE LARGER THAN THE ACTUAL WINDOWS
function loop()
    if reaper.JS_Mouse_GetState(1) ~= 1 then -- QUIT WHEN LEFT-CLICK
        x, y = reaper.GetMousePosition()
        if x ~= prevX or y ~= prevY then
            prevX, prevY = x, y
            track = reaper.GetTrackFromPoint(x, y)
            if track then
                x, y = x-tvLeft, y-tvRight -- CONVERT TO RELATIVE CLIENT COORDINATES
                reaper.JS_LICE_Clear(canvas, 0) -- CLEAR PREVIOUS CONTENT TO TRANSPARENT
                reaper.JS_LICE_ScaledBlit(canvas, x, tT[track].top, ASWidth, tT[track].bottom-tT[track].top, ghost1, 0, 0, ASWidth, sourceHeight, 1, "COPY") -- STRETCH TO FIT TARGET TRACK
                reaper.JS_Window_InvalidateRect(trackview, 0, 0, 1, 1, true) -- INVALIDATE COORDINATES DON'T MATTER FOR COMPOSITE: COMPOSITE WILL UPDATE ENTIRE WINDOW
            end
        end
        reaper.defer(loop)
    end
end

function atexit()
    if ghost1 then reaper.JS_LICE_DestroyBitmap(ghost1) end -- DESTROYING BITMAP WILL AUTOMATICAAL UNLINK TOO
    if bm1 then reaper.JS_LICE_DestroyBitmap(bm1) end
    if canvas then reaper.JS_LICE_DestroyBitmap(canvas) end
    if tvDC then reaper.JS_GDI_ReleaseDC(trackview, tvDC) end
    reaper.JS_Window_InvalidateRect(trackview, 0, 0, 5000, 5000, true)
end

reaper.atexit(atexit)

-- WAIT FOR MOUSE CLICK BEFORE STARTING
while reaper.JS_Mouse_GetState(1) ~= 1 do end
while reaper.JS_Mouse_GetState(1) == 1 do end
loop()

Last edited by juliansader; 05-12-2019 at 03:04 PM.
juliansader is offline   Reply With Quote
Old 05-12-2019, 03:35 PM   #490
Sexan
Human being with feelings
 
Sexan's Avatar
 
Join Date: Jun 2009
Location: Croatia
Posts: 2,819
Default

Sorry need to ask....

Code:
tT[track] = {top = bottomPixel}
so this is actually working no matter tT is reported as 0 (in IDE)?

I converted them to string since I thought its not getting user data as a key

again thank you veeeeeeeery much for your help

Last edited by Sexan; 05-12-2019 at 03:46 PM.
Sexan is offline   Reply With Quote
Old 05-12-2019, 03:53 PM   #491
juliansader
Human being with feelings
 
Join Date: Jul 2009
Posts: 3,219
Default

Quote:
Originally Posted by Sexan View Post
so this is actually working no matter there is no value and tT is reported as 0 (in IDE)?
Yes - Lua tables can use any type of variable as a key.

Hmmm... I'm not sure how the IDE calculates the size. It seems to ignore some types of keys. (The IDE also only displays string up to the first \0, and truncates long floating point numbers.)
juliansader is offline   Reply With Quote
Old 05-12-2019, 04:00 PM   #492
Sexan
Human being with feelings
 
Sexan's Avatar
 
Join Date: Jun 2009
Location: Croatia
Posts: 2,819
Default

Yeah I know it can use anything for key but that table calculation got me... oh well, need to fix some stuff now
Sexan is offline   Reply With Quote
Old 05-13-2019, 03:30 AM   #493
Sexan
Human being with feelings
 
Sexan's Avatar
 
Join Date: Jun 2009
Location: Croatia
Posts: 2,819
Default

Julian is this the best we can get from the image (its not exact copy of whats on the screen, its washed out, little hard to see)?
Its transparency is depended on AS transparency? Want stronger peak color/contrast, I know I can only manipulate with whole image



Code:
local function get_item_blit(tbl, as_tr, as_start, as_end)
  if not tbl then return end
  local zoom_lvl, Arr_start_time, Arr_end_time, Arr_pixel, x_view_start, y_view_start, x_view_end, y_view_end, state, scroll = project_info() 
  local items_bm = {}
  local item_bar = 15
  for i = 1, #tbl do
    items_bm[i] = {}
    local item_t, item_h, item_b = A[as_tr].t, A[as_tr].h, A[as_tr].b
    local item_start, item_lenght = item_blit(tbl[i], as_start, as_end)
    items_bm[i].item_bm = reaper.JS_LICE_CreateBitmap(true, math.floor(item_lenght * zoom_lvl), item_h)
    items_bm[i].dc = reaper.JS_LICE_GetDC(items_bm[i].item_bm)
    reaper.JS_LICE_Clear(items_bm[i].item_bm, 0)
    reaper.JS_GDI_Blit(items_bm[i].dc, 0, 0, track_window_dc, math.floor(item_start * zoom_lvl) - Arr_pixel, ((item_t+item_bar) - y_view_start), math.floor(item_lenght * zoom_lvl), item_h-19) -- (-19 TO COMPENSATE ITEM BAR REMOVING)
  end
  return items_bm
end

Last edited by Sexan; 05-13-2019 at 03:38 AM.
Sexan is offline   Reply With Quote
Old 05-13-2019, 03:46 AM   #494
juliansader
Human being with feelings
 
Join Date: Jul 2009
Posts: 3,219
Default

I will soon add some functions to the extension to manipulate alpha and other colors.

In the meantime, you can increase a bitmap's alpha by blitting onto it another bitmap with "ADD" option. ADD adds the values of each channel (A, R, G, B) separately for each pixel:
Code:
-- AS_bitmap is the target Area Select bitmap
alpha_bitmap = reaper.JS_LICE_CreateBitmap(true, 1, 1)
reaper.JS_LICE_Clear(alpha_bitmap, 0xFF000000) -- This value will added to ASbm
reaper.JS_LICE_ScaledBlit(AS_bitmap, 0, 0, w, h, alpha_bitmap, 0, 0, 1, 1, 1, "ADD")
I only discovered this trick today, after experimenting with the blitting modes. My previous examples would have been better if I used this.

"MUL" mode can be used to lower the brightness of each channel separately.

I'm not quite sure yet what "HSVADJ" and "MASK" do on a bitwise level.

Last edited by juliansader; 05-13-2019 at 04:02 AM.
juliansader is offline   Reply With Quote
Old 05-13-2019, 04:22 AM   #495
Sexan
Human being with feelings
 
Sexan's Avatar
 
Join Date: Jun 2009
Location: Croatia
Posts: 2,819
Default

I will wait for your update so I do not add unnecessary code which I will probably forget later (the script is not yet in "usable" state so it wont mind this little graphics drawbacks atm.

Anyway this is pretty cool

You are the great blitting magician!!
Sexan is offline   Reply With Quote
Old 05-14-2019, 08:23 PM   #496
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,551
Default

- I imagine a number of the window functions shouldn't be expected to work on Linux, right? AttachTopmostPin isn't doing anything here, at any rate.

Edit: It's not working on Windows 8 for me either. I'm getting valid HWND from Window_Find, calling AttachTopmostPin... nothing happens. Just for fun I tried setting Window_Find to exact, and it still didn't work, but it also sent Reaper's main window to the very back.

- I'm getting errors when I try to use reaper.JS_Window_SetZOrder(hwnd, "TOPMOST"). If I don't provide the third parameter it gets mad, but if I provide the third parameter it crashes with 'reaper.JS_Window_SetZOrder' argument 3: expected void*.
__________________
I'm no longer using Reaper or working on scripts for it. Sorry. :(
Default 5.0 Nitpicky Edition / GUI library for Lua scripts / Theory Helper / Radial Menu / Donate

Last edited by Lokasenna; 05-14-2019 at 08:50 PM.
Lokasenna is offline   Reply With Quote
Old 05-15-2019, 01:29 AM   #497
Sexan
Human being with feelings
 
Sexan's Avatar
 
Join Date: Jun 2009
Location: Croatia
Posts: 2,819
Default

Julian is there any way to "flush" VK keys got with JS_VKeys_GetState()? Sometimes they got stuck and script gets their state as pressed even they are not so while is script is running you need to press every stucked one to reset its state. It mostly happens when script crashes but also some other times which I cannot reliably reproduce. I'm making setup script which will intercept only keys that are selected, but sometimes they are falsely triggered

https://github.com/GoranKovac/ReaScr...a_51_Setup.lua

The script


This is what I have when the the script crashes.

On script restart it thinks all of this keys are pressed

Last edited by Sexan; 05-15-2019 at 01:44 AM.
Sexan is offline   Reply With Quote
Old 05-15-2019, 04:38 AM   #498
juliansader
Human being with feelings
 
Join Date: Jul 2009
Posts: 3,219
Default

Quote:
Originally Posted by Sexan View Post
Julian is there any way to "flush" VK keys got with JS_VKeys_GetState()? Sometimes they got stuck and script gets their state as pressed even they are not so while is script is running you need to press every stucked one to reset its state.
This is exactly why I needed to add the cutoffTime parameter. For example, you can use GetState/Down(-0.5) at the beginning of the script to get only those keys that were pressed immediately before the script started, and GetState/Down(prevTime) to get keys that were pressed since the previous defer cycle.
juliansader is offline   Reply With Quote
Old 05-15-2019, 05:31 AM   #499
Sexan
Human being with feelings
 
Sexan's Avatar
 
Join Date: Jun 2009
Location: Croatia
Posts: 2,819
Default

I'm not sure about second part, I need to count defer cycles via time_precise and then use that as time? Could you give example code?
Sexan is offline   Reply With Quote
Old 05-16-2019, 04:28 PM   #500
X-Raym
Human being with feelings
 
X-Raym's Avatar
 
Join Date: Apr 2013
Location: France
Posts: 6,605
Default

@juliansader
Can you remember me,
We can have GFW window without titlebar with this script right ?
How do you remove title bar ?

THX !
X-Raym is offline   Reply With Quote
Old 05-18-2019, 03:59 AM   #501
juliansader
Human being with feelings
 
Join Date: Jul 2009
Posts: 3,219
Default

Quote:
Originally Posted by Sexan View Post
I will wait for your update so I do not add unnecessary code which I will probably forget later (the script is not yet in "usable" state so it wont mind this little graphics drawbacks atm.
I have uploaded v0.987 with some new functions and options for color processing LICE bitmaps:
* LICE_Blit options "BLUR", "ALPHAMUL" and "CHANCOPY_XTOY"
* LICE_ProcessRect
* LICE_AlterRect/BitmapHSV

You can use LICE_ProcessRect with SET_A to set the alpha of the ghosts, and AlterHSV to change the hues.

NOTE: I realized that Windows' GDI_Blit function doesn't do alpha multiplication of the source pixels on the fly while blitting, unlike the Linux and OSX functions. If it is important to get exactly the same color rendering on Windows as on Linux/OSX, the source bitmap must be pre-multiplied with alpha.


Quote:
Originally Posted by X-Raym View Post
@juliansader
We can have GFW window without titlebar with this script right ?
How do you remove title bar ?
This is something that I've wanted to do for a long time, but unfortunately, I couldn't figure it out. On Windows, it is possible to remove the frames of REAPER's script GUIs, but it leaves ugly artefacts.


Quote:
Originally Posted by Lokasenna View Post
- I imagine a number of the window functions shouldn't be expected to work on Linux, right?
Hopefully only a few. Thanks for testing and please let me know if you find any other Linux problems! I have updated the API help docs.


Quote:
Originally Posted by Lokasenna View Post
AttachTopmostPin isn't doing anything here, at any rate.
Edit: It's not working on Windows 8 for me either.
This is unexpected. I wonder if anyone else has tried it on Windows 8? (It works on Windows 7 x64 and OSX High Sierra x64.)

The HWND must be a top-level, framed window. For example:
Code:
gfx.init("qwerty", 200, 200, 0, 200, 200)
w = reaper.JS_Window_Find("qwerty", true)
reaper.JS_Window_AttachTopmostPin(w)

Quote:
Originally Posted by Lokasenna View Post
- I'm getting errors when I try to use reaper.JS_Window_SetZOrder(hwnd, "TOPMOST"). If I don't provide the third parameter it gets mad, but if I provide the third parameter it crashes with 'reaper.JS_Window_SetZOrder' argument 3: expected void*
In TOPMOST mode, the extension ignores the third parameter, but REAPER still requires it, so you can simply use the same HWND as in the first parameter. (I tried to convince REAPER to make the third parameter optional, but apparently REAPER doesn't like optional void* parameters.)
juliansader is offline   Reply With Quote
Old 05-18-2019, 04:09 AM   #502
Dafarkias
Human being with feelings
 
Dafarkias's Avatar
 
Join Date: Feb 2019
Location: Spankland
Posts: 564
Default

I know how stingy everyone is with their time in regards to answering the pedantic questions of the lowly, but:

Is there any itemized documentation regarding your functions and updates to? I looked on your github and even made three google searches* and couldn't find much.

Currently, it seems like the bulk info regarding usage of your extensions come from X-Raym's phenomenal website-utility, https://www.extremraym.com/cloud/reascript-doc/.

*I'll send you an invoice, for my time...
Dafarkias is offline   Reply With Quote
Old 05-18-2019, 04:30 AM   #503
Sexan
Human being with feelings
 
Sexan's Avatar
 
Join Date: Jun 2009
Location: Croatia
Posts: 2,819
Default

Awesome thank you! If its not too much trouble can you please help me with that VK_Key cutoff (2 posts above you)? Not sure how the code should look like
Sexan is offline   Reply With Quote
Old 05-18-2019, 04:55 AM   #504
juliansader
Human being with feelings
 
Join Date: Jul 2009
Posts: 3,219
Default

Quote:
Originally Posted by Dafarkias View Post
I know how stingy everyone is with their time in regards to answering the pedantic questions of the lowly, but:

Is there any itemized documentation regarding your functions and updates to? I looked on your github and even made three google searches* and couldn't find much.

Currently, it seems like the bulk info regarding usage of your extensions come from X-Raym's phenomenal website-utility,
The idea behind this extension is to make all the useful and powerful functions that are available to C++ extensions available to ReaScripts too. The online documentation for the corresponding C++ functions is therefore the best place to learn how to use these functions. For example, Window messages and Drawing with GDI.

Cockos's own LICE and swell C++ functions are not so extensively documented, and you will unfortunately have to browse through the "ReaScript, JSFX, REAPER Plug-in Extensions, Developer" subforum as well as the "WDL users" subforum.

For functions that do not have direct C++ equivalents, such as JS_Composite, the best (and only) source of information is this and other discussion threads.

You can also get a better idea of what's going on under the hood by checking the source code on github.

The information on X-Raym's website can also be accessed through REAPER itself, by running the action "ReaScript: Open reaScript documentation". (X-Raym's website is much better formatted, of course.)
juliansader is offline   Reply With Quote
Old 05-18-2019, 05:10 AM   #505
juliansader
Human being with feelings
 
Join Date: Jul 2009
Posts: 3,219
Default

Quote:
Originally Posted by Sexan View Post
Awesome thank you! If its not too much trouble can you please help me with that VK_Key cutoff (2 posts above you)? Not sure how the code should look like
How do you intend the keyboard control for Area(51) to work, ideally?

My own js_Mouse editing script are somewhat unusual, since they only use keystrokes to terminate, and in two ways: 1) if any key is pressed, the scripts terminates; 2) if the shortcut key is held down for more than 0.5 second, it becomes similar to a "left drag", and the scripts terminates when the keys are released. I use the following code:

Some preparatory stuff:
Code:
-- The script will intercept keystrokes, to allow control of script via keyboard, 
--    and to prevent inadvertently running other actions such as closing MIDI editor by pressing ESC
local VKLow, VKHi = 8, 0xFE --0xA5 -- Range of virtual key codes to check for key presses
local VKState0 = string.rep("\0", VKHi-VKLow+1) -- For quick comparison to zero state
local dragTime = 0.5 -- How long must the shortcut key be held down before left-drag is activated?
local dragTimeStarted = false
At the start of the script:
Code:
    -- GET MOUSE AND KEYBOARD STARTING STATE:
    -- as soon as possible.  Hopefully, if script is started with mouse click, mouse button will still be down.
    -- VKeys_Intercept is also urgent, because must prevent multiple WM_KEYDOWN message from being sent, which may trigger script termination.
    interceptKeysOK = (reaper.JS_VKeys_Intercept(-1, 1) > 0)
        if not interceptKeysOK then reaper.MB("Could not intercept keyboard input.", "ERROR", 0) return false end
    mouseState = reaper.JS_Mouse_GetState(0xFF)    
    mouseOrigX, mouseOrigY = reaper.GetMousePosition()
    startTime = reaper.time_precise()
    prevMouseTime = startTime + 0.5 -- In case mousewheel sends multiple messages, don't react to messages sent too closely spaced, so wait till little beyond startTime.
    keyState = reaper.JS_VKeys_GetState(-2):sub(VKLow, VKHi) -- Ignore keys that were pressed more than 2 second ago.
and then at the start of each defer cycle:
Code:
    -- Must the script terminate?
    -- There are several ways to terminate the script:  Any keystroke or mouse button will terminate the script;
    --   except unmodified middle button and unmodified mousewheel, which toggles or scrolls through options, respectively.
    -- Also, the script will terminate if the shortcut key is held down and only released *after* dragTime.
    -- This gives the user flexibility to control the script via keyboard or mouse, as desired.
    local prevCycleTime = thisCycleTime or startTime
    thisCycleTime = reaper.time_precise()
    dragTimeStarted = dragTimeStarted or (thisCycleTime > startTime + dragTime)
    
    -- KEYBOARD: Script can be terminated by pressing key twice to start/stop, or by holding key and releasing after dragTime
    local prevKeyState = keyState
    keyState = reaper.JS_VKeys_GetState(startTime-2):sub(VKLow, VKHi)
    if dragTimeStarted and keyState ~= prevKeyState and keyState == VKState0 then -- Only lift after every key has been lifted, to avoid immediately trigger action again. NOTE: modifier keys don't always send repeat KEYDOWN if held together with another key.
        return false
    end
    local keyDown = reaper.JS_VKeys_GetDown(prevCycleTime):sub(VKLow, VKHi)
    if keyDown ~= prevKeyState and keyDown ~= VKState0 then
        local p = 0
        ::checkNextKeyDown:: do
            p = keyDown:find("\1", p+1)
            if p then 
                if prevKeyState:byte(p) == 0 then 
                    return false 
                else 
                    goto checkNextKeyDown 
                end
            end
        end
    end
juliansader is offline   Reply With Quote
Old 05-18-2019, 05:34 AM   #506
Sexan
Human being with feelings
 
Sexan's Avatar
 
Join Date: Jun 2009
Location: Croatia
Posts: 2,819
Default

well the plan is :

1. Users setup their modifiers and keys via setup script (split,delete,move,resize,stretch envelopes etc)

2 Script makes table of all the key/keys group

2. While AS is active/drawn it will intercepts all the keys in that table

3. If key/key group is pressed (Ctrl+a, Ctrl+Shift + v, Ctrl + xy, or any combination made in setup script) and it will trigger corresponding function (split,delete whatever)

4. If there is no AS on the screen then it will release all intercepts

Basically it will intercept keys while there is AS on screen
Sexan is offline   Reply With Quote
Old 05-18-2019, 07:13 AM   #507
_Stevie_
Human being with feelings
 
_Stevie_'s Avatar
 
Join Date: Oct 2017
Posts: 3,821
Default

@Julian, is there any way to detect a touchscreen press with JS_MouseGetState()? I haven't found the right flag for it.
__________________
My Reascripts forum thread | My Reascripts on GitHub
If you wish to donate for my scripts: please consider an organization like: animal shelter, doctors without borders, UNICEF, etc...
_Stevie_ is online now   Reply With Quote
Old 05-18-2019, 01:40 PM   #508
mespotine
Human being with feelings
 
mespotine's Avatar
 
Join Date: May 2017
Location: Leipzig, Germany
Posts: 2,133
Default

Since JS-extension has measuring of texts-functions now, how do I use them?
I would want to attempt a version of GetUserInputs, that automatically adjusts to the text given as captions and default-input-boxes, but need to know, how long the caption-strings are actually in pixels.
__________________
Use she/her, when contacting me, please. Thanks :) Not mentoring via PMs, sorry.
Ultraschall-API - 1200 ReaScript functions for Reaper - Reaper Internals - Developerdocs4Reaper - Donate, if you want
mespotine is offline   Reply With Quote
Old 05-18-2019, 01:41 PM   #509
mespotine
Human being with feelings
 
mespotine's Avatar
 
Join Date: May 2017
Location: Leipzig, Germany
Posts: 2,133
Default

Quote:
Originally Posted by lb0 View Post
WOW!! What a HUGE list! Thank you for your hard work on this - this will be invaluable!
Thanks
__________________
Use she/her, when contacting me, please. Thanks :) Not mentoring via PMs, sorry.
Ultraschall-API - 1200 ReaScript functions for Reaper - Reaper Internals - Developerdocs4Reaper - Donate, if you want
mespotine is offline   Reply With Quote
Old 05-18-2019, 03:14 PM   #510
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,551
Default

Quote:
Originally Posted by juliansader View Post
Hopefully only a few. Thanks for testing and please let me know if you find any other Linux problems! I have updated the API help docs.
I would actually be surprised if they all work, as window decorations are handled very differently in Linux and the various window managers a user might be running. Reaper doesn't even have a right-click menu on the titlebar for a script window, for example.

Quote:
This is unexpected. I wonder if anyone else has tried it on Windows 8? (It works on Windows 7 x64 and OSX High Sierra x64.)

The HWND must be a top-level, framed window. For example:
Code:
gfx.init("qwerty", 200, 200, 0, 200, 200)
w = reaper.JS_Window_Find("qwerty", true)
reaper.JS_Window_AttachTopmostPin(w)
That's pretty much what I have. Normal script window, same variable for the window title and the Find string. It does find a valid HWND, it just doesn't add a pin.

Quote:
In TOPMOST mode, the extension ignores the third parameter, but REAPER still requires it, so you can simply use the same HWND as in the first parameter. (I tried to convince REAPER to make the third parameter optional, but apparently REAPER doesn't like optional void* parameters.)
Fair enough. This would definitely be worth specifying in the docs, if you haven't already, since any functions with optional parameters will need something type-appropriate passed in as a placeholder.
__________________
I'm no longer using Reaper or working on scripts for it. Sorry. :(
Default 5.0 Nitpicky Edition / GUI library for Lua scripts / Theory Helper / Radial Menu / Donate
Lokasenna is offline   Reply With Quote
Old 05-20-2019, 06:00 AM   #511
juliansader
Human being with feelings
 
Join Date: Jul 2009
Posts: 3,219
Default

Quote:
Originally Posted by _Stevie_ View Post
@Julian, is there any way to detect a touchscreen press with JS_MouseGetState()? I haven't found the right flag for it.
I don't know. If the touchscreen sends standard mouse messages, Mouse_GetState or VKeys might be able to detect it, but AFAIK touchscreens send other kinds of messages such as WM_TOUCH.

I don't have a touchscreen to test myself, but perhaps someone else can? If the touchscreen sends any kind of WM_ message to a REAPER window, it should be possible to detect it with the WindowMessage functions.
juliansader is offline   Reply With Quote
Old 05-20-2019, 06:06 AM   #512
Sexan
Human being with feelings
 
Sexan's Avatar
 
Join Date: Jun 2009
Location: Croatia
Posts: 2,819
Default

Quote:
Originally Posted by juliansader View Post
I don't know. If the touchscreen sends standard mouse messages, Mouse_GetState or VKeys might be able to detect it, but AFAIK touchscreens send other kinds of messages such as WM_TOUCH.

I don't have a touchscreen to test myself, but perhaps someone else can? If the touchscreen sends any kind of WM_ message to a REAPER window, it should be possible to detect it with the WindowMessage functions.
It works here out of the box, I have XPS 13 with touch screen and it JUST works,no additional configuration


Nothing changed in the code, It receives responds from JS_MOUSE_STATE

Last edited by Sexan; 05-20-2019 at 06:12 AM.
Sexan is offline   Reply With Quote
Old 05-20-2019, 07:10 AM   #513
juliansader
Human being with feelings
 
Join Date: Jul 2009
Posts: 3,219
Default

Quote:
Originally Posted by mespotine View Post
Since JS-extension has measuring of texts-functions now, how do I use them?
I would want to attempt a version of GetUserInputs, that automatically adjusts to the text given as captions and default-input-boxes, but need to know, how long the caption-strings are actually in pixels.
Unfortunately I'm not sure if any of the extension function are relevant for measuring text for GetUserInputs.

It would be great if you could somehow tweak the width of the GetUserInputs dialog box! How do you intend to do it?

BTW, as far as I can tell, on WindowsOS, GetUserInputs uses dialog box resource #436, with a logical font "MS Shell Dlg" and font size 8. However, the pixel width differ between Windows and Linux.
juliansader is offline   Reply With Quote
Old 05-20-2019, 08:13 AM   #514
_Stevie_
Human being with feelings
 
_Stevie_'s Avatar
 
Join Date: Oct 2017
Posts: 3,821
Default

Hey Julian and Sexan,

yes, touch screen works in Reaper.

But I would like to try if Reaper can catch the WM_TOUCH message
and then send a click to a window WITHOUT stealing the focus of the currently
activated window.

@Julian, tried the Peek function. Apparently WM_TOUCH is not deteced. What a pity.

EDIT: is there a way to listen for ALL window messages, without checking for a specific one?
__________________
My Reascripts forum thread | My Reascripts on GitHub
If you wish to donate for my scripts: please consider an organization like: animal shelter, doctors without borders, UNICEF, etc...

Last edited by _Stevie_; 05-20-2019 at 08:50 AM.
_Stevie_ is online now   Reply With Quote
Old 05-20-2019, 08:57 AM   #515
mespotine
Human being with feelings
 
mespotine's Avatar
 
Join Date: May 2017
Location: Leipzig, Germany
Posts: 2,133
Default

Quote:
Originally Posted by _Stevie_ View Post
Hey Julian and Sexan,

yes, touch screen works in Reaper.

But I would like to try if Reaper can catch the WM_TOUCH message
and then send a click to a window WITHOUT stealing the focus of the currently
activated window.

@Julian, tried the Peek function. Apparently WM_TOUCH is not deteced. What a pity.

EDIT: is there a way to listen for ALL window messages, without checking for a specific one?
If manage to do that completely, could you write a small tutorial on that one into the Reaper-Internals-thread? We might have use for touch-stuff in our Ultraschall-extension
__________________
Use she/her, when contacting me, please. Thanks :) Not mentoring via PMs, sorry.
Ultraschall-API - 1200 ReaScript functions for Reaper - Reaper Internals - Developerdocs4Reaper - Donate, if you want
mespotine is offline   Reply With Quote
Old 05-20-2019, 09:02 AM   #516
mespotine
Human being with feelings
 
mespotine's Avatar
 
Join Date: May 2017
Location: Leipzig, Germany
Posts: 2,133
Default

Quote:
Originally Posted by juliansader View Post
Unfortunately I'm not sure if any of the extension function are relevant for measuring text for GetUserInputs.

It would be great if you could somehow tweak the width of the GetUserInputs dialog box! How do you intend to do it?

BTW, as far as I can tell, on WindowsOS, GetUserInputs uses dialog box resource #436, with a logical font "MS Shell Dlg" and font size 8. However, the pixel width differ between Windows and Linux.
My current approach is to work with a background-script, that I start before opening the GetUserInput-dialog, which reads all the attributes from the window and childhwnds.
This works already for catching the text the user input into the inputboxes to circumvent the csv-retval-problem.
I would just use that script as well to automatically adjust the length of the dialog-boxes and their correct position, including window-size.
With the length of the text, I could autosize it, otherwise, I would need to let the user decide on that one.

I also think about adding the feature, that when a caption ends with a \n, I would move the inputbox to the next line, giving the caption full width of the window.
So the width would not be split into two fields(caption and inputbox) but rather full width for both.

Edit: is there a way to get the currently used font in a hwnd?
__________________
Use she/her, when contacting me, please. Thanks :) Not mentoring via PMs, sorry.
Ultraschall-API - 1200 ReaScript functions for Reaper - Reaper Internals - Developerdocs4Reaper - Donate, if you want
mespotine is offline   Reply With Quote
Old 05-20-2019, 10:55 AM   #517
nofish
Human being with feelings
 
nofish's Avatar
 
Join Date: Oct 2007
Location: home is where the heart is
Posts: 9,789
Default

Quote:
Originally Posted by tparker24 View Post
Although I don't know much about Perl or C, I muddled through somehow and was able to cobble together the python interface file needed for python users. I'm calling it JS_ReaScriptAPI.py

You need to place it in your Plugins (not UserPlugins) directory. For example, in my portable install it goes in: D:\REAPER\Plugins

Then, in your python script, you need to have an import like: from JS_ReaScriptAPI import *


Here's my little python test script:
Code:
from JS_ReaScriptAPI import *
v = JS_ReaScriptAPI_Version(0)
RPR_ShowConsoleMsg(v)
This is unofficial, and there are no guarantees, but it works fine in my little test script.

Attached is the txt file (916 lines), which you need to rename to: JS_ReaScriptAPI.py
Attachment 35525

Hope this helps, but let me know if I've encroached on the author!

- Tom
Since above one probably got a bit outdated meanwhile, here's one generated fron v0.987:
https://stash.reaper.fm/v/36404/js_ReaScriptAPI.py

(Btw. the Python function wrappers file can be created rather easily using the Pearl scripts SWS is also using.)

Last edited by nofish; 05-20-2019 at 11:19 AM.
nofish is offline   Reply With Quote
Old 05-20-2019, 12:38 PM   #518
Sexan
Human being with feelings
 
Sexan's Avatar
 
Join Date: Jun 2009
Location: Croatia
Posts: 2,819
Default

Edit... my bad

Last edited by Sexan; 05-20-2019 at 12:47 PM.
Sexan is offline   Reply With Quote
Old 05-20-2019, 12:52 PM   #519
_Stevie_
Human being with feelings
 
_Stevie_'s Avatar
 
Join Date: Oct 2017
Posts: 3,821
Default

Quote:
Originally Posted by mespotine View Post
If manage to do that completely, could you write a small tutorial on that one into the Reaper-Internals-thread? We might have use for touch-stuff in our Ultraschall-extension
I will! At the moment I don't have high hopes for that, though.
__________________
My Reascripts forum thread | My Reascripts on GitHub
If you wish to donate for my scripts: please consider an organization like: animal shelter, doctors without borders, UNICEF, etc...
_Stevie_ is online now   Reply With Quote
Old 05-20-2019, 01:11 PM   #520
juliansader
Human being with feelings
 
Join Date: Jul 2009
Posts: 3,219
Default

Quote:
how do you revert bitmap to its original state/color?
I'm trying JS_LICE_AlterBitmapHSV
Besides the obvious solution of just saving the original bitmap and switching between them, you can use any invertible transformation. AFAIK, in the case of HSV, saturation and value aren't reversible, since they can bump against max and min values. Hue, on the other hand, is a continuous ring that will wrap around when it reaches the maximum, so if you use AlterHSV with any +hue, just use -hue to revert the change.

Another option is to use ProcessRect in XOR mode, since XOR is invertible. Just XOR with any number (0x00FFFFFF will nicely invert the colors without changing alpha) and then XOR again to revert.
juliansader 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 11:24 AM.


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