1
0
Fork 0
mirror of https://github.com/librespot-org/librespot.git synced 2025-10-05 02:39:53 +02:00

Merge branch 'dev' into tokio_migration

This commit is contained in:
johannesd3 2021-04-10 10:27:24 +02:00
commit 26c127c2ec
23 changed files with 961 additions and 800 deletions

View file

@ -12,13 +12,16 @@ use librespot::core::config::{ConnectConfig, DeviceType, SessionConfig, VolumeCt
use librespot::core::session::Session;
use librespot::core::version;
use librespot::playback::audio_backend::{self, Sink, BACKENDS};
use librespot::playback::config::{Bitrate, NormalisationType, PlayerConfig};
use librespot::playback::config::{
AudioFormat, Bitrate, NormalisationMethod, NormalisationType, PlayerConfig,
};
use librespot::playback::mixer::{self, Mixer, MixerConfig};
use librespot::playback::player::Player;
use librespot::playback::player::{NormalisationData, Player};
mod player_event_handler;
use player_event_handler::{emit_sink_event, run_program_on_events};
use std::convert::TryFrom;
use std::path::Path;
use std::process::exit;
use std::str::FromStr;
@ -28,6 +31,8 @@ use std::{
pin::Pin,
};
const MILLIS: f32 = 1000.0;
fn device_id(name: &str) -> String {
hex::encode(Sha1::digest(name.as_bytes()))
}
@ -105,7 +110,8 @@ fn print_version() {
#[derive(Clone)]
struct Setup {
backend: fn(Option<String>) -> Box<dyn Sink + 'static>,
format: AudioFormat,
backend: fn(Option<String>, AudioFormat) -> Box<dyn Sink + 'static>,
device: Option<String>,
mixer: fn(Option<MixerConfig>) -> Box<dyn Mixer>,
@ -169,6 +175,12 @@ fn setup(args: &[String]) -> Setup {
"Audio device to use. Use '?' to list options if using portaudio or alsa",
"DEVICE",
)
.optopt(
"",
"format",
"Output format (F32, S32, S24, S24_3 or S16). Defaults to S16",
"FORMAT",
)
.optopt("", "mixer", "Mixer to use (alsa or softvol)", "MIXER")
.optopt(
"m",
@ -210,6 +222,12 @@ fn setup(args: &[String]) -> Setup {
"enable-volume-normalisation",
"Play all tracks at the same volume",
)
.optopt(
"",
"normalisation-method",
"Specify the normalisation method to use - [basic, dynamic]. Default is dynamic.",
"NORMALISATION_METHOD",
)
.optopt(
"",
"normalisation-gain-type",
@ -222,6 +240,30 @@ fn setup(args: &[String]) -> Setup {
"Pregain (dB) applied by volume normalisation",
"PREGAIN",
)
.optopt(
"",
"normalisation-threshold",
"Threshold (dBFS) to prevent clipping. Default is -1.0.",
"THRESHOLD",
)
.optopt(
"",
"normalisation-attack",
"Attack time (ms) in which the dynamic limiter is reducing gain. Default is 5.",
"ATTACK",
)
.optopt(
"",
"normalisation-release",
"Release or decay time (ms) in which the dynamic limiter is restoring gain. Default is 100.",
"RELEASE",
)
.optopt(
"",
"normalisation-knee",
"Knee steepness of the dynamic limiter. Default is 1.0.",
"KNEE",
)
.optopt(
"",
"volume-ctrl",
@ -276,9 +318,15 @@ fn setup(args: &[String]) -> Setup {
let backend = audio_backend::find(backend_name).expect("Invalid backend");
let format = matches
.opt_str("format")
.as_ref()
.map(|format| AudioFormat::try_from(format).expect("Invalid output format"))
.unwrap_or(AudioFormat::default());
let device = matches.opt_str("device");
if device == Some("?".into()) {
backend(device);
backend(device, format);
exit(0);
}
@ -410,15 +458,48 @@ fn setup(args: &[String]) -> Setup {
NormalisationType::from_str(gain_type).expect("Invalid normalisation type")
})
.unwrap_or_default();
let normalisation_method = matches
.opt_str("normalisation-method")
.as_ref()
.map(|gain_type| {
NormalisationMethod::from_str(gain_type).expect("Invalid normalisation method")
})
.unwrap_or_default();
PlayerConfig {
bitrate,
gapless: !matches.opt_present("disable-gapless"),
normalisation: matches.opt_present("enable-volume-normalisation"),
normalisation_method: normalisation_method,
normalisation_type: gain_type,
normalisation_pregain: matches
.opt_str("normalisation-pregain")
.map(|pregain| pregain.parse::<f32>().expect("Invalid pregain float value"))
.unwrap_or(PlayerConfig::default().normalisation_pregain),
normalisation_threshold: NormalisationData::db_to_ratio(
matches
.opt_str("normalisation-threshold")
.map(|threshold| {
threshold
.parse::<f32>()
.expect("Invalid threshold float value")
})
.unwrap_or(PlayerConfig::default().normalisation_threshold),
),
normalisation_attack: matches
.opt_str("normalisation-attack")
.map(|attack| attack.parse::<f32>().expect("Invalid attack float value"))
.unwrap_or(PlayerConfig::default().normalisation_attack * MILLIS)
/ MILLIS,
normalisation_release: matches
.opt_str("normalisation-release")
.map(|release| release.parse::<f32>().expect("Invalid release float value"))
.unwrap_or(PlayerConfig::default().normalisation_release * MILLIS)
/ MILLIS,
normalisation_knee: matches
.opt_str("normalisation-knee")
.map(|knee| knee.parse::<f32>().expect("Invalid knee float value"))
.unwrap_or(PlayerConfig::default().normalisation_knee),
passthrough,
}
};
@ -448,6 +529,7 @@ fn setup(args: &[String]) -> Setup {
let enable_discovery = !matches.opt_present("disable-discovery");
Setup {
format,
backend,
cache,
session_config,
@ -539,11 +621,12 @@ async fn main() {
let connect_config = setupp.connect_config.clone();
let audio_filter = mixer.get_audio_filter();
let format = setupp.format;
let backend = setupp.backend;
let device = setupp.device.clone();
let (player, event_channel) =
Player::new(player_config, session.clone(), audio_filter, move || {
(backend)(device)
(backend)(device, format)
});
if setupp.emit_sink_events {