old
  1{
  2  lib,
  3  config,
  4  pkgs,
  5  ...
  6}: let
  7  inherit (lib) mkOption types;
  8  cfg = config.programs.deadbeef;
  9
 10  keyValueFormat = pkgs.formats.keyValue {};
 11  JSONFormat = pkgs.formats.json {};
 12
 13  embededJSONType = types.submodule {freeformType = JSONFormat.type;};
 14in {
 15  options.programs.deadbeef = {
 16    enable = lib.mkEnableOption "Enable DeaDBeeF";
 17    package = lib.mkPackageOption pkgs "deadbeef-with-plugins" {};
 18    plugins = mkOption {
 19      type = types.listOf types.package;
 20      default = [];
 21      example = lib.literalExpression ''
 22        with pkgs.deadbeefPlugins; [
 23          mpris2
 24        ];
 25      '';
 26    };
 27    settings = mkOption {
 28      default = {};
 29      example = lib.literalExpression ''
 30        {
 31          "gtkui.start_hidden" = 1;
 32          "hotkey.key1" = "\"space\" 0 0 toggle_pause";
 33        }
 34      '';
 35      type = types.submodule {
 36        freeformType = keyValueFormat.type;
 37        options = {
 38          gtkui.layout = mkOption {
 39            default = {};
 40            description = ''
 41              This option will generate a JSON string into "gtkui.layout.1.9.0" key.
 42            '';
 43            type = embededJSONType;
 44          };
 45          gtkui.columns.playlist = mkOption {
 46            default = [];
 47            description = ''
 48              This option will generate a JSON string into "gtkui.columns.playlist" key.
 49            '';
 50            type = types.listOf embededJSONType;
 51          };
 52          gtkui.columns.search = mkOption {
 53            default = [];
 54            description = ''
 55              This option will generate a JSON string into "gtkui.columns.search" key.
 56            '';
 57            type = types.listOf embededJSONType;
 58          };
 59        };
 60      };
 61    };
 62  };
 63
 64  config = lib.mkIf cfg.enable {
 65    home.packages = [(cfg.package.override {plugins = cfg.plugins;})];
 66    systemd.user.services.merge-deadbeef-config = let
 67      deadbeefProcessedConfig =
 68        {
 69          "gtkui.layout.1.9.0" = builtins.toJSON cfg.settings.gtkui.layout;
 70          "gtkui.columns.playlist" = builtins.toJSON cfg.settings.gtkui.columns.playlist;
 71          "gtkui.columns.search" = builtins.toJSON cfg.settings.gtkui.columns.search;
 72        }
 73        // (lib.removeAttrs cfg.settings ["gtkui"]);
 74      deadbeefConfig = with lib.generators;
 75        toKeyValue {mkKeyValue = mkKeyValueDefault {} " ";} deadbeefProcessedConfig;
 76    in {
 77      Unit = {
 78        Description = "Merge Nix-managed DeaDBeeF configuration";
 79        After = ["graphical-session-pre.target"];
 80        PartOf = ["graphical-session.target"];
 81      };
 82      Service = {
 83        Type = "oneshot";
 84        ExecStart = lib.getExe (pkgs.writeShellScriptBin "merge-deadbeef-config" ''
 85          #!${pkgs.runtimeShell}
 86          set -eu
 87
 88          MANAGED_CONFIG_FILE="${pkgs.writeText "deadbeef-managed-config" deadbeefConfig}"
 89
 90          TARGET_CONFIG_FILE="$HOME/.config/deadbeef/config"
 91          mkdir -p "$(dirname "$TARGET_CONFIG_FILE")"
 92          touch "$TARGET_CONFIG_FILE"
 93
 94          ${pkgs.gawk}/bin/awk '
 95            NR==FNR { a[$1]=$0; next }
 96            {
 97              if ($1 in a) {
 98                print a[$1]
 99                delete a[$1]
100              } else {
101                print $0
102              }
103            }
104            END {
105              for (k in a) {
106                print a[k]
107              }
108            }
109          ' "$MANAGED_CONFIG_FILE" "$TARGET_CONFIG_FILE" > "$TARGET_CONFIG_FILE.tmp" && \
110          mv "$TARGET_CONFIG_FILE.tmp" "$TARGET_CONFIG_FILE"
111          echo "DeaDBeeF config merged successfully."
112        '');
113      };
114      Install = {
115        WantedBy = ["graphical-session.target"];
116      };
117    };
118  };
119}