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

Traceback occurs when switching synths in latest alpha #11482

Closed
Mohamed00 opened this issue Aug 11, 2020 · 6 comments · Fixed by #11531
Closed

Traceback occurs when switching synths in latest alpha #11482

Mohamed00 opened this issue Aug 11, 2020 · 6 comments · Fixed by #11531
Milestone

Comments

@Mohamed00
Copy link

Steps to reproduce:

  1. Switch between two synthesizers several times and wait a bit. I was able to reproduce this reliably using ESpeak and Vocalizer, but it may happen for other synths as well.

Actual behavior:

A traceback is displayed. The following log fragment demonstrates me switching from ESpeak to Vocalizer and then getting the traceback.
INFO - synthDriverHandler.setSynth (09:26:49.664) - MainThread (2068):
Loaded synthDriver espeak
DEBUGWARNING - synthDriverHandler.getSynthList (09:26:52.441) - MainThread (2068):
Synthesizer 'mssp' doesn't pass the check, excluding from list
DEBUGWARNING - external:synthDrivers.vocalizer_expressive._voiceManager.VoiceManager.setDefaultVoice (09:26:54.850) - MainThread (2068):
Voice not available, using default voice.
DEBUGWARNING - external:synthDrivers.vocalizer_expressive.SynthDriver._set_variant (09:26:54.855) - MainThread (2068):
Model not available: full_155mrf22
INFO - synthDriverHandler.setSynth (09:26:54.856) - MainThread (2068):
Loaded synthDriver vocalizer_expressive
ERROR - unhandled exception (09:26:59.835) - MainThread (2068):
Traceback (most recent call last):
File "wx\core.pyc", line 2196, in Notify
File "nvwave.pyc", line 349, in _close
File "nvwave.pyc", line 90, in _winmm_errcheck
OSError: [Errno 5] The specified device handle is invalid.

Expected behavior:

No error.

System configuration

NVDA installed/portable/running from source:

Installed.

NVDA version:

alpha-20718,633435db.

Windows version:

Windows 10, version 10.0.20185 Build 20185.

Name and version of other software in use when reproducing the issue:

N/a

Other information about your system:

N/a

Other questions

Does the issue still occur after restarting your computer?

Yes.

Have you tried any other versions of NVDA? If so, please report their behaviors.

Yes, this seems to have started when #11024 was merged.

If addons are disabled, is your problem still occuring?

Yes.

Did you try to run the COM registry fixing tool in NVDA menu / tools?

N/a.

@Mohamed00
Copy link
Author

CC @jcsteh

@jcsteh
Copy link
Contributor

jcsteh commented Aug 12, 2020

Curious. I included explicit code which should deal with this case, so I'm not sure why that isn't working here. I can't reproduce it with eSpeak and OneCore and I don't have Vocalizer.

@Mohamed00
Copy link
Author

You may be able to reproduce it by switching between ESpeak and RHVoice. The common thread here seems to be pressing control quickly after the synth first loads, example, switch to ESpeak, press control quickly after it first starts speaking, then switch to RHVoice and press control quickly again.

@tspivey
Copy link
Collaborator

tspivey commented Aug 12, 2020

If I'm understanding the nvwave code right, there's at least one way it can fail.

  1. If a player method is called in a thread, e.g. player.stop or player.idle, the timer will be started on the main thread with wx.CallAfter.
  2. If you then call player.close from the main thread, then the timer will be stopped from the main thread (without CallAfter). However, the CallAfter to start the timer might not have ran yet.
  3. The CallAfter runs to start the timer, the timer eventually fires and calls self._close, but the handle is invalid by then.

@amirsol81
Copy link

I can also duplicate this by, say, switching from eSpeak to MS Sapi 5 (Eva), or vice versa.
My log shows the following:
INFO - synthDriverHandler.setSynth (18:02:29.581) - MainThread (7288):
Loaded synthDriver sapi5
ERROR - unhandled exception (18:02:34.389) - MainThread (7288):
Traceback (most recent call last):
File "wx\core.pyc", line 2196, in Notify
File "nvwave.pyc", line 349, in _close
File "nvwave.pyc", line 90, in _winmm_errcheck
OSError: [Errno 5] The specified device handle is invalid.
ERROR - unhandled exception (18:02:39.627) - MainThread (7288):
Traceback (most recent call last):
File "wx\core.pyc", line 2196, in Notify
File "nvwave.pyc", line 349, in _close
File "nvwave.pyc", line 90, in _winmm_errcheck
OSError: [Errno 5] The specified device handle is invalid.

@jcsteh
Copy link
Contributor

jcsteh commented Aug 12, 2020

Thanks @tspivey; I somehow missed that. I'll look into a fix.

feerrenrut added a commit that referenced this issue Sep 1, 2020
Fixes #5172
Fixes #10721
Fixes #11482
Fixes #11490

### History
#5172
Some audio drivers/hardware take a long time to open the device and/or truncate the start/end of the audio.

#10721
Calling WaveOutOpen in the OneCore synth callback mysteriously blocks (and thus lags) for ~100 ms. Because we close the audio device on idle, we can trigger this problem. Although PR #11023 mostly fixed this, it's impossible (or at least very difficult) to resolve this completely from within the OneCore driver.

PR #11024 attempted to fix these issues by waiting 10 seconds before closing the audio device"

### Problem to solve
Subsequent to #11024, there are occasional exceptions from nvwave, particularly when switching synthesisers. In particular the following cases need to be handled smoothly:
- When using Microsoft Sound Mapper, NVDA should use the Windows default device (even if it changes)
- When the NVDA configured devices becomes invalid, nvWave should fall back to Microsoft Sound Mapper
- When the NVDA configured device becomes available again, NVDA should switch back to using it.
- Handle no audio device at all.

Since these issues needed to be fixed, and also:
- Closing and opening the audio device was originally introduced to support Remote Desktop audio, this is now better served by other solutions. 
- Performance is improved by keeping it open, using a timeout means that the lag is more rare, but will still occur.

### How it is solved
Instead, now don't close the device at all. As per the discussion:
#11505 (comment)

To fix issues with current / preferred device:
- nvWave now saves the preferred device when it is constructed.
- If using a device fails, it is considered unavailable, nvWave attempts to fall back to "Microsoft Sound Mapper".
- From my testing, using "Microsoft Sound Mapper" correctly handled changing the default device (Win 10 2004). It would be helpful if others could confirm, especially on different OS versions.
- During `_idleUnbuffered`
  - The current device is checked to see if it matches the preferred device.
  - The available devices are polled to see if the preferred device is available, if so it switches.
@nvaccessAuto nvaccessAuto added this to the 2020.3 milestone Sep 1, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
5 participants