1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
use crate::{
    extract_high_7_bit_value_from_14_bit_value, extract_low_7_bit_value_from_14_bit_value, Channel,
    ControllerNumber, ShortMessageFactory, U14,
};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

/// A 14-bit MIDI Control Change message.
///
/// Unlike a [`ShortMessage`] of type [`ShortMessageType::ControlChange`], this one supports 14-bit
/// resolution, that means 16384 different values instead of only 128. MIDI systems emit those by
/// sending 2 short Control Change messages in a row. The [`ControlChange14BitMessageScanner`]
/// can be used to extract such messages from a stream of [`ShortMessage`]s.
///
/// # Example
///
/// ```
/// use helgoboss_midi::{
///     controller_numbers, Channel, ControlChange14BitMessage, RawShortMessage, U14,
/// };
///
/// let msg = ControlChange14BitMessage::new(
///     Channel::new(5),
///     controller_numbers::CHANNEL_VOLUME,
///     U14::new(1057),
/// );
/// assert_eq!(msg.channel().get(), 5);
/// assert_eq!(msg.msb_controller_number().get(), 7);
/// assert_eq!(
///     msg.lsb_controller_number(),
///     controller_numbers::CHANNEL_VOLUME_LSB
/// );
/// use helgoboss_midi::test_util::control_change;
/// assert_eq!(msg.value().get(), 1057);
/// let short_messages: [RawShortMessage; 2] = msg.to_short_messages();
/// assert_eq!(
///     short_messages,
///     [control_change(5, 7, 8), control_change(5, 39, 33)]
/// );
/// ```
///
/// [`ShortMessage`]: trait.ShortMessage.html
/// [`ShortMessageType::ControlChange`]: enum.ShortMessageType.html#variant.ControlChange
/// [`ControlChange14BitMessageScanner`]: struct.ControlChange14BitMessageScanner.html
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct ControlChange14BitMessage {
    channel: Channel,
    msb_controller_number: ControllerNumber,
    value: U14,
}

impl ControlChange14BitMessage {
    /// Creates a 14-bit Control Change message.
    ///
    /// # Panics
    ///
    /// This function panics if `msb_controller_number` can't serve as controller number for
    /// transmitting the most significant byte of a 14-bit Control Change message.
    pub fn new(
        channel: Channel,
        msb_controller_number: ControllerNumber,
        value: U14,
    ) -> ControlChange14BitMessage {
        assert!(msb_controller_number
            .corresponding_14_bit_lsb_controller_number()
            .is_some());
        ControlChange14BitMessage {
            channel,
            msb_controller_number,
            value,
        }
    }

    /// Returns the channel of this message.
    pub fn channel(&self) -> Channel {
        self.channel
    }

    /// Returns the controller number for transmitting the most significant byte of this message.
    pub fn msb_controller_number(&self) -> ControllerNumber {
        self.msb_controller_number
    }

    /// Returns the controller number for transmitting the least significant byte of this message.
    pub fn lsb_controller_number(&self) -> ControllerNumber {
        self.msb_controller_number
            .corresponding_14_bit_lsb_controller_number()
            .expect("impossible")
    }

    /// Returns the 14-bit value of this message.
    pub fn value(&self) -> U14 {
        self.value
    }

    /// Translates this message into 2 short messages, which need to be sent in a row in order to
    /// encode this 14-bit Control Change message.
    pub fn to_short_messages<T: ShortMessageFactory>(&self) -> [T; 2] {
        [
            T::control_change(
                self.channel,
                self.msb_controller_number(),
                extract_high_7_bit_value_from_14_bit_value(self.value),
            ),
            T::control_change(
                self.channel,
                self.lsb_controller_number(),
                extract_low_7_bit_value_from_14_bit_value(self.value),
            ),
        ]
    }
}

impl<T: ShortMessageFactory> From<ControlChange14BitMessage> for [T; 2] {
    fn from(msg: ControlChange14BitMessage) -> Self {
        msg.to_short_messages()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::test_util::{channel as ch, controller_number as cn, u14, u7};
    use crate::RawShortMessage;

    #[test]
    fn basics() {
        // Given
        let msg = ControlChange14BitMessage::new(ch(5), cn(2), u14(1057));
        // When
        // Then
        assert_eq!(msg.channel(), ch(5));
        assert_eq!(msg.msb_controller_number(), cn(2));
        assert_eq!(msg.lsb_controller_number(), cn(34));
        assert_eq!(msg.value(), u14(1057));
        let short_msgs = msg.to_short_messages();
        assert_eq!(
            short_msgs,
            [
                RawShortMessage::control_change(ch(5), cn(2), u7(8)),
                RawShortMessage::control_change(ch(5), cn(34), u7(33))
            ]
        );
        let short_msgs_2: [RawShortMessage; 2] = msg.into();
        assert_eq!(short_msgs_2, short_msgs);
    }
}