@@ -108,7 +108,15 @@ impl CommandManager {
|
||||
Command::Quit => {
|
||||
let queue = self.queue.queue.read().expect("can't readlock queue");
|
||||
self.config.with_state_mut(move |mut s| {
|
||||
s.queue = queue.clone();
|
||||
debug!(
|
||||
"saving state, {} items, current track: {:?}",
|
||||
queue.len(),
|
||||
self.queue.get_current_index()
|
||||
);
|
||||
s.queuestate.queue = queue.clone();
|
||||
s.queuestate.random_order = self.queue.get_random_order();
|
||||
s.queuestate.current_track = self.queue.get_current_index();
|
||||
s.queuestate.track_progress = self.spotify.get_current_progress();
|
||||
});
|
||||
self.config.save_state();
|
||||
s.quit();
|
||||
|
||||
@@ -60,12 +60,21 @@ pub struct SortingOrder {
|
||||
pub direction: SortDirection,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Default, Deserialize, Debug, Clone)]
|
||||
pub struct QueueState {
|
||||
pub current_track: Option<usize>,
|
||||
pub random_order: Option<Vec<usize>>,
|
||||
pub track_progress: std::time::Duration,
|
||||
pub queue: Vec<Playable>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct UserState {
|
||||
pub volume: u16,
|
||||
pub shuffle: bool,
|
||||
pub repeat: queue::RepeatSetting,
|
||||
pub queue: Vec<Playable>,
|
||||
pub queuestate: QueueState,
|
||||
#[serde(serialize_with = "toml::ser::tables_last")]
|
||||
pub playlist_orders: HashMap<String, SortingOrder>,
|
||||
}
|
||||
|
||||
@@ -75,7 +84,7 @@ impl Default for UserState {
|
||||
volume: u16::max_value(),
|
||||
shuffle: false,
|
||||
repeat: queue::RepeatSetting::None,
|
||||
queue: Vec::new(),
|
||||
queuestate: QueueState::default(),
|
||||
playlist_orders: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
27
src/queue.rs
27
src/queue.rs
@@ -31,14 +31,23 @@ pub struct Queue {
|
||||
|
||||
impl Queue {
|
||||
pub fn new(spotify: Spotify, cfg: Arc<Config>) -> Queue {
|
||||
let queue = cfg.state().queue.clone();
|
||||
Queue {
|
||||
queue: Arc::new(RwLock::new(queue)),
|
||||
spotify,
|
||||
current_track: RwLock::new(None),
|
||||
random_order: RwLock::new(None),
|
||||
let state = cfg.state().queuestate.clone();
|
||||
let queue = Queue {
|
||||
queue: Arc::new(RwLock::new(state.queue)),
|
||||
spotify: spotify.clone(),
|
||||
current_track: RwLock::new(state.current_track),
|
||||
random_order: RwLock::new(state.random_order),
|
||||
cfg,
|
||||
};
|
||||
|
||||
if let Some(playable) = queue.get_current() {
|
||||
spotify.load(&playable, false, state.track_progress.as_millis() as u32);
|
||||
spotify.update_track();
|
||||
spotify.pause();
|
||||
spotify.seek(state.track_progress.as_millis() as u32);
|
||||
}
|
||||
|
||||
queue
|
||||
}
|
||||
|
||||
pub fn next_index(&self) -> Option<usize> {
|
||||
@@ -245,7 +254,7 @@ impl Queue {
|
||||
}
|
||||
|
||||
if let Some(track) = &self.queue.read().unwrap().get(index) {
|
||||
self.spotify.load(&track);
|
||||
self.spotify.load(&track, true, 0);
|
||||
let mut current = self.current_track.write().unwrap();
|
||||
current.replace(index);
|
||||
self.spotify.update_track();
|
||||
@@ -342,6 +351,10 @@ impl Queue {
|
||||
self.cfg.state().shuffle
|
||||
}
|
||||
|
||||
pub fn get_random_order(&self) -> Option<Vec<usize>> {
|
||||
self.random_order.read().unwrap().clone()
|
||||
}
|
||||
|
||||
fn generate_random_order(&self) {
|
||||
let q = self.queue.read().unwrap();
|
||||
let mut order: Vec<usize> = Vec::with_capacity(q.len());
|
||||
|
||||
@@ -735,9 +735,13 @@ impl Spotify {
|
||||
self.api_with_retry(|api| api.current_user())
|
||||
}
|
||||
|
||||
pub fn load(&self, track: &Playable) {
|
||||
pub fn load(&self, track: &Playable, start_playing: bool, position_ms: u32) {
|
||||
info!("loading track: {:?}", track);
|
||||
self.send_worker(WorkerCommand::Load(track.clone()));
|
||||
self.send_worker(WorkerCommand::Load(
|
||||
track.clone(),
|
||||
start_playing,
|
||||
position_ms,
|
||||
));
|
||||
}
|
||||
|
||||
pub fn update_status(&self, new_status: PlayerEvent) {
|
||||
|
||||
@@ -18,7 +18,7 @@ use std::pin::Pin;
|
||||
use std::time::Duration;
|
||||
|
||||
pub(crate) enum WorkerCommand {
|
||||
Load(Playable),
|
||||
Load(Playable, bool, u32),
|
||||
Play,
|
||||
Pause,
|
||||
Stop,
|
||||
@@ -90,21 +90,23 @@ impl futures::Future for Worker {
|
||||
progress = true;
|
||||
debug!("message received!");
|
||||
match cmd {
|
||||
WorkerCommand::Load(playable) => match SpotifyId::from_uri(&playable.uri()) {
|
||||
Ok(id) => {
|
||||
info!("player loading track: {:?}", id);
|
||||
if id.audio_type == SpotifyAudioType::NonPlayable {
|
||||
warn!("track is not playable");
|
||||
WorkerCommand::Load(playable, start_playing, position_ms) => {
|
||||
match SpotifyId::from_uri(&playable.uri()) {
|
||||
Ok(id) => {
|
||||
info!("player loading track: {:?}", id);
|
||||
if id.audio_type == SpotifyAudioType::NonPlayable {
|
||||
warn!("track is not playable");
|
||||
self.events.send(Event::Player(PlayerEvent::FinishedTrack));
|
||||
} else {
|
||||
self.player.load(id, start_playing, position_ms);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
error!("error parsing uri: {:?}", e);
|
||||
self.events.send(Event::Player(PlayerEvent::FinishedTrack));
|
||||
} else {
|
||||
self.player.load(id, true, 0);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
error!("error parsing uri: {:?}", e);
|
||||
self.events.send(Event::Player(PlayerEvent::FinishedTrack));
|
||||
}
|
||||
},
|
||||
}
|
||||
WorkerCommand::Play => {
|
||||
self.player.play();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user