Open CyrilleB79 opened 4 years ago
Adding the log: LogSayAllDoesNotResume.txt
I am unable to reproduce this issue on a webpage in Firefox 78.0.1 with NVDA 2020.2 Beta 2. I was erratically switching between pausing and resuming say all by pressing the left and right Shift keys; but everything kept working as expected in my brief test.
I can still reproduce the issue with:
@bhavyashah do you confirm that you have tried with eSpeak, rate 100, rate boost on? Can you try on the same webpage than I? Thanks.
I can now confirm this issue with the said webpage, browser, and NVDA version. I first had to disable the Sticky Keys (press Shift key 5 times) setting. Then, I went on the linked page, started a say all, and kept pressing and releasing the right Shift key multiple times each second. After 15 seconds or so, the say all ceased to resume. I tried this again and was able to reproduce the issue quicker than the first time. However, I think this issue persists even with lower speech rates (40% with Rate Boost) but just that it seems to take longer before the issue crops up. Also, while doing this testing, I also get the following error once or twice during each iteration of the exercise: ERROR - queueHandler.flushQueue (14:33:48.633) - MainThread (5304): Error in func nextLine from eventQueue Traceback (most recent call last): File "queueHandler.pyc", line 50, in flushQueue File "sayAllHandler.pyc", line 181, in nextLine AttributeError: 'NoneType' object has no attribute 'collapse' To be clear, this error is somewhat separate from say all stopping. This is because I get this error 5-10 seconds into the test, whereas Shift fails to resume the say all approximately 15 seconds into the test.
On the contrary, it seems to me that the error cause sayAll not to resume properly.
Here is a slightly different STR procedure to prove this:
Additional note: The issue seems to occur (at least) in a piece of text containing many links. That's why the table of contents of NVDA user guide is a good place to reproduce this issue.
@feerrenrut may you have a look on this since we already have a clear way to reproduce this issue and since it is a regression introduced with speech refactor?
As noted by @bhavyashah, sticky key shortcut has to be disabled. Thanks! I had forgotten to indicate this since I always live with this shortcut disabled.
Note that I have also reproduced this issue using SayAll with review cursor (gesture = NumpadPlus) in the Notepad edit area.
The error is the following (with following debug message also giving an indication):
Error running speech callback Traceback (most recent call last): File "speech\manager.pyc", line 669, in _handleIndex File "speech\commands.pyc", line 326, in run File "sayAllHandler.pyc", line 155, in _onLineReached File "sayAllHandler.pyc", line 212, in lineReached File "sayAllHandler.pyc", line 181, in nextLine AttributeError: 'NoneType' object has no attribute 'collapse' DEBUG - sayAllHandler._TextReader.nextLine (22:18:51.516) - MainThread (34744): no self.reader```
@feerrenrut is the log enough? Or should I check some debug log options in the Advanced setting panel?
On last alpha the log seems to give more information:
Input: kb(desktop):NVDA+downArrow IO - speech.speak (17:19:15.213) - MainThread (14988): Speaking [CallbackCommand(name=say-all:lineReached), LangChangeCommand ('fr_FR'), '#inputCore.py\r\n', CallbackCommand(name=say-all:lineReached), '#A part of NonVisual Desktop Access (NVDA)\r\n', CallbackCommand(name=say-all:lineReached), '#This file is covered by the GNU General Public License.\r\n'] DEBUG - synthDrivers.oneCore.SynthDriver._processQueue (17:19:15.213) - MainThread (14988): Begin processing speech DEBUG - synthDrivers.oneCore.SynthDriver.cancel (17:19:17.142) - MainThread (14988): Cancelling DEBUG - synthDrivers.oneCore.SynthDriver._callback (17:19:17.142) - Dummy-4 (11196): Done pushing audio DEBUG - synthDrivers.oneCore.SynthDriver._processQueue (17:19:17.142) - Dummy-4 (11196): Calling sync on audio player DEBUG - nvwave.WavePlayer._isPreferredDeviceOpen (17:19:17.142) - MainThread (14988): preferred device: WAVE_MAPPER current device name: WAVE_MAPPER (id: -1) IO - speech.speak (17:19:17.142) - MainThread (14988): Speaking [CallbackCommand(name=say-all:lineReached), LangChangeCommand ('fr_FR'), '#See the file COPYING for more details.\r\n'] DEBUG - synthDrivers.oneCore.SynthDriver._processQueue (17:19:17.142) - Dummy-4 (11196): Calling idle on audio player DEBUG - nvwave.WavePlayer._isPreferredDeviceOpen (17:19:17.142) - Dummy-4 (11196): preferred device: WAVE_MAPPER current device name: WAVE_MAPPER (id: -1) DEBUG - synthDrivers.oneCore.SynthDriver._processQueue (17:19:17.142) - Dummy-4 (11196): Begin processing speech DEBUG - nvwave.WavePlayer._isPreferredDeviceOpen (17:19:17.142) - MainThread (14988): preferred device: WAVE_MAPPER current device name: WAVE_MAPPER (id: -1) DEBUG - nvwave.WavePlayer.open (17:19:17.142) - MainThread (14988): Calling winmm.waveOutOpen. outputDeviceName: WAVE_MAPPER outputDeviceID: -1 DEBUG - nvwave.WavePlayer._isPreferredDeviceOpen (17:19:17.153) - MainThread (14988): preferred device: WAVE_MAPPER current device name: WAVE_MAPPER (id: -1) DEBUG - nvwave.WavePlayer._close (17:19:17.153) - MainThread (14988): Calling winmm.waveOutClose ERROR - speech.manager.SpeechManager._handleIndex (17:19:17.142) - MainThread (14988): Error running speech callback Traceback (most recent call last): File "speech\manager.py", line 669, in _handleIndex callbackCommand.run() File "speech\commands.py", line 326, in run return self._callback(*args,**kwargs) File "sayAllHandler.py", line 164, in _onLineReached self.lineReached(obj, bookmark, state) File "sayAllHandler.py", line 221, in lineReached self.nextLine() File "sayAllHandler.py", line 190, in nextLine self.reader.collapse(end=True) AttributeError: 'NoneType' object has no attribute 'collapse' DEBUG - sayAllHandler._TextReader.nextLine (17:19:17.193) - MainThread (14988): no self.reader DEBUG - nvwave.WavePlayer._isPreferredDeviceOpen (17:19:17.559) - nvwave.playWaveFile(error.wav) (5892): preferred device: WAVE_MAPPER current device name: WAVE_MAPPER (id: -1)```
I have only pressed NVDA+downArrow and then quickly many times the shift key until the error sound is heard. But strangely the audio device (WavePlayer) is closed. I do not have knowledge about PRs ##11531 and #11024. But I seem to understand that the audio device should not be closed at all now. Let me know if I am wrong.
cc: @jcsteh, @michaelDCurran
@michaelDCurran since you have just worked on #11651, you may be able to see the root cause of this issue in case it is linked? I had tried to investigate but I do not have a clear idea of the speech framework.
Or if you or someone else has any advice where I should dig in, I may try to investigate again.
Also would it be useful to provide a new log with some extra debug channels activated?
But strangely the audio device (WavePlayer) is closed.
This is misleading. When an error sound is played, a new nvWave instance is created to play the audio file. This results in an open and close of the audio device. It would be really good if this logging only happened with nvWave logging category enabled, it would also be good if it differentiated itself from the normal nvWave logging.
One thing to note about the above log is the timestamps, the order of the log entries does not match the timestamps, the error log entry happened at the same moment as the call to open wave out.
But strangely the audio device (WavePlayer) is closed.
This is misleading. When an error sound is played, a new nvWave instance is created to play the audio file. This results in an open and close of the audio device.
OK. Thanks for the explanation. So all is normal here.
It would be really good if this logging only happened with nvWave logging category enabled,
Yes, it does now. If I am not mistaken the log I had provided was done before the integration of ##11582.
it would also be good if it differentiated itself from the normal nvWave logging.
One thing to note about the above log is the timestamps, the order of the log entries does not match the timestamps, the error log entry happened at the same moment as the call to open wave out.
I had not realized this. I do not know however what it implies.
I do not know however what it implies.
The cause is likely due to the messages originating from different threads, not a concern. But its worth knowing about because it is tempting to assume the order of the messages in the log reflects the order of execution. In this particular case it is hard to determine that this message was due to the error sound without noticing the time stamps.
Here are some more investigation on this issue (on last alpha):
First of all, doing more carefully these tests, I have been able to see that the real issue is that at a moment, pressing shift key while reading does not pause immediately the synthesis. Instead, an error sound is heard and the speech synth continues to speak until the end of the current short chunk. Once reading this chunk is finished, sayAll is completely stopped and pressing shift again does not allow to restart sayAll.
I will modify the title of this issue accordingly.
I have been able to see that _TextReader.stop
function was called whereas I only press shift key and the we are not at all at the end of the text to be read.
The call stack of the stop
function is the following:
stop in nvda\source\sayAllHandler.py line 29
cancelSpeech in nvda\source\speech\__init__.py line 138
speak in nvda\source\speech\__init__.py line 740
speakWithoutPauses in nvda\source\speech\__init__.py line 2459
nextLine in nvda\source\sayAllHandler.py line 185
flushQueue in nvda\source\queueHandler.py line 55
pumpAll in nvda\source\queueHandler.py line 88
run in nvda\source\core.py line 538
Notify in nvda\source\gui\__init__.py line 1062
MainLoop in nvda\include\wxPython\wx\core.py line 2134
main in nvda\source\core.py line 568
<module> in source\nvda.pyw line 247
Note that the line number in sayAllHandler.py may not be exact due to log points and other debug code added by me.
What seems strange to me is the following statements in speech\__init__.py\speak
if isPaused:
cancelSpeech()
Why should speech be cancelled upon pause? @feerrenrut (for your work on speech refactor), @michaelDCurran (since you were the one who wrote these lines... in 2007) or anyone else, any clarification would help. Thanks!
Thanks for the investigation @CyrilleB79. We have some unit tests that can imitate say-all. It would be great if we could replicate this in a unit test.
In order to stop the synth from speaking, we have to call cancel. SayAllHandler should maintain the current position / reading state I believe.
Instead, an error sound is heard and the speech synth continues to speak until the end of the current short chunk.
Please paste the error text from the log into a comment, ideally the stack at this moment too (you may need to add stack_info=True
to the log call)
@feerrenrut, I am not sure to understand what you are expecting.
Please find below the issue reproduced on this page with eSpeak rate 100, rate boost on. I have:
IO - external:inputCore.executeGesture (23:01:42.719) - winInputHook (24000): Input: kb(desktop):NVDA+downArrow IO - external:speech.speak (23:01:42.735) - MainThread (19864): Speaking [CallbackCommand(name=say-all:lineReached), 'visité', 'lien', 'Homepage', CallbackCommand(name=say-all:lineReached)] IO - external:speech.speak (23:01:42.751) - MainThread (19864): Speaking ['Global', 'navigation région', 'visité', 'lien', 'Pull requests you created', CallbackCommand(name=say-all:lineReached)] IO - external:speech.speak (23:01:42.751) - MainThread (19864): Speaking ['visité', 'lien', 'Issues you created', CallbackCommand(name=say-all:lineReached)] IO - external:speech.speak (23:01:42.760) - MainThread (19864): Speaking ['lien', 'Marketplace ', CallbackCommand(name=say-all:lineReached)] IO - external:speech.speak (23:01:42.760) - MainThread (19864): Speaking ['visité', 'lien', 'Explore ', CallbackCommand(name=say-all:lineReached)] IO - external:speech.speak (23:01:42.787) - MainThread (19864): Speaking ['lien', 'You have no unread notifications', CallbackCommand(name=say-all:lineReached)] IO - external:speech.speak (23:01:42.787) - MainThread (19864): Speaking ['cliquable', 'bouton', 'réduit', 'sous-Menu', 'Create new…', CallbackCommand(name=say-all:lineReached)] IO - external:speech.speak (23:01:42.806) - MainThread (19864): Speaking ['cliquable', 'bouton', 'réduit', 'sous-Menu', 'View profile and more', CallbackCommand(name=say-all:lineReached)] IO - external:speech.speak (23:01:42.811) - MainThread (19864): Speaking ['principale région', 'titre', 'niveau 1', 'visité', 'lien', 'nvaccess', CallbackCommand(name=say-all:lineReached)] IO - external:speech.speak (23:01:42.826) - MainThread (19864): Speaking ['titre', 'niveau 1', '/', CallbackCommand(name=say-all:lineReached)] IO - external:speech.speak (23:01:42.826) - MainThread (19864): Speaking ['titre', 'niveau 1', 'visité', 'lien', 'nvda'] IO - external:speech.speak (23:01:53.747) - MainThread (19864): Speaking [CallbackCommand(name=say-all:lineReached)] IO - external:speech.speak (23:01:53.757) - MainThread (19864): Speaking ['liste', 'de 4 éléments', 'bouton', 'réduit', ' Sponsor ', CallbackCommand(name=say-all:lineReached)] IO - external:speech.speak (23:01:53.766) - MainThread (19864): Speaking ['cliquable', 'bouton', 'réduit', 'sous-Menu', 'Notifications settings', CallbackCommand(name=say-all:lineReached)] IO - external:speech.speak (23:01:53.771) - MainThread (19864): Speaking ['lien', '142 users are watching this repository', CallbackCommand(name=say-all:lineReached)] IO - external:speech.speak (23:01:53.777) - MainThread (19864): Speaking ['bouton', 'Unstar this repository', CallbackCommand(name=say-all:lineReached)] IO - external:speech.speak (23:01:53.782) - MainThread (19864): Speaking ['lien', '1047 users starred this repository', CallbackCommand(name=say-all:lineReached)] IO - external:speech.speak (23:01:53.787) - MainThread (19864): Speaking ['bouton', 'Fork your own copy of nvaccess/nvda to your account', CallbackCommand(name=say-all:lineReached)] IO - external:speech.speak (23:01:53.787) - MainThread (19864): Speaking ['lien', '398 users forked this repository', CallbackCommand(name=say-all:lineReached), 'hors de liste'] IO - external:speech.speak (23:01:53.817) - MainThread (19864): Speaking ['Repository', 'navigation région', 'liste', 'de 9 éléments', 'visité', 'lien', 'Code', CallbackCommand(name=say-all:lineReached)] IO - external:speech.speak (23:01:53.827) - MainThread (19864): Speaking ['visité', 'lien', 'page courante', 'Issues', CallbackCommand(name=say-all:lineReached)] ERROR - external:queueHandler.flushQueue (23:01:53.827) - MainThread (19864): Error in func _TextReader.nextLine Traceback (most recent call last): File "queueHandler.py", line 55, in flushQueue func(*args,**kwargs) File "sayAllHandler.py", line 190, in nextLine self.reader.collapse(end=True) AttributeError: 'NoneType' object has no attribute 'collapse' IO - external:inputCore.executeGesture (23:01:55.663) - winInputHook (24000): Input: kb(desktop):NVDA+f1
Let me know if this log is enough or if I should log something else. I may add additional log points in the code if required.
As a follow-up, I have just tested last alpha (Version : source-master-c4de394) containing the recent rework on SayAll. But the issue is still present. As before, the occurence of this issue is very rare with eSpeak and a bit more frequent but still rare (1/20 - 1/50) with IBMTTS.
Also to clarify regarding the initial description of #12397, the issue may occur at first press but the probability of occurrence is low. So STR indicate to press shift many times to raise the probability of occurrence of the issue.
I can reproduce this reliably with eSpeak while reading the table of contents in the NVDA user guide, WASAPI enabled, no add-ons in use, with NVDA 2024.3 Beta and Firefox 127.
Following is written to the log:
IO - inputCore.InputManager.executeGesture (23:27:59.389) - winInputHook (12176):
Input: kb(laptop):NVDA+a
IO - speech.speech.speak (23:27:59.394) - MainThread (14812):
Speaking [CallbackCommand(name=say-all:lineReached), 'Link', 'NVDA alpha-32650,405f9bfa Benutzerhandbuch', CallbackCommand(name=say-all:lineReached), 'Link', '1. ']
IO - speech.speech.speak (23:28:02.014) - MainThread (14812):
Speaking ['Einleitung', CallbackCommand(name=say-all:lineReached), 'Link', '1.1. ']
IO - speech.speech.speak (23:28:02.684) - MainThread (14812):
Speaking ['Allgemeine Features', CallbackCommand(name=say-all:lineReached)]
IO - speech.speech.speak (23:28:02.684) - MainThread (14812):
Speaking ['Link', '1.2. ']
IO - speech.speech.speak (23:28:03.849) - MainThread (14812):
Speaking ['System-Voraussetzungen', CallbackCommand(name=say-all:lineReached)]
IO - speech.speech.speak (23:28:03.849) - MainThread (14812):
Speaking ['Link', '1.3. ']
ERROR - speech.manager.SpeechManager._handleIndex (23:28:03.849) - MainThread (14812):
Error running speech callback
Traceback (most recent call last):
File "speech\manager.pyc", line 686, in _handleIndex
File "speech\commands.pyc", line 401, in run
File "speech\sayAll.pyc", line 280, in _onLineReached
File "speech\sayAll.pyc", line 329, in lineReached
File "speech\sayAll.pyc", line 304, in nextLine
File "speech\sayAll.pyc", line 241, in collapseLineImpl
AttributeError: 'NoneType' object has no attribute 'collapse'
DEBUG - speech.sayAll._TextReader.nextLine (23:28:04.424) - MainThread (14812):
no self.reader
and the speech is cancelled.
cc: @LeonarddeR any idea on this?
Steps to reproduce:
Steps for a stress test since this issue appears only sporadically:
Actual behavior:
After max 20-30 seconds pressing pausing and resuming quickly, SayAll does not resume anymore.
Expected behavior:
If SayAll is paused with shift key, it should always be able to be resumed.
Note
Elaborated this stress test since I can see that sometimes (but quite rarely), sayAll does not resume even at normal rate, with eSpeak and with IBMTTS.
System configuration
NVDA installed/portable/running from source:
Installed 2019.3, portable 2020.1beta1
NVDA version:
All
Windows version:
Windows 7 (both NVDA versions), Windows 10 (NVDA 2019.3 tested).
Name and version of other software in use when reproducing the issue:
Any where SayAll works. E.g. Firefox 68.
Other information about your system:
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.
NVDA 2019.2.1: cannot reproduce this issue.
If addons are disabled, is your problem still occuring?
Yes
Did you try to run the COM registry fixing tool in NVDA menu / tools?
No