entry point now accepts a 'matrix' kind although it's main purpose is to disable the rt listener threads.

{VbanCmd}.sendtext():
- remove the @script decorator which I'm sure nobody has ever used anyway
- if rt listeners are disabled and it's a matrix query request, attempt to read a response.
This commit is contained in:
onyx-and-iris 2026-03-01 16:21:47 +00:00
parent 1123fe6432
commit ad2cfeaae6
3 changed files with 23 additions and 29 deletions

View File

@ -85,7 +85,7 @@ class FactoryBase(VbanCmd):
'channel': 0,
'ratelimit': 0.01,
'timeout': 5,
'outbound': False,
'disable_rt_listeners': False,
'sync': False,
'pdirty': False,
'ldirty': False,
@ -202,7 +202,13 @@ def vbancmd_factory(kind_id: str, **kwargs) -> VbanCmd:
_factory = BasicFactory
case 'banana':
_factory = BananaFactory
case 'potato':
case 'potato' | 'matrix':
# matrix is a special kind where:
# - we don't need to scale the interface with the builder (in other words kind is arbitrary).
# - we don't ever need to use real-time listeners, so we disable them to avoid confusion
if kind_id == 'matrix':
kwargs['disable_rt_listeners'] = True
kind_id = 'potato'
_factory = PotatoFactory
case _:
raise ValueError(f"Unknown Voicemeeter kind '{kind_id}'")

View File

@ -63,27 +63,6 @@ def depth(d):
return 0
def script(func):
"""Convert dictionary to script"""
def wrapper(*args):
remote, script = args
if isinstance(script, dict):
params = ''
for key, val in script.items():
obj, m2, *rem = key.split('-')
index = int(m2) if m2.isnumeric() else int(*rem)
params += ';'.join(
f'{obj}{f".{m2}stream" if not m2.isnumeric() else ""}[{index}].{k}={int(v) if isinstance(v, bool) else v}'
for k, v in val.items()
)
params += ';'
script = params
return func(remote, script)
return wrapper
def comp(t0: tuple, t1: tuple) -> Iterator[bool]:
"""
Generator function, accepts two tuples of dB values.

View File

@ -10,9 +10,9 @@ from typing import Union
from .enums import NBS
from .error import VBANCMDError
from .event import Event
from .packet.headers import VbanRequestHeader
from .packet.headers import VbanMatrixResponseHeader, VbanRequestHeader
from .subject import Subject
from .util import bump_framecounter, deep_merge, script
from .util import bump_framecounter, deep_merge
from .worker import Producer, Subscriber, Updater
logger = logging.getLogger(__name__)
@ -86,8 +86,8 @@ class VbanCmd(abc.ABC):
self.logout()
def login(self) -> None:
"""Starts the subscriber and updater threads (unless in outbound mode)"""
if not self.outbound:
"""Starts the subscriber and updater threads (unless disable_rt_listeners is True) and logs into Voicemeeter."""
if not self.disable_rt_listeners:
self.event.info()
self.stop_event = threading.Event()
@ -139,11 +139,20 @@ class VbanCmd(abc.ABC):
self._send_request(f'{cmd}={val};')
self.cache[cmd] = val
@script
def sendtext(self, script):
def sendtext(self, script) -> str | None:
"""Sends a multiple parameter string over a network."""
self._send_request(script)
self.logger.debug(f'sendtext: {script}')
if self.disable_rt_listeners and script.endswith(('?', '?;')):
try:
response = VbanMatrixResponseHeader.extract_payload(
self.sock.recv(1024)
)
return response
except ValueError as e:
self.logger.warning(f'Error extracting matrix response: {e}')
time.sleep(self.DELAY)
@property