Work in progress optimizations

This commit is contained in:
G2-Games 2023-11-06 16:41:28 -06:00
parent 2e0ce48506
commit f00df67844
2 changed files with 110 additions and 103 deletions

View file

@ -12,12 +12,12 @@ keywords = ["audio", "music"]
categories = ["multimedia::audio"] categories = ["multimedia::audio"]
[dependencies] [dependencies]
file-format = { version = "0.17.3", features = ["reader", "serde"] } file-format = { version = "0.22.0", features = ["reader-asf", "reader-ebml", "reader-mp4", "reader-rm", "reader-txt", "reader-xml", "serde"] }
lofty = "0.16.1" lofty = "0.16.1"
serde = { version = "1.0.164", features = ["derive"] } serde = { version = "1.0.191", features = ["derive"] }
time = "0.3.22" time = "0.3.22"
toml = "0.7.5" toml = "0.7.5"
walkdir = "2.3.3" walkdir = "2.4.0"
cpal = "0.15.2" cpal = "0.15.2"
heapless = "0.7.16" heapless = "0.7.16"
rb = "0.4.1" rb = "0.4.1"
@ -37,8 +37,6 @@ unidecode = "0.3.0"
rayon = "1.8.0" rayon = "1.8.0"
log = "0.4" log = "0.4"
pretty_env_logger = "0.4" pretty_env_logger = "0.4"
cue = "2.0.0"
base64 = "0.21.5" base64 = "0.21.5"
zip = "0.6.6"
flate2 = "1.0.28"
snap = "1.1.0" snap = "1.1.0"
rcue = "0.1.3"

View file

