Attempt to make auto at least somewhat more reliable. Recommend that device be explicitly set if possible.
This commit is contained in:
@@ -460,13 +460,15 @@ setting <action> [parameters]
|
|||||||
- `speech#voice=voice_name` - Voice selection (e.g., "en-us+f3")
|
- `speech#voice=voice_name` - Voice selection (e.g., "en-us+f3")
|
||||||
- `speech#module=module_name` - TTS module (e.g., "espeak-ng")
|
- `speech#module=module_name` - TTS module (e.g., "espeak-ng")
|
||||||
- `speech#driver=driver_name` - Speech driver (speechdDriver/genericDriver/dectalkDriver/litetalkDriver/doubletalkDriver/tripletalkDriver)
|
- `speech#driver=driver_name` - Speech driver (speechdDriver/genericDriver/dectalkDriver/litetalkDriver/doubletalkDriver/tripletalkDriver)
|
||||||
- `speech#hardware_device=auto` - Hardware synth serial device for dectalkDriver/litetalkDriver
|
- `speech#hardware_device=/dev/ttyS0` - Hardware synth serial device for dectalkDriver/litetalkDriver
|
||||||
- `speech#hardware_baud_rate=9600` - Hardware synth serial baud rate
|
- `speech#hardware_baud_rate=9600` - Hardware synth serial baud rate
|
||||||
- `speech#history_size=50` - Number of spoken items kept in runtime speech history
|
- `speech#history_size=50` - Number of spoken items kept in runtime speech history
|
||||||
|
|
||||||
USB hardware synths are supported only when Linux exposes them as a serial tty
|
USB hardware synths are supported only when Linux exposes them as a serial tty
|
||||||
such as `/dev/ttyACM0` or `/dev/ttyUSB0`. A USB-only TripleTalk with no tty
|
such as `/dev/ttyACM0` or `/dev/ttyUSB0`. A USB-only TripleTalk with no tty
|
||||||
device would require a separate USB protocol driver.
|
device would require a separate USB protocol driver. Use an explicit
|
||||||
|
`speech#hardware_device` path for stable hardware speech; `auto` is limited to
|
||||||
|
devices that respond to a driver-specific probe.
|
||||||
- `speech#auto_read_incoming=True/False` - Auto-read new text
|
- `speech#auto_read_incoming=True/False` - Auto-read new text
|
||||||
|
|
||||||
*Sound Settings:*
|
*Sound Settings:*
|
||||||
|
|||||||
@@ -79,12 +79,13 @@ volume=1.0
|
|||||||
# Used by dectalkDriver, litetalkDriver, doubletalkDriver, and tripletalkDriver.
|
# Used by dectalkDriver, litetalkDriver, doubletalkDriver, and tripletalkDriver.
|
||||||
# USB serial devices are supported if Linux exposes them as /dev/ttyACM*
|
# USB serial devices are supported if Linux exposes them as /dev/ttyACM*
|
||||||
# or /dev/ttyUSB*. USB-only synths with no tty device need a separate driver.
|
# or /dev/ttyUSB*. USB-only synths with no tty device need a separate driver.
|
||||||
# auto checks /dev/ttyACM* first, then /dev/ttyUSB*.
|
# Set an explicit device for stable hardware speech. auto only uses devices
|
||||||
|
# that respond to a driver-specific probe and may fail on silent synths.
|
||||||
# Examples:
|
# Examples:
|
||||||
# hardware_device=/dev/ttyACM0 # RPITalk USB gadget mode
|
# hardware_device=/dev/ttyACM0 # RPITalk USB gadget mode
|
||||||
# hardware_device=/dev/ttyUSB0 # USB serial adapter
|
# hardware_device=/dev/ttyUSB0 # USB serial adapter
|
||||||
# hardware_device=/dev/ttyS0 # built-in serial port
|
# hardware_device=/dev/ttyS0 # built-in serial port
|
||||||
hardware_device=auto
|
hardware_device=/dev/ttyS0
|
||||||
|
|
||||||
# Serial baud rate for hardware speech synthesizers.
|
# Serial baud rate for hardware speech synthesizers.
|
||||||
hardware_baud_rate=9600
|
hardware_baud_rate=9600
|
||||||
|
|||||||
+4
-4
@@ -1684,15 +1684,15 @@ the pico module:
|
|||||||
language=de-DE
|
language=de-DE
|
||||||
....
|
....
|
||||||
|
|
||||||
Hardware speech drivers use a serial device. The default `+auto+` checks
|
Hardware speech drivers use a serial device. Set an explicit path for stable
|
||||||
`+/dev/ttyACM*+` first, then `+/dev/ttyUSB*+`. Set an explicit path for
|
systems. `+auto+` is limited to devices that respond to a driver-specific
|
||||||
stable systems.
|
probe and may fail on silent synths.
|
||||||
|
|
||||||
....
|
....
|
||||||
hardware_device=auto
|
|
||||||
hardware_device=/dev/ttyACM0
|
hardware_device=/dev/ttyACM0
|
||||||
hardware_device=/dev/ttyUSB0
|
hardware_device=/dev/ttyUSB0
|
||||||
hardware_device=/dev/ttyS0
|
hardware_device=/dev/ttyS0
|
||||||
|
hardware_device=auto
|
||||||
....
|
....
|
||||||
|
|
||||||
Hardware speech drivers use 9600 baud by default.
|
Hardware speech drivers use 9600 baud by default.
|
||||||
|
|||||||
+6
-5
@@ -101,7 +101,7 @@ driver=speechdDriver
|
|||||||
rate=0.5
|
rate=0.5
|
||||||
pitch=0.5
|
pitch=0.5
|
||||||
volume=1.0
|
volume=1.0
|
||||||
hardware_device=auto
|
hardware_device=/dev/ttyS0
|
||||||
hardware_baud_rate=9600
|
hardware_baud_rate=9600
|
||||||
history_size=50
|
history_size=50
|
||||||
|
|
||||||
@@ -341,10 +341,11 @@ Fenrir automatically detects and provides audio feedback for progress indicators
|
|||||||
- **doubletalkDriver** - Serial DoubleTalk LT-compatible hardware speech
|
- **doubletalkDriver** - Serial DoubleTalk LT-compatible hardware speech
|
||||||
- **tripletalkDriver** - Serial TripleTalk-compatible hardware speech
|
- **tripletalkDriver** - Serial TripleTalk-compatible hardware speech
|
||||||
|
|
||||||
For hardware speech, set `speech#hardware_device` to `auto` or an explicit
|
For hardware speech, set `speech#hardware_device` to an explicit serial path.
|
||||||
serial path. RPITalk gadget mode usually appears as `/dev/ttyACM0`; USB serial
|
RPITalk gadget mode usually appears as `/dev/ttyACM0`; USB serial adapters
|
||||||
adapters usually appear as `/dev/ttyUSB0`; built-in serial ports may be
|
usually appear as `/dev/ttyUSB0`; built-in serial ports may be `/dev/ttyS0`.
|
||||||
`/dev/ttyS0`. The default baud rate is `9600`. `doubletalkDriver` targets
|
The default baud rate is `9600`. `auto` is limited to devices that respond to a
|
||||||
|
driver-specific probe and may fail on silent synths. `doubletalkDriver` targets
|
||||||
DoubleTalk LT-style serial devices, not the internal DoubleTalk PC ISA card.
|
DoubleTalk LT-style serial devices, not the internal DoubleTalk PC ISA card.
|
||||||
USB TripleTalk devices work only if Linux exposes them as a serial tty such as
|
USB TripleTalk devices work only if Linux exposes them as a serial tty such as
|
||||||
`/dev/ttyACM0` or `/dev/ttyUSB0`; USB-only models with no tty device need a
|
`/dev/ttyACM0` or `/dev/ttyUSB0`; USB-only models with no tty device need a
|
||||||
|
|||||||
+2
-2
@@ -927,11 +927,11 @@ Select the language you want Fenrir to use.
|
|||||||
language=english-us
|
language=english-us
|
||||||
Values: Text, see your TTS synths documentation what is available.
|
Values: Text, see your TTS synths documentation what is available.
|
||||||
|
|
||||||
Hardware speech drivers use a serial device. The default ''auto'' checks /dev/ttyACM* first, then /dev/ttyUSB*. Set an explicit path for stable systems.
|
Hardware speech drivers use a serial device. Set an explicit path for stable systems. ''auto'' is limited to devices that respond to a driver-specific probe and may fail on silent synths.
|
||||||
hardware_device=auto
|
|
||||||
hardware_device=/dev/ttyACM0
|
hardware_device=/dev/ttyACM0
|
||||||
hardware_device=/dev/ttyUSB0
|
hardware_device=/dev/ttyUSB0
|
||||||
hardware_device=/dev/ttyS0
|
hardware_device=/dev/ttyS0
|
||||||
|
hardware_device=auto
|
||||||
|
|
||||||
Hardware speech drivers use 9600 baud by default.
|
Hardware speech drivers use 9600 baud by default.
|
||||||
hardware_baud_rate=9600
|
hardware_baud_rate=9600
|
||||||
|
|||||||
@@ -166,8 +166,6 @@ class hardware_serial_driver(speech_driver):
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
fallback_device = None
|
|
||||||
fallback_port = None
|
|
||||||
for device in devices:
|
for device in devices:
|
||||||
port = self._open_configured_serial_port(device)
|
port = self._open_configured_serial_port(device)
|
||||||
if port is None:
|
if port is None:
|
||||||
@@ -178,28 +176,20 @@ class hardware_serial_driver(speech_driver):
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
if self._probe_serial_port(port):
|
if self._probe_serial_port(port):
|
||||||
if fallback_port is not None:
|
|
||||||
self._close_port(fallback_port)
|
|
||||||
self._activate_serial_port(device, port, probe_matched=True)
|
self._activate_serial_port(device, port, probe_matched=True)
|
||||||
return
|
return
|
||||||
if fallback_port is None:
|
|
||||||
fallback_device = device
|
|
||||||
fallback_port = port
|
|
||||||
else:
|
|
||||||
self._close_port(port)
|
self._close_port(port)
|
||||||
|
|
||||||
if fallback_port is not None:
|
if auto_detect and self.hardware_probe_command:
|
||||||
self._debug(
|
self._debug(
|
||||||
"Hardware speech probe did not identify a synth; "
|
"Hardware speech auto did not identify a synth; set "
|
||||||
f"falling back to {fallback_device}",
|
"speech#hardware_device to the known serial device",
|
||||||
debug.DebugLevel.WARNING,
|
debug.DebugLevel.ERROR,
|
||||||
on_any_level=True,
|
on_any_level=True,
|
||||||
)
|
)
|
||||||
self._activate_serial_port(
|
|
||||||
fallback_device, fallback_port, probe_matched=False
|
|
||||||
)
|
|
||||||
|
|
||||||
def _open_configured_serial_port(self, device):
|
def _open_configured_serial_port(self, device):
|
||||||
|
port = None
|
||||||
try:
|
try:
|
||||||
port = os.open(device, os.O_RDWR | os.O_NOCTTY)
|
port = os.open(device, os.O_RDWR | os.O_NOCTTY)
|
||||||
tty.setraw(port)
|
tty.setraw(port)
|
||||||
@@ -214,6 +204,7 @@ class hardware_serial_driver(speech_driver):
|
|||||||
termios.tcsetattr(port, termios.TCSANOW, attrs)
|
termios.tcsetattr(port, termios.TCSANOW, attrs)
|
||||||
return port
|
return port
|
||||||
except (OSError, termios.error) as error:
|
except (OSError, termios.error) as error:
|
||||||
|
self._close_port(port)
|
||||||
self._debug(
|
self._debug(
|
||||||
f"Hardware speech device open failed: {device}: {error}",
|
f"Hardware speech device open failed: {device}: {error}",
|
||||||
debug.DebugLevel.ERROR,
|
debug.DebugLevel.ERROR,
|
||||||
@@ -331,7 +322,11 @@ class hardware_serial_driver(speech_driver):
|
|||||||
)
|
)
|
||||||
return [device]
|
return [device]
|
||||||
devices = []
|
devices = []
|
||||||
for pattern in ("/dev/ttyACM*", "/dev/ttyUSB*", "/dev/ttyS*"):
|
for pattern in (
|
||||||
|
"/dev/serial/by-id/*",
|
||||||
|
"/dev/ttyACM*",
|
||||||
|
"/dev/ttyUSB*",
|
||||||
|
):
|
||||||
matches = sorted(glob.glob(pattern))
|
matches = sorted(glob.glob(pattern))
|
||||||
self._debug(
|
self._debug(
|
||||||
f"Hardware speech auto scan {pattern}: {matches}",
|
f"Hardware speech auto scan {pattern}: {matches}",
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ def test_litetalk_driver_writes_settings_and_cancel(serial_pair):
|
|||||||
speech_driver.shutdown()
|
speech_driver.shutdown()
|
||||||
|
|
||||||
|
|
||||||
def test_auto_device_detection_includes_classic_serial(
|
def test_configured_device_supports_classic_serial(
|
||||||
monkeypatch, serial_pair
|
monkeypatch, serial_pair
|
||||||
):
|
):
|
||||||
master_fd, slave_name = serial_pair
|
master_fd, slave_name = serial_pair
|
||||||
@@ -120,11 +120,11 @@ def test_auto_device_detection_includes_classic_serial(
|
|||||||
fake_glob,
|
fake_glob,
|
||||||
)
|
)
|
||||||
speech_driver = litetalkDriver.driver()
|
speech_driver = litetalkDriver.driver()
|
||||||
speech_driver.initialize(build_environment("auto"))
|
speech_driver.initialize(build_environment(slave_name))
|
||||||
try:
|
try:
|
||||||
assert speech_driver.device == slave_name
|
assert speech_driver.device == slave_name
|
||||||
speech_driver.speak("Serial")
|
speech_driver.speak("Serial")
|
||||||
assert read_available(master_fd, 9) == b"\x01ISerial\r"
|
assert read_available(master_fd, 7) == b"Serial\r"
|
||||||
finally:
|
finally:
|
||||||
speech_driver.shutdown()
|
speech_driver.shutdown()
|
||||||
|
|
||||||
@@ -219,7 +219,7 @@ def test_auto_device_detection_prefers_probe_response(monkeypatch):
|
|||||||
speech_driver.shutdown()
|
speech_driver.shutdown()
|
||||||
|
|
||||||
|
|
||||||
def test_auto_device_detection_falls_back_without_probe_response(
|
def test_auto_device_detection_fails_without_probe_response(
|
||||||
monkeypatch
|
monkeypatch
|
||||||
):
|
):
|
||||||
opened_ports = []
|
opened_ports = []
|
||||||
@@ -265,13 +265,12 @@ def test_auto_device_detection_falls_back_without_probe_response(
|
|||||||
)
|
)
|
||||||
|
|
||||||
speech_driver = litetalkDriver.driver()
|
speech_driver = litetalkDriver.driver()
|
||||||
|
with pytest.raises(RuntimeError, match="hardware speech device"):
|
||||||
speech_driver.initialize(build_environment("auto"))
|
speech_driver.initialize(build_environment("auto"))
|
||||||
try:
|
|
||||||
assert opened_ports == ["/dev/ttyUSB0", "/dev/ttyUSB1"]
|
assert opened_ports == ["/dev/ttyUSB0", "/dev/ttyUSB1"]
|
||||||
assert closed_ports == [2]
|
assert closed_ports == [1, 2]
|
||||||
assert speech_driver.device == "/dev/ttyUSB0"
|
assert speech_driver.device == "auto"
|
||||||
finally:
|
|
||||||
speech_driver.shutdown()
|
|
||||||
|
|
||||||
|
|
||||||
def test_auto_device_detection_skips_termios_failures(monkeypatch):
|
def test_auto_device_detection_skips_termios_failures(monkeypatch):
|
||||||
@@ -280,10 +279,8 @@ def test_auto_device_detection_skips_termios_failures(monkeypatch):
|
|||||||
|
|
||||||
monkeypatch.setattr(
|
monkeypatch.setattr(
|
||||||
"fenrirscreenreader.speechDriver.hardwareSerialDriver.glob.glob",
|
"fenrirscreenreader.speechDriver.hardwareSerialDriver.glob.glob",
|
||||||
lambda pattern: ["/dev/ttyUSB0"]
|
lambda pattern: ["/dev/ttyUSB0", "/dev/ttyUSB1"]
|
||||||
if pattern == "/dev/ttyUSB*"
|
if pattern == "/dev/ttyUSB*"
|
||||||
else ["/dev/ttyS0"]
|
|
||||||
if pattern == "/dev/ttyS*"
|
|
||||||
else [],
|
else [],
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -293,7 +290,7 @@ def test_auto_device_detection_skips_termios_failures(monkeypatch):
|
|||||||
return port
|
return port
|
||||||
|
|
||||||
def fake_tcgetattr(port):
|
def fake_tcgetattr(port):
|
||||||
if port == 101:
|
if port == 100:
|
||||||
raise termios.error(5, "Input/output error")
|
raise termios.error(5, "Input/output error")
|
||||||
return [0, 0, 0, 0, 0, 0, [0] * 32]
|
return [0, 0, 0, 0, 0, 0, [0] * 32]
|
||||||
|
|
||||||
@@ -331,12 +328,12 @@ def test_auto_device_detection_skips_termios_failures(monkeypatch):
|
|||||||
)
|
)
|
||||||
|
|
||||||
speech_driver = litetalkDriver.driver()
|
speech_driver = litetalkDriver.driver()
|
||||||
|
with pytest.raises(RuntimeError, match="hardware speech device"):
|
||||||
speech_driver.initialize(build_environment("auto"))
|
speech_driver.initialize(build_environment("auto"))
|
||||||
try:
|
|
||||||
assert opened_ports == [("/dev/ttyUSB0", 100), ("/dev/ttyS0", 101)]
|
assert opened_ports == [("/dev/ttyUSB0", 100), ("/dev/ttyUSB1", 101)]
|
||||||
assert speech_driver.device == "/dev/ttyUSB0"
|
assert closed_ports == [100, 101]
|
||||||
finally:
|
assert speech_driver.device == "auto"
|
||||||
speech_driver.shutdown()
|
|
||||||
|
|
||||||
|
|
||||||
def test_auto_device_detection_fails_when_no_serial_device(monkeypatch):
|
def test_auto_device_detection_fails_when_no_serial_device(monkeypatch):
|
||||||
|
|||||||
Reference in New Issue
Block a user