Просмотр исходного кода

Make cache directory optional.

If the -c argument is omitted, librespot will run without a cache, and
download tracks overtime they are played.
Paul Lietar 9 лет назад
Родитель
Сommit
a5453de572
3 измененных файлов с 32 добавлено и 29 удалено
  1. 19 20
      src/audio_file.rs
  2. 9 7
      src/main.rs
  3. 4 2
      src/session.rs

+ 19 - 20
src/audio_file.rs

@@ -103,7 +103,7 @@ impl AudioFileLoading {
             let bitmap = shared.bitmap.lock().unwrap();
             let bitmap = shared.bitmap.lock().unwrap();
             if bitmap.len() >= shared.chunk_count {
             if bitmap.len() >= shared.chunk_count {
                 drop(bitmap);
                 drop(bitmap);
-                AudioFileLoading::store(session, &shared, &mut write_file);
+                AudioFileLoading::persist_to_cache(session, &shared, &mut write_file);
                 break;
                 break;
             }
             }
 
 
@@ -150,14 +150,14 @@ impl AudioFileLoading {
         shared.cond.notify_all();
         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
         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<PathBuf> {
+        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 {
     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))
+        })
     }
     }
 }
 }

+ 9 - 7
src/main.rs

@@ -33,7 +33,7 @@ fn main() {
     opts.reqopt("a", "appkey", "Path to a spotify appkey", "APPKEY")
     opts.reqopt("a", "appkey", "Path to a spotify appkey", "APPKEY")
         .optopt("u", "username", "Username to sign in with (optional)", "USERNAME")
         .optopt("u", "username", "Username to sign in with (optional)", "USERNAME")
         .optopt("p", "password", "Password (optional)", "PASSWORD")
         .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")
         .reqopt("n", "name", "Device name", "NAME")
         .optopt("b", "bitrate", "Bitrate (96, 160 or 320). Defaults to 160", "BITRATE");
         .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 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 name = matches.opt_str("n").unwrap();
 
 
     let credentials = username.map(|u| {
     let credentials = username.map(|u| {
@@ -91,21 +91,23 @@ fn main() {
 
 
     let session = Session::new(config);
     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)| {
     let credentials = credentials.map(|(username, password)| {
         Credentials::with_password(username, password)
         Credentials::with_password(username, password)
     }).or_else(|| {
     }).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(|| {
     }).unwrap_or_else(|| {
         let mut discovery = DiscoveryManager::new(session.clone());
         let mut discovery = DiscoveryManager::new(session.clone());
         discovery.run()
         discovery.run()
     });
     });
 
 
     let reusable_credentials = session.login(credentials).unwrap();
     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 player = Player::new(session.clone(), || DefaultSink::open());
     let spirc = SpircManager::new(session.clone(), player);
     let spirc = SpircManager::new(session.clone(), player);

+ 4 - 2
src/session.rs

@@ -34,7 +34,7 @@ pub struct Config {
     pub application_key: Vec<u8>,
     pub application_key: Vec<u8>,
     pub user_agent: String,
     pub user_agent: String,
     pub device_name: String,
     pub device_name: String,
-    pub cache_location: PathBuf,
+    pub cache_location: Option<PathBuf>,
     pub bitrate: Bitrate,
     pub bitrate: Bitrate,
 }
 }
 
 
@@ -62,7 +62,9 @@ pub struct Session(pub Arc<SessionInternal>);
 
 
 impl Session {
 impl Session {
     pub fn new(config: Config) -> 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 device_id = {
             let mut h = Sha1::new();
             let mut h = Sha1::new();