Code Monkey home page Code Monkey logo

reapy's People

Contributors

chaberch avatar kostikvento avatar levitanus avatar mercuree avatar romeodespres avatar teetow avatar tomas1808 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

reapy's Issues

Parent/Child Track with ReorderSelectedTracks

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?

reapy.core.Project.selected_items gets non-selected items

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))
        ]

MacOSX - Python3.8 - PyEnv VirtualEnv - Anaconda

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

Screenshot 2019-11-21 at 02 55 46

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
Screenshot 2019-11-21 at 02 59 51

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?

Inserting a wav file in a track/item/take.

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:

  1. Create a new track. new_track = proj.add_track(..)
  2. Add a new item. new_item = new_track.add_item(..)
  3. Add a new take. new_take = new_item.add_take(..)
  4. Finally associate my wave file name to new_take.source.filename.

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.

  1. my_src_id = RPR.PCM_Source_CreateFromFile(my_wave_filename)
  2. RPR.SetMediaItemTake_Source(new_take.id, my_src_id)

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?

unable to add MIDI notes

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")

Bug - KeyError raised when accessing Track FX by name

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 KeyError

And 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.

Python 2 support

It would be nice to ensure Python 2.7+ is supported by reapy.

Iterating over project tracks retrieves attributes only for the current project

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?

add ยซaggressiveยป mode

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)
)

command-line installation

I don't have time for that right now, but I can forget the steps:

  • make argparse for the __main__.py
  • make cross-platform python library lookup, for Linux it is:
    dir_ = pathlib.Path('/usr/lib/x86_64-linux-gnu')
    so = list(dir_.glob('libpython3*.so'))[0]
  • make reaper resource folder lookup (God knows, how, maybe take from argparce)
  • add dir_ to the 'reaper.ini': 'REAPER', 'pythonlibpath64'
  • add so to the 'reaper.ini': 'REAPER', 'pythonlibdll64'
  • add line SCR 4 0 RS51d805a68ee3c2516cf4d3dc757e5fb67e3719df "Custom: activate_reapy_server.py" {activate_server_path} to the reaper-kb.ini
  • somehow run this action (OSC?, register startup somewhere?)

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

standardize serialization of core objects (tracks, projects, items etc)

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.

has_ext_state -> remove self arg

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

RPR.SetMediaItemInfo_Value() not working for project.items

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.

update play_state dict

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

reconnect issue under Mac OS

Hi
Screen Shot 2020-09-29 at 10 54 33 AM
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

sws api is missing

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.

retriveing of audio data from outside of reaper

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.

add 'outside_reaper' mode for defer and at_exit

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

Start recording through api

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

Unable to install

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!

SWS functions not working

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

Subclassing is unavailble

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:

  • mainly, I can suggest that if importlib arg is changed from the reapy.core to the something cacheble, it can allow to import the same classes from inside reaper.
  • but I consider, that such mechanic is chosen for avoiding of losing the uncacheble data from third-party classes.
  • also, a couple of times I've missed the possibility to make inside_reaper() work really inside, and, considering this, I wonder why not to pickle?
  • but I also cannot notice, that reapy is much more stable than I ever been in my attempts to make Reaper respond from outside, and I feel uncomfortable to ask more...

Question - Cross communication between Reaper and Reapy

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?

wrong command in take.py

line 159 GetTakeInfo_Value has to be GetMediaItemTakeInfo_Value
don't want to make pull-request for 1 line)

psutil requirements

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?

complex encoding problems

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.

project ext_state support

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

performance of C-calls

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:

  • we should consider load testing
  • size argument matters
  • but sometimes it is not counted even inside reaper_python.py, so, maybe, patching should be made

Also, 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}

typing extensions and python 3.8

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

Broken pipe when program completes

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

FR: Add time_to_beat and beat_to_time method to take class

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.

Cannot add MIDI note in item/take

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.

potential sockets leakage

in my package i'm implementing folowing structure:
connections
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)

Adding functions using @reapy.inside_reaper()

@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!

Project class add_track method

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.

Any way to reset the connection?

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?

access reapy server through network

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?)

Endless loop in project.tracks

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?

reapy GUI

Since #74 brings c-bindings, we can discuss the possibilities for GUI.
I see 3 ways of it core:

  • make bindings for JS_* functions, which would require of installing JS Rescript extension. It is the easiest way, and, since on the Win and OSX it can be installed from reapack it's not a burden for the end-user. But Linux is different at the moment: building of it is quite painful, I made it only once.
  • look for the platform-independent way of painting on the window, got from the core reaper functions. It's the really painful way and I dropped the idea several times yet.
  • grab the own copy of LICE(WDL) library and bind to it directly. Can't imagine how much harder it could be opposite to JS-way.

any ideas?

Consider adding pytest?

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.

Writing a blog on Reaper Python and Reapy

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 ;-))

distant errors handling

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

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.