Skip to main content

play/
play.rs

1extern crate sfml;
2extern crate sfml_modstream;
3
4use sfml::audio::{SoundStatus, SoundStreamPlayer};
5use sfml_modstream::{Metadata, ModStream};
6use std::fmt;
7use std::io::Write;
8use std::path::Path;
9
10struct HrTime {
11    seconds: f64,
12}
13
14impl fmt::Display for HrTime {
15    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
16        write!(
17            f,
18            "{:02.0}:{:04.1}",
19            (self.seconds / 60.).floor(),
20            self.seconds % 60.
21        )
22    }
23}
24
25struct OptStrFmt<'a> {
26    str: &'a str,
27    prepend: &'static str,
28    append: &'static str,
29}
30
31impl<'a> OptStrFmt<'a> {
32    fn new(prepend: &'static str, str: &'a str, append: &'static str) -> Self {
33        Self {
34            str,
35            prepend,
36            append,
37        }
38    }
39}
40
41impl<'a> std::fmt::Display for OptStrFmt<'a> {
42    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
43        if !self.str.is_empty() {
44            write!(f, "{}{}{}", self.prepend, self.str, self.append)
45        } else {
46            Ok(())
47        }
48    }
49}
50
51fn play_song(path: &Path) {
52    let mut stream = ModStream::from_file(path).unwrap();
53    let duration = HrTime {
54        seconds: stream.get_duration_seconds(),
55    };
56    let filename = path.file_name().unwrap().to_string_lossy();
57    let title = stream.metadata(Metadata::Title).unwrap();
58    let artist = stream.metadata(Metadata::Artist).unwrap();
59    let date = stream.metadata(Metadata::Date).unwrap();
60    let message = stream.metadata(Metadata::Message).unwrap();
61    let tracker = stream.metadata(Metadata::Tracker).unwrap();
62    let made_in_string = match (tracker.as_str().is_empty(), date.as_str().is_empty()) {
63        (true, true) => String::new(),
64        (false, true) => format!("Made in {}\n", tracker),
65        (true, false) => format!("Made in {}\n", date),
66        (false, false) => format!("Made in {} on {}\n", tracker, date),
67    };
68    println!(
69        "Playing {} {}[{}]\n\
70        {}\
71        {}",
72        title,
73        OptStrFmt::new(" by ", artist.as_str(), " "),
74        filename,
75        made_in_string,
76        message
77    );
78    let mut player = SoundStreamPlayer::new(&mut stream);
79    player.play();
80    while player.status() == SoundStatus::PLAYING {
81        let offset = HrTime {
82            seconds: f64::from(player.playing_offset().as_seconds()),
83        };
84        print!("{}/{}\r", offset, duration);
85        let _ = std::io::stdout().flush();
86        std::thread::sleep(std::time::Duration::from_millis(100));
87    }
88    // Leave the output of the previous song on the previous line
89    println!()
90}
91
92fn main() {
93    let args = std::env::args_os().skip(1);
94
95    if args.len() == 0 {
96        println!("You might want to supply some song paths as arguments. Just saying.");
97    }
98
99    for arg in args {
100        play_song(arg.as_ref());
101    }
102}