Added support for APE metadata
This commit is contained in:
parent
d9abb35e4d
commit
f21e4e055f
6 changed files with 92 additions and 2 deletions
16
Cargo.lock
generated
16
Cargo.lock
generated
|
@ -2,6 +2,7 @@
|
||||||
name = "polaris"
|
name = "polaris"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"ape 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
"getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"hyper 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"hyper 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"id3 0.1.10 (git+https://github.com/jameshurst/rust-id3)",
|
"id3 0.1.10 (git+https://github.com/jameshurst/rust-id3)",
|
||||||
|
@ -32,6 +33,14 @@ dependencies = [
|
||||||
"memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ape"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
|
@ -54,6 +63,11 @@ name = "buf_redux"
|
||||||
version = "0.1.3"
|
version = "0.1.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byteorder"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "0.5.3"
|
version = "0.5.3"
|
||||||
|
@ -1041,9 +1055,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
"checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66"
|
"checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66"
|
||||||
|
"checksum ape 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b419c2e36e91776200588f91e24c970d16d34236369136ca819f12dd903c5691"
|
||||||
"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
|
"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
|
||||||
"checksum bodyparser 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "07b171b407e583dc8f01011a713f20575a81ac60acecf3b8153012709aeb1fd6"
|
"checksum bodyparser 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "07b171b407e583dc8f01011a713f20575a81ac60acecf3b8153012709aeb1fd6"
|
||||||
"checksum buf_redux 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b115bd9935c68b58f80ff867e1c46942c4aed79e78bcc8c2bc22d50f52bb9099"
|
"checksum buf_redux 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b115bd9935c68b58f80ff867e1c46942c4aed79e78bcc8c2bc22d50f52bb9099"
|
||||||
|
"checksum byteorder 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96c8b41881888cc08af32d47ac4edd52bc7fa27fef774be47a92443756451304"
|
||||||
"checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855"
|
"checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855"
|
||||||
"checksum color_quant 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a475fc4af42d83d28adf72968d9bcfaf035a1a9381642d8e85d8a04957767b0d"
|
"checksum color_quant 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a475fc4af42d83d28adf72968d9bcfaf035a1a9381642d8e85d8a04957767b0d"
|
||||||
"checksum conduit-mime-types 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "95ca30253581af809925ef68c2641cc140d6183f43e12e0af4992d53768bd7b8"
|
"checksum conduit-mime-types 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "95ca30253581af809925ef68c2641cc140d6183f43e12e0af4992d53768bd7b8"
|
||||||
|
|
|
@ -7,6 +7,7 @@ authors = ["Antoine Gersant <antoine.gersant@lesforges.org>"]
|
||||||
ui = []
|
ui = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
ape = "0.1.2"
|
||||||
getopts = "0.2.14"
|
getopts = "0.2.14"
|
||||||
hyper = "0.9.10"
|
hyper = "0.9.10"
|
||||||
id3 = { git = "https://github.com/jameshurst/rust-id3" }
|
id3 = { git = "https://github.com/jameshurst/rust-id3" }
|
||||||
|
|
|
@ -38,6 +38,8 @@ impl From<PError> for IronError {
|
||||||
}
|
}
|
||||||
PError::AlbumArtSearchError => IronError::new(err, status::InternalServerError),
|
PError::AlbumArtSearchError => IronError::new(err, status::InternalServerError),
|
||||||
PError::ImageProcessingError => IronError::new(err, status::InternalServerError),
|
PError::ImageProcessingError => IronError::new(err, status::InternalServerError),
|
||||||
|
PError::UnsupportedMetadataFormat => IronError::new(err, status::InternalServerError),
|
||||||
|
PError::APEParseError => IronError::new(err, status::InternalServerError),
|
||||||
PError::ID3ParseError => IronError::new(err, status::InternalServerError),
|
PError::ID3ParseError => IronError::new(err, status::InternalServerError),
|
||||||
PError::Unauthorized => IronError::new(err, status::Unauthorized),
|
PError::Unauthorized => IronError::new(err, status::Unauthorized),
|
||||||
PError::IncorrectCredentials => IronError::new(err, status::BadRequest),
|
PError::IncorrectCredentials => IronError::new(err, status::BadRequest),
|
||||||
|
|
13
src/error.rs
13
src/error.rs
|
@ -1,3 +1,4 @@
|
||||||
|
use ape;
|
||||||
use std::error;
|
use std::error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
@ -20,11 +21,19 @@ pub enum PError {
|
||||||
ConfigAlbumArtPatternParseError,
|
ConfigAlbumArtPatternParseError,
|
||||||
AlbumArtSearchError,
|
AlbumArtSearchError,
|
||||||
ImageProcessingError,
|
ImageProcessingError,
|
||||||
|
UnsupportedMetadataFormat,
|
||||||
|
APEParseError,
|
||||||
ID3ParseError,
|
ID3ParseError,
|
||||||
Unauthorized,
|
Unauthorized,
|
||||||
IncorrectCredentials,
|
IncorrectCredentials,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<ape::Error> for PError {
|
||||||
|
fn from(_: ape::Error) -> PError {
|
||||||
|
PError::APEParseError
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<io::Error> for PError {
|
impl From<io::Error> for PError {
|
||||||
fn from(err: io::Error) -> PError {
|
fn from(err: io::Error) -> PError {
|
||||||
PError::Io(err)
|
PError::Io(err)
|
||||||
|
@ -62,6 +71,8 @@ impl error::Error for PError {
|
||||||
}
|
}
|
||||||
PError::AlbumArtSearchError => "Error while looking for album art",
|
PError::AlbumArtSearchError => "Error while looking for album art",
|
||||||
PError::ImageProcessingError => "Error while processing image",
|
PError::ImageProcessingError => "Error while processing image",
|
||||||
|
PError::UnsupportedMetadataFormat => "Unsupported metadata format",
|
||||||
|
PError::APEParseError => "Error while reading APE tag",
|
||||||
PError::ID3ParseError => "Error while reading ID3 tag",
|
PError::ID3ParseError => "Error while reading ID3 tag",
|
||||||
PError::Unauthorized => "Authentication required",
|
PError::Unauthorized => "Authentication required",
|
||||||
PError::IncorrectCredentials => "Incorrect username/password combination",
|
PError::IncorrectCredentials => "Incorrect username/password combination",
|
||||||
|
@ -97,6 +108,8 @@ impl fmt::Display for PError {
|
||||||
}
|
}
|
||||||
PError::AlbumArtSearchError => write!(f, "Error while looking for album art"),
|
PError::AlbumArtSearchError => write!(f, "Error while looking for album art"),
|
||||||
PError::ImageProcessingError => write!(f, "Error while processing image"),
|
PError::ImageProcessingError => write!(f, "Error while processing image"),
|
||||||
|
PError::UnsupportedMetadataFormat => write!(f, "Unsupported metadata format"),
|
||||||
|
PError::APEParseError => write!(f, "Error while reading APE tag"),
|
||||||
PError::ID3ParseError => write!(f, "Error while reading ID3 tag"),
|
PError::ID3ParseError => write!(f, "Error while reading ID3 tag"),
|
||||||
PError::Unauthorized => write!(f, "Authentication required"),
|
PError::Unauthorized => write!(f, "Authentication required"),
|
||||||
PError::IncorrectCredentials => write!(f, "Incorrect username/password combination"),
|
PError::IncorrectCredentials => write!(f, "Incorrect username/password combination"),
|
||||||
|
|
57
src/index.rs
57
src/index.rs
|
@ -1,4 +1,5 @@
|
||||||
use core::ops::Deref;
|
use core::ops::Deref;
|
||||||
|
use ape;
|
||||||
use id3::Tag;
|
use id3::Tag;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use sqlite;
|
use sqlite;
|
||||||
|
@ -10,6 +11,8 @@ use std::thread;
|
||||||
use std::time;
|
use std::time;
|
||||||
|
|
||||||
use error::*;
|
use error::*;
|
||||||
|
use utils;
|
||||||
|
use utils::AudioFormat;
|
||||||
use vfs::Vfs;
|
use vfs::Vfs;
|
||||||
|
|
||||||
const INDEX_BUILDING_INSERT_BUFFER_SIZE: usize = 500; // Put 500 insertions in each transaction
|
const INDEX_BUILDING_INSERT_BUFFER_SIZE: usize = 500; // Put 500 insertions in each transaction
|
||||||
|
@ -32,6 +35,14 @@ struct SongTags {
|
||||||
|
|
||||||
impl SongTags {
|
impl SongTags {
|
||||||
fn read(path: &Path) -> Result<SongTags, PError> {
|
fn read(path: &Path) -> Result<SongTags, PError> {
|
||||||
|
match utils::get_audio_format(path) {
|
||||||
|
Some(AudioFormat::MP3) => SongTags::read_id3(path),
|
||||||
|
Some(AudioFormat::MPC) => SongTags::read_ape(path),
|
||||||
|
_ => Err(PError::UnsupportedMetadataFormat),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_id3(path: &Path) -> Result<SongTags, PError> {
|
||||||
let tag = try!(Tag::read_from_path(path));
|
let tag = try!(Tag::read_from_path(path));
|
||||||
|
|
||||||
let artist = tag.artist().map(|s| s.to_string());
|
let artist = tag.artist().map(|s| s.to_string());
|
||||||
|
@ -53,6 +64,52 @@ impl SongTags {
|
||||||
year: year,
|
year: year,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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> {
|
||||||
|
match item.value {
|
||||||
|
ape::ItemValue::Text(ref s) => s.parse::<i32>().ok(),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_ape_track_number(item: &ape::Item) -> Option<u32> {
|
||||||
|
match item.value {
|
||||||
|
ape::ItemValue::Text(ref s) => {
|
||||||
|
let format = Regex::new(r#"^\d+"#).unwrap();
|
||||||
|
if let Some((start, end)) = format.find(s) {
|
||||||
|
s[start..end].parse().ok()
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 track_number = tag.item("Track").and_then(SongTags::read_ape_track_number);
|
||||||
|
Ok(SongTags {
|
||||||
|
artist: artist,
|
||||||
|
album_artist: album_artist,
|
||||||
|
album: album,
|
||||||
|
title: title,
|
||||||
|
track_number: track_number,
|
||||||
|
year: year,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, RustcEncodable)]
|
#[derive(Debug, RustcEncodable)]
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
extern crate ape;
|
||||||
extern crate core;
|
extern crate core;
|
||||||
extern crate getopts;
|
extern crate getopts;
|
||||||
extern crate hyper;
|
extern crate hyper;
|
||||||
|
|
Loading…
Add table
Reference in a new issue