1use 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
11fn 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 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 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, 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}