No description
  • Rust 96.8%
  • Nix 3.2%
Find a file
atagen 1df2be2a87 docs: document the expanded player surface
Users need the persistence, interchange, normalization, and protocol limits stated where they configure and automate the daemon.
2026-09-18 00:03:46 +10:00
contrib player: add expected library and playback features 2026-09-18 00:03:46 +10:00
docs docs: document the expanded player surface 2026-09-18 00:03:46 +10:00
nix nix: expose every daemon setting 2026-09-18 00:03:46 +10:00
src player: add expected library and playback features 2026-09-18 00:03:46 +10:00
.cade init 2026-09-08 13:55:50 +10:00
.gitignore init 2026-09-08 13:55:50 +10:00
Cargo.lock playback: stream remote audio through appsrc 2026-09-18 00:02:49 +10:00
Cargo.toml playback: stream remote audio through appsrc 2026-09-18 00:02:49 +10:00
flake.lock init 2026-09-08 13:55:50 +10:00
flake.nix nix: expose every daemon setting 2026-09-18 00:03:46 +10:00
LICENSE init 2026-09-08 13:55:50 +10:00
README.md docs: document the expanded player surface 2026-09-18 00:03:46 +10:00

MUD

MUD is a music daemon for Linux. It owns the library, queue, playlists, and playback, and exposes all of it through a versioned JSON protocol over a per-user Unix socket. mudd is the daemon; mud is its command-line client, and any TUI, GUI, or script can speak the same protocol.

Out of the box MUD plays local files and Subsonic libraries through GStreamer, keeps the queue and playlists in SQLite so they survive restarts, publishes live events for library, queue, player, scanner, source, playlist, and artwork changes, and shows up on the session bus as an MPRIS player. It installs cleanly as a Nix package, a NixOS user service, or a plain systemd user unit.

What MUD can do today

Library: scan local roots with content-aware change detection, full-text search over titles, artists, albums, genres, and contributors, hierarchical browsing by artist, album, genre, year, and source, per-track details, and Subsonic sync with salted token auth, paginated discovery, and bounded parallel fetching. Metadata covers display and plural artists, album artists, dates, lyrics, work/movement, MusicBrainz and industry identifiers, ReplayGain/R128 values, and locally indexed duration. Untagged files use the filename stem as their title. The 8 MiB scanner ceiling limits cumulative metadata reads for each file, not the size of the media file.

Playback and queue: GStreamer playbin3 playback with play, pause, resume, stop, next, previous, seek, volume, mute, repeat, deterministic shuffle, ReplayGain normalization, perceptual volume scaling, gapless queue transitions, broken-track skipping, and restart resume; a persistent, revision-safe queue with add, remove, move, replace, and clear; daemon-owned persistent playlists with full mutation operations, M3U/M3U8 interchange, and direct playback; persistent favorites and a bounded recent listening history; embedded or common sidecar artwork with a bounded private cache.

Control: the mud CLI covers every protocol operation including search, browse, favorites, recent history, scan, source sync, queue and playlist editing, playlist import and export, playback transport, and live watch event streams. Queue and playlist mutations accept an expected revision so concurrent GUI/TUI edits fail loudly instead of silently clobbering each other. The protocol is versioned (currently version 1, reported by hello), capability-described, length-prefixed JSON, and documented in docs/protocol.md.

Service integration: hardened systemd user unit, desktop entry, MPRIS adapter sharing the same protocol as every other client, XDG paths with strict 0700 / 0600 permissions, UID-checked socket peers, and a NixOS module with secret-file support for Subsonic passwords.

Quick start

nix develop
cargo build
cargo run --bin mudd
cargo run --bin mud -- status
cargo run --bin mud -- scan /path/to/music
cargo run --bin mud -- search "artist or title"
cargo run --bin mud -- play TRACK_UUID
cargo run --bin mud -- watch

mud subcommands cover status, search, browse, fields, details, favorite, recent, scan, source list, source sync, artwork, play, play-entry, pause, resume, stop, next, previous, seek, volume, mute, unmute, queue, playlist, and watch. The favorite command supports add, remove, and list. recent lists listening history. queue shuffle toggles the persisted traversal order. playlist import and playlist export handle M3U and M3U8 files. Run mud --help for the full tree.

The daemon uses $XDG_RUNTIME_DIR/mud/control.sock, $XDG_DATA_HOME/mud/library.sqlite3, $XDG_CONFIG_HOME/mud/config.toml, and $XDG_CACHE_HOME/mud/artwork/. Set MUD_GST_AUDIO_SINK=fakesink to exercise playback without an audio device.

Configuration

[local]
roots = ["/home/me/Music", "/mnt/archive/music"]
scan_on_start = true
scan_interval_seconds = 3600 # zero disables periodic reconciliation
watch = false                # optional inotify responsiveness hints
watch_debounce_seconds = 2
watch_max_directories = 8192
[[subsonic]]
name = "home"
url = "https://music.example.net" # server root, not the /rest path
username = "alice"
password_env = "MUD_SUBSONIC_PASSWORD_HOME" # kept in daemon memory only
sync_on_start = true
sync_interval_seconds = 3600
parallel_requests = 4
[playback.replaygain]
mode = "track"
fallback_gain_db = 0.0
preamp_db = 0.0
headroom_db = 0.0

ReplayGain is applied in the playback pipeline. mode selects track or album tags, fallback_gain_db applies when tags are absent, preamp_db adds gain, and headroom_db reserves clipping headroom. User volume remains in the 0.0..=1.0 range and uses a cubic audio-gain curve.

See contrib/config.toml. Manual mud scan always works. Use mud source list to find a Subsonic source UUID, then run mud source sync SOURCE_UUID. Scans are rejected while one is active. The NixOS module exposes every daemon configuration field under services.mud.settings with matching defaults and validation.

Install

nix build .#mud
nix profile install .#mud

The flake provides a package wrapping mudd with its GStreamer plugins plus overlays.default, nixosModules.default, and nixosModules.mud. For NixOS, import the module and set services.mud:

services.mud = {
  enable = true;
  settings.local = {
    roots = [ "/home/you/Music" ];
    scan_on_start = true;
    scan_interval_seconds = 3600;
  };
};

Subsonic passwords stay out of the store: put only password_env in settings and point environmentFile at a secret file, or leave settings empty and set configFile to a runtime path. After rebuilding, check systemctl --user status mudd and journalctl --user -u mudd -f.

Without Nix, install the release binaries to ~/.local/bin and enable the example unit at contrib/systemd/mudd.service:

install -Dm755 target/release/mudd ~/.local/bin/mudd
install -Dm755 target/release/mud ~/.local/bin/mud
install -Dm644 contrib/systemd/mudd.service ~/.config/systemd/user/mudd.service
systemctl --user daemon-reload
systemctl --user enable --now mudd.service

A desktop entry lives at contrib/mud.desktop.

How it works

One nonblocking socket thread, one core thread owning state and SQLite writes, one GStreamer thread, and a bounded scanner pool communicate over bounded channels; there is no async runtime. The queue persists transactionally, events are bounded invalidation hints recoverable through snapshots, and artwork is fetched on demand rather than during scans.

Deliberately deferred: Jellyfin, Spotify and external engines, crossfade, MPD compatibility, and stable cross-source artist identity.

License

MUD is licensed under the European Union Public Licence v. 1.2 (EUPL-1.2). See LICENSE.