use anyhow::{anyhow,bail,ensure};
use log::{info,error,warn,trace,debug};
use crate::macros::{
ok_debug,
sleep,
recv,
send,
};
use crate::collection::{
Album,
Collection,
Keychain,
ArtistKey,
AlbumKey,
SongKey,
};
use super::msg::{
CcdToKernel,
KernelToCcd,
};
use crate::collection::Art;
use crossbeam_channel::{Sender,Receiver};
use std::path::{Path,PathBuf};
use std::sync::Arc;
use disk::Bincode;
use std::time::Instant;
pub(crate) struct Ccd;
impl Ccd {
#[inline(always)]
pub(crate) fn convert_art(to_kernel: Sender<CcdToKernel>, collection: Collection) {
debug!("CCD - Purpose in life: convert_art()");
if collection.albums.len() == 0 {
send!(to_kernel, CcdToKernel::NewCollection(collection));
} else {
send!(to_kernel, CcdToKernel::NewCollection(Self::priv_convert_art(&to_kernel, collection)));
}
}
#[inline(always)]
pub(crate) fn new_collection(
to_kernel: Sender<CcdToKernel>,
from_kernel: Receiver<KernelToCcd>,
old_collection: Arc<Collection>,
paths: Vec<PathBuf>,
) {
let beginning = Instant::now();
debug!("CCD - Purpose in life: new_collection()");
let now = Instant::now();
let paths = Self::walkdir_audio(&to_kernel, paths);
debug!("CCD [1/10] | WalkDir: {}", now.elapsed().as_secs_f32());
let now = Instant::now();
let (vec_artist, mut vec_album, vec_song) = Self::audio_paths_to_incomplete_vecs(&to_kernel, paths);
debug!("CCD [2/10] | Metadata: {}", now.elapsed().as_secs_f32());
let now = Instant::now();
Self::fix_album_metadata_from_songs(&mut vec_album, &vec_song);
debug!("CCD [3/10] | Fix: {}", now.elapsed().as_secs_f32());
let now = Instant::now();
let sort_artist_lexi = Self::sort_artist_lexi(&vec_artist);
let sort_artist_album_count = Self::sort_artist_album_count(&vec_artist);
let sort_artist_song_count = Self::sort_artist_song_count(&vec_artist, &vec_album);
let sort_album_release_artist_lexi = Self::sort_album_release_artist_lexi(&sort_artist_lexi, &vec_artist, &vec_album);
let sort_album_lexi_artist_lexi = Self::sort_album_lexi_artist_lexi(&sort_artist_lexi, &vec_artist, &vec_album);
let sort_album_lexi = Self::sort_album_lexi(&vec_album);
let sort_album_release = Self::sort_album_release(&vec_album);
let sort_album_runtime = Self::sort_album_runtime(&vec_album);
let sort_song_artist_lexi_album_release = Self::sort_song_iterating_over_albums(&sort_album_release_artist_lexi, &vec_artist, &vec_album);
let sort_song_artist_lexi_album_lexi = Self::sort_song_iterating_over_albums(&sort_album_lexi_artist_lexi, &vec_artist, &vec_album);
let sort_song_lexi = Self::sort_song_lexi(&vec_song);
let sort_song_release = Self::sort_song_iterating_over_albums(&sort_album_release, &vec_artist, &vec_album);
let sort_song_runtime = Self::sort_song_runtime(&vec_song);
debug!("CCD [4/10] | Sort: {}", now.elapsed().as_secs_f32());
let now = Instant::now();
let collection = Collection {
empty: false,
timestamp: Collection::timestamp_now(),
count_artist: vec_artist.len(),
count_album: vec_album.len(),
count_song: vec_song.len(),
artists: vec_artist,
albums: vec_album,
songs: vec_song,
sort_artist_lexi,
sort_artist_album_count,
sort_artist_song_count,
sort_album_release_artist_lexi,
sort_album_lexi_artist_lexi,
sort_album_lexi,
sort_album_release,
sort_album_runtime,
sort_song_artist_lexi_album_release,
sort_song_artist_lexi_album_lexi,
sort_song_lexi,
sort_song_release,
sort_song_runtime,
};
debug!("CCD [5/10] | Collection: {}", now.elapsed().as_secs_f32());
let now = Instant::now();
let collection = Self::priv_convert_art(&to_kernel, collection);
debug!("CCD [7/10] | Image: {}", now.elapsed().as_secs_f32());
let now = Instant::now();
send!(to_kernel, CcdToKernel::NewCollection(collection));
debug!("CCD [8/10] | ToKernel: {}", now.elapsed().as_secs_f32());
let now = Instant::now();
match recv!(from_kernel) {
KernelToCcd::Die => debug!("CCD [9/10] | Die: {}", now.elapsed().as_secs_f32()),
}
for i in 1..=4 {
if i == 4 {
error!("CCD [10/10] | Someone else is pointing to the old Collection...! I can't deconstruct it noooooooooo~");
break
}
if Arc::strong_count(&old_collection) == 1 {
let now = Instant::now();
drop(old_collection);
debug!("CCD [10/10] | Deconstruct: {}", now.elapsed().as_secs_f32());
break
}
warn!("CCD [10/10] Attempt ({}/3) | Failed to deconstruct old Collection...", i);
sleep!(1000); }
debug!("CCD ... Took {} seconds, bye!", beginning.elapsed().as_secs_f32());
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::ccd::*;
use std::path::PathBuf;
use disk::Bincode;
#[test]
#[ignore]
fn serialize_and_convert_collection() {
crate::logger::init_logger(log::LevelFilter::Trace);
let (to_kernel, from_ccd) = crossbeam_channel::unbounded::<CcdToKernel>();
let now = Instant::now();
let collection = Collection::from_file().unwrap();
info!("Read: {}", now.elapsed().as_secs_f32());
let now = Instant::now();
let collection = Ccd::convert_art(to_kernel, collection);
info!("Convert: {}", now.elapsed().as_secs_f32());
}
#[test]
#[ignore]
fn new_collection() {
crate::logger::init_logger(log::LevelFilter::Trace);
let (to_kernel, from_ccd) = crossbeam_channel::unbounded::<CcdToKernel>();
let (to_ccd, from_kernel) = crossbeam_channel::unbounded::<KernelToCcd>();
let old_collection = Arc::new(Collection::new());
let paths = vec![
PathBuf::from("src"),
PathBuf::from("assets"),
PathBuf::from("assets"),
PathBuf::from("assets/audio"),
PathBuf::from("assets/images"),
PathBuf::from("assets/albums"),
];
let old_clone = Arc::clone(&old_collection);
std::thread::spawn(move || Ccd::new_collection(to_kernel, from_kernel, old_clone, paths));
let collection = loop {
match recv!(from_ccd) {
CcdToKernel::NewCollection(collection) => break collection,
CcdToKernel::Failed(error) => panic!("{}", error),
CcdToKernel::Update(string) => eprintln!("{}", string),
}
};
drop(old_collection);
send!(to_ccd, KernelToCcd::Die);
crate::macros::sleep!(5000);
info!("{}", collection.empty);
info!("{}", collection.timestamp);
info!("{}", collection.count_artist);
info!("{}", collection.count_album);
info!("{}", collection.count_song);
assert!(collection.empty == false);
assert!(collection.timestamp > 1678382892);
assert!(collection.count_artist == 1);
assert!(collection.count_album == 1);
assert!(collection.count_song == 506);
}
}