Skip to content

Commit a67128a

Browse files
committed
Added enum variants for System Common and System Realtime messages
1 parent 69e1e1e commit a67128a

File tree

2 files changed

+157
-0
lines changed

2 files changed

+157
-0
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
66
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
77

8+
## [Unreleased]
9+
10+
### Added
11+
12+
- `Message` enum variants for *System Common* and *System Realtime* messages.
13+
814
## [0.4.0] - 2025-01-03
915

1016
This release focuses on:

src/message/mod.rs

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,28 @@ pub enum Message {
3939
PitchWheelChange(Channel, U7, U7),
4040
/// Control Change (CC) message.
4141
ControlChange(Channel, ControlFunction, U7),
42+
/// MTC Quarter Frame message.
43+
MtcQuarterFrame(U7),
44+
/// Song Position Pointer message.
45+
SongPositionPointer(U7, U7),
46+
/// Song Select message.
47+
SongSelect(U7),
48+
/// Tune Request message.
49+
TuneRequest,
50+
/// Timing Clock message.
51+
TimingClock,
52+
/// Tick message.
53+
Tick,
54+
/// Start message.
55+
Start,
56+
/// Continue message.
57+
Continue,
58+
/// Stop message.
59+
Stop,
60+
/// Active Sensing message.
61+
ActiveSensing,
62+
/// Reset message.
63+
Reset,
4264
}
4365

4466
const NOTE_OFF_MASK: u8 = 0b1000_0000;
@@ -49,6 +71,18 @@ const CHANNEL_AFTERTOUCH_MASK: u8 = 0b1101_0000;
4971
const PITCH_BEND_MASK: u8 = 0b1110_0000;
5072
const CONTROL_CHANGE_MASK: u8 = 0b1011_0000;
5173

74+
const MTC_QUARTER_FRAME: u8 = 0xF1;
75+
const SONG_POSITION_POINTER: u8 = 0xF2;
76+
const SONG_SELECT: u8 = 0xF3;
77+
const TUNE_REQUEST: u8 = 0xF6;
78+
const TIMING_CLOCK: u8 = 0xF8;
79+
const TICK: u8 = 0xF9;
80+
const START: u8 = 0xFA;
81+
const CONTINUE: u8 = 0xFB;
82+
const STOP: u8 = 0xFC;
83+
const ACTIVE_SENSING: u8 = 0xFE;
84+
const RESET: u8 = 0xFF;
85+
5286
impl From<Message> for Raw {
5387
fn from(value: Message) -> Raw {
5488
match value {
@@ -87,6 +121,61 @@ impl From<Message> for Raw {
87121
let status = CONTROL_CHANGE_MASK | u8::from(chan);
88122
Raw { status, payload }
89123
}
124+
Message::MtcQuarterFrame(frame) => {
125+
let payload = Payload::SingleByte(frame);
126+
let status = MTC_QUARTER_FRAME;
127+
Raw { status, payload }
128+
}
129+
Message::SongPositionPointer(lsb, msb) => {
130+
let payload = Payload::DoubleByte(lsb, msb);
131+
let status = SONG_POSITION_POINTER;
132+
Raw { status, payload }
133+
}
134+
Message::SongSelect(song) => {
135+
let payload = Payload::SingleByte(song);
136+
let status = SONG_SELECT;
137+
Raw { status, payload }
138+
}
139+
Message::TuneRequest => {
140+
let payload = Payload::Empty;
141+
let status = TUNE_REQUEST;
142+
Raw { status, payload }
143+
}
144+
Message::TimingClock => {
145+
let payload = Payload::Empty;
146+
let status = TIMING_CLOCK;
147+
Raw { status, payload }
148+
}
149+
Message::Tick => {
150+
let payload = Payload::Empty;
151+
let status = TICK;
152+
Raw { status, payload }
153+
}
154+
Message::Start => {
155+
let payload = Payload::Empty;
156+
let status = START;
157+
Raw { status, payload }
158+
}
159+
Message::Continue => {
160+
let payload = Payload::Empty;
161+
let status = CONTINUE;
162+
Raw { status, payload }
163+
}
164+
Message::Stop => {
165+
let payload = Payload::Empty;
166+
let status = STOP;
167+
Raw { status, payload }
168+
}
169+
Message::ActiveSensing => {
170+
let payload = Payload::Empty;
171+
let status = ACTIVE_SENSING;
172+
Raw { status, payload }
173+
}
174+
Message::Reset => {
175+
let payload = Payload::Empty;
176+
let status = RESET;
177+
Raw { status, payload }
178+
}
90179
}
91180
}
92181
}
@@ -100,6 +189,46 @@ impl TryFrom<&[u8]> for Message {
100189
None => return Err(UsbMidiEventPacketError::MissingDataPacket),
101190
};
102191

