Rust Audio

Vst + vst_window + sdl2 plugin broken

Hi all,

I’ve setup a basic VST plugin with a window managed by SDL2. The code compiles without errors, but when I try to load it into a VST host (tried both VSTHost and LMMS), the host hangs for a fraction of a second and then quits loading the plugin without an error message. The plugin is not successfully loaded at all.

I’ve tried setting up some basic logging using the log and simplelog crates to write to a file, but when I try to load the plugin into a host, it doesn’t even execute PluginTest::new(), which is where I setup the logger.

Does someone know what could be causing the issue? Any help is appreciated.

Code:

use std::ffi::c_void;

use sdl2::{EventPump, Sdl, event::Event, keyboard::Keycode, pixels::Color, render::Canvas, video::Window};
use vst::{editor::Editor, plugin::{HostCallback, Info, Plugin}};

pub const WINDOW_DIMENSIONS: (i32, i32) = (640, 360);



#[derive(Default)]
pub struct PluginTest {
    editor_placeholder: Option<PluginEditor>
}

impl Plugin for PluginTest {
    fn new(host: HostCallback) -> PluginTest {
        return PluginTest {
            editor_placeholder: Some(PluginEditor::default())
        };
    }
    
    fn get_info(&self) -> Info {
        return Info {
            name: "PluginTest".to_string(),
            
            unique_id: 42069,
            inputs: 0,
            outputs: 2,
            
            
            ..Default::default()
        };
    }
    
    fn get_editor(&mut self) -> Option<Box<dyn Editor>> {
        self.editor_placeholder
            .take()
            .map(|editor| Box::new(editor) as Box<dyn Editor>)
    }
}


#[derive(Default)]
pub struct PluginEditor {
    renderer: Option<PluginRenderer>
}

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

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

    fn open(&mut self, parent: *mut c_void) -> bool {
        self.renderer = Some(PluginRenderer::new(parent));
        return true;
    }
    
    fn is_open(&mut self) -> bool {
        return self.renderer.is_some();
    }

    fn close(&mut self) {
        drop(self.renderer.take());
    }
    
    fn idle(&mut self) {
        if let Some(renderer) = &mut self.renderer {
            renderer.draw_frame();
        }
    }
}



pub struct PluginRenderer {
    sdl: Sdl,
    canvas: Canvas<Window>,
    event_pump: EventPump,
    i: u8
}

impl PluginRenderer {
    pub fn new(parent: *mut c_void) -> PluginRenderer {
        let sdl = sdl2::init().unwrap();
        
        let w: *mut sdl2_sys::SDL_Window =
            unsafe { sdl2_sys::SDL_CreateWindowFrom(parent as *const c_void) };
        
        let video_subsystem = sdl.video().unwrap();
        
        let window: sdl2::video::Window = {
            unsafe { sdl2::video::Window::from_ll(video_subsystem, w) }
        };
        
        let mut canvas = window.into_canvas().build().unwrap();
        canvas.clear();
        canvas.present();
        
        let event_pump = sdl.event_pump().unwrap();
        
        return PluginRenderer {
            sdl: sdl,
            canvas: canvas,
            event_pump: event_pump,
            i: 0
        }
    }
    
    pub fn draw_frame(&mut self) {
        self.i = (self.i + 1) % 255;
        
        self.canvas.set_draw_color(Color::RGB(self.i, 64, 255 - self.i));
        
        self.canvas.clear();
        
        for event in self.event_pump.poll_iter() {
            match event {
                Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
                    
                }
                _ => {}
            }
        }
        
        self.canvas.present();
    }
}

plugin_main!(PluginTest);

Answer: Since DLLs are dynamically linked, all of the SDL.dll files need to be in the same directory as the plugin dll.

I still have problems getting SDL to work with vst, but this allows the plugin to actually load.

1 Like