diff --git a/IoTuring/Entity/Deployments/Volume/Volume.py b/IoTuring/Entity/Deployments/Volume/Volume.py index 7870d715e..c10f12562 100644 --- a/IoTuring/Entity/Deployments/Volume/Volume.py +++ b/IoTuring/Entity/Deployments/Volume/Volume.py @@ -2,7 +2,7 @@ from IoTuring.Entity.Entity import Entity from IoTuring.Entity.EntityData import EntityCommand, EntitySensor -from IoTuring.Entity.ValueFormat import ValueFormatter, ValueFormatterOptions +from IoTuring.Entity.ValueFormat import ValueFormatterOptions from IoTuring.MyApp.SystemConsts import OperatingSystemDetection as OsD KEY_STATE = 'volume_state' @@ -20,19 +20,18 @@ OsD.MACOS: 'osascript -e "set volume output volume {}"' } +UNMUTE_PREFIX_LINUX = 'pactl set-sink-mute @DEFAULT_SINK@ 0' + class Volume(Entity): NAME = "Volume" def Initialize(self): - # Extra attributes only on macos: - extra_attributes = OsD.IsMacos() - # Register: self.RegisterEntitySensor(EntitySensor( self, KEY_STATE, - supportsExtraAttributes=extra_attributes, + supportsExtraAttributes=True, valueFormatterOptions=VALUEFORMATTEROPTIONS_PERCENTAGE_ROUND0)) self.RegisterEntityCommand(EntityCommand( self, KEY_CMD, self.Callback, KEY_STATE)) @@ -41,14 +40,29 @@ def Update(self): if OsD.IsMacos(): self.UpdateMac() elif OsD.IsLinux(): - # Example: 'Volume: front-left: 39745 / 61% / -13,03 dB, ... - # Only care about the first percent. - p = self.RunCommand(command="pactl get-sink-volume @DEFAULT_SINK@", + # Check if it's muted: + p = self.RunCommand(command="pactl get-sink-mute @DEFAULT_SINK@", shell=True) - m = re.search(r"/ +(\d{1,3})% /", p.stdout) - if m: - volume = m.group(1) - self.SetEntitySensorValue(KEY_STATE, volume) + output_muted = bool(re.search("Mute: yes", p.stdout)) + + if output_muted: + output_volume = 0 + + else: + # Example: 'Volume: front-left: 39745 / 61% / -13,03 dB, ... + # Only care about the first percent. + p = self.RunCommand(command="pactl get-sink-volume @DEFAULT_SINK@", + shell=True) + m = re.search(r"/ +(\d{1,3})% /", p.stdout) + + if not m: + raise Exception(f"Error getting volume from {p.stdout}") + + output_volume = m.group(1) + + self.SetEntitySensorValue(KEY_STATE, output_volume) + self.SetEntitySensorExtraAttribute( + KEY_STATE, EXTRA_KEY_MUTED_OUTPUT, output_muted) def Callback(self, message): payloadString = message.payload.decode('utf-8') @@ -57,9 +71,15 @@ def Callback(self, message): volume = int(payloadString) if not 0 <= volume <= 100: raise Exception('Incorrect payload!') - else: - self.RunCommand(command=commands[OsD.GetOs()].format(volume), - shell=True) + + cmd = commands[OsD.GetOs()] + + # Unmute on Linux: + if 0 < volume and OsD.IsLinux(): + cmd = UNMUTE_PREFIX_LINUX + " && " + cmd + + self.RunCommand(command=cmd.format(volume), + shell=True) def UpdateMac(self): # result like: output volume:44, input volume:89, alert volume:100, output muted:false