- snd_mixer_selem_get_playback_volume(elem, 0, &val);
- if (max != 100) {
- float avgf = ((float)val / max) * 100;
+ err = snd_mixer_selem_get_playback_dB_range(elem, &min, &max) ||
+ snd_mixer_selem_get_playback_dB(elem, 0, &val);
+ if (err != 0 || min >= max) {
+ err = snd_mixer_selem_get_playback_volume_range(elem, &min, &max) ||
+ snd_mixer_selem_get_playback_volume(elem, 0, &val);
+ force_linear = true;
+ }
+
+ if (err != 0) {
+ fprintf(stderr, "i3status: ALSA: Cannot get playback volume.\n");
+ goto out;
+ }
+
+ /* Use linear mapping for raw register values or small ranges of 24 dB */
+ if (force_linear || max - min <= MAX_LINEAR_DB_SCALE * 100) {
+ float avgf = ((float)(val - min) / (max - min)) * 100;