Potential fix for nvda2cthulhu plugin crash bug.

This commit is contained in:
Storm Dragon
2026-05-02 17:59:39 -04:00
parent 265feb8188
commit 77b7c81d73
+41 -5
View File
@@ -29,6 +29,9 @@ from collections import OrderedDict
import subprocess import subprocess
import threading import threading
import urllib.parse import urllib.parse
from typing import Any, Callable
from gi.repository import GLib
try: try:
import msgpack import msgpack
@@ -202,17 +205,27 @@ class Nvda2Cthulhu(Plugin):
return True return True
def handle_message(self, message): def handle_message(self, message):
try:
request = self._parse_request(message) request = self._parse_request(message)
except Exception as exc:
logger.warning(f"NVDA to Cthulhu: failed to parse message: {exc}")
debug.printException(debug.LEVEL_WARNING)
return
if not request: if not request:
return return
try:
requestType, payload = request requestType, payload = request
if requestType == "SpeakText": if requestType == "SpeakText":
self._handle_speak(payload) self._handle_speak(payload)
elif requestType == "BrailleText": elif requestType == "BrailleText":
self._handle_braille(payload) self._schedule_on_main_thread(self._handle_braille, payload)
elif requestType == "CancelSpeech": elif requestType == "CancelSpeech":
speech.stop() self._schedule_on_main_thread(self._handle_cancel_speech)
except Exception as exc:
logger.warning(f"NVDA to Cthulhu: failed to handle message: {exc}")
debug.printException(debug.LEVEL_WARNING)
def _server_main(self): def _server_main(self):
if not self._dependencies_available(): if not self._dependencies_available():
@@ -234,7 +247,7 @@ class Nvda2Cthulhu(Plugin):
self.ioLoop.start() self.ioLoop.start()
except Exception as exc: except Exception as exc:
logger.error(f"NVDA to Cthulhu failed to start server: {exc}") logger.error(f"NVDA to Cthulhu failed to start server: {exc}")
self._present_message("NVDA to Cthulhu server failed to start") self._schedule_on_main_thread(self._present_message, "NVDA to Cthulhu server failed to start")
finally: finally:
self.httpServer = None self.httpServer = None
if self.ioLoop: if self.ioLoop:
@@ -261,7 +274,7 @@ class Nvda2Cthulhu(Plugin):
if not self._dependencies_available(): if not self._dependencies_available():
return None return None
if isinstance(message, str): if isinstance(message, str):
return "SpeakText", message return self._parse_payload(message)
if not isinstance(message, (bytes, bytearray)): if not isinstance(message, (bytes, bytearray)):
return None return None
@@ -318,7 +331,13 @@ class Nvda2Cthulhu(Plugin):
translated = self._translate_text(text) translated = self._translate_text(text)
logger.info(f"NVDA to Cthulhu: translated to: {translated[:50]}") logger.info(f"NVDA to Cthulhu: translated to: {translated[:50]}")
text = translated text = translated
speech.speak(text, interrupt=self.interruptEnabled) self._schedule_on_main_thread(self._speak_text, text, self.interruptEnabled)
def _speak_text(self, text: str, interrupt: bool) -> None:
speech.speak(text, interrupt=interrupt)
def _handle_cancel_speech(self) -> None:
speech.stop()
def _handle_braille(self, text): def _handle_braille(self, text):
if not text or not text.strip(): if not text or not text.strip():
@@ -350,6 +369,23 @@ class Nvda2Cthulhu(Plugin):
except Exception: except Exception:
logger.info(message) logger.info(message)
def _schedule_on_main_thread(self, callback: Callable[..., Any], *args: Any) -> bool:
try:
GLib.idle_add(self._run_on_main_thread, callback, args)
return True
except Exception as exc:
logger.warning(f"NVDA to Cthulhu: failed to queue main-loop callback: {exc}")
debug.printException(debug.LEVEL_WARNING)
return False
def _run_on_main_thread(self, callback: Callable[..., Any], args: tuple[Any, ...]) -> bool:
try:
callback(*args)
except Exception as exc:
logger.warning(f"NVDA to Cthulhu: main-loop callback failed: {exc}")
debug.printException(debug.LEVEL_WARNING)
return False
def _dependencies_available(self): def _dependencies_available(self):
return msgpack is not None and tornado is not None return msgpack is not None and tornado is not None