|
@ -9,14 +9,35 @@ fn read_lines<P>(path: P) -> io::Result<io::Lines<io::BufReader<File>>> |
|
|
Ok(io::BufReader::new(file).lines())
|
|
|
Ok(io::BufReader::new(file).lines())
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
|
pub struct PlaylistTrack {
|
|
|
|
|
|
duration: String,
|
|
|
|
|
|
display: String,
|
|
|
|
|
|
track: String |
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl PlaylistTrack {
|
|
|
|
|
|
pub fn new(duration: Option<String>, display: Option<String>, track: &str) -> PlaylistTrack {
|
|
|
|
|
|
PlaylistTrack {
|
|
|
|
|
|
duration: duration.unwrap_or(String::from("")),
|
|
|
|
|
|
display: display.unwrap_or(String::from("")),
|
|
|
|
|
|
track: String::from(track)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn render(&self) -> String {
|
|
|
|
|
|
format!("#EXTINFO:{},{}\n{}\n", self.duration, self.display, self.track)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
#[derive(Debug)]
|
|
|
pub struct Playlist {
|
|
|
pub struct Playlist {
|
|
|
path: String,
|
|
|
path: String,
|
|
|
tracks: Box<Vec<String>>
|
|
|
|
|
|
|
|
|
tracks: Box<Vec<PlaylistTrack>>
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
impl Playlist {
|
|
|
impl Playlist {
|
|
|
pub fn new(path: &str, tracks: Vec<String>) -> Playlist {
|
|
|
|
|
|
|
|
|
pub fn new(path: &str, tracks: Vec<PlaylistTrack>) -> Playlist {
|
|
|
Playlist {
|
|
|
Playlist {
|
|
|
path: String::from(path),
|
|
|
path: String::from(path),
|
|
|
tracks: Box::new(tracks)
|
|
|
tracks: Box::new(tracks)
|
|
@ -24,13 +45,40 @@ impl Playlist { |
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
pub fn read(path: &str) -> Result<Playlist, io::Error> {
|
|
|
pub fn read(path: &str) -> Result<Playlist, io::Error> {
|
|
|
let mut playlist_tracks: Vec<String> = Vec::new();
|
|
|
|
|
|
|
|
|
let mut playlist_tracks: Vec<PlaylistTrack> = Vec::new();
|
|
|
let lines = read_lines(path)?;
|
|
|
let lines = read_lines(path)?;
|
|
|
|
|
|
|
|
|
|
|
|
let mut found_header = false;
|
|
|
|
|
|
let mut duration: Option<String> = None;
|
|
|
|
|
|
let mut display: Option<String> = None;
|
|
|
|
|
|
|
|
|
lines.for_each(|read_line| {
|
|
|
lines.for_each(|read_line| {
|
|
|
if read_line.is_ok() {
|
|
|
if read_line.is_ok() {
|
|
|
let line = read_line.unwrap();
|
|
|
let line = read_line.unwrap();
|
|
|
if line.len() > 0 && !line.starts_with("#") {
|
|
|
|
|
|
playlist_tracks.push(line)
|
|
|
|
|
|
|
|
|
if line.len() > 0 {
|
|
|
|
|
|
if line.starts_with("#") {
|
|
|
|
|
|
if line.starts_with("#EXTINF:") {
|
|
|
|
|
|
found_header = true;
|
|
|
|
|
|
let slice = String::from(&line[8..]);
|
|
|
|
|
|
let split = slice.split(",");
|
|
|
|
|
|
let parts: Vec<&str> = split.collect();
|
|
|
|
|
|
if parts[0].len() > 0 {
|
|
|
|
|
|
duration = Some(String::from(parts[0]))
|
|
|
|
|
|
}
|
|
|
|
|
|
if parts[1].len() > 0 {
|
|
|
|
|
|
display = Some(String::from(parts[1]))
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
if ! found_header {
|
|
|
|
|
|
panic!("Misformatted m3u!!!");
|
|
|
|
|
|
}
|
|
|
|
|
|
let track = &line;
|
|
|
|
|
|
playlist_tracks.push(PlaylistTrack::new(duration.clone(), display.clone(), track));
|
|
|
|
|
|
duration = None;
|
|
|
|
|
|
display = None;
|
|
|
|
|
|
found_header = false;
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
});
|
|
@ -41,8 +89,7 @@ impl Playlist { |
|
|
let mut file = File::create(path)?;
|
|
|
let mut file = File::create(path)?;
|
|
|
file.write("#EXTM3U\n".as_bytes())?;
|
|
|
file.write("#EXTM3U\n".as_bytes())?;
|
|
|
for track in &*self.tracks {
|
|
|
for track in &*self.tracks {
|
|
|
file.write(track.as_bytes())?;
|
|
|
|
|
|
file.write("\n".as_bytes())?;
|
|
|
|
|
|
|
|
|
file.write(track.render().as_bytes())?;
|
|
|
}
|
|
|
}
|
|
|
Ok(())
|
|
|
Ok(())
|
|
|
}
|
|
|
}
|