3 个版本 (破坏性更新)

0.3.0 2022 年 2 月 8 日
0.2.0 2022 年 1 月 20 日
0.1.0 2020 年 9 月 27 日

操作系统 中排名第 661

每月下载 32

MIT/Apache

39KB
610 代码行

vst_window

crates.io Docs License

vst_window 是一个适用于 VST 插件的跨平台窗口库,用 Rust 编写!你可以使用它来使用 vst 包创建一个插件编辑器界面。

理念

全平台兼容性是这个库的首要任务。

没有合理的理由继续根据用户选择的平台限制他们对高质量音频工具的访问。插件开发者应该能够在他们最舒适的机器上编译和测试,并且惊喜地发现它“到处都一样好使”。

考虑到这一点,只有当功能在 Linux、macOS 和 Windows 上都得到支持时,才会将其纳入上游。然而,单平台 PR 总是受欢迎!新功能的发展分支将一直维护到实现跨平台一致性。

功能

  • 使用宿主提供的指针打开和关闭窗口
  • 可定制的窗口大小
  • 提供 raw-window-handle::RawWindowHandle 以在流行的 Rust 图形后端中进行渲染
  • 识别鼠标移动
  • 识别鼠标按钮
    • 左键按下
    • 左键释放
    • 右键按下
    • 右键释放
    • 中键按下
    • 中键释放
  • 识别鼠标滚轮
    • 垂直滚动
    • 水平滚动
  • 识别键盘事件
    • 按键
    • 按键释放
  • 更新鼠标光标
  • 为主机或独立使用生成兼容的父窗口

示例用法

野外

ampli-Fe 是一个最小且完整的 VST 插件示例,免费许可下 MIT 和 Apache-2.0。

从头开始

首先,建议按照 示例插件 部分从 vst 包开始,以获得一个没有编辑器界面的工作插件。

请确保将 vst_windowraw-window-handle 添加为依赖项到您的 Cargo.toml 清单中。

然后,为一个新的结构体实现 vst::editor::Editor,使其能够构建跨平台的 vst_window 窗口句柄和事件源包装,并管理它们。

use core::ffi::c_void;
use vst::editor::Editor;
use vst_window::{setup, EventSource, WindowEvent};

#[derive(Default)]
struct MyPluginEditor {
    renderer: Option<MyRenderer>,
    window_events: Option<EventSource>,
}

const WINDOW_DIMENSIONS: (i32, i32) = (300, 200);

impl Editor for MyPluginEditor {
    fn size(&self) -> (i32, i32) {
        (WINDOW_DIMENSIONS.0 as i32, WINDOW_DIMENSIONS.1 as i32)
    }

    fn position(&self) -> (i32, i32) {
        (0, 0)
    }

    fn open(&mut self, parent: *mut c_void) -> bool {
        if self.window_events.is_none() {
            let (window_handle, event_source) = setup(parent, WINDOW_DIMENSIONS);
            self.renderer = Some(MyRenderer::new(window_handle));
            self.window_events = Some(event_source);
            true
        } else {
            false
        }
    }

    fn is_open(&mut self) -> bool {
        self.window_events.is_some()
    }

    fn close(&mut self) {
        drop(self.renderer.take());
        drop(self.window_events.take());
    }

    fn idle(&mut self) {
        if let Some(window_events) = &mut self.window_events {
            while let Some(event) = window_events.poll_event() {
                match event {
                    WindowEvent::MouseClick(_) => println!("Click!"),
                    _ => (),
                }
            }
        }
        if let Some(renderer) = &mut self.renderer {
            renderer.draw_frame();
        }
    }
}

struct MyRenderer;

impl MyRenderer {
    pub fn new<W: raw_window_handle::HasRawWindowHandle>(_handle: W) -> Self {
        Self
    }
    pub fn draw_frame(&mut self) {
        /* ... */
    }
}

渲染代码不在此示例的范围内,但有许多与 raw-window-handle 兼容的优秀渲染解决方案。 wgpu 是高性能跨平台渲染的一个很好的选择。

最后,为您的外部插件实现 vst::plugin::Plugin::get_editor 方法。您可能希望使用以下类似的模式

use vst::{
    editor::Editor,
    plugin::{HostCallback, Plugin},
};
use vst_window::{setup, EventSource, WindowEvent};

struct BasicPlugin {
    editor_placeholder: Option<BasicPluginEditor>,
}

impl Plugin for BasicPlugin {
    // ...

    fn new(_host: HostCallback) -> Self {
        Self {
            editor_placeholder: Some(MyPluginEditor::default()),
        }
    }

    fn get_editor(&mut self) -> Option<Box<dyn Editor>> {
        self.editor_placeholder
            .take()
            .map(|editor| Box::new(editor) as Box<dyn Editor>)
    }
}

在实现以上代码后,您现在应该能够在DAW中构建并加载一个具有空白窗口的插件。如果DAW暴露了插件的标准输出,您将在窗口内部按下鼠标时看到新的“点击!”消息。

此示例的完整代码可在 examples 目录 中找到。

依赖项

~78–580KB