This opens a window and generates OSC messages of the form /kb/something/ACMSx for
Alt-Ctrl-Meta-Shift-x where something is an arbitrary string to allow for multiple profiles.
Naturally you could have the script look up the key combo and if it finds something,
do some action instead. Also having the window larger and display the profile, possibly
with some help text, all such things are easily possible.
Note one quirk: the modifiers are always prepended. So if you get + via the top row,
you will get Splus, whereas if you get it via a keypad, you'll get plus. The main current
target application is Reaper, where these OSC messages can be bound to actions.
It may also make sense to pass in an OSC client, rather than creating it in the class as we do. Indeed the 'client' needn't be an actual client, rather any object with a send_message method.
#!/usr/bin/env python
import sys
import os
import math
import random
from PySide6.QtCore import *
from PySide6.QtGui import *
from PySide6.QtWidgets import *
from PySide6.QtNetwork import *
from pythonosc import udp_client
from icecream import ic; ic.configureOutput(includeContext=True)
app = QApplication([])
lookup = {
"!": "bang",
'"': "dquote",
"£": "gbp",
"$": "dollar",
"%": "percent",
"^": "caret",
"&": "amp",
"*": "asterisk",
"(": "lparen",
")": "rparen",
"-": "hyphen",
"=": "equals",
"_": "underscore",
"+": "plus",
"[": "lbracket",
"]": "rbracket",
"{": "lbrace",
"}": "rbrace",
";": "semicolon",
":": "colon",
"'": "quote",
"@": "at",
"#": "hash",
"~": "tilde",
",": "comma",
"<": "lt",
".": "period",
">": "gt",
"/": "slash",
"?": "question",
"\\": "backslash",
"|": "pipe",
"`": "backquote",
"¬": "neg",
" ": "space",
'\x01': "a",
'\x02': "b",
'\x03': "c",
'\x04': "d",
'\x05': "e",
'\x06': "f",
'\x07': "g",
'\x08': "h",
'\t': "i",
'\n': "j",
'\x0b': "k",
'\x0c': "l",
'\r': "m",
'\x0e': "n",
'\x0f': "o",
'\x10': "p",
'\x11': "q",
'\x12': "r",
'\x13': "s",
'\x14': "t",
'\x15': "u",
'\x16': "v",
'\x17': "w",
'\x18': "x",
'\x19': "y",
'\x1a': "z",
}
class Kb(QWidget):
def __init__(self,target="localhost",port=2900,profile="init"):
super().__init__()
self.target = target
self.port = port
self.osc_client = udp_client.SimpleUDPClient(target, port)
self.move(20,20)
self.resize(80,60)
self.profile = profile
def setProfile(self,profile):
self.profile = profile
def keyPressEvent(self,e):
#ic(e,repr(e.text()))
t = e.text().lower()
if len(t) == 0:
return
if t in lookup:
t = lookup[t]
ms = e.modifiers().value
av = Qt.AltModifier.value
cv = Qt.ControlModifier.value
mv = Qt.MetaModifier.value
sv = Qt.ShiftModifier.value
a = (av&ms) > 0
c = (cv&ms) > 0
m = (mv&ms) > 0
s = (sv&ms) > 0
if s:
t = "S"+t
if m:
t = "M"+t
if c:
t = "C"+t
if a:
t = "A"+t
addr = f"/kb/{self.profile}/{t}"
self.osc_client.send_message(addr,[])
print(t)
def paintEvent(self,e):
rect = self.rect()
with QPainter(self) as p:
p.fillRect(rect,Qt.black)
w = Kb()
w.show()
app.exec()