main
  1{
  2  den.aspects.desktop.app.mpv = {
  3    cacheHome = {config, ...}: {
  4      directories = [
  5        "${config.xdg.state.directory}/mpv"
  6      ];
  7    };
  8
  9    hjem = {
 10      pkgs,
 11      lib,
 12      ...
 13    }: let
 14      # Port of home-manager's programs.mpv
 15      # See https://github.com/nix-community/home-manager/blob/c53d643b3737e2fcd04e6cb3b3580ef50b2087a0/modules/programs/mpv.nix
 16      mpvConfGenerator = {
 17        defaultProfiles ? [],
 18        config ? {},
 19        profiles ? {},
 20        includes ? [],
 21      }: let
 22        renderOption = option:
 23          if lib.isBool option
 24          then
 25            (
 26              if option
 27              then "yes"
 28              else "no"
 29            )
 30          else toString option;
 31
 32        renderOptionValue = value: let
 33          rendered = renderOption value;
 34        in "%${toString (builtins.stringLength rendered)}%${rendered}";
 35
 36        mkKeyValue = lib.generators.mkKeyValueDefault {
 37          mkValueString = renderOptionValue;
 38        } "=";
 39
 40        renderOptions = lib.generators.toKeyValue {
 41          inherit mkKeyValue;
 42          listsAsDuplicateKeys = true;
 43        };
 44
 45        renderProfiles = lib.generators.toINI {
 46          inherit mkKeyValue;
 47          listsAsDuplicateKeys = true;
 48        };
 49
 50        renderDefaultProfiles = profiles: renderOptions {profile = lib.concatStringsSep "," profiles;};
 51      in
 52        lib.concatStringsSep "\n" (lib.filter (s: s != "") [
 53          (lib.optionalString (defaultProfiles != []) (renderDefaultProfiles defaultProfiles))
 54          (lib.optionalString (config != {}) (renderOptions config))
 55          (lib.optionalString (profiles != {}) (renderProfiles profiles))
 56          (lib.concatMapStringsSep "\n" (include: "include=${include}") includes)
 57        ]);
 58
 59      mpvScriptOptsGenerator = value:
 60        lib.generators.toKeyValue {
 61          mkKeyValue = lib.generators.mkKeyValueDefault {
 62            mkValueString = option:
 63              if lib.isBool option
 64              then
 65                (
 66                  if option
 67                  then "yes"
 68                  else "no"
 69                )
 70              else toString option;
 71          } "=";
 72          listsAsDuplicateKeys = true;
 73        }
 74        value;
 75    in {
 76      packages = [
 77        (pkgs.mpv.override {
 78          scripts = with pkgs.mpvScripts; [
 79            mpris
 80            uosc
 81            thumbfast
 82            autoload
 83            reload
 84            mpv-playlistmanager
 85          ];
 86        })
 87      ];
 88
 89      xdg.config.files = {
 90        "mpv/mpv.conf" = {
 91          generator = mpvConfGenerator;
 92          value = {
 93            defaultProfiles = ["gpu-hq"];
 94            config = {
 95              vo = "gpu-next";
 96              hwdec = "auto-copy";
 97              scale = "ewa_lanczossharp";
 98              # --- 动态范围与色彩管理 --- #
 99              target-colorspace-hint = "auto";
100              tone-mapping = "hable";
101              dither = "fruit";
102              dither-depth = "auto";
103              # --- 音频质量配置 --- #
104              ao = "pipewire";
105              audio-resample-filter-size = 64;
106              audio-resample-phase-shift = 10;
107              # --- 字幕配置 --- #
108              sub-auto = "fuzzy";
109              sub-bold = "yes";
110              sub-outline-size = 2.25;
111              sub-outline-color = "#111111";
112              sub-color = "#FEFEFE";
113              sub-font-size = "36";
114              sub-use-margins = "yes";
115              sub-ass-override = "force";
116              # --- 用户体验 --- #
117              save-position-on-quit = true;
118              keep-open = "yes";
119              osd-bar = "no"; # use uosc
120              # 音量控制
121              volume = 80;
122              volume-max = 120;
123              # OSD 显示
124              osd-duration = 2500;
125              osd-font-size = 32;
126              # 截图设置
127              screenshot-format = "png";
128              screenshot-dir = "$XDG_PICTURES_DIR/mpv";
129              screenshot-template = "%F-%P";
130            };
131          };
132        };
133
134        "mpv/script-opts/uosc.conf" = {
135          generator = mpvScriptOptsGenerator;
136          value = {
137            languages = "slang,zh-hans";
138          };
139        };
140      };
141
142      xdg.mime-apps.default-applications = {
143        "audio/*" = ["mpv.desktop"];
144        "video/*" = ["mpv.desktop"];
145      };
146    };
147  };
148
149  den.aspects.desktop.app.mpv.themes = {
150    catppuccin = {
151      hjem = {pkgs, ...}: let
152        catppuccin-mpv = pkgs.fetchFromGitHub {
153          owner = "catppuccin";
154          repo = "mpv";
155          rev = "08e90daf511eee2c10c98f0031b51bb9de240d60";
156          hash = "sha256-oUheJNWk2R6gNEmkK8H6PWX0iofx2KMGDoFWtnr420A=";
157        };
158      in {
159        xdg.config.files."mpv/mpv.conf".value.includes = ["${catppuccin-mpv}/mocha/mauve.conf"];
160      };
161    };
162  };
163}