mirror of
https://codeberg.org/Fl1tzi/microdeck.git
synced 2024-05-08 14:40:44 +00:00
implement module registry instead of pattern matching solution
This commit is contained in:
parent
8bed8a6fa9
commit
4536e0a8cd
|
@ -20,3 +20,4 @@ tracing = "0.1"
|
|||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
font-loader = "0.11.0"
|
||||
clru = "0.6.1"
|
||||
once_cell = "1.19.0"
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
config::{Button, ConfigError, DeviceConfig, Space},
|
||||
modules::{retrieve_module_from_name, start_module, HostEvent},
|
||||
modules::{start_module, HostEvent, MODULE_REGISTRY},
|
||||
unwrap_or_error,
|
||||
};
|
||||
use clru::CLruCache;
|
||||
|
@ -141,7 +141,7 @@ impl Device {
|
|||
.as_ref()
|
||||
.expect("Runtime has to be created before module can be spawned");
|
||||
let (module_sender, module_receiver) = mpsc::channel(4);
|
||||
if let Some(module) = retrieve_module_from_name(&btn.module) {
|
||||
if let Some(module) = MODULE_REGISTRY.get_module(&btn.module) {
|
||||
{
|
||||
// initialize the module
|
||||
let ser = self.serial.clone();
|
||||
|
@ -150,7 +150,7 @@ impl Device {
|
|||
let image_cache = self.image_cache.clone();
|
||||
|
||||
runtime.spawn(async move {
|
||||
start_module(ser, b, module, dev, module_receiver, image_cache).await
|
||||
start_module(ser, b, *module, dev, module_receiver, image_cache).await
|
||||
});
|
||||
}
|
||||
// if the receiver already dropped the listener then just directly insert none.
|
||||
|
|
|
@ -8,7 +8,6 @@ use std::{
|
|||
collections::HashMap,
|
||||
process::exit,
|
||||
sync::{Arc, Mutex, OnceLock},
|
||||
thread,
|
||||
time::Duration,
|
||||
};
|
||||
use tracing::{debug, error, info, trace, warn};
|
||||
|
|
|
@ -17,6 +17,8 @@ use ::image::DynamicImage;
|
|||
use async_trait::async_trait;
|
||||
pub use deck_driver as streamdeck;
|
||||
use futures_util::Future;
|
||||
use once_cell::sync::Lazy;
|
||||
use std::collections::HashMap;
|
||||
use std::{error::Error, pin::Pin, sync::Arc};
|
||||
use streamdeck::info::ImageFormat;
|
||||
use streamdeck::info::Kind;
|
||||
|
@ -25,6 +27,8 @@ use streamdeck::StreamDeckError;
|
|||
use tokio::sync::{mpsc, Mutex};
|
||||
use tracing::{debug, error, trace};
|
||||
|
||||
pub static MODULE_REGISTRY: Lazy<ModuleRegistry> = Lazy::new(|| ModuleRegistry::default());
|
||||
|
||||
/// Events that are coming from the host
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum HostEvent {
|
||||
|
@ -39,12 +43,34 @@ pub type ModuleFuture =
|
|||
Pin<Box<dyn Future<Output = Result<ModuleObject, ButtonConfigError>> + Send>>;
|
||||
pub type ModuleInitFunction = fn(Arc<Button>, ModuleCache) -> ModuleFuture;
|
||||
|
||||
pub fn retrieve_module_from_name(name: &str) -> Option<ModuleInitFunction> {
|
||||
match name {
|
||||
"space" => Some(Space::new as ModuleInitFunction),
|
||||
"counter" => Some(Counter::new as ModuleInitFunction),
|
||||
"image" => Some(Image::new as ModuleInitFunction),
|
||||
_ => None,
|
||||
pub type ModuleMap = HashMap<&'static str, ModuleInitFunction>;
|
||||
|
||||
/// Registry of available modules
|
||||
pub struct ModuleRegistry {
|
||||
modules: ModuleMap,
|
||||
}
|
||||
|
||||
impl Default for ModuleRegistry {
|
||||
fn default() -> Self {
|
||||
let mut modules = ModuleMap::new();
|
||||
modules.insert("space", Space::new as ModuleInitFunction);
|
||||
modules.insert("image", Image::new as ModuleInitFunction);
|
||||
modules.insert("counter", Counter::new as ModuleInitFunction);
|
||||
ModuleRegistry { modules }
|
||||
}
|
||||
}
|
||||
|
||||
impl ModuleRegistry {
|
||||
/// Retrieve a module from the registry
|
||||
pub fn get_module(&self, name: &str) -> Option<&ModuleInitFunction> {
|
||||
self.modules.get(name)
|
||||
}
|
||||
|
||||
// TODO: Idk if the &&str will be fine in the future
|
||||
/// List all available modules
|
||||
#[allow(dead_code)]
|
||||
pub fn list_modules(&self) -> Vec<&&str> {
|
||||
self.modules.keys().collect()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,9 +93,10 @@ pub async fn start_module(
|
|||
);
|
||||
let da = DeviceAccess::new(device, button.index).await;
|
||||
|
||||
// run init first
|
||||
// init
|
||||
//
|
||||
// panic should be prevented by the config being checked before running
|
||||
// This function should be called after the config was checked,
|
||||
// otherwise it will panic and the module wont be started.
|
||||
let mut module = match module_init_function(button, mc).await {
|
||||
Ok(m) => m,
|
||||
Err(e) => panic!("{}", e),
|
||||
|
@ -198,6 +225,9 @@ pub trait Module: Sync + Send {
|
|||
/// Function for validating configuration and creating module instance. Every time the config
|
||||
/// is checked this function gets called. It therefore should validate the most efficient
|
||||
/// things first.
|
||||
///
|
||||
/// This function should **not** panic as the panic will not be catched and therefore would be
|
||||
/// not noticed.
|
||||
async fn new(
|
||||
config: Arc<Button>,
|
||||
mut cache: ModuleCache,
|
||||
|
@ -206,6 +236,8 @@ pub trait Module: Sync + Send {
|
|||
Self: Sized;
|
||||
/// Function for actually running the module and interacting with the device. Errors that
|
||||
/// happen here should be mostly prevented.
|
||||
///
|
||||
/// TODO: The return error is not sent anywhere and is just a panic
|
||||
async fn run(
|
||||
&mut self,
|
||||
device: DeviceAccess,
|
||||
|
|
Loading…
Reference in a new issue