Compare commits

...

5 Commits

Author SHA1 Message Date
0dd6c89f96 implements up/down slider mode binds
adjustments to pdirty event toggling.

press/release events defined for slider binds

note:
the main window no longer returns keyboard events

minor bump
2023-09-23 16:36:48 +01:00
893f9f59ff patch asio spinboxes set as readonly
patch insert checkboxes enter bind added
2023-09-21 16:39:21 +01:00
3ca9e14e96 adds bass, mid and treble slider modes
patch bump
2023-09-21 09:33:22 +01:00
4ca64f94bc re 2023-09-21 08:35:55 +01:00
22bf109499 removes the spinbox from the rename popup
updates README

fixes #12

b1 bump
2023-09-20 18:24:24 +01:00
6 changed files with 364 additions and 302 deletions

View File

@@ -106,7 +106,7 @@ All sliders may be controlled in three different ways:
- `Shift + Left|Right arrow` to move a slider by 0.1 steps. - `Shift + Left|Right arrow` to move a slider by 0.1 steps.
- `Control + Left|Right arrow` to move a slider by 3 steps. - `Control + Left|Right arrow` to move a slider by 3 steps.
To rename a strip/bus channel navigate to the relevant tab, then press `F2`. This will open a popup window where you can set the channel index (with a spinbox) and set the new label using a text input box. To rename a strip/bus channel focus on the channel in question and press `F2`. Then enter the new channel name into the text input widget and press the `Ok` button.
Pressing the `OK` button with an empty text input will clear the label. In this case the label will be read as a default value for that channel. For example, if the leftmost Strip label were cleared, the screen reader will now read `Hardware Input 1`. Pressing the `OK` button with an empty text input will clear the label. In this case the label will be read as a default value for that channel. For example, if the leftmost Strip label were cleared, the screen reader will now read `Hardware Input 1`.
@@ -143,6 +143,9 @@ You may also enter slider modes which allow for control of the channels sliders
- `Control + G` will enter Gain mode - `Control + G` will enter Gain mode
- `Control + T` will enter Gate mode - `Control + T` will enter Gate mode
- `Control + L` will enter Limit mode - `Control + L` will enter Limit mode
- `Control + B` will enter Bass mode
- `Control + I` will enter Mid mode
- `Control + R` will enter Treble mode
To exit any of the slider modes press `Escape`. To exit any of the slider modes press `Escape`.

View File

