diff --git a/.gitignore b/.gitignore index 62c5a2f..72106f3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,15 @@ +# Rust binary output dir target/ -music_database* -*.db3* -config.toml +# Rust configuration Cargo.lock + +# Database files +*.db3* +music_database* + +# Storage formats *.kate-swp* *.m3u -*.m3u8 \ No newline at end of file +*.m3u8 +*.json diff --git a/src/config/config.rs b/src/config/config.rs index 8979907..7c3ffa8 100644 --- a/src/config/config.rs +++ b/src/config/config.rs @@ -1,7 +1,11 @@ -use std::{path::{PathBuf, Path}, marker::PhantomData, fs::{File, OpenOptions, self}, io::{Error, Write, Read}, default}; +use std::{ + path::PathBuf, + fs::{File, OpenOptions, self}, + io::{Error, Write, Read}, +}; use serde::{Serialize, Deserialize}; -use serde_json::{to_string, to_string_pretty}; +use serde_json::to_string_pretty; use thiserror::Error; use uuid::Uuid; @@ -11,6 +15,7 @@ pub struct ConfigLibrary { pub path: PathBuf, pub uuid: Uuid } + impl ConfigLibrary { pub fn new() -> Self { ConfigLibrary::default() @@ -22,6 +27,7 @@ impl ConfigLibrary { } } } + impl Default for ConfigLibrary { fn default() -> Self { ConfigLibrary { @@ -31,29 +37,71 @@ impl Default for ConfigLibrary { } } } + #[derive(Debug, Default, Serialize, Deserialize)] pub struct ConfigLibraries { default_library: Uuid, pub library_folder: PathBuf, pub libraries: Vec, } + +impl ConfigLibraries { + //TODO: Add new function for test tube + pub fn set_default(mut self, uuid: &Uuid) { + self.default_library = *uuid; + } + + pub fn get_default(&self) -> Result<&ConfigLibrary, ConfigError> { + for library in &self.libraries { + if library.uuid == self.default_library { + return Ok(library) + } + } + Err(ConfigError::NoDefaultLibrary) + } + + pub fn get_library(&self, uuid: &Uuid) -> Result { + for library in &self.libraries { + if &library.uuid == uuid { + return Ok(library.to_owned()) + } + } + Err(ConfigError::NoConfigLibrary(*uuid)) + } + + pub fn uuid_exists(&self, uuid: &Uuid) -> bool { + for library in &self.libraries { + if &library.uuid == uuid { + return true + } + } + false + } +} + #[derive(Debug, Default, Serialize, Deserialize)] pub struct Config { pub path: PathBuf, pub libraries: ConfigLibraries, volume: f32, } + #[test] -fn config_test_() { - Config { - path: PathBuf::from("F:\\temp\\config.json"), +fn config_test() { + let _ = Config { + path: PathBuf::from("config_test.json"), libraries: ConfigLibraries { - libraries: vec![ConfigLibrary::default(),ConfigLibrary::default(),ConfigLibrary::default()], + libraries: vec![ + ConfigLibrary::default(), + ConfigLibrary::default(), + ConfigLibrary::default() + ], ..Default::default() }, ..Default::default() - }.to_file(); + }.write_file(); } + impl Config { pub fn new() -> Self { Config { @@ -64,38 +112,12 @@ impl Config { ..Default::default() } } + pub fn new_main() -> Self { Config::default() } - //TODO: Add new function for test tube - pub fn set_default_library(mut self, uuid: &Uuid) { - self.libraries.default_library = *uuid; - } - pub fn get_default_library(&self) -> Result<&ConfigLibrary, ConfigError> { - for library in &self.libraries.libraries { - if library.uuid == self.libraries.default_library { - return Ok(library) - } - } - Err(ConfigError::NoDefaultLibrary) - } - pub fn get_library(&self, uuid: &Uuid) -> Result { - for library in &self.libraries.libraries { - if &library.uuid == uuid { - return Ok(library.to_owned()) - } - } - Err(ConfigError::NoConfigLibrary(*uuid)) - } - pub fn library_exists(&self, uuid: &Uuid) -> bool { - for library in &self.libraries.libraries { - if &library.uuid == uuid { - return true - } - } - false - } - pub fn to_file(&self) -> Result<(), Error> { + + pub fn write_file(&self) -> Result<(), Error> { let mut writer = self.path.clone(); writer.set_extension("tmp"); let mut file = OpenOptions::new().create(true).truncate(true).read(true).write(true).open(&writer)?; @@ -106,7 +128,8 @@ impl Config { fs::rename(writer, self.path.as_path())?; Ok(()) } - pub fn load_file(path: PathBuf) -> Result { + + pub fn read_file(path: PathBuf) -> Result { let mut file: File = File::open(path)?; let mut bun: String = String::new(); _ = file.read_to_string(&mut bun); diff --git a/src/lib.rs b/src/lib.rs index 3222def..2c479ae 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,6 +3,8 @@ pub mod music_storage { pub mod music_collection; pub mod playlist; mod utils; + + #[allow(dead_code)] pub mod db_reader; } diff --git a/src/music_storage/library.rs b/src/music_storage/library.rs index 2bd3145..4e4711b 100644 --- a/src/music_storage/library.rs +++ b/src/music_storage/library.rs @@ -1,8 +1,6 @@ // Crate things -use super::utils::{find_images, normalize, read_library, write_library}; -use super::music_collection::MusicCollection; +use super::utils::{find_images, normalize, read_file, write_file}; use crate::config::config::Config; -use crate::music_storage::library; // Various std things use std::collections::BTreeMap; @@ -316,25 +314,30 @@ impl Album<'_> { const BLOCKED_EXTENSIONS: [&str; 4] = ["vob", "log", "txt", "sf2"]; -#[derive(Debug)] +#[derive(Debug, Serialize, Deserialize)] pub struct MusicLibrary { pub name: String, pub uuid: Uuid, pub library: Vec, } + #[test] - fn test_() { - let a = MusicLibrary::init(Arc::new(RwLock::from(Config::new())), None).unwrap(); - dbg!(a); - } +fn library_init() { + let uuidv4 = Uuid::new_v4(); + let a = MusicLibrary::init(Arc::new(RwLock::from(Config::new())), uuidv4).unwrap(); + dbg!(a); +} + impl MusicLibrary { - pub fn new() -> Self { + pub fn new(name: String, uuid: Uuid) -> Self { MusicLibrary { - name: String::default(), - uuid: Uuid::default(), + name, + uuid, library: Vec::new(), } } + + /* pub fn with_uuid(uuid: Uuid, path: PathBuf) -> Result> { MusicLibrary { name: String::new(), @@ -344,40 +347,35 @@ impl MusicLibrary { todo!() } + */ /// Initialize the database /// /// If the database file already exists, return the [MusicLibrary], otherwise create /// the database first. This needs to be run before anything else to retrieve /// the [MusicLibrary] Vec - pub fn init(config: Arc>, uuid: Option) -> Result> { + pub fn init(config: Arc>, uuid: Uuid) -> Result> { let global_config = &*config.read().unwrap(); - let mut library = MusicLibrary::new(); + let library: MusicLibrary = match global_config.libraries.uuid_exists(&uuid) { + true => read_file(global_config.libraries.get_library(&uuid)?.path)?, + false => { + // If the library does not exist, re-create it + let lib = MusicLibrary::new(String::new(), uuid); + write_file(&lib, global_config.libraries.get_library(&uuid)?.path)?; + lib + } + }; - if let Some(uuid) = uuid { - match global_config.library_exists(&uuid) { - true => { - library.library = read_library(global_config.get_library(&uuid)?.path)?; - }, - false => { - // Create the database if it does not exist - write_library(&library.library, global_config.path.clone())?; - library = MusicLibrary::with_uuid(uuid, global_config.path.parent().unwrap().to_path_buf())?; - } - }; - }else { - write_library(&library.library, global_config.path.clone())?; - } Ok(library) } /// Serializes the database out to the file specified in the config pub fn save(&self, config: &Config) -> Result<(), Box> { - let path = config.get_library(&self.uuid)?.path; + let path = config.libraries.get_library(&self.uuid)?.path; match path.try_exists() { Ok(_) => { - write_library(&self.library, path)?; + write_file(&self.library, path)?; } Err(error) => return Err(error.into()), } diff --git a/src/music_storage/utils.rs b/src/music_storage/utils.rs index c42a6b5..945aa4c 100644 --- a/src/music_storage/utils.rs +++ b/src/music_storage/utils.rs @@ -6,7 +6,7 @@ use walkdir::WalkDir; use snap; -use super::library::{AlbumArt, Song, URI}; +use super::library::{AlbumArt, URI}; use unidecode::unidecode; pub(super) fn normalize(input_string: &str) -> String { @@ -19,35 +19,36 @@ pub(super) fn normalize(input_string: &str) -> String { normalized } -pub(super) fn read_library(path: PathBuf) -> Result, Box> { +pub(super) fn read_file serde::Deserialize<'de>>(path: PathBuf) -> Result> { // Create a new snap reader over the database file let database = fs::File::open(path)?; let reader = BufReader::new(database); let mut d = snap::read::FrameDecoder::new(reader); // Decode the library from the serialized data into the vec - let library: Vec = bincode::serde::decode_from_std_read( + let library: T = bincode::serde::decode_from_std_read( &mut d, bincode::config::standard() .with_little_endian() .with_variable_int_encoding(), )?; + Ok(library) } -pub(super) fn write_library( - library: &Vec, +pub(super) fn write_file( + library: &T, path: PathBuf, ) -> Result<(), Box> { - // Create 2 new names for the file, a temporary one for writing out, and a backup + // Create a temporary name for writing out let mut writer_name = path.clone(); writer_name.set_extension("tmp"); - // Create a new BufWriter on the file and make a snap frame encoer for it too + // Create a new BufWriter on the file and a snap frame encoder let writer = BufWriter::new(fs::File::create(&writer_name)?); let mut e = snap::write::FrameEncoder::new(writer); - // Write out the data using bincode + // Write out the data bincode::serde::encode_into_std_write( library, &mut e,