From fd8abd4fc00abfb910ceda274f2e12634672a6bb Mon Sep 17 00:00:00 2001 From: Nuno Pereira Date: Mon, 13 Mar 2023 17:17:27 +0000 Subject: [PATCH] Added lyrics fetcher --- Cargo.lock | 165 ++++++++++++++++++++++++++++++++++++++++-- Cargo.toml | 1 + src/lyrics.rs | 52 +++++++++++++ src/lyrics/mod.rs | 0 src/lyrics_fetcher.rs | 23 ++++++ src/main.rs | 2 + src/ui/lyrics.rs | 58 +++++++++------ 7 files changed, 274 insertions(+), 27 deletions(-) create mode 100644 src/lyrics.rs delete mode 100644 src/lyrics/mod.rs create mode 100644 src/lyrics_fetcher.rs diff --git a/Cargo.lock b/Cargo.lock index b3d295edf..0e513c1c0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -755,8 +755,22 @@ dependencies = [ ] [[package]] -name = "crc32fast" -version = "1.4.0" +name = "crossbeam" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2801af0d36612ae591caa9568261fddce32ce6e08a7275ea334a06a4ad021a2c" +dependencies = [ + "cfg-if", + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" dependencies = [ @@ -772,6 +786,40 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset 0.8.0", + "scopeguard", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.19" @@ -856,6 +904,22 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "cursive-async-view" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "192c058a725c80d9759b3e8957d6ee9e169a0b46c9f11216ec8c8d7990644761" +dependencies = [ + "crossbeam", + "cursive_core", + "doc-comment", + "interpolation", + "lazy_static", + "log", + "num 0.4.0", + "send_wrapper", +] + [[package]] name = "cursive_buffered_backend" version = "0.6.1" @@ -1030,8 +1094,14 @@ dependencies = [ ] [[package]] -name = "dlib" -version = "0.5.2" +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + +[[package]] +name = "downcast-rs" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" dependencies = [ @@ -1788,6 +1858,23 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "interpolation" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3b7357d2bbc5ee92f8e899ab645233e43d21407573cceb37fed8bc3dede2c02" + +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys", +] + [[package]] name = "ioctl-rs" version = "0.2.0" @@ -2170,7 +2257,16 @@ dependencies = [ [[package]] name = "memoffset" -version = "0.9.1" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +dependencies = [ + "autocfg", +] + +[[package]] +name = "mime" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" dependencies = [ @@ -2238,6 +2334,7 @@ dependencies = [ "clap", "crossbeam-channel", "cursive", + "cursive-async-view", "cursive_buffered_backend", "fern", "futures", @@ -2360,7 +2457,45 @@ dependencies = [ "cfg-if", "cfg_aliases", "libc", +<<<<<<< HEAD "memoffset 0.9.1", +||||||| parent of 53c07a7 (Added lyrics fetcher) + "memoffset 0.6.5", +] + +[[package]] +name = "nix" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", + "memoffset 0.7.1", + "static_assertions", +======= +<<<<<<< HEAD + "memoffset 0.6.5", +] + +[[package]] +name = "nix" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", + "memoffset 0.7.1", + "static_assertions", +||||||| parent of 1f462a4 (Added lyrics fetcher) + "memoffset", +======= + "memoffset 0.6.5", +>>>>>>> 1f462a4 (Added lyrics fetcher) +>>>>>>> 53c07a7 (Added lyrics fetcher) ] [[package]] @@ -2406,7 +2541,14 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" dependencies = [ +<<<<<<< HEAD "num-complex 0.4.6", +||||||| parent of 53c07a7 (Added lyrics fetcher) + "num-complex 0.4.3", +======= + "num-bigint 0.4.3", + "num-complex 0.4.3", +>>>>>>> 53c07a7 (Added lyrics fetcher) "num-integer", "num-iter", "num-rational 0.4.2", @@ -2509,6 +2651,13 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ +<<<<<<< HEAD +||||||| parent of 53c07a7 (Added lyrics fetcher) + "autocfg", +======= + "autocfg", + "num-bigint 0.4.3", +>>>>>>> 53c07a7 (Added lyrics fetcher) "num-integer", "num-traits", ] @@ -3434,6 +3583,12 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +[[package]] +name = "send_wrapper" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "930c0acf610d3fdb5e2ab6213019aaa04e227ebe9547b0649ba599b16d788bd7" + [[package]] name = "serde" version = "1.0.203" diff --git a/Cargo.toml b/Cargo.toml index de662c52a..32c107742 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -68,6 +68,7 @@ toml = "0.8" unicode-width = "0.1.13" url = "2.5" cursive_buffered_backend = "0.6.1" +cursive-async-view = "0.6.0" [target.'cfg(unix)'.dependencies] signal-hook = "0.3.0" diff --git a/src/lyrics.rs b/src/lyrics.rs new file mode 100644 index 000000000..a942819a1 --- /dev/null +++ b/src/lyrics.rs @@ -0,0 +1,52 @@ +use std::sync::Arc; + +use crate::{ + lyrics_fetcher::LyricsFetcher, + model::{playable::Playable, track::Track}, + queue::Queue, +}; + +#[derive(Clone)] +pub struct LyricsManager { + queue: Arc, + fetcher: LyricsFetcher, + // TODO: add a cache +} + +impl LyricsManager { + pub fn new(queue: Arc, fetcher: LyricsFetcher) -> Self { + LyricsManager { queue, fetcher } + } + + /// Saves the given lyrics to the user's filesystem. + /// + /// Returns an optional message indicating the outcome of this operation. + pub fn save_lyrics(&self, lyrics: String) -> Option { + Some("".to_string()) + } + + /// Fetches and returns the lyrics of the given track + pub fn get_lyrics(&self, track: Track) -> String { + // TODO: implement caching + + self.fetcher.fetch(&track) + } + + /// Fetches and returns the lyrics of the currently playing track + pub fn get_lyrics_for_current(&self) -> String { + match self.get_current_track() { + None => String::from("No track currently playing: could not get lyrics"), + Some(track) => self.get_lyrics(track), + } + } + + /// Returns the track being played currently, or nothing if the user is listening to a podcast episodes + fn get_current_track(&self) -> Option { + let playable = self.queue.get_current().unwrap(); + + match playable { + Playable::Track(track) => Some(track), + Playable::Episode(_) => None, + } + } +} diff --git a/src/lyrics/mod.rs b/src/lyrics/mod.rs deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/lyrics_fetcher.rs b/src/lyrics_fetcher.rs new file mode 100644 index 000000000..9761ef3b4 --- /dev/null +++ b/src/lyrics_fetcher.rs @@ -0,0 +1,23 @@ +use crate::model::track::Track; + +#[derive(Clone)] +pub struct LyricsFetcher {} + +impl LyricsFetcher { + pub fn new() -> LyricsFetcher { + Self {} + } + + /// Fetches the lyrics of the given song using the specified lyrics source + pub fn fetch(&self, track: &Track) -> String { + // std::thread::sleep(std::time::Duration::from_secs(2)); + + format!("Sample Lyrics for {}\n", track.title) + } +} + +impl Default for LyricsFetcher { + fn default() -> Self { + LyricsFetcher::new() // TODO: check the prefered fetcher + } +} diff --git a/src/main.rs b/src/main.rs index b8798fd51..40eb4ec6a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,6 +19,8 @@ mod config; mod events; mod ext_traits; mod library; +mod lyrics; +mod lyrics_fetcher; mod model; mod panic; mod queue; diff --git a/src/ui/lyrics.rs b/src/ui/lyrics.rs index 940919437..bbd93ac58 100644 --- a/src/ui/lyrics.rs +++ b/src/ui/lyrics.rs @@ -4,43 +4,61 @@ use cursive::{ theme::Effect, utils::markup::StyledString, view::ViewWrapper, - views::{ScrollView, TextView}, + views::{DummyView, LinearLayout, ScrollView, TextView}, }; -use crate::{commands::CommandResult, queue::Queue, traits::ViewExt, command::Command}; +use crate::{commands::CommandResult, lyrics::LyricsManager, traits::ViewExt, command::Command}; pub struct LyricsView { - queue: Arc, - view: ScrollView, + manager: Arc, + view: LinearLayout, } impl LyricsView { - pub fn new(queue: Arc) -> LyricsView { + pub fn new(manager: Arc) -> LyricsView { let mut text = StyledString::styled("Keybindings\n\n", Effect::Bold); let note = format!( "Custom bindings can be set in the {} file within the [keybindings] section.\n\n", "test" ); + + // TODO: fixme + let content = String::from(""); + text.append(StyledString::styled(note, Effect::Italic)); + text.append(content); - LyricsView { - queue, - view: ScrollView::new(TextView::new(text)), - } - } + text.append("\n\n"); + text.append(StyledString::styled( + manager.get_lyrics_for_current(), + Effect::Simple, + )); - pub fn save_lyrics(&mut self, lyrics: String) -> Result { - // println!("Saving Lyrics: {}", lyrics); + let lyrics_view = ScrollView::new(TextView::new(text).center()); - self.view.get_inner_mut().set_content(lyrics); + let view = LinearLayout::vertical() + .child(TextView::new("Title").center()) + .child(TextView::new("Authors").center()) + .child(TextView::new("Album").center()) + .child(DummyView) + .child(lyrics_view); - Ok(CommandResult::Consumed(None)) + LyricsView { manager, view } + } + + /// Saves the lyrics of the current song + pub fn save_lyrics(&self) -> Result { + let result = self + .manager + .save_lyrics(self.manager.get_lyrics_for_current()); + + Ok(CommandResult::Consumed(result)) } } impl ViewWrapper for LyricsView { - wrap_impl!(self.view: ScrollView); + wrap_impl!(self.view: LinearLayout); } impl ViewExt for LyricsView { @@ -49,9 +67,7 @@ impl ViewExt for LyricsView { } fn title_sub(&self) -> String { - let current_track = self.queue.get_current().unwrap(); - - format!("{}", current_track) + "".to_string() } fn on_leave(&self) {} @@ -62,10 +78,8 @@ impl ViewExt for LyricsView { cmd: &Command, ) -> Result { match cmd { - Command::Save => self.save_lyrics(format!("{}", cmd)), - Command::Quit => Ok(CommandResult::Ignored), - Command::Focus(_) => Ok(CommandResult::Ignored), - _ => Ok(CommandResult::Ignored) + Command::Save => self.save_lyrics(), + _ => Ok(CommandResult::Ignored), } } }