From 6c9e4b1a89e215aa307318a42b1d2022bb72a2b9 Mon Sep 17 00:00:00 2001 From: onyx-and-iris Date: Thu, 19 Mar 2026 22:42:43 +0000 Subject: [PATCH] add bus mode binds (next + previous). --- addon/globalPlugins/voicemeeter/commands.py | 72 ++++++++++++++++----- addon/globalPlugins/voicemeeter/context.py | 20 +----- addon/globalPlugins/voicemeeter/util.py | 48 +++++++++++++- 3 files changed, 107 insertions(+), 33 deletions(-) diff --git a/addon/globalPlugins/voicemeeter/commands.py b/addon/globalPlugins/voicemeeter/commands.py index 419f0b8..aab05da 100644 --- a/addon/globalPlugins/voicemeeter/commands.py +++ b/addon/globalPlugins/voicemeeter/commands.py @@ -1,7 +1,7 @@ import ui from logHandler import log -from . import context +from . import context, util class CommandsMixin: @@ -56,7 +56,7 @@ class CommandsMixin: def script_audibility_mode(self, _): self.__set_slider_mode('audibility') - # Mono is a special case because the parameter is a boolean for strips and an int for buses + ### STRIP|BUS PARAMETERS ### def script_rotate_mono(self, _): if isinstance(self.controller.ctx.strategy, context.StripStrategy): @@ -70,7 +70,12 @@ class CommandsMixin: self.controller.ctx.set_int('mono', new_val) ui.message(opts[new_val]) - ### BOOLEAN PARAMETERS ### + def script_toggle_mute(self, _): + val = not self.controller.ctx.get_bool('mute') + self.controller.ctx.set_bool('mute', val) + ui.message('on' if val else 'off') + + ### STRIP PARAMETERS ### def script_toggle_solo(self, _): if not isinstance(self.controller.ctx.strategy, context.StripStrategy): @@ -81,11 +86,6 @@ class CommandsMixin: self.controller.ctx.set_bool('solo', val) ui.message('on' if val else 'off') - def script_toggle_mute(self, _): - val = not self.controller.ctx.get_bool('mute') - self.controller.ctx.set_bool('mute', val) - ui.message('on' if val else 'off') - def script_toggle_mc(self, _): if not isinstance(self.controller.ctx.strategy, context.StripStrategy): ui.message('MC only available for strips') @@ -110,7 +110,7 @@ class CommandsMixin: self.controller.ctx.set_bool('mc', val) ui.message('on' if val else 'off') - def script_karaoke(self, _): + def script_rotate_karaoke(self, _): if not isinstance(self.controller.ctx.strategy, context.StripStrategy): ui.message('Karaoke mode only available for strips') return @@ -152,34 +152,76 @@ class CommandsMixin: self.controller.ctx.set_bool(output, val) ui.message('on' if val else 'off') + ### BUS PARAMETERS ### + + def script_rotate_bus_mode_next(self, _): + if not isinstance(self.controller.ctx.strategy, context.BusStrategy): + ui.message('Bus mode only available for buses') + return + + opts = util._get_bus_mode_opts(self.kind.name) + for mode in opts: + if self.controller.ctx.get_bool(f'mode.{mode}'): + current_mode = mode + log.info(f'INFO - bus {self.controller.ctx.index} current mode {current_mode}') + break + else: + log.warning(f'WARNING - no bus mode found for bus {self.controller.ctx.index}') + return + + new_val = (opts.index(current_mode) + 1) % len(opts) + log.info(f'INFO - bus {self.controller.ctx.index} mode {opts[new_val]}') + self.controller.ctx.set_bool(f'mode.{opts[new_val]}', True) + ui.message(util._get_bus_mode_readable_name(opts[new_val])) + + def script_rotate_bus_mode_previous(self, _): + if not isinstance(self.controller.ctx.strategy, context.BusStrategy): + ui.message('Bus mode only available for buses') + return + + opts = util._get_bus_mode_opts(self.kind.name) + for mode in opts: + if self.controller.ctx.get_bool(f'mode.{mode}'): + current_mode = mode + log.info(f'INFO - bus {self.controller.ctx.index} current mode {current_mode}') + break + else: + log.warning(f'WARNING - no bus mode found for bus {self.controller.ctx.index}') + return + + new_val = (opts.index(current_mode) - 1) % len(opts) + log.info(f'INFO - bus {self.controller.ctx.index} mode {opts[new_val]}') + self.controller.ctx.set_bool(f'mode.{opts[new_val]}', True) + ui.message(util._get_bus_mode_readable_name(opts[new_val])) + ### CONTROL SLIDERS ### - def script_slider_increase_by_point_one(self, gesture): + def script_slider_increase_by_point_one(self, _): val = self.controller.ctx.get_float(self.controller.ctx.slider_mode) + 0.1 self.controller.ctx.set_float(self.controller.ctx.slider_mode, val) ui.message(str(round(val, 1))) - def script_slider_decrease_by_point_one(self, gesture): + def script_slider_decrease_by_point_one(self, _): val = self.controller.ctx.get_float(self.controller.ctx.slider_mode) - 0.1 self.controller.ctx.set_float(self.controller.ctx.slider_mode, val) ui.message(str(round(val, 1))) - def script_slider_increase_by_one(self, gesture): + def script_slider_increase_by_one(self, _): val = self.controller.ctx.get_float(self.controller.ctx.slider_mode) + 1 self.controller.ctx.set_float(self.controller.ctx.slider_mode, val) ui.message(str(round(val, 1))) - def script_slider_decrease_by_one(self, gesture): + def script_slider_decrease_by_one(self, _): val = self.controller.ctx.get_float(self.controller.ctx.slider_mode) - 1 self.controller.ctx.set_float(self.controller.ctx.slider_mode, val) ui.message(str(round(val, 1))) - def script_slider_increase_by_three(self, gesture): + def script_slider_increase_by_three(self, _): val = self.controller.ctx.get_float(self.controller.ctx.slider_mode) + 3 self.controller.ctx.set_float(self.controller.ctx.slider_mode, val) ui.message(str(round(val, 1))) - def script_slider_decrease_by_three(self, gesture): + def script_slider_decrease_by_three(self, _): val = self.controller.ctx.get_float(self.controller.ctx.slider_mode) - 3 self.controller.ctx.set_float(self.controller.ctx.slider_mode, val) ui.message(str(round(val, 1))) diff --git a/addon/globalPlugins/voicemeeter/context.py b/addon/globalPlugins/voicemeeter/context.py index e9c5e7e..2a5002b 100644 --- a/addon/globalPlugins/voicemeeter/context.py +++ b/addon/globalPlugins/voicemeeter/context.py @@ -92,20 +92,6 @@ class Context: def slider_mode(self, val): self._strategy._slider_mode = val - def get_bool(self, *args) -> bool: - return self._strategy.get_bool(*args) - - def set_bool(self, *args): - self._strategy.set_bool(*args) - - def get_float(self, *args) -> float: - return self._strategy.get_float(*args) - - def set_float(self, *args): - self._strategy.set_float(*args) - - def get_int(self, *args) -> int: - return self._strategy.get_int(*args) - - def set_int(self, *args): - self._strategy.set_int(*args) + def __getattr__(self, name): + """Delegate method calls to the strategy object.""" + return getattr(self._strategy, name) diff --git a/addon/globalPlugins/voicemeeter/util.py b/addon/globalPlugins/voicemeeter/util.py index 9ec8466..11dd401 100644 --- a/addon/globalPlugins/voicemeeter/util.py +++ b/addon/globalPlugins/voicemeeter/util.py @@ -30,7 +30,9 @@ def _make_gestures(kind_id): 'kb:NVDA+shift+s': 'toggle_solo', 'kb:NVDA+shift+m': 'toggle_mute', 'kb:NVDA+shift+c': 'toggle_mc', - 'kb:NVDA+shift+k': 'karaoke', + 'kb:NVDA+shift+k': 'rotate_karaoke', + 'kb:NVDA+shift+n': 'rotate_bus_mode_next', + 'kb:NVDA+shift+p': 'rotate_bus_mode_previous', 'kb:NVDA+shift+upArrow': 'slider_increase_by_point_one', 'kb:NVDA+shift+downArrow': 'slider_decrease_by_point_one', 'kb:NVDA+shift+alt+upArrow': 'slider_increase_by_one', @@ -49,3 +51,47 @@ def _make_gestures(kind_id): defaults = {k: v for k, v in defaults.items() if v not in matching_values} return {**defaults, **overrides} return defaults + + +_bus_mode_map = { + 'normal': 'Normal', + 'amix': 'Mix Down A', + 'bmix': 'Mix Down B', + 'repeat': 'Stereo Repeat', + 'composite': 'Composite', + 'tvmix': 'Up Mix TV', + 'upmix21': 'Up Mix 2.1', + 'upmix41': 'Up Mix 4.1', + 'upmix61': 'Up Mix 6.1', + 'centeronly': 'Center Only', + 'lfeonly': 'Low Frequency Effect Only', + 'rearonly': 'Rear Only', +} + + +def _get_bus_mode_opts(kind_id): + if kind_id == 'basic': + return [ + 'normal', + 'amix', + 'repeat', + 'composite', + ] + return [ + 'normal', + 'amix', + 'bmix', + 'repeat', + 'composite', + 'tvmix', + 'upmix21', + 'upmix41', + 'upmix61', + 'centeronly', + 'lfeonly', + 'rearonly', + ] + + +def _get_bus_mode_readable_name(mode): + return _bus_mode_map.get(mode, mode)