diff options
Diffstat (limited to 'raveos-center/raveos_center/gaming.py')
| -rw-r--r-- | raveos-center/raveos_center/gaming.py | 272 |
1 files changed, 272 insertions, 0 deletions
diff --git a/raveos-center/raveos_center/gaming.py b/raveos-center/raveos_center/gaming.py new file mode 100644 index 0000000..9652958 --- /dev/null +++ b/raveos-center/raveos_center/gaming.py @@ -0,0 +1,272 @@ +import os +import re +import subprocess +from pathlib import Path + +from raveos_center.muveletek import Lepes, root + +KONFIG = Path(os.environ.get("XDG_CONFIG_HOME", Path.home() / ".config")) +KORNYEZET = KONFIG / "environment.d" / "raveos-gaming.conf" +GAMEMODE_INI = KONFIG / "gamemode.ini" +GAMESCOPE = ["gamescope", "gamescope-session-git", "gamescope-session-steam-git"] +MANGOHUD_CONF = KONFIG / "MangoHud" / "MangoHud.conf" +MANGOHUD_MODOK = [ + ("", "Alapértelmezett"), + ("1", "Csak FPS"), + ("2", "Vízszintes sáv"), + ("3", "Bővített"), + ("4", "Részletes"), +] +SCHED_EXT = Path("/sys/kernel/sched_ext") +PROTON_CACHYOS = "proton-cachyos-slr" +GAMING_MOD = ["gamemode", "governor", "ntsync", "utemezo"] +GOV_ALAPBOL = "A rendszer alapból is performance módban fut." + + +def _telepitett(): + try: + kimenet = subprocess.run(["pacman", "-Qq"], capture_output=True, text=True, timeout=30).stdout + except (OSError, subprocess.TimeoutExpired): + return set() + return set(kimenet.split()) + + +def _cpufreq(): + return Path("/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor").exists() + + +def _ntsync_beepitett(): + try: + kimenet = subprocess.run(["modinfo", "-F", "filename", "ntsync"], capture_output=True, text=True, timeout=10) + except (OSError, subprocess.TimeoutExpired): + return False + return kimenet.stdout.strip() == "(builtin)" + + +def _rendszer_gov(): + try: + return Path("/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor").read_text().strip() + except OSError: + return "" + + +def _desiredgov(): + try: + sorok = GAMEMODE_INI.read_text(encoding="utf-8").splitlines() + except OSError: + return None + szakasz = "" + for sor in sorok: + t = sor.strip() + if t.startswith("[") and t.endswith("]"): + szakasz = t[1:-1].strip() + elif szakasz == "general": + talalat = re.match(r"desiredgov\s*=\s*(\S+)", t) + if talalat: + return talalat.group(1) + return None + + +def _desiredgov_ir(ertek): + try: + sorok = GAMEMODE_INI.read_text(encoding="utf-8").splitlines() + except FileNotFoundError: + sorok = [] + uj = [] + szakasz = "" + general_volt = False + beirva = False + for sor in sorok: + t = sor.strip() + if t.startswith("[") and t.endswith("]"): + if szakasz == "general" and not beirva: + uj.append(f"desiredgov={ertek}") + beirva = True + szakasz = t[1:-1].strip() + general_volt = general_volt or szakasz == "general" + elif szakasz == "general" and re.match(r"desiredgov\s*=", t): + if not beirva: + uj.append(f"desiredgov={ertek}") + beirva = True + continue + uj.append(sor) + if not beirva: + if not general_volt: + uj.append("[general]") + uj.append(f"desiredgov={ertek}") + GAMEMODE_INI.parent.mkdir(parents=True, exist_ok=True) + ideiglenes = GAMEMODE_INI.with_suffix(".ini.uj") + ideiglenes.write_text("\n".join(uj) + "\n", encoding="utf-8") + os.replace(ideiglenes, GAMEMODE_INI) + + +def _mangohud_sor(): + try: + return any(s.strip() == "MANGOHUD=1" for s in KORNYEZET.read_text().splitlines()) + except OSError: + return False + + +def _utemezo_allapot(): + if not SCHED_EXT.is_dir(): + return { + "aktiv": False, + "elerheto": False, + "megjegyzes": "A futó kernel nem támogatja (sched_ext nélkül fordították).", + } + try: + fut = (SCHED_EXT / "state").read_text().strip() == "enabled" + nev = (SCHED_EXT / "root" / "ops").read_text().strip() if fut else "" + except OSError: + fut, nev = False, "" + return {"aktiv": fut, "elerheto": True, "megjegyzes": f"Most fut: {nev}" if nev else ""} + + +def mangohud_mod(): + try: + sorok = MANGOHUD_CONF.read_text(encoding="utf-8").splitlines() + except OSError: + return "" + for sor in sorok: + talalat = re.match(r"\s*preset\s*=\s*(-?\d)", sor) + if talalat: + return talalat.group(1) + return "" + + +def mangohud_mod_beallit(mod): + try: + sorok = MANGOHUD_CONF.read_text(encoding="utf-8").splitlines() + except FileNotFoundError: + sorok = [] + sorok = [s for s in sorok if not re.match(r"\s*preset\s*=", s)] + if mod: + tobbi = [m for m, _ in MANGOHUD_MODOK if m and m != mod] + sorok.insert(0, "preset=" + ",".join([mod] + tobbi + ["0"])) + if not sorok: + MANGOHUD_CONF.unlink(missing_ok=True) + return + MANGOHUD_CONF.parent.mkdir(parents=True, exist_ok=True) + ideiglenes = MANGOHUD_CONF.with_suffix(".conf.uj") + ideiglenes.write_text("\n".join(sorok) + "\n", encoding="utf-8") + os.replace(ideiglenes, MANGOHUD_CONF) + + +def _proton_cachyos_elerheto(): + try: + return subprocess.run(["pacman", "-Si", PROTON_CACHYOS], capture_output=True, timeout=30).returncode == 0 + except (OSError, subprocess.TimeoutExpired): + return False + + +def _governor_allapot(gamemode): + rendszer = _rendszer_gov() + kivant = _desiredgov() or "performance" + if not gamemode: + return {"aktiv": False, "elerheto": False, "megjegyzes": "Ehhez előbb a GameMode-ot kapcsold be."} + if not rendszer: + return {"aktiv": False, "elerheto": False, "megjegyzes": "Ezen a gépen nincs órajel-szabályozás (pl. virtuális gép)."} + if rendszer == "performance": + return {"aktiv": True, "elerheto": False, "megjegyzes": GOV_ALAPBOL} + return {"aktiv": kivant == "performance", "elerheto": True, "megjegyzes": ""} + + +def allapot(): + telepitett = _telepitett() + gamemode = {"gamemode", "lib32-gamemode"} <= telepitett + mangohud = "mangohud" in telepitett + ntsync_beepitett = _ntsync_beepitett() + return { + "gamemode": {"aktiv": gamemode, "elerheto": True, "megjegyzes": "", "root": True}, + "mangohud": { + "aktiv": _mangohud_sor() and mangohud, + "elerheto": True, + "megjegyzes": "Kijelentkezés és újra bejelentkezés után lép életbe.", + "root": not mangohud, + }, + "gamescope": { + "aktiv": set(GAMESCOPE) <= telepitett, + "elerheto": True, + "megjegyzes": "" if "steam" in telepitett else "A Steam munkamenethez a Steam is szükséges.", + "root": True, + }, + "governor": dict(_governor_allapot(gamemode), root=False, cpufreq=bool(_rendszer_gov())), + "ntsync": { + "aktiv": ntsync_beepitett + or (Path("/etc/modules-load.d/ntsync.conf").exists() and Path("/dev/ntsync").exists()), + "elerheto": not ntsync_beepitett, + "megjegyzes": "A RaveOS kernelébe be van építve, mindig aktív." if ntsync_beepitett else "", + "root": True, + }, + "utemezo": dict(_utemezo_allapot(), root=True), + "proton_cachyos": { + "aktiv": PROTON_CACHYOS in telepitett, + "elerheto": PROTON_CACHYOS in telepitett or _proton_cachyos_elerheto(), + "megjegyzes": "", + "root": True, + }, + } + + +def lepesek(azon, be): + if azon == "gamemode": + csomagok = ["gamemode", "lib32-gamemode"] + return [Lepes("GameMode", root("telepit" if be else "eltavolit", *csomagok))], None + if azon == "mangohud": + lista = [] + if be and "mangohud" not in _telepitett(): + lista.append(Lepes("MangoHud telepítése", root("telepit", "mangohud", "lib32-mangohud"))) + return lista, lambda: _mangohud(be) + if azon == "gamescope": + return [Lepes("Gamescope session", root("telepit" if be else "eltavolit", *(GAMESCOPE if be else GAMESCOPE[1:])))], None + if azon == "governor": + return [], lambda: _governor(be) + if azon == "ntsync": + return [Lepes("NTSync", root("ntsync", "be" if be else "ki"))], None + if azon == "utemezo": + return [Lepes("Játékra hangolt ütemező", root("utemezo", "be" if be else "ki"))], None + if azon == "proton_cachyos": + return [Lepes("Proton-CachyOS", root("telepit" if be else "eltavolit", PROTON_CACHYOS))], None + return [], None + + +def _mangohud(be): + sorok = [] + try: + sorok = [s for s in KORNYEZET.read_text().splitlines() if s.strip() != "MANGOHUD=1"] + except OSError: + pass + if be: + sorok.append("MANGOHUD=1") + if sorok: + KORNYEZET.parent.mkdir(parents=True, exist_ok=True) + KORNYEZET.write_text("\n".join(sorok) + "\n") + else: + KORNYEZET.unlink(missing_ok=True) + + +def _governor(be): + rendszer = _rendszer_gov() + if be: + _desiredgov_ir("performance") + elif rendszer and rendszer != "performance": + _desiredgov_ir(rendszer) + + +def gaming_mod_valtozasok(adat, be): + valtozasok = [] + gamemode_lesz = adat["gamemode"]["aktiv"] or be + for a in GAMING_MOD: + if a == "gamemode" and not be: + continue + if a == "governor": + elerheto = gamemode_lesz and adat[a]["cpufreq"] and adat[a]["megjegyzes"] != GOV_ALAPBOL + else: + elerheto = adat[a]["elerheto"] + if elerheto and adat[a]["aktiv"] != be: + valtozasok.append((a, be)) + return valtozasok + + +def gaming_mod_aktiv(adat): + return all(adat[a]["aktiv"] for a in GAMING_MOD if adat[a]["elerheto"] or adat[a]["aktiv"]) |