From 2abaab1769ee2b47f33d820e7dde23227eced556 Mon Sep 17 00:00:00 2001 From: Fabian Tobias Rajter Date: Sat, 5 Dec 2015 18:12:44 +0100 Subject: [PATCH 1/2] Implemented optional volume display/setting as in AlsaMixer. --- i3pystatus/alsa.py | 87 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 81 insertions(+), 6 deletions(-) diff --git a/i3pystatus/alsa.py b/i3pystatus/alsa.py index f53815b..52e1180 100644 --- a/i3pystatus/alsa.py +++ b/i3pystatus/alsa.py @@ -1,4 +1,5 @@ from alsaaudio import Mixer, ALSAAudioError +from math import exp, log, log10, ceil, floor from i3pystatus import IntervalModule @@ -28,7 +29,8 @@ class ALSA(IntervalModule): ("increment", "integer percentage of max volume to in/decrement volume on mousewheel"), "muted", "unmuted", "color_muted", "color", - "channel" + "channel", + ("map_volume", "volume display/setting as in AlsaMixer. increment option is ignored then.") ) muted = "M" @@ -43,6 +45,8 @@ class ALSA(IntervalModule): channel = 0 increment = 5 + map_volume = False + alsamixer = None has_mute = True @@ -63,6 +67,11 @@ class ALSA(IntervalModule): "mixer": self.mixer, } + self.dbRng = self.alsamixer.getrange() + + self.dbMin = self.dbRng[0] + self.dbMax = self.dbRng[1] + def create_mixer(self): self.alsamixer = Mixer( control=self.mixer, id=self.mixer_id, cardindex=self.card) @@ -74,8 +83,9 @@ class ALSA(IntervalModule): if self.has_mute: muted = self.alsamixer.getmute()[self.channel] == 1 - self.fdict["volume"] = self.alsamixer.getvolume()[self.channel] + self.fdict["volume"] = self.get_cur_volume() self.fdict["muted"] = self.muted if muted else self.unmuted + self.fdict["db"] = self.get_db() if muted and self.format_muted is not None: output_format = self.format_muted @@ -92,10 +102,75 @@ class ALSA(IntervalModule): muted = self.alsamixer.getmute()[self.channel] self.alsamixer.setmute(not muted) + def get_cur_volume(self): + if self.map_volume: + dbCur = self.get_db() * 100.0 + dbMin = self.dbMin * 100.0 + dbMax = self.dbMax * 100.0 + + dbCur_norm = self.exp10((dbCur - dbMax) / 6000.0) + dbMin_norm = self.exp10((dbMin - dbMax) / 6000.0) + + vol = (dbCur_norm - dbMin_norm) / (1 - dbMin_norm) + vol = int(round(vol * 100,0)) + + return vol + else: + return self.alsamixer.getvolume()[self.channel] + + def get_new_volume(self, direction): + if direction == "inc": + volume = (self.fdict["volume"] + 1) / 100 + elif direction == "dec": + volume = (self.fdict["volume"] - 1) / 100 + + dbMin = self.dbMin * 100 + dbMax = self.dbMax * 100 + + dbMin_norm = self.exp10((dbMin - dbMax) / 6000.0) + + vol = volume * (1 - dbMin_norm) + dbMin_norm + + if direction == "inc": + dbNew = min(self.dbMax, ceil(((6000.0 * log10(vol)) + dbMax) / 100)) + elif direction == "dec": + dbNew = max(self.dbMin, floor(((6000.0 * log10(vol)) + dbMax) / 100)) + + volNew = int(round(self.map_db(dbNew, self.dbMin, self.dbMax, 0, 100),0)) + + return volNew + def increase_volume(self, delta=None): - vol = self.alsamixer.getvolume()[self.channel] - self.alsamixer.setvolume(min(100, vol + (delta if delta else self.increment))) + if self.map_volume: + vol = self.get_new_volume("inc") + + self.alsamixer.setvolume(vol) + else: + vol = self.alsamixer.getvolume()[self.channel] + self.alsamixer.setvolume(min(100, vol + (delta if delta else self.increment))) def decrease_volume(self, delta=None): - vol = self.alsamixer.getvolume()[self.channel] - self.alsamixer.setvolume(max(0, vol - (delta if delta else self.increment))) + if self.map_volume: + vol = self.get_new_volume("dec") + + self.alsamixer.setvolume(vol) + else: + vol = self.alsamixer.getvolume()[self.channel] + self.alsamixer.setvolume(max(0, vol - (delta if delta else self.increment))) + + def get_db(self): + db = (((self.dbMax - self.dbMin) / 100) * self.alsamixer.getvolume()[self.channel]) + self.dbMin + db = int(round(db,0)) + + return db + + def map_db(self, value, dbMin, dbMax, volMin, volMax): + dbRange = dbMax - dbMin + volRange = volMax - volMin + + volScaled = float(value - dbMin) / float(dbRange) + + return volMin + (volScaled * volRange) + + def exp10(self, x): + return exp(x * log(10)) From 1376f5f6bed0e278e5efd635b216f8a9ca3472e2 Mon Sep 17 00:00:00 2001 From: Fabian Tobias Rajter Date: Sat, 5 Dec 2015 18:31:45 +0100 Subject: [PATCH 2/2] Changed cosmetical things Travis CI was complaining about. --- i3pystatus/alsa.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/i3pystatus/alsa.py b/i3pystatus/alsa.py index 52e1180..ba52e74 100644 --- a/i3pystatus/alsa.py +++ b/i3pystatus/alsa.py @@ -1,5 +1,5 @@ from alsaaudio import Mixer, ALSAAudioError -from math import exp, log, log10, ceil, floor +from math import exp, log, log10, ceil, floor from i3pystatus import IntervalModule @@ -83,7 +83,7 @@ class ALSA(IntervalModule): if self.has_mute: muted = self.alsamixer.getmute()[self.channel] == 1 - self.fdict["volume"] = self.get_cur_volume() + self.fdict["volume"] = self.get_cur_volume() self.fdict["muted"] = self.muted if muted else self.unmuted self.fdict["db"] = self.get_db() @@ -107,16 +107,16 @@ class ALSA(IntervalModule): dbCur = self.get_db() * 100.0 dbMin = self.dbMin * 100.0 dbMax = self.dbMax * 100.0 - + dbCur_norm = self.exp10((dbCur - dbMax) / 6000.0) dbMin_norm = self.exp10((dbMin - dbMax) / 6000.0) vol = (dbCur_norm - dbMin_norm) / (1 - dbMin_norm) - vol = int(round(vol * 100,0)) + vol = int(round(vol * 100, 0)) return vol else: - return self.alsamixer.getvolume()[self.channel] + return self.alsamixer.getvolume()[self.channel] def get_new_volume(self, direction): if direction == "inc": @@ -128,15 +128,15 @@ class ALSA(IntervalModule): dbMax = self.dbMax * 100 dbMin_norm = self.exp10((dbMin - dbMax) / 6000.0) - + vol = volume * (1 - dbMin_norm) + dbMin_norm - + if direction == "inc": dbNew = min(self.dbMax, ceil(((6000.0 * log10(vol)) + dbMax) / 100)) elif direction == "dec": dbNew = max(self.dbMin, floor(((6000.0 * log10(vol)) + dbMax) / 100)) - volNew = int(round(self.map_db(dbNew, self.dbMin, self.dbMax, 0, 100),0)) + volNew = int(round(self.map_db(dbNew, self.dbMin, self.dbMax, 0, 100), 0)) return volNew @@ -160,7 +160,7 @@ class ALSA(IntervalModule): def get_db(self): db = (((self.dbMax - self.dbMin) / 100) * self.alsamixer.getvolume()[self.channel]) + self.dbMin - db = int(round(db,0)) + db = int(round(db, 0)) return db