Closed CyrilleB79 closed 8 months ago
@mltony
This issue completely breaks AI Content Describer, and I suspect other add-ons too as reported by three people in the last few days.
there are situations where it is necessary to call ui.message
or any speech.speak*
method from within another thread. However, until this is resolved, users have to basically choose between Bluetooth audio and other pieces of their workflow.
After executing the code above, we get:
ERROR - stderr (11:50:32.891) - Thread-2 (11304):
Exception in thread Thread-2:
Traceback (most recent call last):
File "threading.pyc", line 926, in _bootstrap_inner
File "threading.pyc", line 870, in run
File "C:\Users\cartertemm\AppData\Roaming\nvda\addons\AIContentDescriber\globalPlugins\AIContentDescriber\__init__.py", line 220, in describe_image
ui.message(_("Retrieving description..."))
File "ui.pyc", line 132, in message
File "speech\speech.pyc", line 193, in speakMessage
File "C:\Users\cartertemm\AppData\Roaming\nvda\addons\bluetoothaudio\globalPlugins\bluetoothAudio.py", line 185, in wrapperFunc
hookFunc()
File "C:\Users\cartertemm\AppData\Roaming\nvda\addons\bluetoothaudio\globalPlugins\bluetoothAudio.py", line 66, in resetCounter
beepThread.play(t, reopen)
File "C:\Users\cartertemm\AppData\Roaming\nvda\addons\bluetoothaudio\globalPlugins\bluetoothAudio.py", line 165, in play
self.timer.Start(timerDuration, wx.TIMER_ONE_SHOT)
wx._core.wxAssertionError: C++ assertion "wxThread::IsMain()" failed at ..\..\src\common\timerimpl.cpp(57) in wxTimerImpl::Start(): timer can only be started from the main thread
ERROR - comtypes._comobject.call_without_this (11:50:36.862) - Dummy-1 (2688):
Exception in IUIAutomationEventHandler.HandleAutomationEvent implementation:
Traceback (most recent call last):
File "comtypes\_comobject.pyc", line 154, in call_without_this
File "UIAHandler\__init__.pyc", line 714, in IUIAutomationEventHandler_HandleAutomationEvent
File "comtypes\__init__.pyc", line 278, in __getattr__
File "monkeyPatches\comtypesMonkeyPatches.pyc", line 32, in __call__
_ctypes.COMError: (-2147220991, 'An event was unable to invoke any of the subscribers', (None, None, None, 0, None))
ERROR - comtypes._comobject.call_without_this (11:50:37.162) - Dummy-1 (2688):
Exception in IUIAutomationEventHandler.HandleAutomationEvent implementation:
Traceback (most recent call last):
File "comtypes\_comobject.pyc", line 154, in call_without_this
File "UIAHandler\__init__.pyc", line 714, in IUIAutomationEventHandler_HandleAutomationEvent
File "comtypes\__init__.pyc", line 278, in __getattr__
File "monkeyPatches\comtypesMonkeyPatches.pyc", line 32, in __call__
_ctypes.COMError: (-2147220991, 'An event was unable to invoke any of the subscribers', (None, None, None, 0, None))
ERROR - comtypes._comobject.call_without_this (11:50:37.164) - Dummy-1 (2688):
Exception in IUIAutomationEventHandler.HandleAutomationEvent implementation:
Traceback (most recent call last):
File "comtypes\_comobject.pyc", line 154, in call_without_this
File "UIAHandler\__init__.pyc", line 714, in IUIAutomationEventHandler_HandleAutomationEvent
File "comtypes\__init__.pyc", line 278, in __getattr__
File "monkeyPatches\comtypesMonkeyPatches.pyc", line 32, in __call__
_ctypes.COMError: (-2147220991, 'An event was unable to invoke any of the subscribers', (None, None, None, 0, None))
To fix, we simply need to ensure that the WX timer is always only called on the main thread. In bluetoothAudio.py (line 165):
wx.CallAfter(self.timer.Start, timerDuration, wx.TIMER_ONE_SHOT)
I have created a pull request and confirmed that it solves the problem without introducing others.
Please review and merge at your earliest convenience.
Issue
Consider the following code to paste in NVDA's console
Then, in the console, type:
test()
Actual result
With this add-on, an error is logged and the message is not spoken.
Expected result
ui.message
should be usable from any thread as when this add-on is not installed in NVDA.