diff --git a/pkgs/applications/audio/mp3gain/default.nix b/pkgs/applications/audio/mp3gain/default.nix index 340658f813d..3fef8398e9c 100644 --- a/pkgs/applications/audio/mp3gain/default.nix +++ b/pkgs/applications/audio/mp3gain/default.nix @@ -14,8 +14,7 @@ stdenv.mkDerivation { buildFlags = [ "OSTYPE=linux" ]; installPhase = '' - mkdir -p $out/usr/bin - cp mp3gain $out/usr/bin + install -vD mp3gain "$out/bin/mp3gain" ''; meta = { diff --git a/pkgs/tools/audio/beets/default.nix b/pkgs/tools/audio/beets/default.nix new file mode 100644 index 00000000000..7e14154eb20 --- /dev/null +++ b/pkgs/tools/audio/beets/default.nix @@ -0,0 +1,177 @@ +{ stdenv, fetchFromGitHub, writeScript +, buildPythonPackage, pythonPackages, python + +, enableAcoustid ? true +, enableBeatport ? true +, enableDiscogs ? true +, enableEchonest ? true +, enableFetchart ? true +, enableLastfm ? true +, enableMpd ? true +, enableReplaygain ? true +, enableWeb ? true + +, bashInteractive, bashCompletion +}: + +assert enableAcoustid -> pythonPackages.pyacoustid != null; +assert enableBeatport -> pythonPackages.responses != null; +assert enableDiscogs -> pythonPackages.discogs_client != null; +assert enableEchonest -> pythonPackages.pyechonest != null; +assert enableFetchart -> pythonPackages.responses != null; +assert enableLastfm -> pythonPackages.pylast != null; +assert enableMpd -> pythonPackages.mpd != null; +assert enableReplaygain -> pythonPackages.audiotools != null; +assert enableWeb -> pythonPackages.flask != null; + +with stdenv.lib; + +let + optionalPlugins = { + beatport = enableBeatport; + chroma = enableAcoustid; + discogs = enableDiscogs; + echonest = enableEchonest; + echonest_tempo = enableEchonest; + fetchart = enableFetchart; + lastgenre = enableLastfm; + lastimport = enableLastfm; + mpdstats = enableMpd; + mpdupdate = enableMpd; + replaygain = enableReplaygain; + web = enableWeb; + }; + + pluginsWithoutDeps = [ + "bench" "bpd" "bpm" "bucket" "convert" "duplicates" "embedart" "freedesktop" + "fromfilename" "ftintitle" "fuzzy" "ihate" "importadded" "importfeeds" + "info" "inline" "keyfinder" "lyrics" "mbcollection" "mbsync" "missing" + "play" "random" "rewrite" "scrub" "smartplaylist" "spotify" "the" "types" + "zero" + ]; + + enabledOptionalPlugins = attrNames (filterAttrs (_: id) optionalPlugins); + + allPlugins = pluginsWithoutDeps ++ attrNames optionalPlugins; + allEnabledPlugins = pluginsWithoutDeps ++ enabledOptionalPlugins; + + # Discogs plugin wants to have an API token, so skip install checks. + allTestablePlugins = remove "discogs" allEnabledPlugins; + + testShell = "${bashInteractive}/bin/bash --norc"; + completion = "${bashCompletion}/share/bash-completion/bash_completion"; + +in buildPythonPackage rec { + name = "beets-${version}"; + version = "1.3.9"; + namePrefix = ""; + + src = fetchFromGitHub { + owner = "sampsyo"; + repo = "beets"; + rev = "v${version}"; + sha256 = "1srhkiyjqx6i3gn20ihf087l5pa77yh5b81ivc52lj491fda7xqk"; + }; + + propagatedBuildInputs = [ + pythonPackages.enum34 + pythonPackages.munkres + pythonPackages.musicbrainzngs + pythonPackages.mutagen + pythonPackages.pyyaml + pythonPackages.unidecode + python.modules.sqlite3 + python.modules.readline + ] ++ optional enableAcoustid pythonPackages.pyacoustid + ++ optional (enableBeatport || enableFetchart) pythonPackages.requests2 + ++ optional enableDiscogs pythonPackages.discogs_client + ++ optional enableEchonest pythonPackages.pyechonest + ++ optional enableLastfm pythonPackages.pylast + ++ optional enableMpd pythonPackages.mpd + ++ optional enableReplaygain pythonPackages.audiotools + ++ optional enableWeb pythonPackages.flask; + + buildInputs = with pythonPackages; [ + beautifulsoup4 + flask + mock + nose + pyechonest + pylast + rarfile + requests2 + responses + ]; + + patches = [ + ./mediafile-codec-fix.patch + ./replaygain-default-audiotools.patch + ]; + + postPatch = '' + sed -i -e '/assertIn.*item.*path/d' test/test_info.py + echo echo completion tests passed > test/test_completion.sh + + sed -i -e '/^BASH_COMPLETION_PATHS *=/,/^])$/ { + /^])$/i u"${completion}" + }' beets/ui/commands.py + ''; + + doCheck = true; + + preCheck = '' + (${concatMapStrings (s: "echo \"${s}\";") allPlugins}) \ + | sort -u > plugins_defined + 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 + + if ! mismatches="$(diff -y plugins_defined plugins_available)"; then + echo "The the list of defined plugins (left side) doesn't match" \ + "the list of available plugins (right side):" >&2 + echo "$mismatches" >&2 + exit 1 + fi + ''; + + checkPhase = '' + runHook preCheck + + 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" '' + #!${stdenv.shell} + cat > "$1" < +Date: Wed, 26 Nov 2014 19:04:40 -0800 +Subject: [PATCH] Fix codec reference in MediaFile (fix #1117) + +--- + beets/mediafile.py | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/beets/mediafile.py b/beets/mediafile.py +index ce42621..a459e09 100644 +--- a/beets/mediafile.py ++++ b/beets/mediafile.py +@@ -1340,8 +1340,9 @@ def __init__(self, path, id3v23=False): + raise FileTypeError(path) + elif (type(self.mgfile).__name__ == 'M4A' or + type(self.mgfile).__name__ == 'MP4'): +- if hasattr(self.mgfile.info, 'codec'): +- if self.mgfile.codec and self.mgfile.codec.startswith('alac'): ++ info = self.mgfile.info ++ if hasattr(info, 'codec'): ++ if info.codec and info.codec.startswith('alac'): + self.type = 'alac' + else: + self.type = 'aac' diff --git a/pkgs/tools/audio/beets/replaygain-default-audiotools.patch b/pkgs/tools/audio/beets/replaygain-default-audiotools.patch new file mode 100644 index 00000000000..d852ea6feca --- /dev/null +++ b/pkgs/tools/audio/beets/replaygain-default-audiotools.patch @@ -0,0 +1,17 @@ +diff --git a/beetsplug/replaygain.py b/beetsplug/replaygain.py +index 40b3a3a..9b54a5a 100644 +--- a/beetsplug/replaygain.py ++++ b/beetsplug/replaygain.py +@@ -627,11 +627,10 @@ class ReplayGainPlugin(BeetsPlugin): + super(ReplayGainPlugin, self).__init__() + self.import_stages = [self.imported] + +- # default backend is 'command' for backward-compatibility. + self.config.add({ + 'overwrite': False, + 'auto': True, +- 'backend': u'command', ++ 'backend': u'audiotools', + 'targetlevel': 89, + }) + diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index f066f339f08..aef3dc31166 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -757,6 +757,8 @@ let beanstalkd = callPackage ../servers/beanstalkd { }; + beets = callPackage ../tools/audio/beets { }; + bgs = callPackage ../tools/X11/bgs { }; biber = callPackage ../tools/typesetting/biber { diff --git a/pkgs/top-level/python-packages.nix b/pkgs/top-level/python-packages.nix index 77e380105c8..1f84bf22220 100644 --- a/pkgs/top-level/python-packages.nix +++ b/pkgs/top-level/python-packages.nix @@ -531,6 +531,36 @@ let }; }); + audioread = buildPythonPackage rec { + name = "audioread-1.2.1"; + + src = pkgs.fetchurl { + url = "https://pypi.python.org/packages/source/a/audioread/${name}.tar.gz"; + md5 = "01a80357f38dbd9bf8d7403802df89ac"; + }; + + meta = { + description = "Cross-platform audio decoding"; + homepage = "https://github.com/sampsyo/audioread"; + license = stdenv.lib.licenses.mit; + }; + }; + + audiotools = buildPythonPackage rec { + name = "audiotools-2.22"; + + src = pkgs.fetchurl { + url = "mirror://sourceforge/audiotools/${name}.tar.gz"; + sha256 = "1c52pggsbxdbj8h92njf4h0jgfndh4yv58ad723pidys47nw1y71"; + }; + + meta = { + description = "Utilities and Python modules for handling audio."; + homepage = "http://audiotools.sourceforge.net/"; + license = stdenv.lib.licenses.gpl2Plus; + }; + }; + autopep8 = buildPythonPackage (rec { name = "autopep8-1.0.4"; @@ -789,44 +819,6 @@ let }; }; - beets = buildPythonPackage rec { - name = "beets-1.3.6"; - - src = pkgs.fetchurl { - url = "http://pypi.python.org/packages/source/b/beets/${name}.tar.gz"; - md5 = "59615a54b3ac3983159e77ff9dda373e"; - }; - - # tests depend on $HOME setting - preConfigure = "export HOME=$TMPDIR"; - - propagatedBuildInputs = - [ self.pyyaml - self.unidecode - self.mutagen - self.munkres - self.musicbrainzngs - self.enum34 - self.pylast - self.rarfile - self.flask - modules.sqlite3 - modules.readline - ]; - - buildInputs = with self; [ mock pyechonest six responses nose ]; - - # 10 tests are failing - doCheck = false; - - meta = { - homepage = http://beets.radbox.org; - description = "Music tagger and library organizer"; - license = licenses.mit; - maintainers = [ stdenv.lib.maintainers.iElectric ]; - }; - }; - circus = buildPythonPackage rec { name = "circus-0.11.1"; @@ -2191,6 +2183,23 @@ let }; }; + discogs_client = buildPythonPackage rec { + name = "discogs-client-2.0.2"; + + src = pkgs.fetchurl { + url = "https://pypi.python.org/packages/source/d/discogs-client/${name}.tar.gz"; + md5 = "2cc57e1d134aa93404e779b9311676fa"; + }; + + propagatedBuildInputs = with self; [ oauth2 requests ]; + + meta = { + description = "Official Python API client for Discogs"; + license = licenses.bsd2; + homepage = "https://github.com/discogs/discogs_client"; + }; + }; + dns = buildPythonPackage rec { name = "dnspython-${version}"; version = "1.12.0"; @@ -5760,15 +5769,15 @@ let }; mutagen = buildPythonPackage (rec { - name = "mutagen-1.23"; + name = "mutagen-1.27"; src = pkgs.fetchurl { url = "http://pypi.python.org/packages/source/m/mutagen/${name}.tar.gz"; - sha256 = "12f70aaf5ggdzll76bhhkn64b27xy9s1acx417dbsaqnnbis8s76"; + md5 = "6a9bb5cc33214add35348f1bb3448340"; }; - # one unicode test fails - doCheck = false; + # Needed for tests only + buildInputs = [ pkgs.faad2 pkgs.flac pkgs.vorbisTools pkgs.liboggz ]; meta = { description = "Python multimedia tagging library"; @@ -6984,6 +6993,30 @@ let }; + pyacoustid = buildPythonPackage rec { + name = "pyacoustid-1.1.0"; + + src = pkgs.fetchurl { + url = "https://pypi.python.org/packages/source/p/pyacoustid/${name}.tar.gz"; + md5 = "b27c714d530300b917eb869726334226"; + }; + + propagatedBuildInputs = with self; [ requests audioread ]; + + postPatch = '' + sed -i \ + -e '/^FPCALC_COMMAND *=/s|=.*|= "${pkgs.chromaprint}/bin/fpcalc"|' \ + acoustid.py + ''; + + meta = { + description = "Bindings for Chromaprint acoustic fingerprinting"; + homepage = "https://github.com/sampsyo/pyacoustid"; + license = stdenv.lib.licenses.mit; + }; + }; + + pyalgotrade = buildPythonPackage { name = "pyalogotrade-0.16";