All checks were successful
SonarQube Code Quality Scan / SonarQube Scan (push) Successful in 3m36s
99 lines
3.1 KiB
Python
99 lines
3.1 KiB
Python
"""Tunetti configuration — stored at ~/.config/tunetti/config.json ."""
|
|
|
|
import json
|
|
from pathlib import Path
|
|
|
|
# ── Config file location (XDG compliant) ──────────────────────────────────
|
|
CONFIG_DIR = Path.home() / ".config" / "tunetti"
|
|
CONFIG_FILE = CONFIG_DIR / "config.json"
|
|
|
|
# Legacy config in the project directory (for migration).
|
|
_LEGACY_FILE = Path(__file__).parent / "tunetti_config.json"
|
|
|
|
DEFAULT_CONFIG: dict = {
|
|
# Playback
|
|
"volume": 50,
|
|
"max_history": 5000,
|
|
"ffplay_args": ["-nodisp", "-autoexit", "-loglevel", "quiet"],
|
|
# Database
|
|
"db_path": str(CONFIG_DIR / "music_history.db"),
|
|
# Discord
|
|
"discord_client_id": "1510266468388835328",
|
|
"discord_rpc_enabled": True,
|
|
# Visualizer
|
|
"visualizer_enabled": True,
|
|
}
|
|
|
|
|
|
def _migrate_legacy() -> None:
|
|
"""Copy old project-level config and database to the new XDG location."""
|
|
if CONFIG_FILE.exists():
|
|
return # new config already exists — nothing to do
|
|
if not _LEGACY_FILE.exists():
|
|
return # nothing to migrate
|
|
|
|
CONFIG_DIR.mkdir(parents=True, exist_ok=True)
|
|
try:
|
|
with open(_LEGACY_FILE) as f:
|
|
old = json.load(f)
|
|
|
|
# Migrate the database file if it lived in the old project dir.
|
|
old_db_path = Path(old.get("db_path", ""))
|
|
if old_db_path.parent == Path(__file__).parent and old_db_path.exists():
|
|
new_db_path = CONFIG_DIR / "music_history.db"
|
|
if not new_db_path.exists():
|
|
import shutil
|
|
shutil.copy2(str(old_db_path), str(new_db_path))
|
|
old["db_path"] = str(new_db_path)
|
|
|
|
save_config({**DEFAULT_CONFIG, **old})
|
|
# Rename legacy config so we don't re-migrate every launch.
|
|
_LEGACY_FILE.rename(_LEGACY_FILE.with_suffix(".json.migrated"))
|
|
except (json.JSONDecodeError, OSError):
|
|
pass
|
|
|
|
|
|
def load_config() -> dict:
|
|
_migrate_legacy()
|
|
|
|
if CONFIG_FILE.exists():
|
|
try:
|
|
with open(CONFIG_FILE) as f:
|
|
return {**DEFAULT_CONFIG, **json.load(f)}
|
|
except (json.JSONDecodeError, OSError):
|
|
pass
|
|
|
|
# First launch — create the directory and write defaults.
|
|
CONFIG_DIR.mkdir(parents=True, exist_ok=True)
|
|
save_config(dict(DEFAULT_CONFIG))
|
|
return dict(DEFAULT_CONFIG)
|
|
|
|
|
|
def save_config(config: dict) -> None:
|
|
"""Merge *config* over defaults and persist to disk."""
|
|
CONFIG_DIR.mkdir(parents=True, exist_ok=True)
|
|
merged = {**DEFAULT_CONFIG, **config}
|
|
with open(CONFIG_FILE, "w") as f:
|
|
json.dump(merged, f, indent=2)
|
|
|
|
|
|
def save_volume(volume: int) -> None:
|
|
"""Persist current volume to disk and update in-memory SETTINGS."""
|
|
volume = max(0, min(100, volume))
|
|
SETTINGS["volume"] = volume
|
|
save_config(dict(SETTINGS))
|
|
|
|
|
|
def save_setting(key: str, value) -> None:
|
|
"""Persist a single setting and update the in-memory SETTINGS dict."""
|
|
SETTINGS[key] = value
|
|
save_config(dict(SETTINGS))
|
|
|
|
|
|
def get_setting(key: str):
|
|
"""Return a setting value from the in-memory dict."""
|
|
return SETTINGS.get(key, DEFAULT_CONFIG.get(key))
|
|
|
|
|
|
SETTINGS = load_config()
|