diff --git a/README.md b/README.md index 73d08f0..bb82561 100644 --- a/README.md +++ b/README.md @@ -116,6 +116,63 @@ Recommends: vorbis-tools, libdigest-sha-perl, bsd-mailx, glyrc, imagemagick Suggests: eject, distmp3, id3 (>= 0.12), id3v2, eyed3 (<< 0.7~), normalize-audio, vorbisgain, mkcue, mp3gain, atomicparsley ``` +## NixOS +A flake is provided that wires up all the runtime dependencies for you. + +Add the input to your `flake.nix`: +```nix +inputs = { + abcde = { + url = "github:poddmo/abcde"; + inputs.nixpkgs.follows = "nixpkgs"; + }; +}; +``` + +Import the module and enable it in your configuration: +```nix +imports = [ + inputs.abcde.nixosModules.default +]; + +programs.abcde = { + enable = true; + + # Optional: written to /etc/abcde.conf, overriding the packaged defaults. + # Users can still override per-account via ~/.abcde.conf. + settings = { + OUTPUTTYPE = "flac"; + OUTPUTDIR = "/srv/music"; + MAXPROCS = 2; + + # Booleans render as abcde's y/n, so you can use true/false directly. + EJECTCD = true; + PADTRACKS = false; + }; + + # `settings` only covers KEY=value scalars. For anything else abcde.conf + # accepts as shell - notably the munge_* helper functions - use + # extraConfig, which is appended verbatim (no quoting) after settings. + extraConfig = '' + munge_simplify_punctuation () { + sed -e "s/\xe2\x80\x99/'/g" -e 's/\r//g' + } + ''; +}; +``` + +Or just add the package and configure abcde the traditional way with `~/.abcde.conf`: +```nix +environment.systemPackages = [ + inputs.abcde.packages.${pkgs.stdenv.hostPlatform.system}.default +]; +``` + +Or run it directly without installing: +``` +nix run github:poddmo/abcde +``` + # Configuration - Configuration is a process you will refine over time as you rip more CDs and play the files on a variety of music players - I recommend to get started, just put a disc in your optical drive and type: diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..13ef078 --- /dev/null +++ b/flake.lock @@ -0,0 +1,27 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1783224372, + "narHash": "sha256-8i/87eeoqiGE4yOTjwSA3Eh/ziJRQEmd/unYU+K27sk=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "d407951447dcd00442e97087bf374aad70c04cea", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..244b7e5 --- /dev/null +++ b/flake.nix @@ -0,0 +1,36 @@ +{ + description = "abcde - A Better CD Encoder (poddmo fork)"; + + inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + + outputs = + { self, nixpkgs }: + let + # abcde is Linux-only (CD ripping). + systems = [ + "x86_64-linux" + "aarch64-linux" + ]; + forAllSystems = nixpkgs.lib.genAttrs systems; + pkgsFor = system: nixpkgs.legacyPackages.${system}; + in + { + packages = forAllSystems ( + system: + let + abcde = (pkgsFor system).callPackage ./nix/package.nix { }; + in + { + inherit abcde; + default = abcde; + } + ); + + nixosModules = rec { + abcde = import ./nix/module.nix; + default = abcde; + }; + + formatter = forAllSystems (system: (pkgsFor system).nixfmt); + }; +} diff --git a/nix/module.nix b/nix/module.nix new file mode 100644 index 0000000..54ca0db --- /dev/null +++ b/nix/module.nix @@ -0,0 +1,83 @@ +{ + config, + lib, + pkgs, + ... +}: + +let + cfg = config.programs.abcde; + + # Render an attrset of settings into abcde.conf "KEY=value" lines. abcde + # sources this file as shell, so values are shell-quoted. + renderConf = lib.concatStringsSep "\n" ( + lib.mapAttrsToList ( + name: value: + let + v = + if lib.isBool value then + (if value then "y" else "n") + else if lib.isInt value then + toString value + else + lib.escapeShellArg value; + in + "${name}=${v}" + ) cfg.settings + ); + + # settings first, then any raw extraConfig (e.g. shell function overrides). + etcText = + lib.concatStringsSep "\n" (lib.filter (s: s != "") [ + renderConf + cfg.extraConfig + ]) + + "\n"; +in +{ + options.programs.abcde = { + enable = lib.mkEnableOption "abcde, a command-line audio CD ripper"; + + package = lib.mkPackageOption pkgs "abcde" { }; + + settings = lib.mkOption { + type = + with lib.types; + attrsOf (oneOf [ + str + int + bool + ]); + default = { }; + example = lib.literalExpression '' + { + OUTPUTTYPE = "flac"; + CDROMREADERSYNTAX = "cdparanoia"; + OUTPUTDIR = "/srv/music"; + } + ''; + description = "Variables written to {file}`/etc/abcde.conf`. Booleans render as abcde's `y`/`n`."; + }; + + extraConfig = lib.mkOption { + type = lib.types.lines; + default = ""; + example = '' + munge_simplify_punctuation () { + sed -e "s/\xe2\x80\x99/'/g" -e 's/\r//g' + } + ''; + description = "Extra lines appended verbatim to {file}`/etc/abcde.conf`, written without quoting."; + }; + }; + + config = lib.mkIf cfg.enable { + environment.systemPackages = [ cfg.package ]; + + # abcde reads /etc/abcde.conf after the package's baked defaults and before + # ~/.abcde.conf, so this is the right layer for system-wide overrides. + environment.etc."abcde.conf" = lib.mkIf (cfg.settings != { } || cfg.extraConfig != "") { + text = etcText; + }; + }; +} diff --git a/nix/package.nix b/nix/package.nix new file mode 100644 index 0000000..acfaacc --- /dev/null +++ b/nix/package.nix @@ -0,0 +1,117 @@ +{ + lib, + stdenv, + cddiscid, + wget, + which, + vorbis-tools, + id3v2, + python3Packages, + lame, + flac, + opus-tools, + speex, + wavpack, + monkeysAudio, + glyr, + imagemagick, + mkcue, + normalize, + vorbisgain, + eject, + atomicparsley, + libcdio-paranoia, + perlPackages, + makeWrapper, +}: + +stdenv.mkDerivation { + pname = "abcde"; + version = "2.12.2"; + + # Sources live at the repo root, one level up from this file. + src = ../.; + + nativeBuildInputs = [ makeWrapper ]; + + buildInputs = with perlPackages; [ + perl + MusicBrainz + MusicBrainzDiscID + IOSocketSSL + ]; + + configurePhase = '' + runHook preConfigure + + # The Makefile hardcodes /usr/bin/install and /usr/local. + sed -i "s|^[[:blank:]]*prefix *=.*$|prefix = $out|g ; + s|^[[:blank:]]*INSTALL *=.*$|INSTALL = install -c|g" \ + Makefile + + # abcde hardcodes CDPARANOIA=cdparanoia before reading any config + # (abcde:4307), so point it at cd-paranoia through a config file. + echo 'CDPARANOIA=${lib.getExe libcdio-paranoia}' >>abcde.conf + echo CDROMREADERSYNTAX=cdparanoia >>abcde.conf + + # Source the packaged defaults before /etc/abcde.conf, so a bare install + # works while /etc (e.g. the NixOS module) and ~/.abcde.conf can override. + substituteInPlace abcde \ + --replace-fail \ + "# Load system defaults" \ + "if [ -r $out/etc/abcde.conf ]; then . $out/etc/abcde.conf; fi + # Load system defaults" + + runHook postConfigure + ''; + + installFlags = [ "sysconfdir=$(out)/etc" ]; + + postFixup = '' + for cmd in abcde cddb-tool abcde-musicbrainz-tool; do + wrapProgram "$out/bin/$cmd" \ + --prefix PERL5LIB : "$PERL5LIB" \ + --prefix PATH ":" ${ + lib.makeBinPath [ + (placeholder "out") + which + libcdio-paranoia + cddiscid + wget + vorbis-tools + id3v2 + python3Packages.eyed3 + lame + flac + opus-tools + speex + wavpack + monkeysAudio + glyr + imagemagick + mkcue + normalize + vorbisgain + eject + atomicparsley + ] + } + done + ''; + + meta = { + homepage = "https://github.com/poddmo/abcde"; + description = "Command-line audio CD ripper (poddmo fork of abcde)"; + longDescription = '' + abcde grabs tracks off a CD, encodes them to formats such as FLAC, + Opus, MP3 or Ogg/Vorbis, and tags them, all in one go. This poddmo + fork focuses on lossless FLAC output and capturing as much archival + information from the read process as possible (TOC, cue sheets, + CD-TEXT, cover art and rich metadata). + ''; + license = lib.licenses.gpl2Plus; + maintainers = [ ]; + mainProgram = "abcde"; + platforms = lib.platforms.linux; + }; +}