You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

95 lines
3.0 KiB

  1. use std::fs::File;
  2. use std::io::{self, BufRead, Write};
  3. use std::path::Path;
  4. use std::string::String;
  5. fn read_lines<P>(path: P) -> io::Result<io::Lines<io::BufReader<File>>>
  6. where P: AsRef<Path>, {
  7. let file = File::open(path)?;
  8. Ok(io::BufReader::new(file).lines())
  9. }
  10. #[derive(Debug)]
  11. pub struct PlaylistTrack {
  12. pub duration: String,
  13. pub display: String,
  14. pub track: String
  15. }
  16. impl PlaylistTrack {
  17. pub fn new(duration: Option<String>, display: Option<String>, track: &str) -> PlaylistTrack {
  18. PlaylistTrack {
  19. duration: duration.unwrap_or(String::from("")),
  20. display: display.unwrap_or(String::from("")),
  21. track: String::from(track)
  22. }
  23. }
  24. pub fn render(&self) -> String {
  25. format!("#EXTINFO:{},{}\n{}\n", self.duration, self.display, self.track)
  26. }
  27. }
  28. #[derive(Debug)]
  29. pub struct Playlist {
  30. pub path: String,
  31. pub tracks: Box<Vec<PlaylistTrack>>
  32. }
  33. impl Playlist {
  34. pub fn new(path: &str, tracks: Vec<PlaylistTrack>) -> Playlist {
  35. Playlist {
  36. path: String::from(path),
  37. tracks: Box::new(tracks)
  38. }
  39. }
  40. pub fn read(path: &str) -> Result<Playlist, io::Error> {
  41. let mut playlist_tracks: Vec<PlaylistTrack> = Vec::new();
  42. let lines = read_lines(path)?;
  43. let mut found_header = false;
  44. let mut duration: Option<String> = None;
  45. let mut display: Option<String> = None;
  46. lines.for_each(|read_line| {
  47. if read_line.is_ok() {
  48. let line = read_line.unwrap();
  49. if line.len() > 0 {
  50. if line.starts_with("#") {
  51. if line.starts_with("#EXTINF:") {
  52. found_header = true;
  53. let slice = String::from(&line[8..]);
  54. let split = slice.split(",");
  55. let parts: Vec<&str> = split.collect();
  56. if parts[0].len() > 0 {
  57. duration = Some(String::from(parts[0]))
  58. }
  59. if parts[1].len() > 0 {
  60. display = Some(String::from(parts[1]))
  61. }
  62. }
  63. } else {
  64. if ! found_header {
  65. panic!("Misformatted m3u!!!");
  66. }
  67. let track = &line;
  68. playlist_tracks.push(PlaylistTrack::new(duration.clone(), display.clone(), track));
  69. duration = None;
  70. display = None;
  71. found_header = false;
  72. }
  73. }
  74. }
  75. });
  76. Ok(Playlist::new(path, playlist_tracks))
  77. }
  78. pub fn write(&self, path: &str) -> Result<(), io::Error> {
  79. let mut file = File::create(path)?;
  80. file.write("#EXTM3U\n".as_bytes())?;
  81. for track in &*self.tracks {
  82. file.write(track.render().as_bytes())?;
  83. }
  84. Ok(())
  85. }
  86. }