This is a simple text window to which we can send OSC messages of the form ``` /append "Some text" /set "Some more text" /clear ``` and these appear in the window. It provides an easy way to print debug output to a window on a remote machine. The `ReceiverBase` class handles creating a UDP socket and decoding OSC messages (using python-osc) and hands off parsed messages to `receiver.process_message()`. It is better to keep the receiver out of the debug window class, as this gives better flexibility and less coupling. The debug window's only responsibility is showing what it is told to show; the Receiver's only responsibility is to receive UDP packets, decode the OSC, and act on the messages, by calling methods on the debug window. ```py from PySide6.QtCore import * from PySide6.QtGui import * from PySide6.QtWidgets import * from PySide6.QtNetwork import * import sys app = QApplication([]) class DebugWindow(QTextEdit): def __init__(self,*xs,**kw): super().__init__(*xs,**kw) self.content = "" self.updateContent() self.font = QFont("Hack Nerd Font Mono",20) self.setFont(self.font) def updateContent(self): self.setPlainText(self.content) self.update() def setContent(self,content): self.content = content self.updateContent() def appendContent(self,newContent): if len(self.content) > 0 and self.content[-1] != "\n": self.content += "\n" self.content += newContent self.updateContent() def keyPressEvent(self,e): k = e.key() if k == Qt.Key_Q: return app.quit() if k == Qt.Key_C: return self.setContent("") from pythonosc.osc_message import OscMessage class ReceiverBase(QObject): def __init__(self,target,port=4010): self.target = target self.udpSocket = QUdpSocket() self.udpSocket.readyRead.connect(self.handleUdp) self.udpSocket.bind(QHostAddress.Any,port) def handleUdp(self): while self.udpSocket.hasPendingDatagrams(): datagram = self.udpSocket.receiveDatagram(4096) data = datagram.data().data() print(f"Recv {data=} {len(data)} bytes") try: message = OscMessage(data) except Exception as e: print(f"Failed to parse {e} : {data=}") return self.processMessage(message) def processMessage(self,message): pass class DebugWindowReceiver(ReceiverBase): def processMessage(self,message): addr = message.address params = message.params if addr == "append": t = " ".join(map(str,params)) self.target.appendContent(t) elif addr == "set": t = " ".join(map(str,params)) self.target.setContent(t) elif addr == "clear": self.target.setContent("") else: print(f"Unrecognised {addr=}") debugWindow = DebugWindow() debugWindow.resize(900,600) debugWindow.setContent("Mr Flibble\nHex Vision") debugWindow.show() receiver = DebugWindowReceiver(debugWindow,4009) exit(app.exec()) ```