midi-player 0.2.3

A MIDI file player library with integrated synthesizer
Documentation
#![allow(missing_docs)]

use std::{thread, time::Duration};

use cpal::{
    traits::{DeviceTrait, HostTrait, StreamTrait},
    StreamConfig,
};
use indicatif::{ProgressBar, ProgressStyle};
use midi_player::{Player, Settings};

fn main() {
    let settings = Settings::builder().build();
    let (player, mut controller) =
        Player::new("examples/Nice-Steinway-Lite-v3.0.sf2", settings).unwrap();

    thread::spawn(|| {
        start_audio_loop(player);
    });

    thread::sleep(Duration::from_secs(2));
    controller
        .set_file(Some("examples/Sibelius_The_Spruce.mid"))
        .unwrap();

    controller.play();

    println!("tempo: {:.2} BPM", controller.tempo().unwrap());

    let position_observer = controller.new_position_observer();

    // check releases on play/stop toggle
    // thread::spawn(move || loop {
    //     thread::sleep(Duration::from_secs(2));
    //     controller.stop();
    //     thread::sleep(Duration::from_secs(1));
    //     controller.play();
    // });

    thread::spawn(move || {
        let pb = ProgressBar::new(1000);
        pb.set_style(
            ProgressStyle::with_template("{wide_bar:.magenta.on_white/blue.on_white}")
                .unwrap()
                .progress_chars("━━-"),
        );

        loop {
            let position = (1000.0 * position_observer.get()) as u64;
            pb.set_position(position);
            thread::sleep(Duration::from_millis(100));
        }
    });

    loop {}
}

fn start_audio_loop(mut player: Player) {
    let host = cpal::default_host();
    let device = host
        .default_output_device()
        .expect("No output device available");
    let channels = 2_usize;
    let config = StreamConfig {
        channels: channels as u16,
        sample_rate: cpal::SampleRate(player.settings().sample_rate),
        buffer_size: cpal::BufferSize::Fixed(player.settings().audio_buffer_size),
    };

    let err_fn = |err| eprintln!("An error occurred on the output audio stream: {}", err);

    let mut left = vec![0f32; player.settings().audio_buffer_size as usize];
    let mut right = vec![0f32; player.settings().audio_buffer_size as usize];

    let stream = device
        .build_output_stream(
            &config,
            move |data: &mut [f32], _: &cpal::OutputCallbackInfo| {
                let sample_count = data.len() / channels;

                player.render(&mut left, &mut right);

                if !left.is_empty() {
                    for i in 0..sample_count {
                        data[channels * i] = left[i];
                        data[channels * i + 1] = right[i];
                    }
                }
            },
            err_fn,
            None,
        )
        .unwrap();

    stream.play().expect("cannot run audio stream");

    std::thread::park();
}