|
|
|
08-19-2021, 04:50 AM
|
#1601
|
Human being with feelings
Join Date: May 2019
Location: Berlin
Posts: 2,202
|
I managed to answer my own question. It's not even necessary to move the mouse, you can just send a 'WM_MOUSEFIRST' message and the time selection will show immediately (in the same defer cycle).
Here's the resulting function for anyone interested:
Code:
function MediaExplorer_GetTimeSelection()
local mx_title = reaper.JS_Localize('Media Explorer', 'common')
local mx = reaper.JS_Window_Find(mx_title, true)
if not mx then return false end
-- Simulate mouse event on waveform to read out time selection
local x, y = reaper.GetMousePosition()
local wave_hwnd = reaper.JS_Window_FindChildByID(mx, 1046)
local c_x, c_y = reaper.JS_Window_ScreenToClient(wave_hwnd, x, y)
reaper.JS_WindowMessage_Send(wave_hwnd, 'WM_MOUSEFIRST', c_y, 0, c_x, 0)
-- If a time selection exists, it will be shown in the wave info window
local wave_info_hwnd = reaper.JS_Window_FindChildByID(mx, 1014)
local wave_info = reaper.JS_Window_GetTitle(wave_info_hwnd)
local pattern = ': ([^%s]+) .-: ([^%s]+)'
local start_timecode, end_timecode = wave_info:match(pattern)
if not start_timecode then return false end
-- Convert timecode to seconds
local start_mins, start_secs = start_timecode:match('^(.-):(.-)$')
start_secs = tonumber(start_secs) + tonumber(start_mins) * 60
local end_mins, end_secs = end_timecode:match('^(.-):(.-)$')
end_secs = tonumber(end_secs) + tonumber(end_mins) * 60
-- Note: When no media file is loaded, start and end are both 0
return start_secs ~= end_secs, start_secs, end_secs
end
Last edited by FeedTheCat; 08-19-2021 at 05:16 AM.
|
|
|
08-19-2021, 02:55 PM
|
#1602
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
Quote:
Originally Posted by FeedTheCat
I managed to answer my own question. It's not even necessary to move the mouse, you can just send a 'WM_MOUSEFIRST' message and the time selection will show immediately (in the same defer cycle).
|
Cool! Thanks for letting us know about this trick.
|
|
|
08-23-2021, 03:43 PM
|
#1603
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
Quote:
Originally Posted by euxebio
Very interesting..it's possible a exemple to understand how to construct the C++ struct in a Lua string, store it using JS_Mem_Alloc and JS_Mem_FromString, and then pass the malloc address as an argument of JS_WindowMessage_Send?
I don't understand how do that.
|
Are you familiar with how to do this in C++?
|
|
|
08-23-2021, 06:32 PM
|
#1604
|
Human being with feelings
Join Date: Apr 2011
Posts: 3,458
|
Quote:
Originally Posted by FeedTheCat
I managed to answer my own question. It's not even necessary to move the mouse, you can just send a 'WM_MOUSEFIRST' message and the time selection will show immediately (in the same defer cycle).
Here's the resulting function for anyone interested:
Code:
function MediaExplorer_GetTimeSelection()
local mx_title = reaper.JS_Localize('Media Explorer', 'common')
local mx = reaper.JS_Window_Find(mx_title, true)
if not mx then return false end
-- Simulate mouse event on waveform to read out time selection
local x, y = reaper.GetMousePosition()
local wave_hwnd = reaper.JS_Window_FindChildByID(mx, 1046)
local c_x, c_y = reaper.JS_Window_ScreenToClient(wave_hwnd, x, y)
reaper.JS_WindowMessage_Send(wave_hwnd, 'WM_MOUSEFIRST', c_y, 0, c_x, 0)
-- If a time selection exists, it will be shown in the wave info window
local wave_info_hwnd = reaper.JS_Window_FindChildByID(mx, 1014)
local wave_info = reaper.JS_Window_GetTitle(wave_info_hwnd)
local pattern = ': ([^%s]+) .-: ([^%s]+)'
local start_timecode, end_timecode = wave_info:match(pattern)
if not start_timecode then return false end
-- Convert timecode to seconds
local start_mins, start_secs = start_timecode:match('^(.-):(.-)$')
start_secs = tonumber(start_secs) + tonumber(start_mins) * 60
local end_mins, end_secs = end_timecode:match('^(.-):(.-)$')
end_secs = tonumber(end_secs) + tonumber(end_mins) * 60
-- Note: When no media file is loaded, start and end are both 0
return start_secs ~= end_secs, start_secs, end_secs
end
|
WM_MOUSEFIRST = WM_MOUSEMOVE = 512
|
|
|
08-23-2021, 06:36 PM
|
#1605
|
Human being with feelings
Join Date: Apr 2011
Posts: 3,458
|
Quote:
Originally Posted by juliansader
Are you familiar with how to do this in C++?
|
I think he is not as I am not .. This was a question of mine initially, so I am interested in this too.
I had tried to do it but didn't succeed so I gave up. I think one must know how C++ structs are stored in memory and how to properly align things etc etc.. If you do know and could give us an example in reascript, it would be really great!
|
|
|
08-24-2021, 06:47 AM
|
#1606
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
I quickly checked how the relevant structs are stored in memory (in my Windows 10 x64 bit system), and I think the following may work. (I haven't tested it myself, however, since I don't know what exactly you are trying to do with the HDM_LAYOUT message.)
The HDM_LAYOUT message requires a pointer to a HDLAYOUT structure as argument. This HDLAYOUT struct is simple, 16 bytes containing two 64bit pointers:
Code:
typedef struct _HD_LAYOUT {
RECT *prc;
WINDOWPOS *pwpos;
} HDLAYOUT
So to create the HDLAYOUT struct via Lua, you can try this:
Code:
HDLAYOUT = string.pack("<i8i8", RECT_address, WINDOWPOS_address)
HDLAYOUT_handle = reaper.JS_Mem_Alloc(16)
reaper.JS_Mem_FromString(HDLAYOUT_handle, 0, HDLAYOUT, #HDLAYOUT)
The first component in HDLAYOUT points to a RECT structure, which is 16 bytes containing four 32-bit signed integers:
Code:
typedef struct tagRECT {
LONG left;
LONG top;
LONG right;
LONG bottom;
} RECT
To create a RECT, try this:
Code:
RECT = string.pack("<i4i4i4i4", left, top, right, bottom)
RECT_handle = reaper.JS_Mem_Alloc(16)
reaper.JS_Mem_FromString(RECT_handle, 0, RECT, #RECT)
The WINDOWPOS structure is a bit more complex:
Code:
typedef struct tagWINDOWPOS {
HWND hwnd;
HWND hwndInsertAfter;
int x;
int y;
int cx;
int cy;
UINT flags;
} WINDOWPOS
On my Windows 10 x64 system, it uses 4 bytes of padding at the end to get the total size to 40 bytes:
Code:
WINDOWPOS = string.pack("<i8i8i4i4i4i4I4xxxx", hwnd, hwndInsertAfter, x, y, cx, cy, flags)
WINDOWPOS_handle = reaper.JS_Mem_Alloc(40)
reaper.JS_Mem_FromString(WINDOWPOS_handle, 0, WINDOWPOS, #WINDOWPOS)
So putting it all together, you get something like this:
(If you prefer, you can pack everything into a single 72-byte string with a single string.pack, Mem_Alloc and Mem_Free.)
Code:
hwnd = reaper.JS_Window_Find("My Window", true)
hwnd_address = reaper.JS_Window_AddressFromHandle(hwnd)
left, top, right, bottom = 100, 100, 300, 300
x, y, width, height, flags = 0, 0, 200, 200, 0x020
hwndInsertAfter = 0
RECT = string.pack("<i4i4i4i4", left, top, right, bottom)
RECT_handle = reaper.JS_Mem_Alloc(16)
RECT_address = reaper.JS_Window_AddressFromHandle(RECT_handle)
reaper.JS_Mem_FromString(RECT_handle, 0, RECT, #RECT)
WINDOWPOS = string.pack("<i8i8i4i4i4i4I4xxxx", hwnd_address, hwndInsertAfter, x, y, width, height, flags)
WINDOWPOS_handle = reaper.JS_Mem_Alloc(40)
WINDOWPOS_address = reaper.JS_Window_AddressFromHandle(WINDOWPOS_handle)
reaper.JS_Mem_FromString(WINDOWPOS_handle, 0, WINDOWPOS, #WINDOWPOS)
HDLAYOUT = string.pack("<i8i8", RECT_address, WINDOWPOS_address)
HDLAYOUT_handle = reaper.JS_Mem_Alloc(16)
HDLAYOUT_address = reaper.JS_Window_AddressFromHandle(HDLAYOUT_handle)
reaper.JS_Mem_FromString(HDLAYOUT_address, 0, HDLAYOUT, #HDLAYOUT)
reaper.JS_WindowMessage_Send(hwnd, "0x1205", HDLAYOUT_address, 0, 0, 0)
reaper.JS_Mem_Free(HDLAYOUT_handle)
reaper.JS_Mem_Free(RECT_handle)
reaper.JS_Mem_Free(WINDOWPOS_handle)
Last edited by juliansader; 08-24-2021 at 07:39 AM.
|
|
|
08-25-2021, 08:06 AM
|
#1607
|
Human being with feelings
Join Date: Apr 2011
Posts: 3,458
|
Thank you very much for your help julian!! I am going to try it again now. I wanted this in order to make preset sizes of the ReaScript IDE window.
|
|
|
08-25-2021, 11:53 AM
|
#1608
|
Human being with feelings
Join Date: Apr 2020
Location: Italy
Posts: 22
|
Quote:
Originally Posted by juliansader
Are you familiar with how to do this in C++?
|
To better understand what I mean go to the link
https://forum.cockos.com/showthread.php?t=256629
If you can help me, you do me a great favor
Thanks a lot
|
|
|
08-25-2021, 02:13 PM
|
#1609
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
I will answer in the other thread.
Last edited by juliansader; 08-25-2021 at 02:27 PM.
|
|
|
08-28-2021, 11:38 AM
|
#1610
|
Human being with feelings
Join Date: Apr 2016
Location: ASU`ogacihC
Posts: 3,921
|
I guess JS_ListView_SetItemState doesn't work on MAC? ( see thread & post #5 for scripts,).
Or I using the functions incorrectly?
MAC doesn't support these functions?
Its all REAPER's fault?
Quote:
Originally Posted by Edgemeal
Cool!
Whats the correct way to select/unselect LV items? This was the only way I could get it to work (Win10_x64), but doesn't seem to be what the doc is saying.
|
Last edited by Edgemeal; 12-09-2021 at 02:48 PM.
|
|
|
08-28-2021, 02:26 PM
|
#1611
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
Quote:
Originally Posted by Edgemeal
I guess JS_ListView_SetItemState doesn't work on MAC? ( see thread & post #5 for scripts,).
Or I using the functions incorrectly?
MAC doesn't support these functions?
Its all REAPER's fault?
|
Whoops, there is an error in my documentation for ListView_Get/SetItemState: Focused and Selected should be 1 and 2, respectively (from the Win32 definitions: #define LVIS_FOCUSED 0x0001 #define LVIS_SELECTED 0x0002)
|
|
|
08-29-2021, 07:14 AM
|
#1612
|
Human being with feelings
Join Date: Apr 2016
Location: ASU`ogacihC
Posts: 3,921
|
Quote:
Originally Posted by juliansader
Whoops, there is an error in my documentation for ListView_Get/SetItemState: Focused and Selected should be 1 and 2, respectively (from the Win32 definitions: #define LVIS_FOCUSED 0x0001 #define LVIS_SELECTED 0x0002)
|
Not sure I follow the documentation and param settings, looked at code in my Windows app, maybe this is the correct way to use your function then?
Code:
reaper.JS_ListView_SetItemState(hwnd, index, 0xF, 0x2) -- select item @ index
reaper.JS_ListView_SetItemState(hwnd, -1, 0xF, 0x2) -- select all items
reaper.JS_ListView_SetItemState(hwnd, index, 0x0, 0x2) -- unselect item @ index
reaper.JS_ListView_SetItemState(hwnd, -1, 0x0, 0x2) -- unselect all items
Any feedback would be appreciated.
|
|
|
08-29-2021, 12:38 PM
|
#1613
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
That should be correct, yes.
|
|
|
09-15-2021, 04:50 AM
|
#1614
|
Human being with feelings
Join Date: Apr 2011
Posts: 3,458
|
Could JS_Dialog_BrowseForFolder be made to allow multiple selection of folders?
|
|
|
09-16-2021, 06:14 AM
|
#1615
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
Quote:
Originally Posted by amagalma
Could JS_Dialog_BrowseForFolder be made to allow multiple selection of folders?
|
Unfortunately not, AFAIK.
|
|
|
09-16-2021, 07:36 AM
|
#1616
|
Human being with feelings
Join Date: Jun 2012
Location: Spain
Posts: 7,268
|
I direct downloaded reaper_js_ReaScriptAPI64.so from https://github.com/juliansader/ReaEx...riptAPI/v1.220
copied to UserPlugins directory, but it doesn't work on Linux... can't see any JS_ function on the reaper reascript documentation generated page either.. Previous version 1.10 I think it was, worked well. I'll try again later with all versions maybe I did something wrong
|
|
|
09-16-2021, 01:29 PM
|
#1617
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
Please check out these posts for a possible solution. I hope it was simply a download problem.
|
|
|
09-16-2021, 03:08 PM
|
#1618
|
Human being with feelings
Join Date: Jun 2012
Location: Spain
Posts: 7,268
|
Quote:
Originally Posted by juliansader
Please check out these posts for a possible solution. I hope it was simply a download problem.
|
Just tried it again... it doesn't give any error but the JS_ functions are not there. I used the "Download" button and also tried Save link as... on the View Raw link... same result.
so I tried previous versions and 1.215 works. so strange.
v1.220 no
v1.217 no
v1.215 works
|
|
|
09-19-2021, 04:07 PM
|
#1620
|
Human being with feelings
Join Date: Jun 2012
Location: Spain
Posts: 7,268
|
Quote:
Originally Posted by juliansader
|
yay! it works! Thank you. I hope it was easy to fix
to discard that I got a corrupted download on the old 1.220 one
Code:
this one SHA256 is:
fc8f426feade478ba6e78508e7d43bc0184675a896d604cd83d81707d52adb8b
and the old one SHA256:
7e567a95a478df853f01d7d700a36ed9b35e842ef6afeada47616bef9a2f98d4
|
|
|
10-12-2021, 02:34 AM
|
#1621
|
Human being with feelings
Join Date: Jan 2019
Location: China
Posts: 662
|
reaper.JS_VKeys_GetState
Can I mask when entering text?
For example, when I enter track name.
|
|
|
10-12-2021, 04:33 AM
|
#1622
|
Banned
Join Date: Dec 2018
Posts: 642
|
Setting secondary record path
Is there any way to SET the secondary recording path using js_ReaScriptAPI?
Yes, I know you can set it manually in the Project Settings dialog.
Yes, I know you can read it from the RPP file.
Yes, I know you could rewrite the RPP file and reload the RPP file from scratch.
I'm wondering if there is a way to SET it directly in memory from a script as the primary recording path (RECORD_PATH) can be set using
Code:
reaper.GetSetProjectInfo_String
but this function doesn't include any parameter for the secondary recording path.
|
|
|
10-20-2021, 12:15 AM
|
#1623
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
Unfortunately not that I know of. It would probably be best to submit a FR for GetSetProjectInfo_String.
|
|
|
10-20-2021, 04:21 AM
|
#1624
|
Banned
Join Date: Dec 2018
Posts: 642
|
Thank you Julian.
|
|
|
10-21-2021, 02:01 PM
|
#1625
|
Banned
Join Date: Dec 2018
Posts: 642
|
JS_WindowMessage_Send, and JS_Window_FindChildByID
Does JS_WindowMessage_Send not work on Mac?
Does JS_Window_FindChildByID not work on Mac?
|
|
|
10-21-2021, 05:40 PM
|
#1626
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
Both should work fine. Are you encountering any problems?
BTW, RECORD_PATH_SECONDARY has now been implemented for GetSetProjectInfo_String in the dev version.
|
|
|
10-21-2021, 06:43 PM
|
#1627
|
Banned
Join Date: Dec 2018
Posts: 642
|
Sending either button clicks or keystrokes using the standard windows messages to the Project Settings window doesn't produce any response.
And using FindChildByID on the Project Settings window doesn't work.
Thanks for the info on the new dev version!
|
|
|
10-22-2021, 05:26 AM
|
#1628
|
Banned
Join Date: Dec 2018
Posts: 642
|
Quote:
Originally Posted by cohler
Sending either button clicks or keystrokes using the standard windows messages to the Project Settings window doesn't produce any response.
And using FindChildByID on the Project Settings window doesn't work.
|
To be more specific, I used the WM_KEYDOWN, WM_KEYUP messages as follows to send the SPACE character to the OK button. "win" below is the validated handle of the OK button (I confirmed this by successfully modifying the "OK" title of the window using JS_Window_SetTitle to "FOO" for example, and that works, but the following code does not activate the button, while manually typing a space does):
Code:
reaper.JS_WindowMessageSend(win,"WM_KEYDOWN",0x20,0,1,0x002C)
reaper.JS_WindowMessageSend(win,"WM_KEYUP",0x20,0,1,0xC02C)
I also tried "clicking" the OK button with the following code and nothing happens while manually clicking it works fine:
Code:
reaper.JS_WindowMessageSend(win,"WM_LBUTTONDOWN",1,0,0,0)
reaper.JS_WindowMessageSend(win,"WM_LBUTTONUP",0,0,0,0)
I know that the Project Settings window is a modal window. So obviously my script access to it is not from the same process that opened the window--which would be impossible--but rather from another independent process running simultaneously in the background using reaper.defer.
As for FindChildByID, the following code returns nil (also run from the separate process):
Code:
reaper.JS_Window_FindChildByID(win,1702)
where win is again the handle of the Project Settings window and 1702 is the ID (obtained with reaper.JS_Window_GetLong) of the primary record path child window.
Thanks for your help on this!
|
|
|
10-22-2021, 10:37 AM
|
#1629
|
Human being with feelings
Join Date: Apr 2016
Location: ASU`ogacihC
Posts: 3,921
|
Quote:
Originally Posted by cohler
As for FindChildByID, the following code returns nil (also run from the separate process):
Code:
reaper.JS_Window_FindChildByID(win,1702)
where win is again the handle of the Project Settings window and 1702 is the ID (obtained with reaper.JS_Window_GetLong) of the primary record path child window.
|
Are you sure you have the correct parent handle? Here on Win10 each Tab is a separate container child control of the main window. Only the buttons near the very bottom are on the main window.
On Windows we could use FindWindowEx with classname ('#32770') to identify which Tab the control we want is on, but I don't think MAC uses classnames? (I'm a Windows only guy )
So if there is only one child control with the ID of 1072 (or the one you want is the very first one) then you could probably just loop thru the child controls to find it?,..
Code:
main_hwnd = reaper.JS_Window_FindTop("Project Settings", true)
if not main_hwnd then return end
-- loop thru all children on main window
arr = reaper.new_array({}, 1024)
reaper.JS_Window_ArrayAllChild(main_hwnd, arr)
childs = arr.table()
-- find first child with Command ID of 1072 and set text
for j = 1, #childs do
hwnd = reaper.JS_Window_HandleFromAddress(childs[j])
primary_path_hwnd = reaper.JS_Window_FindChildByID(hwnd, 1702)
if primary_path_hwnd then
reaper.JS_Window_SetTitle(primary_path_hwnd,"Path_Text_Goes_Here")
break
end
end
FWIW, one way I'd probably do it in Windows in case anyone is interested See SPY++ image above.
Code:
function Main()
-- get main window ("Project Settings")
main_hwnd = reaper.JS_Window_FindTop("Project Settings", true)
if not main_hwnd then return end -- exit if not found!
-- get handle of the tabpage we want, then the controls on that tabpage
tabpage1 = reaper.JS_Window_FindEx(main_hwnd, main_hwnd, '#32770', '' ) -- 1st child with clasname '#32770' (1st tab)
tabpage2 = reaper.JS_Window_FindEx(main_hwnd, tabpage1, '#32770', '' ) -- 2nd '#32770' child ('Media' / 2nd tab)
primary_path_hwnd = reaper.JS_Window_FindChildByID(tabpage2, 1702) -- hwnd for primary path (edit control)
secondary_path_hwnd = reaper.JS_Window_FindChildByID(tabpage2, 1703) -- hwnd for secondary path (edit control)
-- Set text for paths
reaper.JS_Window_SetTitle(primary_path_hwnd,"E:\\Primary_Path")
reaper.JS_Window_SetTitle(secondary_path_hwnd,"E:\\Secondary_Path")
-- click the OK button near bottom of window
OK_button = reaper.JS_Window_FindChildByID(main_hwnd, 1)
reaper.JS_WindowMessage_Send(OK_button, "0xF5", 0, 0, 0, 0)
end
Last edited by Edgemeal; 10-23-2021 at 09:35 AM.
|
|
|
10-22-2021, 10:44 AM
|
#1630
|
Banned
Join Date: Dec 2018
Posts: 642
|
As I said, yes, I am sure I have the correct window handle and ID, because I was able to modify the window title from "OK" to "FOO" or whatever.
Furthermore, I obtained the window ID using reaper.JS_Window_GetLong(win,"ID") as I also noted.
|
|
|
10-22-2021, 10:46 AM
|
#1631
|
Banned
Join Date: Dec 2018
Posts: 642
|
reaper.JS_Window_FindChildByID exists precisely to avoid ugly and cumbersome loops of code just to access a window for which we already know the ID.
|
|
|
10-22-2021, 11:57 AM
|
#1632
|
Human being with feelings
Join Date: Apr 2016
Location: ASU`ogacihC
Posts: 3,921
|
Your button example works because it is on the main window handle and you are passing that handle to the function, But that primary path textbox is on Tab2 which is a container on the main window and has its own handle! To find a child by ID on Tab2 you'd need to pass the Tab2 handle to JS_Window_FindChildByID() function.
FWIW, FindChildByID does not enumerate, it only looks for a child on the parent handle you pass to it, so when I try this it will return NIL as expected since that textbox (ID 1702) is NOT on the main window!
Code:
main_hwnd = reaper.JS_Window_FindTop("Project Settings", true)
primary_path_hwnd = reaper.JS_Window_FindChildByID(main_hwnd, 1702)
All this is based on how it works in Windows.
If I'm wrong (since I don't use MAC) PLEASE post your code so others can help.
|
|
|
10-22-2021, 12:18 PM
|
#1633
|
Banned
Join Date: Dec 2018
Posts: 642
|
I see! Thank you @Edgemeal. I will try that and let you know...
|
|
|
10-22-2021, 12:37 PM
|
#1634
|
Human being with feelings
Join Date: May 2017
Location: Leipzig
Posts: 6,630
|
Instead of using hacks, why not testing the last few dev? Had been added recently.
|
|
|
10-22-2021, 02:29 PM
|
#1635
|
Banned
Join Date: Dec 2018
Posts: 642
|
Quote:
Originally Posted by Meo-Ada Mespotine
Instead of using hacks, why not testing the last few dev? Had been added recently.
|
Nothing we do here is a "hack". I am aware of what was recently added in the last couple of devs and have already implemented that.
Writing programs that improve REAPER's user interface is not a "hack" as you say. We sell only quality, bug-free software, written using REAPER's publicly available API ( Application Programming Interface).
|
|
|
10-22-2021, 05:26 PM
|
#1636
|
Banned
Join Date: Dec 2018
Posts: 642
|
Quote:
Originally Posted by Edgemeal
Your button example works because it is on the main window handle and you are passing that handle to the function, But that primary path textbox is on Tab2 which is a container on the main window and has its own handle! To find a child by ID on Tab2 you'd need to pass the Tab2 handle to JS_Window_FindChildByID() function.
FWIW, FindChildByID does not enumerate, it only looks for a child on the parent handle you pass to it, so when I try this it will return NIL as expected since that textbox (ID 1702) is NOT on the main window!
Code:
main_hwnd = reaper.JS_Window_FindTop("Project Settings", true)
primary_path_hwnd = reaper.JS_Window_FindChildByID(main_hwnd, 1702)
All this is based on how it works in Windows.
If I'm wrong (since I don't use MAC) PLEASE post your code so others can help.
|
I've investigated and it doesn't work the same on the Mac. I've got it working to the point where I know I have the correct window handles, because I can change the text of the child window IDs 1702 and 1703 using JS_Window_SetTitle and that works.
But the JS_WindowMessage_Send does not work. And I've tried using WM_LBUTTONDOWN/WM_LBUTTONUP, and WM_KEYDOWN/WM_KEYUP. The example given above uses BM_CLICK, but that message is not supported by swell.
Any ideas? Is the fact that it is a modal window somehow blocking key and mouse click messages from independent processes?
|
|
|
10-22-2021, 05:47 PM
|
#1637
|
Banned
Join Date: Dec 2018
Posts: 642
|
Here is the code I am using:
Code:
_c=require("Cohler")
_=reaper
local ps
found = function()
local r2w = _c.mychildbyid(ps,1703)
_.JS_Window_SetTitle(r2w,"Scooby do")
local OK = _c.mychildbyid(ps, 1)
_.JS_Window_SetTitle(OK,"FOO")
_.JS_WindowMessage_Send(OK, "WM_KEYDOWN", 0x20,0,0,0x2C)
_.JS_WindowMessage_Send(OK, "WM_KEYUP", 0x20,0,1,0xC02C)
end
test = function()
_.ShowConsoleMsg("Checking\n")
ps =_.JS_Window_FindTop("Project Settings",true)
return not not ps
end
_c.Wait(found,test,1)
_c.mychildbyid is my own routine to find the child window by ID because reaper.JS_Window_FindChildByID doesn't work on this modal window I guess. Clearly, this routine is working correctly, because the title updates work as expected.
_c.Wait is a routine that executes reaper.defer(test) every 1 second and executes function found when test returns true.
Everything else is standard REAPER.
To run the test, you run the code above, which creates the background process that is waiting for the Project Settings window to be opened (and thereby created). The background process prints "Checking" every one second in the Console, so you know that it is alive.
Then you go to the Action list and double click on Command ID 40934 ("Project recording settings") which opens/creates the Project Settings window with the Media tab already selected.
When you do that, the background process terminates, and succeeds in updating the title of child window 1703 and the text of the OK button to FOO.
But the click of the OK button (by the two JS_WindowMessage_Send calls) doesn't work. So the Project Settings window remains open.
(In the example above, I am sending a SPACE to the OK button, because that also clicks the button on Mac. I have also tried mouse click and button up/down etc, and none of them succeed in clicking the OK button and closing the window.)
|
|
|
10-23-2021, 08:49 AM
|
#1638
|
Human being with feelings
Join Date: Apr 2016
Location: ASU`ogacihC
Posts: 3,921
|
Quote:
Originally Posted by cohler
Nothing we do here is a "hack". I am aware of what was recently added in the last couple of devs and have already implemented that.
Writing programs that improve REAPER's user interface is not a "hack" as you say. We sell only quality, bug-free software, written using REAPER's publicly available API (Application Programming Interface).
|
Ya but Julian's API is an extension, things like in these last few posts are hacks IMO. The REAPER devs could change controls and/or their Command IDs at anytime and these scripts will no longer work as expected, whereas its very unlikely REAPERs own API functions will stop working so it really is best to use the REAPER API functions if when/where possible.
Speaking of hacks, when launching actions that open a modal window that stop a script from continuing its code, you can usually get around that by launching the action using PostMessage. Post does not wait for a return, so a defer loop will most likely be required to detect the window the action just opened, at least on Windows this trick/hack works great,..
Code:
function Main()
main_hwnd = reaper.JS_Window_FindTop("Project Settings", true)
if main_hwnd then
-- Do stuff once the window is found ---
reaper.ShowConsoleMsg('Window found!' .. '\n')
else
reaper.ShowConsoleMsg('Window not yet found, trying again\n')
reaper.defer(Main)
end
end
-- Run action "File: Project settings..." without blocking this script,
reaper.JS_WindowMessage_Post(reaper.GetMainHwnd(), "WM_COMMAND", 40021,0,0,0)
Main()
|
|
|
10-23-2021, 09:12 AM
|
#1639
|
Banned
Join Date: Dec 2018
Posts: 642
|
Quote:
Originally Posted by Edgemeal
when launching actions that open a modal window that stop a script from continuing its code, you can usually get around that by launching the action using PostMessage. Post does not wait for a return, so a defer loop will most likely be required to detect the window the action just opened, at least on Windows this trick/hack works great,..
Code:
function Main()
main_hwnd = reaper.JS_Window_FindTop("Project Settings", true)
if main_hwnd then
-- Do stuff once the window is found ---
reaper.ShowConsoleMsg('Window found!' .. '\n')
else
reaper.ShowConsoleMsg('Window not yet found, trying again\n')
reaper.defer(Main)
end
end
-- Run action "File: Project settings..." without blocking this script,
reaper.JS_WindowMessage_Post(reaper.GetMainHwnd(), "WM_COMMAND", 40021,0,0,0)
Main()
|
Nice! Thanks for that. I was in essence doing the reverse of that, but that is also a helpful tool.
|
|
|
10-24-2021, 02:57 PM
|
#1640
|
Human being with feelings
Join Date: Apr 2016
Location: ASU`ogacihC
Posts: 3,921
|
Quote:
Originally Posted by cohler
Nice! Thanks for that. I was in essence doing the reverse of that, but that is also a helpful tool.
|
So what about the OK button? You still can't click it? Sending left mouse down/up messages on Mac should work...
Code:
function ClickWindow(hwnd)
reaper.JS_WindowMessage_Send(hwnd, "WM_LBUTTONDOWN", 1, 0, 0, 0)
reaper.JS_WindowMessage_Send(hwnd, "WM_LBUTTONUP", 0, 0, 0, 0)
end
function Main()
main_hwnd = reaper.JS_Window_FindTop("Project Settings", true)
if main_hwnd then
-- Do stuff once the window is found ---
reaper.ShowConsoleMsg('Window found!\n')
-- find & click the OK button
OK_button = reaper.JS_Window_FindChildByID(main_hwnd, 1)
if OK_button then
reaper.ShowConsoleMsg('OK button found, Clicking OK button\n')
ClickWindow(OK_button)
end
else
reaper.ShowConsoleMsg('Window not yet found, trying again\n')
reaper.defer(Main)
end
end
-- Run action "File: Project settings..." without blocking this script,
reaper.JS_WindowMessage_Post(reaper.GetMainHwnd(), "WM_COMMAND", 40021,0,0,0)
Main()
|
|
|
Thread Tools |
|
Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -7. The time now is 04:44 AM.
|