added m3u8 to playlist function and fixed playlist to m3u8 function

This commit is contained in:
MrDulfin 2024-04-05 02:09:15 -04:00
parent 7da0b1a1db
commit a75081d4fc
3 changed files with 142 additions and 74 deletions

View file

@ -69,10 +69,10 @@ impl ConfigLibraries {
}
pub fn get_library(&self, uuid: &Uuid) -> Result<ConfigLibrary, ConfigError> {
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::<Config>(&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]

View file

@ -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
}

View file

@ -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<Uuid>) {
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<usize> {
// 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<RwLock<MusicLibrary>>) -> 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<Song>) {
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<RwLock<MusicLibrary>>, location: &str) -> Result<(), Box<dyn Error>> {
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::<Vec<MediaSegment>>();
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<Playlist, Error> {
pub fn from_m3u8(path: &str, lib: Arc<RwLock<MusicLibrary>>) -> Result<Playlist, Box<dyn Error>> {
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::<Vec<String>>();
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::<Vec<Song>>();
// 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);
}
}