implement playlist caching
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
use std::sync::{Arc, Mutex, RwLock};
|
||||
use std::thread;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use cursive::direction::Orientation;
|
||||
use cursive::event::Key;
|
||||
@@ -7,46 +6,26 @@ use cursive::traits::Boxable;
|
||||
use cursive::traits::Identifiable;
|
||||
use cursive::views::*;
|
||||
use cursive::Cursive;
|
||||
use rspotify::spotify::model::playlist::SimplifiedPlaylist;
|
||||
|
||||
use events::{Event, EventManager};
|
||||
use playlists::{Playlist, PlaylistEvent, Playlists};
|
||||
use queue::Queue;
|
||||
use spotify::Spotify;
|
||||
use track::Track;
|
||||
use ui::splitbutton::SplitButton;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Playlist {
|
||||
meta: SimplifiedPlaylist,
|
||||
tracks: Vec<Track>,
|
||||
}
|
||||
|
||||
pub enum PlaylistEvent {
|
||||
NewList(Playlist),
|
||||
}
|
||||
|
||||
pub struct PlaylistView {
|
||||
pub view: Option<BoxView<ScrollView<IdView<LinearLayout>>>>,
|
||||
queue: Arc<Mutex<Queue>>,
|
||||
playlists: Arc<RwLock<Vec<Playlist>>>,
|
||||
playlists: Playlists,
|
||||
}
|
||||
|
||||
impl PlaylistView {
|
||||
pub fn new(ev: EventManager, queue: Arc<Mutex<Queue>>, spotify: Arc<Spotify>) -> PlaylistView {
|
||||
pub fn new(playlists: &Playlists, queue: Arc<Mutex<Queue>>) -> PlaylistView {
|
||||
let playlists_view = LinearLayout::new(Orientation::Vertical).with_id("playlists");
|
||||
let scrollable = ScrollView::new(playlists_view).full_screen();
|
||||
let playlists = Arc::new(RwLock::new(Vec::new()));
|
||||
|
||||
{
|
||||
let spotify = spotify.clone();
|
||||
let playlists = playlists.clone();
|
||||
Self::load_playlists(ev, spotify, playlists);
|
||||
}
|
||||
|
||||
PlaylistView {
|
||||
view: Some(scrollable),
|
||||
queue: queue,
|
||||
playlists: playlists,
|
||||
playlists: playlists.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,68 +65,6 @@ impl PlaylistView {
|
||||
button
|
||||
}
|
||||
|
||||
fn load_playlist(list: &SimplifiedPlaylist, spotify: Arc<Spotify>) -> Playlist {
|
||||
debug!("got list: {}", list.name);
|
||||
let id = list.id.clone();
|
||||
|
||||
let mut collected_tracks = Vec::new();
|
||||
|
||||
let mut tracks_result = spotify.user_playlist_tracks(&id, 100, 0).ok();
|
||||
while let Some(ref tracks) = tracks_result.clone() {
|
||||
for listtrack in &tracks.items {
|
||||
collected_tracks.push(Track::new(&listtrack.track));
|
||||
}
|
||||
debug!("got {} tracks", tracks.items.len());
|
||||
|
||||
// load next batch if necessary
|
||||
tracks_result = match tracks.next {
|
||||
Some(_) => {
|
||||
debug!("requesting tracks again..");
|
||||
spotify
|
||||
.user_playlist_tracks(&id, 100, tracks.offset + tracks.items.len() as u32)
|
||||
.ok()
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
Playlist {
|
||||
meta: list.clone(),
|
||||
tracks: collected_tracks,
|
||||
}
|
||||
}
|
||||
|
||||
fn load_playlists(
|
||||
ev: EventManager,
|
||||
spotify: Arc<Spotify>,
|
||||
playlists: Arc<RwLock<Vec<Playlist>>>,
|
||||
) {
|
||||
thread::spawn(move || {
|
||||
debug!("loading playlists");
|
||||
let mut lists_result = spotify.current_user_playlist(50, 0).ok();
|
||||
while let Some(ref lists) = lists_result.clone() {
|
||||
for list in &lists.items {
|
||||
let playlist = Self::load_playlist(&list, spotify.clone());
|
||||
ev.send(Event::Playlist(PlaylistEvent::NewList(playlist.clone())));
|
||||
playlists
|
||||
.write()
|
||||
.expect("could not acquire write lock on playlists")
|
||||
.push(playlist);
|
||||
}
|
||||
|
||||
// load next batch if necessary
|
||||
lists_result = match lists.next {
|
||||
Some(_) => {
|
||||
debug!("requesting playlists again..");
|
||||
spotify
|
||||
.current_user_playlist(50, lists.offset + lists.items.len() as u32)
|
||||
.ok()
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn clear_playlists(&self, playlists: &mut ViewRef<LinearLayout>) {
|
||||
while playlists.len() > 0 {
|
||||
playlists.remove_child(0);
|
||||
@@ -159,12 +76,13 @@ impl PlaylistView {
|
||||
if let Some(mut playlists) = view_ref {
|
||||
self.clear_playlists(&mut playlists);
|
||||
|
||||
for list in self
|
||||
let playlist_store = &self
|
||||
.playlists
|
||||
.store
|
||||
.read()
|
||||
.expect("could not acquire read lock on playlists")
|
||||
.iter()
|
||||
{
|
||||
.expect("can't readlock playlists");
|
||||
info!("repopulating {} lists", playlist_store.playlists.len());
|
||||
for list in &playlist_store.playlists {
|
||||
let button = self.create_button(&list);
|
||||
playlists.add_child(button);
|
||||
}
|
||||
@@ -176,9 +94,13 @@ impl PlaylistView {
|
||||
|
||||
if let Some(mut playlists) = view_ref {
|
||||
match event {
|
||||
PlaylistEvent::NewList(list) => {
|
||||
PlaylistEvent::NewList(index, list) => {
|
||||
let button = self.create_button(&list);
|
||||
playlists.add_child(button);
|
||||
|
||||
if let Some(_) = playlists.get_child(index) {
|
||||
playlists.remove_child(index);
|
||||
}
|
||||
playlists.insert_child(index, button);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user