winisland_plugin_api/
lib.rs1use std::ffi::c_char;
2
3pub type PluginHandle = *mut std::ffi::c_void;
4
5#[cfg(feature = "packager")]
6pub mod packager;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum PluginType {
10 Content = 1,
11 Theme = 2,
12 Shortcut = 3,
13}
14
15impl PluginType {
16 pub fn from_u32(v: u32) -> Option<Self> {
17 match v {
18 1 => Some(Self::Content),
19 2 => Some(Self::Theme),
20 3 => Some(Self::Shortcut),
21 _ => None,
22 }
23 }
24}
25
26#[repr(C)]
27pub struct PluginResultC {
28 pub ok: bool,
29 pub error: [u8; 256],
30}
31
32impl PluginResultC {
33 pub fn ok() -> Self {
34 Self {
35 ok: true,
36 error: [0u8; 256],
37 }
38 }
39
40 pub fn err(msg: &str) -> Self {
41 let mut error = [0u8; 256];
42 let bytes = msg.as_bytes();
43 let len = bytes.len().min(255);
44 error[..len].copy_from_slice(&bytes[..len]);
45 Self { ok: false, error }
46 }
47
48 pub fn into_result(self) -> Result<(), String> {
49 if self.ok {
50 Ok(())
51 } else {
52 let end = self.error.iter().position(|&b| b == 0).unwrap_or(256);
53 Err(String::from_utf8_lossy(&self.error[..end]).into_owned())
54 }
55 }
56}
57
58#[repr(C)]
59pub struct PluginMetadataC {
60 pub id: [u8; 64],
61 pub name: [u8; 128],
62 pub version: [u8; 32],
63 pub author: [u8; 128],
64 pub description: [u8; 256],
65}
66
67#[repr(C)]
68pub struct IslandContentC {
69 pub tag: u32,
70 pub title: [u8; 256],
71 pub artist: [u8; 256],
72 pub cover_url: [u8; 512],
73 pub is_playing: bool,
74 pub message: [u8; 256],
75 pub label: [u8; 128],
76 pub value: [u8; 128],
77}
78
79pub const ISLAND_CONTENT_TAG_MUSIC: u32 = 1;
80pub const ISLAND_CONTENT_TAG_NOTIFICATION: u32 = 2;
81pub const ISLAND_CONTENT_TAG_STATUS: u32 = 3;
82
83#[repr(C)]
84pub struct ThemeColorsC {
85 pub primary: [u8; 4],
86 pub secondary: [u8; 4],
87 pub background: [u8; 4],
88 pub text: [u8; 4],
89 pub border: [u8; 4],
90}
91
92#[repr(C)]
93pub struct AnimationConfigC {
94 pub expand_duration_ms: u32,
95 pub collapse_duration_ms: u32,
96 pub bounce_intensity: f32,
97}
98
99#[repr(C)]
100pub struct ShortcutC {
101 pub id: [u8; 64],
102 pub name: [u8; 128],
103 pub description: [u8; 256],
104 pub icon: [u8; 256],
105 pub hotkey: [u8; 32],
106}
107
108#[repr(C)]
109pub struct PluginVTable {
110 pub on_load: unsafe extern "C" fn(PluginHandle) -> PluginResultC,
111 pub on_unload: unsafe extern "C" fn(PluginHandle) -> PluginResultC,
112 pub destroy: unsafe extern "C" fn(PluginHandle),
113 pub get_content: Option<unsafe extern "C" fn(PluginHandle) -> IslandContentC>,
114 pub on_click: Option<unsafe extern "C" fn(PluginHandle)>,
115 pub on_expanded: Option<unsafe extern "C" fn(PluginHandle, bool)>,
116 pub supports_expand: Option<unsafe extern "C" fn(PluginHandle) -> bool>,
117 pub get_colors: Option<unsafe extern "C" fn(PluginHandle) -> ThemeColorsC>,
118 pub get_animations: Option<unsafe extern "C" fn(PluginHandle) -> AnimationConfigC>,
119 pub get_shortcuts_count: Option<unsafe extern "C" fn(PluginHandle) -> u32>,
120 pub get_shortcut_at: Option<unsafe extern "C" fn(PluginHandle, i: u32, out: *mut ShortcutC)>,
121 pub execute_shortcut:
122 Option<unsafe extern "C" fn(PluginHandle, id: *const c_char) -> PluginResultC>,
123}
124
125#[repr(C)]
126pub struct PluginInstanceC {
127 pub handle: PluginHandle,
128 pub metadata: PluginMetadataC,
129 pub vtable: *const PluginVTable,
130 pub plugin_type: u32,
131}
132
133pub type PluginGetInstanceFn = unsafe extern "C" fn() -> PluginInstanceC;