romeodespres / reapy Goto Github PK
View Code? Open in Web Editor NEWA pythonic wrapper for REAPER's ReaScript Python API
License: MIT License
A pythonic wrapper for REAPER's ReaScript Python API
License: MIT License
Given:
import argparse
import sys
import logging
import random
import math
import reapy
from colors import randColorByHue
from reapy import reascript_api as RPR
def makeTracks(project):
tracks = ['Chords - Scratch', 'Chords', 'Arpeggio', 'Bass', 'Sub', 'Pad',
'Lead', 'FX1', 'FX2', 'FX3', 'Rhythmic', 'Percussion', 'Harmony', 'Melody']
tracks.reverse()
for track in tracks:
t = project.add_track(name=track)
t.color = randColorByHue('red')
if track == 'Melody':
t.add_fx(name='Captain Melody')
if track == 'Bass':
t.add_fx(name='Captain Deep')
if track == 'Arpeggio':
t.add_fx(name='ChordPotion')
t.add_fx(name='ReaSynth')
if track == 'Chords - Scratch':
t.add_fx(name='Captain Chords')
t.add_send(destination=project.tracks['Chords'])
t.add_send(destination=project.tracks['Arpeggio'])
for track in project.tracks:
if track.name == 'Chords - Scratch':
track.select()
# Fetch the index for scratch
RPR.ReorderSelectedTracks(1, 1)
ReorderSelectedTracks doesn't seem to make the track 'Chords - Scratch' a child of parent track 'Chords'
Is there some kind of magic I am missing, or is this not implemented yet?
Project.selected_items is returning all items in the project. This may be a bug in reaper since RPR_GetSelectedMediaItems() should only return selected items.
Workaround: use reaper's selected item count as the range, rather than self.n_items:
return [reapy.Item(RPR.GetSelectedMediaItem(self.id, i))
for i in range(RPR.CountSelectedMediaItems(self.id))
]
I've been trying to setup using PyEnv VirtualEnv which lately seems to be preferred way of managing environments. (once you try it, you love it and no going back)
Had a hell of a time finding .dylib file for my virtualenv. Found people linking with main lib folder and all sorts of crazy stuff. I think the answer is Anaconda.
Once you install Pyenv and Pyenv-VirtualEnv Try the following:
> pyenv install -l
Available versions:
..
..
..
..
3.6.8
3.6.9
3.7.0
3.7-dev
3.7.1
3.7.2
3.7.3
3.7.4
3.8-dev
3.9-dev
activepython-2.7.14
activepython-3.5.4
activepython-3.6.0
..
...
..
anaconda3-4.4.0
anaconda3-5.0.0
anaconda3-5.0.1
anaconda3-5.1.0
anaconda3-5.2.0
anaconda3-5.3.0
anaconda3-5.3.1
anaconda3-2018.12
anaconda3-2019.03
ironpython-dev
ironpython-2.7.4
ironpython-2.7.5
ironpython-2.7.6.3
ironpython-2.7.7
jython-dev
jython-2.5.0
jython-2.5-dev
jython-2.5.1
jython-2.5.2
jython-2.5.3
jython-2.5.4-rc1
jython-2.7.0
jython-2.7.1
micropython-dev
micropython-1.9.3
micropython-1.9.4
micropython-1.10
miniconda-latest
miniconda-2.2.2
miniconda-3.0.0
miniconda-3.0.4
miniconda-3.0.5
miniconda-3.3.0
..
..
..
pypy3.6-7.1.0
pypy3.6-7.1.1-src
pypy3.6-7.1.1
pyston-0.5.1
pyston-0.6.0
pyston-0.6.1
stackless-dev
stackless-2.7-dev
stackless-2.7.2
..
..
..
stackless-3.4.7
stackless-3.5.4
Then pick latest Anaconda
> pyenv install anaconda3-5.3.1
Downloading Anaconda3-5.3.1-MacOSX-x86_64.sh.sh...
-> https://repo.continuum.io/archive/Anaconda3-5.3.1-MacOSX-x86_64.sh
Installing Anaconda3-5.3.1-MacOSX-x86_64.sh...
Installed Anaconda3-5.3.1-MacOSX-x86_64.sh to /Users/piotrek/.pyenv/versions/anaconda3-5.3.1
Then switch to new Anaconda environment and out of that spawn environment called reaper
> pyenv shell anaconda3-5.3.1
> pyenv virtualenv reaper
Solving environment: done
==> WARNING: A newer version of conda exists. <==
current version: 4.5.11
latest version: 4.8.0rc0
Please update conda by running
$ conda update -n base -c defaults conda
## Package Plan ##
environment location: /Users/piotrek/.pyenv/versions/anaconda3-5.3.1/envs/reaper
added / updated specs:
- python
The following packages will be downloaded:
package | build
---------------------------|-----------------
libedit-3.1.20181209 | hb402a30_0 159 KB
setuptools-41.6.0 | py38_0 649 KB
libcxx-4.0.1 | hcfea43d_1 1.2 MB
ca-certificates-2019.10.16 | 0 131 KB
sqlite-3.30.1 | ha441bb4_0 2.4 MB
python-3.8.0 | h359304d_2 22.6 MB
certifi-2019.9.11 | py38_0 154 KB
wheel-0.33.6 | py38_0 35 KB
libcxxabi-4.0.1 | hcfea43d_1 458 KB
openssl-1.1.1d | h1de35cc_3 3.4 MB
zlib-1.2.11 | h1de35cc_3 105 KB
pip-19.3.1 | py38_0 1.9 MB
ncurses-6.1 | h0a44026_1 887 KB
------------------------------------------------------------
Total: 34.0 MB
The following NEW packages will be INSTALLED:
ca-certificates: 2019.10.16-0
certifi: 2019.9.11-py38_0
libcxx: 4.0.1-hcfea43d_1
libcxxabi: 4.0.1-hcfea43d_1
libedit: 3.1.20181209-hb402a30_0
libffi: 3.2.1-h475c297_4
ncurses: 6.1-h0a44026_1
openssl: 1.1.1d-h1de35cc_3
pip: 19.3.1-py38_0
python: 3.8.0-h359304d_2
readline: 7.0-h1de35cc_5
setuptools: 41.6.0-py38_0
sqlite: 3.30.1-ha441bb4_0
tk: 8.6.8-ha441bb4_0
wheel: 0.33.6-py38_0
xz: 5.2.4-h1de35cc_4
zlib: 1.2.11-h1de35cc_3
Downloading and Extracting Packages
libedit-3.1.20181209 | 159 KB | ############################################################################################################################################################################################## | 100%
setuptools-41.6.0 | 649 KB | ############################################################################################################################################################################################## | 100%
libcxx-4.0.1 | 1.2 MB | ############################################################################################################################################################################################## | 100%
ca-certificates-2019 | 131 KB | ############################################################################################################################################################################################## | 100%
sqlite-3.30.1 | 2.4 MB | ############################################################################################################################################################################################## | 100%
python-3.8.0 | 22.6 MB | ############################################################################################################################################################################################## | 100%
certifi-2019.9.11 | 154 KB | ############################################################################################################################################################################################## | 100%
wheel-0.33.6 | 35 KB | ############################################################################################################################################################################################## | 100%
libcxxabi-4.0.1 | 458 KB | ############################################################################################################################################################################################## | 100%
openssl-1.1.1d | 3.4 MB | ############################################################################################################################################################################################## | 100%
zlib-1.2.11 | 105 KB | ############################################################################################################################################################################################## | 100%
pip-19.3.1 | 1.9 MB | ############################################################################################################################################################################################## | 100%
ncurses-6.1 | 887 KB | ############################################################################################################################################################################################## | 100%
Preparing transaction: done
Verifying transaction: done
Executing transaction: done
#
# To activate this environment, use:
# > source activate reaper
#
# To deactivate an active environment, use:
# > source deactivate
#
Looking in links: /var/folders/lv/0cl2mzz96ws6hyg03hwdr8th0000gn/T/tmphogl8bqa
Requirement already satisfied: setuptools in /Users/piotrek/.pyenv/versions/anaconda3-5.3.1/envs/reaper/lib/python3.8/site-packages (41.6.0.post20191030)
Requirement already satisfied: pip in /Users/piotrek/.pyenv/versions/anaconda3-5.3.1/envs/reaper/lib/python3.8/site-packages (19.3.1)
So now when you go to the actual environment folder you will see
> ~/.pyenv/versions/reaper$ ls -al
total 0
drwxr-xr-x 8 piotrek staff 256 21 Nov 02:37 .
drwxr-xr-x 3 piotrek staff 96 21 Nov 02:37 ..
drwxr-xr-x 59 piotrek staff 1888 21 Nov 02:37 bin
drwxr-xr-x 20 piotrek staff 640 21 Nov 02:37 conda-meta
drwxr-xr-x 93 piotrek staff 2976 21 Nov 02:37 include
drwxr-xr-x 95 piotrek staff 3040 21 Nov 02:37 lib
drwxr-xr-x 8 piotrek staff 256 21 Nov 02:37 share
drwxr-xr-x 9 piotrek staff 288 21 Nov 02:37 ssl
and lib folder
> ~/.pyenv/versions/reaper/lib$ ls -al
total 84856
drwxr-xr-x 95 piotrek staff 3040 21 Nov 02:37 .
drwxr-xr-x 8 piotrek staff 256 21 Nov 02:37 ..
-rw-r--r-- 3 piotrek staff 154497 28 Aug 2018 Tk.icns
-rw-r--r-- 3 piotrek staff 53684 28 Aug 2018 Tk.tiff
drwxr-xr-x 4 piotrek staff 128 21 Nov 02:37 engines-1.1
drwxr-xr-x 9 piotrek staff 288 21 Nov 02:37 itcl4.1.1
-rwxrwxr-x 2 piotrek staff 838028 28 Oct 2018 libc++.1.0.dylib
lrwxr-xr-x 1 piotrek staff 16 21 Nov 02:37 libc++.1.dylib -> libc++.1.0.dylib
-rw-rw-r-- 2 piotrek staff 1290608 28 Oct 2018 libc++.a
lrwxr-xr-x 1 piotrek staff 16 21 Nov 02:37 libc++.dylib -> libc++.1.0.dylib
-rwxrwxr-x 2 piotrek staff 297040 28 Oct 2018 libc++abi.1.0.dylib
lrwxr-xr-x 1 piotrek staff 19 21 Nov 02:37 libc++abi.1.dylib -> libc++abi.1.0.dylib
-rw-rw-r-- 2 piotrek staff 356968 28 Oct 2018 libc++abi.a
lrwxr-xr-x 1 piotrek staff 19 21 Nov 02:37 libc++abi.dylib -> libc++abi.1.0.dylib
-rw-rw-r-- 2 piotrek staff 121568 28 Oct 2018 libc++experimental.a
-rwxrwxr-x 1 piotrek staff 2538376 21 Nov 02:37 libcrypto.1.1.dylib
-rw-rw-r-- 1 piotrek staff 4201480 21 Nov 02:37 libcrypto.a
lrwxr-xr-x 1 piotrek staff 19 21 Nov 02:37 libcrypto.dylib -> libcrypto.1.1.dylib
-rwxrwxr-x 1 piotrek staff 192188 21 Nov 02:37 libedit.0.dylib
-rw-rw-r-- 2 piotrek staff 289064 20 Jan 2019 libedit.a
lrwxr-xr-x 1 piotrek staff 15 21 Nov 02:37 libedit.dylib -> libedit.0.dylib
-rwxr-xr-x 3 piotrek staff 32900 8 Nov 2017 libffi.6.dylib
-rw-r--r-- 3 piotrek staff 35112 8 Nov 2017 libffi.a
lrwxr-xr-x 1 piotrek staff 14 21 Nov 02:37 libffi.dylib -> libffi.6.dylib
-rwxr-xr-x 1 piotrek staff 952 21 Nov 02:37 libffi.la
lrwxr-xr-x 1 piotrek staff 10 21 Nov 02:37 libform.a -> libformw.a
lrwxr-xr-x 1 piotrek staff 16 21 Nov 02:37 libform.dylib -> libformw.6.dylib
-rwxrwxr-x 2 piotrek staff 70928 28 Nov 2018 libformw.6.dylib
-rw-rw-r-- 2 piotrek staff 111168 28 Nov 2018 libformw.a
lrwxr-xr-x 1 piotrek staff 16 21 Nov 02:37 libformw.dylib -> libformw.6.dylib
-rwxr-xr-x 1 piotrek staff 44144 21 Nov 02:37 libhistory.7.0.dylib
lrwxr-xr-x 1 piotrek staff 20 21 Nov 02:37 libhistory.7.dylib -> libhistory.7.0.dylib
-rw-r--r-- 3 piotrek staff 48304 28 Aug 2018 libhistory.a
lrwxr-xr-x 1 piotrek staff 20 21 Nov 02:37 libhistory.dylib -> libhistory.7.0.dylib
-rwxr-xr-x 1 piotrek staff 154396 21 Nov 02:37 liblzma.5.dylib
-rw-r--r-- 3 piotrek staff 237512 16 May 2018 liblzma.a
lrwxr-xr-x 1 piotrek staff 15 21 Nov 02:37 liblzma.dylib -> liblzma.5.dylib
-rwxr-xr-x 1 piotrek staff 1045 21 Nov 02:37 liblzma.la
lrwxr-xr-x 1 piotrek staff 10 21 Nov 02:37 libmenu.a -> libmenuw.a
lrwxr-xr-x 1 piotrek staff 16 21 Nov 02:37 libmenu.dylib -> libmenuw.6.dylib
-rwxrwxr-x 2 piotrek staff 34812 28 Nov 2018 libmenuw.6.dylib
-rw-rw-r-- 2 piotrek staff 46648 28 Nov 2018 libmenuw.a
lrwxr-xr-x 1 piotrek staff 16 21 Nov 02:37 libmenuw.dylib -> libmenuw.6.dylib
lrwxr-xr-x 1 piotrek staff 15 21 Nov 02:37 libncurses++.a -> libncurses++w.a
-rw-rw-r-- 2 piotrek staff 106576 28 Nov 2018 libncurses++w.a
lrwxr-xr-x 1 piotrek staff 13 21 Nov 02:37 libncurses.a -> libncursesw.a
lrwxr-xr-x 1 piotrek staff 19 21 Nov 02:37 libncurses.dylib -> libncursesw.6.dylib
-rwxrwxr-x 2 piotrek staff 190908 28 Nov 2018 libncursesw.6.dylib
-rw-rw-r-- 2 piotrek staff 322584 28 Nov 2018 libncursesw.a
lrwxr-xr-x 1 piotrek staff 19 21 Nov 02:37 libncursesw.dylib -> libncursesw.6.dylib
lrwxr-xr-x 1 piotrek staff 11 21 Nov 02:37 libpanel.a -> libpanelw.a
lrwxr-xr-x 1 piotrek staff 17 21 Nov 02:37 libpanel.dylib -> libpanelw.6.dylib
-rwxrwxr-x 2 piotrek staff 17852 28 Nov 2018 libpanelw.6.dylib
-rw-rw-r-- 2 piotrek staff 17768 28 Nov 2018 libpanelw.a
lrwxr-xr-x 1 piotrek staff 17 21 Nov 02:37 libpanelw.dylib -> libpanelw.6.dylib
-rwxrwxr-x 2 piotrek staff 17914728 6 Nov 21:53 libpython3.8.a
-rwxrwxr-x 2 piotrek staff 3614176 6 Nov 21:53 libpython3.8.dylib
-rwxr-xr-x 1 piotrek staff 265576 21 Nov 02:37 libreadline.7.0.dylib
lrwxr-xr-x 1 piotrek staff 21 21 Nov 02:37 libreadline.7.dylib -> libreadline.7.0.dylib
-rw-r--r-- 3 piotrek staff 433744 28 Aug 2018 libreadline.a
lrwxr-xr-x 1 piotrek staff 21 21 Nov 02:37 libreadline.dylib -> libreadline.7.0.dylib
-rwxrwxr-x 1 piotrek staff 1578376 21 Nov 02:37 libsqlite3.0.dylib
-rw-rw-r-- 2 piotrek staff 1935112 25 Oct 14:33 libsqlite3.a
lrwxr-xr-x 1 piotrek staff 18 21 Nov 02:37 libsqlite3.dylib -> libsqlite3.0.dylib
-rwxrwxr-x 1 piotrek staff 546720 21 Nov 02:37 libssl.1.1.dylib
-rw-rw-r-- 2 piotrek staff 785720 16 Oct 16:25 libssl.a
lrwxr-xr-x 1 piotrek staff 16 21 Nov 02:37 libssl.dylib -> libssl.1.1.dylib
-rwxr-xr-x 1 piotrek staff 1631044 21 Nov 02:37 libtcl8.6.dylib
-rwxr-xr-x 3 piotrek staff 5056 28 Aug 2018 libtclstub8.6.a
lrwxr-xr-x 1 piotrek staff 11 21 Nov 02:37 libtinfo.a -> libtinfow.a
lrwxr-xr-x 1 piotrek staff 17 21 Nov 02:37 libtinfo.dylib -> libtinfow.6.dylib
-rwxrwxr-x 1 piotrek staff 196704 21 Nov 02:37 libtinfow.6.dylib
-rw-rw-r-- 1 piotrek staff 295144 21 Nov 02:37 libtinfow.a
lrwxr-xr-x 1 piotrek staff 17 21 Nov 02:37 libtinfow.dylib -> libtinfow.6.dylib
-rwxr-xr-x 1 piotrek staff 1499840 21 Nov 02:37 libtk8.6.dylib
-rwxr-xr-x 3 piotrek staff 3960 28 Aug 2018 libtkstub8.6.a
-rwxrwxr-x 1 piotrek staff 100996 21 Nov 02:37 libz.1.2.11.dylib
lrwxr-xr-x 1 piotrek staff 17 21 Nov 02:37 libz.1.dylib -> libz.1.2.11.dylib
-rw-rw-r-- 2 piotrek staff 117448 21 Nov 2018 libz.a
lrwxr-xr-x 1 piotrek staff 17 21 Nov 02:37 libz.dylib -> libz.1.2.11.dylib
drwxr-xr-x 28 piotrek staff 896 21 Nov 02:37 pkgconfig
drwxr-xr-x 213 piotrek staff 6816 21 Nov 02:37 python3.8
drwxr-xr-x 4 piotrek staff 128 21 Nov 02:37 sqlite3.21.0
drwxr-xr-x 5 piotrek staff 160 21 Nov 02:37 tcl8
drwxr-xr-x 17 piotrek staff 544 21 Nov 02:37 tcl8.6
-rw-r--r-- 1 piotrek staff 9428 21 Nov 02:37 tclConfig.sh
-rw-r--r-- 3 piotrek staff 773 28 Aug 2018 tclooConfig.sh
drwxr-xr-x 7 piotrek staff 224 21 Nov 02:37 tdbc1.0.6
drwxr-xr-x 5 piotrek staff 160 21 Nov 02:37 tdbcmysql1.0.6
drwxr-xr-x 5 piotrek staff 160 21 Nov 02:37 tdbcodbc1.0.6
drwxr-xr-x 5 piotrek staff 160 21 Nov 02:37 tdbcpostgres1.0.6
lrwxr-xr-x 1 piotrek staff 17 21 Nov 02:37 terminfo -> ../share/terminfo
drwxr-xr-x 5 piotrek staff 160 21 Nov 02:37 thread2.8.2
drwxr-xr-x 40 piotrek staff 1280 21 Nov 02:37 tk8.6
-rw-r--r-- 1 piotrek staff 4858 21 Nov 02:37 tkConfig.sh
and TADA:
-rwxrwxr-x 2 piotrek staff 3614176 6 Nov 21:53 libpython3.8.dylib
So now we can satisfy Reaper python setup
Now ensure again we are running in new reaper
env
> ~/.pyenv/versions/reaper$ pyenv shell
reaper
if not just switch
pyenv shell reaper
install reapy
pip install python-reapy
run reapy test
piotrek@pmac3:~/.pyenv/versions/reaper$ python -m reapy
/Users/piotrek/.pyenv/versions/reaper/lib/python3.8/site-packages/reapy/tools/_inside_reaper.py:14: DisabledDistAPIWarning: 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
/Users/piotrek/.pyenv/versions/reaper/lib/python3.8/site-packages/reapy/reascripts/enable_dist_api.py
Disable dist API
/Users/piotrek/.pyenv/versions/reaper/lib/python3.8/site-packages/reapy/reascripts/disable_dist_api.py
as you can see runs from correct pyenv reaper path however we know that
they are called .dylib
files on mac not .dll
any way you can provide a dual check?
However that still doesn't matter since as soon as I try to do LoadScript reaper crashes. All that for nothing? Any hints? Anyone on Mac tried this from virtualenv?
Hi,
I'm trying to use the library to add a wav from an actual wave file on my disk to a track in a Reaper project.
I tried using the following steps:
The last step does not seem to work (1 to 3 work fine and I can see the results live in the Reaper project). I checked the reapy.core.item.take and reapy.core.item.source code and I can see that
Take.source and Source.filename are "read only" properties so they cannot be set.
I tried using the native reascript_api calls to try and initialize a new source with my_wave_filename.
This does nothing and the take source file does not change in the Reaper project.
I tried setting an already available source from another track/item/take and it works juste fine.
This seems to me like the reascript_api calls (specifically PCM_Source_CreateFromFile() ) do not work as expected.
Any thoughts?
As asked by this forum post there should be a reapy
version of RPR.TrackFX_AddByName
and RPR.TakeFX_AddByName
.
Hi Romeo,
I'm really excited about your Pythonic interface to Reaper! This issue is probably user error but I'm not sure where to post my question. I'm able to add tracks, items, and takes--but not MIDI notes with this code, which I expected to add 8 notes:
# load Reaper library/API
import reapy
from random import randint as r
# connect to current project
project = reapy.Project()
# add a new track, item, take, and notes
track = project.add_track(name="drums")
item = track.add_midi_item(start=0,end=2)
take = item.add_take()
for n in range(0,8):
take.add_note(start=n,end=n+0.1,pitch=r(0,127),channel=1,unit="beats")
For example when using AudioAccessor.get_samples with a too large n_samples_per_channels, some data seems to get lost and json can't decode the output.
How do You feel about using SWS functions inside the library code?
I could made a major update for the Send class, but it depends on some SWS.
Now my Jedi completion does not see autogenerated API.
But, I think it's not so hard to change, within, maybe moving some imports at the start of files?
Bug originally reported on the Cockos forum thread here. Just copying it here for easier reference.
I'm having trouble with Track FX, when trying to use an FX name as an index, whereby I got a KeyError.
To further investigate, I tried to duplicate the basic example on page https://python-reapy.readthedocs.io/en/latest/reapy.core.html#reapy.core.FX which is:
Code:
>>> fx_list = track.fxs >>> fx_list[0] FX(parent_id="(MediaTrack*)0x0000000006CDEBE0", index=0) >>> len(fx_list) 1 >>> fx_list["VST: ReaComp (Cockos)"] FX(parent_id="(MediaTrack*)0x0000000006CDEBE0", index=0)But my test case fails with:
KeyError: 'No FX named VST: ReaComp (Cockos)'
It was run outside reaper, on a project that had ReaComp as the only FX on a Selected track:
Code:
import reapy, sys project = reapy.Project() x = project.selected_tracks if len(x) != 1: sys.exit(1) track = x[0] fx_list = track.fxs print("Number of FX is", track.n_fxs) print(fx_list[0]) print(fx_list[0].name) print(fx_list["VST: ReaComp (Cockos)"]) # Gets KeyErrorAnd here is the output:
Code:
Number of FX is 1 FX(parent_id="(MediaTrack*)0x00000000049C0EE0", index=0) VST: ReaComp (Cockos) Traceback (most recent call last): File "D:\Work\bug1.py", line 11, in <module> print(fx_list["VST: ReaComp (Cockos)"]) # Gets KeyError File "C:\Users\Tom Parker\AppData\Local\Programs\Python\Python38\lib\site-packages\reapy\core\fx\fx.py", line 409, in __getitem__ i = self._get_fx_index(name=i) File "C:\Users\Tom Parker\AppData\Local\Programs\Python\Python38\lib\site-packages\reapy\core\fx\fx.py", line 434, in _get_fx_index raise KeyError("No FX named {}".format(name)) KeyError: 'No FX named VST: ReaComp (Cockos)'I'm running Reaper 5.99/x64, Reapy 0.6.0, and Python 3.8.2.
It would be nice to ensure Python 2.7+ is supported by reapy
.
I'm not sure if this is a bug or if I am using the API incorrectly. But when I iterate over projects and their tracks, I lose access to track attributes such as name, items, etc.
Here is some lua code:
projects = {}
for i = 0, 10 do
retval, projfn = reaper.EnumProjects(i)
if retval ~= nil then
projects[i] = {}
projects[i][i] = retval
end
end
projectCount = tableLength(projects) -- just gets the number of elements in the project table
for x = 0, projectCount -1 do
projecttrackCount = reaper.CountTracks(projects[x][x])
projects[x].trackCount = projecttrackCount
end
index = 0
for x = 0, projectCount -1 do
trackCount = projects[x].trackCount
for y = 0, trackCount -1 do
track = reaper.GetTrack(projects[x][x], y)
retval, trackname = reaper.GetSetMediaTrackInfo_String(track, "P_NAME", "string", false )
Msg(trackname)
end
end
What this does is gets the number of projects, gets the number of tracks in each project, and stores to a table. Then I iterate over each project, then each track and retrieve the name of the track and Msg out to the Reaper console. It's long-winded, but this shows that in Lua I don't have to be aware of the current project setting.
Here is some (simpler!!) reapy python code:
import reapy as rp
with rp.inside_reaper():
for proj in rp.get_projects():
print([s.name for s in proj.tracks])
I am attempting to do exactly the same here by iterating over every project and using the OOB abilities of reapy to retrieve the track names. However I only ever get the track names for whichever project is currently active in reaper.
Is this a bug, or am I misunderstanding the API?
I'm not sure reapy needs it, but, several times, yet I was wondering of wrapping reapy.core
classes into ยซaggressiveยป decorators, which will invoke make_current_project
and connect
on initialization and attribute access. As well as @inside_reaper
does.
I'm still not sure it is good idea, even if turned on within environment variable or config value, as sometimes we cannot control its influence on GUI, performance, while cannot guarantee stability in cases, when attributes are used after resolving. But, deeply in the soul I wish to write:
o_track = ss.MasterOutTrack(
track=rpr.Track(id='out', project=rpr.Project(MASTER_PROJ_NAME)),
slave=ss.SlaveProject(),
target=ss.SlaveInTrack(
rpr.Track(id='in', project=rpr.Project(SLAVE_PROJECT_NAME))
)
)
instead of
m_pr = rpr.Project(MASTER_PROJ_NAME)
s_pr = rpr.Project(SLAVE_PROJECT_NAME)
with m_pr.make_current_project():
pr = rpr.Project().name
sleep(1)
m_tr = rpr.Track(id='out', project=m_pr)
with s_pr.make_current_project():
s_tr = rpr.Track(id='in', project=s_pr)
o_track = ss.MasterOutTrack(
track=m_tr, slave=ss.SlaveProject(), target=ss.SlaveInTrack(s_tr)
)
I don't have time for that right now, but I can forget the steps:
argparse
for the __main__.py
dir_ = pathlib.Path('/usr/lib/x86_64-linux-gnu')
so = list(dir_.glob('libpython3*.so'))[0]
dir_
to the 'reaper.ini': 'REAPER', 'pythonlibpath64'
so
to the 'reaper.ini': 'REAPER', 'pythonlibdll64'
SCR 4 0 RS51d805a68ee3c2516cf4d3dc757e5fb67e3719df "Custom: activate_reapy_server.py" {activate_server_path}
to the reaper-kb.ini
I think, I'll make nails-made solution for Linux today during my CI research, but we'll need to think about making it cross-platform
On the start of my project, I've made some tests considering how to keep objects between Reaper sessions.
And, occasionally, I found, that id property is good. But the test itself was wrong, and only today I really got that id property is nothing than just a pointer. So, at first, I think, the docs should be updated to clearly make user understand that id persists only during one Reaper session.
At the second, I think we should consider the unified interface to save and restore objects, like it can be done with Track.GUID, for example.
def has_ext_state(self, section, key):
"""
Return whether extended state exists for given section and key.
Parameters
----------
section : str
Extended state section.
key : str
Extended state key.
Returns
-------
has_ext_state : bool
"""
has_ext_state = bool(RPR.HasExtState(section, key))
return has_ext_state
making stub files for mypy and cannot reveal the type of them. Maybe, I can also fix the missing, if they are)
This call to RPR.SetMediaItemInfo_Value does not work when iterating over items gotten from project.items.
with rp.inside_reaper():
all_items = project.items
max_group_id = [item.get_info_value('I_GROUPID') for item in all_items]
max_group_id = int(max(max_group_id))
selected_items = project.selected_items
for item in selected_items:
new_group_id = max_group_id + 1
RPR.SetMediaItemInfo_Value(item, 'I_GROUPID', new_group_id)
If I swap the for loop for the following:
for item in range(0, len(selected_items)):
gotten = RPR.GetSelectedMediaItem(0, item)
RPR.SetMediaItemInfo_Value(gotten, 'I_GROUPID', new_group_id)
Then I get the result I expect - the items I select should all be in the same group.
Script execution error
Traceback (most recent call last):
File "master.py", line 43, in <module>
main_loop()
File "master.py", line 27, in main_loop
if rpr.Project().play_state() not in ('play, record'):
File "/home/levitanus/.local/lib/python3.7/site-packages/reapy/core/project/project.py", line 688, in play_state
state = states[RPR.GetPlayStateEx(self.id)]
KeyError: 0
worked:
@property
def play_state(self):
"""
Project play state ("play", "pause" or "record").
:type: str
"""
states = {0: 'stop', 1: "play", 2: "pause", 4: "record"}
state = states[RPR.GetPlayStateEx(self.id)]
return state
Hi
first of all, thanks for all your efforts making this module.. really appreciated :)
I'm using reapy to build automation flows and tests based on REAPER where I have an issue under MAC
what I noticed (see attached image) whenever REAPER get crashed for any reason like adding defect fx, I cannot continue using reapy with REAPER in the same session and many times it required to restart the OS to solve it.
under Win, I used reapy.reconnect() and all works well
any advise?
Regards
reapy imports only reaper_python module, still many functions (within installed SWS) are placed inside sws_python module.
It includes all reaper_python functions
I've tried to locate the import statement of the client (inside reaper), but haven't got success...
Tried to import sws_python inside reascript_api module, but it doesn't work...
The distant API seemed to have all functions from SWS repository wrapped.
during my last experience with reapy (last spring, I think), I found that retriveing of audio data through socket is almost impossible because of timeouts.
Considering this I want to suggest reaper-independed import of source.
I'm going to make small help-lib with usage of librosa as audio accessing and analysing tool, and, if You don't mind, I can implement it as part of reapy package, for example, by extending of item sub-package.
But this solution has quite remarkable contra: adding dependecy of heavy librosa (which depends on numpy and scipy) to the reapy package.
But, also, librosa has a great advantage of loading audio within resampling and seeking inside with float time, which takes off a tone of support code, needed for working with raw wave data got from Reaper.
So I need your feedback on this idea and, maybe, will look to other variants, pointed by you.
I think it's good idea to make this functions availble to run outside for just testing purposes.
I've built this implementation in 10 minutes, maybe there is a point to test it and include?
import reapy as rpr
import atexit
import time
def safe_defer(f, *args, **kwargs):
if rpr.is_inside_reaper():
return rpr.defer(f, *args, **kwargs)
time.sleep(.03)
return f(*args, **kwargs)
def safe_at_exit(f, *args, **kwargs):
if rpr.is_inside_reaper():
return rpr.at_exit(f, *args, **kwargs)
atexit.register(f, *args, **kwargs)
if __name__ == '__main__':
def test_loop(i):
print(i)
safe_defer(test_loop, i + 1)
safe_at_exit(print, 'exiting')
test_loop(0)
P.S. I'll wrap original functions in my local copy of reapy and watch how things will go.
I don't like this sleep(.03) statement, because, as I interpret ReaScript explanation, defer is more like acync call, then just waiting. So, theoretically something like that:
defer(first)
defer(second)
defer(third)
will be put in queue, but executed shorter than in .09 sec
First of all - love this module, it's kind of exactly what i was looking for... I really appreciate a project that "just works" - nicely done!
I noticed there is no method to start the recording on a project. I can play(), pause() and stop() - shouldn't there be a record() too? I mean there is CSurf_OnRecord, but having a record method in Project would be more elegant...
Is that just not implemented, or is there another reason for not providing it? If it's an easy fix, I would be up for creating a PR.
Thanks & Cheers,
Christian
Hi!
I'm unable to install Reapy. The PIP procedure is fine, the modules are in my only Python (3.9) site-packages folder but each time I try to run:
python -c "import reapy; reapy.configure_reaper()" from the windows command prompt while Reaper is running, I get:
C:\Users\Patrick\AppData\Local\Programs\Python\Python39\lib\site-packages\reapy\tools\network\machines.py:99: DisabledDistAPIWarning: Can't reach distant API. Please start REAPER, or call reapy.config.enable_dist_api() from inside REAPER to enable distant API.
warnings.warn(errors.DisabledDistAPIWarning())
Both Python and the path to site-packages are inscribed in Windows PATH environment variable.
What am I doing wrong?
Thanks for all!
Hi,
first of all thanks for creating reapy it is of great use.
I installed the SWS Extension sucessfully. (The menus show up under Extensions)
But when I try to use them from outside with python I get errors:
from reapy import reascript_api as rpr
FILE_NAME = "YOUR AUDIO FILE"
rpr.InsertTrackAtIndex(0, False)
track = rpr.GetTrack(0, 0)
item = rpr.AddMediaItemToTrack(track)
rpr.SetMediaItemLength(item, 1, False)
take = rpr.AddTakeToMediaItem(item)
rpr.BR_SetTakeSourceFromFile(take, FILE_NAME, False)
rpr.UpdateArrange()
throws
AttributeError: module 'reapy.reascript_api' has no attribute 'BR_SetTakeSourceFromFile'
I am on Ubuntu 19.10 what could be the problem?
Thank you very much
Best
Tim
I'm confused in quick localizing the issue and suggesting the solution.
When I received the deferred script error
with subclassing reapy.Project
I had checked the cache mechanic and, mainly understood what is going there. But I'm totally confused of how can it be resolved:
importlib
arg is changed from the reapy.core to the something cacheble, it can allow to import the same classes from inside reaper.inside_reaper()
work really inside, and, considering this, I wonder why not to pickle?I'm writing some wrapper classes around the Reapy classes so I can pull all of the best bits of Numpy, SciPy, and Librosa into a selection of "media item analysis classes". It's working quite well when running PycharmCE and Reapy. I can do all the stuff I want to do.
Now I'm thinking about how to interface with Reaper, and trigger methods within these classes from Reaper.
Is it possible to have any kind of cross communication between Reaper and Reapy?
Take this small example:
import reapy as rp
class ReapyConnection:
def __init__(self):
self.project = rp.Project()
def get_Selected_Items(self):
with rp.inside_reaper():
selected_items = self.project.selected_items
rp.show_console_message(selected_items)
while True:
con = ReapyConnection()
I have an object called con, which is instantiating an instance of the ReapyConnection class. What I want to do is from inside Reaper tell that instance to call it's get_Selected_Items() method.
Is this possible?
line 159 GetTakeInfo_Value
has to be GetMediaItemTakeInfo_Value
don't want to make pull-request for 1 line)
I'am trying to update reapy from 0.5 version to 0.8 and get this:
> pip install python-reapy
Collecting python-reapy
...
Installing collected packages: psutil, python-reapy
Running setup.py install for psutil: started
Running setup.py install for psutil: finished with status 'error'
...
... fatal error C1083: ... No such file or directory,
VisualStudio is not installed; get it from http://www.visualstudio.com/...
Am i doing smth wrong or i need VS to use reapy?
Well, it is not just about reapy
, but about the reaper_python
itself also.
At first, reaper_python.py
uses encode('utf-8')
for the any of string arguments taken to and from the C interface. But, here the thing, if we take, for example the RPR_MIDI_GetEvnt
with SysEx, for example, it will crash as it cannot be encoded to the utf-8.
Moving forward I've patched the function just to see where it can lead to, and, occasionally, reapy can't work with bytes also, so, I've tried to patch reapy server, and it, somehow, still tries to dump the bytes. I suppose to can handle it at the next iterations, but here the place I stopped, as now I feel that do some stuff in lua
is cheaper, than do on python.
So, I have a question: what do we do? Look for all the "bytes" functions in the original reaper_python.py
and ask Justin to fix 'em or make a lua helper for the particular things? I ask, as I never succeed with bug reports on the cokos forum.
as I understand, the original avoiding of this methods could be caused by undefined size of ext state.
More than, I discovered, that API does not return size of passed state, as it docmented.
But, generally, this code works well for me, and I think, within documentation (inside docstring or in the main doc) it can be integrated to the reapy.Project:
import reapy as rpr
import reapy.reascript_api as RPR
import typing as ty
def get_ext_state(project: rpr.Project, section: str, key: str) -> str:
size_str: str
(_, _, _, _, size_str, _) = RPR.GetProjExtState( # type:ignore
project.id, section, key+'_size', 'valOutNeedBig', 1001
)
size = int(size_str)
(_, _, _, _, result, _) = RPR.GetProjExtState( # type:ignore
project.id, section, key, 'valOutNeedBig', size+1
)
rpr.print('get_size_str: ', size_str)
rpr.print(size)
return ty.cast(str, result)
def set_ext_state(
project: rpr.Project, section: str, key: str, value: str
) -> int:
size: int = len(value)
RPR.SetProjExtState( # type:ignore
project.id, # noob formatting comment
section,
key,
value
)
size_str: str = str(str(size).encode().zfill(1000), 'utf-8')
rpr.print('set_size_str: ', size_str)
RPR.SetProjExtState( # type:ignore
project.id, # noob formatting comment
section,
key+'_size',
size_str
)
return size
It can sound like a saving on trifles, but I've found some leakage in performance of original API calls.
I've started profiling from the function which inserting about 2500 MIDI events (average 2-min MIDI-item), it took above 6 sec from the outside of reaper, where only 1 sec was spent on the data transfer.
Thanks to easy access to the MIDI_InsertEvt
function (which takes 0.5 sec on 2500 calls), I've made some changes to not initialize the full-sized string buffer on the call and, surprise, it made significantly faster (0.05 sec on 2500 calls).
So, I want to make some conclusions from this:
reaper_python.py
, so, maybe, patching should be madeAlso, I would leave it here to just show API calls which we may consider of reducing:
ncalls tottime percall cumtime percall filename:lineno(function)
2882 0.008 0.000 3.166 0.001 take.py:416(_resolve_midi_unit)
3219 0.012 0.000 3.047 0.001 take.py:436(resolver)
3220 0.004 0.000 2.870 0.001 track.py:530(project)
3219 0.020 0.000 2.867 0.001 track.py:71(_get_project)
2545 0.010 0.000 2.574 0.001 take.py:33(add_event)
3219 0.034 0.000 2.343 0.001 reaper.py:300(get_projects)
12876 0.033 0.000 2.290 0.000 project.py:16(__init__)
12876 0.072 0.000 2.249 0.000 reaper_python.py:875(RPR_EnumProjects) !!! too much calls?
12876 0.018 0.000 2.118 0.000 reaper_python.py:42(rpr_packs) !!! original slow unicode version of putting string to the C function
15421 2.099 0.000 2.101 0.000 __init__.py:47(create_string_buffer) !!! this is inside above call, size matters
337 0.002 0.000 0.681 0.002 take.py:96(add_note)
6438 0.012 0.000 0.494 0.000 track.py:80(<listcomp>)
22533 0.009 0.000 0.482 0.000 track.py:658(__iter__)
22535/6439 0.027 0.000 0.474 0.000 track.py:653(__getitem__)
6439 0.015 0.000 0.466 0.000 track.py:670(_get_items_from_slice)
40847 0.132 0.000 0.433 0.000 reaper_python.py:15(rpr_packp) !!! one more refactoring candidate, it makes work not needed thanks to your id variables
6439 0.011 0.000 0.320 0.000 track.py:673(<listcomp>)
19316 0.037 0.000 0.294 0.000 track.py:46(__init__)
16096 0.045 0.000 0.248 0.000 reaper_python.py:1987(RPR_GetTrack)
40847 0.106 0.000 0.181 0.000 reaper_python.py:34(RPR_ValidatePtr)
11866 0.006 0.000 0.127 0.000 {built-in method builtins.len}
6439 0.005 0.000 0.121 0.000 track.py:663(__len__)
6439 0.006 0.000 0.116 0.000 project.py:763(n_tracks)
6439 0.018 0.000 0.110 0.000 reaper_python.py:314(RPR_CountTracks)
40847 0.025 0.000 0.109 0.000 re.py:170(match)
92024 0.066 0.000 0.089 0.000 __init__.py:73(CFUNCTYPE)
35077 0.066 0.000 0.066 0.000 reaper_python.py:27(rpr_unpackp)
3219 0.006 0.000 0.062 0.000 take.py:526(track)
2882 0.006 0.000 0.058 0.000 take.py:240(item)
3219 0.004 0.000 0.052 0.000 take.py:174(beat_to_ppq)
2882 0.009 0.000 0.050 0.000 reaper_python.py:1363(RPR_GetMediaItemTake_Item)
3220 0.003 0.000 0.050 0.000 project.py:1119(time_to_beats)
2883 0.002 0.000 0.050 0.000 item.py:125(position)
3219 0.009 0.000 0.049 0.000 reaper_python.py:1384(RPR_GetMediaItemTake_Track)
3219 0.013 0.000 0.049 0.000 reaper_python.py:2645(RPR_MIDI_GetPPQPosFromProjQN)
2883 0.003 0.000 0.048 0.000 item.py:51(get_info_value)
3220 0.011 0.000 0.047 0.000 reaper_python.py:3903(RPR_TimeMap2_timeToQN)
40847 0.046 0.000 0.046 0.000 {method 'match' of 're.Pattern' objects}
2883 0.010 0.000 0.045 0.000 reaper_python.py:1342(RPR_GetMediaItemInfo_Value)
2545 0.009 0.000 0.044 0.000 additional_api.py:292(MIDI_InsertEvt)
43730 0.030 0.000 0.041 0.000 reaper_python.py:39(rpr_packsc)
40847 0.026 0.000 0.038 0.000 re.py:271(_compile)
337 0.026 0.000 0.030 0.000 reaper_python.py:2708(RPR_MIDI_InsertNote)
184048 0.023 0.000 0.023 0.000 {method 'pop' of 'dict' objects}
114215 0.022 0.000 0.022 0.000 {built-in method builtins.isinstance}
12876 0.013 0.000 0.017 0.000 reaper_python.py:46(rpr_unpacks)
12876 0.010 0.000 0.016 0.000 reapy_object.py:41(_is_defined)
59151 0.016 0.000 0.016 0.000 {method 'encode' of 'str' objects}
40847 0.011 0.000 0.011 0.000 {method 'groups' of 're.Match' objects}
337 0.007 0.000 0.011 0.000 render_midi.py:190(_get_note)
6439 0.006 0.000 0.009 0.000 project.py:1140(tracks)
28972 0.008 0.000 0.008 0.000 {method 'endswith' of 'str' objects}
2545 0.003 0.000 0.008 0.000 additional_api.py:14(packs_l)
15421 0.006 0.000 0.006 0.000 {method 'decode' of 'bytes' objects}
16096 0.006 0.000 0.006 0.000 {method 'startswith' of 'str' objects}
2545 0.003 0.000 0.005 0.000 take.py:293(_midi_to_bytestr)
6439 0.004 0.000 0.004 0.000 {method 'indices' of 'slice' objects}
7916 0.004 0.000 0.004 0.000 render_midi.py:43(mmsg_parce)
12876 0.003 0.000 0.003 0.000 {built-in method builtins.hasattr}
6439 0.003 0.000 0.003 0.000 track.py:636(__init__)
10200 0.003 0.000 0.003 0.000 render_midi.py:185(<genexpr>)
9657 0.002 0.000 0.002 0.000 {method 'append' of 'list' objects}
2884 0.002 0.000 0.002 0.000 item.py:10(__init__)
1 0.000 0.000 0.002 0.002 track.py:158(add_midi_item)
1 0.002 0.002 0.002 0.002 reaper_python.py:321(RPR_CreateNewMIDIItemInProj)
3219 0.001 0.000 0.001 0.000 {method 'pop' of 'list' objects}
337 0.001 0.000 0.001 0.000 typing_extensions.py:1573(_dict_new)
6 0.000 0.000 0.000 0.000 {built-in method builtins.__build_class__}
1 0.000 0.000 0.000 0.000 item.py:46(delete)
1 0.000 0.000 0.000 0.000 reaper_python.py:745(RPR_DeleteTrackMediaItem)
338 0.000 0.000 0.000 0.000 {built-in method _ctypes.byref}
1 0.000 0.000 0.000 0.000 item.py:198(track)
1 0.000 0.000 0.000 0.000 reaper_python.py:1405(RPR_GetMediaItemTrack)
1 0.000 0.000 0.000 0.000 item.py:20(active_take)
1 0.000 0.000 0.000 0.000 reaper_python.py:1013(RPR_GetActiveTake)
1 0.000 0.000 0.000 0.000 track.py:345(items)
1 0.000 0.000 0.000 0.000 {built-in method builtins.print}
1 0.000 0.000 0.000 0.000 reaper_python.py:307(RPR_CountTrackMediaItems)
1 0.000 0.000 0.000 0.000 track.py:355(<listcomp>)
6 0.000 0.000 0.000 0.000 __init__.py:99(CFunctionType)
1 0.000 0.000 0.000 0.000 reaper_python.py:2050(RPR_GetTrackMediaItem)
2 0.000 0.000 0.000 0.000 {built-in method time.time}
3 0.000 0.000 0.000 0.000 render_midi.py:150(<genexpr>)
1 0.000 0.000 0.000 0.000 take.py:10(__init__)
1 0.000 0.000 0.000 0.000 {method 'values' of 'dict' objects}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
I've updated on Xubuntu 20.04 and, eventually, there is no direct support of typing_extensions module by python3.8 here. It can be installed manually within apt, but the fact it breaks installation of reapy is disaster. I'll think how to handle this on a week
Every time a script with a reapy
client exits, the server raises the following exception:
Deferred script execution error
Traceback (most recent call last):
File "defer", line 1, in <module>
File "activate_reapy_server.py", line 27, in main_loop
SERVER.send_results(results)
File "/usr/local/Cellar/python/3.7.4/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/reapy/reascript_api/network/server.py", line 115, in send_results
self._send_result(connection, result)
File "/usr/local/Cellar/python/3.7.4/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/reapy/reascript_api/network/server.py", line 82, in _send_result
connection.send(result)
File "/usr/local/Cellar/python/3.7.4/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/reapy/reascript_api/network/socket.py", line 68, in send
self._socket.sendall(length)
BrokenPipeError: [Errno 32] Broken pipe
The user is required to manually close the error pop-up through the GUI. Is there any for the client to close the connection, so that this doesn't happen every time a program completes execution?
System info:
OSX 10.14.6
python 3.7.4
python-reapy 0.3.0
Reaper v5.983
Currently, we have time_to_ppq and ppq_to_beat from the native reaper API, and same for reversed.
It would be convenient to provide a time_to_beat and beat_to_time function to the Take class.
The workaround currently is to define the following function
def time_to_beat(take, t):
return take.ppq_to_beat(take.time_to_ppq(t))
As you can see, the take argument is completely unnecessary except for the calling of two methods. Thus if we simply implement this method into Take class, we only need to provide t as the only argument, which is consistent with the two native methods used above.
When adding MIDI notes to item (actually to item's take) nothing happens. Here's what I did in shell:
>>> import reapy
>>> p = reapy.Project()
>>> t = p.add_track()
>>> mi = t.add_midi_item(0, 10)
>>> tk = mi.active_take
>>> tk.add_note(0, 2, 60)
Item appears in Reaper, yet no notes seen. Neither in MIDI editor.
in my package i'm implementing folowing structure:
While I had server only on slave.py everything was OK, but adding server at master.py made things weird:
Occasionally, I cannot make it stable, catching some crashes, within separatelly turning master and slave scripts on and off when both: master.py and slave.py has servers.
Because of non-verbose Reaper crashes I cannot find the point of failure, but sometimes I catch traceback to the reapy.defer and distant_api. Can it be some tcp conflicts of my servers and reapy?
https://www.youtube.com/watch?v=vF0wT0BA8xI&feature=youtu.be
(the last reaper dissapearing is crash)
@RomeoDespres
just added my first functions to reapy, hope coding style is OK.
I stumbled on one thing. When I add the decorator @reapy.inside_reaper() the function call crashed. Is that due to the fact, that I am using a different installation of reapy inside reaper than for development?
Thanks!
In the project class add_track method could functionality be added so that when adding a track we could specify the name of the created track?
A keyword argument would work great for this so that if a name is not wanted it could be left blank.
I'm writing an external tool that occasionally polls Reaper about its active project tab, whether it's rendering, stuff like that.
It seems whenever Reaper throws an error box, the reapy "host" gets stuck in a state where my running code throws ConnectionResetError: [WinError 10054] An existing connection was forcibly closed by the remote host
and I have to restart the tool. Given that the tool is designed to be fire-and-forget, I'd like to avoid this.
Any pointers? Any way of reinitializing reapy without restarting my tool?
As I understand there is no really difference in connection to localhost or, for example, to 192.168.0.2:2307.
Can it be implemented as use-case? Now I see solution in extraction IP to the config.py
as well as WEB_INTERFACE_PORT
, and reassigning at need. But I'm not sure in consequences of just this extraction: Could for example couple of scripts work together with different IP?)
I tried to use a simple pass through tracks
import reapy
project = reapy.Project()
for track in project.tracks:
print(track.GUID)
and got an endless loop
(GUID*)0x000000000279C7C0
(GUID*)0x00000000027F0430
(GUID*)0x00000000028028A0
(GUID*)0x0000000002814D10
(GUID*)0x000000000279C7C0
(GUID*)0x000000000279C7C0
(GUID*)0x000000000279C7C0
...
but reaper project contains only four tracks.
Am I doing something wrong?
Since #74 brings c-bindings, we can discuss the possibilities for GUI.
I see 3 ways of it core:
any ideas?
Ideally, they would fix the native REAPER misbehavior reported here and allow for function input and not just str.
Currently there's no test involved in the source code at all, would you consider the option of adding pytest (and likely pytest-cov pytest-benchmark) to the project for unit testing?
We can use monkeypatch fixture to mock the return of ReaScript API, and gradually build up a mock module for all tests.
If you would like to consider this possibility, I can look into it and start implementing some basic tests.
Hi all,
just wanted to check if no ones gets angry.
Wanted to start a small blog on this topics to help other users get Python and Reapy installed and maybe enlarge the community a bit. Are you OK with that? Until now I did not find something on that (except the Reapy doc ;-))
How from your side of view is better to handle distant errors?
I couldn't imagine better solution than
try:
<do_code>
except: Exception as e:
if "reapy.errors.UndefinedMarkerError" in str(e):
<handle>
else:
raise e
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.