Merge pull request #148 from awiouy/sisyphus

core API review changes.
This commit is contained in:
Sasha Hilton 2018-02-13 22:25:17 +01:00 committed by GitHub
commit 1de8049a58
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 101 additions and 104 deletions

View file

@ -11,7 +11,7 @@ use tempfile::NamedTempFile;
use core::channel::{Channel, ChannelData, ChannelError, ChannelHeaders}; use core::channel::{Channel, ChannelData, ChannelError, ChannelHeaders};
use core::session::Session; use core::session::Session;
use core::util::FileId; use core::spotify_id::FileId;
const CHUNK_SIZE: usize = 0x20000; const CHUNK_SIZE: usize = 0x20000;
@ -115,7 +115,7 @@ impl Future for AudioFileOpenStreaming {
if id == 0x3 { if id == 0x3 {
let size = BigEndian::read_u32(&data) as usize * 4; let size = BigEndian::read_u32(&data) as usize * 4;
let file = self.finish(size); let file = self.finish(size);
return Ok(Async::Ready(file)); return Ok(Async::Ready(file));
} }
} }

View file

@ -6,7 +6,8 @@ use protobuf::{self, Message};
use core::config::ConnectConfig; use core::config::ConnectConfig;
use core::mercury::MercuryError; use core::mercury::MercuryError;
use core::session::Session; use core::session::Session;
use core::util::{SeqGenerator, SpotifyId}; use core::spotify_id::SpotifyId;
use core::util::SeqGenerator;
use core::version; use core::version;
use protocol; use protocol;

View file

@ -5,7 +5,7 @@ use futures::sync::oneshot;
use std::collections::HashMap; use std::collections::HashMap;
use std::io::Write; use std::io::Write;
use util::{FileId, SpotifyId}; use spotify_id::{FileId, SpotifyId};
use util::SeqGenerator; use util::SeqGenerator;
#[derive(Debug, Hash, PartialEq, Eq, Copy, Clone)] #[derive(Debug, Hash, PartialEq, Eq, Copy, Clone)]

View file

