- Rust 98.5%
- Nix 1.5%
| contrib | ||
| docs | ||
| nix | ||
| src | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| flake.lock | ||
| flake.nix | ||
| LICENSE | ||
| README.md | ||
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, and ReplayGain/R128 values.
Playback and queue: GStreamer playbin3 playback with play, pause, resume,
stop, next, previous, seek, volume, mute, and repeat; a persistent,
revision-safe queue with add, remove, move, replace, and clear; daemon-owned
persistent playlists with full mutation operations and direct playlist
playback; on-demand artwork with a bounded private cache.
Control: the mud CLI covers every protocol operation including search,
browse, scan, source sync, queue and playlist editing, 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,
scan, source list, source sync, artwork, play, play-entry, pause,
resume, stop, next, previous, seek, volume, mute, unmute,
queue, playlist, and watch. 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
See contrib/config.toml. Manual mud scan and
mud source sync home always work; scans are rejected while one is active.
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, ReplayGain application, gapless playback and crossfade, MPD compatibility, shuffle, and stable cross-source artist identity.
License
MUD is licensed under the European Union Public Licence v. 1.2 (EUPL-1.2).
See LICENSE.