#reaper #midi #daw #plugin #api-bindings

reaper-medium

REAPER C++ API的绑定 - 中级API

1个不稳定版本

0.1.0 2020年5月8日

#781音频


用于 reaper-macros

MIT 许可证

1.5MB
30K SLoC

reaper-rs

RustREAPER C++ API 的绑定。

GitHub license

简介

reaper-rs 允许程序员使用 Rust 编程语言编写 REAPER DAW(数字音频工作站)的插件。它是通过提供对 REAPER C++ API 的原始 Rust 绑定和在之上更方便的 API 来实现的。

基础

reaper-rs 由 4 个生产 Crates 组成

reaper-macros 提供了一个简单的属性宏,以简化 REAPER 扩展插件的引导。

其余的 Crates 代表了 reaper-rs 的 3 种不同的 API。

1. 低级API

Latest Version documentation

此 API 包含原始绑定,没有更多。它在很大程度上是不安全的,并不打算直接使用。然而,它作为所有其他 API 的基础,并且由于它主要是从 reaper_plugin_functions.h 自动生成的,因此易于保持最新。它还可以作为最后的手段,如果某个函数尚未在中级 API 中实现(尽管我更希望在这种情况下鼓励为中级 API 做贡献)。

状态

  • crates.io:已发布
  • API稳定性:接近稳定(已经很完善,可能存在破坏性更改,但未计划进行更改)
  • 完成度:~95%(一些虚拟函数调用仍缺失)

示例

unsafe {
    reaper.ShowConsoleMsg(c_str!("Hello world from reaper-rs low-level API!").as_ptr());
    let track = reaper.GetTrack(null_mut(), 0);
    reaper.DeleteTrack(track);
}

2. 中级API

Latest Version documentation

本API构建在低级API之上。它几乎一对一地暴露了原始REAPER C++ API函数,但以惯用和类型安全的方式。与原始绑定相比,这是一个巨大的进步,使用起来更加方便。其重点是稳定性,而不是探索新范式。由于高级API仍然非常不稳定,这是推荐的API

状态

  • crates.io:已发布
  • API稳定性:接近稳定(已经很完善,可能存在破坏性更改,但未计划进行更改)
  • 完成度:~13%(坚实基础,大约800个函数中的100个已实现)

示例

let functions = reaper.functions();
functions.show_console_msg("Hello world from reaper-rs medium-level API!");
let track = functions.get_track(CurrentProject, 0).ok_or("no tracks")?;
unsafe { functions.delete_track(track); }

3. 高级API

本API构建在中级API之上。它打破了原始REAPER C++ API“平面函数”的特性,并使用响应式和面向对象范式替代它。这种突破使得提供直观的API成为可能,可以完全安全地使用。

状态

  • crates.io:尚未发布
  • API稳定性:不稳定(处于变化状态,但正在工作)
  • 完成度:~13%(与中级API大致相当)

示例

reaper.show_console_msg("Hello world from reaper-rs high-level API!");
reaper.track_removed().subscribe(|t| println!("Track {:?} removed", t));
let project = reaper.get_current_project();
let track = project.get_track_by_index(0).ok_or("no tracks")?;
project.remove_track(&track);

使用方法

该过程取决于所需的插件类型。除了编写REAPER扩展插件外,reaper-rs还可以用于开发使用REAPER函数的VST插件。无论您选择哪种方式,与REAPER交互的可能性本质上都是相同的。两者的区别在于您的插件将在哪种环境中运行。

扩展插件在REAPER启动时加载,并保持活动状态,直到REAPER退出,因此非常适合添加一些全局可用的功能。流行的例子包括SWSReaPack(两者都使用C++编写)。

REAPER VST插件作为特定REAPER项目中的轨道、取或监控FX加载,就像任何乐器或效果插件一样。这也意味着它可以多次实例化。例子有Playtime(使用C++编写)和ReaLearn(使用C++编写,但正在移植到Rust)。

在这两种情况下,您都需要创建一个类型为cdylib的库crate。

REAPER扩展插件

使用reaper_extension_plugin宏是快速开始的最快方法。

将其添加到您的Cargo.toml

