implement playlist update on demand + prune stale playlists
This commit is contained in:
@@ -42,6 +42,7 @@ have them configurable.
|
||||
* Tracks and playlists can be played using `Return` and queued using `Space`
|
||||
* `Shift-p` toggles playback of a track
|
||||
* `Shift-s` stops a track
|
||||
* `Shift-r` updates the playlist cache
|
||||
* `<` and `>` play the previous or next track, respectively
|
||||
* `q` quits ncspot
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ use std::sync::Arc;
|
||||
use cursive::event::{Event, Key};
|
||||
use cursive::Cursive;
|
||||
|
||||
use playlists::Playlist;
|
||||
use playlists::{Playlist, Playlists};
|
||||
use queue::Queue;
|
||||
use spotify::Spotify;
|
||||
use track::Track;
|
||||
@@ -39,7 +39,12 @@ impl CommandManager {
|
||||
self.commands.insert(name, cb);
|
||||
}
|
||||
|
||||
pub fn register_all(&mut self, spotify: Arc<Spotify>, queue: Arc<Queue>) {
|
||||
pub fn register_all(
|
||||
&mut self,
|
||||
spotify: Arc<Spotify>,
|
||||
queue: Arc<Queue>,
|
||||
playlists: Arc<Playlists>,
|
||||
) {
|
||||
self.register(
|
||||
"quit",
|
||||
vec!["q", "x"],
|
||||
@@ -120,10 +125,17 @@ impl CommandManager {
|
||||
self.register(
|
||||
"playlists",
|
||||
vec!["lists"],
|
||||
Box::new(move |s, _args| {
|
||||
s.call_on_id("main", |v: &mut Layout| {
|
||||
v.set_view("playlists");
|
||||
});
|
||||
Box::new(move |s, args| {
|
||||
if let Some(arg) = args.get(0) {
|
||||
if arg == "update" {
|
||||
playlists.fetch_playlists();
|
||||
playlists.save_cache();
|
||||
}
|
||||
} else {
|
||||
s.call_on_id("main", |v: &mut Layout| {
|
||||
v.set_view("playlists");
|
||||
});
|
||||
}
|
||||
Ok(None)
|
||||
}),
|
||||
);
|
||||
@@ -342,6 +354,7 @@ impl CommandManager {
|
||||
|
||||
kb.insert("q".into(), "quit".into());
|
||||
kb.insert("P".into(), "toggle".into());
|
||||
kb.insert("R".into(), "playlists update".into());
|
||||
kb.insert("S".into(), "stop".into());
|
||||
kb.insert("<".into(), "previous".into());
|
||||
kb.insert(">".into(), "next".into());
|
||||
|
||||
18
src/main.rs
18
src/main.rs
@@ -29,7 +29,7 @@ use std::process;
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
|
||||
use clap::{Arg, App};
|
||||
use clap::{App, Arg};
|
||||
use cursive::traits::Identifiable;
|
||||
use cursive::Cursive;
|
||||
|
||||
@@ -80,12 +80,14 @@ fn main() {
|
||||
.version("0.1.0")
|
||||
.author("Henrik Friedrichsen <henrik@affekt.org>")
|
||||
.about("cross-platform ncurses Spotify client")
|
||||
.arg(Arg::with_name("debug")
|
||||
.short("d")
|
||||
.long("debug")
|
||||
.value_name("FILE")
|
||||
.help("Enable debug logging to the specified file")
|
||||
.takes_value(true))
|
||||
.arg(
|
||||
Arg::with_name("debug")
|
||||
.short("d")
|
||||
.long("debug")
|
||||
.value_name("FILE")
|
||||
.help("Enable debug logging to the specified file")
|
||||
.takes_value(true),
|
||||
)
|
||||
.get_matches();
|
||||
|
||||
if let Some(filename) = matches.value_of("debug") {
|
||||
@@ -181,7 +183,7 @@ fn main() {
|
||||
cursive.add_fullscreen_layer(layout.with_id("main"));
|
||||
|
||||
let mut cmd_manager = CommandManager::new();
|
||||
cmd_manager.register_all(spotify.clone(), queue.clone());
|
||||
cmd_manager.register_all(spotify.clone(), queue.clone(), playlists.clone());
|
||||
|
||||
let cmd_manager = Arc::new(cmd_manager);
|
||||
CommandManager::register_keybindings(cmd_manager.clone(), &mut cursive, cfg.keybindings);
|
||||
|
||||
@@ -12,7 +12,7 @@ use spotify::Spotify;
|
||||
use track::Track;
|
||||
use traits::ListItem;
|
||||
|
||||
#[derive(Clone, Deserialize, Serialize)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct Playlist {
|
||||
pub meta: SimplifiedPlaylist,
|
||||
pub tracks: Vec<Track>,
|
||||
@@ -144,9 +144,16 @@ impl Playlists {
|
||||
|
||||
pub fn fetch_playlists(&self) {
|
||||
debug!("loading playlists");
|
||||
let mut stale_lists = self.store.read().unwrap().clone();
|
||||
|
||||
let mut lists_result = self.spotify.current_user_playlist(50, 0);
|
||||
while let Some(ref lists) = lists_result.clone() {
|
||||
for remote in &lists.items {
|
||||
// remove from stale playlists so we won't prune it later on
|
||||
if let Some(index) = stale_lists.iter().position(|x| x.meta.id == remote.id) {
|
||||
stale_lists.remove(index);
|
||||
}
|
||||
|
||||
if self.needs_download(remote) {
|
||||
info!("updating playlist {}", remote.name);
|
||||
let playlist = Self::process_playlist(&remote, &self.spotify);
|
||||
@@ -166,5 +173,21 @@ impl Playlists {
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
// remove stale playlists
|
||||
for stale in stale_lists {
|
||||
let index = self
|
||||
.store
|
||||
.read()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.position(|x| x.meta.id == stale.meta.id);
|
||||
if let Some(index) = index {
|
||||
debug!("removing stale list: {:?}", stale.meta.name);
|
||||
self.store.write().unwrap().remove(index);
|
||||
}
|
||||
}
|
||||
// trigger redraw
|
||||
self.ev.trigger();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,6 +215,7 @@ impl Spotify {
|
||||
fn create_session(core: &mut Core, credentials: Credentials) -> Session {
|
||||
let session_config = SessionConfig::default();
|
||||
let handle = core.handle();
|
||||
debug!("opening spotify session");
|
||||
core.run(Session::connect(session_config, credentials, None, handle))
|
||||
.ok()
|
||||
.unwrap()
|
||||
|
||||
Reference in New Issue
Block a user