added subject module

added ldirty parameter

_updates thread now notifies observers of updates to pdirty, ldirty.

minor version bump
This commit is contained in:
onyx-and-iris 2022-05-14 14:00:08 +01:00
parent 9de4116c1b
commit 933d182f60
5 changed files with 94 additions and 12 deletions

View File

@ -2,7 +2,7 @@ from setuptools import setup
setup( setup(
name="vbancmd", name="vbancmd",
version="0.3.0", version="0.4.0",
description="VBAN CMD Python API", description="VBAN CMD Python API",
packages=["vbancmd"], packages=["vbancmd"],
install_requires=["toml"], install_requires=["toml"],

View File

@ -9,7 +9,7 @@ kind_id = random.choice(tuple(kind.id for kind in kinds.all))
opts = { opts = {
"ip": "codey.local", "ip": "codey.local",
"streamname": "testing", "streamname": "codey",
"port": 6990, "port": 6990,
"bps": 0, "bps": 0,
"sync": True, "sync": True,

View File

@ -33,8 +33,9 @@ class VBAN_VMRT_Packet_Data:
_stripLabelUTF8c60: bytes _stripLabelUTF8c60: bytes
_busLabelUTF8c60: bytes _busLabelUTF8c60: bytes
def isdirty(self, other): def pdirty(self, other):
"""defines the dirty flag""" """True iff any defined parameter has changed"""
return not ( return not (
self._stripState == other._stripState self._stripState == other._stripState
and self._busState == other._busState and self._busState == other._busState

35
vbancmd/subject.py Normal file
View File

@ -0,0 +1,35 @@
class Subject:
def __init__(self):
"""list of current observers"""
self._observables = []
def notify(self, modifier=None, data=None):
"""run callbacks on update"""
for observer in self._observables:
observer.on_update(modifier, data)
def add(self, observer):
"""adds an observer to observables"""
if observer not in self._observables:
self._observables.append(observer)
def remove(self, observer):
"""removes an observer from observables"""
try:
self._observables.remove(observer)
except ValueError:
pass
def get(self) -> list:
"""returns the current observables"""
return self._observables
def clear(self):
"""clears the observables list"""
self._observables.clear()

View File

@ -19,6 +19,7 @@ from .strip import InputStrip
from .bus import OutputBus from .bus import OutputBus
from .command import Command from .command import Command
from .util import script from .util import script
from .subject import Subject
class VbanCmd(abc.ABC): class VbanCmd(abc.ABC):
@ -66,6 +67,8 @@ class VbanCmd(abc.ABC):
self._public_packet = None self._public_packet = None
self.running = True self.running = True
self._pdirty = False self._pdirty = False
self._ldirty = False
self.subject = Subject()
self.cache = {} self.cache = {}
def __enter__(self): def __enter__(self):
@ -87,9 +90,9 @@ class VbanCmd(abc.ABC):
worker = Thread(target=self._send_register_rt, daemon=True) worker = Thread(target=self._send_register_rt, daemon=True)
worker.start() worker.start()
self._public_packet = self._get_rt() self._public_packet = self._get_rt()
worker2 = Thread(target=self._keepupdated, daemon=True) worker2 = Thread(target=self._updates, daemon=True)
worker2.start() worker2.start()
self._clear_dirty() self.clear_dirty()
def _send_register_rt(self): def _send_register_rt(self):
""" """
@ -147,29 +150,71 @@ class VbanCmd(abc.ABC):
"""True iff a parameter has changed""" """True iff a parameter has changed"""
return self._pdirty return self._pdirty
@property
def ldirty(self):
"""True iff a level value has changed."""
return self._ldirty
@property @property
def public_packet(self): def public_packet(self):
return self._public_packet return self._public_packet
def _clear_dirty(self): def clear_dirty(self):
while self.pdirty: while self.pdirty:
pass pass
def _keepupdated(self) -> NoReturn: def _updates(self) -> NoReturn:
""" """
Continously update public packet in background. Continously update public packet in background.
Set parameter dirty flag. Set parameter and level dirty flags.
Update public packet only if new private packet is found. Update public packet only if new private packet is found.
Then notify observers of updates to states.
This function to be run in its own thread. This function to be run in its own thread.
""" """
while self.running: while self.running:
private_packet = self._get_rt() private_packet = self._get_rt()
self._pdirty = private_packet.isdirty(self.public_packet)
if not private_packet == self.public_packet: private_input_levels = private_packet.inputlevels
public_input_levels = self.public_packet.inputlevels
strip_comp = [
not a == b
for a, b in zip(
private_input_levels,
public_input_levels,
)
]
private_output_levels = private_packet.outputlevels
public_output_levels = self.public_packet.outputlevels
bus_comp = [
not a == b
for a, b in zip(
private_output_levels,
public_output_levels,
)
]
self._pdirty = private_packet.pdirty(self.public_packet)
self._ldirty = any(any(list_) for list_ in [strip_comp, bus_comp])
if self._public_packet != private_packet:
self._public_packet = private_packet self._public_packet = private_packet
if self.pdirty:
self.subject.notify("pdirty")
if self.ldirty:
self.subject.notify(
"ldirty",
[
public_input_levels,
strip_comp,
public_output_levels,
bus_comp,
],
)
sleep(self._delay)
def _get_rt(self) -> VBAN_VMRT_Packet_Data: def _get_rt(self) -> VBAN_VMRT_Packet_Data:
"""Attempt to fetch data packet until a valid one found""" """Attempt to fetch data packet until a valid one found"""
@ -281,7 +326,6 @@ class VbanCmd(abc.ABC):
) )
def logout(self): def logout(self):
"""sets thread flag, closes sockets"""
self.running = False self.running = False
sleep(0.2) sleep(0.2)
self._rt_register_socket.close() self._rt_register_socket.close()
@ -315,6 +359,8 @@ def _make_remote(kind: NamedTuple) -> VbanCmd:
self.kind = kind self.kind = kind
self.phys_in, self.virt_in = kind.ins self.phys_in, self.virt_in = kind.ins
self.phys_out, self.virt_out = kind.outs self.phys_out, self.virt_out = kind.outs
self.strip_comp = [False for _ in range(2 * self.phys_in + 8 * self.virt_in)]
self.bus_comp = [False for _ in range(8 * (self.phys_out + self.virt_out))]
self.strip = tuple( self.strip = tuple(
InputStrip.make((i < self.phys_in), self, i) InputStrip.make((i < self.phys_in), self, i)
for i in range(self.phys_in + self.virt_in) for i in range(self.phys_in + self.virt_in)