rytm_rs/object/sound/
de.rs

1use super::Sound;
2use crate::object::{pattern::plock::ParameterLockPool, sound::machine::MachineParameters};
3use parking_lot::Mutex;
4use serde::{
5    de::{Deserializer, Error, MapAccess, Visitor},
6    Deserialize,
7};
8use std::{fmt, sync::Arc};
9
10#[allow(clippy::too_many_lines)]
11impl<'de> Deserialize<'de> for Sound {
12    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
13    where
14        D: Deserializer<'de>,
15    {
16        struct SoundVisitor;
17
18        impl<'de> Visitor<'de> for SoundVisitor {
19            type Value = Sound;
20
21            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
22                formatter.write_str("struct Sound")
23            }
24
25            fn visit_map<V>(self, mut map: V) -> Result<Sound, V::Error>
26            where
27                V: MapAccess<'de>,
28            {
29                let mut sysex_meta = None;
30                let mut version = None;
31                let mut index = None;
32                let mut pool_index = None;
33                let mut kit_number = None;
34                let mut assigned_track = None;
35                let mut name = None;
36                let mut accent_level = None;
37                let mut def_note = None;
38                let mut sample = None;
39                let mut filter = None;
40                let mut amplitude = None;
41                let mut lfo = None;
42                let mut settings = None;
43                let mut machine_parameters: Option<MachineParameters> = None;
44                let mut __unknown = None;
45                let mut parameter_lock_pool: Option<Option<Arc<Mutex<ParameterLockPool>>>> = None;
46
47                while let Some(key) = map.next_key()? {
48                    match key {
49                        "sysex_meta" => sysex_meta = Some(map.next_value()?),
50                        "version" => version = Some(map.next_value()?),
51                        "index" => index = Some(map.next_value()?),
52                        "pool_index" => pool_index = Some(map.next_value()?),
53                        "kit_number" => kit_number = Some(map.next_value()?),
54                        "assigned_track" => assigned_track = Some(map.next_value()?),
55                        "name" => name = Some(map.next_value()?),
56                        "accent_level" => accent_level = Some(map.next_value()?),
57                        "def_note" => def_note = Some(map.next_value()?),
58                        "sample" => sample = Some(map.next_value()?),
59                        "filter" => filter = Some(map.next_value()?),
60                        "amplitude" => amplitude = Some(map.next_value()?),
61                        "lfo" => lfo = Some(map.next_value()?),
62                        "settings" => settings = Some(map.next_value()?),
63                        "machine_parameters" => machine_parameters = Some(map.next_value()?),
64                        "__unknown" => __unknown = Some(map.next_value()?),
65                        // Inject to the machine parameters if a previously linked parameter lock pool is present.
66                        "parameter_lock_pool" => {
67                            let parameter_lock_pool_value: Option<ParameterLockPool> =
68                                map.next_value()?;
69                            if let Some(parameter_lock_pool_value) = parameter_lock_pool_value {
70                                let pool = Arc::new(Mutex::new(parameter_lock_pool_value));
71                                if let Some(mp) = machine_parameters.as_mut() {
72                                    // TODO: When deserializing machine parameters we can also check validity but maybe overkill.
73                                    mp.link_parameter_lock_pool(Arc::clone(&pool));
74                                }
75                                parameter_lock_pool = Some(Some(pool));
76                            } else {
77                                parameter_lock_pool = Some(None);
78                            }
79                        }
80                        _ => return Err(V::Error::unknown_field(key, FIELDS)),
81                    }
82                }
83
84                Ok(Sound {
85                    sysex_meta: sysex_meta.ok_or_else(|| V::Error::missing_field("sysex_meta"))?,
86                    version: version.ok_or_else(|| V::Error::missing_field("version"))?,
87                    index: index.ok_or_else(|| V::Error::missing_field("index"))?,
88                    pool_index: pool_index.ok_or_else(|| V::Error::missing_field("pool_index"))?,
89                    kit_number: kit_number.ok_or_else(|| V::Error::missing_field("kit_number"))?,
90                    assigned_track: assigned_track
91                        .ok_or_else(|| V::Error::missing_field("assigned_track"))?,
92                    name: name.ok_or_else(|| V::Error::missing_field("name"))?,
93                    accent_level: accent_level
94                        .ok_or_else(|| V::Error::missing_field("accent_level"))?,
95                    def_note: def_note.ok_or_else(|| V::Error::missing_field("def_note"))?,
96                    sample: sample.ok_or_else(|| V::Error::missing_field("sample"))?,
97                    filter: filter.ok_or_else(|| V::Error::missing_field("filter"))?,
98                    amplitude: amplitude.ok_or_else(|| V::Error::missing_field("amplitude"))?,
99                    lfo: lfo.ok_or_else(|| V::Error::missing_field("lfo"))?,
100                    settings: settings.ok_or_else(|| V::Error::missing_field("settings"))?,
101                    machine_parameters: machine_parameters
102                        .ok_or_else(|| V::Error::missing_field("machine_parameters"))?,
103                    __unknown: __unknown.ok_or_else(|| V::Error::missing_field("__unknown"))?,
104                    parameter_lock_pool: parameter_lock_pool
105                        .ok_or_else(|| V::Error::missing_field("parameter_lock_pool"))?,
106                })
107            }
108        }
109
110        const FIELDS: &[&str] = &[
111            "sysex_meta",
112            "version",
113            "index",
114            "pool_index",
115            "kit_number",
116            "assigned_track",
117            "name",
118            "accent_level",
119            "def_note",
120            "sample",
121            "filter",
122            "amplitude",
123            "lfo",
124            "settings",
125            "machine_parameters",
126            "__unknown",
127            "parameter_lock_pool",
128        ];
129
130        deserializer.deserialize_struct("Sound", FIELDS, SoundVisitor)
131    }
132}