Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Audio settings with stereo headset (or speakers) - Send NVDA sounds on one side and the rest of Windows sounds on the other side #12985

Closed
CyrilleB79 opened this issue Oct 25, 2021 · 34 comments · Fixed by #16071
Labels
p5 https://github.com/nvaccess/nvda/blob/master/projectDocs/issues/triage.md#priority triaged Has been triaged, issue is waiting for implementation.
Milestone

Comments

@CyrilleB79
Copy link
Collaborator

I have had this feature request in mind since many years. But I finally open this ticket thanks to another person asking it on a French mailing list.

Is your feature request related to a problem? Please describe.

When participating to audio-conferences on the computer, it's often confusing to have NVDA's vocal feedback mixed up with the audio stream of the conference.

Describe the solution you'd like

NVDA audio stream is produced by synthesizer output but also beeps (progress bars, indent reporting) as well as other sounds such as focus/browse mode and spelling mistakes detection.
With a stereo headset or stereo speakers, it would be handy to have an option allowing to split the audio stream in two parts:

  • NVDA audio stream on one side, (e.g. left ear)
  • the rest of the computer's audio stream on the other side (e.g. right ear). That includes Windows sounds and sounds of the applications, which may include:
    • the audio stream of an aundio conference (Skype, Zoom, Teams either withe desktop application or in the browser)
    • the audio stream of audio or video editing/processing software (e.g. mp3DirectCut)

Describe alternatives you've considered

  • Maybe there is one or more applications that may already do this job; if yes, it would be good to reference it here.
  • In this issue, we may also consider the opportunity to add this feature in an add-on.

But IMO it would be valuable to have this feature integrated in NVDA or in an add-on rather that an external application. It would allow many people to discover this feature even if they do not express the need clearly.
Also it would be a plus to have this feature available in a portable version of NVDA; I do not know if it is technically doable however.

Additional context

Jaws 2022 will provide this feature (and that's what convinced me that this feature could be embedded in a screen reader). Below is a quote of its release notes (What's new):

Sound Splitter
Earlier in JAWS and Fusion 2021, we introduced a way for users to lower the volume of JAWS speech independently of system audio to help make it easier to hear audio from other applications. Version 2022 takes this a step further by now allowing those using stereo headsets or speakers to route all JAWS or Fusion speech to one ear while routing audio from all other applications to the other ear. This helps make it easier to continue getting work done with JAWS while following along during a Zoom or Teams meeting, a Skype call, or a YouTube video.
To split audio:

  1. Press INSERT+SPACEBAR followed by V to activate the Volume layer.
  2. Press B for Balance, and then do one of the following:
    ◦ Press LEFT ARROW to route JAWS Speech to the left and audio from all other applications to the right.
    ◦ Press RIGHT ARROW to route JAWS speech to the right and audio from all other applications to the left.
    ◦ Press UP ARROW to restore both JAWS speech and application audio to both channels.
    Note: Before attempting to split your audio, make sure your headset or speakers are properly oriented. For instance, if you route JAWS speech to the left and instead hear it in your right ear, your headset is most likely reversed.
    Once you split your JAWS speech and application audio, it remains in effect until you restart JAWS, or use the command to restore the audio balance.

I do not advocate for copying all features of Jaws in NVDA. But I think in this case that having this feature integrated in NVDA is a real plus.

@cary-rowen
Copy link
Contributor

This is what I have always wanted to say, not only in zoom and teams, sometimes when I am watching a movie, NVDA can read subtitles aloud, which is very good, but the sound of the NVDA and the sound of the movie will be mixed together. It feels bad. I really hope that NVDA can achieve this.

@msviolafangirl
Copy link

I think this would also be a cool feature to have. However I suspect it requires some significant interaction with the windows system or similar API or something like that. I'm not sure how JAWS got around the problem, but there's probably a way..

@mltony
Copy link
Contributor

mltony commented Nov 1, 2021

I've actually had this in my plans to implement this in one of my add-ons when time permits.
It appears this can be done via wasapi, there is IChannelAudioVolume interface that allows to control sound produced by other programs separately for left and right channels. But that would require calling some com interfaces, wihch I don't have much experience with. Another risk here is that I fear it might not work with Skype, since Skype might be using some fancy audio interfaces. And I would think that Skype and other VC apps must be the primary use case for this feature. Anyway, this requires some trial and error and some hacking. I'll update this thread if I manage to make it to work.

