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:
commit
26c127c2ec
23 changed files with 961 additions and 800 deletions
93
src/main.rs
93
src/main.rs
|
@ -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 {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue