mirror of
https://github.com/Dangoware/dmp-core.git
synced 2025-04-19 13:22:54 -05:00
added m3u8 to playlist function and fixed playlist to m3u8 function
This commit is contained in:
parent
7da0b1a1db
commit
a75081d4fc
3 changed files with 142 additions and 74 deletions
|
@ -69,10 +69,10 @@ impl ConfigLibraries {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_library(&self, uuid: &Uuid) -> Result<ConfigLibrary, ConfigError> {
|
pub fn get_library(&self, uuid: &Uuid) -> Result<ConfigLibrary, ConfigError> {
|
||||||
dbg!(&uuid);
|
|
||||||
for library in &self.libraries {
|
for library in &self.libraries {
|
||||||
|
// dbg!(&library.uuid, &uuid);
|
||||||
if &library.uuid == uuid {
|
if &library.uuid == uuid {
|
||||||
dbg!(&library.uuid);
|
|
||||||
return Ok(library.to_owned())
|
return Ok(library.to_owned())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -148,6 +148,13 @@ impl Config {
|
||||||
let config: Config = serde_json::from_str::<Config>(&bun)?;
|
let config: Config = serde_json::from_str::<Config>(&bun)?;
|
||||||
Ok(config)
|
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)]
|
#[derive(Error, Debug)]
|
||||||
|
@ -165,45 +172,42 @@ pub enum ConfigError {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
pub mod tests {
|
||||||
use std::{path::PathBuf, sync::{Arc, RwLock}};
|
use std::{path::PathBuf, sync::{Arc, RwLock}};
|
||||||
use crate::music_storage::library::MusicLibrary;
|
use crate::music_storage::library::MusicLibrary;
|
||||||
use super::{Config, ConfigLibraries, ConfigLibrary};
|
use super::{Config, ConfigLibraries, ConfigLibrary};
|
||||||
|
|
||||||
#[test]
|
pub fn new_config_lib() -> (Config, MusicLibrary) {
|
||||||
fn config_test() {
|
let lib = ConfigLibrary::new(PathBuf::from("test-config/library"), String::from("library"), None);
|
||||||
let lib_a = ConfigLibrary::new(PathBuf::from("test-config/library1"), String::from("library1"), None);
|
let mut config = Config {
|
||||||
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 {
|
|
||||||
path: PathBuf::from("test-config/config_test.json"),
|
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()
|
..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]
|
let mut lib = MusicLibrary::init(Arc::new(RwLock::from(config.clone())), dbg!(config.libraries.default_library)).unwrap();
|
||||||
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();
|
|
||||||
lib.scan_folder("test-config/music/").unwrap();
|
lib.scan_folder("test-config/music/").unwrap();
|
||||||
lib.save(config.clone()).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]
|
#[test]
|
||||||
|
|
|
@ -686,6 +686,7 @@ impl MusicLibrary {
|
||||||
false => {
|
false => {
|
||||||
// If the library does not exist, re-create it
|
// If the library does not exist, re-create it
|
||||||
let lib = MusicLibrary::new(String::new(), uuid);
|
let lib = MusicLibrary::new(String::new(), uuid);
|
||||||
|
|
||||||
write_file(&lib, path)?;
|
write_file(&lib, path)?;
|
||||||
lib
|
lib
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 chrono::Duration;
|
||||||
use uuid::Uuid;
|
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};
|
use m3u8_rs::{MediaPlaylist, MediaPlaylistType, MediaSegment, Playlist as List2};
|
||||||
|
|
||||||
|
@ -34,16 +35,14 @@ impl Playlist {
|
||||||
pub fn set_tracks(&mut self, tracks: Vec<Uuid>) {
|
pub fn set_tracks(&mut self, tracks: Vec<Uuid>) {
|
||||||
self.tracks = tracks;
|
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);
|
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;
|
let index = index as usize;
|
||||||
if (self.tracks.len() - 1) >= index {
|
if (self.tracks.len() - 1) >= index {
|
||||||
self.tracks.remove(index);
|
self.tracks.remove(index);
|
||||||
}
|
}
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
// pub fn get_index(&self, song_name: &str) -> Option<usize> {
|
// pub fn get_index(&self, song_name: &str) -> Option<usize> {
|
||||||
// let mut index = 0;
|
// let mut index = 0;
|
||||||
|
@ -58,26 +57,41 @@ impl Playlist {
|
||||||
// }
|
// }
|
||||||
// None
|
// None
|
||||||
// }
|
// }
|
||||||
pub fn contains_value(&self, tag: &Tag, value: &str) -> bool {
|
pub fn contains_value(&self, tag: &Tag, value: &String, lib: Arc<RwLock<MusicLibrary>>) -> bool {
|
||||||
&self.tracks.iter().for_each(|track| {
|
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
|
false
|
||||||
}
|
}
|
||||||
pub fn to_m3u8(&mut self, tracks: Vec<Song>) {
|
|
||||||
let seg = tracks
|
|
||||||
.iter()
|
|
||||||
.map({
|
|
||||||
|track| {
|
|
||||||
|
|
||||||
MediaSegment {
|
pub fn to_m3u8(&mut self, lib: Arc<RwLock<MusicLibrary>>, location: &str) -> Result<(), Box<dyn Error>> {
|
||||||
uri: track.location.to_string().into(),
|
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,
|
duration: track.duration.as_millis() as f32,
|
||||||
title: Some(track.tags.get_key_value(&Tag::Title).unwrap().1.into()),
|
title: track.tags.get_key_value(&Tag::Title).map(|tag| tag.1.into()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
}else { None }
|
||||||
|
}else { None }
|
||||||
|
}
|
||||||
|
)
|
||||||
.collect::<Vec<MediaSegment>>();
|
.collect::<Vec<MediaSegment>>();
|
||||||
|
|
||||||
let m3u8 = MediaPlaylist {
|
let m3u8 = MediaPlaylist {
|
||||||
|
@ -90,19 +104,21 @@ impl Playlist {
|
||||||
segments: seg.clone(),
|
segments: seg.clone(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
//TODO: change this to put in a real file path
|
|
||||||
let mut file = std::fs::OpenOptions::new()
|
let mut file = std::fs::OpenOptions::new()
|
||||||
.read(true)
|
.read(true)
|
||||||
.create(true)
|
.create(true)
|
||||||
|
.truncate(true)
|
||||||
.write(true)
|
.write(true)
|
||||||
.open("F:\\Dango Music Player\\playlist.m3u8")
|
.open(location)?;
|
||||||
.unwrap();
|
m3u8.write_to(&mut file)?;
|
||||||
m3u8.write_to(&mut file).unwrap();
|
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) {
|
let mut file = match File::open(path) {
|
||||||
Ok(file) => file,
|
Ok(file) => file,
|
||||||
Err(e) => return Err(e),
|
Err(e) => return Err(e.into()),
|
||||||
};
|
};
|
||||||
let mut bytes = Vec::new();
|
let mut bytes = Vec::new();
|
||||||
file.read_to_end(&mut bytes).unwrap();
|
file.read_to_end(&mut bytes).unwrap();
|
||||||
|
@ -110,18 +126,53 @@ impl Playlist {
|
||||||
let parsed = m3u8_rs::parse_playlist(&bytes);
|
let parsed = m3u8_rs::parse_playlist(&bytes);
|
||||||
|
|
||||||
let playlist = match parsed {
|
let playlist = match parsed {
|
||||||
Result::Ok((i, playlist)) => playlist,
|
Result::Ok((_, playlist)) => playlist,
|
||||||
Result::Err(e) => panic!("Parsing error: \n{}", e),
|
Result::Err(e) => panic!("Parsing error: \n{}", e),
|
||||||
};
|
};
|
||||||
|
|
||||||
match playlist {
|
match playlist {
|
||||||
List2::MasterPlaylist(_) => panic!(),
|
List2::MasterPlaylist(_) => Err("This is a Master Playlist!\nPlase input a Media Playlist".into()),
|
||||||
List2::MediaPlaylist(pl) => {
|
List2::MediaPlaylist(playlist_) => {
|
||||||
let values = pl.segments.iter().map(|seg| seg.uri.to_owned() ).collect::<Vec<String>>();
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
todo!()
|
playlist.set_tracks(uuids);
|
||||||
|
Ok(playlist)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fn title(&self) -> &String {
|
fn title(&self) -> &String {
|
||||||
&self.title
|
&self.title
|
||||||
|
@ -153,14 +204,26 @@ impl Default for Playlist {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[test]
|
#[cfg(test)]
|
||||||
// fn list_to_m3u8() {
|
mod test_super {
|
||||||
// let lib = ITunesLibrary::from_file(Path::new(
|
use super::*;
|
||||||
// "F:\\Music\\Mp3\\Music Main\\iTunes Music Library.xml",
|
use crate::config::config::tests::read_config_lib;
|
||||||
// ));
|
|
||||||
// let mut a = Playlist::new();
|
#[test]
|
||||||
// let c = lib.to_songs();
|
fn list_to_m3u8() {
|
||||||
// let mut b = c.iter().map(|song| song.to_owned()).collect::<Vec<Song>>();
|
let (_, lib) = read_config_lib();
|
||||||
// a.tracks.append(&mut b);
|
let mut playlist = Playlist::new();
|
||||||
// a.to_m3u8()
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue