From 552d9145f4eed3a27dbcf459a113ff1a8fb0c77a Mon Sep 17 00:00:00 2001 From: Roderick van Domburg Date: Tue, 25 Jan 2022 20:46:10 +0100 Subject: [PATCH] Feature-gate passthrough decoder --- Cargo.toml | 2 ++ playback/Cargo.toml | 4 +++- playback/src/decoder/mod.rs | 4 +++- playback/src/player.rs | 23 ++++++++++++++++------- src/main.rs | 17 ++++++++++++----- 5 files changed, 36 insertions(+), 14 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3df60b84..7fe13f43 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -72,6 +72,8 @@ gstreamer-backend = ["librespot-playback/gstreamer-backend"] with-dns-sd = ["librespot-core/with-dns-sd", "librespot-discovery/with-dns-sd"] +passthrough-decoder = ["librespot-playback/passthrough-decoder"] + default = ["rodio-backend"] [package.metadata.deb] diff --git a/playback/Cargo.toml b/playback/Cargo.toml index 707d28f9..60304507 100644 --- a/playback/Cargo.toml +++ b/playback/Cargo.toml @@ -46,7 +46,7 @@ cpal = { version = "0.13", optional = true } symphonia = { version = "0.4", default-features = false, features = ["mp3", "ogg", "vorbis"] } # Legacy Ogg container decoder for the passthrough decoder -ogg = "0.8" +ogg = { version = "0.8", optional = true } # Dithering rand = { version = "0.8", features = ["small_rng"] } @@ -61,3 +61,5 @@ rodio-backend = ["rodio", "cpal"] rodiojack-backend = ["rodio", "cpal/jack"] sdl-backend = ["sdl2"] gstreamer-backend = ["gstreamer", "gstreamer-app", "glib"] + +passthrough-decoder = ["ogg"] diff --git a/playback/src/decoder/mod.rs b/playback/src/decoder/mod.rs index 2526da34..f980b680 100644 --- a/playback/src/decoder/mod.rs +++ b/playback/src/decoder/mod.rs @@ -2,7 +2,9 @@ use std::ops::Deref; use thiserror::Error; +#[cfg(feature = "passthrough-decoder")] mod passthrough_decoder; +#[cfg(feature = "passthrough-decoder")] pub use passthrough_decoder::PassthroughDecoder; mod symphonia_decoder; @@ -41,7 +43,7 @@ impl AudioPacket { } } - pub fn oggdata(&self) -> AudioPacketResult<&[u8]> { + pub fn raw(&self) -> AudioPacketResult<&[u8]> { match self { AudioPacket::Raw(d) => Ok(d), AudioPacket::Samples(_) => Err(AudioPacketError::Samples), diff --git a/playback/src/player.rs b/playback/src/player.rs index a52cc01b..a679908e 100644 --- a/playback/src/player.rs +++ b/playback/src/player.rs @@ -35,13 +35,14 @@ use crate::{ config::{Bitrate, NormalisationMethod, NormalisationType, PlayerConfig}, convert::Converter, core::{util::SeqGenerator, Error, Session, SpotifyId}, - decoder::{ - AudioDecoder, AudioPacket, AudioPacketPosition, PassthroughDecoder, SymphoniaDecoder, - }, + decoder::{AudioDecoder, AudioPacket, AudioPacketPosition, SymphoniaDecoder}, metadata::audio::{AudioFileFormat, AudioFiles, AudioItem}, mixer::AudioFilter, }; +#[cfg(feature = "passthrough-decoder")] +use crate::decoder::PassthroughDecoder; + use crate::SAMPLES_PER_SECOND; const PRELOAD_NEXT_TRACK_BEFORE_END_DURATION_MS: u32 = 30000; @@ -931,9 +932,7 @@ impl PlayerTrackLoader { } }; - let result = if self.config.passthrough { - PassthroughDecoder::new(audio_file, format).map(|x| Box::new(x) as Decoder) - } else { + let mut symphonia_decoder = |audio_file, format| { SymphoniaDecoder::new(audio_file, format).map(|mut decoder| { // For formats other that Vorbis, we'll try getting normalisation data from // ReplayGain metadata fields, if present. @@ -944,12 +943,22 @@ impl PlayerTrackLoader { }) }; + #[cfg(feature = "passthrough-decoder")] + let decoder_type = if self.config.passthrough { + PassthroughDecoder::new(audio_file, format).map(|x| Box::new(x) as Decoder) + } else { + symphonia_decoder(audio_file, format) + }; + + #[cfg(not(feature = "passthrough-decoder"))] + let decoder_type = symphonia_decoder(audio_file, format); + let normalisation_data = normalisation_data.unwrap_or_else(|| { warn!("Unable to get normalisation data, continuing with defaults."); NormalisationData::default() }); - let mut decoder = match result { + let mut decoder = match decoder_type { Ok(decoder) => decoder, Err(e) if is_cached => { warn!( diff --git a/src/main.rs b/src/main.rs index 2919ade7..6f837c02 100644 --- a/src/main.rs +++ b/src/main.rs @@ -227,6 +227,7 @@ fn get_setup() -> Setup { const NORMALISATION_RELEASE: &str = "normalisation-release"; const NORMALISATION_THRESHOLD: &str = "normalisation-threshold"; const ONEVENT: &str = "onevent"; + #[cfg(feature = "passthrough-decoder")] const PASSTHROUGH: &str = "passthrough"; const PASSWORD: &str = "password"; const PROXY: &str = "proxy"; @@ -262,6 +263,7 @@ fn get_setup() -> Setup { const NAME_SHORT: &str = "n"; const DISABLE_DISCOVERY_SHORT: &str = "O"; const ONEVENT_SHORT: &str = "o"; + #[cfg(feature = "passthrough-decoder")] const PASSTHROUGH_SHORT: &str = "P"; const PASSWORD_SHORT: &str = "p"; const EMIT_SINK_EVENTS_SHORT: &str = "Q"; @@ -371,11 +373,6 @@ fn get_setup() -> Setup { EMIT_SINK_EVENTS, "Run PROGRAM set by `--onevent` before the sink is opened and after it is closed.", ) - .optflag( - PASSTHROUGH_SHORT, - PASSTHROUGH, - "Pass a raw stream to the output. Only works with the pipe and subprocess backends.", - ) .optflag( ENABLE_VOLUME_NORMALISATION_SHORT, ENABLE_VOLUME_NORMALISATION, @@ -568,6 +565,13 @@ fn get_setup() -> Setup { "PORT", ); + #[cfg(feature = "passthrough-decoder")] + opts.optflag( + PASSTHROUGH_SHORT, + PASSTHROUGH, + "Pass a raw stream to the output. Only works with the pipe and subprocess backends.", + ); + let args: Vec<_> = std::env::args_os() .filter_map(|s| match s.into_string() { Ok(valid) => Some(valid), @@ -1505,7 +1509,10 @@ fn get_setup() -> Setup { }, }; + #[cfg(feature = "passthrough-decoder")] let passthrough = opt_present(PASSTHROUGH); + #[cfg(not(feature = "passthrough-decoder"))] + let passthrough = false; PlayerConfig { bitrate,