3个版本
0.1.31 | 2024年3月31日 |
---|---|
0.1.2 | 2022年12月26日 |
0.1.1 | 2022年12月26日 |
11 在 #daw
每月28次下载
用于 3 crates
15KB
76 行
rea-rs
易于使用的ReaScript API。虽然 reaper-rs 在底层实现了全部功能,在中等层面部分实现,在其之上(大多数情况下在底层之上)此crate构建了一个易于使用的API。实际上,目前它是Reapy项目的更好版本。
此API的主要结构是从Reapy克隆的,但以更“Rust”的方式重新实现。还添加了许多新的函数到 Track、Item 和 Take,以及 ExtState 和 midi 的良好新实现。可以说,目前封装了 ~95% 的Track、Take、Item、AudioAccessor 和 FX 原始函数;大约70%的Envelope 和 Source。其余的可能不到50%。它也应该可以从VST插件中使用,但这尚未完全测试。
在 reaper-rs
的新版本出现之前,它与当前主分支有很大的不同,这是我强烈推荐的依赖列表
这些是依赖项
[dependencies]
rea-rs = "0.1.3"
rea-rs-low = "0.1.3" # optional
rea-rs-macros = "0.1.3"
但实际上,所有中等和底层功能仍然存在于 Reaper 对象中。只需使用 Reaper::low
、Reaper::medium
和 Reaper::medium_session
。通用入口点应如下所示
use rea_rs::{errors::ReaperResult, ActionKind, Reaper, PluginContext};
use rea_rs_macros::reaper_extension_plugin;
use std::error::Error;
#[reaper_extension_plugin]
fn plugin_main(context: PluginContext) -> Result<(), Box<dyn Error>> {
Reaper::init_global(context);
let reaper = Reaper::get_mut();
let message = "Hello from small extension";
reaper.show_console_msg(message);
Ok(())
}
由于Reaper启动时没有太多事情要做,因此有两种常见的方法来调用代码:动作和Timer
。
use rea_rs::{PluginContext, Reaper, RegisteredAccel, Timer};
use rea_rs_macros::reaper_extension_plugin;
use std::error::Error;
#[derive(Debug)]
struct Listener {
action: RegisteredAccel,
}
// Full list of function larger.
impl Timer for Listener {
fn run(&mut self) -> Result<(), Box<dyn Error>> {
Reaper::get().perform_action(self.action.command_id, 0, None);
Ok(())
}
fn id_string(&self) -> String {"test listener".to_string()}
}
fn my_action_func(_flag: i32) -> Result<(), Box<dyn Error>> {
Reaper::get().show_console_msg("running");
Ok(())
}
#[reaper_extension_plugin]
fn plugin_main(context: PluginContext) -> Result<(), Box<dyn Error>> {
Reaper::init_global(context);
let reaper = Reaper::get_mut();
let action = reaper.register_action(
// This will be capitalized and used as action ID in action window
"command_name",
// This is the line user searches action for
"description",
my_action_func,
// Only type currently supported
None
)?;
reaper.register_timer(Box::new(Listener{action}));
Ok(())
}
API中存在浮点值。我建议使用float_eq
crate。
API结构
大多数情况下,API是按层次使用的:Reaper 包含顶层函数,可以返回 Project、Item 等。而 Project 可以通过 Track、Item、Take 来操作。层次结构的关键点——尽可能保证安全性。由于Project是活跃的,因此可以从track中安全地引用它。其他子对象也是如此。由于同样的原因,同时修改两个对象几乎是不可能的。如果一个track是可变的,那么它将响应整个底层对象。我们可以几乎肯定,其余的track由我们之前留下的对象组成。大部分的API都由测试覆盖,它们是一组很好的使用示例。
use rea_rs::Reaper;
use std::collections::HashMap;
let rpr = Reaper::get();
let captions =
vec!["age(18)", "name(user)", "leave blank", "fate(atheist)"];
let mut answers = HashMap::new();
answers.insert(String::from("age(18)"), String::from("18"));
answers.insert(String::from("name(user)"), String::from("user"));
answers.insert(String::from("leave blank"), String::from(""));
answers.insert(String::from("fate(atheist)"), String::from("atheist"));
let result = rpr.get_user_inputs(
"Fill values as asked in fields",
captions,
None,
).unwrap();
assert_eq!(result, answers);
需要了解的更多
目前,API的缺点是
- 顶层功能:我不确定至少有一半的小Reaper函数被包装。比如所有窗口化和主题化内容。
- GUI。与
reapy
一样,GUI也是一个问题。我已经开始了一个名为reaper-imgui
的crate,它使得从Rust使用ReaImGui扩展成为可能。但它等待被rea-rs
适当地包装。 - 线程安全性。重要的是要知道,几乎Reaper的所有内容都不应该留在主线程中。有一些函数是为音频线程设计的,还有一些可以在任何线程中安全执行。但基本上,这里有一条规则:如果你创建了一个监听器、GUI或套接字通信——
Reaper
生活在主线程中,否则由std::sync::mpsc
完成。享受编码吧!
依赖项
~2MB
~43K SLoC