diff --git a/src/lib.rs b/src/lib.rs index 61198a1..c9ad65e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,15 +1,16 @@ pub mod globals { - pub fn art_path() -> &'static std::path::Path { - static ART_PATH: std::sync::LazyLock = std::sync::LazyLock::new(|| { - let xdg_dirs = - xdg::BaseDirectories::with_prefix("audrey").expect("failed to get xdg dirs"); - xdg_dirs - .place_state_file("mpris-art") - .expect("failed to create mpris art state dir") + use std::path::PathBuf; + use tokio::sync::Mutex; + + pub fn xdg_dirs() -> &'static xdg::BaseDirectories { + static DIRS: std::sync::LazyLock = std::sync::LazyLock::new(|| { + xdg::BaseDirectories::with_prefix("audrey").expect("failed to get xdg dirs") }); - &ART_PATH + &DIRS } + pub static MPRIS_ART_PATH: Mutex> = Mutex::const_new(None); + pub fn runtime() -> &'static tokio::runtime::Runtime { static RUNTIME: std::sync::LazyLock = std::sync::LazyLock::new(|| { diff --git a/src/model/song.rs b/src/model/song.rs index 884abbd..eb88071 100644 --- a/src/model/song.rs +++ b/src/model/song.rs @@ -30,6 +30,8 @@ mod imp { duration: Cell, #[property(get, set)] track: Cell, + #[property(get, set)] + cover_art: RefCell, #[property(get, set)] stream_url: RefCell, @@ -83,6 +85,7 @@ impl Song { .property("duration", song.duration as i64) .property("track", song.track.map(i64::from).unwrap_or(-1)) .property("stream-url", api.stream_url(&song.id).as_str()) + .property("cover-art", &song.cover_art) .build(); song diff --git a/src/mpris/player.rs b/src/mpris/player.rs index 5fa35ca..5a03cbd 100644 --- a/src/mpris/player.rs +++ b/src/mpris/player.rs @@ -92,10 +92,11 @@ impl Player { #[tracing::instrument(skip(self), parent = None, target = "audrey::mpris", level = Level::DEBUG, ret)] fn set_position(&self, track_id: ObjectPath<'_>, position: i64) -> zbus::fdo::Result<()> { - let metadata = self.metadata(); - if Some(&track_id.into()) == metadata.get("track_id") { - self.window().set_time_pos(position as f64 / MICROSECONDS); - } + //let metadata = self.metadata(); + // TODO: reimplment stale seeks + //if Some(&track_id.into()) == metadata.get("track_id") { + self.window().set_time_pos(position as f64 / MICROSECONDS); + //} Ok(()) } @@ -153,8 +154,9 @@ impl Player { } #[zbus(property)] - fn metadata(&self) -> HashMap<&'static str, Value<'_>> { + async fn metadata(&self) -> HashMap<&'static str, Value<'_>> { let mut map = HashMap::new(); + let mpris_art_path = audrey::globals::MPRIS_ART_PATH.lock().await; if let Some(song) = self.window().song() { map.insert( @@ -165,13 +167,12 @@ impl Player { "mpris:length", ((self.window().duration() * MICROSECONDS) as i64).into(), ); - map.insert( - "mpris:artUrl", - (url::Url::from_file_path(audrey::globals::art_path()) - .unwrap() - .to_string(),) - .into(), - ); + if let Some(path) = mpris_art_path.as_ref() { + map.insert( + "mpris:artUrl", + (url::Url::from_file_path(path).unwrap().to_string()).into(), + ); + } map.insert("xesam:album", song.album().into()); // TODO: use the right opensubsonic data map.insert("xesam:artist", vec![song.artist()].into()); diff --git a/src/ui/window.rs b/src/ui/window.rs index 7f45901..e1d1e25 100644 --- a/src/ui/window.rs +++ b/src/ui/window.rs @@ -733,7 +733,7 @@ mod imp { self.mpris_player_playback_status_changed(); let window = self.obj().clone(); - let song_id = window.song().unwrap().id(); + let song_id = song.id(); if let Some(handle) = self .loading_cover_handle .replace(Some(glib::spawn_future_local(async move { @@ -754,12 +754,27 @@ mod imp { // we consume image below into a pixbuf so we need a copy for save let image_copy = image.clone(); + let save_path = audrey::globals::xdg_dirs() + .place_state_file(format!("{}.jpg", song.cover_art())) + .expect("failed to create mpris art state dir"); + let save_path_copy = save_path.clone(); + let mut mpris_art_path = audrey::globals::MPRIS_ART_PATH.lock().await; let save_future = audrey::globals::runtime().spawn_blocking( move || -> Result<(), image::ImageError> { - let save_path = audrey::globals::art_path(); + // TODO: wipe xdg state folder on init + if let Some(path) = mpris_art_path.take() { + if let Err(err) = std::fs::remove_file(&path) { + event!( + Level::ERROR, + "could not remove previous mpris art at {}: {err}", + path.display() + ); + } + } let resized = image_copy.resize(400, 400, image::imageops::FilterType::Lanczos3); - resized.save_with_format(save_path, image::ImageFormat::Jpeg)?; + resized.save_with_format(&save_path_copy, image::ImageFormat::Jpeg)?; + *mpris_art_path = Some(save_path_copy); Ok(()) }, );