diff --git a/waypaper_engine_daemon/src/app_state.rs b/waypaper_engine_daemon/src/app_state.rs index aefc716..d03c9ef 100644 --- a/waypaper_engine_daemon/src/app_state.rs +++ b/waypaper_engine_daemon/src/app_state.rs @@ -2,14 +2,15 @@ use std::error::Error; use std::path::PathBuf; use std::sync::mpsc; use std::sync::mpsc::{Sender, TryRecvError}; -use std::thread; +use std::{env, fs, thread}; use linux_ipc::IpcChannel; +use std::collections::HashMap; +use std::fs::File; use waypaper_engine_shared::ipc::{IPCError, IPCRequest, IPCResponse}; use crate::wallpaper::Wallpaper; use crate::wl_renderer::RenderingContext; - pub struct AppState { wpe_dir: PathBuf, rendering_context: RenderingContext, @@ -76,89 +77,17 @@ impl AppState { } }); + self.load_wallpaper() + .expect("Unable to load wallpapers configuration"); + loop { self.rendering_context.tick(); match rx.try_recv() { Ok((req, response)) => match req { IPCRequest::SetWallpaper { id, screen } => { - let outputs = self.rendering_context.get_outputs(); - - if let Some(output) = outputs - .iter() - .find(|output| output.1.name.as_ref().unwrap() == &screen) - { - let path = self.wpe_dir.join(id.to_string()); - - if !path.exists() { - tracing::warn!("Wallpaper path does not exist: {:?}", path); - response - .send(IPCResponse::Error(IPCError::WallpaperNotFound)) - .unwrap(); - continue; - } - - if !path.is_dir() { - tracing::warn!("Wallpaper path is not a directory: {:?}", path); - response - .send(IPCResponse::Error(IPCError::WallpaperNotFound)) - .unwrap(); - continue; - } - - let wallpaper = Wallpaper::new(path)?; - let path = self.wpe_dir.join(id.to_string()); - match wallpaper { - Wallpaper::Video { ref project, .. } => { - let video_path = path.join(project.file.as_ref().unwrap()); - - if video_path.exists() { - tracing::info!( - "Found video file ! (Path : {video_path:?})" - ); - - self.rendering_context.set_wallpaper(output, wallpaper); - } - } - Wallpaper::Scene { .. } => { - let scene_pkg_file = path.join("scene.pkg"); - - if scene_pkg_file.exists() { - tracing::info!( - "Found scene package file ! (Path : {scene_pkg_file:?})" - ); - - self.rendering_context.set_wallpaper(output, wallpaper); - } - } - _ => { - tracing::warn!( - "Unsupported wallpaper type for SetWallpaper request: [{}]", - screen - ); - response - .send(IPCResponse::Error( - IPCError::UnsupportedWallpaperType, - )) - .unwrap(); - continue; - } - } - - tracing::info!( - "Set wallpaper for output [{}] with id [{}]", - screen, - id - ); - response.send(IPCResponse::Success).unwrap(); - } else { - tracing::warn!( - "Received wrong output in SetWallpaper request: [{}]", - screen - ); - response - .send(IPCResponse::Error(IPCError::ScreenNotFound)) - .unwrap(); + if Self::set_wallpaper(self, id, screen.clone(), response) { + Self::save_wallpaper(id, &screen).expect("Unable to save wallpaper"); } } IPCRequest::ListOutputs => { @@ -187,4 +116,135 @@ impl AppState { Ok(()) } + + fn set_wallpaper(&mut self, id: u64, screen: String, response: Sender) -> bool { + let outputs = self.rendering_context.get_outputs(); + + if let Some(output) = outputs + .iter() + .find(|output| output.1.name.as_ref().unwrap() == &screen) + { + let path = self.wpe_dir.join(id.to_string()); + + if !path.exists() { + tracing::warn!("Wallpaper path does not exist: {:?}", path); + response + .send(IPCResponse::Error(IPCError::WallpaperNotFound)) + .unwrap(); + return false; + } + + if !path.is_dir() { + tracing::warn!("Wallpaper path is not a directory: {:?}", path); + response + .send(IPCResponse::Error(IPCError::WallpaperNotFound)) + .unwrap(); + return false; // not sure about this + } + + let wallpaper = Wallpaper::new(path).expect("no path found"); + let path = self.wpe_dir.join(id.to_string()); + match wallpaper { + Wallpaper::Video { ref project, .. } => { + let video_path = path.join(project.file.as_ref().unwrap()); + + if video_path.exists() { + tracing::info!("Found video file ! (Path : {video_path:?})"); + + self.rendering_context.set_wallpaper(output, wallpaper); + } + } + Wallpaper::Scene { .. } => { + let scene_pkg_file = path.join("scene.pkg"); + + if scene_pkg_file.exists() { + tracing::info!("Found scene package file ! (Path : {scene_pkg_file:?})"); + + self.rendering_context.set_wallpaper(output, wallpaper); + } + } + _ => { + tracing::warn!( + "Unsupported wallpaper type for SetWallpaper request: [{}]", + screen + ); + response + .send(IPCResponse::Error(IPCError::UnsupportedWallpaperType)) + .unwrap(); + return false; + } + } + + tracing::info!("Set wallpaper for output [{}] with id [{}]", screen, id); + response.send(IPCResponse::Success).unwrap(); + + true + } else { + tracing::warn!( + "Received wrong output in SetWallpaper request: [{}]", + screen + ); + response + .send(IPCResponse::Error(IPCError::ScreenNotFound)) + .unwrap(); + + false + } + } + pub fn save_wallpaper(id: u64, screen: &str) -> Result<(), Box> { + match wallpapers_config() { + Ok(mut lines) => { + lines.insert(screen.to_string(), id); + let save_path = save_path()?; + let file = File::create(&save_path)?; + serde_json::to_writer_pretty(file, &lines)?; + Ok(()) + } + Err(e) => Err(e), + } + } + + fn load_wallpaper(&mut self) -> Result<(), Box> { + match wallpapers_config() { + Ok(lines) => { + let (tx, _rx) = mpsc::channel::(); + lines.iter().for_each(|(screen, &id)| { + self.set_wallpaper(id, screen.to_owned(), tx.clone()); + }); + Ok(()) + } + Err(e) => Err(e), + } + } +} + +fn wallpapers_config() -> Result, Box> { + match save_path() { + Ok(file_path) => match File::open(&file_path) { + Ok(file) => Ok(serde_json::from_reader(file).unwrap_or_default()), + Err(e) => Err(Box::new(e)), + }, + Err(e) => Err(e), + } +} + +fn save_path() -> Result> { + let base_dir = if let Ok(xdg_config) = env::var("XDG_CONFIG_HOME") { + PathBuf::from(xdg_config) + } else if let Ok(home) = env::var("HOME") { + PathBuf::from(home).join(".config") + } else { + return Err(Box::new(std::io::Error::new( + std::io::ErrorKind::NotFound, + "Impossible de déterminer le répertoire de configuration", + ))); + }; + + let parent = base_dir.join("waypaper_engine"); + if !parent.exists() { + fs::create_dir_all(&parent)?; + } + + let file_path = parent.join("wallpapers.conf"); + Ok(file_path.to_string_lossy().into_owned()) }