ncspot 0.9.4

ncurses Spotify client written in Rust using librespot, inspired by ncmpc and the likes.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
<p align="center" style="text-align:center">
	<img src="images/logo.svg" width="128px" alt="logo"/>
</p>

# ncspot

[![Crates.io](https://img.shields.io/crates/v/ncspot.svg)](https://crates.io/crates/ncspot)
[![Gitter](https://badges.gitter.im/ncspot/community.svg)](https://gitter.im/ncspot/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
[![Build](https://github.com/hrkfdn/ncspot/workflows/Build/badge.svg)](https://github.com/hrkfdn/ncspot/actions?query=workflow%3ABuild)

[![Packaging status](https://repology.org/badge/vertical-allrepos/ncspot.svg)](https://repology.org/project/ncspot/versions)

[![ncspot](https://snapcraft.io//ncspot/badge.svg)](https://snapcraft.io/ncspot)
[![ncspot](https://snapcraft.io//ncspot/trending.svg?name=0)](https://snapcraft.io/ncspot)

`ncspot` is a ncurses Spotify client written in Rust using `librespot`. It is
heavily inspired by ncurses MPD clients, such as ncmpc. My motivation was to
provide a simple and resource friendly alternative to the official client as
well as to support platforms that currently don't have a Spotify client, such
as the \*BSDs.

[![Search](/images/screenshot-thumb.png?raw=true)](/images/screenshot.png?raw=true)

## Table of Contents

- [ncspot]#ncspot
  - [Table of Contents]#table-of-contents
  - [Resource Footprint Comparison]#resource-footprint-comparison
  - [Installation]#installation
    - [On macOS]#on-macos
    - [On Windows]#on-windows
    - [On Linux]#on-linux
      - [Building a Debian Package]#building-a-debian-package
  - [Build]#build
    - [Audio Backends]#audio-backends
  - [Key Bindings]#key-bindings
    - [Navigation]#navigation
    - [Playback]#playback
    - [Context Menus]#context-menus
    - [Sharing]#sharing
    - [Queue]#queue
    - [Library]#library
    - [Vim-Like Search Bar]#vim-like-search-bar
  - [Vim-Like Commands]#vim-like-commands
  - [Configuration]#configuration
    - [Custom Keybindings]#custom-keybindings
    - [Proxy]#proxy
    - [Theming]#theming
  - [Cover Drawing]#cover-drawing
  - [Authentication]#authentication

## Resource Footprint Comparison

Measured using `ps_mem` on Linux during playback:

| Client  | Private Memory | Shared Memory | Total      |
| ------- | -------------- | ------------- | ---------- |
| ncspot  | 22.1 MiB       | 24.1 MiB      | 46.2 MiB   |
| Spotify | 407.3 MiB      | 592.7 MiB     | 1000.0 MiB |

## Installation

### On macOS

`ncspot` is available via [Homebrew](https://brew.sh/):

```zsh
brew install ncspot
```

### On Windows

`ncspot` is available via [Scoop](https://scoop.sh/):

```powershell
scoop install ncspot
```

### On Linux

Requirements:

- Rust
- Python 3 (needed for building `rust-xcb` dependency)
- `libpulse-dev` (or `portaudio-dev`, if you want to use the PortAudio backend)
- `libncurses-dev` and `libssl-dev`
- `libdbus-1-dev`
- `libxcb` + development headers (for clipboard access)
- `pkg-config`
- A Spotify premium account

On Debian based systems you need following packages for development headers:

```bash
sudo apt install libncursesw5-dev libdbus-1-dev libpulse-dev libssl-dev libxcb1-dev libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev
```

For Fedora, these dependencies are required:

```bash
dnf install pulseaudio-libs-devel libxcb-devel openssl-devel ncurses-devel dbus-devel
```

#### Building a Debian Package

You can use `cargo-deb` create in order to build a Debian package from source.
Install it with:

```bash
cargo install cargo-deb
```

Then you can build a Debian package with:

```bash
cargo deb
```

You can find it under `target/debian`.

## Build

Install the latest `ncspot` release using:

```bash
cargo install ncspot
```

Or build it yourself using:

```bash
cargo build --release

# NB: add these flags on Windows
cargo build --release --no-default-features --features rodio_backend,cursive/pancurses-backend
```

- Both approaches require a working [Rust installation]https://www.rust-lang.org/tools/install.
- For debugging, you can pass a debug log filename and log stderr to a file,
  e.g. :

  ```bash
  RUST_BACKTRACE=full cargo run -- -d debug.log 2> stderr.log
  ```

### Audio Backends

By default `ncspot` is built using the PulseAudio backend. To make it use the
PortAudio backend (e.g. for \*BSD or macOS) or Rodio backend (e.g. for
Windows), you need to recompile `ncspot` with the respective features:

```bash
# PortAudio (BSD/macOS)
cargo run --no-default-features --features portaudio_backend,cursive/pancurses-backend

# Rodio (Windows)
cargo run --no-default-features --features rodio_backend,cursive/pancurses-backend
```

## Key Bindings

The keybindings listed below are configured by default. Additionally, if you
run `ncspot` with MPRIS support, you may be able to use media keys to control
playback depending on your desktop environment settings. Have a look at the
[configuration section](#configuration) if you want to set custom bindings.

### Navigation

| Key               | Command                                                                       |
| :---------------- | :---------------------------------------------------------------------------- |
| <kbd>?</kbd>      | Show help screen.                                                             |
| <kbd>F1</kbd>     | Queue (See [specific commands]#queue).                                      |
| <kbd>F2</kbd>     | Search.                                                                       |
| <kbd>F3</kbd>     | Library (See [specific commands]#library).                                  |
| <kbd>F8</kbd>     | Album Art (if compiled with the `cover` feature).                             |
| <kbd>/</kbd>      | Open a Vim-like search bar (See [specific commands]#vim-like-search-bar).   |
| <kbd>:</kbd>      | Open a Vim-like command prompt (See [specific commands]#vim-like-commands). |
| <kbd>Escape</kbd> | Close Vim-like search bar or command prompt.                                  |
| <kbd>Q</kbd>      | Quit `ncspot`.                                                                |

### Playback

| Key                           | Command                                                        |
| :---------------------------- | :------------------------------------------------------------- |
| <kbd>Return</kbd>             | Play track or playlist.                                        |
| <kbd>Space</kbd>              | Queue track or playlist.                                       |
| <kbd>.</kbd>                  | Play the selected item after the currently playing track.      |
| <kbd>P</kbd>                  | Move to the currently playing track in the queue.              |
| <kbd>S</kbd>                  | Save the currently playing track to your library.              |
| <kbd>D</kbd>                  | Remove the currently playing track from your library.          |
| <kbd>Shift</kbd>+<kbd>P</kbd> | Toggle playback (i.e. Play/Pause).                             |
| <kbd>Shift</kbd>+<kbd>S</kbd> | Stop playback.                                                 |
| <kbd>Shift</kbd>+<kbd>U</kbd> | Update the library cache (tracks, artists, albums, playlists). |
| <kbd><</kbd>                  | Play the previous track.                                       |
| <kbd>></kbd>                  | Play the next track.                                           |
| <kbd>F</kbd>                  | Seek forward.                                                  |
| <kbd>Shift</kbd>+<kbd>F</kbd> | Seek forward with a 10-second step.                            |
| <kbd>B</kbd>                  | Seek backwards.                                                |
| <kbd>Shift</kbd>+<kbd>B</kbd> | Seek backwards with a 10-second step.                          |
| <kbd>-</kbd>                  | Decrease volume by 1.                                          |
| <kbd>+</kbd>                  | Increase volume by 1.                                          |
| <kbd>[</kbd>                  | Decrease volume by 5.                                          |
| <kbd>]</kbd>                  | Increase volume by 5.                                          |
| <kbd>R</kbd>                  | Toggle _Repeat_ mode.                                          |
| <kbd>Z</kbd>                  | Toggle _Shuffle_ state.                                        |

### Context Menus

| Key                           | Command                                                                |
| :---------------------------- | :--------------------------------------------------------------------- |
| <kbd>O</kbd>                  | Open a detail view or context for the **selected item**.               |
| <kbd>Shift</kbd>+<kbd>O</kbd> | Open a context menu for the **currently playing track**.               |
| <kbd>A</kbd>                  | Open the **album view** for the selected item.                         |
| <kbd>Shift</kbd>+<kbd>A</kbd> | Open the **artist view** for the selected item.                        |
| <kbd>M</kbd>                  | Open the **recommendations view** for the **selected item**.           |
| <kbd>Shift</kbd>+<kbd>M</kbd> | Open the **recommendations view** for the **currently playing track**. |
| <kbd>Ctrl</kbd>+<kbd>V</kbd>  | Open the context menu for a Spotify link in your clipboard.            |
| <kbd>Backspace</kbd>          | Close the current view.                                                |

When pressing <kbd>O</kbd>:

- If the _selected item_ is **not** a track, it opens a detail view.
- If the _selected item_ **is** a track, it opens a context menu with:
  - "Show Artist"
  - "Show Album"
  - "Share"
  - "Add to playlist"
  - "Similar tracks"

### Sharing

| Key                           | Command                                                                         |
| :---------------------------- | :------------------------------------------------------------------------------ |
| <kbd>X</kbd>                  | Copy a shareable URL of the **currently selected item** to the system clipboard. |
| <kbd>Shift</kbd>+<kbd>X</kbd> | Copy a shareable URL of the **currently playing track** to the system clipboard. |

### Queue

| Key                          | Command                              |
| :--------------------------- | :----------------------------------- |
| <kbd>C</kbd>                 | Clear the entire queue.              |
| <kbd>D</kbd>                 | Delete the currently selected track. |
| <kbd>Ctrl</kbd>+<kbd>S</kbd> | Delete the currently selected track. |

### Library

| Key          | Command                                 |
| :----------- | :-------------------------------------- |
| <kbd>D</kbd> | Delete the currently selected playlist. |

### Vim-Like Search Bar

| Key          | Command                    |
| :----------- | :------------------------- |
| <kbd>n</kbd> | Previous search occurrence. |
| <kbd>N</kbd> | Next search occurrence.     |

## Vim-Like Commands

You can open a Vim-style command prompt using <kbd>:</kbd>, and close it at any
time with <kbd>Escape</kbd>.

The following is an abridged list of commonly-used commands. For the full list, see [source code](/src/command.rs).

| Command | Action |
|---|---|
| `help` | Show current key bindings. |
| `quit`<br/>Aliases: `q`, `x` | Quit `ncspot`. |
| `logout` | Remove any cached credentials from disk and quit `ncspot`. |
| `playpause`<br/>Aliases: `pause`, `toggleplay`, `toggleplayback` | Toggle playback. |
| `stop` | Stop playback. |
| `seek [+\|-]<time>` | Seek to the specified position, or seek relative to current position by prepending `+`/`-`. Supports mixing time units (e.g. `seek 1m42s`). Default unit is `millisecond`. |
| `repeat [repeat_mode]`<br/>Aliases: `loop` | Set repeat mode. Omit `repeat_mode` argument to step through the available modes. |
| `shuffle [on\|off]` | Enable or disable shuffle. Omit argument to toggle. |
| `previous` | Play previous track. |
| `next` | Play next track. |
| `focus <queue\|search\|library>` | Switch to a screen. |
| `search <keyword>` | Search a song. |
| `clear` | Clear playlist. |
| `share <item>` | Copies a shareable URL of the item to the system clipboard. |
| `newplaylist <name>` | Create new playlist with name `name`. |
| `sort <sort_key> [sort_direction]` | Sort a playlist by `sort_key` in direction `sort_direction`. Default direction is ascending. |
| `exec <cmd>` | Executes a command in the system shell. Be aware that command output is printed to the terminal, so redirection to `/dev/null` e.g. by appending `2> /dev/null` may be necessary. |

- Supported `repeat_mode` are:
  - `list` | `playlist` | `queue`
  - `track` | `once` | `single`
  - `none` | `off`
- Supported `item` are:
  - `selected`: Selected item.
  - `current`: Current song.
- Supported `sort_key` are:
  - `title`
  - `album`
  - `artist`
  - `duration`
  - `added`
- Supported `sort_direction` are:
  - `a` | `asc` | `ascending`
  - `d` | `desc` | `descending`

## Configuration

Configuration is saved to `~/.config/ncspot/config.toml` (or
`%AppData%\ncspot\config.toml` on Windows). To reload the configuration during
runtime use the command prompt by typing `:reload`.

Possible configuration values are:

| Name                     | Description                                 | Possible values                                   |   Default   |
| :----------------------- | :------------------------------------------ | :------------------------------------------------ | :---------: |
| `command_key`            | Key to open command line                    | Single character                                  |     `:`     |
| `initial_screen`         | Screen to show after startup                | `"library"`, `"search"`, `"queue"`, `"cover"`[^2] | `"library"` |
| `use_nerdfont`           | Turn nerdfont glyphs on/off                 | `true`, `false`                                   |   `false`   |
| `flip_status_indicators` | Reverse play/pause icon meaning[^1]         | `true`, `false`                                   |   `false`   |
| `backend`                | Audio backend to use                        | String [^3]                                       |             |
| `backend_device`         | Audio device to configure the backend       | String                                            |             |
| `audio_cache`            | Enable caching of audio files               | `true`, `false`                                   |   `true`    |
| `audio_cache_size`       | Maximum size of audio cache in MiB          | Number                                            |             |
| `volnorm`                | Enable volume normalization                 | `true`, `false`                                   |   `false`   |
| `volnorm_pregain`        | Normalization pregain to apply (if enabled) | Number                                            |      0      |
| `default_keybindings`    | Enable default keybindings                  | `true`, `false`                                   |   `false`   |
| `notify`                 | Enable desktop notifications                | `true`, `false`                                   |   `false`   |
| `bitrate`                | Audio bitrate to use for streaming          | `96`, `160`, `320`                                |    `320`    |
| `album_column`           | Show album column for tracks                | `true`, `false`                                   |   `true`    |
| `gapless`                | Enable gapless playback                     | `true`, `false`                                   |   `false`   |
| `shuffle`                | Set default shuffle state                   | `true`, `false`                                   |   `false`   |
| `repeat`                 | Set default repeat mode                     | `off`, `track`, `playlist`                        |    `off`    |
| `[theme]`                | Custom theme                                | See [custom theme]#theming                      |             |
| `[keybindings]`          | Custom keybindings                          | See [custom keybindings]#custom-keybindings     |             |

[^1]:
    By default the statusbar will show a play icon when a track is playing and
    a pause icon when playback is stopped. If this setting is enabled, the behavior
    is reversed.

[^2]: If [enabled]#cover-drawing.
[^3]: Run `ncspot -h` for a list of devices.

### Custom Keybindings

Keybindings can be configured in `[keybindings]` section in `config.toml`,
e.g. as such:

```toml
[keybindings]
"Shift+i" = "seek +10000"
```

### Proxy

`ncspot` will respect system proxy settings defined via the `http_proxy`
environment variable.

### Theming

[Theme generator](https://ncspot-theme-generator.vaa.red/) by [@vaarad](https://github.com/vaared).

The color palette can be modified in the configuration. For instance, to have
`ncspot` match Spotify's official client, you can add the following entries to
the configuration file:

```toml
[theme]
background = "black"
primary = "light white"
secondary = "light black"
title = "green"
playing = "green"
playing_selected = "light green"
playing_bg = "black"
highlight = "light white"
highlight_bg = "#484848"
error = "light white"
error_bg = "red"
statusbar = "black"
statusbar_progress = "green"
statusbar_bg = "green"
cmdline = "light white"
cmdline_bg = "black"
search_match = "light red"
```

More examples can be found in [this pull request](https://github.com/hrkfdn/ncspot/pull/40).

## Cover Drawing

When compiled with the `cover` feature, `ncspot` can draw the album art of the
current track in a dedicated view (`:focus cover` or <kbd>F8</kbd> by default)
using [Überzug](https://github.com/seebye/ueberzug). For more information on
installation and terminal compatibility, consult that repository.

To allow scaling the album art up beyond its resolution (640x640 for Spotify
covers), use the config key `cover_max_scale`. This is especially useful for
HiDPI displays:

```toml
cover_max_scale = 2
```

## Authentication

`ncspot` prompts for a Spotify username and password on first launch, uses this
to generate an OAuth token, and stores it to disk.

The credentials are stored in `~/.cache/ncspot/librespot/credentials.json`
(unless the base path has been changed with the `--basepath` option).

The `:logout` command can be used to programmatically remove cached credentials
(see [Vim-Like Commands](#vim-like-commands) above).