vst-rsでeguiを使う
この記事はRust Advent Calendar 2022 - Qiitaの14日目の記事です。
はじめに
この記事ではegui
を改造してvst-rs
で使っていきます。
他のライブラリでもwinit
のバックエンドあるGUIライブラリなら似たようなやり方でvst-rs
で使うように改造することはさほど難しくないと思います。
参考
RustでGUI付きのVSTプラグイン作る(Conrod, iced)
vst-rsでGUIを使うための制約
RustでGUI付きのVSTプラグイン作る(Conrod, iced)に書いたようにvst-rs
にGUIをつけるには、GUIライブラリが以下を満たしている必要があります
- openメソッドが呼ばれたときに、引数のウインドウハンドルを親にした小ウインドウとして自分のウインドウを作らなくてはいけない。WinAPIでいうと、CreateWindowExWのhWndParentに入れてやる。これを他のプラットフォームでどうやるかわからないのが本記事がWindowsのみである主な理由。
- イベントループはidleメソッドで細切れにやる。つまり、一回走らせるとウインドウを閉じるまで帰ってこないようなGUIライブラリはだめ。
winit
バックエンドを持つライブラリであれば1.
はwindowsを作るときにwinit::platform::windows::WindowBuilderExtWindows::with_parent_window
を呼ぶだけです(Windowsの場合)。
また、2.
はwinit
のイベントループをwinit::platform::run_return::EventLoopExtRunReturn::run_return
を使って処理する必要があります。
しかし、egui
を含む大抵のGUIライブラリのバックエンドはwinit::event_loop::EventLoop::run
を使ってイベントループを処理しているので(これだと処理が一生帰ってこないのでだめ)、run_return
を使ったイベントループに書き換える必要があります。
eguiの改造
そのままのeframe
(egui
のネイティブバクエンド)では上で書いた制約を満たすことができないので改造していきます。
eframe
ではバックエンドとしてglow
とwgpu
を選べますが、glow
はバージョンが古くパニックが出てしまったので今回はwgpu
バックエンドのみ改造します。
コードはこちら https://github.com/hatoo/egui/tree/vst
1. 親ウインドウを指定して子ウインドウにする
これは簡単です。
egui
のバックエンドであるeframe
はeframe::NativeOptions
でウインドウの設定を管理しているのでそれに親ウインドウ用の項目を足します。
あとはeframe::NativeOptions
をwinit
のビルダーに渡す箇所で親ウインドウのハンドルを設定するだけです。
run_return
を使ったイベントループ
2. run_return
を使ったイベントループをするためにGUIの情報全体をstruct
でまとめます
ウインドウを閉じる操作は下手なタイミングでやるとクラッシュしてしまうのでクローズ用のフラグを追加しています。
pub struct WgpuIdle {
wgpu_eframe: WgpuWinitApp,
native_options: NativeOptions,
close: bool, // 次のイベントでクローズしてほしい
closed: bool, // 実際にクローズした
}
impl WgpuIdle {
pub fn idle(&mut self) -> bool /* is exited */ {
todo!()
}
pub fn close(&mut self) {
todo!()
}
pub fn size(&self) -> (i32, i32) {
todo!()
}
}
pub fn idle_wgpu(
app_name: &str,
native_options: epi::NativeOptions,
app_creator: epi::AppCreator,
) -> WgpuIdle {
todo!()
}
vst用にrun_return
を使ったイベントループを処理するときは常に*control_flow = ControlFlow::Exit;
で大丈夫です。
あとはegui
を含む大抵のいGUIライブラリには、ウインドウを描画する関数、イベントを処理する関数が用意されているのでそれを適当に呼ぶだけです。
詳細はコード参照
利用例
適当なvstプラグインを上記のegui
を使って作ってみました。
コードはこちら https://github.com/hatoo/vst-rs-example-egui
- GUI上の変更がBitWigのGUIに反映されない
- おそらくパラメーターの変更をホストに通知するAPIは存在するが
vst-rs
でどうやるかわからない
- おそらくパラメーターの変更をホストに通知するAPIは存在するが
- VstHostではうまく表示されない
などの問題点はありますがだいたい動いてます。
Discussion