a705adf207
With multiple devices, extracting mute status and volumes failed (because the loop would continue even after it found the correct device)
104 lines
3.3 KiB
Python
104 lines
3.3 KiB
Python
# pylint: disable=C0111,R0903
|
|
|
|
"""Displays volume and mute status of PulseAudio devices.
|
|
|
|
Aliases: pasink, pasource
|
|
"""
|
|
|
|
import re
|
|
|
|
import bumblebee.util
|
|
import bumblebee.input
|
|
import bumblebee.output
|
|
import bumblebee.engine
|
|
|
|
ALIASES = [ "pasink", "pasource" ]
|
|
|
|
class Module(bumblebee.engine.Module):
|
|
def __init__(self, engine, config):
|
|
super(Module, self).__init__(engine, config,
|
|
bumblebee.output.Widget(full_text=self.volume)
|
|
)
|
|
|
|
self._left = 0
|
|
self._right = 0
|
|
self._mono = 0
|
|
self._mute = False
|
|
channel = "sink" if self.name == "pasink" else "source"
|
|
|
|
self._patterns = [
|
|
{ "expr": "Name:", "callback": (lambda line: False) },
|
|
{ "expr": "Mute:", "callback": (lambda line: self.mute(False if " no" in line.lower() else True)) },
|
|
{ "expr": "Volume:", "callback": self.getvolume },
|
|
]
|
|
|
|
engine.input.register_callback(self, button=bumblebee.input.RIGHT_MOUSE, cmd="pavucontrol")
|
|
|
|
events = [
|
|
{ "type": "mute", "action": "toggle", "button": bumblebee.input.LEFT_MOUSE },
|
|
{ "type": "volume", "action": "+2%", "button": bumblebee.input.WHEEL_UP },
|
|
{ "type": "volume", "action": "-2%", "button": bumblebee.input.WHEEL_DOWN },
|
|
]
|
|
|
|
for event in events:
|
|
engine.input.register_callback(self, button=event["button"],
|
|
cmd="pactl set-{}-{} @DEFAULT_{}@ {}".format(channel, event["type"],
|
|
channel.upper(), event["action"]))
|
|
|
|
def mute(self, value):
|
|
self._mute = value
|
|
|
|
def getvolume(self, line):
|
|
if "mono" in line:
|
|
m = re.search(r'mono:.*\s*\/\s*(\d+)%', line)
|
|
if m:
|
|
self._mono = m.group(1)
|
|
else:
|
|
m = re.search(r'left:.*\s*\/\s*(\d+)%.*right:.*\s*\/\s*(\d+)%', line)
|
|
if m:
|
|
self._left = m.group(1)
|
|
self._right = m.group(2)
|
|
return True
|
|
|
|
def _default_device(self):
|
|
output = bumblebee.util.execute("pactl info")
|
|
pattern = "Default Sink: " if self.name == "pasink" else "Default Source: "
|
|
for line in output.split("\n"):
|
|
if line.startswith(pattern):
|
|
return line.replace(pattern, "")
|
|
return "n/a"
|
|
|
|
def volume(self, widget):
|
|
if int(self._mono) > 0:
|
|
return "{}%".format(self._mono)
|
|
elif self._left == self._right:
|
|
return "{}%".format(self._left)
|
|
else:
|
|
return "{}%/{}%".format(self._left, self._right)
|
|
return "n/a"
|
|
|
|
def update(self, widgets):
|
|
channel = "sinks" if self.name == "pasink" else "sources"
|
|
device = self._default_device()
|
|
|
|
result = bumblebee.util.execute("pactl list {}".format(channel))
|
|
found = False
|
|
|
|
for line in result.split("\n"):
|
|
if device in line:
|
|
found = True
|
|
continue
|
|
if found == False:
|
|
continue
|
|
for pattern in self._patterns:
|
|
if not pattern["expr"] in line:
|
|
continue
|
|
if pattern["callback"](line) == False and found == True:
|
|
return
|
|
|
|
def state(self, widget):
|
|
if self._mute:
|
|
return [ "warning", "muted" ]
|
|
return [ "unmuted" ]
|
|
|
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|