bmidi/
parser.rs

1use std::fs::File as FsFile;
2use std::io::{BufReader, Read};
3use std::path::Path;
4
5use crate::combined_iterator::CombinedIterator;
6use crate::reader::MidiReader;
7use crate::types::{Event, Ticks};
8
9pub type Track = Vec<u8>;
10
11pub struct File {
12    pub tracks: Vec<Track>,
13    pub format: u16,
14    pub division: Ticks,
15}
16
17impl File {
18    pub fn track_iter<'a>(&'a self, index: usize) -> Box<dyn Iterator<Item = Event> + 'a> {
19        let track = &self.tracks[index];
20        let iter = track.iter().cloned();
21        let my_reader = MidiReader::new(iter);
22        Box::new(my_reader)
23    }
24
25    pub fn iter<'a>(&'a self) -> CombinedIterator<'a> {
26        CombinedIterator::<'a>::new((0..self.tracks.len()).map(|n| self.track_iter(n)).collect())
27    }
28
29    pub fn parse(filename: &Path) -> File {
30        let f = FsFile::open(filename).unwrap();
31        let reader = BufReader::new(f);
32        let mut reader = reader.bytes().map(Result::unwrap);
33        let mut reader = MidiReader::new(&mut reader);
34
35        let header = reader.read_string(4);
36
37        if header != "MThd" {
38            panic!("Not a MIDI file")
39        }
40
41        if reader.read_int() != 6 {
42            panic!("Still not a MIDI file")
43        }
44
45        let format = reader.read_short();
46        if format >= 3 {
47            panic!("Version greater than 2, not implemented")
48        }
49
50        let track_count = reader.read_short();
51        let mut tracks = Vec::<Track>::with_capacity(track_count as usize);
52        let division = reader.read_short().into();
53
54        println!("Found {} tracks, division {}", track_count, division);
55
56        for _ in 0..track_count {
57            let header = reader.read_string(4);
58
59            if header != "MTrk" {
60                panic!("Invalid track header")
61            }
62
63            let length = reader.read_int() as usize;
64
65            println!("Found track of length {}", length);
66
67            tracks.push(reader.read_bytes(length))
68        }
69
70        for t in &tracks {
71            println!("Parsed track of length {}", t.len());
72        }
73
74        File {
75            format,
76            division,
77            tracks,
78        }
79    }
80}