Skip to content

Instantly share code, notes, and snippets.

@DGriffin91
Created December 23, 2020 05:22
Show Gist options
  • Save DGriffin91/32fc42a4fc0e74a7ae0b8b036ac4ac40 to your computer and use it in GitHub Desktop.
Save DGriffin91/32fc42a4fc0e74a7ae0b8b036ac4ac40 to your computer and use it in GitHub Desktop.
//! 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