1use std::collections::HashMap;
4use std::ffi::OsStr;
5use std::fs;
6use std::hash::Hasher;
7use std::path::Path;
8use std::sync::{Arc, Mutex};
9use dlopen::Error;
10use crate::modules::{ModuleManager, PluginMetadata, SDModule, UniqueSDModule};
11use dlopen::wrapper::{Container, WrapperApi};
12use dlopen_derive::WrapperApi;
13use image::DynamicImage;
14use tokio::task::{JoinError, spawn_blocking};
15use crate::core::button::Button;
16use crate::core::manager::CoreManager;
17use crate::core::{check_feature_list_for_feature, CoreHandle, UniqueButton, warn_for_feature};
18use crate::modules::components::{ComponentDefinition, UIValue};
19use crate::modules::events::{SDCoreEvent, SDGlobalEvent};
20use crate::{Config, RenderingManager};
21use crate::socket::{SocketManager, UniqueSocketListener};
22use crate::thread::rendering::custom::UniqueRenderer;
23use crate::versions::SUPPORTED_FEATURES;
24
25#[derive(WrapperApi)]
26struct PluginApi {
27 get_metadata: extern fn() -> PluginMetadata,
28 register: fn(socket_manager: Arc<PluginSocketManager>, render_manager: Arc<PluginRenderingManager>, module_manager: Arc<PluginModuleManager>),
29}
30
31#[allow(dead_code)]
32struct PluginProxy {
33 pub wrapper: Arc<Container<PluginApi>>,
34 pub metadata: PluginMetadata,
35 pub plugin: UniqueSDModule
36}
37
38#[async_trait]
39impl SDModule for PluginProxy {
40 fn name(&self) -> String {
41 self.plugin.name()
42 }
43
44 fn components(&self) -> HashMap<String, ComponentDefinition> {
45 self.plugin.components()
46 }
47
48 async fn add_component(&self, core: CoreHandle, button: &mut Button, name: &str) {
49 self.plugin.add_component(core, button, name).await
50 }
51
52 async fn remove_component(&self, core: CoreHandle, button: &mut Button, name: &str) {
53 self.plugin.remove_component(core, button, name).await
54 }
55
56 async fn paste_component(&self, core: CoreHandle, reference_button: &Button, new_button: &mut Button) {
57 self.plugin.paste_component(core, reference_button, new_button).await
58 }
59
60 async fn component_values(&self, core: CoreHandle, button: &Button, name: &str) -> Vec<UIValue> {
61 self.plugin.component_values(core, button, name).await
62 }
63
64 async fn set_component_value(&self, core: CoreHandle, button: &mut Button, name: &str, value: Vec<UIValue>) {
65 self.plugin.set_component_value(core, button, name, value).await
66 }
67
68 fn listening_for(&self) -> Vec<String> {
69 self.plugin.listening_for()
70 }
71
72 async fn settings(&self, core: Arc<CoreManager>) -> Vec<UIValue> {
73 self.plugin.settings(core).await
74 }
75
76 async fn set_setting(&self, core: Arc<CoreManager>, value: Vec<UIValue>) {
77 self.plugin.set_setting(core, value).await
78 }
79
80 async fn global_event(&self, event: SDGlobalEvent) {
81 if check_feature_list_for_feature(&self.metadata.used_features, "global_events") {
82 self.plugin.global_event(event).await
83 }
84 }
85
86 async fn event(&self, core: CoreHandle, event: SDCoreEvent) {
87 if core.check_for_feature("core_events") {
88 self.plugin.event(core, event).await
89 }
90 }
91
92 async fn render(&self, core: CoreHandle, button: &UniqueButton, frame: &mut DynamicImage) {
93 if core.check_for_feature("rendering") {
94 self.plugin.render(core, button, frame).await
95 }
96 }
97
98 fn render_hash(&self, core: CoreHandle, button: &UniqueButton, hash: &mut Box<dyn Hasher>) {
99 if core.check_for_feature("rendering") {
100 self.plugin.render_hash(core, button, hash)
101 }
102 }
103
104 fn metadata(&self) -> PluginMetadata {
105 self.metadata.clone()
106 }
107}
108
109pub struct PluginSocketManager {
111 socket_manager: Arc<SocketManager>,
112
113 listeners: Arc<Mutex<Vec<UniqueSocketListener>>>
114}
115
116impl PluginSocketManager {
117 pub fn add_listener(&self, listener: UniqueSocketListener) {
119 self.listeners.lock().unwrap().push(listener);
120 }
121
122 async fn load_listeners(&self) -> Result<(), JoinError> {
123 let listeners = self.listeners.clone();
124 let listeners = spawn_blocking(move || listeners.lock().unwrap().clone()).await?;
125
126 for listener in listeners {
127 self.socket_manager.add_listener(listener).await;
128 }
129
130 Ok(())
131 }
132}
133
134pub struct PluginRenderingManager {
136 rendering_manager: Arc<RenderingManager>,
137
138 renderers: Arc<Mutex<Vec<UniqueRenderer>>>
139}
140
141impl PluginRenderingManager {
142 pub fn add_renderer(&self, renderer: UniqueRenderer) {
144 self.renderers.lock().unwrap().push(renderer);
145 }
146
147 async fn load_renderers(&self) -> Result<(), JoinError> {
148 let renderers = self.renderers.clone();
149 let renderers = spawn_blocking(move || renderers.lock().unwrap().clone()).await?;
150
151 for renderer in renderers {
152 self.rendering_manager.add_custom_renderer(renderer).await;
153 }
154
155 Ok(())
156 }
157}
158
159
160pub struct PluginModuleManager {
162 module_manager: Arc<ModuleManager>,
164 metadata: PluginMetadata,
165 wrapper: Arc<Container<PluginApi>>,
166
167 modules: Arc<Mutex<Vec<UniqueSDModule>>>,
169}
170
171impl PluginModuleManager {
172 pub fn add_module(&self, module: UniqueSDModule) {
174 self.modules.lock().unwrap().push(module);
175 }
176
177 async fn load_modules(&self) -> Result<(), PluginError> {
178 let modules = self.modules.clone();
179 let modules = spawn_blocking(move || modules.lock().unwrap().clone()).await?;
180
181 if modules.is_empty() {
182 return Err(PluginError::NoModulesFound);
183 }
184
185 for module in modules {
186 for component in module.components().keys() {
187 if self.module_manager.get_component(component).await.is_some() {
188 return Err(PluginError::ComponentConflict(module.name(), component.to_string()))
189 }
190 }
191
192 self.module_manager.add_module(Arc::new(PluginProxy {
193 wrapper: self.wrapper.clone(),
194 metadata: self.metadata.clone(),
195 plugin: module
196 })).await;
197 }
198
199 Ok(())
200 }
201}
202
203pub fn compare_plugin_versions(versions: &Vec<(String, String)>) -> Result<(), PluginError> {
205 let core_versions = SUPPORTED_FEATURES.clone().into_iter()
206 .map(|(n, v)| (*n, *v))
207 .collect::<HashMap<&str, &str>>();
208
209 for (name, version) in versions {
210 if let Some(software_version) = core_versions.get(name.as_str()) {
211 if software_version != version {
212 return Err(PluginError::WrongVersion(format!("{} {}", name, version), format!("{} {}", name, software_version)))
213 }
214 } else {
215 return Err(PluginError::TooNew(format!("{} {}", name, version)))
216 }
217 }
218
219 Ok(())
220}
221
222fn warn_about_essential_features(meta: &PluginMetadata) {
224 let name = &meta.name;
225 let features = &meta.used_features;
226
227 warn_for_feature(name, &features, "compiler_version");
228 warn_for_feature(name, &features, "plugin_api");
229 warn_for_feature(name, &features, "sdmodule_trait");
230}
231
232pub async fn load_plugin<T: AsRef<OsStr>>(config: Arc<Config>, module_manager: Arc<ModuleManager>, socket_manager: Arc<SocketManager>, render_manager: Arc<RenderingManager>, path: T) -> Result<(), PluginError> {
234 let wrapper: Container<PluginApi> = unsafe { Container::load(path) }?;
236
237 let wrapper = Arc::new(wrapper);
238
239 let metadata = wrapper.get_metadata();
241
242 if config.plugin_compatibility_checks() {
244 compare_plugin_versions(&metadata.used_features)?;
245 }
246
247 warn_about_essential_features(&metadata);
249
250 if module_manager.get_module(&metadata.name).await.is_none() {
252 let plugin_manager = Arc::new(PluginModuleManager {
253 module_manager,
254 metadata: metadata.clone(),
255 wrapper,
256 modules: Default::default()
257 });
258
259 let plugin_socket_manager = Arc::new(PluginSocketManager {
260 socket_manager,
261 listeners: Default::default()
262 });
263
264 let plugin_rendering_manager = Arc::new(PluginRenderingManager {
265 rendering_manager: render_manager,
266 renderers: Default::default()
267 });
268
269 plugin_manager.wrapper.register(plugin_socket_manager.clone(), plugin_rendering_manager.clone(), plugin_manager.clone());
271
272 plugin_manager.load_modules().await?;
273 plugin_socket_manager.load_listeners().await?;
274 plugin_rendering_manager.load_renderers().await?;
275
276 Ok(())
277 } else {
278 Err(PluginError::AlreadyExists(metadata.name))
279 }
280}
281
282pub async fn load_plugins_from_folder<T: AsRef<OsStr>>(config: Arc<Config>, module_manager: Arc<ModuleManager>, socket_manager: Arc<SocketManager>, render_manager: Arc<RenderingManager>, path: T) {
284 let path = Path::new(&path);
285 match fs::read_dir(path) {
286 Ok(read_dir) => {
287 for item in read_dir {
288 match item {
289 Ok(entry) => {
290 if entry.path().is_file() {
291 if let Some(file_name) = entry.path().file_name() {
292 log::info!("Loading plugin {:?}", file_name);
293 match load_plugin(config.clone(), module_manager.clone(), socket_manager.clone(), render_manager.clone(), entry.path()).await {
294 Err(err) => match err {
295 PluginError::LoadError(err) => log::error!("Failed to load plugin: {}", err),
296 PluginError::WrongVersion(plugin, software) => log::error!("Failed to load plugin: Plugin is using unsupported version of '{}', software's using '{}'", plugin, software),
297 PluginError::TooNew(version) => log::error!("Failed to load plugin: Software doesn't support '{}', try updating the software", version),
298 PluginError::AlreadyExists(name) => log::error!("Failed to load plugin: Module '{}' was already defined", name),
299 PluginError::ComponentConflict(name, component_name) => log::error!("Failed to load plugin: Module '{}' is declaring '{}' component, but it was already previously declared by other module", name, component_name),
300 PluginError::JoinError(err) => log::error!("Failed to load plugin: {}", err),
301 PluginError::NoModulesFound => log::error!("Failed to load plugin: No modules found")
302 },
303 _ => {}
304 }
305 }
306 }
307 }
308 Err(err) => log::error!("Failed to reach entry. {}", err),
309 }
310 }
311 }
312 Err(e) => {
313 if let std::io::ErrorKind::NotFound = e.kind() {
314 log::info!("Loaded no plugins, missing plugins folder")
315 } else {
316 log::error!("Plugins folder is unreachable: {:?}", path);
317 }
318 }
319 }
320}
321
322#[derive(Debug)]
324pub enum PluginError {
325 NoModulesFound,
327 LoadError(dlopen::Error),
329 WrongVersion(String, String),
331 TooNew(String),
333 AlreadyExists(String),
335 ComponentConflict(String, String),
337 JoinError(tokio::task::JoinError)
339}
340
341impl From<dlopen::Error> for PluginError {
342 fn from(err: Error) -> Self {
343 PluginError::LoadError(err)
344 }
345}
346
347impl From<tokio::task::JoinError> for PluginError {
348 fn from(err: JoinError) -> Self {
349 PluginError::JoinError(err)
350 }
351}