diff --git a/src/config/config.rs b/src/config/config.rs index 76c59cc..5a209ae 100644 --- a/src/config/config.rs +++ b/src/config/config.rs @@ -69,10 +69,10 @@ impl ConfigLibraries { } pub fn get_library(&self, uuid: &Uuid) -> Result { - dbg!(&uuid); + for library in &self.libraries { + // dbg!(&library.uuid, &uuid); if &library.uuid == uuid { - dbg!(&library.uuid); return Ok(library.to_owned()) } } @@ -148,6 +148,13 @@ impl Config { let config: Config = serde_json::from_str::(&bun)?; Ok(config) } + + pub fn push_library(&mut self, lib: ConfigLibrary) { + if self.libraries.libraries.is_empty() { + self.libraries.default_library = lib.uuid; + } + self.libraries.libraries.push(lib); + } } #[derive(Error, Debug)] @@ -165,45 +172,42 @@ pub enum ConfigError { } #[cfg(test)] -mod tests { +pub mod tests { use std::{path::PathBuf, sync::{Arc, RwLock}}; use crate::music_storage::library::MusicLibrary; use super::{Config, ConfigLibraries, ConfigLibrary}; - #[test] - fn config_test() { - let lib_a = ConfigLibrary::new(PathBuf::from("test-config/library1"), String::from("library1"), None); - let lib_b = ConfigLibrary::new(PathBuf::from("test-config/library2"), String::from("library2"), None); - let lib_c = ConfigLibrary::new(PathBuf::from("test-config/library3"), String::from("library3"), None); - let config = Config { + pub fn new_config_lib() -> (Config, MusicLibrary) { + let lib = ConfigLibrary::new(PathBuf::from("test-config/library"), String::from("library"), None); + let mut config = Config { path: PathBuf::from("test-config/config_test.json"), - libraries: ConfigLibraries { - libraries: vec![ - lib_a.clone(), - lib_b.clone(), - lib_c.clone(), - ], - ..Default::default() - }, ..Default::default() }; - config.write_file(); - let arc = Arc::new(RwLock::from(config)); - MusicLibrary::init(arc.clone(), lib_a.uuid).unwrap(); - MusicLibrary::init(arc.clone(), lib_b.uuid).unwrap(); - MusicLibrary::init(arc.clone(), lib_c.uuid).unwrap(); - } + config.push_library(lib); + config.write_file().unwrap(); - #[test] - fn test2() { - let config = Config::read_file(PathBuf::from("test-config/config_test.json")).unwrap(); - let uuid = config.libraries.get_default().unwrap().uuid; - let mut lib = MusicLibrary::init(Arc::new(RwLock::from(config.clone())), uuid).unwrap(); + let mut lib = MusicLibrary::init(Arc::new(RwLock::from(config.clone())), dbg!(config.libraries.default_library)).unwrap(); lib.scan_folder("test-config/music/").unwrap(); lib.save(config.clone()).unwrap(); - dbg!(&lib); - dbg!(&config); + + (config, lib) + } + + pub fn read_config_lib() -> (Config, MusicLibrary) { + let config = Config::read_file(PathBuf::from("test-config/config_test.json")).unwrap(); + + // dbg!(&config); + + let mut lib = MusicLibrary::init(Arc::new(RwLock::from(config.clone())), config.libraries.get_default().unwrap().uuid).unwrap(); + + + lib.scan_folder("test-config/music/").unwrap(); + + lib.save(config.clone()).unwrap(); + + + (config, lib) } #[test] diff --git a/src/music_storage/library.rs b/src/music_storage/library.rs index 1afc991..22452a9 100644 --- a/src/music_storage/library.rs +++ b/src/music_storage/library.rs @@ -686,6 +686,7 @@ impl MusicLibrary { false => { // If the library does not exist, re-create it let lib = MusicLibrary::new(String::new(), uuid); + write_file(&lib, path)?; lib } diff --git a/src/music_storage/playlist.rs b/src/music_storage/playlist.rs index 783a293..bd40b6a 100644 --- a/src/music_storage/playlist.rs +++ b/src/music_storage/playlist.rs @@ -1,8 +1,9 @@ -use std::{fs::File, io::{Read, Error}}; +use std::{fs::File, io::Read, path:: PathBuf, sync::{Arc, RwLock}}; +use std::error::Error; use chrono::Duration; use uuid::Uuid; -use super::library::{AlbumArt, Song, Tag}; +use super::library::{AlbumArt, MusicLibrary, Song, Tag, URI}; use m3u8_rs::{MediaPlaylist, MediaPlaylistType, MediaSegment, Playlist as List2}; @@ -34,16 +35,14 @@ impl Playlist { pub fn set_tracks(&mut self, tracks: Vec) { self.tracks = tracks; } - pub fn add_track(&mut self, track: Uuid) -> Result<(), Error> { + pub fn add_track(&mut self, track: Uuid) { self.tracks.push(track); - Ok(()) } - pub fn remove_track(&mut self, index: i32) -> Result<(), Error> { + pub fn remove_track(&mut self, index: i32) { let index = index as usize; if (self.tracks.len() - 1) >= index { self.tracks.remove(index); } - Ok(()) } // pub fn get_index(&self, song_name: &str) -> Option { // let mut index = 0; @@ -58,26 +57,41 @@ impl Playlist { // } // None // } - pub fn contains_value(&self, tag: &Tag, value: &str) -> bool { - &self.tracks.iter().for_each(|track| { + pub fn contains_value(&self, tag: &Tag, value: &String, lib: Arc>) -> bool { + let lib = lib.read().unwrap(); + let items = match lib.query_tracks(value, &vec![tag.to_owned()], &vec![tag.to_owned()]) { + Some(e) => e, + None => return false + }; + + for item in items { + for uuid in &self.tracks { + if uuid == &item.uuid { + return true; + } + } + } - }); false } - pub fn to_m3u8(&mut self, tracks: Vec) { - let seg = tracks - .iter() - .map({ - |track| { - MediaSegment { - uri: track.location.to_string().into(), - duration: track.duration.as_millis() as f32, - title: Some(track.tags.get_key_value(&Tag::Title).unwrap().1.into()), - ..Default::default() - } + pub fn to_m3u8(&mut self, lib: Arc>, location: &str) -> Result<(), Box> { + let lib = lib.read().unwrap(); + let seg = self.tracks + .iter() + .filter_map( |uuid| { + if let Some((track, _)) = lib.query_uuid(uuid) { + if let URI::Local(_) = track.location { + Some(MediaSegment { + uri: track.location.to_string(), + duration: track.duration.as_millis() as f32, + title: track.tags.get_key_value(&Tag::Title).map(|tag| tag.1.into()), + ..Default::default() + }) + }else { None } + }else { None } } - }) + ) .collect::>(); let m3u8 = MediaPlaylist { @@ -90,19 +104,21 @@ impl Playlist { segments: seg.clone(), ..Default::default() }; - //TODO: change this to put in a real file path + let mut file = std::fs::OpenOptions::new() .read(true) .create(true) + .truncate(true) .write(true) - .open("F:\\Dango Music Player\\playlist.m3u8") - .unwrap(); - m3u8.write_to(&mut file).unwrap(); + .open(location)?; + m3u8.write_to(&mut file)?; + Ok(()) } - pub fn from_m3u8(path: &str) -> Result { + + pub fn from_m3u8(path: &str, lib: Arc>) -> Result> { let mut file = match File::open(path) { Ok(file) => file, - Err(e) => return Err(e), + Err(e) => return Err(e.into()), }; let mut bytes = Vec::new(); file.read_to_end(&mut bytes).unwrap(); @@ -110,18 +126,53 @@ impl Playlist { let parsed = m3u8_rs::parse_playlist(&bytes); let playlist = match parsed { - Result::Ok((i, playlist)) => playlist, + Result::Ok((_, playlist)) => playlist, Result::Err(e) => panic!("Parsing error: \n{}", e), }; match playlist { - List2::MasterPlaylist(_) => panic!(), - List2::MediaPlaylist(pl) => { - let values = pl.segments.iter().map(|seg| seg.uri.to_owned() ).collect::>(); + List2::MasterPlaylist(_) => Err("This is a Master Playlist!\nPlase input a Media Playlist".into()), + List2::MediaPlaylist(playlist_) => { + let mut uuids = Vec::new(); + for seg in playlist_.segments { + let path_ = PathBuf::from(seg.uri.to_owned()); + let mut lib = lib.write().unwrap(); + + let uuid = if let Some((song, _)) = lib.query_uri(&URI::Local(path_.clone())) { + song.uuid + }else { + let song_ = Song::from_file(&path_)?; + let uuid = song_.uuid.to_owned(); + lib.add_song(song_)?; + uuid + }; + uuids.push(uuid); + } + let mut playlist = Playlist::new(); + + #[cfg(target_family = "windows")] + { + playlist.title = path.split("\\") + .last() + .unwrap_or_default() + .strip_suffix(".m3u8") + .unwrap_or_default() + .to_string(); + } + #[cfg(target_family = "unix")] + { + playlist.title = path.split("/") + .last() + .unwrap_or_default() + .strip_suffix(".m3u8") + .unwrap_or_default() + .to_string(); + } + + playlist.set_tracks(uuids); + Ok(playlist) } } - - todo!() } fn title(&self) -> &String { &self.title @@ -153,14 +204,26 @@ impl Default for Playlist { } } -// #[test] -// fn list_to_m3u8() { -// let lib = ITunesLibrary::from_file(Path::new( -// "F:\\Music\\Mp3\\Music Main\\iTunes Music Library.xml", -// )); -// let mut a = Playlist::new(); -// let c = lib.to_songs(); -// let mut b = c.iter().map(|song| song.to_owned()).collect::>(); -// a.tracks.append(&mut b); -// a.to_m3u8() -// } +#[cfg(test)] +mod test_super { + use super::*; + use crate::config::config::tests::read_config_lib; + + #[test] + fn list_to_m3u8() { + let (_, lib) = read_config_lib(); + let mut playlist = Playlist::new(); + let tracks = lib.library.iter().map(|track| track.uuid ).collect(); + playlist.set_tracks(tracks); + + _ = playlist.to_m3u8(Arc::new(RwLock::from(lib)), ".\\test-config\\playlists\\playlist.m3u8"); + } + + #[test] + fn m3u8_to_list() { + let (_, lib) = read_config_lib(); + let arc = Arc::new(RwLock::from(lib)); + let playlist = Playlist::from_m3u8(".\\test-config\\playlists\\playlist.m3u8", arc).unwrap(); + dbg!(playlist); + } +}