mirror of
https://github.com/feschber/lan-mouse.git
synced 2026-03-07 20:09:59 +03:00
*breaking change* this changes the configuration syntax, allowing for an unlimited amount of configured clients. Also a first step towards enabling a "save config" feature.
139 lines
4.2 KiB
Rust
139 lines
4.2 KiB
Rust
use env_logger::Env;
|
|
use input_capture::InputCaptureError;
|
|
use input_emulation::InputEmulationError;
|
|
use lan_mouse::{
|
|
capture_test,
|
|
config::{self, Command, Config, ConfigError},
|
|
emulation_test,
|
|
service::{Service, ServiceError},
|
|
};
|
|
use lan_mouse_cli::CliError;
|
|
#[cfg(feature = "gtk")]
|
|
use lan_mouse_gtk::GtkError;
|
|
use lan_mouse_ipc::{IpcError, IpcListenerCreationError};
|
|
use std::{
|
|
future::Future,
|
|
io,
|
|
process::{self, Child},
|
|
};
|
|
use thiserror::Error;
|
|
use tokio::task::LocalSet;
|
|
|
|
#[derive(Debug, Error)]
|
|
enum LanMouseError {
|
|
#[error(transparent)]
|
|
Service(#[from] ServiceError),
|
|
#[error(transparent)]
|
|
IpcError(#[from] IpcError),
|
|
#[error(transparent)]
|
|
Config(#[from] ConfigError),
|
|
#[error(transparent)]
|
|
Io(#[from] io::Error),
|
|
#[error(transparent)]
|
|
Capture(#[from] InputCaptureError),
|
|
#[error(transparent)]
|
|
Emulation(#[from] InputEmulationError),
|
|
#[cfg(feature = "gtk")]
|
|
#[error(transparent)]
|
|
Gtk(#[from] GtkError),
|
|
#[error(transparent)]
|
|
Cli(#[from] CliError),
|
|
}
|
|
|
|
fn main() {
|
|
// init logging
|
|
let env = Env::default().filter_or("LAN_MOUSE_LOG_LEVEL", "info");
|
|
env_logger::init_from_env(env);
|
|
|
|
if let Err(e) = run() {
|
|
log::error!("{e}");
|
|
process::exit(1);
|
|
}
|
|
}
|
|
|
|
fn run() -> Result<(), LanMouseError> {
|
|
let config = config::Config::new()?;
|
|
match config.command() {
|
|
Some(command) => match command {
|
|
Command::TestEmulation(args) => run_async(emulation_test::run(config, args))?,
|
|
Command::TestCapture(args) => run_async(capture_test::run(config, args))?,
|
|
Command::Cli(cli_args) => run_async(lan_mouse_cli::run(cli_args))?,
|
|
Command::Daemon => {
|
|
// if daemon is specified we run the service
|
|
match run_async(run_service(config)) {
|
|
Err(LanMouseError::Service(ServiceError::IpcListen(
|
|
IpcListenerCreationError::AlreadyRunning,
|
|
))) => log::info!("service already running!"),
|
|
r => r?,
|
|
}
|
|
}
|
|
},
|
|
None => {
|
|
// otherwise start the service as a child process and
|
|
// run a frontend
|
|
#[cfg(feature = "gtk")]
|
|
{
|
|
let mut service = start_service()?;
|
|
let res = lan_mouse_gtk::run();
|
|
#[cfg(unix)]
|
|
{
|
|
// on unix we give the service a chance to terminate gracefully
|
|
let pid = service.id() as libc::pid_t;
|
|
unsafe {
|
|
libc::kill(pid, libc::SIGINT);
|
|
}
|
|
service.wait()?;
|
|
}
|
|
service.kill()?;
|
|
res?;
|
|
}
|
|
#[cfg(not(feature = "gtk"))]
|
|
{
|
|
// run daemon if gtk is diabled
|
|
match run_async(run_service(config)) {
|
|
Err(LanMouseError::Service(ServiceError::IpcListen(
|
|
IpcListenerCreationError::AlreadyRunning,
|
|
))) => log::info!("service already running!"),
|
|
r => r?,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn run_async<F, E>(f: F) -> Result<(), LanMouseError>
|
|
where
|
|
F: Future<Output = Result<(), E>>,
|
|
LanMouseError: From<E>,
|
|
{
|
|
// create single threaded tokio runtime
|
|
let runtime = tokio::runtime::Builder::new_current_thread()
|
|
.enable_io()
|
|
.enable_time()
|
|
.build()?;
|
|
|
|
// run async event loop
|
|
Ok(runtime.block_on(LocalSet::new().run_until(f))?)
|
|
}
|
|
|
|
fn start_service() -> Result<Child, io::Error> {
|
|
let child = process::Command::new(std::env::current_exe()?)
|
|
.args(std::env::args().skip(1))
|
|
.arg("daemon")
|
|
.spawn()?;
|
|
Ok(child)
|
|
}
|
|
|
|
async fn run_service(config: Config) -> Result<(), ServiceError> {
|
|
let release_bind = config.release_bind();
|
|
let config_path = config.config_path().to_owned();
|
|
let mut service = Service::new(config).await?;
|
|
log::info!("using config: {config_path:?}");
|
|
log::info!("Press {release_bind:?} to release the mouse");
|
|
service.run().await?;
|
|
log::info!("service exited!");
|
|
Ok(())
|
|
}
|