diff --git a/Cargo.lock b/Cargo.lock index 1db9dec..c017459 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -137,6 +137,28 @@ version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +[[package]] +name = "alsa" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed7572b7ba83a31e20d1b48970ee402d2e3e0537dcfe0a3ff4d6eb7508617d43" +dependencies = [ + "alsa-sys", + "bitflags 2.6.0", + "cfg-if", + "libc", +] + +[[package]] +name = "alsa-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527" +dependencies = [ + "libc", + "pkg-config", +] + [[package]] name = "android-activity" version = "0.5.2" @@ -532,6 +554,24 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "bindgen" +version = "0.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" +dependencies = [ + "bitflags 2.6.0", + "cexpr", + "clang-sys", + "itertools", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.87", +] + [[package]] name = "bit-set" version = "0.5.3" @@ -750,6 +790,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -771,6 +820,17 @@ dependencies = [ "libc", ] +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading 0.8.5", +] + [[package]] name = "clap" version = "4.5.20" @@ -811,6 +871,12 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +[[package]] +name = "claxon" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bfbf56724aa9eca8afa4fcfadeb479e722935bb2a0900c2d37e0cc477af0688" + [[package]] name = "clipboard-win" version = "5.4.0" @@ -968,6 +1034,49 @@ dependencies = [ "libc", ] +[[package]] +name = "coreaudio-rs" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "321077172d79c662f64f5071a03120748d5bb652f5231570141be24cfcd2bace" +dependencies = [ + "bitflags 1.3.2", + "core-foundation-sys", + "coreaudio-sys", +] + +[[package]] +name = "coreaudio-sys" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ce857aa0b77d77287acc1ac3e37a05a8c95a2af3647d23b15f263bdaeb7562b" +dependencies = [ + "bindgen", +] + +[[package]] +name = "cpal" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "873dab07c8f743075e57f524c583985fbaf745602acbe916a01539364369a779" +dependencies = [ + "alsa", + "core-foundation-sys", + "coreaudio-rs", + "dasp_sample", + "jni", + "js-sys", + "libc", + "mach2", + "ndk", + "ndk-context", + "oboe", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows 0.54.0", +] + [[package]] name = "cpufeatures" version = "0.2.14" @@ -1008,6 +1117,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991" +[[package]] +name = "dasp_sample" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" + [[package]] name = "data-url" version = "0.3.1" @@ -1256,6 +1371,12 @@ dependencies = [ "web-sys", ] +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + [[package]] name = "emath" version = "0.27.2" @@ -1272,6 +1393,15 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a6a21708405ea88f63d8309650b4d77431f4bc28fb9d8e6f77d3963b51249e6" +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + [[package]] name = "enum-map" version = "2.7.3" @@ -1439,6 +1569,12 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "extended" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af9673d8203fcb076b19dfd17e38b3d4ae9f44959416ea532ce72415a6020365" + [[package]] name = "fastrand" version = "1.9.0" @@ -1631,6 +1767,12 @@ dependencies = [ "xml-rs", ] +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + [[package]] name = "glow" version = "0.13.1" @@ -1830,6 +1972,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "hound" +version = "3.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62adaabb884c94955b19907d60019f4e145d091c75345379e70d1ee696f7854f" + [[package]] name = "humantime" version = "2.1.0" @@ -1912,6 +2060,15 @@ version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" @@ -1990,6 +2147,17 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "lewton" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "777b48df9aaab155475a83a7df3070395ea1ac6902f5cd062b8f2b028075c030" +dependencies = [ + "byteorder", + "ogg", + "tinyvec", +] + [[package]] name = "libc" version = "0.2.161" @@ -2061,6 +2229,15 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +[[package]] +name = "mach2" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" +dependencies = [ + "libc", +] + [[package]] name = "malloc_buf" version = "0.0.6" @@ -2134,6 +2311,12 @@ dependencies = [ "unicase", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.8.0" @@ -2225,6 +2408,27 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -2424,6 +2628,38 @@ dependencies = [ "memchr", ] +[[package]] +name = "oboe" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8b61bebd49e5d43f5f8cc7ee2891c16e0f41ec7954d36bcb6c14c5e0de867fb" +dependencies = [ + "jni", + "ndk", + "ndk-context", + "num-derive", + "num-traits", + "oboe-sys", +] + +[[package]] +name = "oboe-sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8bb09a4a2b1d668170cfe0a7d5bc103f8999fb316c98099b6a9939c9f2e79d" +dependencies = [ + "cc", +] + +[[package]] +name = "ogg" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6951b4e8bf21c8193da321bcce9c9dd2e13c858fe078bf9054a288b419ae5d6e" +dependencies = [ + "byteorder", +] + [[package]] name = "once_cell" version = "1.20.2" @@ -2801,6 +3037,19 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rodio" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ceb6607dd738c99bc8cb28eff249b7cd5c8ec88b9db96c0608c1480d140fb1" +dependencies = [ + "claxon", + "cpal", + "hound", + "lewton", + "symphonia", +] + [[package]] name = "roxmltree" version = "0.19.0" @@ -3173,6 +3422,151 @@ dependencies = [ "siphasher", ] +[[package]] +name = "symphonia" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "815c942ae7ee74737bb00f965fa5b5a2ac2ce7b6c01c0cc169bbeaf7abd5f5a9" +dependencies = [ + "lazy_static", + "symphonia-bundle-flac", + "symphonia-bundle-mp3", + "symphonia-codec-aac", + "symphonia-codec-adpcm", + "symphonia-codec-pcm", + "symphonia-codec-vorbis", + "symphonia-core", + "symphonia-format-isomp4", + "symphonia-format-riff", + "symphonia-metadata", +] + +[[package]] +name = "symphonia-bundle-flac" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72e34f34298a7308d4397a6c7fbf5b84c5d491231ce3dd379707ba673ab3bd97" +dependencies = [ + "log", + "symphonia-core", + "symphonia-metadata", + "symphonia-utils-xiph", +] + +[[package]] +name = "symphonia-bundle-mp3" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c01c2aae70f0f1fb096b6f0ff112a930b1fb3626178fba3ae68b09dce71706d4" +dependencies = [ + "lazy_static", + "log", + "symphonia-core", + "symphonia-metadata", +] + +[[package]] +name = "symphonia-codec-aac" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdbf25b545ad0d3ee3e891ea643ad115aff4ca92f6aec472086b957a58522f70" +dependencies = [ + "lazy_static", + "log", + "symphonia-core", +] + +[[package]] +name = "symphonia-codec-adpcm" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c94e1feac3327cd616e973d5be69ad36b3945f16b06f19c6773fc3ac0b426a0f" +dependencies = [ + "log", + "symphonia-core", +] + +[[package]] +name = "symphonia-codec-pcm" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f395a67057c2ebc5e84d7bb1be71cce1a7ba99f64e0f0f0e303a03f79116f89b" +dependencies = [ + "log", + "symphonia-core", +] + +[[package]] +name = "symphonia-codec-vorbis" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a98765fb46a0a6732b007f7e2870c2129b6f78d87db7987e6533c8f164a9f30" +dependencies = [ + "log", + "symphonia-core", + "symphonia-utils-xiph", +] + +[[package]] +name = "symphonia-core" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "798306779e3dc7d5231bd5691f5a813496dc79d3f56bf82e25789f2094e022c3" +dependencies = [ + "arrayvec", + "bitflags 1.3.2", + "bytemuck", + "lazy_static", + "log", +] + +[[package]] +name = "symphonia-format-isomp4" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abfdf178d697e50ce1e5d9b982ba1b94c47218e03ec35022d9f0e071a16dc844" +dependencies = [ + "encoding_rs", + "log", + "symphonia-core", + "symphonia-metadata", + "symphonia-utils-xiph", +] + +[[package]] +name = "symphonia-format-riff" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f7be232f962f937f4b7115cbe62c330929345434c834359425e043bfd15f50" +dependencies = [ + "extended", + "log", + "symphonia-core", + "symphonia-metadata", +] + +[[package]] +name = "symphonia-metadata" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc622b9841a10089c5b18e99eb904f4341615d5aa55bbf4eedde1be721a4023c" +dependencies = [ + "encoding_rs", + "lazy_static", + "log", + "symphonia-core", +] + +[[package]] +name = "symphonia-utils-xiph" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "484472580fa49991afda5f6550ece662237b00c6f562c7d9638d1b086ed010fe" +dependencies = [ + "symphonia-core", + "symphonia-metadata", +] + [[package]] name = "syn" version = "1.0.109" @@ -3983,7 +4377,17 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" dependencies = [ - "windows-core", + "windows-core 0.52.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows" +version = "0.54.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49" +dependencies = [ + "windows-core 0.54.0", "windows-targets 0.52.6", ] @@ -3996,6 +4400,16 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-core" +version = "0.54.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", +] + [[package]] name = "windows-implement" version = "0.48.0" @@ -4018,6 +4432,15 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "windows-result" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-sys" version = "0.45.0" @@ -4448,6 +4871,13 @@ dependencies = [ "uuid", ] +[[package]] +name = "xmpd-player" +version = "2.0.0" +dependencies = [ + "rodio", +] + [[package]] name = "xmpd-settings" version = "2.0.0" diff --git a/Cargo.toml b/Cargo.toml index cb51893..bc9c4a5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ members=[ "xmpd-cache", "xmpd-settings", "xmpd-tooling", + "xmpd-player", # "xmpd-tui" ] diff --git a/assets/error.svg b/assets/error.svg new file mode 100644 index 0000000..c0b9858 --- /dev/null +++ b/assets/error.svg @@ -0,0 +1 @@ + diff --git a/assets/info.svg b/assets/info.svg new file mode 100644 index 0000000..3a59676 --- /dev/null +++ b/assets/info.svg @@ -0,0 +1 @@ + diff --git a/xmpd-gui/src/components/mod.rs b/xmpd-gui/src/components/mod.rs index 3d75592..71adbf3 100644 --- a/xmpd-gui/src/components/mod.rs +++ b/xmpd-gui/src/components/mod.rs @@ -6,6 +6,7 @@ pub mod left_nav; pub mod song_list; pub mod top_nav; pub mod player; +pub mod toast; pub trait CompUi { fn draw(ui: &mut egui::Ui, state: &mut GuiState) -> crate::Result<()>; diff --git a/xmpd-gui/src/components/toast.rs b/xmpd-gui/src/components/toast.rs new file mode 100644 index 0000000..247280b --- /dev/null +++ b/xmpd-gui/src/components/toast.rs @@ -0,0 +1,107 @@ + +use std::{collections::VecDeque, time::SystemTime}; + +use egui::{epaint::Shadow, load::TexturePoll, Align2, Color32, Frame, Image, Margin, Pos2, Rect, RichText, Rounding, Stroke, Style, Vec2}; + +use super::{CompGetter, CompUi}; + +#[derive(Debug, Default, PartialEq, Clone, Copy)] +pub enum ToastType { + #[default] + Info, + Warn, + Error, +} + + +#[derive(Debug, Default)] +pub struct Toast { + queue: VecDeque<(String, String, ToastType, SystemTime)> +} + +component_register!(Toast); + +impl CompUi for Toast { + fn draw(ui: &mut egui::Ui, _: &mut crate::GuiState) -> crate::Result<()> { + let screen_size = ui.ctx().screen_rect().size(); + let (w, h) = (300.0, 100.0); + let theme = &xmpd_settings::Settings::get()?.theme; + let mut toastw = Toast::get()?; + let mut height_iter = 6.0; + let mut to_remove = Vec::new(); + + for (i, (title, description, toast_type, shown_since)) in toastw.queue.iter().enumerate() { + let area = egui::Area::new(egui::Id::new(format!("toast_{i}"))) + .fixed_pos(Pos2::new(screen_size.x - w, height_iter)) + .pivot(Align2::LEFT_TOP) + .show(ui.ctx(), |ui| { + ui.set_width(w); + + let img; + let color; + match toast_type { + ToastType::Info => { + color = theme.accent_color; + img = Image::new(crate::data::INFO_ICON) + .max_size(Vec2::new(16.0, 16.0)) + .tint(color); + } + ToastType::Warn => { + color = crate::data::C_WARN; + img = Image::new(crate::data::WARN_ICON) + .max_size(Vec2::new(16.0, 16.0)) + .tint(color); + } + ToastType::Error => { + color = Color32::LIGHT_RED; + img = Image::new(crate::data::ERROR_ICON) + .max_size(Vec2::new(16.0, 16.0)) + .tint(color); + } + } + Frame::none() + .stroke(Stroke::new(1.0, color)) + .fill(theme.primary_bg_color) + .rounding(Rounding::same(3.0)) + .inner_margin(Margin::same(3.0)) + .show(ui, |ui| { + ui.set_width(w-9.0); + ui.style_mut().visuals.override_text_color = Some(theme.text_color); + ui.horizontal(|ui| { + + ui.add(img); + ui.label(RichText::new(title)); + }); + ui.label( + RichText::new(description) + .size(10.0) + ); + ui.shrink_height_to_current(); + // height_iter += ui.available_height(); + } + ) + } + ); + height_iter += area.response.rect.height() + 6.0; + + // if shown for longer than 5 seconds remove it + if SystemTime::now().duration_since(*shown_since)?.as_secs() > 5 { + to_remove.push(i); + } + } + + for idx in to_remove { + toastw.queue.remove(idx); + } + + Ok(()) + } +} + + +impl Toast { + pub fn show_toast(&mut self, title: &str, description: &str, toast_type: ToastType) { + self.queue.push_front((title.to_string(), description.to_string(), toast_type, SystemTime::now())); + } +} + diff --git a/xmpd-gui/src/components/top_nav.rs b/xmpd-gui/src/components/top_nav.rs index ace61a2..5684558 100644 --- a/xmpd-gui/src/components/top_nav.rs +++ b/xmpd-gui/src/components/top_nav.rs @@ -28,6 +28,12 @@ impl CompUi for TopNav { ui.ctx().open_url(egui::OpenUrl::new_tab("https://git.mcorangehq.xyz/XOR64/music")); ui.close_menu(); } + + #[cfg(debug_assertions)] + if ui.button("Debug").clicked() { + state.windows.toggle(&WindowId::Debug, true); + ui.close_menu(); + } }); diff --git a/xmpd-gui/src/data.rs b/xmpd-gui/src/data.rs index b1dd09e..491d85b 100644 --- a/xmpd-gui/src/data.rs +++ b/xmpd-gui/src/data.rs @@ -8,4 +8,10 @@ pub const PLAY_ICON: egui::ImageSource = egui::include_image!("../../assets/pla pub const PAUSE_ICON: egui::ImageSource = egui::include_image!("../../assets/pause.svg"); pub const CHECK_ICON: egui::ImageSource = egui::include_image!("../../assets/check.svg"); pub const DL_ICON: egui::ImageSource = egui::include_image!("../../assets/download.svg"); +pub const INFO_ICON: egui::ImageSource = egui::include_image!("../../assets/info.svg"); pub const WARN_ICON: egui::ImageSource = egui::include_image!("../../assets/warning.svg"); +pub const ERROR_ICON: egui::ImageSource = egui::include_image!("../../assets/error.svg"); + + +pub const C_WARN: egui::Color32 = egui::Color32::from_rgb(255, 183, 0); // #ffb700 + diff --git a/xmpd-gui/src/lib.rs b/xmpd-gui/src/lib.rs index 004e10f..286c8c6 100644 --- a/xmpd-gui/src/lib.rs +++ b/xmpd-gui/src/lib.rs @@ -16,7 +16,7 @@ const W_NAME: &str = "xmpd v2.0.0a"; type Result = anyhow::Result; pub fn start() -> Result<()> { - xmpd_cache::Cache::get()?.init(); + 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| { diff --git a/xmpd-gui/src/macros.rs b/xmpd-gui/src/macros.rs index f32d7e7..3497e4c 100644 --- a/xmpd-gui/src/macros.rs +++ b/xmpd-gui/src/macros.rs @@ -21,7 +21,15 @@ macro_rules! handle_error_ui { match $val { Ok(v) => v, Err(e) => { - log::error!("Error in ui: {e:?}"); + use crate::components::CompGetter; + log::error!("Error in {}:{}: {e}", std::file!(), std::line!()); + if let Ok(mut toast) = crate::components::toast::Toast::get() { + toast.show_toast( + &format!("Error in {}:{}", std::file!(), std::line!()), + &format!("{e}"), + crate::components::toast::ToastType::Error, + ); + } return; } } diff --git a/xmpd-gui/src/main_window.rs b/xmpd-gui/src/main_window.rs index fb7a575..9776d58 100644 --- a/xmpd-gui/src/main_window.rs +++ b/xmpd-gui/src/main_window.rs @@ -1,10 +1,8 @@ use xmpd_settings::theme::Theme; -use crate::{components::{song_list, CompUi}, GuiState}; +use crate::{components::{self, song_list, CompUi}, GuiState}; pub fn draw(ctx: &egui::Context, state: &mut GuiState) -> crate::Result<()> { - // The central panel the region left after adding TopPanel's and SidePanel's - // ui.heading(format!("Songs ({})", self.manifest.get_song_count())); let theme = xmpd_settings::Settings::get()?.theme.clone(); egui::TopBottomPanel::new(egui::panel::TopBottomSide::Top, "top_nav") .frame(get_themed_frame(&theme)) @@ -16,6 +14,7 @@ pub fn draw(ctx: &egui::Context, state: &mut GuiState) -> crate::Result<()> { egui::CentralPanel::default() .frame(get_themed_frame(&theme)) .show(ctx, |ui| { + handle_error_ui!(components::toast::Toast::draw(ui, state)); let avail = ui.available_size(); ui.vertical(|ui| { crate::utils::super_separator(ui, theme.accent_color, avail.x, 2.0); @@ -23,7 +22,7 @@ pub fn draw(ctx: &egui::Context, state: &mut GuiState) -> crate::Result<()> { let main_height = avail.y * 0.91; let left_nav_width = (avail.x * 0.25).clamp(0.0, 200.0); - let song_list_width = (avail.x - left_nav_width - 35.0); + let song_list_width = avail.x - left_nav_width - 35.0; ui.horizontal(|ui| { ui.set_height(main_height); ui.group(|ui| { @@ -54,6 +53,7 @@ pub fn draw(ctx: &egui::Context, state: &mut GuiState) -> crate::Result<()> { handle_error_ui!(crate::components::player::Player::draw(ui, state)); } ); + Ok(()) } diff --git a/xmpd-gui/src/windows/debug.rs b/xmpd-gui/src/windows/debug.rs new file mode 100644 index 0000000..84a3e21 --- /dev/null +++ b/xmpd-gui/src/windows/debug.rs @@ -0,0 +1,74 @@ +use egui::RichText; + +use crate::components::{toast::{self, ToastType}, CompGetter}; + +use super::Window; + + +#[derive(Debug, Default)] +pub struct DebugW { + toast_title: String, + toast_descr: String, + toast_type: ToastType, +} + +impl Window for DebugW { + fn draw(&mut self, ui: &mut egui::Ui, _: &mut crate::GuiState) -> crate::Result<()> { + ui.group(|ui| { + ui.vertical(|ui| { + ui.label( + RichText::new("DEBUG") + .heading() + ); + ui.horizontal(|ui| { + { + ui.group(|ui| { + ui.vertical(|ui| { + ui.label( + RichText::new("Toast") + .heading() + ); + Self::add_input_field(&mut self.toast_title, ui, "Title"); + Self::add_input_field(&mut self.toast_descr, ui, "Description"); + ui.horizontal(|ui| { + ui.label("Type:"); + egui::ComboBox::from_id_source("debug_combo") + .selected_text(format!("{:?}", self.toast_type)) + .show_ui(ui, |ui| { + ui.selectable_value(&mut self.toast_type, ToastType::Info, "Info"); + ui.selectable_value(&mut self.toast_type, ToastType::Warn, "Warn"); + ui.selectable_value(&mut self.toast_type, ToastType::Error, "Error"); + } + ); + }); + if ui.button("Add").clicked() { + toast::Toast::get().unwrap().show_toast(&self.toast_title, &self.toast_descr, self.toast_type); + } + if ui.button("Throw Error").clicked() { + handle_error_ui!(Err(anyhow::anyhow!("{}: {}", self.toast_title, self.toast_descr))); + } + }); + }); + + } + }); + }); + }); + Ok(()) + } +} + +impl DebugW { + fn add_input_field(inp: &mut String, ui: &mut egui::Ui, name: &str) { + ui.horizontal(|ui|{ + ui.label(format!("{name}: ")); + ui.text_edit_singleline(inp); + }); + } + fn add_input_field_ml(inp: &mut String, ui: &mut egui::Ui, name: &str) { + ui.horizontal(|ui|{ + ui.label(format!("{name}: ")); + ui.text_edit_multiline(inp); + }); + } +} diff --git a/xmpd-gui/src/windows/mod.rs b/xmpd-gui/src/windows/mod.rs index 126e007..bb747af 100644 --- a/xmpd-gui/src/windows/mod.rs +++ b/xmpd-gui/src/windows/mod.rs @@ -2,6 +2,8 @@ use std::{collections::{HashMap, HashSet}, sync::{Arc, Mutex}}; use egui::{ViewportBuilder, ViewportId}; use crate::GuiState; +#[cfg(debug_assertions)] +mod debug; mod error; mod settings; @@ -18,7 +20,9 @@ pub trait Window: std::fmt::Debug + Send { #[derive(Debug, Clone, Hash, PartialEq, PartialOrd, Ord, Eq)] pub enum WindowId { Settings, - Error + Error, + #[cfg(debug_assertions)] + Debug } #[derive(Debug, Clone)] @@ -38,6 +42,8 @@ impl Windows { pub fn add_all_windows(&mut self) { self.add_new_window(WindowId::Error, "Error!", Box::::default()); self.add_new_window(WindowId::Settings, "Settings", Box::::default()); + #[cfg(debug_assertions)] + self.add_new_window(WindowId::Debug, "Debug", Box::::default()); } pub fn add_new_window(&mut self, id: WindowId, title: &str, cb: Box) { diff --git a/xmpd-player/Cargo.toml b/xmpd-player/Cargo.toml new file mode 100644 index 0000000..f3dc537 --- /dev/null +++ b/xmpd-player/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "xmpd-player" +edition = "2021" +version.workspace = true +repository.workspace = true +license.workspace = true +authors.workspace = true + +[dependencies] +rodio = { version = "0.20.1", features = ["symphonia-all"] } diff --git a/xmpd-player/src/lib.rs b/xmpd-player/src/lib.rs new file mode 100644 index 0000000..e69de29