mirror of
https://github.com/librespot-org/librespot.git
synced 2024-12-18 17:11:53 +00:00
Remove AudioFileManager and MetadataManager since they are stateless.
This commit is contained in:
parent
72070b6ce0
commit
d59f3eff81
5 changed files with 31 additions and 60 deletions
|
@ -4,11 +4,6 @@ applications to use Spotify's service, without using the official but
|
||||||
closed-source libspotify. Additionally, it will provide extra features
|
closed-source libspotify. Additionally, it will provide extra features
|
||||||
which are not available in the official library.
|
which are not available in the official library.
|
||||||
|
|
||||||
**I will be very busy with other stuff until July, and won't be able to
|
|
||||||
dedicate much time to librespot. Please keep using it and open issues,
|
|
||||||
but it's likely I won't be able to answer them until then. Non-trivial
|
|
||||||
pull requests will probably not be reviewed either.**
|
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
Rust 1.15.0 or later is required to build librespot.
|
Rust 1.15.0 or later is required to build librespot.
|
||||||
|
|
||||||
|
|
|
@ -16,10 +16,6 @@ use util::FileId;
|
||||||
|
|
||||||
const CHUNK_SIZE: usize = 0x20000;
|
const CHUNK_SIZE: usize = 0x20000;
|
||||||
|
|
||||||
component! {
|
|
||||||
AudioFileManager : AudioFileManagerInner { }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum AudioFile {
|
pub enum AudioFile {
|
||||||
Cached(fs::File),
|
Cached(fs::File),
|
||||||
Streaming(AudioFileStreaming),
|
Streaming(AudioFileStreaming),
|
||||||
|
@ -127,9 +123,9 @@ impl Future for AudioFileOpenStreaming {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AudioFileManager {
|
impl AudioFile {
|
||||||
pub fn open(&self, file_id: FileId) -> AudioFileOpen {
|
pub fn open(session: &Session, file_id: FileId) -> AudioFileOpen {
|
||||||
let cache = self.session().cache().cloned();
|
let cache = session.cache().cloned();
|
||||||
|
|
||||||
if let Some(file) = cache.as_ref().and_then(|cache| cache.file(file_id)) {
|
if let Some(file) = cache.as_ref().and_then(|cache| cache.file(file_id)) {
|
||||||
debug!("File {} already in cache", file_id);
|
debug!("File {} already in cache", file_id);
|
||||||
|
@ -139,10 +135,10 @@ impl AudioFileManager {
|
||||||
debug!("Downloading file {}", file_id);
|
debug!("Downloading file {}", file_id);
|
||||||
|
|
||||||
let (complete_tx, complete_rx) = oneshot::channel();
|
let (complete_tx, complete_rx) = oneshot::channel();
|
||||||
let (headers, data) = request_chunk(&self.session(), file_id, 0).split();
|
let (headers, data) = request_chunk(session, file_id, 0).split();
|
||||||
|
|
||||||
let open = AudioFileOpenStreaming {
|
let open = AudioFileOpenStreaming {
|
||||||
session: self.session(),
|
session: session.clone(),
|
||||||
file_id: file_id,
|
file_id: file_id,
|
||||||
|
|
||||||
headers: headers,
|
headers: headers,
|
||||||
|
@ -151,10 +147,10 @@ impl AudioFileManager {
|
||||||
complete_tx: Some(complete_tx),
|
complete_tx: Some(complete_tx),
|
||||||
};
|
};
|
||||||
|
|
||||||
let session = self.session();
|
let session_ = session.clone();
|
||||||
self.session().spawn(move |_| {
|
session.spawn(move |_| {
|
||||||
complete_rx.map(move |mut file| {
|
complete_rx.map(move |mut file| {
|
||||||
if let Some(cache) = session.cache() {
|
if let Some(cache) = session_.cache() {
|
||||||
cache.save_file(file_id, &mut file);
|
cache.save_file(file_id, &mut file);
|
||||||
debug!("File {} complete, saving to cache", file_id);
|
debug!("File {} complete, saving to cache", file_id);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -43,11 +43,24 @@ fn parse_restrictions<'s, I>(restrictions: I, country: &str, catalogue: &str) ->
|
||||||
(!has_allowed || countrylist_contains(allowed.as_str(), country))
|
(!has_allowed || countrylist_contains(allowed.as_str(), country))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait MetadataTrait : Send + '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;
|
||||||
fn parse(msg: &Self::Message, session: &Session) -> Self;
|
fn parse(msg: &Self::Message, session: &Session) -> Self;
|
||||||
|
|
||||||
|
fn get(session: &Session, id: SpotifyId) -> BoxFuture<Self, MercuryError> {
|
||||||
|
let uri = format!("{}/{}", Self::base_url(), id.to_base16());
|
||||||
|
let request = session.mercury().get(uri);
|
||||||
|
|
||||||
|
let session = session.clone();
|
||||||
|
request.and_then(move |response| {
|
||||||
|
let data = response.payload.first().expect("Empty payload");
|
||||||
|
let msg: Self::Message = protobuf::parse_from_bytes(data).unwrap();
|
||||||
|
|
||||||
|
Ok(Self::parse(&msg, &session))
|
||||||
|
}).boxed()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -77,7 +90,7 @@ pub struct Artist {
|
||||||
pub top_tracks: Vec<SpotifyId>,
|
pub top_tracks: Vec<SpotifyId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MetadataTrait for Track {
|
impl Metadata for Track {
|
||||||
type Message = protocol::metadata::Track;
|
type Message = protocol::metadata::Track;
|
||||||
|
|
||||||
fn base_url() -> &'static str {
|
fn base_url() -> &'static str {
|
||||||
|
@ -120,7 +133,7 @@ impl MetadataTrait for Track {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MetadataTrait for Album {
|
impl Metadata for Album {
|
||||||
type Message = protocol::metadata::Album;
|
type Message = protocol::metadata::Album;
|
||||||
|
|
||||||
fn base_url() -> &'static str {
|
fn base_url() -> &'static str {
|
||||||
|
@ -163,7 +176,7 @@ impl MetadataTrait for Album {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl MetadataTrait for Artist {
|
impl Metadata for Artist {
|
||||||
type Message = protocol::metadata::Artist;
|
type Message = protocol::metadata::Artist;
|
||||||
|
|
||||||
fn base_url() -> &'static str {
|
fn base_url() -> &'static str {
|
||||||
|
@ -191,22 +204,3 @@ impl MetadataTrait for Artist {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
component! {
|
|
||||||
MetadataManager : MetadataManagerInner { }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MetadataManager {
|
|
||||||
pub fn get<T: MetadataTrait>(&self, id: SpotifyId) -> BoxFuture<T, MercuryError> {
|
|
||||||
let session = self.session();
|
|
||||||
|
|
||||||
let uri = format!("{}/{}", T::base_url(), id.to_base16());
|
|
||||||
let request = session.mercury().get(uri);
|
|
||||||
|
|
||||||
request.and_then(move |response| {
|
|
||||||
let data = response.payload.first().expect("Empty payload");
|
|
||||||
let msg: T::Message = protobuf::parse_from_bytes(data).unwrap();
|
|
||||||
|
|
||||||
Ok(T::parse(&msg, &session))
|
|
||||||
}).boxed()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ use vorbis::{self, VorbisError};
|
||||||
use audio_backend::Sink;
|
use audio_backend::Sink;
|
||||||
use audio_decrypt::AudioDecrypt;
|
use audio_decrypt::AudioDecrypt;
|
||||||
use audio_file::AudioFile;
|
use audio_file::AudioFile;
|
||||||
use metadata::{FileFormat, Track};
|
use metadata::{FileFormat, Track, Metadata};
|
||||||
use session::Session;
|
use session::Session;
|
||||||
use mixer::AudioFilter;
|
use mixer::AudioFilter;
|
||||||
use util::{self, SpotifyId, Subfile};
|
use util::{self, SpotifyId, Subfile};
|
||||||
|
@ -338,7 +338,7 @@ impl PlayerInternal {
|
||||||
let alternatives = track.alternatives
|
let alternatives = track.alternatives
|
||||||
.iter()
|
.iter()
|
||||||
.map(|alt_id| {
|
.map(|alt_id| {
|
||||||
self.session.metadata().get::<Track>(*alt_id)
|
Track::get(&self.session, *alt_id)
|
||||||
});
|
});
|
||||||
let alternatives = future::join_all(alternatives).wait().unwrap();
|
let alternatives = future::join_all(alternatives).wait().unwrap();
|
||||||
|
|
||||||
|
@ -347,7 +347,7 @@ impl PlayerInternal {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_track(&self, track_id: SpotifyId, position: i64) -> Option<Decoder> {
|
fn load_track(&self, track_id: SpotifyId, position: i64) -> Option<Decoder> {
|
||||||
let track = self.session.metadata().get::<Track>(track_id).wait().unwrap();
|
let track = Track::get(&self.session, track_id).wait().unwrap();
|
||||||
|
|
||||||
info!("Loading track \"{}\"", track.name);
|
info!("Loading track \"{}\"", track.name);
|
||||||
|
|
||||||
|
@ -375,10 +375,9 @@ impl PlayerInternal {
|
||||||
|
|
||||||
let key = self.session.audio_key().request(track.id, file_id).wait().unwrap();
|
let key = self.session.audio_key().request(track.id, file_id).wait().unwrap();
|
||||||
|
|
||||||
let open = self.session.audio_file().open(file_id);
|
let encrypted_file = AudioFile::open(&self.session, file_id).wait().unwrap();
|
||||||
let encrypted_file = open.wait().unwrap();
|
|
||||||
|
|
||||||
let audio_file = Subfile::new(AudioDecrypt::new(key, encrypted_file), 0xa7);
|
let audio_file = Subfile::new(AudioDecrypt::new(key, encrypted_file), 0xa7);
|
||||||
|
|
||||||
let mut decoder = vorbis::Decoder::new(audio_file).unwrap();
|
let mut decoder = vorbis::Decoder::new(audio_file).unwrap();
|
||||||
|
|
||||||
match vorbis_time_seek_ms(&mut decoder, position) {
|
match vorbis_time_seek_ms(&mut decoder, position) {
|
||||||
|
|
|
@ -18,8 +18,6 @@ use config::SessionConfig;
|
||||||
use audio_key::AudioKeyManager;
|
use audio_key::AudioKeyManager;
|
||||||
use channel::ChannelManager;
|
use channel::ChannelManager;
|
||||||
use mercury::MercuryManager;
|
use mercury::MercuryManager;
|
||||||
use metadata::MetadataManager;
|
|
||||||
use audio_file::AudioFileManager;
|
|
||||||
|
|
||||||
pub struct SessionData {
|
pub struct SessionData {
|
||||||
country: String,
|
country: String,
|
||||||
|
@ -33,10 +31,8 @@ pub struct SessionInternal {
|
||||||
tx_connection: mpsc::UnboundedSender<(u8, Vec<u8>)>,
|
tx_connection: mpsc::UnboundedSender<(u8, Vec<u8>)>,
|
||||||
|
|
||||||
audio_key: Lazy<AudioKeyManager>,
|
audio_key: Lazy<AudioKeyManager>,
|
||||||
audio_file: Lazy<AudioFileManager>,
|
|
||||||
channel: Lazy<ChannelManager>,
|
channel: Lazy<ChannelManager>,
|
||||||
mercury: Lazy<MercuryManager>,
|
mercury: Lazy<MercuryManager>,
|
||||||
metadata: Lazy<MetadataManager>,
|
|
||||||
cache: Option<Arc<Cache>>,
|
cache: Option<Arc<Cache>>,
|
||||||
|
|
||||||
handle: Remote,
|
handle: Remote,
|
||||||
|
@ -62,6 +58,7 @@ impl Session {
|
||||||
{
|
{
|
||||||
let access_point = apresolve_or_fallback::<io::Error>(&handle);
|
let access_point = apresolve_or_fallback::<io::Error>(&handle);
|
||||||
|
|
||||||
|
|
||||||
let handle_ = handle.clone();
|
let handle_ = handle.clone();
|
||||||
let connection = access_point.and_then(move |addr| {
|
let connection = access_point.and_then(move |addr| {
|
||||||
info!("Connecting to AP \"{}\"", addr);
|
info!("Connecting to AP \"{}\"", addr);
|
||||||
|
@ -114,10 +111,8 @@ impl Session {
|
||||||
cache: cache.map(Arc::new),
|
cache: cache.map(Arc::new),
|
||||||
|
|
||||||
audio_key: Lazy::new(),
|
audio_key: Lazy::new(),
|
||||||
audio_file: Lazy::new(),
|
|
||||||
channel: Lazy::new(),
|
channel: Lazy::new(),
|
||||||
mercury: Lazy::new(),
|
mercury: Lazy::new(),
|
||||||
metadata: Lazy::new(),
|
|
||||||
|
|
||||||
handle: handle.remote().clone(),
|
handle: handle.remote().clone(),
|
||||||
|
|
||||||
|
@ -139,10 +134,6 @@ impl Session {
|
||||||
self.0.audio_key.get(|| AudioKeyManager::new(self.weak()))
|
self.0.audio_key.get(|| AudioKeyManager::new(self.weak()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn audio_file(&self) -> &AudioFileManager {
|
|
||||||
self.0.audio_file.get(|| AudioFileManager::new(self.weak()))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn channel(&self) -> &ChannelManager {
|
pub fn channel(&self) -> &ChannelManager {
|
||||||
self.0.channel.get(|| ChannelManager::new(self.weak()))
|
self.0.channel.get(|| ChannelManager::new(self.weak()))
|
||||||
}
|
}
|
||||||
|
@ -151,10 +142,6 @@ impl Session {
|
||||||
self.0.mercury.get(|| MercuryManager::new(self.weak()))
|
self.0.mercury.get(|| MercuryManager::new(self.weak()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn metadata(&self) -> &MetadataManager {
|
|
||||||
self.0.metadata.get(|| MetadataManager::new(self.weak()))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn spawn<F, R>(&self, f: F)
|
pub fn spawn<F, R>(&self, f: F)
|
||||||
where F: FnOnce(&Handle) -> R + Send + 'static,
|
where F: FnOnce(&Handle) -> R + Send + 'static,
|
||||||
R: IntoFuture<Item=(), Error=()>,
|
R: IntoFuture<Item=(), Error=()>,
|
||||||
|
|
Loading…
Reference in a new issue