use mpd_client::{Client, commands};
use crate::App;
use crate::app::SongInfo;
pub trait MPDUpdates {
async fn run_updates(&mut self, client: &Client) -> color_eyre::Result<()>;
async fn run_optimized_updates(
&mut self,
client: &Client,
needs_queue: bool,
needs_current_song: bool,
) -> color_eyre::Result<()>;
async fn update_status_only(&mut self, client: &Client) -> color_eyre::Result<()>;
}
impl MPDUpdates for App {
async fn run_updates(&mut self, client: &Client) -> color_eyre::Result<()> {
self.run_optimized_updates(client, true, true).await
}
async fn run_optimized_updates(
&mut self,
client: &Client,
needs_queue: bool,
needs_current_song: bool,
) -> color_eyre::Result<()> {
let status = client.command(commands::Status).await?;
let queue_changed = self
.last_playlist_version
.map(|v| v != status.playlist_version)
.unwrap_or(true);
let current_song_id = status.current_song.map(|(_, id)| id);
let song_changed = self.last_song_id != current_song_id;
if needs_queue && queue_changed {
log::debug!(
"Queue changed: version {} -> {}",
self.last_playlist_version.unwrap_or(0),
status.playlist_version
);
let queue_songs = client.command(commands::Queue).await?;
self.queue = queue_songs
.into_iter()
.map(|song_in_queue| SongInfo::from_song(&song_in_queue.song))
.collect();
self.update_queue_selection();
self.last_playlist_version = Some(status.playlist_version);
self.dirty.mark_queue();
}
if needs_current_song && song_changed {
log::debug!(
"Song changed: {:?} -> {:?}",
self.last_song_id,
current_song_id
);
match client.command(commands::CurrentSong).await? {
Some(song_in_queue) => {
self.current_song = Some(SongInfo::from_song(&song_in_queue.song));
}
None => {
self.current_song = None;
}
}
self.last_song_id = current_song_id;
self.dirty.mark_current_song();
self.dirty.mark_cover_art();
}
self.update_from_status(status);
Ok(())
}
async fn update_status_only(&mut self, client: &Client) -> color_eyre::Result<()> {
let status = client.command(commands::Status).await?;
self.update_from_status(status);
Ok(())
}
}
impl App {
fn update_queue_selection(&mut self) {
match self.queue_list_state.selected() {
Some(selected) => {
if selected >= self.queue.len() {
if self.queue.is_empty() {
self.queue_list_state.select(None);
} else {
self.queue_list_state
.select(Some(self.queue.len().saturating_sub(1)));
}
}
}
None => {
if !self.queue.is_empty() {
self.queue_list_state.select(Some(0));
}
}
}
self.selected_queue_index = self.queue_list_state.selected();
}
fn update_from_status(&mut self, status: mpd_client::responses::Status) {
let progress = match (status.elapsed, status.duration) {
(Some(elapsed), Some(duration)) => Some(elapsed.as_secs_f64() / duration.as_secs_f64()),
_ => None,
};
if let Some(ref mut song) = self.current_song {
song.update_playback_info(Some(status.state), progress);
song.update_time_info(status.elapsed, status.duration);
}
self.dirty.mark_status();
self.dirty.mark_progress();
self.mpd_status = Some(status);
}
}