|
@@ -17,11 +17,9 @@ use librespot_core::spotify_id::SpotifyId;
|
|
|
use audio::{AudioDecrypt, AudioFile, StreamLoaderController};
|
|
|
use audio::{VorbisDecoder, VorbisPacket};
|
|
|
use audio_backend::Sink;
|
|
|
-use metadata::{FileFormat, Metadata, Track};
|
|
|
+use metadata::{AudioItem, FileFormat};
|
|
|
use mixer::AudioFilter;
|
|
|
|
|
|
-
|
|
|
-
|
|
|
pub struct Player {
|
|
|
commands: Option<std::sync::mpsc::Sender<PlayerCommand>>,
|
|
|
thread_handle: Option<thread::JoinHandle<()>>,
|
|
@@ -547,17 +545,19 @@ impl PlayerInternal {
|
|
|
let _ = self.event_sender.unbounded_send(event.clone());
|
|
|
}
|
|
|
|
|
|
- fn find_available_alternative<'a>(&self, track: &'a Track) -> Option<Cow<'a, Track>> {
|
|
|
- if track.available {
|
|
|
- Some(Cow::Borrowed(track))
|
|
|
+ fn find_available_alternative<'a>(&self, audio: &'a AudioItem) -> Option<Cow<'a, AudioItem>> {
|
|
|
+ if audio.available {
|
|
|
+ Some(Cow::Borrowed(audio))
|
|
|
} else {
|
|
|
- let alternatives = track
|
|
|
- .alternatives
|
|
|
- .iter()
|
|
|
- .map(|alt_id| Track::get(&self.session, *alt_id));
|
|
|
- let alternatives = future::join_all(alternatives).wait().unwrap();
|
|
|
-
|
|
|
- alternatives.into_iter().find(|alt| alt.available).map(Cow::Owned)
|
|
|
+ if let Some(alternatives) = &audio.alternatives {
|
|
|
+ let alternatives = alternatives
|
|
|
+ .iter()
|
|
|
+ .map(|alt_id| AudioItem::get_audio_item(&self.session, *alt_id));
|
|
|
+ let alternatives = future::join_all(alternatives).wait().unwrap();
|
|
|
+ alternatives.into_iter().find(|alt| alt.available).map(Cow::Owned)
|
|
|
+ } else {
|
|
|
+ None
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -569,60 +569,53 @@ impl PlayerInternal {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- fn load_track(&self, track_id: SpotifyId, position: i64) -> Option<(Decoder, f32, StreamLoaderController)> {
|
|
|
- let track = Track::get(&self.session, track_id).wait().unwrap();
|
|
|
-
|
|
|
- info!(
|
|
|
- "Loading track \"{}\" with Spotify URI \"spotify:track:{}\"",
|
|
|
- track.name,
|
|
|
- track_id.to_base62()
|
|
|
- );
|
|
|
-
|
|
|
- info!("find_available_alternative");
|
|
|
+ fn load_track(&self, spotify_id: SpotifyId, position: i64) -> Option<(Decoder, f32, StreamLoaderController)> {
|
|
|
+ let audio = AudioItem::get_audio_item(&self.session, spotify_id)
|
|
|
+ .wait()
|
|
|
+ .unwrap();
|
|
|
+ info!("Loading <{}> with Spotify URI <{}>", audio.name, audio.uri);
|
|
|
|
|
|
- let track = match self.find_available_alternative(&track) {
|
|
|
- Some(track) => track,
|
|
|
+ let audio = match self.find_available_alternative(&audio) {
|
|
|
+ Some(audio) => audio,
|
|
|
None => {
|
|
|
- warn!("Track \"{}\" is not available", track.name);
|
|
|
+ warn!("<{}> is not available", audio.uri);
|
|
|
return None;
|
|
|
}
|
|
|
};
|
|
|
-
|
|
|
- info!("config.bitrate");
|
|
|
-
|
|
|
-
|
|
|
- let format = match self.config.bitrate {
|
|
|
- Bitrate::Bitrate96 => FileFormat::OGG_VORBIS_96,
|
|
|
- Bitrate::Bitrate160 => FileFormat::OGG_VORBIS_160,
|
|
|
- Bitrate::Bitrate320 => FileFormat::OGG_VORBIS_320,
|
|
|
+ // (Most) podcasts seem to support only 96 bit Vorbis, so fall back to it
|
|
|
+ let formats = match self.config.bitrate {
|
|
|
+ Bitrate::Bitrate96 => [
|
|
|
+ FileFormat::OGG_VORBIS_96,
|
|
|
+ FileFormat::OGG_VORBIS_160,
|
|
|
+ FileFormat::OGG_VORBIS_320,
|
|
|
+ ],
|
|
|
+ Bitrate::Bitrate160 => [
|
|
|
+ FileFormat::OGG_VORBIS_160,
|
|
|
+ FileFormat::OGG_VORBIS_96,
|
|
|
+ FileFormat::OGG_VORBIS_320,
|
|
|
+ ],
|
|
|
+ Bitrate::Bitrate320 => [
|
|
|
+ FileFormat::OGG_VORBIS_320,
|
|
|
+ FileFormat::OGG_VORBIS_160,
|
|
|
+ FileFormat::OGG_VORBIS_96,
|
|
|
+ ],
|
|
|
};
|
|
|
+ let format = formats
|
|
|
+ .iter()
|
|
|
+ .find(|format| audio.files.contains_key(format))
|
|
|
+ .unwrap();
|
|
|
|
|
|
- info!("file_id");
|
|
|
-
|
|
|
- let file_id = match track.files.get(&format) {
|
|
|
+ let file_id = match audio.files.get(&format) {
|
|
|
Some(&file_id) => file_id,
|
|
|
None => {
|
|
|
- warn!("Track \"{}\" is not available in format {:?}", track.name, format);
|
|
|
+ warn!("<{}> in not available in format {:?}", audio.name, format);
|
|
|
return None;
|
|
|
}
|
|
|
};
|
|
|
|
|
|
- info!("key");
|
|
|
-
|
|
|
- let key = self
|
|
|
- .session
|
|
|
- .audio_key()
|
|
|
- .request(track.id, file_id);
|
|
|
- //.wait()
|
|
|
- //.unwrap()
|
|
|
-
|
|
|
- info!("encrypted_file");
|
|
|
-
|
|
|
+ let key = self.session.audio_key().request(spotify_id, file_id);
|
|
|
let encrypted_file = AudioFile::open(&self.session, file_id);
|
|
|
|
|
|
-
|
|
|
- info!("waiting for encrypted_file");
|
|
|
-
|
|
|
let encrypted_file = encrypted_file.wait().unwrap();
|
|
|
|
|
|
let mut stream_loader_controller = encrypted_file.get_stream_loader_controller();
|
|
@@ -639,16 +632,9 @@ impl PlayerInternal {
|
|
|
}
|
|
|
|
|
|
|
|
|
-
|
|
|
- info!("wait for key");
|
|
|
let key = key.wait().unwrap();
|
|
|
-
|
|
|
- info!("decrypted_file");
|
|
|
-
|
|
|
let mut decrypted_file = AudioDecrypt::new(key, encrypted_file);
|
|
|
|
|
|
- info!("normalisation_factor");
|
|
|
-
|
|
|
let normalisation_factor = match NormalisationData::parse_from_file(&mut decrypted_file) {
|
|
|
Ok(normalisation_data) => NormalisationData::get_factor(&self.config, normalisation_data),
|
|
|
Err(_) => {
|
|
@@ -657,12 +643,8 @@ impl PlayerInternal {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
- info!("new Subfile");
|
|
|
-
|
|
|
let audio_file = Subfile::new(decrypted_file, 0xa7);
|
|
|
|
|
|
- info!("new VorbisDecoder");
|
|
|
-
|
|
|
let mut decoder = VorbisDecoder::new(audio_file).unwrap();
|
|
|
|
|
|
if position != 0 {
|
|
@@ -672,9 +654,7 @@ impl PlayerInternal {
|
|
|
}
|
|
|
stream_loader_controller.set_stream_mode();
|
|
|
}
|
|
|
-
|
|
|
- info!("Track \"{}\" loaded", track.name);
|
|
|
-
|
|
|
+ info!("<{}> loaded", audio.name);
|
|
|
Some((decoder, normalisation_factor, stream_loader_controller))
|
|
|
}
|
|
|
}
|