"""Central configuration, driven by environment variables.""" import os from pathlib import Path PROJECT_ROOT = Path(__file__).resolve().parent.parent DATA_DIR = Path(os.environ.get("PSP_DATA_DIR", str(PROJECT_ROOT / "data"))) DATS_DIR = Path(os.environ.get("PSP_DATS_DIR", str(DATA_DIR / "dats"))) def _default_state_dir(): """Local state directory (fast, reliable local disk). SQLite locking is unreliable over network filesystems (SMB/FUSE), so the library DB and the cover cache live on local storage while DATs, manual covers and credentials stay in ``DATA_DIR`` (which may be a network share). """ xdg = os.environ.get("XDG_STATE_HOME") base = Path(xdg) if xdg else Path.home() / ".local" / "state" return base / "psp-preserve" STATE_DIR = Path(os.environ.get("PSP_STATE_DIR", str(_default_state_dir()))) DB_PATH = Path(os.environ.get("PSP_DB_PATH", str(STATE_DIR / "library.sqlite"))) COVERS_DIR = Path(os.environ.get("PSP_COVERS_DIR", str(STATE_DIR / "covers"))) LEGACY_DB_PATH = DATA_DIR / "library.sqlite" LEGACY_COVERS_DIR = DATA_DIR / "covers" # Redump 7z store (browsable in the Store tab). Env override; GUI setting wins. STORE_ROOT = Path(os.environ.get("PSP_STORE_DIR", "/media/downloads/Sony - PlayStation Portable")) # Remote store server (HTTPS). Used by the Store tab as the primary source. STORE_SERVER_URL = os.environ.get("PSP_STORE_SERVER", "https://psp.ceaf.dev") STORE_TOKEN = os.environ.get("PSP_STORE_TOKEN", "") # Optional direct URLs for the offline cover bundle zips. When unset, the GUI # derives them from the store server URL (/api/covers/.zip). LIBRETRO_COVERS_URL = os.environ.get("PSP_LIBRETRO_COVERS_URL", "") OVGDB_COVERS_URL = os.environ.get("PSP_OVGDB_COVERS_URL", "") # archive.org item hosting the same Redump 7z set (identifier or full URL). ARCHIVE_ITEM = os.environ.get("PSP_ARCHIVE_ITEM", "psp-redump-roms321.com") # Optional archive.org login cookies (for items whose files are "private" / # login-required). Grab these from a logged-in browser session on archive.org. ARCHIVE_LOGGED_IN_SIG = os.environ.get("PSP_ARCHIVE_LOGGED_IN_SIG", "") ARCHIVE_LOGGED_IN_USER = os.environ.get("PSP_ARCHIVE_LOGGED_IN_USER", "") # NoPayStation: where extracted .pkg content lands, and the TSV source base. # PSP games go to /PSP//; PS1 Classics to .../PSX/. NPS_OUTPUT_DIR = Path(os.environ.get("PSP_NPS_DIR", str(STATE_DIR / "nps"))) NPS_TSV_BASE = os.environ.get("PSP_NPS_TSV_BASE", "https://nopaystation.com/tsv/") # pkg2zip binary used to decrypt/extract NPS .pkg files (blank = auto-detect). PKG2ZIP_PATH = os.environ.get("PSP_PKG2ZIP_PATH", "") # Scan roots (used by the scanner phase). Comma-separated in env. GAMES_ROOTS = [Path(p) for p in os.environ.get("PSP_GAMES_ROOTS", "/data/umd_games").split(",") if p.strip()] VIDEO_ROOTS = [Path(p) for p in os.environ.get("PSP_VIDEO_ROOTS", "/data/umd_videos").split(",") if p.strip()] # PS1: source folder (raw ISO/BIN/CUE) and converted EBOOT.PBP output folder. PS1_ROOTS = [Path(p) for p in os.environ.get("PSP_PS1_ROOTS", "/data/ps1").split(",") if p.strip()] PS1_OUTPUT_DIR = Path(os.environ.get("PSP_PS1_OUTPUT_DIR", "/data/ps1_converted")) # Only .iso discs are tracked; everything below is explicitly ignored. DISC_EXTENSIONS = {".iso"} IGNORED_EXTENSIONS = {".pkg", ".pbp", ".cso"} # PS1 source images (scanned separately from PSP .iso discs). PS1_EXTENSIONS = {".cue", ".iso", ".img", ".bin"} # Parallel hashing workers for the scanner. Keep at 1 on spinning disks # (concurrent reads cause seek thrash); raise it for SSD / fast arrays. SCAN_WORKERS = int(os.environ.get("PSP_SCAN_WORKERS", "1"))