diff --git a/Cargo.lock b/Cargo.lock index b311b46..5ca1c2e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1202,6 +1202,14 @@ dependencies = [ "failure 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "mp4ameta" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "native-tls" version = "0.2.4" @@ -1477,6 +1485,7 @@ dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "metaflac 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "mp3-duration 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "mp4ameta 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2939,6 +2948,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum mio-extras 2.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum mp3-duration 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "eda61ba6c266cd2c7bfcea9a2719837dc062869e24e101a93c1b0873d17c2d35" +"checksum mp4ameta 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2b0de7480e6605e303c127e236712f866ed1b748de03908fd1f584d60d135878" "checksum native-tls 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "2b0d88c06fe90d5ee94048ba40409ef1d9315d86f6f38c2efdaad4fb50c58b2d" "checksum net2 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)" = "2ba7c918ac76704fb42afcbbb43891e72731f3dcca3bef2a19786297baf14af7" "checksum notify 4.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "80ae4a7688d1fab81c5bf19c64fc8db920be8d519ce6336ed4e7efe024724dbd" diff --git a/Cargo.toml b/Cargo.toml index e30aa99..81e410a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,7 @@ lewton = "0.10.1" log = "0.4.5" metaflac = "0.2.3" mp3-duration = "0.1.9" +mp4ameta = "0.2.2" pbkdf2 = "0.3" rand = "0.7" rayon = "1.3" diff --git a/src/index/metadata.rs b/src/index/metadata.rs index e383a0b..da08cb1 100644 --- a/src/index/metadata.rs +++ b/src/index/metadata.rs @@ -5,6 +5,7 @@ use lewton::inside_ogg::OggStreamReader; use log::error; use metaflac; use mp3_duration; +use mp4ameta; use regex::Regex; use std::fs; use std::path::Path; @@ -29,6 +30,7 @@ pub fn read(path: &Path) -> Option { let data = match utils::get_audio_format(path) { Some(AudioFormat::FLAC) => Some(read_flac(path)), Some(AudioFormat::MP3) => Some(read_id3(path)), + Some(AudioFormat::MP4) => Some(read_mp4(path)), Some(AudioFormat::MPC) => Some(read_ape(path)), Some(AudioFormat::OGG) => Some(read_vorbis(path)), _ => None, @@ -203,6 +205,31 @@ fn read_flac(path: &Path) -> Result { }) } +#[cfg_attr(feature = "profile-index", flame)] +fn read_mp4(path: &Path) -> Result { + let tag = mp4ameta::Tag::read_from_path(path)?; + let mut tags = SongTags { + artist: None, + album_artist: None, + album: None, + title: None, + duration: None, + disc_number: None, + track_number: None, + year: None, + }; + tags.artist = tag.artist().map(|v| v.to_string()); + tags.album_artist = tag.album_artist().map(|v| v.to_string()); + tags.album = tag.album().map(|v| v.to_string()); + tags.title = tag.title().map(|v| v.to_string()); + tags.duration = tag.duration().map(|v| v as u32); + tags.disc_number = tag.disk_number().0.and_then(|d| Some(d as u32)); + tags.track_number = tag.track_number().0.and_then(|d| Some(d as u32)); + tags.year = tag.year().and_then(|v| v.parse::().ok()); + + Ok(tags) +} + #[test] fn test_read_metadata() { let sample_tags = SongTags { @@ -223,10 +250,12 @@ fn test_read_metadata() { duration: Some(0), ..sample_tags.clone() }; + let m4a_sample_tag = SongTags { + duration: Some(0), + ..sample_tags.clone() + }; assert_eq!(read(Path::new("test/sample.mp3")).unwrap(), mp3_sample_tag); assert_eq!(read(Path::new("test/sample.ogg")).unwrap(), sample_tags); - assert_eq!( - read(Path::new("test/sample.flac")).unwrap(), - flac_sample_tag - ); + assert_eq!(read(Path::new("test/sample.flac")).unwrap(), flac_sample_tag); + assert_eq!(read(Path::new("test/sample.m4a")).unwrap(), m4a_sample_tag); } diff --git a/test/sample.m4a b/test/sample.m4a new file mode 100644 index 0000000..1b4866a Binary files /dev/null and b/test/sample.m4a differ