@mltony
Copy link
Contributor

mltony commented Nov 13, 2021

Implemented in Tony's enhancements add-on. Sound splitting can be toggled by pressing NVDA+Alt+S.
https://github.com/mltony/nvda-tonys-enhancements/releases/download/v1.11/tonysEnhancements-1.11.nvda-addon

@nidza07
Copy link
Contributor

nidza07 commented Nov 14, 2021

Thanks so much @mltony for this.
Might be better to move to your repo and create a separate issue, but there is currently one case you are not handling.
If you enable sound split, and then quit NVDA, the rest of the audio remains on one side instead of being restored.
Now, if you start NVDA, NVDA goes to center obviously since sound split is no longer enabled, but the rest remains on one side.
Hope that is clear enough and that you can fix this in a future build.
Thanks once again for taking this up.

@cary-rowen
Copy link
Contributor

Thanks to tony’s efforts, it seems that the sound can only be fixed to the right at the moment,Can the left and right sides be realized?
In addition, when I enabled sound splitting, the other side was not completely muted.

@nidza07
Copy link
Contributor

nidza07 commented Nov 14, 2021

@cary-rowen yes, if you go to NVDA's settings, under the Tony's enhancements panel, check the checkbox named Switch left and right during sound split. This will revert it, meaning that NVDA will be on the left and everything else on the right.

@cary-rowen
Copy link
Contributor

Wow! Thank you for your reminder, it might be better if addon allow the shortcut keys to switch between the left, right and disabled modes.

@mltony
Copy link
Contributor

mltony commented Nov 16, 2021 via email

@josephsl
Copy link
Collaborator

josephsl commented May 2, 2022

Hi,

Partly resolved with add-ons from Tony and yours truly.

Thanks.

@cary-rowen
Copy link
Contributor

Hi, @josephsl
Will it be a big challenge to bring 'sound spliter' into the NVDA core? Regarding the psutil module, is there any reason for NVAccess to reject it?
Also, I have to say that the sound separation in the 'NVDA Extensions Global Plugin' is more useful, It allows me to concentrate on the movie and subtitles, could you further enrich the functionality of the 'Sound Splitter'?

Thanks

@josephsl
Copy link
Collaborator

josephsl commented May 2, 2022 via email

@mltony
Copy link
Contributor

mltony commented May 2, 2022 via email

@josephsl
Copy link
Collaborator

josephsl commented May 2, 2022 via email

@feerrenrut feerrenrut added the triaged Has been triaged, issue is waiting for implementation. label May 5, 2022
@Adriani90
Copy link
Collaborator

@CyrilleB79 is this somehow a duplicate of #13818? I think there is more technical discussion going on, I wonder if we can close this one in favor of #13818.

@CyrilleB79
Copy link
Collaborator Author

@CyrilleB79 is this somehow a duplicate of #13818? I think there is more technical discussion going on, I wonder if we can close this one in favor of #13818.

I agree that the implementation of both issues may be based on the same functions. But the use cases are different.
The use case of the current issue is to have Sound Splitter add-on feature integrated in core. On the other side, #13818 seems a more general use case, with the possibility to mix among various channels. IMO it may be worth to keep both tickets open: NVAccess may accept/implement this one in core and want to keep #13818 in an add-on.

@CyrilleB79
Copy link
Collaborator Author

There are already three add-ons that provide this feature: Sound Splitter (cc @XLTechie), Tony's Enhancements (cc @cary-rowen, @mltony) and NVDAExtensionGlobalPlugin (cc @paulber19).

WASAPI is now integrated in alpha and is activated by default. Unfortunately, from what I know, the authors or contributors of these add-ons have not yet found a compatible way to implement the sound splitting feature. If no solution is found, there is the risk that many user disable the WASAPI checkbox. In addition, unfortunately, we do not have a FeatureFlag on this feature to manage it more precisely.

Would this be the opportunity to include sound split it in NVDA? Is this something hard to do or not? If not and since you have worked recently on WASAPI, @jcsteh would you be interested in implementing it?

@seanbudd and @michaelDCurran what do
you think, especially regarding the risk that many users disable the checkbox to be able to use their sound splitting add-ons? Should you reconsider WASAPI enabled by default in 2023.2 and implement a feature flag for it?

