diff --git a/CHANGELOG.md b/CHANGELOG.md index 58ef266..b36c03c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# 0.5.1 +# 0.5.3 docs: flex data module docs docs: adds system common module docs docs: channel voice 2 module docs diff --git a/Cargo.toml b/Cargo.toml index 48af5b7..498fc30 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "midi2" -version = "0.5.2" +version = "0.5.3" description = "Ergonomic, versatile, strong types wrapping MIDI 2.0 message data." edition = "2021" readme = "README.md" @@ -35,7 +35,7 @@ utility = [] [dependencies] derive_more = { version = "0.99.17", features = ["from"], default-features = false } -midi2_proc = { version = "0.5.2", path = "midi2_proc" } +midi2_proc = { version = "0.5.3", path = "midi2_proc" } ux = "0.1.6" [dev-dependencies] diff --git a/README.md b/README.md index 2aeb215..8c47f7f 100644 --- a/README.md +++ b/README.md @@ -156,7 +156,7 @@ You'll want to setup midi2 without default features to compile without the `std` feature. ```toml -midi2 = { version = "0.5.2", default-features = false, features = ["channel-voice2", "sysex7"], } +midi2 = { version = "0.5.3", default-features = false, features = ["channel-voice2", "sysex7"], } ``` ### Generic Representation diff --git a/midi2_proc/Cargo.toml b/midi2_proc/Cargo.toml index e6e524a..a23e410 100644 --- a/midi2_proc/Cargo.toml +++ b/midi2_proc/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "midi2_proc" description = "Internal procedural macro crate. Only intended for use with midi2" -version = "0.5.2" +version = "0.5.3" edition = "2021" readme = "README.md" license = "MIT OR Apache-2.0" diff --git a/src/channel_voice2.rs b/src/channel_voice2.rs index 208c77b..8e7ee6f 100644 --- a/src/channel_voice2.rs +++ b/src/channel_voice2.rs @@ -1,3 +1,5 @@ +#![doc = include_str!("channel_voice2/README.md")] + mod assignable_controller; mod assignable_per_note_controller; mod attribute; diff --git a/src/channel_voice2/README.md b/src/channel_voice2/README.md index 42ba57b..4db275d 100644 --- a/src/channel_voice2/README.md +++ b/src/channel_voice2/README.md @@ -8,78 +8,86 @@ use midi2::{ channel_voice2::NoteOn, }; -let mut message = ControlChange::<[u32; 4]>::new(); -message.set_channel(u4::new(0xA)); -message.set_group(u4::new(0xC)); -message.set_control(u7::new(0x36)); -message.set_control_data(u7::new(0x37)); - -assert_eq!(message.data(), &[0x2CBA_3637]); +let mut message = NoteOn::<[u32; 4]>::new(); +message.set_group(u4::new(0x8)); +message.set_channel(u4::new(0x8)); +message.set_note(u7::new(0x5E)); +message.set_velocity(0x6A14); +message.set_attribute(Some(channel_voice2::NoteAttribute::Pitch7_9 { + note: u7::new(0x74), + pitch_up: u9::new(0x18A), +})); + +assert_eq!(message.data(), &[0x4898_5E03, 0x6A14_E98A]); +assert_eq!(message.group(), u4::new(0x8)); +assert_eq!(message.channel(), u4::new(0x8)); +assert_eq!(message.note(), u7::new(0x5E)); +assert_eq!(message.velocity(), 0x6A14); +assert_eq!( + message.attribute(), + Some(channel_voice2::NoteAttribute::Pitch7_9 { + note: u7::new(0x74), + pitch_up: u9::new(0x18A), + } +)); ``` ## Channeled -`channel_voice1` messages are [Channeled](crate::Channeled). +`channel_voice2` messages are [Channeled](crate::Channeled). ## Grouped -`channel_voice1` messages are [Grouped](crate::Grouped) -when backed with [Ump](crate::buffer::Ump) buffers. +`channel_voice2` messages are [Grouped](crate::Grouped). ## Aggregate Message -There is a single aggregate [ChannelVoice1] enum type which -can represent an arbitrary `channel_voice1` message. +There is a single aggregate [ChannelVoice2] enum type which +can represent an arbitrary `channel_voice2` message. ```rust use midi2::{ prelude::*, - channel_voice1::ChannelVoice1, + channel_voice2::ChannelVoice2, }; -let mut message = ChannelVoice1::try_from(&[0x2CBA_3637_u32][..]).expect("Valid data"); +let mut message = ChannelVoice2::try_from(&[0x4898_5E03, 0x6A14_E98A][..]).expect("Valid data"); match message { - ChannelVoice1::ChannelPressure(m) => println!("channel_pressure {:?}", m.data()), - ChannelVoice1::ControlChange(m) => println!("control_change {:?}", m.data()), - ChannelVoice1::KeyPressure(m) => println!("key_pressure {:?}", m.data()), - ChannelVoice1::NoteOff(m) => println!("note_off {:?}", m.data()), - ChannelVoice1::NoteOn(m) => println!("note_on {:?}", m.data()), - ChannelVoice1::PitchBend(m) => println!("pitch_bend {:?}", m.data()), - ChannelVoice1::ProgramChange(m) => println!("program_change {:?}", m.data()), + ChannelVoice2::AssignableController(m) => println!("assignable_controller {:?}", m.data()), + ChannelVoice2::AssignablePerNoteController(m) => println!("assignable_per_note_controller {:?}", m.data()), + ChannelVoice2::ChannelPitchBend(m) => println!("channel_pitch_bend {:?}", m.data()), + ChannelVoice2::ChannelPressure(m) => println!("channel_pressure {:?}", m.data()), + ChannelVoice2::ControlChange(m) => println!("control_change {:?}", m.data()), + ChannelVoice2::KeyPressure(m) => println!("key_pressure {:?}", m.data()), + ChannelVoice2::NoteOff(m) => println!("note_off {:?}", m.data()), + ChannelVoice2::NoteOn(m) => println!("note_on {:?}", m.data()), + ChannelVoice2::PerNoteManagement(m) => println!("per_note_management {:?}", m.data()), + ChannelVoice2::PerNotePitchBend(m) => println!("per_note_pitch_bend {:?}", m.data()), + ChannelVoice2::ProgramChange(m) => println!("program_change {:?}", m.data()), + ChannelVoice2::RegisteredController(m) => println!("registered_controller {:?}", m.data()), + ChannelVoice2::RegisteredPerNoteController(m) => println!("registered_per_note_controller {:?}", m.data()), + ChannelVoice2::RelativeAssignableController(m) => println!("relative_assignable_controller {:?}", m.data()), + ChannelVoice2::RelativeRegisteredController(m) => println!("relative_registered_controller {:?}", m.data()), } ``` -## Generic Over [Unit](crate::buffer::Unit) +## Fixed Size -`channel_voice1` messages can also be represented with [Bytes](crate::buffer::Bytes) buffers - as well as [Ump](crate::buffer::Ump) buffers. +All `channel_voice1` messages are Fixed size and will fit +into an array of [u32] size 2 or greater. ```rust -use midi2::{ - prelude::*, - channel_voice1::ControlChange, -}; - -let mut message = ControlChange::<[u8; 3]>::new(); -message.set_channel(u4::new(0xA)); -message.set_control(u7::new(0x36)); -message.set_control_data(u7::new(0x37)); +use midi2::channel_voice2::NoteOn; -assert_eq!(message.data(), &[0xBA, 0x36, 0x37]); +let _ = NoteOn::<[u32; 2]>::new(); +let _ = NoteOn::<[u32; 4]>::new(); ``` -## Fixed Size - -All `channel_voice1` messages are Fixed size. - -```rust -use midi2::channel_voice1::KeyPressure; - +Arrays smaller than two are invalid backing buffers. -// All channel_voice1 bytes-backed messages fit into a `[u8; 3]` -let _ = KeyPressure::<[u8; 3]>::new(); +```rust,compile_fail,E0080 +use midi2::channel_voice2::NoteOn; -// All channel_voice1 ump-backed messages fit into a `[u32; 1]` -let _ = KeyPressure::<[u32; 1]>::new(); +let _ = NoteOn::<[u32; 1]>::new(); // compile err - buffer too short ``` diff --git a/src/channel_voice2/assignable_controller.rs b/src/channel_voice2/assignable_controller.rs index 4d26160..539dac9 100644 --- a/src/channel_voice2/assignable_controller.rs +++ b/src/channel_voice2/assignable_controller.rs @@ -6,6 +6,9 @@ use crate::{ pub(crate) const STATUS: u8 = 0b0011; +/// MIDI 2.0 Channel Voice Assignable Controller Message +/// +/// See the [module docs](crate::channel_voice2) for more info. #[midi2_proc::generate_message(Via(crate::channel_voice2::ChannelVoice2), FixedSize, MinSizeUmp(2))] struct AssignableController { #[property(common_properties::UmpMessageTypeProperty)] diff --git a/src/channel_voice2/assignable_per_note_controller.rs b/src/channel_voice2/assignable_per_note_controller.rs index e00a90e..51255c8 100644 --- a/src/channel_voice2/assignable_per_note_controller.rs +++ b/src/channel_voice2/assignable_per_note_controller.rs @@ -6,6 +6,9 @@ use crate::{ pub(crate) const STATUS: u8 = 0b0001; +/// MIDI 2.0 Channel Voice Assignable Per Note Controller Message +/// +/// See the [module docs](crate::channel_voice2) for more info. #[midi2_proc::generate_message(Via(crate::channel_voice2::ChannelVoice2), FixedSize, MinSizeUmp(2))] struct AssignablePerNoteController { #[property(common_properties::UmpMessageTypeProperty)] diff --git a/src/channel_voice2/channel_pitch_bend.rs b/src/channel_voice2/channel_pitch_bend.rs index c84be9b..9025a7c 100644 --- a/src/channel_voice2/channel_pitch_bend.rs +++ b/src/channel_voice2/channel_pitch_bend.rs @@ -6,6 +6,9 @@ use crate::{ pub(crate) const STATUS: u8 = 0b1110; +/// MIDI 2.0 Channel Voice Channel Pitch Bend Message +/// +/// See the [module docs](crate::channel_voice2) for more info. #[midi2_proc::generate_message(Via(crate::channel_voice2::ChannelVoice2), FixedSize, MinSizeUmp(2))] struct ChannelPitchBend { #[property(common_properties::UmpMessageTypeProperty)] diff --git a/src/channel_voice2/channel_pressure.rs b/src/channel_voice2/channel_pressure.rs index 16820bb..88944ca 100644 --- a/src/channel_voice2/channel_pressure.rs +++ b/src/channel_voice2/channel_pressure.rs @@ -6,6 +6,9 @@ use crate::{ pub(crate) const STATUS: u8 = 0b1101; +/// MIDI 2.0 Channel Voice Channel Pressure Message +/// +/// See the [module docs](crate::channel_voice2) for more info. #[midi2_proc::generate_message(Via(crate::channel_voice2::ChannelVoice2), FixedSize, MinSizeUmp(2))] struct ChannelPressure { #[property(common_properties::UmpMessageTypeProperty)] diff --git a/src/channel_voice2/control_change.rs b/src/channel_voice2/control_change.rs index 09460bc..1712a1c 100644 --- a/src/channel_voice2/control_change.rs +++ b/src/channel_voice2/control_change.rs @@ -6,6 +6,9 @@ use crate::{ pub(crate) const STATUS: u8 = 0b1011; +/// MIDI 2.0 Channel Voice Control Change Message +/// +/// See the [module docs](crate::channel_voice2) for more info. #[midi2_proc::generate_message(Via(crate::channel_voice2::ChannelVoice2), FixedSize, MinSizeUmp(2))] struct ControlChange { #[property(common_properties::UmpMessageTypeProperty)] diff --git a/src/channel_voice2/key_pressure.rs b/src/channel_voice2/key_pressure.rs index 7595384..2a3884b 100644 --- a/src/channel_voice2/key_pressure.rs +++ b/src/channel_voice2/key_pressure.rs @@ -6,6 +6,9 @@ use crate::{ pub(crate) const STATUS: u8 = 0b1010; +/// MIDI 2.0 Channel Voice Key Pressure Message +/// +/// See the [module docs](crate::channel_voice2) for more info. #[midi2_proc::generate_message(Via(crate::channel_voice2::ChannelVoice2), FixedSize, MinSizeUmp(2))] struct KeyPressure { #[property(common_properties::UmpMessageTypeProperty)] diff --git a/src/channel_voice2/note_off.rs b/src/channel_voice2/note_off.rs index ce8a76f..44dd13d 100644 --- a/src/channel_voice2/note_off.rs +++ b/src/channel_voice2/note_off.rs @@ -9,6 +9,9 @@ use crate::{ pub(crate) const STATUS: u8 = 0b1000; +/// MIDI 2.0 Channel Voice Note Off Message +/// +/// See the [module docs](crate::channel_voice2) for more info. #[midi2_proc::generate_message(Via(crate::channel_voice2::ChannelVoice2), FixedSize, MinSizeUmp(2))] struct NoteOff { #[property(common_properties::UmpMessageTypeProperty)] diff --git a/src/channel_voice2/note_on.rs b/src/channel_voice2/note_on.rs index ff5737a..e3a4217 100644 --- a/src/channel_voice2/note_on.rs +++ b/src/channel_voice2/note_on.rs @@ -9,26 +9,9 @@ use crate::{ pub(crate) const STATUS: u8 = 0b1001; -/// Note On MIDI 2.0 Channel Voice message. +/// MIDI 2.0 Channel Voice Note On Message /// -/// # Basic Usage -/// -/// ```rust -/// use midi2::prelude::*; -/// use midi2::prelude::*; -/// -/// let mut message = channel_voice2::NoteOn::<[u32; 4]>::new(); -/// message.set_group(u4::new(0x8)); -/// message.set_channel(u4::new(0x8)); -/// message.set_note(u7::new(0x5E)); -/// message.set_velocity(0x6A14); -/// message.set_attribute(Some(channel_voice2::NoteAttribute::Pitch7_9 { -/// note: u7::new(0x74), -/// pitch_up: u9::new(0x18A), -/// })); -/// -/// assert_eq!(message.data(), &[0x4898_5E03, 0x6A14_E98A]); -/// ``` +/// See the [module docs](crate::channel_voice2) for more info. #[midi2_proc::generate_message(Via(crate::channel_voice2::ChannelVoice2), FixedSize, MinSizeUmp(2))] struct NoteOn { #[property(common_properties::UmpMessageTypeProperty)] diff --git a/src/channel_voice2/per_note_management.rs b/src/channel_voice2/per_note_management.rs index 00d11ef..6a9011e 100644 --- a/src/channel_voice2/per_note_management.rs +++ b/src/channel_voice2/per_note_management.rs @@ -6,6 +6,9 @@ use crate::{ pub(crate) const STATUS: u8 = 0b1111; +/// MIDI 2.0 Channel Voice Per Note Management Message +/// +/// See the [module docs](crate::channel_voice2) for more info. #[midi2_proc::generate_message(Via(crate::channel_voice2::ChannelVoice2), FixedSize, MinSizeUmp(1))] struct PerNoteManagement { #[property(common_properties::UmpMessageTypeProperty)] diff --git a/src/channel_voice2/per_note_pitch_bend.rs b/src/channel_voice2/per_note_pitch_bend.rs index 662c527..0ad485d 100644 --- a/src/channel_voice2/per_note_pitch_bend.rs +++ b/src/channel_voice2/per_note_pitch_bend.rs @@ -6,6 +6,9 @@ use crate::{ pub(crate) const STATUS: u8 = 0b0110; +/// MIDI 2.0 Channel Voice Per Note Pitch Bend Message +/// +/// See the [module docs](crate::channel_voice2) for more info. #[midi2_proc::generate_message(Via(crate::channel_voice2::ChannelVoice2), FixedSize, MinSizeUmp(2))] struct PerNotePitchBend { #[property(common_properties::UmpMessageTypeProperty)] diff --git a/src/channel_voice2/program_change.rs b/src/channel_voice2/program_change.rs index 9ab3382..f06a771 100644 --- a/src/channel_voice2/program_change.rs +++ b/src/channel_voice2/program_change.rs @@ -6,6 +6,9 @@ use crate::{ pub(crate) const STATUS: u8 = 0b1100; +/// MIDI 2.0 Channel Voice Program Change Message +/// +/// See the [module docs](crate::channel_voice2) for more info. #[midi2_proc::generate_message(Via(crate::channel_voice2::ChannelVoice2), FixedSize, MinSizeUmp(2))] struct ProgramChange { #[property(common_properties::UmpMessageTypeProperty)] diff --git a/src/channel_voice2/registered_controller.rs b/src/channel_voice2/registered_controller.rs index cda13ef..9b0daf1 100644 --- a/src/channel_voice2/registered_controller.rs +++ b/src/channel_voice2/registered_controller.rs @@ -6,6 +6,9 @@ use crate::{ pub(crate) const STATUS: u8 = 0b0010; +/// MIDI 2.0 Channel Voice Registered Controller Message +/// +/// See the [module docs](crate::channel_voice2) for more info. #[midi2_proc::generate_message(Via(crate::channel_voice2::ChannelVoice2), FixedSize, MinSizeUmp(2))] struct RegisteredController { #[property(common_properties::UmpMessageTypeProperty)] diff --git a/src/channel_voice2/registered_per_note_controller.rs b/src/channel_voice2/registered_per_note_controller.rs index 965a767..c413b29 100644 --- a/src/channel_voice2/registered_per_note_controller.rs +++ b/src/channel_voice2/registered_per_note_controller.rs @@ -6,6 +6,9 @@ use crate::{ pub(crate) const STATUS: u8 = 0b0000; +/// MIDI 2.0 Channel Voice Registered Per Note Controller Message +/// +/// See the [module docs](crate::channel_voice2) for more info. #[midi2_proc::generate_message(Via(crate::channel_voice2::ChannelVoice2), FixedSize, MinSizeUmp(2))] struct RegisteredPerNoteController { #[property(common_properties::UmpMessageTypeProperty)] diff --git a/src/channel_voice2/relative_assignable_controller.rs b/src/channel_voice2/relative_assignable_controller.rs index 6c92b90..29ba1e1 100644 --- a/src/channel_voice2/relative_assignable_controller.rs +++ b/src/channel_voice2/relative_assignable_controller.rs @@ -6,6 +6,9 @@ use crate::{ pub(crate) const STATUS: u8 = 0b0101; +/// MIDI 2.0 Channel Voice Relative Assignable Controller Message +/// +/// See the [module docs](crate::channel_voice2) for more info. #[midi2_proc::generate_message(Via(crate::channel_voice2::ChannelVoice2), FixedSize, MinSizeUmp(2))] struct RelativeAssignableController { #[property(common_properties::UmpMessageTypeProperty)] diff --git a/src/channel_voice2/relative_registered_controller.rs b/src/channel_voice2/relative_registered_controller.rs index 6124483..0db3757 100644 --- a/src/channel_voice2/relative_registered_controller.rs +++ b/src/channel_voice2/relative_registered_controller.rs @@ -6,6 +6,9 @@ use crate::{ pub(crate) const STATUS: u8 = 0b0100; +/// MIDI 2.0 Channel Voice Relative Registered Controller Message +/// +/// See the [module docs](crate::channel_voice2) for more info. #[midi2_proc::generate_message(Via(crate::channel_voice2::ChannelVoice2), FixedSize, MinSizeUmp(2))] struct RelativeRegisteredController { #[property(common_properties::UmpMessageTypeProperty)] diff --git a/src/flex_data.rs b/src/flex_data.rs index 4748105..9b5763d 100644 --- a/src/flex_data.rs +++ b/src/flex_data.rs @@ -1,3 +1,5 @@ +#![doc = include_str!("flex_data/README.md")] + use crate::{ buffer::{BufferMut, Ump}, detail::{ @@ -21,6 +23,9 @@ mod project_name { const BANK: u8 = super::METADATA_TEXT_BANK; const STATUS: u8 = 0x1; + /// MIDI 2.0 Project Name Message + /// + /// See the [module docs](crate::flex_data) for more info. #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), MinSizeUmp(4))] struct ProjectName { #[property(common_properties::UmpMessageTypeProperty<{flex_data::UMP_MESSAGE_TYPE}>)] @@ -62,6 +67,9 @@ mod composition_name { const BANK: u8 = super::METADATA_TEXT_BANK; const STATUS: u8 = 0x2; + /// MIDI 2.0 Composition Name Message + /// + /// See the [module docs](crate::flex_data) for more info. #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), MinSizeUmp(4))] struct CompositionName { #[property(common_properties::UmpMessageTypeProperty<{flex_data::UMP_MESSAGE_TYPE}>)] @@ -103,6 +111,9 @@ mod midi_clip_name { const BANK: u8 = super::METADATA_TEXT_BANK; const STATUS: u8 = 0x3; + /// MIDI 2.0 Midi Clip Name Message + /// + /// See the [module docs](crate::flex_data) for more info. #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), MinSizeUmp(4))] struct MidiClipName { #[property(common_properties::UmpMessageTypeProperty<{flex_data::UMP_MESSAGE_TYPE}>)] @@ -144,6 +155,9 @@ mod copyright_notice { const BANK: u8 = super::METADATA_TEXT_BANK; const STATUS: u8 = 0x4; + /// MIDI 2.0 Copyright Notice Message + /// + /// See the [module docs](crate::flex_data) for more info. #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), MinSizeUmp(4))] struct CopyrightNotice { #[property(common_properties::UmpMessageTypeProperty<{flex_data::UMP_MESSAGE_TYPE}>)] @@ -185,6 +199,9 @@ mod composer_name { const BANK: u8 = super::METADATA_TEXT_BANK; const STATUS: u8 = 0x5; + /// MIDI 2.0 Composer Name Message + /// + /// See the [module docs](crate::flex_data) for more info. #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), MinSizeUmp(4))] struct ComposerName { #[property(common_properties::UmpMessageTypeProperty<{flex_data::UMP_MESSAGE_TYPE}>)] @@ -226,6 +243,9 @@ mod lyricist_name { const BANK: u8 = super::METADATA_TEXT_BANK; const STATUS: u8 = 0x6; + /// MIDI 2.0 Lyricist Name Message + /// + /// See the [module docs](crate::flex_data) for more info. #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), MinSizeUmp(4))] struct LyricistName { #[property(common_properties::UmpMessageTypeProperty<{flex_data::UMP_MESSAGE_TYPE}>)] @@ -267,6 +287,9 @@ mod arranger_name { const BANK: u8 = super::METADATA_TEXT_BANK; const STATUS: u8 = 0x7; + /// MIDI 2.0 Arranger Name Message + /// + /// See the [module docs](crate::flex_data) for more info. #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), MinSizeUmp(4))] struct ArrangerName { #[property(common_properties::UmpMessageTypeProperty<{flex_data::UMP_MESSAGE_TYPE}>)] @@ -308,6 +331,9 @@ mod publisher_name { const BANK: u8 = super::METADATA_TEXT_BANK; const STATUS: u8 = 0x8; + /// MIDI 2.0 Publisher Name Message + /// + /// See the [module docs](crate::flex_data) for more info. #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), MinSizeUmp(4))] struct PublisherName { #[property(common_properties::UmpMessageTypeProperty<{flex_data::UMP_MESSAGE_TYPE}>)] @@ -349,6 +375,9 @@ mod primary_performer_name { const BANK: u8 = super::METADATA_TEXT_BANK; const STATUS: u8 = 0x9; + /// MIDI 2.0 Primary Performer Name Message + /// + /// See the [module docs](crate::flex_data) for more info. #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), MinSizeUmp(4))] struct PrimaryPerformerName { #[property(common_properties::UmpMessageTypeProperty<{flex_data::UMP_MESSAGE_TYPE}>)] @@ -390,6 +419,9 @@ mod accompanying_performer_name { const BANK: u8 = super::METADATA_TEXT_BANK; const STATUS: u8 = 0xA; + /// MIDI 2.0 Accompanying Performer Name Message + /// + /// See the [module docs](crate::flex_data) for more info. #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), MinSizeUmp(4))] struct AccompanyingPerformerName { #[property(common_properties::UmpMessageTypeProperty<{flex_data::UMP_MESSAGE_TYPE}>)] @@ -431,6 +463,9 @@ mod recording_date { const BANK: u8 = super::METADATA_TEXT_BANK; const STATUS: u8 = 0xB; + /// MIDI 2.0 Recording Date Message + /// + /// See the [module docs](crate::flex_data) for more info. #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), MinSizeUmp(4))] struct RecordingDate { #[property(common_properties::UmpMessageTypeProperty<{flex_data::UMP_MESSAGE_TYPE}>)] @@ -472,6 +507,9 @@ mod recording_location { const BANK: u8 = super::METADATA_TEXT_BANK; const STATUS: u8 = 0xC; + /// MIDI 2.0 Recording Location Message + /// + /// See the [module docs](crate::flex_data) for more info. #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), MinSizeUmp(4))] struct RecordingLocation { #[property(common_properties::UmpMessageTypeProperty<{flex_data::UMP_MESSAGE_TYPE}>)] @@ -513,6 +551,9 @@ mod unknown_performance_text { const BANK: u8 = super::PERFORMANCE_TEXT_BANK; const STATUS: u8 = 0x0; + /// MIDI 2.0 Unknown Performance Text Message + /// + /// See the [module docs](crate::flex_data) for more info. #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), MinSizeUmp(4))] struct UnknownPerformanceText { #[property(common_properties::UmpMessageTypeProperty<{flex_data::UMP_MESSAGE_TYPE}>)] @@ -554,6 +595,9 @@ mod lyrics { const BANK: u8 = super::PERFORMANCE_TEXT_BANK; const STATUS: u8 = 0x1; + /// MIDI 2.0 Lyrics Message + /// + /// See the [module docs](crate::flex_data) for more info. #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), MinSizeUmp(4))] struct Lyrics { #[property(common_properties::UmpMessageTypeProperty<{flex_data::UMP_MESSAGE_TYPE}>)] @@ -595,6 +639,9 @@ mod lyrics_language { const BANK: u8 = super::PERFORMANCE_TEXT_BANK; const STATUS: u8 = 0x2; + /// MIDI 2.0 Lyrics Language Message + /// + /// See the [module docs](crate::flex_data) for more info. #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), MinSizeUmp(4))] struct LyricsLanguage { #[property(common_properties::UmpMessageTypeProperty<{flex_data::UMP_MESSAGE_TYPE}>)] @@ -636,6 +683,9 @@ mod ruby { const BANK: u8 = super::PERFORMANCE_TEXT_BANK; const STATUS: u8 = 0x3; + /// MIDI 2.0 Ruby Message + /// + /// See the [module docs](crate::flex_data) for more info. #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), MinSizeUmp(4))] struct Ruby { #[property(common_properties::UmpMessageTypeProperty<{flex_data::UMP_MESSAGE_TYPE}>)] @@ -677,6 +727,9 @@ mod ruby_language { const BANK: u8 = super::PERFORMANCE_TEXT_BANK; const STATUS: u8 = 0x4; + /// MIDI 2.0 Ruby Language Message + /// + /// See the [module docs](crate::flex_data) for more info. #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), MinSizeUmp(4))] struct RubyLanguage { #[property(common_properties::UmpMessageTypeProperty<{flex_data::UMP_MESSAGE_TYPE}>)] @@ -802,8 +855,8 @@ impl<'a> TryFrom<&'a [u32]> for FlexData<&'a [u32]> { SetTimeSignature(set_time_signature::SetTimeSignature::try_from(value)?.into()) } 0x00_02 => SetMetronome(set_metronome::SetMetronome::try_from(value)?.into()), - 0x00_03 => SetKeySignature(set_key_signature::SetKeySignature::try_from(value)?.into()), - 0x00_04 => SetChordName(set_chord_name::SetChordName::try_from(value)?.into()), + 0x00_05 => SetKeySignature(set_key_signature::SetKeySignature::try_from(value)?.into()), + 0x00_06 => SetChordName(set_chord_name::SetChordName::try_from(value)?.into()), 0x01_00 => UnknownMetadataText( unknown_metadata_text::UnknownMetadataText::try_from(value)?.into(), ), @@ -1244,4 +1297,10 @@ mod tests { ); assert_eq!(packets.next(), None); } + + #[test] + fn try_from_set_chord_name_data() { + let message = FlexData::try_from(&[0xD70B_0006, 0xF703_3519, 0x4B00_0000, 0x110A_0020][..]); + message.expect("Valid data"); + } } diff --git a/src/flex_data/README.md b/src/flex_data/README.md new file mode 100644 index 0000000..83b45c3 --- /dev/null +++ b/src/flex_data/README.md @@ -0,0 +1,65 @@ +MIDI 2.0 Flex Data Messages + +## Basic Usage + +```rust +use midi2::{ + prelude::*, + flex_data::{FlexData, FlexDataMessage}, +}; + +let message = FlexData::try_from(&[ + 0xD70B_0006, + 0xF703_3519, + 0x4B00_0000, + 0x110A_0020 +][..]).expect("Valid data"); + +// all flex_data messages are grouped +println!("Group: {}", message.group()); +// all flex_data messages have a bank property +println!("Bank: {:?}", message.bank()); + +match message { + FlexData::SetChordName(m) => { + println!("Set Chord Name {:?}", m.data()); + // some flex_data messages have an optional `channel` field + println!("Channel: {:?}", m.optional_channel()); + }, + FlexData::ComposerName(m) => { + println!("Composer Name {:?}", m.data()); + // string properties of flex_data messages carrying string data + // can be read as a std::string::String (std feature enabled) + println!("Name {:?}", m.name()); + // or as an iterator over the utf-8 bytes (no_std freindly) + println!("Name bytes {:?}", m.name_bytes().collect::>()); + } + FlexData::SetKeySignature(m) => println!("Set Key Signature {:?}", m.data()), + FlexData::SetMetronome(m) => println!("Set Metronome {:?}", m.data()), + FlexData::SetTempo(m) => println!("Set Tempo {:?}", m.data()), + FlexData::SetTimeSignature(m) => println!("Set Time Signature {:?}", m.data()), + FlexData::UnknownMetadataText(m) => println!("Unknown Metadata Text {:?}", m.data()), + FlexData::ProjectName(m) => println!("Project Name {:?}", m.data()), + FlexData::CompositionName(m) => println!("Composition Name {:?}", m.data()), + FlexData::MidiClipName(m) => println!("Midi Clip Name {:?}", m.data()), + FlexData::CopyrightNotice(m) => println!("Copyright Notice {:?}", m.data()), + FlexData::LyricistName(m) => println!("Lyricist Name {:?}", m.data()), + FlexData::ArrangerName(m) => println!("Arranger Name {:?}", m.data()), + FlexData::PublisherName(m) => println!("Publisher Name {:?}", m.data()), + FlexData::PrimaryPerformerName(m) => println!("Primary Performer Name {:?}", m.data()), + FlexData::AccompanyingPerformerName(m) => println!("Accompanying Performer Name {:?}", m.data()), + FlexData::RecordingDate(m) => println!("Recording Date {:?}", m.data()), + FlexData::RecordingLocation(m) => println!("Recording Location {:?}", m.data()), + FlexData::UnknownPerformanceText(m) => println!("Unknown Performance Text {:?}", m.data()), + FlexData::Lyrics(m) => println!("Lyrics {:?}", m.data()), + FlexData::LyricsLanguage(m) => println!("Lyrics Language {:?}", m.data()), + FlexData::Ruby(m) => println!("Ruby {:?}", m.data()), + FlexData::RubyLanguage(m) => println!("Ruby Language {:?}", m.data()), + _ => {}, +} +``` + +## Dynamically Sized + +Some flex_data messages are fixed size and some are dynamically sized. +All default constructed flex_data messages will fit into a `[u32; 4]`. diff --git a/src/flex_data/set_chord_name.rs b/src/flex_data/set_chord_name.rs index a89cfcc..c90f0e7 100644 --- a/src/flex_data/set_chord_name.rs +++ b/src/flex_data/set_chord_name.rs @@ -6,6 +6,9 @@ use crate::{ const STATUS: u8 = 0x6; +/// MIDI 2.0 Flex Data Set Chord Name Message +/// +/// See the [module docs](crate::flex_data) for more info. #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), FixedSize, MinSizeUmp(4))] struct SetChordName { #[property(common_properties::UmpMessageTypeProperty)] diff --git a/src/flex_data/set_key_signature.rs b/src/flex_data/set_key_signature.rs index a3d26a3..6f55e58 100644 --- a/src/flex_data/set_key_signature.rs +++ b/src/flex_data/set_key_signature.rs @@ -6,6 +6,9 @@ use crate::{ const STATUS: u8 = 0x5; +/// MIDI 2.0 Flex Data Set Key Signature Message +/// +/// See the [module docs](crate::flex_data) for more info. #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), FixedSize, MinSizeUmp(2))] struct SetKeySignature { #[property(common_properties::UmpMessageTypeProperty)] diff --git a/src/flex_data/set_metronome.rs b/src/flex_data/set_metronome.rs index 196c128..f1e0716 100644 --- a/src/flex_data/set_metronome.rs +++ b/src/flex_data/set_metronome.rs @@ -5,6 +5,9 @@ use crate::{ const STATUS: u8 = 0x2; +/// MIDI 2.0 Flex Data Set Metronome Message +/// +/// See the [module docs](crate::flex_data) for more info. #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), FixedSize, MinSizeUmp(3))] struct SetMetronome { #[property(common_properties::UmpMessageTypeProperty)] diff --git a/src/flex_data/set_tempo.rs b/src/flex_data/set_tempo.rs index 162148f..486f397 100644 --- a/src/flex_data/set_tempo.rs +++ b/src/flex_data/set_tempo.rs @@ -5,6 +5,9 @@ use crate::{ const STATUS: u8 = 0x0; +/// MIDI 2.0 Flex Data Set Tempo Message +/// +/// See the [module docs](crate::flex_data) for more info. #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), FixedSize, MinSizeUmp(2))] struct SetTempo { #[property(common_properties::UmpMessageTypeProperty)] diff --git a/src/flex_data/set_time_signature.rs b/src/flex_data/set_time_signature.rs index f81c232..0bb4f41 100644 --- a/src/flex_data/set_time_signature.rs +++ b/src/flex_data/set_time_signature.rs @@ -5,6 +5,9 @@ use crate::{ const STATUS: u8 = 0x1; +/// MIDI 2.0 Flex Data Set Time Signature Message +/// +/// See the [module docs](crate::flex_data) for more info. #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), FixedSize, MinSizeUmp(2))] struct SetTimeSignature { #[property(common_properties::UmpMessageTypeProperty)] diff --git a/src/flex_data/unknown_metadata_text.rs b/src/flex_data/unknown_metadata_text.rs index 87c2b55..63ff2eb 100644 --- a/src/flex_data/unknown_metadata_text.rs +++ b/src/flex_data/unknown_metadata_text.rs @@ -2,6 +2,9 @@ use crate::{detail::common_properties, flex_data}; const STATUS: u8 = 0x00; +/// MIDI 2.0 Flex Data Unknown Metadata Text Message +/// +/// See the [module docs](crate::flex_data) for more info. #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), MinSizeUmp(4))] struct UnknownMetadataText { #[property(common_properties::UmpMessageTypeProperty<{flex_data::UMP_MESSAGE_TYPE}>)] diff --git a/src/system_common.rs b/src/system_common.rs index 4256d61..0bb8e1a 100644 --- a/src/system_common.rs +++ b/src/system_common.rs @@ -12,6 +12,9 @@ mod tune_request { system_common::{self, UMP_MESSAGE_TYPE}, }; pub(crate) const STATUS: u8 = 0xF6; + /// MIDI 2.0 Channel Voice Tune Request Message + /// + /// See the [module docs](crate::system_common) for more info. #[midi2_proc::generate_message( Via(system_common::SystemCommon), FixedSize, @@ -33,6 +36,9 @@ mod timing_clock { system_common::{self, UMP_MESSAGE_TYPE}, }; pub(crate) const STATUS: u8 = 0xF8; + /// MIDI 2.0 Channel Voice Timing Clock Message + /// + /// See the [module docs](crate::system_common) for more info. #[midi2_proc::generate_message( Via(system_common::SystemCommon), FixedSize, @@ -54,6 +60,9 @@ mod start { system_common::{self, UMP_MESSAGE_TYPE}, }; pub(crate) const STATUS: u8 = 0xFA; + /// MIDI 2.0 Channel Voice Start Message + /// + /// See the [module docs](crate::system_common) for more info. #[midi2_proc::generate_message( Via(system_common::SystemCommon), FixedSize, @@ -75,6 +84,9 @@ mod cont { system_common::{self, UMP_MESSAGE_TYPE}, }; pub(crate) const STATUS: u8 = 0xFB; + /// MIDI 2.0 Channel Voice Continue Message + /// + /// See the [module docs](crate::system_common) for more info. #[midi2_proc::generate_message( Via(system_common::SystemCommon), FixedSize, @@ -96,6 +108,9 @@ mod stop { system_common::{self, UMP_MESSAGE_TYPE}, }; pub(crate) const STATUS: u8 = 0xFC; + /// MIDI 2.0 Channel Voice Stop Message + /// + /// See the [module docs](crate::system_common) for more info. #[midi2_proc::generate_message( Via(system_common::SystemCommon), FixedSize, @@ -117,6 +132,9 @@ mod active_sensing { system_common::{self, UMP_MESSAGE_TYPE}, }; pub(crate) const STATUS: u8 = 0xFE; + /// MIDI 2.0 Channel Voice Active Sensing Message + /// + /// See the [module docs](crate::system_common) for more info. #[midi2_proc::generate_message( Via(system_common::SystemCommon), FixedSize, @@ -138,6 +156,9 @@ mod reset { system_common::{self, UMP_MESSAGE_TYPE}, }; pub(crate) const STATUS: u8 = 0xFF; + /// MIDI 2.0 Channel Voice Reset Message + /// + /// See the [module docs](crate::system_common) for more info. #[midi2_proc::generate_message( Via(system_common::SystemCommon), FixedSize, diff --git a/src/system_common/README.md b/src/system_common/README.md index fbe449c..7e4a62e 100644 --- a/src/system_common/README.md +++ b/src/system_common/README.md @@ -1,6 +1,6 @@ -Semantic wrapper types around MIDI System Common and System Real Time data. +MIDI System Common and System Real Time messages. -# Abstract over [Buffer](crate::buffer::Buffer) +## Abstract over [Buffer](crate::buffer::Buffer) System Common and System Real Time messages can be represented with classical MIDI byte arrays or with the MIDI 2.0 Universal @@ -31,3 +31,26 @@ message.set_song(u7::new(0x42)); message.set_group(u4::new(0x3)); assert_eq!(message.data(), &[0x13F3_4200]); ``` + +## Fixed Size + +`system_common` messages always fit within an +array of 'u32' size 1 or greater, when represented +with a [Ump](crate::buffer::Ump) buffer. + +```rust +use midi2::system_common::SongSelect; + +let _ = SongSelect::<[u32; 1]>::new(); +let _ = SongSelect::<[u32; 4]>::new(); +``` + +`system_common` messages always fit within an +array of 'u8' size 3 or greater, when represented +with a [Bytes](crate::buffer::Bytes) buffer. + +```rust +use midi2::system_common::SongSelect; + +let _ = SongSelect::<[u8; 3]>::new(); +``` diff --git a/src/system_common/song_position_pointer.rs b/src/system_common/song_position_pointer.rs index 6de13db..f417a00 100644 --- a/src/system_common/song_position_pointer.rs +++ b/src/system_common/song_position_pointer.rs @@ -5,6 +5,9 @@ use crate::{ pub const STATUS: u8 = 0xF2; +/// MIDI 2.0 Channel Voice Song Position Pointer Message +/// +/// See the [module docs](crate::system_common) for more info. #[midi2_proc::generate_message( Via(system_common::SystemCommon), FixedSize, diff --git a/src/system_common/song_select.rs b/src/system_common/song_select.rs index b5715f4..2fcba9e 100644 --- a/src/system_common/song_select.rs +++ b/src/system_common/song_select.rs @@ -5,6 +5,9 @@ use crate::{ pub const STATUS: u8 = 0xF3; +/// MIDI 2.0 Channel Voice Song Select Message +/// +/// See the [module docs](crate::system_common) for more info. #[midi2_proc::generate_message( Via(system_common::SystemCommon), FixedSize, diff --git a/src/system_common/time_code.rs b/src/system_common/time_code.rs index ee7b7f0..97ba7cd 100644 --- a/src/system_common/time_code.rs +++ b/src/system_common/time_code.rs @@ -5,6 +5,9 @@ use crate::{ pub const STATUS: u8 = 0xF1; +/// MIDI 2.0 Channel Voice Time Code Message +/// +/// See the [module docs](crate::system_common) for more info. #[midi2_proc::generate_message( Via(system_common::SystemCommon), FixedSize,