From 16ef6bfec7e446ed1a30ad519e900efcfc7e6961 Mon Sep 17 00:00:00 2001 From: undermirrors Date: Tue, 4 Nov 2025 00:17:59 +0100 Subject: [PATCH 1/2] feat: save when setting wallpaper, and load previous wallpapers when launching daemon --- waypaper_engine_daemon/src/app_state.rs | 233 ++++++++++++++++-------- 1 file changed, 153 insertions(+), 80 deletions(-) diff --git a/waypaper_engine_daemon/src/app_state.rs b/waypaper_engine_daemon/src/app_state.rs index aefc716..35bdb5b 100644 --- a/waypaper_engine_daemon/src/app_state.rs +++ b/waypaper_engine_daemon/src/app_state.rs @@ -1,15 +1,14 @@ use std::error::Error; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::sync::mpsc; use std::sync::mpsc::{Sender, TryRecvError}; -use std::thread; +use std::{fs, thread}; use linux_ipc::IpcChannel; 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 +75,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 +114,150 @@ 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) -> std::io::Result<()> { + let file_path = save_path(); + if file_path.is_empty() { + return Err(std::io::Error::new( + std::io::ErrorKind::NotFound, + "HOME environment variable not set", + )); + } + let mut lines = read_save_file(&file_path); + + if let Some(line) = lines.iter_mut().find(|line| line.starts_with(screen)) { + *line = format!("{} = {}", screen, id); + } else { + lines.push(format!("{} = {}", screen, id)); + } + + fs::write(file_path, lines.join("\n"))?; + tracing::info!("{}", format!("Save wallpaper : {}", lines.join("\n"))); + Ok(()) + } + + fn load_wallpaper(&mut self) -> std::io::Result<()> { + let file_path = save_path(); + let lines = read_save_file(&file_path); + + lines + .iter() + .filter_map(|line| { + line.split_once('=').and_then(|(screen_part, id_part)| { + id_part + .trim() + .parse::() + .ok() + .map(|id| (id, screen_part.trim().to_string())) + }) + }) + .for_each(|(id, screen)| { + let (tx, _rx) = mpsc::channel::(); + self.set_wallpaper(id, screen, tx); + }); + + Ok(()) + } +} + +fn read_save_file(file_path: &str) -> Vec { + let content = if Path::new(file_path).exists() { + fs::read_to_string(file_path).unwrap_or_else(|_| String::new()) + } else { + String::new() + }; + + content.lines().map(|line| line.to_string()).collect() } + +fn save_path() -> String { + if let Ok(home) = std::env::var("HOME") { + let file_path: PathBuf = PathBuf::from(home).join(".config/waypaper_engine/wallpapers.conf"); + if let Some(parent) = file_path.parent() { + if !parent.exists() { + if let Err(err) = fs::create_dir_all(parent) { + tracing::warn!("Failed to create directory {:?}: {}", parent, err); + } else { + tracing::info!("Created directory {:?}", parent); + } + } + } + file_path.to_string_lossy().into_owned() + } else { + "".to_string() + } +} \ No newline at end of file From 90781acfd3d61065a1f3addd3c98496c0c807648 Mon Sep 17 00:00:00 2001 From: undermirrors Date: Tue, 4 Nov 2025 13:52:06 +0100 Subject: [PATCH 2/2] feat: save when setting wallpaper, and load previous wallpapers when launching daemon --- waypaper_engine_daemon/src/app_state.rs | 111 +++++++++++------------- 1 file changed, 49 insertions(+), 62 deletions(-) diff --git a/waypaper_engine_daemon/src/app_state.rs b/waypaper_engine_daemon/src/app_state.rs index 35bdb5b..d03c9ef 100644 --- a/waypaper_engine_daemon/src/app_state.rs +++ b/waypaper_engine_daemon/src/app_state.rs @@ -1,10 +1,12 @@ use std::error::Error; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use std::sync::mpsc; use std::sync::mpsc::{Sender, TryRecvError}; -use std::{fs, 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; @@ -189,75 +191,60 @@ impl AppState { false } } - pub fn save_wallpaper(id: u64, screen: &str) -> std::io::Result<()> { - let file_path = save_path(); - if file_path.is_empty() { - return Err(std::io::Error::new( - std::io::ErrorKind::NotFound, - "HOME environment variable not set", - )); - } - let mut lines = read_save_file(&file_path); - - if let Some(line) = lines.iter_mut().find(|line| line.starts_with(screen)) { - *line = format!("{} = {}", screen, id); - } else { - lines.push(format!("{} = {}", screen, id)); + 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), } - - fs::write(file_path, lines.join("\n"))?; - tracing::info!("{}", format!("Save wallpaper : {}", lines.join("\n"))); - Ok(()) } - fn load_wallpaper(&mut self) -> std::io::Result<()> { - let file_path = save_path(); - let lines = read_save_file(&file_path); - - lines - .iter() - .filter_map(|line| { - line.split_once('=').and_then(|(screen_part, id_part)| { - id_part - .trim() - .parse::() - .ok() - .map(|id| (id, screen_part.trim().to_string())) - }) - }) - .for_each(|(id, screen)| { + fn load_wallpaper(&mut self) -> Result<(), Box> { + match wallpapers_config() { + Ok(lines) => { let (tx, _rx) = mpsc::channel::(); - self.set_wallpaper(id, screen, tx); - }); + lines.iter().for_each(|(screen, &id)| { + self.set_wallpaper(id, screen.to_owned(), tx.clone()); + }); + Ok(()) + } + Err(e) => Err(e), + } + } +} - Ok(()) +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 read_save_file(file_path: &str) -> Vec { - let content = if Path::new(file_path).exists() { - fs::read_to_string(file_path).unwrap_or_else(|_| String::new()) +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 { - String::new() + return Err(Box::new(std::io::Error::new( + std::io::ErrorKind::NotFound, + "Impossible de déterminer le répertoire de configuration", + ))); }; - content.lines().map(|line| line.to_string()).collect() -} - -fn save_path() -> String { - if let Ok(home) = std::env::var("HOME") { - let file_path: PathBuf = PathBuf::from(home).join(".config/waypaper_engine/wallpapers.conf"); - if let Some(parent) = file_path.parent() { - if !parent.exists() { - if let Err(err) = fs::create_dir_all(parent) { - tracing::warn!("Failed to create directory {:?}: {}", parent, err); - } else { - tracing::info!("Created directory {:?}", parent); - } - } - } - file_path.to_string_lossy().into_owned() - } else { - "".to_string() + let parent = base_dir.join("waypaper_engine"); + if !parent.exists() { + fs::create_dir_all(&parent)?; } -} \ No newline at end of file + + let file_path = parent.join("wallpapers.conf"); + Ok(file_path.to_string_lossy().into_owned()) +}