inputlevels, ouputlevels now return generators

'strip_level', 'bus_level' added to cache.

defautl ratelimit set to 0.01
ratelimit adjusted to wait by ratelimit - elapsed time.

is_updated now returns a bool

minor ver bump
This commit is contained in:
onyx-and-iris 2022-07-06 13:40:46 +01:00
parent a47a29d9f7
commit 86b7fb5d32
6 changed files with 69 additions and 66 deletions

View File

@ -1,6 +1,6 @@
[tool.poetry] [tool.poetry]
name = "vban-cmd" name = "vban-cmd"
version = "1.0.8" version = "1.1.0"
description = "Python interface for the VBAN RT Packet Service (Sendtext)" description = "Python interface for the VBAN RT Packet Service (Sendtext)"
authors = ["onyx-and-iris <code@onyxandiris.online>"] authors = ["onyx-and-iris <code@onyxandiris.online>"]
license = "MIT" license = "MIT"

View File

@ -1,9 +1,10 @@
import dataclasses
import socket import socket
import time import time
from abc import ABCMeta, abstractmethod from abc import ABCMeta, abstractmethod
from enum import IntEnum from enum import IntEnum
from threading import Thread from threading import Thread
from typing import NoReturn, Optional, Union from typing import Iterable, NoReturn, Optional, Union
from .packet import ( from .packet import (
HEADER_SIZE, HEADER_SIZE,
@ -165,12 +166,22 @@ class VbanCmd(metaclass=ABCMeta):
@property @property
def pdirty(self): def pdirty(self):
"""True iff a parameter has changed""" """True iff a parameter has changed"""
return self._pdirty return self._pp.pdirty(self.public_packet)
@property @property
def ldirty(self): def ldirty(self):
"""True iff a level value has changed.""" """True iff a level value has changed."""
return self._ldirty self._strip_comp, self._bus_comp = (
tuple(
not a == b
for a, b in zip(self._public_packet.inputlevels, self._strip_buf)
),
tuple(
not a == b
for a, b in zip(self._public_packet.outputlevels, self._bus_buf)
),
)
return any(any(l) for l in (self._strip_comp, self._bus_comp))
@property @property
def public_packet(self): def public_packet(self):
@ -181,49 +192,35 @@ class VbanCmd(metaclass=ABCMeta):
pass pass
def _updates(self) -> NoReturn: def _updates(self) -> NoReturn:
while self.running: self.cache["strip_level"], self.cache["bus_level"] = self._get_levels(
private_packet = self._get_rt() self.public_packet
self._strip_comp, self._bus_comp = (
tuple(
not a == b
for a, b in zip(
private_packet.inputlevels, self.public_packet.inputlevels
)
),
tuple(
not a == b
for a, b in zip(
private_packet.outputlevels, self.public_packet.outputlevels
)
),
)
self._pdirty = private_packet.pdirty(self.public_packet)
self._ldirty = any(
any(list_) for list_ in (self._strip_comp, self._bus_comp)
)
if self._public_packet != private_packet:
self._public_packet = private_packet
if self.pdirty:
self.subject.notify("pdirty")
if self.ldirty:
self.subject.notify("ldirty")
time.sleep(self.ratelimit)
@property
def strip_levels(self):
"""Returns the full strip level array for a kind, PREFADER mode, before math conversion"""
return tuple(
list(filter(lambda x: x != ((1 << 16) - 1), self.public_packet.inputlevels))
) )
@property while self.running:
def bus_levels(self): start = time.time()
"""Returns the full bus level array for a kind, before math conversion""" self._pp = self._get_rt()
return tuple( self._strip_buf, self._bus_buf = self._get_levels(self._pp)
list(
filter(lambda x: x != ((1 << 16) - 1), self.public_packet.outputlevels) if self.pdirty:
) self._public_packet = self._pp
self.subject.notify("pdirty")
if self.ldirty:
self.cache["strip_level"] = tuple(self._strip_buf)
self.cache["bus_level"] = tuple(self._bus_buf)
self.subject.notify("ldirty")
elapsed = time.time() - start
if self.ratelimit - elapsed > 0:
time.sleep(self.ratelimit - elapsed)
def _get_levels(self, packet) -> Iterable:
"""
returns both level arrays (strip_levels, bus_levels) BEFORE math conversion
strip levels in PREFADER mode.
"""
return (
[val for val in packet.inputlevels],
[val for val in packet.outputlevels],
) )
def apply(self, data: dict): def apply(self, data: dict):

View File

@ -66,13 +66,15 @@ class BusLevel(IRemote):
(i, i + 8) (i, i + 8)
for i in range(0, (remote.kind.phys_out + remote.kind.virt_out) * 8, 8) for i in range(0, (remote.kind.phys_out + remote.kind.virt_out) * 8, 8)
) )
self.range = self.level_map[self.index]
def getter(self): def getter(self):
"""Returns a tuple of level values for the channel.""" """Returns a tuple of level values for the channel."""
range_ = self.level_map[self.index] range_ = self.level_map[self.index]
return tuple( return tuple(
round(-i * 0.01, 1) for i in self._remote.bus_levels[range_[0] : range_[-1]] round(-i * 0.01, 1)
for i in self._remote.cache["bus_level"][self.range[0] : self.range[-1]]
) )
@property @property
@ -84,8 +86,8 @@ class BusLevel(IRemote):
return self.getter() return self.getter()
@property @property
def updated(self) -> tuple: def is_updated(self) -> bool:
return self._remote._bus_comp return any(self._remote._bus_comp[self.range[0] : self.range[-1]])
def _make_bus_mode_mixin(): def _make_bus_mode_mixin():

