mirror of
https://github.com/librespot-org/librespot.git
synced 2024-12-18 17:11:53 +00:00
parse environment variables (#886)
Make librespot able to parse environment variables for options and flags. To avoid name collisions environment variables must be prepended with `LIBRESPOT_` so option/flag `foo-bar` becomes `LIBRESPOT_FOO_BAR`. Verbose logging mode (`-v`, `--verbose`) logs all parsed environment variables and command line arguments (credentials are redacted).
This commit is contained in:
parent
bbd575ed23
commit
e66cc5508c
2 changed files with 134 additions and 74 deletions
|
@ -12,12 +12,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- [main] Don't evaluate options that would otherwise have no effect.
|
- [main] Don't evaluate options that would otherwise have no effect.
|
||||||
- [playback] `alsa`: Improve `--device ?` functionality for the alsa backend.
|
- [playback] `alsa`: Improve `--device ?` functionality for the alsa backend.
|
||||||
- [contrib] Hardened security of the systemd service units
|
- [contrib] Hardened security of the systemd service units
|
||||||
|
- [main] Verbose logging mode (`-v`, `--verbose`) now logs all parsed environment variables and command line arguments (credentials are redacted).
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
- [cache] Add `disable-credential-cache` flag (breaking).
|
- [cache] Add `disable-credential-cache` flag (breaking).
|
||||||
- [main] Use different option descriptions and error messages based on what backends are enabled at build time.
|
- [main] Use different option descriptions and error messages based on what backends are enabled at build time.
|
||||||
- [main] Add a `-q`, `--quiet` option that changes the logging level to warn.
|
- [main] Add a `-q`, `--quiet` option that changes the logging level to warn.
|
||||||
- [main] Add a short name for every flag and option.
|
- [main] Add a short name for every flag and option.
|
||||||
|
- [main] Add the ability to parse environment variables.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- [main] Prevent hang when discovery is disabled and there are no credentials or when bad credentials are given.
|
- [main] Prevent hang when discovery is disabled and there are no credentials or when bad credentials are given.
|
||||||
|
|
206
src/main.rs
206
src/main.rs
|
@ -1,6 +1,6 @@
|
||||||
use futures_util::{future, FutureExt, StreamExt};
|
use futures_util::{future, FutureExt, StreamExt};
|
||||||
use librespot_playback::player::PlayerEvent;
|
use librespot_playback::player::PlayerEvent;
|
||||||
use log::{error, info, warn};
|
use log::{error, info, trace, warn};
|
||||||
use sha1::{Digest, Sha1};
|
use sha1::{Digest, Sha1};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use tokio::sync::mpsc::UnboundedReceiver;
|
use tokio::sync::mpsc::UnboundedReceiver;
|
||||||
|
@ -44,6 +44,23 @@ fn usage(program: &str, opts: &getopts::Options) -> String {
|
||||||
opts.usage(&brief)
|
opts.usage(&brief)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn arg_to_var(arg: &str) -> String {
|
||||||
|
// To avoid name collisions environment variables must be prepended
|
||||||
|
// with `LIBRESPOT_` so option/flag `foo-bar` becomes `LIBRESPOT_FOO_BAR`.
|
||||||
|
format!("LIBRESPOT_{}", arg.to_uppercase().replace("-", "_"))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn env_var_present(arg: &str) -> bool {
|
||||||
|
env::var(arg_to_var(arg)).is_ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn env_var_opt_str(option: &str) -> Option<String> {
|
||||||
|
match env::var(arg_to_var(option)) {
|
||||||
|
Ok(value) => Some(value),
|
||||||
|
Err(_) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn setup_logging(quiet: bool, verbose: bool) {
|
fn setup_logging(quiet: bool, verbose: bool) {
|
||||||
let mut builder = env_logger::Builder::new();
|
let mut builder = env_logger::Builder::new();
|
||||||
match env::var("RUST_LOG") {
|
match env::var("RUST_LOG") {
|
||||||
|
@ -591,20 +608,84 @@ fn get_setup(args: &[String]) -> Setup {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if matches.opt_present(HELP) {
|
let opt_present = |opt| matches.opt_present(opt) || env_var_present(opt);
|
||||||
|
|
||||||
|
let opt_str = |opt| {
|
||||||
|
if matches.opt_present(opt) {
|
||||||
|
matches.opt_str(opt)
|
||||||
|
} else {
|
||||||
|
env_var_opt_str(opt)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if opt_present(HELP) {
|
||||||
println!("{}", usage(&args[0], &opts));
|
println!("{}", usage(&args[0], &opts));
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if matches.opt_present(VERSION) {
|
if opt_present(VERSION) {
|
||||||
println!("{}", get_version_string());
|
println!("{}", get_version_string());
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
setup_logging(matches.opt_present(QUIET), matches.opt_present(VERBOSE));
|
setup_logging(opt_present(QUIET), opt_present(VERBOSE));
|
||||||
|
|
||||||
info!("{}", get_version_string());
|
info!("{}", get_version_string());
|
||||||
|
|
||||||
|
let librespot_env_vars: Vec<String> = env::vars_os()
|
||||||
|
.filter_map(|(k, v)| {
|
||||||
|
let mut env_var = None;
|
||||||
|
if let Some(key) = k.to_str() {
|
||||||
|
if key.starts_with("LIBRESPOT_") {
|
||||||
|
if matches!(key, "LIBRESPOT_PASSWORD" | "LIBRESPOT_USERNAME") {
|
||||||
|
// Don't log creds.
|
||||||
|
env_var = Some(format!("\t\t{}=XXXXXXXX", key));
|
||||||
|
} else if let Some(value) = v.to_str() {
|
||||||
|
env_var = Some(format!("\t\t{}={}", key, value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
env_var
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
if !librespot_env_vars.is_empty() {
|
||||||
|
trace!("Environment variable(s):");
|
||||||
|
|
||||||
|
for kv in librespot_env_vars {
|
||||||
|
trace!("{}", kv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let cmd_args = &args[1..];
|
||||||
|
|
||||||
|
let cmd_args_len = cmd_args.len();
|
||||||
|
|
||||||
|
if cmd_args_len > 0 {
|
||||||
|
trace!("Command line argument(s):");
|
||||||
|
|
||||||
|
for (index, key) in cmd_args.iter().enumerate() {
|
||||||
|
if key.starts_with('-') || key.starts_with("--") {
|
||||||
|
if matches!(key.as_str(), "--password" | "-p" | "--username" | "-u") {
|
||||||
|
// Don't log creds.
|
||||||
|
trace!("\t\t{} XXXXXXXX", key);
|
||||||
|
} else {
|
||||||
|
let mut value = "".to_string();
|
||||||
|
let next = index + 1;
|
||||||
|
if next < cmd_args_len {
|
||||||
|
let next_key = cmd_args[next].clone();
|
||||||
|
if !next_key.starts_with('-') && !next_key.starts_with("--") {
|
||||||
|
value = next_key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trace!("\t\t{} {}", key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "alsa-backend"))]
|
#[cfg(not(feature = "alsa-backend"))]
|
||||||
for a in &[
|
for a in &[
|
||||||
MIXER_TYPE,
|
MIXER_TYPE,
|
||||||
|
@ -612,13 +693,13 @@ fn get_setup(args: &[String]) -> Setup {
|
||||||
ALSA_MIXER_INDEX,
|
ALSA_MIXER_INDEX,
|
||||||
ALSA_MIXER_CONTROL,
|
ALSA_MIXER_CONTROL,
|
||||||
] {
|
] {
|
||||||
if matches.opt_present(a) {
|
if opt_present(a) {
|
||||||
warn!("Alsa specific options have no effect if the alsa backend is not enabled at build time.");
|
warn!("Alsa specific options have no effect if the alsa backend is not enabled at build time.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let backend_name = matches.opt_str(BACKEND);
|
let backend_name = opt_str(BACKEND);
|
||||||
if backend_name == Some("?".into()) {
|
if backend_name == Some("?".into()) {
|
||||||
list_backends();
|
list_backends();
|
||||||
exit(0);
|
exit(0);
|
||||||
|
@ -629,14 +710,13 @@ fn get_setup(args: &[String]) -> Setup {
|
||||||
"Invalid `--{}` / `-{}`: {}",
|
"Invalid `--{}` / `-{}`: {}",
|
||||||
BACKEND,
|
BACKEND,
|
||||||
BACKEND_SHORT,
|
BACKEND_SHORT,
|
||||||
matches.opt_str(BACKEND).unwrap_or_default()
|
opt_str(BACKEND).unwrap_or_default()
|
||||||
);
|
);
|
||||||
list_backends();
|
list_backends();
|
||||||
exit(1);
|
exit(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
let format = matches
|
let format = opt_str(FORMAT)
|
||||||
.opt_str(FORMAT)
|
|
||||||
.as_deref()
|
.as_deref()
|
||||||
.map(|format| {
|
.map(|format| {
|
||||||
AudioFormat::from_str(format).unwrap_or_else(|_| {
|
AudioFormat::from_str(format).unwrap_or_else(|_| {
|
||||||
|
@ -656,7 +736,7 @@ fn get_setup(args: &[String]) -> Setup {
|
||||||
feature = "rodio-backend",
|
feature = "rodio-backend",
|
||||||
feature = "portaudio-backend"
|
feature = "portaudio-backend"
|
||||||
))]
|
))]
|
||||||
let device = matches.opt_str(DEVICE);
|
let device = opt_str(DEVICE);
|
||||||
|
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
feature = "alsa-backend",
|
feature = "alsa-backend",
|
||||||
|
@ -680,7 +760,7 @@ fn get_setup(args: &[String]) -> Setup {
|
||||||
feature = "rodio-backend",
|
feature = "rodio-backend",
|
||||||
feature = "portaudio-backend"
|
feature = "portaudio-backend"
|
||||||
)))]
|
)))]
|
||||||
if matches.opt_present(DEVICE) {
|
if opt_present(DEVICE) {
|
||||||
warn!(
|
warn!(
|
||||||
"The `--{}` / `-{}` option is not supported by the included audio backend(s), and has no effect.",
|
"The `--{}` / `-{}` option is not supported by the included audio backend(s), and has no effect.",
|
||||||
DEVICE, DEVICE_SHORT,
|
DEVICE, DEVICE_SHORT,
|
||||||
|
@ -688,7 +768,7 @@ fn get_setup(args: &[String]) -> Setup {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "alsa-backend")]
|
#[cfg(feature = "alsa-backend")]
|
||||||
let mixer_type = matches.opt_str(MIXER_TYPE);
|
let mixer_type = opt_str(MIXER_TYPE);
|
||||||
#[cfg(not(feature = "alsa-backend"))]
|
#[cfg(not(feature = "alsa-backend"))]
|
||||||
let mixer_type: Option<String> = None;
|
let mixer_type: Option<String> = None;
|
||||||
|
|
||||||
|
@ -697,7 +777,7 @@ fn get_setup(args: &[String]) -> Setup {
|
||||||
"Invalid `--{}` / `-{}`: {}",
|
"Invalid `--{}` / `-{}`: {}",
|
||||||
MIXER_TYPE,
|
MIXER_TYPE,
|
||||||
MIXER_TYPE_SHORT,
|
MIXER_TYPE_SHORT,
|
||||||
matches.opt_str(MIXER_TYPE).unwrap_or_default()
|
opt_str(MIXER_TYPE).unwrap_or_default()
|
||||||
);
|
);
|
||||||
println!(
|
println!(
|
||||||
"Valid `--{}` / `-{}` values: alsa, softvol",
|
"Valid `--{}` / `-{}` values: alsa, softvol",
|
||||||
|
@ -711,7 +791,7 @@ fn get_setup(args: &[String]) -> Setup {
|
||||||
let mixer_default_config = MixerConfig::default();
|
let mixer_default_config = MixerConfig::default();
|
||||||
|
|
||||||
#[cfg(feature = "alsa-backend")]
|
#[cfg(feature = "alsa-backend")]
|
||||||
let device = matches.opt_str(ALSA_MIXER_DEVICE).unwrap_or_else(|| {
|
let device = opt_str(ALSA_MIXER_DEVICE).unwrap_or_else(|| {
|
||||||
if let Some(ref device_name) = device {
|
if let Some(ref device_name) = device {
|
||||||
device_name.to_string()
|
device_name.to_string()
|
||||||
} else {
|
} else {
|
||||||
|
@ -723,8 +803,7 @@ fn get_setup(args: &[String]) -> Setup {
|
||||||
let device = mixer_default_config.device;
|
let device = mixer_default_config.device;
|
||||||
|
|
||||||
#[cfg(feature = "alsa-backend")]
|
#[cfg(feature = "alsa-backend")]
|
||||||
let index = matches
|
let index = opt_str(ALSA_MIXER_INDEX)
|
||||||
.opt_str(ALSA_MIXER_INDEX)
|
|
||||||
.map(|index| {
|
.map(|index| {
|
||||||
index.parse::<u32>().unwrap_or_else(|_| {
|
index.parse::<u32>().unwrap_or_else(|_| {
|
||||||
error!(
|
error!(
|
||||||
|
@ -741,15 +820,12 @@ fn get_setup(args: &[String]) -> Setup {
|
||||||
let index = mixer_default_config.index;
|
let index = mixer_default_config.index;
|
||||||
|
|
||||||
#[cfg(feature = "alsa-backend")]
|
#[cfg(feature = "alsa-backend")]
|
||||||
let control = matches
|
let control = opt_str(ALSA_MIXER_CONTROL).unwrap_or(mixer_default_config.control);
|
||||||
.opt_str(ALSA_MIXER_CONTROL)
|
|
||||||
.unwrap_or(mixer_default_config.control);
|
|
||||||
|
|
||||||
#[cfg(not(feature = "alsa-backend"))]
|
#[cfg(not(feature = "alsa-backend"))]
|
||||||
let control = mixer_default_config.control;
|
let control = mixer_default_config.control;
|
||||||
|
|
||||||
let volume_range = matches
|
let volume_range = opt_str(VOLUME_RANGE)
|
||||||
.opt_str(VOLUME_RANGE)
|
|
||||||
.map(|range| {
|
.map(|range| {
|
||||||
let on_error = || {
|
let on_error = || {
|
||||||
error!(
|
error!(
|
||||||
|
@ -790,8 +866,7 @@ fn get_setup(args: &[String]) -> Setup {
|
||||||
_ => VolumeCtrl::DEFAULT_DB_RANGE,
|
_ => VolumeCtrl::DEFAULT_DB_RANGE,
|
||||||
});
|
});
|
||||||
|
|
||||||
let volume_ctrl = matches
|
let volume_ctrl = opt_str(VOLUME_CTRL)
|
||||||
.opt_str(VOLUME_CTRL)
|
|
||||||
.as_deref()
|
.as_deref()
|
||||||
.map(|volume_ctrl| {
|
.map(|volume_ctrl| {
|
||||||
VolumeCtrl::from_str_with_range(volume_ctrl, volume_range).unwrap_or_else(|_| {
|
VolumeCtrl::from_str_with_range(volume_ctrl, volume_range).unwrap_or_else(|_| {
|
||||||
|
@ -818,29 +893,26 @@ fn get_setup(args: &[String]) -> Setup {
|
||||||
};
|
};
|
||||||
|
|
||||||
let cache = {
|
let cache = {
|
||||||
let volume_dir = matches
|
let volume_dir = opt_str(SYSTEM_CACHE)
|
||||||
.opt_str(SYSTEM_CACHE)
|
.or_else(|| opt_str(CACHE))
|
||||||
.or_else(|| matches.opt_str(CACHE))
|
|
||||||
.map(|p| p.into());
|
.map(|p| p.into());
|
||||||
|
|
||||||
let cred_dir = if matches.opt_present(DISABLE_CREDENTIAL_CACHE) {
|
let cred_dir = if opt_present(DISABLE_CREDENTIAL_CACHE) {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
volume_dir.clone()
|
volume_dir.clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
let audio_dir = if matches.opt_present(DISABLE_AUDIO_CACHE) {
|
let audio_dir = if opt_present(DISABLE_AUDIO_CACHE) {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
matches
|
opt_str(CACHE)
|
||||||
.opt_str(CACHE)
|
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|p| AsRef::<Path>::as_ref(p).join("files"))
|
.map(|p| AsRef::<Path>::as_ref(p).join("files"))
|
||||||
};
|
};
|
||||||
|
|
||||||
let limit = if audio_dir.is_some() {
|
let limit = if audio_dir.is_some() {
|
||||||
matches
|
opt_str(CACHE_SIZE_LIMIT)
|
||||||
.opt_str(CACHE_SIZE_LIMIT)
|
|
||||||
.as_deref()
|
.as_deref()
|
||||||
.map(parse_file_size)
|
.map(parse_file_size)
|
||||||
.map(|e| {
|
.map(|e| {
|
||||||
|
@ -856,7 +928,7 @@ fn get_setup(args: &[String]) -> Setup {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
if audio_dir.is_none() && matches.opt_present(CACHE_SIZE_LIMIT) {
|
if audio_dir.is_none() && opt_present(CACHE_SIZE_LIMIT) {
|
||||||
warn!(
|
warn!(
|
||||||
"Without a `--{}` / `-{}` path, and/or if the `--{}` / `-{}` flag is set, `--{}` / `-{}` has no effect.",
|
"Without a `--{}` / `-{}` path, and/or if the `--{}` / `-{}` flag is set, `--{}` / `-{}` has no effect.",
|
||||||
CACHE, CACHE_SHORT, DISABLE_AUDIO_CACHE, DISABLE_AUDIO_CACHE_SHORT, CACHE_SIZE_LIMIT, CACHE_SIZE_LIMIT_SHORT
|
CACHE, CACHE_SHORT, DISABLE_AUDIO_CACHE, DISABLE_AUDIO_CACHE_SHORT, CACHE_SIZE_LIMIT, CACHE_SIZE_LIMIT_SHORT
|
||||||
|
@ -882,21 +954,21 @@ fn get_setup(args: &[String]) -> Setup {
|
||||||
};
|
};
|
||||||
|
|
||||||
get_credentials(
|
get_credentials(
|
||||||
matches.opt_str(USERNAME),
|
opt_str(USERNAME),
|
||||||
matches.opt_str(PASSWORD),
|
opt_str(PASSWORD),
|
||||||
cached_credentials,
|
cached_credentials,
|
||||||
password,
|
password,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let enable_discovery = !matches.opt_present(DISABLE_DISCOVERY);
|
let enable_discovery = !opt_present(DISABLE_DISCOVERY);
|
||||||
|
|
||||||
if credentials.is_none() && !enable_discovery {
|
if credentials.is_none() && !enable_discovery {
|
||||||
error!("Credentials are required if discovery is disabled.");
|
error!("Credentials are required if discovery is disabled.");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !enable_discovery && matches.opt_present(ZEROCONF_PORT) {
|
if !enable_discovery && opt_present(ZEROCONF_PORT) {
|
||||||
warn!(
|
warn!(
|
||||||
"With the `--{}` / `-{}` flag set `--{}` / `-{}` has no effect.",
|
"With the `--{}` / `-{}` flag set `--{}` / `-{}` has no effect.",
|
||||||
DISABLE_DISCOVERY, DISABLE_DISCOVERY_SHORT, ZEROCONF_PORT, ZEROCONF_PORT_SHORT
|
DISABLE_DISCOVERY, DISABLE_DISCOVERY_SHORT, ZEROCONF_PORT, ZEROCONF_PORT_SHORT
|
||||||
|
@ -904,8 +976,7 @@ fn get_setup(args: &[String]) -> Setup {
|
||||||
}
|
}
|
||||||
|
|
||||||
let zeroconf_port = if enable_discovery {
|
let zeroconf_port = if enable_discovery {
|
||||||
matches
|
opt_str(ZEROCONF_PORT)
|
||||||
.opt_str(ZEROCONF_PORT)
|
|
||||||
.map(|port| {
|
.map(|port| {
|
||||||
let on_error = || {
|
let on_error = || {
|
||||||
error!(
|
error!(
|
||||||
|
@ -938,12 +1009,9 @@ fn get_setup(args: &[String]) -> Setup {
|
||||||
let connect_config = {
|
let connect_config = {
|
||||||
let connect_default_config = ConnectConfig::default();
|
let connect_default_config = ConnectConfig::default();
|
||||||
|
|
||||||
let name = matches
|
let name = opt_str(NAME).unwrap_or_else(|| connect_default_config.name.clone());
|
||||||
.opt_str(NAME)
|
|
||||||
.unwrap_or_else(|| connect_default_config.name.clone());
|
|
||||||
|
|
||||||
let initial_volume = matches
|
let initial_volume = opt_str(INITIAL_VOLUME)
|
||||||
.opt_str(INITIAL_VOLUME)
|
|
||||||
.map(|initial_volume| {
|
.map(|initial_volume| {
|
||||||
let on_error = || {
|
let on_error = || {
|
||||||
error!(
|
error!(
|
||||||
|
@ -984,8 +1052,7 @@ fn get_setup(args: &[String]) -> Setup {
|
||||||
_ => cache.as_ref().and_then(Cache::volume),
|
_ => cache.as_ref().and_then(Cache::volume),
|
||||||
});
|
});
|
||||||
|
|
||||||
let device_type = matches
|
let device_type = opt_str(DEVICE_TYPE)
|
||||||
.opt_str(DEVICE_TYPE)
|
|
||||||
.as_deref()
|
.as_deref()
|
||||||
.map(|device_type| {
|
.map(|device_type| {
|
||||||
DeviceType::from_str(device_type).unwrap_or_else(|_| {
|
DeviceType::from_str(device_type).unwrap_or_else(|_| {
|
||||||
|
@ -1001,7 +1068,7 @@ fn get_setup(args: &[String]) -> Setup {
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
let has_volume_ctrl = !matches!(mixer_config.volume_ctrl, VolumeCtrl::Fixed);
|
let has_volume_ctrl = !matches!(mixer_config.volume_ctrl, VolumeCtrl::Fixed);
|
||||||
let autoplay = matches.opt_present(AUTOPLAY);
|
let autoplay = opt_present(AUTOPLAY);
|
||||||
|
|
||||||
ConnectConfig {
|
ConnectConfig {
|
||||||
name,
|
name,
|
||||||
|
@ -1018,7 +1085,7 @@ fn get_setup(args: &[String]) -> Setup {
|
||||||
SessionConfig {
|
SessionConfig {
|
||||||
user_agent: version::VERSION_STRING.to_string(),
|
user_agent: version::VERSION_STRING.to_string(),
|
||||||
device_id,
|
device_id,
|
||||||
proxy: matches.opt_str(PROXY).or_else(|| std::env::var("http_proxy").ok()).map(
|
proxy: opt_str(PROXY).or_else(|| std::env::var("http_proxy").ok()).map(
|
||||||
|s| {
|
|s| {
|
||||||
match Url::parse(&s) {
|
match Url::parse(&s) {
|
||||||
Ok(url) => {
|
Ok(url) => {
|
||||||
|
@ -1041,8 +1108,7 @@ fn get_setup(args: &[String]) -> Setup {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
ap_port: matches
|
ap_port: opt_str(AP_PORT)
|
||||||
.opt_str(AP_PORT)
|
|
||||||
.map(|port| {
|
.map(|port| {
|
||||||
let on_error = || {
|
let on_error = || {
|
||||||
error!("Invalid `--{}` / `-{}`: {}", AP_PORT, AP_PORT_SHORT, port);
|
error!("Invalid `--{}` / `-{}`: {}", AP_PORT, AP_PORT_SHORT, port);
|
||||||
|
@ -1067,8 +1133,7 @@ fn get_setup(args: &[String]) -> Setup {
|
||||||
let player_config = {
|
let player_config = {
|
||||||
let player_default_config = PlayerConfig::default();
|
let player_default_config = PlayerConfig::default();
|
||||||
|
|
||||||
let bitrate = matches
|
let bitrate = opt_str(BITRATE)
|
||||||
.opt_str(BITRATE)
|
|
||||||
.as_deref()
|
.as_deref()
|
||||||
.map(|bitrate| {
|
.map(|bitrate| {
|
||||||
Bitrate::from_str(bitrate).unwrap_or_else(|_| {
|
Bitrate::from_str(bitrate).unwrap_or_else(|_| {
|
||||||
|
@ -1086,9 +1151,9 @@ fn get_setup(args: &[String]) -> Setup {
|
||||||
})
|
})
|
||||||
.unwrap_or(player_default_config.bitrate);
|
.unwrap_or(player_default_config.bitrate);
|
||||||
|
|
||||||
let gapless = !matches.opt_present(DISABLE_GAPLESS);
|
let gapless = !opt_present(DISABLE_GAPLESS);
|
||||||
|
|
||||||
let normalisation = matches.opt_present(ENABLE_VOLUME_NORMALISATION);
|
let normalisation = opt_present(ENABLE_VOLUME_NORMALISATION);
|
||||||
|
|
||||||
let normalisation_method;
|
let normalisation_method;
|
||||||
let normalisation_type;
|
let normalisation_type;
|
||||||
|
@ -1108,7 +1173,7 @@ fn get_setup(args: &[String]) -> Setup {
|
||||||
NORMALISATION_RELEASE,
|
NORMALISATION_RELEASE,
|
||||||
NORMALISATION_KNEE,
|
NORMALISATION_KNEE,
|
||||||
] {
|
] {
|
||||||
if matches.opt_present(a) {
|
if opt_present(a) {
|
||||||
warn!(
|
warn!(
|
||||||
"Without the `--{}` / `-{}` flag normalisation options have no effect.",
|
"Without the `--{}` / `-{}` flag normalisation options have no effect.",
|
||||||
ENABLE_VOLUME_NORMALISATION, ENABLE_VOLUME_NORMALISATION_SHORT,
|
ENABLE_VOLUME_NORMALISATION, ENABLE_VOLUME_NORMALISATION_SHORT,
|
||||||
|
@ -1125,8 +1190,7 @@ fn get_setup(args: &[String]) -> Setup {
|
||||||
normalisation_release = player_default_config.normalisation_release;
|
normalisation_release = player_default_config.normalisation_release;
|
||||||
normalisation_knee = player_default_config.normalisation_knee;
|
normalisation_knee = player_default_config.normalisation_knee;
|
||||||
} else {
|
} else {
|
||||||
normalisation_method = matches
|
normalisation_method = opt_str(NORMALISATION_METHOD)
|
||||||
.opt_str(NORMALISATION_METHOD)
|
|
||||||
.as_deref()
|
.as_deref()
|
||||||
.map(|method| {
|
.map(|method| {
|
||||||
warn!(
|
warn!(
|
||||||
|
@ -1158,8 +1222,7 @@ fn get_setup(args: &[String]) -> Setup {
|
||||||
})
|
})
|
||||||
.unwrap_or(player_default_config.normalisation_method);
|
.unwrap_or(player_default_config.normalisation_method);
|
||||||
|
|
||||||
normalisation_type = matches
|
normalisation_type = opt_str(NORMALISATION_GAIN_TYPE)
|
||||||
.opt_str(NORMALISATION_GAIN_TYPE)
|
|
||||||
.as_deref()
|
.as_deref()
|
||||||
.map(|gain_type| {
|
.map(|gain_type| {
|
||||||
NormalisationType::from_str(gain_type).unwrap_or_else(|_| {
|
NormalisationType::from_str(gain_type).unwrap_or_else(|_| {
|
||||||
|
@ -1177,8 +1240,7 @@ fn get_setup(args: &[String]) -> Setup {
|
||||||
})
|
})
|
||||||
.unwrap_or(player_default_config.normalisation_type);
|
.unwrap_or(player_default_config.normalisation_type);
|
||||||
|
|
||||||
normalisation_pregain = matches
|
normalisation_pregain = opt_str(NORMALISATION_PREGAIN)
|
||||||
.opt_str(NORMALISATION_PREGAIN)
|
|
||||||
.map(|pregain| {
|
.map(|pregain| {
|
||||||
let on_error = || {
|
let on_error = || {
|
||||||
error!(
|
error!(
|
||||||
|
@ -1209,8 +1271,7 @@ fn get_setup(args: &[String]) -> Setup {
|
||||||
})
|
})
|
||||||
.unwrap_or(player_default_config.normalisation_pregain);
|
.unwrap_or(player_default_config.normalisation_pregain);
|
||||||
|
|
||||||
normalisation_threshold = matches
|
normalisation_threshold = opt_str(NORMALISATION_THRESHOLD)
|
||||||
.opt_str(NORMALISATION_THRESHOLD)
|
|
||||||
.map(|threshold| {
|
.map(|threshold| {
|
||||||
let on_error = || {
|
let on_error = || {
|
||||||
error!(
|
error!(
|
||||||
|
@ -1244,8 +1305,7 @@ fn get_setup(args: &[String]) -> Setup {
|
||||||
})
|
})
|
||||||
.unwrap_or(player_default_config.normalisation_threshold);
|
.unwrap_or(player_default_config.normalisation_threshold);
|
||||||
|
|
||||||
normalisation_attack = matches
|
normalisation_attack = opt_str(NORMALISATION_ATTACK)
|
||||||
.opt_str(NORMALISATION_ATTACK)
|
|
||||||
.map(|attack| {
|
.map(|attack| {
|
||||||
let on_error = || {
|
let on_error = || {
|
||||||
error!(
|
error!(
|
||||||
|
@ -1279,8 +1339,7 @@ fn get_setup(args: &[String]) -> Setup {
|
||||||
})
|
})
|
||||||
.unwrap_or(player_default_config.normalisation_attack);
|
.unwrap_or(player_default_config.normalisation_attack);
|
||||||
|
|
||||||
normalisation_release = matches
|
normalisation_release = opt_str(NORMALISATION_RELEASE)
|
||||||
.opt_str(NORMALISATION_RELEASE)
|
|
||||||
.map(|release| {
|
.map(|release| {
|
||||||
let on_error = || {
|
let on_error = || {
|
||||||
error!(
|
error!(
|
||||||
|
@ -1314,8 +1373,7 @@ fn get_setup(args: &[String]) -> Setup {
|
||||||
})
|
})
|
||||||
.unwrap_or(player_default_config.normalisation_release);
|
.unwrap_or(player_default_config.normalisation_release);
|
||||||
|
|
||||||
normalisation_knee = matches
|
normalisation_knee = opt_str(NORMALISATION_KNEE)
|
||||||
.opt_str(NORMALISATION_KNEE)
|
|
||||||
.map(|knee| {
|
.map(|knee| {
|
||||||
let on_error = || {
|
let on_error = || {
|
||||||
error!(
|
error!(
|
||||||
|
@ -1347,7 +1405,7 @@ fn get_setup(args: &[String]) -> Setup {
|
||||||
.unwrap_or(player_default_config.normalisation_knee);
|
.unwrap_or(player_default_config.normalisation_knee);
|
||||||
}
|
}
|
||||||
|
|
||||||
let ditherer_name = matches.opt_str(DITHER);
|
let ditherer_name = opt_str(DITHER);
|
||||||
let ditherer = match ditherer_name.as_deref() {
|
let ditherer = match ditherer_name.as_deref() {
|
||||||
// explicitly disabled on command line
|
// explicitly disabled on command line
|
||||||
Some("none") => None,
|
Some("none") => None,
|
||||||
|
@ -1363,7 +1421,7 @@ fn get_setup(args: &[String]) -> Setup {
|
||||||
"Invalid `--{}` / `-{}`: {}",
|
"Invalid `--{}` / `-{}`: {}",
|
||||||
DITHER,
|
DITHER,
|
||||||
DITHER_SHORT,
|
DITHER_SHORT,
|
||||||
matches.opt_str(DITHER).unwrap_or_default()
|
opt_str(DITHER).unwrap_or_default()
|
||||||
);
|
);
|
||||||
println!(
|
println!(
|
||||||
"Valid `--{}` / `-{}` values: none, gpdf, tpdf, tpdf_hp",
|
"Valid `--{}` / `-{}` values: none, gpdf, tpdf, tpdf_hp",
|
||||||
|
@ -1384,7 +1442,7 @@ fn get_setup(args: &[String]) -> Setup {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let passthrough = matches.opt_present(PASSTHROUGH);
|
let passthrough = opt_present(PASSTHROUGH);
|
||||||
|
|
||||||
PlayerConfig {
|
PlayerConfig {
|
||||||
bitrate,
|
bitrate,
|
||||||
|
@ -1402,8 +1460,8 @@ fn get_setup(args: &[String]) -> Setup {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let player_event_program = matches.opt_str(ONEVENT);
|
let player_event_program = opt_str(ONEVENT);
|
||||||
let emit_sink_events = matches.opt_present(EMIT_SINK_EVENTS);
|
let emit_sink_events = opt_present(EMIT_SINK_EVENTS);
|
||||||
|
|
||||||
Setup {
|
Setup {
|
||||||
format,
|
format,
|
||||||
|
|
Loading…
Reference in a new issue