@jcsteh
Copy link
Contributor

jcsteh commented May 21, 2023

I'm not willing to implement the feature in its entirety, as that means figuring out the right user experience and interface and I just don't have the time to go back and forth on that. However, I might be able to make it possible for add-ons to do this easily. I could provide a setChannelVolume method on WavePlayer instances or something like that. I'd also need to know what extensionPoints would be required for an add-on to implement this without monkey patching. For example, I'm guessing we'd need actions for when a stream is opened, when it is stopped, etc.

Alternatively, I could implement the backend parts of this (setChannelVolume or similar) and someone else could implement the UX/UI for channel splitting, working with others to figure out the best UX/UI.

@cary-rowen
Copy link
Contributor

Alternatively, I could implement the backend parts of this (setChannelVolume or similar) and someone else could implement the UX/UI for channel splitting, working with others to figure out the best UX/UI.

I think that would be nice too, that's enough, someone will be willing to put in the effort on the UI/UX side.

@CyrilleB79
Copy link
Collaborator Author

I'm not willing to implement the feature in its entirety, as that means figuring out the right user experience and interface and I just don't have the time to go back and forth on that. However, I might be able to make it possible for add-ons to do this easily. I could provide a setChannelVolume method on WavePlayer instances or something like that. I'd also need to know what extensionPoints would be required for an add-on to implement this without monkey patching. For example, I'm guessing we'd need actions for when a stream is opened, when it is stopped, etc.

Alternatively, I could implement the backend parts of this (setChannelVolume or similar) and someone else could implement the UX/UI for channel splitting, working with others to figure out the best UX/UI.

@jcsteh thanks for this proposal. Such contribution would be very helpful. Add-on authors or anyone wanting to implement it in core will be able to provide a GUI without any problem.

To help you, maybe add-on authors (@cary-rowen, @XLTechie and @paulber19) can indicate the functions and extension points taht they would need in the API. That is indicate the private functions they use in their add-on and the functions that they are monkey patching.

@XLTechie
Copy link
Collaborator

XLTechie commented May 23, 2023

jcsteh Thank you for your consideration. We already have UI for this behavior, extant in at least three add-ons; though one of them, Sound Splitter, is an updated version of what was already being done in one of the others. @josephsl did that work, but I recently started maintaining it.

Based on my grasp of what's going on in the code used, we would definitely need channel based volume control as you mentioned, and probably the session notification Actions you talked about. I haven't looked into how WASAPI differs in the way it handles audio, so I don't know what else we would need, but that sounds like the minimum (and maybe also the maximum).

Below, I have pasted the most important code that is used to patch stable NVDA to accomplish this, minus the obvious parts that you can infer. The full sourcecode is available here.

Code Excerpts...
import ctypes
import types
import os
import core
import nvwave

winmm = ctypes.windll.winmm
originalWaveOpen = None

def noWASAPI_preWaveOpen(selfself, *args, **kwargs):
	global originalWaveOpen
	result = originalWaveOpen(selfself, *args, **kwargs)
	# All we care about is splitting sounds, so set volume to 100 percent always.
	volume = 100
	volume2 = int(0xFFFF * (volume / 100))
if not config.conf["soundSplitter"]["soundSplit"]:
		volume2 = volume2 | (volume2 << 16)
	else:
		if config.conf["soundSplitter"]["soundSplitLeft"]:
			pass
		else:
			volume2 = (volume2 << 16)
	winmm.waveOutSetVolume(selfself._waveout, volume2)
	return result

if not isUsingWASAPI():
	preWaveOpen = noWASAPI_preWaveOpen

def setAppsVolume(volumes=None, exit=False):
	from . pycaw.pycaw import AudioUtilities, IChannelAudioVolume
	if volumes is not None:
		leftVolume, rightVolume = volumes
	else:
		volume = 100
		# By default, if enabled, NVDA is on the right, left only is on the left
		if config.conf["soundSplitter"]["soundSplit"]:
			# If this option is set, NVDA is on the left, and right sounds are on the right
			if config.conf["soundSplitter"]["soundSplitLeft"]:
				leftVolume = 0
				rightVolume = volume
			else:
				leftVolume = volume
				rightVolume = 0
		else:
			leftVolume = rightVolume = volume
	leftVolume /= 100.0
	rightVolume /= 100.0
	audioSessions = AudioUtilities.GetAllSessions()
	for s in audioSessions:
		if (
			not exit
			and s.Process is not None
			and s.ProcessId == os.getpid()  # FixMe should this be here? (Luke)
		):
			continue
		channelVolume = s._ctl.QueryInterface(IChannelAudioVolume)
		if channelVolume.GetChannelCount() == 2:
			channelVolume.SetChannelVolume(0, leftVolume, None)
			channelVolume.SetChannelVolume(1, rightVolume, None)