[dependencies]
reaper-low = "0.1.0"
reaper-medium = "0.1.0"
reaper-macros = "0.1.0"

[lib]
name = "my_reaper_extension_plugin"
crate-type = ["cdylib"]

然后在您的lib.rs

use std::error::Error;
use reaper_macros::reaper_extension_plugin;
use reaper_low::ReaperPluginContext;
use reaper_medium::Reaper;

#[reaper_extension_plugin]
fn plugin_main(context: &ReaperPluginContext) -> Result<(), Box<dyn Error>> {
    let reaper = Reaper::load(context);
    reaper.functions().show_console_msg("Hello world from reaper-rs medium-level API!");
    Ok(())
}

该宏所做的不仅仅是暴露一个调用reaper_low::bootstrap_extension_plugin()函数的extern "C" ReaperPluginEntry()函数。因此,如果您出于某种原因不想使用宏,请查看宏实现。没有魔法。

REAPER VST插件

REAPER VST 插件其实就是一个普通的 VST 插件,它通过 REAPER C++ API 获取功能。幸运的是,已经有一个用于创建 VST 插件的 Rust 包:[vst-rs](https://crates.org.cn/crates/vst)。所以你只需要使用 vst-rs 编写一个 VST 插件,并通过让 reaper-rs 访问 HostCallback 函数来获取 REAPER 的功能。

将其添加到您的Cargo.toml

[dependencies]
reaper-low = "0.1.0"
reaper-medium = "0.1.0"
vst = "0.2.0"

[lib]
name = "my_reaper_vst_plugin"
crate-type = ["cdylib"]

然后在您的lib.rs

use vst::plugin::{Info, Plugin, HostCallback};
use reaper_low::ReaperPluginContext;
use reaper_medium::Reaper;

#[derive(Default)]
struct MyReaperVstPlugin {
    host: HostCallback,
};

impl Plugin for MyReaperVstPlugin {
    fn new(host: HostCallback) -> Self {
        Self { host }
    }

    fn get_info(&self) -> Info {
        Info {
            name: "My REAPER VST plug-in".to_string(),
            unique_id: 6830,
            ..Default::default()
        }
    }

    fn init(&mut self) {
        if let Ok(context) = ReaperPluginContext::from_vst_plugin(self.host) {
            let reaper = Reaper::load(&context);
            reaper
                .functions()
                .show_console_msg("Hello world from reaper-rs medium-level API!");
        }
    }
}

vst::plugin_main!(MyReaperVstPlugin);

贡献

我们非常欢迎贡献!尤其是对中等程度的 API。

目录结构

目录条目 内容
/ 工作区根目录
/main 生产代码
/main/high 高级 API (reaper-high
/main/low 低级 API (reaper-low
/main/macros 宏(reaper-macros
/main/medium 中级 API (reaper-medium
/test 集成测试代码
/test/test 集成测试逻辑(reaper-test
/test/test-extension-plugin 测试扩展插件(reaper-test-extension-plugin
/test/test-vst-plugin 测试 VST 插件(reaper-test-vst-plugin

低级 API 代码生成

reaper-low 有几个生成的文件,即 bindings.rsreaper.rs。然而,这些文件并非每次构建都会生成。为了减少构建时间和提高 IDE/调试支持,它们就像其他 Rust 源文件一样包含在 Git 仓库中。

您可以在需要时生成这些文件(参见构建部分),例如在您已调整 reaper_plugin_functions.h 之后。根据您在哪个操作系统上生成文件,bindings.rs 的外观可能会有很大不同(而 reaper.rs 应该保持不变)。原因在于,在 Windows 上,reaper_plugin.h 只包含 windows.h。在 Linux 和 Mac OS X 上,它使用 swell.h([简单 Windows 模拟层](https://www.cockos.com/wdl/))作为替代。

bindings.rs 的大部分用于生成 reaper.rs,其他部分被忽略,但一些结构体、类型和常量作为 raw 模块的一部分发布。为了实现确定性构建,目前约定只提交在 Linux 上生成的文件。理由是:swell.hwindows.h 的一个子集,所以如果子集能工作,超集也应该能工作。反之则不成立。目前还不清楚这种策略是否完全正确,但到目前为止似乎是对的。此外,在 Linux 上生成文件对 CI 很好。

构建

感谢 Cargo,构建 reaper-rs 并非难事。

Windows

以下是在 Windows 10 上的说明。需要考虑目标架构(REAPER 32 位与 64 位)的地方用 ⭐ 标记(以下说明假设为 64 位)。

  1. 设置 "Visual Studio 2019 构建工具"
    • Rust 使用原生构建工具链。在 Windows 上,必须使用 MSVC(Microsoft Visual Studio C++)工具链,因为 REAPER 插件只能与该工具链一起使用。
    • [Visual Studio 下载](https://visualstudio.microsoft.com/downloads/) → 所有下载 → Visual Studio 2019 工具 → Visual Studio 2019 构建工具
    • 启动它并按照安装说明进行操作
    • 所需组件
      • 工作负载选项卡
        • "C++ 构建工具"(左侧的大框)
        • 请确保右侧已选中 "Windows 10 SDK"(通常已选中)
      • 语言包
        • 英语
  2. 设置 Rust
    • [下载](https://www.rust-lang.net.cn/tools/install) 并执行 rustup-init.exe
    • 接受默认设置
    • 设置正确的工具链默认值(如果您只想构建 reaper-lowreaper-medium,则不需要 nightly 工具链)⭐
      rustup default nightly-x86_64-pc-windows-msvc
      
  3. 下载并安装 Git for Windows
  4. 克隆 reaper-rs Git 仓库
    git clone --recurse-submodules https://github.com/helgoboss/reaper-rs.git`
    
  5. 构建 reaper-rs
    cd reaper-rs
    cargo build
    

重新生成低级 API(生成的代码不应提交!)

  1. 下载 并安装 Windows 64 位 LLVM ⭐
  2. 启用 generate 功能进行构建
    cd main\low
    cargo build --features generate
    cargo fmt
    

Linux

从全新的 Ubuntu 18.04.3 LTS 安装完成构建 reaper-rs 的完整说明

# Install basic stuff
sudo apt update
sudo apt install curl git build-essential -y

# Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh # choose 1 (default)
source $HOME/.cargo/env
# Using nightly is not necessary if you want to build just the low-level or medium-level API!
rustup default nightly

# Clone reaper-rs
cd Downloads
git clone --recurse-submodules https://github.com/helgoboss/reaper-rs.git
cd reaper-rs
cargo build

使测试插件在 REAPER 中可用

  1. 下载 REAPER for Linux 并至少启动一次。
  2. 创建符号链接
    ln -s $HOME/Downloads/reaper-rs/target/debug/libreaper_test_extension_plugin.so $HOME/.config/REAPER/UserPlugins/reaper_test_extension_plugin.so
    mkdir -p $HOME/.config/REAPER/UserPlugins/FX
    ln -s $HOME/Downloads/reaper-rs/target/debug/libreaper_test_vst_plugin.so $HOME/.config/REAPER/UserPlugins/FX/reaper_test_extension_plugin.so
    

重新生成低级 API

cd main/low
cargo build --features generate
cargo fmt

Mac OS X

待完成

测试

在构建完整的 reaper-rs 工作区时,将生成 3 个测试 crate

  • reaper-test
  • reaper-test-extension-plugin
  • reaper-test-vst-plugin

reaper-test 提供了一个集成测试,该测试应在 REAPER 本身运行。这是 reaper-rs 的主要测试机制。《code>reaper-test-extension-pluginreaper-test-vst-plugin 都是测试插件,它们将集成测试注册为 REAPER 操作。

运行集成测试不仅是找到 reaper-rs 回归错误的好方法,还可以帮助暴露 REAPER C++ API 本身的一些微妙变化。目前,测试断言非常严格,以便揭示即使是微小的偏差。

项目背景

reaper-rs 诞生于将 REAPER VST 插件 ReaLearn 端口到 Rust 并将其作为开源项目发布的一部分努力。高层 API 受 ReaPlus 启发,ReaPlus 是 REAPER 本地 C++ API 的 C++ 门面,这是原始 ReaLearn 的基本构建块。

依赖关系

~1.1–2.1MB
~39K SLoC