192+
match *status_byte {
193+
MTC_QUARTER_FRAME => {
194+
return Ok(Message::MtcQuarterFrame(get_u7_at(data, 1)?));
195+
}
196+
SONG_POSITION_POINTER => {
197+
return Ok(Message::SongPositionPointer(
198+
get_u7_at(data, 1)?,
199+
get_u7_at(data, 2)?,
200+
));
201+
}
202+
SONG_SELECT => {
203+
return Ok(Message::SongSelect(get_u7_at(data, 1)?));
204+
}
205+
TUNE_REQUEST => {
206+
return Ok(Message::TuneRequest);
207+
}
208+
TIMING_CLOCK => {
209+
return Ok(Message::TimingClock);
210+
}
211+
TICK => {
212+
return Ok(Message::Tick);
213+
}
214+
START => {
215+
return Ok(Message::Start);
216+
}
217+
CONTINUE => {
218+
return Ok(Message::Continue);
219+
}
220+
STOP => {
221+
return Ok(Message::Stop);
222+
}
223+
ACTIVE_SENSING => {
224+
return Ok(Message::ActiveSensing);
225+
}
226+
RESET => {
227+
return Ok(Message::Reset);
228+
}
229+
_ => {}
230+
}
231+
103232
let event_type = status_byte & 0b1111_0000;
104233
let channel_bytes = (status_byte) & 0b0000_1111;
105234

@@ -184,6 +313,17 @@ impl Message {
184313
Self::PolyphonicAftertouch(_, _, _) => CodeIndexNumber::PolyKeyPress,
185314
Self::ProgramChange(_, _) => CodeIndexNumber::ProgramChange,
186315
Self::ControlChange(_, _, _) => CodeIndexNumber::ControlChange,
316+
Self::MtcQuarterFrame(_) => CodeIndexNumber::SystemCommon2Bytes,
317+
Self::SongPositionPointer(_, _) => CodeIndexNumber::SystemCommon3Bytes,
318+
Self::SongSelect(_) => CodeIndexNumber::SystemCommon2Bytes,
319+
Self::TuneRequest => CodeIndexNumber::SystemCommon1Byte,
320+
Self::TimingClock => CodeIndexNumber::SingleByte,
321+
Self::Tick => CodeIndexNumber::SingleByte,
322+
Self::Start => CodeIndexNumber::SingleByte,
323+
Self::Continue => CodeIndexNumber::SingleByte,
324+
Self::Stop => CodeIndexNumber::SingleByte,
325+
Self::ActiveSensing => CodeIndexNumber::SingleByte,
326+
Self::Reset => CodeIndexNumber::SingleByte,
187327
}
188328
}
189329
}
@@ -239,5 +379,16 @@ mod tests {
239379
channel_aftertouch: ([13, 208, 127, 0], Message::ChannelAftertouch(Channel1, U7(127)).into_packet(Cable0)),
240380
pitch_wheel: ([14, 224, 64, 32], Message::PitchWheelChange(Channel1, U7(64), U7(32)).into_packet(Cable0)),
241381
control_change: ([11, 177, 1, 32], Message::ControlChange(Channel2, ControlFunction::MOD_WHEEL_1, U7(32)).into_packet(Cable0)),
382+
mtc_quarter_frame: ([0x02, 0xF1, 12, 0], Message::MtcQuarterFrame(U7(12)).into_packet(Cable0)),
383+
song_position_pointer: ([0x03, 0xF2, 38, 75], Message::SongPositionPointer(U7(38), U7(75)).into_packet(Cable0)),
384+
song_select: ([0x02, 0xF3, 4, 0], Message::SongSelect(U7(4)).into_packet(Cable0)),
385+
tune_request: ([0x05, 0xF6, 0, 0], Message::TuneRequest.into_packet(Cable0)),
386+
timing_clock: ([0x0F, 0xF8, 0, 0], Message::TimingClock.into_packet(Cable0)),
387+
tick: ([0x0F, 0xF9, 0, 0], Message::Tick.into_packet(Cable0)),
388+
start: ([0x0F, 0xFA, 0, 0], Message::Start.into_packet(Cable0)),
389+
continue_: ([0x0F, 0xFB, 0, 0], Message::Continue.into_packet(Cable0)),
390+
stop: ([0x0F, 0xFC, 0, 0], Message::Stop.into_packet(Cable0)),
391+
active_sensing: ([0x0F, 0xFE, 0, 0], Message::ActiveSensing.into_packet(Cable0)),
392+
reset: ([0x0F, 0xFF, 0, 0], Message::Reset.into_packet(Cable0)),
242393
}
243394
}

0 commit comments

Comments
 (0)