88 lines
2.3 KiB
Python
Executable file
88 lines
2.3 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
|
|
import sys
|
|
import pulsectl
|
|
|
|
from Xlib import X, XK, display
|
|
from Xlib.ext import record
|
|
from Xlib.protocol import rq
|
|
|
|
KEY = XK.XK_F7
|
|
|
|
|
|
def mute(state):
|
|
with pulsectl.Pulse("list-source") as pulse:
|
|
for source in pulse.source_list():
|
|
if source.port_active:
|
|
if source.mute != state:
|
|
pulse.mute(source, state)
|
|
print(f"{source.name} {'un' if not state else ''}muted")
|
|
|
|
|
|
mute(True)
|
|
|
|
local_dpy = display.Display()
|
|
record_dpy = display.Display()
|
|
|
|
|
|
def record_callback(reply):
|
|
if reply.category != record.FromServer:
|
|
return
|
|
if reply.client_swapped:
|
|
print("* received swapped protocol data, cowardly ignored")
|
|
return
|
|
if not len(reply.data) or reply.data[0] < 2:
|
|
# not an event
|
|
return
|
|
|
|
data = reply.data
|
|
while len(data):
|
|
event, data = rq.EventField(None).parse_binary_value(
|
|
data, record_dpy.display, None, None
|
|
)
|
|
|
|
if event.type in [X.KeyPress, X.KeyRelease]:
|
|
keysym = local_dpy.keycode_to_keysym(event.detail, 0)
|
|
|
|
print(KEY)
|
|
if keysym == KEY:
|
|
mute(event.type == X.KeyRelease)
|
|
|
|
|
|
# Check if the extension is present
|
|
if not record_dpy.has_extension("RECORD"):
|
|
print("RECORD extension not found")
|
|
sys.exit(1)
|
|
r = record_dpy.record_get_version(0, 0)
|
|
print("RECORD extension version %d.%d" % (r.major_version, r.minor_version))
|
|
|
|
# Create a recording context; we only want key and mouse events
|
|
ctx = record_dpy.record_create_context(
|
|
0,
|
|
[record.AllClients],
|
|
[
|
|
{
|
|
"core_requests": (0, 0),
|
|
"core_replies": (0, 0),
|
|
"ext_requests": (0, 0, 0, 0),
|
|
"ext_replies": (0, 0, 0, 0),
|
|
"delivered_events": (0, 0),
|
|
"device_events": (X.KeyPress, X.MotionNotify),
|
|
"errors": (0, 0),
|
|
"client_started": False,
|
|
"client_died": False,
|
|
}
|
|
],
|
|
)
|
|
|
|
# Enable the context; this only returns after a call to record_disable_context,
|
|
# while calling the callback function in the meantime
|
|
try:
|
|
record_dpy.record_enable_context(ctx, record_callback)
|
|
except KeyboardInterrupt:
|
|
local_dpy.record_disable_context(ctx)
|
|
local_dpy.flush()
|
|
|
|
# Finally free the context
|
|
record_dpy.record_free_context(ctx)
|