Browse Source

Refactor Volume control, allow for a fixed volume option (#447)

Refactored the old `--linear-volume` flag to a more generic `--volume-ctrl` flag that takes the options of `[linear, log, fixed]`. It defaults as previously to log.
Ash 4 years ago
parent
commit
f0b3b2c7e8
3 changed files with 58 additions and 19 deletions
  1. 19 13
      connect/src/spirc.rs
  2. 27 1
      core/src/config.rs
  3. 12 5
      src/main.rs

+ 19 - 13
connect/src/spirc.rs

@@ -14,8 +14,7 @@ use crate::playback::mixer::Mixer;
 use crate::playback::player::{Player, PlayerEvent, PlayerEventChannel};
 use crate::protocol;
 use crate::protocol::spirc::{DeviceState, Frame, MessageType, PlayStatus, State, TrackRef};
-
-use librespot_core::config::ConnectConfig;
+use librespot_core::config::{ConnectConfig, VolumeCtrl};
 use librespot_core::mercury::MercuryError;
 use librespot_core::session::Session;
 use librespot_core::spotify_id::{SpotifyAudioType, SpotifyId, SpotifyIdError};
@@ -80,7 +79,7 @@ pub enum SpircCommand {
 }
 
 struct SpircTaskConfig {
-    linear_volume: bool,
+    volume_ctrl: VolumeCtrl,
     autoplay: bool,
 }
 
@@ -161,7 +160,11 @@ fn initial_device_state(config: ConnectConfig) -> DeviceState {
                 msg.set_typ(protocol::spirc::CapabilityType::kVolumeSteps);
                 {
                     let repeated = msg.mut_intValue();
-                    repeated.push(64)
+                    if let VolumeCtrl::Fixed = config.volume_ctrl {
+                        repeated.push(0)
+                    } else {
+                        repeated.push(64)
+                    }
                 };
                 msg
             };
@@ -170,7 +173,7 @@ fn initial_device_state(config: ConnectConfig) -> DeviceState {
                 msg.set_typ(protocol::spirc::CapabilityType::kSupportsPlaylistV2);
                 {
                     let repeated = msg.mut_intValue();
-                    repeated.push(64)
+                    repeated.push(1)
                 };
                 msg
             };
@@ -230,12 +233,14 @@ fn calc_logarithmic_volume(volume: u16) -> u16 {
     val
 }
 
-fn volume_to_mixer(volume: u16, linear_volume: bool) -> u16 {
-    if linear_volume {
-        debug!("linear volume: {}", volume);
-        volume
-    } else {
-        calc_logarithmic_volume(volume)
+fn volume_to_mixer(volume: u16, volume_ctrl: &VolumeCtrl) -> u16 {
+    match volume_ctrl {
+        VolumeCtrl::Linear => {
+            debug!("linear volume: {}", volume);
+            volume
+        }
+        VolumeCtrl::Log => calc_logarithmic_volume(volume),
+        VolumeCtrl::Fixed => volume,
     }
 }
 
@@ -274,9 +279,10 @@ impl Spirc {
 
         let volume = config.volume;
         let task_config = SpircTaskConfig {
-            linear_volume: config.linear_volume,
+            volume_ctrl: config.volume_ctrl.to_owned(),
             autoplay: config.autoplay,
         };
+
         let device = initial_device_state(config);
 
         let player_events = player.get_player_event_channel();
@@ -1292,7 +1298,7 @@ impl SpircTask {
     fn set_volume(&mut self, volume: u16) {
         self.device.set_volume(volume as u32);
         self.mixer
-            .set_volume(volume_to_mixer(volume, self.config.linear_volume));
+            .set_volume(volume_to_mixer(volume, &self.config.volume_ctrl));
         if let Some(cache) = self.session.cache() {
             cache.save_volume(Volume { volume })
         }

+ 27 - 1
core/src/config.rs

@@ -84,6 +84,32 @@ pub struct ConnectConfig {
     pub name: String,
     pub device_type: DeviceType,
     pub volume: u16,
-    pub linear_volume: bool,
+    pub volume_ctrl: VolumeCtrl,
     pub autoplay: bool,
 }
+
+#[derive(Clone, Debug)]
+pub enum VolumeCtrl {
+    Linear,
+    Log,
+    Fixed,
+}
+
+impl FromStr for VolumeCtrl {
+    type Err = ();
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        use self::VolumeCtrl::*;
+        match s.to_lowercase().as_ref() {
+            "linear" => Ok(Linear),
+            "log" => Ok(Log),
+            "fixed" => Ok(Fixed),
+            _ => Err(()),
+        }
+    }
+}
+
+impl Default for VolumeCtrl {
+    fn default() -> VolumeCtrl {
+        VolumeCtrl::Linear
+    }
+}

+ 12 - 5
src/main.rs

@@ -15,7 +15,7 @@ use url::Url;
 
 use librespot::core::authentication::{get_credentials, Credentials};
 use librespot::core::cache::Cache;
-use librespot::core::config::{ConnectConfig, DeviceType, SessionConfig};
+use librespot::core::config::{ConnectConfig, DeviceType, SessionConfig, VolumeCtrl};
 use librespot::core::session::Session;
 use librespot::core::version;
 
@@ -173,10 +173,11 @@ fn setup(args: &[String]) -> Setup {
             "Pregain (dB) applied by volume normalisation",
             "PREGAIN",
         )
-        .optflag(
+        .optopt(
             "",
-            "linear-volume",
-            "increase volume linear instead of logarithmic.",
+            "volume-ctrl",
+            "Volume control type - [linear, log, fixed]. Default is logarithmic",
+            "VOLUME_CTRL"
         )
         .optflag(
             "",
@@ -337,11 +338,17 @@ fn setup(args: &[String]) -> Setup {
             .map(|device_type| DeviceType::from_str(device_type).expect("Invalid device type"))
             .unwrap_or(DeviceType::default());
 
+        let volume_ctrl = matches
+            .opt_str("volume-ctrl")
+            .as_ref()
+            .map(|volume_ctrl| VolumeCtrl::from_str(volume_ctrl).expect("Invalid volume ctrl type"))
+            .unwrap_or(VolumeCtrl::default());
+
         ConnectConfig {
             name: name,
             device_type: device_type,
             volume: initial_volume,
-            linear_volume: matches.opt_present("linear-volume"),
+            volume_ctrl: volume_ctrl,
             autoplay: matches.opt_present("autoplay"),
         }
     };