Exemple #1
0
def reconnect():
    """
    Reconnect to REAPER ReaScript API.

    This function has no effect from inside REAPER.

    Examples
    --------
    Assume no REAPER instance is active.
    >>> import reapy
    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())
    >>> p = reapy.Project()  # Results in error
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "C:\\Users\\despres\\Desktop\\reaper\\scripts\\reapy\\reapy\\core\\project\\project.py", line 26, in __init__
        id = RPR.EnumProjects(index, None, 0)[0]
    AttributeError: module 'reapy.reascript_api' has no attribute 'EnumProjects'
    >>> # Now start REAPER
    ...
    >>> reapy.reconnect()
    >>> p = reapy.Project()  # No error!
    """
    global _WEB_INTERFACE, _CLIENT
    if not reapy.is_inside_reaper():
        try:
            _WEB_INTERFACE = WebInterface(reapy.config.WEB_INTERFACE_PORT)
            _CLIENT = Client(_WEB_INTERFACE.get_reapy_server_port())
            importlib.reload(reapy.reascript_api)
        except DisabledDistAPIError:
            pass
Exemple #2
0
def reconnect():
    """
    Reconnect to REAPER ReaScript API.

    Examples
    --------
    Assume no REAPER instance is active.
    >>> import reapy
    errors.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())
    >>> p = reapy.Project()  # Results in error
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "reapy\\core\\project\\project.py", line 26, in __init__
        id = RPR.EnumProjects(index, None, 0)[0]
    AttributeError: module 'reapy.reascript_api' has no attribute 'EnumProjects'
    >>> # Now start REAPER
    ...
    >>> reapy.reconnect()
    >>> p = reapy.Project()  # No error!
    """
    if not reapy.is_inside_reaper():
        host = get_selected_machine_host()
        if host is None:
            # We are outside REAPER, so this means initial import failed to
            # connect and we want to retry with default host (i.e. localhost)
            host = "localhost"
        try:
            del CLIENTS[host]
        except KeyError:
            pass
        connect(host)
Exemple #3
0
def enable_dist_api():
    """Enable distant API.

    .. deprecated:: 0.8.0
          ``enable_dist_api`` will be removed in reapy 1.0.0.
          Use :func:`reapy.config.configure_reaper` that works
          even from outside REAPER.

    Create a Web interface and add the ReaScript
    ``reapy.reascripts.activate_reapy_server`` to the Actions list.
    """
    msg = ("Function enable_dist_api is deprecated since 0.8.0. "
           "Use reapy.config.configure_reaper instead.")
    warnings.warn(FutureWarning(msg))
    if not reapy.is_inside_reaper():
        raise OutsideREAPERError
    create_new_web_interface(WEB_INTERFACE_PORT)
    reascript_path = get_activate_reapy_server_path()
    action_id = reapy.add_reascript(reascript_path)
    command_name = json.dumps(reapy.get_command_name(action_id))
    section, key, value = "reapy", "activate_reapy_server", command_name
    reapy.set_ext_state(section, key, value, persist=True)
    message = (
        "reapy successfully enabled!\n\nPlease restart REAPER.\n\nYou will "
        "then be able to import reapy from the outside.")
    reapy.show_message_box(message)
Exemple #4
0
def main_loop() -> None:
    if is_stopped():
        server.run()
        announce.run()
    if rpr.is_inside_reaper():
        rpr.defer(main_loop)
    else:
        sleep(.03)
        main_loop()
Exemple #5
0
 def __call__(cls, *args: Stringable, sep: str = ' ') -> None:
     line = sep.join([str(i) for i in args])
     if cls._console:
         if rpr.is_inside_reaper():
             rpr.defer(rpr.print, line)
         else:
             rpr.print(line)
     if cls._print:
         print(line)
Exemple #6
0
def disable_dist_api():
    """
    Disable distant API.

    Delete ``reapy`` Web interface, and remove the ReaScript
    ``reapy.reascripts.activate_reapy_server`` from the
    Actions list.
    """
    if not reapy.is_inside_reaper():
        raise OutsideREAPERError
    delete_web_interface(reapy.get_resource_path(), WEB_INTERFACE_PORT)
    reascript_path = get_activate_reapy_server_path()
    reapy.remove_reascript(reascript_path)
    message = ("reapy will be disabled as soon as you restart REAPER.")
    reapy.show_message_box(message)
Exemple #7
0
    def __call__(self, func, encoded_func=None):
        if reapy.is_inside_reaper() or _CLIENT is None:
            return func
        if isinstance(func, property):
            return DistProperty.from_property(func)
        # Check if the decorated function is from reapy
        module_name = func.__module__
        if module_name == 'reapy' or module_name.startswith('reapy.'):

            @functools.wraps(func)
            def wrap(*args, **kwargs):
                f = func if encoded_func is None else encoded_func
                return _CLIENT.request(f, {"args": args, "kwargs": kwargs})

            return wrap
        # Otherwise, use the context manager
        return super().__call__(func)
Exemple #8
0
def register_machine(host):
    """Register a slave machine.

    Parameters
    ----------
    host : str
        Slave machine host (e.g. ``"localhost"``).

    See also
    --------
    ``reapy.connect``
    """
    if reapy.is_inside_reaper() and host == "localhost":
        msg = "A REAPER instance can not connect to istelf."
        raise errors.InsideREAPERError(msg)
    interface_port = reapy.config.WEB_INTERFACE_PORT
    interface = web_interface.WebInterface(interface_port, host)
    CLIENTS[host] = client.Client(interface.get_reapy_server_port(), host)
