Browse Source
Changes to be committed: new file: .gitignore new file: README new file: mouse_mute.py new file: requirements.txtmain
commit
d1e8404545
4 changed files with 119 additions and 0 deletions
@ -0,0 +1,2 @@ |
|||||||
|
Did you ever need to send a mouse event to a sandboxed X11 program while using |
||||||
|
Wayland? Me neither. But, for the weirdo that wants to, here's this thing. |
||||||
@ -0,0 +1,113 @@ |
|||||||
|
|
||||||
|
import re |
||||||
|
import select |
||||||
|
import sys |
||||||
|
|
||||||
|
import evdev # https://github.com/gvalkov/python-evdev |
||||||
|
import pulsectl # https://github.com/mk-fg/python-pulse-control |
||||||
|
|
||||||
|
|
||||||
|
# NOTE: adapted from evdev/evtest.py |
||||||
|
def select_mouse(key_code:int = -1) -> evdev.InputDevice: |
||||||
|
def devicenum(device_path): |
||||||
|
digits = re.findall(r"\d+$", device_path) |
||||||
|
return [int(i) for i in digits] |
||||||
|
|
||||||
|
devices = sorted(evdev.list_devices('/dev/input'), key=devicenum) |
||||||
|
devices = [evdev.InputDevice(path) for path in devices] |
||||||
|
if not devices: |
||||||
|
msg = "error: no input devices found (do you have rw permission on %s/*?)" |
||||||
|
print(msg % device_dir, file=sys.stderr) |
||||||
|
return None |
||||||
|
|
||||||
|
for i, dev in enumerate(devices): |
||||||
|
print("{}: {}".format(i, dev.name)) |
||||||
|
|
||||||
|
selection = input("select mouse device: ") |
||||||
|
try: |
||||||
|
if int(selection) > len(devices): |
||||||
|
return None |
||||||
|
except (TypeError, ValueError): |
||||||
|
print("invalid comparison") |
||||||
|
return None |
||||||
|
|
||||||
|
dev_caps = devices[int(selection)].capabilities() |
||||||
|
|
||||||
|
if (evdev.ecodes.EV_KEY not in dev_caps or |
||||||
|
key_code not in dev_caps[evdev.ecodes.EV_KEY]): |
||||||
|
print("this device doesn't have a BTN_SIDE") |
||||||
|
return None |
||||||
|
|
||||||
|
return devices[int(selection)] |
||||||
|
|
||||||
|
def parse_event(e:evdev.InputEvent, listen_key:int) -> int: |
||||||
|
if e.type == evdev.ecodes.EV_KEY: |
||||||
|
if e.code == listen_key: |
||||||
|
return e.value |
||||||
|
|
||||||
|
return -1 |
||||||
|
|
||||||
|
def select_source() -> pulsectl.PulseSourceInfo: |
||||||
|
with pulsectl.Pulse() as pulse: |
||||||
|
source_list = pulse.source_list() |
||||||
|
|
||||||
|
for i, source in enumerate(source_list): |
||||||
|
print("{}: {}".format(i, source.description)) |
||||||
|
|
||||||
|
selection = input("select sount input device: ") |
||||||
|
try: |
||||||
|
if int(selection) > i: |
||||||
|
return None |
||||||
|
except (TypeError, ValueError): |
||||||
|
print("invalid comparison") |
||||||
|
return None |
||||||
|
|
||||||
|
return source_list[int(selection)] |
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__': |
||||||
|
# TODO: capture initial mute state |
||||||
|
|
||||||
|
# TODO: select other devices/buttons |
||||||
|
key_code = evdev.ecodes.BTN_SIDE |
||||||
|
device = select_mouse(key_code) |
||||||
|
|
||||||
|
if device == None: |
||||||
|
print("error selecting device") |
||||||
|
# FIXME: restore initial mute state here too |
||||||
|
sys.exit(1) |
||||||
|
|
||||||
|
source = select_source() |
||||||
|
|
||||||
|
if source is None: |
||||||
|
print("error selecting pulse source") |
||||||
|
# FIXME: restore initial mute state here too |
||||||
|
sys.exit(1) |
||||||
|
|
||||||
|
pulse = pulsectl.Pulse() |
||||||
|
|
||||||
|
# NOTE: listen for the BTN_SIDE event |
||||||
|
# TODO: an option to play a sound on mute/unmute here would be nice too: |
||||||
|
# https://github.com/hamiltron/py-simple-audio |
||||||
|
|
||||||
|
try: |
||||||
|
print("Listening for events (press ctrl-c to exit) ...") |
||||||
|
pulse = pulsectl.Pulse() |
||||||
|
pulse.source_list() |
||||||
|
|
||||||
|
while True: |
||||||
|
for event in device.read_loop(): |
||||||
|
ret = parse_event(event, key_code) |
||||||
|
if ret == 0: |
||||||
|
pulse.mute(source, True) |
||||||
|
elif ret == 1: |
||||||
|
pulse.mute(source, False) |
||||||
|
else: |
||||||
|
pass |
||||||
|
except (KeyboardInterrupt, EOFError): |
||||||
|
pass |
||||||
|
|
||||||
|
# TODO: restore initial mute state |
||||||
|
|
||||||
|
|
||||||
|
sys.exit(0) |
||||||
Loading…
Reference in new issue