rebind + change playlist update command to update entire library
This commit is contained in:
@@ -78,7 +78,7 @@ have them configurable.
|
|||||||
* `Backspace` closes the current view
|
* `Backspace` closes the current view
|
||||||
* `Shift-p` toggles playback of a track
|
* `Shift-p` toggles playback of a track
|
||||||
* `Shift-s` stops a track
|
* `Shift-s` stops a track
|
||||||
* `Shift-r` updates the playlist cache
|
* `Shift-u` updates the library cache (tracks, artists, albums, playlists)
|
||||||
* `<` and `>` play the previous or next track
|
* `<` and `>` play the previous or next track
|
||||||
* `,` and `.` to rewind or skip forward
|
* `,` and `.` to rewind or skip forward
|
||||||
* `r` to toggle repeat mode
|
* `r` to toggle repeat mode
|
||||||
|
|||||||
@@ -2,11 +2,6 @@ use queue::RepeatSetting;
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize, Debug)]
|
|
||||||
pub enum PlaylistCommands {
|
|
||||||
Update,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize, Debug)]
|
#[derive(Clone, Serialize, Deserialize, Debug)]
|
||||||
pub enum SeekInterval {
|
pub enum SeekInterval {
|
||||||
Forward,
|
Forward,
|
||||||
@@ -50,13 +45,13 @@ pub enum SeekDirection {
|
|||||||
pub enum Command {
|
pub enum Command {
|
||||||
Quit,
|
Quit,
|
||||||
TogglePlay,
|
TogglePlay,
|
||||||
Playlists(PlaylistCommands),
|
|
||||||
Stop,
|
Stop,
|
||||||
Previous,
|
Previous,
|
||||||
Next,
|
Next,
|
||||||
Clear,
|
Clear,
|
||||||
Queue,
|
Queue,
|
||||||
Play,
|
Play,
|
||||||
|
UpdateLibrary,
|
||||||
Save,
|
Save,
|
||||||
SaveQueue,
|
SaveQueue,
|
||||||
Delete,
|
Delete,
|
||||||
@@ -121,6 +116,7 @@ pub fn parse(input: &str) -> Option<Command> {
|
|||||||
"clear" => Some(Command::Clear),
|
"clear" => Some(Command::Clear),
|
||||||
"queue" => Some(Command::Queue),
|
"queue" => Some(Command::Queue),
|
||||||
"play" => Some(Command::Play),
|
"play" => Some(Command::Play),
|
||||||
|
"update" => Some(Command::UpdateLibrary),
|
||||||
"delete" => Some(Command::Delete),
|
"delete" => Some(Command::Delete),
|
||||||
"back" => Some(Command::Back),
|
"back" => Some(Command::Back),
|
||||||
"open" => args
|
"open" => args
|
||||||
@@ -210,13 +206,6 @@ pub fn parse(input: &str) -> Option<Command> {
|
|||||||
.map(|amount| Command::Seek(SeekDirection::Absolute(amount))),
|
.map(|amount| Command::Seek(SeekDirection::Absolute(amount))),
|
||||||
}),
|
}),
|
||||||
"focus" => args.get(0).map(|target| Command::Focus(target.to_string())),
|
"focus" => args.get(0).map(|target| Command::Focus(target.to_string())),
|
||||||
"playlists" => args
|
|
||||||
.get(0)
|
|
||||||
.and_then(|action| match *action {
|
|
||||||
"update" => Some(PlaylistCommands::Update),
|
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
.map(Command::Playlists),
|
|
||||||
"save" => args.get(0).map(|target| match *target {
|
"save" => args.get(0).map(|target| match *target {
|
||||||
"queue" => Command::SaveQueue,
|
"queue" => Command::SaveQueue,
|
||||||
_ => Command::Save,
|
_ => Command::Save,
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ use std::collections::HashMap;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use command::{
|
use command::{Command, GotoMode, MoveMode, SeekDirection, ShiftMode, TargetMode};
|
||||||
Command, GotoMode, MoveMode, PlaylistCommands, SeekDirection, ShiftMode, TargetMode,
|
|
||||||
};
|
|
||||||
use cursive::event::{Event, Key};
|
use cursive::event::{Event, Key};
|
||||||
use cursive::traits::View;
|
use cursive::traits::View;
|
||||||
use cursive::views::ViewRef;
|
use cursive::views::ViewRef;
|
||||||
@@ -82,10 +80,8 @@ impl CommandManager {
|
|||||||
self.queue.clear();
|
self.queue.clear();
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
Command::Playlists(mode) => {
|
Command::UpdateLibrary => {
|
||||||
match mode {
|
self.library.update_library();
|
||||||
PlaylistCommands::Update => self.library.update_playlists(),
|
|
||||||
}
|
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
Command::TogglePlay => {
|
Command::TogglePlay => {
|
||||||
@@ -193,10 +189,7 @@ impl CommandManager {
|
|||||||
|
|
||||||
kb.insert("q".into(), Command::Quit);
|
kb.insert("q".into(), Command::Quit);
|
||||||
kb.insert("Shift+p".into(), Command::TogglePlay);
|
kb.insert("Shift+p".into(), Command::TogglePlay);
|
||||||
kb.insert(
|
kb.insert("Shift+u".into(), Command::UpdateLibrary);
|
||||||
"Shift+r".into(),
|
|
||||||
Command::Playlists(PlaylistCommands::Update),
|
|
||||||
);
|
|
||||||
kb.insert("Shift+s".into(), Command::Stop);
|
kb.insert("Shift+s".into(), Command::Stop);
|
||||||
kb.insert("<".into(), Command::Previous);
|
kb.insert("<".into(), Command::Previous);
|
||||||
kb.insert(">".into(), Command::Next);
|
kb.insert(">".into(), Command::Next);
|
||||||
|
|||||||
134
src/library.rs
134
src/library.rs
@@ -28,7 +28,7 @@ pub struct Library {
|
|||||||
pub albums: Arc<RwLock<Vec<Album>>>,
|
pub albums: Arc<RwLock<Vec<Album>>>,
|
||||||
pub artists: Arc<RwLock<Vec<Artist>>>,
|
pub artists: Arc<RwLock<Vec<Artist>>>,
|
||||||
pub playlists: Arc<RwLock<Vec<Playlist>>>,
|
pub playlists: Arc<RwLock<Vec<Playlist>>>,
|
||||||
is_done: Arc<RwLock<bool>>,
|
pub is_done: Arc<RwLock<bool>>,
|
||||||
user_id: Option<String>,
|
user_id: Option<String>,
|
||||||
ev: EventManager,
|
ev: EventManager,
|
||||||
spotify: Arc<Spotify>,
|
spotify: Arc<Spotify>,
|
||||||
@@ -51,71 +51,7 @@ impl Library {
|
|||||||
use_nerdfont,
|
use_nerdfont,
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
library.update_library();
|
||||||
let library = library.clone();
|
|
||||||
thread::spawn(move || {
|
|
||||||
let t_tracks = {
|
|
||||||
let library = library.clone();
|
|
||||||
thread::spawn(move || {
|
|
||||||
library
|
|
||||||
.load_cache(config::cache_path(CACHE_TRACKS), library.tracks.clone());
|
|
||||||
library.fetch_tracks();
|
|
||||||
library
|
|
||||||
.save_cache(config::cache_path(CACHE_TRACKS), library.tracks.clone());
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
let t_albums = {
|
|
||||||
let library = library.clone();
|
|
||||||
thread::spawn(move || {
|
|
||||||
library
|
|
||||||
.load_cache(config::cache_path(CACHE_ALBUMS), library.albums.clone());
|
|
||||||
library.fetch_albums();
|
|
||||||
library
|
|
||||||
.save_cache(config::cache_path(CACHE_ALBUMS), library.albums.clone());
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
let t_artists = {
|
|
||||||
let library = library.clone();
|
|
||||||
thread::spawn(move || {
|
|
||||||
library
|
|
||||||
.load_cache(config::cache_path(CACHE_ARTISTS), library.artists.clone());
|
|
||||||
library.fetch_artists();
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
let t_playlists = {
|
|
||||||
let library = library.clone();
|
|
||||||
thread::spawn(move || {
|
|
||||||
library.load_cache(
|
|
||||||
config::cache_path(CACHE_PLAYLISTS),
|
|
||||||
library.playlists.clone(),
|
|
||||||
);
|
|
||||||
library.fetch_playlists();
|
|
||||||
library.save_cache(
|
|
||||||
config::cache_path(CACHE_PLAYLISTS),
|
|
||||||
library.playlists.clone(),
|
|
||||||
);
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
t_tracks.join().unwrap();
|
|
||||||
t_artists.join().unwrap();
|
|
||||||
|
|
||||||
library.populate_artists();
|
|
||||||
library.save_cache(config::cache_path(CACHE_ARTISTS), library.artists.clone());
|
|
||||||
|
|
||||||
t_albums.join().unwrap();
|
|
||||||
t_playlists.join().unwrap();
|
|
||||||
|
|
||||||
let mut is_done = library.is_done.write().unwrap();
|
|
||||||
*is_done = true;
|
|
||||||
|
|
||||||
library.ev.trigger();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
library
|
library
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,7 +144,8 @@ impl Library {
|
|||||||
debug!("saving {} tracks to {}", tracks.len(), id);
|
debug!("saving {} tracks to {}", tracks.len(), id);
|
||||||
self.spotify.overwrite_playlist(id, &tracks);
|
self.spotify.overwrite_playlist(id, &tracks);
|
||||||
|
|
||||||
self.update_playlists();
|
self.fetch_playlists();
|
||||||
|
self.save_cache(config::cache_path(CACHE_PLAYLISTS), self.playlists.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save_playlist(&self, name: &str, tracks: &[Track]) {
|
pub fn save_playlist(&self, name: &str, tracks: &[Track]) {
|
||||||
@@ -219,9 +156,66 @@ impl Library {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_playlists(&self) {
|
pub fn update_library(&self) {
|
||||||
self.fetch_playlists();
|
*self.is_done.write().unwrap() = false;
|
||||||
self.save_cache(config::cache_path(CACHE_PLAYLISTS), self.playlists.clone());
|
|
||||||
|
let library = self.clone();
|
||||||
|
thread::spawn(move || {
|
||||||
|
let t_tracks = {
|
||||||
|
let library = library.clone();
|
||||||
|
thread::spawn(move || {
|
||||||
|
library.load_cache(config::cache_path(CACHE_TRACKS), library.tracks.clone());
|
||||||
|
library.fetch_tracks();
|
||||||
|
library.save_cache(config::cache_path(CACHE_TRACKS), library.tracks.clone());
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
let t_albums = {
|
||||||
|
let library = library.clone();
|
||||||
|
thread::spawn(move || {
|
||||||
|
library.load_cache(config::cache_path(CACHE_ALBUMS), library.albums.clone());
|
||||||
|
library.fetch_albums();
|
||||||
|
library.save_cache(config::cache_path(CACHE_ALBUMS), library.albums.clone());
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
let t_artists = {
|
||||||
|
let library = library.clone();
|
||||||
|
thread::spawn(move || {
|
||||||
|
library.load_cache(config::cache_path(CACHE_ARTISTS), library.artists.clone());
|
||||||
|
library.fetch_artists();
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
let t_playlists = {
|
||||||
|
let library = library.clone();
|
||||||
|
thread::spawn(move || {
|
||||||
|
library.load_cache(
|
||||||
|
config::cache_path(CACHE_PLAYLISTS),
|
||||||
|
library.playlists.clone(),
|
||||||
|
);
|
||||||
|
library.fetch_playlists();
|
||||||
|
library.save_cache(
|
||||||
|
config::cache_path(CACHE_PLAYLISTS),
|
||||||
|
library.playlists.clone(),
|
||||||
|
);
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
t_tracks.join().unwrap();
|
||||||
|
t_artists.join().unwrap();
|
||||||
|
|
||||||
|
library.populate_artists();
|
||||||
|
library.save_cache(config::cache_path(CACHE_ARTISTS), library.artists.clone());
|
||||||
|
|
||||||
|
t_albums.join().unwrap();
|
||||||
|
t_playlists.join().unwrap();
|
||||||
|
|
||||||
|
let mut is_done = library.is_done.write().unwrap();
|
||||||
|
*is_done = true;
|
||||||
|
|
||||||
|
library.ev.trigger();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fetch_playlists(&self) {
|
fn fetch_playlists(&self) {
|
||||||
|
|||||||
@@ -89,6 +89,12 @@ impl View for StatusBar {
|
|||||||
printer.print((1, 1), &state_icon);
|
printer.print((1, 1), &state_icon);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let updating = if !*self.library.is_done.read().unwrap() {
|
||||||
|
if self.use_nerdfont { "\u{f9e5} " } else { "[U] " }
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
};
|
||||||
|
|
||||||
let repeat = if self.use_nerdfont {
|
let repeat = if self.use_nerdfont {
|
||||||
match self.queue.get_repeat() {
|
match self.queue.get_repeat() {
|
||||||
RepeatSetting::None => "",
|
RepeatSetting::None => "",
|
||||||
@@ -137,7 +143,8 @@ impl View for StatusBar {
|
|||||||
""
|
""
|
||||||
};
|
};
|
||||||
|
|
||||||
let right = repeat.to_string()
|
let right = updating.to_string()
|
||||||
|
+ repeat
|
||||||
+ shuffle
|
+ shuffle
|
||||||
+ saved
|
+ saved
|
||||||
+ &format!("{} / {} ", formatted_elapsed, t.duration_str());
|
+ &format!("{} / {} ", formatted_elapsed, t.duration_str());
|
||||||
@@ -153,7 +160,7 @@ impl View for StatusBar {
|
|||||||
printer.print((0, 0), &"━".repeat(duration_width + 1));
|
printer.print((0, 0), &"━".repeat(duration_width + 1));
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
let right = repeat.to_string() + shuffle;
|
let right = updating.to_string() + repeat + shuffle;
|
||||||
let offset = HAlign::Right.get_offset(right.width(), printer.size.x);
|
let offset = HAlign::Right.get_offset(right.width(), printer.size.x);
|
||||||
|
|
||||||
printer.with_color(style, |printer| {
|
printer.with_color(style, |printer| {
|
||||||
|
|||||||
Reference in New Issue
Block a user