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)