Skip to content

Commit

Permalink
Merge 720b187 into 1ffad7d
Browse files Browse the repository at this point in the history
  • Loading branch information
seanbudd authored Jul 24, 2023
2 parents 1ffad7d + 720b187 commit 030d487
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 46 deletions.
2 changes: 1 addition & 1 deletion source/config/configSpec.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
# Audio settings
[audio]
audioDuckingMode = integer(default=0)
wasapi = boolean(default=true)
WASAPI = featureFlag(optionsEnum="BoolFlag", behaviorOfDefault="disabled")
soundVolumeFollowsVoice = boolean(default=false)
soundVolume = integer(default=100, min=0, max=100)
Expand Down
3 changes: 0 additions & 3 deletions source/config/profileUpgradeSteps.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@
ReportTableHeaders,
ReportCellBorders,
)
from typing import (
Dict,
)
import configobj.validate
from configobj import ConfigObj

Expand Down
12 changes: 10 additions & 2 deletions source/gui/nvdaControls.py
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@ def __init__(
name=name,
)

self.SetSelection(self._getChoiceIndex(self._getConfigValue().value))
self.SetSelection(self._getChoiceIndex(configValue.value))
self.defaultValue = self._getConfSpecDefaultValue()
"""The default value of the config spec. Not the "behavior of default".
This is provided to maintain compatibility with other controls in the
Expand Down Expand Up @@ -499,10 +499,18 @@ def resetToConfigSpecDefault(self) -> None:
"""
self.SetSelection(self._getChoiceIndex(self.defaultValue))

def _getControlCurrentValue(self) -> enum.Enum:
return list(self._translatedOptions.keys())[self.GetSelection()]

def _getControlCurrentFlag(self) -> FeatureFlag:
flagValue = self._getControlCurrentValue()
currentFlag = self._getConfigValue()
return FeatureFlag(flagValue, currentFlag.behaviorOfDefault)

def saveCurrentValueToConf(self) -> None:
""" Set the config value to the current value of the control.
"""
flagValue: enum.Enum = list(self._translatedOptions.keys())[self.GetSelection()]
flagValue = self._getControlCurrentValue()
keyPath = self._confPath
if not keyPath or len(keyPath) < 1:
raise ValueError("Key path not provided")
Expand Down
83 changes: 53 additions & 30 deletions source/gui/settingsDialogs.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
List,
Optional,
Set,
cast,
)
import core
import keyboardHandler
Expand Down Expand Up @@ -976,28 +977,26 @@ def postSave(self):
LanguageRestartDialog(self).ShowModal()