soundSplitterMonitorCounter = 0

def soundSplitterMonitorThread(localSoundSplitterMonitorCounter):
	global soundSplitterMonitorCounter
	while localSoundSplitterMonitorCounter == soundSplitterMonitorCounter:
		if (
			not config.conf["soundSplitter"]["soundSplit"]
			or isUsingWASAPI()
		):
			return
		setAppsVolume()
		yield 1000

def updateSoundSplitterMonitorThread(exit=False):
	global soundSplitterMonitorCounter
	soundSplitterMonitorCounter += 1
	if exit:
		setAppsVolume((100, 100), exit=True)
		return
	ss = config.conf["soundSplitter"]["soundSplit"]
	if ss:
		executeAsynchronously(soundSplitterMonitorThread(soundSplitterMonitorCounter))
	else:
		setAppsVolume()

def executeAsynchronously(gen):
	"""This function executes a generator in such a manner, that allows updates
	from the operating system to be processed during execution.
	Specifically, every time the generator yields a positive number,,
	the rest of the generator function will be executed from within wx.CallLater().
	If the generator yields a value of 0, then the rest of the generator
	will be executed from within wx.CallAfter().
	This allows clear and simple expression of the logic inside the generator body,
	while still allowing NVDA to process update events from the operating system.
	Essentially the generator will be paused every time it calls yield, then the updates will be
	processed by NVDA and then the remainder of generator function will continue executing.
	"""
	if not isinstance(gen, types.GeneratorType):
		raise Exception("A generator is required")
	try:
		value = gen.__next__()
	except StopIteration:
		return
	# FixMe: The below line may require a rewrite as multiple Flake8/lint errors are raised.
	l = lambda gen=gen: executeAsynchronously(gen)  # NOQA
	core.callLater(value, executeAsynchronously, gen)

updateSoundSplitterMonitorThread()

class GlobalPlugin(globalPluginHandler.GlobalPlugin):

	def __init__(self, *args, **kwargs):
		super().__init__(*args, **kwargs)
		global originalWaveOpen
		if not isUsingWASAPI():
			originalWaveOpen = nvwave.WavePlayer.open
			nvwave.WavePlayer.open = preWaveOpen

	def terminate(self):
		global originalWaveOpen
		updateSoundSplitterMonitorThread(exit=True)
		if not isUsingWASAPI():
			nvwave.WavePlayer.open = originalWaveOpen
		super().terminate()  # Probably unnecessary but maybe needed in the future

@jcsteh
Copy link
Contributor

jcsteh commented May 23, 2023

It looks like you already have everything you need in the setAppsVolume function. NVDA's main output (usually just speech) and sounds are now in separate sessions. You can get the session GUIDs using nvwave.defaultSession.guid and nvwave.soundsSession.guid. You could adjust the channels for those sessions as needed.

That said, it'd obviously be better if this wasn't done with monkey patching in future.

@jcsteh
Copy link
Contributor

jcsteh commented May 23, 2023

Now I'm realising you don't even want to separate NVDA speech from NVDA sounds. But I don't understand why you have the monkey patching winmm path when you have setAppsVolume which can already adjust all channel volumes, including NVDA. Can you explain?

@XLTechie
Copy link
Collaborator

XLTechie commented May 24, 2023 via email

@josephsl
Copy link
Collaborator

josephsl commented May 24, 2023 via email

@mltony
Copy link
Contributor

mltony commented May 24, 2023

So the question is why do we need monkey patching in sound splitter, right?
It's been a while since I wrote that code and I see it's been modified since then. I see only a single place where it monkey patches nvwave.WavePlayer.open function. So this is needed to adjust volume of NVDA output - it appears to require _waveout object and we need to adjust volume for every _waveout object in NVDA.
As to why we cannot use pycaw and Com interface magic to adjust NVDA volume the ansewr is simple: it doesn't appear to work. IIRC via that API I could successfully change volume of all the other apps, but not NVDA itself.