View File

@ -64,7 +64,7 @@ class FactoryBase(VbanCmd):
"streamname": "Command1", "streamname": "Command1",
"bps": 0, "bps": 0,
"channel": 0, "channel": 0,
"ratelimit": 0, "ratelimit": 0.01,
"sync": False, "sync": False,
} }
kwargs = defaultkwargs | kwargs kwargs = defaultkwargs | kwargs

View File

@ -1,4 +1,5 @@
from dataclasses import dataclass from dataclasses import dataclass
from typing import Generator
VBAN_SERVICE_RTPACKETREGISTER = 32 VBAN_SERVICE_RTPACKETREGISTER = 32
VBAN_SERVICE_RTPACKET = 33 VBAN_SERVICE_RTPACKET = 33
@ -76,21 +77,24 @@ class VBAN_VMRT_Packet_Data:
return int.from_bytes(self._samplerate, "little") return int.from_bytes(self._samplerate, "little")
@property @property
def inputlevels(self) -> tuple: def inputlevels(self) -> Generator[float, None, None]:
"""returns the entire level array across all inputs""" """returns the entire level array across all inputs"""
return tuple( for i in range(0, 68, 2):
((1 << 16) - 1) - int.from_bytes(self._inputLeveldB100[i : i + 2], "little") val = ((1 << 16) - 1) - int.from_bytes(
for i in range(0, 68, 2) self._inputLeveldB100[i : i + 2], "little"
) )
if val != ((1 << 16) - 1):
yield val
@property @property
def outputlevels(self) -> tuple: def outputlevels(self) -> Generator[float, None, None]:
"""returns the entire level array across all outputs""" """returns the entire level array across all outputs"""
return tuple( for i in range(0, 128, 2):
((1 << 16) - 1) val = ((1 << 16) - 1) - int.from_bytes(
- int.from_bytes(self._outputLeveldB100[i : i + 2], "little") self._outputLeveldB100[i : i + 2], "little"
for i in range(0, 128, 2) )
) if val != ((1 << 16) - 1):
yield val
@property @property
def stripstate(self) -> tuple: def stripstate(self) -> tuple:

View File

@ -100,12 +100,12 @@ class StripLevel(IRemote):
) )
) )
self.level_map = phys_map + virt_map self.level_map = phys_map + virt_map
self.range = self.level_map[self.index]
def getter_prefader(self): def getter(self):
range_ = self.level_map[self.index]
return tuple( return tuple(
round(-i * 0.01, 1) round(-i * 0.01, 1)
for i in self._remote.strip_levels[range_[0] : range_[-1]] for i in self._remote.cache["strip_level"][self.range[0] : self.range[-1]]
) )
@property @property
@ -114,7 +114,7 @@ class StripLevel(IRemote):
@property @property
def prefader(self) -> tuple: def prefader(self) -> tuple:
return self.getter_prefader() return self.getter()
@property @property
def postfader(self) -> tuple: def postfader(self) -> tuple:
@ -125,8 +125,8 @@ class StripLevel(IRemote):
return return
@property @property
def updated(self) -> tuple: def is_updated(self) -> bool:
return self._remote._strip_comp return any(self._remote._strip_comp[self.range[0] : self.range[-1]])
class GainLayer(IRemote): class GainLayer(IRemote):