diff --git a/vban_cmd/factory.py b/vban_cmd/factory.py index ee17d6b..b34256d 100644 --- a/vban_cmd/factory.py +++ b/vban_cmd/factory.py @@ -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}'") diff --git a/vban_cmd/util.py b/vban_cmd/util.py index 0bd215d..19ed1ab 100644 --- a/vban_cmd/util.py +++ b/vban_cmd/util.py @@ -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. diff --git a/vban_cmd/vbancmd.py b/vban_cmd/vbancmd.py index 7f5ade4..5890e66 100644 --- a/vban_cmd/vbancmd.py +++ b/vban_cmd/vbancmd.py @@ -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