Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multimedia Keys in Python (Linux)

I want to detect when the XF86Launch1 key is pressed on my keyboard, using Python.

I have a headless server with a Bluetooth connected keyboard. I'd like to launch a command-line program whenever a specific multimedia key is pressed.

At the moment, I'm using:

import sys
import tty, termios

def getch():
    fd = sys.stdin.fileno()
    old_settings = termios.tcgetattr(fd)
    try:
        tty.setraw(fd)
        ch = sys.stdin.read(1)
    finally:
        termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
    return ch

print getch()

But it won't detect multimedia keys. Nothing prints out when I press them.

Is there a way to detect these keys on a headless Ubuntu box - or a better way to launch a program on keypress?

like image 575
Terence Eden Avatar asked Feb 20 '16 16:02

Terence Eden


Video Answer


2 Answers

Rather than trying to read stdin of the tty, you can use linux's input device api to read them.

On linux, all input devices show up as a file under /dev/input (such as /dev/input/event0) and when one read()s from these files, structured data indicating when keys are pressed and released is returned.

In C, the libevdev library provides a wrapper around those. In python, you could use the python-evdev library. It should also be possible to read directly from the input device (though you may need to carefully read the kernel documentation & source to handle that properly).

like image 94
Cody Schafer Avatar answered Oct 16 '22 10:10

Cody Schafer


I think that your problem is that multimedia keys do not map to terminal input.

It's possible that you could make progress by running xev to trap the key and xmodmap to map the key to a different input.

Alternatively, use something like TKinter and see if a graphical program doesn't collect the keypresses.

from Tkinter import *

root = Tk()

def key(event):
    print "pressed", repr(event.char)

def callback(event):
    frame.focus_set()

frame = Frame(root, width=100, height=100)
frame.bind("<Key>", key)
frame.bind("<Button-1>", callback)
frame.pack()

root.mainloop()

Another possibility is to map to an F key instead of a multimedia key. (i.e. F9)


Edit: Further research into this resulted in these two links:

Extra Keyboard Keys

Extra Keyboard Keys in Console

The console itself does not support multimedia keys. But it does support custom F keys. F30-F246 are always free. Rather than map to XF86Launch1, map to F70. Then map F70 to keyboard input in your keymap, or use the Python script you already wrote to handle it.

like image 43
Steve Kallestad Avatar answered Oct 16 '22 08:10

Steve Kallestad