play/
play.rs

1use lyrica::{MidiFile, MidiOutput, MidiPlayer};
2use std::{
3    env,
4    error::Error,
5    fs,
6    io::{stdin, stdout, Write},
7};
8
9fn main() -> Result<(), Box<dyn Error>> {
10    let args = env::args().collect::<Vec<_>>();
11
12    if args.len() != 2 {
13        println!("usage: {} [filename]", args[0]);
14
15        return Err(format!(
16            "incorrect number of arguments (expected 1, got {})",
17            args.len() - 1
18        )
19        .into());
20    }
21
22    let filename = &args[1];
23
24    let midi_output = MidiOutput::new("lyrica-play")?;
25    let midi_ports = midi_output.ports();
26
27    if midi_ports.is_empty() {
28        eprintln!("there are no MIDI devices available");
29        #[cfg(windows)]
30        eprintln!("if you are on Wine, this is expected behaviour");
31        return Ok(());
32    }
33
34    let port_number = loop {
35        println!("Available MIDI ports:");
36        for (i, port) in midi_ports.iter().enumerate() {
37            println!("{}: {}", i, midi_output.port_name(port)?);
38        }
39
40        print!("Please select a port: ");
41        stdout().flush()?;
42        let mut input = String::new();
43        stdin().read_line(&mut input)?;
44        let trimmed_input = input.trim();
45
46        let port_number = match trimmed_input.parse::<usize>() {
47            Ok(port_number) => port_number,
48
49            Err(_) => {
50                println!("port number must be a number (got {trimmed_input})");
51                continue;
52            }
53        };
54
55        if port_number > midi_output.port_count() {
56            println!(
57                "port number is too high (last port is {})",
58                midi_output.port_count()
59            );
60            continue;
61        }
62
63        break port_number;
64    };
65
66    let connection = midi_output.connect(&midi_ports[port_number], "lyrica-play")?;
67    let file = fs::read(filename)?;
68    let midi_file = MidiFile::from_bytes(&file)?;
69    let mut player = MidiPlayer::new(connection);
70    player.set_midi_file(midi_file)?;
71
72    while !player.is_finished() {
73        player.update()?;
74    }
75
76    Ok(())
77}