简体   繁体   中英

pynput keyboard Listener autorepeat

I'm trying to use pynput to get realtime keyboard input, but the on_press function gets called on autorepeat.

example code:

#!/usr/bin/env python3

import sys

import numpy as np
import sounddevice as sd

from pynput import keyboard

frequency = []

def on_press(key):
    global frequency
    try:
        print(key.vk)
        if key.char == "q":
            frequency.append(440)
        elif key.char == "w":
            frequency.append(880)
    except AttributeError:
        pass

def on_release(key):
    global frequency
    if key == keyboard.Key.esc:
        # Stop listener
        print("Press Enter")
        return False
    elif key.char == "q":
        frequency.remove(440)
    elif key.char == "w":
        frequency.remove(880)

listener = keyboard.Listener(
    on_press=on_press,
    on_release=on_release,
    suppress = True)
listener.start()

start_idx = 0

def callback(outdata, frames, time, status):
    if status:
        print(status, file=sys.stderr)
    print(frames)
    global start_idx
    t = (start_idx + np.arange(frames)) / 48000
    t = t.reshape(-1, 1)
    outdata[:] = 0 * t
    if len(frequency) > 0:
        print("Playing")
    for freq in frequency:
        outdata[:] = outdata[:] + 0.2 * np.sin(2 * np.pi * freq * t)

    start_idx += frames

try:
    with sd.OutputStream(channels=1, callback=callback,
            samplerate=48000):
        input()
        listener.stop()
except Exception as e:
    print("Exception")
    listener.stop()
    exit()

If you run the code and press and hold the Q key, the keyboard autorepeat kicks in and ruins the whole listener. Is there a python input module which handles raw keyboard input properly?

The second thing is that the code tends to crash my Xorg quite regularly. I just run the script a few times and the Xorg goes down. And I can't figure out why. Linux 5.5.2-zen1-1-zen x86_64 GNU/Linux , X.Org 1.20.7 .

The third thing is that the sound synthesis seems to lag quite a bit. The number of frames to the callback function seems to hang around 400, which at the rate of 48000 samples per second is less then 10 milliseconds, but the actual audio feedback feels like on hundreds of milliseconds delay.

pygame has a good keylistener and is easy to build a GUI window that displays output. It also works well in Linux:

import pygame

def main_loop():
    #code
    loopExit = False
    while not loopExit:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                loopExit = True
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_q:
                    #code

            if event.type == pygame.KEYUP:
                if event.key == pygame.K_q:
                    #code

https://www.pygame.org/docs/ref/key.html

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM