"""Launch external applications (currently PPSSPP).""" import os import shutil import subprocess from pathlib import Path def find_ppsspp(): """Return a candidate PPSSPP executable path, or None.""" for name in ("ppsspp", "PPSSPP", "PPSSPPSDL", "PPSSPPQt"): p = shutil.which(name) if p: return p home = Path.home() for cand in ( home / ".local" / "bin" / "ppsspp", home / ".local" / "bin" / "PPSSPPSDL", home / "Applications" / "PPSSPP" / "PPSSPP", Path("/usr/games/ppsspp"), Path("/usr/bin/ppsspp"), Path("/usr/bin/PPSSPPSDL"), Path("/snap/bin/ppsspp"), ): if cand.is_file(): return str(cand) return None def _env(): env = dict(os.environ) # PPSSPPSDL (the SDL build) frequently crashes on Wayland; route it through # XWayland instead. Kept local to PPSSPP so nothing else is affected. env["SDL_VIDEODRIVER"] = "x11" env.setdefault("SDL_AUDIODRIVER", "pulseaudio") return env def launch_ppsspp(iso, exe=""): """Launch PPSSPP with the given ISO. Returns ``(ok, message)``.""" iso = str(iso) exe = (exe or "").strip() if exe: cmd = [exe, iso] else: found = find_ppsspp() if found: cmd = [found, iso] else: return False, "PPSSPP not found. Install it or set its path in Settings → Saves." try: kwargs = {"env": _env(), "stdout": subprocess.DEVNULL, "stderr": subprocess.DEVNULL} if os.name != "nt": kwargs["start_new_session"] = True # POSIX-only: detach from our process group subprocess.Popen(cmd, **kwargs) return True, "" except OSError as exc: return False, str(exc)