muss/m3u8/src/main.rs

104 lines
3 KiB
Rust
Raw Normal View History

2022-01-28 19:32:52 +00:00
//! Minimal CLI tool to generate a m3u8 playlist from a MPS file.
//! This does not support playback, so it can run on any platform with a filesystem.
//! Use `mps-m3u8 --help` for usage instructions.
//!
mod cli;
use std::fs::File;
use std::io::{BufReader, BufWriter, Cursor};
2022-01-31 14:22:36 +00:00
use std::path::Path;
2022-01-28 19:32:52 +00:00
use m3u8_rs::{MediaPlaylist, MediaSegment};
2022-07-01 21:20:52 +01:00
use mps_interpreter::{Interpreter, Item};
2022-01-28 19:32:52 +00:00
fn main() {
let args = cli::parse();
let out_path = Path::new(&args.playlist);
let mut out_file = BufWriter::new(File::create(out_path).expect("Invalid output file"));
let mut playlist = MediaPlaylist {
version: 6,
..Default::default()
};
let mut skipped_count = 0;
if args.raw {
println!("Executing: {}", &args.input);
let in_file = Cursor::new(&args.input);
2022-07-01 21:20:52 +01:00
let runner = Interpreter::with_stream(in_file);
2022-01-28 19:32:52 +00:00
for item in runner {
match item {
Ok(music) => {
if let Some(filename) =
music_filename(&music)
2022-01-28 19:32:52 +00:00
{
playlist.segments.push(MediaSegment {
uri: filename,
title: music_title(&music),
2022-01-28 19:32:52 +00:00
..Default::default()
});
} else {
skipped_count += 1;
}
2022-01-31 14:22:36 +00:00
}
2022-01-28 19:32:52 +00:00
Err(e) => eprintln!("{}", e),
}
}
} else {
let in_path = Path::new(&args.input);
let in_file = BufReader::new(File::open(in_path).expect("Invalid/missing input file"));
2022-07-01 21:20:52 +01:00
let runner = Interpreter::with_stream(in_file);
2022-01-28 19:32:52 +00:00
for item in runner {
match item {
Ok(music) => {
if let Some(filename) =
music_filename(&music)
2022-01-28 19:32:52 +00:00
{
playlist.segments.push(MediaSegment {
uri: filename,
title: music_title(&music),
2022-01-28 19:32:52 +00:00
..Default::default()
});
} else {
skipped_count += 1;
}
2022-01-31 14:22:36 +00:00
}
2022-01-28 19:32:52 +00:00
Err(e) => eprintln!("{}", e),
}
}
}
if skipped_count != 0 {
2022-01-31 14:22:36 +00:00
eprintln!(
"Skipped {} items due to missing `filename` field",
skipped_count
);
2022-01-28 19:32:52 +00:00
}
if let Err(e) = playlist.write_to(&mut out_file) {
eprintln!("Playlist save error: {}", e);
}
}
2022-07-01 21:20:52 +01:00
fn music_title(item: &Item) -> Option<String> {
item.field("title").and_then(|x| x.to_owned().to_str())
}
2022-07-01 21:20:52 +01:00
fn music_filename(item: &Item) -> Option<String> {
if let Some(filename) = item.field("filename") {
if let Ok(cwd) = std::env::current_dir() {
let path: &Path = &cwd;
Some(filename.as_str().replace(path.to_str().unwrap_or(""), "./"))
} else {
Some(filename.to_string())
}
} else {
None
}
}