@@ -1,6 +1,6 @@
[project] [project]
name = "nvda_voicemeeter" name = "nvda_voicemeeter"
version = "0.3.0" version = "0.4.0"
description = "A Voicemeeter app compatible with NVDA" description = "A Voicemeeter app compatible with NVDA"
authors = [ authors = [
{ name = "onyx-and-iris", email = "code@onyxandiris.online" }, { name = "onyx-and-iris", email = "code@onyxandiris.online" },

View File

@@ -220,7 +220,9 @@ class Builder:
[ [
psg.Checkbox( psg.Checkbox(
text=channel, text=channel,
default=self.vm.patch.insert[util.get_insert_checkbox_index(self.kind, j, i)].on, default=self.window.cache["insert"][
f"INSERT CHECKBOX||{util.get_insert_checkbox_index(self.kind, j, i)}"
],
enable_events=True, enable_events=True,
key=f"INSERT CHECKBOX||IN{i} {j}", key=f"INSERT CHECKBOX||IN{i} {j}",
) )
@@ -233,7 +235,9 @@ class Builder:
[ [
psg.Checkbox( psg.Checkbox(
text=channel, text=channel,
default=self.vm.patch.insert[util.get_insert_checkbox_index(self.kind, j, i)].on, default=self.window.cache["insert"][
f"INSERT CHECKBOX||{util.get_insert_checkbox_index(self.kind, j, i)}"
],
enable_events=True, enable_events=True,
key=f"INSERT CHECKBOX||IN{i} {j}", key=f"INSERT CHECKBOX||IN{i} {j}",
) )
@@ -323,7 +327,7 @@ class Builder:
) )
def add_param_sliders(layout): def add_param_sliders(layout):
layout.append([LabelSlider(self.window, i, param) for param in util.get_slider_params(i, self.vm)]) layout.append([LabelSlider(self.window, i, param) for param in util.get_slider_params(i, self.kind)])
def add_limit_slider(layout): def add_limit_slider(layout):
layout.append( layout.append(
@@ -416,13 +420,13 @@ class Builder:
def add_param_sliders(layout): def add_param_sliders(layout):
if self.kind.name in ("basic", "banana"): if self.kind.name in ("basic", "banana"):
for param in util.get_slider_params(i, self.vm): for param in util.get_slider_params(i, self.kind):
layout.append([LabelSlider(self.window, i, param, range_=(-12, 12))]) layout.append([LabelSlider(self.window, i, param, range_=(-12, 12))])
else: else:
layout.append( layout.append(
[ [
LabelSlider(self.window, i, param, range_=(-12, 12)) LabelSlider(self.window, i, param, range_=(-12, 12))
for param in util.get_slider_params(i, self.vm) for param in util.get_slider_params(i, self.kind)
] ]
) )

View File

@@ -11,6 +11,7 @@ logger = logging.getLogger(__name__)
class Popup: class Popup:
def __init__(self, window): def __init__(self, window):
self.window = window self.window = window
self.kind = self.window.kind
self.logger = logger.getChild(type(self).__name__) self.logger = logger.getChild(type(self).__name__)
def save_as(self, message, title=None, initial_folder=None): def save_as(self, message, title=None, initial_folder=None):
@@ -46,28 +47,27 @@ class Popup:
if filepath: if filepath:
return Path(filepath) return Path(filepath)
def rename(self, message, title=None, tab=None): def rename(self, message, index, title=None, tab=None):
if tab == "Physical Strip": if "Strip" in tab:
upper = self.window.kind.phys_in + 1 if index < self.kind.phys_in:
elif tab == "Virtual Strip": title += f" Physical Strip {index + 1}"
upper = self.window.kind.virt_in + 1 else:
elif tab == "Buses": title += f" Virtual Strip {index - self.kind.phys_in + 1}"
upper = self.window.kind.num_bus + 1 else:
if index < self.kind.phys_out:
title += f" Physical Bus {index + 1}"
else:
title += f" Virtual Bus {index - self.kind.phys_out + 1}"
layout = [ layout = [
[psg.Text(message)], [psg.Text(message)],
[ [
[ [
psg.Spin(
list(range(1, upper)), initial_value=1, size=2, enable_events=True, key=f"Index", readonly=True
),
psg.Input(key="Edit"), psg.Input(key="Edit"),
], ],
[psg.Button("Ok"), psg.Button("Cancel")], [psg.Button("Ok"), psg.Button("Cancel")],
], ],
] ]
popup = psg.Window(title, layout, finalize=True) popup = psg.Window(title, layout, finalize=True)
popup["Index"].bind("<FocusIn>", "||FOCUS IN")
popup["Edit"].bind("<FocusIn>", "||FOCUS IN") popup["Edit"].bind("<FocusIn>", "||FOCUS IN")
popup["Ok"].bind("<FocusIn>", "||FOCUS IN") popup["Ok"].bind("<FocusIn>", "||FOCUS IN")
popup["Ok"].bind("<Return>", "||KEY ENTER") popup["Ok"].bind("<Return>", "||KEY ENTER")
@@ -81,15 +81,8 @@ class Popup:
if event in (psg.WIN_CLOSED, "Cancel"): if event in (psg.WIN_CLOSED, "Cancel"):
break break
match parsed_cmd := self.window.parser.match.parseString(event): match parsed_cmd := self.window.parser.match.parseString(event):
case ["Index"]:
val = values["Index"]
self.window.nvda.speak(f"Index {val}")
case [[button], ["FOCUS", "IN"]]: case [[button], ["FOCUS", "IN"]]:
if button == "Index": self.window.nvda.speak(button)
val = values["Index"]
self.window.nvda.speak(f"Index {val}")
else:
self.window.nvda.speak(button)
case [[button], ["KEY", "ENTER"]]: case [[button], ["KEY", "ENTER"]]:
popup.find_element_with_focus().click() popup.find_element_with_focus().click()
case ["Ok"]: case ["Ok"]:

View File

@@ -141,12 +141,19 @@ def check_bounds(val, bounds: tuple) -> int | float:
return val return val
def get_slider_params(i, vm) -> Iterable: def get_slider_params(i, kind) -> Iterable:
if i < vm.kind.phys_in: if i < kind.phys_in:
if vm.kind.name == "basic": if kind.name == "basic":
return ("AUDIBILITY",) return ("AUDIBILITY",)
if vm.kind.name == "banana": if kind.name == "banana":
return ("COMP", "GATE") return ("COMP", "GATE")
if vm.kind.name == "potato": if kind.name == "potato":
return ("COMP", "GATE", "DENOISER") return ("COMP", "GATE", "DENOISER")
return ("BASS", "MID", "TREBLE") return ("BASS", "MID", "TREBLE")
def get_full_slider_params(i, kind) -> Iterable:
params = list(get_slider_params(i, kind) + ("GAIN", "LIMIT"))
if kind.name == "basic":
params.remove("LIMIT")
return params

View File

@@ -38,7 +38,7 @@ class NVDAVMWindow(psg.Window):
self.popup = Popup(self) self.popup = Popup(self)
self.builder = Builder(self) self.builder = Builder(self)
layout = self.builder.run() layout = self.builder.run()
super().__init__(title, layout, return_keyboard_events=True, finalize=True) super().__init__(title, layout, return_keyboard_events=False, finalize=True)
buttonmenu_opts = {"takefocus": 1, "highlightthickness": 1} buttonmenu_opts = {"takefocus": 1, "highlightthickness": 1}
for i in range(self.kind.phys_in): for i in range(self.kind.phys_in):
self[f"HARDWARE IN||{i + 1}"].Widget.config(**buttonmenu_opts) self[f"HARDWARE IN||{i + 1}"].Widget.config(**buttonmenu_opts)
@@ -50,13 +50,17 @@ class NVDAVMWindow(psg.Window):
[self[f"PATCH COMPOSITE||PC{i + 1}"].Widget.config(**buttonmenu_opts) for i in range(self.kind.phys_out)] [self[f"PATCH COMPOSITE||PC{i + 1}"].Widget.config(**buttonmenu_opts) for i in range(self.kind.phys_out)]
slider_opts = {"takefocus": 1, "highlightthickness": 1} slider_opts = {"takefocus": 1, "highlightthickness": 1}
for i in range(self.kind.num_strip): for i in range(self.kind.num_strip):
for param in util.get_slider_params(i, self.vm): for param in util.get_slider_params(i, self.kind):
self[f"STRIP {i}||SLIDER {param}"].Widget.config(**slider_opts) self[f"STRIP {i}||SLIDER {param}"].Widget.config(**slider_opts)
self[f"STRIP {i}||SLIDER GAIN"].Widget.config(**slider_opts) self[f"STRIP {i}||SLIDER GAIN"].Widget.config(**slider_opts)
if self.kind.name != "basic": if self.kind.name != "basic":
self[f"STRIP {i}||SLIDER LIMIT"].Widget.config(**slider_opts) self[f"STRIP {i}||SLIDER LIMIT"].Widget.config(**slider_opts)
for i in range(self.kind.num_bus): for i in range(self.kind.num_bus):
self[f"BUS {i}||SLIDER GAIN"].Widget.config(**slider_opts) self[f"BUS {i}||SLIDER GAIN"].Widget.config(**slider_opts)
if self.kind.name != "basic":
for i in range(self.kind.phys_out):
self[f"ASIO CHECKBOX||IN{i + 1} 0"].Widget.config(state="readonly")
self[f"ASIO CHECKBOX||IN{i + 1} 1"].Widget.config(state="readonly")
self.register_events() self.register_events()
self["tabgroup"].set_focus() self["tabgroup"].set_focus()
@@ -109,7 +113,7 @@ class NVDAVMWindow(psg.Window):
self[f"STRIP {i}||SLIDER GAIN"].update(value=self.vm.strip[i].gain) self[f"STRIP {i}||SLIDER GAIN"].update(value=self.vm.strip[i].gain)
if self.kind.name != "basic": if self.kind.name != "basic":
self[f"STRIP {i}||SLIDER LIMIT"].update(value=self.vm.strip[i].limit) self[f"STRIP {i}||SLIDER LIMIT"].update(value=self.vm.strip[i].limit)
for param in util.get_slider_params(i, self.vm): for param in util.get_slider_params(i, self.kind):
if param in ("AUDIBILITY", "BASS", "MID", "TREBLE"): if param in ("AUDIBILITY", "BASS", "MID", "TREBLE"):
val = getattr(self.vm.strip[i], param.lower()) val = getattr(self.vm.strip[i], param.lower())
else: else:
@@ -138,6 +142,7 @@ class NVDAVMWindow(psg.Window):
self[f"tabgroup||{tabname}"].bind("<Shift-KeyPress-Tab>", "||KEY SHIFT TAB") self[f"tabgroup||{tabname}"].bind("<Shift-KeyPress-Tab>", "||KEY SHIFT TAB")
self.bind("<Control-KeyPress-Tab>", "CTRL-TAB") self.bind("<Control-KeyPress-Tab>", "CTRL-TAB")
self.bind("<Control-Shift-KeyPress-Tab>", "CTRL-SHIFT-TAB") self.bind("<Control-Shift-KeyPress-Tab>", "CTRL-SHIFT-TAB")
self.bind("<F2>", "F2")
# NAV # NAV
self.bind("<Control-a>", "CTRL-A") self.bind("<Control-a>", "CTRL-A")
@@ -148,27 +153,30 @@ class NVDAVMWindow(psg.Window):
self.bind("<Control-o>", "CTRL-O") self.bind("<Control-o>", "CTRL-O")
self.bind("<Control-s>", "CTRL-S") self.bind("<Control-s>", "CTRL-S")
self.bind("<Control-m>", "CTRL-M") self.bind("<Control-m>", "CTRL-M")
self.bind("<Control-g>", "GAIN MODE")
self.bind("<Control-b>", "BASS MODE")
self.bind("<Control-i>", "MID MODE")
self.bind("<Control-r>", "TREBLE MODE")
if self.kind.name == "basic": if self.kind.name == "basic":
self.bind("<Control-u>", "AUDIBILITY MODE") self.bind("<Control-u>", "AUDIBILITY MODE")
self.bind("<Control-g>", "GAIN MODE")
elif self.kind.name == "banana": elif self.kind.name == "banana":
self.bind("<Control-g>", "GAIN MODE")
self.bind("<Control-c>", "COMP MODE") self.bind("<Control-c>", "COMP MODE")
self.bind("<Control-t>", "GATE MODE") self.bind("<Control-t>", "GATE MODE")
self.bind("<Control-l>", "LIMIT MODE") self.bind("<Control-l>", "LIMIT MODE")
else: else:
self.bind("<Control-g>", "GAIN MODE")
self.bind("<Control-c>", "COMP MODE") self.bind("<Control-c>", "COMP MODE")
self.bind("<Control-t>", "GATE MODE") self.bind("<Control-t>", "GATE MODE")
self.bind("<Control-d>", "DENOISER MODE") self.bind("<Control-d>", "DENOISER MODE")
self.bind("<Control-l>", "LIMIT MODE") self.bind("<Control-l>", "LIMIT MODE")
self.bind("<Escape>", "ESCAPE")
self.bind("<Alt-Left>", "LEFT") for event in ("KeyPress", "KeyRelease"):
self.bind("<Alt-Right>", "RIGHT") event_id = event.removeprefix("Key").upper()
self.bind("<Alt-Shift-KeyPress-Left>", "SHIFT-LEFT") for direction in ("Left", "Right", "Up", "Down"):
self.bind("<Alt-Shift-KeyPress-Right>", "SHIFT-RIGHT") self.bind(f"<Alt-{event}-{direction}>", f"ALT {direction.upper()}||{event_id}")
self.bind("<Alt-Control-KeyPress-Left>", "CTRL-LEFT") self.bind(f"<Alt-Shift-{event}-{direction}>", f"ALT SHIFT {direction.upper()}||{event_id}")
self.bind("<Alt-Control-KeyPress-Right>", "CTRL-RIGHT") self.bind(f"<Alt-Control-{event}-{direction}>", f"ALT CTRL {direction.upper()}||{event_id}")
# Hardware In # Hardware In
for i in range(self.vm.kind.phys_in): for i in range(self.vm.kind.phys_in):
@@ -205,8 +213,11 @@ class NVDAVMWindow(psg.Window):
if i < self.kind.phys_in: if i < self.kind.phys_in:
self[f"INSERT CHECKBOX||IN{i + 1} 0"].bind("<FocusIn>", "||FOCUS IN") self[f"INSERT CHECKBOX||IN{i + 1} 0"].bind("<FocusIn>", "||FOCUS IN")
self[f"INSERT CHECKBOX||IN{i + 1} 1"].bind("<FocusIn>", "||FOCUS IN") self[f"INSERT CHECKBOX||IN{i + 1} 1"].bind("<FocusIn>", "||FOCUS IN")
self[f"INSERT CHECKBOX||IN{i + 1} 0"].bind("<Return>", "||KEY ENTER")
self[f"INSERT CHECKBOX||IN{i + 1} 1"].bind("<Return>", "||KEY ENTER")
else: else:
[self[f"INSERT CHECKBOX||IN{i + 1} {j}"].bind("<FocusIn>", "||FOCUS IN") for j in range(8)] [self[f"INSERT CHECKBOX||IN{i + 1} {j}"].bind("<FocusIn>", "||FOCUS IN") for j in range(8)]
[self[f"INSERT CHECKBOX||IN{i + 1} {j}"].bind("<Return>", "||KEY ENTER") for j in range(8)]
# Advanced Settings # Advanced Settings
self["ADVANCED SETTINGS"].bind("<FocusIn>", "||FOCUS IN") self["ADVANCED SETTINGS"].bind("<FocusIn>", "||FOCUS IN")
@@ -231,23 +242,21 @@ class NVDAVMWindow(psg.Window):
# Strip Sliders # Strip Sliders
for i in range(self.kind.num_strip): for i in range(self.kind.num_strip):
for param in util.get_slider_params(i, self.vm) + ("GAIN", "LIMIT"): for param in util.get_full_slider_params(i, self.kind):
if self.kind.name == "basic" and param == "LIMIT":
continue
self[f"STRIP {i}||SLIDER {param}"].bind("<FocusIn>", "||FOCUS IN") self[f"STRIP {i}||SLIDER {param}"].bind("<FocusIn>", "||FOCUS IN")
self[f"STRIP {i}||SLIDER {param}"].bind("<FocusOut>", "||FOCUS OUT") self[f"STRIP {i}||SLIDER {param}"].bind("<FocusOut>", "||FOCUS OUT")
self[f"STRIP {i}||SLIDER {param}"].bind("<Left>", "||KEY LEFT") for event in ("KeyPress", "KeyRelease"):
self[f"STRIP {i}||SLIDER {param}"].bind("<Right>", "||KEY RIGHT") event_id = event.removeprefix("Key").upper()
self[f"STRIP {i}||SLIDER {param}"].bind("<Shift-KeyPress-Left>", "||KEY SHIFT LEFT") for direction in ("Left", "Right", "Up", "Down"):
self[f"STRIP {i}||SLIDER {param}"].bind("<Shift-KeyPress-Right>", "||KEY SHIFT RIGHT") self[f"STRIP {i}||SLIDER {param}"].bind(
self[f"STRIP {i}||SLIDER {param}"].bind("<Control-KeyPress-Left>", "||KEY CTRL LEFT") f"<{event}-{direction}>", f"||KEY {direction.upper()} {event_id}"
self[f"STRIP {i}||SLIDER {param}"].bind("<Control-KeyPress-Right>", "||KEY CTRL RIGHT") )
self[f"STRIP {i}||SLIDER {param}"].bind("<Up>", "||KEY UP") self[f"STRIP {i}||SLIDER {param}"].bind(
self[f"STRIP {i}||SLIDER {param}"].bind("<Down>", "||KEY DOWN") f"<Shift-{event}-{direction}>", f"||KEY SHIFT {direction.upper()} {event_id}"
self[f"STRIP {i}||SLIDER {param}"].bind("<Shift-KeyPress-Up>", "||KEY SHIFT UP") )
self[f"STRIP {i}||SLIDER {param}"].bind("<Shift-KeyPress-Down>", "||KEY SHIFT DOWN") self[f"STRIP {i}||SLIDER {param}"].bind(
self[f"STRIP {i}||SLIDER {param}"].bind("<Control-KeyPress-Up>", "||KEY CTRL UP") f"<Control-{event}-{direction}>", f"||KEY CTRL {direction.upper()} {event_id}"
self[f"STRIP {i}||SLIDER {param}"].bind("<Control-KeyPress-Down>", "||KEY CTRL DOWN") )
self[f"STRIP {i}||SLIDER {param}"].bind("<Control-Shift-KeyPress-R>", "||KEY CTRL SHIFT R") self[f"STRIP {i}||SLIDER {param}"].bind("<Control-Shift-KeyPress-R>", "||KEY CTRL SHIFT R")
# Bus Params # Bus Params
@@ -261,20 +270,18 @@ class NVDAVMWindow(psg.Window):
# Bus Sliders # Bus Sliders
for i in range(self.kind.num_bus): for i in range(self.kind.num_bus):
self[f"BUS {i}||SLIDER GAIN"].bind("<FocusIn>", "||FOCUS IN") for event in ("KeyPress", "KeyRelease"):
self[f"BUS {i}||SLIDER GAIN"].bind("<FocusOut>", "||FOCUS OUT") event_id = event.removeprefix("Key").upper()
self[f"BUS {i}||SLIDER GAIN"].bind("<Left>", "||KEY LEFT") for direction in ("Left", "Right", "Up", "Down"):
self[f"BUS {i}||SLIDER GAIN"].bind("<Right>", "||KEY RIGHT") self[f"BUS {i}||SLIDER GAIN"].bind(
self[f"BUS {i}||SLIDER GAIN"].bind("<Shift-KeyPress-Left>", "||KEY SHIFT LEFT") f"<{event}-{direction}>", f"||KEY {direction.upper()} {event_id}"
self[f"BUS {i}||SLIDER GAIN"].bind("<Shift-KeyPress-Right>", "||KEY SHIFT RIGHT") )
self[f"BUS {i}||SLIDER GAIN"].bind("<Control-KeyPress-Left>", "||KEY CTRL LEFT") self[f"BUS {i}||SLIDER GAIN"].bind(
self[f"BUS {i}||SLIDER GAIN"].bind("<Control-KeyPress-Right>", "||KEY CTRL RIGHT") f"<Shift-{event}-{direction}>", f"||KEY SHIFT {direction.upper()} {event_id}"
self[f"BUS {i}||SLIDER GAIN"].bind("<Up>", "||KEY UP") )
self[f"BUS {i}||SLIDER GAIN"].bind("<Down>", "||KEY DOWN") self[f"BUS {i}||SLIDER GAIN"].bind(
self[f"BUS {i}||SLIDER GAIN"].bind("<Shift-KeyPress-Up>", "||KEY SHIFT UP") f"<Control-{event}-{direction}>", f"||KEY CTRL {direction.upper()} {event_id}"
self[f"BUS {i}||SLIDER GAIN"].bind("<Shift-KeyPress-Down>", "||KEY SHIFT DOWN") )
self[f"BUS {i}||SLIDER GAIN"].bind("<Control-KeyPress-Up>", "||KEY CTRL UP")
self[f"BUS {i}||SLIDER GAIN"].bind("<Control-KeyPress-Down>", "||KEY CTRL DOWN")
self[f"BUS {i}||SLIDER GAIN"].bind("<Control-Shift-KeyPress-R>", "||KEY CTRL SHIFT R") self[f"BUS {i}||SLIDER GAIN"].bind("<Control-Shift-KeyPress-R>", "||KEY CTRL SHIFT R")
def run(self): def run(self):
@@ -291,20 +298,28 @@ class NVDAVMWindow(psg.Window):
self.logger.debug(f"values::{values}") self.logger.debug(f"values::{values}")
if event in (psg.WIN_CLOSED, "Exit"): if event in (psg.WIN_CLOSED, "Exit"):
break break
elif event in ("GAIN MODE", "COMP MODE", "GATE MODE", "DENOISER MODE", "LIMIT MODE"): elif event.endswith("MODE"):
mode = event mode = event
self.nvda.speak(f"{mode} enabled") self.nvda.speak(f"{mode} enabled")
elif event == "Escape:27": continue
elif event == "ESCAPE":
if mode: if mode:
self.nvda.speak(f"{mode.split()[0]} mode disabled") self.nvda.speak(f"{mode} disabled")
mode = None mode = None
continue
if mode:
if event in ("LEFT", "RIGHT", "SHIFT-LEFT", "SHIFT-RIGHT", "CTRL-LEFT", "CTRL-RIGHT"):
self.write_event_value(f"SLIDER-MODE-{event}", mode.split()[0])
continue
match parsed_cmd := self.parser.match.parseString(event): match parsed_cmd := self.parser.match.parseString(event):
# Slide mode
case [["ALT", "LEFT" | "RIGHT" | "UP" | "DOWN" as direction], ["PRESS" | "RELEASE" as e]]:
if mode:
self.write_event_value(f"SLIDER MODE {direction}||{e}", mode.split()[0])
case [
["ALT", "SHIFT" | "CTRL" as modifier, "LEFT" | "RIGHT" | "UP" | "DOWN" as direction],
["PRESS" | "RELEASE" as e],
]:
if mode:
self.write_event_value(f"SLIDER MODE {modifier} {direction}||{e}", mode.split()[0])
# Focus tabgroup # Focus tabgroup
case ["CTRL-TAB"] | ["CTRL-SHIFT-TAB"]: case ["CTRL-TAB"] | ["CTRL-SHIFT-TAB"]:
self["tabgroup"].set_focus() self["tabgroup"].set_focus()
@@ -372,51 +387,62 @@ class NVDAVMWindow(psg.Window):
if focus := self.find_element_with_focus(): if focus := self.find_element_with_focus():
identifier, param = focus.Key.split("||") identifier, param = focus.Key.split("||")
self.write_event_value(f"{identifier}||MUTE", None) self.write_event_value(f"{identifier}||MUTE", None)
case [ case [["SLIDER", "MODE", direction], ["PRESS" | "RELEASE" as e]]:
"SLIDER-MODE-LEFT"
| "SLIDER-MODE-RIGHT"
| "SLIDER-MODE-SHIFT-LEFT"
| "SLIDER-MODE-SHIFT-RIGHT"
| "SLIDER-MODE-CTRL-LEFT"
| "SLIDER-MODE-CTRL-RIGHT" as op
]:
op = op.removeprefix("SLIDER-MODE-").split("-")
if values["tabgroup"] not in ("tab||Physical Strip", "tab||Virtual Strip", "tab||Buses"): if values["tabgroup"] not in ("tab||Physical Strip", "tab||Virtual Strip", "tab||Buses"):
continue continue
param = values[event] param = values[event]
if focus := self.find_element_with_focus(): if focus := self.find_element_with_focus():
identifier, partial = focus.Key.split("||") identifier, partial = focus.Key.split("||")
if "SLIDER" not in partial: _, index = identifier.split()
self.write_event_value(f"{identifier}||SLIDER {param}||KEY {' '.join(op)}", None) if param in util.get_full_slider_params(int(index), self.kind):
if "SLIDER" not in partial:
self.write_event_value(f"{identifier}||SLIDER {param}||KEY {direction} {e}", None)
case [
["SLIDER", "MODE", "SHIFT" | "CTRL" as modifier, direction],
["PRESS" | "RELEASE" as e],
]:
if values["tabgroup"] not in ("tab||Physical Strip", "tab||Virtual Strip", "tab||Buses"):
continue
param = values[event]
if focus := self.find_element_with_focus():
identifier, partial = focus.Key.split("||")
_, index = identifier.split()
if param in util.get_full_slider_params(int(index), self.kind):
if "SLIDER" not in partial:
self.write_event_value(
f"{identifier}||SLIDER {param}||KEY {modifier} {direction} {e}", None
)
# Rename popups # Rename popups
case ["F2:113"]: case ["F2"]:
tab = values["tabgroup"].split("||")[1] tab = values["tabgroup"].split("||")[1]
if tab in ("Physical Strip", "Virtual Strip", "Buses"): if tab in ("Physical Strip", "Virtual Strip", "Buses"):
data = self.popup.rename("Label", title=f"Rename {tab}", tab=tab) if focus := self.find_element_with_focus():
if not data: # cancel was pressed identifier, partial = focus.Key.split("||")
continue _, index = identifier.split()
index = int(data["Index"]) - 1 index = int(index)
match tab: data = self.popup.rename("Label", index, title=f"Rename", tab=tab)
case "Physical Strip": if not data: # cancel was pressed
label = data.get("Edit", f"Hardware Input {index + 1}") continue
self.vm.strip[index].label = label match tab:
self[f"STRIP {index}||LABEL"].update(value=label) case "Physical Strip":
self.cache["labels"][f"STRIP {index}||LABEL"] = label label = data.get("Edit", f"Hardware Input {int(index) + 1}")
case "Virtual Strip": self.vm.strip[int(index)].label = label
index += self.kind.phys_in self[f"STRIP {index}||LABEL"].update(value=label)
label = data.get("Edit", f"Virtual Input {index - self.kind.phys_in + 1}") self.cache["labels"][f"STRIP {index}||LABEL"] = label
self.vm.strip[index].label = label case "Virtual Strip":
self[f"STRIP {index}||LABEL"].update(value=label) label = data.get("Edit", f"Virtual Input {int(index) + 1}")
self.cache["labels"][f"STRIP {index}||LABEL"] = label self.vm.strip[int(index)].label = label
case "Buses": self[f"STRIP {index}||LABEL"].update(value=label)
if index < self.kind.phys_out: self.cache["labels"][f"STRIP {index}||LABEL"] = label
label = data.get("Edit", f"Physical Bus {index + 1}") case "Buses":
else: if index < self.kind.phys_out:
label = data.get("Edit", f"Virtual Bus {index - self.kind.phys_out + 1}") label = data.get("Edit", f"Physical Bus {int(index) + 1}")
self.vm.bus[index].label = label else:
self[f"BUS {index}||LABEL"].update(value=label) label = data.get("Edit", f"Virtual Bus {int(index) - self.kind.phys_out + 1}")
self.cache["labels"][f"BUS {index}||LABEL"] = label self.vm.bus[int(index)].label = label
self[f"BUS {index}||LABEL"].update(value=label)
self.cache["labels"][f"BUS {index}||LABEL"] = label
# Menus # Menus
case [["Restart", "Audio", "Engine"], ["MENU"]]: case [["Restart", "Audio", "Engine"], ["MENU"]]:
@@ -575,7 +601,7 @@ class NVDAVMWindow(psg.Window):
) )
val = values[f"INSERT CHECKBOX||{in_num} {channel}"] val = values[f"INSERT CHECKBOX||{in_num} {channel}"]
self.vm.patch.insert[index].on = val self.vm.patch.insert[index].on = val
self.nvda.speak(f"{'on' if val else 'off'}") self.nvda.speak("on" if val else "off")
case [["INSERT", "CHECKBOX"], [in_num, channel], ["FOCUS", "IN"]]: case [["INSERT", "CHECKBOX"], [in_num, channel], ["FOCUS", "IN"]]:
if self.find_element_with_focus() is not None: if self.find_element_with_focus() is not None:
index = util.get_insert_checkbox_index( index = util.get_insert_checkbox_index(
@@ -587,6 +613,9 @@ class NVDAVMWindow(psg.Window):
channel = util._patch_insert_channels[int(channel)] channel = util._patch_insert_channels[int(channel)]
num = int(in_num[-1]) num = int(in_num[-1])
self.nvda.speak(f"Patch INSERT IN#{num} {channel} {'on' if val else 'off'}") self.nvda.speak(f"Patch INSERT IN#{num} {channel} {'on' if val else 'off'}")
case [["INSERT", "CHECKBOX"], [in_num, channel], ["KEY", "ENTER"]]:
val = not values[f"INSERT CHECKBOX||{in_num} {channel}"]
self.write_event_value(f"INSERT CHECKBOX||{in_num} {channel}", val)
# Advanced Settings # Advanced Settings
case ["ADVANCED SETTINGS"] | ["CTRL-A"]: case ["ADVANCED SETTINGS"] | ["CTRL-A"]:
@@ -697,7 +726,6 @@ class NVDAVMWindow(psg.Window):
["FOCUS", "IN"], ["FOCUS", "IN"],
]: ]:
if self.find_element_with_focus() is not None: if self.find_element_with_focus() is not None:
self.vm.event.pdirty = False
val = values[f"STRIP {index}||SLIDER {param}"] val = values[f"STRIP {index}||SLIDER {param}"]
label = self.cache["labels"][f"STRIP {index}||LABEL"] label = self.cache["labels"][f"STRIP {index}||LABEL"]
self.nvda.speak(f"{label} {param} {int(val) if param == 'LIMIT' else val}") self.nvda.speak(f"{label} {param} {int(val) if param == 'LIMIT' else val}")
@@ -709,7 +737,7 @@ class NVDAVMWindow(psg.Window):
], ],
["FOCUS", "OUT"], ["FOCUS", "OUT"],
]: ]:
self.vm.event.pdirty = True pass
case [ case [
["STRIP", index], ["STRIP", index],
[ [
@@ -724,112 +752,53 @@ class NVDAVMWindow(psg.Window):
| "MID" | "MID"
| "TREBLE" as param, | "TREBLE" as param,
], ],
["KEY", "LEFT" | "RIGHT" | "UP" | "DOWN" as direction], ["KEY", "LEFT" | "RIGHT" | "UP" | "DOWN" as direction, "PRESS" | "RELEASE" as e],
]: ]:
match param: if e == "PRESS":
case "GAIN": self.vm.event.pdirty = False
val = self.vm.strip[int(index)].gain match param:
case "COMP" | "GATE" | "DENOISER": case "GAIN":
target = getattr(self.vm.strip[int(index)], param.lower()) val = self.vm.strip[int(index)].gain
val = target.knob case "COMP" | "GATE" | "DENOISER":
case "AUDIBILITY": target = getattr(self.vm.strip[int(index)], param.lower())
val = self.vm.strip[int(index)].audibility val = target.knob
case "BASS" | "MID" | "TREBLE": case "AUDIBILITY":
val = getattr(self.vm.strip[int(index)], param.lower()) val = self.vm.strip[int(index)].audibility
case "LIMIT": case "BASS" | "MID" | "TREBLE":
val = self.vm.strip[int(index)].limit val = getattr(self.vm.strip[int(index)], param.lower())
case "LIMIT":
val = self.vm.strip[int(index)].limit
match direction: match direction:
case "RIGHT" | "UP": case "RIGHT" | "UP":
val += 1
case "LEFT" | "DOWN":
val -= 1
match param:
case "GAIN":
val = util.check_bounds(val, (-60, 12))
self.vm.strip[int(index)].gain = val
self[f"STRIP {index}||SLIDER {param}"].update(value=val)
case "COMP" | "GATE" | "DENOISER":
val = util.check_bounds(val, (0, 10))
setattr(target, "knob", val)
self[f"STRIP {index}||SLIDER {param}"].update(value=val)
case "AUDIBILITY":
val = util.check_bounds(val, (0, 10))
self.vm.strip[int(index)].audibility = val
self[f"STRIP {index}||SLIDER {param}"].update(value=val)
case "BASS" | "MID" | "TREBLE":
val = util.check_bounds(val, (-12, 12))
setattr(self.vm.strip[int(index)], param.lower(), val)
self[f"STRIP {index}||SLIDER {param}"].update(value=val)
case "LIMIT":
val = util.check_bounds(val, (-40, 12))
self.vm.strip[int(index)].limit = val
self[f"STRIP {index}||SLIDER {param}"].update(value=val)
self.nvda.speak(str(val))
case [
["STRIP", index],
[
"SLIDER",
"GAIN"
| "COMP"
| "GATE"
| "DENOISER"
| "AUDIBILITY"
| "LIMIT"
| "BASS"
| "MID"
| "TREBLE" as param,
],
["KEY", "CTRL", "LEFT" | "RIGHT" | "UP" | "DOWN" as direction],
]:
match param:
case "GAIN":
val = self.vm.strip[int(index)].gain
case "COMP" | "GATE" | "DENOISER":
target = getattr(self.vm.strip[int(index)], param.lower())
val = target.knob
case "AUDIBILITY":
val = self.vm.strip[int(index)].audibility
case "BASS" | "MID" | "TREBLE":
val = getattr(self.vm.strip[int(index)], param.lower())
case "LIMIT":
val = self.vm.strip[int(index)].limit
match direction:
case "RIGHT" | "UP":
if param in ("COMP", "GATE", "DENOISER", "AUDIBILITY", "BASS", "MID", "TREBLE"):
val += 1 val += 1
else: case "LEFT" | "DOWN":
val += 3
case "LEFT" | "DOWN":
if param in ("COMP", "GATE", "DENOISER", "AUDIBILITY", "BASS", "MID", "TREBLE"):
val -= 1 val -= 1
else:
val -= 3
match param: match param:
case "GAIN": case "GAIN":
val = util.check_bounds(val, (-60, 12)) val = util.check_bounds(val, (-60, 12))
self.vm.strip[int(index)].gain = val self.vm.strip[int(index)].gain = val
self[f"STRIP {index}||SLIDER {param}"].update(value=val) self[f"STRIP {index}||SLIDER {param}"].update(value=val)
case "COMP" | "GATE" | "DENOISER": case "COMP" | "GATE" | "DENOISER":
val = util.check_bounds(val, (0, 10)) val = util.check_bounds(val, (0, 10))
setattr(target, "knob", val) setattr(target, "knob", val)
self[f"STRIP {index}||SLIDER {param}"].update(value=val) self[f"STRIP {index}||SLIDER {param}"].update(value=val)
case "AUDIBILITY": case "AUDIBILITY":
val = util.check_bounds(val, (0, 10)) val = util.check_bounds(val, (0, 10))
self.vm.strip[int(index)].audibility = val self.vm.strip[int(index)].audibility = val
self[f"STRIP {index}||SLIDER {param}"].update(value=val) self[f"STRIP {index}||SLIDER {param}"].update(value=val)
case "BASS" | "MID" | "TREBLE": case "BASS" | "MID" | "TREBLE":
val = util.check_bounds(val, (-12, 12)) val = util.check_bounds(val, (-12, 12))
setattr(self.vm.strip[int(index)], param.lower(), val) setattr(self.vm.strip[int(index)], param.lower(), val)
self[f"STRIP {index}||SLIDER {param}"].update(value=val) self[f"STRIP {index}||SLIDER {param}"].update(value=val)
case "LIMIT": case "LIMIT":
val = util.check_bounds(val, (-40, 12)) val = util.check_bounds(val, (-40, 12))
self.vm.strip[int(index)].limit = val self.vm.strip[int(index)].limit = val
self[f"STRIP {index}||SLIDER {param}"].update(value=val) self[f"STRIP {index}||SLIDER {param}"].update(value=val)
self.nvda.speak(f"{param} {val}") self.nvda.speak(str(val))
else:
self.vm.event.pdirty = True
case [ case [
["STRIP", index], ["STRIP", index],
[ [
@@ -844,55 +813,126 @@ class NVDAVMWindow(psg.Window):
| "MID" | "MID"
| "TREBLE" as param, | "TREBLE" as param,
], ],
["KEY", "SHIFT", "LEFT" | "RIGHT" | "UP" | "DOWN" as direction], ["KEY", "CTRL", "LEFT" | "RIGHT" | "UP" | "DOWN" as direction, "PRESS" | "RELEASE" as e],
]: ]:
match param: if e == "PRESS":
case "GAIN": self.vm.event.pdirty = False
val = self.vm.strip[int(index)].gain match param:
case "COMP" | "GATE" | "DENOISER": case "GAIN":
target = getattr(self.vm.strip[int(index)], param.lower()) val = self.vm.strip[int(index)].gain
val = target.knob case "COMP" | "GATE" | "DENOISER":
case "AUDIBILITY": target = getattr(self.vm.strip[int(index)], param.lower())
val = self.vm.strip[int(index)].audibility val = target.knob
case "BASS" | "MID" | "TREBLE": case "AUDIBILITY":
val = getattr(self.vm.strip[int(index)], param.lower()) val = self.vm.strip[int(index)].audibility
case "LIMIT": case "BASS" | "MID" | "TREBLE":
val = self.vm.strip[int(index)].limit val = getattr(self.vm.strip[int(index)], param.lower())
case "LIMIT":
val = self.vm.strip[int(index)].limit
match direction: match direction:
case "RIGHT" | "UP": case "RIGHT" | "UP":
if param == "LIMIT": if param in ("COMP", "GATE", "DENOISER", "AUDIBILITY", "BASS", "MID", "TREBLE"):
val += 1 val += 1
else: else:
val += 0.1 val += 3
case "LEFT" | "DOWN": case "LEFT" | "DOWN":
if param == "LIMIT": if param in ("COMP", "GATE", "DENOISER", "AUDIBILITY", "BASS", "MID", "TREBLE"):
val -= 1 val -= 1
else: else:
val -= 0.1 val -= 3
match param: match param:
case "GAIN": case "GAIN":
val = util.check_bounds(val, (-60, 12)) val = util.check_bounds(val, (-60, 12))
self.vm.strip[int(index)].gain = val self.vm.strip[int(index)].gain = val
self[f"STRIP {index}||SLIDER {param}"].update(value=val) self[f"STRIP {index}||SLIDER {param}"].update(value=val)
case "COMP" | "GATE" | "DENOISER": case "COMP" | "GATE" | "DENOISER":
val = util.check_bounds(val, (0, 10)) val = util.check_bounds(val, (0, 10))
setattr(target, "knob", val) setattr(target, "knob", val)
self[f"STRIP {index}||SLIDER {param}"].update(value=val) self[f"STRIP {index}||SLIDER {param}"].update(value=val)
case "AUDIBILITY": case "AUDIBILITY":
val = util.check_bounds(val, (0, 10)) val = util.check_bounds(val, (0, 10))
self.vm.strip[int(index)].audibility = val self.vm.strip[int(index)].audibility = val
self[f"STRIP {index}||SLIDER {param}"].update(value=val) self[f"STRIP {index}||SLIDER {param}"].update(value=val)
case "BASS" | "MID" | "TREBLE": case "BASS" | "MID" | "TREBLE":
val = util.check_bounds(val, (-12, 12)) val = util.check_bounds(val, (-12, 12))
setattr(self.vm.strip[int(index)], param.lower(), val) setattr(self.vm.strip[int(index)], param.lower(), val)
self[f"STRIP {index}||SLIDER {param}"].update(value=val) self[f"STRIP {index}||SLIDER {param}"].update(value=val)
case "LIMIT": case "LIMIT":
val = util.check_bounds(val, (-40, 12)) val = util.check_bounds(val, (-40, 12))
self.vm.strip[int(index)].limit = val self.vm.strip[int(index)].limit = val
self[f"STRIP {index}||SLIDER {param}"].update(value=val) self[f"STRIP {index}||SLIDER {param}"].update(value=val)
self.nvda.speak(f"{param} {val}") self.nvda.speak(f"{param} {val}")
else:
self.vm.event.pdirty = True
case [
["STRIP", index],
[
"SLIDER",
"GAIN"
| "COMP"
| "GATE"
| "DENOISER"
| "AUDIBILITY"
| "LIMIT"
| "BASS"
| "MID"
| "TREBLE" as param,
],
["KEY", "SHIFT", "LEFT" | "RIGHT" | "UP" | "DOWN" as direction, "PRESS" | "RELEASE" as e],
]:
if e == "PRESS":
self.vm.event.pdirty = False
match param:
case "GAIN":
val = self.vm.strip[int(index)].gain
case "COMP" | "GATE" | "DENOISER":
target = getattr(self.vm.strip[int(index)], param.lower())
val = target.knob
case "AUDIBILITY":
val = self.vm.strip[int(index)].audibility
case "BASS" | "MID" | "TREBLE":
val = getattr(self.vm.strip[int(index)], param.lower())
case "LIMIT":
val = self.vm.strip[int(index)].limit
match direction:
case "RIGHT" | "UP":
if param == "LIMIT":
val += 1
else:
val += 0.1
case "LEFT" | "DOWN":
if param == "LIMIT":
val -= 1
else:
val -= 0.1
match param:
case "GAIN":
val = util.check_bounds(val, (-60, 12))
self.vm.strip[int(index)].gain = val
self[f"STRIP {index}||SLIDER {param}"].update(value=val)
case "COMP" | "GATE" | "DENOISER":
val = util.check_bounds(val, (0, 10))
setattr(target, "knob", val)
self[f"STRIP {index}||SLIDER {param}"].update(value=val)
case "AUDIBILITY":
val = util.check_bounds(val, (0, 10))
self.vm.strip[int(index)].audibility = val
self[f"STRIP {index}||SLIDER {param}"].update(value=val)
case "BASS" | "MID" | "TREBLE":
val = util.check_bounds(val, (-12, 12))
setattr(self.vm.strip[int(index)], param.lower(), val)
self[f"STRIP {index}||SLIDER {param}"].update(value=val)
case "LIMIT":
val = util.check_bounds(val, (-40, 12))
self.vm.strip[int(index)].limit = val
self[f"STRIP {index}||SLIDER {param}"].update(value=val)
self.nvda.speak(f"{param} {val}")
else:
self.vm.event.pdirty = True
case [["STRIP", index], ["SLIDER", param], ["KEY", "CTRL", "SHIFT", "R"]]: case [["STRIP", index], ["SLIDER", param], ["KEY", "CTRL", "SHIFT", "R"]]:
match param: match param:
case "GAIN": case "GAIN":
@@ -978,53 +1018,68 @@ class NVDAVMWindow(psg.Window):
self.vm.bus[int(index)].gain = val self.vm.bus[int(index)].gain = val
case [["BUS", index], ["SLIDER", "GAIN"], ["FOCUS", "IN"]]: case [["BUS", index], ["SLIDER", "GAIN"], ["FOCUS", "IN"]]:
if self.find_element_with_focus() is not None: if self.find_element_with_focus() is not None:
self.vm.event.pdirty = False
label = self.cache["labels"][f"BUS {index}||LABEL"] label = self.cache["labels"][f"BUS {index}||LABEL"]
val = values[f"BUS {index}||SLIDER GAIN"] val = values[f"BUS {index}||SLIDER GAIN"]
self.nvda.speak(f"{label} gain {val}") self.nvda.speak(f"{label} gain {val}")
case [["BUS", index], ["SLIDER", "GAIN"], ["FOCUS", "OUT"]]: case [["BUS", index], ["SLIDER", "GAIN"], ["FOCUS", "OUT"]]:
self.vm.event.pdirty = True pass
case [["BUS", index], ["SLIDER", "GAIN"], ["KEY", "LEFT" | "RIGHT" | "UP" | "DOWN" as direction]]:
val = self.vm.bus[int(index)].gain
match direction:
case "RIGHT" | "UP":
val += 1
case "LEFT" | "DOWN":
val -= 1
val = util.check_bounds(val, (-60, 12))
self.vm.bus[int(index)].gain = val
self[f"BUS {index}||SLIDER GAIN"].update(value=val)
self.nvda.speak(str(val))
case [ case [
["BUS", index], ["BUS", index],
["SLIDER", "GAIN"], ["SLIDER", "GAIN"],
["KEY", "CTRL", "LEFT" | "RIGHT" | "UP" | "DOWN" as direction], ["KEY", "LEFT" | "RIGHT" | "UP" | "DOWN" as direction, "PRESS" | "RELEASE" as e],
]: ]:
val = self.vm.bus[int(index)].gain if e == "PRESS":
match direction: self.vm.event.pdirty = False
case "RIGHT" | "UP": val = self.vm.bus[int(index)].gain
val += 3 match direction:
case "LEFT" | "DOWN": case "RIGHT" | "UP":
val -= 3 val += 1
val = util.check_bounds(val, (-60, 12)) case "LEFT" | "DOWN":
self.vm.bus[int(index)].gain = val val -= 1
self[f"BUS {index}||SLIDER GAIN"].update(value=val) val = util.check_bounds(val, (-60, 12))
self.nvda.speak(str(val)) self.vm.bus[int(index)].gain = val
self[f"BUS {index}||SLIDER GAIN"].update(value=val)
self.nvda.speak(str(val))
else:
self.vm.event.pdirty = True
case [ case [
["BUS", index], ["BUS", index],
["SLIDER", "GAIN"], ["SLIDER", "GAIN"],
["KEY", "SHIFT", "LEFT" | "RIGHT" | "UP" | "DOWN" as direction], ["KEY", "CTRL", "LEFT" | "RIGHT" | "UP" | "DOWN" as direction, "PRESS" | "RELEASE" as e],
]: ]:
val = self.vm.bus[int(index)].gain if e == "PRESS":
match direction: self.vm.event.pdirty = False
case "RIGHT" | "UP": val = self.vm.bus[int(index)].gain
val += 0.1 match direction:
case "LEFT" | "DOWN": case "RIGHT" | "UP":
val -= 0.1 val += 3
val = util.check_bounds(val, (-60, 12)) case "LEFT" | "DOWN":
self.vm.bus[int(index)].gain = val val -= 3
self[f"BUS {index}||SLIDER GAIN"].update(value=val) val = util.check_bounds(val, (-60, 12))
self.nvda.speak(str(val)) self.vm.bus[int(index)].gain = val
self[f"BUS {index}||SLIDER GAIN"].update(value=val)
self.nvda.speak(str(val))
else:
self.vm.event.pdirty = True
case [
["BUS", index],
["SLIDER", "GAIN"],
["KEY", "SHIFT", "LEFT" | "RIGHT" | "UP" | "DOWN" as direction, "PRESS" | "RELEASE" as e],
]:
if e == "PRESS":
self.vm.event.pdirty = False
val = self.vm.bus[int(index)].gain
match direction:
case "RIGHT" | "UP":
val += 0.1
case "LEFT" | "DOWN":
val -= 0.1
val = util.check_bounds(val, (-60, 12))
self.vm.bus[int(index)].gain = val
self[f"BUS {index}||SLIDER GAIN"].update(value=val)
self.nvda.speak(str(val))
else:
self.vm.event.pdirty = True
case [["BUS", index], ["SLIDER", "GAIN"], ["KEY", "CTRL", "SHIFT", "R"]]: case [["BUS", index], ["SLIDER", "GAIN"], ["KEY", "CTRL", "SHIFT", "R"]]:
self.vm.bus[int(index)].gain = 0 self.vm.bus[int(index)].gain = 0
self[f"BUS {index}||SLIDER GAIN"].update(value=0) self[f"BUS {index}||SLIDER GAIN"].update(value=0)