Files
MTS-music-another-client/settings.py
jads de9bf80d11 feat: download tracks with full ID3 metadata
- Add downloads.py: "Artist - Title.mp3" naming, no-overwrite dedupe,
  configurable download_dir, progress and per-item callbacks.
- Save maximum metadata via tags.py (ID3v2.3, mutagen): artists, album
  and album artist, track/disc, year/date, raw genre, label, duration,
  explicit flag, cover 600x600, plain and synced lyrics (MTS then
  LRCLIB), track URLs and Yandex/MTS ids.
- TUI/Qt: download current track and queue from the menu, "d" key in
  lists, folder picker in settings; CLI download gains -d/--dir and
  --no-tags.
- Add mutagen to requirements and document download/metadata in README.
- Fix MPRIS update_metadata crashing without dbus-next.
2026-10-25 20:06:59 +03:00

114 lines
3.5 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Настройки MTS Music: хранятся в .mts-music/settings.json."""
from __future__ import annotations
import json
from pathlib import Path
from typing import Any
from mtsmusic import CONFIG_DIR
SETTINGS_PATH = CONFIG_DIR / "settings.json"
DEFAULT_DOWNLOAD_DIR = str(Path.home() / "Music" / "MTS Music")
DEFAULTS: dict[str, Any] = {
"volume": 80, # громкость 0..100
"seek_step": 5, # шаг перемотки стрелками, секунды
"autoplay": False, # запускать воспроизведение сразу
"start_queue": "wave", # wave | favorites | history
"wave_from_history": True, # продолжать волну с последних треков
"download_dir": DEFAULT_DOWNLOAD_DIR, # куда сохранять скачанные MP3
}
START_QUEUES = ("wave", "favorites", "history")
START_QUEUE_LABELS = {
"wave": "Моя волна",
"favorites": "Избранное",
"history": "История",
}
_cache: dict[str, Any] | None = None
def _coerce(key: str, value: Any) -> Any:
if key == "volume":
try:
return max(0, min(100, int(value)))
except (TypeError, ValueError):
return DEFAULTS[key]
if key == "seek_step":
try:
return max(1, min(60, int(value)))
except (TypeError, ValueError):
return DEFAULTS[key]
if key in ("autoplay", "wave_from_history"):
if isinstance(value, bool):
return value
return str(value).strip().lower() in (
"1", "true", "yes", "on", "да", "вкл")
if key == "start_queue":
text = str(value)
return text if text in START_QUEUES else DEFAULTS[key]
if key == "download_dir":
text = str(value).strip()
if not text:
return DEFAULTS[key]
return str(Path(text).expanduser())
return value
def load_settings() -> dict[str, Any]:
"""Возвращает настройки с дефолтами; файл читается один раз."""
global _cache
if _cache is not None:
return dict(_cache)
raw: dict[str, Any] = {}
try:
data = json.loads(SETTINGS_PATH.read_text(encoding="utf-8"))
if isinstance(data, dict):
raw = data
except (OSError, ValueError):
raw = {}
merged = dict(DEFAULTS)
for key, value in raw.items():
if key in DEFAULTS:
merged[key] = _coerce(key, value)
_cache = merged
return dict(merged)
def save_settings(values: dict[str, Any]) -> dict[str, Any]:
"""Сохраняет изменённые настройки и возвращает актуальный набор."""
global _cache
merged = load_settings()
for key, value in values.items():
if key in DEFAULTS:
merged[key] = _coerce(key, value)
_cache = merged
try:
SETTINGS_PATH.parent.mkdir(parents=True, exist_ok=True)
SETTINGS_PATH.write_text(
json.dumps(merged, ensure_ascii=False, indent=2),
encoding="utf-8",
)
except OSError:
pass
return dict(merged)
def get_setting(key: str, default: Any = None) -> Any:
return load_settings().get(key, DEFAULTS.get(key, default))
def set_setting(key: str, value: Any) -> Any:
return save_settings({key: value}).get(key)
def update_settings(**values: Any) -> dict[str, Any]:
return save_settings(dict(values))
def settings_path() -> Path:
return SETTINGS_PATH