speculative fixes for hardware speech.
This commit is contained in:
@@ -4,5 +4,5 @@
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
version = "2026.05.22"
|
||||
version = "2026.05.23"
|
||||
code_name = "testing"
|
||||
|
||||
@@ -51,6 +51,8 @@ class hardware_serial_driver(speech_driver):
|
||||
)
|
||||
self._open_serial_port()
|
||||
self._is_initialized = self.serial_port is not None
|
||||
if not self._is_initialized:
|
||||
raise RuntimeError("hardware speech device is not available")
|
||||
if self._is_initialized:
|
||||
self._stop_worker = False
|
||||
self.worker_thread = threading.Thread(
|
||||
@@ -124,6 +126,7 @@ class hardware_serial_driver(speech_driver):
|
||||
self._debug(
|
||||
"Hardware speech device not found",
|
||||
debug.DebugLevel.ERROR,
|
||||
on_any_level=True,
|
||||
)
|
||||
return
|
||||
try:
|
||||
@@ -140,10 +143,16 @@ class hardware_serial_driver(speech_driver):
|
||||
termios.tcsetattr(port, termios.TCSANOW, attrs)
|
||||
self.serial_port = port
|
||||
self.device = device
|
||||
self._debug(
|
||||
f"Hardware speech device opened: {device}",
|
||||
debug.DebugLevel.INFO,
|
||||
on_any_level=True,
|
||||
)
|
||||
except OSError as error:
|
||||
self._debug(
|
||||
f"Hardware speech device open failed: {device}: {error}",
|
||||
debug.DebugLevel.ERROR,
|
||||
on_any_level=True,
|
||||
)
|
||||
self.serial_port = None
|
||||
|
||||
@@ -173,12 +182,13 @@ class hardware_serial_driver(speech_driver):
|
||||
self._debug(
|
||||
f"Hardware speech write failed: {error}",
|
||||
debug.DebugLevel.ERROR,
|
||||
on_any_level=True,
|
||||
)
|
||||
|
||||
def _resolve_device(self, device):
|
||||
if device and device != "auto":
|
||||
return device
|
||||
for pattern in ("/dev/ttyACM*", "/dev/ttyUSB*"):
|
||||
for pattern in ("/dev/ttyACM*", "/dev/ttyUSB*", "/dev/ttyS*"):
|
||||
matches = sorted(glob.glob(pattern))
|
||||
if matches:
|
||||
return matches[0]
|
||||
@@ -205,10 +215,10 @@ class hardware_serial_driver(speech_driver):
|
||||
value = max(0.0, min(1.0, value))
|
||||
return int(round(minimum + value * (maximum - minimum)))
|
||||
|
||||
def _debug(self, message, level):
|
||||
def _debug(self, message, level, on_any_level=False):
|
||||
try:
|
||||
self.env["runtime"]["DebugManager"].write_debug_out(
|
||||
message, level
|
||||
message, level, on_any_level=on_any_level
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import os
|
||||
import select
|
||||
import time
|
||||
from unittest.mock import ANY
|
||||
from unittest.mock import Mock
|
||||
|
||||
import pytest
|
||||
@@ -103,6 +104,48 @@ def test_litetalk_driver_writes_settings_and_cancel(serial_pair):
|
||||
speech_driver.shutdown()
|
||||
|
||||
|
||||
def test_auto_device_detection_includes_classic_serial(
|
||||
monkeypatch, serial_pair
|
||||
):
|
||||
master_fd, slave_name = serial_pair
|
||||
|
||||
def fake_glob(pattern):
|
||||
if pattern == "/dev/ttyS*":
|
||||
return [slave_name]
|
||||
return []
|
||||
|
||||
monkeypatch.setattr(
|
||||
"fenrirscreenreader.speechDriver.hardwareSerialDriver.glob.glob",
|
||||
fake_glob,
|
||||
)
|
||||
speech_driver = litetalkDriver.driver()
|
||||
speech_driver.initialize(build_environment("auto"))
|
||||
try:
|
||||
assert speech_driver.device == slave_name
|
||||
speech_driver.speak("Serial")
|
||||
assert read_available(master_fd, 7) == b"Serial\r"
|
||||
finally:
|
||||
speech_driver.shutdown()
|
||||
|
||||
|
||||
def test_auto_device_detection_fails_when_no_serial_device(monkeypatch):
|
||||
monkeypatch.setattr(
|
||||
"fenrirscreenreader.speechDriver.hardwareSerialDriver.glob.glob",
|
||||
lambda pattern: [],
|
||||
)
|
||||
speech_driver = litetalkDriver.driver()
|
||||
|
||||
with pytest.raises(RuntimeError, match="hardware speech device"):
|
||||
speech_driver.initialize(build_environment("auto"))
|
||||
|
||||
debug_manager = speech_driver.env["runtime"]["DebugManager"]
|
||||
debug_manager.write_debug_out.assert_called_with(
|
||||
"Hardware speech device not found",
|
||||
ANY,
|
||||
on_any_level=True,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("driver_class", [doubletalkDriver, tripletalkDriver])
|
||||
def test_litetalk_compatible_alias_drivers(driver_class, serial_pair):
|
||||
speech_driver, master_fd = initialized_driver(driver_class, serial_pair)
|
||||
|
||||
Reference in New Issue
Block a user