refactor levels.

only compute strip/bus comp tuples if ldirty.

add comp generator function to util.

added some docstrings

patch bump
This commit is contained in:
onyx-and-iris 2022-07-09 11:06:48 +01:00
parent 210c75ed5f
commit e979595a09
5 changed files with 67 additions and 28 deletions

View File

@ -1,6 +1,6 @@
[tool.poetry] [tool.poetry]
name = "voicemeeter-api" name = "voicemeeter-api"
version = "0.2.2" version = "0.2.3"
description = "A Python wrapper for the Voiceemeter API" description = "A Python wrapper for the Voiceemeter API"
authors = ["onyx-and-iris <code@onyxandiris.online>"] authors = ["onyx-and-iris <code@onyxandiris.online>"]
license = "MIT" license = "MIT"

View File

@ -9,7 +9,7 @@ from .cbindings import CBindings
from .error import VMError from .error import VMError
from .kinds import KindId from .kinds import KindId
from .subject import Subject from .subject import Subject
from .util import polling, script from .util import comp, polling, script
class Remote(CBindings): class Remote(CBindings):
@ -44,7 +44,13 @@ class Remote(CBindings):
t.start() t.start()
def _updates(self): def _updates(self):
"""Continously update observers of dirty states.""" """
Continously update observers of dirty states.
Generate _strip_comp, _bus_comp and update level cache if ldirty.
Runs updates at a rate of self.ratelimit.
"""
self.cache["strip_level"], self.cache["bus_level"] = self._get_levels() self.cache["strip_level"], self.cache["bus_level"] = self._get_levels()
while self.running: while self.running:
@ -53,6 +59,12 @@ class Remote(CBindings):
if self.mdirty: if self.mdirty:
self.subject.notify("mdirty") self.subject.notify("mdirty")
if self.ldirty: if self.ldirty:
self._strip_comp, self._bus_comp = (
tuple(
not x for x in comp(self.cache["strip_level"], self._strip_buf)
),
tuple(not x for x in comp(self.cache["bus_level"], self._bus_buf)),
)
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")
@ -110,16 +122,10 @@ class Remote(CBindings):
def ldirty(self) -> bool: def ldirty(self) -> bool:
"""True iff levels have been updated.""" """True iff levels have been updated."""
self._strip_buf, self._bus_buf = self._get_levels() self._strip_buf, self._bus_buf = self._get_levels()
self._strip_comp, self._bus_comp = ( return not (
tuple( self.cache.get("strip_level") == self._strip_buf
not a == b and self.cache.get("bus_level") == self._bus_buf
for a, b in zip(self.cache.get("strip_level"), self._strip_buf)
),
tuple(
not a == b for a, b in zip(self.cache.get("bus_level"), self._bus_buf)
),
) )
return any(any(l) for l in (self._strip_comp, self._bus_comp))
def clear_dirty(self): def clear_dirty(self):
while self.pdirty or self.mdirty: while self.pdirty or self.mdirty:

View File

@ -116,16 +116,21 @@ class BusLevel(IRemote):
self.range = self.level_map[self.index] self.range = self.level_map[self.index]
def getter(self, mode): def getter(self, mode):
"""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.
"""
def fget(i): def fget(i):
if self._remote.running and "bus_level" in self._remote.cache: return round(20 * log(i, 10), 1) if i > 0 else -200.0
res = self._remote.cache["bus_level"][i]
else:
res = self._remote.get_level(mode, i)
return round(20 * log(res, 10), 1) if res > 0 else -200.0
return tuple(fget(i) for i in range(*self.range)) if self._remote.running and "bus_level" in self._remote.cache:
vals = self._remote.cache["bus_level"][self.range[0] : self.range[-1]]
else:
vals = [self._remote.get_level(mode, i) for i in range(*self.range)]
return tuple(fget(i) for i in vals)
@property @property
def identifier(self) -> str: def identifier(self) -> str:
@ -137,6 +142,12 @@ class BusLevel(IRemote):
@property @property
def is_updated(self) -> bool: def is_updated(self) -> bool:
"""
Returns dirty status for this specific channel.
Expected to be used in a callback only.
"""
if self._remote.running:
return any(self._remote._bus_comp[self.range[0] : self.range[-1]]) return any(self._remote._bus_comp[self.range[0] : self.range[-1]])

View File

@ -189,16 +189,21 @@ class StripLevel(IRemote):
self.range = self.level_map[self.index] self.range = self.level_map[self.index]
def getter(self, mode): def getter(self, mode):
"""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.
"""
def fget(i): def fget(i):
if self._remote.running and "strip_level" in self._remote.cache: return round(20 * log(i, 10), 1) if i > 0 else -200.0
res = self._remote.cache["strip_level"][i]
else:
res = self._remote.get_level(mode, i)
return round(20 * log(res, 10), 1) if res > 0 else -200.0
return tuple(fget(i) for i in range(*self.range)) if self._remote.running and "strip_level" in self._remote.cache:
vals = self._remote.cache["strip_level"][self.range[0] : self.range[-1]]
else:
vals = [self._remote.get_level(mode, i) for i in range(*self.range)]
return tuple(fget(i) for i in vals)
@property @property
def identifier(self) -> str: def identifier(self) -> str:
@ -221,6 +226,12 @@ class StripLevel(IRemote):
@property @property
def is_updated(self) -> bool: def is_updated(self) -> bool:
"""
Returns dirty status for this specific channel.
Expected to be used in a callback only.
"""
if self._remote.running:
return any(self._remote._strip_comp[self.range[0] : self.range[-1]]) return any(self._remote._strip_comp[self.range[0] : self.range[-1]])

View File

@ -1,4 +1,5 @@
import functools import functools
from typing import Iterator
def polling(func): def polling(func):
@ -50,3 +51,13 @@ def script(func):
return func(remote, script) return func(remote, script)
return wrapper return wrapper
def comp(t0: tuple, t1: tuple) -> Iterator[bool]:
"""
Generator function, accepts two tuples.
Evaluates equality of each member in both tuples.
"""
for a, b in zip(t0, t1):
yield a == b