class LanguageRestartDialog(
class _RestartDialog(
gui.contextHelp.ContextHelpMixin,
wx.Dialog, # wxPython does not seem to call base class initializer, put last in MRO
):
_title: str
_message: str

helpId = "GeneralSettingsLanguage"

def __init__(self, parent):
# Translators: The title of the dialog which appears when the user changed NVDA's interface language.
super(LanguageRestartDialog, self).__init__(parent, title=_("Language Configuration Change"))
def __init__(self, parent: wx.Window):
super().__init__(parent, title=self._title)
mainSizer = wx.BoxSizer(wx.VERTICAL)
sHelper = guiHelper.BoxSizerHelper(self, orientation=wx.VERTICAL)
# Translators: The message displayed after NVDA interface language has been changed.
sHelper.addItem(wx.StaticText(self, label=_("NVDA must be restarted for the new language to take effect.")))
sHelper.addItem(wx.StaticText(self, label=self._message))

bHelper = sHelper.addDialogDismissButtons(guiHelper.ButtonHelper(wx.HORIZONTAL))
# Translators: The label for a button in the dialog which appears when the user changed NVDA's interface language.
# Translators: The label for a button in a dialog
restartNowButton = bHelper.addButton(self, label=_("Restart &now"))
restartNowButton.Bind(wx.EVT_BUTTON, self.onRestartNowButton)
restartNowButton.SetFocus()

# Translators: The label for a button in the dialog which appears when the user changed NVDA's interface language.
# Translators: The label for a button in a dialog
restartLaterButton = bHelper.addButton(self, wx.ID_CLOSE, label=_("Restart &later"))
restartLaterButton.Bind(wx.EVT_BUTTON, lambda evt: self.Close())
self.Bind(wx.EVT_CLOSE, lambda evt: self.Destroy())
Expand All @@ -1011,7 +1010,28 @@ def __init__(self, parent):
def onRestartNowButton(self, evt):
self.Destroy()
config.conf.save()
queueHandler.queueFunction(queueHandler.eventQueue,core.restart)
queueHandler.queueFunction(queueHandler.eventQueue, core.restart)


class _WASAPIRestartDialog(_RestartDialog):
helpId = "WASAPI"

# Translators: The title of the dialog which appears when the user updated a setting for audio output
_title = _("Audio output change")

# Translators: The message displayed when the user updated a setting for audio output
_message = _("NVDA must be restarted for the new audio settings to take effect.")


class LanguageRestartDialog(_RestartDialog):
helpId = "GeneralSettingsLanguage"

# Translators: The title of the dialog which appears when the user changed NVDA's interface language.
_title = _("Language Configuration Change")

# Translators: The message displayed after NVDA interface language has been changed.
_message = _("NVDA must be restarted for the new language to take effect.")


class SpeechSettingsPanel(SettingsPanel):
# Translators: This is the label for the speech panel
Expand Down Expand Up @@ -3074,27 +3094,26 @@ def __init__(self, parent):
audioGroup = guiHelper.BoxSizerHelper(self, sizer=audio)
sHelper.addItem(audioGroup)

# Translators: This is the label for a checkbox control in the
# Advanced settings panel.
# Translators: This is the label for a checkbox control in the Advanced settings panel.
label = _("Use WASAPI for audio output (requires restart)")
self.wasapiCheckBox: wx.CheckBox = audioGroup.addItem(
wx.CheckBox(audioBox, label=label)
)
self.bindHelpEvent("WASAPI", self.wasapiCheckBox)
self.wasapiCheckBox.Bind(wx.EVT_CHECKBOX, self.onAudioCheckBoxChange)
self.wasapiCheckBox.SetValue(
config.conf["audio"]["wasapi"]
)
self.wasapiCheckBox.defaultValue = self._getDefaultValue(
["audio", "wasapi"])
self.wasapiComboBox = cast(nvdaControls.FeatureFlagCombo, audioGroup.addLabeledControl(
labelText=label,
wxCtrlClass=nvdaControls.FeatureFlagCombo,
keyPath=["audio", "WASAPI"],
conf=config.conf,
))
self.bindHelpEvent("WASAPI", self.wasapiComboBox)
self.wasapiComboBox.Bind(wx.EVT_CHOICE, self._onWASAPIChange)
self._oldWASAPIValue: bool = self.wasapiComboBox._getConfigValue().calculated()

# Translators: This is the label for a checkbox control in the
# Advanced settings panel.
label = _("Volume of NVDA sounds follows voice volume (requires WASAPI)")
self.soundVolFollowCheckBox: wx.CheckBox = audioGroup.addItem(
wx.CheckBox(audioBox, label=label)
)
self.bindHelpEvent("SoundVolumeFollowsVoice", self.soundVolFollowCheckBox)
self.soundVolFollowCheckBox.Bind(wx.EVT_CHECKBOX, self.onAudioCheckBoxChange)
self.soundVolFollowCheckBox.Bind(wx.EVT_CHECKBOX, self._onWASAPIChange)
self.soundVolFollowCheckBox.SetValue(
config.conf["audio"]["soundVolumeFollowsVoice"]
)
Expand All @@ -3115,7 +3134,7 @@ def __init__(self, parent):
)
self.soundVolSlider.defaultValue = self._getDefaultValue(
["audio", "soundVolume"])
self.onAudioCheckBoxChange()
self._onWASAPIChange()

