| @@ -5,33 +5,42 @@ |
| 5 | 5 | | |
| 6 | 6 | | **A fast, keyboard-driven MPD client for your terminal.** |
| 7 | 7 | | |
| 8 | | − | rmptui is a lightweight music player interface for [Music Player Daemon |
| 9 | | − | (MPD)](https://www.musicpd.org/). Browse your library, manage the play queue, |
| 10 | | − | work with playlists, and control playback without leaving the terminal. |
| 8 | + | rmptui is a terminal interface for [Music Player Daemon |
| 9 | + | (MPD)](https://www.musicpd.org/) in the spirit of ncmpcpp and rmpc. Browse your |
| 10 | + | library, manage the queue and playlists, edit tags, read synced lyrics and |
| 11 | + | watch a spectrum visualizer without leaving the terminal. |
| 11 | 12 | | |
| 12 | 13 | |  |
| 13 | 14 | | |
| 14 | | − | ## Highlights |
| 15 | | − | |
| 16 | | − | - **Three focused views:** browse your music library, control the current queue, |
| 17 | | − | and inspect saved playlists. |
| 18 | | − | - **Metadata at a glance:** see artist, track, title, album, and duration in |
| 19 | | − | the browser and queue. |
| 20 | | − | - **Fuzzy, repeatable search:** search the current view with `/`; in the song |
| 21 | | − | browser, keep the query and cycle matching folders and songs with `n` and |
| 22 | | − | `N`. |
| 23 | | − | - **Playlist tools:** load playlists, add selected tracks or folders to a |
| 24 | | − | playlist, create playlists, and rename them. |
| 25 | | − | - **Queue control:** play, remove, reorder, and append tracks. |
| 26 | | − | - **Responsive MPD updates:** the client uses MPD's asynchronous `idle` |
| 27 | | − | notifications instead of regularly polling the server. |
| 28 | | − | - **Direct MPD connection:** speaks MPD's standard text protocol over |
| 29 | | − | asynchronous TCP; no `mpd` crate or WebSocket proxy is required. |
| 15 | + | ## Screens |
| 16 | + | |
| 17 | + | | Key | Screen | What it does | |
| 18 | + | | --- | --- | --- | |
| 19 | + | | `1` | **Queue** | The play queue with configurable columns. Play, remove, reorder, mark, shuffle, clear or save it as a playlist. `L` shows a synced lyrics pane next to it. | |
| 20 | + | | `2` | **Browse** | Your music folders, ncmpcpp style. Stored playlists are listed at the bottom of the root folder. | |
| 21 | + | | `3` | **Playlists** | Stored playlists and their songs: load, play from a song, remove or reorder songs, rename or delete playlists. | |
| 22 | + | | `4` | **Library** | Album artists → albums (with year) → songs. `t` switches between AlbumArtist and Artist. | |
| 23 | + | | `5` | **Tags** | Edit Title, Artist, Album Artist, Album, Track, Disc, Date, Genre and Comment of one or many songs. | |
| 24 | + | | `6` | **Visualizer** | A spectrum analyzer fed by an MPD fifo output. | |
| 25 | + | | `7` | **Lyrics** | Synced lyrics that follow playback, or plain lyrics you can scroll. | |
| 26 | + | |
| 27 | + | Other highlights: |
| 28 | + | |
| 29 | + | - **Instant controls.** All MPD traffic runs in background tasks over MPD's |
| 30 | + | `idle` notifications, so seeking, volume changes and skipping never wait for |
| 31 | + | the UI, and the UI never waits for the server. |
| 32 | + | - **Fuzzy search everywhere.** `/` searches the focused list; `n`/`N` cycle |
| 33 | + | through the matches. |
| 34 | + | - **Marks.** `v` marks items; queue removal, add-to-playlist and tag edits |
| 35 | + | then apply to every marked item. |
| 36 | + | - **Mouse support.** Click to select, double-click to play/open, scroll with |
| 37 | + | the wheel, click a tab to switch screens and click the progress bar to seek. |
| 38 | + | - **TCP or Unix socket**, with password support and automatic reconnection. |
| 30 | 39 | | |
| 31 | 40 | | ## Requirements |
| 32 | 41 | | |
| 33 | 42 | | - A running MPD server with its music library configured. |
| 34 | | − | - Rust and Cargo to build from source. |
| 43 | + | - Rust 1.88 or newer and Cargo to build from source. |
| 35 | 44 | | |
| 36 | 45 | | ## Install |
| 37 | 46 | | |
| @@ -42,9 +51,8 @@ copy it to `/usr/local/bin/rmptui`: |
| 42 | 51 | | ./install.sh |
| 43 | 52 | | ``` |
| 44 | 53 | | |
| 45 | | − | The script uses `sudo` for the system-directory operations when needed. It |
| 46 | | − | requires Rust and Cargo to build from source. To use a different binary |
| 47 | | − | directory or uninstall rmptui: |
| 54 | + | The script uses `sudo` for the system-directory operations when needed. To use |
| 55 | + | a different binary directory or uninstall rmptui: |
| 48 | 56 | | |
| 49 | 57 | | ```sh |
| 50 | 58 | | ./install.sh --bin-dir "$HOME/.local/bin" |
| @@ -63,170 +71,173 @@ cd rmptui |
| 63 | 71 | | cargo run --release |
| 64 | 72 | | ``` |
| 65 | 73 | | |
| 66 | | − | To build and run without installing, use `cargo run --release`. |
| 74 | + | ## Configuration |
| 67 | 75 | | |
| 68 | | − | On first launch, rmptui creates a default configuration file at |
| 76 | + | On first launch rmptui writes a fully commented configuration to |
| 69 | 77 | | `$CONFIG_HOME/rmptui/config.toml`. If `CONFIG_HOME` is not set, it uses |
| 70 | 78 | | `$XDG_CONFIG_HOME/rmptui/config.toml`, then `~/.config/rmptui/config.toml`. |
| 71 | | − | Edit the file and restart rmptui to apply changes: |
| 79 | + | Use `rmptui --config FILE` to load a different file, and |
| 80 | + | `rmptui --print-default-config` to see every option with its default. Restart |
| 81 | + | rmptui to apply changes. |
| 82 | + | |
| 83 | + | You only need to keep the settings you change: anything left out keeps its |
| 84 | + | default, table by table. Unknown options and conflicting key bindings are |
| 85 | + | reported with the file and the offending value. |
| 86 | + | |
| 87 | + | > **Upgrading from 0.1:** the configuration format changed. rmptui refuses to |
| 88 | + | > start with a 0.1 file and tells you so; move the old file aside, start |
| 89 | + | > rmptui to generate the new one, and copy your MPD settings over. |
| 90 | + | |
| 91 | + | The main sections: |
| 72 | 92 | | |
| 73 | 93 | | ```toml |
| 74 | 94 | | [mpd] |
| 75 | | − | host = "127.0.0.1" |
| 95 | + | host = "127.0.0.1" # or a Unix socket path such as "~/.config/mpd/socket" |
| 76 | 96 | | port = 6600 |
| 77 | | − | password = "" # Set this only if your MPD server requires a password. |
| 97 | + | password = "" |
| 98 | + | music_directory = "" # needed for the tag editor and local .lrc files |
| 78 | 99 | | |
| 79 | 100 | | [playback] |
| 80 | | − | seek_seconds = 2 |
| 81 | | − | volume_step = 2 |
| 82 | | − | |
| 83 | | − | [keybindings] |
| 84 | | − | quit = ["q", "Ctrl+c"] |
| 85 | | − | clear_queue = ["c", "C"] |
| 86 | | − | toggle_pause = ["p"] |
| 87 | | − | pause = ["s"] |
| 88 | | − | toggle_repeat = ["r"] |
| 89 | | − | toggle_random = ["z"] |
| 90 | | − | open_playlist_menu = ["a"] |
| 91 | | − | seek_forward = ["f"] |
| 92 | | − | seek_backward = ["b"] |
| 93 | | − | cycle_tabs = ["Tab"] |
| 94 | | − | select_queue = ["1"] |
| 95 | | − | select_browser = ["2"] |
| 96 | | − | select_playlists = ["3"] |
| 97 | | − | next_track = [">"] |
| 98 | | − | previous_track = ["<"] |
| 99 | | − | volume_up = ["=", "+"] |
| 100 | | − | volume_down = ["-"] |
| 101 | | − | toggle_mute = ["m"] |
| 102 | | − | update_database = ["U"] |
| 103 | | − | search = ["/"] |
| 104 | | − | toggle_selected_item = ["Space"] |
| 105 | | − | search_next = ["n"] |
| 106 | | − | search_previous = ["N"] |
| 107 | | − | move_down = ["j", "Down"] |
| 108 | | − | move_up = ["k", "Up"] |
| 109 | | − | activate = ["Enter", "l", "Right"] |
| 110 | | − | go_back = ["h", "Left"] |
| 111 | | − | go_to_top = ["g"] |
| 112 | | − | go_to_bottom = ["G"] |
| 113 | | − | queue_delete = ["d"] |
| 114 | | − | queue_move_down = ["J"] |
| 115 | | − | queue_move_up = ["K"] |
| 116 | | − | playlist_rename = ["R"] |
| 117 | | − | playlist_focus_contents = ["Right", "l"] |
| 118 | | − | playlist_focus_list = ["Left", "h"] |
| 119 | | − | playlist_delete_song = ["d"] |
| 120 | | − | playlist_move_song_down = ["J"] |
| 121 | | − | playlist_move_song_up = ["K"] |
| 122 | | − | playlist_delete = ["D"] |
| 123 | | − | playlist_load = ["Space", "Enter"] |
| 124 | | − | popup_close = ["q", "Esc"] |
| 125 | | − | popup_select = ["Enter"] |
| 126 | | − | input_cancel = ["Esc"] |
| 127 | | − | input_backspace = ["Backspace"] |
| 128 | | − | input_cursor_left = ["Left"] |
| 129 | | − | input_cursor_right = ["Right"] |
| 130 | | − | input_submit = ["Enter"] |
| 101 | + | seek_seconds = 5 |
| 102 | + | volume_step = 5 |
| 103 | + | |
| 104 | + | [ui] |
| 105 | + | startup_screen = "queue" |
| 106 | + | mouse = true |
| 107 | + | lyrics_pane = false |
| 108 | + | queue_columns = [ |
| 109 | + | { field = "artist", width = 25 }, |
| 110 | + | { field = "track", width = 5 }, |
| 111 | + | { field = "title", width = 35 }, |
| 112 | + | { field = "album", width = 30 }, |
| 113 | + | { field = "duration", width = 7 }, |
| 114 | + | ] |
| 115 | + | |
| 116 | + | [theme] |
| 117 | + | accent = "magenta" # color names, 256-color indices or "#rrggbb" |
| 118 | + | visualizer = ["blue", "cyan", "green", "yellow", "red"] |
| 119 | + | |
| 120 | + | [lyrics] |
| 121 | + | online = true # look up lyrics on lrclib.net |
| 122 | + | cache = true |
| 123 | + | |
| 124 | + | [visualizer] |
| 125 | + | fifo = "/tmp/mpd.fifo" |
| 131 | 126 | | ``` |
| 132 | 127 | | |
| 133 | | − | Runtime errors and panic details are appended to `/tmp/rmptui.log`. If logging |
| 134 | | − | cannot be initialized, rmptui prints a warning and continues without a log |
| 135 | | − | file. |
| 128 | + | The MPD connection can also be set with environment variables, which take |
| 129 | + | precedence over the file: |
| 136 | 130 | | |
| 137 | | − | Every listed action is configurable in `[keybindings]`; each value is an array |
| 138 | | − | so actions can have multiple aliases. Remove an alias or set an action to `[]` |
| 139 | | − | to disable it. A key can be a single character or a named key such as `Enter`, |
| 140 | | − | `Esc`, `Tab`, `Space`, `Up`, `Down`, `Left`, `Right`, or `Backspace`. Add |
| 141 | | − | modifiers with `Ctrl+`, `Alt+`, or `Shift+`, for example `Ctrl+x` or |
| 142 | | − | `Alt+Enter`. Bindings are matched in the current UI context, so avoid assigning |
| 143 | | − | the same key to different actions that can be active in the same context. |
| 144 | | − | Characters typed into search and playlist-name fields remain text unless |
| 145 | | − | configured as an input action. |
| 131 | + | | Variable | Description | |
| 132 | + | | --- | --- | |
| 133 | + | | `MPD_HOST` | Hostname, address or Unix socket path. Use `password@host` to set both host and password. | |
| 134 | + | | `MPD_PORT` | Port; an explicit port in `MPD_HOST` takes precedence. | |
| 146 | 135 | | |
| 147 | | − | `playback.seek_seconds` sets the `seek_forward`/`seek_backward` distance, and |
| 148 | | − | `playback.volume_step` sets the `volume_up`/`volume_down` amount. Supported |
| 149 | | − | audio formats remain built in. The config stores an MPD password as plain text; |
| 150 | | − | newly created config files are restricted to the current user. |
| 136 | + | ```sh |
| 137 | + | MPD_HOST=192.168.1.20 MPD_PORT=6600 rmptui |
| 138 | + | MPD_HOST='secret@localhost' rmptui |
| 139 | + | MPD_HOST=~/.config/mpd/socket rmptui |
| 140 | + | ``` |
| 151 | 141 | | |
| 152 | | − | The MPD connection settings can also be overridden with environment variables: |
| 142 | + | Logs (and panic details) are appended to `/tmp/rmptui.log`. Set |
| 143 | + | `RMPTUI_LOG=debug` for more detail. |
| 153 | 144 | | |
| 154 | | − | | Variable | Default | Description | |
| 155 | | − | | --- | --- | --- | |
| 156 | | − | | `MPD_HOST` | Config file | MPD hostname or address. Use `password@host` to set both host and password. | |
| 157 | | − | | `MPD_PORT` | Config file | MPD port; an explicit port in `MPD_HOST` takes precedence. | |
| 145 | + | ### Visualizer |
| 158 | 146 | | |
| 159 | | − | For example: |
| 147 | + | The visualizer reads raw audio from an MPD fifo output. Add this to |
| 148 | + | `mpd.conf` and restart MPD: |
| 160 | 149 | | |
| 161 | | − | ```sh |
| 162 | | − | MPD_HOST=192.168.1.20 MPD_PORT=6600 ./target/release/rmptui |
| 150 | + | ``` |
| 151 | + | audio_output { |
| 152 | + | type "fifo" |
| 153 | + | name "Visualizer feed" |
| 154 | + | path "/tmp/mpd.fifo" |
| 155 | + | format "44100:16:2" |
| 156 | + | } |
| 163 | 157 | | ``` |
| 164 | 158 | | |
| 165 | | − | Or, for a password-protected local server: |
| 159 | + | `[visualizer]` must match the `path` and `format`. The fifo is only read while |
| 160 | + | the Visualizer screen is visible. |
| 166 | 161 | | |
| 167 | | − | ```sh |
| 168 | | − | MPD_HOST='secret@localhost' ./target/release/rmptui |
| 169 | | − | ``` |
| 162 | + | ### Lyrics |
| 170 | 163 | | |
| 171 | | − | ## Controls |
| 164 | + | Lyrics are looked up in this order: |
| 172 | 165 | | |
| 173 | | − | The keys below are the defaults; edit the `[keybindings]` table above to change |
| 174 | | − | them. |
| 166 | + | 1. An `.lrc` file next to the song (`Song.flac` → `Song.lrc`), when the music |
| 167 | + | directory is known. |
| 168 | + | 2. The cache in `$XDG_CACHE_HOME/rmptui/lyrics` (`~/.cache` by default). |
| 169 | + | 3. [LRCLIB](https://lrclib.net), a free lyrics database. Results are cached. |
| 175 | 170 | | |
| 176 | | − | ### Navigation |
| 171 | + | Set `lyrics.online = false` to stay offline. `F5` on the Lyrics screen fetches |
| 172 | + | the lyrics of the current song again. |
| 177 | 173 | | |
| 178 | | − | | Key | Action | |
| 179 | | − | | --- | --- | |
| 180 | | − | | `Tab` | Cycle between Queue, Browser, and Playlists | |
| 181 | | − | | `1` / `2` / `3` | Open Queue / Browser / Playlists | |
| 182 | | − | | `j` / `Down` | Move selection down | |
| 183 | | − | | `k` / `Up` | Move selection up | |
| 184 | | − | | `g` / `G` | Jump to the top / bottom of the current list | |
| 185 | | − | | `Enter` / `l` / `Right` | Activate the selected item | |
| 186 | | − | | `h` / `Left` | Go to the parent directory in the browser | |
| 187 | | − | | `q` / `Ctrl+C` | Quit | |
| 174 | + | ### Tag editor |
| 175 | + | |
| 176 | + | MPD cannot change tags, so the tag editor writes the files directly. That |
| 177 | + | requires the music files to be on this machine: set `mpd.music_directory`, or |
| 178 | + | connect through MPD's Unix socket so rmptui can ask MPD for it. After saving, |
| 179 | + | rmptui asks MPD to rescan the edited folders. |
| 188 | 180 | | |
| 189 | | − | ### Search |
| 181 | + | ## Key bindings |
| 190 | 182 | | |
| 191 | | − | 1. Press `/` and type a query. |
| 192 | | − | 2. In the browser, press `Enter` to keep the query and return to the list. |
| 193 | | − | 3. Press `n` for the next fuzzy match or `N` for the previous match. Results |
| 194 | | − | wrap around when you reach either end. |
| 195 | | − | 4. Press `/` to start a new search, or `Esc` to cancel search input. |
| 183 | + | These are the defaults; every binding is configurable in the `[keys.*]` tables |
| 184 | + | of the config. `?` shows the active bindings inside rmptui. |
| 196 | 185 | | |
| 197 | | − | Search matches the names shown in the current view. Browser search includes |
| 198 | | − | both folders and songs. |
| 186 | + | Bindings are grouped by context. A key is looked up in the focused popup or |
| 187 | + | screen first, then in `navigation`, then in `global`, so screen bindings |
| 188 | + | shadow global ones on that screen (for example `R` renames a playlist on the |
| 189 | + | Playlists screen and toggles consume elsewhere). |
| 199 | 190 | | |
| 200 | | − | ### Playback and queue |
| 191 | + | ### Global |
| 201 | 192 | | |
| 202 | 193 | | | Key | Action | |
| 203 | 194 | | | --- | --- | |
| 195 | + | | `1`–`7` | Switch screen | |
| 196 | + | | `Tab` / `Shift+Tab` | Next / previous screen | |
| 204 | 197 | | | `p` | Toggle play/pause | |
| 205 | | − | | `s` | Pause | |
| 206 | | − | | `>` / `<` | Play next / previous track | |
| 207 | | − | | `f` / `b` | Seek forward / backward by two seconds | |
| 208 | | − | | `+` / `=` / `-` | Increase / decrease volume | |
| 198 | + | | `s` / `x` | Pause / stop | |
| 199 | + | | `>` / `<` | Next / previous track | |
| 200 | + | | `f` / `b` | Seek forward / backward | |
| 201 | + | | `+` `=` / `-` | Volume up / down | |
| 209 | 202 | | | `m` | Toggle mute | |
| 210 | | − | | `r` / `z` | Toggle repeat / random | |
| 211 | | − | | `d` | Remove the selected queue item | |
| 212 | | − | | `Space` | Remove a queue item; toggle a browser song in the queue | |
| 213 | | − | | `J` / `K` | Move the selected queue item down / up | |
| 214 | | − | | `c` | Clear the queue | |
| 215 | | − | | `a` | Open the add-to-playlist menu | |
| 216 | | − | | `U` | Rescan the MPD music database | |
| 217 | | − | |
| 218 | | − | ### Playlists |
| 219 | | − | |
| 220 | | − | The Playlists view has a playlist pane and a contents pane. Select a playlist |
| 221 | | − | with `j`/`k` and press `Space` or `Enter` to load it into the queue and start |
| 222 | | − | playback. Press `Right` or `l` to focus its songs and `Left` or `h` to return |
| 223 | | − | to the playlist pane. In the contents pane, `j`/`k` selects a song, `Enter` |
| 224 | | − | plays it, `d` removes it from the saved playlist, and `J`/`K` moves it |
| 225 | | − | down/up. `D` deletes the selected saved playlist. `R` renames a playlist. |
| 226 | | − | |
| 227 | | − | Press `a` to open the add-to-playlist menu; choose **Current Playlist**, **New |
| 228 | | − | Playlist**, or a saved playlist. When creating a playlist, type its name and |
| 229 | | − | press `Enter` to save. Playlist contents update after each edit. |
| 203 | + | | `r` `z` `y` `R` | Toggle repeat, random, single, consume | |
| 204 | + | | `U` | Rescan the music database | |
| 205 | + | | `?` `F1` | Show key bindings | |
| 206 | + | | `q` `Ctrl+c` | Quit | |
| 207 | + | |
| 208 | + | ### Lists |
| 209 | + | |
| 210 | + | | Key | Action | |
| 211 | + | | --- | --- | |
| 212 | + | | `j` `k` / arrows | Move down / up | |
| 213 | + | | `g` `G` / `Home` `End` | Top / bottom | |
| 214 | + | | `Ctrl+d` `Ctrl+u`, `PageDown` `PageUp` | Half page / page | |
| 215 | + | | `h` `l` / arrows | Back or previous column / open or next column | |
| 216 | + | | `Enter` | Play or open the selected item | |
| 217 | + | | `Space` | Add to the queue (toggles songs in the browser) | |
| 218 | + | | `a` | Add to the queue, a new playlist or an existing one | |
| 219 | + | | `v` / `V` | Mark item / clear marks | |
| 220 | + | | `/`, `n` / `N` | Search, next / previous match | |
| 221 | + | |
| 222 | + | ### Screens |
| 223 | + | |
| 224 | + | | Screen | Key | Action | |
| 225 | + | | --- | --- | --- | |
| 226 | + | | Queue | `d` `Delete` | Remove the song (or all marked songs) | |
| 227 | + | | Queue | `J` / `K` | Move the song down / up | |
| 228 | + | | Queue | `c` | Clear the queue (asks first) | |
| 229 | + | | Queue | `Z` / `S` | Shuffle / save as playlist | |
| 230 | + | | Queue | `o` | Jump to the playing song | |
| 231 | + | | Queue | `L` | Toggle the lyrics pane | |
| 232 | + | | Playlists | `d`, `J` / `K` | Remove / move the selected song | |
| 233 | + | | Playlists | `R` / `D` | Rename / delete the playlist | |
| 234 | + | | Library | `t` | Switch between AlbumArtist and Artist | |
| 235 | + | | Tags | `Enter` | Edit the selected tag | |
| 236 | + | | Tags | `w` / `u` | Write / discard pending changes | |
| 237 | + | | Lyrics | `F5` | Fetch lyrics again | |
| 238 | + | |
| 239 | + | In text fields, `Enter` submits, `Esc` cancels, `Ctrl+w` deletes a word and |
| 240 | + | `Ctrl+a` / `Ctrl+e` jump to the start / end. |
| 230 | 241 | | |
| 231 | 242 | | ## License |
| 232 | 243 | | |