streamduck_core/modules/
mod.rs

1mod folders;
2
3/// Definitions for UI controls for components
4pub mod components;
5/// Definition for event enumeration
6pub mod events;
7pub mod plugins;
8pub mod core_module;
9
10use std::collections::HashMap;
11use std::hash::Hasher;
12use std::sync::Arc;
13
14use crate::core::button::{Button};
15use crate::modules::components::{ComponentDefinition, UIPathValue, UIValue};
16use crate::modules::events::{SDCoreEvent, SDGlobalEvent};
17use crate::modules::folders::FolderModule;
18
19use serde::{Deserialize, Serialize};
20
21use image::DynamicImage;
22use tokio::sync::{RwLock, RwLockReadGuard};
23use crate::core::manager::CoreManager;
24use crate::core::{check_feature_list_for_feature, CoreHandle, UniqueButton};
25use crate::modules::core_module::CoreModule;
26use crate::SocketManager;
27use crate::util::{add_array_function, change_from_path, convert_value_to_path, remove_array_function, set_value_function};
28
29/// Manages modules
30#[derive(Default)]
31pub struct ModuleManager {
32    // Using a bunch of various maps to move performance cost to adding module, so getting info is as costless as possible
33
34    module_map: RwLock<HashMap<String, UniqueSDModule>>,
35    module_component_map: RwLock<HashMap<String, HashMap<String, ComponentDefinition>>>,
36    component_map: RwLock<HashMap<String, (ComponentDefinition, UniqueSDModule)>>,
37    component_listener_map: RwLock<HashMap<String, Vec<UniqueSDModule>>>,
38
39    /// Separate list of modules that can render things
40    rendering_modules: RwLock<HashMap<String, HashMap<String, UniqueSDModule>>>,
41}
42
43impl ModuleManager {
44    /// Creates new module manager, used in daemon for loading plugins and base modules
45    pub fn new() -> Arc<ModuleManager> {
46        Arc::new(ModuleManager::default())
47    }
48
49    /// Adds a new module to be used with core
50    pub async fn add_module(&self, module: UniqueSDModule) {
51        let module_name = module.name();
52
53        // Adding to module map
54        let mut module_map = self.module_map.write().await;
55        module_map.insert(module_name.clone(), module.clone());
56        drop(module_map);
57
58        // Adding to module component map
59        let mut module_component_map = self.module_component_map.write().await;
60        for (component, definition) in module.components() {
61            if let Some(component_map) = module_component_map.get_mut(&module_name) {
62                component_map.insert(component, definition);
63            } else {
64                module_component_map.insert(module_name.clone(), {
65                    let mut map = HashMap::new();
66                    map.insert(component, definition);
67                    map
68                });
69            }
70        }
71        drop(module_component_map);
72
73        // Adding to component to module map
74        let mut component_map = self.component_map.write().await;
75        for (component, definition) in module.components() {
76            component_map.insert(component, (definition, module.clone()));
77        }
78        drop(component_map);
79
80        // Adding to component listener map
81        let mut component_listener_map = self.component_listener_map.write().await;
82        for listens_for in module.listening_for() {
83            if let Some(array) = component_listener_map.get_mut(&listens_for) {
84                array.push(module.clone());
85            } else {
86                component_listener_map.insert(listens_for, vec![module.clone()]);
87            }
88        }
89        drop(component_listener_map);
90
91        // Adding rendering modules to rendering map
92        let mut rendering_modules = self.rendering_modules.write().await;
93        if check_feature_list_for_feature(&module.metadata().used_features, "rendering") {
94            for component in module.listening_for() {
95                if let Some(map) = rendering_modules.get_mut(&component) {
96                    map.insert(module.name(), module.clone());
97                } else {
98                    rendering_modules.insert(component, {
99                        let mut map = HashMap::new();
100
101                        map.insert(module.name(), module.clone());
102
103                        map
104                    });
105                }
106            }
107        }
108        drop(rendering_modules);
109    }
110
111    /// Attempts to get module with specified name
112    pub async fn get_module(&self, name: &str) -> Option<UniqueSDModule> {
113        self.get_modules().await.get(name).cloned()
114    }
115
116    /// Returns all modules in map format
117    pub async fn get_modules(&self) -> HashMap<String, UniqueSDModule> {
118        self.module_map.read().await.clone()
119    }
120
121    /// Returns all modules in vector format
122    pub async fn get_module_list(&self) -> Vec<UniqueSDModule> {
123        self.module_map.read().await.values().cloned().collect()
124    }
125
126    /// Returns modules from names provided if they exist
127    pub async fn get_modules_from_list(&self, list: &[String]) -> Vec<UniqueSDModule> {
128        let module_map = self.get_modules().await;
129
130        let mut modules = vec![];
131
132        for item in list {
133            if let Some(module) = module_map.get(item) {
134                modules.push(module.clone())
135            }
136        }
137
138        modules
139    }
140
141    /// Retrieves modules that are listening to a specified component
142    pub async fn get_modules_for_component(&self, component: &str) -> Vec<UniqueSDModule> {
143        let handle = self.component_listener_map.read().await;
144
145        if let Some(modules) = handle.get(component) {
146            modules.clone()
147        } else {
148            vec![]
149        }
150    }
151
152    /// Retrieves modules that have added specified components
153    pub async fn get_modules_for_declared_components(&self, components: &[String]) -> Vec<UniqueSDModule> {
154        let handle = self.component_map.read().await;
155
156        let mut shared_modules = vec![];
157
158        for component in components {
159            if let Some((_, module)) = handle.get(component) {
160                shared_modules.push(module.clone());
161            }
162        }
163
164        shared_modules.sort_by(|a, b| a.name().cmp(&b.name()));
165        shared_modules.dedup_by(|a, b| a.name() == b.name());
166
167        shared_modules
168    }
169
170    /// Retrieves modules that are listening to specified components
171    pub async fn get_modules_for_components(&self, components: &[String]) -> Vec<UniqueSDModule> {
172        let handle = self.component_listener_map.read().await;
173
174        let mut shared_modules = vec![];
175
176        for component in components {
177            if let Some(modules) = handle.get(component) {
178                shared_modules.extend(modules.clone());
179            }
180        }
181
182        shared_modules.sort_by(|a, b| a.name().cmp(&b.name()));
183        shared_modules.dedup_by(|a, b| a.name() == b.name());
184
185        shared_modules
186    }
187
188    /// Retrieves components that module defined
189    pub async fn get_components_of_module(&self, module_name: &str) -> Option<HashMap<String, ComponentDefinition>> {
190        let handle = self.module_map.read().await;
191
192        if let Some(module) = handle.get(module_name) {
193            Some(module.components())
194        } else {
195            None
196        }
197    }
198
199    /// Retrieves all components that all modules define
200    pub async fn get_components(&self) -> HashMap<String, (ComponentDefinition, UniqueSDModule)> {
201        self.component_map.read().await.clone()
202    }
203
204    /// Retrieves all components that all modules define, but in module to component map format
205    pub async fn get_module_component_map(&self) -> HashMap<String, HashMap<String, ComponentDefinition>> {
206        self.module_component_map.read().await.clone()
207    }
208
209    /// Retrieves all modules that can render things
210    pub async fn get_rendering_module_map(&self) -> HashMap<String, HashMap<String, UniqueSDModule>> {
211        self.rendering_modules.read().await.clone()
212    }
213
214    /// Retrieves all modules that should be able to render according to list of component names
215    pub async fn get_modules_for_rendering(&self, names: &Vec<String>) -> HashMap<String, UniqueSDModule> {
216        let rendering_map = self.rendering_modules.read().await;
217
218        let mut map = HashMap::new();
219
220        for name in names {
221            if let Some(modules) = rendering_map.get(name) {
222                map.extend(modules.clone())
223            }
224        }
225
226        map
227    }
228
229
230    /// Retrieves component if it exists
231    pub async fn get_component(&self, component_name: &str) -> Option<(ComponentDefinition, UniqueSDModule)> {
232        self.component_map.read().await.get(component_name).cloned()
233    }
234
235    /// Returns module map read lock
236    pub async fn read_module_map(&self) -> RwLockReadGuard<'_, HashMap<String, UniqueSDModule>> {
237        self.module_map.read().await
238    }
239
240    /// Returns component map read lock
241    pub async fn read_component_map(&self) -> RwLockReadGuard<'_, HashMap<String, (ComponentDefinition, UniqueSDModule)>> {
242        self.component_map.read().await
243    }
244
245    /// Returns module component map read lock
246    pub async fn read_module_component_map(&self) -> RwLockReadGuard<'_, HashMap<String, HashMap<String, ComponentDefinition>>> {
247        self.module_component_map.read().await
248    }
249
250    /// Returns component listener map read lock
251    pub async fn read_component_listener_map(&self) -> RwLockReadGuard<'_, HashMap<String, Vec<UniqueSDModule>>> {
252        self.component_listener_map.read().await
253    }
254
255    /// Returns rendering modules map read lock
256    pub async fn read_rendering_modules_map(&self) -> RwLockReadGuard<'_, HashMap<String, HashMap<String, UniqueSDModule>>> {
257        self.rendering_modules.read().await
258    }
259
260    /// Sends global event to all modules, spawns a separate thread to do it, so doesn't block current thread
261    pub async fn send_global_event_to_modules(&self, event: SDGlobalEvent) {
262        send_global_event_to_modules(event, self.get_module_list().await.into_iter());
263    }
264}
265
266/// Loads built-in modules into the module manager
267pub async fn load_base_modules(module_manager: Arc<ModuleManager>, socket_manager: Arc<SocketManager>) {
268    module_manager.add_module(Arc::new(CoreModule { socket_manager })).await;
269    module_manager.add_module(Arc::new(FolderModule::default())).await;
270}
271
272/// Reference counted module object
273pub type UniqueSDModule = Arc<dyn SDModule>;
274
275/// Module trait
276#[allow(unused)]
277#[async_trait]
278pub trait SDModule: Send + Sync {
279    // Module data
280    /// Module name
281    fn name(&self) -> String;
282
283    // Components
284    /// Definition for components that module will be providing
285    fn components(&self) -> HashMap<String, ComponentDefinition>;
286
287    /// Method for adding components onto buttons
288    async fn add_component(&self, core: CoreHandle, button: &mut Button, name: &str);
289
290    /// Method for removing components from buttons
291    async fn remove_component(&self, core: CoreHandle, button: &mut Button, name: &str);
292
293    /// Method for handling pasting components of plugin, can be used for any additional handling
294    async fn paste_component(&self, core: CoreHandle, reference_button: &Button, new_button: &mut Button);
295
296    /// Method for letting core know what values component currently has
297    async fn component_values(&self, core: CoreHandle, button: &Button, name: &str) -> Vec<UIValue>;
298
299    /// Method for setting values on components
300    async fn set_component_value(&self, core: CoreHandle, button: &mut Button, name: &str, value: Vec<UIValue>);
301
302    /// Specifies which components the module will be receiving events for
303    fn listening_for(&self) -> Vec<String>;
304
305    /// Current settings state of the plugin
306    async fn settings(&self, core_manager: Arc<CoreManager>) -> Vec<UIValue> { vec![] }
307
308    /// Method for updating plugin settings from UI
309    async fn set_setting(&self, core_manager: Arc<CoreManager>, value: Vec<UIValue>) { }
310
311    /// Method for handling global events, add GLOBAL_EVENTS feature to the plugin metadata to receive global events
312    async fn global_event(&self, event: SDGlobalEvent) {}
313
314    /// Method for handling core events, add CORE_EVENTS feature to the plugin metadata to receive core events
315    async fn event(&self, core: CoreHandle, event: SDCoreEvent) {}
316
317    /// Method renderer will run for rendering additional information on a button if RENDERING feature was specified
318    async fn render(&self, core: CoreHandle, button: &UniqueButton, frame: &mut DynamicImage) {}
319
320    /// Method for telling renderer if anything changed
321    ///
322    /// Changing state of the hash in anyway will cause renderer to either rerender, or use previous cache.
323    /// This method will also called very frequently, so keep code in here fast
324    fn render_hash(&self, core: CoreHandle, button: &UniqueButton, hash: &mut Box<dyn Hasher>) {}
325
326    /// Metadata of the module, auto-implemented for plugins from plugin metadata
327    fn metadata(&self) -> PluginMetadata {
328        let mut meta = PluginMetadata::default();
329
330        meta.name = self.name();
331
332        meta
333    }
334}
335
336/// Keeps relevant information about plugins
337#[derive(Serialize, Deserialize, Clone)]
338pub struct PluginMetadata {
339    /// Name of the plugin
340    pub name: String,
341    /// Author of the plugin
342    pub author: String,
343    /// Description of the plugin
344    pub description: String,
345    /// Version of the plugin
346    pub version: String,
347    /// Used features of the plugin, used to determine if plugin is compatible with different software versions, see [crate::versions]
348    pub used_features: Vec<(String, String)>
349}
350
351impl PluginMetadata {
352    /// Lets you create plugin metadata without having to bother with creating strings for each property
353    pub fn from_literals(name: &str, author: &str, description: &str, version: &str, used_features: &[(&str, &str)]) -> PluginMetadata {
354        PluginMetadata {
355            name: name.to_string(),
356            author: author.to_string(),
357            description: description.to_string(),
358            version: version.to_string(),
359            used_features: features_to_vec(used_features)
360        }
361    }
362}
363
364/// Retrieves module settings in array of UIPathValue
365pub async fn get_module_settings(core_manager: Arc<CoreManager>, module: &UniqueSDModule) -> Vec<UIPathValue> {
366    module.settings(core_manager).await
367        .into_iter()
368        .map(|x| convert_value_to_path(x, ""))
369        .collect()
370}
371
372/// Adds new element into module setting's array
373pub async fn add_element_module_setting(core_manager: Arc<CoreManager>, module: &UniqueSDModule, path: &str) -> bool {
374    let (changes, success) = change_from_path(path, module.settings(core_manager.clone()).await, &add_array_function(), false);
375
376    if success {
377        if !changes.is_empty() {
378            module.set_setting(core_manager, changes).await;
379            true
380        } else {
381            false
382        }
383    } else {
384        false
385    }
386}
387
388/// Removes an element from module setting's array
389pub async fn remove_element_module_setting(core_manager: Arc<CoreManager>, module: &UniqueSDModule, path: &str, index: usize) -> bool {
390    let (changes, success) = change_from_path(path, module.settings(core_manager.clone()).await, &remove_array_function(index), false);
391
392    if success {
393        if !changes.is_empty() {
394            module.set_setting(core_manager, changes).await;
395            true
396        } else {
397            false
398        }
399    } else {
400        false
401    }
402}
403
404/// Sets value into module's setting
405pub async fn set_module_setting(core_manager: Arc<CoreManager>, module: &UniqueSDModule, value: UIPathValue) -> bool {
406    let (changes, success) = change_from_path(&value.path, module.settings(core_manager.clone()).await, &set_value_function(value.clone()), false);
407
408    if success {
409        if !changes.is_empty() {
410            module.set_setting(core_manager, changes).await;
411            true
412        } else {
413            false
414        }
415    } else {
416        false
417    }
418}
419
420/// Sends global event to all modules, spawns a separate thread to do it, so doesn't block current thread
421fn send_global_event_to_modules<T: Iterator<Item=UniqueSDModule> + Send + 'static>(event: SDGlobalEvent, modules: T) {
422    modules.for_each(|x| {
423        let task_event = event.clone();
424        tokio::spawn(async move {
425            x.global_event(task_event).await
426        });
427    });
428}
429
430/// Converts features slice into Vec
431pub fn features_to_vec(features: &[(&str, &str)]) -> Vec<(String, String)> {
432    features.iter().map(|(n, v)| (n.to_string(), v.to_string())).collect()
433}
434
435impl Default for PluginMetadata {
436    fn default() -> Self {
437        PluginMetadata::from_literals(
438            "unspecified",
439            "unspecified",
440            "unspecified",
441            "unspecified",
442            &[]
443        )
444    }
445}