Skip to content

Commit 59381cc

Browse files
authored
Handle/Ignore unknown audio formats (#1467)
* ignore unknown enum values * update CHANGELOG.md * metadata: introduce own AudioFileFormat * metadata: adjust handling for better readability
1 parent cb958a0 commit 59381cc

3 files changed

Lines changed: 84 additions & 7 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1616
- [connect] Replaced `SpircLoadCommand` with `LoadRequest`, `LoadRequestOptions` and `LoadContextOptions` (breaking)
1717
- [connect] Moved all public items to the highest level (breaking)
1818
- [connect] Replaced Mercury usage in `Spirc` with Dealer
19+
- [metadata] Replaced `AudioFileFormat` with own enum. (breaking)
1920

2021
### Added
2122

@@ -39,6 +40,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3940
- [connect] Fix "play" command not handled if missing "offset" property
4041
- [discovery] Fix libmdns zerconf setup errors not propagating to the main task.
4142
- [metadata] `Show::trailer_uri` is now optional since it isn't always present (breaking)
43+
- [metadata] Fix incorrect parsing of audio format
4244
- [connect] Handle transfer of playback with empty "uri" field
4345
- [connect] Correctly apply playing/paused state when transferring playback
4446
- [player] Saturate invalid seek positions to track duration

metadata/src/audio/file.rs

Lines changed: 78 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,73 @@ use std::{
66

77
use librespot_core::FileId;
88

9+
use crate::util::impl_deref_wrapped;
910
use librespot_protocol as protocol;
10-
pub use protocol::metadata::audio_file::Format as AudioFileFormat;
1111
use protocol::metadata::AudioFile as AudioFileMessage;
1212

13-
use crate::util::impl_deref_wrapped;
13+
use librespot_protocol::metadata::audio_file::Format;
14+
use protobuf::Enum;
15+
16+
#[allow(non_camel_case_types)]
17+
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
18+
pub enum AudioFileFormat {
19+
OGG_VORBIS_96, // 0
20+
OGG_VORBIS_160, // 1
21+
OGG_VORBIS_320, // 2
22+
MP3_256, // 3
23+
MP3_320, // 4
24+
MP3_160, // 5
25+
MP3_96, // 6
26+
MP3_160_ENC, // 7
27+
AAC_24, // 8
28+
AAC_48, // 9
29+
FLAC_FLAC, // 16
30+
XHE_AAC_24, // 18
31+
XHE_AAC_16, // 19
32+
XHE_AAC_12, // 20
33+
FLAC_FLAC_24BIT, // 22
34+
// not defined in protobuf, but sometimes send
35+
AAC_160, // 10
36+
AAC_320, // 11
37+
MP4_128, // 12
38+
OTHER5, // 13
39+
}
40+
41+
impl TryFrom<i32> for AudioFileFormat {
42+
type Error = i32;
43+
44+
fn try_from(value: i32) -> Result<Self, Self::Error> {
45+
Ok(match value {
46+
10 => AudioFileFormat::AAC_160,
47+
11 => AudioFileFormat::AAC_320,
48+
12 => AudioFileFormat::MP4_128,
49+
13 => AudioFileFormat::OTHER5,
50+
_ => Format::from_i32(value).ok_or(value)?.into(),
51+
})
52+
}
53+
}
54+
55+
impl From<Format> for AudioFileFormat {
56+
fn from(value: Format) -> Self {
57+
match value {
58+
Format::OGG_VORBIS_96 => AudioFileFormat::OGG_VORBIS_96,
59+
Format::OGG_VORBIS_160 => AudioFileFormat::OGG_VORBIS_160,
60+
Format::OGG_VORBIS_320 => AudioFileFormat::OGG_VORBIS_320,
61+
Format::MP3_256 => AudioFileFormat::MP3_256,
62+
Format::MP3_320 => AudioFileFormat::MP3_320,
63+
Format::MP3_160 => AudioFileFormat::MP3_160,
64+
Format::MP3_96 => AudioFileFormat::MP3_96,
65+
Format::MP3_160_ENC => AudioFileFormat::MP3_160_ENC,
66+
Format::AAC_24 => AudioFileFormat::AAC_24,
67+
Format::AAC_48 => AudioFileFormat::AAC_48,
68+
Format::FLAC_FLAC => AudioFileFormat::FLAC_FLAC,
69+
Format::XHE_AAC_24 => AudioFileFormat::XHE_AAC_24,
70+
Format::XHE_AAC_16 => AudioFileFormat::XHE_AAC_16,
71+
Format::XHE_AAC_12 => AudioFileFormat::XHE_AAC_12,
72+
Format::FLAC_FLAC_24BIT => AudioFileFormat::FLAC_FLAC_24BIT,
73+
}
74+
}
75+
}
1476

1577
#[derive(Debug, Clone, Default)]
1678
pub struct AudioFiles(pub HashMap<AudioFileFormat, FileId>);
@@ -49,12 +111,21 @@ impl From<&[AudioFileMessage]> for AudioFiles {
49111
.iter()
50112
.filter_map(|file| {
51113
let file_id = FileId::from(file.file_id());
52-
if file.has_format() {
53-
Some((file.format(), file_id))
54-
} else {
55-
trace!("Ignoring file <{}> with unspecified format", file_id);
56-
None
114+
let format = file
115+
.format
116+
.ok_or(format!("Ignoring file <{file_id}> with unspecified format",))
117+
.and_then(|format| match format.enum_value() {
118+
Ok(f) => Ok((f.into(), file_id)),
119+
Err(unknown) => Err(format!(
120+
"Ignoring file <{file_id}> with unknown format {unknown}",
121+
)),
122+
});
123+
124+
if let Err(ref why) = format {
125+
trace!("{why}");
57126
}
127+
128+
format.ok()
58129
})
59130
.collect();
60131

playback/src/player.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -917,6 +917,10 @@ impl PlayerTrackLoader {
917917
AudioFileFormat::MP3_160_ENC => 20.,
918918
AudioFileFormat::AAC_24 => 3.,
919919
AudioFileFormat::AAC_48 => 6.,
920+
AudioFileFormat::AAC_160 => 20.,
921+
AudioFileFormat::AAC_320 => 40.,
922+
AudioFileFormat::MP4_128 => 16.,
923+
AudioFileFormat::OTHER5 => 40.,
920924
AudioFileFormat::FLAC_FLAC => 112., // assume 900 kbit/s on average
921925
AudioFileFormat::XHE_AAC_12 => 1.5,
922926
AudioFileFormat::XHE_AAC_16 => 2.,

0 commit comments

Comments
 (0)