Browse Source

Add --disable-audio-cache startup parameter (#204)

Disable caching of downloaded audio files at runtime. Comes in handy when running librespot on a small device with SD card or other small storage.
michaelherger 7 years ago
parent
commit
67deb07250
3 changed files with 13 additions and 108 deletions
  1. 0 101
      src/cache/default_cache.rs
  2. 10 6
      src/cache/mod.rs
  3. 3 1
      src/main.rs

+ 0 - 101
src/cache/default_cache.rs

@@ -1,101 +0,0 @@
-use std::path::PathBuf;
-use std::io::Read;
-use std::fs::File;
-
-use util::{SpotifyId, FileId, ReadSeek, mkdir_existing};
-use authentication::Credentials;
-use audio_key::AudioKey;
-
-use super::Cache;
-
-pub struct DefaultCache {
-    environment: lmdb::Environment,
-    root: PathBuf,
-}
-
-impl DefaultCache {
-    pub fn new(location: PathBuf) -> Result<DefaultCache, ()> {
-        let env = lmdb::EnvBuilder::new().max_dbs(5).open(&location.join("db"), 0o755).unwrap();
-
-        mkdir_existing(&location).unwrap();
-        mkdir_existing(&location.join("files")).unwrap();
-
-        Ok(DefaultCache {
-            environment: env,
-            root: location
-        })
-    }
-
-    fn audio_keys(&self) -> MdbResult<lmdb::DbHandle> {
-        self.environment.create_db("audio-keys", lmdb::DbFlags::empty())
-    }
-
-    fn file_path(&self, file: FileId) -> PathBuf {
-        let name = file.to_base16();
-        self.root.join("files").join(&name[0..2]).join(&name[2..])
-    }
-
-    fn credentials_path(&self) -> PathBuf {
-        self.root.join("credentials.json")
-    }
-}
-
-impl Cache for DefaultCache {
-    fn get_audio_key(&self, track: SpotifyId, file: FileId) -> Option<AudioKey> {
-        let reader = self.environment.get_reader().unwrap();
-        let handle = self.audio_keys().unwrap();
-        let db = reader.bind(&handle);
-
-        let mut key = Vec::new();
-        key.extend_from_slice(&track.to_raw());
-        key.extend_from_slice(&file.0);
-
-        let value : Option<Vec<_>> = db.get(&key).ok();
-        value.and_then(|value| if value.len() == 16 {
-            let mut result = [0u8; 16];
-            result.clone_from_slice(&value);
-            Some(AudioKey(result))
-        } else {
-            None
-        })
-    }
-
-    fn put_audio_key(&self, track: SpotifyId, file: FileId, audio_key: AudioKey) {
-        let xact = self.environment.new_transaction().unwrap();
-        let handle = self.audio_keys().unwrap();
-
-        {
-            let db = xact.bind(&handle);
-
-            let mut key = Vec::new();
-            key.extend_from_slice(&track.to_raw());
-            key.extend_from_slice(&file.0);
-
-            db.set(&key, &audio_key.0.as_ref()).unwrap();
-        }
-
-        xact.commit().unwrap();
-    }
-
-    fn get_credentials(&self) -> Option<Credentials> {
-        let path = self.credentials_path();
-        Credentials::from_file(path)
-    }
-    fn put_credentials(&self, cred: &Credentials) {
-        let path = self.credentials_path();
-        cred.save_to_file(&path);
-    }
-
-    fn get_file(&self, file: FileId) -> Option<Box<ReadSeek>> {
-        File::open(self.file_path(file)).ok().map(|f| Box::new(f) as Box<ReadSeek>)
-    }
-
-    fn put_file(&self, file: FileId, contents: &mut Read) {
-        let path = self.file_path(file);
-
-        mkdir_existing(path.parent().unwrap()).unwrap();
-
-        let mut cache_file = File::create(path).unwrap();
-        ::std::io::copy(contents, &mut cache_file).unwrap();
-    }
-}

+ 10 - 6
src/cache/mod.rs

@@ -8,15 +8,17 @@ use authentication::Credentials;
 #[derive(Clone)]
 pub struct Cache {
     root: PathBuf,
+    use_audio_cache: bool,
 }
 
 impl Cache {
-    pub fn new(location: PathBuf) -> Cache {
+    pub fn new(location: PathBuf, use_audio_cache: bool) -> Cache {
         mkdir_existing(&location).unwrap();
         mkdir_existing(&location.join("files")).unwrap();
 
         Cache {
-            root: location
+            root: location,
+            use_audio_cache: use_audio_cache
         }
     }
 }
@@ -48,11 +50,13 @@ impl Cache {
     }
 
     pub fn save_file(&self, file: FileId, contents: &mut Read) {
-        let path = self.file_path(file);
+        if self.use_audio_cache {
+            let path = self.file_path(file);
 
-        mkdir_existing(path.parent().unwrap()).unwrap();
+            mkdir_existing(path.parent().unwrap()).unwrap();
 
-        let mut cache_file = File::create(path).unwrap();
-        ::std::io::copy(contents, &mut cache_file).unwrap();
+            let mut cache_file = File::create(path).unwrap();
+            ::std::io::copy(contents, &mut cache_file).unwrap();
+        }
     }
 }

+ 3 - 1
src/main.rs

@@ -86,6 +86,7 @@ struct Setup {
 fn setup(args: &[String]) -> Setup {
     let mut opts = getopts::Options::new();
     opts.optopt("c", "cache", "Path to a directory where files will be cached.", "CACHE")
+        .optflag("", "disable-audio-cache", "Disable caching of the audio data.")
         .reqopt("n", "name", "Device name", "NAME")
         .optopt("b", "bitrate", "Bitrate (96, 160 or 320). Defaults to 160", "BITRATE")
         .optopt("", "onstart", "Run PROGRAM when playback is about to begin.", "PROGRAM")
@@ -133,9 +134,10 @@ fn setup(args: &[String]) -> Setup {
 
     let name = matches.opt_str("name").unwrap();
     let device_id = librespot::session::device_id(&name);
+    let use_audio_cache = !matches.opt_present("disable-audio-cache");
 
     let cache = matches.opt_str("c").map(|cache_location| {
-        Cache::new(PathBuf::from(cache_location))
+        Cache::new(PathBuf::from(cache_location), use_audio_cache)
     });
 
     let cached_credentials = cache.as_ref().and_then(Cache::credentials);