From 4bf5f61df88cecf16e2e8283753f1f3eb1e607fe Mon Sep 17 00:00:00 2001
From: Jochen Vothknecht <jochen3120@gmail.com>
Date: Wed, 15 Dec 2021 08:26:06 +0100
Subject: [PATCH] =?UTF-8?q?Adding=20callback=20register=20stuff=E2=80=A6?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 SiliconTorch/fxCyanF.py | 46 +++++++++++++++++++++++++++++++++++++----
 1 file changed, 42 insertions(+), 4 deletions(-)

diff --git a/SiliconTorch/fxCyanF.py b/SiliconTorch/fxCyanF.py
index 7b1f853..4d7b1bd 100644
--- a/SiliconTorch/fxCyanF.py
+++ b/SiliconTorch/fxCyanF.py
@@ -1,6 +1,9 @@
 
+from __future__ import annotations
+
 import struct
 from threading import Thread
+from inspect import signature
 from socket import socket, AF_INET, SOCK_DGRAM
 
 
@@ -59,19 +62,51 @@ class Receiver:
     self._socket = socket(AF_INET, SOCK_DGRAM)
     self._socket.bind((host, port))
 
-    self._callbacks = set()
+    self._callbacks = {}
 
     t = Thread(target=self._recvLoop)
     t.daemon = True
     t.start()
 
+  def addCallback(self, callback) -> Receiver:
+    """Register a new callback
+    
+    The callback may take 2 parameters, but must take at least 1.
+    If it takes more than one it will get the sender's address too.
+    
+    Signature should look like:
+    `def callback(channels, address): pass`
+    where channels takes a list of floats and adress will be the senders address.
+    The address parameter may be ommitted."""
+
+    params = len(signature(callback).parameters)
+
+    if params < 1 or params:
+      raise AttributeError(f'callback must take at least param#[ 1 ], takes param#[ {params} ]')
+    else:
+      self._callbacks[callback] = params
+      return self
+
+  # TODO: write a decorator which copies se docstring from the other function
+  def __iadd__(self, callback) -> Receiver:
+    return self.addCallback(callback)
+
+  def removeCallback(self, callback) -> Receiver:
+    if callback in self._callbacks:
+      del self._callbacks[callback]
+    return self
+
+  # TODO: write a decorator which copies se docstring from the other function
+  def __isubb__(self, callback) -> Receiver:
+    return self.removeCallback(callback)
+
   def _recvLoop(self):
 
     header = DEFAULT.header
     headerLen = len(header)
 
     while True:
-      data = self._socket.recv(2048)
+      data, addr = self._socket.recvfrom(2048)
 
       if data.startswith(header):
         data = data[ headerLen : ]
@@ -90,9 +125,12 @@ class Receiver:
         if ch < 0.0: ch = 0.0
         channels += [ch]
 
-      for callback in self._callbacks:
+      for callback, params in self._callbacks.items():
         try:
-          callback(channels)
+          if params == 1:
+            callback(channels)
+          elif params == 2:
+            callback(channels, addr)
         except:
           # TODO: logging…?
           pass
-- 
GitLab