Skip to content

Instantly share code, notes, and snippets.

@shitpoet
Created May 13, 2025 20:01
Show Gist options
  • Save shitpoet/b029c89bd62cbf6339c77ae7025ffc19 to your computer and use it in GitHub Desktop.
Save shitpoet/b029c89bd62cbf6339c77ae7025ffc19 to your computer and use it in GitHub Desktop.
Toggle keyboard led according to PulseAudio/Pipewire mic muted/unmuted state [HP ProBook 450 G10]
#!/usr/bin/env python3
# required `light` utility and correct configuration of its parameters
# in `update_keyboard_mic_mute_led` function
# the current settings work on HP ProBook 450 G10
import time
import subprocess
from subprocess import Popen
from pulsectl import Pulse, PulseLoopStop, PulseDisconnected
def spawn(cmd): # doen't block
Popen([cmd], shell=True)
def sh(cmd): # synchronous, do not use in the actions
#print(cmd)
try:
output = subprocess.check_output(cmd, shell=True)
return output.decode()
except:
return ''
def update_keyboard_mic_mute_led():
muted = 'yes' in sh('pactl get-source-mute @DEFAULT_SOURCE@')
print(f'muted? {muted}')
if muted:
sh('light -s sysfs/leds/hda::micmute -S 0')
else:
sh('light -s sysfs/leds/hda::micmute -S 100')
def event_callback(ev):
if ev.t == 'change':
if ev.facility == 'sink_input':
print(f"Sink input event: {ev.index}")
elif ev.facility == 'source_output':
print(f"Source output event: {ev.index}")
if ev.facility == 'source':
#print(f"Source event: {ev.index}")
if ev.index == default_source_id: # mic status change
print(f"default source event")
update_keyboard_mic_mute_led()
elif ev.facility == 'server':
print("Server event")
while True:
try:
default_sink_id = int(sh('pactl list sinks short | grep `pactl get-default-sink`').strip().split('\t')[0].strip())
default_source_id = int(sh('pactl list sources short | grep `pactl get-default-source`').strip().split('\t')[0].strip())
print(f'default_source_id {default_source_id}')
except:
print('audio subsystem seems to be stopped, restart')
time.sleep(0.100)
continue
update_keyboard_mic_mute_led()
# create a PulseAudio client
print('start monitoring')
with Pulse('event-monitor') as pulse:
# Set the event callback
pulse.event_callback = event_callback
# Subscribe to events
pulse.event_mask_set('all')
# Start event listening loop
try:
for ev in pulse.event_listen():
pass # events are handled by the `event_callback`
except PulseLoopStop:
print('error occured, restart')
pass
except PulseDisconnected:
print('error occured, restart')
pass
time.sleep(0.100)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment