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}