# Translators: This is the label for a group of advanced options in the
# Advanced settings panel
Expand Down Expand Up @@ -3178,8 +3197,8 @@ def onOpenScratchpadDir(self,evt):
path=config.getScratchpadDir(ensureExists=True)
os.startfile(path)

def onAudioCheckBoxChange(self, evt: Optional[wx.CommandEvent] = None):
wasapi = self.wasapiCheckBox.IsChecked()
def _onWASAPIChange(self, evt: Optional[wx.CommandEvent] = None):
wasapi = bool(self.wasapiComboBox._getControlCurrentFlag())
self.soundVolFollowCheckBox.Enable(wasapi)
self.soundVolSlider.Enable(
wasapi
Expand Down Expand Up @@ -3213,7 +3232,7 @@ def haveConfigDefaultsBeenRestored(self):
and self.loadChromeVBufWhenBusyCombo.isValueConfigSpecDefault()
and self.caretMoveTimeoutSpinControl.GetValue() == self.caretMoveTimeoutSpinControl.defaultValue
and self.reportTransparentColorCheckBox.GetValue() == self.reportTransparentColorCheckBox.defaultValue
and self.wasapiCheckBox.GetValue() == self.wasapiCheckBox.defaultValue
and self.wasapiComboBox.isValueConfigSpecDefault()
and self.soundVolFollowCheckBox.GetValue() == self.soundVolFollowCheckBox.defaultValue
and self.soundVolSlider.GetValue() == self.soundVolSlider.defaultValue
and set(self.logCategoriesList.CheckedItems) == set(self.logCategoriesList.defaultCheckedItems)
Expand Down Expand Up @@ -3242,7 +3261,7 @@ def restoreToDefaults(self):
self.loadChromeVBufWhenBusyCombo.resetToConfigSpecDefault()
self.caretMoveTimeoutSpinControl.SetValue(self.caretMoveTimeoutSpinControl.defaultValue)
self.reportTransparentColorCheckBox.SetValue(self.reportTransparentColorCheckBox.defaultValue)
self.wasapiCheckBox.SetValue(self.wasapiCheckBox.defaultValue)
self.wasapiComboBox.resetToConfigSpecDefault()
self.soundVolFollowCheckBox.SetValue(self.soundVolFollowCheckBox.defaultValue)
self.soundVolSlider.SetValue(self.soundVolSlider.defaultValue)
self.logCategoriesList.CheckedItems = self.logCategoriesList.defaultCheckedItems
Expand Down Expand Up @@ -3275,7 +3294,7 @@ def onSave(self):
config.conf["documentFormatting"]["reportTransparentColor"] = (
self.reportTransparentColorCheckBox.IsChecked()
)
config.conf["audio"]["wasapi"] = self.wasapiCheckBox.IsChecked()
self.wasapiComboBox.saveCurrentValueToConf()
config.conf["audio"]["soundVolumeFollowsVoice"] = self.soundVolFollowCheckBox.IsChecked()
config.conf["audio"]["soundVolume"] = self.soundVolSlider.GetValue()
config.conf["annotations"]["reportDetails"] = self.annotationsDetailsCheckBox.IsChecked()
Expand All @@ -3288,6 +3307,7 @@ def onSave(self):
config.conf['debugLog'][key]=self.logCategoriesList.IsChecked(index)
config.conf["featureFlag"]["playErrorSound"] = self.playErrorSoundCombo.GetSelection()


class AdvancedPanel(SettingsPanel):
enableControlsCheckBox = None # type: wx.CheckBox
# Translators: This is the label for the Advanced settings panel.
Expand Down Expand Up @@ -3359,6 +3379,9 @@ def onSave(self):
):
self.advancedControls.onSave()

