Potential fix for nvda2cthulhu plugin crash bug.
This commit is contained in:
@@ -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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user