mirror of
https://github.com/onyx-and-iris/nvda-voicemeeter.git
synced 2026-04-07 18:03:35 +00:00
Compare commits
11 Commits
v1.1.0
...
add-braill
| Author | SHA1 | Date | |
|---|---|---|---|
| 10425f50d5 | |||
| 7f327b4cce | |||
| 2e3ba66b5a | |||
| 5fca7da033 | |||
| 92f357f003 | |||
| d54995dbf1 | |||
| bc0b25032a | |||
| 2a86c05bea | |||
| aae62fa136 | |||
| 5b4a76c484 | |||
| dfb96777bb |
12
.github/workflows/release.yml
vendored
12
.github/workflows/release.yml
vendored
@@ -180,9 +180,9 @@ jobs:
|
|||||||
- name: Build Summary
|
- name: Build Summary
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: |
|
run: |
|
||||||
Write-Host -ForegroundColor Green "🎉 Build completed successfully!"
|
Write-Host -ForegroundColor Green "Build completed successfully!"
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host "📦 Built artifacts:"
|
Write-Host "Built artifacts:"
|
||||||
Write-Host " - nvda-voicemeeter-basic.zip"
|
Write-Host " - nvda-voicemeeter-basic.zip"
|
||||||
Write-Host " - nvda-voicemeeter-banana.zip"
|
Write-Host " - nvda-voicemeeter-banana.zip"
|
||||||
Write-Host " - nvda-voicemeeter-potato.zip"
|
Write-Host " - nvda-voicemeeter-potato.zip"
|
||||||
@@ -208,22 +208,22 @@ jobs:
|
|||||||
--title "NVDA-Voicemeeter $TAG_NAME" \
|
--title "NVDA-Voicemeeter $TAG_NAME" \
|
||||||
--notes "## NVDA-Voicemeeter Release $TAG_NAME
|
--notes "## NVDA-Voicemeeter Release $TAG_NAME
|
||||||
|
|
||||||
### 📦 Downloads
|
### Downloads
|
||||||
- **nvda-voicemeeter-basic.zip** - Basic version with dependencies
|
- **nvda-voicemeeter-basic.zip** - Basic version with dependencies
|
||||||
- **nvda-voicemeeter-banana.zip** - Banana version with dependencies
|
- **nvda-voicemeeter-banana.zip** - Banana version with dependencies
|
||||||
- **nvda-voicemeeter-potato.zip** - Potato version with dependencies
|
- **nvda-voicemeeter-potato.zip** - Potato version with dependencies
|
||||||
|
|
||||||
### 🔧 Requirements
|
### Requirements
|
||||||
- Windows 10/11
|
- Windows 10/11
|
||||||
- Voicemeeter (Basic/Banana/Potato) installed
|
- Voicemeeter (Basic/Banana/Potato) installed
|
||||||
- NVDA screen reader
|
- NVDA screen reader
|
||||||
|
|
||||||
### 🚀 Installation
|
### Installation
|
||||||
1. Download the appropriate zip for your Voicemeeter version
|
1. Download the appropriate zip for your Voicemeeter version
|
||||||
2. Extract and run the executable - no installation required
|
2. Extract and run the executable - no installation required
|
||||||
3. The application will integrate with NVDA automatically
|
3. The application will integrate with NVDA automatically
|
||||||
|
|
||||||
### 📝 Notes
|
### Notes
|
||||||
- Built with dynamic build system using PyInstaller
|
- Built with dynamic build system using PyInstaller
|
||||||
- Includes NVDA Controller Client for screen reader integration"
|
- Includes NVDA Controller Client for screen reader integration"
|
||||||
env:
|
env:
|
||||||
|
|||||||
@@ -1,4 +1,11 @@
|
|||||||
repos:
|
repos:
|
||||||
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
|
rev: v2.3.0
|
||||||
|
hooks:
|
||||||
|
- id: check-yaml
|
||||||
|
- id: end-of-file-fixer
|
||||||
|
- id: trailing-whitespace
|
||||||
|
|
||||||
- repo: https://github.com/pdm-project/pdm
|
- repo: https://github.com/pdm-project/pdm
|
||||||
rev: 2.26.6
|
rev: 2.26.6
|
||||||
hooks:
|
hooks:
|
||||||
|
|||||||
@@ -22,6 +22,12 @@ tasks:
|
|||||||
build:
|
build:
|
||||||
desc: Build the project
|
desc: Build the project
|
||||||
deps: [generate-specs]
|
deps: [generate-specs]
|
||||||
|
preconditions:
|
||||||
|
- sh: |
|
||||||
|
if [ ! -f controllerClient/x64/nvdaControllerClient.dll ] || [ ! -f controllerClient/x86/nvdaControllerClient.dll ]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
msg: 'nvdaControllerClient.dll is missing. See https://github.com/nvaccess/nvda/blob/master/extras/controllerClient/readme.md for instructions on how to obtain it.'
|
||||||
cmds:
|
cmds:
|
||||||
- for:
|
- for:
|
||||||
matrix:
|
matrix:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "nvda-voicemeeter"
|
name = "nvda-voicemeeter"
|
||||||
version = "1.1.0"
|
version = "1.1.2"
|
||||||
description = "A Voicemeeter app compatible with NVDA"
|
description = "A Voicemeeter app compatible with NVDA"
|
||||||
authors = [{ name = "Onyx and Iris", email = "code@onyxandiris.online" }]
|
authors = [{ name = "Onyx and Iris", email = "code@onyxandiris.online" }]
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
|||||||
@@ -1,15 +1,21 @@
|
|||||||
import ctypes as ct
|
import ctypes as ct
|
||||||
import platform
|
import platform
|
||||||
import winreg
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from .errors import NVDAVMError
|
from .errors import NVDAVMError
|
||||||
|
|
||||||
BITS = 64 if ct.sizeof(ct.c_void_p) == 8 else 32
|
try:
|
||||||
|
import winreg
|
||||||
|
except ImportError as e:
|
||||||
|
ERR_MSG = 'winreg module not found, only Windows OS supported'
|
||||||
|
raise NVDAVMError(ERR_MSG) from e
|
||||||
|
|
||||||
|
# Defense against edge cases where winreg imports but we're not on Windows
|
||||||
if platform.system() != 'Windows':
|
if platform.system() != 'Windows':
|
||||||
raise NVDAVMError('Only Windows OS supported')
|
raise NVDAVMError('Only Windows OS supported')
|
||||||
|
|
||||||
|
BITS = 64 if ct.sizeof(ct.c_void_p) == 8 else 32
|
||||||
|
|
||||||
REG_KEY = '\\'.join(
|
REG_KEY = '\\'.join(
|
||||||
filter(
|
filter(
|
||||||
None,
|
None,
|
||||||
@@ -43,4 +49,4 @@ if not controller_path.exists():
|
|||||||
|
|
||||||
DLL_PATH = controller_path / f'x{64 if BITS == 64 else 86}' / 'nvdaControllerClient.dll'
|
DLL_PATH = controller_path / f'x{64 if BITS == 64 else 86}' / 'nvdaControllerClient.dll'
|
||||||
|
|
||||||
libc = ct.CDLL(str(DLL_PATH))
|
libc = ct.WinDLL(str(DLL_PATH))
|
||||||
|
|||||||
@@ -1,30 +1,56 @@
|
|||||||
|
from enum import IntEnum
|
||||||
|
|
||||||
from .cdll import libc
|
from .cdll import libc
|
||||||
from .errors import NVDAVMCAPIError
|
from .errors import NVDAVMCAPIError
|
||||||
|
|
||||||
|
|
||||||
|
class ServerState(IntEnum):
|
||||||
|
RUNNING = 0
|
||||||
|
UNAVAILABLE = 1722
|
||||||
|
|
||||||
|
|
||||||
class CBindings:
|
class CBindings:
|
||||||
bind_test_if_running = libc.nvdaController_testIfRunning
|
bind_test_if_running = libc.nvdaController_testIfRunning
|
||||||
bind_speak_text = libc.nvdaController_speakText
|
bind_speak_text = libc.nvdaController_speakText
|
||||||
bind_cancel_speech = libc.nvdaController_cancelSpeech
|
bind_cancel_speech = libc.nvdaController_cancelSpeech
|
||||||
bind_braille_message = libc.nvdaController_brailleMessage
|
bind_braille_message = libc.nvdaController_brailleMessage
|
||||||
|
|
||||||
def call(self, fn, *args, ok=(0,)):
|
def _call(self, fn, *args, ok=(0,)) -> int:
|
||||||
retval = fn(*args)
|
retval = fn(*args)
|
||||||
if retval not in ok:
|
if retval not in ok:
|
||||||
raise NVDAVMCAPIError(fn.__name__, retval)
|
raise NVDAVMCAPIError(fn.__name__, retval)
|
||||||
return retval
|
return retval
|
||||||
|
|
||||||
|
def test_if_running(self) -> int:
|
||||||
|
return self._call(self.bind_test_if_running, ok=(ServerState.RUNNING, ServerState.UNAVAILABLE))
|
||||||
|
|
||||||
|
def speak_text(self, text: str) -> None:
|
||||||
|
self._call(self.bind_speak_text, text)
|
||||||
|
|
||||||
|
def cancel_speech(self) -> None:
|
||||||
|
self._call(self.bind_cancel_speech)
|
||||||
|
|
||||||
|
def braille_message(self, text: str) -> None:
|
||||||
|
self._call(self.bind_braille_message, text)
|
||||||
|
|
||||||
|
|
||||||
|
class Nvda:
|
||||||
|
def __init__(self):
|
||||||
|
self._bindings = CBindings()
|
||||||
|
|
||||||
class Nvda(CBindings):
|
|
||||||
@property
|
@property
|
||||||
def is_running(self):
|
def is_running(self) -> bool:
|
||||||
return self.call(self.bind_test_if_running) == 0
|
return self._bindings.test_if_running() == ServerState.RUNNING
|
||||||
|
|
||||||
def speak(self, text):
|
def speak(self, text: str) -> None:
|
||||||
self.call(self.bind_speak_text, text)
|
self._bindings.speak_text(text)
|
||||||
|
|
||||||
def cancel_speech(self):
|
def cancel_speech(self) -> None:
|
||||||
self.call(self.bind_cancel_speech)
|
self._bindings.cancel_speech()
|
||||||
|
|
||||||
def braille_message(self, text):
|
def braille_message(self, text: str) -> None:
|
||||||
self.call(self.bind_braille_message, text)
|
self._bindings.braille_message(text)
|
||||||
|
|
||||||
|
def speak_and_braille(self, text: str) -> None:
|
||||||
|
self.speak(text)
|
||||||
|
self.braille_message(text)
|
||||||
|
|||||||
@@ -35,12 +35,12 @@ class Popup:
|
|||||||
self.logger.debug(f'values::{values}')
|
self.logger.debug(f'values::{values}')
|
||||||
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.parse_string(event):
|
||||||
case [[button], ['FOCUS', 'IN']]:
|
case [[button], ['FOCUS', 'IN']]:
|
||||||
if values['Browse']:
|
if values['Browse']:
|
||||||
filepath = values['Browse']
|
filepath = values['Browse']
|
||||||
break
|
break
|
||||||
self.window.nvda.speak(button)
|
self.window.nvda.speak_and_braille(button)
|
||||||
case [_, ['KEY', 'ENTER']]:
|
case [_, ['KEY', 'ENTER']]:
|
||||||
popup.find_element_with_focus().click()
|
popup.find_element_with_focus().click()
|
||||||
self.logger.debug(f'parsed::{parsed_cmd}')
|
self.logger.debug(f'parsed::{parsed_cmd}')
|
||||||
@@ -105,9 +105,9 @@ class Popup:
|
|||||||
self.logger.debug(f'values::{values}')
|
self.logger.debug(f'values::{values}')
|
||||||
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.parse_string(event):
|
||||||
case [[button], ['FOCUS', 'IN']]:
|
case [[button], ['FOCUS', 'IN']]:
|
||||||
self.window.nvda.speak(button)
|
self.window.nvda.speak_and_braille(button)
|
||||||
case [_, ['KEY', 'ENTER']]:
|
case [_, ['KEY', 'ENTER']]:
|
||||||
popup.find_element_with_focus().click()
|
popup.find_element_with_focus().click()
|
||||||
case ['Ok']:
|
case ['Ok']:
|
||||||
@@ -227,27 +227,27 @@ class Popup:
|
|||||||
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
|
||||||
match parsed_cmd := self.window.parser.match.parseString(event):
|
match parsed_cmd := self.window.parser.match.parse_string(event):
|
||||||
case [['ASIO', 'INPUT', 'SPINBOX'], [in_num, channel]]:
|
case [['ASIO', 'INPUT', 'SPINBOX'], [in_num, channel]]:
|
||||||
index = util.get_asio_input_spinbox_index(int(channel), int(in_num[-1]))
|
index = util.get_asio_input_spinbox_index(int(channel), int(in_num[-1]))
|
||||||
val = values[f'ASIO INPUT SPINBOX||{in_num} {channel}']
|
val = values[f'ASIO INPUT SPINBOX||{in_num} {channel}']
|
||||||
self.window.vm.patch.asio[index].set(val)
|
self.window.vm.patch.asio[index].set(val)
|
||||||
channel = ('left', 'right')[int(channel)]
|
channel = ('left', 'right')[int(channel)]
|
||||||
self.window.nvda.speak(str(val))
|
self.window.nvda.speak_and_braille(str(val))
|
||||||
case [['ASIO', 'INPUT', 'SPINBOX'], [in_num, channel], ['FOCUS', 'IN']]:
|
case [['ASIO', 'INPUT', 'SPINBOX'], [in_num, channel], ['FOCUS', 'IN']]:
|
||||||
if self.popup.find_element_with_focus() is not None:
|
if self.popup.find_element_with_focus() is not None:
|
||||||
val = values[f'ASIO INPUT SPINBOX||{in_num} {channel}']
|
val = values[f'ASIO INPUT SPINBOX||{in_num} {channel}']
|
||||||
channel = ('left', 'right')[int(channel)]
|
channel = ('left', 'right')[int(channel)]
|
||||||
num = int(in_num[-1])
|
num = int(in_num[-1])
|
||||||
self.window.nvda.speak(f'Patch ASIO inputs to strips IN#{num} {channel} {val}')
|
self.window.nvda.speak_and_braille(f'Patch ASIO inputs to strips IN#{num} {channel} {val}')
|
||||||
case [['ASIO', 'OUTPUT', param, 'SPINBOX'], [index]]:
|
case [['ASIO', 'OUTPUT', param, 'SPINBOX'], [index]]:
|
||||||
target = getattr(self.window.vm.patch, param)[int(index)]
|
target = getattr(self.window.vm.patch, param)[int(index)]
|
||||||
target.set(values[event])
|
target.set(values[event])
|
||||||
self.window.nvda.speak(str(values[event]))
|
self.window.nvda.speak_and_braille(str(values[event]))
|
||||||
case [['ASIO', 'OUTPUT', param, 'SPINBOX'], [index], ['FOCUS', 'IN']]:
|
case [['ASIO', 'OUTPUT', param, 'SPINBOX'], [index], ['FOCUS', 'IN']]:
|
||||||
if self.popup.find_element_with_focus() is not None:
|
if self.popup.find_element_with_focus() is not None:
|
||||||
val = values[f'ASIO OUTPUT {param} SPINBOX||{index}']
|
val = values[f'ASIO OUTPUT {param} SPINBOX||{index}']
|
||||||
self.window.nvda.speak(
|
self.window.nvda.speak_and_braille(
|
||||||
f'Patch BUS to A1 ASIO Outputs OUT {param} channel {int(index) + 1} {val}'
|
f'Patch BUS to A1 ASIO Outputs OUT {param} channel {int(index) + 1} {val}'
|
||||||
)
|
)
|
||||||
case ['BUFFER MME' | 'BUFFER WDM' | 'BUFFER KS' | 'BUFFER ASIO']:
|
case ['BUFFER MME' | 'BUFFER WDM' | 'BUFFER KS' | 'BUFFER ASIO']:
|
||||||
@@ -263,15 +263,15 @@ class Popup:
|
|||||||
driver = event.split()[1]
|
driver = event.split()[1]
|
||||||
self.window.vm.set(f'option.buffer.{driver.lower()}', val)
|
self.window.vm.set(f'option.buffer.{driver.lower()}', val)
|
||||||
self.window.TKroot.after(
|
self.window.TKroot.after(
|
||||||
200, self.window.nvda.speak, f'{driver} BUFFER {val if val else "default"}'
|
200, self.window.nvda.speak_and_braille, f'{driver} BUFFER {val if val else "default"}'
|
||||||
)
|
)
|
||||||
case [['BUFFER', driver], ['FOCUS', 'IN']]:
|
case [['BUFFER', driver], ['FOCUS', 'IN']]:
|
||||||
val = int(self.window.vm.get(f'option.buffer.{driver.lower()}'))
|
val = int(self.window.vm.get(f'option.buffer.{driver.lower()}'))
|
||||||
self.window.nvda.speak(f'{driver} BUFFER {val if val else "default"}')
|
self.window.nvda.speak_and_braille(f'{driver} BUFFER {val if val else "default"}')
|
||||||
case [['BUFFER', driver], ['KEY', 'SPACE' | 'ENTER']]:
|
case [['BUFFER', driver], ['KEY', 'SPACE' | 'ENTER']]:
|
||||||
util.open_context_menu_for_buttonmenu(self.popup, f'BUFFER {driver}')
|
util.open_context_menu_for_buttonmenu(self.popup, f'BUFFER {driver}')
|
||||||
case [[button], ['FOCUS', 'IN']]:
|
case [[button], ['FOCUS', 'IN']]:
|
||||||
self.window.nvda.speak(button)
|
self.window.nvda.speak_and_braille(button)
|
||||||
case [_, ['KEY', 'ENTER']]:
|
case [_, ['KEY', 'ENTER']]:
|
||||||
self.popup.find_element_with_focus().click()
|
self.popup.find_element_with_focus().click()
|
||||||
self.logger.debug(f'parsed::{parsed_cmd}')
|
self.logger.debug(f'parsed::{parsed_cmd}')
|
||||||
@@ -310,14 +310,16 @@ class Popup:
|
|||||||
f'<Shift-{event}-{direction}>', f'||KEY SHIFT {direction.upper()} {event_id}'
|
f'<Shift-{event}-{direction}>', f'||KEY SHIFT {direction.upper()} {event_id}'
|
||||||
)
|
)
|
||||||
self.popup[f'COMPRESSOR||SLIDER {param}'].bind(
|
self.popup[f'COMPRESSOR||SLIDER {param}'].bind(
|
||||||
f'<Control-{event}-{direction}>', f'||KEY CTRL {direction.upper()} {event_id}'
|
f'<Control-{event}-{direction}>', f'||KEY CTRL {direction.upper()} {event_id}', propagate=False
|
||||||
)
|
)
|
||||||
if param == 'RELEASE':
|
if param == 'RELEASE':
|
||||||
self.popup[f'COMPRESSOR||SLIDER {param}'].bind(
|
self.popup[f'COMPRESSOR||SLIDER {param}'].bind(
|
||||||
f'<Alt-{event}-{direction}>', f'||KEY ALT {direction.upper()} {event_id}'
|
f'<Alt-{event}-{direction}>', f'||KEY ALT {direction.upper()} {event_id}'
|
||||||
)
|
)
|
||||||
self.popup[f'COMPRESSOR||SLIDER {param}'].bind(
|
self.popup[f'COMPRESSOR||SLIDER {param}'].bind(
|
||||||
f'<Control-Alt-{event}-{direction}>', f'||KEY CTRL ALT {direction.upper()} {event_id}'
|
f'<Control-Alt-{event}-{direction}>',
|
||||||
|
f'||KEY CTRL ALT {direction.upper()} {event_id}',
|
||||||
|
propagate=False,
|
||||||
)
|
)
|
||||||
self.popup[f'COMPRESSOR||SLIDER {param}'].bind('<Control-Shift-KeyPress-R>', '||KEY CTRL SHIFT R')
|
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('<FocusIn>', '||FOCUS IN')
|
||||||
@@ -331,11 +333,11 @@ class Popup:
|
|||||||
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
|
||||||
match parsed_cmd := self.window.parser.match.parseString(event):
|
match parsed_cmd := self.window.parser.match.parse_string(event):
|
||||||
case [['COMPRESSOR'], ['SLIDER', param]]:
|
case [['COMPRESSOR'], ['SLIDER', param]]:
|
||||||
setattr(self.window.vm.strip[index].comp, param.lower(), values[event])
|
setattr(self.window.vm.strip[index].comp, param.lower(), values[event])
|
||||||
case [['COMPRESSOR'], ['SLIDER', param], ['FOCUS', 'IN']]:
|
case [['COMPRESSOR'], ['SLIDER', param], ['FOCUS', 'IN']]:
|
||||||
self.window.nvda.speak(f'{param} {values[f"COMPRESSOR||SLIDER {param}"]}')
|
self.window.nvda.speak_and_braille(f'{param} {values[f"COMPRESSOR||SLIDER {param}"]}')
|
||||||
case [
|
case [
|
||||||
['COMPRESSOR'],
|
['COMPRESSOR'],
|
||||||
['SLIDER', param],
|
['SLIDER', param],
|
||||||
@@ -362,9 +364,9 @@ class Popup:
|
|||||||
setattr(self.window.vm.strip[index].comp, param.lower(), val)
|
setattr(self.window.vm.strip[index].comp, param.lower(), val)
|
||||||
self.popup[f'COMPRESSOR||SLIDER {param}'].update(value=val)
|
self.popup[f'COMPRESSOR||SLIDER {param}'].update(value=val)
|
||||||
if param == 'KNEE':
|
if param == 'KNEE':
|
||||||
self.window.nvda.speak(str(round(val, 2)))
|
self.window.nvda.speak_and_braille(str(round(val, 2)))
|
||||||
else:
|
else:
|
||||||
self.window.nvda.speak(str(round(val, 1)))
|
self.window.nvda.speak_and_braille(str(round(val, 1)))
|
||||||
else:
|
else:
|
||||||
self.window.vm.event.pdirty = True
|
self.window.vm.event.pdirty = True
|
||||||
case [
|
case [
|
||||||
@@ -397,9 +399,9 @@ class Popup:
|
|||||||
setattr(self.window.vm.strip[index].comp, param.lower(), val)
|
setattr(self.window.vm.strip[index].comp, param.lower(), val)
|
||||||
self.popup[f'COMPRESSOR||SLIDER {param}'].update(value=val)
|
self.popup[f'COMPRESSOR||SLIDER {param}'].update(value=val)
|
||||||
if param == 'KNEE':
|
if param == 'KNEE':
|
||||||
self.window.nvda.speak(str(round(val, 2)))
|
self.window.nvda.speak_and_braille(str(round(val, 2)))
|
||||||
else:
|
else:
|
||||||
self.window.nvda.speak(str(round(val, 1)))
|
self.window.nvda.speak_and_braille(str(round(val, 1)))
|
||||||
else:
|
else:
|
||||||
self.window.vm.event.pdirty = True
|
self.window.vm.event.pdirty = True
|
||||||
case [
|
case [
|
||||||
@@ -428,9 +430,9 @@ class Popup:
|
|||||||
setattr(self.window.vm.strip[index].comp, param.lower(), val)
|
setattr(self.window.vm.strip[index].comp, param.lower(), val)
|
||||||
self.popup[f'COMPRESSOR||SLIDER {param}'].update(value=val)
|
self.popup[f'COMPRESSOR||SLIDER {param}'].update(value=val)
|
||||||
if param == 'KNEE':
|
if param == 'KNEE':
|
||||||
self.window.nvda.speak(str(round(val, 2)))
|
self.window.nvda.speak_and_braille(str(round(val, 2)))
|
||||||
else:
|
else:
|
||||||
self.window.nvda.speak(str(round(val, 1)))
|
self.window.nvda.speak_and_braille(str(round(val, 1)))
|
||||||
else:
|
else:
|
||||||
self.window.vm.event.pdirty = True
|
self.window.vm.event.pdirty = True
|
||||||
case [
|
case [
|
||||||
@@ -451,7 +453,7 @@ class Popup:
|
|||||||
val = util.check_bounds(val, (0, 5000))
|
val = util.check_bounds(val, (0, 5000))
|
||||||
self.window.vm.strip[index].comp.release = val
|
self.window.vm.strip[index].comp.release = val
|
||||||
self.popup[f'COMPRESSOR||SLIDER {param}'].update(value=val)
|
self.popup[f'COMPRESSOR||SLIDER {param}'].update(value=val)
|
||||||
self.window.nvda.speak(str(round(val, 1)))
|
self.window.nvda.speak_and_braille(str(round(val, 1)))
|
||||||
else:
|
else:
|
||||||
self.window.vm.event.pdirty = True
|
self.window.vm.event.pdirty = True
|
||||||
case [
|
case [
|
||||||
@@ -472,7 +474,7 @@ class Popup:
|
|||||||
val = util.check_bounds(val, (0, 5000))
|
val = util.check_bounds(val, (0, 5000))
|
||||||
self.window.vm.strip[index].comp.release = val
|
self.window.vm.strip[index].comp.release = val
|
||||||
self.popup[f'COMPRESSOR||SLIDER {param}'].update(value=val)
|
self.popup[f'COMPRESSOR||SLIDER {param}'].update(value=val)
|
||||||
self.window.nvda.speak(str(round(val, 1)))
|
self.window.nvda.speak_and_braille(str(round(val, 1)))
|
||||||
else:
|
else:
|
||||||
self.window.vm.event.pdirty = True
|
self.window.vm.event.pdirty = True
|
||||||
|
|
||||||
@@ -483,7 +485,7 @@ class Popup:
|
|||||||
self.window.vm.strip[index].comp.gainout = values[event]
|
self.window.vm.strip[index].comp.gainout = values[event]
|
||||||
case [['COMPRESSOR'], ['SLIDER', 'INPUT' | 'OUTPUT' as direction, 'GAIN'], ['FOCUS', 'IN']]:
|
case [['COMPRESSOR'], ['SLIDER', 'INPUT' | 'OUTPUT' as direction, 'GAIN'], ['FOCUS', 'IN']]:
|
||||||
label = f'{direction} GAIN'
|
label = f'{direction} GAIN'
|
||||||
self.window.nvda.speak(f'{label} {values[f"COMPRESSOR||SLIDER {label}"]}')
|
self.window.nvda.speak_and_braille(f'{label} {values[f"COMPRESSOR||SLIDER {label}"]}')
|
||||||
case [
|
case [
|
||||||
['COMPRESSOR'],
|
['COMPRESSOR'],
|
||||||
['SLIDER', 'INPUT' | 'OUTPUT' as direction, 'GAIN'],
|
['SLIDER', 'INPUT' | 'OUTPUT' as direction, 'GAIN'],
|
||||||
@@ -508,7 +510,7 @@ class Popup:
|
|||||||
else:
|
else:
|
||||||
self.window.vm.strip[index].comp.gainout = val
|
self.window.vm.strip[index].comp.gainout = val
|
||||||
self.popup[f'COMPRESSOR||SLIDER {direction} GAIN'].update(value=val)
|
self.popup[f'COMPRESSOR||SLIDER {direction} GAIN'].update(value=val)
|
||||||
self.window.nvda.speak(str(round(val, 1)))
|
self.window.nvda.speak_and_braille(str(round(val, 1)))
|
||||||
else:
|
else:
|
||||||
self.window.vm.event.pdirty = True
|
self.window.vm.event.pdirty = True
|
||||||
case [
|
case [
|
||||||
@@ -535,7 +537,7 @@ class Popup:
|
|||||||
else:
|
else:
|
||||||
self.window.vm.strip[index].comp.gainout = val
|
self.window.vm.strip[index].comp.gainout = val
|
||||||
self.popup[f'COMPRESSOR||SLIDER {direction} GAIN'].update(value=val)
|
self.popup[f'COMPRESSOR||SLIDER {direction} GAIN'].update(value=val)
|
||||||
self.window.nvda.speak(str(round(val, 1)))
|
self.window.nvda.speak_and_braille(str(round(val, 1)))
|
||||||
else:
|
else:
|
||||||
self.window.vm.event.pdirty = True
|
self.window.vm.event.pdirty = True
|
||||||
case [
|
case [
|
||||||
@@ -562,7 +564,7 @@ class Popup:
|
|||||||
else:
|
else:
|
||||||
self.window.vm.strip[index].comp.gainout = val
|
self.window.vm.strip[index].comp.gainout = val
|
||||||
self.popup[f'COMPRESSOR||SLIDER {direction} GAIN'].update(value=val)
|
self.popup[f'COMPRESSOR||SLIDER {direction} GAIN'].update(value=val)
|
||||||
self.window.nvda.speak(str(round(val, 1)))
|
self.window.nvda.speak_and_braille(str(round(val, 1)))
|
||||||
else:
|
else:
|
||||||
self.window.vm.event.pdirty = True
|
self.window.vm.event.pdirty = True
|
||||||
|
|
||||||
@@ -576,7 +578,7 @@ class Popup:
|
|||||||
else:
|
else:
|
||||||
self.window.vm.strip[index].comp.gainout = 0
|
self.window.vm.strip[index].comp.gainout = 0
|
||||||
self.popup[f'COMPRESSOR||SLIDER {direction} GAIN'].update(value=0)
|
self.popup[f'COMPRESSOR||SLIDER {direction} GAIN'].update(value=0)
|
||||||
self.window.nvda.speak(str(0))
|
self.window.nvda.speak_and_braille(str(0))
|
||||||
case [['COMPRESSOR'], ['SLIDER', param], ['KEY', 'CTRL', 'SHIFT', 'R']]:
|
case [['COMPRESSOR'], ['SLIDER', param], ['KEY', 'CTRL', 'SHIFT', 'R']]:
|
||||||
match param:
|
match param:
|
||||||
case 'RATIO':
|
case 'RATIO':
|
||||||
@@ -591,19 +593,19 @@ class Popup:
|
|||||||
val = 0.5
|
val = 0.5
|
||||||
setattr(self.window.vm.strip[index].comp, param.lower(), val)
|
setattr(self.window.vm.strip[index].comp, param.lower(), val)
|
||||||
self.popup[f'COMPRESSOR||SLIDER {param}'].update(value=val)
|
self.popup[f'COMPRESSOR||SLIDER {param}'].update(value=val)
|
||||||
self.window.nvda.speak(str(round(val, 1)))
|
self.window.nvda.speak_and_braille(str(round(val, 1)))
|
||||||
|
|
||||||
case ['MAKEUP']:
|
case ['MAKEUP']:
|
||||||
val = not self.window.vm.strip[index].comp.makeup
|
val = not self.window.vm.strip[index].comp.makeup
|
||||||
self.window.vm.strip[index].comp.makeup = val
|
self.window.vm.strip[index].comp.makeup = val
|
||||||
self.window.nvda.speak('on' if val else 'off')
|
self.window.nvda.speak_and_braille('on' if val else 'off')
|
||||||
case [[button], ['FOCUS', 'IN']]:
|
case [[button], ['FOCUS', 'IN']]:
|
||||||
if button == 'MAKEUP':
|
if button == 'MAKEUP':
|
||||||
self.window.nvda.speak(
|
self.window.nvda.speak_and_braille(
|
||||||
f'{button} {"on" if self.window.vm.strip[index].comp.makeup else "off"}'
|
f'{button} {"on" if self.window.vm.strip[index].comp.makeup else "off"}'
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self.window.nvda.speak(button)
|
self.window.nvda.speak_and_braille(button)
|
||||||
case [_, ['KEY', 'ENTER']]:
|
case [_, ['KEY', 'ENTER']]:
|
||||||
self.popup.find_element_with_focus().click()
|
self.popup.find_element_with_focus().click()
|
||||||
self.logger.debug(f'parsed::{parsed_cmd}')
|
self.logger.debug(f'parsed::{parsed_cmd}')
|
||||||
@@ -642,14 +644,16 @@ class Popup:
|
|||||||
f'<Shift-{event}-{direction}>', f'||KEY SHIFT {direction.upper()} {event_id}'
|
f'<Shift-{event}-{direction}>', f'||KEY SHIFT {direction.upper()} {event_id}'
|
||||||
)
|
)
|
||||||
self.popup[f'GATE||SLIDER {param}'].bind(
|
self.popup[f'GATE||SLIDER {param}'].bind(
|
||||||
f'<Control-{event}-{direction}>', f'||KEY CTRL {direction.upper()} {event_id}'
|
f'<Control-{event}-{direction}>', f'||KEY CTRL {direction.upper()} {event_id}', propagate=False
|
||||||
)
|
)
|
||||||
if param in ('BPSIDECHAIN', 'ATTACK', 'HOLD', 'RELEASE'):
|
if param in ('BPSIDECHAIN', 'ATTACK', 'HOLD', 'RELEASE'):
|
||||||
self.popup[f'GATE||SLIDER {param}'].bind(
|
self.popup[f'GATE||SLIDER {param}'].bind(
|
||||||
f'<Alt-{event}-{direction}>', f'||KEY ALT {direction.upper()} {event_id}'
|
f'<Alt-{event}-{direction}>', f'||KEY ALT {direction.upper()} {event_id}'
|
||||||
)
|
)
|
||||||
self.popup[f'GATE||SLIDER {param}'].bind(
|
self.popup[f'GATE||SLIDER {param}'].bind(
|
||||||
f'<Control-Alt-{event}-{direction}>', f'||KEY CTRL ALT {direction.upper()} {event_id}'
|
f'<Control-Alt-{event}-{direction}>',
|
||||||
|
f'||KEY CTRL ALT {direction.upper()} {event_id}',
|
||||||
|
propagate=False,
|
||||||
)
|
)
|
||||||
self.popup[f'GATE||SLIDER {param}'].bind('<Control-Shift-KeyPress-R>', '||KEY CTRL SHIFT R')
|
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('<FocusIn>', '||FOCUS IN')
|
||||||
@@ -661,7 +665,7 @@ class Popup:
|
|||||||
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
|
||||||
match parsed_cmd := self.window.parser.match.parseString(event):
|
match parsed_cmd := self.window.parser.match.parse_string(event):
|
||||||
case [['GATE'], ['SLIDER', param]]:
|
case [['GATE'], ['SLIDER', param]]:
|
||||||
setattr(self.window.vm.strip[index].gate, param.lower(), values[event])
|
setattr(self.window.vm.strip[index].gate, param.lower(), values[event])
|
||||||
case [['GATE'], ['SLIDER', param], ['FOCUS', 'IN']]:
|
case [['GATE'], ['SLIDER', param], ['FOCUS', 'IN']]:
|
||||||
@@ -669,7 +673,9 @@ class Popup:
|
|||||||
'DAMPING': 'Damping Max',
|
'DAMPING': 'Damping Max',
|
||||||
'BPSIDECHAIN': 'BP Sidechain',
|
'BPSIDECHAIN': 'BP Sidechain',
|
||||||
}
|
}
|
||||||
self.window.nvda.speak(f'{label_map.get(param, param)} {values[f"GATE||SLIDER {param}"]}')
|
self.window.nvda.speak_and_braille(
|
||||||
|
f'{label_map.get(param, param)} {values[f"GATE||SLIDER {param}"]}'
|
||||||
|
)
|
||||||
|
|
||||||
case [
|
case [
|
||||||
['GATE'],
|
['GATE'],
|
||||||
@@ -691,9 +697,9 @@ class Popup:
|
|||||||
setattr(self.window.vm.strip[index].gate, param.lower(), val)
|
setattr(self.window.vm.strip[index].gate, param.lower(), val)
|
||||||
self.popup[f'GATE||SLIDER {param}'].update(value=val)
|
self.popup[f'GATE||SLIDER {param}'].update(value=val)
|
||||||
if param == 'BPSIDECHAIN':
|
if param == 'BPSIDECHAIN':
|
||||||
self.window.nvda.speak(str(int(val)))
|
self.window.nvda.speak_and_braille(str(int(val)))
|
||||||
else:
|
else:
|
||||||
self.window.nvda.speak(str(round(val, 1)))
|
self.window.nvda.speak_and_braille(str(round(val, 1)))
|
||||||
else:
|
else:
|
||||||
self.window.vm.event.pdirty = True
|
self.window.vm.event.pdirty = True
|
||||||
case [
|
case [
|
||||||
@@ -716,9 +722,9 @@ class Popup:
|
|||||||
setattr(self.window.vm.strip[index].gate, param.lower(), val)
|
setattr(self.window.vm.strip[index].gate, param.lower(), val)
|
||||||
self.popup[f'GATE||SLIDER {param}'].update(value=val)
|
self.popup[f'GATE||SLIDER {param}'].update(value=val)
|
||||||
if param == 'BPSIDECHAIN':
|
if param == 'BPSIDECHAIN':
|
||||||
self.window.nvda.speak(str(int(val)))
|
self.window.nvda.speak_and_braille(str(int(val)))
|
||||||
else:
|
else:
|
||||||
self.window.nvda.speak(str(round(val, 1)))
|
self.window.nvda.speak_and_braille(str(round(val, 1)))
|
||||||
else:
|
else:
|
||||||
self.window.vm.event.pdirty = True
|
self.window.vm.event.pdirty = True
|
||||||
case [
|
case [
|
||||||
@@ -741,9 +747,9 @@ class Popup:
|
|||||||
setattr(self.window.vm.strip[index].gate, param.lower(), val)
|
setattr(self.window.vm.strip[index].gate, param.lower(), val)
|
||||||
self.popup[f'GATE||SLIDER {param}'].update(value=val)
|
self.popup[f'GATE||SLIDER {param}'].update(value=val)
|
||||||
if param == 'BPSIDECHAIN':
|
if param == 'BPSIDECHAIN':
|
||||||
self.window.nvda.speak(str(int(val)))
|
self.window.nvda.speak_and_braille(str(int(val)))
|
||||||
else:
|
else:
|
||||||
self.window.nvda.speak(str(round(val, 1)))
|
self.window.nvda.speak_and_braille(str(round(val, 1)))
|
||||||
else:
|
else:
|
||||||
self.window.vm.event.pdirty = True
|
self.window.vm.event.pdirty = True
|
||||||
case [
|
case [
|
||||||
@@ -765,9 +771,9 @@ class Popup:
|
|||||||
setattr(self.window.vm.strip[index].gate, param.lower(), val)
|
setattr(self.window.vm.strip[index].gate, param.lower(), val)
|
||||||
self.popup[f'GATE||SLIDER {param}'].update(value=val)
|
self.popup[f'GATE||SLIDER {param}'].update(value=val)
|
||||||
if param == 'BPSIDECHAIN':
|
if param == 'BPSIDECHAIN':
|
||||||
self.window.nvda.speak(str(int(val)))
|
self.window.nvda.speak_and_braille(str(int(val)))
|
||||||
else:
|
else:
|
||||||
self.window.nvda.speak(str(round(val, 1)))
|
self.window.nvda.speak_and_braille(str(round(val, 1)))
|
||||||
else:
|
else:
|
||||||
self.window.vm.event.pdirty = True
|
self.window.vm.event.pdirty = True
|
||||||
case [
|
case [
|
||||||
@@ -789,9 +795,9 @@ class Popup:
|
|||||||
setattr(self.window.vm.strip[index].gate, param.lower(), val)
|
setattr(self.window.vm.strip[index].gate, param.lower(), val)
|
||||||
self.popup[f'GATE||SLIDER {param}'].update(value=val)
|
self.popup[f'GATE||SLIDER {param}'].update(value=val)
|
||||||
if param == 'BPSIDECHAIN':
|
if param == 'BPSIDECHAIN':
|
||||||
self.window.nvda.speak(str(int(val)))
|
self.window.nvda.speak_and_braille(str(int(val)))
|
||||||
else:
|
else:
|
||||||
self.window.nvda.speak(str(round(val, 1)))
|
self.window.nvda.speak_and_braille(str(round(val, 1)))
|
||||||
else:
|
else:
|
||||||
self.window.vm.event.pdirty = True
|
self.window.vm.event.pdirty = True
|
||||||
case [['GATE'], ['SLIDER', param], ['KEY', 'CTRL', 'SHIFT', 'R']]:
|
case [['GATE'], ['SLIDER', param], ['KEY', 'CTRL', 'SHIFT', 'R']]:
|
||||||
@@ -810,10 +816,10 @@ class Popup:
|
|||||||
val = 1000
|
val = 1000
|
||||||
setattr(self.window.vm.strip[index].gate, param.lower(), val)
|
setattr(self.window.vm.strip[index].gate, param.lower(), val)
|
||||||
self.popup[f'GATE||SLIDER {param}'].update(value=val)
|
self.popup[f'GATE||SLIDER {param}'].update(value=val)
|
||||||
self.window.nvda.speak(str(round(val, 1)))
|
self.window.nvda.speak_and_braille(str(round(val, 1)))
|
||||||
|
|
||||||
case [[button], ['FOCUS', 'IN']]:
|
case [[button], ['FOCUS', 'IN']]:
|
||||||
self.window.nvda.speak(button)
|
self.window.nvda.speak_and_braille(button)
|
||||||
case [_, ['KEY', 'ENTER']]:
|
case [_, ['KEY', 'ENTER']]:
|
||||||
self.popup.find_element_with_focus().click()
|
self.popup.find_element_with_focus().click()
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import FreeSimpleGUI as psg
|
|||||||
|
|
||||||
from . import configuration, models, util
|
from . import configuration, models, util
|
||||||
from .builder import Builder
|
from .builder import Builder
|
||||||
|
from .errors import NVDAVMError
|
||||||
from .nvda import Nvda
|
from .nvda import Nvda
|
||||||
from .parser import Parser
|
from .parser import Parser
|
||||||
from .popup import Popup
|
from .popup import Popup
|
||||||
@@ -25,6 +26,10 @@ class NVDAVMWindow(psg.Window):
|
|||||||
self.kind = self.vm.kind
|
self.kind = self.vm.kind
|
||||||
self.logger = logger.getChild(type(self).__name__)
|
self.logger = logger.getChild(type(self).__name__)
|
||||||
self.logger.debug(f'loaded with theme: {psg.theme()}')
|
self.logger.debug(f'loaded with theme: {psg.theme()}')
|
||||||
|
self.nvda = Nvda()
|
||||||
|
if not self.nvda.is_running:
|
||||||
|
self.logger.error('NVDA is not running. Exiting...')
|
||||||
|
raise NVDAVMError('NVDA is not running')
|
||||||
self.cache = {
|
self.cache = {
|
||||||
'hw_ins': models._make_hardware_ins_cache(self.vm),
|
'hw_ins': models._make_hardware_ins_cache(self.vm),
|
||||||
'hw_outs': models._make_hardware_outs_cache(self.vm),
|
'hw_outs': models._make_hardware_outs_cache(self.vm),
|
||||||
@@ -34,7 +39,6 @@ class NVDAVMWindow(psg.Window):
|
|||||||
'asio': models._make_patch_asio_cache(self.vm),
|
'asio': models._make_patch_asio_cache(self.vm),
|
||||||
'insert': models._make_patch_insert_cache(self.vm),
|
'insert': models._make_patch_insert_cache(self.vm),
|
||||||
}
|
}
|
||||||
self.nvda = Nvda()
|
|
||||||
self.parser = Parser()
|
self.parser = Parser()
|
||||||
self.popup = Popup(self)
|
self.popup = Popup(self)
|
||||||
self.builder = Builder(self)
|
self.builder = Builder(self)
|
||||||
@@ -74,7 +78,7 @@ class NVDAVMWindow(psg.Window):
|
|||||||
self.logger.debug(f'config {defaultconfig} loaded')
|
self.logger.debug(f'config {defaultconfig} loaded')
|
||||||
self.TKroot.after(
|
self.TKroot.after(
|
||||||
200,
|
200,
|
||||||
self.nvda.speak,
|
self.nvda.speak_and_braille,
|
||||||
f'config {defaultconfig.stem} has been loaded',
|
f'config {defaultconfig.stem} has been loaded',
|
||||||
)
|
)
|
||||||
except json.JSONDecodeError:
|
except json.JSONDecodeError:
|
||||||
@@ -247,7 +251,9 @@ class NVDAVMWindow(psg.Window):
|
|||||||
f'<Shift-{event}-{direction}>', f'||KEY SHIFT {direction.upper()} {event_id}'
|
f'<Shift-{event}-{direction}>', f'||KEY SHIFT {direction.upper()} {event_id}'
|
||||||
)
|
)
|
||||||
self[f'STRIP {i}||SLIDER {param}'].bind(
|
self[f'STRIP {i}||SLIDER {param}'].bind(
|
||||||
f'<Control-{event}-{direction}>', f'||KEY CTRL {direction.upper()} {event_id}'
|
f'<Control-{event}-{direction}>',
|
||||||
|
f'||KEY CTRL {direction.upper()} {event_id}',
|
||||||
|
propagate=False,
|
||||||
)
|
)
|
||||||
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')
|
||||||
|
|
||||||
@@ -280,7 +286,7 @@ class NVDAVMWindow(psg.Window):
|
|||||||
f'<Shift-{event}-{direction}>', f'||KEY SHIFT {direction.upper()} {event_id}'
|
f'<Shift-{event}-{direction}>', f'||KEY SHIFT {direction.upper()} {event_id}'
|
||||||
)
|
)
|
||||||
self[f'BUS {i}||SLIDER GAIN'].bind(
|
self[f'BUS {i}||SLIDER GAIN'].bind(
|
||||||
f'<Control-{event}-{direction}>', f'||KEY CTRL {direction.upper()} {event_id}'
|
f'<Control-{event}-{direction}>', f'||KEY CTRL {direction.upper()} {event_id}', propagate=False
|
||||||
)
|
)
|
||||||
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')
|
||||||
|
|
||||||
@@ -300,12 +306,12 @@ class NVDAVMWindow(psg.Window):
|
|||||||
break
|
break
|
||||||
elif event in util.get_slider_modes():
|
elif event in util.get_slider_modes():
|
||||||
mode = event
|
mode = event
|
||||||
self.nvda.speak(f'{mode} enabled')
|
self.nvda.speak_and_braille(f'{mode} enabled')
|
||||||
self.logger.debug(f'entered slider mode {mode}')
|
self.logger.debug(f'entered slider mode {mode}')
|
||||||
continue
|
continue
|
||||||
elif event == 'ESCAPE':
|
elif event == 'ESCAPE':
|
||||||
if mode:
|
if mode:
|
||||||
self.nvda.speak(f'{mode} disabled')
|
self.nvda.speak_and_braille(f'{mode} disabled')
|
||||||
self.logger.debug(f'exited from slider mode {mode}')
|
self.logger.debug(f'exited from slider mode {mode}')
|
||||||
mode = None
|
mode = None
|
||||||
continue
|
continue
|
||||||
@@ -325,7 +331,7 @@ class NVDAVMWindow(psg.Window):
|
|||||||
# Focus tabgroup
|
# Focus tabgroup
|
||||||
case ['CTRL-TAB'] | ['CTRL-SHIFT-TAB']:
|
case ['CTRL-TAB'] | ['CTRL-SHIFT-TAB']:
|
||||||
self['tabgroup'].set_focus()
|
self['tabgroup'].set_focus()
|
||||||
self.nvda.speak(f'{values["tabgroup"]}')
|
self.nvda.speak_and_braille(f'{values["tabgroup"]}')
|
||||||
|
|
||||||
# Quick Navigation
|
# Quick Navigation
|
||||||
case ['CTRL-1' | 'CTRL-2' | 'CTRL-3' | 'CTRL-4' | 'CTRL-5' | 'CTRL-6' | 'CTRL-7' | 'CTRL-8' as bind]:
|
case ['CTRL-1' | 'CTRL-2' | 'CTRL-3' | 'CTRL-4' | 'CTRL-5' | 'CTRL-6' | 'CTRL-7' | 'CTRL-8' as bind]:
|
||||||
@@ -469,7 +475,7 @@ class NVDAVMWindow(psg.Window):
|
|||||||
case [['ENGINE', 'RESTART'], ['END']]:
|
case [['ENGINE', 'RESTART'], ['END']]:
|
||||||
self.TKroot.after(
|
self.TKroot.after(
|
||||||
200,
|
200,
|
||||||
self.nvda.speak,
|
self.nvda.speak_and_braille,
|
||||||
'Audio Engine restarted',
|
'Audio Engine restarted',
|
||||||
)
|
)
|
||||||
case [['Save', 'Settings'], ['MENU']]:
|
case [['Save', 'Settings'], ['MENU']]:
|
||||||
@@ -481,7 +487,7 @@ class NVDAVMWindow(psg.Window):
|
|||||||
self.logger.debug(f'saving config file to {filepath}')
|
self.logger.debug(f'saving config file to {filepath}')
|
||||||
self.TKroot.after(
|
self.TKroot.after(
|
||||||
200,
|
200,
|
||||||
self.nvda.speak,
|
self.nvda.speak_and_braille,
|
||||||
f'config file {filepath.stem} has been saved',
|
f'config file {filepath.stem} has been saved',
|
||||||
)
|
)
|
||||||
case [['Load', 'Settings'], ['MENU']]:
|
case [['Load', 'Settings'], ['MENU']]:
|
||||||
@@ -500,7 +506,7 @@ class NVDAVMWindow(psg.Window):
|
|||||||
self.TKroot.after(i, self.on_pdirty)
|
self.TKroot.after(i, self.on_pdirty)
|
||||||
self.TKroot.after(
|
self.TKroot.after(
|
||||||
200,
|
200,
|
||||||
self.nvda.speak,
|
self.nvda.speak_and_braille,
|
||||||
f'config file {filepath.stem} has been loaded',
|
f'config file {filepath.stem} has been loaded',
|
||||||
)
|
)
|
||||||
case [['Load', 'Settings', 'on', 'Startup'], ['MENU']]:
|
case [['Load', 'Settings', 'on', 'Startup'], ['MENU']]:
|
||||||
@@ -516,7 +522,7 @@ class NVDAVMWindow(psg.Window):
|
|||||||
configuration.set('default_config', str(filepath))
|
configuration.set('default_config', str(filepath))
|
||||||
self.TKroot.after(
|
self.TKroot.after(
|
||||||
200,
|
200,
|
||||||
self.nvda.speak,
|
self.nvda.speak_and_braille,
|
||||||
f'config {filepath.stem} set as default on startup',
|
f'config {filepath.stem} set as default on startup',
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
@@ -530,7 +536,7 @@ class NVDAVMWindow(psg.Window):
|
|||||||
configuration.set('default_theme', chosen)
|
configuration.set('default_theme', chosen)
|
||||||
self.TKroot.after(
|
self.TKroot.after(
|
||||||
200,
|
200,
|
||||||
self.nvda.speak,
|
self.nvda.speak_and_braille,
|
||||||
f'theme {chosen} selected.',
|
f'theme {chosen} selected.',
|
||||||
)
|
)
|
||||||
self.logger.debug(f'theme {chosen} selected')
|
self.logger.debug(f'theme {chosen} selected')
|
||||||
@@ -538,13 +544,13 @@ class NVDAVMWindow(psg.Window):
|
|||||||
# Tabs
|
# Tabs
|
||||||
case ['tabgroup'] | [['tabgroup'], ['FOCUS', 'IN']]:
|
case ['tabgroup'] | [['tabgroup'], ['FOCUS', 'IN']]:
|
||||||
if self.find_element_with_focus() is None:
|
if self.find_element_with_focus() is None:
|
||||||
self.nvda.speak(f'{values["tabgroup"]}')
|
self.nvda.speak_and_braille(f'{values["tabgroup"]}')
|
||||||
case [['tabgroup'], tabname] | [['tabgroup'], tabname, ['FOCUS', 'IN']]:
|
case [['tabgroup'], tabname] | [['tabgroup'], tabname, ['FOCUS', 'IN']]:
|
||||||
if self.find_element_with_focus() is None:
|
if self.find_element_with_focus() is None:
|
||||||
name = ' '.join(tabname)
|
name = ' '.join(tabname)
|
||||||
self.nvda.speak(f'{values[f"tabgroup||{name}"]}')
|
self.nvda.speak_and_braille(f'{values[f"tabgroup||{name}"]}')
|
||||||
case [['tabgroup'], _, ['KEY', 'SHIFT', 'TAB']]:
|
case [['tabgroup'], _, ['KEY', 'SHIFT', 'TAB']]:
|
||||||
self.nvda.speak(values['tabgroup'])
|
self.nvda.speak_and_braille(values['tabgroup'])
|
||||||
|
|
||||||
# Hardware In
|
# Hardware In
|
||||||
case [['HARDWARE', 'IN'], [key]]:
|
case [['HARDWARE', 'IN'], [key]]:
|
||||||
@@ -553,18 +559,22 @@ class NVDAVMWindow(psg.Window):
|
|||||||
match selection.split(':'):
|
match selection.split(':'):
|
||||||
case [device_name]:
|
case [device_name]:
|
||||||
setattr(self.vm.strip[index].device, 'wdm', '')
|
setattr(self.vm.strip[index].device, 'wdm', '')
|
||||||
self.TKroot.after(200, self.nvda.speak, f'HARDWARE IN {key} device selection removed')
|
self.TKroot.after(
|
||||||
|
200, self.nvda.speak_and_braille, f'HARDWARE IN {key} device selection removed'
|
||||||
|
)
|
||||||
case [driver, device_name]:
|
case [driver, device_name]:
|
||||||
setattr(self.vm.strip[index].device, driver, device_name.lstrip())
|
setattr(self.vm.strip[index].device, driver, device_name.lstrip())
|
||||||
phonetic = {'mme': 'em em e'}
|
phonetic = {'mme': 'em em e'}
|
||||||
self.TKroot.after(
|
self.TKroot.after(
|
||||||
200,
|
200,
|
||||||
self.nvda.speak,
|
self.nvda.speak_and_braille,
|
||||||
f'HARDWARE IN {key} set {phonetic.get(driver, driver)} {device_name}',
|
f'HARDWARE IN {key} set {phonetic.get(driver, driver)} {device_name}',
|
||||||
)
|
)
|
||||||
case [['HARDWARE', 'IN'], [key], ['FOCUS', 'IN']]:
|
case [['HARDWARE', 'IN'], [key], ['FOCUS', 'IN']]:
|
||||||
if self.find_element_with_focus() is not None:
|
if self.find_element_with_focus() is not None:
|
||||||
self.nvda.speak(f'HARDWARE INPUT {key} {self.cache["hw_ins"][f"HARDWARE IN||{key}"]}')
|
self.nvda.speak_and_braille(
|
||||||
|
f'HARDWARE INPUT {key} {self.cache["hw_ins"][f"HARDWARE IN||{key}"]}'
|
||||||
|
)
|
||||||
case [['HARDWARE', 'IN'], [key], ['KEY', 'SPACE' | 'ENTER']]:
|
case [['HARDWARE', 'IN'], [key], ['KEY', 'SPACE' | 'ENTER']]:
|
||||||
util.open_context_menu_for_buttonmenu(self, f'HARDWARE IN||{key}')
|
util.open_context_menu_for_buttonmenu(self, f'HARDWARE IN||{key}')
|
||||||
|
|
||||||
@@ -575,18 +585,22 @@ class NVDAVMWindow(psg.Window):
|
|||||||
match selection.split(':'):
|
match selection.split(':'):
|
||||||
case [device_name]:
|
case [device_name]:
|
||||||
setattr(self.vm.bus[index].device, 'wdm', '')
|
setattr(self.vm.bus[index].device, 'wdm', '')
|
||||||
self.TKroot.after(200, self.nvda.speak, f'HARDWARE OUT {key} device selection removed')
|
self.TKroot.after(
|
||||||
|
200, self.nvda.speak_and_braille, f'HARDWARE OUT {key} device selection removed'
|
||||||
|
)
|
||||||
case [driver, device_name]:
|
case [driver, device_name]:
|
||||||
setattr(self.vm.bus[index].device, driver, device_name.lstrip())
|
setattr(self.vm.bus[index].device, driver, device_name.lstrip())
|
||||||
phonetic = {'mme': 'em em e'}
|
phonetic = {'mme': 'em em e'}
|
||||||
self.TKroot.after(
|
self.TKroot.after(
|
||||||
200,
|
200,
|
||||||
self.nvda.speak,
|
self.nvda.speak_and_braille,
|
||||||
f'HARDWARE OUT {key} set {phonetic.get(driver, driver)} {device_name}',
|
f'HARDWARE OUT {key} set {phonetic.get(driver, driver)} {device_name}',
|
||||||
)
|
)
|
||||||
case [['HARDWARE', 'OUT'], [key], ['FOCUS', 'IN']]:
|
case [['HARDWARE', 'OUT'], [key], ['FOCUS', 'IN']]:
|
||||||
if self.find_element_with_focus() is not None:
|
if self.find_element_with_focus() is not None:
|
||||||
self.nvda.speak(f'HARDWARE OUT {key} {self.cache["hw_outs"][f"HARDWARE OUT||{key}"]}')
|
self.nvda.speak_and_braille(
|
||||||
|
f'HARDWARE OUT {key} {self.cache["hw_outs"][f"HARDWARE OUT||{key}"]}'
|
||||||
|
)
|
||||||
case [['HARDWARE', 'OUT'], [key], ['KEY', 'SPACE' | 'ENTER']]:
|
case [['HARDWARE', 'OUT'], [key], ['KEY', 'SPACE' | 'ENTER']]:
|
||||||
util.open_context_menu_for_buttonmenu(self, f'HARDWARE OUT||{key}')
|
util.open_context_menu_for_buttonmenu(self, f'HARDWARE OUT||{key}')
|
||||||
|
|
||||||
@@ -595,7 +609,7 @@ class NVDAVMWindow(psg.Window):
|
|||||||
val = values[f'PATCH COMPOSITE||{key}']
|
val = values[f'PATCH COMPOSITE||{key}']
|
||||||
index = int(key[-1]) - 1
|
index = int(key[-1]) - 1
|
||||||
self.vm.patch.composite[index].set(util.get_patch_composite_list(self.kind).index(val) + 1)
|
self.vm.patch.composite[index].set(util.get_patch_composite_list(self.kind).index(val) + 1)
|
||||||
self.TKroot.after(200, self.nvda.speak, val)
|
self.TKroot.after(200, self.nvda.speak_and_braille, val)
|
||||||
case [['PATCH', 'COMPOSITE'], [key], ['FOCUS', 'IN']]:
|
case [['PATCH', 'COMPOSITE'], [key], ['FOCUS', 'IN']]:
|
||||||
if self.find_element_with_focus() is not None:
|
if self.find_element_with_focus() is not None:
|
||||||
if values[f'PATCH COMPOSITE||{key}']:
|
if values[f'PATCH COMPOSITE||{key}']:
|
||||||
@@ -609,7 +623,7 @@ class NVDAVMWindow(psg.Window):
|
|||||||
except IndexError as e:
|
except IndexError as e:
|
||||||
val = comp_list[-1]
|
val = comp_list[-1]
|
||||||
self.logger.error(f'{type(e).__name__}: {e}')
|
self.logger.error(f'{type(e).__name__}: {e}')
|
||||||
self.nvda.speak(f'Patch COMPOSITE {key[-1]} {val}')
|
self.nvda.speak_and_braille(f'Patch COMPOSITE {key[-1]} {val}')
|
||||||
case [['PATCH', 'COMPOSITE'], [key], ['KEY', 'SPACE' | 'ENTER']]:
|
case [['PATCH', 'COMPOSITE'], [key], ['KEY', 'SPACE' | 'ENTER']]:
|
||||||
util.open_context_menu_for_buttonmenu(self, f'PATCH COMPOSITE||{key}')
|
util.open_context_menu_for_buttonmenu(self, f'PATCH COMPOSITE||{key}')
|
||||||
|
|
||||||
@@ -622,7 +636,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('on' if val else 'off')
|
self.nvda.speak_and_braille('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(
|
||||||
@@ -633,7 +647,7 @@ class NVDAVMWindow(psg.Window):
|
|||||||
val = values[f'INSERT CHECKBOX||{in_num} {channel}']
|
val = values[f'INSERT CHECKBOX||{in_num} {channel}']
|
||||||
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_and_braille(f'Patch INSERT IN#{num} {channel} {"on" if val else "off"}')
|
||||||
case [['INSERT', 'CHECKBOX'], [in_num, channel], ['KEY', 'ENTER']]:
|
case [['INSERT', 'CHECKBOX'], [in_num, channel], ['KEY', 'ENTER']]:
|
||||||
val = not values[f'INSERT CHECKBOX||{in_num} {channel}']
|
val = not values[f'INSERT CHECKBOX||{in_num} {channel}']
|
||||||
self.write_event_value(f'INSERT CHECKBOX||{in_num} {channel}', val)
|
self.write_event_value(f'INSERT CHECKBOX||{in_num} {channel}', val)
|
||||||
@@ -643,7 +657,7 @@ class NVDAVMWindow(psg.Window):
|
|||||||
if values['tabgroup'] == 'tab||Settings':
|
if values['tabgroup'] == 'tab||Settings':
|
||||||
self.popup.advanced_settings(title='Advanced Settings')
|
self.popup.advanced_settings(title='Advanced Settings')
|
||||||
case [['ADVANCED', 'SETTINGS'], ['FOCUS', 'IN']]:
|
case [['ADVANCED', 'SETTINGS'], ['FOCUS', 'IN']]:
|
||||||
self.nvda.speak('ADVANCED SETTINGS')
|
self.nvda.speak_and_braille('ADVANCED SETTINGS')
|
||||||
case [['ADVANCED', 'SETTINGS'], ['KEY', 'ENTER']]:
|
case [['ADVANCED', 'SETTINGS'], ['KEY', 'ENTER']]:
|
||||||
self.find_element_with_focus().click()
|
self.find_element_with_focus().click()
|
||||||
|
|
||||||
@@ -657,28 +671,30 @@ class NVDAVMWindow(psg.Window):
|
|||||||
next_val = 0
|
next_val = 0
|
||||||
self.vm.strip[int(index)].k = next_val
|
self.vm.strip[int(index)].k = next_val
|
||||||
self.cache['strip'][f'STRIP {index}||{param}'] = next_val
|
self.cache['strip'][f'STRIP {index}||{param}'] = next_val
|
||||||
self.nvda.speak(opts[next_val])
|
self.nvda.speak_and_braille(opts[next_val])
|
||||||
case output if param in util._get_bus_assignments(self.kind):
|
case output if param in util._get_bus_assignments(self.kind):
|
||||||
val = not self.cache['strip'][f'STRIP {index}||{output}']
|
val = not self.cache['strip'][f'STRIP {index}||{output}']
|
||||||
setattr(self.vm.strip[int(index)], output, val)
|
setattr(self.vm.strip[int(index)], output, val)
|
||||||
self.cache['strip'][f'STRIP {index}||{output}'] = val
|
self.cache['strip'][f'STRIP {index}||{output}'] = val
|
||||||
self.nvda.speak('on' if val else 'off')
|
self.nvda.speak_and_braille('on' if val else 'off')
|
||||||
case _:
|
case _:
|
||||||
val = not self.cache['strip'][f'STRIP {index}||{param}']
|
val = not self.cache['strip'][f'STRIP {index}||{param}']
|
||||||
setattr(self.vm.strip[int(index)], param.lower(), val)
|
setattr(self.vm.strip[int(index)], param.lower(), val)
|
||||||
self.cache['strip'][f'STRIP {index}||{param}'] = val
|
self.cache['strip'][f'STRIP {index}||{param}'] = val
|
||||||
self.nvda.speak('on' if val else 'off')
|
self.nvda.speak_and_braille('on' if val else 'off')
|
||||||
case [['STRIP', index], [param], ['FOCUS', 'IN']]:
|
case [['STRIP', index], [param], ['FOCUS', 'IN']]:
|
||||||
if self.find_element_with_focus() is not None:
|
if self.find_element_with_focus() is not None:
|
||||||
val = self.cache['strip'][f'STRIP {index}||{param}']
|
val = self.cache['strip'][f'STRIP {index}||{param}']
|
||||||
phonetic = {'KARAOKE': 'karaoke'}
|
phonetic = {'KARAOKE': 'karaoke'}
|
||||||
label = self.cache['labels'][f'STRIP {index}||LABEL']
|
label = self.cache['labels'][f'STRIP {index}||LABEL']
|
||||||
if param == 'KARAOKE':
|
if param == 'KARAOKE':
|
||||||
self.nvda.speak(
|
self.nvda.speak_and_braille(
|
||||||
f'{label} {phonetic.get(param, param)} {["off", "k m", "k 1", "k 2", "k v"][self.cache["strip"][f"STRIP {int(index)}||{param}"]]}'
|
f'{label} {phonetic.get(param, param)} {["off", "k m", "k 1", "k 2", "k v"][self.cache["strip"][f"STRIP {int(index)}||{param}"]]}'
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self.nvda.speak(f'{label} {phonetic.get(param, param)} {"on" if val else "off"}')
|
self.nvda.speak_and_braille(
|
||||||
|
f'{label} {phonetic.get(param, param)} {"on" if val else "off"}'
|
||||||
|
)
|
||||||
case [['STRIP', index], [param], ['KEY', 'ENTER']]:
|
case [['STRIP', index], [param], ['KEY', 'ENTER']]:
|
||||||
self.find_element_with_focus().click()
|
self.find_element_with_focus().click()
|
||||||
|
|
||||||
@@ -731,7 +747,7 @@ class NVDAVMWindow(psg.Window):
|
|||||||
if self.find_element_with_focus() is not None:
|
if self.find_element_with_focus() is not None:
|
||||||
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_and_braille(f'{label} {param} {int(val) if param == "LIMIT" else val}')
|
||||||
case [
|
case [
|
||||||
['STRIP', index],
|
['STRIP', index],
|
||||||
[
|
[
|
||||||
@@ -799,7 +815,7 @@ class NVDAVMWindow(psg.Window):
|
|||||||
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(str(round(val, 1)))
|
self.nvda.speak_and_braille(str(round(val, 1)))
|
||||||
else:
|
else:
|
||||||
self.vm.event.pdirty = True
|
self.vm.event.pdirty = True
|
||||||
case [
|
case [
|
||||||
@@ -867,9 +883,9 @@ class NVDAVMWindow(psg.Window):
|
|||||||
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)
|
||||||
if param == 'LIMIT':
|
if param == 'LIMIT':
|
||||||
self.nvda.speak(str(int(val)))
|
self.nvda.speak_and_braille(str(int(val)))
|
||||||
else:
|
else:
|
||||||
self.nvda.speak(str(round(val, 1)))
|
self.nvda.speak_and_braille(str(round(val, 1)))
|
||||||
else:
|
else:
|
||||||
self.vm.event.pdirty = True
|
self.vm.event.pdirty = True
|
||||||
case [
|
case [
|
||||||
@@ -937,9 +953,9 @@ class NVDAVMWindow(psg.Window):
|
|||||||
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)
|
||||||
if param == 'LIMIT':
|
if param == 'LIMIT':
|
||||||
self.nvda.speak(str(int(val)))
|
self.nvda.speak_and_braille(str(int(val)))
|
||||||
else:
|
else:
|
||||||
self.nvda.speak(str(round(val, 1)))
|
self.nvda.speak_and_braille(str(round(val, 1)))
|
||||||
else:
|
else:
|
||||||
self.vm.event.pdirty = True
|
self.vm.event.pdirty = True
|
||||||
case [['STRIP', index], ['SLIDER', param], ['KEY', 'CTRL', 'SHIFT', 'R']]:
|
case [['STRIP', index], ['SLIDER', param], ['KEY', 'CTRL', 'SHIFT', 'R']]:
|
||||||
@@ -960,7 +976,7 @@ class NVDAVMWindow(psg.Window):
|
|||||||
case 'LIMIT':
|
case 'LIMIT':
|
||||||
self.vm.strip[int(index)].limit = 12
|
self.vm.strip[int(index)].limit = 12
|
||||||
self[f'STRIP {index}||SLIDER {param}'].update(value=12)
|
self[f'STRIP {index}||SLIDER {param}'].update(value=12)
|
||||||
self.nvda.speak(f'{12 if param == "LIMIT" else 0}')
|
self.nvda.speak_and_braille(f'{12 if param == "LIMIT" else 0}')
|
||||||
|
|
||||||
# Bus Params
|
# Bus Params
|
||||||
case [['BUS', index], [param]]:
|
case [['BUS', index], [param]]:
|
||||||
@@ -973,7 +989,7 @@ class NVDAVMWindow(psg.Window):
|
|||||||
self.cache['bus'][event] = val
|
self.cache['bus'][event] = val
|
||||||
self.TKroot.after(
|
self.TKroot.after(
|
||||||
200,
|
200,
|
||||||
self.nvda.speak,
|
self.nvda.speak_and_braille,
|
||||||
'on' if val else 'off',
|
'on' if val else 'off',
|
||||||
)
|
)
|
||||||
case 'MUTE':
|
case 'MUTE':
|
||||||
@@ -982,7 +998,7 @@ class NVDAVMWindow(psg.Window):
|
|||||||
self.cache['bus'][event] = val
|
self.cache['bus'][event] = val
|
||||||
self.TKroot.after(
|
self.TKroot.after(
|
||||||
200,
|
200,
|
||||||
self.nvda.speak,
|
self.nvda.speak_and_braille,
|
||||||
'on' if val else 'off',
|
'on' if val else 'off',
|
||||||
)
|
)
|
||||||
case 'MONO':
|
case 'MONO':
|
||||||
@@ -991,7 +1007,7 @@ class NVDAVMWindow(psg.Window):
|
|||||||
self.cache['bus'][event] = chosen
|
self.cache['bus'][event] = chosen
|
||||||
self.TKroot.after(
|
self.TKroot.after(
|
||||||
200,
|
200,
|
||||||
self.nvda.speak,
|
self.nvda.speak_and_braille,
|
||||||
f'mono {chosen}',
|
f'mono {chosen}',
|
||||||
)
|
)
|
||||||
case 'MODE':
|
case 'MODE':
|
||||||
@@ -1000,7 +1016,7 @@ class NVDAVMWindow(psg.Window):
|
|||||||
self.cache['bus'][event] = chosen
|
self.cache['bus'][event] = chosen
|
||||||
self.TKroot.after(
|
self.TKroot.after(
|
||||||
200,
|
200,
|
||||||
self.nvda.speak,
|
self.nvda.speak_and_braille,
|
||||||
util._bus_mode_map[chosen],
|
util._bus_mode_map[chosen],
|
||||||
)
|
)
|
||||||
case [['BUS', index], [param], ['FOCUS', 'IN']]:
|
case [['BUS', index], [param], ['FOCUS', 'IN']]:
|
||||||
@@ -1008,15 +1024,15 @@ class NVDAVMWindow(psg.Window):
|
|||||||
label = self.cache['labels'][f'BUS {index}||LABEL']
|
label = self.cache['labels'][f'BUS {index}||LABEL']
|
||||||
val = self.cache['bus'][f'BUS {index}||{param}']
|
val = self.cache['bus'][f'BUS {index}||{param}']
|
||||||
if param == 'MODE':
|
if param == 'MODE':
|
||||||
self.nvda.speak(f'{label} bus {param} {util._bus_mode_map[val]}')
|
self.nvda.speak_and_braille(f'{label} bus {param} {util._bus_mode_map[val]}')
|
||||||
elif param == 'MONO':
|
elif param == 'MONO':
|
||||||
busmode = util.get_bus_mono()[val]
|
busmode = util.get_bus_mono()[val]
|
||||||
if busmode in ('on', 'off'):
|
if busmode in ('on', 'off'):
|
||||||
self.nvda.speak(f'{label} {param} {busmode}')
|
self.nvda.speak_and_braille(f'{label} {param} {busmode}')
|
||||||
else:
|
else:
|
||||||
self.nvda.speak(f'{label} {busmode}')
|
self.nvda.speak_and_braille(f'{label} {busmode}')
|
||||||
else:
|
else:
|
||||||
self.nvda.speak(f'{label} {param} {"on" if val else "off"}')
|
self.nvda.speak_and_braille(f'{label} {param} {"on" if val else "off"}')
|
||||||
case [['BUS', index], [param], ['KEY', 'SPACE' | 'ENTER']]:
|
case [['BUS', index], [param], ['KEY', 'SPACE' | 'ENTER']]:
|
||||||
if param == 'MODE':
|
if param == 'MODE':
|
||||||
util.open_context_menu_for_buttonmenu(self, f'BUS {index}||MODE')
|
util.open_context_menu_for_buttonmenu(self, f'BUS {index}||MODE')
|
||||||
@@ -1034,7 +1050,7 @@ class NVDAVMWindow(psg.Window):
|
|||||||
if self.find_element_with_focus() is not None:
|
if self.find_element_with_focus() is not None:
|
||||||
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_and_braille(f'{label} gain {val}')
|
||||||
case [['BUS', index], ['SLIDER', 'GAIN'], ['FOCUS', 'OUT']]:
|
case [['BUS', index], ['SLIDER', 'GAIN'], ['FOCUS', 'OUT']]:
|
||||||
pass
|
pass
|
||||||
case [
|
case [
|
||||||
@@ -1053,7 +1069,7 @@ class NVDAVMWindow(psg.Window):
|
|||||||
val = util.check_bounds(val, (-60, 12))
|
val = util.check_bounds(val, (-60, 12))
|
||||||
self.vm.bus[int(index)].gain = val
|
self.vm.bus[int(index)].gain = val
|
||||||
self[f'BUS {index}||SLIDER GAIN'].update(value=val)
|
self[f'BUS {index}||SLIDER GAIN'].update(value=val)
|
||||||
self.nvda.speak(str(round(val, 1)))
|
self.nvda.speak_and_braille(str(round(val, 1)))
|
||||||
else:
|
else:
|
||||||
self.vm.event.pdirty = True
|
self.vm.event.pdirty = True
|
||||||
case [
|
case [
|
||||||
@@ -1072,7 +1088,7 @@ class NVDAVMWindow(psg.Window):
|
|||||||
val = util.check_bounds(val, (-60, 12))
|
val = util.check_bounds(val, (-60, 12))
|
||||||
self.vm.bus[int(index)].gain = val
|
self.vm.bus[int(index)].gain = val
|
||||||
self[f'BUS {index}||SLIDER GAIN'].update(value=val)
|
self[f'BUS {index}||SLIDER GAIN'].update(value=val)
|
||||||
self.nvda.speak(str(round(val, 1)))
|
self.nvda.speak_and_braille(str(round(val, 1)))
|
||||||
else:
|
else:
|
||||||
self.vm.event.pdirty = True
|
self.vm.event.pdirty = True
|
||||||
case [
|
case [
|
||||||
@@ -1091,13 +1107,13 @@ class NVDAVMWindow(psg.Window):
|
|||||||
val = util.check_bounds(val, (-60, 12))
|
val = util.check_bounds(val, (-60, 12))
|
||||||
self.vm.bus[int(index)].gain = val
|
self.vm.bus[int(index)].gain = val
|
||||||
self[f'BUS {index}||SLIDER GAIN'].update(value=val)
|
self[f'BUS {index}||SLIDER GAIN'].update(value=val)
|
||||||
self.nvda.speak(str(round(val, 1)))
|
self.nvda.speak_and_braille(str(round(val, 1)))
|
||||||
else:
|
else:
|
||||||
self.vm.event.pdirty = True
|
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)
|
||||||
self.nvda.speak(str(0))
|
self.nvda.speak_and_braille(str(0))
|
||||||
|
|
||||||
# Unknown
|
# Unknown
|
||||||
case _:
|
case _:
|
||||||
|
|||||||
Reference in New Issue
Block a user