[][src]Trait helgoboss_midi::ShortMessage

pub trait ShortMessage {
    pub fn status_byte(&self) -> u8;
pub fn data_byte_1(&self) -> U7;
pub fn data_byte_2(&self) -> U7; pub fn to_bytes(&self) -> (u8, U7, U7) { ... }
pub fn to_other<O: ShortMessageFactory>(&self) -> O { ... }
pub fn to_structured(&self) -> StructuredShortMessage { ... }
pub fn type(&self) -> ShortMessageType { ... }
pub fn super_type(&self) -> MessageSuperType { ... }
pub fn main_category(&self) -> MessageMainCategory { ... }
pub fn is_note_on(&self) -> bool { ... }
pub fn is_note_off(&self) -> bool { ... }
pub fn is_note(&self) -> bool { ... }
pub fn channel(&self) -> Option<Channel> { ... }
pub fn key_number(&self) -> Option<KeyNumber> { ... }
pub fn velocity(&self) -> Option<U7> { ... }
pub fn controller_number(&self) -> Option<ControllerNumber> { ... }
pub fn control_value(&self) -> Option<U7> { ... }
pub fn program_number(&self) -> Option<U7> { ... }
pub fn pressure_amount(&self) -> Option<U7> { ... }
pub fn pitch_bend_value(&self) -> Option<U14> { ... } }

A single short MIDI message, where short means it's made up by a maximum of 3 bytes.

This trait is supposed to be implemented for structs that represent a short MIDI message. Only the three byte-returning methods need to be implemented, the rest is done by default methods. Optimizations can be applied by overwriting default methods.

Please also implement the trait ShortMessageFactory for your struct if creating new short messages should be supported.

Design

Why a trait and not just a data structure?

The advantage of using a trait is that a unified API can be used to work with short MIDI messages regardless of the underlying data structure. This crate comes with two implementations: the "no-fuzz" byte-based data structure RawShortMessage and the match-friendly data structure StructuredShortMessage. Each one has its own subtle strengths, yet both are really just MIDI messages and should have the same capabilities. This fact is reflected by having a common trait.

If there wouldn't be a trait, we would probably keep the StructuredShortMessage implementation and ditch RawShortMessage. But this would come at a small cost. In real-world applications, short MIDI messages are constructed from raw bytes. When creating a StructuredShortMessage from raw bytes, a small amount of conversion is required - even if the consumer doesn't need the matching capabilities at all. With RawShortMessage, it's just a matter of copying the bytes. The conversion can happen at a later point when we have to inspect the message. However, keeping only RawShortMessage is also not a good idea because then we lose the matching capabilities.

Another benefit is flexibility. We might have an existing struct (e.g. an FFI struct) which already represents a short MIDI message. Okay, in this case we could just eagerly copy those 3 bytes to a RawShortMessage, that's cheap. But what if that existing struct represents more than a short MIDI message, e.g. it also supports System Exclusive messages or carries MIDI event information such as a frame? Then simply copying it a dozen times can decrease performance. So we might want to pass it around as a reference instead. Then we can just implement the trait for it and it will look and behave like a short MIDI message.

Why doesn't this trait support System Exclusive messages?

This trait is not designed to represent messages that are longer than 3 bytes, such as complete System Exclusive messages. One benefit is that implementations of this trait can easily get by without doing heap allocations. This is important because MIDI messages are often processed in a real-time thread where things need to happen fast and heap allocations are a no-go. Also, implementations can be made copyable just by deriving Copy, which is essential for passing around messages by copying rather then dealing with references.

For the majority of use cases, System Exclusive messages are not necessary. Support for them can be built as a separate data structure on top of this trait and will probably added to helgoboss-midi in future.

Why doesn't this trait support 14-bit Control Change or (N)RPN messages?

This trait is not used to represent MIDI messages made up by multiple short messages, such as (N)RPN messages. Those are implemented in separate structs in order to follow the single-responsibility principle.

Why do methods in this trait take self by reference?

Methods of this trait take self by reference, not by value. Other functions in this crate do the same, as long as they don't take a concrete short MIDI message type. This might seem unnecessary considering that it takes only 3 bytes to represent a short MIDI message and that they are usually Copy. The reason for still taking a reference is the same like mentioned above: Existing structs that implement this trait could represent more than just a short MIDI message, consist of more than 3 bytes and not even be Copy - we just don't know when we work with generics.

Required methods

pub fn status_byte(&self) -> u8[src]

Returns the status byte.

pub fn data_byte_1(&self) -> U7[src]

Returns the first data byte.

pub fn data_byte_2(&self) -> U7[src]

Returns the second data byte.

Loading content...

Provided methods

pub fn to_bytes(&self) -> (u8, U7, U7)[src]

Returns the status byte and the two data bytes as a tuple.

Implementations can override this default implementation if it's cheaper to get all bytes in one go.

pub fn to_other<O: ShortMessageFactory>(&self) -> O[src]

Converts this message to a short message of another type.

pub fn to_structured(&self) -> StructuredShortMessage[src]

Converts this message to a StructuredShortMessage, which is ideal for matching.

pub fn type(&self) -> ShortMessageType[src]

Returns the type of this message.

pub fn super_type(&self) -> MessageSuperType[src]

Returns the super type of this message.

pub fn main_category(&self) -> MessageMainCategory[src]

Returns the main category of this message.

pub fn is_note_on(&self) -> bool[src]

Returns whether this message is a note-on in a practical sense. That means, it also returns false if the message type is NoteOn but the velocity is zero.

pub fn is_note_off(&self) -> bool[src]

Returns whether this message is a note-off in a practical sense. That means, it also returns true if the message type is NoteOn but the velocity is zero.

pub fn is_note(&self) -> bool[src]

Returns whether this message is a note-on or note-off.

pub fn channel(&self) -> Option<Channel>[src]

Returns the channel of this message if applicable.

pub fn key_number(&self) -> Option<KeyNumber>[src]

Returns the key number of this message if applicable.

pub fn velocity(&self) -> Option<U7>[src]

Returns the velocity of this message if applicable.

pub fn controller_number(&self) -> Option<ControllerNumber>[src]

Returns the controller number of this message if applicable.

pub fn control_value(&self) -> Option<U7>[src]

Returns the control value of this message if applicable.

pub fn program_number(&self) -> Option<U7>[src]

Returns the program number of this message if applicable.

pub fn pressure_amount(&self) -> Option<U7>[src]

Returns the pressure amount of this message if applicable.

pub fn pitch_bend_value(&self) -> Option<U14>[src]

Returns the pitch bend value of this message if applicable.

Loading content...

Implementors

impl ShortMessage for StructuredShortMessage[src]

impl ShortMessage for RawShortMessage[src]

Loading content...