retronix/modules/es-config.nix
2024-01-11 02:07:28 +01:00

189 lines
4.5 KiB
Nix

{ lib, config, pkgs, ... }:
let
t = v: builtins.trace v v;
filterAttrs' = l: lib.filterAttrs (v: _: builtins.elem v l);
cfg = config.retronix.emulationstation;
attrToXml = attrs: lib.concatLines (lib.mapAttrsToList (k: v: "<${k}>${builtins.toString v}</${k}>") attrs);
gameTemplate = args: let
attr = [
"path"
"name"
"desc"
"image"
"thumbnail"
"video"
"rating"
"releasedate"
"developer"
"publisher"
"genre"
"players"
"sortname"
];
in ''
<game>
${attrToXml (filterAttrs' attr args)}
</game>
'';
systemTemplate = args: let
attr = [
"name"
"fullname"
"path"
"extension"
"command"
"platform"
"theme"
];
in ''
<system>
${attrToXml (filterAttrs' attr args)}
</system>
'';
mkSystemPath = name: games: let
gamelist = ''
<?xml version="1.0"?>
<gameList>
${lib.concatLines (builtins.map gameTemplate games)}
</gameList>
'';
symlinkCommands = builtins.map (
v: "ln -s ${v.src} $out/${v.filename}"
) games;
in pkgs.runCommand "${name}-roms" {
inherit gamelist symlinkCommands;
passAsFile = [
"gamelist"
];
} ''
mkdir -p $out
cp $gamelistPath $out/gamelist.xml
substituteInPlace $out/gamelist.xml --subst-var out
${lib.concatLines symlinkCommands}
'';
sectionOptions = lib.types.submodule ({config, name, ...}: {
freeformType = with lib.types; attrsOf str;
options = {
name = lib.mkOption {
type = lib.types.str;
default = name;
};
fullname = lib.mkOption {
type = lib.types.str;
default = name;
};
path = lib.mkOption { # TODO: check it works
type = lib.types.path;
};
command = lib.mkOption {
type = lib.types.str;
default = "echo \"Hello world !\"";
};
extension = lib.mkOption {
type = lib.types.str;
default = ".zip";
};
games = lib.mkOption {
type = lib.types.listOf gameOptions;
description = "Takes attributes of `games` tag in gamelist.xml";
};
};
config = {
path = mkSystemPath config.name config.games;
};
});
gameOptions = lib.types.submodule ({config, name, ... }: {
freeformType = with lib.types; attrsOf str;
options = {
src = lib.mkOption {
type = lib.types.path;
};
name = lib.mkOption {
type = lib.types.str;
};
desc = lib.mkOption {
type = lib.types.str;
default = "";
};
path = lib.mkOption {
type = lib.types.str;
default = "@out@/${config.filename}";
};
filename = lib.mkOption {
type = lib.types.str;
};
};
});
in {
options = {
retronix.emulationstation = {
systems = lib.mkOption {
type = lib.types.attrsOf (sectionOptions);
default = {};
};
systemCfgFile = lib.mkOption {
type = lib.types.path;
};
inputCfgFile = lib.mkOption {
type = lib.types.path;
};
systemsDir = lib.mkOption {
internal = true;
type = lib.types.path;
description = "Directory containing the symlinks to roms and gamelists.xml files";
};
themesDir = lib.mkOption {
type = lib.types.path;
};
inputCfg = lib.mkOption {
type = lib.types.str;
default = "";
};
homeDir = lib.mkOption {
internal = true;
type = lib.types.path;
};
extraConfigFiles = lib.mkOption {
type = with lib.types; listOf path;
default = [];
description = ''
Must be store paths.
Directory structure will be merged.
Must contain .emulationstation folder
'';
};
cli = lib.mkOption {
type = lib.types.str;
};
};
};
config = {
retronix.emulationstation = {
systemCfgFile = writeESDir "es_systems.cfg" ''
<?xml version="1.0"?>
<systemList>
${lib.concatLines (lib.mapAttrsToList (_: systemTemplate) cfg.systems)}
</systemList>
'';
inputCfgFile = lib.mkDefault (writeTextDir "es_input.cfg" cfg.inputCfg);
homeDir = pkgs.symlinkJoinSubDir {
name = "es-config-dir";
paths = [
cfg.systemCfgFile
cfg.inputCfgFile
] ++ cfg.extraConfigFiles;
};
cli = t "${pkgs.emulationstation}/bin/emulationstation --home ${cfg.homeDir}";
};
};
}