From afd3e68570da8999a00ed91bb10cbf83a41e5143 Mon Sep 17 00:00:00 2001 From: Storm Dragon Date: Mon, 16 Jun 2025 13:38:50 -0400 Subject: [PATCH] Orca speech and Braille support added for Linux. --- accessible_output2/outputs/__init__.py | 1 + accessible_output2/outputs/orca.py | 108 +++++++++++++++++++++++++ readme.rst | 2 + 3 files changed, 111 insertions(+) create mode 100644 accessible_output2/outputs/orca.py diff --git a/accessible_output2/outputs/__init__.py b/accessible_output2/outputs/__init__.py index 5142a45..c8b2598 100644 --- a/accessible_output2/outputs/__init__.py +++ b/accessible_output2/outputs/__init__.py @@ -36,6 +36,7 @@ def _load_com(*names): from . import voiceover if platform.system() == "Linux": + from . import orca from . import speech_dispatcher from . import e_speak diff --git a/accessible_output2/outputs/orca.py b/accessible_output2/outputs/orca.py new file mode 100644 index 0000000..eafcb18 --- /dev/null +++ b/accessible_output2/outputs/orca.py @@ -0,0 +1,108 @@ +from __future__ import absolute_import +import subprocess +import platform +from .base import Output + + +class Orca(Output): + """Supports Orca screen reader self-voicing on Linux via D-Bus + + Uses the new Orca remote service API to present messages directly + through Orca's speech/braille output system. Falls back gracefully + if D-Bus service is not available. + + Note: This requires Orca to be running and the D-Bus service to be active. + """ + + name = "Orca Screen Reader" + priority = 99 # Higher priority than speech_dispatcher (100) + system_output = False + + def __init__(self): + self.service_name = "org.gnome.Orca.Service" + self.main_path = "/org/gnome/Orca/Service" + self._is_active = None + if platform.system() == "Linux": + self._test_connection() + + def _test_connection(self): + """Test if Orca D-Bus service is available""" + try: + result = subprocess.run([ + "gdbus", "call", "--session", + "--dest", self.service_name, + "--object-path", self.main_path, + "--method", "org.gnome.Orca.Service.ListCommands" + ], check=True, capture_output=True, text=True, timeout=2) + self._is_active = True + except (subprocess.CalledProcessError, subprocess.TimeoutExpired, FileNotFoundError): + self._is_active = False + + def is_active(self): + """Check if Orca D-Bus service is available""" + if self._is_active is None: + self._test_connection() + return self._is_active + + def speak(self, text, interrupt=0): + """ + Speak text through Orca's speech output system + + Args: + text (str): The text to speak + interrupt (int): Whether to interrupt current speech (unused for Orca) + + Returns: + bool: True if successful, False otherwise + """ + if not self.is_active(): + return False + + try: + result = subprocess.run([ + "gdbus", "call", "--session", + "--dest", self.service_name, + "--object-path", self.main_path, + "--method", "org.gnome.Orca.Service.PresentMessage", + str(text) + ], check=True, capture_output=True, text=True, timeout=5) + return "true" in result.stdout.lower() + except (subprocess.CalledProcessError, subprocess.TimeoutExpired, FileNotFoundError): + return False + + def braille(self, text, **options): + """ + Display text on braille display through Orca + + Orca's PresentMessage method handles both speech and braille automatically + based on user preferences. + + Args: + text (str): The text to display + **options: Additional options (unused) + + Returns: + bool: True if successful, False otherwise + """ + return self.speak(text) + + def silence(self): + """Interrupt current speech output""" + if not self.is_active(): + return False + + try: + # Try to execute InterruptSpeech command if available + result = subprocess.run([ + "gdbus", "call", "--session", + "--dest", self.service_name, + "--object-path", self.main_path + "/Speech", + "--method", "org.gnome.Orca.Module.ExecuteCommand", + "InterruptSpeech", "false" + ], check=True, capture_output=True, text=True, timeout=2) + return True + except (subprocess.CalledProcessError, subprocess.TimeoutExpired, FileNotFoundError): + return False + + +output_class = Orca \ No newline at end of file diff --git a/readme.rst b/readme.rst index 3739c68..b537a75 100644 --- a/readme.rst +++ b/readme.rst @@ -26,6 +26,7 @@ Speech: - PC Talker - ZDSR - Microsoft Speech API +- Orca Screen Reader (Linux) Braille: @@ -35,4 +36,5 @@ Braille: - Window Eyes - System Access - Supernova and other Dolphin products +- Orca Screen Reader (Linux)