Old 02-22-2019, 07:42 AM   #1
romeo_despres
Human being with feelings
 
Join Date: Jan 2019
Posts: 63
Default reapy: a pythonic wrapper around the ReaScript API

Hi everyone,

I know we are only a few Python ReaScripters here. But there are reasons for that:
  • the ReaScript API is a mess (almost no structure, inconsistent names, non-descriptive parameters names, no use of keyword optional arguments, buffer strings everywhere which makes no sense in Python),
  • its documentation is pretty bad (it's not just me saying it),
  • community libraries are one of Python's greatest strengths, yet importing them crashes REAPER (see complaints with Numpy, Scipy or Kivy),
  • no GUI programming is available since ReaScripts run in the main thread, even though GUI libraries exist for Python (see this thread to discover Tkinter's gorgeousness).

There have been several attempts to overcome these issues before:
  • The most estalished one is probably beyond.Reaper, which allows to call API functions from outside REAPER in a usual Python script. It's great, because:
    • it allows GUI programming,
    • it allows to import third-party libraries.
    It's not great, because:
    • it's been unmaintained since 2016,
    • though it has a (very thin) object-oriented layer around the ReaScript API, one can't say it provides a pythonic API,
    • there is almost no documentation (just a bunch of examples scripts),
    • the source code and the programming flow are very unusual (do we really need to override Python import process and have global variables jumping all over the place?), which makes it almost impossible for a standard Python user to read the source and figure out how it works.
  • ReaPyLib also implemented an object-oriented, human-readable model of the API. Yet the project has been unmaintained since the end of 2012 and doesn't cover much of the API.
  • The reaper-api project aims to replace bad parameters names by descriptive ones, and build documentation with a few docstrings. It is still alive, but doesn't help with the external libraries and GUI issues.

These projects weren't satisfying to me, so I wrote a new one. Its name is reapy, and it has the following features:
  • pip-installable (how convenient)
  • crazy simple to configure
  • can help with setting up Python in REAPER (if it's your first time)
  • sensible object-oriented interface to the ReaScript API
  • access to the whole native ReaScript API if you prefer it
  • can be imported inside REAPER and transparently act as a better API
  • can be imported outside REAPER and is faster than beyond.Reaper (see P.S. at the end)
  • a lot of well-formatted docstrings
  • PEP-compliant
  • Sphinx-generated online doc
  • nice GitHub with all explained on it so that people can improve it, request features, etc.

However, it is not a fully grown-up. Right now, only about a third of ReaScript API functions are wrapped in the reapy API. The other ones are still callable from reapy (inside and oustide REAPER), but without the pythonic feel. I think this project can become interesting only if other people in the community provide feedback and improvement, on the code itself as well as the documentation, structure, etc. So please don't hesitate to try it out and report bugs or missing features. And if you feel like coding yourself, feel free to fork the repository! As a Python ReaScripter, I know you dream like me of a well-established community-based REAPER API!


P.S. Performance comparison with beyond.Reaper

When you run a single API call with beyond.Reaper (e.g. path = Reaper.GetExePath()), it takes on average 0.15 s on my computer. With reapy (path = reapy.get_exe_dir()), it takes 0.03 s. However when performing several consecutive calls in the adapted context manager, the performance is asymptotically similar

Code:
>>> # beyond way
>>> import beyond.Reaper
>>> with Reaper as r:
...     # I hate the fact that the global variable `Reaper` appears without
...     # permission...
...     paths = [r.GetExePath() for _ in range(1000)]

>>> # reapy way
>>> import reapy
>>> with reapy.inside_reaper()
...     paths = [reapy.get_exe_path() for _ in range(1000)]

P.P.S. reapy should be cross-platform but since I have only tested it on Windows I couldn't swear. Yet I do think this is an important feature. We all love REAPER for Linux.

Last edited by romeo_despres; 02-26-2019 at 02:48 AM. Reason: added with reapy.inside_reaper() to the API
romeo_despres is offline   Reply With Quote
Old 02-22-2019, 09:54 AM   #2
Meo-Ada Mespotine
Human being with feelings
 
Meo-Ada Mespotine's Avatar
 
Join Date: May 2017
Location: Leipzig
Posts: 6,621
Default

Nice work. I'm no Python-programmer at all, but this should make things better for those who do
__________________
Use you/she/her.Ultraschall-Api Lua Api4Reaper - Donate, if you wish

On vacation for the time being...
Meo-Ada Mespotine is offline   Reply With Quote
Old 02-22-2019, 06:16 PM   #3
X-Raym
Human being with feelings
 
X-Raym's Avatar
 
Join Date: Apr 2013
Location: France
Posts: 9,875
Default

Very very intersting ! Especially if it has more doc than beyong.reaper and GUI prpgramming. Ill have to test that !



I wonder, as it works as extension, it could be shared via reapack for more transparent updates ?
X-Raym is offline   Reply With Quote
Old 02-23-2019, 04:49 AM   #4
romeo_despres
Human being with feelings
 
Join Date: Jan 2019
Posts: 63
Default

Thanks for the positive comments!

@mespotine
I found your ReaScript documentation categorization pretty nice so I edited the Translation Table to include it! I hope it's fine.

@X-Raym
The purpose of making it available on PyPI was already to allow for transparent updates via pip package manager, which is standard for Python. But it would definitely be nice to make it ReaPack-compatible as well. I am not familiar with the process for this so I'll have to learn more first.
romeo_despres is offline   Reply With Quote
Old 02-23-2019, 08:39 AM   #5
JerContact
Human being with feelings
 
Join Date: Feb 2017
Posts: 54
Default

Interesting!!! I do a bunch of python scripting with Reaper and was also sad about the GUI and other limitations. I’ll have to check this out!
JerContact is offline   Reply With Quote
Old 02-23-2019, 01:10 PM   #6
TonE
Human being with feelings
 
Join Date: Feb 2009
Location: Reaper HAS send control via midi !!!
Posts: 4,031
Default

What I am missing for Reaper mostly is something for this scenario:
-you have some old project, lots of track, fx, no or few mapped automation
-you want to add more automation
-and you have a concept of how the mapping should be over tracks, over fx, over parameters, all name based, something like;
PHP Code:
if track is x
   
if fx is y
      
if param is z
         map xyz to channel a
cc b     # for sliders
         
map xyz to channel anote b   # for toggle/switches 
Having a file like csv, with columns x,y,z,a,b to load such mapping would be good starting point. More columns could be added later in case Reaper would support min,max ranges for example.

Could reapy help implementing something like this? Now or in future? Name based mappings nothing is supported yet, afaik, ReaLearn is very cool, offering json import and export via clipboard, however it supports only numbered fx, parameters, not name based. I made a suggestion there, but nothing so far.

Then one could build such a csv file for their structure and import, easily, into any past or future project, and getting in one move a big set of mappings, ready to be used via their hardware set. In short, some tool, for converting software Reaper more into a hardware feeling Reaper. Open a project, hit a button, there you have your hardware feel. That would be top!

Then imagine users sharing those csv files here in the forum. It help file could be something like: mapping structure from Reason mode to following .RPP template. So anyone having a hardware set suppporting 'Reason mode', could immediately switch their device to Reason mode, open that .rpp template and all mappings would work, and be compatible to other csv structures for this combination, meaning reason mode > .rpp.

Last edited by TonE; 02-23-2019 at 01:50 PM.
TonE is offline   Reply With Quote
Old 02-28-2019, 08:00 AM   #7
Meo-Ada Mespotine
Human being with feelings
 
Meo-Ada Mespotine's Avatar
 
Join Date: May 2017
Location: Leipzig
Posts: 6,621
Default

Quote:
Originally Posted by romeo_despres View Post
Thanks for the positive comments!

@mespotine
I found your ReaScript documentation categorization pretty nice so I edited the Translation Table to include it! I hope it's fine.
Sure. Just add a link to the docs so people can find the other docs as well and everything's fine
__________________
Use you/she/her.Ultraschall-Api Lua Api4Reaper - Donate, if you wish

On vacation for the time being...
Meo-Ada Mespotine is offline   Reply With Quote
Old 02-28-2019, 09:50 AM   #8
romeo_despres
Human being with feelings
 
Join Date: Jan 2019
Posts: 63
Default

Of course I did it
romeo_despres is offline   Reply With Quote
Old 04-09-2019, 04:02 AM   #9
Centauria
Human being with feelings
 
Join Date: Apr 2019
Posts: 3
Default

Hey bro, when I ran python -m reapy, it can't find python.dll

================================================== =
(py36) C:\Users\Administrator>python -m reapy
D:\PF\Anaconda3\envs\py36\lib\site-packages\reapy\tools\dist_program.py:14: Disa
bledDistAPIWarning: Can't reach distant API. Please start REAPER, or call reapy.
config.enable_dist_api() from inside REAPER to enable distant API.
warnings.warn(DisabledDistAPIWarning())

======================
reapy config infos
======================

Python DLL
----------
Can't find python DLL...

Enable or disable reapy dist API
--------------------------------
Enable dist API
D:\PF\Anaconda3\envs\py36\lib\site-packages\reapy\reascripts\enable_dist_api
.py

Disable dist API
D:\PF\Anaconda3\envs\py36\lib\site-packages\reapy\reascripts\disable_dist_ap
i.py
==================================================





and I ran into an issue when I was trying to run enable_dist_api.py in REAPER


================================================== =
Script execution error

Traceback (most recent call last):
File "enable_dist_api.py", line 12, in <module>
import reapy
ModuleNotFoundError: No module named 'reapy'
================================================== =

why can't find the module reapy?
I am sure about the version of python is the one REAPER uses.
Help...
Centauria is offline   Reply With Quote
Old 04-09-2019, 04:40 AM   #10
romeo_despres
Human being with feelings
 
Join Date: Jan 2019
Posts: 63
Default

@nir.arad

To be honest I am puzzled by your bug... I'll let you know if I find out where that comes from.

@Centauria

It seems you have installed reapy through Anaconda? I am not an Anaconda expert but from your traceback I am guessing REAPER might have trouble finding the path to your conda environment... Could you try running the following inside REAPER and show us the result?

Code:
import sys
RPR_ShowConsoleMsg(sys.path)
romeo_despres is offline   Reply With Quote
Old 04-09-2019, 05:09 AM   #11
Centauria
Human being with feelings
 
Join Date: Apr 2019
Posts: 3
Default

The output is


['C:/Users/Administrator/AppData/Roaming/REAPER/Scripts', 'C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\Python36_64\\Lib', 'C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\Python36_64\\DLLs', 'D:\\PF\\REAPER (x64)', 'C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\Python36_64', 'C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\Python36_64\\lib\\site-packages', 'D://PF//REAPER (x64)//Plugins']

thx.
Centauria is offline   Reply With Quote
Old 04-09-2019, 05:23 AM   #12
romeo_despres
Human being with feelings
 
Join Date: Jan 2019
Posts: 63
Default

Thanks. So you can see that the place where reapy is located (D:\PF\Anaconda3\envs\py36\lib\site-packages) is not in sys.path by default when you run Python outside Anaconda. That explains why REAPER can't find it.

You can extend sys.path permanently by creating a path configuration file.

In your case, go to C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64\lib\site-packages and create a .pth file (for instance, "anaconda_env.pth") containing the following:

Code:
D:\PF\Anaconda3\envs\py36\lib\site-packages
If I'm not missing anything about Anaconda, you should now be able to import reapy from inside REAPER and thus to enable the distant API.

Last edited by romeo_despres; 04-09-2019 at 05:29 AM.
romeo_despres is offline   Reply With Quote
Old 04-09-2019, 09:27 AM   #13
Centauria
Human being with feelings
 
Join Date: Apr 2019
Posts: 3
Default

It worked!
Thank you
Centauria is offline   Reply With Quote
Old 04-21-2019, 12:29 PM   #14
chabErch
Human being with feelings
 
Join Date: Feb 2017
Posts: 1
Default

Hi @romeo_despres, great work!

Is it possible to run sws scripts with reapy?
chabErch is offline   Reply With Quote
Old 04-21-2019, 03:15 PM   #15
fladd
Human being with feelings
 
fladd's Avatar
 
Join Date: May 2006
Posts: 1,030
Default

This is great! I already thought I'm the only one who cares about pep8 :-)
__________________
www.fladd.de/sound
fladd is offline   Reply With Quote
Old 05-13-2019, 08:59 AM   #16
romeo_despres
Human being with feelings
 
Join Date: Jan 2019
Posts: 63
Default

Quick update: thanks to chabErch's contribution, SWS functions can now be run from outside REAPER with reapy. More precisely, if the SWS extension is installed, then reapy.reascript_api contains all functions in sws_python; otherwise it only contains native ReaScript functions.
romeo_despres is offline   Reply With Quote
Old 05-13-2019, 10:31 AM   #17
X-Raym
Human being with feelings
 
X-Raym's Avatar
 
Join Date: Apr 2013
Location: France
Posts: 9,875
Default

@romeo_despres
Cool !


Does it also contains JS_ReaScript and Reapack API functions ?
X-Raym is offline   Reply With Quote
Old 05-14-2019, 02:48 AM   #18
romeo_despres
Human being with feelings
 
Join Date: Jan 2019
Posts: 63
Default

I have only recently discovered these and haven't been able to make them work yet (I posted a related question recently but didn't get any reply...) But it would definitely make sense to include them as well
romeo_despres is offline   Reply With Quote
Old 06-06-2019, 01:38 AM   #19
Kostik Vento
Human being with feelings
 
Join Date: Nov 2013
Location: Yekaterinburg, Russia
Posts: 11
Default

Quote:
Originally Posted by romeo_despres View Post
I think this project can become interesting only if other people in the community provide feedback and improvement, on the code itself as well as the documentation, structure, etc. So please don't hesitate to try it out and report bugs or missing features. And if you feel like coding yourself, feel free to fork the repository! As a Python ReaScripter, I know you dream like me of a well-established community-based REAPER API!
That's about me)) I like both Python and Reaper, I do dream, so I've forked ))
And I do have some suggestions about improvements, would you prefer to discuss them here or on GitHub?

