summaryrefslogtreecommitdiffstats
path: root/pkgs/by-name/mp/mpv/package.nix
blob: 1b7c744d2f1fa2c084ae97eccbae9acfada8e03e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
{
  stdenv,
  buildEnv,
  lib,
  makeBinaryWrapper,
  makeFontsConf,
  mpvScripts,
  mpv-unwrapped,
  symlinkJoin,
  writeTextDir,
  yt-dlp,
  extraMakeWrapperArgs ? [ ],
  youtubeSupport ? true,
  # a set of derivations (probably from `mpvScripts`) where each is expected
  # to have a `scriptName` passthru attribute that points to the name of the
  # script that would reside in the script's derivation's
  # `$out/share/mpv/scripts/`.
  #
  # A script that comes with fonts (e.g. icon font used by OSC replacement)
  # can provide `passthru.fontDirectories` with a list of dirs.
  # They will be merged into fontconfig for the wrapper.
  #
  # A script can optionally also provide `passthru.extraWrapperArgs`
  # attribute.
  scripts ? [ ],
  extraUmpvWrapperArgs ? [ ],
}:

let
  binPath = lib.makeBinPath (
    [
      mpv-unwrapped.luaEnv
    ]
    ++ lib.optionals mpv-unwrapped.vapoursynthSupport [
      mpv-unwrapped.vapoursynth.python3
    ]
  );

  # With some tools, we want to prioritize tools that are in PATH. For example, users may want
  # to quickly expose a newer version of yt-dlp through the nix shell because it needs to be
  # kept up-to-date for it to work.
  fallbackBinPath = lib.makeBinPath (lib.optionals youtubeSupport [ yt-dlp ]);

  # All arguments besides the input and output binaries (${mpv-unwrapped}/bin/mpv and
  # $out/bin/mpv). These are used by the darwin specific makeWrapper call
  # used to wrap $out/Applications/mpv.app/Contents/MacOS/mpv as well.
  mostMakeWrapperArgs = lib.strings.escapeShellArgs (
    [
      "--inherit-argv0"
      # These are always needed (TODO: Explain why)
      "--prefix"
      "LUA_CPATH"
      ";"
      "${mpv-unwrapped.luaEnv}/lib/lua/${mpv-unwrapped.lua.luaversion}/?.so"
      "--prefix"
      "LUA_PATH"
      ";"
      "${mpv-unwrapped.luaEnv}/share/lua/${mpv-unwrapped.lua.luaversion}/?.lua"
    ]
    ++ lib.optionals mpv-unwrapped.vapoursynthSupport [
      "--prefix"
      "PYTHONPATH"
      ":"
      "${mpv-unwrapped.vapoursynth}/${mpv-unwrapped.vapoursynth.python3.sitePackages}"
    ]
    ++ lib.optionals (binPath != "") [
      "--prefix"
      "PATH"
      ":"
      binPath
    ]
    ++ lib.optionals (fallbackBinPath != "") [
      "--suffix"
      "PATH"
      ":"
      fallbackBinPath
    ]
    ++ (
      let
        fontDirectories = lib.concatMap (script: script.fontDirectories or [ ]) scripts;
      in
      lib.optionals (fontDirectories != [ ]) (
        [
          "--set"
          "FONTCONFIG_FILE"
          (toString (makeFontsConf {
            inherit fontDirectories;
          }))
        ]
        ++ lib.optionals stdenv.hostPlatform.isDarwin [
          "--add-flags"
          "--osd-font-provider=fontconfig"
        ]
      )
    )
    ++ (lib.lists.flatten (
      map
        # For every script in the `scripts` argument, add the necessary flags to the wrapper
        (
          script:
          let
            mkScriptArgs = script: scriptName: [
              "--add-flags"
              "--script=${script}/share/mpv/scripts/${scriptName}"
            ];
          in
          # Here we rely on the existence of the `scriptName` passthru
          # attribute of the script derivation from the `scripts`
          (mkScriptArgs script script.scriptName)
          # scripts might need others to be explicitly loaded
          ++ (map (extraScriptName: mkScriptArgs script extraScriptName) (script.extraScriptsToLoad or [ ]))
          # scripts can also set the `extraWrapperArgs` passthru
          ++ (script.extraWrapperArgs or [ ])
        )
        scripts
    ))
    ++ extraMakeWrapperArgs
  );
  umpvWrapperArgs = lib.strings.escapeShellArgs (
    [
      "--inherit-argv0"
      "--set"
      "MPV"
      "${placeholder "out"}/bin/mpv"
    ]
    ++ extraUmpvWrapperArgs
  );
in
symlinkJoin {
  pname = "mpv-with-scripts";
  inherit (mpv-unwrapped) version;

  # TODO: don't link all mpv outputs
  paths = [ mpv-unwrapped.all ];

  nativeBuildInputs = [ makeBinaryWrapper ];

  passthru.unwrapped = mpv-unwrapped;

  passthru.tests.mpv-scripts-should-not-collide = buildEnv {
    name = "mpv-scripts-env";
    paths = lib.pipe mpvScripts [
      # filters "throw" aliases
      (lib.filterAttrs (key: script: (builtins.tryEval (lib.isDerivation script)).success))
      # filters "override" "overrideDerivation" "recurseForDerivations"
      (lib.filterAttrs (key: script: lib.isDerivation script))
      # filters mpv scripts that opt out of this check
      (lib.filterAttrs (key: script: !(script.passthru.dontCollideCheck or false)))
      # replaces unfree and meta.broken scripts with decent placeholders
      (lib.mapAttrsToList (
        key: script:
        if (builtins.tryEval script.outPath).success then
          script
        else
          writeTextDir "share/mpv/scripts/${script.scriptName}" "placeholder of ${script.name}"
      ))
    ];
  };

  postBuild = ''
    # wrapProgram can't operate on symlinks
    rm "$out/bin/mpv"
    makeWrapper "${mpv-unwrapped}/bin/mpv" "$out/bin/mpv" ${mostMakeWrapperArgs}
    rm "$out/bin/umpv"
    makeWrapper "${mpv-unwrapped}/bin/umpv" "$out/bin/umpv" ${umpvWrapperArgs}
  ''
  + lib.optionalString stdenv.hostPlatform.isDarwin ''
    # wrapProgram can't operate on symlinks
    rm "$out/Applications/mpv.app/Contents/MacOS/mpv"
    makeWrapper "${mpv-unwrapped}/Applications/mpv.app/Contents/MacOS/mpv" "$out/Applications/mpv.app/Contents/MacOS/mpv" ${mostMakeWrapperArgs}
  '';

  meta = {
    inherit (mpv-unwrapped.meta)
      homepage
      description
      longDescription
      maintainers
      ;
    mainProgram = "mpv";
  };
}