From b4e7dc30702388c845d01d564e105a6c6cdddfca Mon Sep 17 00:00:00 2001 From: Michael Herger Date: Sun, 8 Sep 2024 07:38:17 +0200 Subject: [PATCH] Introduce `spotty` feature flag --- Cargo.lock | 25 +++++++++-------- Cargo.toml | 4 ++- src/main.rs | 77 ++++++++++++++++++++++++++++++--------------------- src/spotty.rs | 58 +++++++++++++++++++------------------- 4 files changed, 90 insertions(+), 74 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c1ff4f04a..a576d998e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -231,9 +231,9 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.17.1" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773d90827bc3feecfb67fab12e24de0749aad83c74b9504ecde46237b5cd24e2" +checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae" [[package]] name = "byteorder" @@ -249,9 +249,9 @@ checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "cc" -version = "1.1.15" +version = "1.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" +checksum = "e9d013ecb737093c0e86b151a7b837993cf9ec6c502946cfb44bedc392421e0b" dependencies = [ "jobserver", "libc", @@ -2318,9 +2318,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustix" -version = "0.38.35" +version = "0.38.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a85d50532239da68e9addb745ba38ff4612a242c1c7ceea689c4bc7c2f43c36f" +checksum = "3f55e80d50763938498dd5ebb18647174e0c76dc38c5505294bb224624f30f36" dependencies = [ "bitflags 2.6.0", "errno", @@ -2500,9 +2500,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.127" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ "itoa", "memchr", @@ -2629,6 +2629,7 @@ dependencies = [ "futures-util", "getopts", "hyper", + "hyper-util", "librespot-audio", "librespot-connect", "librespot-core", @@ -2936,9 +2937,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" dependencies = [ "futures-core", "pin-project-lite", @@ -2963,9 +2964,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.11" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ "bytes", "futures-core", diff --git a/Cargo.toml b/Cargo.toml index 7a64050e5..19a450b96 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,6 +55,7 @@ env_logger = { version = "0.11.2", default-features = false, features = ["color futures-util = { version = "0.3", default-features = false } getopts = "0.2" hyper = { version = "1.3", features = [] } +hyper-util = { version = "0.1", features = ["client"] } log = "0.4" rpassword = "7.0" serde_json = "1.0" @@ -78,8 +79,9 @@ 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"] +spotty = [] -default = ["passthrough-decoder"] +default = ["passthrough-decoder", "spotty"] [package.metadata.deb] maintainer = "librespot-org" diff --git a/src/main.rs b/src/main.rs index bde2c6d05..e7fcbdab1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,7 +16,7 @@ use sysinfo::System; use thiserror::Error; use url::Url; -#[cfg(feature = "passthrough-decoder")] +#[cfg(feature = "spotty")] use librespot::playback::mixer::softmixer::SoftMixer; #[allow(unused)] @@ -37,22 +37,24 @@ use librespot::{ }, }; -#[cfg(feature = "passthrough-decoder")] +#[cfg(feature = "spotty")] mod spotty; -#[cfg(feature = "passthrough-decoder")] +#[cfg(feature = "spotty")] use spotty::LMS; const VERSION: &str = concat!(env!("CARGO_PKG_NAME"), " v", env!("CARGO_PKG_VERSION")); -#[cfg(all(target_os = "windows", feature = "passthrough-decoder"))] -const NULLDEVICE: &str = "NUL"; -#[cfg(all(not(target_os = "windows"), feature = "passthrough-decoder"))] -const NULLDEVICE: &str = "/dev/null"; +// #[cfg(all(target_os = "windows", feature = "spotty"))] +// const NULLDEVICE: &str = "NUL"; +// #[cfg(all(not(target_os = "windows"), feature = "spotty"))] +// const NULLDEVICE: &str = "/dev/null"; #[cfg(feature = "alsa-backend")] use librespot::playback::mixer::alsamixer::AlsaMixer; +#[cfg(not(feature = "spotty"))] mod player_event_handler; +#[cfg(not(feature = "spotty"))] use player_event_handler::{run_program_on_sink_events, EventHandler}; fn device_id(name: &str) -> String { @@ -98,7 +100,7 @@ fn setup_logging(quiet: bool, verbose: bool) { } } -#[cfg(not(feature = "passthrough-decoder"))] +#[cfg(not(feature = "spotty"))] fn list_backends() { println!("Available backends: "); for (&(name, _), idx) in BACKENDS.iter().zip(0..) { @@ -200,7 +202,9 @@ struct Setup { credentials: Option, enable_discovery: bool, zeroconf_port: u16, + #[cfg(not(feature = "spotty"))] player_event_program: Option, + #[cfg(not(feature = "spotty"))] emit_sink_events: bool, zeroconf_ip: Vec, // spotty @@ -216,7 +220,7 @@ struct Setup { fn get_setup() -> Setup { const VALID_INITIAL_VOLUME_RANGE: RangeInclusive = 0..=100; - #[cfg(not(feature = "passthrough-decoder"))] + #[cfg(not(feature = "spotty"))] const VALID_VOLUME_RANGE: RangeInclusive = 0.0..=100.0; const VALID_NORMALISATION_KNEE_RANGE: RangeInclusive = 0.0..=10.0; const VALID_NORMALISATION_PREGAIN_RANGE: RangeInclusive = -10.0..=10.0; @@ -771,6 +775,7 @@ fn get_setup() -> Setup { exit(0); } + #[cfg(feature = "spotty")] if opt_present(CHECK) { spotty::check(get_version_string()); } @@ -844,9 +849,9 @@ fn get_setup() -> Setup { } } - #[cfg(not(feature = "passthrough-decoder"))] + #[cfg(not(feature = "spotty"))] let backend_name = opt_str(BACKEND); - #[cfg(not(feature = "passthrough-decoder"))] + #[cfg(not(feature = "spotty"))] if backend_name == Some("?".into()) { list_backends(); exit(0); @@ -870,7 +875,7 @@ fn get_setup() -> Setup { exit(1); }; - #[cfg(not(feature = "passthrough-decoder"))] + #[cfg(not(feature = "spotty"))] let backend = audio_backend::find(backend_name).unwrap_or_else(|| { invalid_error_msg( BACKEND, @@ -884,7 +889,7 @@ fn get_setup() -> Setup { exit(1); }); - #[cfg(not(feature = "passthrough-decoder"))] + #[cfg(not(feature = "spotty"))] let format = opt_str(FORMAT) .as_deref() .map(|format| { @@ -906,7 +911,7 @@ fn get_setup() -> Setup { let device = opt_str(DEVICE); if let Some(ref value) = device { if value == "?" { - #[cfg(not(feature = "passthrough-decoder"))] + #[cfg(not(feature = "spotty"))] backend(device, format); exit(0); } else if value.is_empty() { @@ -916,10 +921,10 @@ fn get_setup() -> Setup { #[cfg(feature = "alsa-backend")] let mixer_type = opt_str(MIXER_TYPE); - #[cfg(all(not(feature = "alsa-backend"), not(feature = "passthrough-decoder")))] + #[cfg(all(not(feature = "alsa-backend"), not(feature = "spotty")))] let mixer_type: Option = None; - #[cfg(not(feature = "passthrough-decoder"))] + #[cfg(not(feature = "spotty"))] let mixer = mixer::find(mixer_type.as_deref()).unwrap_or_else(|| { invalid_error_msg( MIXER_TYPE, @@ -932,13 +937,13 @@ fn get_setup() -> Setup { exit(1); }); - #[cfg(feature = "passthrough-decoder")] + #[cfg(feature = "spotty")] let mixer = mixer::find(Some(SoftMixer::NAME)).expect("Invalid mixer"); - #[cfg(feature = "passthrough-decoder")] + #[cfg(feature = "spotty")] let is_alsa_mixer = false; - #[cfg(not(feature = "passthrough-decoder"))] + #[cfg(not(feature = "spotty"))] let is_alsa_mixer = match mixer_type.as_deref() { #[cfg(feature = "alsa-backend")] Some(AlsaMixer::NAME) => true, @@ -1080,10 +1085,10 @@ fn get_setup() -> Setup { #[cfg(not(feature = "alsa-backend"))] let control = mixer_default_config.control; - #[cfg(feature = "passthrough-decoder")] + #[cfg(feature = "spotty")] let volume_ctrl = VolumeCtrl::Linear; - #[cfg(not(feature = "passthrough-decoder"))] + #[cfg(not(feature = "spotty"))] let volume_range = opt_str(VOLUME_RANGE) .map(|range| match range.parse::() { Ok(value) if (VALID_VOLUME_RANGE).contains(&value) => value, @@ -1122,7 +1127,7 @@ fn get_setup() -> Setup { } }); - #[cfg(not(feature = "passthrough-decoder"))] + #[cfg(not(feature = "spotty"))] let volume_ctrl = opt_str(VOLUME_CTRL) .as_deref() .map(|volume_ctrl| { @@ -1714,12 +1719,12 @@ fn get_setup() -> Setup { .unwrap_or(player_default_config.normalisation_knee_db); } - #[cfg(feature = "passthrough-decoder")] + #[cfg(feature = "spotty")] let ditherer = None; - #[cfg(not(feature = "passthrough-decoder"))] + #[cfg(not(feature = "spotty"))] let ditherer_name = opt_str(DITHER); - #[cfg(not(feature = "passthrough-decoder"))] + #[cfg(not(feature = "spotty"))] let ditherer = match ditherer_name.as_deref() { Some(value) => match value { "none" => None, @@ -1773,7 +1778,9 @@ fn get_setup() -> Setup { let authenticate = opt_present(AUTHENTICATE); + #[cfg(not(feature = "spotty"))] let player_event_program = opt_str(ONEVENT); + #[cfg(not(feature = "spotty"))] let emit_sink_events = opt_present(EMIT_SINK_EVENTS); // Spotty @@ -1782,14 +1789,14 @@ fn get_setup() -> Setup { .parse::() .unwrap_or(0.0); - let save_token = opt_str(SAVE_TOKEN).unwrap_or_else(|| "".to_string()); - let client_id = opt_str(CLIENT_ID).unwrap_or_else(|| include_str!("client_id.txt").to_string()); + let save_token = opt_str(SAVE_TOKEN).unwrap_or_else(|| "".to_string()); + let client_id = opt_str(CLIENT_ID).unwrap_or_else(|| include_str!("client_id.txt").to_string()); - let lms = LMS::new( - opt_str(LYRION_MUSIC_SERVER), - opt_str(PLAYER_MAC), - opt_str(LMS_AUTH), - ); + let lms = LMS::new( + opt_str(LYRION_MUSIC_SERVER), + opt_str(PLAYER_MAC), + opt_str(LMS_AUTH), + ); Setup { format: AudioFormat::default(), @@ -1804,7 +1811,9 @@ fn get_setup() -> Setup { credentials, enable_discovery, zeroconf_port, + #[cfg(not(feature = "spotty"))] player_event_program, + #[cfg(not(feature = "spotty"))] emit_sink_events, zeroconf_ip, @@ -1847,6 +1856,7 @@ async fn main() { let mut auto_connect_times: Vec = vec![]; let mut discovery = None; let mut connecting = false; + #[cfg(not(feature = "spotty"))] let mut _event_handler: Option = None; let mut session = Session::new(setup.session_config.clone(), setup.cache.clone()); @@ -1902,6 +1912,7 @@ async fn main() { exit(1); } + #[cfg(feature = "spotty")] if let Some(ref track_id) = setup.single_track { spotty::play_track( track_id.to_string(), @@ -1936,6 +1947,7 @@ async fn main() { (backend)(device, format) }); + #[cfg(not(feature = "spotty"))] if let Some(player_event_program) = setup.player_event_program.clone() { _event_handler = Some(EventHandler::new( player.get_player_event_channel(), @@ -1984,6 +1996,7 @@ async fn main() { } }, // Spotty auth mode: exit after saving credentials + // #[cfg(feature = "spotty")] _ = async {}, if setup.authenticate && !connecting && last_credentials.is_some() => { println!("authorized"); break; diff --git a/src/spotty.rs b/src/spotty.rs index d2fcf7060..1f375365e 100644 --- a/src/spotty.rs +++ b/src/spotty.rs @@ -219,14 +219,14 @@ impl LMS { // track_id.to_base62().unwrap_or_default() // ); // } -// PlayerEvent::Stopped { track_id, .. } => { -// #[cfg(debug_assertions)] -// info!( -// "event: stopped, track: {}", -// track_id.to_base62().unwrap_or_default() -// ); -// command = r#"["spottyconnect","stop"]"#.to_string(); -// } + // PlayerEvent::Stopped { track_id, .. } => { + // #[cfg(debug_assertions)] + // info!( + // "event: stopped, track: {}", + // track_id.to_base62().unwrap_or_default() + // ); + // command = r#"["spottyconnect","stop"]"#.to_string(); + // } PlayerEvent::Playing { track_id, play_request_id, @@ -309,27 +309,27 @@ impl LMS { auth_header = auth.trim().to_string(); } -// let req = Request::builder() -// .method(Method::POST) -// .uri(base_url.to_string()) -// .header("user-agent", VERSION.to_string()) -// .header("content-type", "application/json") -// .header("authorization", format!("Basic {}", auth_header)) -// .header("x-scanner", "1") -// .body(Body::from(json.clone())); - -// let client = Client::new(); -// let resp = client.request(req).await; - -// match resp { -// Ok(resp) => { -// #[cfg(debug_assertions)] -// info!("Response: {}", resp.status()); -// } -// Err(error) => { -// warn!("Problem posting to {} / {}: {:?}", base_url, json, error); -// } -// } + // let req = Request::builder() + // .method(Method::POST) + // .uri(base_url.to_string()) + // .header("user-agent", VERSION.to_string()) + // .header("content-type", "application/json") + // .header("authorization", format!("Basic {}", auth_header)) + // .header("x-scanner", "1") + // .body(Body::from(json.clone())); + + // let client = Client::new(); + // let resp = client.request(req).await; + + // match resp { + // Ok(resp) => { + // #[cfg(debug_assertions)] + // info!("Response: {}", resp.status()); + // } + // Err(error) => { + // warn!("Problem posting to {} / {}: {:?}", base_url, json, error); + // } + // } } } }