Added metadata decoding tests

This commit is contained in:
Antoine Gersant 2016-11-30 22:10:16 -08:00
parent a16595a2e1
commit 1099c0dcf1
5 changed files with 135 additions and 120 deletions

View file

@ -9,7 +9,7 @@ use std::thread;
use std::time;
use error::*;
use metadata::SongTags;
use metadata;
use utils;
use vfs::Vfs;
@ -364,7 +364,7 @@ impl Index {
self.populate_directory(builder, file_path.as_path());
} else {
if let Some(file_path_string) = file_path.to_str() {
if let Ok(tags) = SongTags::read(file_path.as_path()) {
if let Ok(tags) = metadata::read(file_path.as_path()) {
if tags.year.is_some() {
inconsistent_directory_year |= directory_year.is_some() &&
directory_year != tags.year;

View file

@ -11,6 +11,7 @@ use error::PError;
use utils;
use utils::AudioFormat;
#[derive(Debug, PartialEq)]
pub struct SongTags {
pub disc_number: Option<u32>,
pub track_number: Option<u32>,
@ -21,18 +22,17 @@ pub struct SongTags {
pub year: Option<i32>,
}
impl SongTags {
pub fn read(path: &Path) -> Result<SongTags, PError> {
pub fn read(path: &Path) -> Result<SongTags, PError> {
match utils::get_audio_format(path) {
Some(AudioFormat::FLAC) => SongTags::read_flac(path),
Some(AudioFormat::MP3) => SongTags::read_id3(path),
Some(AudioFormat::MPC) => SongTags::read_ape(path),
Some(AudioFormat::OGG) => SongTags::read_vorbis(path),
Some(AudioFormat::FLAC) => read_flac(path),
Some(AudioFormat::MP3) => read_id3(path),
Some(AudioFormat::MPC) => read_ape(path),
Some(AudioFormat::OGG) => read_vorbis(path),
_ => Err(PError::UnsupportedMetadataFormat),
}
}
}
fn read_id3(path: &Path) -> Result<SongTags, PError> {
fn read_id3(path: &Path) -> Result<SongTags, PError> {
let tag = try!(id3::Tag::read_from_path(path));
let artist = tag.artist().map(|s| s.to_string());
@ -55,23 +55,23 @@ impl SongTags {
track_number: track_number,
year: year,
})
}
}
fn read_ape_string(item: &ape::Item) -> Option<String> {
fn read_ape_string(item: &ape::Item) -> Option<String> {
match item.value {
ape::ItemValue::Text(ref s) => Some(s.clone()),
_ => None,
}
}
}
fn read_ape_i32(item: &ape::Item) -> Option<i32> {
fn read_ape_i32(item: &ape::Item) -> Option<i32> {
match item.value {
ape::ItemValue::Text(ref s) => s.parse::<i32>().ok(),
_ => None,
}
}
}
fn read_ape_x_of_y(item: &ape::Item) -> Option<u32> {
fn read_ape_x_of_y(item: &ape::Item) -> Option<u32> {
match item.value {
ape::ItemValue::Text(ref s) => {
let format = Regex::new(r#"^\d+"#).unwrap();
@ -83,17 +83,17 @@ impl SongTags {
}
_ => None,
}
}
}
fn read_ape(path: &Path) -> Result<SongTags, PError> {
fn read_ape(path: &Path) -> Result<SongTags, PError> {
let tag = try!(ape::read(path));
let artist = tag.item("Artist").and_then(SongTags::read_ape_string);
let album = tag.item("Album").and_then(SongTags::read_ape_string);
let album_artist = tag.item("Album artist").and_then(SongTags::read_ape_string);
let title = tag.item("Title").and_then(SongTags::read_ape_string);
let year = tag.item("Year").and_then(SongTags::read_ape_i32);
let disc_number = tag.item("Disc").and_then(SongTags::read_ape_x_of_y);
let track_number = tag.item("Track").and_then(SongTags::read_ape_x_of_y);
let artist = tag.item("Artist").and_then(read_ape_string);
let album = tag.item("Album").and_then(read_ape_string);
let album_artist = tag.item("Album artist").and_then(read_ape_string);
let title = tag.item("Title").and_then(read_ape_string);
let year = tag.item("Year").and_then(read_ape_i32);
let disc_number = tag.item("Disc").and_then(read_ape_x_of_y);
let track_number = tag.item("Track").and_then(read_ape_x_of_y);
Ok(SongTags {
artist: artist,
album_artist: album_artist,
@ -103,9 +103,9 @@ impl SongTags {
track_number: track_number,
year: year,
})
}
}
fn read_vorbis(path: &Path) -> Result<SongTags, PError> {
fn read_vorbis(path: &Path) -> Result<SongTags, PError> {
let file = try!(fs::File::open(path));
let source = try!(OggStreamReader::new(PacketReader::new(file)));
@ -134,9 +134,9 @@ impl SongTags {
}
Ok(tags)
}
}
fn read_flac(path: &Path) -> Result<SongTags, PError> {
fn read_flac(path: &Path) -> Result<SongTags, PError> {
let tag = try!(metaflac::Tag::read_from_path(path));
let vorbis = try!(tag.vorbis_comments().ok_or(PError::MetadataDecodingError));
let disc_number = vorbis.get("DISCNUMBER").and_then(|d| d[0].parse::<u32>().ok());
@ -150,5 +150,20 @@ impl SongTags {
track_number: vorbis.track(),
year: year,
})
}
}
#[test]
fn test_read_metadata() {
let sample_tags = SongTags {
disc_number: Some(3),
track_number: Some(1),
title: Some("TEST TITLE".into()),
artist: Some("TEST ARTIST".into()),
album_artist: Some("TEST ALBUM ARTIST".into()),
album: Some("TEST ALBUM".into()),
year: Some(2016),
};
assert_eq!(read(Path::new("test/sample.mp3")).unwrap(), sample_tags);
assert_eq!(read(Path::new("test/sample.ogg")).unwrap(), sample_tags);
assert_eq!(read(Path::new("test/sample.flac")).unwrap(), sample_tags);
}

BIN
test/sample.flac Normal file

Binary file not shown.

BIN
test/sample.mp3 Normal file

Binary file not shown.

BIN
test/sample.ogg Normal file

Binary file not shown.