From a5453de572e8c05744800a5a64149d56f35686be Mon Sep 17 00:00:00 2001 From: Paul Lietar Date: Mon, 14 Mar 2016 22:56:50 +0000 Subject: [PATCH] Make cache directory optional. If the -c argument is omitted, librespot will run without a cache, and download tracks overtime they are played. --- src/audio_file.rs | 39 +++++++++++++++++++-------------------- src/main.rs | 16 +++++++++------- src/session.rs | 6 ++++-- 3 files changed, 32 insertions(+), 29 deletions(-) diff --git a/src/audio_file.rs b/src/audio_file.rs index 09fd782..622af07 100644 --- a/src/audio_file.rs +++ b/src/audio_file.rs @@ -103,7 +103,7 @@ impl AudioFileLoading { let bitmap = shared.bitmap.lock().unwrap(); if bitmap.len() >= shared.chunk_count { drop(bitmap); - AudioFileLoading::store(session, &shared, &mut write_file); + AudioFileLoading::persist_to_cache(session, &shared, &mut write_file); break; } @@ -150,14 +150,14 @@ impl AudioFileLoading { shared.cond.notify_all(); } - fn store(session: &Session, shared: &AudioFileShared, write_file: &mut NamedTempFile) { - write_file.seek(SeekFrom::Start(0)).unwrap(); + fn persist_to_cache(session: &Session, shared: &AudioFileShared, write_file: &mut NamedTempFile) { + if let Some(path) = AudioFileManager::cache_path(session, shared.file_id) { + write_file.seek(SeekFrom::Start(0)).unwrap(); + mkdir_existing(path.parent().unwrap()).unwrap(); - mkdir_existing(&AudioFileManager::cache_dir(session, shared.file_id)).unwrap(); - - let mut f = fs::File::create(AudioFileManager::cache_path(session, shared.file_id)) - .unwrap(); - io::copy(write_file, &mut f).unwrap(); + let mut cache_file = fs::File::create(path).unwrap(); + io::copy(write_file, &mut cache_file).unwrap(); + } } } @@ -217,20 +217,19 @@ impl AudioFileManager { AudioFileManager } - pub fn cache_dir(session: &Session, file_id: FileId) -> PathBuf { - let name = file_id.to_base16(); - session.config().cache_location.join(&name[0..2]) - } - - pub fn cache_path(session: &Session, file_id: FileId) -> PathBuf { - let name = file_id.to_base16(); - AudioFileManager::cache_dir(session, file_id).join(&name[2..]) + pub fn cache_path(session: &Session, file_id: FileId) -> Option { + session.config().cache_location.as_ref().map(|cache| { + let name = file_id.to_base16(); + cache.join(&name[0..2]).join(&name[2..]) + }) } pub fn request(&mut self, session: &Session, file_id: FileId) -> AudioFile { - match fs::File::open(AudioFileManager::cache_path(session, file_id)) { - Ok(f) => AudioFile::Direct(f), - Err(..) => AudioFile::Loading(AudioFileLoading::new(session, file_id)), - } + let cache_path = AudioFileManager::cache_path(session, file_id); + let cache_file = cache_path.and_then(|p| fs::File::open(p).ok()); + + cache_file.map(AudioFile::Direct).unwrap_or_else(|| { + AudioFile::Loading(AudioFileLoading::new(session, file_id)) + }) } } diff --git a/src/main.rs b/src/main.rs index 69ec203..7a6aa14 100644 --- a/src/main.rs +++ b/src/main.rs @@ -33,7 +33,7 @@ fn main() { opts.reqopt("a", "appkey", "Path to a spotify appkey", "APPKEY") .optopt("u", "username", "Username to sign in with (optional)", "USERNAME") .optopt("p", "password", "Password (optional)", "PASSWORD") - .reqopt("c", "cache", "Path to a directory where files will be cached.", "CACHE") + .optopt("c", "cache", "Path to a directory where files will be cached.", "CACHE") .reqopt("n", "name", "Device name", "NAME") .optopt("b", "bitrate", "Bitrate (96, 160 or 320). Defaults to 160", "BITRATE"); @@ -56,7 +56,7 @@ fn main() { }; let username = matches.opt_str("u"); - let cache_location = PathBuf::from(matches.opt_str("c").unwrap()); + let cache_location = matches.opt_str("c").map(PathBuf::from); let name = matches.opt_str("n").unwrap(); let credentials = username.map(|u| { @@ -91,21 +91,23 @@ fn main() { let session = Session::new(config); - let credentials_path = cache_location.join("credentials.json"); + let credentials_path = cache_location.map(|c| c.join("credentials.json")); let credentials = credentials.map(|(username, password)| { Credentials::with_password(username, password) }).or_else(|| { - File::open(&credentials_path).map(|file| { - Credentials::from_reader(file) - }).ok() + credentials_path.as_ref() + .and_then(|p| File::open(p).ok()) + .map(Credentials::from_reader) }).unwrap_or_else(|| { let mut discovery = DiscoveryManager::new(session.clone()); discovery.run() }); let reusable_credentials = session.login(credentials).unwrap(); - reusable_credentials.save_to_file(credentials_path); + if let Some(path) = credentials_path { + reusable_credentials.save_to_file(path); + } let player = Player::new(session.clone(), || DefaultSink::open()); let spirc = SpircManager::new(session.clone(), player); diff --git a/src/session.rs b/src/session.rs index 331e4b0..7c8a466 100644 --- a/src/session.rs +++ b/src/session.rs @@ -34,7 +34,7 @@ pub struct Config { pub application_key: Vec, pub user_agent: String, pub device_name: String, - pub cache_location: PathBuf, + pub cache_location: Option, pub bitrate: Bitrate, } @@ -62,7 +62,9 @@ pub struct Session(pub Arc); impl Session { pub fn new(config: Config) -> Session { - mkdir_existing(&config.cache_location).unwrap(); + if let Some(cache_location) = config.cache_location.as_ref() { + mkdir_existing(cache_location).unwrap(); + } let device_id = { let mut h = Sha1::new();