@ -8,7 +8,7 @@ use std::error::Error;
use std::ops::ControlFlow::{Break, Continue}; use std::ops::ControlFlow::{Break, Continue};
// Files // Files
use cue::cd::CD; use rcue::parser::parse_from_file;
use file_format::{FileFormat, Kind}; use file_format::{FileFormat, Kind};
use walkdir::WalkDir; use walkdir::WalkDir;
use lofty::{AudioFile, ItemKey, ItemValue, Probe, TagType, TaggedFileExt}; use lofty::{AudioFile, ItemKey, ItemValue, Probe, TagType, TaggedFileExt};
@ -33,6 +33,15 @@ pub enum AlbumArt {
External(URI), External(URI),
} }
impl AlbumArt {
pub fn uri(&self) -> Option<&URI> {
match self {
Self::Embedded(_) => None,
Self::External(uri) => Some(uri),
}
}
}
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord)]
pub enum Tag { pub enum Tag {
Title, Title,
@ -490,21 +499,15 @@ impl MusicLibrary {
pub fn add_cuesheet(&mut self, cuesheet: &PathBuf) -> Result<usize, Box<dyn Error>> { pub fn add_cuesheet(&mut self, cuesheet: &PathBuf) -> Result<usize, Box<dyn Error>> {
let mut tracks_added = 0; let mut tracks_added = 0;
let cue_data = CD::parse_file(cuesheet.to_owned()).unwrap(); let cue_data = parse_from_file(&cuesheet.as_path().to_string_lossy(), false).unwrap();
// Get album level information // Get album level information
let album_title = &cue_data let album_title = &cue_data.title;
.get_cdtext() let album_artist = &cue_data.performer;
.read(cue::cd_text::PTI::Title)
.unwrap_or(String::new());
let album_artist = &cue_data
.get_cdtext()
.read(cue::cd_text::PTI::Performer)
.unwrap_or(String::new());
let parent_dir = cuesheet.parent().expect("The file has no parent path??"); let parent_dir = cuesheet.parent().expect("The file has no parent path??");
for (i, track) in cue_data.tracks().iter().enumerate() { for file in cue_data.files.iter() {
let audio_location = parent_dir.join(track.get_filename()); let audio_location = &parent_dir.join(file.file.clone());
if !audio_location.exists() { if !audio_location.exists() {
continue; continue;
@ -516,100 +519,106 @@ impl MusicLibrary {
Err(_) => () Err(_) => ()
}; };
// Get the track timing information let next_track = file.tracks.clone();
let pregap = match track.get_zero_pre() { let mut next_track = next_track.iter().skip(1);
Some(pregap) => Duration::from_micros((pregap as f32 * 13333.333333) as u64), for (i, track) in file.tracks.iter().enumerate() {
None => Duration::from_secs(0), // Get the track timing information
}; let pregap = match track.pregap {
let postgap = match track.get_zero_post() { Some(pregap) => pregap,
Some(postgap) => Duration::from_micros((postgap as f32 * 13333.333333) as u64), None => Duration::from_secs(0),
None => Duration::from_secs(0), };
}; let postgap = match track.postgap {
let mut start = Duration::from_micros((track.get_start() as f32 * 13333.333333) as u64); Some(postgap) => postgap,
start -= pregap; None => Duration::from_secs(0),
};
let mut start = track.indices[0].1;
start -= pregap;
let duration = match track.get_length() { let duration = match next_track.next() {
Some(len) => Duration::from_micros((len as f32 * 13333.333333) as u64), Some(future) => match future.indices.get(0) {
None => { Some(val) => val.1 - start,
let tagged_file = match lofty::read_from_path(&audio_location) { None => Duration::from_secs(0)
Ok(tagged_file) => tagged_file, }
None => {
Err(_) => match Probe::open(&audio_location)?.read() { let tagged_file = match lofty::read_from_path(&audio_location) {
Ok(tagged_file) => tagged_file, Ok(tagged_file) => tagged_file,
Err(error) => return Err(error.into()), Err(_) => match Probe::open(&audio_location)?.read() {
}, Ok(tagged_file) => tagged_file,
};
tagged_file.properties().duration() - start Err(error) => return Err(error.into()),
} },
}; };
let end = start + duration + postgap;
// Get the format as a string tagged_file.properties().duration() - start
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();
tags.insert(Tag::Album, album_title.clone());
tags.insert(Tag::Key("AlbumArtist".to_string()), album_artist.clone());
tags.insert(Tag::Track, (i + 1).to_string());
match track.get_cdtext().read(cue::cd_text::PTI::Title) {
Some(title) => tags.insert(Tag::Title, title),
None => match track.get_cdtext().read(cue::cd_text::PTI::UPC_ISRC) {
Some(title) => tags.insert(Tag::Title, title),
None => {
let namestr = format!("{} - {}", i, track.get_filename());
tags.insert(Tag::Title, namestr)
} }
}, };
}; let end = start + duration + postgap;
match track.get_cdtext().read(cue::cd_text::PTI::Performer) {
Some(artist) => tags.insert(Tag::Artist, artist),
None => None,
};
match track.get_cdtext().read(cue::cd_text::PTI::Genre) {
Some(genre) => tags.insert(Tag::Genre, genre),
None => None,
};
match track.get_cdtext().read(cue::cd_text::PTI::Message) {
Some(comment) => tags.insert(Tag::Comment, comment),
None => None,
};
let album_art = Vec::new(); // Get the format as a string
let format: Option<FileFormat> = match FileFormat::from_file(&audio_location) {
Ok(fmt) => Some(fmt),
Err(_) => None,
};
let new_song = Song { // Get some useful tags
location: URI::Cue { let mut tags: BTreeMap<Tag, String> = BTreeMap::new();
location: audio_location, match album_title {
index: i, Some(title) => {tags.insert(Tag::Album, title.clone());},
start, None => (),
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) {
Ok(_) => tracks_added += 1,
Err(_error) => {
//println!("{}", _error);
continue;
} }
}; match album_artist {
Some(artist) => {tags.insert(Tag::Album, 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) {
Ok(_) => tracks_added += 1,
Err(_error) => {
//println!("{}", _error);
continue;
}
};
}
} }
Ok(tracks_added) Ok(tracks_added)