added volume manager for pipewire and i3blocks
This commit is contained in:
parent
b9b4fd6ddc
commit
c49dd68b2f
|
@ -34,6 +34,11 @@ A collection of standalone python scripts for the slightly more complicated thin
|
|||
* call `cpu.py 1` to get the avg from last min
|
||||
* call `cpu.py 5` to get the avg from last 5 min
|
||||
* call `cpu.py 15` to get the avg from last 15 min
|
||||
* **volume.py**: Now compatible with *pipewire*, parses output of `pactl` to output activ sink and current volume to i3blocks and manages music volume hotkeys.
|
||||
* call `volume.py` without args to output status for i3blocks
|
||||
* call `volume.py vol_up` to increase volume by 5%
|
||||
* call `volume.py vol_down` to decrease volume by 5%
|
||||
* call `volume.py mute` to toggle mute
|
||||
|
||||
|
||||
## i3block_shell
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
handler for media keys
|
||||
integrated with pipewire by parsing pactl
|
||||
"""
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
from time import sleep
|
||||
|
||||
# signal id to update i3blocks
|
||||
I3BLOCKS_SIGNAL_ID = 10
|
||||
|
||||
|
||||
def get_status():
|
||||
""" returns the activ sink pased in a dict """
|
||||
# get list of sinks
|
||||
state = subprocess.run(["pactl", "list", "sinks"], capture_output=True)
|
||||
state_str = state.stdout.decode()
|
||||
sinks = state_str.split('\n\n')
|
||||
# loop through sinks
|
||||
sinks_dict_list = []
|
||||
for sink in sinks:
|
||||
sink_lines = sink.split('\n')
|
||||
# build sink dict
|
||||
sink_dict = {}
|
||||
for i in sink_lines:
|
||||
if ':' in i:
|
||||
key, value = i.split(':', maxsplit=1)
|
||||
elif '=' in i:
|
||||
key, value = i.split('=')
|
||||
else:
|
||||
continue
|
||||
key = key.strip().lower()
|
||||
value = value.strip().strip('"')
|
||||
if value:
|
||||
sink_dict[key] = value
|
||||
# append to list
|
||||
sinks_dict_list.append(sink_dict)
|
||||
# find active
|
||||
if len(sinks_dict_list) == 1:
|
||||
activ_sink = sinks_dict_list[0]
|
||||
else:
|
||||
for sink_dict in sinks_dict_list:
|
||||
sink_name = sink_dict['name']
|
||||
if 'bluez' in sink_name:
|
||||
activ_sink = sink_dict
|
||||
break
|
||||
# return activ
|
||||
return activ_sink
|
||||
|
||||
|
||||
def get_vol(activ_sink):
|
||||
""" get the current volume level of activ sink """
|
||||
vol_string = activ_sink['volume']
|
||||
vol_list = [i for i in vol_string.split(' / ') if '%' in i]
|
||||
vol = int(vol_list[0].strip().strip('%'))
|
||||
return vol
|
||||
|
||||
|
||||
def print_status(activ_sink):
|
||||
""" print status for i3 blocks """
|
||||
mute = activ_sink['mute']
|
||||
# based on sink
|
||||
if 'bluez' in activ_sink['name']:
|
||||
# bluetooth
|
||||
icon = ''
|
||||
elif activ_sink['active port'] == 'analog-output-headphones':
|
||||
# headphones
|
||||
icon = ''
|
||||
elif activ_sink['active port'] == 'analog-output-speaker':
|
||||
# speaker
|
||||
if mute == 'no':
|
||||
icon = ''
|
||||
else:
|
||||
icon = ''
|
||||
# color
|
||||
if mute == 'no':
|
||||
color = "#ffffff"
|
||||
vol = str(get_vol(activ_sink)) + '%'
|
||||
else:
|
||||
color = "#404040"
|
||||
vol = "MUTE"
|
||||
# print three lines
|
||||
print(f'{icon} {vol}')
|
||||
print(f'{icon}')
|
||||
print(color)
|
||||
|
||||
|
||||
def mute(activ_sink):
|
||||
""" toggle mute of activ sink """
|
||||
sink_id = activ_sink['object.id']
|
||||
subprocess.call(['pactl', 'set-sink-mute', sink_id, 'toggle'])
|
||||
|
||||
|
||||
def vol_up(activ_sink):
|
||||
""" increase vol in 5% increments """
|
||||
sink_id = activ_sink['object.id']
|
||||
vol = get_vol(activ_sink)
|
||||
# if uneven vol level
|
||||
if vol % 5 == 0:
|
||||
target_vol = vol + 5
|
||||
else:
|
||||
target_vol = vol + 5 - (vol % 5)
|
||||
# how many times to loop
|
||||
iterations = target_vol - vol
|
||||
for _ in range(iterations):
|
||||
subprocess.call(['pactl', 'set-sink-volume', sink_id, '+1%'])
|
||||
sleep(0.1)
|
||||
|
||||
|
||||
def vol_down(activ_sink):
|
||||
""" decrese vol in 5% increments """
|
||||
sink_id = activ_sink['object.id']
|
||||
vol = get_vol(activ_sink)
|
||||
# if uneven vol level
|
||||
if vol % 5 == 0:
|
||||
target_vol = vol - 5
|
||||
else:
|
||||
target_vol = vol - (vol % 5)
|
||||
# how many times to loop
|
||||
iterations = vol - target_vol
|
||||
for _ in range(iterations):
|
||||
subprocess.call(['pactl', 'set-sink-volume', sink_id, '-1%'])
|
||||
sleep(0.1)
|
||||
|
||||
|
||||
def main():
|
||||
""" main to run """
|
||||
# parse args
|
||||
args = sys.argv
|
||||
activ_sink = get_status()
|
||||
# if args
|
||||
if len(args) > 1:
|
||||
arg = args[1]
|
||||
if arg == 'vol_up':
|
||||
vol_up(activ_sink)
|
||||
elif arg == 'vol_down':
|
||||
vol_down(activ_sink)
|
||||
elif arg == 'mute':
|
||||
mute(activ_sink)
|
||||
activ_sink = get_status()
|
||||
subprocess.call(['pkill', '-RTMIN+' + str(I3BLOCKS_SIGNAL_ID), 'i3blocks'])
|
||||
# status
|
||||
print_status(activ_sink)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Loading…
Reference in New Issue