Files
keytari/keytari.py
2025-02-24 18:34:46 -08:00

99 lines
2.9 KiB
Python
Executable File

#!/usr/bin/env python3
import signal
import struct
import sys
import json
import socketserver
import socket
from evdev import uinput, ecodes as e
def genconfig(filename):
result = dict()
with open(filename, 'r') as conffile:
config = json.loads(conffile.read())
for key in config.keys():
if config[key][0] is not None:
outkey = e.__dict__[config[key][0]]
modifiers = None
if config[key][1] is not None:
modifiers = [e.__dict__[x] for x in config[key][1]]
result[int(key, 16)] = [outkey, modifiers]
return result
keymap = dict()
class MyTCPHandler(socketserver.BaseRequestHandler):
"""
The request handler class for our server.
It is instantiated once per connection to the server, and must
override the handle() method to implement communication to the
client.
"""
def handle(self):
global keymap
self.request.setblocking(False)
self.request.settimeout(1)
with uinput.UInput() as ui:
while True:
try:
# self.request is the TCP socket connected to the client
self.data = struct.unpack(">H", self.request.recv(2))[0]
if not self.data:
return
if self.data in keymap.keys():
key = keymap[self.data]
# print("%x: %s" % (self.data, key))
if key[1] is not None:
for k in key[1]:
ui.write(e.EV_KEY, k, 1)
ui.write(e.EV_KEY, key[0], 1)
ui.syn()
if key[1] is not None:
for k in key[1]:
ui.write(e.EV_KEY, k, 0)
ui.write(e.EV_KEY, key[0], 0)
ui.syn()
else:
print("KEY CODE %d (%x) NOT HANDLED" % (self.data, self.data))
except TimeoutError:
pass
def load_config():
global keymap
keymap = genconfig('/etc/keytari/keymap.json')
server = None
def int_handler(sig, frame):
server.socket.close()
sys.exit(0)
def reload_handler(sig, frame):
load_config()
if __name__ == "__main__":
HOST, PORT = "0.0.0.0", 2077
load_config()
signal.signal(signal.SIGINT, int_handler)
signal.signal(signal.SIGHUP, reload_handler)
# Create the server, binding to localhost on port 9999
server = socketserver.TCPServer((HOST, PORT), MyTCPHandler)
server.allow_reuse_address = True
server.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
# Activate the server; this will keep running until you
# interrupt the program with Ctrl-C
server.serve_forever()