#插件 #midi #reaper #daw

rea-rs

ReaScript API的Rust版本

3个版本

0.1.31 2024年3月31日
0.1.2 2022年12月26日
0.1.1 2022年12月26日

#112 in 音频


用于2 个Crate

MIT许可证

430KB
12K SLoC

rea-rs

linux windows macos

易于使用的ReaScript API。虽然reaper-rs在底层全面实现,在中层部分实现,在其之上(大多数情况下,在底层之上)此crate构建了易于使用的API。实际上,目前它是Reapy项目的更好版本。

查看文档

此API的主框架是从Reapy克隆的,但以更“Rust”的方式重新实现。还添加了一组新的函数到TrackItemTake,以及针对ExtStatemidi的良好实现。可以说,目前封装了95%的Track、Take、Item、AudioAccessorFX原始函数;约70%的EnvelopeSource。其余的可能不到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::lowReaper::mediumReaper::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_eqcrate。

API结构

大多数情况下,API 都是分层使用的:Reaper 包含顶层函数,可以返回 ProjectItem 等。而 Project 可以通过 TrackItemTake 来操作。分层结构的关键点——尽可能保证安全。由于 Project 是活跃的,从 track 到它的引用是安全的。同样适用于其他子项。由于同样的原因,几乎不可能同时修改两个对象。如果一个 track 是可变的,它将负责所有底层对象。我们可以几乎肯定,其余的 tracks 都是由我们之前留下的对象组成的。大部分的 API 都由 tests 覆盖,它们是一套很好的使用示例。

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,它使得可以使用 ReaImGui 扩展。但它等待被 rea-rs 正确封装。
  • 线程安全。重要的是要知道,几乎 Reaper 的所有内容都不应该留在主线程上。有一些函数是为音频线程设计的,还有一些可以从任何线程安全执行。但基本上,这里有一条规则:如果你创建了一个监听器、GUI 或套接字通信——Reaper 将在主线程上运行,否则使用 std::sync::mpsc。享受编码吧!

依赖项

~20MB
~387K SLoC