Quote:
Originally Posted by romeo_despres View Post
P.P.S. reapy should be cross-platform but since I have only tested it on Windows I couldn't swear. Yet I do think this is an important feature. We all love REAPER for Linux.
I've tried on MacOSX Sierra, it works fine for me. There are, still, minor bugs, I've opened pull requests for them, hope to see them reviewed soon))
And there's a serious bug I've almost run into — if your reaper.ini contains non-ASCII chars, rewriting config would crash half-way with the rest of your settings gone( My luck was to have the file opened in a text editor which had the full copy of the lost contents.

P.S. I made it work under Python2 (except enable/disable_dist_api), but the resulting code lost its pythonicity a bit, so I'll keep refactoring. And alas, you can't use reapy.print in Python2 because print is reserved there and cannot be used as identifier.

Last edited by Kostik Vento; 06-06-2019 at 01:54 AM.
Kostik Vento is offline   Reply With Quote
Old 06-06-2019, 05:41 AM   #20
romeo_despres
Human being with feelings
 
Join Date: Jan 2019
Posts: 63
Default

Thank you a lot for your help! I think the simplest is to communicate on GitHub as you did. I've seen your requests but been very busy lately so I haven't been able to review them in detail... But they seem to fix a lot of important issues! I'll try to reply to you asap there
romeo_despres is offline   Reply With Quote
Old 10-03-2019, 03:10 PM   #21
tparker24
Human being with feelings
 
Join Date: Dec 2017
Posts: 83
Default How invoke?

I'm a little confused on how to invoke the python script that uses reapy.

I actually want the script to run OUTSIDE of Reaper, but I want to be able to invoke the script from WITHIN Reaper, say via an Action item (or a Button and/or a shortcut).

Would I need a small script to call it, that just runs maybe one of these:
ExecProcess()
or
reaper.CF_ShellExecute()
and supplying the full path name to my python script, e.g.
Code:
ExecProcess("C:\some\path\to\my_python_script.py")
Or am I making this too hard?
tparker24 is offline   Reply With Quote
Old 10-06-2019, 09:23 AM   #22
romeo_despres
Human being with feelings
 
Join Date: Jan 2019
Posts: 63
Default

I think you're right, the correct way to do that would be to have two scripts, one that runs inside REAPER and looks like:

Code:
RPR_ExecProcess('py path/to/external_script.py', -1)
and a second one (external_script.py) which is the actual reapy app.
romeo_despres is offline   Reply With Quote
Old 10-06-2019, 10:01 AM   #23
tparker24
Human being with feelings
 
Join Date: Dec 2017
Posts: 83
Default

Ok, thanks for confirming.

I've just started using reapy, and I'm very impressed! It was easy to install and seems very straightforward to use. Running python outside of Reaper really opens up some possibilities, because some python things don't run too well (or at all) inside the Reaper environment ... for example PyQt or wXPthon, two powerful GUI programs.

reapy kind of unleashes python. Thanks for making it available.


Quote:
Originally Posted by romeo_despres View Post
I think you're right, the correct way to do that would be to have two scripts, one that runs inside REAPER and looks like:

Code:
RPR_ExecProcess('py path/to/external_script.py', -1)
and a second one (external_script.py) which is the actual reapy app.
tparker24 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 05:24 AM.


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