Created
December 23, 2020 05:22
-
-
Save DGriffin91/32fc42a4fc0e74a7ae0b8b036ac4ac40 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//! Barebones baseview imgui plugin | |
#[macro_use] | |
extern crate vst; | |
use imgui::*; | |
use baseview::AppRunner; | |
use raw_window_handle::RawWindowHandle; | |
use vst::buffer::AudioBuffer; | |
use vst::editor::Editor; | |
use vst::plugin::{Category, Info, Plugin, PluginParameters}; | |
use vst::util::AtomicFloat; | |
use imgui_baseview::{settings, HiDpiMode, Parent, Runner, Settings}; | |
use std::sync::Arc; | |
const WINDOW_WIDTH: usize = 1024; | |
const WINDOW_HEIGHT: usize = 1024; | |
struct TestPluginEditor { | |
runner: Option<AppRunner>, | |
params: Arc<GainEffectParameters>, | |
} | |
impl Editor for TestPluginEditor { | |
fn position(&self) -> (i32, i32) { | |
(0, 0) | |
} | |
fn size(&self) -> (i32, i32) { | |
(WINDOW_WIDTH as i32, WINDOW_HEIGHT as i32) | |
} | |
fn open(&mut self, parent: *mut ::std::ffi::c_void) -> bool { | |
//::log::info!("self.running {}", self.running); | |
if self.runner.is_some() { | |
return true; | |
} | |
let parent = raw_window_handle_from_parent(parent); | |
::log::info!("raw_window_handle_from_parent"); | |
let settings = Settings { | |
window: settings::Window { | |
title: String::from("imgui-baseview demo window"), | |
logical_size: (WINDOW_WIDTH as u32, WINDOW_HEIGHT as u32), | |
scale_policy: imgui_baseview::WindowScalePolicy::SystemScaleFactor, | |
}, | |
clear_color: (0.0, 0.0, 0.0), | |
hidpi_mode: HiDpiMode::Default, | |
}; | |
::log::info!("Settings"); | |
let (_handle, runner) = Runner::open( | |
settings, | |
Parent::WithParent(parent), | |
self.params.clone(), | |
move |run: &mut bool, ui: &Ui, state: &mut Arc<GainEffectParameters>| { | |
ui.show_demo_window(run); | |
let w = Window::new(im_str!("Example 1: Basic sliders")) | |
.size([700.0, 340.0], Condition::Appearing) | |
.position([20.0, 120.0], Condition::Appearing); | |
w.build(&ui, || { | |
let mut val = state.amplitude.get(); | |
if Slider::new(im_str!("f32 value")) | |
.range(0.0..=1.0) | |
.build(&ui, &mut val) | |
{ | |
state.amplitude.set(val) | |
} | |
}); | |
}, | |
); | |
::log::info!("Runner::open"); | |
self.runner = runner; | |
::log::info!("self.runner.is_some {}", self.runner.is_some()); | |
true | |
} | |
fn is_open(&mut self) -> bool { | |
::log::info!("is_open"); | |
self.runner.is_some() | |
} | |
fn close(&mut self) { | |
::log::info!("close"); | |
self.runner = None; | |
} | |
} | |
struct GainEffectParameters { | |
// The plugin's state consists of a single parameter: amplitude. | |
amplitude: AtomicFloat, | |
} | |
struct TestPlugin { | |
params: Arc<GainEffectParameters>, | |
editor: Option<TestPluginEditor>, | |
} | |
impl Default for TestPlugin { | |
fn default() -> Self { | |
let params = Arc::new(GainEffectParameters::default()); | |
Self { | |
params: params.clone(), | |
editor: Some(TestPluginEditor { | |
runner: None, | |
params: params.clone(), | |
}), | |
} | |
} | |
} | |
impl Default for GainEffectParameters { | |
fn default() -> GainEffectParameters { | |
GainEffectParameters { | |
amplitude: AtomicFloat::new(0.5), | |
} | |
} | |
} | |
impl Plugin for TestPlugin { | |
fn get_info(&self) -> Info { | |
Info { | |
name: "IMGUI Gain Effect in Rust".to_string(), | |
vendor: "DGriffin".to_string(), | |
unique_id: 243123072, | |
version: 1, | |
inputs: 2, | |
outputs: 2, | |
// This `parameters` bit is important; without it, none of our | |
// parameters will be shown! | |
parameters: 1, | |
category: Category::Effect, | |
..Default::default() | |
} | |
} | |
fn init(&mut self) { | |
let log_folder = ::dirs::home_dir().unwrap().join("tmp"); | |
let _ = ::std::fs::create_dir(log_folder.clone()); | |
let log_file = ::std::fs::File::create(log_folder.join("BaseviewTest.log")).unwrap(); | |
let log_config = ::simplelog::ConfigBuilder::new() | |
.set_time_to_local(true) | |
.build(); | |
let _ = ::simplelog::WriteLogger::init(simplelog::LevelFilter::Info, log_config, log_file); | |
::log_panics::init(); | |
::log::info!("init"); | |
} | |
fn get_editor(&mut self) -> Option<Box<dyn Editor>> { | |
if let Some(editor) = self.editor.take() { | |
Some(Box::new(editor) as Box<dyn Editor>) | |
} else { | |
None | |
} | |
} | |
// Here is where the bulk of our audio processing code goes. | |
fn process(&mut self, buffer: &mut AudioBuffer<f32>) { | |
// Read the amplitude from the parameter object | |
let amplitude = self.params.amplitude.get(); | |
// First, we destructure our audio buffer into an arbitrary number of | |
// input and output buffers. Usually, we'll be dealing with stereo (2 of each) | |
// but that might change. | |
for (input_buffer, output_buffer) in buffer.zip() { | |
// Next, we'll loop through each individual sample so we can apply the amplitude | |
// value to it. | |
for (input_sample, output_sample) in input_buffer.iter().zip(output_buffer) { | |
*output_sample = *input_sample * amplitude; | |
} | |
} | |
} | |
// Return the parameter object. This method can be omitted if the | |
// plugin has no parameters. | |
fn get_parameter_object(&mut self) -> Arc<dyn PluginParameters> { | |
Arc::clone(&self.params) as Arc<dyn PluginParameters> | |
} | |
} | |
impl PluginParameters for GainEffectParameters { | |
// the `get_parameter` function reads the value of a parameter. | |
fn get_parameter(&self, index: i32) -> f32 { | |
match index { | |
0 => self.amplitude.get(), | |
_ => 0.0, | |
} | |
} | |
// the `set_parameter` function sets the value of a parameter. | |
fn set_parameter(&self, index: i32, val: f32) { | |
#[allow(clippy::single_match)] | |
match index { | |
0 => self.amplitude.set(val), | |
_ => (), | |
} | |
} | |
// This is what will display underneath our control. We can | |
// format it into a string that makes the most since. | |
fn get_parameter_text(&self, index: i32) -> String { | |
match index { | |
0 => format!("{:.2}", (self.amplitude.get() - 0.5) * 2f32), | |
_ => "".to_string(), | |
} | |
} | |
// This shows the control's name. | |
fn get_parameter_name(&self, index: i32) -> String { | |
match index { | |
0 => "Amplitude", | |
_ => "", | |
} | |
.to_string() | |
} | |
} | |
#[cfg(target_os = "macos")] | |
fn raw_window_handle_from_parent(parent: *mut ::std::ffi::c_void) -> RawWindowHandle { | |
use raw_window_handle::macos::MacOSHandle; | |
RawWindowHandle::MacOS(MacOSHandle { | |
ns_view: parent as *mut ::std::ffi::c_void, | |
..MacOSHandle::empty() | |
}) | |
} | |
#[cfg(target_os = "windows")] | |
fn raw_window_handle_from_parent(parent: *mut ::std::ffi::c_void) -> RawWindowHandle { | |
use raw_window_handle::windows::WindowsHandle; | |
RawWindowHandle::Windows(WindowsHandle { | |
hwnd: parent, | |
..WindowsHandle::empty() | |
}) | |
} | |
#[cfg(target_os = "linux")] | |
fn raw_window_handle_from_parent(parent: *mut ::std::ffi::c_void) -> RawWindowHandle { | |
use raw_window_handle::unix::XcbHandle; | |
RawWindowHandle::Xcb(XcbHandle { | |
window: parent as u32, | |
..XcbHandle::empty() | |
}) | |
} | |
plugin_main!(TestPlugin); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment