diff --git a/apps/magpie/src/protocol.rs b/apps/magpie/src/protocol.rs index 5915e4a..6d83b6f 100644 --- a/apps/magpie/src/protocol.rs +++ b/apps/magpie/src/protocol.rs @@ -24,6 +24,7 @@ pub type PanelId = u32; #[derive(Clone, Debug, Deserialize, Serialize)] pub struct CreatePanel { pub id: PanelId, + pub protocol: String, pub script: PathBuf, } diff --git a/apps/magpie/src/service/ipc.rs b/apps/magpie/src/service/ipc.rs index 744448c..869e297 100644 --- a/apps/magpie/src/service/ipc.rs +++ b/apps/magpie/src/service/ipc.rs @@ -99,7 +99,11 @@ impl Client { while let Some(msg) = self.messenger.recv() { println!("Client #{}: {:?}", self.token.0, msg); match msg { - MagpieServerMsg::CreatePanel(CreatePanel { id, script }) => { + MagpieServerMsg::CreatePanel(CreatePanel { + id, + protocol, + script, + }) => { let window = self.data.write().new_window_id(); if let Some(old_id) = self.id_to_window.insert(id, window) { @@ -107,7 +111,11 @@ impl Client { let _ = self.window_sender.send_event(msg); } - let msg = WindowMessage::OpenWindow { id: window, script }; + let msg = WindowMessage::OpenWindow { + id: window, + protocol, + script, + }; let _ = self.window_sender.send_event(msg); } MagpieServerMsg::SendMessage(SendMessage { id, msg }) => { diff --git a/apps/magpie/src/service/window.rs b/apps/magpie/src/service/window.rs index 6939057..3834224 100644 --- a/apps/magpie/src/service/window.rs +++ b/apps/magpie/src/service/window.rs @@ -17,10 +17,19 @@ use crate::service::ipc::{IpcMessage, IpcMessageSender}; #[derive(Clone, Debug)] pub enum WindowMessage { - OpenWindow { id: usize, script: PathBuf }, - CloseWindow { id: usize }, + OpenWindow { + id: usize, + protocol: String, + script: PathBuf, + }, + CloseWindow { + id: usize, + }, Quit, - SendMessage { id: usize, msg: Vec }, + SendMessage { + id: usize, + msg: Vec, + }, } pub type WindowMessageSender = EventLoopProxy; @@ -155,11 +164,11 @@ impl WindowStore { message: WindowMessage, ) -> anyhow::Result { match message { - WindowMessage::OpenWindow { id, script } => { + WindowMessage::OpenWindow { id, protocol, script } => { println!("Opening window {} with script {:?}", id, script); let module = std::fs::read(script)?; let mut script = self.runtime.load_module(&module)?; - let panel = script.create_panel(vec![])?; + let panel = script.create_panel(&protocol, vec![])?; let window = Window::new(panel, &event_loop)?; let window_id = window.get_id(); self.windows.insert(window_id, window); diff --git a/apps/music-player/src/main.rs b/apps/music-player/src/main.rs index abc23f7..5f07f12 100644 --- a/apps/music-player/src/main.rs +++ b/apps/music-player/src/main.rs @@ -86,8 +86,9 @@ fn main() { let player_finder = PlayerFinder::new().expect("Could not connect to D-Bus"); let mut magpie = MagpieClient::new().unwrap(); + let protocol = "tebibyte-media.desktop.music-player-controller".to_string(); let script = std::path::PathBuf::from(&module_path); - let msg = CreatePanel { id: 0, script }; + let msg = CreatePanel { id: 0, protocol, script }; let msg = MagpieServerMsg::CreatePanel(msg); magpie.messenger.send(&msg).unwrap(); diff --git a/apps/sandbox/src/main.rs b/apps/sandbox/src/main.rs index 8593ebd..9ec1f57 100644 --- a/apps/sandbox/src/main.rs +++ b/apps/sandbox/src/main.rs @@ -31,6 +31,7 @@ struct App { panels: Vec, next_idx: usize, last_update: Instant, + protocol_buf: String, bind_message_buf: String, } @@ -46,6 +47,7 @@ impl App { panels: vec![], next_idx: 0, last_update: Instant::now(), + protocol_buf: String::new(), bind_message_buf: String::new(), } } @@ -56,12 +58,16 @@ impl eframe::App for App { ctx.request_repaint(); egui::SidePanel::left("left_panel").show(ctx, |ui| { + ui.label("Protocol name:"); + ui.text_edit_singleline(&mut self.protocol_buf); + + ui.label("Bind message:"); let text_edit = egui::TextEdit::multiline(&mut self.bind_message_buf).code_editor(); ui.add(text_edit); if ui.button("Bind Panel").clicked() { let msg = self.bind_message_buf.as_bytes().to_vec(); - let panel = self.script.create_panel(msg).unwrap(); + let panel = self.script.create_panel(&self.protocol_buf, msg).unwrap(); let index = self.next_idx; self.next_idx += 1; diff --git a/crates/script/src/api/abi.rs b/crates/script/src/api/abi.rs index 0e70bc5..4ebc255 100644 --- a/crates/script/src/api/abi.rs +++ b/crates/script/src/api/abi.rs @@ -7,11 +7,17 @@ use super::*; static mut PANEL_IMPLS: Vec> = Vec::new(); -pub fn bind_panel(panel: u32, msg: u32) -> u32 { +pub fn bind_panel( + cb: impl Fn(Panel, Message, Message) -> Box, + panel: u32, + protocol: u32, + msg: u32, +) -> u32 { unsafe { let panel = Panel(panel); + let protocol = Message(protocol); let msg = Message(msg); - let panel_impl = T::bind(panel, msg); + let panel_impl = cb(panel, protocol, msg); let id = PANEL_IMPLS.len() as u32; PANEL_IMPLS.push(panel_impl); id diff --git a/crates/script/src/api/mod.rs b/crates/script/src/api/mod.rs index b208388..56484e1 100644 --- a/crates/script/src/api/mod.rs +++ b/crates/script/src/api/mod.rs @@ -9,10 +9,10 @@ pub mod abi; #[macro_export] macro_rules! export_abi { - ($panel_impl: ident) => { + ($bind_panel: ident) => { #[no_mangle] - pub extern "C" fn bind_panel(panel: u32, msg: u32) -> u32 { - ::canary_script::api::abi::bind_panel::<$panel_impl>(panel, msg) + pub extern "C" fn bind_panel(panel: u32, protocol: u32, msg: u32) -> u32 { + ::canary_script::api::abi::bind_panel($bind_panel, panel, protocol, msg) } #[no_mangle] @@ -42,10 +42,6 @@ macro_rules! export_abi { }; } -pub trait BindPanel { - fn bind(panel: Panel, msg: Message) -> Box; -} - pub trait PanelImpl { fn update(&mut self, dt: f32); fn draw(&mut self); @@ -375,7 +371,6 @@ impl DrawContext { self.draw_rect(bottom_edge, color); } - self.draw_rect(inner_rect, color); } diff --git a/scripts/music-player/src/lib.rs b/scripts/music-player/src/lib.rs index a4bee91..956df2b 100644 --- a/scripts/music-player/src/lib.rs +++ b/scripts/music-player/src/lib.rs @@ -4,10 +4,14 @@ #[global_allocator] static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; -use canary_script::*; use api::*; +use canary_script::*; -canary_script::export_abi!(MusicPlayerPanel); +canary_script::export_abi!(bind_panel_impl); + +pub fn bind_panel_impl(panel: Panel, _protocol: Message, message: Message) -> Box { + MusicPlayerPanel::bind(panel, message) +} const DISPLAY_FONT: &str = "Liberation Sans"; @@ -17,19 +21,6 @@ pub struct MusicPlayerPanel { label: Label, } -impl BindPanel for MusicPlayerPanel { - fn bind(panel: Panel, message: Message) -> Box { - let display_font = Font::new(DISPLAY_FONT); - let label = Label::new(display_font, "Hello, world!".into(), 1.2); - let panel = Self { - panel, - display_font, - label, - }; - Box::new(panel) - } -} - impl PanelImpl for MusicPlayerPanel { fn update(&mut self, dt: f32) {} @@ -42,20 +33,31 @@ impl PanelImpl for MusicPlayerPanel { self.label.draw(&ctx, offset, size, color); } - fn on_resize(&mut self, new_size: Vec2) { - - } + fn on_resize(&mut self, new_size: Vec2) {} fn on_cursor_event(&mut self, kind: CursorEventKind, at: Vec2) {} fn on_message(&mut self, msg: Message) { - use canary_music_player::{InMsg, serde_json}; + use canary_music_player::{serde_json, InMsg}; let msg = msg.to_vec(); let msg = serde_json::from_slice::(&msg); self.label.set_text(format!("{:#?}", msg)); } } +impl MusicPlayerPanel { + pub fn bind(panel: Panel, _message: Message) -> Box { + let display_font = Font::new(DISPLAY_FONT); + let label = Label::new(display_font, "Hello, world!".into(), 1.2); + let panel = Self { + panel, + display_font, + label, + }; + Box::new(panel) + } +} + pub struct Label { font: Font, text: String, diff --git a/scripts/sao-ui/src/lib.rs b/scripts/sao-ui/src/lib.rs index 0d12dc2..23d535b 100644 --- a/scripts/sao-ui/src/lib.rs +++ b/scripts/sao-ui/src/lib.rs @@ -8,12 +8,16 @@ pub mod anim; pub mod main_menu; pub mod widgets; -use canary_script::*; use api::*; -use widgets::Widget; +use canary_script::*; use main_menu::MainMenuPanel; +use widgets::Widget; -export_abi!(MainMenuPanel); +export_abi!(bind_panel_impl); + +fn bind_panel_impl(panel: Panel, _protocol: Message, msg: Message) -> Box { + MainMenuPanel::bind(panel, msg) +} pub const ICON_FONT: &str = "Iosevka Nerd Font"; pub const DISPLAY_FONT: &str = "Homenaje"; @@ -24,18 +28,6 @@ pub struct ConfirmationDialogPanel { dialog: widgets::dialog::Dialog, } -impl BindPanel for ConfirmationDialogPanel { - fn bind(panel: Panel, msg: Message) -> Box { - let msg = msg.to_vec(); - let info: DialogInfo = serde_json::from_slice(&msg).unwrap(); - - use widgets::dialog::*; - let style = DialogStyle::default(); - let dialog = Dialog::new(style, &info); - Box::new(Self { panel, dialog }) - } -} - impl PanelImpl for ConfirmationDialogPanel { fn update(&mut self, dt: f32) { self.dialog.update(dt); @@ -54,3 +46,15 @@ impl PanelImpl for ConfirmationDialogPanel { fn on_message(&mut self, _msg: Message) {} } + +impl ConfirmationDialogPanel { + pub fn bind(panel: Panel, msg: Message) -> Box { + let msg = msg.to_vec(); + let info: DialogInfo = serde_json::from_slice(&msg).unwrap(); + + use widgets::dialog::*; + let style = DialogStyle::default(); + let dialog = Dialog::new(style, &info); + Box::new(Self { panel, dialog }) + } +} diff --git a/scripts/sao-ui/src/main_menu.rs b/scripts/sao-ui/src/main_menu.rs index f8e3ffc..87bbbb0 100644 --- a/scripts/sao-ui/src/main_menu.rs +++ b/scripts/sao-ui/src/main_menu.rs @@ -15,15 +15,6 @@ pub struct MainMenuPanel { menu: MainMenu, } -impl BindPanel for MainMenuPanel { - fn bind(panel: Panel, msg: Message) -> Box { - Box::new(Self { - panel, - menu: MainMenu::default(), - }) - } -} - impl PanelImpl for MainMenuPanel { fn update(&mut self, dt: f32) { Widget::update(&mut self.menu, dt); @@ -43,6 +34,15 @@ impl PanelImpl for MainMenuPanel { fn on_message(&mut self, msg: Message) {} } +impl MainMenuPanel { + pub fn bind(panel: Panel, msg: Message) -> Box { + Box::new(Self { + panel, + menu: MainMenu::default(), + }) + } +} + pub struct MainMenu { pub menu: Offset>, pub player_info: Reveal>, diff --git a/src/backend/mod.rs b/src/backend/mod.rs index ca0333f..b815501 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -36,10 +36,11 @@ pub trait Instance { /// Binds script data to a Canary panel. /// /// To "bind" a Canary panel to a Canary script, this function must be - /// called. It passes the ID of a panel to the script, plus an - /// initialization message, and the script returns an integer as - /// userdata. All panel events will be identified to the script with this - /// userdata as the first argument. + /// called. It passes the ID of a panel to the script, the name of the + /// protocol that this panel will be using, plus an initialization + /// message, and the script returns an integer as userdata. All panel + /// events will be identified to the script with this userdata as the first + /// argument. /// /// The intended usecase for this userdata is to contain a pointer. A /// Canary script can allocate some high-level object in memory, and when @@ -47,7 +48,7 @@ pub trait Instance { /// userdata. Then, when the runtime calls back into the script, the /// userdata will be reinterpreted as a pointer and a method can be called /// on that object in memory. - fn bind_panel(&self, panel: PanelId, msg: Vec) -> u32; + fn bind_panel(&self, panel: PanelId, protocol: &str, msg: Vec) -> u32; fn update(&self, panel_ud: u32, dt: f32); diff --git a/src/backend/wasmtime.rs b/src/backend/wasmtime.rs index 73057d8..1024aaa 100644 --- a/src/backend/wasmtime.rs +++ b/src/backend/wasmtime.rs @@ -61,7 +61,7 @@ impl Backend for WasmtimeBackend { pub struct WasmtimeInstance { store: Mutex, - bind_panel: wasmtime::TypedFunc<(u32, u32), u32>, + bind_panel: wasmtime::TypedFunc<(u32, u32, u32), u32>, update: wasmtime::TypedFunc<(u32, f32), ()>, draw: wasmtime::TypedFunc, on_resize: wasmtime::TypedFunc<(u32, f32, f32), ()>, @@ -189,11 +189,13 @@ impl WasmtimeInstance { } impl Instance for WasmtimeInstance { - fn bind_panel(&self, panel: PanelId, msg: Vec) -> u32 { + fn bind_panel(&self, panel: PanelId, protocol: &str, msg: Vec) -> u32 { let mut store = self.store.lock(); + let protocol = store.data().message_new(protocol.as_bytes().to_vec()); let msg = store.data().message_new(msg); - let args = (panel.0 as u32, msg); + let args = (panel.0 as u32, protocol, msg); let data = self.bind_panel.call(store.deref_mut(), args).unwrap(); + store.data().message_free(protocol); store.data().message_free(msg); data } diff --git a/src/lib.rs b/src/lib.rs index 81c5b98..f356234 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -45,10 +45,10 @@ pub struct Script { } impl Script { - pub fn create_panel(&mut self, msg: Vec) -> anyhow::Result { + pub fn create_panel(&mut self, protocol: &str, msg: Vec) -> anyhow::Result { let id = PanelId(self.next_panel); self.next_panel += 1; - let userdata = self.instance.bind_panel(id, msg); + let userdata = self.instance.bind_panel(id, protocol, msg); Ok(Panel { instance: self.instance.clone(), id,