librespot/src/metadata.rs

154 lines
4.2 KiB
Rust
Raw Normal View History

use eventual::{Async, Future};
2015-12-28 00:29:53 +00:00
use protobuf;
2015-06-23 14:38:29 +00:00
use librespot_protocol as protocol;
use mercury::{MercuryRequest, MercuryMethod};
use util::{SpotifyId, FileId, StrChunksExt};
use session::Session;
2015-06-23 14:38:29 +00:00
fn countrylist_contains(list: &str, country: &str) -> bool {
list.chunks(2).any(|cc| cc == country)
}
fn parse_restrictions<'s, I>(restrictions: I, country: &str, catalogue: &str) -> bool
where I : Iterator<Item=&'s protocol::metadata::Restriction> {
restrictions
.filter(|r| r.get_catalogue_str().contains(&catalogue.to_owned()))
.all(|r| !countrylist_contains(r.get_countries_forbidden(), country)
&& (!r.has_countries_allowed()
|| countrylist_contains(r.get_countries_allowed(), country)))
}
pub trait MetadataTrait : Send + 'static {
2015-06-23 14:38:29 +00:00
type Message: protobuf::MessageStatic;
2015-06-23 14:38:29 +00:00
fn base_url() -> &'static str;
fn parse(msg: &Self::Message, session: &Session) -> Self;
2015-06-23 14:38:29 +00:00
}
#[derive(Debug)]
pub struct Track {
pub id: SpotifyId,
2015-06-23 14:38:29 +00:00
pub name: String,
pub album: SpotifyId,
pub files: Vec<FileId>,
pub alternatives: Vec<SpotifyId>,
pub available: bool,
}
#[derive(Debug)]
pub struct Album {
pub id: SpotifyId,
pub name: String,
pub artists: Vec<SpotifyId>,
pub covers: Vec<FileId>
2015-06-23 14:38:29 +00:00
}
#[derive(Debug)]
pub struct Artist {
pub id: SpotifyId,
pub name: String,
}
pub type MetadataRef<T> = Future<T, ()>;
pub type TrackRef = MetadataRef<Track>;
pub type AlbumRef = MetadataRef<Album>;
pub type ArtistRef = MetadataRef<Artist>;
2015-06-23 14:38:29 +00:00
impl MetadataTrait for Track {
type Message = protocol::metadata::Track;
fn base_url() -> &'static str {
"hm://metadata/3/track"
}
fn parse(msg: &Self::Message, session: &Session) -> Self {
2015-06-23 14:38:29 +00:00
Track {
id: SpotifyId::from_raw(msg.get_gid()),
2015-09-01 11:20:37 +00:00
name: msg.get_name().to_owned(),
2015-06-23 14:38:29 +00:00
album: SpotifyId::from_raw(msg.get_album().get_gid()),
files: msg.get_file().iter()
.map(|file| {
let mut dst = [0u8; 20];
2015-12-28 00:29:53 +00:00
dst.clone_from_slice(&file.get_file_id());
2015-07-07 21:40:31 +00:00
FileId(dst)
2015-06-23 14:38:29 +00:00
})
.collect(),
alternatives: msg.get_alternative().iter()
.map(|alt| SpotifyId::from_raw(alt.get_gid()))
.collect(),
available: parse_restrictions(
msg.get_restriction().iter(),
&session.0.data.read().unwrap().country,
"premium"),
2015-06-23 14:38:29 +00:00
}
}
}
impl MetadataTrait for Album {
type Message = protocol::metadata::Album;
fn base_url() -> &'static str {
"hm://metadata/3/album"
}
fn parse(msg: &Self::Message, _: &Session) -> Self {
2015-06-23 14:38:29 +00:00
Album {
id: SpotifyId::from_raw(msg.get_gid()),
2015-09-01 11:20:37 +00:00
name: msg.get_name().to_owned(),
2015-06-23 14:38:29 +00:00
artists: msg.get_artist().iter()
.map(|a| SpotifyId::from_raw(a.get_gid()))
.collect(),
covers: msg.get_cover_group().get_image().iter()
.map(|image| {
let mut dst = [0u8; 20];
2015-12-28 00:29:53 +00:00
dst.clone_from_slice(&image.get_file_id());
2015-07-07 21:40:31 +00:00
FileId(dst)
2015-06-23 14:38:29 +00:00
})
.collect(),
}
}
}
impl MetadataTrait for Artist {
type Message = protocol::metadata::Artist;
2015-06-23 14:38:29 +00:00
fn base_url() -> &'static str {
"hm://metadata/3/artist"
}
fn parse(msg: &Self::Message, _: &Session) -> Self {
Artist {
id: SpotifyId::from_raw(msg.get_gid()),
name: msg.get_name().to_owned(),
2015-06-23 14:38:29 +00:00
}
}
}
pub struct MetadataManager;
2015-06-23 14:38:29 +00:00
impl MetadataManager {
pub fn new() -> MetadataManager {
MetadataManager
2015-06-23 14:38:29 +00:00
}
pub fn get<T: MetadataTrait>(&mut self, session: &Session, id: SpotifyId)
-> MetadataRef<T> {
let _session = session.clone();
session.mercury(MercuryRequest {
method: MercuryMethod::GET,
uri: format!("{}/{}", T::base_url(), id.to_base16()),
content_type: None,
payload: Vec::new()
}).and_then(move |response| {
2015-06-23 14:38:29 +00:00
let msg : T::Message = protobuf::parse_from_bytes(
2015-09-01 11:20:37 +00:00
response.payload.first().unwrap()).unwrap();
2015-06-23 14:38:29 +00:00
Ok(T::parse(&msg, &_session))
})
2015-06-23 14:38:29 +00:00
}
}