# This file is part of Gajim. # # Gajim is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . from __future__ import annotations import logging from functools import partial from pathlib import Path from gi.repository import GLib, Gtk from gajim.common import app from gajim.plugins import GajimPlugin from gajim.plugins.plugins_i18n import _ from .gtk.config_dialog import Configuration, STTVoiceMessagesConfigDialog from .gtk.sttbox import STTBox from .models.model_settings import OnnxAsrSettings log = logging.getLogger('gajim.p.stt_voice_messages') _FOCUS_LOSS_UNLOAD_SECONDS = 30 class STTVoiceMessagesPlugin(GajimPlugin): def init(self) -> None: self.description = _('Transcribes voice messages to text.') self.config_default_values = { 'auto_transcribe': (False, ''), 'model_id': ('nemo-parakeet-tdt-0.6b-v3', ''), 'model_path': ('', ''), } self._config = Configuration(self) self.config_dialog = partial(STTVoiceMessagesConfigDialog, self._config) self.gui_extension_points = { 'preview_audio': (self._on_preview_audio_created, None), } self._active_handler_id = 0 self._focus_unload_source = None def activate(self) -> None: if app.window is not None and self._active_handler_id == 0: self._active_handler_id = app.window.connect( 'notify::is-active', self._on_window_active_changed) def deactivate(self) -> None: if self._focus_unload_source is not None: GLib.source_remove(self._focus_unload_source) self._focus_unload_source = None if self._active_handler_id != 0 and app.window is not None: app.window.disconnect(self._active_handler_id) self._active_handler_id = 0 if self._config.is_available: self._config.unload_model() def _on_window_active_changed(self, window: Gtk.Window, _pspec: object, ) -> None: if window.is_active(): if self._focus_unload_source is not None: GLib.source_remove(self._focus_unload_source) self._focus_unload_source = None elif self._focus_unload_source is None: self._focus_unload_source = GLib.timeout_add_seconds( _FOCUS_LOSS_UNLOAD_SECONDS, self._on_focus_unload_fired) def _on_focus_unload_fired(self) -> bool: self._focus_unload_source = None if self._config.is_available: self._config.unload_model() return GLib.SOURCE_REMOVE def _on_preview_audio_created(self, drawing_box: Gtk.Box, control_box: Gtk.Box, audio_file: Path ) -> None: self._drawing_box = drawing_box; self._control_box = control_box; self._audio_file = audio_file.as_posix() self._create_stt_box() def _create_stt_box(self) -> None: self._stt_box = STTBox(self._config, self._audio_file) self._control_box.append(self._stt_box.button) self._drawing_box.append(self._stt_box)