View Single Post
Old 10-13-2018, 02:32 PM   #1
Human being with feelings
Join Date: Jul 2009
Posts: 2,369
Default js_ReaScriptAPI extension

I have uploaded a new extension that may be of interest to other scripters: "js_ReaScriptAPI".

It can be installed via ReaPack (if ReaTeam/Extensions is not listed among your default repositories, you can add the repository manually with this URL), or via direct download (copy the file to REAPER's /UserPlugins directory).

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 resulting ReaScript API is therefore not the result of my own amazing programming skills, but is mostly just an interface to existing C++ functions.)

The online documentation for the corresponding C++ functions is probably the best place to learn how to use these functions. For example, Window messages and Drawing with GDI.

I have tried to make most functions cross-platform applicable, but I am not able to test the extension on MacOS, so let me know if anything doesn't work as expected.

Many thanks to cfillion, Xenakios and nofish, who helped me a *lot* to figure out the esoteric and undocumented mysteries of REAPER extensions.

Here are a few examples:

Attach "pin on top" button to script GUIs

FR: add 'always on top' pin for EEL script GUI's

w = reaper.JS_Window_Find("MIDI Inspector", true)
if w then reaper.JS_Window_AttachTopmostPin(w) end

Drawing inside REAPER windows

FR: Lasso Select for midi notes

Load custom cursors

FR: ReaScript: Allow scripts to change mouse cursor

-- Load REAPER's native "arpeggiate" cursor
-- Prevent REAPER from changing cursor back, by intercepting "SETCURSOR" messages
reaper.JS_WindowMessage_Intercept(window, "WM_SETCURSOR", false)

Take control of mouse clicks and mousewheel

By intercepting mouse and mousewheel messages, scripts can be controlled with the mouse, without activating REAPER's own mouse modifier actions.

For example, in my own "Mouse editing" CC scripts, I use code like the following to block the mouse from interacting with the piano roll while the script is running:
tIntercepts = { WM_LBUTTONDOWN   = false,
	        WM_LBUTTONUP     = false,
	        WM_LBUTTONDBLCLK = false,
	        WM_MBUTTONDOWN   = false,
	        WM_MBUTTONUP     = false,
	        WM_MBUTTONDBLCLK = false,
	        WM_RBUTTONDOWN   = false,
	        WM_RBUTTONUP     = false,
	        WM_RBUTTONDBLCLK = false,
	        WM_MOUSEWHEEL    = false,
	        WM_MOUSEHWHEEL   = false,
	        WM_MOUSEMOVE     = false,
	        WM_SETCURSOR     = false
midiview = reaper.JS_Window_FromPoint(reaper.GetMousePosition())
for key, value in pairs(tIntercepts) do
    OK = reaper.JS_WindowMessage_Intercept(midiview, key, value)
The scripts can then use JS_WindowMessage_Peek to track mouse events while running:
peekOK, _, time, keys, rotate, x, y = reaper.JS_WindowMessage_Peek(midiview, "WM_MOUSEWHEEL")
if peekOK and time ~= prevTime then
    -- mousewheel has moved since last defer cycle
peekOK, _, time, keys, _, x, y = reaper.JS_WindowMessage_Peek(midiview, "WM_LBUTTONDOWN")
if peekOK and time ~= prevTime then
    -- Left button has been pressed


Send commands to any window, similar to Main_OnCommand and MIDIEditor_OnCommand:
-- Action 1011 = Autoplay: Toggle on/off
me = reaper.JS_Window_Find("Media Explorer", true)
reaper.JS_WindowMessage_Send(me, "WM_COMMAND", 1011, 0, 0, 0)

Keep the Mixer window out of the way

FR: Plugin windows always on top, Mixer window always behind

The API offers several functions for getting and setting the Z order and focus of windows, so one possible solution for the FR is discussed here:
Move Mixer out of the way: example of Win32/SWELL in ReaScript.

Track mouse events outside script GUI

FR: Exposure of mouse state-functions for non gfx.ini-created windows

In addition to the WindowMessage functions, which are specific to a single target window, the mouse can be tracked using JS_Mouse_GetState:
-- Flag 0b00000001+0b00010000 = left mouse button + alt key
if reaper.JS_Mouse_GetState(0x0011) = 0x0011 then

Frameless script GUIs

FR: Stylish ReaScript GUIs: Transparent backgrounds and no titlebars

Unfortunately, even with C++ functions, I have not been able to change script GUIs' window style to "frameless" without getting ugly artefacts. However, scripts can fake a frameless style by using the GDI functions to draw over the entire window area, including the frame:

Last edited by juliansader; 01-19-2019 at 06:15 PM.
juliansader is offline   Reply With Quote