mirror of
https://codeberg.org/Fl1tzi/microdeck.git
synced 2024-05-19 19:20:20 +00:00
improved structure and logging
This commit is contained in:
parent
55bdf71f24
commit
74050ccb17
|
@ -19,4 +19,4 @@ imageproc = "0.23.0"
|
||||||
rusttype = "0.9.3"
|
rusttype = "0.9.3"
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||||
phf = { version = "0.11", features = ["macros"] }
|
lazy_static = "1.4.0"
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
```diff
|
```diff
|
||||||
- WORK IN PROGRESS
|
- WORK IN PROGRESS
|
||||||
```
|
|
||||||
|
|
||||||
# dach-decker
|
# dach-decker
|
||||||
|
|
||||||
|
|
44
src/main.rs
44
src/main.rs
|
@ -13,7 +13,7 @@ use tokio::sync::mpsc;
|
||||||
use tokio::sync::mpsc::error::TrySendError;
|
use tokio::sync::mpsc::error::TrySendError;
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
use tokio::task::JoinHandle;
|
use tokio::task::JoinHandle;
|
||||||
use tracing::{debug, error, info, trace, warn};
|
use tracing::{debug, error, info, trace, warn, info_span, Level};
|
||||||
mod modules;
|
mod modules;
|
||||||
use elgato_streamdeck as streamdeck;
|
use elgato_streamdeck as streamdeck;
|
||||||
use streamdeck::asynchronous::{AsyncStreamDeck, ButtonStateUpdate};
|
use streamdeck::asynchronous::{AsyncStreamDeck, ButtonStateUpdate};
|
||||||
|
@ -105,7 +105,16 @@ fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn start(config: Config, hid: HidApi, hw_devices: Vec<(streamdeck::info::Kind, String)>) {
|
pub async fn start(config: Config, hid: HidApi, hw_devices: Vec<(streamdeck::info::Kind, String)>) {
|
||||||
init_devices(config, hid, hw_devices).await;
|
let devices = init_devices(config, hid, hw_devices).await;
|
||||||
|
|
||||||
|
let mut handles: Vec<JoinHandle<()>> = Vec::new();
|
||||||
|
|
||||||
|
// start listeners
|
||||||
|
for device in devices {
|
||||||
|
handles.push(tokio::spawn(async move {
|
||||||
|
device.key_listener().await
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
tokio::time::sleep(Duration::from_secs(2000)).await;
|
tokio::time::sleep(Duration::from_secs(2000)).await;
|
||||||
|
@ -124,6 +133,7 @@ pub async fn send_to_channel(sender: mpsc::Sender<HostEvent>, event: HostEvent)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Handles everything related to a single device
|
||||||
pub struct DeviceManager {
|
pub struct DeviceManager {
|
||||||
modules: HashMap<u8, (Button, JoinHandle<()>, mpsc::Sender<HostEvent>)>,
|
modules: HashMap<u8, (Button, JoinHandle<()>, mpsc::Sender<HostEvent>)>,
|
||||||
device: Arc<AsyncStreamDeck>,
|
device: Arc<AsyncStreamDeck>,
|
||||||
|
@ -144,7 +154,6 @@ impl DeviceManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// stops all modules of the device
|
/// stops all modules of the device
|
||||||
#[tracing::instrument(skip_all, fields(serial = self.serial))]
|
|
||||||
fn shutdown(self) {
|
fn shutdown(self) {
|
||||||
for (index, (_, handle, _)) in self.modules {
|
for (index, (_, handle, _)) in self.modules {
|
||||||
trace!("Destroying module {}", index);
|
trace!("Destroying module {}", index);
|
||||||
|
@ -195,15 +204,17 @@ impl DeviceManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is the entry point for the application. This will check all devices for their config,
|
/// This is the entry point for the application. This will check all devices for their config,
|
||||||
/// start the bridges and the device button listeners.
|
/// start the modules and the device button listeners.
|
||||||
async fn init_devices(config: Config, hid: HidApi, devices: Vec<(streamdeck::info::Kind, String)>) {
|
async fn init_devices(config: Config, hid: HidApi, devices: Vec<(streamdeck::info::Kind, String)>) -> Vec<DeviceManager> {
|
||||||
// check if configuration is correct for device
|
// check if configuration is correct for device
|
||||||
if devices.len() == 0 {
|
if devices.len() == 0 {
|
||||||
error!("There are no Decks connected");
|
error!("There are no Decks connected");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
info!("There are {} Decks connected", devices.len());
|
info!("There are {} Decks connected", devices.len());
|
||||||
'outer: for device in devices {
|
let mut device_managers = Vec::new();
|
||||||
|
'device: for device in devices {
|
||||||
|
let _span_device = info_span!("device", serial = device.1).entered();
|
||||||
// no pedals are supported
|
// no pedals are supported
|
||||||
if !device.0.is_visual() {
|
if !device.0.is_visual() {
|
||||||
continue;
|
continue;
|
||||||
|
@ -213,12 +224,12 @@ async fn init_devices(config: Config, hid: HidApi, devices: Vec<(streamdeck::inf
|
||||||
// connect to deck or continue to next
|
// connect to deck or continue to next
|
||||||
let deck = match AsyncStreamDeck::connect(&hid, device.0, &device.1) {
|
let deck = match AsyncStreamDeck::connect(&hid, device.0, &device.1) {
|
||||||
Ok(deck) => {
|
Ok(deck) => {
|
||||||
info!("Successfully connected to {}", device.1);
|
info!("Successfully connected");
|
||||||
deck
|
deck
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("Cannot connect to Deck {}: {}", device.1, e);
|
error!("Cannot connect: {}", e);
|
||||||
continue 'outer;
|
continue 'device;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// set brightness
|
// set brightness
|
||||||
|
@ -227,15 +238,21 @@ async fn init_devices(config: Config, hid: HidApi, devices: Vec<(streamdeck::inf
|
||||||
deck.reset().await.unwrap();
|
deck.reset().await.unwrap();
|
||||||
// initialize buttons
|
// initialize buttons
|
||||||
let button_count = device.0.key_count();
|
let button_count = device.0.key_count();
|
||||||
|
// save button senders
|
||||||
let mut buttons_keys = HashMap::new();
|
let mut buttons_keys = HashMap::new();
|
||||||
for button in device_conf.buttons.clone().into_iter() {
|
for button in device_conf.buttons.clone().into_iter() {
|
||||||
|
let _span_button = info_span!("button", index=button.index).entered();
|
||||||
|
if buttons_keys.get(&button.index).is_some() {
|
||||||
|
warn!("The button is configured twice");
|
||||||
|
continue
|
||||||
|
}
|
||||||
// if the index of the button is higher than the button count
|
// if the index of the button is higher than the button count
|
||||||
if button_count < button.index {
|
if button_count < button.index {
|
||||||
warn!(
|
warn!(
|
||||||
"The button {} does not exist on Deck {}; skipping",
|
"The button {} does not exist on Deck {}; skipping",
|
||||||
button.index, device.1
|
button.index, device.1
|
||||||
);
|
);
|
||||||
continue 'outer;
|
continue 'device;
|
||||||
}
|
}
|
||||||
// create a channel for the module to receive device events
|
// create a channel for the module to receive device events
|
||||||
let (button_sender, button_receiver) = mpsc::channel(4);
|
let (button_sender, button_receiver) = mpsc::channel(4);
|
||||||
|
@ -254,15 +271,12 @@ async fn init_devices(config: Config, hid: HidApi, devices: Vec<(streamdeck::inf
|
||||||
warn!("The module \"{}\" does not exist.", button.module)
|
warn!("The module \"{}\" does not exist.", button.module)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let manager = DeviceManager::new(device.1, deck, buttons_keys).await;
|
device_managers.push(DeviceManager::new(device.1, deck, buttons_keys).await);
|
||||||
// start the device key listener
|
|
||||||
tokio::spawn(async move {
|
|
||||||
manager.key_listener().await;
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
info!("Deck {} is not configured; skipping", device.1);
|
info!("Deck {} is not configured; skipping", device.1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
device_managers
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn execute_sh(command: &str) {
|
pub async fn execute_sh(command: &str) {
|
||||||
|
|
|
@ -1,25 +1,33 @@
|
||||||
mod blank;
|
mod blank;
|
||||||
mod counter;
|
mod counter;
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::{error::Error, sync::Arc};
|
use std::{error::Error, sync::Arc};
|
||||||
|
|
||||||
use self::blank::Blank;
|
|
||||||
use self::counter::Counter;
|
use self::counter::Counter;
|
||||||
use crate::Button;
|
use crate::Button;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
pub use elgato_streamdeck as streamdeck;
|
pub use elgato_streamdeck as streamdeck;
|
||||||
use futures_util::Future;
|
use futures_util::Future;
|
||||||
use image::DynamicImage;
|
use image::DynamicImage;
|
||||||
use phf::phf_map;
|
|
||||||
pub use streamdeck::info::ImageFormat;
|
pub use streamdeck::info::ImageFormat;
|
||||||
use streamdeck::info::Kind;
|
use streamdeck::info::Kind;
|
||||||
use streamdeck::AsyncStreamDeck;
|
use streamdeck::AsyncStreamDeck;
|
||||||
pub use streamdeck::StreamDeckError;
|
pub use streamdeck::StreamDeckError;
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
|
use lazy_static::lazy_static;
|
||||||
use tracing::{debug, error, info};
|
use tracing::{debug, error, info};
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref MODULE_MAP: HashMap<&'static str, ModuleFunction> = {
|
||||||
|
let mut m = HashMap::new();
|
||||||
|
m.insert("counter", Counter::run as ModuleFunction);
|
||||||
|
m
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/// Events that are coming from the host
|
/// Events that are coming from the host
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub enum HostEvent {
|
pub enum HostEvent {
|
||||||
|
@ -27,22 +35,17 @@ pub enum HostEvent {
|
||||||
ButtonPressed,
|
ButtonPressed,
|
||||||
/// The button was released
|
/// The button was released
|
||||||
ButtonReleased,
|
ButtonReleased,
|
||||||
/// The channel was initialized and there were no events yet
|
|
||||||
Init,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ModuleFuture = Pin<Box<dyn Future<Output = Result<(), ReturnError>> + Send>>;
|
type ModuleFuture = Pin<Box<dyn Future<Output = Result<(), ReturnError>> + Send>>;
|
||||||
type ModuleFunction = fn(DeviceAccess, ChannelReceiver, Button) -> ModuleFuture;
|
type ModuleFunction = fn(DeviceAccess, ChannelReceiver, Button) -> ModuleFuture;
|
||||||
|
|
||||||
pub fn retrieve_module_from_name(name: String) -> Option<ModuleFunction> {
|
pub fn retrieve_module_from_name(name: String) -> Option<ModuleFunction> {
|
||||||
match name.as_str() {
|
MODULE_MAP.get(name.as_str()).copied()
|
||||||
"counter" => Some(Counter::run),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// starts a module
|
/// starts a module
|
||||||
#[tracing::instrument(skip_all, fields(device = serial, button = button.index, module = button.module))]
|
#[tracing::instrument(name = "module", skip_all, fields(serial = serial, button = button.index, module = button.module))]
|
||||||
pub async fn start_module(
|
pub async fn start_module(
|
||||||
// Just for logging purpose
|
// Just for logging purpose
|
||||||
serial: String,
|
serial: String,
|
||||||
|
|
Loading…
Reference in a new issue