Repository: Spotifyd/spotifyd (language: rust)

Issue:
Volume Controllers behave weirdly
**Description**
softvol: changes it just for spotify and properly from 0 to 100 (I think), but doesnt show these changes in system volume mixer
alsa: Sets 0 volume to be around 80% actual volume so its very loud when I try to increase the volume from my phone through spotify.
alsa_linear: Properly sets it from 0 to 100, but sets system volume and not just "spotifyd" and resets it to 0 everytime I pause and play
none: Doesnt let me change it from the phone

**To Reproduce**
1. Install spotifyd
2. try all different volume controllers

**Expected behavior**
All should show spotifyd's volume on a separate slider in mixer and properly set the volume from 0 to 100

**Logs**
I can't provide logs for all four controllers

**Versions (please complete the following information):**
<!-- DO NOT use words like `latest`. Please specify the exact version/commit hash -->
- OS: Fedora 38
- Spotifyd: 0.3.5
- cargo: 1.72.0


Discussion / hints:
The behaviour you describe for `softvol` and `none` is entirely intended, since `softvol` is doing the volume adjustment within the software and not in the audio server and `none` is for when you don't want to use volume control at all.

<strike>Regarding the other two modes: Do you mean that setting the volume to 0 percent on the phone doesn't mute the audio, but causes `spotifyd` to play at 80% volume?</strike>

I just tried `alsa` and `alsa_linear` and they seem indeed to be broken currently. Will have a look at it.

Regarding the system control vs. app volume control: We are using `alsa` for that and individual app volume controls are a feature that are specific to pulseaudio and other newer sound servers, AFAIK. So such a feature would require some implementation work.
And I would argue that if you're fine with Spotify's volume control only affecting `spotifyd`'s volume, you can just use `softvol`. (although then the volume doesn't get reported to the audio server, but you can still query and change it via the MPRIS interface, if needed)

Hope, that clears things up?

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a8081550..17d887d6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,7 +12,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 ### Changed
 - Credential caching has been re-enabled. ([#1214])
 
+### Fixed
+- alsa mixer: volume calculation has been fixed ([#1229])
+
 [#1214]: https://github.com/Spotifyd/spotifyd/pull/1214
+[#1229]: https://github.com/Spotifyd/spotifyd/pull/1229
 [#1228]: https://github.com/Spotifyd/spotifyd/pull/1228
 
 ## [0.3.5]
diff --git a/src/alsa_mixer.rs b/src/alsa_mixer.rs
index 09c40ebf..ed7f1b70 100644
--- a/src/alsa_mixer.rs
+++ b/src/alsa_mixer.rs
@@ -25,9 +25,9 @@ impl AlsaMixer {
 
         let volume_steps = (max - min) as f64;
         let normalised_volume = if self.linear_scaling {
-            ((f64::from(volume) / f64::from(u16::MAX)) * volume_steps) as i64 + min
+            (((volume as f64) / (u16::MAX as f64)) * volume_steps) as i64 + min
         } else {
-            (f64::from(volume).log(f64::from(u16::MAX)) * volume_steps).floor() as i64 + min
+            ((volume as f64 + 1.0).log((u16::MAX as f64) + 1.0) * volume_steps).floor() as i64 + min
         };
 
         elem.set_playback_volume_all(normalised_volume)?;
@@ -55,8 +55,8 @@ impl Mixer for AlsaMixer {
                 elem.get_playback_volume(alsa::mixer::SelemChannelId::mono())
                     .ok()
                     .map(|volume| {
-                        let volume_steps = max - min + 1;
-                        ((volume - min) * (0xFFFF / volume_steps)) as u16
+                        (((volume - min) as f64 / (max - min) as f64) * (u16::MAX as f64)).floor()
+                            as u16
                     })
             });
         match vol {


Test patch: