You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
113 lines
3.1 KiB
113 lines
3.1 KiB
|
|
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)
|
|
|