mirror of
https://github.com/librespot-org/librespot.git
synced 2024-11-08 16:45:43 +00:00
Improve handling of missing audio keys by failing the future rather than crashing.
This commit is contained in:
parent
8c2aa28d43
commit
654a403459
3 changed files with 32 additions and 16 deletions
|
@ -9,13 +9,16 @@ use session::Session;
|
|||
use connection::PacketHandler;
|
||||
|
||||
pub type AudioKey = [u8; 16];
|
||||
#[derive(Debug,Hash,PartialEq,Eq,Copy,Clone)]
|
||||
pub struct AudioKeyError;
|
||||
|
||||
#[derive(Debug,Hash,PartialEq,Eq,Clone)]
|
||||
struct AudioKeyId(SpotifyId, FileId);
|
||||
|
||||
enum AudioKeyStatus {
|
||||
Loading(Vec<eventual::Complete<AudioKey, ()>>),
|
||||
Loaded(AudioKey)
|
||||
Loading(Vec<eventual::Complete<AudioKey, AudioKeyError>>),
|
||||
Loaded(AudioKey),
|
||||
Failed(AudioKeyError)
|
||||
}
|
||||
|
||||
pub struct AudioKeyManager {
|
||||
|
@ -34,12 +37,15 @@ impl AudioKeyManager {
|
|||
}
|
||||
|
||||
pub fn request(&mut self, session: &Session, track: SpotifyId, file: FileId)
|
||||
-> eventual::Future<AudioKey, ()> {
|
||||
-> eventual::Future<AudioKey, AudioKeyError> {
|
||||
|
||||
let id = AudioKeyId(track, file);
|
||||
self.cache.get_mut(&id).map(|status| match *status {
|
||||
AudioKeyStatus::Failed(error) => {
|
||||
eventual::Future::error(error)
|
||||
}
|
||||
AudioKeyStatus::Loaded(key) => {
|
||||
eventual::Future::of(key.clone())
|
||||
eventual::Future::of(key)
|
||||
}
|
||||
AudioKeyStatus::Loading(ref mut req) => {
|
||||
let (tx, rx) = eventual::Future::pair();
|
||||
|
@ -69,19 +75,29 @@ impl AudioKeyManager {
|
|||
|
||||
impl PacketHandler for AudioKeyManager {
|
||||
fn handle(&mut self, cmd: u8, data: Vec<u8>) {
|
||||
assert_eq!(cmd, 0xd);
|
||||
|
||||
let mut data = Cursor::new(data);
|
||||
let seq = data.read_u32::<BigEndian>().unwrap();
|
||||
let mut key = [0u8; 16];
|
||||
data.read_exact(&mut key).unwrap();
|
||||
|
||||
if let Some(status) = self.pending.remove(&seq).and_then(|id| { self.cache.get_mut(&id) }) {
|
||||
let status = mem::replace(status, AudioKeyStatus::Loaded(key));
|
||||
if cmd == 0xd {
|
||||
let mut key = [0u8; 16];
|
||||
data.read_exact(&mut key).unwrap();
|
||||
|
||||
if let AudioKeyStatus::Loading(cbs) = status {
|
||||
for cb in cbs {
|
||||
cb.complete(key);
|
||||
let status = mem::replace(status, AudioKeyStatus::Loaded(key));
|
||||
|
||||
if let AudioKeyStatus::Loading(cbs) = status {
|
||||
for cb in cbs {
|
||||
cb.complete(key);
|
||||
}
|
||||
}
|
||||
} else if cmd == 0xe {
|
||||
let error = AudioKeyError;
|
||||
let status = mem::replace(status, AudioKeyStatus::Failed(error));
|
||||
|
||||
if let AudioKeyStatus::Loading(cbs) = status {
|
||||
for cb in cbs {
|
||||
cb.fail(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ impl MetadataTrait for Album {
|
|||
"hm://metadata/3/album"
|
||||
}
|
||||
|
||||
fn parse(msg: &Self::Message, session: &Session) -> Self {
|
||||
fn parse(msg: &Self::Message, _: &Session) -> Self {
|
||||
Album {
|
||||
id: SpotifyId::from_raw(msg.get_gid()),
|
||||
name: msg.get_name().to_owned(),
|
||||
|
@ -118,7 +118,7 @@ impl MetadataTrait for Artist {
|
|||
"hm://metadata/3/artist"
|
||||
}
|
||||
|
||||
fn parse(msg: &Self::Message, session: &Session) -> Self {
|
||||
fn parse(msg: &Self::Message, _: &Session) -> Self {
|
||||
Artist {
|
||||
id: SpotifyId::from_raw(msg.get_gid()),
|
||||
name: msg.get_name().to_owned(),
|
||||
|
|
|
@ -14,7 +14,7 @@ use util::{SpotifyId, FileId, mkdir_existing};
|
|||
use mercury::{MercuryManager, MercuryRequest, MercuryResponse};
|
||||
use metadata::{MetadataManager, MetadataRef, MetadataTrait};
|
||||
use stream::{StreamManager, StreamEvent};
|
||||
use audio_key::{AudioKeyManager, AudioKey};
|
||||
use audio_key::{AudioKeyManager, AudioKey, AudioKeyError};
|
||||
use audio_file::{AudioFileManager, AudioFile};
|
||||
use connection::PacketHandler;
|
||||
|
||||
|
@ -189,7 +189,7 @@ impl Session {
|
|||
self.0.tx_connection.lock().unwrap().send_packet(cmd, data)
|
||||
}
|
||||
|
||||
pub fn audio_key(&self, track: SpotifyId, file: FileId) -> Future<AudioKey, ()> {
|
||||
pub fn audio_key(&self, track: SpotifyId, file: FileId) -> Future<AudioKey, AudioKeyError> {
|
||||
self.0.audio_key.lock().unwrap().request(self, track, file)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue