nom_midi/parser/event/
meta.rs

1//! Meta events
2use crate::{
3    parser::util::parse_var_length_bytes,
4    types::{Fps, KeySignature, MetaEvent, SMPTEOffset, TimeSignature},
5};
6use nom::{
7    error::{make_error, ErrorKind},
8    Err, IResult,
9};
10
11/// Takes the data from the parser and turns it into a key signature
12///
13/// Returns none if conversion not valid
14fn parse_to_key(sharps: i8, minor: u8) -> Option<KeySignature> {
15    use KeySignature::*;
16
17    let minor = match minor {
18        0 => false,
19        1 => true,
20        _ => return None,
21    };
22    match (sharps, minor) {
23        (0, true) => Some(AMinor),
24        (0, false) => Some(CMajor),
25        (1, true) => Some(EMinor),
26        (1, false) => Some(GMajor),
27        (2, true) => Some(BMinor),
28        (2, false) => Some(DMajor),
29        (3, true) => Some(FSharpMinor),
30        (3, false) => Some(AMajor),
31        (4, true) => Some(CSharpMinor),
32        (4, false) => Some(EMajor),
33        (5, true) => Some(GSharpMinor),
34        (5, false) => Some(BMajor),
35        (6, true) => Some(DSharpMinor),
36        (6, false) => Some(FSharpMajor),
37        (7, true) => Some(ASharpMinor),
38        (7, false) => Some(CSharpMajor),
39        (-1, true) => Some(DMinor),
40        (-1, false) => Some(FMajor),
41        (-2, true) => Some(GMinor),
42        (-2, false) => Some(BFlatMajor),
43        (-3, true) => Some(CMinor),
44        (-3, false) => Some(EFlatMajor),
45        (-4, true) => Some(FMinor),
46        (-4, false) => Some(AFlatMajor),
47        (-5, true) => Some(BFlatMinor),
48        (-5, false) => Some(DFlatMajor),
49        (-6, true) => Some(EFlatMinor),
50        (-6, false) => Some(GFlatMajor),
51        (-7, true) => Some(AFlatMinor),
52        (-7, false) => Some(CFlatMajor),
53        _ => None,
54    }
55}
56
57pub fn parse_meta_event(i: &[u8]) -> IResult<&[u8], MetaEvent> {
58    use nom::{
59        bytes::{complete::take as complete_take, streaming::tag},
60        number::{
61            complete::{
62                be_i8 as complete_be_i8, be_u16 as complete_be_u16, be_u8 as complete_be_u8,
63            },
64            streaming::be_u8,
65        },
66    };
67    let (i, _) = tag([0xFF])(i)?;
68    let (i, code) = be_u8(i)?;
69    let (i, data) = parse_var_length_bytes(i)?;
70    let evt = match code {
71        0x00 => {
72            let (_, sq_num) = complete_be_u16(data)?;
73            MetaEvent::SequenceNumber(sq_num)
74        }
75        0x01 => MetaEvent::Text(data),
76        0x02 => MetaEvent::Copyright(data),
77        0x03 => MetaEvent::SequenceOrTrackName(data),
78        0x04 => MetaEvent::InstrumentName(data),
79        0x05 => MetaEvent::Lyric(data),
80        0x06 => MetaEvent::Marker(data),
81        0x07 => MetaEvent::CuePoint(data),
82        0x08 => MetaEvent::ProgramName(data),
83        0x09 => MetaEvent::DeviceName(data),
84        0x20 => {
85            let (_, val) = complete_be_u8(data)?;
86            MetaEvent::MidiChannelPrefix(val)
87        }
88        0x21 => {
89            let (_, val) = complete_be_u8(data)?;
90            MetaEvent::MidiPort(val)
91        }
92        0x2F => MetaEvent::EndOfTrack,
93        0x51 => {
94            let (_, data) = complete_take(3usize)(data)?;
95            // 24-bit big-endian unsigned int
96            MetaEvent::Tempo((data[0] as u32) << 16 | (data[1] as u32) << 8 | (data[2] as u32))
97        }
98        0x54 => {
99            let (_, data) = complete_take(5usize)(data)?;
100            // Check top 2 bits
101            let fps = match data[0] & 0xC0 {
102                0x00 => Fps::TwentyFour,
103                0x40 => Fps::TwentyFive,
104                0x80 => Fps::TwentyNine,
105                0xC0 => Fps::Thirty,
106                _ => return Err(Err::Error(make_error(i, ErrorKind::Digit))),
107            };
108            MetaEvent::SMPTEOffset(SMPTEOffset {
109                fps: fps,
110                hour: data[0] & 0x3F, // complement of 0xC0
111                minute: data[1],
112                second: data[2],
113                no_frames: data[3],
114                no_fractional_frames: data[4],
115            })
116        }
117        0x58 => {
118            let (_, data) = complete_take(4usize)(data)?;
119            MetaEvent::TimeSignature(TimeSignature {
120                top: data[0],
121                bottom: data[1],
122                ticks_per_metronome_click: data[2],
123                number_32nd_in_quarter: data[3],
124            })
125        }
126        0x59 => {
127            let (data, sharps) = complete_be_i8(data)?;
128            let (_, major) = complete_be_u8(data)?;
129            match parse_to_key(sharps, major) {
130                Some(a) => MetaEvent::KeySignature(a),
131                None => return Err(Err::Error(make_error(i, ErrorKind::Digit))),
132            }
133        }
134        0x7F => MetaEvent::SequencerSpecificEvent(data),
135        other => MetaEvent::Unknown(other, data),
136    };
137    Ok((i, evt))
138}