- Removed M2M100 Grammar Correction model completely to reduce bloat/complexity. - Implemented 'Style Prompting' in Settings -> AI Engine to handle punctuation natively via Whisper. - Added Style Presets: Standard (Default), Casual, and Custom. - Optimized Build: Bootstrapper no longer requires transformers/sentencepiece. - Fixed 'torch' NameError in Low VRAM mode. - Fixed Bootstrapper missing dependency detection. - Updated UI to reflect removed features. - Included compiled v1.0.2 Executable in dist/.
126 lines
4.2 KiB
Python
126 lines
4.2 KiB
Python
"""
|
|
Configuration Manager Module.
|
|
=============================
|
|
|
|
Singleton class to manage loading and saving application settings to a JSON file.
|
|
Ensures robustness by merging with defaults and handling file paths correctly.
|
|
"""
|
|
|
|
import json
|
|
import logging
|
|
from pathlib import Path
|
|
from typing import Any, Dict
|
|
|
|
from src.core.paths import get_base_path
|
|
|
|
# Default Configuration
|
|
DEFAULT_SETTINGS = {
|
|
"hotkey": "f8",
|
|
"hotkey_translate": "f10",
|
|
"model_size": "small",
|
|
"input_device": None, # Device ID (int) or Name (str), None = Default
|
|
"save_recordings": False, # Save .wav files for debugging
|
|
"silence_threshold": 0.02, # Amplitude threshold (0.0 - 1.0)
|
|
"silence_duration": 1.0, # Seconds of silence to trigger auto-submit
|
|
"visualizer_style": "line", # 'bar' or 'line'
|
|
"opacity": 1.0, # Window opacity (0.1 - 1.0)
|
|
"ui_scale": 1.0, # Global UI Scale (0.75 - 1.5)
|
|
"always_on_top": True,
|
|
"run_on_startup": False, # (Placeholder)
|
|
|
|
# Window Position
|
|
"overlay_position": "Bottom Center",
|
|
"overlay_offset_x": 0,
|
|
"overlay_offset_y": 0,
|
|
|
|
# Input
|
|
"input_method": "Clipboard Paste", # "Clipboard Paste" or "Simulate Typing"
|
|
"typing_speed": 100, # CPM (Chars Per Minute) if typing
|
|
|
|
# AI - Advanced
|
|
"language": "auto", # "auto" or ISO code
|
|
"task": "transcribe", # "transcribe" or "translate" (to English)
|
|
"compute_device": "auto", # "auto", "cuda", "cpu"
|
|
"compute_type": "int8", # "int8", "float16", "float32"
|
|
"beam_size": 5,
|
|
"best_of": 5,
|
|
"vad_filter": True,
|
|
"no_repeat_ngram_size": 0,
|
|
"condition_on_previous_text": True,
|
|
"initial_prompt": "Mm-hmm. Okay, let's go. I speak in full sentences.", # Default: Forces punctuation
|
|
|
|
|
|
|
|
# Low VRAM Mode
|
|
"unload_models_after_use": False # If True, models are unloaded immediately to free VRAM
|
|
}
|
|
|
|
class ConfigManager:
|
|
"""
|
|
Singleton Configuration Manager.
|
|
"""
|
|
_instance = None
|
|
|
|
def __new__(cls):
|
|
if cls._instance is None:
|
|
cls._instance = super(ConfigManager, cls).__new__(cls)
|
|
cls._instance._init()
|
|
return cls._instance
|
|
|
|
def _init(self):
|
|
"""Initialize the config manager (called only once)."""
|
|
self.base_path = get_base_path()
|
|
self.config_file = self.base_path / "settings.json"
|
|
self.data = DEFAULT_SETTINGS.copy()
|
|
self.load()
|
|
|
|
def load(self):
|
|
"""Load settings from JSON file, merging with defaults."""
|
|
if self.config_file.exists():
|
|
try:
|
|
with open(self.config_file, 'r', encoding='utf-8') as f:
|
|
loaded = json.load(f)
|
|
|
|
# Merge loaded data into defaults (preserves new default keys)
|
|
for key, value in loaded.items():
|
|
if key in DEFAULT_SETTINGS:
|
|
self.data[key] = value
|
|
|
|
logging.info(f"Settings loaded from {self.config_file}")
|
|
except Exception as e:
|
|
logging.error(f"Failed to load settings: {e}")
|
|
else:
|
|
logging.info("No settings file found. Using defaults.")
|
|
self.save()
|
|
|
|
def save(self):
|
|
"""Save current settings to JSON file."""
|
|
try:
|
|
with open(self.config_file, 'w', encoding='utf-8') as f:
|
|
json.dump(self.data, f, indent=4)
|
|
logging.info("Settings saved.")
|
|
except Exception as e:
|
|
logging.error(f"Failed to save settings: {e}")
|
|
|
|
def get(self, key: str) -> Any:
|
|
"""Get a setting value."""
|
|
return self.data.get(key, DEFAULT_SETTINGS.get(key))
|
|
|
|
|
|
|
|
def set(self, key: str, value: Any):
|
|
"""Set a setting value and save."""
|
|
if self.data.get(key) != value:
|
|
self.data[key] = value
|
|
self.save()
|
|
|
|
def set_bulk(self, updates: Dict[str, Any]):
|
|
"""Update multiple keys and save once."""
|
|
changed = False
|
|
for k, v in updates.items():
|
|
if self.data.get(k) != v:
|
|
self.data[k] = v
|
|
changed = True
|
|
if changed:
|
|
self.save()
|