mirror of
https://github.com/Dangoware/dmp-core.git
synced 2025-04-20 04:02:54 -05:00
moved Song creation functions to the Song
struct
This commit is contained in:
parent
f751ec6bbf
commit
0a68a12546
3 changed files with 285 additions and 248 deletions
|
@ -137,7 +137,11 @@ pub enum ConfigError {
|
||||||
#[error("No Library Found for {0}!")]
|
#[error("No Library Found for {0}!")]
|
||||||
NoConfigLibrary(Uuid),
|
NoConfigLibrary(Uuid),
|
||||||
#[error("There is no Default Library for this Config")]
|
#[error("There is no Default Library for this Config")]
|
||||||
NoDefaultLibrary
|
NoDefaultLibrary,
|
||||||
|
//TODO: do something about playlists
|
||||||
|
#[error("Please provide a better m3u8 Playlist")]
|
||||||
|
BadPlaylist,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -175,6 +175,225 @@ impl Song {
|
||||||
pub fn remove_tag(&mut self, target_key: &Tag) {
|
pub fn remove_tag(&mut self, target_key: &Tag) {
|
||||||
self.tags.remove(target_key);
|
self.tags.remove(target_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a `Song` from a song file
|
||||||
|
pub fn from_file(target_file: &Path) -> Result<Self, Box<dyn Error>> {
|
||||||
|
let normal_options = ParseOptions::new().parsing_mode(lofty::ParsingMode::Relaxed);
|
||||||
|
|
||||||
|
let blank_tag = &lofty::Tag::new(TagType::Id3v2);
|
||||||
|
let tagged_file: lofty::TaggedFile;
|
||||||
|
let mut duration = Duration::from_secs(0);
|
||||||
|
let tag = match Probe::open(target_file)?.options(normal_options).read() {
|
||||||
|
Ok(file) => {
|
||||||
|
tagged_file = file;
|
||||||
|
|
||||||
|
duration = tagged_file.properties().duration();
|
||||||
|
|
||||||
|
// Ensure the tags exist, if not, insert blank data
|
||||||
|
match tagged_file.primary_tag() {
|
||||||
|
Some(primary_tag) => primary_tag,
|
||||||
|
|
||||||
|
None => match tagged_file.first_tag() {
|
||||||
|
Some(first_tag) => first_tag,
|
||||||
|
None => blank_tag,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(_) => blank_tag,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut tags: BTreeMap<Tag, String> = BTreeMap::new();
|
||||||
|
for item in tag.items() {
|
||||||
|
let key = match item.key() {
|
||||||
|
ItemKey::TrackTitle => Tag::Title,
|
||||||
|
ItemKey::TrackNumber => Tag::Track,
|
||||||
|
ItemKey::TrackArtist => Tag::Artist,
|
||||||
|
ItemKey::AlbumArtist => Tag::AlbumArtist,
|
||||||
|
ItemKey::Genre => Tag::Genre,
|
||||||
|
ItemKey::Comment => Tag::Comment,
|
||||||
|
ItemKey::AlbumTitle => Tag::Album,
|
||||||
|
ItemKey::DiscNumber => Tag::Disk,
|
||||||
|
ItemKey::Unknown(unknown)
|
||||||
|
if unknown == "ACOUSTID_FINGERPRINT" || unknown == "Acoustid Fingerprint" =>
|
||||||
|
{
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ItemKey::Unknown(unknown) => Tag::Key(unknown.to_string()),
|
||||||
|
custom => Tag::Key(format!("{:?}", custom)),
|
||||||
|
};
|
||||||
|
|
||||||
|
let value = match item.value() {
|
||||||
|
ItemValue::Text(value) => value.clone(),
|
||||||
|
ItemValue::Locator(value) => value.clone(),
|
||||||
|
ItemValue::Binary(bin) => format!("BIN#{}", general_purpose::STANDARD.encode(bin)),
|
||||||
|
};
|
||||||
|
|
||||||
|
tags.insert(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get all the album artwork information from the file
|
||||||
|
let mut album_art: Vec<AlbumArt> = Vec::new();
|
||||||
|
for (i, _art) in tag.pictures().iter().enumerate() {
|
||||||
|
let new_art = AlbumArt::Embedded(i);
|
||||||
|
|
||||||
|
album_art.push(new_art)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find images around the music file that can be used
|
||||||
|
let mut found_images = find_images(target_file).unwrap();
|
||||||
|
album_art.append(&mut found_images);
|
||||||
|
|
||||||
|
// Get the format as a string
|
||||||
|
let format: Option<FileFormat> = match FileFormat::from_file(target_file) {
|
||||||
|
Ok(fmt) => Some(fmt),
|
||||||
|
Err(_) => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: Fix error handling
|
||||||
|
let binding = fs::canonicalize(target_file).unwrap();
|
||||||
|
|
||||||
|
let new_song = Song {
|
||||||
|
location: URI::Local(binding),
|
||||||
|
plays: 0,
|
||||||
|
skips: 0,
|
||||||
|
favorited: false,
|
||||||
|
rating: None,
|
||||||
|
format,
|
||||||
|
duration,
|
||||||
|
play_time: Duration::from_secs(0),
|
||||||
|
last_played: None,
|
||||||
|
date_added: Some(chrono::offset::Utc::now()),
|
||||||
|
date_modified: Some(chrono::offset::Utc::now()),
|
||||||
|
tags,
|
||||||
|
album_art,
|
||||||
|
};
|
||||||
|
Ok(new_song)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// creates a `Vec<Song>` from a cue file
|
||||||
|
|
||||||
|
pub fn from_cue(cuesheet: &Path) -> Result<(Vec<(Self, &PathBuf)>), Box<dyn Error>> {
|
||||||
|
let mut tracks = Vec::new();
|
||||||
|
|
||||||
|
let cue_data = parse_from_file(&cuesheet.to_string_lossy(), false).unwrap();
|
||||||
|
|
||||||
|
// Get album level information
|
||||||
|
let album_title = &cue_data.title;
|
||||||
|
let album_artist = &cue_data.performer;
|
||||||
|
|
||||||
|
let parent_dir = cuesheet.parent().expect("The file has no parent path??");
|
||||||
|
for file in cue_data.files.iter() {
|
||||||
|
let audio_location = &parent_dir.join(file.file.clone());
|
||||||
|
|
||||||
|
if !audio_location.exists() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let next_track = file.tracks.clone();
|
||||||
|
let mut next_track = next_track.iter().skip(1);
|
||||||
|
for (i, track) in file.tracks.iter().enumerate() {
|
||||||
|
// Get the track timing information
|
||||||
|
let pregap = match track.pregap {
|
||||||
|
Some(pregap) => pregap,
|
||||||
|
None => Duration::from_secs(0),
|
||||||
|
};
|
||||||
|
let postgap = match track.postgap {
|
||||||
|
Some(postgap) => postgap,
|
||||||
|
None => Duration::from_secs(0),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut start;
|
||||||
|
if track.indices.len() > 1 {
|
||||||
|
start = track.indices[1].1;
|
||||||
|
} else {
|
||||||
|
start = track.indices[0].1;
|
||||||
|
}
|
||||||
|
if !start.is_zero() {
|
||||||
|
start -= pregap;
|
||||||
|
}
|
||||||
|
|
||||||
|
let duration = match next_track.next() {
|
||||||
|
Some(future) => match future.indices.first() {
|
||||||
|
Some(val) => val.1 - start,
|
||||||
|
None => Duration::from_secs(0),
|
||||||
|
},
|
||||||
|
None => match lofty::read_from_path(audio_location) {
|
||||||
|
Ok(tagged_file) => tagged_file.properties().duration() - start,
|
||||||
|
|
||||||
|
Err(_) => match Probe::open(audio_location)?.read() {
|
||||||
|
Ok(tagged_file) => tagged_file.properties().duration() - start,
|
||||||
|
|
||||||
|
Err(_) => Duration::from_secs(0),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let end = start + duration + postgap;
|
||||||
|
|
||||||
|
// Get the format as a string
|
||||||
|
let format: Option<FileFormat> = match FileFormat::from_file(audio_location) {
|
||||||
|
Ok(fmt) => Some(fmt),
|
||||||
|
Err(_) => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get some useful tags
|
||||||
|
let mut tags: BTreeMap<Tag, String> = BTreeMap::new();
|
||||||
|
match album_title {
|
||||||
|
Some(title) => {
|
||||||
|
tags.insert(Tag::Album, title.clone());
|
||||||
|
}
|
||||||
|
None => (),
|
||||||
|
}
|
||||||
|
match album_artist {
|
||||||
|
Some(artist) => {
|
||||||
|
tags.insert(Tag::Artist, artist.clone());
|
||||||
|
}
|
||||||
|
None => (),
|
||||||
|
}
|
||||||
|
tags.insert(Tag::Track, track.no.parse().unwrap_or((i + 1).to_string()));
|
||||||
|
match track.title.clone() {
|
||||||
|
Some(title) => tags.insert(Tag::Title, title),
|
||||||
|
None => match track.isrc.clone() {
|
||||||
|
Some(title) => tags.insert(Tag::Title, title),
|
||||||
|
None => {
|
||||||
|
let namestr = format!("{} - {}", i, file.file.clone());
|
||||||
|
tags.insert(Tag::Title, namestr)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
match track.performer.clone() {
|
||||||
|
Some(artist) => tags.insert(Tag::Artist, artist),
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Find images around the music file that can be used
|
||||||
|
let album_art = find_images(&audio_location.to_path_buf()).unwrap();
|
||||||
|
|
||||||
|
let new_song = Song {
|
||||||
|
location: URI::Cue {
|
||||||
|
location: audio_location.clone(),
|
||||||
|
index: i,
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
plays: 0,
|
||||||
|
skips: 0,
|
||||||
|
favorited: false,
|
||||||
|
rating: None,
|
||||||
|
format,
|
||||||
|
duration,
|
||||||
|
play_time: Duration::from_secs(0),
|
||||||
|
last_played: None,
|
||||||
|
date_added: Some(chrono::offset::Utc::now()),
|
||||||
|
date_modified: Some(chrono::offset::Utc::now()),
|
||||||
|
tags,
|
||||||
|
album_art,
|
||||||
|
};
|
||||||
|
tracks.push((new_song, audio_location));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok((tracks))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
|
@ -499,97 +718,8 @@ impl MusicLibrary {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_file(&mut self, target_file: &Path) -> Result<(), Box<dyn Error>> {
|
pub fn add_file(&mut self, target_file: &Path) -> Result<(), Box<dyn Error>> {
|
||||||
let normal_options = ParseOptions::new().parsing_mode(lofty::ParsingMode::Relaxed);
|
|
||||||
|
|
||||||
let blank_tag = &lofty::Tag::new(TagType::Id3v2);
|
|
||||||
let tagged_file: lofty::TaggedFile;
|
|
||||||
let mut duration = Duration::from_secs(0);
|
|
||||||
let tag = match Probe::open(target_file)?.options(normal_options).read() {
|
|
||||||
Ok(file) => {
|
|
||||||
tagged_file = file;
|
|
||||||
|
|
||||||
duration = tagged_file.properties().duration();
|
|
||||||
|
|
||||||
// Ensure the tags exist, if not, insert blank data
|
|
||||||
match tagged_file.primary_tag() {
|
|
||||||
Some(primary_tag) => primary_tag,
|
|
||||||
|
|
||||||
None => match tagged_file.first_tag() {
|
|
||||||
Some(first_tag) => first_tag,
|
|
||||||
None => blank_tag,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Err(_) => blank_tag,
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut tags: BTreeMap<Tag, String> = BTreeMap::new();
|
|
||||||
for item in tag.items() {
|
|
||||||
let key = match item.key() {
|
|
||||||
ItemKey::TrackTitle => Tag::Title,
|
|
||||||
ItemKey::TrackNumber => Tag::Track,
|
|
||||||
ItemKey::TrackArtist => Tag::Artist,
|
|
||||||
ItemKey::AlbumArtist => Tag::AlbumArtist,
|
|
||||||
ItemKey::Genre => Tag::Genre,
|
|
||||||
ItemKey::Comment => Tag::Comment,
|
|
||||||
ItemKey::AlbumTitle => Tag::Album,
|
|
||||||
ItemKey::DiscNumber => Tag::Disk,
|
|
||||||
ItemKey::Unknown(unknown)
|
|
||||||
if unknown == "ACOUSTID_FINGERPRINT" || unknown == "Acoustid Fingerprint" =>
|
|
||||||
{
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
ItemKey::Unknown(unknown) => Tag::Key(unknown.to_string()),
|
|
||||||
custom => Tag::Key(format!("{:?}", custom)),
|
|
||||||
};
|
|
||||||
|
|
||||||
let value = match item.value() {
|
|
||||||
ItemValue::Text(value) => value.clone(),
|
|
||||||
ItemValue::Locator(value) => value.clone(),
|
|
||||||
ItemValue::Binary(bin) => format!("BIN#{}", general_purpose::STANDARD.encode(bin)),
|
|
||||||
};
|
|
||||||
|
|
||||||
tags.insert(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get all the album artwork information from the file
|
|
||||||
let mut album_art: Vec<AlbumArt> = Vec::new();
|
|
||||||
for (i, _art) in tag.pictures().iter().enumerate() {
|
|
||||||
let new_art = AlbumArt::Embedded(i);
|
|
||||||
|
|
||||||
album_art.push(new_art)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find images around the music file that can be used
|
|
||||||
let mut found_images = find_images(target_file).unwrap();
|
|
||||||
album_art.append(&mut found_images);
|
|
||||||
|
|
||||||
// Get the format as a string
|
|
||||||
let format: Option<FileFormat> = match FileFormat::from_file(target_file) {
|
|
||||||
Ok(fmt) => Some(fmt),
|
|
||||||
Err(_) => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: Fix error handling
|
|
||||||
let binding = fs::canonicalize(target_file).unwrap();
|
|
||||||
|
|
||||||
let new_song = Song {
|
|
||||||
location: URI::Local(binding),
|
|
||||||
plays: 0,
|
|
||||||
skips: 0,
|
|
||||||
favorited: false,
|
|
||||||
rating: None,
|
|
||||||
format,
|
|
||||||
duration,
|
|
||||||
play_time: Duration::from_secs(0),
|
|
||||||
last_played: None,
|
|
||||||
date_added: Some(chrono::offset::Utc::now()),
|
|
||||||
date_modified: Some(chrono::offset::Utc::now()),
|
|
||||||
tags,
|
|
||||||
album_art,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
let new_song = Song::from_file(target_file)?;
|
||||||
match self.add_song(new_song) {
|
match self.add_song(new_song) {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
|
@ -601,137 +731,23 @@ impl MusicLibrary {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_cuesheet(&mut self, cuesheet: &Path) -> Result<i32, Box<dyn Error>> {
|
pub fn add_cuesheet(&mut self, cuesheet: &Path) -> Result<i32, Box<dyn Error>> {
|
||||||
let mut tracks_added = 0;
|
let tracks = Song::from_cue(cuesheet)?;
|
||||||
|
let mut tracks_added = tracks.len() as i32;
|
||||||
|
|
||||||
let cue_data = parse_from_file(&cuesheet.to_string_lossy(), false).unwrap();
|
|
||||||
|
|
||||||
// Get album level information
|
|
||||||
let album_title = &cue_data.title;
|
|
||||||
let album_artist = &cue_data.performer;
|
|
||||||
|
|
||||||
let parent_dir = cuesheet.parent().expect("The file has no parent path??");
|
|
||||||
for file in cue_data.files.iter() {
|
|
||||||
let audio_location = &parent_dir.join(file.file.clone());
|
|
||||||
|
|
||||||
if !audio_location.exists() {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
for (new_song, location) in tracks {
|
||||||
// Try to remove the original audio file from the db if it exists
|
// Try to remove the original audio file from the db if it exists
|
||||||
if self.remove_uri(&URI::Local(audio_location.clone())).is_ok() {
|
if self.remove_uri(&URI::Local(location.clone())).is_ok() {
|
||||||
tracks_added -= 1
|
tracks_added -= 1
|
||||||
}
|
}
|
||||||
|
|
||||||
let next_track = file.tracks.clone();
|
|
||||||
let mut next_track = next_track.iter().skip(1);
|
|
||||||
for (i, track) in file.tracks.iter().enumerate() {
|
|
||||||
// Get the track timing information
|
|
||||||
let pregap = match track.pregap {
|
|
||||||
Some(pregap) => pregap,
|
|
||||||
None => Duration::from_secs(0),
|
|
||||||
};
|
|
||||||
let postgap = match track.postgap {
|
|
||||||
Some(postgap) => postgap,
|
|
||||||
None => Duration::from_secs(0),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut start;
|
|
||||||
if track.indices.len() > 1 {
|
|
||||||
start = track.indices[1].1;
|
|
||||||
} else {
|
|
||||||
start = track.indices[0].1;
|
|
||||||
}
|
|
||||||
if !start.is_zero() {
|
|
||||||
start -= pregap;
|
|
||||||
}
|
|
||||||
|
|
||||||
let duration = match next_track.next() {
|
|
||||||
Some(future) => match future.indices.first() {
|
|
||||||
Some(val) => val.1 - start,
|
|
||||||
None => Duration::from_secs(0),
|
|
||||||
},
|
|
||||||
None => match lofty::read_from_path(audio_location) {
|
|
||||||
Ok(tagged_file) => tagged_file.properties().duration() - start,
|
|
||||||
|
|
||||||
Err(_) => match Probe::open(audio_location)?.read() {
|
|
||||||
Ok(tagged_file) => tagged_file.properties().duration() - start,
|
|
||||||
|
|
||||||
Err(_) => Duration::from_secs(0),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
let end = start + duration + postgap;
|
|
||||||
|
|
||||||
// Get the format as a string
|
|
||||||
let format: Option<FileFormat> = match FileFormat::from_file(audio_location) {
|
|
||||||
Ok(fmt) => Some(fmt),
|
|
||||||
Err(_) => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get some useful tags
|
|
||||||
let mut tags: BTreeMap<Tag, String> = BTreeMap::new();
|
|
||||||
match album_title {
|
|
||||||
Some(title) => {
|
|
||||||
tags.insert(Tag::Album, title.clone());
|
|
||||||
}
|
|
||||||
None => (),
|
|
||||||
}
|
|
||||||
match album_artist {
|
|
||||||
Some(artist) => {
|
|
||||||
tags.insert(Tag::Artist, artist.clone());
|
|
||||||
}
|
|
||||||
None => (),
|
|
||||||
}
|
|
||||||
tags.insert(Tag::Track, track.no.parse().unwrap_or((i + 1).to_string()));
|
|
||||||
match track.title.clone() {
|
|
||||||
Some(title) => tags.insert(Tag::Title, title),
|
|
||||||
None => match track.isrc.clone() {
|
|
||||||
Some(title) => tags.insert(Tag::Title, title),
|
|
||||||
None => {
|
|
||||||
let namestr = format!("{} - {}", i, file.file.clone());
|
|
||||||
tags.insert(Tag::Title, namestr)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
match track.performer.clone() {
|
|
||||||
Some(artist) => tags.insert(Tag::Artist, artist),
|
|
||||||
None => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Find images around the music file that can be used
|
|
||||||
let album_art = find_images(&audio_location.to_path_buf()).unwrap();
|
|
||||||
|
|
||||||
let new_song = Song {
|
|
||||||
location: URI::Cue {
|
|
||||||
location: audio_location.clone(),
|
|
||||||
index: i,
|
|
||||||
start,
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
plays: 0,
|
|
||||||
skips: 0,
|
|
||||||
favorited: false,
|
|
||||||
rating: None,
|
|
||||||
format,
|
|
||||||
duration,
|
|
||||||
play_time: Duration::from_secs(0),
|
|
||||||
last_played: None,
|
|
||||||
date_added: Some(chrono::offset::Utc::now()),
|
|
||||||
date_modified: Some(chrono::offset::Utc::now()),
|
|
||||||
tags,
|
|
||||||
album_art,
|
|
||||||
};
|
|
||||||
|
|
||||||
match self.add_song(new_song) {
|
match self.add_song(new_song) {
|
||||||
Ok(_) => tracks_added += 1,
|
Ok(_) => {},
|
||||||
Err(_error) => {
|
Err(_error) => {
|
||||||
//println!("{}", _error);
|
//println!("{}", _error);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Ok(tracks_added)
|
Ok(tracks_added)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
use std::path::Path;
|
use std::{fs::File, path::{Path, PathBuf}, io::{Read, Error}};
|
||||||
|
|
||||||
|
use bincode::config;
|
||||||
use chrono::Duration;
|
use chrono::Duration;
|
||||||
use walkdir::Error;
|
use uuid::Uuid;
|
||||||
|
// use walkdir::Error;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
library::{AlbumArt, Song, Tag},
|
library::{AlbumArt, Song, Tag},
|
||||||
|
@ -11,14 +13,14 @@ use super::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use m3u8_rs::{MediaPlaylist, MediaPlaylistType, MediaSegment};
|
use m3u8_rs::{MediaPlaylist, MediaPlaylistType, MediaSegment, Playlist as List2, MasterPlaylist};
|
||||||
// use nom::IResult;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Playlist<'a> {
|
pub struct Playlist<'a> {
|
||||||
title: String,
|
title: String,
|
||||||
cover: Option<&'a AlbumArt>,
|
cover: Option<&'a AlbumArt>,
|
||||||
tracks: Vec<Song>,
|
tracks: Vec<Uuid>,
|
||||||
play_count: i32,
|
play_count: i32,
|
||||||
play_time: Duration,
|
play_time: Duration,
|
||||||
}
|
}
|
||||||
|
@ -32,43 +34,37 @@ impl<'a> Playlist<'a> {
|
||||||
pub fn play_time(&self) -> chrono::Duration {
|
pub fn play_time(&self) -> chrono::Duration {
|
||||||
self.play_time
|
self.play_time
|
||||||
}
|
}
|
||||||
pub fn set_tracks(&mut self, songs: Vec<Song>) -> Result<(), Error> {
|
pub fn set_tracks(&mut self, tracks: Vec<Uuid>) {
|
||||||
self.tracks = songs;
|
self.tracks = songs;
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
pub fn add_track(&mut self, song: Song) -> Result<(), Error> {
|
pub fn add_track(&mut self, track: Uuid) -> Result<(), Error> {
|
||||||
self.tracks.push(song);
|
self.tracks.push(song);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
pub fn remove_track(&mut self, index: i32) -> Result<(), Error> {
|
pub fn remove_track(&mut self, index: i32) -> Result<(), Error> {
|
||||||
let bun: usize = index as usize;
|
let index = index as usize;
|
||||||
let mut name = String::new();
|
if (self.tracks.len() - 1) >= index {
|
||||||
if self.tracks.len() >= bun {
|
self.tracks.remove(index);
|
||||||
name = String::from(self.tracks[bun].tags.get_key_value(&Tag::Title).unwrap().1);
|
|
||||||
self.tracks.remove(bun);
|
|
||||||
}
|
}
|
||||||
dbg!(name);
|
|
||||||
Ok(())
|
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;
|
||||||
if self.contains_value(&Tag::Title, song_name) {
|
// if self.contains_value(&Tag::Title, song_name) {
|
||||||
for track in &self.tracks {
|
// for track in &self.tracks {
|
||||||
index += 1;
|
// index += 1;
|
||||||
if song_name == track.tags.get_key_value(&Tag::Title).unwrap().1 {
|
// if song_name == track.tags.get_key_value(&Tag::Title).unwrap().1 {
|
||||||
dbg!("Index gotted! ", index);
|
// dbg!("Index gotted! ", index);
|
||||||
return Some(index);
|
// return Some(index);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
None
|
// None
|
||||||
}
|
// }
|
||||||
pub fn contains_value(&self, tag: &Tag, value: &str) -> bool {
|
pub fn contains_value(&self, tag: &Tag, value: &str) -> bool {
|
||||||
for track in &self.tracks {
|
&self.tracks.iter().for_each(|track| {
|
||||||
if value == track.tags.get_key_value(tag).unwrap().1 {
|
|
||||||
return true;
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
pub fn to_m3u8(&mut self) {
|
pub fn to_m3u8(&mut self) {
|
||||||
|
@ -104,7 +100,28 @@ impl<'a> Playlist<'a> {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
m3u8.write_to(&mut file).unwrap();
|
m3u8.write_to(&mut file).unwrap();
|
||||||
}
|
}
|
||||||
pub fn from_m3u8(file: std::fs::File) -> Playlist<'a> {
|
pub fn from_m3u8(path: &str) -> Result<Playlist<'a>, Error> {
|
||||||
|
let mut file = match File::open(path) {
|
||||||
|
Ok(file) => file,
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
};
|
||||||
|
let mut bytes = Vec::new();
|
||||||
|
file.read_to_end(&mut bytes).unwrap();
|
||||||
|
|
||||||
|
let parsed = m3u8_rs::parse_playlist(&bytes);
|
||||||
|
|
||||||
|
let playlist = match parsed {
|
||||||
|
Result::Ok((i, 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>>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue