use std::path::Path; use lofty::file::TaggedFileExt; use lofty::tag::ItemKey; /// Tags that can be read from a music file. pub enum Tag { ArtistName, ArtistMbid, TrackTitle, TrackMbid, } impl Tag { fn item_key(&self) -> ItemKey { match self { Tag::ArtistName => ItemKey::TrackArtist, Tag::ArtistMbid => ItemKey::MusicBrainzArtistId, Tag::TrackTitle => ItemKey::TrackTitle, Tag::TrackMbid => ItemKey::MusicBrainzRecordingId, } } } fn read_tag(path: &Path, key: ItemKey) -> Result, lofty::error::LoftyError> { let tagged_file = lofty::read_from_path(path)?; let Some(tag) = tagged_file.primary_tag().or_else(|| tagged_file.first_tag()) else { return Ok(None); }; Ok(tag.get_string(key).map(String::from)) } /// Read multiple tags from a music file in a single file open. /// Returns a Vec in the same order as the input keys. pub fn read_tags(path: &Path, keys: &[Tag]) -> Result>, lofty::error::LoftyError> { let tagged_file = lofty::read_from_path(path)?; let Some(tag) = tagged_file.primary_tag().or_else(|| tagged_file.first_tag()) else { return Ok(vec![None; keys.len()]); }; Ok(keys .iter() .map(|k| tag.get_string(k.item_key()).map(String::from)) .collect()) } pub fn read_artist_name(path: &Path) -> Result, lofty::error::LoftyError> { read_tag(path, ItemKey::TrackArtist) } pub fn read_artist_mbid(path: &Path) -> Result, lofty::error::LoftyError> { read_tag(path, ItemKey::MusicBrainzArtistId) }