|
|
|
12-06-2018, 06:05 AM
|
#121
|
Human being with feelings
Join Date: May 2015
Location: Québec, Canada
Posts: 5,154
|
Just tested and it works here, though I get a leading null byte which isn't there on Windows. Are you're using the IDE or ShowConsoleMsg? They won't show anything past a null byte.
Windows (only the first path is absolute?):
(Also can't seem to make it accept all or no file extensions on macOS the same way that works on Windows).
Last edited by cfillion; 12-06-2018 at 07:04 AM.
|
|
|
12-06-2018, 07:18 AM
|
#122
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
Quote:
Originally Posted by mespotine
How do I separate the multiple filenames(in the get-files-functions) from each other in Lua?
|
Code:
for file in files:gmatch("[^\0]+") do
Last edited by juliansader; 12-08-2018 at 04:41 AM.
|
|
|
12-07-2018, 07:26 AM
|
#123
|
Human being with feelings
Join Date: May 2017
Location: Leipzig
Posts: 6,707
|
@JulianSaders @cfillion
Thanx, using \0 to pattern match was probably too obvious for me to see. With that, it works like a charm
|
|
|
12-07-2018, 08:54 AM
|
#124
|
Human being with feelings
Join Date: Apr 2016
Location: ASU`ogacihC
Posts: 4,033
|
Quote:
Originally Posted by juliansader
Code:
for file in files:gmatch("[^\0]") do
|
When I use that (on Win7) I only get one char per loop.
EDIT: OK,it works if I add a '+' to the end of it,
Code:
for file in files:gmatch("[^\0]+") do
I guess that'll work.
Last edited by Edgemeal; 12-07-2018 at 12:23 PM.
|
|
|
12-08-2018, 04:36 AM
|
#125
|
Human being with feelings
Join Date: May 2017
Location: Leipzig
Posts: 6,707
|
I'll post a function tomorrow(forgot to put it on my USB-stick today), that'll deal with that conveniently and return the filenames as array.
|
|
|
12-08-2018, 04:40 AM
|
#126
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
Quote:
Originally Posted by Edgemeal
OK,it works if I add a '+' to the end of it,
|
Oops! Corrected.
|
|
|
12-11-2018, 02:13 AM
|
#127
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
I neglected to include a description of the "extensionList" parameter of the open/save file dialogs in the API help.
This parameter uses the same format as the standard C++ functions GetOpenFileName and GetSaveFileName:
This string is terminated by *double* \0 characters, and contains a list of filter substrings, each terminated by a single \0.
The filter substrings are arranged in pairs: The first substring in each pair describes the filter and is displayed to the user in the dialog; the second substring in the pair specifies the filter pattern that the operating system must use. For example, "Lua scripts (*.lua)\0*.lua"\0.
To specify multiple filter patterns for a single display string, use a semicolon to separate the patterns (for example, "*.lua;*.eel\0").
Warning: in Windows, the filter doesn't require the * filename wildcard in front of the extension, but it appears to be required in Linux. (I'm not sure about macOS.)
So, for example, to include a filter for either all files or just lua scripts, this string can be used:
Code:
"All files (*.*)\0*.*\0Lua scripts (.lua)\0*.lua\0\0"
|
|
|
12-12-2018, 10:06 AM
|
#128
|
Human being with feelings
Join Date: May 2017
Location: Leipzig
Posts: 6,707
|
For the JS_Dialog_BrowseForOpenFiles-function, you can use the following code, to separate the filenames and path:
Code:
function SplitFilenameStringAtNULLBytes(splitstring)
-- if type(splitstring)~=nil
-- add a NULL-Byte at the end, helps us finding the end of the string later
splitstring=splitstring.."\0"
local count=0
local filenames={}
local temp, offset
-- let's get the path
local path, offset=splitstring:match("(.-)()\0")
splitstring=splitstring:sub(offset+1,-1)
-- let's get the filenames
while splitstring~=nil do
-- find the next filename
temp,offset=splitstring:match("(.-)()\0")
if temp~=nil then
-- if the next filename isn't nil, then add it fo filenames-array and count+1
count=count+1
filenames[count]=temp
splitstring=splitstring:sub(offset+1,-1)
else
-- if filename is nil, the string is probably finished splitting
break
end
end
return count, path, filenames
end
|
|
|
12-12-2018, 10:51 AM
|
#129
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
Perhaps something simpler?
The following should give you the path in t[1] and the file names in the rest of the table:
(Except if #t == 1, in which case the entire path and filename is in t[1].)
Code:
t = {}
for file in files:gmatch("[^\0]*")
t[#t+1] = file
end
Last edited by juliansader; 03-21-2019 at 05:13 AM.
|
|
|
12-15-2018, 04:34 AM
|
#130
|
Human being with feelings
Join Date: Aug 2011
Posts: 529
|
Hey i am just curious..are there some scripts out there already using this API?
|
|
|
12-15-2018, 05:44 AM
|
#131
|
Human being with feelings
Join Date: Apr 2014
Posts: 4,178
|
Quote:
Originally Posted by reapero
Hey i am just curious..are there some scripts out there already using this API?
|
I have one in progress that uses certain functions from this API. This API has really opened up a whole new world to scripting in Reaper.
|
|
|
12-15-2018, 06:07 AM
|
#132
|
Human being with feelings
Join Date: Aug 2011
Posts: 529
|
Yeah..looks like it. I with i has the skills to use it
|
|
|
12-15-2018, 11:44 AM
|
#133
|
Human being with feelings
Join Date: Apr 2016
Location: ASU`ogacihC
Posts: 4,033
|
Main Action Command ID Code Generator
Quote:
Originally Posted by reapero
Hey i am just curious..are there some scripts out there already using this API?
|
I have one to reset vertical Vu meters, and just made this..
If you call actions from a lua script its a hassle to copy their Text, ID/convert IDs, etc. Using this script you just highlight the action(s) you want and call this script from a shortcut and it generates the code for you (for Main section).
EDIT: Update v1.00 - Show command ID column if not visible.
Code:
-- Command ID Code Generator v1.00 --
function Main()
local show_id_column = 41170 -- toggle command id column
-- local show_path_column = 41387 -- toggle script paths column
local actions = reaper.JS_Window_Find("Actions", true)
if actions == nil then reaper.MB("Please open the Actions list!", app_name, 0) return end
local hWnd_LV = reaper.JS_Window_FindChildByID(actions, 1323)
local sel_count, sel_indexes = reaper.JS_ListView_ListAllSelItems(hWnd_LV)
if sel_count == 0 then reaper.MB("Please select one or more actions.", app_name, 0) return end
local lv_header = reaper.JS_Window_HandleFromAddress(reaper.JS_WindowMessage_Send(hWnd_LV, "0x101F", 0,0,0,0)) -- 0x101F = LVM_GETHEADER
local lv_column_count = reaper.JS_WindowMessage_Send(lv_header, "0x1200" ,0,0,0,0) -- 0x1200 = HDM_GETITEMCOUNT
-- Show Command ID column if not visible,
-- thanks to amagalma, https://forum.cockos.com/showpost.php?p=2270516&postcount=1
local third_item = reaper.JS_ListView_GetItemText(hWnd_LV, 0, 3)
if lv_column_count < 4 or third_item == "" or third_item:find("[\\/:]") then
reaper.JS_WindowMessage_Send(actions, "WM_COMMAND", show_id_column, 0, 0, 0) -- show Command ID column
end
-- generate code lines for *Main*
local code = ''
for ndx in string.gmatch(sel_indexes, '[^,]+') do
local index = tonumber(ndx)
local desc = reaper.JS_ListView_GetItemText(hWnd_LV, index, 1)
local cmd = reaper.JS_ListView_GetItemText(hWnd_LV, index, 3)
if tonumber(cmd) ~= nil then -- reaper action
code = code .. "reaper.Main_OnCommand(" .. cmd .. ", 0) -- " .. desc .. '\r\n'
else -- custom scripts require a lookup
code = code .. "reaper.Main_OnCommand(reaper.NamedCommandLookup('" .. cmd .. "'), 0) -- " .. desc .. '\r\n'
end
end -- for ndx
reaper.CF_SetClipboard(code) -- copy generated code to clipboard
-- OPTIONAL: Paste text in IDE if open. *Requires special shortcut!
-- * Shortcut must use the ControlKey+key (e.g., Control+F12).
-- See, https://forum.cockos.com/showpost.php?p=2073502&postcount=165
local ide = reaper.JS_Window_Find(" - ReaScript Development Environment", false)
if ide then
local wdl = reaper.JS_Window_FindChildByID(ide, 1106)
reaper.JS_Window_SetFocus(wdl)
reaper.JS_WindowMessage_Post(wdl, "WM_KEYDOWN", 0x0056, 0, 0, 0) -- V key (+ control key is down, so paste!)
reaper.JS_WindowMessage_Post(wdl, "WM_KEYUP", 0x0056, 0, 0, 0)
end
end -- end Main function
app_name = "Cmd_ID Code Gen"
Main()
reaper.defer(function () end)
Last edited by Edgemeal; 04-17-2020 at 03:08 PM.
Reason: v1.00
|
|
|
12-15-2018, 02:48 PM
|
#134
|
Human being with feelings
Join Date: Aug 2011
Posts: 529
|
So you use a script to actually write code? Jesuschrist..you guys are just too smart
|
|
|
12-15-2018, 03:41 PM
|
#135
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
Quote:
Originally Posted by cfillion
Just tested and it works here, though I get a leading null byte which isn't there on Windows. Are you're using the IDE or ShowConsoleMsg? They won't show anything past a null byte.
Windows (only the first path is absolute?):
|
The WDL/swell function is supposed to return the path in the first substring, and the filename (without path) in the following substrings. On Linux, it works correctly. I wonder if there is a bug in the macOS swell function? Perhaps the leading null byte is the terminator of an empty path substring?
Quote:
Originally Posted by cfillion
(Also can't seem to make it accept all or no file extensions on macOS the same way that works on Windows).
|
Could you explain what you mean by "all or no file extensions"?
If the user gives no extension filter, the function should automatically add a *.* filter, so that the filter dropdown menu isn't just blank.
Last edited by juliansader; 12-16-2018 at 04:30 AM.
|
|
|
12-16-2018, 03:36 AM
|
#136
|
Human being with feelings
Join Date: Apr 2011
Posts: 3,547
|
Quote:
Originally Posted by Edgemeal
I have one to reset vertical Vu meters, and just made this..
If you call actions from a lua script its a hassle to copy their ID/convert IDs, etc. Using this script you just highlight the action(s) you want and call this script from a shortcut and it generates the code for you, at least I hope it does.
Code:
-- Command ID Code Generator v0.04 --
-- Testing: x64, Windows 7, REAPER v5.963+dev1213, js_ReaScriptAPI v0.961.
-- v0.04 - Support multiple selected LV items.
local app_name = "Cmd_ID Code Gen"
local code = ""
local hWnd_action = reaper.JS_Window_Find("Actions", true)
if hWnd_action == nil then
reaper.MB("Please open the Actions list!", app_name, 0)
return
end
local hWnd_LV = reaper.JS_Window_FindChildByID(hWnd_action, 1323)
if reaper.JS_ListView_GetItemText(hWnd_LV, 0, 3) == "" then
reaper.MB("Please enable 'Show action IDs' in Actions list!", app_name, 0)
return
end
-- get selected count & selected indexes
sel_count, sel_indexes = reaper.JS_ListView_ListAllSelItems(hWnd_LV)
if sel_count == 0 then
reaper.MB("Please select one or more actions.", app_name, 0)
return
end
-- generate code lines for *Main*
for index in string.gmatch(sel_indexes, '[^,]+') do
local desc = reaper.JS_ListView_GetItemText(hWnd_LV, tonumber(index), 1)
local cmd = reaper.JS_ListView_GetItemText(hWnd_LV, tonumber(index), 3)
if tonumber(cmd) ~= nil then -- reaper action
code = code .. "reaper.Main_OnCommand(" .. cmd .. ", 0) -- " .. desc .. '\r\n'
else -- custom scripts require a lookup
code = code .. "reaper.Main_OnCommand(reaper.NamedCommandLookup('" .. cmd .. "'), 0) -- " .. desc .. '\r\n'
end
end -- for index
reaper.CF_SetClipboard(code)-- copy generated code to clipboard
|
Brilliant! Thanks!
|
|
|
12-16-2018, 05:11 AM
|
#137
|
Human being with feelings
Join Date: Apr 2011
Posts: 3,547
|
How could I paste the text in the clipboard to a focused window?
For example, with Spy++ I get this code when pasting into a window:
Code:
<000001> 00250490 P WM_CHAR chCharCode:'22' (22) cRepeat:1 ScanCode:2F fExtended:0 fAltDown:0 fRepeat:0 fUp:0 [wParam:00000016 lParam:002F0001]
I have tried this but it does not work:
Code:
reaper.JS_WindowMessage_Send( windowHWND, "WM_CHAR", 0x0016, 0x0000, 0x0001, 0x002F)
Any ideas?
Last edited by amagalma; 12-16-2018 at 06:30 AM.
|
|
|
12-16-2018, 10:08 AM
|
#138
|
Human being with feelings
Join Date: Apr 2016
Location: ASU`ogacihC
Posts: 4,033
|
EDIT
You got me wondering about sending text and clicking buttons now.
Since there is no support for "BM_CLICK" or "WM_SETTEXT"
EDIT 2
This seems OK for "BM_CLICK" on Windows..
Code:
-- Send button click message, a.k.a. "BM_CLICK".
reaper.JS_WindowMessage_Send(button_hWnd, "0x00F5", 0, 0, 0, 0)
CODE REMOVED! TRY AGAIN!
Last edited by Edgemeal; 01-02-2019 at 07:22 PM.
Reason: EDIT 2
|
|
|
12-17-2018, 04:24 AM
|
#139
|
Human being with feelings
Join Date: Apr 2013
Location: France
Posts: 10,088
|
Do you think we can get selected media files from Media Explorer and start doing some Media Explorer script ? :P
|
|
|
12-17-2018, 05:03 AM
|
#140
|
Human being with feelings
Join Date: Apr 2016
Location: ASU`ogacihC
Posts: 4,033
|
Quote:
Originally Posted by X-Raym
Do you think we can get selected media files from Media Explorer and start doing some Media Explorer script ? :P
|
Heres one way, I'd prefer using JS_Window_FindEx() to get the handle to the file Listview, the container its in seems to be the only control with an ID of 0, so tested like this,...
Code:
-- Testing: x64, Windows 7, REAPER v5.963+dev1213, js_ReaScriptAPI v0.961.
function print(str)
reaper.ShowConsoleMsg(tostring(str) .. "\n") -- console
end
local hWnd = reaper.JS_Window_Find("Media Explorer", true)
if hWnd == nil then return end
local container = reaper.JS_Window_FindChildByID(hWnd, 0)
local file_LV = reaper.JS_Window_FindChildByID(container, 1000)
sel_count, sel_indexes = reaper.JS_ListView_ListAllSelItems(file_LV)
if sel_count == 0 then return end
for ndx in string.gmatch(sel_indexes, '[^,]+') do
index = tonumber(ndx)
local fname = reaper.JS_ListView_GetItemText(file_LV, index, 0)
local size = reaper.JS_ListView_GetItemText(file_LV, index, 1)
local date = reaper.JS_ListView_GetItemText(file_LV, index, 2)
local ftype = reaper.JS_ListView_GetItemText(file_LV, index, 3)
print(fname .. ', ' .. size .. ', ' .. date .. ', ' .. ftype)
end
-- get selected path from edit control inside combobox
local combo = reaper.JS_Window_FindChildByID(hWnd, 1002)
local edit = reaper.JS_Window_FindChildByID(combo, 1001)
local path = reaper.JS_Window_GetTitle(edit, "", 255)
print(path)
Last edited by Edgemeal; 12-17-2018 at 05:42 AM.
Reason: get more column data
|
|
|
12-17-2018, 05:25 AM
|
#141
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
Quote:
Originally Posted by X-Raym
Do you think we can get selected media files from Media Explorer and start doing some Media Explorer script ? :P
|
As Edgemeal answered, yes you can! (I am actually using some myself.)
Three remarks:
* You can open the Media Explorer (and get its HWND) using reaper.OpenMediaExplorer("", false).
* You can run any action from the Actions list's Media Explorer context (or even any item from the ME's menu), using JS_Window_OnCommand.
* If you are publishing a script that searches for any of REAPER's standard windows, such as the Media Explorer, use JS_Localize to get the translated title.
|
|
|
12-17-2018, 05:39 AM
|
#142
|
Human being with feelings
Join Date: Apr 2013
Location: France
Posts: 10,088
|
@edgemeal
This is awesome !
We can finally make a Rename from media explorer action !
Only problem is that the last clicked selected items in media explorer is in read-only mode. The trick is to close and re-open the media explorer using the native actions (or API functions) which will also refresh the media explorer (a trick I used in some databases scripts I made).
But I wonder is there is any more clever js_extension trick now ? for both release read-only mode and for refreshing the media explorer ?
@juliansader
This script really open new possibilities to scripting ! Cool it is part to default reateam repos.
|
|
|
12-17-2018, 05:59 AM
|
#143
|
Human being with feelings
Join Date: Apr 2011
Posts: 3,547
|
Quote:
Originally Posted by Edgemeal
This seems to work OK, tho not sure its actually correct.
Code:
local hWnd_action = reaper.JS_Window_Find("Actions", true)
if hWnd_action ~= nil then
-- Get handle to Filter editbox in Actions window,
local hWnd_filter = reaper.JS_Window_FindChildByID(hWnd_action, 1324)
-- send it an "A" Char
ret = reaper.JS_WindowMessage_Post(hWnd_filter, "WM_CHAR", string.byte("A"), 0,0,0)
end
|
Yes, simple characters work, but Ctrl+V etc do not.
Quote:
Code:
function JS_Send_Text(hWnd, str)
for char in string.gmatch(str, "%U") do
ret = reaper.JS_WindowMessage_Post(hWnd, "WM_CHAR", string.byte(char), 0, 0, 0)
if ret ~= true then break end -- something went wrong?, abort loop!
end
end
|
For some reason, this works up to 64 characters. If they are more than 64, it truncates the start.
|
|
|
12-17-2018, 06:46 AM
|
#144
|
Human being with feelings
Join Date: Oct 2017
Location: Black Forest
Posts: 5,130
|
0.961 is not listed in the repo, yet, right? We have to download manually. Or did I miss something?
|
|
|
12-17-2018, 03:02 PM
|
#145
|
Human being with feelings
Join Date: Apr 2016
Location: ASU`ogacihC
Posts: 4,033
|
Quote:
Originally Posted by amagalma
For some reason, this works up to 64 characters. If they are more than 64, it truncates the start.
|
It could be a char limit set by the target control. Yesterday that code worked flawless, today acting weird, ok lets try something diff...
EDIT New test...
Code:
local hWnd_action = reaper.JS_Window_Find("Actions", true)
if hWnd_action ~= nil then
filter_editbox = reaper.JS_Window_FindChildByID(hWnd_action, 1324)
reaper.JS_Window_SetTitle(filter_editbox, "tracks unselect all") -- set text of Actions Filter
end
Get Top-Level Control IDs Under Mouse (For Windows only)
Last edited by Edgemeal; 12-17-2018 at 04:05 PM.
|
|
|
12-18-2018, 04:16 AM
|
#146
|
Human being with feelings
Join Date: Apr 2011
Posts: 3,547
|
Quote:
Originally Posted by Edgemeal
EDIT New test...
Code:
local hWnd_action = reaper.JS_Window_Find("Actions", true)
if hWnd_action ~= nil then
filter_editbox = reaper.JS_Window_FindChildByID(hWnd_action, 1324)
reaper.JS_Window_SetTitle(filter_editbox, "tracks unselect all") -- set text of Actions Filter
end
Get Top-Level Control IDs Under Mouse (For Windows only)
|
No, this still doesn't work.. Strangely, it works for the Action List but it doesn't in all the other windows. For example, open Notepad and try this:
Code:
hWnd_action = reaper.JS_Window_Find(" - Notepad", false)
if hWnd_action ~= nil then
child = reaper.JS_Window_FindChildByID(hWnd_action, 15)
reaper.JS_Window_SetTitle(child, "This is a test")
end
Nothing happens.. I tried to mimic the press of Ctrl+V in order to paste the text I have in the clipboard, but again no luck:
Code:
reaper.JS_WindowMessage_Post( child, "WM_KEYDOWN", 0x0011, 0x0000, 0x0001, 0x001D) -- Ctrl
reaper.JS_WindowMessage_Post( child, "WM_KEYDOWN", 0x0011, 0x0000, 0x0001, 0x401D)
reaper.JS_WindowMessage_Post( child, "WM_KEYDOWN", 0x0056, 0x0000, 0x0001, 0x002F) -- V
reaper.JS_WindowMessage_Post( child, "WM_CHAR", 0x0016, 0x0000, 0x0001, 0x002F)
reaper.JS_WindowMessage_Post( child, "WM_KEYUP", 0x0056, 0x0000, 0x0001, 0xC02F)
reaper.JS_WindowMessage_Post( child, "WM_KEYUP", 0x0011, 0x0000, 0x0001, 0xC01D)
P.S. Your exe for getting the Control IDs is very handy! Thanks!
|
|
|
12-18-2018, 07:14 AM
|
#147
|
Human being with feelings
Join Date: Apr 2016
Location: ASU`ogacihC
Posts: 4,033
|
Quote:
Originally Posted by amagalma
No, this still doesn't work.. Strangely, it works for the Action List but it doesn't in all the other windows. For example, open Notepad and try this:
|
Looking at the source code 'JS_Window_SetTitle' is calling the 'SetWindowText' API which is used to change the text of a window's title bar, I'm not sure why it works on Edit controls in REAPER, but was the last thing I tried.
TEST, change title bar text of notepad...
Code:
hWnd = reaper.JS_Window_Find("Untitled - Notepad", true)
if hWnd ~= nil then
reaper.JS_Window_SetTitle(hWnd, "This is a test")
end
Could of sworn I saw WM_SETTEXT in one of the JS source flles, but I think it was commented out so can't be used.
Last edited by Edgemeal; 12-22-2018 at 12:17 AM.
|
|
|
12-18-2018, 08:16 AM
|
#148
|
Human being with feelings
Join Date: May 2017
Location: Leipzig
Posts: 6,707
|
Quote:
Originally Posted by _Stevie_
0.961 is not listed in the repo, yet, right? We have to download manually. Or did I miss something?
|
It works with pre-releases of Reaper only, for the moment.
Though I hope, Reaper 5.964 contains the stuff needed for an "official release".
|
|
|
12-18-2018, 03:23 PM
|
#149
|
Human being with feelings
Join Date: May 2015
Location: Québec, Canada
Posts: 5,154
|
Quote:
Originally Posted by Edgemeal
Looking at the source code 'JS_Window_SetTitle' is calling the 'SetWindowText' API which is used to change the text of a window's title bar, I'm not sure why it works on Edit controls in REAPER, but was the last thing I tried.
|
https://docs.microsoft.com/en-us/win...setwindowtextw
Quote:
Changes the text of the specified window's title bar (if it has one). If the specified window is a control, the text of the control is changed. However, SetWindowText cannot change the text of a control in another application.
[...]
If the target window is owned by the current process, SetWindowText causes a WM_SETTEXT message to be sent to the specified window or control.
|
|
|
|
12-18-2018, 05:36 PM
|
#150
|
Human being with feelings
Join Date: Apr 2011
Posts: 3,547
|
Shouldn't it work to send text to the Reascript IDE window?
I can change the title of the window but I can't send text to it
|
|
|
12-18-2018, 06:32 PM
|
#151
|
Human being with feelings
Join Date: May 2015
Location: Québec, Canada
Posts: 5,154
|
Last edited by cfillion; 12-18-2018 at 06:41 PM.
|
|
|
12-19-2018, 02:08 AM
|
#152
|
Human being with feelings
Join Date: Apr 2011
Posts: 3,547
|
Does this mean that the IDE window is considered a different application, like Notepad?
|
|
|
12-19-2018, 03:00 AM
|
#153
|
Human being with feelings
Join Date: May 2015
Location: Québec, Canada
Posts: 5,154
|
The IDE just doesn't implement WM_SETTEXT. (A different application would mean another process visible in the task manager.)
The curses control receives input through WM_CHAR and keyboard shortcuts through WM_KEYDOWN. However modifier keys (Shift/Control/Alt/Meta) are tested with GetAsyncKeyState which can't be simulated using messages (maybe SendInput?).
Code:
-- likely Windows only (fails to find the curses control on macOS, didn't investigate)
local ide = reaper.JS_Window_Find("test.lua", false)
local curses = reaper.JS_Window_FindChildByID(ide, 0x452)
for c in ("Hello world"):gmatch('.') do
reaper.JS_WindowMessage_Post(curses, "WM_CHAR", string.byte(c), 0, 1, 0)
end
(Looks like C++ would be able to send anything including shortcuts with modifiers. But bad things will happen if REAPER is built using a different curses.h than the extension.)
Last edited by cfillion; 12-19-2018 at 05:23 AM.
|
|
|
12-19-2018, 03:57 AM
|
#154
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
If you are on Windows, if you would like to paste something, try sending a WM_PASTE command.
WDL/swell has not implemented this message type on Linux or macOS (AFAIK?), so the extension will not recognize the name, but on Windows you can use the message value, 0x0302:
Code:
reaper.JS_WindowMessage_Post(filterHWND, "0x0302", 0, 0, 0, 0)
I quickly checked, and it works fine in the Action list's filter editbox.
Quote:
Originally Posted by Edgemeal
Could of sworn I saw WM_SETTEXT in one of the JS source flles, but I think it was commented out so can't be used.
|
WM_SETTEXT has also not been implemented on macOS, so I haven't included it in the list of message names that the extension will recognize.
Last edited by juliansader; 12-19-2018 at 04:21 AM.
|
|
|
12-19-2018, 04:13 AM
|
#155
|
Human being with feelings
Join Date: Apr 2011
Posts: 3,547
|
Quote:
Originally Posted by cfillion
Code:
-- likely Windows only (fails to find the curses control on macOS, didn't investigate)
local ide = reaper.JS_Window_Find("test.lua", false)
local curses = reaper.JS_Window_FindChildByID(ide, 0x452)
for c in ("Hello world"):gmatch('.') do
reaper.JS_WindowMessage_Post(curses, "WM_CHAR", string.byte(c), 0, 1, 0)
end
(Looks like C++ would be able to send anything including shortcuts with modifiers. But bad things will happen if REAPER is built using a different curses.h than the extension.)
|
Yes, this method works as Edgemeal had already showed, but it has a limit of 64 characters.
Quote:
Originally Posted by juliansader
Code:
reaper.JS_WindowMessage_Post(filterHWND, "0x0302", 0, 0, 0, 0)
I quickly checked, and it works fine in the Action list's filter editbox.
WM_SETTEXT has also not been implemented on macOS, so I haven't included it in the list of message names that the extension will recognize.
|
This does not work in the IDE window, where I am interested in.
|
|
|
12-19-2018, 05:02 AM
|
#156
|
Human being with feelings
Join Date: May 2015
Location: Québec, Canada
Posts: 5,154
|
Quote:
Originally Posted by amagalma
Yes, this method works as Edgemeal had already showed, but it has a limit of 64 characters.
|
Ah yes, the IDE's keyboard queue is 64 characters big and (up to) 16 chars are read from it per timer cycle. This works but is of course slow(er), fragile and not cleanly undoable:
Code:
-- just for fun, shouldn't be used in a proper script...
function writeInIDE(file, content)
local CHUNK_SIZE = 16
local ide = reaper.JS_Window_Find(file, false)
local curses = reaper.JS_Window_FindChildByID(ide, 0x452)
local chunkStart = 1
function sendChunk()
local chunkEnd = chunkStart + CHUNK_SIZE - 1
for c in content:sub(chunkStart, chunkEnd):gmatch('.') do
reaper.JS_WindowMessage_Post(curses, "WM_CHAR", string.byte(c), 0, 1, 0)
end
chunkStart = chunkEnd + 1
if chunkStart < #content then
reaper.defer(sendChunk)
end
end
sendChunk()
end
writeInIDE('test.lua', string.rep('abcdefghijklmnopqrstuvwxyz', 8))
What's the end goal for which pasting in the IDE is needed? Perhaps there's a better solution than this sort of hacks...
Last edited by cfillion; 12-19-2018 at 05:16 AM.
|
|
|
12-19-2018, 05:17 AM
|
#157
|
Human being with feelings
Join Date: Apr 2011
Posts: 3,547
|
Quote:
Originally Posted by Edgemeal
If you call actions from a lua script its a hassle to copy their ID/convert IDs, etc. Using this script you just highlight the action(s) you want and call this script from a shortcut and it generates the code for you, at least I hope it does.
Code:
-- Command ID Code Generator v0.04 --
-- Testing: x64, Windows 7, REAPER v5.963+dev1213, js_ReaScriptAPI v0.961.
-- v0.04 - Support multiple selected LV items.
local app_name = "Cmd_ID Code Gen"
local code = ""
local hWnd_action = reaper.JS_Window_Find("Actions", true)
if hWnd_action == nil then
reaper.MB("Please open the Actions list!", app_name, 0)
return
end
local hWnd_LV = reaper.JS_Window_FindChildByID(hWnd_action, 1323)
if reaper.JS_ListView_GetItemText(hWnd_LV, 0, 3) == "" then
reaper.MB("Please enable 'Show action IDs' in Actions list!", app_name, 0)
return
end
-- get selected count & selected indexes
sel_count, sel_indexes = reaper.JS_ListView_ListAllSelItems(hWnd_LV)
if sel_count == 0 then
reaper.MB("Please select one or more actions.", app_name, 0)
return
end
-- generate code lines for *Main*
for index in string.gmatch(sel_indexes, '[^,]+') do
local desc = reaper.JS_ListView_GetItemText(hWnd_LV, tonumber(index), 1)
local cmd = reaper.JS_ListView_GetItemText(hWnd_LV, tonumber(index), 3)
if tonumber(cmd) ~= nil then -- reaper action
code = code .. "reaper.Main_OnCommand(" .. cmd .. ", 0) -- " .. desc .. '\r\n'
else -- custom scripts require a lookup
code = code .. "reaper.Main_OnCommand(reaper.NamedCommandLookup('" .. cmd .. "'), 0) -- " .. desc .. '\r\n'
end
end -- for index
reaper.CF_SetClipboard(code)-- copy generated code to clipboard
|
I wanted to combine it with this script of Edgemeal so that the action gets automatically typed in the open IDE window.
Your code works and now I can achieve it. Thank you! The only problem is the messed up undo (an undo point for each character), which makes it not practical.. So, I 'll just use the script in Edgemeal's original version, and do the pasting manually.
|
|
|
12-19-2018, 10:37 AM
|
#158
|
Human being with feelings
Join Date: Apr 2011
Posts: 3,547
|
On another note, it is great that with the latest additions we can now get the selected FX in a visible Chain :
Code:
function GetSelectedFXinChain()
local FX_win = reaper.JS_Window_Find("FX: ", false )
local sel_FX = {}
if FX_win then
local title = reaper.JS_Window_GetTitle( FX_win, "" )
if title:match("FX: Track ") or title:match("FX: Master Track") or title:match("FX: Item ") then
local list = reaper.JS_Window_FindChildByID(FX_win, 1076)
local _, sel_fx = reaper.JS_ListView_ListAllSelItems(list)
local a = 0
for i in sel_fx:gmatch("%d+") do
sel_FX[a+1] = {id = tonumber(i), name = reaper.JS_ListView_GetItemText(list, tonumber(i), 0)}
a = a + 1
end
end
end
return sel_FX
end
-- TEST CODE --
local fx = GetSelectedFXinChain()
if #fx == 0 then return end
reaper.ClearConsole()
reaper.ShowConsoleMsg("The selected FX in the visible FX chain are:\n\n")
for i = 1, #fx do
reaper.ShowConsoleMsg(i .. ") " .. fx[i].name .. " - - - fxid: " .. fx[i].id .. "\n\n")
end
local w = reaper.JS_Window_Find("ReaScript console output", true )
reaper.JS_Window_SetFocus( reaper.JS_Window_FindChildByID(w, 3) )
reaper.defer(function () end )
And do this :
Last edited by amagalma; 12-24-2018 at 02:06 PM.
|
|
|
12-21-2018, 02:02 PM
|
#159
|
Human being with feelings
Join Date: Apr 2016
Location: ASU`ogacihC
Posts: 4,033
|
v0.962 by juliansader – December 21 2018
* New functions: Browse for files and folders.
* New functions: Various ListView.
* New function: FindChildByID.
* Changed functions: Functions that previously stored strings in ExtStates, now return the strings directly.
* Requirements: On Windows OS, C++ redistributable not required anymore.
* Requirements: REAPER v5.965 or later.
|
|
|
12-21-2018, 05:10 PM
|
#160
|
Human being with feelings
Join Date: Apr 2013
Location: France
Posts: 10,088
|
Updated my ReaScript doc page with REAPER v5.965 and js_Extension v0.962 :P
(link in signature)
|
|
|
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 08:00 AM.
|