# Integrations Spec ## Overview MangoTune implements four integrations accessible from the Integrations page. Each integration is independent — a missing tool shows a "not available" state for that section only, without affecting the rest of the app. --- ## 1. GameMode Integration **What is GameMode?** A daemon by Feral Interactive that applies CPU governor, scheduler, and I/O priority optimizations when games run. MangoHud can display whether GameMode is currently active via the `gamemode=1` config option. ### Detection ```rust // src/integrations/gamemode.rs pub struct GameModeStatus { pub daemon_installed: bool, // gamemoded binary found pub ctl_installed: bool, // gamemodectl binary found pub daemon_running: bool, // gamemoded process in process list pub current_clients: u32, // number of active gamemoded clients } fn detect() -> GameModeStatus ``` Detection steps: 1. `which gamemoded` — sets `daemon_installed` 2. `which gamemodectl` — sets `ctl_installed` 3. Check process list via `sysinfo` for `gamemoded` — sets `daemon_running` 4. If ctl installed: run `gamemodectl status` and parse client count ### UI (on Integrations page) ``` AdwPreferencesGroup "GameMode" description: "Feral Interactive GameMode performance optimization daemon" AdwActionRow "Status" subtitle: "gamemoded process" [suffix] label: "Running (3 clients)" / "Stopped" / "Not installed" AdwSwitchRow "Show GameMode status in overlay" subtitle: "Sets gamemode=1 in current config" (bound to the gamemode config option) AdwActionRow "Enable GameMode for all Steam games" subtitle: "Adds %command% to default Steam launch options helper" [suffix] GtkButton "Configure" ``` ### No direct daemon control MangoTune does NOT start/stop gamemoded. It only shows status and helps the user configure the launch options. Provide a tooltip: "Start/stop GameMode via your system service manager (systemctl --user start gamemoded)." --- ## 2. Steam Launch Option Helper **Purpose:** Generate the correct launch option string for Steam games so that MangoHud (and optionally GameMode) is injected automatically. ### Detection ```rust pub struct SteamStatus { pub installed: bool, pub flatpak: bool, // true if running as Flatpak pub running: bool, pub steam_root: Option, pub localconfig_path: Option, } ``` Detection steps: 1. Check `which steam` and `flatpak list | grep com.valvesoftware.Steam` 2. Find Steam root: - Native: `~/.steam/steam/` or `~/.local/share/Steam/` - Flatpak: `~/.var/app/com.valvesoftware.Steam/.steam/steam/` 3. Find `userdata/{userId}/config/localconfig.vdf` ### Launch Option Generator UI ``` AdwPreferencesGroup "Steam Launch Options" AdwComboRow "Inject method" options: [ "mangohud {command}", ← standard "MANGOHUD=1 %command%", ← env var method "MANGOHUD_CONFIGFILE=~/.config/... %command%", ← explicit config "gamemoderun mangohud %command%", ← with GameMode "gamemoderun mangemoderun mangohud %command%", ← with GameMode (flatpak) ] AdwEntryRow (read-only) title: "Generated launch option" [Shows generated string based on above selection] [suffix] GtkButton "Copy to clipboard" AdwActionRow "Instructions" subtitle: "In Steam: right-click game → Properties → Launch Options → paste above" ``` ### Important note for Flatpak Steam If Flatpak Steam is detected, the generated command uses the correct Flatpak-aware prefix and warns the user that MangoHud must also be installed inside the Flatpak sandbox or as a Flatpak extension. ### DO NOT write to localconfig.vdf MangoTune does NOT modify Steam's localconfig.vdf directly — too fragile and risky. The user copies the generated string manually. This is deliberate and safe. --- ## 3. Lutris Integration **Purpose:** Help users configure MangoHud for games managed by Lutris. ### Detection ```rust pub struct LutrisStatus { pub installed: bool, pub flatpak: bool, pub config_dir: Option, // ~/.config/lutris/ pub games: Vec, } pub struct LutrisGame { pub name: String, pub slug: String, pub config_path: PathBuf, // ~/.config/lutris/games/{slug}.yml pub runner: String, } ``` Detection steps: 1. `which lutris` or `flatpak list | grep net.lutris.Lutris` 2. Enumerate `~/.config/lutris/games/*.yml` — parse YAML for name, slug, runner fields. Use a simple line-by-line parser (avoid heavy YAML dep — these files are simple). ### UI ``` AdwPreferencesGroup "Lutris" AdwActionRow "Status" [suffix] "Installed" / "Not found" (if installed): AdwComboRow "Game" [lists all detected Lutris games] AdwSwitchRow "Enable MangoHud for selected game" subtitle: "Adds mangohud to the game's Lutris runner configuration" AdwActionRow "Open game config in Lutris" [suffix] GtkButton "Open Lutris" AdwPreferencesGroup (informational) AdwActionRow subtitle: "MangoTune can enable MangoHud in Lutris game configs. Per-game MangoHud config files will be placed at: ~/.config/MangoHud/{game-slug}.conf" [suffix] GtkButton "Create per-game config" ``` ### Config modification approach for Lutris When "Enable MangoHud for selected game" is toggled ON: 1. Read `~/.config/lutris/games/{slug}.yml` 2. Find or create the `system:` section 3. Set `mangohud: true` under the `system:` key 4. Write back (preserve all other content, modify only the mangohud line) 5. Show toast: "MangoHud enabled for {game name}. Restart Lutris if it's open." When toggled OFF: set `mangohud: false`. --- ## 4. Heroic Games Launcher Integration **Purpose:** Help users configure MangoHud for games managed by Heroic (Epic Games, GOG, and Amazon Prime on Linux). ### Detection ```rust pub struct HeroicStatus { pub installed: bool, pub flatpak: bool, pub config_dir: Option, pub games: Vec, } pub struct HeroicGame { pub title: String, pub app_name: String, // Heroic's internal ID pub store: HeroicStore, // Epic, GOG, Amazon pub config_path: PathBuf, // ~/.config/heroic/GamesConfig/{app_name}.json } pub enum HeroicStore { Epic, Gog, Amazon } ``` Detection steps: 1. `which heroic` or `flatpak list | grep com.heroicgameslauncher.hgl` 2. Config dirs to check: - Native: `~/.config/heroic/` - Flatpak: `~/.var/app/com.heroicgameslauncher.hgl/config/heroic/` 3. Enumerate `GamesConfig/*.json` — each file = one game config. 4. Parse JSON: extract `title`, `appName`, store type from file content. ### Heroic Game Config JSON structure (relevant fields) ```json { "appName": "AppId", "title": "Game Title", "enviromentOptions": [ { "key": "MANGOHUD", "value": "1" } ], "wrapperOptions": [ { "exe": "mangohud", "args": "" } ] } ``` ### UI ``` AdwPreferencesGroup "Heroic Games Launcher" AdwActionRow "Status" [suffix] "Installed (Flatpak)" / "Not found" AdwComboRow "Game" [lists games grouped by store if > 5 games] AdwSwitchRow "Enable MangoHud via wrapper" subtitle: "Adds mangohud as a wrapper in Heroic game settings" AdwSwitchRow "Enable MangoHud via environment" subtitle: "Sets MANGOHUD=1 in game environment variables" AdwActionRow "Per-game config" subtitle: "~/.config/MangoHud/{app_name}.conf" [suffix] GtkButton "Create / Edit" ``` ### Config modification approach for Heroic When "Enable MangoHud via wrapper" is toggled ON: 1. Read `~/.config/heroic/GamesConfig/{app_name}.json` (handle Flatpak path too) 2. Parse JSON using `serde_json` 3. Add `{ "exe": "mangohud", "args": "" }` to `wrapperOptions` if not present 4. Write back with pretty-printing 5. Show toast: "MangoHud wrapper enabled. Restart Heroic if it's open." When toggled OFF: remove the mangohud entry from `wrapperOptions`. Environment method similarly adds/removes `{ "key": "MANGOHUD", "value": "1" }`. --- ## Integration Page Layout ``` AdwPreferencesPage "Integrations" icon-name: "insert-object-symbolic" [One AdwPreferencesGroup per integration, as described above] AdwPreferencesGroup "Global MangoHud Enable" description: "Enable MangoHud system-wide for all applications" AdwExpanderRow "Auto-enable method" AdwSwitchRow "Via ~/.config/environment.d/mangohud.conf (recommended, user-scoped)" AdwSwitchRow "Via ~/.bashrc (shell sessions only)" AdwSwitchRow "Via /etc/environment (system-wide, requires sudo)" [Shows currently active method with green checkmark] [Warning: "System-wide enable may break some applications. Per-game is preferred."] ```