mirror of
https://github.com/onyx-and-iris/nvda-voicemeeter.git
synced 2026-04-07 09:53:35 +00:00
Compare commits
24 Commits
add-nav-bi
...
v.0.5.2
| Author | SHA1 | Date | |
|---|---|---|---|
| bdd570738a | |||
| 71b137a9c2 | |||
| 912eb8c14d | |||
| 9cd65737e5 | |||
| 4a6ca2a353 | |||
| cc99b14e89 | |||
| 23458debaa | |||
| 496cc35321 | |||
| d758db9dee | |||
| 876de55ad2 | |||
| eab4b1c6a9 | |||
| 0aeb33608f | |||
| 5befe72ca1 | |||
| abab560281 | |||
| 6882adb47b | |||
| af602e087d | |||
| 01e80dc4f6 | |||
| 7262af4bcf | |||
| ef10b224d7 | |||
| 89d0253591 | |||
| 85527e0749 | |||
| 9d8ea5f747 | |||
| 0dd6c89f96 | |||
| 893f9f59ff |
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"black-formatter.args": [
|
||||
"--line-length=120"
|
||||
]
|
||||
}
|
||||
19
README.md
19
README.md
@@ -1,6 +1,7 @@
|
||||
[](https://pdm.fming.dev)
|
||||
[](https://github.com/psf/black)
|
||||
[](https://pycqa.github.io/isort/)
|
||||
[](https://github.com/astral-sh/ruff)
|
||||
|
||||
# NVDA Voicemeeter
|
||||
|
||||
@@ -106,12 +107,30 @@ All sliders may be controlled in three different ways:
|
||||
- `Shift + Left|Right arrow` to move a slider by 0.1 steps.
|
||||
- `Control + Left|Right arrow` to move a slider by 3 steps.
|
||||
|
||||
To reset a slider back to its default value you may use `Control + Shift + R`.
|
||||
|
||||
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 `Cancel` will close the popup window with no affect on the label.
|
||||
|
||||
#### `Advanced Compressor|Gate`
|
||||
|
||||
For potato version only, you may access advanced Compressor and Gate sliders. Simply focus any Gate or Compressor slider and press `Control + A`. This will open a popup window where you can navigate between the different sliders with `TAB`. Move the sliders with the same binds you would for normal sliders. However, there are a couple of extra binds for certain controls.
|
||||
|
||||
For Compressor Release you may use:
|
||||
|
||||
- `Alt + Left|Right arrow` to move the slider by 10 steps.
|
||||
- `Alt + Control + Left|Right arrow` to move the slider by 50 steps.
|
||||
|
||||
For Gate BP Sidechain, Attack, Hold, Release you may use:
|
||||
|
||||
- `Alt + Left|Right arrow` to move the slider by 10 steps.
|
||||
- `Alt + Control + Left|Right arrow` to move the slider by 50 steps.
|
||||
|
||||
To reset a slider back to its default value you may use `Control + Shift + R`.
|
||||
|
||||
#### `Menu`
|
||||
|
||||
A single menu item `Voicemeeter` can be opened using `Alt` and then `v`. The menu allows you to:
|
||||
|
||||
78
pdm.lock
generated
78
pdm.lock
generated
@@ -6,7 +6,7 @@ groups = ["default", "build", "lint", "test"]
|
||||
cross_platform = true
|
||||
static_urls = false
|
||||
lock_version = "4.3"
|
||||
content_hash = "sha256:ba53368b628b713c9cf4eb54e6f5c5c4af207c8e247d473417e4c2a4b47f645d"
|
||||
content_hash = "sha256:680eff1b532e55860290380d4e2f331dc29af6fb898a0df16fdb033843bf15a4"
|
||||
|
||||
[[package]]
|
||||
name = "altgraph"
|
||||
@@ -63,21 +63,6 @@ files = [
|
||||
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "flake8"
|
||||
version = "6.1.0"
|
||||
requires_python = ">=3.8.1"
|
||||
summary = "the modular source code checker: pep8 pyflakes and co"
|
||||
dependencies = [
|
||||
"mccabe<0.8.0,>=0.7.0",
|
||||
"pycodestyle<2.12.0,>=2.11.0",
|
||||
"pyflakes<3.2.0,>=3.1.0",
|
||||
]
|
||||
files = [
|
||||
{file = "flake8-6.1.0-py2.py3-none-any.whl", hash = "sha256:ffdfce58ea94c6580c77888a86506937f9a1a227dfcd15f245d694ae20a6b6e5"},
|
||||
{file = "flake8-6.1.0.tar.gz", hash = "sha256:d5b3857f07c030bdb5bf41c7f53799571d75c4491748a3adcd47de929e34cd23"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "macholib"
|
||||
version = "1.16.2"
|
||||
@@ -90,16 +75,6 @@ files = [
|
||||
{file = "macholib-1.16.2.tar.gz", hash = "sha256:557bbfa1bb255c20e9abafe7ed6cd8046b48d9525db2f9b77d3122a63a2a8bf8"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mccabe"
|
||||
version = "0.7.0"
|
||||
requires_python = ">=3.6"
|
||||
summary = "McCabe checker, plugin for flake8"
|
||||
files = [
|
||||
{file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"},
|
||||
{file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mypy-extensions"
|
||||
version = "1.0.0"
|
||||
@@ -162,26 +137,6 @@ files = [
|
||||
{file = "psgdemos-1.12.1.tar.gz", hash = "sha256:4108af795477531a9b1c8675b9aa9b6628c109e660f6954baf8ba2dc3b5806e9"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pycodestyle"
|
||||
version = "2.11.0"
|
||||
requires_python = ">=3.8"
|
||||
summary = "Python style guide checker"
|
||||
files = [
|
||||
{file = "pycodestyle-2.11.0-py2.py3-none-any.whl", hash = "sha256:5d1013ba8dc7895b548be5afb05740ca82454fd899971563d2ef625d090326f8"},
|
||||
{file = "pycodestyle-2.11.0.tar.gz", hash = "sha256:259bcc17857d8a8b3b4a2327324b79e5f020a13c16074670f9c8c8f872ea76d0"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyflakes"
|
||||
version = "3.1.0"
|
||||
requires_python = ">=3.8"
|
||||
summary = "passive checker of Python programs"
|
||||
files = [
|
||||
{file = "pyflakes-3.1.0-py2.py3-none-any.whl", hash = "sha256:4132f6d49cb4dae6819e5379898f2b8cce3c5f23994194c24b77d5da2e36f774"},
|
||||
{file = "pyflakes-3.1.0.tar.gz", hash = "sha256:a0aae034c444db0071aa077972ba4768d40c830d9539fd45bf4cd3f8f6992efc"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyinstaller"
|
||||
version = "5.13.0"
|
||||
@@ -249,6 +204,31 @@ files = [
|
||||
{file = "pywin32_ctypes-0.2.2-py3-none-any.whl", hash = "sha256:bf490a1a709baf35d688fe0ecf980ed4de11d2b3e37b51e5442587a75d9957e7"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.0.291"
|
||||
requires_python = ">=3.7"
|
||||
summary = "An extremely fast Python linter, written in Rust."
|
||||
files = [
|
||||
{file = "ruff-0.0.291-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:b97d0d7c136a85badbc7fd8397fdbb336e9409b01c07027622f28dcd7db366f2"},
|
||||
{file = "ruff-0.0.291-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:6ab44ea607967171e18aa5c80335237be12f3a1523375fa0cede83c5cf77feb4"},
|
||||
{file = "ruff-0.0.291-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a04b384f2d36f00d5fb55313d52a7d66236531195ef08157a09c4728090f2ef0"},
|
||||
{file = "ruff-0.0.291-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b727c219b43f903875b7503a76c86237a00d1a39579bb3e21ce027eec9534051"},
|
||||
{file = "ruff-0.0.291-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:87671e33175ae949702774071b35ed4937da06f11851af75cd087e1b5a488ac4"},
|
||||
{file = "ruff-0.0.291-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:b75f5801547f79b7541d72a211949754c21dc0705c70eddf7f21c88a64de8b97"},
|
||||
{file = "ruff-0.0.291-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b09b94efdcd162fe32b472b2dd5bf1c969fcc15b8ff52f478b048f41d4590e09"},
|
||||
{file = "ruff-0.0.291-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d5b56bc3a2f83a7a1d7f4447c54d8d3db52021f726fdd55d549ca87bca5d747"},
|
||||
{file = "ruff-0.0.291-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13f0d88e5f367b2dc8c7d90a8afdcfff9dd7d174e324fd3ed8e0b5cb5dc9b7f6"},
|
||||
{file = "ruff-0.0.291-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:b3eeee1b1a45a247758ecdc3ab26c307336d157aafc61edb98b825cadb153df3"},
|
||||
{file = "ruff-0.0.291-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:6c06006350c3bb689765d71f810128c9cdf4a1121fd01afc655c87bab4fb4f83"},
|
||||
{file = "ruff-0.0.291-py3-none-musllinux_1_2_i686.whl", hash = "sha256:fd17220611047de247b635596e3174f3d7f2becf63bd56301fc758778df9b629"},
|
||||
{file = "ruff-0.0.291-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:5383ba67ad360caf6060d09012f1fb2ab8bd605ab766d10ca4427a28ab106e0b"},
|
||||
{file = "ruff-0.0.291-py3-none-win32.whl", hash = "sha256:1d5f0616ae4cdc7a938b493b6a1a71c8a47d0300c0d65f6e41c281c2f7490ad3"},
|
||||
{file = "ruff-0.0.291-py3-none-win_amd64.whl", hash = "sha256:8a69bfbde72db8ca1c43ee3570f59daad155196c3fbe357047cd9b77de65f15b"},
|
||||
{file = "ruff-0.0.291-py3-none-win_arm64.whl", hash = "sha256:d867384a4615b7f30b223a849b52104214442b5ba79b473d7edd18da3cde22d6"},
|
||||
{file = "ruff-0.0.291.tar.gz", hash = "sha256:c61109661dde9db73469d14a82b42a88c7164f731e6a3b0042e71394c1c7ceed"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "setuptools"
|
||||
version = "68.1.2"
|
||||
@@ -271,13 +251,13 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "voicemeeter-api"
|
||||
version = "2.4.9"
|
||||
version = "2.4.11"
|
||||
requires_python = ">=3.10,<4.0"
|
||||
summary = "A Python wrapper for the Voiceemeter API"
|
||||
dependencies = [
|
||||
"tomli<3.0.0,>=2.0.1; python_version < \"3.11\"",
|
||||
]
|
||||
files = [
|
||||
{file = "voicemeeter_api-2.4.9-py3-none-any.whl", hash = "sha256:a09fd07fe3799cd5c880d491048da81d94e49aa97ec753aa1f9289acd27be965"},
|
||||
{file = "voicemeeter_api-2.4.9.tar.gz", hash = "sha256:47ad614a8b9ccb0b4e47acf65666ce0f0537a0890fffda9949e995bea70e679c"},
|
||||
{file = "voicemeeter_api-2.4.11-py3-none-any.whl", hash = "sha256:7a1b290d90c851204438c18e2d343e568c242fcd1e664c5b88d4019a553d44e1"},
|
||||
{file = "voicemeeter_api-2.4.11.tar.gz", hash = "sha256:875591ad326a7a13ef141536cca83953edcda81da256191bab3844bac46a0e70"},
|
||||
]
|
||||
|
||||
100
pyproject.toml
100
pyproject.toml
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "nvda_voicemeeter"
|
||||
version = "0.3.1"
|
||||
version = "0.5.2"
|
||||
description = "A Voicemeeter app compatible with NVDA"
|
||||
authors = [
|
||||
{ name = "onyx-and-iris", email = "code@onyxandiris.online" },
|
||||
@@ -8,7 +8,7 @@ authors = [
|
||||
dependencies = [
|
||||
"pysimplegui>=4.60.5",
|
||||
"pyparsing>=3.1.1",
|
||||
"voicemeeter-api>=2.4.9",
|
||||
"voicemeeter-api>=2.4.11",
|
||||
]
|
||||
requires-python = ">=3.10,<3.12"
|
||||
readme = "README.md"
|
||||
@@ -22,7 +22,7 @@ build = [
|
||||
]
|
||||
lint = [
|
||||
"black>=23.7.0",
|
||||
"flake8>=6.1.0",
|
||||
"ruff>=0.0.291",
|
||||
]
|
||||
test = [
|
||||
"psgdemos>=1.12.1",
|
||||
@@ -30,3 +30,97 @@ test = [
|
||||
|
||||
[tool.pdm.scripts.build]
|
||||
shell = "build.ps1"
|
||||
|
||||
[tool.black]
|
||||
line-length = 119
|
||||
|
||||
[tool.ruff]
|
||||
select = [
|
||||
"E",
|
||||
"F",
|
||||
]
|
||||
ignore = [
|
||||
"E501",
|
||||
]
|
||||
fixable = [
|
||||
"A",
|
||||
"B",
|
||||
"C",
|
||||
"D",
|
||||
"E",
|
||||
"F",
|
||||
"G",
|
||||
"I",
|
||||
"N",
|
||||
"Q",
|
||||
"S",
|
||||
"T",
|
||||
"W",
|
||||
"ANN",
|
||||
"ARG",
|
||||
"BLE",
|
||||
"COM",
|
||||
"DJ",
|
||||
"DTZ",
|
||||
"EM",
|
||||
"ERA",
|
||||
"EXE",
|
||||
"FBT",
|
||||
"ICN",
|
||||
"INP",
|
||||
"ISC",
|
||||
"NPY",
|
||||
"PD",
|
||||
"PGH",
|
||||
"PIE",
|
||||
"PL",
|
||||
"PT",
|
||||
"PTH",
|
||||
"PYI",
|
||||
"RET",
|
||||
"RSE",
|
||||
"RUF",
|
||||
"SIM",
|
||||
"SLF",
|
||||
"TCH",
|
||||
"TID",
|
||||
"TRY",
|
||||
"UP",
|
||||
"YTT",
|
||||
]
|
||||
unfixable = []
|
||||
exclude = [
|
||||
".bzr",
|
||||
".direnv",
|
||||
".eggs",
|
||||
".git",
|
||||
".git-rewrite",
|
||||
".hg",
|
||||
".mypy_cache",
|
||||
".nox",
|
||||
".pants.d",
|
||||
".pytype",
|
||||
".ruff_cache",
|
||||
".svn",
|
||||
".tox",
|
||||
".venv",
|
||||
"__pypackages__",
|
||||
"_build",
|
||||
"buck-out",
|
||||
"build",
|
||||
"dist",
|
||||
"node_modules",
|
||||
"venv",
|
||||
]
|
||||
line-length = 119
|
||||
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
|
||||
target-version = "py310"
|
||||
|
||||
[tool.ruff.mccabe]
|
||||
max-complexity = 10
|
||||
|
||||
[tool.ruff.per-file-ignores]
|
||||
"__init__.py" = [
|
||||
"E402",
|
||||
"F401",
|
||||
]
|
||||
|
||||
@@ -161,7 +161,9 @@ class Builder:
|
||||
[
|
||||
psg.Spin(
|
||||
nums,
|
||||
initial_value=self.window.cache["asio"][f"ASIO CHECKBOX||{util.get_asio_checkbox_index(0, i)}"],
|
||||
initial_value=self.window.cache["asio"][
|
||||
f"ASIO CHECKBOX||{util.get_asio_checkbox_index(0, i)}"
|
||||
],
|
||||
size=2,
|
||||
enable_events=True,
|
||||
key=f"ASIO CHECKBOX||IN{i} 0",
|
||||
@@ -172,7 +174,9 @@ class Builder:
|
||||
[
|
||||
psg.Spin(
|
||||
nums,
|
||||
initial_value=self.window.cache["asio"][f"ASIO CHECKBOX||{util.get_asio_checkbox_index(1, i)}"],
|
||||
initial_value=self.window.cache["asio"][
|
||||
f"ASIO CHECKBOX||{util.get_asio_checkbox_index(1, i)}"
|
||||
],
|
||||
size=2,
|
||||
enable_events=True,
|
||||
key=f"ASIO CHECKBOX||IN{i} 1",
|
||||
@@ -193,7 +197,7 @@ class Builder:
|
||||
"""tab0 row3 represents patch composite"""
|
||||
|
||||
def add_physical_device_opts(layout):
|
||||
outputs = util.get_patch_composite_list(self.vm.kind)
|
||||
outputs = util.get_patch_composite_list(self.kind)
|
||||
layout.append(
|
||||
[
|
||||
psg.ButtonMenu(
|
||||
@@ -202,7 +206,7 @@ class Builder:
|
||||
menu_def=["", outputs],
|
||||
key=f"PATCH COMPOSITE||PC{i + 1}",
|
||||
)
|
||||
for i in range(self.kind.phys_out)
|
||||
for i in range(self.kind.composite)
|
||||
]
|
||||
)
|
||||
|
||||
@@ -220,7 +224,9 @@ class Builder:
|
||||
[
|
||||
psg.Checkbox(
|
||||
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,
|
||||
key=f"INSERT CHECKBOX||IN{i} {j}",
|
||||
)
|
||||
@@ -233,7 +239,9 @@ class Builder:
|
||||
[
|
||||
psg.Checkbox(
|
||||
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,
|
||||
key=f"INSERT CHECKBOX||IN{i} {j}",
|
||||
)
|
||||
@@ -316,6 +324,7 @@ class Builder:
|
||||
disable_number_display=True,
|
||||
expand_x=True,
|
||||
enable_events=True,
|
||||
disabled=True,
|
||||
orientation="horizontal",
|
||||
key=f"STRIP {i}||SLIDER GAIN",
|
||||
),
|
||||
@@ -388,7 +397,11 @@ class Builder:
|
||||
|
||||
outputs = []
|
||||
[step(outputs) for step in (add_strip_outputs,)]
|
||||
return psg.Frame(self.window.cache["labels"][f"STRIP {i}||LABEL"], outputs, key=f"STRIP {i}||LABEL")
|
||||
return psg.Frame(
|
||||
self.window.cache["labels"][f"STRIP {i}||LABEL"],
|
||||
outputs,
|
||||
key=f"STRIP {i}||LABEL",
|
||||
)
|
||||
|
||||
def make_tab2_button_rows(self) -> psg.Frame:
|
||||
layout = [
|
||||
@@ -408,6 +421,7 @@ class Builder:
|
||||
disable_number_display=True,
|
||||
expand_x=True,
|
||||
enable_events=True,
|
||||
disabled=True,
|
||||
orientation="horizontal",
|
||||
key=f"STRIP {i}||SLIDER GAIN",
|
||||
),
|
||||
@@ -448,7 +462,11 @@ class Builder:
|
||||
if self.kind.name in ("banana", "potato"):
|
||||
steps += (add_limit_slider,)
|
||||
[step(layout) for step in steps]
|
||||
return psg.Frame(self.window.cache["labels"][f"STRIP {i}||LABEL"], layout, key=f"STRIP {i}||LABEL||SLIDER")
|
||||
return psg.Frame(
|
||||
self.window.cache["labels"][f"STRIP {i}||LABEL"],
|
||||
layout,
|
||||
key=f"STRIP {i}||LABEL||SLIDER",
|
||||
)
|
||||
|
||||
def make_tab2_slider_rows(self) -> psg.Frame:
|
||||
layout = [
|
||||
@@ -460,24 +478,36 @@ class Builder:
|
||||
"""tab3 row represents bus composite toggle"""
|
||||
|
||||
def add_strip_outputs(layout):
|
||||
params = ["MONO", "EQ", "MUTE", "MODE"]
|
||||
if self.vm.kind.name == "basic":
|
||||
params = ["MONO", "EQ", "MUTE"]
|
||||
if self.kind.name == "basic":
|
||||
params.remove("EQ")
|
||||
label = {"MODE": "BUSMODE"}
|
||||
busmodes = [util._bus_mode_map[mode] for mode in util.get_bus_modes(self.vm)]
|
||||
layout.append(
|
||||
[
|
||||
psg.Button(
|
||||
label.get(param, param.capitalize()),
|
||||
size=(12 if param == "MODE" else 6, 2),
|
||||
key=f"BUS {i}||{param}",
|
||||
)
|
||||
for param in params
|
||||
*[
|
||||
psg.Button(
|
||||
param.capitalize(),
|
||||
size=(6, 2),
|
||||
key=f"BUS {i}||{param}",
|
||||
)
|
||||
for param in params
|
||||
],
|
||||
psg.ButtonMenu(
|
||||
"BUSMODE",
|
||||
size=(12, 2),
|
||||
menu_def=["", busmodes],
|
||||
key=f"BUS {i}||MODE",
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
outputs = []
|
||||
[step(outputs) for step in (add_strip_outputs,)]
|
||||
return psg.Frame(self.window.cache["labels"][f"BUS {i}||LABEL"], outputs, key=f"BUS {i}||LABEL")
|
||||
return psg.Frame(
|
||||
self.window.cache["labels"][f"BUS {i}||LABEL"],
|
||||
outputs,
|
||||
key=f"BUS {i}||LABEL",
|
||||
)
|
||||
|
||||
def make_tab3_button_rows(self) -> psg.Frame:
|
||||
layout = [[self.make_tab3_button_row(i)] for i in range(self.kind.num_bus)]
|
||||
@@ -487,6 +517,7 @@ class Builder:
|
||||
def add_gain_slider(layout):
|
||||
layout.append(
|
||||
[
|
||||
psg.Text("Gain"),
|
||||
psg.Slider(
|
||||
range=(-60, 12),
|
||||
default_value=self.vm.bus[i].gain,
|
||||
@@ -494,9 +525,10 @@ class Builder:
|
||||
disable_number_display=True,
|
||||
expand_x=True,
|
||||
enable_events=True,
|
||||
disabled=True,
|
||||
orientation="horizontal",
|
||||
key=f"BUS {i}||SLIDER GAIN",
|
||||
)
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ def get_nvdapath():
|
||||
|
||||
try:
|
||||
NVDA_PATH = Path(get_nvdapath()) / "nvda.exe"
|
||||
except FileNotFoundError as e:
|
||||
except FileNotFoundError:
|
||||
NVDA_PATH = ""
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
from typing import Union
|
||||
|
||||
import PySimpleGUI as psg
|
||||
|
||||
from . import util
|
||||
|
||||
|
||||
class LabelSlider(psg.Frame):
|
||||
"""Compound Label Slider element"""
|
||||
"""Compound Label Slider Strip element"""
|
||||
|
||||
def __init__(self, parent, i, param, range_=(0, 10), *args, **kwargs):
|
||||
self.parent = parent
|
||||
@@ -33,3 +37,169 @@ class LabelSlider(psg.Frame):
|
||||
if param in ("COMP", "GATE", "DENOISER"):
|
||||
return target.knob
|
||||
return target
|
||||
|
||||
|
||||
class CompSlider(psg.Slider):
|
||||
"""Compressor Slider element"""
|
||||
|
||||
def __init__(self, vm, index, param):
|
||||
self.vm = vm
|
||||
self.index = index
|
||||
super().__init__(
|
||||
disable_number_display=True,
|
||||
expand_x=True,
|
||||
enable_events=True,
|
||||
orientation="horizontal",
|
||||
key=f"COMPRESSOR||SLIDER {param}",
|
||||
**self.default_params(param),
|
||||
)
|
||||
|
||||
def default_params(self, param):
|
||||
match param:
|
||||
case "INPUT GAIN":
|
||||
return {
|
||||
"range": (-24, 24),
|
||||
"default_value": self.vm.strip[self.index].comp.gainin,
|
||||
"resolution": 0.1,
|
||||
"disabled": True,
|
||||
}
|
||||
case "RATIO":
|
||||
return {
|
||||
"range": (1, 8),
|
||||
"default_value": self.vm.strip[self.index].comp.ratio,
|
||||
"resolution": 0.1,
|
||||
}
|
||||
case "THRESHOLD":
|
||||
return {
|
||||
"range": (-40, -3),
|
||||
"default_value": self.vm.strip[self.index].comp.threshold,
|
||||
"resolution": 0.1,
|
||||
}
|
||||
case "ATTACK":
|
||||
return {
|
||||
"range": (0, 200),
|
||||
"default_value": self.vm.strip[self.index].comp.attack,
|
||||
"resolution": 0.1,
|
||||
}
|
||||
case "RELEASE":
|
||||
return {
|
||||
"range": (0, 5000),
|
||||
"default_value": self.vm.strip[self.index].comp.release,
|
||||
"resolution": 0.1,
|
||||
}
|
||||
case "KNEE":
|
||||
return {
|
||||
"range": (0, 1),
|
||||
"default_value": self.vm.strip[self.index].comp.knee,
|
||||
"resolution": 0.01,
|
||||
}
|
||||
case "OUTPUT GAIN":
|
||||
return {
|
||||
"range": (-24, 24),
|
||||
"default_value": self.vm.strip[self.index].comp.gainout,
|
||||
"resolution": 0.1,
|
||||
"disabled": True,
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def check_bounds(param, val):
|
||||
match param:
|
||||
case "RATIO":
|
||||
val = util.check_bounds(val, (1, 8))
|
||||
case "THRESHOLD":
|
||||
val = util.check_bounds(val, (-40, -3))
|
||||
case "ATTACK":
|
||||
val = util.check_bounds(val, (0, 200))
|
||||
case "RELEASE":
|
||||
val = util.check_bounds(val, (0, 5000))
|
||||
case "KNEE":
|
||||
val = util.check_bounds(val, (0, 1))
|
||||
return val
|
||||
|
||||
|
||||
class GateSlider(psg.Slider):
|
||||
def __init__(self, vm, index, param):
|
||||
self.vm = vm
|
||||
self.index = index
|
||||
super().__init__(
|
||||
disable_number_display=True,
|
||||
expand_x=True,
|
||||
enable_events=True,
|
||||
orientation="horizontal",
|
||||
key=f"GATE||SLIDER {param}",
|
||||
**self.default_params(param),
|
||||
)
|
||||
|
||||
def default_params(self, param):
|
||||
match param:
|
||||
case "THRESHOLD":
|
||||
return {
|
||||
"range": (-60, -10),
|
||||
"default_value": self.vm.strip[self.index].gate.threshold,
|
||||
"resolution": 0.1,
|
||||
}
|
||||
case "DAMPING":
|
||||
return {
|
||||
"range": (-60, -10),
|
||||
"default_value": self.vm.strip[self.index].gate.damping,
|
||||
"resolution": 0.1,
|
||||
}
|
||||
case "BPSIDECHAIN":
|
||||
return {
|
||||
"range": (100, 4000),
|
||||
"default_value": self.vm.strip[self.index].gate.bpsidechain,
|
||||
"resolution": 1,
|
||||
}
|
||||
case "ATTACK":
|
||||
return {
|
||||
"range": (0, 1000),
|
||||
"default_value": self.vm.strip[self.index].gate.attack,
|
||||
"resolution": 0.1,
|
||||
}
|
||||
case "HOLD":
|
||||
return {
|
||||
"range": (0, 5000),
|
||||
"default_value": self.vm.strip[self.index].gate.hold,
|
||||
"resolution": 0.1,
|
||||
}
|
||||
case "RELEASE":
|
||||
return {
|
||||
"range": (0, 5000),
|
||||
"default_value": self.vm.strip[self.index].gate.release,
|
||||
"resolution": 0.1,
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def check_bounds(param, val):
|
||||
match param:
|
||||
case "THRESHOLD":
|
||||
val = util.check_bounds(val, (-60, -10))
|
||||
case "DAMPING MAX":
|
||||
val = util.check_bounds(val, (-60, -10))
|
||||
case "BPSIDECHAIN":
|
||||
val = util.check_bounds(val, (100, 4000))
|
||||
case "ATTACK":
|
||||
val = util.check_bounds(val, (0, 1000))
|
||||
case "HOLD":
|
||||
val = util.check_bounds(val, (0, 5000))
|
||||
case "RELEASE":
|
||||
val = util.check_bounds(val, (0, 5000))
|
||||
return val
|
||||
|
||||
|
||||
class LabelSliderAdvanced(psg.Frame):
|
||||
"""Compound Label Slider element for Advanced Comp|Gate"""
|
||||
|
||||
def __init__(self, parent, index, param, slider_cls: Union[CompSlider, GateSlider], *args, **kwargs):
|
||||
label_map = {
|
||||
"DAMPING": "Damping Max",
|
||||
"BPSIDECHAIN": "BP Sidechain",
|
||||
}
|
||||
|
||||
layout = [
|
||||
[
|
||||
psg.Text(label_map.get(param, param.title()), size=10),
|
||||
slider_cls(parent.vm, index, param),
|
||||
]
|
||||
]
|
||||
super().__init__(None, layout=layout, border_width=0, pad=0, *args, **kwargs)
|
||||
|
||||
@@ -5,7 +5,7 @@ def _make_hardware_ins_cache(vm) -> dict:
|
||||
def _make_hardware_outs_cache(vm) -> dict:
|
||||
hw_outs = {**{f"HARDWARE OUT||A{i + 1}": vm.bus[i].device.name for i in range(vm.kind.phys_out)}}
|
||||
if vm.kind.name == "basic":
|
||||
hw_outs |= {f"HARDWARE OUT||A2": vm.bus[1].device.name}
|
||||
hw_outs |= {"HARDWARE OUT||A2": vm.bus[1].device.name}
|
||||
return hw_outs
|
||||
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ from pathlib import Path
|
||||
import PySimpleGUI as psg
|
||||
|
||||
from . import util
|
||||
from .compound import CompSlider, GateSlider, LabelSliderAdvanced
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -40,7 +41,7 @@ class Popup:
|
||||
filepath = values["Browse"]
|
||||
break
|
||||
self.window.nvda.speak(button)
|
||||
case [[button], ["KEY", "ENTER"]]:
|
||||
case [_, ["KEY", "ENTER"]]:
|
||||
popup.find_element_with_focus().click()
|
||||
self.logger.debug(f"parsed::{parsed_cmd}")
|
||||
popup.close()
|
||||
@@ -83,7 +84,7 @@ class Popup:
|
||||
match parsed_cmd := self.window.parser.match.parseString(event):
|
||||
case [[button], ["FOCUS", "IN"]]:
|
||||
self.window.nvda.speak(button)
|
||||
case [[button], ["KEY", "ENTER"]]:
|
||||
case [_, ["KEY", "ENTER"]]:
|
||||
popup.find_element_with_focus().click()
|
||||
case ["Ok"]:
|
||||
data = values
|
||||
@@ -151,7 +152,564 @@ class Popup:
|
||||
util.open_context_menu_for_buttonmenu(popup, f"BUFFER {driver}")
|
||||
case [[button], ["FOCUS", "IN"]]:
|
||||
self.window.nvda.speak(button)
|
||||
case [[button], ["KEY", "ENTER"]]:
|
||||
case [_, ["KEY", "ENTER"]]:
|
||||
popup.find_element_with_focus().click()
|
||||
self.logger.debug(f"parsed::{parsed_cmd}")
|
||||
popup.close()
|
||||
|
||||
def on_pdirty(self):
|
||||
if self.popup.Title == "Advanced Compressor":
|
||||
for param in ("RATIO", "THRESHOLD", "ATTACK", "RELEASE", "KNEE"):
|
||||
self.popup[f"COMPRESSOR||SLIDER {param}"].update(
|
||||
value=getattr(self.window.vm.strip[self.index].comp, param.lower())
|
||||
)
|
||||
self.popup["COMPRESSOR||SLIDER INPUT GAIN"].update(value=self.window.vm.strip[self.index].comp.gainin)
|
||||
self.popup["COMPRESSOR||SLIDER OUTPUT GAIN"].update(value=self.window.vm.strip[self.index].comp.gainout)
|
||||
elif self.popup.Title == "Advanced Gate":
|
||||
for param in ("THRESHOLD", "DAMPING", "BPSIDECHAIN", "ATTACK", "HOLD", "RELEASE"):
|
||||
self.popup[f"GATE||SLIDER {param}"].update(
|
||||
value=getattr(self.window.vm.strip[self.index].gate, param.lower())
|
||||
)
|
||||
|
||||
def compressor(self, index, title=None):
|
||||
self.index = index
|
||||
|
||||
def _make_comp_frame() -> psg.Frame:
|
||||
comp_layout = [
|
||||
[LabelSliderAdvanced(self.window, index, param, CompSlider)]
|
||||
for param in ("INPUT GAIN", "RATIO", "THRESHOLD", "ATTACK", "RELEASE", "KNEE", "OUTPUT GAIN")
|
||||
]
|
||||
return psg.Frame("ADVANCED COMPRESSOR", comp_layout)
|
||||
|
||||
layout = []
|
||||
steps = (_make_comp_frame,)
|
||||
for step in steps:
|
||||
layout.append([step()])
|
||||
layout.append([psg.Button("MAKEUP", size=(12, 1)), psg.Button("Exit", size=(8, 1))])
|
||||
|
||||
self.popup = psg.Window(title, layout, return_keyboard_events=False, finalize=True)
|
||||
buttonmenu_opts = {"takefocus": 1, "highlightthickness": 1}
|
||||
for param in ("INPUT GAIN", "RATIO", "THRESHOLD", "ATTACK", "RELEASE", "KNEE", "OUTPUT GAIN"):
|
||||
self.popup[f"COMPRESSOR||SLIDER {param}"].Widget.config(**buttonmenu_opts)
|
||||
self.popup[f"COMPRESSOR||SLIDER {param}"].bind("<FocusIn>", "||FOCUS IN")
|
||||
self.popup[f"COMPRESSOR||SLIDER {param}"].bind("<FocusOut>", "||FOCUS OUT")
|
||||
for event in ("KeyPress", "KeyRelease"):
|
||||
event_id = event.removeprefix("Key").upper()
|
||||
for direction in ("Left", "Right", "Up", "Down"):
|
||||
self.popup[f"COMPRESSOR||SLIDER {param}"].bind(
|
||||
f"<{event}-{direction}>", f"||KEY {direction.upper()} {event_id}"
|
||||
)
|
||||
self.popup[f"COMPRESSOR||SLIDER {param}"].bind(
|
||||
f"<Shift-{event}-{direction}>", f"||KEY SHIFT {direction.upper()} {event_id}"
|
||||
)
|
||||
self.popup[f"COMPRESSOR||SLIDER {param}"].bind(
|
||||
f"<Control-{event}-{direction}>", f"||KEY CTRL {direction.upper()} {event_id}"
|
||||
)
|
||||
if param == "RELEASE":
|
||||
self.popup[f"COMPRESSOR||SLIDER {param}"].bind(
|
||||
f"<Alt-{event}-{direction}>", f"||KEY ALT {direction.upper()} {event_id}"
|
||||
)
|
||||
self.popup[f"COMPRESSOR||SLIDER {param}"].bind(
|
||||
f"<Control-Alt-{event}-{direction}>", f"||KEY CTRL ALT {direction.upper()} {event_id}"
|
||||
)
|
||||
self.popup[f"COMPRESSOR||SLIDER {param}"].bind("<Control-Shift-KeyPress-R>", "||KEY CTRL SHIFT R")
|
||||
self.popup["MAKEUP"].bind("<FocusIn>", "||FOCUS IN")
|
||||
self.popup["MAKEUP"].bind("<Return>", "||KEY ENTER")
|
||||
self.popup["Exit"].bind("<FocusIn>", "||FOCUS IN")
|
||||
self.popup["Exit"].bind("<Return>", "||KEY ENTER")
|
||||
self.window.vm.observer.add(self.on_pdirty)
|
||||
while True:
|
||||
event, values = self.popup.read()
|
||||
self.logger.debug(f"event::{event}")
|
||||
self.logger.debug(f"values::{values}")
|
||||
if event in (psg.WIN_CLOSED, "Exit"):
|
||||
break
|
||||
match parsed_cmd := self.window.parser.match.parseString(event):
|
||||
case [["COMPRESSOR"], ["SLIDER", param]]:
|
||||
setattr(self.window.vm.strip[index].comp, param.lower(), values[event])
|
||||
case [["COMPRESSOR"], ["SLIDER", param], ["FOCUS", "IN"]]:
|
||||
self.window.nvda.speak(f"{param} {values[f'COMPRESSOR||SLIDER {param}']}")
|
||||
case [
|
||||
["COMPRESSOR"],
|
||||
["SLIDER", param],
|
||||
["KEY", "LEFT" | "RIGHT" | "UP" | "DOWN" as input_direction, "PRESS" | "RELEASE" as e],
|
||||
]:
|
||||
if e == "PRESS":
|
||||
self.window.vm.event.pdirty = False
|
||||
val = getattr(self.window.vm.strip[index].comp, param.lower())
|
||||
|
||||
match input_direction:
|
||||
case "RIGHT" | "UP":
|
||||
if param == "KNEE":
|
||||
val += 0.1
|
||||
else:
|
||||
val += 1
|
||||
case "LEFT" | "DOWN":
|
||||
if param == "KNEE":
|
||||
val -= 0.1
|
||||
else:
|
||||
val -= 1
|
||||
|
||||
val = CompSlider.check_bounds(param, val)
|
||||
|
||||
setattr(self.window.vm.strip[index].comp, param.lower(), val)
|
||||
self.popup[f"COMPRESSOR||SLIDER {param}"].update(value=val)
|
||||
if param == "KNEE":
|
||||
self.window.nvda.speak(str(round(val, 2)))
|
||||
else:
|
||||
self.window.nvda.speak(str(round(val, 1)))
|
||||
else:
|
||||
self.window.vm.event.pdirty = True
|
||||
case [
|
||||
["COMPRESSOR"],
|
||||
["SLIDER", param],
|
||||
["KEY", "CTRL", "LEFT" | "RIGHT" | "UP" | "DOWN" as input_direction, "PRESS" | "RELEASE" as e],
|
||||
]:
|
||||
if e == "PRESS":
|
||||
self.window.vm.event.pdirty = False
|
||||
val = getattr(self.window.vm.strip[index].comp, param.lower())
|
||||
|
||||
match input_direction:
|
||||
case "RIGHT" | "UP":
|
||||
if param == "KNEE":
|
||||
val += 0.3
|
||||
elif param == "RELEASE":
|
||||
val += 5
|
||||
else:
|
||||
val += 3
|
||||
case "LEFT" | "DOWN":
|
||||
if param == "KNEE":
|
||||
val -= 0.3
|
||||
elif param == "RELEASE":
|
||||
val -= 5
|
||||
else:
|
||||
val -= 3
|
||||
|
||||
val = CompSlider.check_bounds(param, val)
|
||||
|
||||
setattr(self.window.vm.strip[index].comp, param.lower(), val)
|
||||
self.popup[f"COMPRESSOR||SLIDER {param}"].update(value=val)
|
||||
if param == "KNEE":
|
||||
self.window.nvda.speak(str(round(val, 2)))
|
||||
else:
|
||||
self.window.nvda.speak(str(round(val, 1)))
|
||||
else:
|
||||
self.window.vm.event.pdirty = True
|
||||
case [
|
||||
["COMPRESSOR"],
|
||||
["SLIDER", param],
|
||||
["KEY", "SHIFT", "LEFT" | "RIGHT" | "UP" | "DOWN" as input_direction, "PRESS" | "RELEASE" as e],
|
||||
]:
|
||||
if e == "PRESS":
|
||||
self.window.vm.event.pdirty = False
|
||||
val = getattr(self.window.vm.strip[index].comp, param.lower())
|
||||
|
||||
match input_direction:
|
||||
case "RIGHT" | "UP":
|
||||
if param == "KNEE":
|
||||
val += 0.01
|
||||
else:
|
||||
val += 0.1
|
||||
case "LEFT" | "DOWN":
|
||||
if param == "KNEE":
|
||||
val -= 0.01
|
||||
else:
|
||||
val -= 0.1
|
||||
|
||||
val = CompSlider.check_bounds(param, val)
|
||||
|
||||
setattr(self.window.vm.strip[index].comp, param.lower(), val)
|
||||
self.popup[f"COMPRESSOR||SLIDER {param}"].update(value=val)
|
||||
if param == "KNEE":
|
||||
self.window.nvda.speak(str(round(val, 2)))
|
||||
else:
|
||||
self.window.nvda.speak(str(round(val, 1)))
|
||||
else:
|
||||
self.window.vm.event.pdirty = True
|
||||
case [
|
||||
["COMPRESSOR"],
|
||||
["SLIDER", "RELEASE"],
|
||||
["KEY", "ALT", "LEFT" | "RIGHT" as input_direction, "PRESS" | "RELEASE" as e],
|
||||
]:
|
||||
if e == "PRESS":
|
||||
self.window.vm.event.pdirty = False
|
||||
val = self.window.vm.strip[index].comp.release
|
||||
|
||||
match input_direction:
|
||||
case "RIGHT" | "UP":
|
||||
val += 10
|
||||
case "LEFT" | "DOWN":
|
||||
val -= 10
|
||||
|
||||
val = util.check_bounds(val, (0, 5000))
|
||||
self.window.vm.strip[index].comp.release = val
|
||||
self.popup[f"COMPRESSOR||SLIDER {param}"].update(value=val)
|
||||
self.window.nvda.speak(str(round(val, 1)))
|
||||
else:
|
||||
self.window.vm.event.pdirty = True
|
||||
case [
|
||||
["COMPRESSOR"],
|
||||
["SLIDER", "RELEASE"],
|
||||
["KEY", "CTRL", "ALT", "LEFT" | "RIGHT" as input_direction, "PRESS" | "RELEASE" as e],
|
||||
]:
|
||||
if e == "PRESS":
|
||||
self.window.vm.event.pdirty = False
|
||||
val = self.window.vm.strip[index].comp.release
|
||||
|
||||
match input_direction:
|
||||
case "RIGHT" | "UP":
|
||||
val += 50
|
||||
case "LEFT" | "DOWN":
|
||||
val -= 50
|
||||
|
||||
val = util.check_bounds(val, (0, 5000))
|
||||
self.window.vm.strip[index].comp.release = val
|
||||
self.popup[f"COMPRESSOR||SLIDER {param}"].update(value=val)
|
||||
self.window.nvda.speak(str(round(val, 1)))
|
||||
else:
|
||||
self.window.vm.event.pdirty = True
|
||||
|
||||
case [["COMPRESSOR"], ["SLIDER", "INPUT" | "OUTPUT" as direction, "GAIN"]]:
|
||||
if direction == "INPUT":
|
||||
self.window.vm.strip[index].comp.gainin = values[event]
|
||||
else:
|
||||
self.window.vm.strip[index].comp.gainout = values[event]
|
||||
case [["COMPRESSOR"], ["SLIDER", "INPUT" | "OUTPUT" as direction, "GAIN"], ["FOCUS", "IN"]]:
|
||||
label = f"{direction} GAIN"
|
||||
self.window.nvda.speak(f"{label} {values[f'COMPRESSOR||SLIDER {label}']}")
|
||||
case [
|
||||
["COMPRESSOR"],
|
||||
["SLIDER", "INPUT" | "OUTPUT" as direction, "GAIN"],
|
||||
["KEY", "LEFT" | "RIGHT" | "UP" | "DOWN" as input_direction, "PRESS" | "RELEASE" as e],
|
||||
]:
|
||||
if e == "PRESS":
|
||||
self.window.vm.event.pdirty = False
|
||||
if direction == "INPUT":
|
||||
val = self.window.vm.strip[index].comp.gainin
|
||||
else:
|
||||
val = self.window.vm.strip[index].comp.gainout
|
||||
|
||||
match input_direction:
|
||||
case "RIGHT" | "UP":
|
||||
val += 1
|
||||
case "LEFT" | "DOWN":
|
||||
val -= 1
|
||||
|
||||
val = util.check_bounds(val, (-24, 24))
|
||||
if direction == "INPUT":
|
||||
self.window.vm.strip[index].comp.gainin = val
|
||||
else:
|
||||
self.window.vm.strip[index].comp.gainout = val
|
||||
self.popup[f"COMPRESSOR||SLIDER {direction} GAIN"].update(value=val)
|
||||
self.window.nvda.speak(str(round(val, 1)))
|
||||
else:
|
||||
self.window.vm.event.pdirty = True
|
||||
case [
|
||||
["COMPRESSOR"],
|
||||
["SLIDER", "INPUT" | "OUTPUT" as direction, "GAIN"],
|
||||
["KEY", "CTRL", "LEFT" | "RIGHT" | "UP" | "DOWN" as input_direction, "PRESS" | "RELEASE" as e],
|
||||
]:
|
||||
if e == "PRESS":
|
||||
self.window.vm.event.pdirty = False
|
||||
if direction == "INPUT":
|
||||
val = self.window.vm.strip[index].comp.gainin
|
||||
else:
|
||||
val = self.window.vm.strip[index].comp.gainout
|
||||
|
||||
match input_direction:
|
||||
case "RIGHT" | "UP":
|
||||
val += 3
|
||||
case "LEFT" | "DOWN":
|
||||
val -= 3
|
||||
|
||||
val = util.check_bounds(val, (-24, 24))
|
||||
if direction == "INPUT":
|
||||
self.window.vm.strip[index].comp.gainin = val
|
||||
else:
|
||||
self.window.vm.strip[index].comp.gainout = val
|
||||
self.popup[f"COMPRESSOR||SLIDER {direction} GAIN"].update(value=val)
|
||||
self.window.nvda.speak(str(round(val, 1)))
|
||||
else:
|
||||
self.window.vm.event.pdirty = True
|
||||
case [
|
||||
["COMPRESSOR"],
|
||||
["SLIDER", "INPUT" | "OUTPUT" as direction, "GAIN"],
|
||||
["KEY", "SHIFT", "LEFT" | "RIGHT" | "UP" | "DOWN" as input_direction, "PRESS" | "RELEASE" as e],
|
||||
]:
|
||||
if e == "PRESS":
|
||||
self.window.vm.event.pdirty = False
|
||||
if direction == "INPUT":
|
||||
val = self.window.vm.strip[index].comp.gainin
|
||||
else:
|
||||
val = self.window.vm.strip[index].comp.gainout
|
||||
|
||||
match input_direction:
|
||||
case "RIGHT" | "UP":
|
||||
val += 0.1
|
||||
case "LEFT" | "DOWN":
|
||||
val -= 0.1
|
||||
|
||||
val = util.check_bounds(val, (-24, 24))
|
||||
if direction == "INPUT":
|
||||
self.window.vm.strip[index].comp.gainin = val
|
||||
else:
|
||||
self.window.vm.strip[index].comp.gainout = val
|
||||
self.popup[f"COMPRESSOR||SLIDER {direction} GAIN"].update(value=val)
|
||||
self.window.nvda.speak(str(round(val, 1)))
|
||||
else:
|
||||
self.window.vm.event.pdirty = True
|
||||
|
||||
case [
|
||||
["COMPRESSOR"],
|
||||
["SLIDER", "INPUT" | "OUTPUT" as direction, "GAIN"],
|
||||
["KEY", "CTRL", "SHIFT", "R"],
|
||||
]:
|
||||
if direction == "INPUT":
|
||||
self.window.vm.strip[index].comp.gainin = 0
|
||||
else:
|
||||
self.window.vm.strip[index].comp.gainout = 0
|
||||
self.popup[f"COMPRESSOR||SLIDER {direction} GAIN"].update(value=0)
|
||||
self.window.nvda.speak(str(0))
|
||||
case [["COMPRESSOR"], ["SLIDER", param], ["KEY", "CTRL", "SHIFT", "R"]]:
|
||||
match param:
|
||||
case "RATIO":
|
||||
val = 1
|
||||
case "THRESHOLD":
|
||||
val = -20
|
||||
case "ATTACK":
|
||||
val = 10
|
||||
case "RELEASE":
|
||||
val = 50
|
||||
case "KNEE":
|
||||
val = 0.5
|
||||
setattr(self.window.vm.strip[index].comp, param.lower(), val)
|
||||
self.popup[f"COMPRESSOR||SLIDER {param}"].update(value=val)
|
||||
self.window.nvda.speak(str(round(val, 1)))
|
||||
|
||||
case ["MAKEUP"]:
|
||||
val = not self.window.vm.strip[index].comp.makeup
|
||||
self.window.vm.strip[index].comp.makeup = val
|
||||
self.window.nvda.speak("on" if val else "off")
|
||||
case [[button], ["FOCUS", "IN"]]:
|
||||
if button == "MAKEUP":
|
||||
self.window.nvda.speak(
|
||||
f"{button} {'on' if self.window.vm.strip[index].comp.makeup else 'off'}"
|
||||
)
|
||||
else:
|
||||
self.window.nvda.speak(button)
|
||||
case [_, ["KEY", "ENTER"]]:
|
||||
self.popup.find_element_with_focus().click()
|
||||
self.logger.debug(f"parsed::{parsed_cmd}")
|
||||
self.window.vm.observer.remove(self.on_pdirty)
|
||||
self.popup.close()
|
||||
|
||||
def gate(self, index, title=None):
|
||||
self.index = index
|
||||
|
||||
def _make_gate_frame() -> psg.Frame:
|
||||
gate_layout = [
|
||||
[LabelSliderAdvanced(self.window, index, param, GateSlider)]
|
||||
for param in ("THRESHOLD", "DAMPING", "BPSIDECHAIN", "ATTACK", "HOLD", "RELEASE")
|
||||
]
|
||||
return psg.Frame("ADVANCED GATE", gate_layout)
|
||||
|
||||
layout = []
|
||||
steps = (_make_gate_frame,)
|
||||
for step in steps:
|
||||
layout.append([step()])
|
||||
layout.append([psg.Button("Exit", size=(8, 1))])
|
||||
|
||||
self.popup = psg.Window(title, layout, return_keyboard_events=False, finalize=True)
|
||||
buttonmenu_opts = {"takefocus": 1, "highlightthickness": 1}
|
||||
for param in ("THRESHOLD", "DAMPING", "BPSIDECHAIN", "ATTACK", "HOLD", "RELEASE"):
|
||||
self.popup[f"GATE||SLIDER {param}"].Widget.config(**buttonmenu_opts)
|
||||
self.popup[f"GATE||SLIDER {param}"].bind("<FocusIn>", "||FOCUS IN")
|
||||
self.popup[f"GATE||SLIDER {param}"].bind("<FocusOut>", "||FOCUS OUT")
|
||||
for event in ("KeyPress", "KeyRelease"):
|
||||
event_id = event.removeprefix("Key").upper()
|
||||
for direction in ("Left", "Right", "Up", "Down"):
|
||||
self.popup[f"GATE||SLIDER {param}"].bind(
|
||||
f"<{event}-{direction}>", f"||KEY {direction.upper()} {event_id}"
|
||||
)
|
||||
self.popup[f"GATE||SLIDER {param}"].bind(
|
||||
f"<Shift-{event}-{direction}>", f"||KEY SHIFT {direction.upper()} {event_id}"
|
||||
)
|
||||
self.popup[f"GATE||SLIDER {param}"].bind(
|
||||
f"<Control-{event}-{direction}>", f"||KEY CTRL {direction.upper()} {event_id}"
|
||||
)
|
||||
if param in ("BPSIDECHAIN", "ATTACK", "HOLD", "RELEASE"):
|
||||
self.popup[f"GATE||SLIDER {param}"].bind(
|
||||
f"<Alt-{event}-{direction}>", f"||KEY ALT {direction.upper()} {event_id}"
|
||||
)
|
||||
self.popup[f"GATE||SLIDER {param}"].bind(
|
||||
f"<Control-Alt-{event}-{direction}>", f"||KEY CTRL ALT {direction.upper()} {event_id}"
|
||||
)
|
||||
self.popup[f"GATE||SLIDER {param}"].bind("<Control-Shift-KeyPress-R>", "||KEY CTRL SHIFT R")
|
||||
self.popup["Exit"].bind("<FocusIn>", "||FOCUS IN")
|
||||
self.popup["Exit"].bind("<Return>", "||KEY ENTER")
|
||||
self.window.vm.observer.add(self.on_pdirty)
|
||||
while True:
|
||||
event, values = self.popup.read()
|
||||
self.logger.debug(f"event::{event}")
|
||||
self.logger.debug(f"values::{values}")
|
||||
if event in (psg.WIN_CLOSED, "Exit"):
|
||||
break
|
||||
match parsed_cmd := self.window.parser.match.parseString(event):
|
||||
case [["GATE"], ["SLIDER", param]]:
|
||||
setattr(self.window.vm.strip[index].gate, param.lower(), values[event])
|
||||
case [["GATE"], ["SLIDER", param], ["FOCUS", "IN"]]:
|
||||
label_map = {
|
||||
"DAMPING": "Damping Max",
|
||||
"BPSIDECHAIN": "BP Sidechain",
|
||||
}
|
||||
self.window.nvda.speak(f"{label_map.get(param, param)} {values[f'GATE||SLIDER {param}']}")
|
||||
|
||||
case [
|
||||
["GATE"],
|
||||
["SLIDER", param],
|
||||
["KEY", "LEFT" | "RIGHT" | "UP" | "DOWN" as input_direction, "PRESS" | "RELEASE" as e],
|
||||
]:
|
||||
if e == "PRESS":
|
||||
self.window.vm.event.pdirty = False
|
||||
val = getattr(self.window.vm.strip[index].gate, param.lower())
|
||||
|
||||
match input_direction:
|
||||
case "RIGHT" | "UP":
|
||||
val += 1
|
||||
case "LEFT" | "DOWN":
|
||||
val -= 1
|
||||
|
||||
val = GateSlider.check_bounds(param, val)
|
||||
|
||||
setattr(self.window.vm.strip[index].gate, param.lower(), val)
|
||||
self.popup[f"GATE||SLIDER {param}"].update(value=val)
|
||||
if param == "BPSIDECHAIN":
|
||||
self.window.nvda.speak(str(int(val)))
|
||||
else:
|
||||
self.window.nvda.speak(str(round(val, 1)))
|
||||
else:
|
||||
self.window.vm.event.pdirty = True
|
||||
case [
|
||||
["GATE"],
|
||||
["SLIDER", param],
|
||||
["KEY", "CTRL", "LEFT" | "RIGHT" | "UP" | "DOWN" as input_direction, "PRESS" | "RELEASE" as e],
|
||||
]:
|
||||
if e == "PRESS":
|
||||
self.window.vm.event.pdirty = False
|
||||
val = getattr(self.window.vm.strip[index].gate, param.lower())
|
||||
|
||||
match input_direction:
|
||||
case "RIGHT" | "UP":
|
||||
val += 3
|
||||
case "LEFT" | "DOWN":
|
||||
val -= 3
|
||||
|
||||
val = GateSlider.check_bounds(param, val)
|
||||
|
||||
setattr(self.window.vm.strip[index].gate, param.lower(), val)
|
||||
self.popup[f"GATE||SLIDER {param}"].update(value=val)
|
||||
if param == "BPSIDECHAIN":
|
||||
self.window.nvda.speak(str(int(val)))
|
||||
else:
|
||||
self.window.nvda.speak(str(round(val, 1)))
|
||||
else:
|
||||
self.window.vm.event.pdirty = True
|
||||
case [
|
||||
["GATE"],
|
||||
["SLIDER", param],
|
||||
["KEY", "SHIFT", "LEFT" | "RIGHT" | "UP" | "DOWN" as input_direction, "PRESS" | "RELEASE" as e],
|
||||
]:
|
||||
if e == "PRESS":
|
||||
self.window.vm.event.pdirty = False
|
||||
val = getattr(self.window.vm.strip[index].gate, param.lower())
|
||||
|
||||
match input_direction:
|
||||
case "RIGHT" | "UP":
|
||||
val += 0.1
|
||||
case "LEFT" | "DOWN":
|
||||
val -= 0.1
|
||||
|
||||
val = GateSlider.check_bounds(param, val)
|
||||
|
||||
setattr(self.window.vm.strip[index].gate, param.lower(), val)
|
||||
self.popup[f"GATE||SLIDER {param}"].update(value=val)
|
||||
if param == "BPSIDECHAIN":
|
||||
self.window.nvda.speak(str(int(val)))
|
||||
else:
|
||||
self.window.nvda.speak(str(round(val, 1)))
|
||||
else:
|
||||
self.window.vm.event.pdirty = True
|
||||
case [
|
||||
["GATE"],
|
||||
["SLIDER", "BPSIDECHAIN" | "ATTACK" | "HOLD" | "RELEASE" as param],
|
||||
["KEY", "ALT", "LEFT" | "RIGHT" as input_direction, "PRESS" | "RELEASE" as e],
|
||||
]:
|
||||
if e == "PRESS":
|
||||
self.window.vm.event.pdirty = False
|
||||
val = getattr(self.window.vm.strip[index].gate, param.lower())
|
||||
|
||||
match input_direction:
|
||||
case "RIGHT" | "UP":
|
||||
val += 10
|
||||
case "LEFT" | "DOWN":
|
||||
val -= 10
|
||||
|
||||
val = GateSlider.check_bounds(param, val)
|
||||
setattr(self.window.vm.strip[index].gate, param.lower(), val)
|
||||
self.popup[f"GATE||SLIDER {param}"].update(value=val)
|
||||
if param == "BPSIDECHAIN":
|
||||
self.window.nvda.speak(str(int(val)))
|
||||
else:
|
||||
self.window.nvda.speak(str(round(val, 1)))
|
||||
else:
|
||||
self.window.vm.event.pdirty = True
|
||||
case [
|
||||
["GATE"],
|
||||
["SLIDER", "BPSIDECHAIN" | "ATTACK" | "HOLD" | "RELEASE" as param],
|
||||
["KEY", "CTRL", "ALT", "LEFT" | "RIGHT" as input_direction, "PRESS" | "RELEASE" as e],
|
||||
]:
|
||||
if e == "PRESS":
|
||||
self.window.vm.event.pdirty = False
|
||||
val = getattr(self.window.vm.strip[index].gate, param.lower())
|
||||
|
||||
match input_direction:
|
||||
case "RIGHT" | "UP":
|
||||
val += 50
|
||||
case "LEFT" | "DOWN":
|
||||
val -= 50
|
||||
|
||||
val = GateSlider.check_bounds(param, val)
|
||||
setattr(self.window.vm.strip[index].gate, param.lower(), val)
|
||||
self.popup[f"GATE||SLIDER {param}"].update(value=val)
|
||||
if param == "BPSIDECHAIN":
|
||||
self.window.nvda.speak(str(int(val)))
|
||||
else:
|
||||
self.window.nvda.speak(str(round(val, 1)))
|
||||
else:
|
||||
self.window.vm.event.pdirty = True
|
||||
case [["GATE"], ["SLIDER", param], ["KEY", "CTRL", "SHIFT", "R"]]:
|
||||
match param:
|
||||
case "THRESHOLD":
|
||||
val = -60
|
||||
case "DAMPING":
|
||||
val = -60
|
||||
case "BPSIDECHAIN":
|
||||
val = 100
|
||||
case "ATTACK":
|
||||
val = 0
|
||||
case "HOLD":
|
||||
val = 500
|
||||
case "RELEASE":
|
||||
val = 1000
|
||||
setattr(self.window.vm.strip[index].gate, param.lower(), val)
|
||||
self.popup[f"GATE||SLIDER {param}"].update(value=val)
|
||||
self.window.nvda.speak(str(round(val, 1)))
|
||||
|
||||
case [[button], ["FOCUS", "IN"]]:
|
||||
self.window.nvda.speak(button)
|
||||
case [_, ["KEY", "ENTER"]]:
|
||||
self.popup.find_element_with_focus().click()
|
||||
|
||||
self.logger.debug(f"parsed::{parsed_cmd}")
|
||||
self.window.vm.observer.remove(self.on_pdirty)
|
||||
self.popup.close()
|
||||
|
||||
@@ -48,8 +48,11 @@ def get_patch_composite_list(kind) -> list:
|
||||
for i in range(kind.phys_out):
|
||||
[temp.append(f"IN#{i + 1} {channel}") for channel in ("Left", "Right")]
|
||||
for i in range(kind.phys_out, kind.phys_out + kind.virt_out):
|
||||
[temp.append(f"IN#{i + 1} {channel}") for channel in ("Left", "Right", "Center", "LFE", "SL", "SR", "BL", "BR")]
|
||||
temp.append(f"BUS Channel")
|
||||
[
|
||||
temp.append(f"IN#{i + 1} {channel}")
|
||||
for channel in ("Left", "Right", "Center", "LFE", "SL", "SR", "BL", "BR")
|
||||
]
|
||||
temp.append("BUS Channel")
|
||||
return temp
|
||||
|
||||
|
||||
@@ -108,6 +111,24 @@ def get_channel_identifier_list(vm) -> list:
|
||||
return identifiers
|
||||
|
||||
|
||||
_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",
|
||||
}
|
||||
|
||||
_bus_mode_map_reversed = dict((reversed(item) for item in _bus_mode_map.items()))
|
||||
|
||||
|
||||
def get_bus_modes(vm) -> list:
|
||||
if vm.kind.name == "basic":
|
||||
return [
|
||||
@@ -157,3 +178,17 @@ def get_full_slider_params(i, kind) -> Iterable:
|
||||
if kind.name == "basic":
|
||||
params.remove("LIMIT")
|
||||
return params
|
||||
|
||||
|
||||
def get_slider_modes() -> Iterable:
|
||||
return (
|
||||
"GAIN MODE",
|
||||
"BASS MODE",
|
||||
"MID MODE",
|
||||
"TREBLE MODE",
|
||||
"AUDIBILITY MODE",
|
||||
"COMP MODE",
|
||||
"GATE MODE",
|
||||
"DENOISER MODE",
|
||||
"LIMIT MODE",
|
||||
)
|
||||
|
||||
@@ -38,16 +38,16 @@ class NVDAVMWindow(psg.Window):
|
||||
self.popup = Popup(self)
|
||||
self.builder = Builder(self)
|
||||
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}
|
||||
for i in range(self.kind.phys_in):
|
||||
self[f"HARDWARE IN||{i + 1}"].Widget.config(**buttonmenu_opts)
|
||||
for i in range(self.kind.phys_out):
|
||||
self[f"HARDWARE OUT||A{i + 1}"].Widget.config(**buttonmenu_opts)
|
||||
if self.kind.name == "basic":
|
||||
self[f"HARDWARE OUT||A2"].Widget.config(**buttonmenu_opts)
|
||||
self["HARDWARE OUT||A2"].Widget.config(**buttonmenu_opts)
|
||||
if self.kind.name != "basic":
|
||||
[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.composite)]
|
||||
slider_opts = {"takefocus": 1, "highlightthickness": 1}
|
||||
for i in range(self.kind.num_strip):
|
||||
for param in util.get_slider_params(i, self.kind):
|
||||
@@ -57,6 +57,11 @@ class NVDAVMWindow(psg.Window):
|
||||
self[f"STRIP {i}||SLIDER LIMIT"].Widget.config(**slider_opts)
|
||||
for i in range(self.kind.num_bus):
|
||||
self[f"BUS {i}||SLIDER GAIN"].Widget.config(**slider_opts)
|
||||
self[f"BUS {i}||MODE"].Widget.config(**buttonmenu_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["tabgroup"].set_focus()
|
||||
@@ -138,6 +143,7 @@ class NVDAVMWindow(psg.Window):
|
||||
self[f"tabgroup||{tabname}"].bind("<Shift-KeyPress-Tab>", "||KEY SHIFT TAB")
|
||||
self.bind("<Control-KeyPress-Tab>", "CTRL-TAB")
|
||||
self.bind("<Control-Shift-KeyPress-Tab>", "CTRL-SHIFT-TAB")
|
||||
self.bind("<F2>", "F2")
|
||||
|
||||
# NAV
|
||||
self.bind("<Control-a>", "CTRL-A")
|
||||
@@ -164,29 +170,30 @@ class NVDAVMWindow(psg.Window):
|
||||
self.bind("<Control-t>", "GATE MODE")
|
||||
self.bind("<Control-d>", "DENOISER MODE")
|
||||
self.bind("<Control-l>", "LIMIT MODE")
|
||||
self.bind("<Escape>", "ESCAPE")
|
||||
|
||||
self.bind("<Alt-Left>", "LEFT")
|
||||
self.bind("<Alt-Right>", "RIGHT")
|
||||
self.bind("<Alt-Shift-KeyPress-Left>", "SHIFT-LEFT")
|
||||
self.bind("<Alt-Shift-KeyPress-Right>", "SHIFT-RIGHT")
|
||||
self.bind("<Alt-Control-KeyPress-Left>", "CTRL-LEFT")
|
||||
self.bind("<Alt-Control-KeyPress-Right>", "CTRL-RIGHT")
|
||||
for event in ("KeyPress", "KeyRelease"):
|
||||
event_id = event.removeprefix("Key").upper()
|
||||
for direction in ("Left", "Right", "Up", "Down"):
|
||||
self.bind(f"<Alt-{event}-{direction}>", f"ALT {direction.upper()}||{event_id}")
|
||||
self.bind(f"<Alt-Shift-{event}-{direction}>", f"ALT SHIFT {direction.upper()}||{event_id}")
|
||||
self.bind(f"<Alt-Control-{event}-{direction}>", f"ALT CTRL {direction.upper()}||{event_id}")
|
||||
|
||||
# Hardware In
|
||||
for i in range(self.vm.kind.phys_in):
|
||||
for i in range(self.kind.phys_in):
|
||||
self[f"HARDWARE IN||{i + 1}"].bind("<FocusIn>", "||FOCUS IN")
|
||||
self[f"HARDWARE IN||{i + 1}"].bind("<space>", "||KEY SPACE", propagate=False)
|
||||
self[f"HARDWARE IN||{i + 1}"].bind("<Return>", "||KEY ENTER", propagate=False)
|
||||
|
||||
# Hardware Out
|
||||
for i in range(self.vm.kind.phys_out):
|
||||
for i in range(self.kind.phys_out):
|
||||
self[f"HARDWARE OUT||A{i + 1}"].bind("<FocusIn>", "||FOCUS IN")
|
||||
self[f"HARDWARE OUT||A{i + 1}"].bind("<space>", "||KEY SPACE", propagate=False)
|
||||
self[f"HARDWARE OUT||A{i + 1}"].bind("<Return>", "||KEY ENTER", propagate=False)
|
||||
if self.vm.kind.name == "basic":
|
||||
self[f"HARDWARE OUT||A2"].bind("<FocusIn>", "||FOCUS IN")
|
||||
self[f"HARDWARE OUT||A2"].bind("<space>", "||KEY SPACE", propagate=False)
|
||||
self[f"HARDWARE OUT||A2"].bind("<Return>", "||KEY ENTER", propagate=False)
|
||||
if self.kind.name == "basic":
|
||||
self["HARDWARE OUT||A2"].bind("<FocusIn>", "||FOCUS IN")
|
||||
self["HARDWARE OUT||A2"].bind("<space>", "||KEY SPACE", propagate=False)
|
||||
self["HARDWARE OUT||A2"].bind("<Return>", "||KEY ENTER", propagate=False)
|
||||
|
||||
# Patch ASIO
|
||||
if self.kind.name != "basic":
|
||||
@@ -196,7 +203,7 @@ class NVDAVMWindow(psg.Window):
|
||||
|
||||
# Patch Composite
|
||||
if self.kind.name != "basic":
|
||||
for i in range(self.vm.kind.phys_out):
|
||||
for i in range(self.kind.composite):
|
||||
self[f"PATCH COMPOSITE||PC{i + 1}"].bind("<FocusIn>", "||FOCUS IN")
|
||||
self[f"PATCH COMPOSITE||PC{i + 1}"].bind("<space>", "||KEY SPACE", propagate=False)
|
||||
self[f"PATCH COMPOSITE||PC{i + 1}"].bind("<Return>", "||KEY ENTER", propagate=False)
|
||||
@@ -207,8 +214,11 @@ class NVDAVMWindow(psg.Window):
|
||||
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} 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:
|
||||
[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
|
||||
self["ADVANCED SETTINGS"].bind("<FocusIn>", "||FOCUS IN")
|
||||
@@ -236,45 +246,48 @@ class NVDAVMWindow(psg.Window):
|
||||
for param in util.get_full_slider_params(i, self.kind):
|
||||
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("<Left>", "||KEY LEFT")
|
||||
self[f"STRIP {i}||SLIDER {param}"].bind("<Right>", "||KEY RIGHT")
|
||||
self[f"STRIP {i}||SLIDER {param}"].bind("<Shift-KeyPress-Left>", "||KEY SHIFT LEFT")
|
||||
self[f"STRIP {i}||SLIDER {param}"].bind("<Shift-KeyPress-Right>", "||KEY SHIFT RIGHT")
|
||||
self[f"STRIP {i}||SLIDER {param}"].bind("<Control-KeyPress-Left>", "||KEY CTRL LEFT")
|
||||
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("<Down>", "||KEY DOWN")
|
||||
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("<Control-KeyPress-Up>", "||KEY CTRL UP")
|
||||
self[f"STRIP {i}||SLIDER {param}"].bind("<Control-KeyPress-Down>", "||KEY CTRL DOWN")
|
||||
for event in ("KeyPress", "KeyRelease"):
|
||||
event_id = event.removeprefix("Key").upper()
|
||||
for direction in ("Left", "Right", "Up", "Down"):
|
||||
self[f"STRIP {i}||SLIDER {param}"].bind(
|
||||
f"<{event}-{direction}>", f"||KEY {direction.upper()} {event_id}"
|
||||
)
|
||||
self[f"STRIP {i}||SLIDER {param}"].bind(
|
||||
f"<Shift-{event}-{direction}>", f"||KEY SHIFT {direction.upper()} {event_id}"
|
||||
)
|
||||
self[f"STRIP {i}||SLIDER {param}"].bind(
|
||||
f"<Control-{event}-{direction}>", f"||KEY CTRL {direction.upper()} {event_id}"
|
||||
)
|
||||
self[f"STRIP {i}||SLIDER {param}"].bind("<Control-Shift-KeyPress-R>", "||KEY CTRL SHIFT R")
|
||||
|
||||
# Bus Params
|
||||
params = ["MONO", "EQ", "MUTE", "MODE"]
|
||||
if self.vm.kind.name == "basic":
|
||||
params = ["MONO", "EQ", "MUTE"]
|
||||
if self.kind.name == "basic":
|
||||
params.remove("EQ")
|
||||
for i in range(self.kind.num_bus):
|
||||
for param in params:
|
||||
self[f"BUS {i}||{param}"].bind("<FocusIn>", "||FOCUS IN")
|
||||
self[f"BUS {i}||{param}"].bind("<Return>", "||KEY ENTER")
|
||||
self[f"BUS {i}||MODE"].bind("<FocusIn>", "||FOCUS IN")
|
||||
self[f"BUS {i}||MODE"].bind("<space>", "||KEY SPACE", propagate=False)
|
||||
self[f"BUS {i}||MODE"].bind("<Return>", "||KEY ENTER", propagate=False)
|
||||
|
||||
# Bus Sliders
|
||||
for i in range(self.kind.num_bus):
|
||||
self[f"BUS {i}||SLIDER GAIN"].bind("<FocusIn>", "||FOCUS IN")
|
||||
self[f"BUS {i}||SLIDER GAIN"].bind("<FocusOut>", "||FOCUS OUT")
|
||||
self[f"BUS {i}||SLIDER GAIN"].bind("<Left>", "||KEY LEFT")
|
||||
self[f"BUS {i}||SLIDER GAIN"].bind("<Right>", "||KEY RIGHT")
|
||||
self[f"BUS {i}||SLIDER GAIN"].bind("<Shift-KeyPress-Left>", "||KEY SHIFT LEFT")
|
||||
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("<Control-KeyPress-Right>", "||KEY CTRL RIGHT")
|
||||
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("<Shift-KeyPress-Up>", "||KEY SHIFT UP")
|
||||
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")
|
||||
for event in ("KeyPress", "KeyRelease"):
|
||||
event_id = event.removeprefix("Key").upper()
|
||||
for direction in ("Left", "Right", "Up", "Down"):
|
||||
self[f"BUS {i}||SLIDER GAIN"].bind(
|
||||
f"<{event}-{direction}>", f"||KEY {direction.upper()} {event_id}"
|
||||
)
|
||||
self[f"BUS {i}||SLIDER GAIN"].bind(
|
||||
f"<Shift-{event}-{direction}>", f"||KEY SHIFT {direction.upper()} {event_id}"
|
||||
)
|
||||
self[f"BUS {i}||SLIDER GAIN"].bind(
|
||||
f"<Control-{event}-{direction}>", f"||KEY CTRL {direction.upper()} {event_id}"
|
||||
)
|
||||
self[f"BUS {i}||SLIDER GAIN"].bind("<Control-Shift-KeyPress-R>", "||KEY CTRL SHIFT R")
|
||||
|
||||
def run(self):
|
||||
@@ -291,20 +304,30 @@ class NVDAVMWindow(psg.Window):
|
||||
self.logger.debug(f"values::{values}")
|
||||
if event in (psg.WIN_CLOSED, "Exit"):
|
||||
break
|
||||
elif event.endswith("MODE"):
|
||||
elif event in util.get_slider_modes():
|
||||
mode = event
|
||||
self.nvda.speak(f"{mode} enabled")
|
||||
elif event == "Escape:27":
|
||||
self.logger.debug(f"entered slider mode {mode}")
|
||||
continue
|
||||
elif event == "ESCAPE":
|
||||
if mode:
|
||||
self.nvda.speak(f"{mode} disabled")
|
||||
self.logger.debug(f"exited from slider mode {mode}")
|
||||
mode = None
|
||||
|
||||
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
|
||||
continue
|
||||
|
||||
match parsed_cmd := self.parser.match.parseString(event):
|
||||
# Slider 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
|
||||
case ["CTRL-TAB"] | ["CTRL-SHIFT-TAB"]:
|
||||
self["tabgroup"].set_focus()
|
||||
@@ -372,13 +395,19 @@ class NVDAVMWindow(psg.Window):
|
||||
if focus := self.find_element_with_focus():
|
||||
identifier, param = focus.Key.split("||")
|
||||
self.write_event_value(f"{identifier}||MUTE", None)
|
||||
case [["SLIDER", "MODE", 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 {direction} {e}", None)
|
||||
case [
|
||||
"SLIDER-MODE-LEFT"
|
||||
| "SLIDER-MODE-RIGHT"
|
||||
| "SLIDER-MODE-SHIFT-LEFT"
|
||||
| "SLIDER-MODE-SHIFT-RIGHT"
|
||||
| "SLIDER-MODE-CTRL-LEFT"
|
||||
| "SLIDER-MODE-CTRL-RIGHT" as op
|
||||
["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
|
||||
@@ -388,18 +417,19 @@ class NVDAVMWindow(psg.Window):
|
||||
_, index = identifier.split()
|
||||
if param in util.get_full_slider_params(int(index), self.kind):
|
||||
if "SLIDER" not in partial:
|
||||
op = op.removeprefix("SLIDER-MODE-").split("-")
|
||||
self.write_event_value(f"{identifier}||SLIDER {param}||KEY {' '.join(op)}", None)
|
||||
self.write_event_value(
|
||||
f"{identifier}||SLIDER {param}||KEY {modifier} {direction} {e}", None
|
||||
)
|
||||
|
||||
# Rename popups
|
||||
case ["F2:113"]:
|
||||
case ["F2"]:
|
||||
tab = values["tabgroup"].split("||")[1]
|
||||
if tab in ("Physical Strip", "Virtual Strip", "Buses"):
|
||||
if focus := self.find_element_with_focus():
|
||||
identifier, partial = focus.Key.split("||")
|
||||
_, index = identifier.split()
|
||||
index = int(index)
|
||||
data = self.popup.rename("Label", index, title=f"Rename", tab=tab)
|
||||
data = self.popup.rename("Label", index, title="Rename", tab=tab)
|
||||
if not data: # cancel was pressed
|
||||
continue
|
||||
match tab:
|
||||
@@ -422,6 +452,23 @@ class NVDAVMWindow(psg.Window):
|
||||
self[f"BUS {index}||LABEL"].update(value=label)
|
||||
self.cache["labels"][f"BUS {index}||LABEL"] = label
|
||||
|
||||
# Advanced popups (settings, comp, gate)
|
||||
case ["CTRL-A"]:
|
||||
match values["tabgroup"]:
|
||||
case "tab||Settings":
|
||||
self.write_event_value("ADVANCED SETTINGS", None)
|
||||
case "tab||Physical Strip":
|
||||
if values["tabgroup||Physical Strip"] == "tab||Physical Strip||sliders":
|
||||
if focus := self.find_element_with_focus():
|
||||
identifier, partial = focus.key.split("||")
|
||||
_, index = identifier.split()
|
||||
match self.kind.name:
|
||||
case "potato":
|
||||
if "SLIDER COMP" in partial:
|
||||
self.popup.compressor(int(index), title="Advanced Compressor")
|
||||
elif "SLIDER GATE" in partial:
|
||||
self.popup.gate(int(index), title="Advanced Gate")
|
||||
|
||||
# Menus
|
||||
case [["Restart", "Audio", "Engine"], ["MENU"]]:
|
||||
self.perform_long_operation(self.vm.command.restart, "ENGINE RESTART||END")
|
||||
@@ -558,14 +605,18 @@ class NVDAVMWindow(psg.Window):
|
||||
val = values[f"PATCH COMPOSITE||{key}"]
|
||||
index = int(key[-1]) - 1
|
||||
self.vm.patch.composite[index].set(util.get_patch_composite_list(self.kind).index(val) + 1)
|
||||
self.TKroot.after(200, self.nvda.speak, f"PATCH COMPOSITE {key[-1]} set {val}")
|
||||
self.TKroot.after(200, self.nvda.speak, val)
|
||||
case [["PATCH", "COMPOSITE"], [key], ["FOCUS", "IN"]]:
|
||||
if self.find_element_with_focus() is not None:
|
||||
if values[f"PATCH COMPOSITE||{key}"]:
|
||||
val = values[f"PATCH COMPOSITE||{key}"]
|
||||
else:
|
||||
index = int(key[-1]) - 1
|
||||
val = util.get_patch_composite_list(self.kind)[self.vm.patch.composite[index].get() - 1]
|
||||
comp_index = self.vm.patch.composite[index].get()
|
||||
if self.kind.name == "banana":
|
||||
if comp_index == 64: # bus channel
|
||||
comp_index = 0
|
||||
val = util.get_patch_composite_list(self.kind)[comp_index - 1]
|
||||
self.nvda.speak(f"Patch COMPOSITE {key[-1]} {val}")
|
||||
case [["PATCH", "COMPOSITE"], [key], ["KEY", "SPACE" | "ENTER"]]:
|
||||
util.open_context_menu_for_buttonmenu(self, f"PATCH COMPOSITE||{key}")
|
||||
@@ -579,7 +630,7 @@ class NVDAVMWindow(psg.Window):
|
||||
)
|
||||
val = values[f"INSERT CHECKBOX||{in_num} {channel}"]
|
||||
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"]]:
|
||||
if self.find_element_with_focus() is not None:
|
||||
index = util.get_insert_checkbox_index(
|
||||
@@ -591,9 +642,12 @@ class NVDAVMWindow(psg.Window):
|
||||
channel = util._patch_insert_channels[int(channel)]
|
||||
num = int(in_num[-1])
|
||||
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
|
||||
case ["ADVANCED SETTINGS"] | ["CTRL-A"]:
|
||||
case ["ADVANCED SETTINGS"]:
|
||||
if values["tabgroup"] == "tab||Settings":
|
||||
self.popup.advanced_settings(title="Advanced Settings")
|
||||
case [["ADVANCED", "SETTINGS"], ["FOCUS", "IN"]]:
|
||||
@@ -701,7 +755,6 @@ class NVDAVMWindow(psg.Window):
|
||||
["FOCUS", "IN"],
|
||||
]:
|
||||
if self.find_element_with_focus() is not None:
|
||||
self.vm.event.pdirty = False
|
||||
val = values[f"STRIP {index}||SLIDER {param}"]
|
||||
label = self.cache["labels"][f"STRIP {index}||LABEL"]
|
||||
self.nvda.speak(f"{label} {param} {int(val) if param == 'LIMIT' else val}")
|
||||
@@ -713,7 +766,7 @@ class NVDAVMWindow(psg.Window):
|
||||
],
|
||||
["FOCUS", "OUT"],
|
||||
]:
|
||||
self.vm.event.pdirty = True
|
||||
pass
|
||||
case [
|
||||
["STRIP", index],
|
||||
[
|
||||
@@ -728,112 +781,53 @@ class NVDAVMWindow(psg.Window):
|
||||
| "MID"
|
||||
| "TREBLE" as param,
|
||||
],
|
||||
["KEY", "LEFT" | "RIGHT" | "UP" | "DOWN" as direction],
|
||||
["KEY", "LEFT" | "RIGHT" | "UP" | "DOWN" as direction, "PRESS" | "RELEASE" as e],
|
||||
]:
|
||||
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
|
||||
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":
|
||||
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"):
|
||||
match direction:
|
||||
case "RIGHT" | "UP":
|
||||
val += 1
|
||||
else:
|
||||
val += 3
|
||||
case "LEFT" | "DOWN":
|
||||
if param in ("COMP", "GATE", "DENOISER", "AUDIBILITY", "BASS", "MID", "TREBLE"):
|
||||
case "LEFT" | "DOWN":
|
||||
val -= 1
|
||||
else:
|
||||
val -= 3
|
||||
|
||||
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}")
|
||||
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(round(val, 1)))
|
||||
else:
|
||||
self.vm.event.pdirty = True
|
||||
case [
|
||||
["STRIP", index],
|
||||
[
|
||||
@@ -848,61 +842,139 @@ class NVDAVMWindow(psg.Window):
|
||||
| "MID"
|
||||
| "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:
|
||||
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
|
||||
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 direction:
|
||||
case "RIGHT" | "UP":
|
||||
if param in ("COMP", "GATE", "DENOISER", "AUDIBILITY", "BASS", "MID", "TREBLE"):
|
||||
val += 1
|
||||
else:
|
||||
val += 3
|
||||
case "LEFT" | "DOWN":
|
||||
if param in ("COMP", "GATE", "DENOISER", "AUDIBILITY", "BASS", "MID", "TREBLE"):
|
||||
val -= 1
|
||||
else:
|
||||
val -= 3
|
||||
|
||||
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}")
|
||||
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)
|
||||
if param == "LIMIT":
|
||||
self.nvda.speak(str(int(val)))
|
||||
else:
|
||||
self.nvda.speak(str(round(val, 1)))
|
||||
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)
|
||||
if param == "LIMIT":
|
||||
self.nvda.speak(str(int(val)))
|
||||
else:
|
||||
self.nvda.speak(str(round(val, 1)))
|
||||
else:
|
||||
self.vm.event.pdirty = True
|
||||
case [["STRIP", index], ["SLIDER", param], ["KEY", "CTRL", "SHIFT", "R"]]:
|
||||
match param:
|
||||
case "GAIN":
|
||||
self.vm.strip[int(index)].gain = 0
|
||||
self[f"STRIP {index}||SLIDER {param}"].update(value=0)
|
||||
case "COMP" | "GATE" | "DENOISER":
|
||||
target = getattr(self.vm.strip[int(index)], param.lower())
|
||||
setattr(target, "knob", 0)
|
||||
self[f"STRIP {index}||SLIDER {param}"].update(value=0)
|
||||
case "AUDIBILITY":
|
||||
@@ -914,7 +986,7 @@ class NVDAVMWindow(psg.Window):
|
||||
case "LIMIT":
|
||||
self.vm.strip[int(index)].limit = 12
|
||||
self[f"STRIP {index}||SLIDER {param}"].update(value=12)
|
||||
self.nvda.speak(f"{param} {12 if param == 'LABEL' else 0}")
|
||||
self.nvda.speak(f"{12 if param == 'LIMIT' else 0}")
|
||||
|
||||
# Bus Params
|
||||
case [["BUS", index], [param]]:
|
||||
@@ -940,40 +1012,27 @@ class NVDAVMWindow(psg.Window):
|
||||
"on" if val else "off",
|
||||
)
|
||||
case "MODE":
|
||||
bus_modes = util.get_bus_modes(self.vm)
|
||||
next_index = bus_modes.index(val) + 1
|
||||
if next_index == len(bus_modes):
|
||||
next_index = 0
|
||||
next_bus = bus_modes[next_index]
|
||||
phonetic = {
|
||||
"amix": "Mix Down A",
|
||||
"bmix": "Mix Down B",
|
||||
"repeat": "Stereo Repeat",
|
||||
"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",
|
||||
}
|
||||
setattr(self.vm.bus[int(index)].mode, next_bus, True)
|
||||
self.cache["bus"][event] = next_bus
|
||||
chosen = util._bus_mode_map_reversed[values[event]]
|
||||
setattr(self.vm.bus[int(index)].mode, chosen, True)
|
||||
self.cache["bus"][event] = chosen
|
||||
self.TKroot.after(
|
||||
200,
|
||||
self.nvda.speak,
|
||||
phonetic.get(next_bus, next_bus),
|
||||
util._bus_mode_map[chosen],
|
||||
)
|
||||
case [["BUS", index], [param], ["FOCUS", "IN"]]:
|
||||
if self.find_element_with_focus() is not None:
|
||||
label = self.cache["labels"][f"BUS {index}||LABEL"]
|
||||
val = self.cache["bus"][f"BUS {index}||{param}"]
|
||||
if param == "MODE":
|
||||
self.nvda.speak(f"{label} bus {param} {val}")
|
||||
self.nvda.speak(f"{label} bus {param} {util._bus_mode_map[val]}")
|
||||
else:
|
||||
self.nvda.speak(f"{label} bus {param} {'on' if val else 'off'}")
|
||||
case [["BUS", index], [param], ["KEY", "ENTER"]]:
|
||||
self.find_element_with_focus().click()
|
||||
self.nvda.speak(f"{label} {param} {'on' if val else 'off'}")
|
||||
case [["BUS", index], [param], ["KEY", "SPACE" | "ENTER"]]:
|
||||
if param == "MODE":
|
||||
util.open_context_menu_for_buttonmenu(self, f"BUS {index}||MODE")
|
||||
else:
|
||||
self.find_element_with_focus().click()
|
||||
|
||||
# Bus Sliders
|
||||
case [["BUS", index], ["SLIDER", "GAIN"]]:
|
||||
@@ -982,57 +1041,72 @@ class NVDAVMWindow(psg.Window):
|
||||
self.vm.bus[int(index)].gain = val
|
||||
case [["BUS", index], ["SLIDER", "GAIN"], ["FOCUS", "IN"]]:
|
||||
if self.find_element_with_focus() is not None:
|
||||
self.vm.event.pdirty = False
|
||||
label = self.cache["labels"][f"BUS {index}||LABEL"]
|
||||
val = values[f"BUS {index}||SLIDER GAIN"]
|
||||
self.nvda.speak(f"{label} gain {val}")
|
||||
case [["BUS", index], ["SLIDER", "GAIN"], ["FOCUS", "OUT"]]:
|
||||
self.vm.event.pdirty = True
|
||||
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))
|
||||
pass
|
||||
case [
|
||||
["BUS", index],
|
||||
["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
|
||||
match direction:
|
||||
case "RIGHT" | "UP":
|
||||
val += 3
|
||||
case "LEFT" | "DOWN":
|
||||
val -= 3
|
||||
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))
|
||||
if e == "PRESS":
|
||||
self.vm.event.pdirty = False
|
||||
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(round(val, 1)))
|
||||
else:
|
||||
self.vm.event.pdirty = True
|
||||
case [
|
||||
["BUS", index],
|
||||
["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
|
||||
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))
|
||||
if e == "PRESS":
|
||||
self.vm.event.pdirty = False
|
||||
val = self.vm.bus[int(index)].gain
|
||||
match direction:
|
||||
case "RIGHT" | "UP":
|
||||
val += 3
|
||||
case "LEFT" | "DOWN":
|
||||
val -= 3
|
||||
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(round(val, 1)))
|
||||
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(round(val, 1)))
|
||||
else:
|
||||
self.vm.event.pdirty = True
|
||||
case [["BUS", index], ["SLIDER", "GAIN"], ["KEY", "CTRL", "SHIFT", "R"]]:
|
||||
self.vm.bus[int(index)].gain = 0
|
||||
self[f"BUS {index}||SLIDER GAIN"].update(value=0)
|
||||
self.nvda.speak(str(val))
|
||||
self.nvda.speak(str(0))
|
||||
|
||||
# Unknown
|
||||
case _:
|
||||
|
||||
Reference in New Issue
Block a user