sfml-modstream 0.3.0

Custom SFML SoundStream for playing modules
Documentation
extern crate sfml;
extern crate sfml_modstream;

use sfml::audio::{SoundStatus, SoundStreamPlayer};
use sfml_modstream::{Metadata, ModStream};
use std::fmt;
use std::io::Write;
use std::path::Path;

struct HrTime {
    seconds: f64,
}

impl fmt::Display for HrTime {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "{:02.0}:{:04.1}",
            (self.seconds / 60.).floor(),
            self.seconds % 60.
        )
    }
}

struct OptStrFmt<'a> {
    str: &'a str,
    prepend: &'static str,
    append: &'static str,
}

impl<'a> OptStrFmt<'a> {
    fn new(prepend: &'static str, str: &'a str, append: &'static str) -> Self {
        Self {
            str,
            prepend,
            append,
        }
    }
}

impl<'a> std::fmt::Display for OptStrFmt<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        if !self.str.is_empty() {
            write!(f, "{}{}{}", self.prepend, self.str, self.append)
        } else {
            Ok(())
        }
    }
}

fn play_song(path: &Path) {
    let mut stream = ModStream::from_file(path).unwrap();
    let duration = HrTime {
        seconds: stream.get_duration_seconds(),
    };
    let filename = path.file_name().unwrap().to_string_lossy();
    let title = stream.metadata(Metadata::Title).unwrap();
    let artist = stream.metadata(Metadata::Artist).unwrap();
    let date = stream.metadata(Metadata::Date).unwrap();
    let message = stream.metadata(Metadata::Message).unwrap();
    let tracker = stream.metadata(Metadata::Tracker).unwrap();
    let made_in_string = match (tracker.as_str().is_empty(), date.as_str().is_empty()) {
        (true, true) => String::new(),
        (false, true) => format!("Made in {}\n", tracker),
        (true, false) => format!("Made in {}\n", date),
        (false, false) => format!("Made in {} on {}\n", tracker, date),
    };
    println!(
        "Playing {} {}[{}]\n\
        {}\
        {}",
        title,
        OptStrFmt::new(" by ", artist.as_str(), " "),
        filename,
        made_in_string,
        message
    );
    let mut player = SoundStreamPlayer::new(&mut stream);
    player.play();
    while player.status() == SoundStatus::PLAYING {
        let offset = HrTime {
            seconds: f64::from(player.playing_offset().as_seconds()),
        };
        print!("{}/{}\r", offset, duration);
        let _ = std::io::stdout().flush();
        std::thread::sleep(std::time::Duration::from_millis(100));
    }
    // Leave the output of the previous song on the previous line
    println!()
}

fn main() {
    let args = std::env::args_os().skip(1);

    if args.len() == 0 {
        println!("You might want to supply some song paths as arguments. Just saying.");
    }

    for arg in args {
        play_song(arg.as_ref());
    }
}