Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
218 changes: 139 additions & 79 deletions waypaper_engine_daemon/src/app_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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 => {
Expand Down Expand Up @@ -187,4 +116,135 @@ impl AppState {

Ok(())
}

fn set_wallpaper(&mut self, id: u64, screen: String, response: Sender<IPCResponse>) -> 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<dyn Error>> {
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<dyn Error>> {
match wallpapers_config() {
Ok(lines) => {
let (tx, _rx) = mpsc::channel::<IPCResponse>();
lines.iter().for_each(|(screen, &id)| {
self.set_wallpaper(id, screen.to_owned(), tx.clone());
});
Ok(())
}
Err(e) => Err(e),
}
}
}

fn wallpapers_config() -> Result<HashMap<String, u64>, Box<dyn Error>> {
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<String, Box<dyn Error>> {
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())
}