use std::path::Path; use std::time::{Duration, Instant}; use anyhow::anyhow; use xmpd_manifest::{store::JsonStore, Manifest}; #[macro_use] mod macros; mod main_window; mod windows; mod components; mod data; mod utils; const W_NAME: &str = "xmpd v2.0.0a"; type Result = anyhow::Result; pub fn start() -> Result<()> { let manifest_p = xmpd_settings::Settings::get()?.cache_settings.manifest_path.clone().into_std_path_buf(); let cache_rx = xmpd_cache::Cache::get() .map_err(|e| anyhow!("Failed to get cache: {e}"))? .init() .map_err(|e| anyhow!("Failed to init cache: {e}"))?; let options = eframe::NativeOptions::default(); let mut state = GuiState::new(&manifest_p)?; let res = eframe::run_simple_native(W_NAME, options, move |ctx, _frame| { #[cfg(debug_assertions)] let f_start = Instant::now(); egui_extras::install_image_loaders(ctx); windows::Windows::draw_all(ctx, &mut state); handle_error_ui!(main_window::draw(ctx, &mut state, &cache_rx)); ctx.request_repaint_after(Duration::from_millis(500)); #[cfg(debug_assertions)] { let f_end = Instant::now(); state.debug_info.last_frame_time = f_end.duration_since(f_start); } }); if let Err(e) = res { // dumb err value by eframe anyhow::bail!(e.to_string()); } Ok(()) } #[cfg(debug_assertions)] #[derive(Debug, Default)] pub struct DebugInfo { pub last_frame_time: Duration, } pub struct GuiState { #[cfg(debug_assertions)] pub debug_info: DebugInfo, pub manifest: Manifest, pub windows: windows::Windows, pub player: xmpd_player::Player, } impl GuiState { #[cfg(debug_assertions)] pub fn new(manifest_p: &Path) -> Result { Ok(Self { debug_info: DebugInfo { last_frame_time: Default::default() }, player: xmpd_player::Player::new(), manifest: Manifest::new(manifest_p)?, windows: windows::Windows::new(), }) } #[cfg(not(debug_assertions))] pub fn new(manifest_p: &Path) -> Result { Ok(Self { player: xmpd_player::Player::new(), manifest: Manifest::new(manifest_p)?, windows: windows::Windows::new(), }) } }