CCE

Listening to Music with MPD

Contents

Listening To Music is something I do a fair lot, and I remain displeased with the clients and interfaces at my disposal. Currently, I use MPD, the Music Playing Daemon which is a local server and a set of clients. On My Laptop where i have Emacs I use a few different clients for different usecases, each one well works for different uses.

MPD and Client Setup

nix:tangle ~/nix/hm/mpd.nix
{ config, pkgs, ... }:

let mkNixGLWrapper = pkgs.lib.mkNixGLWrapper;
    cantata = (mkNixGLWrapper { name="cantata"; });
in {
  services.mpd = {
    enable = true;
    musicDirectory = "/home/rrix/Music";
    playlistDirectory = "/home/rrix/Music/playlists";
    dataDir = "/home/rrix/Music";
    network.listenAddress = "any";
    extraConfig = ''
    audio_output {
        type                    "pulse"
        name                    "My Pulse Output"
    }
    audio_output {
        type                    "fifo"
        name                    "my_fifo"
        path                    "/tmp/mpd.fifo"
        format                  "44100:16:2"
    }
  '';
  };
  services.mpdris2.enable = true;

  programs.ncmpcpp = {
    enable = true;
    settings = {
      visualizer_data_source = "/tmp/mpd.fifo";
      visualizer_output_name = "my_fifo";
      visualizer_in_stereo = "yes";
      visualizer_type = "spectrum";
      visualizer_look = "+|";
    };
    bindings = [
      { key = "j"; command = "scroll_down"; }
      { key = "k"; command = "scroll_up"; }
      { key = "J"; command = [ "select_item" "scroll_down" ]; }
      { key = "K"; command = [ "select_item" "scroll_up" ]; }
    ];
    package = pkgs.ncmpcpp.override { visualizerSupport = true; };
  };

  home.file.".config/autostart/cantata.desktop".source = "${cantata}/share/applications/cantata.desktop";
  home.packages = [ pkgs.mpc cantata ];
}
emacs-lisp:tangle ~/nix/lisp/mpd.el
(use-package mingus)

Mopidy and a Local "Native" Bandcamp client

References

Mopidy is an extensible music server written in Python. It's mostly designed to provide an easy hardware jukebox for Spotify or whatever crappy web service you want to use. I use it for Bandcamp, mainly. There is NixOS module support for it so I enable it in My NixOS configuration. I want to use it for Youtube Music but this doesn't work reliably because they're fucking cops, though...

: #+ARROYO_NIXOS_MODULE: nixos/mopidy.nix : #+ARROYO_SYSTEM_ROLE: endpoint

nix:tangle ~/nix/nixos/mopidy.nix:noweb yes
{ pkgs, ...}:
let
  extPkgs = with pkgs; [
    mopidy-bandcamp
    mopidy-mpd
    mopidy-youtube
  ];
in {
  <<pipewire>>
  <<firewallPorts>>

  systemd.services.mopidy.wants = [ "network-online.target" ];
  services.mopidy = {
    enable = false;
    extensionPackages = extPkgs;
    dataDir = "/var/lib/mopidy";
    settings = {
      audio.output = "pulsesink server=127.0.0.1";
      bandcamp = {
        discover_tags = "8-bit, chiptune, idm, ambient, drone, experimental, dark ambient, glitch, cyberpunk,  nu-jazz, gameboy, breakcore, edm, indie, indie-folk, indie-punk, indie rock, eugene, seattle, phoenix";
          identity = builtins.readFile <org/cce/bandcamp-cookie.txt>;
      };
      youtube = {
        musicapi_cookie = builtins.readFile <org/cce/ytmusic-cookie.txt>;
        musicapi_enabled = true;
      };
      mpd = {
        enabled = true;
        port = 6601;
        hostname = "::";
      };
    };
  };
}

Firewall ports for MPD and Mopidy

nix#+name: firewallPorts:noweb-ref firewallPorts
networking.firewall.allowedTCPPorts = [ 6600 6601 ];

PipeWire-Pulse TCP audio

This configures PipeWire to listen for TCP connections so that the service-user which is set up for Mopidy is able to send audio to my speakers through a PipeWire run through My NixOS user.

(output) above points Mopidy at it.

nix#+name: pipewire
# Set up PipeWire to listen on TCP so that the mopidy user can send audio
services.pipewire.extraConfig.pipewire-pulse."10-enable-tcp-pulse" = {
  "context.exec" = [
    {
      "args" = "load-module module-native-protocol-tcp";
      "path" = "pactl";
    }
  ];
  "pulse.properties" = {
    "server.address" = [
      "unix:native"
      "tcp:4713"
    ];
  };
};

DONE fix this...

Mopidy Bandcamp package

Here's a simple little PyPI package wrapper. This lets me play from my wishlist and discovery tags and my collection. I add stuff on my phone when I'm bored and decide whether I want to buy them later on. This is shoved in to the rixpkgs overlay.

nix:tangle ~/nix/pkgs/mopidy-bandcamp.nix
{ inputs,
  python3Packages,
  mopidy,
  yt-dlp,
  lib,
  callPackage,
  fetchPypi,
  ... }:

python3Packages.buildPythonApplication rec {
  pname = "mopidy-bandcamp";

  version = "1.1.5";
  src = python3Packages.fetchPypi {
    inherit version;
    pname = "Mopidy-Bandcamp";
    sha256 = "012w2iw09skayskbswp5dak0mp5xf3p0ld90lxhh8rczw9q763y2";
  };

  propagatedBuildInputs = [
    mopidy
  ];

  pythonImportsCheck = [ "mopidy_bandcamp" ];

  # has no tests
  doCheck = false;

  meta = with lib; {
    description = "Mopidy extension for playing music from Bandcamp";
    homepage = "https://github.com/impliedchaos/mopidy-bandcamp";
    license = licenses.mit;
    maintainers = [
      {
        email = "nixpkgs@whatthefuck.computer";
        matrix = "@rrix:kickass.systems";
        github = "rrix";
        githubId = 138102;
        name = "rrix";
      }
    ];
  };
}