rtpmidi 0.4.4

A library for RTP-MIDI / AppleMIDI
Documentation
use bytes::BytesMut;
use midi_types::MidiMessage;

use crate::packets::midi_packets::delta_time::read_delta_time;
use crate::packets::midi_packets::rtp_midi_message::RtpMidiMessage;

use super::delta_time::WriteDeltaTimeExt;
use super::midi_message_ext::ReadWriteExt;

#[derive(Debug, Clone, PartialEq)]
pub struct MidiEvent<'a> {
    delta_time: Option<u32>,
    command: RtpMidiMessage<'a>,
}

impl<'a> MidiEvent<'a> {
    pub fn new(delta_time: Option<u32>, command: RtpMidiMessage<'a>) -> Self {
        MidiEvent { delta_time, command }
    }

    pub fn delta_time(&self) -> u32 {
        self.delta_time.unwrap_or(0)
    }

    pub fn command(&self) -> &RtpMidiMessage<'a> {
        &self.command
    }

    pub fn from_be_bytes(bytes: &'a [u8], include_delta_time: bool, running_status: Option<u8>) -> std::io::Result<(Self, &'a [u8])> {
        let mut delta_time = None;

        let mut bytes = bytes;
        if include_delta_time {
            let (dt, new_bytes) = read_delta_time(bytes)?;
            delta_time = Some(dt);
            bytes = new_bytes;
        }

        let (command, offset) = MidiMessage::from_be_bytes(bytes, running_status)?;
        Ok((MidiEvent { delta_time, command }, offset))
    }

    pub(super) fn write(&self, bytes: &mut BytesMut, running_status: Option<u8>, include_delta_time: bool) {
        if include_delta_time {
            match self.delta_time {
                Some(dt) => bytes.write_delta_time(dt),
                None => bytes.write_delta_time(0),
            }
        }

        self.command.write(bytes, running_status);
    }
}

#[cfg(test)]
mod tests {
    use midi_types::{Channel, Note, Value7};

    use super::*;

    #[test]
    fn test_timed_command() {
        let delta_time = 0x123456;
        let command = MidiMessage::NoteOn(Channel::C7, Note::C4, Value7::from(0x7F));
        let timed_command = MidiEvent {
            delta_time: Some(delta_time),
            command: RtpMidiMessage::MidiMessage(command),
        };

        assert_eq!(timed_command.delta_time(), delta_time);
        assert_eq!(timed_command.command(), &RtpMidiMessage::MidiMessage(command));
    }

    #[test]
    fn test_timed_command_write() {
        let mut expected_bytes = BytesMut::with_capacity(10);

        let delta_time = 0x123456;
        expected_bytes.write_delta_time(delta_time);
        let command = MidiMessage::NoteOn(Channel::C7, Note::C4, Value7::from(0x7F));
        command.write(&mut expected_bytes, None);

        let timed_command = MidiEvent {
            delta_time: Some(delta_time),
            command: RtpMidiMessage::MidiMessage(command),
        };

        let mut bytes = BytesMut::with_capacity(10);
        timed_command.write(&mut bytes, None, true);

        assert_eq!(bytes[..], expected_bytes[..]);
    }

    #[test]
    fn test_timed_command_write_without_delta_time() {
        let mut expected_bytes = BytesMut::with_capacity(10);

        let command = MidiMessage::NoteOn(Channel::C7, Note::C4, Value7::from(0x7F));
        command.write(&mut expected_bytes, None);

        let timed_command = MidiEvent {
            delta_time: None,
            command: RtpMidiMessage::MidiMessage(command),
        };

        let mut bytes = BytesMut::with_capacity(10);
        timed_command.write(&mut bytes, None, false);

        assert_eq!(bytes[..], expected_bytes[..]);
    }

    #[test]
    fn test_timed_command_write_with_zero_delta_time() {
        let mut expected_bytes = BytesMut::with_capacity(10);

        let delta_time = 0;
        expected_bytes.write_delta_time(delta_time);

        let command = MidiMessage::NoteOn(Channel::C7, Note::C4, Value7::from(0x7F));
        command.write(&mut expected_bytes, None);

        let timed_command = MidiEvent {
            delta_time: None,
            command: RtpMidiMessage::MidiMessage(command),
        };

        let mut bytes = BytesMut::with_capacity(10);
        timed_command.write(&mut bytes, None, true);

        assert_eq!(bytes[..], expected_bytes[..]);
    }
}