1个不稳定版本
0.1.0 | 2020年5月8日 |
---|
#321 in 音频
42每月下载量
用于 2 crates
1MB
26K SLoC
reaper-rs
简介
reaper-rs允许程序员使用Rust编程语言为REAPER数字音频工作站(DAW)编写插件。它通过提供原始的Rust绑定以及对REAPER C++ API的更方便的API来实现这一点。
基本功能
reaper-rs由4个生产级crates组成
- reaper-macros
- reaper-low
- reaper-medium
reaper-high
(尚未发布)
reaper-macros提供了一个简单的属性宏,以简化REAPER扩展插件的启动。
其余的crates代表了reaper-rs的3种不同的API。
1. 低级API
此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
本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来替代。这种突破使得提供直观的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退出,因此非常适合向REAPER添加一些全局可用的功能。常见例子是SWS和ReaPack(两者均用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(())
}
这个宏并没有做什么更多的事情,只是公开了一个extern "C" ReaperPluginEntry()
函数,该函数调用reaper_low::bootstrap_extension_plugin()
。所以如果您出于某种原因不想使用宏,看看宏的实现。那里没有魔法。
REAPER VST插件
REAPER VST 插件实际上只是一个普通的 VST 插件,它能够访问 REAPER C++ API 的功能。幸运的是,已经有用于创建 VST 插件的 Rust crate:[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.rs
和 reaper.rs
。但这些文件并不是每次构建时都会生成。为了减少构建时间和提高 IDE/调试支持,它们被包含在 Git 仓库中,就像任何其他 Rust 源代码一样。
您可以根据需要生成这些文件(请参阅构建部分),例如在您调整了 reaper_plugin_functions.h
之后。根据您在哪个操作系统上生成文件,bindings.rs
的外观可能会有很大不同(而 reaper.rs
应该最终相同)。原因是 reaper_plugin.h
只在 Windows 上包含 windows.h
。在 Linux 和 Mac OS X 上,它使用 swell.h
([Simple Windows Emulation Layer](https://www.cockos.com/wdl/))作为替代。
bindings.rs
的大部分用于生成 reaper.rs
,否则会被忽略,但一些结构体、类型和常量作为 raw
模块的一部分发布。为了确保构建的可重复性,目前约定只提交在 Linux 上生成的文件。理由是:swell.h
是 windows.h
的一个子集,所以如果子集能工作,超集也应该能工作。反之则不然。目前尚不清楚这种策略是否完全正确,但似乎大致正确。此外,在 Linux 上生成文件对 CI 也是有益的。
构建
多亏了 Cargo,构建 reaper-rs 不是一个很大的问题。
Windows
以下是在 Windows 10 上的说明。需要考虑目标架构(REAPER 32 位 vs. 64 位)的地方用 ⭐ 标记(说明假定 64 位)。
- 设置 "Visual Studio 2019 的构建工具"
- Rust 使用本机构建工具链。在 Windows 上,由于 REAPER 插件只能与 MSVC(Microsoft Visual Studio C++)工具链一起使用,因此必须使用它。
- [Visual Studio 下载](https://visualstudio.microsoft.com/downloads/) → 所有下载 → Visual Studio 2019 工具 → Visual Studio 2019 的构建工具
- 启动它并按照安装说明进行操作
- 所需组件
- 工作负载选项卡
- "C++ build tools"(左侧的大框)
- 确保右侧已勾选 "Windows 10 SDK"(通常是这样)
- 语言包
- 英语
- 工作负载选项卡
- 设置 Rust
- 下载并执行
rustup-init.exe
- 接受默认设置
- 设置正确的工具链默认值(如果你只想构建
reaper-low
和reaper-medium
,则不需要nightly工具链)⭐rustup default nightly-x86_64-pc-windows-msvc
- 下载并执行
- 下载并安装Git for Windows
- 克隆reaper-rs Git仓库
git clone --recurse-submodules https://github.com/helgoboss/reaper-rs.git`
- 构建reaper-rs
cd reaper-rs cargo build
重新生成低级API(生成的代码不应提交!)
- 下载并安装Windows 64位LLVM⭐
- 启用
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中可用
- 下载Linux版的REAPER并至少启动一次。
- 创建符号链接
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的主要测试机制。reaper-test-extension-plugin
和reaper-test-vst-plugin
都是测试插件,它们将集成测试注册为REAPER操作。
运行集成测试不仅是查找reaper-rs回归错误的好方法,还可以帮助暴露REAPER C++ API本身的微妙变化。目前,测试断言非常严格,以揭示最细微的偏差。
项目背景
reaper-rs诞生于将REAPER VST插件ReaLearn移植到Rust并将其作为开源项目发布的努力的一部分。高级API深受ReaPlus的启发,ReaPlus是原生REAPER C++ API的C++外观,是原始ReaLearn的基本构建块。
依赖关系
~0.5–1.1MB
~18K SLoC