(self, text: str, lang: str, called_from: Literal["src", "dest"])
| 861 | |
| 862 | @background_task |
| 863 | async def _on_speech(self, text: str, lang: str, called_from: Literal["src", "dest"]): |
| 864 | # Retry loading TTS provider |
| 865 | if self.speech_provider_failed: |
| 866 | self.load_tts() |
| 867 | return |
| 868 | |
| 869 | if not text or not self.provider["tts"] or not self.player: |
| 870 | return |
| 871 | |
| 872 | # Set loading state and current speech to update UI |
| 873 | self.speech_loading = True |
| 874 | self.current_speech = {"text": text, "lang": lang, "called_from": called_from} |
| 875 | self._check_speech_enabled() |
| 876 | |
| 877 | if called_from == "src": # Show spinner on button |
| 878 | self.src_speech_btn.loading() |
| 879 | else: |
| 880 | self.dest_speech_btn.loading() |
| 881 | |
| 882 | # Download speech |
| 883 | try: |
| 884 | file_ = await self.provider["tts"].speech(self.current_speech["text"], self.current_speech["lang"]) |
| 885 | uri = "file://" + file_.name |
| 886 | self.player.set_property("uri", uri) |
| 887 | self.player.set_state(Gst.State.PLAYING) |
| 888 | self.add_tick_callback(self._gst_progress_timeout) |
| 889 | file_.close() |
| 890 | |
| 891 | except (RequestError, ProviderError) as exc: |
| 892 | logging.error(exc) |
| 893 | |
| 894 | text = _("Text-to-Speech failed") |
| 895 | action: _NotificationAction | None = None |
| 896 | |
| 897 | if isinstance(exc, RequestError): |
| 898 | text = _("Text-to-Speech failed, check for network issues") |
| 899 | |
| 900 | if self.current_speech: |
| 901 | called_from = self.current_speech["called_from"] |
| 902 | action = { |
| 903 | "label": _("Retry"), |
| 904 | "name": "win.listen-src" if called_from == "src" else "win.listen-dest", |
| 905 | } |
| 906 | |
| 907 | button_text = _("Text-to-Speech failed. Retry?") |
| 908 | if called_from == "src": |
| 909 | self.src_speech_btn.error(button_text) |
| 910 | else: |
| 911 | self.dest_speech_btn.error(button_text) |
| 912 | |
| 913 | self.send_notification(text, action=action) |
| 914 | self._speech_reset(False) |
| 915 | |
| 916 | def _speech_reset(self, set_ready: bool = True): |
| 917 | if not self.player: |
no test coverage detected