@ -6,7 +6,7 @@ use std::path::Path;
use std::path::PathBuf; use std::path::PathBuf;
use authentication::Credentials; use authentication::Credentials;
use util::FileId; use spotify_id::FileId;
#[derive(Clone)] #[derive(Clone)]
pub struct Cache { pub struct Cache {

View file

@ -4,7 +4,7 @@ macro_rules! component {
pub struct $name(::std::sync::Arc<($crate::session::SessionWeak, ::std::sync::Mutex<$inner>)>); pub struct $name(::std::sync::Arc<($crate::session::SessionWeak, ::std::sync::Mutex<$inner>)>);
impl $name { impl $name {
#[allow(dead_code)] #[allow(dead_code)]
pub fn new(session: $crate::session::SessionWeak) -> $name { pub(crate) fn new(session: $crate::session::SessionWeak) -> $name {
debug!(target:"librespot::component", "new {}", stringify!($name)); debug!(target:"librespot::component", "new {}", stringify!($name));
$name(::std::sync::Arc::new((session, ::std::sync::Mutex::new($inner { $name(::std::sync::Arc::new((session, ::std::sync::Mutex::new($inner {
@ -39,17 +39,17 @@ macro_rules! component {
use std::cell::UnsafeCell; use std::cell::UnsafeCell;
use std::sync::Mutex; use std::sync::Mutex;
pub struct Lazy<T>(Mutex<bool>, UnsafeCell<Option<T>>); pub(crate) struct Lazy<T>(Mutex<bool>, UnsafeCell<Option<T>>);
unsafe impl<T: Sync> Sync for Lazy<T> {} unsafe impl<T: Sync> Sync for Lazy<T> {}
unsafe impl<T: Send> Send for Lazy<T> {} unsafe impl<T: Send> Send for Lazy<T> {}
#[cfg_attr(feature = "cargo-clippy", allow(mutex_atomic))] #[cfg_attr(feature = "cargo-clippy", allow(mutex_atomic))]
impl<T> Lazy<T> { impl<T> Lazy<T> {
pub fn new() -> Lazy<T> { pub(crate) fn new() -> Lazy<T> {
Lazy(Mutex::new(false), UnsafeCell::new(None)) Lazy(Mutex::new(false), UnsafeCell::new(None))
} }
pub fn get<F: FnOnce() -> T>(&self, f: F) -> &T { pub(crate) fn get<F: FnOnce() -> T>(&self, f: F) -> &T {
let mut inner = self.0.lock().unwrap(); let mut inner = self.0.lock().unwrap();
if !*inner { if !*inner {
unsafe { unsafe {

View file

@ -44,5 +44,6 @@ pub mod diffie_hellman;
pub mod keymaster; pub mod keymaster;
pub mod mercury; pub mod mercury;
pub mod session; pub mod session;
pub mod spotify_id;
pub mod util; pub mod util;
pub mod version; pub mod version;

View file

@ -51,7 +51,7 @@ impl MercuryManager {
seq seq
} }
pub fn request(&self, req: MercuryRequest) -> MercuryFuture<MercuryResponse> { fn request(&self, req: MercuryRequest) -> MercuryFuture<MercuryResponse> {
let (tx, rx) = oneshot::channel(); let (tx, rx) = oneshot::channel();
let pending = MercuryPending { let pending = MercuryPending {

View file

@ -19,12 +19,12 @@ use audio_key::AudioKeyManager;
use channel::ChannelManager; use channel::ChannelManager;
use mercury::MercuryManager; use mercury::MercuryManager;
pub struct SessionData { struct SessionData {
country: String, country: String,
canonical_username: String, canonical_username: String,
} }
pub struct SessionInternal { struct SessionInternal {
config: SessionConfig, config: SessionConfig,
data: RwLock<SessionData>, data: RwLock<SessionData>,
@ -43,7 +43,7 @@ pub struct SessionInternal {
static SESSION_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT; static SESSION_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;
#[derive(Clone)] #[derive(Clone)]
pub struct Session(pub Arc<SessionInternal>); pub struct Session(Arc<SessionInternal>);
pub fn device_id(name: &str) -> String { pub fn device_id(name: &str) -> String {
let mut h = Sha1::new(); let mut h = Sha1::new();
@ -226,7 +226,7 @@ impl Session {
} }
#[derive(Clone)] #[derive(Clone)]
pub struct SessionWeak(pub Weak<SessionInternal>); pub struct SessionWeak(Weak<SessionInternal>);
impl SessionWeak { impl SessionWeak {
fn try_upgrade(&self) -> Option<Session> { fn try_upgrade(&self) -> Option<Session> {

View file

@ -6,10 +6,8 @@ use std::mem;
use std::ops::{Mul, Rem, Shr}; use std::ops::{Mul, Rem, Shr};
mod int128; mod int128;
mod spotify_id;
pub use util::int128::u128; pub use util::int128::u128;
pub use util::spotify_id::{FileId, SpotifyId};
pub fn rand_vec<G: Rng, R: Rand>(rng: &mut G, size: usize) -> Vec<R> { pub fn rand_vec<G: Rng, R: Rand>(rng: &mut G, size: usize) -> Vec<R> {
rng.gen_iter().take(size).collect() rng.gen_iter().take(size).collect()
@ -31,32 +29,6 @@ pub fn powm(base: &BigUint, exp: &BigUint, modulus: &BigUint) -> BigUint {
result result
} }
pub struct StrChunks<'s>(&'s str, usize);
pub trait StrChunksExt {
fn chunks(&self, size: usize) -> StrChunks;
}
impl StrChunksExt for str {
fn chunks(&self, size: usize) -> StrChunks {
StrChunks(self, size)
}
}
impl<'s> Iterator for StrChunks<'s> {
type Item = &'s str;
fn next(&mut self) -> Option<&'s str> {
let &mut StrChunks(data, size) = self;
if data.is_empty() {
None
} else {
let ret = Some(&data[..size]);
self.0 = &data[size..];
ret
}
}
}
pub trait ReadSeek: ::std::io::Read + ::std::io::Seek {} pub trait ReadSeek: ::std::io::Read + ::std::io::Seek {}
impl<T: ::std::io::Read + ::std::io::Seek> ReadSeek for T {} impl<T: ::std::io::Read + ::std::io::Seek> ReadSeek for T {}

View file

@ -7,7 +7,7 @@ use tokio_core::reactor::Core;
use librespot::core::authentication::Credentials; use librespot::core::authentication::Credentials;
use librespot::playback::config::{PlayerConfig, SessionConfig}; use librespot::playback::config::{PlayerConfig, SessionConfig};
use librespot::core::session::Session; use librespot::core::session::Session;
use librespot::core::util::SpotifyId; use librespot::core::spotify_id::SpotifyId;
use librespot::audio_backend; use librespot::audio_backend;
use librespot::player::Player; use librespot::player::Player;

View file

@ -3,7 +3,7 @@ use std::io::Write;
use core::channel::ChannelData; use core::channel::ChannelData;
use core::session::Session; use core::session::Session;
use core::util::FileId; use core::spotify_id::FileId;
pub fn get(session: &Session, file: FileId) -> ChannelData { pub fn get(session: &Session, file: FileId) -> ChannelData {
let (channel_id, channel) = session.channel().allocate(); let (channel_id, channel) = session.channel().allocate();

View file

@ -13,7 +13,7 @@ use linear_map::LinearMap;
use core::mercury::MercuryError; use core::mercury::MercuryError;
use core::session::Session; use core::session::Session;
use core::util::{SpotifyId, FileId, StrChunksExt}; use core::spotify_id::{FileId, SpotifyId};
pub use protocol::metadata::AudioFile_Format as FileFormat; pub use protocol::metadata::AudioFile_Format as FileFormat;
@ -22,7 +22,8 @@ fn countrylist_contains(list: &str, country: &str) -> bool {
} }
fn parse_restrictions<'s, I>(restrictions: I, country: &str, catalogue: &str) -> bool fn parse_restrictions<'s, I>(restrictions: I, country: &str, catalogue: &str) -> bool
where I: IntoIterator<Item = &'s protocol::metadata::Restriction> where
I: IntoIterator<Item = &'s protocol::metadata::Restriction>,
{ {
let mut forbidden = "".to_string(); let mut forbidden = "".to_string();
let mut has_forbidden = false; let mut has_forbidden = false;
@ -30,9 +31,9 @@ fn parse_restrictions<'s, I>(restrictions: I, country: &str, catalogue: &str) ->
let mut allowed = "".to_string(); let mut allowed = "".to_string();
let mut has_allowed = false; let mut has_allowed = false;
let rs = restrictions.into_iter().filter(|r| let rs = restrictions
r.get_catalogue_str().contains(&catalogue.to_owned()) .into_iter()
); .filter(|r| r.get_catalogue_str().contains(&catalogue.to_owned()));
for r in rs { for r in rs {
if r.has_countries_forbidden() { if r.has_countries_forbidden() {
@ -46,12 +47,12 @@ fn parse_restrictions<'s, I>(restrictions: I, country: &str, catalogue: &str) ->
} }
} }
(has_forbidden || has_allowed) && (has_forbidden || has_allowed)
(!has_forbidden || !countrylist_contains(forbidden.as_str(), country)) && && (!has_forbidden || !countrylist_contains(forbidden.as_str(), country))
(!has_allowed || countrylist_contains(allowed.as_str(), country)) && (!has_allowed || countrylist_contains(allowed.as_str(), country))
} }
pub trait Metadata : Send + Sized + 'static { pub trait Metadata: Send + Sized + 'static {
type Message: protobuf::MessageStatic; type Message: protobuf::MessageStatic;
fn base_url() -> &'static str; fn base_url() -> &'static str;
@ -110,20 +111,20 @@ impl Metadata for Track {
let country = session.country(); let country = session.country();
let artists = msg.get_artist() let artists = msg.get_artist()
.iter() .iter()
.filter(|artist| artist.has_gid()) .filter(|artist| artist.has_gid())
.map(|artist| SpotifyId::from_raw(artist.get_gid())) .map(|artist| SpotifyId::from_raw(artist.get_gid()))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let files = msg.get_file() let files = msg.get_file()
.iter() .iter()
.filter(|file| file.has_file_id()) .filter(|file| file.has_file_id())
.map(|file| { .map(|file| {
let mut dst = [0u8; 20]; let mut dst = [0u8; 20];
dst.clone_from_slice(file.get_file_id()); dst.clone_from_slice(file.get_file_id());
(file.get_format(), FileId(dst)) (file.get_format(), FileId(dst))
}) })
.collect(); .collect();
Track { Track {
id: SpotifyId::from_raw(msg.get_gid()), id: SpotifyId::from_raw(msg.get_gid()),
@ -133,12 +134,10 @@ impl Metadata for Track {
artists: artists, artists: artists,
files: files, files: files,
alternatives: msg.get_alternative() alternatives: msg.get_alternative()
.iter() .iter()
.map(|alt| SpotifyId::from_raw(alt.get_gid())) .map(|alt| SpotifyId::from_raw(alt.get_gid()))
.collect(), .collect(),
available: parse_restrictions(msg.get_restriction(), available: parse_restrictions(msg.get_restriction(), &country, "premium"),
&country,
"premium"),
} }
} }
} }
@ -152,28 +151,28 @@ impl Metadata for Album {
fn parse(msg: &Self::Message, _: &Session) -> Self { fn parse(msg: &Self::Message, _: &Session) -> Self {
let artists = msg.get_artist() let artists = msg.get_artist()
.iter() .iter()
.filter(|artist| artist.has_gid()) .filter(|artist| artist.has_gid())
.map(|artist| SpotifyId::from_raw(artist.get_gid())) .map(|artist| SpotifyId::from_raw(artist.get_gid()))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let tracks = msg.get_disc() let tracks = msg.get_disc()
.iter() .iter()
.flat_map(|disc| disc.get_track()) .flat_map(|disc| disc.get_track())
.filter(|track| track.has_gid()) .filter(|track| track.has_gid())
.map(|track| SpotifyId::from_raw(track.get_gid())) .map(|track| SpotifyId::from_raw(track.get_gid()))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let covers = msg.get_cover_group() let covers = msg.get_cover_group()
.get_image() .get_image()
.iter() .iter()
.filter(|image| image.has_file_id()) .filter(|image| image.has_file_id())
.map(|image| { .map(|image| {
let mut dst = [0u8; 20]; let mut dst = [0u8; 20];
dst.clone_from_slice(image.get_file_id()); dst.clone_from_slice(image.get_file_id());
FileId(dst) FileId(dst)
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
Album { Album {
id: SpotifyId::from_raw(msg.get_gid()), id: SpotifyId::from_raw(msg.get_gid()),
@ -185,7 +184,6 @@ impl Metadata for Album {
} }
} }
impl Metadata for Artist { impl Metadata for Artist {
type Message = protocol::metadata::Artist; type Message = protocol::metadata::Artist;
@ -197,23 +195,48 @@ impl Metadata for Artist {
let country = session.country(); let country = session.country();
let top_tracks: Vec<SpotifyId> = match msg.get_top_track() let top_tracks: Vec<SpotifyId> = match msg.get_top_track()
.iter() .iter()
.find(|tt| !tt.has_country() || countrylist_contains(tt.get_country(), &country)) { .find(|tt| !tt.has_country() || countrylist_contains(tt.get_country(), &country))
Some(tracks) => { {
tracks.get_track() Some(tracks) => tracks
.iter() .get_track()
.filter(|track| track.has_gid()) .iter()
.map(|track| SpotifyId::from_raw(track.get_gid())) .filter(|track| track.has_gid())
.collect::<Vec<_>>() .map(|track| SpotifyId::from_raw(track.get_gid()))
}, .collect::<Vec<_>>(),
None => Vec::new() None => Vec::new(),
}; };
Artist { Artist {
id: SpotifyId::from_raw(msg.get_gid()), id: SpotifyId::from_raw(msg.get_gid()),
name: msg.get_name().to_owned(), name: msg.get_name().to_owned(),
top_tracks: top_tracks top_tracks: top_tracks,
}
}
}
struct StrChunks<'s>(&'s str, usize);
trait StrChunksExt {
fn chunks(&self, size: usize) -> StrChunks;
}
impl StrChunksExt for str {
fn chunks(&self, size: usize) -> StrChunks {
StrChunks(self, size)
}
}
impl<'s> Iterator for StrChunks<'s> {
type Item = &'s str;
fn next(&mut self) -> Option<&'s str> {
let &mut StrChunks(data, size) = self;
if data.is_empty() {
None
} else {
let ret = Some(&data[..size]);
self.0 = &data[size..];
ret
} }
} }
} }

View file

@ -11,7 +11,7 @@ use std::time::Duration;
use config::{Bitrate, PlayerConfig}; use config::{Bitrate, PlayerConfig};
use core::session::Session; use core::session::Session;
use core::util::SpotifyId; use core::spotify_id::SpotifyId;
use audio_backend::Sink; use audio_backend::Sink;
use audio::{AudioFile, AudioDecrypt}; use audio::{AudioFile, AudioDecrypt};