@Adriani90
Copy link
Collaborator

Quote from @mltony in #16051 regarding UX and code design for the implementation.

Description

• NVDA+Alt+S would toggle sound split. In sound split mode NVDA speech and beeps will be heard in one channel (say left), while sounds from all other applications will be heard in the other channel (right).
• I will also add a checkbox setting in Audio panel to allow users to toggle sound split from settings dialog.
• I will also add a new setting in Audio panel to allow users to select which channel NVDA will be redirected to and which channel will be for all other apps
Prior discussion: #16037
Technical details
Two things I'd like NVAccess to be aware of:

  1. Sound Splitting can be achieved using wasapi by adjusting the volume of all running applications and setting left volume to zero, while setting NVDA right volume to zero (or vice versa). So I will need to call wasapi COM objects. I would need to implement interfaces in Python for these objects. I am not very familiar with Python interoperability with COM, and I haven't found a way to automatically generate Python stubs for COM interfaces, so I propose to copy relevant interfaces from PyCaw library. The library is published under a permissive MIT license and based on Google v. Oracle case a couple of years ago - APIs are not copyrightable. An alternative solution could be including PyCaw library as a dependency, but I personally think this would be an overkill.
  2. In order for sound split to work properly, we would need to monitor audio sessions and if new audio sessions appear, we'd need to adjust their volume. I propose to create a new thread for that. The thread would be checking all audio sessions every second and adjust volume of new onse.

@XLTechie
Copy link
Collaborator

XLTechie commented Jan 16, 2024 via email

@mltony
Copy link
Contributor

mltony commented Jan 16, 2024

@michaelDCurran, @seanbudd, since guys closed my other issue, I would like to align with you here on the following two issues before I can start implementing this:

  1. Sound Splitting can be achieved using wasapi by adjusting the volume of all running applications and setting left volume to zero, while setting NVDA right volume to zero (or vice versa). So I will need to call wasapi COM objects. I would need to implement interfaces in Python for these objects. I am not very familiar with Python interoperability with COM, and I haven't found a way to automatically generate Python stubs for COM interfaces, so I propose to copy relevant interfaces from PyCaw library. The library is published under a permissive MIT license and based on Google v. Oracle case a couple of years ago - APIs are not copyrightable. An alternative solution could be including PyCaw library as a dependency, but I personally think this would be an overkill.
  2. In order for sound split to work properly, we would need to monitor audio sessions and if new audio sessions appear, we'd need to adjust their volume. I propose to create a new thread for that. The thread would be checking all audio sessions every second and adjust volume of new ones.

So do I have green light on copying Com APIs from PyCaw library and to create a new thread within NVDA - that thread would only be active as long as sound split is active?

@seanbudd seanbudd added the p5 https://github.com/nvaccess/nvda/blob/master/projectDocs/issues/triage.md#priority label Jan 17, 2024
@michaelDCurran
Copy link
Member

Yes, we would accept the comtypes COM interface definitions from pyCaw. As long as the file clearly stated where it came from.
A thread also sounds fine to me, but obviously more review can occur once a pr is opened or drafted.

@XLTechie
Copy link
Collaborator

XLTechie commented Jan 17, 2024 via email

@mltony
Copy link
Contributor

mltony commented Jan 17, 2024

@XLTechie, what exactly are you talking about? I looked at global extension a while ago and the guy just copied relevant code from Tony's Enhancements. So yeah, I'm familiar with that approach because I wrote it in the first place.

@CyrilleB79
Copy link
Collaborator Author

CyrilleB79 commented Jan 17, 2024

@XLTechie, what exactly are you talking about? I looked at global extension a while ago and the guy just copied relevant code from Tony's Enhancements. So yeah, I'm familiar with that approach because I wrote it in the first place.

In the meantime, NVDA Global Extensions' sound splitting capability works both with WASAPI. If I am not mistaken, Sound Splitter and Tony's Enhancements instead have only sound splitting working when WASAPI is disabled.
Hence the suggestion to look at NVDA Global Extensions add-on.

Cc @paulber19 in case you have some advice to give.

@paulber19
Copy link

paulber19 commented Jan 18, 2024 via email

