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

rea-rs-macros

REAPER C++ API绑定 - 宏

3个版本

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

11#daw

每月28次下载
用于 3 crates

MIT 许可证

15KB
76

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_eq crate。

API结构

大多数情况下,API是按层次使用的:Reaper 包含顶层函数,可以返回 ProjectItem 等。而 Project 可以通过 TrackItemTake 来操作。层次结构的关键点——尽可能保证安全性。由于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