Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 98 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use librespot_playback::player::PlayerEvent;
use log::{error, info, trace, warn};
use sha1::{Digest, Sha1};
use tokio::sync::mpsc::UnboundedReceiver;
use thiserror::Error;
use url::Url;

use librespot::connect::spirc::Spirc;
Expand Down Expand Up @@ -87,6 +88,66 @@ fn setup_logging(quiet: bool, verbose: bool) {
}
}

#[derive(Debug, Error)]
pub enum ParseFileSizeError {
#[error("empty argument")]
EmptyInput,
#[error("invalid suffix")]
InvalidSuffix,
#[error("invalid number: {0}")]
InvalidNumber(#[from] std::num::ParseFloatError),
#[error("non-finite number specified")]
NotFinite(f64),
}

pub fn parse_file_size(input: &str) -> Result<u64, ParseFileSizeError> {
use ParseFileSizeError::*;

let mut iter = input.chars();
let mut suffix = iter.next_back().ok_or(EmptyInput)?;
let mut suffix_len = 0;

let iec = matches!(suffix, 'i' | 'I');

if iec {
suffix_len += 1;
suffix = iter.next_back().ok_or(InvalidSuffix)?;
}

let base: u64 = if iec { 1024 } else { 1000 };

suffix_len += 1;
let exponent = match suffix.to_ascii_uppercase() {
'0'..='9' if !iec => {
suffix_len -= 1;
0
}
'K' => 1,
'M' => 2,
'G' => 3,
'T' => 4,
'P' => 5,
'E' => 6,
'Z' => 7,
'Y' => 8,
_ => return Err(InvalidSuffix),
};

let num = {
let mut iter = input.chars();

for _ in (&mut iter).rev().take(suffix_len) {}

iter.as_str().parse::<f64>()?
};

if !num.is_finite() {
return Err(NotFinite(num));
}

Ok((num * base.pow(exponent) as f64) as u64)
}

fn get_version_string() -> String {
#[cfg(debug_assertions)]
const BUILD_PROFILE: &str = "debug";
Expand Down Expand Up @@ -135,6 +196,7 @@ fn get_setup() -> Setup {
const AUTOPLAY: &str = "autoplay";
const BITRATE: &str = "bitrate";
const CACHE: &str = "cache";
const CACHE_SIZE_LIMIT: &str = "cache-size-limit";
const CHECK: &str = "check";
const CLIENT_ID: &str = "client-id";
const DISABLE_AUDIO_CACHE: &str = "disable-audio-cache";
Expand Down Expand Up @@ -170,6 +232,7 @@ fn get_setup() -> Setup {
const AP_PORT_SHORT: &str = "";
const BITRATE_SHORT: &str = "b";
const CACHE_SHORT: &str = "c";
const CACHE_SIZE_LIMIT_SHORT: &str = "M";
const DISABLE_AUDIO_CACHE_SHORT: &str = "G";
const ENABLE_AUDIO_CACHE_SHORT: &str = "";
const DISABLE_GAPLESS_SHORT: &str = "g";
Expand Down Expand Up @@ -270,6 +333,12 @@ fn get_setup() -> Setup {
"Path to a directory where files will be cached.",
"PATH",
)
.optopt(
CACHE_SIZE_LIMIT_SHORT,
CACHE_SIZE_LIMIT,
"Limits the size of the cache for audio files. It's possible to use suffixes like K, M or G, e.g. 16G for example.",
"SIZE"
)
.optopt(
USERNAME_SHORT,
USERNAME,
Expand Down Expand Up @@ -559,15 +628,41 @@ fn get_setup() -> Setup {

let cred_dir = volume_dir.clone();

let audio_dir = if opt_present(DISABLE_AUDIO_CACHE) {
let audio_dir = if !opt_present(ENABLE_AUDIO_CACHE) {
None
} else {
opt_str(CACHE)
.as_ref()
.map(|p| AsRef::<Path>::as_ref(p).join("files"))
};

let limit = None;
let limit = if audio_dir.is_some() {
opt_str(CACHE_SIZE_LIMIT)
.as_deref()
.map(parse_file_size)
.map(|e| {
e.unwrap_or_else(|e| {
invalid_error_msg(
CACHE_SIZE_LIMIT,
CACHE_SIZE_LIMIT_SHORT,
&e.to_string(),
"",
"",
);

exit(1);
})
})
} else {
None
};

if audio_dir.is_none() && opt_present(CACHE_SIZE_LIMIT) {
warn!(
"Without a `--{}` / `-{}` path, and/or if the `--{}` flag is not set, `--{}` / `-{}` has no effect.",
CACHE, CACHE_SHORT, ENABLE_AUDIO_CACHE, CACHE_SIZE_LIMIT, CACHE_SIZE_LIMIT_SHORT
);
}

match Cache::new(cred_dir, volume_dir, audio_dir, limit) {
Ok(cache) => Some(cache),
Expand Down Expand Up @@ -929,6 +1024,7 @@ async fn main() {
last_credentials,
setup.player_config,
setup.session_config,
setup.cache,
)
.await;
exit(0);
Expand Down
4 changes: 3 additions & 1 deletion src/spotty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use librespot::core::config::SessionConfig;
use librespot::core::keymaster;
use librespot::core::session::Session;
use librespot::core::spotify_id::SpotifyId;
use librespot::core::cache::Cache;

use librespot::playback::audio_backend;
use librespot::playback::config::{AudioFormat, PlayerConfig};
Expand Down Expand Up @@ -116,6 +117,7 @@ pub async fn play_track(
last_credentials: Option<Credentials>,
player_config: PlayerConfig,
session_config: SessionConfig,
cache: Option<Cache>
) {
match last_credentials {
Some(last_credentials) => {
Expand All @@ -130,7 +132,7 @@ pub async fn play_track(
);

match track {
Ok(track) => match Session::connect(session_config, last_credentials, None, true)
Ok(track) => match Session::connect(session_config, last_credentials, cache, true)
.await
{
Ok((session, _)) => {
Expand Down