1
0
Fork 0
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:
Roderick van Domburg 2022-01-03 00:13:28 +01:00
parent 2d699e288a
commit 7921f23927
No known key found for this signature in database
GPG key ID: FE2585E713F9F30A
13 changed files with 445 additions and 240 deletions

View file

@ -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)
}