diff --git a/xmpd-cache/src/lib.rs b/xmpd-cache/src/lib.rs index caed2f0..bc86ff7 100644 --- a/xmpd-cache/src/lib.rs +++ b/xmpd-cache/src/lib.rs @@ -1,5 +1,6 @@ -use std::{collections::HashMap, str::FromStr, sync::{Arc, Mutex, MutexGuard}, time::Duration}; +use std::{collections::HashMap, str::FromStr, sync::{mpsc::{self, Receiver, Sender}, Arc, Mutex, MutexGuard}, time::Duration}; use downloader::song::SongStatus; +use log::warn; use xmpd_manifest::song::Song; pub mod downloader; @@ -25,6 +26,11 @@ pub enum DlStatus { Error(String), } +#[derive(Debug, Clone)] +pub enum Message { + DownloadDone(uuid::Uuid), +} + impl Cache { pub fn get() -> crate::Result> { match CACHE.lock() { @@ -33,8 +39,10 @@ impl Cache { } } - pub fn init(&mut self) -> Result<()> { - start_cache_mv_thread(); + pub fn init(&mut self) -> Result> { + let (internal_tx, cache_rx) = mpsc::channel::(); + // let (internal_rx, cache_tx) = mpsc::channel::(); + start_cache_mv_thread(internal_tx); self.cache_dir = xmpd_cliargs::CLIARGS.cache_path(); { // Get cached songs @@ -62,7 +70,7 @@ impl Cache { } { // Get Cached meta } - Ok(()) + Ok(cache_rx) } pub fn download_to_cache(&mut self, sid: uuid::Uuid, song: Song) { @@ -77,12 +85,13 @@ impl Cache { } pub fn get_cached_song_status(&mut self, sid: &uuid::Uuid) -> Option { - Some(self.song_cache.get(sid)?.clone()) + let original = self.song_cache.get(sid)?.clone(); + Some(original) } } -fn start_cache_mv_thread() { - std::thread::spawn(|| { +fn start_cache_mv_thread(tx: Sender) { + std::thread::spawn(move || { loop { { std::thread::sleep(Duration::from_millis(500)); @@ -98,6 +107,7 @@ fn start_cache_mv_thread() { let song_p = song_p.with_extension(&song_format); log::debug!("Found done: {:?}: {}", song_p, song_p.exists()); if song_p.exists() { + let _ = tx.send(Message::DownloadDone(sid.clone())); cache.song_cache.insert(sid.clone(), DlStatus::Done(song_p)); done_jobs.push(sid.clone()); } diff --git a/xmpd-gui/src/components/song_list/mod.rs b/xmpd-gui/src/components/song_list/mod.rs index 5f3bc3d..d4842d8 100644 --- a/xmpd-gui/src/components/song_list/mod.rs +++ b/xmpd-gui/src/components/song_list/mod.rs @@ -160,7 +160,13 @@ fn display_song_tab(ui: &mut egui::Ui, sid: &uuid::Uuid, song: &Song) { .fit_to_exact_size(Vec2::new(16.0, 16.0)) ); if img.clicked() { - handle_error_ui!(xmpd_cache::Cache::get()).download_to_cache(sid.clone(), song.clone()) + handle_error_ui!(xmpd_cache::Cache::get()).download_to_cache(sid.clone(), song.clone()); + let mut toast = handle_error_ui!(crate::components::toast::Toast::get()); + toast.show_toast( + "Downloading Song", + &format!("Started downloading {} by {}", song.name(), song.author()), + super::toast::ToastType::Info + ); } } } diff --git a/xmpd-gui/src/components/song_list/song_list_nav.rs b/xmpd-gui/src/components/song_list/song_list_nav.rs index 1eceb83..362436d 100644 --- a/xmpd-gui/src/components/song_list/song_list_nav.rs +++ b/xmpd-gui/src/components/song_list/song_list_nav.rs @@ -1,7 +1,7 @@ use uuid::Uuid; use xmpd_manifest::store::BaseStore; -use crate::components::{left_nav::LeftNav, CompGetter, CompUi}; +use crate::components::{left_nav::LeftNav, toast::ToastType, CompGetter, CompUi}; #[derive(Debug, Clone)] pub enum SearchType { @@ -53,6 +53,12 @@ impl CompUi for SongListNav { handle_error_ui!(xmpd_cache::Cache::get()).download_to_cache(sid.clone(), song.clone()) } } + let mut toast = handle_error_ui!(crate::components::toast::Toast::get()); + toast.show_toast( + "Downloading Songs", + &format!("Started downloading {} songs", songs.len()), + ToastType::Info + ); } }); }); diff --git a/xmpd-gui/src/components/toast.rs b/xmpd-gui/src/components/toast.rs index 247280b..d9ac3f9 100644 --- a/xmpd-gui/src/components/toast.rs +++ b/xmpd-gui/src/components/toast.rs @@ -100,7 +100,9 @@ impl CompUi for Toast { impl Toast { - pub fn show_toast(&mut self, title: &str, description: &str, toast_type: ToastType) { + pub fn show_toast(&mut self, title: S, description: S, toast_type: ToastType) + where S: ToString + { self.queue.push_front((title.to_string(), description.to_string(), toast_type, SystemTime::now())); } } diff --git a/xmpd-gui/src/lib.rs b/xmpd-gui/src/lib.rs index 286c8c6..c7c2d10 100644 --- a/xmpd-gui/src/lib.rs +++ b/xmpd-gui/src/lib.rs @@ -16,13 +16,13 @@ const W_NAME: &str = "xmpd v2.0.0a"; type Result = anyhow::Result; pub fn start() -> Result<()> { - xmpd_cache::Cache::get()?.init()?; + let cache_rx = xmpd_cache::Cache::get()?.init()?; let options = eframe::NativeOptions::default(); let mut state = GuiState::new()?; let res = eframe::run_simple_native(W_NAME, options, move |ctx, _frame| { egui_extras::install_image_loaders(ctx); state.windows.clone().draw_all(ctx, &mut state); - handle_error_ui!(main_window::draw(ctx, &mut state)); + handle_error_ui!(main_window::draw(ctx, &mut state, &cache_rx)); ctx.request_repaint_after(Duration::from_millis(500)); }); if let Err(e) = res { // dumb err value by eframe @@ -31,6 +31,8 @@ pub fn start() -> Result<()> { Ok(()) } + + pub struct GuiState { pub manifest: Manifest, pub windows: windows::Windows, diff --git a/xmpd-gui/src/main_window.rs b/xmpd-gui/src/main_window.rs index 9776d58..0dbffff 100644 --- a/xmpd-gui/src/main_window.rs +++ b/xmpd-gui/src/main_window.rs @@ -1,8 +1,12 @@ +use std::sync::mpsc::Receiver; + +use xmpd_cache::Message; +use xmpd_manifest::store::BaseStore; use xmpd_settings::theme::Theme; -use crate::{components::{self, song_list, CompUi}, GuiState}; +use crate::{components::{self, song_list, toast::ToastType, CompGetter, CompUi}, GuiState}; -pub fn draw(ctx: &egui::Context, state: &mut GuiState) -> crate::Result<()> { +pub fn draw(ctx: &egui::Context, state: &mut GuiState, cache_rx: &Receiver) -> crate::Result<()> { let theme = xmpd_settings::Settings::get()?.theme.clone(); egui::TopBottomPanel::new(egui::panel::TopBottomSide::Top, "top_nav") .frame(get_themed_frame(&theme)) @@ -53,6 +57,21 @@ pub fn draw(ctx: &egui::Context, state: &mut GuiState) -> crate::Result<()> { handle_error_ui!(crate::components::player::Player::draw(ui, state)); } ); + if let Ok(msg) = cache_rx.try_recv() { + match msg { + Message::DownloadDone(sid) => { + if let Some(song) = state.manifest.store().get_song(&sid) { + let mut toast = crate::components::toast::Toast::get()?; + toast.show_toast( + "Done downloading", + &format!("Downloaded {} by {}", song.name(), song.author()), + ToastType::Info + ); + } + } + } + } + Ok(()) }