Skip to main content

midi_msg/system_exclusive/
controller_destination.rs

1use crate::message::Channel;
2use crate::parse_error::*;
3use crate::util::*;
4use alloc::vec::Vec;
5
6/// Allows for the selection of the destination of a channel pressure/poly key pressure message.
7/// Used by [`UniversalRealTimeMsg`](crate::UniversalRealTimeMsg).
8///
9/// Defined in CA-022.
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11#[derive(Debug, Clone, PartialEq, Eq)]
12pub struct ControllerDestination {
13    pub channel: Channel,
14    /// Any number of (ControlledParameter, range) pairs
15    pub param_ranges: Vec<(ControlledParameter, u8)>,
16}
17
18impl ControllerDestination {
19    pub(crate) fn extend_midi(&self, v: &mut Vec<u8>) {
20        v.push(self.channel as u8);
21        for (p, r) in self.param_ranges.iter() {
22            v.push(*p as u8);
23            push_u7(*r, v);
24        }
25    }
26
27    #[allow(dead_code)]
28    pub(crate) fn from_midi(_m: &[u8]) -> Result<(Self, usize), ParseError> {
29        Err(ParseError::NotImplemented("ControllerDestination"))
30    }
31}
32
33/// Allows for the selection of the destination of a control change message.
34/// Used by [`UniversalRealTimeMsg::GlobalParameterControl`](crate::UniversalRealTimeMsg::GlobalParameterControl).
35///
36/// Defined in CA-022.
37#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
38#[derive(Debug, Clone, PartialEq, Eq)]
39pub struct ControlChangeControllerDestination {
40    pub channel: Channel,
41    /// A control number between `0x01` - `0x1F` or `0x40` - `0x5F`
42    /// Values outside these ranges will be coerced
43    pub control_number: u8,
44    /// Any number of (ControlledParameter, range) pairs
45    pub param_ranges: Vec<(ControlledParameter, u8)>,
46}
47
48impl ControlChangeControllerDestination {
49    pub(crate) fn extend_midi(&self, v: &mut Vec<u8>) {
50        v.push(self.channel as u8);
51        if self.control_number < 0x40 {
52            v.push(self.control_number.clamp(0x01, 0x1F));
53        } else {
54            v.push(self.control_number.clamp(0x40, 0x5F));
55        }
56        for (p, r) in self.param_ranges.iter() {
57            v.push(*p as u8);
58            push_u7(*r, v);
59        }
60    }
61
62    #[allow(dead_code)]
63    pub(crate) fn from_midi(_m: &[u8]) -> Result<(Self, usize), ParseError> {
64        Err(ParseError::NotImplemented(
65            "ControlChangeControllerDestination",
66        ))
67    }
68}
69/// The parameters that can be controlled by [`ControllerDestination`] or
70/// [`ControlChangeControllerDestination`].
71#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
72#[derive(Debug, Clone, Copy, PartialEq, Eq)]
73pub enum ControlledParameter {
74    PitchControl = 0,
75    FilterCutoffControl = 1,
76    AmplitudeControl = 2,
77    LFOPitchDepth = 3,
78    LFOFilterDepth = 4,
79    LFOAmplitudeDepth = 5,
80}
81
82#[cfg(test)]
83mod tests {
84    use crate::*;
85    use alloc::vec;
86
87    #[test]
88    fn serialize_controller_destination() {
89        assert_eq!(
90            MidiMsg::SystemExclusive {
91                msg: SystemExclusiveMsg::UniversalRealTime {
92                    device: DeviceID::AllCall,
93                    msg: UniversalRealTimeMsg::ControlChangeControllerDestination(
94                        ControlChangeControllerDestination {
95                            channel: Channel::Ch2,
96                            control_number: 0x50,
97                            param_ranges: vec![
98                                (ControlledParameter::PitchControl, 0x42),
99                                (ControlledParameter::FilterCutoffControl, 0x60)
100                            ]
101                        }
102                    ),
103                }
104            }
105            .to_midi(),
106            vec![
107                0xF0, 0x7F, 0x7F, // Receiver device
108                0x9, 0x3, // Sysex IDs
109                0x1, 0x50, 0x0, 0x42, 0x1, 0x60, 0xF7
110            ]
111        );
112    }
113}