diff --git a/stt_voice_messages/configs.py b/stt_voice_messages/configs.py deleted file mode 100644 index c7d505c..0000000 --- a/stt_voice_messages/configs.py +++ /dev/null @@ -1,108 +0,0 @@ -# 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 . - -import logging -import typing - -from gajim.common.app import Any -from gajim.plugins.plugins_i18n import _ - -from .models import openai_whisper -from .stt_voice_messages import STTVoiceMessagesPlugin - -log = logging.getLogger('gajim.p.stt_voice_messages_config') - -SUPPORTED_MODELS: dict[str, dict[str, typing.Union[list[str], Any, str]]] = { - 'model_openaiwhisper': { - 'moduls': ['whisper'], - 'class': openai_whisper.WhisperModel, - 'name': 'OpenAI Whisper' - }, - 'model_ctranslate2': { - 'moduls': ['ctranslate2'], - 'class': None, - 'name': _('CTranslate2') - }, - 'model_faster-whisper': { - 'moduls': ['faster-whisper'], - 'class': None, - 'name:': _('Faster-Whisper') - }, - 'model_distill': { - 'moduls': ['transformers', 'accelerate', 'datasets[audio]'], - 'class': None, - 'name': _('Distill') - } -} - - -class Configuration: - def __init__(self, plugin: STTVoiceMessagesPlugin): - self.plugin = plugin - self._available_models: dict[ - str, dict[str, typing.Union[list[str], Any, str]]] = {} - self.check_available_moduls() - - @property - def available_models(self) -> dict[str, dict[str, typing.Union[list[str], Any, str]]]: - return self._available_models - - def on_setting(self, value: Any, data: Any) -> None: - if isinstance(value, str): - value.strip() - log.debug('plugin config before:\n %s', self.plugin.config.data) - self.plugin.config[data] = value - log.debug('plugin config after:\n %s', self.plugin.config.data) - - def on_set_model(self, value: Any, data: Any) -> None: - if isinstance(value, str): - value.strip() - log.debug('plugin config before:\n %s', self.plugin.config.data) - self.plugin.config['model_class'] = self._available_models[value][ - 'class'] - self.on_setting(value, data) - log.debug('plugin config after:\n %s', self.plugin.config.data) - - @staticmethod - def is_module_available(module: str) -> bool: - try: - __import__(module) - return True - except ModuleNotFoundError: - log.debug('Could not find module %s', module) - return False - except ImportError as ex: - log.debug(str(ex)) - return False - - def check_available_moduls(self): - for model in SUPPORTED_MODELS: - available = True - for modul in SUPPORTED_MODELS[model]['moduls']: - if not self.is_module_available(modul): - available = False - continue - if available: - self._available_models[model] = SUPPORTED_MODELS[model] - - if (self.plugin.config.data['model_class'] is None - and len(self._available_models) > 0): - model = list(self._available_models)[0] - self.on_set_model(model, 'model') - log.debug('Choose first available model!') - else: - log.debug('Available model already chosen!') - - log.debug('models = %s', self._available_models) diff --git a/stt_voice_messages/gtk/config_dialog.py b/stt_voice_messages/gtk/config_dialog.py index cf25efe..4592d80 100644 --- a/stt_voice_messages/gtk/config_dialog.py +++ b/stt_voice_messages/gtk/config_dialog.py @@ -16,6 +16,7 @@ from __future__ import annotations import logging +import typing from pathlib import Path from typing import TYPE_CHECKING @@ -23,6 +24,7 @@ import whisper from gi.repository import Gtk from gajim.common import app +from gajim.common.app import Any from gajim.gtk.builder import get_builder from gajim.gtk.const import Setting, SettingKind, SettingType from gajim.gtk.settings import SettingsBox @@ -30,7 +32,7 @@ from gajim.gtk.sidebar_switcher import SideBarSwitcher from gajim.plugins.helpers import get_builder from gajim.plugins.plugins_i18n import _ -from ..configs import Configuration +from ..models import openai_whisper if TYPE_CHECKING: from ..stt_voice_messages import STTVoiceMessagesPlugin @@ -38,6 +40,95 @@ if TYPE_CHECKING: log = logging.getLogger('gajim.p.stt_voice_messages_config_dialog') +SUPPORTED_MODELS: dict[str, dict[str, typing.Union[list[str], Any, str]]] = { + 'model_openaiwhisper': { + 'moduls': ['whisper'], + 'class': openai_whisper.WhisperModel, + 'name': 'OpenAI Whisper' + }, + 'model_ctranslate2': { + 'moduls': ['ctranslate2'], + 'class': None, + 'name': _('CTranslate2') + }, + 'model_faster-whisper': { + 'moduls': ['faster-whisper'], + 'class': None, + 'name:': _('Faster-Whisper') + }, + 'model_distill': { + 'moduls': ['transformers', 'accelerate', 'datasets[audio]'], + 'class': None, + 'name': _('Distill') + } +} + + +class Configuration: + def __init__(self, plugin: STTVoiceMessagesPlugin): + self._plugin = plugin + self._available_models: dict[ + str, dict[str, typing.Union[list[str], Any, str]]] = {} + self.check_available_moduls() + + @property + def plugin(self) -> STTVoiceMessagesPlugin: + return self._plugin + + @property + def available_models(self) -> dict[str, dict[str, typing.Union[list[str], Any, str]]]: + return self._available_models + + def on_setting(self, value: Any, data: Any) -> None: + if isinstance(value, str): + value.strip() + log.debug('plugin config before:\n %s', self.plugin.config.data) + self.plugin.config[data] = value + log.debug('plugin config after:\n %s', self.plugin.config.data) + + def on_set_model(self, value: Any, data: Any) -> None: + if isinstance(value, str): + value.strip() + log.debug('plugin config before:\n %s', self.plugin.config.data) + self.plugin.config['model_class'] = self._available_models[value][ + 'class'] + self.on_setting(value, data) + log.debug('plugin config after:\n %s', self.plugin.config.data) + + @staticmethod + def is_module_available(module: str) -> bool: + try: + __import__(module) + return True + except ModuleNotFoundError: + log.debug('Could not find module %s', module) + return False + except ImportError as ex: + log.debug(str(ex)) + return False + + def check_available_moduls(self): + for model in SUPPORTED_MODELS: + available = True + for modul in SUPPORTED_MODELS[model]['moduls']: + if not self.is_module_available(modul): + available = False + continue + if available: + self._available_models[model] = SUPPORTED_MODELS[model] + + if (self.plugin.config.data['model_class'] is None + and len(self._available_models) > 0): + model = list(self._available_models)[0] + self.on_set_model(model, 'model') + log.debug('Choose first available model!') + else: + log.debug('Available model already chosen!') + + log.debug('models = %s', self._available_models) + + + class PreferenceBox(SettingsBox): def __init__(self, settings: list[Setting]) -> None: SettingsBox.__init__(self, None) @@ -52,7 +143,7 @@ class PreferenceBox(SettingsBox): class STTVoiceMessagesConfigDialog(Gtk.ApplicationWindow): - def __init__(self, plugin: STTVoiceMessagesPlugin, parent: Gtk.Window) -> None: + def __init__(self, config: Configuration, parent: Gtk.Window) -> None: Gtk.ApplicationWindow.__init__(self) self.set_application(app.app) @@ -72,45 +163,47 @@ class STTVoiceMessagesConfigDialog(Gtk.ApplicationWindow): self._ui.grid.attach(side_bar_switcher, 0, 0, 1, 1) self.add(self._ui.grid) + self.config = config + self.plugin = self.config.plugin + prefs: list[tuple[str, type[PreferenceBox]]] = [ ('stt_behaviour', self.STTBehaviour), ('models', self.Models), ('whisper_general', self.OpenAIWhisperGeneral), ] - self._add_prefs(prefs) + self.show_all() class STTBehaviour(PreferenceBox): - def __init__(self, config: Configuration) -> None: + def __init__(self, config_dialog: STTVoiceMessagesConfigDialog) -> None: settings = [ Setting(SettingKind.SWITCH, _('Auto Transcribe'), SettingType.VALUE, - value=config.plugin.config['auto_transcribe'], + value=config_dialog.plugin.config['auto_transcribe'], data='auto_transcribe', - callback=config.on_setting) + callback=config_dialog.config.on_setting) ] PreferenceBox.__init__(self, settings) class Models(PreferenceBox): - def __init__(self, config: Configuration) -> None: + def __init__(self, config_dialog: STTVoiceMessagesConfigDialog) -> None: models: list[tuple[str, str]] = [] - for key, value in config.available_models.items(): - assert value['name'] is str + for key, value in config_dialog.config.available_models.items(): models.append( - (key, value['name']) + (key, str(value['name'])) ) settings = [ Setting(SettingKind.COMBO, _('Speech To Text Model'), SettingType.VALUE, - value=config.plugin.config['model'], + value=config_dialog.plugin.config['model'], data='model', - callback=config.on_set_model, + callback=config_dialog.config.on_set_model, props={'combo_items': models}, desc=_('Choose Model to use')), ] @@ -118,23 +211,23 @@ class STTVoiceMessagesConfigDialog(Gtk.ApplicationWindow): PreferenceBox.__init__(self, settings) class OpenAIWhisperGeneral(PreferenceBox): - def __init__(self, config: Configuration) -> None: + def __init__(self, config_dialog: STTVoiceMessagesConfigDialog) -> None: settings = [ Setting(SettingKind.POPOVER, _('Language Model Size'), SettingType.VALUE, - value=config.plugin.config['whisperai_model_size'], + value=config_dialog.plugin.config['whisperai_model_size'], data='whisperai_model_size', - callback=config.on_setting, + callback=config_dialog.config.on_setting, props={'entries': whisper.available_models()}), Setting(SettingKind.SWITCH, _('Translate'), SettingType.VALUE, - value=config.plugin.config['whisperai_translate'], + value=config_dialog.plugin.config['whisperai_translate'], data='whisperai_translate', - callback=config.on_setting) + callback=config_dialog.config.on_setting) ] PreferenceBox.__init__(self, settings) diff --git a/stt_voice_messages/gtk/sttbox.py b/stt_voice_messages/gtk/sttbox.py index c9b50ff..995ab3f 100644 --- a/stt_voice_messages/gtk/sttbox.py +++ b/stt_voice_messages/gtk/sttbox.py @@ -13,14 +13,15 @@ # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . -from gi.repository import Gtk import logging -from .. import helper +from gi.repository import Gtk from gajim.plugins.gajimplugin import GajimPluginConfig from gajim.plugins.plugins_i18n import _ +from .. import helper + log = logging.getLogger('gajim.p.stt_voice_messages_sttbox') class STTBox(Gtk.Box): @@ -52,9 +53,6 @@ class STTBox(Gtk.Box): self.show_all() - #def update_config(self, config: GajimPluginConfig): - # self._model = config.data['class']() - def _on_transcribe_clicked(self, _button: Gtk.Button) -> None: log.debug('config.data = %s', self._config.data) model_class = self._config.data['model_class'] diff --git a/stt_voice_messages/stt_voice_messages.py b/stt_voice_messages/stt_voice_messages.py index f761c1e..5b78d35 100644 --- a/stt_voice_messages/stt_voice_messages.py +++ b/stt_voice_messages/stt_voice_messages.py @@ -15,17 +15,13 @@ from __future__ import annotations -import logging from functools import partial -from pathlib import Path - -from gi.repository import Gtk from gajim.plugins import GajimPlugin from gajim.plugins.plugins_i18n import _ +from .gtk.config_dialog import * from .gtk.sttbox import STTBox -from .gtk.config_dialog import STTVoiceMessagesConfigDialog log = logging.getLogger('gajim.p.stt_voice_messages') @@ -33,7 +29,9 @@ log = logging.getLogger('gajim.p.stt_voice_messages') class STTVoiceMessagesPlugin(GajimPlugin): def init(self) -> None: self.description = _('Transcribes voice messages to text.') - self.config_dialog = partial(STTVoiceMessagesConfigDialog, self) + self._config = Configuration(self) + self._config.check_available_moduls() + self.config_dialog = partial(STTVoiceMessagesConfigDialog, self._config) self.gui_extension_points = { 'preview_audio': (self._on_preview_audio_created, None),