From cb181b0d86f3a837eb9bba6c727044d9be06d424 Mon Sep 17 00:00:00 2001 From: unspeaker Date: Wed, 24 Jul 2024 15:12:48 +0300 Subject: [PATCH] and now to debug some SIGSEGVs --- Cargo.lock | 1 + crates/suil/Cargo.toml | 1 + crates/suil/src/lib.rs | 19 ++++---- crates/suil/src/test.rs | 102 ++++++++++++++++++++++++++++++++++++---- 4 files changed, 105 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 767f4fdc..7ca09b41 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2134,6 +2134,7 @@ name = "suil" version = "0.1.0" dependencies = [ "bindgen", + "livi", "winit", ] diff --git a/crates/suil/Cargo.toml b/crates/suil/Cargo.toml index 9b8522b2..81b9b0d6 100644 --- a/crates/suil/Cargo.toml +++ b/crates/suil/Cargo.toml @@ -10,3 +10,4 @@ bindgen = "0.69.4" [dev-dependencies] winit = { version = "0.30.4", features = [ "x11" ] } +livi = "0.7.4" diff --git a/crates/suil/src/lib.rs b/crates/suil/src/lib.rs index 6a7627d3..30f55835 100644 --- a/crates/suil/src/lib.rs +++ b/crates/suil/src/lib.rs @@ -7,16 +7,11 @@ pub struct Host(*mut self::bound::SuilHost); pub struct Instance(*mut self::bound::SuilInstance); -pub struct Controller(*mut self::bound::SuilController); - impl Host { pub fn new () -> Self { - //let write = std::ptr::null(); - //let index = std::ptr::null(); - //let subscribe = std::ptr::null(); - //let unsubscribe = std::ptr::null(); Self(unsafe { - bound::suil_init(&mut 0, std::ptr::null_mut(), 0); + let argv = &mut [] as *mut *mut *mut i8; + bound::suil_init(&mut 0, argv, 0); bound::suil_host_new( Some(Self::write), Some(Self::index), @@ -40,9 +35,9 @@ impl Host { fn set_touch_func (&self) { unimplemented!(); } - fn instance ( + fn instance ( &self, - controller: &Controller, + controller: &mut T, container_type_uri: &str, plugin_uri: &str, ui_uri: &str, @@ -60,7 +55,7 @@ impl Host { Ok(Instance(unsafe { bound::suil_instance_new( self.0, - *controller.0, + controller as *mut _ as *mut std::ffi::c_void, container_type_uri.into_raw(), plugin_uri.into_raw(), ui_uri.into_raw(), @@ -88,3 +83,7 @@ impl Drop for Instance { } } } + +unsafe impl Send for Instance {} + +unsafe impl Sync for Instance {} diff --git a/crates/suil/src/test.rs b/crates/suil/src/test.rs index f7437ca8..b55e7d2f 100644 --- a/crates/suil/src/test.rs +++ b/crates/suil/src/test.rs @@ -1,13 +1,26 @@ use crate::*; +use std::sync::Arc; #[test] fn panics () { let host = Host::new(); - self::ui::UI::run().join(); + let mut plugin = plugin::LV2Plugin::new("file:///home/user/.lv2/Odin2.lv2").unwrap(); + let instance = Arc::new(host.instance( + &mut plugin, + "", + "https://thewavewarden.com/odin2", + "https://thewavewarden.com/odin2#ParentUI", + "", + "", + "/home/user/.lv2/Odin2.lv2/Odin2.so", + &[], + ).unwrap()); + self::ui::UI::run(&instance).join(); panic!(); } mod ui { + use std::sync::Arc; use std::thread::{spawn, JoinHandle}; use ::winit::{ application::ApplicationHandler, @@ -16,11 +29,20 @@ mod ui { window::{Window, WindowId}, platform::x11::EventLoopBuilderExtX11 }; - pub struct UI(Option); + use crate::{Host, Instance}; + pub struct UI { + host: Arc, + window: Option + } impl UI { - pub fn new () -> Self { Self(None) } - pub fn run () -> JoinHandle<()> { - let mut ui = Self::new(); + pub fn new (host: &Arc) -> Self { + Self { + host: host.clone(), + window: None + } + } + pub fn run (host: &Arc) -> JoinHandle<()> { + let mut ui = Self::new(host); spawn(move||{ let event_loop = EventLoop::builder().with_x11().with_any_thread(true).build().unwrap(); event_loop.set_control_flow(ControlFlow::Wait); @@ -30,19 +52,83 @@ mod ui { } impl ApplicationHandler for UI { fn resumed (&mut self, event_loop: &ActiveEventLoop) { - self.0 = Some(event_loop.create_window(Window::default_attributes()).unwrap()); + self.window = Some(event_loop.create_window(Window::default_attributes()).unwrap()); } fn window_event (&mut self, event_loop: &ActiveEventLoop, id: WindowId, event: WindowEvent) { match event { WindowEvent::CloseRequested => { - self.0.as_ref().unwrap().set_visible(false); + self.window.as_ref().unwrap().set_visible(false); event_loop.exit(); }, WindowEvent::RedrawRequested => { - self.0.as_ref().unwrap().request_redraw(); + self.window.as_ref().unwrap().request_redraw(); } _ => (), } } } } + +mod plugin { + use std::thread::JoinHandle; + use std::sync::Arc; + use ::livi::{ + World, + Instance, + Plugin as LiviPlugin, + Features, + FeaturesBuilder, + Port, + event::LV2AtomSequence, + }; + /// A LV2 plugin. + pub struct LV2Plugin { + pub world: World, + pub instance: Instance, + pub plugin: LiviPlugin, + pub features: Arc, + pub port_list: Vec, + pub input_buffer: Vec, + pub ui_thread: Option>, + } + + impl LV2Plugin { + pub fn new (uri: &str) -> Result> { + // Get 1st plugin at URI + let world = World::with_load_bundle(&uri); + let features = FeaturesBuilder { min_block_length: 1, max_block_length: 65536 }; + let features = world.build_features(features); + let mut plugin = None; + for p in world.iter_plugins() { + plugin = Some(p); + break + } + if plugin.is_none() { + return Err(format!("plugin not found: {uri}").into()) + } + let plugin = plugin.unwrap(); + let err = &format!("init {uri}"); + + // Instantiate + Ok(Self { + world, + instance: unsafe { + plugin + .instantiate(features.clone(), 48000.0) + .expect(&err) + }, + port_list: { + let mut port_list = vec![]; + for port in plugin.ports() { + port_list.push(port); + } + port_list + }, + plugin, + features, + input_buffer: Vec::with_capacity(1024), + ui_thread: None + }) + } + } +}