This commit is contained in:
Moritz Ruth 2024-03-06 22:45:24 +01:00
parent 2fce4312eb
commit 2059555174
Signed by: moritzruth
GPG key ID: C9BBAB79405EE56D
5 changed files with 142 additions and 1 deletions

13
Cargo.lock generated
View file

@ -624,6 +624,19 @@ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
[[package]]
name = "execute"
version = "0.1.0"
dependencies = [
"clap",
"color-eyre",
"deckster_mode",
"env_logger",
"log",
"serde",
"tokio",
]
[[package]] [[package]]
name = "eyre" name = "eyre"
version = "0.6.11" version = "0.6.11"

View file

@ -59,3 +59,10 @@ config.entity_id = "light.moritz_zimmer_stehlampe"
config.style.on.icon = "@ph/computer-tower[color=#58fc11]" config.style.on.icon = "@ph/computer-tower[color=#58fc11]"
config.style.disconnected.icon = "@ph/computer-tower[alpha=0.2]" config.style.disconnected.icon = "@ph/computer-tower[alpha=0.2]"
config.disconnected_state = "disconnected" config.disconnected_state = "disconnected"
[keys.4x1]
label = "9"
handler = "execute"
config.program = "wtype"
config.args = ["9"]

View file

@ -0,0 +1,13 @@
[package]
name = "execute"
version = "0.1.0"
edition = "2021"
[dependencies]
deckster_mode = { path = "../../crates/deckster_mode" }
clap = { version = "4.4.18", features = ["derive"] }
color-eyre = "0.6.2"
serde = { version = "1.0.196", features = ["derive"] }
env_logger = "0.11.1"
log = "0.4.20"
tokio = { version = "1.35.1", features = ["macros", "parking_lot", "rt", "process", "sync"] }

View file

@ -0,0 +1,82 @@
use deckster_mode::shared::handler_communication::{HandlerEvent, HandlerInitializationError, InitialHandlerMessage, KeyEvent};
use deckster_mode::shared::path::KeyPath;
use deckster_mode::DecksterHandler;
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
use std::thread;
use tokio::process::Command;
use tokio::sync::broadcast;
use tokio::task::LocalSet;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct KeyConfig {
program: Box<str>,
#[serde(default)]
args: Box<[String]>,
}
pub struct Handler {
events_sender: broadcast::Sender<(KeyPath, KeyEvent)>,
}
impl Handler {
pub fn new(data: InitialHandlerMessage<(), KeyConfig, ()>) -> Result<Self, HandlerInitializationError> {
let (events_sender, _) = broadcast::channel::<(KeyPath, KeyEvent)>(5);
thread::spawn({
let events_sender = events_sender.clone();
move || {
let runtime = tokio::runtime::Builder::new_current_thread().enable_io().build().unwrap();
let task_set = LocalSet::new();
for (path, config) in data.key_configs {
task_set.spawn_local(manage_key(events_sender.subscribe(), path, config));
}
runtime.block_on(task_set)
}
});
Ok(Handler { events_sender })
}
}
impl DecksterHandler for Handler {
fn handle(&mut self, event: HandlerEvent) {
if let HandlerEvent::Key { path, event } = event {
self.events_sender.send((path, event)).unwrap();
}
}
}
pub async fn manage_key(mut events: broadcast::Receiver<(KeyPath, KeyEvent)>, path: KeyPath, config: KeyConfig) {
let mut command = Command::new(config.program.as_ref());
let command = command.args(config.args.clone().iter());
while let Ok((p, event)) = events.recv().await {
if p != path {
continue;
}
if event == KeyEvent::Press {
tokio::spawn({
let future = command.status();
let path = path.clone();
async move {
let result = future.await;
match result {
Ok(status) => {
if !status.success() {
log::error!("Process failed with status (key at {}): {}", &path, status)
}
}
Err(error) => log::error!("Failed to spawn process (key at {}): {}", &path, error),
}
}
});
}
}
}

View file

@ -0,0 +1,26 @@
use clap::Parser;
use color_eyre::Result;
use crate::handler::Handler;
mod handler;
#[derive(Debug, Parser)]
#[command(name = "execute")]
enum CliCommand {
#[command(name = "deckster-run", hide = true)]
Run,
}
fn main() -> Result<()> {
env_logger::init();
let command = CliCommand::parse();
match command {
CliCommand::Run => {
deckster_mode::run(Handler::new)?;
}
}
Ok(())
}