diff options
Diffstat (limited to 'nixpkgs/pkgs/tools/audio/beets')
9 files changed, 536 insertions, 0 deletions
diff --git a/nixpkgs/pkgs/tools/audio/beets/badfiles-plugin-nix-paths.patch b/nixpkgs/pkgs/tools/audio/beets/badfiles-plugin-nix-paths.patch new file mode 100644 index 000000000000..6956183344c4 --- /dev/null +++ b/nixpkgs/pkgs/tools/audio/beets/badfiles-plugin-nix-paths.patch @@ -0,0 +1,21 @@ +diff --git i/beetsplug/badfiles.py w/beetsplug/badfiles.py +index 36b45de3..5208b696 100644 +--- i/beetsplug/badfiles.py ++++ w/beetsplug/badfiles.py +@@ -71,14 +71,14 @@ class BadFiles(BeetsPlugin): + return status, errors, [line for line in output.split("\n") if line] + + def check_mp3val(self, path): +- status, errors, output = self.run_command(["mp3val", path]) ++ status, errors, output = self.run_command(["@mp3val@/bin/mp3val", path]) + if status == 0: + output = [line for line in output if line.startswith("WARNING:")] + errors = len(output) + return status, errors, output + + def check_flac(self, path): +- return self.run_command(["flac", "-wst", path]) ++ return self.run_command(["@flac@/bin/flac", "-wst", path]) + + def check_custom(self, command): + def checker(path): diff --git a/nixpkgs/pkgs/tools/audio/beets/bash-completion-always-print.patch b/nixpkgs/pkgs/tools/audio/beets/bash-completion-always-print.patch new file mode 100644 index 000000000000..7bc3e57117e3 --- /dev/null +++ b/nixpkgs/pkgs/tools/audio/beets/bash-completion-always-print.patch @@ -0,0 +1,43 @@ +diff --git i/beets/ui/commands.py w/beets/ui/commands.py +index 4d010f4b..0b023585 100755 +--- i/beets/ui/commands.py ++++ w/beets/ui/commands.py +@@ -1741,20 +1741,6 @@ default_commands.append(config_cmd) + def print_completion(*args): + for line in completion_script(default_commands + plugins.commands()): + print_(line, end=u'') +- if not any(map(os.path.isfile, BASH_COMPLETION_PATHS)): +- log.warning(u'Warning: Unable to find the bash-completion package. ' +- u'Command line completion might not work.') +- +-BASH_COMPLETION_PATHS = map(syspath, [ +- u'/etc/bash_completion', +- u'/usr/share/bash-completion/bash_completion', +- u'/usr/local/share/bash-completion/bash_completion', +- # SmartOS +- u'/opt/local/share/bash-completion/bash_completion', +- # Homebrew (before bash-completion2) +- u'/usr/local/etc/bash_completion', +-]) +- + + def completion_script(commands): + """Yield the full completion shell script as strings. +diff --git i/test/test_ui.py w/test/test_ui.py +index 5cfed1fd..9d3dc458 100644 +--- i/test/test_ui.py ++++ w/test/test_ui.py +@@ -1230,12 +1230,7 @@ class CompletionTest(_common.TestCase, TestHelper): + stdout=subprocess.PIPE, env=env) + + # Load bash_completion library. +- for path in commands.BASH_COMPLETION_PATHS: +- if os.path.exists(util.syspath(path)): +- bash_completion = path +- break +- else: +- self.skipTest(u'bash-completion script not found') ++ self.skipTest(u'bash-completion script not found') + try: + with open(util.syspath(bash_completion), 'rb') as f: + tester.stdin.writelines(f) diff --git a/nixpkgs/pkgs/tools/audio/beets/convert-plugin-ffmpeg-path.patch b/nixpkgs/pkgs/tools/audio/beets/convert-plugin-ffmpeg-path.patch new file mode 100644 index 000000000000..bcc77179d796 --- /dev/null +++ b/nixpkgs/pkgs/tools/audio/beets/convert-plugin-ffmpeg-path.patch @@ -0,0 +1,43 @@ +diff --git i/beetsplug/convert.py w/beetsplug/convert.py +index 70363f6e..2962aa4f 100644 +--- i/beetsplug/convert.py ++++ w/beetsplug/convert.py +@@ -81,7 +81,7 @@ def get_format(fmt=None): + command = config['convert']['command'].as_str() + elif 'opts' in keys: + # Undocumented option for backwards compatibility with < 1.3.1. +- command = u'ffmpeg -i $source -y {0} $dest'.format( ++ command = u'@ffmpeg@/bin/ffmpeg -i $source -y {0} $dest'.format( + config['convert']['opts'].as_str() + ) + if 'extension' in keys: +@@ -121,22 +121,22 @@ class ConvertPlugin(BeetsPlugin): + u'id3v23': u'inherit', + u'formats': { + u'aac': { +- u'command': u'ffmpeg -i $source -y -vn -acodec aac ' ++ u'command': u'@ffmpeg@/bin/ffmpeg -i $source -y -vn -acodec aac ' + u'-aq 1 $dest', + u'extension': u'm4a', + }, + u'alac': { +- u'command': u'ffmpeg -i $source -y -vn -acodec alac $dest', ++ u'command': u'@ffmpeg@/bin/ffmpeg -i $source -y -vn -acodec alac $dest', + u'extension': u'm4a', + }, +- u'flac': u'ffmpeg -i $source -y -vn -acodec flac $dest', +- u'mp3': u'ffmpeg -i $source -y -vn -aq 2 $dest', ++ u'flac': u'@ffmpeg@/bin/ffmpeg -i $source -y -vn -acodec flac $dest', ++ u'mp3': u'@ffmpeg@/bin/ffmpeg -i $source -y -vn -aq 2 $dest', + u'opus': +- u'ffmpeg -i $source -y -vn -acodec libopus -ab 96k $dest', ++ u'@ffmpeg@/bin/ffmpeg -i $source -y -vn -acodec libopus -ab 96k $dest', + u'ogg': +- u'ffmpeg -i $source -y -vn -acodec libvorbis -aq 3 $dest', ++ u'@ffmpeg@/bin/ffmpeg -i $source -y -vn -acodec libvorbis -aq 3 $dest', + u'wma': +- u'ffmpeg -i $source -y -vn -acodec wmav2 -vn $dest', ++ u'@ffmpeg@/bin/ffmpeg -i $source -y -vn -acodec wmav2 -vn $dest', + }, + u'max_bitrate': 500, + u'auto': False, diff --git a/nixpkgs/pkgs/tools/audio/beets/default.nix b/nixpkgs/pkgs/tools/audio/beets/default.nix new file mode 100644 index 000000000000..c218aa7e4e12 --- /dev/null +++ b/nixpkgs/pkgs/tools/audio/beets/default.nix @@ -0,0 +1,279 @@ +{ stdenv, lib, fetchFromGitHub, writeScript, glibcLocales, diffPlugins, substituteAll +, pythonPackages, imagemagick, gobject-introspection, gst_all_1 +, runtimeShell, unstableGitUpdater + +# external plugins package set +, beetsExternalPlugins + +, enableAbsubmit ? lib.elem stdenv.hostPlatform.system essentia-extractor.meta.platforms, essentia-extractor +, enableAcousticbrainz ? true +, enableAcoustid ? true +, enableAura ? true +, enableBadfiles ? true, flac, mp3val +, enableBeatport ? true +, enableBpsync ? true +, enableConvert ? true, ffmpeg +, enableDeezer ? true +, enableDiscogs ? true +, enableEmbyupdate ? true +, enableFetchart ? true +, enableKeyfinder ? true, keyfinder-cli +, enableKodiupdate ? true +, enableLastfm ? true +, enableLoadext ? true +, enableLyrics ? true +, enableMpd ? true +, enablePlaylist ? true +, enableReplaygain ? true +, enableSonosUpdate ? true +, enableSubsonicplaylist ? true +, enableSubsonicupdate ? true +, enableThumbnails ? true +, enableWeb ? true + +# External plugins +, enableAlternatives ? false +, enableCopyArtifacts ? false +, enableExtraFiles ? false + +, bashInteractive, bash-completion +}: + +assert enableBpsync -> enableBeatport; + +let + optionalPlugins = { + absubmit = enableAbsubmit; + acousticbrainz = enableAcousticbrainz; + aura = enableAura; + badfiles = enableBadfiles; + beatport = enableBeatport; + bpsync = enableBpsync; + chroma = enableAcoustid; + convert = enableConvert; + deezer = enableDeezer; + discogs = enableDiscogs; + embyupdate = enableEmbyupdate; + fetchart = enableFetchart; + keyfinder = enableKeyfinder; + kodiupdate = enableKodiupdate; + lastgenre = enableLastfm; + lastimport = enableLastfm; + loadext = enableLoadext; + lyrics = enableLyrics; + mpdstats = enableMpd; + mpdupdate = enableMpd; + playlist = enablePlaylist; + replaygain = enableReplaygain; + sonosupdate = enableSonosUpdate; + subsonicplaylist = enableSubsonicplaylist; + subsonicupdate = enableSubsonicupdate; + thumbnails = enableThumbnails; + web = enableWeb; + }; + + pluginsWithoutDeps = [ + "bareasc" "bench" "bpd" "bpm" "bucket" "duplicates" "edit" "embedart" + "export" "filefilter" "fish" "freedesktop" "fromfilename" "ftintitle" "fuzzy" + "hook" "ihate" "importadded" "importfeeds" "info" "inline" "ipfs" + "mbcollection" "mbsubmit" "mbsync" "metasync" "missing" "parentwork" "permissions" "play" + "plexupdate" "random" "rewrite" "scrub" "smartplaylist" "spotify" "the" + "types" "unimported" "zero" + ]; + + enabledOptionalPlugins = lib.attrNames (lib.filterAttrs (_: lib.id) optionalPlugins); + + allPlugins = pluginsWithoutDeps ++ lib.attrNames optionalPlugins; + allEnabledPlugins = pluginsWithoutDeps ++ enabledOptionalPlugins; + + testShell = "${bashInteractive}/bin/bash --norc"; + completion = "${bash-completion}/share/bash-completion/bash_completion"; + + # This is a stripped down beets for testing of the external plugins. + externalTestArgs.beets = (lib.beets.override { + enableAlternatives = false; + enableCopyArtifacts = false; + enableExtraFiles = false; + }).overrideAttrs (lib.const { + doInstallCheck = false; + }); + +in pythonPackages.buildPythonApplication rec { + pname = "beets"; + # While there is a stable version, 1.4.9, it is more than 1000 commits behind + # master and lacks many bug fixes and improvements[1]. Also important, + # unstable does not require bs1770gain[2]. + # [1]: https://discourse.beets.io/t/forming-a-beets-core-team/639 + # [2]: https://github.com/NixOS/nixpkgs/pull/90504 + version = "unstable-2021-05-13"; + + src = fetchFromGitHub { + owner = "beetbox"; + repo = "beets"; + rev = "1faa41f8c558d3f4415e5e48cf4513d50b466d34"; + sha256 = "sha256-P0bV7WNqCYe9+3lqnFmAoRlb2asdsBUjzRMc24RngpU="; + }; + + propagatedBuildInputs = [ + pythonPackages.six + pythonPackages.enum34 + pythonPackages.jellyfish + pythonPackages.munkres + pythonPackages.musicbrainzngs + pythonPackages.mutagen + pythonPackages.pyyaml + pythonPackages.unidecode + pythonPackages.gst-python + pythonPackages.pygobject3 + pythonPackages.reflink + pythonPackages.confuse + pythonPackages.mediafile + gobject-introspection + ] ++ lib.optional enableAbsubmit essentia-extractor + ++ lib.optional enableAcoustid pythonPackages.pyacoustid + ++ lib.optional enableBeatport pythonPackages.requests_oauthlib + ++ lib.optional enableConvert ffmpeg + ++ lib.optional enableDiscogs pythonPackages.discogs_client + ++ lib.optional (enableFetchart + || enableDeezer + || enableEmbyupdate + || enableKodiupdate + || enableLoadext + || enablePlaylist + || enableSubsonicplaylist + || enableSubsonicupdate + || enableAcousticbrainz) pythonPackages.requests + ++ lib.optional enableKeyfinder keyfinder-cli + ++ lib.optional enableLastfm pythonPackages.pylast + ++ lib.optional enableLyrics pythonPackages.beautifulsoup4 + ++ lib.optional enableMpd pythonPackages.mpd2 + ++ lib.optional enableSonosUpdate pythonPackages.soco + ++ lib.optional enableThumbnails pythonPackages.pyxdg + ++ lib.optional (enableAura + || enableWeb) pythonPackages.flask + ++ lib.optional enableAlternatives beetsExternalPlugins.alternatives + ++ lib.optional enableCopyArtifacts beetsExternalPlugins.copyartifacts + ++ lib.optional enableExtraFiles beetsExternalPlugins.extrafiles + ; + + buildInputs = [ + imagemagick + ] ++ (with gst_all_1; [ + gst-plugins-base + gst-plugins-good + gst-plugins-ugly + ]); + + checkInputs = with pythonPackages; [ + beautifulsoup4 + mock + nose + rarfile + responses + # Although considered as plugin dependencies, they are needed for the + # tests, for disabling them via an override makes the build fail. see: + # https://github.com/beetbox/beets/blob/v1.4.9/setup.py + pylast + mpd2 + discogs_client + pyxdg + ]; + + patches = [ + # Bash completion fix for Nix + ./bash-completion-always-print.patch + # From some reason upstream assumes the program 'keyfinder-cli' is located + # in the path as `KeyFinder` + ./keyfinder-default-bin.patch + ] + # We need to force ffmpeg as the default, since we do not package + # bs1770gain, and set the absolute path there, to avoid impurities. + ++ lib.optional enableReplaygain (substituteAll { + src = ./replaygain-default-ffmpeg.patch; + ffmpeg = lib.getBin ffmpeg; + }) + # Put absolute Nix paths in place + ++ lib.optional enableConvert (substituteAll { + src = ./convert-plugin-ffmpeg-path.patch; + ffmpeg = lib.getBin ffmpeg; + }) + ++ lib.optional enableBadfiles (substituteAll { + src = ./badfiles-plugin-nix-paths.patch; + inherit mp3val flac; + }) + ; + + # Disable failing tests + postPatch = '' + sed -i -e '/assertIn.*item.*path/d' test/test_info.py + echo echo completion tests passed > test/rsrc/test_completion.sh + + sed -i -e 's/len(mf.images)/0/' test/test_zero.py + + # Google Play Music was discontinued + rm -r beetsplug/gmusic.py + ''; + + postInstall = '' + mkdir -p $out/share/zsh/site-functions + cp extra/_beet $out/share/zsh/site-functions/ + ''; + + doCheck = true; + + preCheck = '' + 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 allPlugins "plugins_available"} + ''; + + checkPhase = '' + runHook preCheck + + LANG=en_US.UTF-8 \ + LOCALE_ARCHIVE=${assert stdenv.isLinux; glibcLocales}/lib/locale/locale-archive \ + BEETS_TEST_SHELL="${testShell}" \ + BASH_COMPLETION_SCRIPT="${completion}" \ + HOME="$(mktemp -d)" nosetests -v + + runHook postCheck + ''; + + doInstallCheck = true; + + installCheckPhase = '' + runHook preInstallCheck + + tmphome="$(mktemp -d)" + + EDITOR="${writeScript "beetconfig.sh" '' + #!${runtimeShell} + cat > "$1" <<CFG + plugins: ${lib.concatStringsSep " " allEnabledPlugins} + 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\"" ]; + + passthru = { + # FIXME: remove in favor of pkgs.beetsExternalPlugins + externalPlugins = beetsExternalPlugins; + updateScript = unstableGitUpdater { url = "https://github.com/beetbox/beets"; }; + }; + + meta = with lib; { + description = "Music tagger and library organizer"; + homepage = "http://beets.io"; + license = licenses.mit; + maintainers = with maintainers; [ aszlig doronbehar lovesegfault pjones ]; + platforms = platforms.linux; + }; +} diff --git a/nixpkgs/pkgs/tools/audio/beets/keyfinder-default-bin.patch b/nixpkgs/pkgs/tools/audio/beets/keyfinder-default-bin.patch new file mode 100644 index 000000000000..ec6bc3a5561c --- /dev/null +++ b/nixpkgs/pkgs/tools/audio/beets/keyfinder-default-bin.patch @@ -0,0 +1,26 @@ +diff --git a/beetsplug/keyfinder.py b/beetsplug/keyfinder.py +index 702003f0..08689cd8 100644 +--- a/beetsplug/keyfinder.py ++++ b/beetsplug/keyfinder.py +@@ -31,7 +31,7 @@ class KeyFinderPlugin(BeetsPlugin): + def __init__(self): + super(KeyFinderPlugin, self).__init__() + self.config.add({ +- u'bin': u'KeyFinder', ++ u'bin': u'keyfinder-cli', + u'auto': True, + u'overwrite': False, + }) +diff --git a/test/test_keyfinder.py b/test/test_keyfinder.py +index c8735e47..d7d670a4 100644 +--- a/test/test_keyfinder.py ++++ b/test/test_keyfinder.py +@@ -44,7 +44,7 @@ class KeyFinderTest(unittest.TestCase, TestHelper): + item.load() + self.assertEqual(item['initial_key'], 'C#m') + command_output.assert_called_with( +- ['KeyFinder', '-f', util.syspath(item.path)]) ++ ['keyfinder-cli', util.syspath(item.path)]) + + def test_add_key_on_import(self, command_output): + command_output.return_value = util.CommandOutput(b"dbm", b"") diff --git a/nixpkgs/pkgs/tools/audio/beets/plugins/alternatives.nix b/nixpkgs/pkgs/tools/audio/beets/plugins/alternatives.nix new file mode 100644 index 000000000000..146e9f506641 --- /dev/null +++ b/nixpkgs/pkgs/tools/audio/beets/plugins/alternatives.nix @@ -0,0 +1,32 @@ +{ lib, fetchFromGitHub, beets, pythonPackages }: + +pythonPackages.buildPythonApplication rec { + pname = "beets-alternatives"; + version = "unstable-2021-02-01"; + + src = fetchFromGitHub { + repo = "beets-alternatives"; + owner = "geigerzaehler"; + rev = "288299e3aa9a1602717b04c28696fce5ce4259bf"; + sha256 = "sha256-Xl7AHr33hXQqQDuFbWuj8HrIugeipJFPmvNXpCkU/mI="; + }; + + postPatch = '' + substituteInPlace setup.cfg \ + --replace "addopts = --cov --cov-report=term --cov-report=html" "" + ''; + + nativeBuildInputs = [ beets ]; + + checkInputs = with pythonPackages; [ + pytestCheckHook + mock + ]; + + meta = with lib; { + description = "Beets plugin to manage external files"; + homepage = "https://github.com/geigerzaehler/beets-alternatives"; + maintainers = with maintainers; [ aszlig lovesegfault ]; + license = licenses.mit; + }; +} diff --git a/nixpkgs/pkgs/tools/audio/beets/plugins/copyartifacts.nix b/nixpkgs/pkgs/tools/audio/beets/plugins/copyartifacts.nix new file mode 100644 index 000000000000..2f1ecdfc3695 --- /dev/null +++ b/nixpkgs/pkgs/tools/audio/beets/plugins/copyartifacts.nix @@ -0,0 +1,34 @@ +{ lib, fetchFromGitHub, beets, pythonPackages, glibcLocales }: + +pythonPackages.buildPythonApplication { + pname = "beets-copyartifacts"; + version = "unstable-2020-02-15"; + + src = fetchFromGitHub { + repo = "beets-copyartifacts"; + owner = "adammillerio"; + rev = "85eefaebf893cb673fa98bfde48406ec99fd1e4b"; + sha256 = "sha256-bkT2BZZ2gdcacgvyrVe2vMrOMV8iMAm8Q5xyrZzyqU0="; + }; + + postPatch = '' + sed -i -e '/install_requires/,/\]/{/beets/d}' setup.py + sed -i -e '/namespace_packages/d' setup.py + printf 'from pkgutil import extend_path\n__path__ = extend_path(__path__, __name__)\n' >beetsplug/__init__.py + + # Skip test which is already failing upstream. + sed -i -e '1i import unittest' \ + -e 's/\(^ *\)# failing/\1@unittest.skip/' \ + tests/test_reimport.py + ''; + + nativeBuildInputs = [ beets pythonPackages.nose glibcLocales ]; + + checkPhase = "LANG=en_US.UTF-8 nosetests"; + + meta = { + description = "Beets plugin to move non-music files during the import process"; + homepage = "https://github.com/sbarakat/beets-copyartifacts"; + license = lib.licenses.mit; + }; +} diff --git a/nixpkgs/pkgs/tools/audio/beets/plugins/extrafiles.nix b/nixpkgs/pkgs/tools/audio/beets/plugins/extrafiles.nix new file mode 100644 index 000000000000..9118765cc1be --- /dev/null +++ b/nixpkgs/pkgs/tools/audio/beets/plugins/extrafiles.nix @@ -0,0 +1,32 @@ +{ lib, fetchFromGitHub, beets, pythonPackages }: + +pythonPackages.buildPythonApplication rec { + pname = "beets-extrafiles"; + version = "unstable-2020-12-13"; + + src = fetchFromGitHub { + repo = "beets-extrafiles"; + owner = "Holzhaus"; + rev = "a1d6ef9a9682b6bf7af9483541e56a3ff12247b8"; + sha256 = "sha256-ajuEbieWjTCNjdRZuGUwvStZwjx260jmY0m+ZqNd7ec="; + }; + + postPatch = '' + sed -i -e '/install_requires/,/\]/{/beets/d}' setup.py + sed -i -e '/namespace_packages/d' setup.py + ''; + + nativeBuildInputs = [ beets ]; + + propagatedBuildInputs = with pythonPackages; [ mediafile ]; + + preCheck = '' + HOME=$TEMPDIR + ''; + + meta = { + homepage = "https://github.com/Holzhaus/beets-extrafiles"; + description = "A plugin for beets that copies additional files and directories during the import process"; + license = lib.licenses.mit; + }; +} diff --git a/nixpkgs/pkgs/tools/audio/beets/replaygain-default-ffmpeg.patch b/nixpkgs/pkgs/tools/audio/beets/replaygain-default-ffmpeg.patch new file mode 100644 index 000000000000..0ceba3c09442 --- /dev/null +++ b/nixpkgs/pkgs/tools/audio/beets/replaygain-default-ffmpeg.patch @@ -0,0 +1,26 @@ +diff --git i/beetsplug/replaygain.py w/beetsplug/replaygain.py +index 9d6fa23c..c5800039 100644 +--- i/beetsplug/replaygain.py ++++ w/beetsplug/replaygain.py +@@ -391,7 +391,7 @@ class FfmpegBackend(Backend): + + def __init__(self, config, log): + super(FfmpegBackend, self).__init__(config, log) +- self._ffmpeg_path = "ffmpeg" ++ self._ffmpeg_path = "@ffmpeg@/bin/ffmpeg" + + # check that ffmpeg is installed + try: +@@ -1228,11 +1228,10 @@ class ReplayGainPlugin(BeetsPlugin): + def __init__(self): + super(ReplayGainPlugin, self).__init__() + +- # default backend is 'command' for backward-compatibility. + self.config.add({ + 'overwrite': False, + 'auto': True, +- 'backend': u'command', ++ 'backend': u'ffmpeg', + 'threads': cpu_count(), + 'parallel_on_import': False, + 'per_disc': False, |