Event class added to misc.

defaultkwarg subs added. iniitialize event subscriptions.

base class observable thread now checks for currently registered events.

make capi call if polling strip/bus levels and ldirty not in events.
This commit is contained in:
onyx-and-iris 2022-08-02 09:17:11 +01:00
parent b7c716daf4
commit 446848fe89
5 changed files with 66 additions and 15 deletions

View File

@ -9,7 +9,7 @@ from .cbindings import CBindings
from .error import CAPIError, VMError from .error import CAPIError, VMError
from .inst import bits from .inst import bits
from .kinds import KindId from .kinds import KindId
from .misc import Midi from .misc import Event, Midi
from .subject import Subject from .subject import Subject
from .util import comp, grouper, polling, script from .util import comp, grouper, polling, script
@ -20,15 +20,18 @@ class Remote(CBindings):
DELAY = 0.001 DELAY = 0.001
def __init__(self, **kwargs): def __init__(self, **kwargs):
self.strip_mode = 0
self.cache = {} self.cache = {}
self.cache["strip_level"], self.cache["bus_level"] = self._get_levels()
self.midi = Midi() self.midi = Midi()
self.subject = Subject() self.subject = Subject()
self.strip_mode = 0
self.running = None self.running = None
for attr, val in kwargs.items(): for attr, val in kwargs.items():
setattr(self, attr, val) setattr(self, attr, val)
self.event = Event(self.subs)
def __enter__(self) -> Self: def __enter__(self) -> Self:
"""setup procedures""" """setup procedures"""
self.login() self.login()
@ -43,6 +46,7 @@ class Remote(CBindings):
def init_thread(self): def init_thread(self):
"""Starts updates thread.""" """Starts updates thread."""
self.running = True self.running = True
print(f"Listening for {', '.join(self.event.get())} events")
t = Thread(target=self._updates, daemon=True) t = Thread(target=self._updates, daemon=True)
t.start() t.start()
@ -54,14 +58,14 @@ class Remote(CBindings):
Runs updates at a rate of self.ratelimit. Runs updates at a rate of self.ratelimit.
""" """
self.cache["strip_level"], self.cache["bus_level"] = self._get_levels()
while self.running: while self.running:
if self.pdirty: if self.event.pdirty and self.pdirty:
self.subject.notify("pdirty") self.subject.notify("pdirty")
if self.mdirty: if self.event.mdirty and self.mdirty:
self.subject.notify("mdirty") self.subject.notify("mdirty")
if self.ldirty: if self.event.midi and self.get_midi_message():
self.subject.notify("midi")
if self.event.ldirty and self.ldirty:
self._strip_comp, self._bus_comp = ( self._strip_comp, self._bus_comp = (
tuple( tuple(
not x for x in comp(self.cache["strip_level"], self._strip_buf) not x for x in comp(self.cache["strip_level"], self._strip_buf)
@ -71,10 +75,8 @@ class Remote(CBindings):
self.cache["strip_level"] = self._strip_buf self.cache["strip_level"] = self._strip_buf
self.cache["bus_level"] = self._bus_buf self.cache["bus_level"] = self._bus_buf
self.subject.notify("ldirty") self.subject.notify("ldirty")
if self.get_midi_message():
self.subject.notify("midi")
time.sleep(self.ratelimit) time.sleep(self.ratelimit if self.event.any() else 0.5)
def login(self) -> NoReturn: def login(self) -> NoReturn:
"""Login to the API, initialize dirty parameters""" """Login to the API, initialize dirty parameters"""

View File

@ -161,13 +161,15 @@ class BusLevel(IRemote):
""" """
Returns a tuple of level values for the channel. Returns a tuple of level values for the channel.
If observables thread running fetch values from cache otherwise call CAPI func. If observables thread running and level updates are subscribed to, fetch values from cache
Otherwise call CAPI func.
""" """
def fget(x): def fget(x):
return round(20 * log(x, 10), 1) if x > 0 else -200.0 return round(20 * log(x, 10), 1) if x > 0 else -200.0
if self._remote.running and "bus_level" in self._remote.cache: if self._remote.running and self._remote.event.ldirty:
vals = self._remote.cache["bus_level"][self.range[0] : self.range[-1]] vals = self._remote.cache["bus_level"][self.range[0] : self.range[-1]]
else: else:
vals = [self._remote.get_level(mode, i) for i in range(*self.range)] vals = [self._remote.get_level(mode, i) for i in range(*self.range)]

View File

@ -102,7 +102,10 @@ class FactoryBase(Remote):
"""Base class for factories, subclasses Remote.""" """Base class for factories, subclasses Remote."""
def __init__(self, kind_id: str, **kwargs): def __init__(self, kind_id: str, **kwargs):
defaultkwargs = {"sync": False, "ratelimit": 0.033} defaultevents = {"pdirty": True, "mdirty": True, "midi": True, "ldirty": False}
if "subs" in kwargs:
defaultevents = defaultevents | kwargs.pop("subs")
defaultkwargs = {"sync": False, "ratelimit": 0.033, "subs": defaultevents}
kwargs = defaultkwargs | kwargs kwargs = defaultkwargs | kwargs
self.kind = kindmap(kind_id) self.kind = kindmap(kind_id)
super().__init__(**kwargs) super().__init__(**kwargs)

View File

@ -250,3 +250,45 @@ class Midi:
def _set(self, key: int, velocity: int): def _set(self, key: int, velocity: int):
self.cache[key] = velocity self.cache[key] = velocity
class Event:
def __init__(self, subs: dict):
self.subs = subs
def info(self, msg):
info = (
f"{msg} events",
f"Now listening for {', '.join(self.get())} events",
)
print("\n".join(info))
@property
def pdirty(self):
return self.subs["pdirty"]
@property
def mdirty(self):
return self.subs["mdirty"]
@property
def midi(self):
return self.subs["midi"]
@property
def ldirty(self):
return self.subs["ldirty"]
def get(self) -> list:
return [k for k, v in self.subs.items() if v]
def any(self) -> bool:
return any(self.subs.values())
def add(self, event):
self.subs[event] = True
self.info(f"{event} added to")
def remove(self, event):
self.subs[event] = False
self.info(f"{event} removed from")

View File

@ -193,13 +193,15 @@ class StripLevel(IRemote):
""" """
Returns a tuple of level values for the channel. Returns a tuple of level values for the channel.
If observables thread running fetch values from cache otherwise call CAPI func. If observables thread running and level updates are subscribed to, fetch values from cache
Otherwise call CAPI func.
""" """
def fget(x): def fget(x):
return round(20 * log(x, 10), 1) if x > 0 else -200.0 return round(20 * log(x, 10), 1) if x > 0 else -200.0
if self._remote.running and "strip_level" in self._remote.cache: if self._remote.running and self._remote.event.ldirty:
vals = self._remote.cache["strip_level"][self.range[0] : self.range[-1]] vals = self._remote.cache["strip_level"][self.range[0] : self.range[-1]]
else: else:
vals = [self._remote.get_level(mode, i) for i in range(*self.range)] vals = [self._remote.get_level(mode, i) for i in range(*self.range)]