midnote/
init.rs

1mod helpers;
2mod meta_events;
3
4use std::{
5	error::Error,
6	fs,
7	sync::mpsc::{self, Receiver},
8};
9
10use meta_events::extract_meta_events;
11use midly::{Format, Smf, Timing};
12use nodi::Sheet;
13
14use crate::{app, bar, config::Config, player::Player, Response};
15
16pub struct Args {
17	pub config: Config,
18	pub player: Player,
19	pub response: Receiver<Response>,
20}
21
22impl Args {
23	pub fn parse_args() -> Result<Self, Box<dyn Error>> {
24		let m = app::new().get_matches();
25		if m.is_present("list") {
26			helpers::list_devices()?;
27			std::process::exit(0);
28		}
29
30		let mut config = m
31			.value_of("config")
32			.map(Config::read_from)
33			.unwrap_or_else(|| Ok(Config::default()))?;
34
35		if m.is_present("no-color") {
36			config.colors = false;
37		}
38
39		let data = m.value_of("file").map(fs::read).unwrap()?;
40		let device_no = m.value_of("device").unwrap().parse::<usize>()?;
41		let con = helpers::get_midi(device_no)?;
42
43		let Smf { tracks, header } = Smf::parse(&data)?;
44
45		let tpb = match header.timing {
46			Timing::Metrical(n) => u16::from(n),
47			_ => return Err("the midi file has an unsupported time format".into()),
48		};
49
50		let (sender, receiver) = mpsc::channel();
51
52		let (all, sheet) = match header.format {
53			Format::Parallel => {
54				let all = Sheet::parallel(&tracks);
55				let mut sheet = helpers::choose_track(&tracks[0..]);
56				sheet.merge_with(extract_meta_events(&all));
57				(all, sheet)
58			}
59			_ => {
60				let sheet = Sheet::sequential(&tracks);
61				(sheet.clone(), sheet)
62			}
63		};
64
65		let player = Player::new(con, sender, bar::bars(all, tpb), bar::bars(sheet, tpb));
66
67		Ok(Self {
68			player,
69			response: receiver,
70			config,
71		})
72	}
73}