use librespot::core::spotify_id::SpotifyId; use crate::utils::{self, spotify}; #[derive(Clone)] pub struct PlaybackInfo { last_updated: u128, position_ms: u32, pub track: Option, pub episode: Option, pub spotify_id: Option, pub duration_ms: u32, pub is_playing: bool, } impl PlaybackInfo { /// Create a new instance of PlaybackInfo pub fn new(duration_ms: u32, position_ms: u32, is_playing: bool) -> Self { Self { last_updated: utils::get_time_ms(), track: None, episode: None, spotify_id: None, duration_ms, position_ms, is_playing, } } /// Update position, duration and playback state pub fn update_pos_dur(&mut self, position_ms: u32, duration_ms: u32, is_playing: bool) { self.position_ms = position_ms; self.duration_ms = duration_ms; self.is_playing = is_playing; self.last_updated = utils::get_time_ms(); } /// Update spotify id, track and episode pub fn update_track_episode( &mut self, spotify_id: SpotifyId, track: Option, episode: Option, ) { self.spotify_id = Some(spotify_id); self.track = track; self.episode = episode; } /// Get the current playback position pub fn get_position(&self) -> u32 { if self.is_playing { let now = utils::get_time_ms(); let diff = now - self.last_updated; self.position_ms + diff as u32 } else { self.position_ms } } /// Get the name of the track or episode pub fn get_name(&self) -> Option { if let Some(track) = &self.track { Some(track.name.clone()) } else { self.episode.as_ref().map(|episode| episode.name.clone()) } } /// Get the artist(s) or show name of the current track pub fn get_artists(&self) -> Option { if let Some(track) = &self.track { Some( track .artists .iter() .map(|a| a.name.clone()) .collect::>() .join(", "), ) } else { self .episode .as_ref() .map(|episode| episode.show.name.clone()) } } /// Get the album art url pub fn get_thumbnail_url(&self) -> Option { if let Some(track) = &self.track { let mut images = track.album.images.clone(); images.sort_by(|a, b| b.width.cmp(&a.width)); images.get(0).as_ref().map(|image| image.url.clone()) } else if let Some(episode) = &self.episode { let mut images = episode.show.images.clone(); images.sort_by(|a, b| b.width.cmp(&a.width)); images.get(0).as_ref().map(|image| image.url.clone()) } else { None } } /// Get the type of audio (track or episode) #[allow(dead_code)] pub fn get_type(&self) -> Option { if self.track.is_some() { Some("track".into()) } else if self.episode.is_some() { Some("episode".into()) } else { None } } /// Get the public facing url of the track or episode #[allow(dead_code)] pub fn get_url(&self) -> Option<&str> { if let Some(ref track) = self.track { Some(track.external_urls.spotify.as_str()) } else if let Some(ref episode) = self.episode { Some(episode.external_urls.spotify.as_str()) } else { None } } }