Exemple #9
0
def enable_dist_api():
    """
    Enable distant API.

    Create a Web interface and add the ReaScript
    ``reapy.reascripts.activate_reapy_server`` to the Actions list.
    """
    if not reapy.is_inside_reaper():
        raise OutsideREAPERError
    create_new_web_interface(WEB_INTERFACE_PORT)
    reascript_path = get_activate_reapy_server_path()
    action_id = reapy.add_reascript(reascript_path)
    command_name = json.dumps(reapy.get_command_name(action_id))
    section, key, value = "reapy", "activate_reapy_server", command_name
    reapy.set_ext_state(section, key, value, persist=True)
    message = (
        "reapy successfully enabled!\n\nPlease restart REAPER.\n\nYou will "
        "then be able to import reapy from the outside.")
    reapy.show_message_box(message)
Exemple #10
0
def defer(f, *args, **kwargs):
    """
    Make REAPER call a function later.

    Parameters
    ----------
    f : callable
        Function to be called later.
    args : tuple, optional
        Positional arguments to pass to ``f``.
    kwargs : dict, optional
        Keyword arguments to pass to ``f``.

    Raises
    ------
    AssertionError
        When called from outside REAPER.

    Notes
    -----
    The average time before a defered call is actually run is about
    0.03 seconds (around 30 defered calls are allowed per second).

    Examples
    --------
    Typical use case of ``defer`` is running loops that don't block
    REAPER GUI.

    The following example creates a loop that indefinitely prints
    integers to the REAPER console, without blocking REAPER GUI.

    >>> import reapy
    >>> def stupid_loop(i):
    ...     reapy.print(i)
    ...     reapy.defer(stupid_loop, i + 1)
    ...
    >>> stupid_loop(0)
    """
    # Check we are inside REAPER
    message = "reapy.defer can only be called inside REAPER."
    assert reapy.is_inside_reaper(), message
    Deferrer().defer(f, args, kwargs)
Exemple #11
0
def at_exit(f, *args, **kwargs):
    """
    Make REAPER call a function after script execution.

    The function is also called if excution is terminated by user.

    Parameters
    ----------
    f : callable
        Function to be called later.
    args : tuple, optional
        Positional arguments to pass to ``f``.
    kwargs : dict, optional
        Keyword arguments to pass to ``f``.

    Raises
    ------
    AssertionError
        When called from outside REAPER.

    Examples
    --------
    Typical use case of ``at_exit`` is cleaning up after a ``defer``
    loop.

    The following example opens a file and starts a loop that
    indefinitely writes integers to that file. Since we want the file
    to be closed when the user terminates script execution, call to
    its ``close`` method is deferred to ``reapy.at_exit``.

    >>> import reapy
    >>> file = open("somefile.txt", "w")
    >>> def stupid_loop(i):
    ...     file.write(i)
    ...     reapy.defer(stupid_loop, i + 1)
    ...
    >>> reapy.at_exit(file.close)
    >>> stupid_loop(0)
    """
    message = "reapy.at_exit can only be called inside REAPER."
    assert reapy.is_inside_reaper(), message
    Deferrer().defer(f, args, kwargs, at_exit=True)
Exemple #12
0
import reapy
if not reapy.is_inside_reaper():
    try:
        from reapy_generated_api import __all__
        from reapy_generated_api import *
    except ImportError:  # Happens when ``reapy`` dist API is disabled
        __all__ = []
Exemple #13
0
        raise RuntimeError('cannot run slave')
    HOST = host
else:
    HOST = rpr.get_ext_state(EXT_SECTION, ADDRESS_KEY_SLAVE)

handlers = [PrintHandler, PingHandler]
server = ReaperServer(HOST, PORT, handlers)

announce = Announce(HOST, PORT)


def main_loop() -> None:
    if is_stopped():
        server.run()
        announce.run()
    if rpr.is_inside_reaper():
        rpr.defer(main_loop)
    else:
        sleep(.03)
        main_loop()


def at_exit() -> None:
    server.at_exit()


log(f'starting slave on {HOST}:{PORT}')
if rpr.is_inside_reaper():
    rpr.at_exit(at_exit)
main_loop()
Exemple #14
0
 def __enter__(self):
     if not reapy.is_inside_reaper():
         _CLIENT.request("HOLD")
 def __exit__(self, exc_type, exc_val, exc_tb):
     if not reapy.is_inside_reaper():
         machines.get_selected_client().request("RELEASE")
     return False
 def __enter__(self):
     if not reapy.is_inside_reaper():
         machines.get_selected_client().request("HOLD")
Exemple #17
0
 def __exit__(self, exc_type, exc_val, exc_tb):
     if not reapy.is_inside_reaper():
         _CLIENT.request("RELEASE")
     return False
Exemple #18
0
 def run(self, **input):
     if reapy.is_inside_reaper():
         return super(Program, self).run(**input)
     else:
         return CLIENT.run_program(self, input)
Exemple #19
0
 def __exit__(self, exc_type, exc_val, exc_tb):
     if not reapy.is_inside_reaper():
         dist_program.Program("RELEASE").run()
     return False
Exemple #20
0
import reapy

import sys

if reapy.is_inside_reaper():
    # Import functions without the useless starting "RPR_".
    import reaper_python as _RPR
    __all__ = [s[4:] for s in _RPR.__dict__ if s.startswith("RPR_")]
    for s in __all__:
        exec("{} = _RPR.__dict__['{}']".format(s, "RPR_" + s))
    # Import SWS functions.
    try:
        import sws_python as _SWS
        sws_functions = set(_SWS.__dict__) - set(_RPR.__dict__)
        __all__ += list(sws_functions)
        for s in sws_functions:
            exec("from sws_python import {}".format(s))
    except ModuleNotFoundError:  # SWS is not installed
        pass
else:
    from .dist_api import __all__
    from .dist_api import *
Exemple #21
0
 def __enter__(self):
     if not reapy.is_inside_reaper():
         dist_program.Program("HOLD").run()