proteus_lib/container/play_settings/
mod.rs1use log::{info, warn};
4use serde::{Deserialize, Deserializer, Serialize, Serializer};
5
6pub mod legacy;
7pub mod v1;
8pub mod v2;
9
10pub use legacy::{PlaySettingsLegacy, PlaySettingsLegacyFile, PlaySettingsTrackLegacy};
11pub use v1::{PlaySettingsV1, PlaySettingsV1File};
12pub use v2::{PlaySettingsV2, PlaySettingsV2File};
13
14#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct ReverbSettings {
17 pub decay: f32,
18 pub pre_delay: f32,
19 pub mix: f32,
20 pub active: bool,
21}
22
23#[derive(Debug, Clone, Serialize, Deserialize)]
25pub struct CompressorSettings {
26 pub attack: f32,
27 pub knee: f32,
28 pub ratio: f32,
29 pub release: f32,
30 pub threshold: f32,
31 pub active: bool,
32}
33
34#[derive(Debug, Clone, Serialize, Deserialize)]
36pub enum EffectSettings {
37 ReverbSettings(ReverbSettings),
38 CompressorSettings(CompressorSettings),
39 ConvolutionReverbSettings(ConvolutionReverbSettings),
40}
41
42#[derive(Debug, Clone, Serialize, Deserialize)]
44pub struct SettingsTrack {
45 pub level: f32,
46 pub pan: f32,
47 pub ids: Vec<u32>,
48 pub name: String,
49 pub safe_name: String,
50}
51
52#[derive(Debug, Clone, Serialize, Deserialize)]
54pub struct ConvolutionReverbSettings {
55 pub impulse_response: Option<String>,
56 pub impulse_response_attachment: Option<String>,
57 pub impulse_response_path: Option<String>,
58 pub impulse_response_tail_db: Option<f32>,
59 pub impulse_response_tail: Option<f32>,
60}
61
62#[derive(Debug, Clone, Serialize, Deserialize)]
64#[serde(untagged)]
65pub enum PlaySettingsContainer<T> {
66 Nested { play_settings: T },
67 Flat(T),
68}
69
70impl<T> PlaySettingsContainer<T> {
71 pub fn inner(&self) -> &T {
73 match self {
74 PlaySettingsContainer::Nested { play_settings } => play_settings,
75 PlaySettingsContainer::Flat(inner) => inner,
76 }
77 }
78}
79
80#[derive(Debug, Clone)]
82pub enum PlaySettingsFile {
83 Legacy(PlaySettingsLegacyFile),
84 V1(PlaySettingsV1File),
85 V2(PlaySettingsV2File),
86 Unknown {
87 encoder_version: Option<String>,
88 raw: serde_json::Value,
89 },
90}
91
92impl PlaySettingsFile {
93 pub fn encoder_version(&self) -> Option<&str> {
95 match self {
96 PlaySettingsFile::Legacy(_) => None,
97 PlaySettingsFile::V1(_) => Some("1"),
98 PlaySettingsFile::V2(_) => Some("2"),
99 PlaySettingsFile::Unknown {
100 encoder_version, ..
101 } => encoder_version.as_deref(),
102 }
103 }
104}
105
106impl<'de> Deserialize<'de> for PlaySettingsFile {
107 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
108 where
109 D: Deserializer<'de>,
110 {
111 let value = serde_json::Value::deserialize(deserializer)?;
112 let encoder_version = value.get("encoder_version").and_then(|raw| match raw {
113 serde_json::Value::String(version) => Some(version.clone()),
114 serde_json::Value::Number(number) => number
115 .as_f64()
116 .map(|val| {
117 if (val - 1.0).abs() < f64::EPSILON {
118 "1".to_string()
119 } else if (val - 2.0).abs() < f64::EPSILON {
120 "2".to_string()
121 } else {
122 number.to_string()
123 }
124 })
125 .or_else(|| Some(number.to_string())),
126 _ => None,
127 });
128
129 info!("Encoder version: {:?}", encoder_version);
130
131 let parsed = match encoder_version.as_deref() {
132 None => serde_json::from_value::<PlaySettingsLegacyFile>(value.clone())
133 .map(PlaySettingsFile::Legacy),
134 Some("1") => serde_json::from_value::<PlaySettingsV1File>(value.clone())
135 .map(PlaySettingsFile::V1),
136 Some("2") => serde_json::from_value::<PlaySettingsV2File>(value.clone())
137 .map(PlaySettingsFile::V2),
138 Some(version) => {
139 warn!("Unknown encoder version: {:?}", version);
140 return Ok(PlaySettingsFile::Unknown {
141 encoder_version,
142 raw: value,
143 });
144 }
145 };
146
147 parsed.or_else(|_| {
148 Ok(PlaySettingsFile::Unknown {
149 encoder_version,
150 raw: value,
151 })
152 })
153 }
154}
155
156impl Serialize for PlaySettingsFile {
157 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
158 where
159 S: Serializer,
160 {
161 fn with_version<T, S>(payload: &T, version: &str, serializer: S) -> Result<S::Ok, S::Error>
162 where
163 T: Serialize,
164 S: Serializer,
165 {
166 let mut value =
167 serde_json::to_value(payload).map_err(serde::ser::Error::custom)?;
168 match value {
169 serde_json::Value::Object(ref mut map) => {
170 map.insert(
171 "encoder_version".to_string(),
172 serde_json::Value::String(version.to_string()),
173 );
174 }
175 other => {
176 let mut map = serde_json::Map::new();
177 map.insert(
178 "encoder_version".to_string(),
179 serde_json::Value::String(version.to_string()),
180 );
181 map.insert("play_settings".to_string(), other);
182 value = serde_json::Value::Object(map);
183 }
184 }
185 value.serialize(serializer)
186 }
187
188 match self {
189 PlaySettingsFile::Legacy(file) => file.serialize(serializer),
190 PlaySettingsFile::V1(file) => with_version(file, "1", serializer),
191 PlaySettingsFile::V2(file) => with_version(file, "2", serializer),
192 PlaySettingsFile::Unknown { raw, .. } => raw.serialize(serializer),
193 }
194 }
195}