diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d3bd886..b65f536e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,10 @@ https://github.com/librespot-org/librespot - [core] Cache resolved access points during runtime (breaking) - [core] `FileId` is moved out of `SpotifyId`. For now it will be re-exported. - [core] Report actual platform data on login +- [main] `autoplay {on|off}` now acts as an override. If unspecified, `librespot` + now follows the setting in the Connect client that controls it. (breaking) +- [metadata] Most metadata is now retrieved with the `spclient` (breaking) +- [metadata] Playlists are moved to the `playlist4_external` protobuf (breaking) - [playback] The audio decoder has been switched from `lewton` to `Symphonia`. This improves the Vorbis sound quality, adds support for MP3 as well as for FLAC in the future. (breaking) @@ -56,8 +60,6 @@ https://github.com/librespot-org/librespot - [playback] The passthrough decoder is now feature-gated (breaking) - [playback] `rodio`: call play and pause - [protocol] protobufs have been updated -- [metadata] Most metadata is now retrieved with the `spclient` (breaking) -- [metadata] Playlists are moved to the `playlist4_external` protobuf (breaking) ### Added @@ -100,13 +102,6 @@ https://github.com/librespot-org/librespot - [playback] Handle disappearing and invalid devices better - [playback] Handle seek, pause, and play commands while loading -### Removed - -- [main] `autoplay` is no longer a command-line option. Instead, librespot now - follows the setting in the Connect client that controls it. Applications that - use librespot as a library without Connect should now instead use the - 'autoplay' user attribute in the session. - ## [0.4.2] - 2022-07-29 Besides a couple of small fixes, this point release is mainly to blacklist the diff --git a/connect/src/spirc.rs b/connect/src/spirc.rs index a9144568..31223921 100644 --- a/connect/src/spirc.rs +++ b/connect/src/spirc.rs @@ -772,6 +772,12 @@ impl SpircTask { fn handle_user_attributes_mutation(&mut self, mutation: UserAttributesMutation) { for attribute in mutation.get_fields().iter() { let key = attribute.get_name(); + + if key == "autoplay" && self.session.config().autoplay.is_some() { + trace!("Autoplay override active. Ignoring mutation."); + continue; + } + if let Some(old_value) = self.session.user_data().attributes.get(key) { let new_value = match old_value.as_ref() { "0" => "1", diff --git a/core/src/config.rs b/core/src/config.rs index 7d45cdd7..ada5354b 100644 --- a/core/src/config.rs +++ b/core/src/config.rs @@ -13,6 +13,7 @@ pub struct SessionConfig { pub proxy: Option, pub ap_port: Option, pub tmp_dir: PathBuf, + pub autoplay: Option, } impl Default for SessionConfig { @@ -31,6 +32,7 @@ impl Default for SessionConfig { proxy: None, ap_port: None, tmp_dir: std::env::temp_dir(), + autoplay: None, } } } diff --git a/core/src/session.rs b/core/src/session.rs index 82c9e4a8..1936467e 100644 --- a/core/src/session.rs +++ b/core/src/session.rs @@ -438,6 +438,10 @@ impl Session { } pub fn autoplay(&self) -> bool { + if let Some(overide) = self.config().autoplay { + return overide; + } + match self.get_user_attribute("autoplay") { Some(value) => matches!(&*value, "1"), None => false, diff --git a/src/main.rs b/src/main.rs index aac7119a..5cd19bd2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -197,6 +197,7 @@ fn get_setup() -> Setup { const VALID_NORMALISATION_RELEASE_RANGE: RangeInclusive = 1..=1000; const AP_PORT: &str = "ap-port"; + const AUTOPLAY: &str = "autoplay"; const BACKEND: &str = "backend"; const BITRATE: &str = "bitrate"; const CACHE: &str = "cache"; @@ -242,6 +243,7 @@ fn get_setup() -> Setup { // Mostly arbitrary. const AP_PORT_SHORT: &str = "a"; + const AUTOPLAY_SHORT: &str = "A"; const BACKEND_SHORT: &str = "B"; const BITRATE_SHORT: &str = "b"; const SYSTEM_CACHE_SHORT: &str = "C"; @@ -562,6 +564,12 @@ fn get_setup() -> Setup { AP_PORT, "Connect to an AP with a specified port 1 - 65535. Available ports are usually 80, 443 and 4070.", "PORT", + ) + .optopt( + AUTOPLAY_SHORT, + AUTOPLAY, + "Explicitly set autoplay {on|off}. Defaults to following the client setting.", + "OVERRIDE", ); #[cfg(feature = "passthrough-decoder")] @@ -1140,6 +1148,26 @@ fn get_setup() -> Setup { 0 }; + // #1046: not all connections are supplied an `autoplay` user attribute to run statelessly. + // This knob allows for a manual override. + let autoplay = match opt_str(AUTOPLAY) { + Some(value) => match value.as_ref() { + "on" => Some(true), + "off" => Some(false), + _ => { + invalid_error_msg( + AUTOPLAY, + AUTOPLAY_SHORT, + &opt_str(AUTOPLAY).unwrap_or_default(), + "on, off", + "", + ); + exit(1); + } + }, + None => SessionConfig::default().autoplay, + }; + let connect_config = { let connect_default_config = ConnectConfig::default(); @@ -1293,7 +1321,8 @@ fn get_setup() -> Setup { } }), tmp_dir, - ..SessionConfig::default() + autoplay, + ..SessionConfig::default() }; let player_config = {