mirror of
https://github.com/librespot-org/librespot.git
synced 2025-10-04 18:29:45 +02:00
Improve format handling and support MP3
- Switch from `lewton` to `Symphonia`. This is a pure Rust demuxer and decoder in active development that supports a wide range of formats, including Ogg Vorbis, MP3, AAC and FLAC for future HiFi support. At the moment only Ogg Vorbis and MP3 are enabled; all AAC files are DRM-protected. - Bump MSRV to 1.51, required for `Symphonia`. - Filter out all files whose format is not specified. - Not all episodes seem to be encrypted. If we can't get an audio key, try and see if we can play the file without decryption. - After seeking, report the actual position instead of the target. - Remove the 0xa7 bytes offset from `Subfile`, `Symphonia` does not balk at Spotify's custom Ogg packet before it. This also simplifies handling of formats other than Ogg Vorbis. - When there is no next track to load, signal the UI that the player has stopped. Before, the player would get stuck in an infinite reloading loop when there was only one track in the queue and that track could not be loaded.
This commit is contained in:
parent
2d699e288a
commit
7921f23927
13 changed files with 445 additions and 240 deletions
|
@ -14,16 +14,20 @@ const AUDIO_AESIV: [u8; 16] = [
|
|||
];
|
||||
|
||||
pub struct AudioDecrypt<T: io::Read> {
|
||||
cipher: Aes128Ctr,
|
||||
// a `None` cipher is a convenience to make `AudioDecrypt` pass files unaltered
|
||||
cipher: Option<Aes128Ctr>,
|
||||
reader: T,
|
||||
}
|
||||
|
||||
impl<T: io::Read> AudioDecrypt<T> {
|
||||
pub fn new(key: AudioKey, reader: T) -> AudioDecrypt<T> {
|
||||
let cipher = Aes128Ctr::new(
|
||||
GenericArray::from_slice(&key.0),
|
||||
GenericArray::from_slice(&AUDIO_AESIV),
|
||||
);
|
||||
pub fn new(key: Option<AudioKey>, reader: T) -> AudioDecrypt<T> {
|
||||
let cipher = key.map(|key| {
|
||||
Aes128Ctr::new(
|
||||
GenericArray::from_slice(&key.0),
|
||||
GenericArray::from_slice(&AUDIO_AESIV),
|
||||
)
|
||||
});
|
||||
|
||||
AudioDecrypt { cipher, reader }
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +36,9 @@ impl<T: io::Read> io::Read for AudioDecrypt<T> {
|
|||
fn read(&mut self, output: &mut [u8]) -> io::Result<usize> {
|
||||
let len = self.reader.read(output)?;
|
||||
|
||||
self.cipher.apply_keystream(&mut output[..len]);
|
||||
if let Some(ref mut cipher) = self.cipher {
|
||||
cipher.apply_keystream(&mut output[..len]);
|
||||
}
|
||||
|
||||
Ok(len)
|
||||
}
|
||||
|
@ -42,7 +48,9 @@ impl<T: io::Read + io::Seek> io::Seek for AudioDecrypt<T> {
|
|||
fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
|
||||
let newpos = self.reader.seek(pos)?;
|
||||
|
||||
self.cipher.seek(newpos);
|
||||
if let Some(ref mut cipher) = self.cipher {
|
||||
cipher.seek(newpos);
|
||||
}
|
||||
|
||||
Ok(newpos)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue