diff --git a/src/main.rs b/src/main.rs index a1b09ce..c57b112 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,80 +1,116 @@ mod eventloop; mod homeassistant; -mod settings; mod screenshot; +mod settings; mod state; mod ui; -use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::atomic::AtomicBool; use std::sync::mpsc::channel; use std::sync::{Arc, Mutex}; -fn main() { - let rt = tokio::runtime::Runtime::new().unwrap(); - let rt_handle = rt.handle().clone(); +use homeassistant::HaClient; +use settings::Settings; - let settings = settings::Settings::new().unwrap_or_else(|err| { - eprintln!("Error loading configuration: {}", err); - std::process::exit(1); - }); +struct App { + settings: Arc, + ha_client: Arc, + is_running: Arc, + target_lights: Arc>>>, + rt: tokio::runtime::Runtime, +} - let ha_client = Arc::new(homeassistant::HaClient::new(&settings.ha_url, &settings.ha_token)); - let settings_arc = Arc::new(settings); +impl App { + fn new() -> Self { + let settings = Settings::new().unwrap_or_else(|err| { + eprintln!("Error loading configuration: {}", err); + std::process::exit(1); + }); - let is_running = Arc::new(AtomicBool::new(false)); - let (async_exit_tx, async_exit_rx) = tokio::sync::mpsc::channel(1); - let (sync_exit_tx, sync_exit_rx) = channel(); + let rt = tokio::runtime::Runtime::new().unwrap(); + let ha_client = HaClient::new(&settings.ha_url, &settings.ha_token); - let target_lights: Arc>>> = Arc::new(Mutex::new(None)); - let state_arc = Arc::new(state::AppState::new()); - - let is_running_clone = is_running.clone(); - let settings_arc_clone = settings_arc.clone(); - let ha_client_arc_clone = ha_client.clone(); - let target_lights_clone = target_lights.clone(); - - let app_thread = std::thread::spawn(move || { - eventloop::run_loop( - settings_arc_clone, - ha_client_arc_clone, - target_lights_clone, - state_arc, - is_running_clone, - async_exit_rx, - ); - }); - - let tray_ctx = ui::TrayContext { - is_running: is_running.clone(), - target_lights: target_lights.clone(), - settings: settings_arc.clone(), - ha_client: ha_client.clone(), - rt_handle: rt_handle.clone(), - exit_tx: sync_exit_tx.clone(), - }; - - let _tray = ui::create_tray(tray_ctx); - - ctrlc::set_handler(move || { - let _ = sync_exit_tx.send(()); - }) - .expect("Error setting Ctrl-C handler"); - - let _ = sync_exit_rx.recv(); - println!("Shutting down..."); - - let _ = async_exit_tx.try_send(()); - - if settings_arc.restore_on_exit { - if let Some(ref lights) = *target_lights.lock().unwrap() { - println!("Restoring lights to original state..."); - if let Err(e) = rt.block_on(ha_client.turn_on_scene("scene.ambilight_restore")) { - eprintln!("Failed to restore scene: {}", e); - } else { - println!("Lights restored successfully."); - } + App { + settings: Arc::new(settings), + ha_client: Arc::new(ha_client), + is_running: Arc::new(AtomicBool::new(false)), + target_lights: Arc::new(Mutex::new(None)), + rt, } } - let _ = app_thread.join(); + fn run(self) { + let (async_exit_tx, async_exit_rx) = tokio::sync::mpsc::channel(1); + let (sync_exit_tx, sync_exit_rx) = channel(); + + let state = Arc::new(state::AppState::new()); + let rt_handle = self.rt.handle().clone(); + + let app_thread = { + let settings = self.settings.clone(); + let ha_client = self.ha_client.clone(); + let target_lights = self.target_lights.clone(); + let is_running = self.is_running.clone(); + + std::thread::spawn(move || { + eventloop::run_loop( + settings, + ha_client, + target_lights, + state, + is_running, + async_exit_rx, + ); + }) + }; + + let tray_ctx = ui::TrayContext { + is_running: self.is_running.clone(), + target_lights: self.target_lights.clone(), + settings: self.settings.clone(), + ha_client: self.ha_client.clone(), + rt_handle, + exit_tx: sync_exit_tx.clone(), + }; + + let _tray = ui::create_tray(tray_ctx); + + ctrlc::set_handler(move || { + let _ = sync_exit_tx.send(()); + }) + .expect("Error setting Ctrl-C handler"); + + let _ = sync_exit_rx.recv(); + println!("Shutting down..."); + + let _ = async_exit_tx.try_send(()); + self.restore_lights(); + + let _ = app_thread.join(); + } + + fn restore_lights(&self) { + if !self.settings.restore_on_exit { + return; + } + + let lights = self.target_lights.lock().unwrap(); + if lights.is_none() { + return; + } + + println!("Restoring lights to original state..."); + if let Err(e) = self + .rt + .block_on(self.ha_client.turn_on_scene("scene.ambilight_restore")) + { + eprintln!("Failed to restore scene: {}", e); + } else { + println!("Lights restored successfully."); + } + } +} + +fn main() { + App::new().run(); } diff --git a/src/settings.rs b/src/settings.rs index 814ea43..cb9fba7 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -90,7 +90,6 @@ pub fn get_config_file_path() -> PathBuf { impl Settings { pub fn new() -> Result { - let config_dir = get_config_dir(); let config_file = get_config_file_path(); let mut builder = Config::builder() diff --git a/src/ui.rs b/src/ui.rs index 2f05bbd..26c79ff 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -1,6 +1,5 @@ use crate::homeassistant; use crate::settings; -use crate::state; use std::io::Cursor; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::mpsc::Sender;