Dup Ver Goto 📝

KeySender2

PT2/music/daw/reaper/osc reaper osc does not exist
To
124 lines, 429 words, 4014 chars Page 'KeySender2' does not exist.

An improved key sender. You can send /ch name to this to change the channel name. The use here is for throwaway bindings. If you use a silly channel name like boing, then you can add a bunch of temporary shortcuts on using that channel, and then when done, you can edit <ReaperResourceDir>/OSC/reaper-osc-actions.ini and remove any lines containing that string (e.g. boing) like

"/rpr/boing/key/g/press" 0 0 40362

e.g. by using GNU sed if you're happy with the command line, save actually even opening and editor:

sed -i '/boing/d' OSC/reaper-osc-actions.ini

Or you can save lines containing that string to a separate file. The beauty of Reaper's config files is that they are simple text files that are easy to manipulate.

Another possible modification is to use some of the keys to switch profiles, sending an osc or udp message to indicate the selected profile.

Code

#!/usr/bin/env python

from PySide6.QtCore import *
from PySide6.QtGui import *
from PySide6.QtWidgets import *
from PySide6.QtNetwork import *
from getip import get_ip_for_host
from pythonosc import udp_client
from pythonosc.osc_message import OscMessage
from icecream import ic; ic.configureOutput(includeContext=True)
import sys,os
args = sys.argv[1:]
init_channel = args[0] if len(args) > 0 else os.getenv("HHCHAN","999")

host = "hostname"
port = 9999
default_inport = 2901 # receive osc message to change profile

class SendKey:
  def __init__(self,host,port,chan=999):
    self.host = host
    self.port = port
    self.ip = get_ip_for_host(self.host)
    self.client = udp_client.SimpleUDPClient(self.ip,self.port)
    self.setChannel(chan)
  def send(self,k):
    addr = f"/hh/{self.chan}/key/{k}"
    self.client.send_message(addr,[])
  def setChannel(self,chan):
    chan = str(chan).replace("/","")
    if len(chan) == 0:
      return
    self.ch-an = chan
    print(f"Channel now {chan}")

class Win(QWidget):
  def __init__(self,content="Key To OSC",inport=default_inport):
    super().__init__()
    self.sendkey = SendKey("behemoth",2808,chan=init_channel)
    self.resize(640,400)
    self.label = QLabel(self)
    self.label.setText(content)
    self.udpSocket = QUdpSocket()
    self.udpSocket.readyRead.connect(self.handleUdp)
    try:
      if not self.udpSocket.bind(QHostAddress.Any,inport):
        raise Exception("Address bind failed")
    except Exception:
      print(f"Failed to bind UDP port {inport}")
      exit(1)
      app.quit()
    print(f"Listening on {inport}")
  def handleUdp(self):
    while self.udpSocket.hasPendingDatagrams():
      datagram = self.udpSocket.receiveDatagram(4096)
      data = datagram.data().data()
      print(f"Recv ({len(data)}): {data}")
      try:
        message = OscMessage(data)
      except Exception as e:
        print(f"#Fail to parse datagram ({e}) : {data}")
      self.processMessage(message)
  def processMessage(self,message):
    addr = message.address
    args = message.params
    ic(addr,args)
    match addr:
      case "/ch"|"/channel":
        if len(args) > 0:
          return self.sendkey.setChannel(args[0])
        else:
          return self.sendkey.setChannel("_")
      case "/quit":
        return app.quit()
      case _:
        print(f"Unrecognised {addr} {args}")
        return
  def keyPressEvent(self,event):
    key = event.key()
    key = QKeySequence(key).toString().lower()
    if not key in "abcdefghijklmnopqrstuvwxyz0123456789" and\
        not key in ["left","right","up","down"] and\
        not key in "!\"£$%^&*()_+-=[]{};:'#@~,./<>?\\|`¬":
      return
    modifiers = event.modifiers()
    if modifiers & Qt.ShiftModifier:
      key = "S-"+key
    if modifiers & Qt.MetaModifier:
      key = "M-"+key
    if modifiers & Qt.ControlModifier:
      key = "C-"+key
    if modifiers & Qt.AltModifier:
      key = "A-"+key
    if key == "C-q":
      app.quit()
    print(f"Key: {key} to {self.sendkey.chan}")
    self.sendkey.send(key)

app = QApplication([])
win = Win()
win.show()
app.exec()