From bede564618e78d2a4eee5af329178be89ae34412 Mon Sep 17 00:00:00 2001
From: Max Kellermann <max@musicpd.org>
Date: Sat, 10 Feb 2018 09:07:51 +0100
Subject: [PATCH] mixer/alsa: work around rounding error at volume 0

Due to rounding errors, a slightly negative value can be passed to
set_normalized_volume(), which will make the log10() call fail.
Actually, volume 0 is already failing because log10(0) is illegal.  So
let's fix this by implementing two corner cases: <=0 and >=100.

Closes #212
---
 NEWS                               | 2 ++
 src/mixer/plugins/volume_mapping.c | 7 +++++++
 2 files changed, 9 insertions(+)

diff --git a/NEWS b/NEWS
index 9ee17962a..190ef1015 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,8 @@
 ver 0.20.17 (not yet released)
 * output
   - alsa: fix crash bug with 8 channels
+* mixer
+  - alsa: fix rounding error at volume 0
 * fix real-time and idle scheduling with Musl
 * Android
   - fix compatibility with Android 4.0
diff --git a/src/mixer/plugins/volume_mapping.c b/src/mixer/plugins/volume_mapping.c
index 4e559cf54..2078d346d 100644
--- a/src/mixer/plugins/volume_mapping.c
+++ b/src/mixer/plugins/volume_mapping.c
@@ -139,6 +139,13 @@ static int set_normalized_volume(snd_mixer_elem_t *elem,
 		return set_raw[ctl_dir](elem, value);
 	}
 
+	/* two special cases to avoid rounding errors at 0% and
+	   100% */
+	if (volume <= 0)
+		return set_dB[ctl_dir](elem, min, dir);
+	else if (volume >= 100)
+		return set_dB[ctl_dir](elem, max, dir);
+
 	if (use_linear_dB_scale(min, max)) {
 		value = lrint_dir(volume * (max - min), dir) + min;
 		return set_dB[ctl_dir](elem, value, dir);