use eventual::{Async, Future}; use protobuf; use librespot_protocol as protocol; use mercury::{MercuryRequest, MercuryMethod}; use util::{SpotifyId, FileId}; use session::Session; pub trait MetadataTrait : Send + 'static { type Message: protobuf::MessageStatic; fn base_url() -> &'static str; fn parse(msg: &Self::Message) -> Self; } #[derive(Debug)] pub struct Track { pub id: SpotifyId, pub name: String, pub album: SpotifyId, pub files: Vec, } #[derive(Debug)] pub struct Album { pub id: SpotifyId, pub name: String, pub artists: Vec, pub covers: Vec } #[derive(Debug)] pub struct Artist { pub id: SpotifyId, pub name: String, } pub type MetadataRef = Future; pub type TrackRef = MetadataRef; pub type AlbumRef = MetadataRef; pub type ArtistRef = MetadataRef; impl MetadataTrait for Track { type Message = protocol::metadata::Track; fn base_url() -> &'static str { "hm://metadata/3/track" } fn parse(msg: &Self::Message) -> Self { Track { id: SpotifyId::from_raw(msg.get_gid()), name: msg.get_name().to_owned(), album: SpotifyId::from_raw(msg.get_album().get_gid()), files: msg.get_file().iter() .map(|file| { let mut dst = [0u8; 20]; dst.clone_from_slice(&file.get_file_id()); FileId(dst) }) .collect(), } } } impl MetadataTrait for Album { type Message = protocol::metadata::Album; fn base_url() -> &'static str { "hm://metadata/3/album" } fn parse(msg: &Self::Message) -> Self { Album { id: SpotifyId::from_raw(msg.get_gid()), name: msg.get_name().to_owned(), 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]; dst.clone_from_slice(&image.get_file_id()); FileId(dst) }) .collect(), } } } impl MetadataTrait for Artist { type Message = protocol::metadata::Artist; fn base_url() -> &'static str { "hm://metadata/3/artist" } fn parse(msg: &Self::Message) -> Self { Artist { id: SpotifyId::from_raw(msg.get_gid()), name: msg.get_name().to_owned(), } } } pub struct MetadataManager; impl MetadataManager { pub fn new() -> MetadataManager { MetadataManager } pub fn get(&mut self, session: &Session, id: SpotifyId) -> MetadataRef { session.mercury(MercuryRequest { method: MercuryMethod::GET, uri: format!("{}/{}", T::base_url(), id.to_base16()), content_type: None, payload: Vec::new() }).and_then(|response| { let msg : T::Message = protobuf::parse_from_bytes( response.payload.first().unwrap()).unwrap(); Ok(T::parse(&msg)) }) } }