Fixed a bug that could leave you without speech if changing the active window.

This commit is contained in:
Storm Dragon
2026-07-25 05:05:46 -04:00
parent 6ec512ea33
commit 57e9661468
3 changed files with 126 additions and 0 deletions
@@ -6,12 +6,121 @@ from unittest import mock
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
from cthulhu import guilabels
from cthulhu import settings
from cthulhu import settings_manager
from cthulhu import speech_and_verbosity_manager
from cthulhu import speechdispatcherfactory
from cthulhu import speechserver
class SpeechDispatcherVoiceSelectionRegressionTests(unittest.TestCase):
def test_session_speech_settings_override_profile_reload(self):
manager = settings_manager.SettingsManager.__new__(
settings_manager.SettingsManager
)
manager._session_settings = {
"speechServerInfo": ["doubletalk", "doubletalk"],
"voices": {
settings.DEFAULT_VOICE: {
"family": {
speechserver.VoiceFamily.NAME: "Perfect Paul",
speechserver.VoiceFamily.LANG: "en",
speechserver.VoiceFamily.DIALECT: "US",
speechserver.VoiceFamily.VARIANT: "none",
}
}
},
}
manager.customizedSettings = {}
manager._getCustomizedSettings = mock.Mock(return_value={})
manager._logRoleSoundPresentationChange = mock.Mock()
saved_settings = {
"speechServerInfo": ["rhvoice", "rhvoice"],
"voices": {
settings.DEFAULT_VOICE: {
"family": {
speechserver.VoiceFamily.NAME: "Previous Voice",
}
}
},
}
with mock.patch.object(
settings,
"speechServerInfo",
saved_settings["speechServerInfo"],
), mock.patch.object(settings, "voices", saved_settings["voices"]):
manager._setSettingsRuntime(saved_settings)
self.assertEqual(
["doubletalk", "doubletalk"],
settings.speechServerInfo,
)
self.assertEqual(
"Perfect Paul",
settings.voices[settings.DEFAULT_VOICE]["family"][
speechserver.VoiceFamily.NAME
],
)
def test_quick_module_switch_preserves_module_and_voice_for_session(self):
current_module = {"name": "rhvoice"}
perfect_paul = speechserver.VoiceFamily(
{
speechserver.VoiceFamily.NAME: "Perfect Paul",
speechserver.VoiceFamily.LANG: "en",
speechserver.VoiceFamily.DIALECT: "US",
speechserver.VoiceFamily.VARIANT: "none",
}
)
server = mock.Mock()
server.list_output_modules.return_value = ["rhvoice", "doubletalk"]
server.getOutputModule.side_effect = lambda: current_module["name"]
server.setOutputModule.side_effect = (
lambda module: current_module.update(name=module)
)
server.getVoiceFamilies.return_value = [perfect_paul]
session_settings = mock.Mock()
app = mock.Mock()
app.getSettingsManager.return_value = session_settings
manager = speech_and_verbosity_manager.SpeechAndVerbosityManager.__new__(
speech_and_verbosity_manager.SpeechAndVerbosityManager
)
manager.app = app
manager._get_server = mock.Mock(return_value=server)
manager._present_message = mock.Mock()
runtime_voices = {
settings.DEFAULT_VOICE: {
"family": {
speechserver.VoiceFamily.NAME: "Previous Voice",
}
}
}
with mock.patch.object(settings, "voices", runtime_voices), \
mock.patch.object(
settings,
"speechServerInfo",
["rhvoice", "rhvoice"],
):
manager._adjust_module(script=None, decrease=False)
session_values = {
call.args[0]: call.args[1]
for call in session_settings.set_session_setting.call_args_list
}
self.assertEqual(
["doubletalk", "doubletalk"],
session_values["speechServerInfo"],
)
self.assertEqual(
"Perfect Paul",
session_values["voices"][settings.DEFAULT_VOICE]["family"][
speechserver.VoiceFamily.NAME
],
)
def test_output_module_updates_the_synthetic_default_voice_name(self):
server = speechdispatcherfactory.SpeechServer.__new__(
speechdispatcherfactory.SpeechServer