diff --git a/README.md b/README.md index 050e37c..146a112 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ have them configurable. * `F1`: Debug log * `F2`: Queue * `F3`: Search + * `F4`: Playlists, then hit `Return` to queue all songs from the playlist * Tracks can be played using `Return` and queued using `Space` * `Shift-p` toggles playback of a track * `Shift-s` stops a track diff --git a/src/main.rs b/src/main.rs index 771c316..0aca9d2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -132,6 +132,10 @@ fn main() { let search = ui::search::SearchView::new(spotify.clone(), queue.clone()); cursive.add_fullscreen_layer(search.view); + let playlistscreen = cursive.add_active_screen(); + let playlists = ui::playlist::PlaylistView::new(queue.clone(), spotify.clone()); + cursive.add_fullscreen_layer(playlists.view); + let queuescreen = cursive.add_active_screen(); let mut queueview = ui::queue::QueueView::new(queue.clone(), spotify.clone()); cursive.add_fullscreen_layer(queueview.view.take().unwrap()); @@ -157,6 +161,10 @@ fn main() { s.set_screen(searchscreen); }); + cursive.add_global_callback(Key::F4, move |s| { + s.set_screen(playlistscreen); + }); + // cursive event loop while cursive.is_running() { cursive.step(); diff --git a/src/spotify.rs b/src/spotify.rs index 7d5bf81..0dc2b13 100644 --- a/src/spotify.rs +++ b/src/spotify.rs @@ -12,6 +12,8 @@ use librespot::playback::player::Player; use rspotify::spotify::client::Spotify as SpotifyAPI; use rspotify::spotify::model::search::SearchTracks; +use rspotify::spotify::model::playlist::{SimplifiedPlaylist, PlaylistTrack}; +use rspotify::spotify::model::page::Page; use failure::Error; @@ -49,6 +51,7 @@ pub struct Spotify { pub api: SpotifyAPI, channel: mpsc::UnboundedSender, events: EventManager, + user: String, } struct Worker { @@ -184,6 +187,7 @@ impl Spotify { api: api, channel: tx, events: events, + user: user, } } @@ -223,6 +227,14 @@ impl Spotify { self.api.search_track(query, limit, offset, None) } + pub fn current_user_playlist(&self, limit: u32, offset: u32) -> Result, Error> { + self.api.current_user_playlists(limit, offset) + } + + pub fn user_playlist_tracks(&self, playlist_id: &str) -> Result, Error> { + self.api.user_playlist_tracks(&self.user, playlist_id, None, 50, 0, None) + } + pub fn load(&self, track: SpotifyId) { info!("loading track: {:?}", track); self.channel diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 2b157e5..da2ab26 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -1,3 +1,4 @@ pub mod queue; pub mod search; pub mod trackbutton; +pub mod playlist; diff --git a/src/ui/playlist.rs b/src/ui/playlist.rs new file mode 100644 index 0000000..b0b4ca0 --- /dev/null +++ b/src/ui/playlist.rs @@ -0,0 +1,42 @@ +use std::sync::{Arc, Mutex}; + +use cursive::direction::Orientation; +use cursive::traits::Boxable; +use cursive::views::*; + +use spotify::Spotify; +use queue::Queue; + +pub struct PlaylistView { + pub view: Panel, +} + +impl PlaylistView { + pub fn new(queue: Arc>, spotify: Arc) -> PlaylistView { + let mut results = SelectView::new(); + let playlists = spotify.current_user_playlist(50, 0).unwrap().items; + + for playlist in &playlists { + results.add_item(playlist.name.clone(), playlist.id.clone()); + } + + let spotify_ref = spotify.clone(); + results.set_on_submit(move |_s, id| { + let tracks = spotify_ref.user_playlist_tracks(id).unwrap().items; + + let mut l_queue = queue.lock().expect("Could not aquire lock"); + for playlist_track in tracks { + l_queue.enqueue(playlist_track.track.clone()); + } + }); + + let scrollable = ScrollView::new(results).full_width().full_height(); + let layout = LinearLayout::new(Orientation::Vertical).child(scrollable); + let rootpanel = Panel::new(layout).title("Playlists"); + + PlaylistView { + view: rootpanel, + } + } +} +