diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1ee7eaf..c24de9a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,38 +1,38 @@ -# This is a basic workflow to help you get started with Actions - -name: Build - -on: - push: - branches: [ main, stable ] - -jobs: - build: - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, windows-latest] - runs-on: ${{ matrix.os }} - steps: - - name: Install GTK - if: ${{ matrix.os == 'ubuntu-latest' }} - run: sudo apt install libgtk-3-dev - - uses: actions/checkout@v2 - - name: Build (release) - run: cargo build --release - - name: Upload a Build Artifact - uses: actions/upload-artifact@v2.2.2 - with: - # Artifact name - name: release - # A file, directory or wildcard pattern that describes what to upload - path: target/release/vstminihost - if-no-files-found: error - retention-days: 7 - - name: Cache - uses: actions/cache@v2.1.3 - with: - # A list of files, directories, and wildcard patterns to cache and restore - path: target - # An explicit key for restoring and saving the cache - key: deps-build +# This is a basic workflow to help you get started with Actions + +name: Build + +on: + push: + branches: [ main, stable ] + +jobs: + build: + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest] + runs-on: ${{ matrix.os }} + steps: + - name: Install GTK + if: ${{ matrix.os == 'ubuntu-latest' }} + run: sudo apt install libgtk-3-dev + - uses: actions/checkout@v2 + - name: Build (release) + run: cargo build --release + - name: Upload a Build Artifact + uses: actions/upload-artifact@v2.2.2 + with: + # Artifact name + name: release + # A file, directory or wildcard pattern that describes what to upload + path: target/release/vstminihost + if-no-files-found: error + retention-days: 7 + - name: Cache + uses: actions/cache@v2.1.3 + with: + # A list of files, directories, and wildcard patterns to cache and restore + path: target + # An explicit key for restoring and saving the cache + key: deps-build diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ad440db..3d96a2e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,42 +1,42 @@ -name: Test - -on: [push, pull_request] - -env: - CARGO_TERM_COLOR: always - -jobs: - lint: - runs-on: ubuntu-latest - steps: - - name: Install GTK - run: sudo apt install libgtk-3-dev - - uses: actions/checkout@v2 - - name: Run clippy - run: cargo clippy - - name: Cache - uses: actions/cache@v2.1.3 - with: - # A list of files, directories, and wildcard patterns to cache and restore - path: target - # An explicit key for restoring and saving the cache - key: deps-lint - test: - strategy: - matrix: - os: [windows-latest, ubuntu-latest] - runs-on: ${{ matrix.os }} - steps: - - name: Install GTK - if: ${{ matrix.os == 'ubuntu-latest' }} - run: sudo apt install libgtk-3-dev - - uses: actions/checkout@v2 - - name: Run tests - run: cargo test - - name: Cache - uses: actions/cache@v2.1.3 - with: - # A list of files, directories, and wildcard patterns to cache and restore - path: target - # An explicit key for restoring and saving the cache - key: deps-test +name: Test + +on: [push, pull_request] + +env: + CARGO_TERM_COLOR: always + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - name: Install GTK + run: sudo apt install libgtk-3-dev + - uses: actions/checkout@v2 + - name: Run clippy + run: cargo clippy + - name: Cache + uses: actions/cache@v2.1.3 + with: + # A list of files, directories, and wildcard patterns to cache and restore + path: target + # An explicit key for restoring and saving the cache + key: deps-lint + test: + strategy: + matrix: + os: [windows-latest, ubuntu-latest] + runs-on: ${{ matrix.os }} + steps: + - name: Install GTK + if: ${{ matrix.os == 'ubuntu-latest' }} + run: sudo apt install libgtk-3-dev + - uses: actions/checkout@v2 + - name: Run tests + run: cargo test + - name: Cache + uses: actions/cache@v2.1.3 + with: + # A list of files, directories, and wildcard patterns to cache and restore + path: target + # An explicit key for restoring and saving the cache + key: deps-test diff --git a/.gitignore b/.gitignore index e2c500e..7778092 100644 --- a/.gitignore +++ b/.gitignore @@ -1,21 +1,21 @@ -# Generated by Cargo -# will have compiled files and executables -/target/ - -# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries -# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html -Cargo.lock - -src/window.rs -src/newwindow.rs - -# These are backup files generated by rustfmt -**/*.rs.bk - - -# Added by cargo - -/target -# VS Code related stuff -.vscode/* +# Generated by Cargo +# will have compiled files and executables +/target/ + +# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries +# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html +Cargo.lock + +src/window.rs +src/newwindow.rs + +# These are backup files generated by rustfmt +**/*.rs.bk + + +# Added by cargo + +/target +# VS Code related stuff +.vscode/* !/.vscode/settings.json \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 3b2556e..40ed819 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,22 +1,22 @@ -[package] -name = "vsthost" -version = "0.1.0" -authors = ["Nathan Graule ", "George Atkinson ", "Andrew Numrich "] -edition = "2018" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -vst = { git = "https://github.com/RustAudio/vst-rs.git" } -#vst2-sys = "0.2.0" -#tuix = { git = "https://github.com/geom3trik/tuix.git", branch = "without_send" } -nfd = {version = "0.0.4", optional = true } -raw-window-handle = {version = "0.3.3", optional = true } -winit = { version = "0.24.0", optional = true } -#winapi = "0.3.9" -ringbuf = "0.2.4" - -[features] -default = ["editor-window"] -editor-window = ["raw-window-handle", "winit"] -nfd-select = ["nfd"] +[package] +name = "vsthost" +version = "0.1.0" +authors = ["Nathan Graule ", "George Atkinson ", "Andrew Numrich "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +vst = { git = "https://github.com/RustAudio/vst-rs.git" } +#vst2-sys = "0.2.0" +#tuix = { git = "https://github.com/geom3trik/tuix.git", branch = "without_send" } +nfd = {version = "0.0.4", optional = true } +raw-window-handle = {version = "0.3.3", optional = true } +winit = { version = "0.24.0", optional = true } +#winapi = "0.3.9" +ringbuf = "0.2.4" + +[features] +default = ["editor-window"] +editor-window = ["raw-window-handle", "winit"] +nfd-select = ["nfd"] diff --git a/LICENSE b/LICENSE index 05ae1a9..8f9343c 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,21 @@ -MIT License - -Copyright (c) 2021 Nathan Graule - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +MIT License + +Copyright (c) 2021 Nathan Graule + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 2148a55..bfe96a1 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,19 @@ -# vsthost -A simple VST host toolset. - -# About (note: this library is a big WIP) -The idea here is to provide a swiss army knife for VST hosting.
- -- `create_vsthost` to opens a VST given the path to the DLL/lib - * The `nfd-select` feature enables `Method::FileSelectDialog` which will open the NFD to fetch a path. - * This returns the `PluginInstance` and `Editor` - * note: The `PluginInstance` can be sent across threads, but not Editor. -- `open_window` provides a winit window given the editor which will attach itself to the window. - * This returns the `Window` and `EventLoop` - * The use of `EventLoop` will determine how you want the VST to run - * In a DAW setting I would recommend running GUI on the main thread, and calling `run_return` on that thread while sending your `PluginInstance` to the audio processing thread - -# TODOs -- Clean up the code -- Add support for bridging (32bit<->64bit) -- Possibly expand on windowing? +# vsthost +A simple VST host toolset. + +# About (note: this library is a big WIP) +The idea here is to provide a swiss army knife for VST hosting.
+ +- `create_vsthost` to opens a VST given the path to the DLL/lib + * The `nfd-select` feature enables `Method::FileSelectDialog` which will open the NFD to fetch a path. + * This returns the `PluginInstance` and `Editor` + * note: The `PluginInstance` can be sent across threads, but not Editor. +- `open_window` provides a winit window given the editor which will attach itself to the window. + * This returns the `Window` and `EventLoop` + * The use of `EventLoop` will determine how you want the VST to run + * In a DAW setting I would recommend running GUI on the main thread, and calling `run_return` on that thread while sending your `PluginInstance` to the audio processing thread + +# TODOs +- Clean up the code +- Add support for bridging (32bit<->64bit) +- Possibly expand on windowing? diff --git a/src/host.rs b/src/host.rs index cc4377d..379ffa7 100644 --- a/src/host.rs +++ b/src/host.rs @@ -1,53 +1,53 @@ -use std::{ - path::Path, - sync::{Arc, Mutex}, -}; - -use vst::{ - host::{Host, PluginInstance, PluginLoadError, PluginLoader}, - plugin::Plugin, -}; - -#[derive(Default)] -struct VstHostImpl { - plugin: Option, -} - -impl VstHostImpl { - fn load(&mut self, mut loader: PluginLoader) -> Result<(), PluginLoadError> { - println!("Loading plugin instance"); - let mut instance = loader.instance()?; - println!("Initializing plugin"); - instance.init(); - self.plugin.replace(instance); - println!("Done"); - Ok(()) - } - - fn get_instance(&self) -> Option<&PluginInstance> { - self.plugin.as_ref() - } -} - -#[derive(Default)] -pub struct VstHost(Arc>); - -impl Host for VstHostImpl {} - -impl VstHost { - pub fn new() -> Self { - Self(Default::default()) - } - - pub fn load>(&self, path: P) -> Result<(), PluginLoadError> { - let path = path.as_ref(); - - let loader = PluginLoader::load(path, self.0.clone())?; - self.0.lock().unwrap().load(loader)?; - Ok(()) - } - - pub fn get_ref_map T>(&self, func: F) -> Option { - self.0.lock().unwrap().get_instance().map(func) - } -} +use std::{ + path::Path, + sync::{Arc, Mutex}, +}; + +use vst::{ + host::{Host, PluginInstance, PluginLoadError, PluginLoader}, + plugin::Plugin, +}; + +#[derive(Default)] +struct VstHostImpl { + plugin: Option, +} + +impl VstHostImpl { + fn load(&mut self, mut loader: PluginLoader) -> Result<(), PluginLoadError> { + println!("Loading plugin instance"); + let mut instance = loader.instance()?; + println!("Initializing plugin"); + instance.init(); + self.plugin.replace(instance); + println!("Done"); + Ok(()) + } + + fn get_instance(&self) -> Option<&PluginInstance> { + self.plugin.as_ref() + } +} + +#[derive(Default)] +pub struct VstHost(Arc>); + +impl Host for VstHostImpl {} + +impl VstHost { + pub fn new() -> Self { + Self(Default::default()) + } + + pub fn load>(&self, path: P) -> Result<(), PluginLoadError> { + let path = path.as_ref(); + + let loader = PluginLoader::load(path, self.0.clone())?; + self.0.lock().unwrap().load(loader)?; + Ok(()) + } + + pub fn get_ref_map T>(&self, func: F) -> Option { + self.0.lock().unwrap().get_instance().map(func) + } +} diff --git a/src/lib.rs b/src/lib.rs index 6e69fce..2bf2827 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,239 +1,239 @@ -use std::{ - path::Path, - sync::{ - mpsc::{channel, Sender}, - Arc, Mutex, - }, -}; - -use raw_window_handle::{HasRawWindowHandle, RawWindowHandle}; -//use tuix::*; - -use nfd::Response; -pub use vst::{ - host::{Host, PluginInstance, PluginLoadError, PluginLoader}, - plugin::Plugin, -}; -pub use winit::window::Window; -use std::ffi::c_void; -use std::sync::atomic::AtomicU32; -use winit::dpi::{LogicalSize, PhysicalSize}; -pub use ringbuf::*; -use vst::api; -use vst::event; -use crate::event_gen::{new_midievent, encode_midi_message_as_events}; -use std::time::Duration; -use vst::buffer::AudioBuffer; -use vst::host::HostBuffer; -//use crate::newwindow::open_window; -pub use vst::editor::Editor; - -mod host; -mod event_gen; -pub mod winit_window; -mod audioframe; - -#[derive(Default)] -struct VstHost; - -impl Host for VstHost {} - -#[derive(Clone, Debug, PartialEq)] -enum HostWidgetEvent { - OpenFile, -} - -#[derive(Default)] -pub struct HostWidget { - host: Arc>, -} - -// impl BuildHandler for HostWidget { -// type Ret = Entity; -// fn on_build(&mut self, state: &mut State, entity: Entity) -> Self::Ret { -// state.insert_stylesheet("src/theme.css"); -// -// let container = VBox::new().build(state, entity, |builder| builder); -// -// let open_file_button = Button::with_label("Open File") -// .on_press(Event::new(HostWidgetEvent::OpenFile).target(entity)) -// .build(state, container, |builder| { -// builder.class("open_file_dialogue_button") -// }); -// -// self.label = Label::new("").build(state, container, |builder| builder); -// -// entity -// } -// } -// -// impl EventHandler for HostWidget { -// fn on_event(&mut self, state: &mut State, entity: Entity, event: &mut Event) -> bool { -// if let Some(host_widget_event) = event.message.downcast::() { -// match host_widget_event { -// HostWidgetEvent::OpenFile => { -// if event.target == entity { -// let result = nfd::open_file_dialog(None, None).unwrap_or_else(|e| { -// panic!(e); -// }); -// -// let path = match result { -// Response::Okay(file_path) => file_path, -// Response::OkayMultiple(mut files) => { -// files.drain(..).take(1).next().unwrap() -// } -// _ => return false, -// }; -// let mut instance = load(self.host.clone(), path).unwrap(); -// if let Some(editor) = instance.get_editor() { -// let parent = todo!(); -// //let success = editor.open(parent); -// println!("Editor window opened successfully"); -// } -// -// self.label -// .set_text(state, &format!("{:?}", instance.get_info())); -// -// return true; -// } -// } -// } -// } -// -// false -// } -// } - -fn load>( - host: Arc>, - path: P, -) -> Result { - let mut loader = PluginLoader::load(path.as_ref(), Arc::clone(&host))?; - loader.instance() -} - -pub enum Method { - Path(String), - #[cfg(feature = "nfd-select")] - FileSelectDialog -} - -// pub struct VSTSeat{ -// host: Arc>, -// instance: PluginInstance -// } - -//-> (Producer<[u8;3]>, Consumer, Application) -pub fn create_vsthost(method: Method) -> Result { - - // LOAD PLUGIN - let host = Arc::new(Mutex::new(VstHost)); - - let path: String = match method { - Method::Path(p) => p, - - #[cfg(feature = "nfd-select")] - Method::FileSelectDialog => { - match nfd::open_file_dialog(None,None) { - Ok(r) => { - match r { - Response::Okay(f) => { - f - } - Response::OkayMultiple(fs) => { - panic!("Too many picked!"); - } - Response::Cancel => { - panic!("Nothing picked!"); - } - } - } - Err(e) => { - panic!("{:?}",e); - } - } - } - }; - - println!("loading VST: {:?}",path); - load(host, &path) -} - -// pub fn start_generator_vsthost() -> (Producer<[u8;3]>, Consumer, Box) { -// -// // LOAD PLUGIN -// -// let args = std::env::args().collect::>(); -// let host = Arc::new(Mutex::new(VstHost)); -// -// let lol = match nfd::open_file_dialog(None,None) { -// Ok(r) => { -// match r { -// Response::Okay(f) => { -// f -// } -// Response::OkayMultiple(fs) => { -// panic!("Too many picked!"); -// } -// Response::Cancel => { -// panic!("Nothing picked!"); -// } -// } -// } -// Err(e) => { -// panic!("{:?}",e); -// } -// }; -// println!("{:?}",lol); -// let mut instance = load(host, &lol).unwrap(); -// let mut editor = instance.get_editor().unwrap(); -// -// println!("running application"); -// -// let mut midi_io: RingBuffer<[u8; 3]> = RingBuffer::new(1); -// let mut sound_io: RingBuffer = RingBuffer::new(4096); -// -// let (mut midi_to_plug, mut midi_from_player) = midi_io.split(); -// let (mut audio_to_player, mut audio_from_plug) = sound_io.split(); -// -// std::thread::spawn(move ||{ -// println!("VST midi/audio processing thread..."); -// -// //instance.resume(); -// -// // instance.set_block_size(1); -// // instance.set_sample_rate(44100.0); -// -// let mut count = 0; -// loop { -// let mut host_buffer: HostBuffer = HostBuffer::new(2, 2); -// let inputs = vec![vec![0.0; 1]; 2]; -// let mut outputs = vec![vec![0.0; 1]; 2]; -// let mut audio_buffer = host_buffer.bind(&inputs, &mut outputs); -// -// //print!("midi"); -// -// // count += 1; -// // println!("{}",count); -// // if count >= 44 { -// // println!("sending midi..."); -// // -// // count = 0; -// // } -// -// if !midi_from_player.is_empty() { -// let mut e = encode_midi_message_as_events(midi_from_player.pop().unwrap()); -// instance.process_events(&e.events); -// } -// -// instance.process(&mut audio_buffer); -// while audio_to_player.is_full() { -// // wait -// } -// audio_to_player.push(audio_buffer.split().1.get(0)[0]); -// -// } -// }); -// (midi_to_plug, audio_from_plug, editor) -// } - +use std::{ + path::Path, + sync::{ + mpsc::{channel, Sender}, + Arc, Mutex, + }, +}; + +use raw_window_handle::{HasRawWindowHandle, RawWindowHandle}; +//use tuix::*; + +use nfd::Response; +pub use vst::{ + host::{Host, PluginInstance, PluginLoadError, PluginLoader}, + plugin::Plugin, +}; +pub use winit::window::Window; +use std::ffi::c_void; +use std::sync::atomic::AtomicU32; +use winit::dpi::{LogicalSize, PhysicalSize}; +pub use ringbuf::*; +use vst::api; +use vst::event; +use crate::event_gen::{new_midievent, encode_midi_message_as_events}; +use std::time::Duration; +use vst::buffer::AudioBuffer; +use vst::host::HostBuffer; +//use crate::newwindow::open_window; +pub use vst::editor::Editor; + +mod host; +mod event_gen; +pub mod winit_window; +mod audioframe; + +#[derive(Default)] +struct VstHost; + +impl Host for VstHost {} + +#[derive(Clone, Debug, PartialEq)] +enum HostWidgetEvent { + OpenFile, +} + +#[derive(Default)] +pub struct HostWidget { + host: Arc>, +} + +// impl BuildHandler for HostWidget { +// type Ret = Entity; +// fn on_build(&mut self, state: &mut State, entity: Entity) -> Self::Ret { +// state.insert_stylesheet("src/theme.css"); +// +// let container = VBox::new().build(state, entity, |builder| builder); +// +// let open_file_button = Button::with_label("Open File") +// .on_press(Event::new(HostWidgetEvent::OpenFile).target(entity)) +// .build(state, container, |builder| { +// builder.class("open_file_dialogue_button") +// }); +// +// self.label = Label::new("").build(state, container, |builder| builder); +// +// entity +// } +// } +// +// impl EventHandler for HostWidget { +// fn on_event(&mut self, state: &mut State, entity: Entity, event: &mut Event) -> bool { +// if let Some(host_widget_event) = event.message.downcast::() { +// match host_widget_event { +// HostWidgetEvent::OpenFile => { +// if event.target == entity { +// let result = nfd::open_file_dialog(None, None).unwrap_or_else(|e| { +// panic!(e); +// }); +// +// let path = match result { +// Response::Okay(file_path) => file_path, +// Response::OkayMultiple(mut files) => { +// files.drain(..).take(1).next().unwrap() +// } +// _ => return false, +// }; +// let mut instance = load(self.host.clone(), path).unwrap(); +// if let Some(editor) = instance.get_editor() { +// let parent = todo!(); +// //let success = editor.open(parent); +// println!("Editor window opened successfully"); +// } +// +// self.label +// .set_text(state, &format!("{:?}", instance.get_info())); +// +// return true; +// } +// } +// } +// } +// +// false +// } +// } + +fn load>( + host: Arc>, + path: P, +) -> Result { + let mut loader = PluginLoader::load(path.as_ref(), Arc::clone(&host))?; + loader.instance() +} + +pub enum Method { + Path(String), + #[cfg(feature = "nfd-select")] + FileSelectDialog +} + +// pub struct VSTSeat{ +// host: Arc>, +// instance: PluginInstance +// } + +//-> (Producer<[u8;3]>, Consumer, Application) +pub fn create_vsthost(method: Method) -> Result { + + // LOAD PLUGIN + let host = Arc::new(Mutex::new(VstHost)); + + let path: String = match method { + Method::Path(p) => p, + + #[cfg(feature = "nfd-select")] + Method::FileSelectDialog => { + match nfd::open_file_dialog(None,None) { + Ok(r) => { + match r { + Response::Okay(f) => { + f + } + Response::OkayMultiple(fs) => { + panic!("Too many picked!"); + } + Response::Cancel => { + panic!("Nothing picked!"); + } + } + } + Err(e) => { + panic!("{:?}",e); + } + } + } + }; + + println!("loading VST: {:?}",path); + load(host, &path) +} + +// pub fn start_generator_vsthost() -> (Producer<[u8;3]>, Consumer, Box) { +// +// // LOAD PLUGIN +// +// let args = std::env::args().collect::>(); +// let host = Arc::new(Mutex::new(VstHost)); +// +// let lol = match nfd::open_file_dialog(None,None) { +// Ok(r) => { +// match r { +// Response::Okay(f) => { +// f +// } +// Response::OkayMultiple(fs) => { +// panic!("Too many picked!"); +// } +// Response::Cancel => { +// panic!("Nothing picked!"); +// } +// } +// } +// Err(e) => { +// panic!("{:?}",e); +// } +// }; +// println!("{:?}",lol); +// let mut instance = load(host, &lol).unwrap(); +// let mut editor = instance.get_editor().unwrap(); +// +// println!("running application"); +// +// let mut midi_io: RingBuffer<[u8; 3]> = RingBuffer::new(1); +// let mut sound_io: RingBuffer = RingBuffer::new(4096); +// +// let (mut midi_to_plug, mut midi_from_player) = midi_io.split(); +// let (mut audio_to_player, mut audio_from_plug) = sound_io.split(); +// +// std::thread::spawn(move ||{ +// println!("VST midi/audio processing thread..."); +// +// //instance.resume(); +// +// // instance.set_block_size(1); +// // instance.set_sample_rate(44100.0); +// +// let mut count = 0; +// loop { +// let mut host_buffer: HostBuffer = HostBuffer::new(2, 2); +// let inputs = vec![vec![0.0; 1]; 2]; +// let mut outputs = vec![vec![0.0; 1]; 2]; +// let mut audio_buffer = host_buffer.bind(&inputs, &mut outputs); +// +// //print!("midi"); +// +// // count += 1; +// // println!("{}",count); +// // if count >= 44 { +// // println!("sending midi..."); +// // +// // count = 0; +// // } +// +// if !midi_from_player.is_empty() { +// let mut e = encode_midi_message_as_events(midi_from_player.pop().unwrap()); +// instance.process_events(&e.events); +// } +// +// instance.process(&mut audio_buffer); +// while audio_to_player.is_full() { +// // wait +// } +// audio_to_player.push(audio_buffer.split().1.get(0)[0]); +// +// } +// }); +// (midi_to_plug, audio_from_plug, editor) +// } +