def postSave(self):
if self.advancedControls._oldWASAPIValue != config.conf["audio"]["WASAPI"].calculated():
_WASAPIRestartDialog(self).ShowModal()

def onEnableControlsCheckBox(self, evt):
# due to some not very well understood mis ordering of event processing, we force NVDA to
Expand Down
2 changes: 1 addition & 1 deletion source/nvwave.py
Original file line number Diff line number Diff line change
Expand Up @@ -1044,7 +1044,7 @@ def _deviceNameToId(name, fallbackToDefault=True):

def initialize():
global WavePlayer
if not config.conf["audio"]["wasapi"]:
if not config.conf["audio"]["WASAPI"]:
return
WavePlayer = WasapiWavePlayer
NVDAHelper.localLib.wasPlay_create.restype = c_void_p
Expand Down
17 changes: 9 additions & 8 deletions user_docs/en/changes.t2t
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,6 @@ What's New in NVDA
- The Add-ons Manager has been removed and replaced by the Add-on Store.
- For more information please read the updated user guide.
-
- Enhanced sound management:
- NVDA now outputs audio via the Windows Audio Session API (WASAPI), which may improve the responsiveness, performance and stability of NVDA speech and sounds.
This can be disabled in Advanced settings if audio problems are encountered. (#14697)
- It is now possible to have the volume of NVDA sounds and beeps follow the volume setting of the voice you are using.
This option can be enabled in Advanced settings. (#1409)
- You can now separately control the volume of NVDA sounds.
This can be configured in Advanced settings. (#1409)
-
- New input gestures:
- An unbound gesture to cycle through the available languages for Windows OCR. (#13036)
- An unbound gesture to cycle through the Braille show messages modes. (#14864)
Expand Down Expand Up @@ -57,6 +49,15 @@ What's New in NVDA
- When colors are enabled Document Formatting, background colours are now reported in Microsoft Word. (#5866)
- When using Excel shortcuts to toggle format such as bold, italic, underline and strike through of a cell in Excel, the result is now reported. (#14923)
-
- Experimental enhanced sound management:
- NVDA can now output audio via the Windows Audio Session API (WASAPI), which may improve the responsiveness, performance and stability of NVDA speech and sounds. (#14697)
- WASAPI usage can be enabled in Advanced settings.
Additionally, if WASAPI is enabled, the following Advanced settings can also be configured.
- An option to have the volume of NVDA sounds and beeps follow the volume setting of the voice you are using. (#1409)
- An option to separately configure the volume of NVDA sounds. (#1409, #15038)
-
- There is a known issue with intermittent crashing when WASAPI is enabled. (#15150)
-
- In Mozilla Firefox and Google Chrome, NVDA now reports when a control opens a dialog, grid, list or tree if the author has specified this using aria-haspopup. (#14709)
- It is now possible to use system variables (such as ``%temp%`` or ``%homepath%``) in the path specification while creating portable copies of NVDA. (#14680)
- In Windows 10 May 2019 Update and later, NVDA can announce virtual desktop names when opening, changing, and closing them. (#5641)
Expand Down
2 changes: 1 addition & 1 deletion user_docs/en/userGuide.t2t
Original file line number Diff line number Diff line change
Expand Up @@ -2360,7 +2360,7 @@ With several historically popular GUI APIs, the text may be rendered with a tran
==== Use WASAPI for audio output ====[WASAPI]
This option enables audio output via the Windows Audio Session API (WASAPI).
WASAPI is a more modern audio framework which may improve the responsiveness, performance and stability of NVDA audio output, including both speech and sounds.
This option is enabled by default.
This option is disabled by default.
After changing this option, you will need to restart NVDA for the change to take effect.

==== Volume of NVDA sounds follows voice volume ====[SoundVolumeFollowsVoice]
Expand Down

0 comments on commit 030d487

Please sign in to comment.