nixpkgs/pkgs/tools/audio/beets/common.nix
2023-08-13 21:44:29 -03:00

187 lines
4.3 KiB
Nix

{ stdenv
, fetchpatch
, bashInteractive
, diffPlugins
, glibcLocales
, gobject-introspection
, gst_all_1
, lib
, python3Packages
, sphinxHook
, runtimeShell
, writeScript
# plugin deps
, aacgain
, essentia-extractor
, ffmpeg
, flac
, imagemagick
, keyfinder-cli
, mp3gain
, mp3val
, src
, version
, extraPatches ? [ ]
, pluginOverrides ? { }
, disableAllPlugins ? false
# tests
, runCommand
, beets
}@inputs:
let
inherit (lib) attrNames attrValues concatMap;
mkPlugin = { enable ? !disableAllPlugins, builtin ? false, propagatedBuildInputs ? [ ], testPaths ? [ ], wrapperBins ? [ ] }: {
inherit enable builtin propagatedBuildInputs testPaths wrapperBins;
};
basePlugins = lib.mapAttrs (_: a: { builtin = true; } // a) (import ./builtin-plugins.nix inputs);
allPlugins = lib.mapAttrs (_: mkPlugin) (lib.recursiveUpdate basePlugins pluginOverrides);
builtinPlugins = lib.filterAttrs (_: p: p.builtin) allPlugins;
enabledPlugins = lib.filterAttrs (_: p: p.enable) allPlugins;
disabledPlugins = lib.filterAttrs (_: p: !p.enable) allPlugins;
pluginWrapperBins = concatMap (p: p.wrapperBins) (attrValues enabledPlugins);
in
python3Packages.buildPythonApplication {
pname = "beets";
inherit src version;
patches = extraPatches;
postPatch = ''
# https://github.com/beetbox/beets/pull/4868
substituteInPlace beets/util/artresizer.py \
--replace "Image.ANTIALIAS" "Image.Resampling.LANCZOS"
'';
propagatedBuildInputs = with python3Packages; [
confuse
gst-python
jellyfish
mediafile
munkres
musicbrainzngs
mutagen
pygobject3
pyyaml
reflink
unidecode
typing-extensions
] ++ (concatMap (p: p.propagatedBuildInputs) (attrValues enabledPlugins));
nativeBuildInputs = [
gobject-introspection
sphinxHook
];
buildInputs = [
] ++ (with gst_all_1; [
gst-plugins-base
gst-plugins-good
gst-plugins-ugly
]);
outputs = [ "out" "doc" "man" ];
sphinxBuilders = [ "html" "man" ];
postInstall = ''
mkdir -p $out/share/zsh/site-functions
cp extra/_beet $out/share/zsh/site-functions/
'';
doInstallCheck = true;
installCheckPhase = ''
runHook preInstallCheck
tmphome="$(mktemp -d)"
EDITOR="${writeScript "beetconfig.sh" ''
#!${runtimeShell}
cat > "$1" <<CFG
plugins: ${lib.concatStringsSep " " (attrNames enabledPlugins)}
CFG
''}" HOME="$tmphome" "$out/bin/beet" config -e
EDITOR=true HOME="$tmphome" "$out/bin/beet" config -e
runHook postInstallCheck
'';
makeWrapperArgs = [
"--set GI_TYPELIB_PATH \"$GI_TYPELIB_PATH\""
"--set GST_PLUGIN_SYSTEM_PATH_1_0 \"$GST_PLUGIN_SYSTEM_PATH_1_0\""
"--prefix PATH : ${lib.makeBinPath pluginWrapperBins}"
];
nativeCheckInputs = with python3Packages; [
pytest
mock
rarfile
responses
] ++ pluginWrapperBins;
disabledTestPaths = lib.flatten (attrValues (lib.mapAttrs (n: v: v.testPaths ++ [ "test/test_${n}.py" ]) disabledPlugins));
checkPhase = ''
runHook preCheck
# Check for undefined plugins
find beetsplug -mindepth 1 \
\! -path 'beetsplug/__init__.py' -a \
\( -name '*.py' -o -path 'beetsplug/*/__init__.py' \) -print \
| sed -n -re 's|^beetsplug/([^/.]+).*|\1|p' \
| sort -u > plugins_available
${diffPlugins (attrNames builtinPlugins) "plugins_available"}
export BEETS_TEST_SHELL="${bashInteractive}/bin/bash --norc"
export HOME="$(mktemp -d)"
args=" -m pytest -r fEs"
eval "disabledTestPaths=($disabledTestPaths)"
for path in ''${disabledTestPaths[@]}; do
if [ -e "$path" ]; then
args+=" --ignore $path"
else
echo "Skipping non-existent test path '$path'"
fi
done
python $args
runHook postCheck
'';
passthru.plugins = allPlugins;
passthru.tests.gstreamer = runCommand "beets-gstreamer-test" {
meta.timeout = 60;
}
''
set -euo pipefail
export HOME=$(mktemp -d)
mkdir $out
cat << EOF > $out/config.yaml
replaygain:
backend: gstreamer
EOF
echo $out/config.yaml
${beets}/bin/beet -c $out/config.yaml > /dev/null
'';
meta = with lib; {
description = "Music tagger and library organizer";
homepage = "https://beets.io";
license = licenses.mit;
maintainers = with maintainers; [ aszlig doronbehar lovesegfault pjones ];
platforms = platforms.linux;
mainProgram = "beet";
};
}