mirror of
https://github.com/onyx-and-iris/voicemeeter-api-python.git
synced 2024-11-22 11:00:47 +00:00
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:
parent
210c75ed5f
commit
e979595a09
@ -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"
|
||||||
|
@ -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:
|
||||||
|
@ -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,7 +142,13 @@ class BusLevel(IRemote):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def is_updated(self) -> bool:
|
def is_updated(self) -> bool:
|
||||||
return any(self._remote._bus_comp[self.range[0] : self.range[-1]])
|
"""
|
||||||
|
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]])
|
||||||
|
|
||||||
|
|
||||||
def _make_bus_mode_mixin():
|
def _make_bus_mode_mixin():
|
||||||
|
@ -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,7 +226,13 @@ class StripLevel(IRemote):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def is_updated(self) -> bool:
|
def is_updated(self) -> bool:
|
||||||
return any(self._remote._strip_comp[self.range[0] : self.range[-1]])
|
"""
|
||||||
|
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]])
|
||||||
|
|
||||||
|
|
||||||
class GainLayer(IRemote):
|
class GainLayer(IRemote):
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user