@mltony mltony mentioned this issue Jan 20, 2024
5 tasks
seanbudd pushed a commit that referenced this issue Mar 6, 2024
Fixes #12985

Summary of the issue:
Feature request: sound split. Splits system sound into two channels: NVDA speaks in one channel (e.g. left), while all other applications play their sound in the other channel (e.g. right).

Description of user facing changes
Added global command NVDA+alt+s that toggles sound split between off, NVDA on the left and NVDA on the right (default behavior).
Added combo box on Audio panel in NVDA settings that also allows to switch between Sound split modes.
Added list of checkboxes in Audio panel, that allows to change behavior of NVDA+alt+s command: it allows to select all modes that the global command will cycle through.
Description of development approach
Added pycaw library as a dependency.
Created file source\audio\soundSplit.py where I implemented all logic.
Contrary to what I said before, I managed to implement sound split without creating an extra monitor thread. It works like this:
When sound split is toggled, it uses IAudioSessionEnumerator to set volume in all currently active audio sessions.
Then it does sessionManager.RegisterSessionNotification() to create a callback that listens for any new audio sessions being created, an it executes the the same volume updating function upon creation.
On the next call or on shutdown we unregister the previous notification callback.
@nvaccessAuto nvaccessAuto added this to the 2024.2 milestone Mar 6, 2024
Adriani90 pushed a commit to Adriani90/nvda that referenced this issue Mar 13, 2024
Fixes nvaccess#12985

Summary of the issue:
Feature request: sound split. Splits system sound into two channels: NVDA speaks in one channel (e.g. left), while all other applications play their sound in the other channel (e.g. right).

Description of user facing changes
Added global command NVDA+alt+s that toggles sound split between off, NVDA on the left and NVDA on the right (default behavior).
Added combo box on Audio panel in NVDA settings that also allows to switch between Sound split modes.
Added list of checkboxes in Audio panel, that allows to change behavior of NVDA+alt+s command: it allows to select all modes that the global command will cycle through.
Description of development approach
Added pycaw library as a dependency.
Created file source\audio\soundSplit.py where I implemented all logic.
Contrary to what I said before, I managed to implement sound split without creating an extra monitor thread. It works like this:
When sound split is toggled, it uses IAudioSessionEnumerator to set volume in all currently active audio sessions.
Then it does sessionManager.RegisterSessionNotification() to create a callback that listens for any new audio sessions being created, an it executes the the same volume updating function upon creation.
On the next call or on shutdown we unregister the previous notification callback.
seanbudd added a commit that referenced this issue May 10, 2024
Reverts PR
Reverts #16273

Issues fixed
Fixes #16409
Fixes #16402

Issues reopened
#16052

Brief reason for revert
We started with mltony creating:
#16051 Feature request: Sound split

Which was a duplicate of:
#12985 Audio settings with stereo headset (or speakers) - Send NVDA sounds on one side and the rest of Windows sounds on the other side

And then implemented by:
#16071 Sound split

mltony also created:
#16052 Feature request: add command to adjust volume of all applications except for NVDA

Which was implemented in:
#16273 Keystrokes to adjust applications volume and mute

This PR was approved and merged and was then found to cause issues:
#16402 Unmuting other apps does not work as expected
#16409 Apps mute and volume features work very unexpectedly with WASAPI disabled

Due to these issues and the considerable debate on the approach, the above PR #16273 was reverted by:
#16440

As an alternative to the revert #16440 to resolve the 2 issues (#16402, #16409) and keep #16273, mltony created:
#16404

The question now becomes, how do we proceed from here?

NV Access's position is that the sound split functionality (#16051) is a useful feature to add into core. However, due to the following reasons, we believe that further work on the volume adjustment features (#16273, #16404) to improve the UX is required on a branch (off master/alpha) before it can be added back in:

Windows sound mixer has reasonable accessibility.
Sound split on its own provides value to users.
The UX of swapping between NVDA volume control and windows volume control needs to be resolved.
The UX of resolving volume issues due to NVDA crashes needs to be resolved.
As one of the contributors on the threads said, "So now there are two mixers in the chain, one of which can be invisible, and overrides the other, or makes its settings relative instead of absolute."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
p5 https://github.com/nvaccess/nvda/blob/master/projectDocs/issues/triage.md#priority triaged Has been triaged, issue is waiting for implementation.
Projects
None yet
Development

Successfully merging a pull request may close this issue.