use std::fs::File; use image::DynamicImage; use std::error::Error; use std::fs::OpenOptions; use std::path::Path; use std::io; use std::fmt; use std::ffi::OsStr; use symphonia::default; use symphonia::core::io::MediaSourceStream; use symphonia::core::probe::{Hint, ProbeResult}; use symphonia::core::meta::StandardVisualKey; use symphonia::core::formats::FormatReader; pub fn load_song(path: &Path) -> Result<(File, ProbeResult), LoadError> { let probe = default::get_probe(); let file = OpenOptions::new() .read(true) .write(false) .open(path) .map_err(LoadError::OpenError)?; let media_source_stream = MediaSourceStream::new( Box::new( file.try_clone() .map_err(LoadError::OpenError)? ), Default::default() ); let ext_hint = path.extension() .and_then(OsStr::to_str) .map_or_else( Hint::new, |ext| { let mut h = Hint::new(); h.with_extension(ext); h } ); probe.format( &ext_hint, media_source_stream, &Default::default(), &Default::default(), ).map_err(LoadError::SymphoniaError) .map(|fr| (file, fr)) } pub fn extract_cover(format: &mut dyn FormatReader) -> Option{ #[allow(clippy::zero_prefixed_literal)] format.metadata() .current() .into_iter() // Replace this whole closure with MetadataRef::usage once we update .flat_map(|meta| meta.visuals().iter().map(|v|(v.data.clone(), v.usage)).collect::>()) .filter_map(|(data, usage)| image::load_from_memory(&data).ok().map(|img| (usage, img))) .max_by_key(|(usage, _)| usage.map(|usage| match usage { StandardVisualKey::FrontCover => 00, StandardVisualKey::FileIcon => 01, StandardVisualKey::Illustration => 02, StandardVisualKey::BandArtistLogo => 03, StandardVisualKey::BackCover => 04, StandardVisualKey::Media => 05, StandardVisualKey::Leaflet => 06, StandardVisualKey::OtherIcon => 07, StandardVisualKey::LeadArtistPerformerSoloist => 08, StandardVisualKey::ArtistPerformer => 09, StandardVisualKey::Conductor => 10, StandardVisualKey::BandOrchestra => 11, StandardVisualKey::Composer => 12, StandardVisualKey::Lyricist => 13, StandardVisualKey::RecordingLocation => 14, StandardVisualKey::RecordingSession => 15, StandardVisualKey::Performance => 16, StandardVisualKey::ScreenCapture => 17, StandardVisualKey::PublisherStudioLogo => 18, }).unwrap_or(u32::MAX) ) .map(|(_, img)| img) } #[derive(Debug)] pub enum LoadError { OpenError(io::Error), SymphoniaError(symphonia::core::errors::Error), } impl fmt::Display for LoadError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { Self::OpenError(e) => write!(f, "Problem opening song: {}", e), Self::SymphoniaError(e) => write!(f, "Symphonia encountered a problem: {}", e), } } } impl Error for LoadError {}