664
README.md
664
README.md
@@ -1,643 +1,47 @@
|
||||
<p align="center" style="text-align:center">
|
||||
<img src="images/logo.svg" width="128px" alt="logo"/>
|
||||
</p>
|
||||
|
||||
# ncspot
|
||||
<div align="center" style="text-align:center">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="images/logo_text_dark.svg">
|
||||
<source media="(prefers-color-scheme: light)" srcset="images/logo_text_light.svg">
|
||||
<img alt="ncspot logo" height="128" src="images/logo_text_light.svg">
|
||||
</picture>
|
||||
<h3>An ncurses Spotify client written in Rust using librespot</h3>
|
||||
|
||||
[](https://crates.io/crates/ncspot)
|
||||
[](https://gitter.im/ncspot/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||
[](https://github.com/hrkfdn/ncspot/actions/workflows/ci.yml)
|
||||
|
||||
[](https://repology.org/project/ncspot/versions)
|
||||
<img alt="ncspot search tab" src="images/screenshot.png">
|
||||
</div>
|
||||
|
||||
<a href='https://flathub.org/apps/details/io.github.hrkfdn.ncspot'><img width='130' alt='Download on Flathub' src='https://flathub.org/assets/badges/flathub-badge-en.png'/></a>
|
||||
ncspot is an ncurses Spotify client written in Rust using librespot. It is heavily inspired by
|
||||
ncurses MPD clients, such as [ncmpc](https://musicpd.org/clients/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.
|
||||
|
||||
[](https://snapcraft.io/ncspot)
|
||||
ncspot only works with a Spotify premium account as it offers features that are not available for
|
||||
free accounts.
|
||||
|
||||
`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.
|
||||
|
||||
Note that `ncspot` offers features that are legally incompatible with free Spotify
|
||||
accounts. See [feature comparison](https://support.spotify.com/us/article/premium-plans/)
|
||||
and [Spotify user guidelines](https://www.spotify.com/us/legal/user-guidelines/).
|
||||
You **must** have an existing premium Spotify subscription to use `ncspot`.
|
||||
|
||||

|
||||
|
||||
## 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)
|
||||
- [Build](#build)
|
||||
- [Prerequisites](#prerequisites)
|
||||
- [Debugging](#debugging)
|
||||
- [Compiling](#compiling)
|
||||
- [Building a Debian Package](#building-a-debian-package)
|
||||
- [Packaging Information](#packaging-information)
|
||||
- [Audio Backends](#audio-backends)
|
||||
- [Other Features](#other-features)
|
||||
- [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)
|
||||
- [Remote control (IPC)](#remote-control-ipc)
|
||||
- [Extracting info on currently playing song](#extracting-info-on-currently-playing-song)
|
||||
- [Configuration](#configuration)
|
||||
- [Custom Keybindings](#custom-keybindings)
|
||||
- [Proxy](#proxy)
|
||||
- [Theming](#theming)
|
||||
- [Track Formatting](#track-formatting)
|
||||
- [Notification Formatting](#notification-formatting)
|
||||
- [Cover Drawing](#cover-drawing)
|
||||
- [Authentication](#authentication)
|
||||
- [Using a password manager](#using-a-password-manager)
|
||||
|
||||
## 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 |
|
||||
## Features
|
||||
- Support for tracks, albums, playlists, genres, searching...
|
||||
- Small [resource footprint](doc/resource_footprint.md)
|
||||
- Support for a lot of platforms
|
||||
- Vim keybindings out of the box
|
||||
- IPC socket for remote control
|
||||
- Automatic authentication using a password manager
|
||||
|
||||
## 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
|
||||
|
||||
Your distribution may have packaged `ncspot` in its package repository.
|
||||
If so, simply install using your distribution's package manager - it
|
||||
is by far the easiest way. If not, you can build from source instead.
|
||||
See [Build](#build).
|
||||
|
||||
In case your package manager does not perform dependency resolution,
|
||||
here are the runtime dependencies:
|
||||
|
||||
- `dbus`, `libncurses`, `libssl`
|
||||
- `libpulse` (or `portaudio`, if built using the PortAudio backend)
|
||||
- `libxcb` (if built with the `clipboard` feature)
|
||||
- `ueberzug` (if built with the `cover` feature)
|
||||
|
||||
## Build
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- A working [Rust installation](https://www.rust-lang.org/tools/install)
|
||||
- Python 3 (needed for building `rust-xcb` dependency)
|
||||
|
||||
On Linux, you also need:
|
||||
|
||||
- `pkgconf` (or `pkg-config`)
|
||||
- Development headers for the [aforementioned runtime dependencies](#on-linux)
|
||||
- Debian and derivatives:
|
||||
```sh
|
||||
sudo apt install libdbus-1-dev libncursesw5-dev libpulse-dev libssl-dev libxcb1-dev libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev
|
||||
```
|
||||
- Fedora:
|
||||
```sh
|
||||
sudo dnf install dbus-devel libxcb-devel ncurses-devel openssl-devel pulseaudio-libs-devel
|
||||
```
|
||||
- Arch and derivatives:
|
||||
```sh
|
||||
# headers are included in the base packages
|
||||
sudo pacman -S dbus libpulse libxcb ncurses openssl
|
||||
```
|
||||
|
||||
### Debugging
|
||||
|
||||
For debugging, you can pass a debug log filename:
|
||||
|
||||
```sh
|
||||
cargo run -- -d debug.log
|
||||
```
|
||||
|
||||
If ncspot has crashed you can find the latest backtrace at `~/.cache/ncspot/backtrace.log`.
|
||||
|
||||
### Compiling
|
||||
|
||||
Compile and install the latest release with `cargo-install`:
|
||||
|
||||
```sh
|
||||
cargo install ncspot
|
||||
```
|
||||
|
||||
Or clone and build locally:
|
||||
|
||||
```sh
|
||||
git clone https://github.com/hrkfdn/ncspot
|
||||
cargo build --release
|
||||
```
|
||||
|
||||
**You may need to manually set the audio backend on non-Linux OSes.** See
|
||||
[Audio Backends](#audio-backends).
|
||||
|
||||
#### Building a Debian Package
|
||||
|
||||
You can also use `cargo-deb` to build a Debian package
|
||||
|
||||
```sh
|
||||
cargo install cargo-deb
|
||||
cargo deb
|
||||
```
|
||||
|
||||
You can find the package under `target/debian`.
|
||||
|
||||
#### Packaging Information
|
||||
|
||||
The following files are provided and should be bundled together with ncspot:
|
||||
- LICENSE
|
||||
- images/logo.svg (optional)
|
||||
- misc/ncspot.desktop (for Linux systems)
|
||||
- misc/ncspot.1 (for Linux systems)
|
||||
- misc/ncspot.bash (bash completions)
|
||||
- misc/\_ncspot (zsh completions)
|
||||
- misc/ncspot.fish (fish completions)
|
||||
- misc/ncspot.elv (elvish completions)
|
||||
- misc/\_ncspot.ps1 (powershell completions)
|
||||
|
||||
Some of these files have to be generated. Execute `cargo xtask --help` for more information.
|
||||
|
||||
### 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 compile `ncspot` with the respective features:
|
||||
|
||||
```sh
|
||||
# PortAudio (BSD/macOS)
|
||||
cargo build --release --no-default-features --features portaudio_backend,pancurses_backend
|
||||
|
||||
# Rodio (Windows)
|
||||
cargo build --release --no-default-features --features rodio_backend,pancurses_backend
|
||||
```
|
||||
|
||||
### Other Features
|
||||
|
||||
Here are some auxiliary features you may wish to enable:
|
||||
|
||||
| Feature | Default | Description |
|
||||
|-------------------|---------|--------------------------------------------------------------------------------------------|
|
||||
| `cover` | off | Add a screen to show the album art. See [Cover Drawing](#cover-drawing). |
|
||||
| `mpris` | on | Control `ncspot` via dbus. See [Arch Wiki: MPRIS](https://wiki.archlinux.org/title/MPRIS). |
|
||||
| `notify` | on | Send a notification to show what's playing. |
|
||||
| `share_clipboard` | on | Ability to copy the URL of a song/playlist/etc. to system clipboard. |
|
||||
|
||||
Consult [Cargo.toml](Cargo.toml) for the full list of supported features.
|
||||
|
||||
## Key Bindings
|
||||
|
||||
The keybindings listed below are configured by default. Additionally, if you
|
||||
built `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 built 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 item to your library. |
|
||||
| <kbd>D</kbd> | Remove the currently playing item 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 by 1 second. |
|
||||
| <kbd>Shift</kbd>+<kbd>F</kbd> | Seek forward by 10 seconds. |
|
||||
| <kbd>B</kbd> | Seek backward by 1 second. |
|
||||
| <kbd>Shift</kbd>+<kbd>B</kbd> | Seek backward by 10 seconds. |
|
||||
| <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 (if built with the `share_clipboard` feature). |
|
||||
| <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:
|
||||
- "Artist(s)" (let's you show or (un)follow a track's artist(s))
|
||||
- "Show Album"
|
||||
- "Share" (if built with the `share_clipboard` feature)
|
||||
- "Add to playlist"
|
||||
- "Similar tracks"
|
||||
|
||||
### Sharing
|
||||
|
||||
(if built with the `share_clipboard` feature)
|
||||
|
||||
| Key | Command |
|
||||
|-------------------------------|--------------------------------------------------------------------------|
|
||||
| <kbd>X</kbd> | Copy the URL to the **currently selected item** to the system clipboard. |
|
||||
| <kbd>Shift</kbd>+<kbd>X</kbd> | Copy the URL to 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 the more useful commands. For the full list, see [source code](/src/command.rs).
|
||||
|
||||
Note: \<FOO\> - mandatory arg; [BAR] - optional arg
|
||||
|
||||
| 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 `+`/`-`.<br/>\* TIME is anything accepted by [parse_duration](https://docs.rs/parse_duration/latest/parse_duration/)<br/>\* Default unit is `ms` for backward compatibility. |
|
||||
| `move` \<DIRECTION\> \<STEP_SIZE\> | Scroll the current view `up`/`down`/`left`/`right` with integer step sizes, or `pageup`/`pagedown`/`pageleft`/`pageright` with float step sizes.
|
||||
| `repeat` [REPEAT_MODE]<br/>Alias: `loop` | Set repeat mode. Omit argument to step through the available modes.<br/>\* Valid values for REPEAT_MODE: `list` (aliases: `playlist`, `queue`), `track` (aliases: `once`, `single`), `none` (alias: `off`) |
|
||||
| `shuffle` [`on`\|`off`] | Enable or disable shuffle. Omit argument to toggle. |
|
||||
| `previous` | Play the previous track. |
|
||||
| `next` | Play the next track. |
|
||||
| `focus` \<SCREEN\> | Switch to a different view.<br/>\* Valid values for SCREEN: `queue`, `search`, `library`, `cover` (if built with the `cover` feature) |
|
||||
| `search` \<SEARCH\> | Search for a song/artist/album/etc. |
|
||||
| `clear` | Clear the queue. |
|
||||
| `share` \<ITEM\> | Copy a shareable URL of the item to the system clipboard. Requires the `share_clipboard` feature.<br/>\* Valid values for ITEM: `selected`, `current` |
|
||||
| `newplaylist` \<NAME\> | Create a new playlist. |
|
||||
| `sort` \<SORT_KEY\> [SORT_DIRECTION] | Sort a playlist.<br/>\* Valid values for SORT_KEY: `title`, `album`, `artist`, `duration`, `added`<br/>\* Valid values for SORT_DIRECTION: `ascending` (default; aliases: `a`, `asc`), `descending` (aliases: `d`, `desc`) |
|
||||
| `exec` \<CMD\> | Execute a command in the system shell.<br/>\* Command output is printed to the terminal, so redirection (`2> /dev/null`) may be necessary. |
|
||||
| `noop` | Do nothing. Useful for disabling default keybindings. See [custom keybindings](#custom-keybindings). |
|
||||
| `reload` | Reload the configuration from disk. See [Configuration](#configuration). |
|
||||
| `reconnect` | Reconnect to Spotify (useful when session has expired or connection was lost |
|
||||
|
||||
## Remote control (IPC)
|
||||
|
||||
Apart from MPRIS, ncspot will also create a domain socket on UNIX platforms
|
||||
(Linux, macOS, *BSD) at `~/.cache/ncspot/ncspot.sock`. Applications or scripts
|
||||
can connect to this socket to send commands or be notified of the currently
|
||||
playing track, i.e. with `netcat`:
|
||||
|
||||
```
|
||||
% nc -U ~/.cache/ncspot/ncspot.sock
|
||||
play
|
||||
{"mode":{"Playing":{"secs_since_epoch":1672249086,"nanos_since_epoch":547517730}},"playable":{"type":"Track","id":"2wcrQZ7ZJolYEfIaPP9yL4","uri":"spotify:track:2wcrQZ7ZJolYEfIaPP9yL4","title":"Hit Me Where It Hurts","track_number":4,"disc_number":1,"duration":184132,"artists":["Caroline Polachek"],"artist_ids":["4Ge8xMJNwt6EEXOzVXju9a"],"album":"Pang","album_id":"4ClyeVlAKJJViIyfVW0yQD","album_artists":["Caroline Polachek"],"cover_url":"https://i.scdn.co/image/ab67616d0000b2737d983e7bf67c2806218c2759","url":"https://open.spotify.com/track/2wcrQZ7ZJolYEfIaPP9yL4","added_at":"2022-12-19T22:41:05Z","list_index":0}}
|
||||
playpause
|
||||
{"mode":{"Paused":{"secs":25,"nanos":575000000}},"playable":{"type":"Track","id":"2wcrQZ7ZJolYEfIaPP9yL4","uri":"spotify:track:2wcrQZ7ZJolYEfIaPP9yL4","title":"Hit Me Where It Hurts","track_number":4,"disc_number":1,"duration":184132,"artists":["Caroline Polachek"],"artist_ids":["4Ge8xMJNwt6EEXOzVXju9a"],"album":"Pang","album_id":"4ClyeVlAKJJViIyfVW0yQD","album_artists":["Caroline Polachek"],"cover_url":"https://i.scdn.co/image/ab67616d0000b2737d983e7bf67c2806218c2759","url":"https://open.spotify.com/track/2wcrQZ7ZJolYEfIaPP9yL4","added_at":"2022-12-19T22:41:05Z","list_index":0}}
|
||||
```
|
||||
|
||||
Each time the playback status changes (i.e. after sending the `play`/`playpause`
|
||||
command or simply by playing the queue), the current status will be published as
|
||||
a JSON structure.
|
||||
|
||||
Possible use cases for this could be:
|
||||
- Controlling a detached ncspot session (in `tmux` for example)
|
||||
- Displaying the currently playing track in your favorite application/status bar (see below)
|
||||
- Setting up routines, i.e. to play specific songs/playlists when ncspot starts
|
||||
|
||||
### Extracting info on currently playing song
|
||||
|
||||
Using `netcat` and the domain socket, you can query the currently playing track
|
||||
and other relevant information. Note that not all `netcat` versions are suitable,
|
||||
as they typically tend to keep the connection to the socket open. OpenBSD's
|
||||
`netcat` offers a work-around: by using the `-W` flag, it will close after a
|
||||
specific number of packets have been received.
|
||||
|
||||
```
|
||||
% nc -W 1 -U ~/.cache/ncspot/ncspot.sock
|
||||
{"mode":{"Playing":{"secs_since_epoch":1675188934,"nanos_since_epoch":50913345}},"playable":{"type":"Track","id":"5Cp6a1h2VnuOtsh1Nqxfv6","uri":"spotify:track:5Cp6a1h2VnuOtsh1Nqxfv6","title":"New Track","track_number":1,"disc_number":1,"duration":498358,"artists":["Francis Bebey"],"artist_ids":["0mdmrbu5UZ32uRcRp2z6mr"],"album":"African Electronic Music (1975-1982)","album_id":"7w99Aae1tYSTSb1OiDnxYY","album_artists":["Francis Bebey"],"cover_url":"https://i.scdn.co/image/ab67616d0000b2736ab57cedf27177fae1eaed87","url":"https://open.spotify.com/track/5Cp6a1h2VnuOtsh1Nqxfv6","added_at":"2020-12-22T09:57:17Z","list_index":0}}
|
||||
```
|
||||
|
||||
This results in a single output in `JSON` format, which can e.g. be parsed using [jq](https://stedolan.github.io/jq/).
|
||||
For example, you can get the currently playing artist and title in your
|
||||
terminal as follows:
|
||||
|
||||
```
|
||||
% nc -W 1 -U ~/.cache/ncspot/ncspot.sock | jq '.playable.title'
|
||||
"PUMPIN' JUMPIN'"
|
||||
|
||||
% nc -W 1 -U ~/.cache/ncspot/ncspot.sock | jq '.playable.artists[0]'
|
||||
"Hideki Naganuma"
|
||||
```
|
||||
ncspot is available on macOS (Homebrew), Windows (Scoop), Linux (native package, Snapcraft and
|
||||
Flathub) and the BSD's. Detailed installation instructions for each platform can be found
|
||||
[here](/doc/users.md).
|
||||
|
||||
## Configuration
|
||||
A configuration file can be provided at `$XDG_CONFIG_HOME/ncspot/config.toml`. Detailed
|
||||
configuration information can be found [here](/doc/users.md#configuration).
|
||||
|
||||
Configuration is saved to `~/.config/ncspot/config.toml` (or
|
||||
`%AppData%\ncspot\config.toml` on Windows). To reload the configuration during
|
||||
runtime use the `reload` command.
|
||||
## Building
|
||||
Building ncspot requires a working [Rust installation](https://www.rust-lang.org/tools/install) and
|
||||
a Python 3 installation. To compile ncspot, run `cargo build`. For detailed instructions on building
|
||||
ncspot, there is more information [here](/doc/developers.md).
|
||||
|
||||
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"`<sup>[1]</sup> | `"library"` |
|
||||
| `use_nerdfont` | Turn nerdfont glyphs on/off | `true`, `false` | `false` |
|
||||
| `flip_status_indicators` | Reverse play/pause icon meaning<sup>[2]</sup> | `true`, `false` | `false` |
|
||||
| `backend` | Audio backend to use | String<sup>[3]</sup> | |
|
||||
| `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 in dB (if enabled) | Number | `0.0` |
|
||||
| `default_keybindings` | Enable default keybindings | `true`, `false` | `false` |
|
||||
| `notify`<sup>[4]</sup> | Enable desktop notifications | `true`, `false` | `false` |
|
||||
| `bitrate` | Audio bitrate to use for streaming | `96`, `160`, `320` | `320` |
|
||||
| `gapless` | Enable gapless playback | `true`, `false` | `true` |
|
||||
| `shuffle` | Set default shuffle state | `true`, `false` | `false` |
|
||||
| `repeat` | Set default repeat mode | `off`, `track`, `playlist` | `off` |
|
||||
| `playback_state` | Set default playback state | `"Stopped"`, `"Paused"`, `"Playing"`, `"Default"` | `"Paused"` |
|
||||
| `library_tabs` | Tabs to show in library screen | Array of `"tracks"`, `"albums"`, `"artists"`, `"playlists"`, `"podcasts"` | All tabs |
|
||||
| `cover_max_scale`<sup>[1]</sup> | Set maximum scaling ratio for cover art | Number | `1.0` |
|
||||
| `hide_display_names` | Hides spotify usernames in the library header and on playlists | `true`, `false` | `false` |
|
||||
| `statusbar_format` | Formatting for tracks in the statusbar | See [track_formatting](#track-formatting) | `%artists - %track` |
|
||||
| `[track_format]` | Set active fields shown in Library/Queue views | See [track formatting](#track-formatting) | |
|
||||
| `[notification_format]` | Set the text displayed in notifications<sup>[4]</sup> | See [notification formatting](#notification-formatting) | |
|
||||
| `[theme]` | Custom theme | See [custom theme](#theming) | |
|
||||
| `[keybindings]` | Custom keybindings | See [custom keybindings](#custom-keybindings) | |
|
||||
|
||||
1. If built with the `cover` feature.
|
||||
2. 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.
|
||||
3. Run `ncspot -h` for a list of devices.
|
||||
4. If built with the `notify` feature.
|
||||
|
||||
### Custom Keybindings
|
||||
|
||||
Keybindings can be configured in `[keybindings]` section in `config.toml`.
|
||||
|
||||
Each key-value pair specifies one keybinding, where the key is a string in the
|
||||
format of:
|
||||
|
||||
```
|
||||
[MODIFIER+]<CHAR|NAMED_KEY>
|
||||
where:
|
||||
MODIFIER: Shift|Alt|Ctrl
|
||||
CHAR: Any printable character
|
||||
NAMED_KEY: Enter|Space|Tab|Backspace|Esc|Left|Right|Up|Down
|
||||
|Ins|Del|Home|End|PageUp|PageDown|PauseBreak|NumpadCenter
|
||||
|F0|F1|F2|F3|F4|F5|F6|F7|F8|F9|F10|F11|F12
|
||||
```
|
||||
|
||||
For implementation see [commands::CommandManager::parse_key](/src/commands.rs).
|
||||
|
||||
Its value is a string that can be parsed as a command. See
|
||||
[Vim-Like Commands](#vim-like-commands).
|
||||
|
||||
<details>
|
||||
<summary>Examples: (Click to show/hide)</summary>
|
||||
|
||||
```toml
|
||||
[keybindings]
|
||||
# Bind "Shift+i" to "Seek forward 10 seconds"
|
||||
"Shift+i" = "seek +10s"
|
||||
```
|
||||
|
||||
To disable a default keybinding, set its command to `noop`:
|
||||
|
||||
```toml
|
||||
# Use "Shift+q" to quit instead of the default "q"
|
||||
[keybindings]
|
||||
"Shift+q" = "quit"
|
||||
"q" = "noop"
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### Proxy
|
||||
|
||||
`ncspot` will respect system proxy settings defined via the `http_proxy`
|
||||
environment variable.
|
||||
|
||||
```sh
|
||||
# In sh-like shells
|
||||
http_proxy="http://foo.bar:4444" ncspot
|
||||
```
|
||||
|
||||
### 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).
|
||||
|
||||
### Track Formatting
|
||||
|
||||
It's possible to customize how tracks are shown in Queue/Library views and the
|
||||
statusbar, whereas `statusbar_format` will hold the statusbar formatting and
|
||||
`[track_format]` the formatting for tracks in list views.
|
||||
If you don't define `center` for example, the default value will be used.
|
||||
Available options for tracks: `%artists`, `%title`, `%album`, `%saved`,
|
||||
`%duration`
|
||||
|
||||
Default configuration:
|
||||
|
||||
```toml
|
||||
statusbar_format = "%artists - %title"
|
||||
|
||||
[track_format]
|
||||
left = "%artists - %title"
|
||||
center = "%album"
|
||||
right = "%saved %duration"
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>Examples: (Click to show/hide)</summary>
|
||||
|
||||
Example 1 - Show only album name and track name after it:
|
||||
|
||||
```toml
|
||||
[track_format]
|
||||
left = "%album"
|
||||
center = "%title"
|
||||
right = ""
|
||||
```
|
||||
|
||||
Example 2 - Show track title before artists, and don't show album at all:
|
||||
|
||||
```toml
|
||||
[track_format]
|
||||
left = "%title - %artists"
|
||||
center = ""
|
||||
```
|
||||
|
||||
Example 3 - Show everything as default, but hide saved status and track length:
|
||||
|
||||
```toml
|
||||
[track_format]
|
||||
right = ""
|
||||
```
|
||||
|
||||
Example 4 - Show everything as default, except show title before artists:
|
||||
|
||||
```toml
|
||||
[track_format]
|
||||
left = "%title - %artists"
|
||||
```
|
||||
|
||||
Example 5 - Show saved status and duration first, followed by track title and artists, with the album last:
|
||||
|
||||
```toml
|
||||
[track_format]
|
||||
left = "|%saved| %duration | %title - %artists"
|
||||
center = ""
|
||||
right = "%album"
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### Notification Formatting
|
||||
|
||||
`ncspot` also supports customizing the way notifications are displayed
|
||||
(which appear when compiled with the `notify` feature and `notify = true`).
|
||||
The title and body of the notification can be set, with `title` and `body`, or the default will be used.
|
||||
The formatting options are the same as those for [track formatting](#track-formatting) (`%artists`, `%title`, etc)
|
||||
|
||||
Default configuration:
|
||||
|
||||
```toml
|
||||
[notification_format]
|
||||
title = "%title"
|
||||
body = "%artists"
|
||||
```
|
||||
|
||||
## 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 up the album art beyond its native 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 remove cached credentials. See
|
||||
[Vim-Like Commands](#vim-like-commands).
|
||||
|
||||
### Using a password manager
|
||||
|
||||
If you would like ncspot to retrieve your login data from command results,
|
||||
i.e. because you use a password manager like `pass`, you can add the following
|
||||
configuration:
|
||||
|
||||
```toml
|
||||
[credentials]
|
||||
username_cmd = "echo username"
|
||||
password_cmd = "pass spotify.com/username"
|
||||
```
|
||||
|
||||
Do note that this is only required for the initial login or when your credential
|
||||
token has expired.
|
||||
## Packaging
|
||||
Information about provided files, how to generate some of them and current package status accross
|
||||
platforms can be found [here](/doc/package_maintainers.md).
|
||||
|
||||
83
doc/developers.md
Normal file
83
doc/developers.md
Normal file
@@ -0,0 +1,83 @@
|
||||
# Development
|
||||
|
||||
## Prerequisites
|
||||
- A working [Rust installation](https://www.rust-lang.org/tools/install)
|
||||
- Python 3 (needed for building `rust-xcb` dependency)
|
||||
|
||||
On Linux, you also need:
|
||||
|
||||
- `pkgconf` (sometimes called `pkg-config`)
|
||||
- Development headers for the aforementioned runtime dependencies:
|
||||
- Debian and derivatives:
|
||||
```sh
|
||||
sudo apt install libdbus-1-dev libncursesw5-dev libpulse-dev libssl-dev libxcb1-dev libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev
|
||||
```
|
||||
- Fedora:
|
||||
```sh
|
||||
sudo dnf install dbus-devel libxcb-devel ncurses-devel openssl-devel pulseaudio-libs-devel
|
||||
```
|
||||
- Arch and derivatives:
|
||||
```sh
|
||||
# headers are included in the base packages
|
||||
sudo pacman -S dbus libpulse libxcb ncurses openssl
|
||||
```
|
||||
|
||||
## Debugging
|
||||
For simple debugging, you can pass a debug log filename:
|
||||
|
||||
```sh
|
||||
cargo run -- -d debug.log
|
||||
```
|
||||
|
||||
It can be difficult to debug a TUI application as it might not run well in an IDE terminal or the
|
||||
terminal could be used by the text editor. It is however possible to run ncspot in its own process
|
||||
and attach a debugger. On Linux this can be achieved with `gdb` or `lldb`. It is important that
|
||||
[ptrace](https://www.kernel.org/doc/html/latest/admin-guide/LSM/Yama.html) is disabled for this to
|
||||
work. To disable it, execute `echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope`. This will allow
|
||||
any process to inspect the memory of another process. It is automatically re-enabled after a reboot.
|
||||
|
||||
If ncspot has crashed you can find the latest backtrace at `~/.cache/ncspot/backtrace.log`.
|
||||
|
||||
## Compiling
|
||||
Compile and install the latest release with `cargo-install`:
|
||||
|
||||
```sh
|
||||
cargo install ncspot
|
||||
```
|
||||
|
||||
Or clone and build locally:
|
||||
|
||||
```sh
|
||||
git clone https://github.com/hrkfdn/ncspot
|
||||
cargo build --release
|
||||
```
|
||||
|
||||
**You may need to manually set the audio backend on non-Linux OSes.** See [Audio
|
||||
Backends](#audio-backends).
|
||||
|
||||
## Audio Backends
|
||||
ncspot uses PulseAudio by default. Support for other backends can be enabled with the following
|
||||
commands.
|
||||
|
||||
PortAudio for BSD's or macOS
|
||||
```sh
|
||||
cargo build --no-default-features --features portaudio_backend,pancurses_backend
|
||||
```
|
||||
|
||||
Rodio for Windows
|
||||
```sh
|
||||
cargo build --no-default-features --features rodio_backend,pancurses_backend
|
||||
```
|
||||
|
||||
## Other Features
|
||||
Here are some auxiliary features you may wish to enable:
|
||||
|
||||
| Feature | Default | Description |
|
||||
|-------------------|---------|--------------------------------------------------------------------------------------------|
|
||||
| `cover` | off | Add a screen to show the album art. |
|
||||
| `mpris` | on | Control `ncspot` via dbus. See [Arch Wiki: MPRIS](https://wiki.archlinux.org/title/MPRIS). |
|
||||
| `notify` | on | Send a notification to show what's playing. |
|
||||
| `share_clipboard` | on | Ability to copy the URL of a song/playlist/etc. to system clipboard. |
|
||||
|
||||
Consult [Cargo.toml](/Cargo.toml) for the full list of supported features.
|
||||
|
||||
36
doc/package_maintainers.md
Normal file
36
doc/package_maintainers.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# Packaging
|
||||
[](https://repology.org/project/ncspot/versions)
|
||||
|
||||
## Compilation Instructions
|
||||
ncspot makes use of the standard Cargo build system for everything. To compile a release version,
|
||||
execute `cargo build --release` in the terminal from the project root. The executable file can be
|
||||
found at `target/release/ncspot`. For detailed build instructions, have a look at [the developer
|
||||
documentation](/doc/developers.md).
|
||||
|
||||
Additional features can be included by appending them to the build command. A list of all the
|
||||
available features can be found in the [Cargo.toml](/Cargo.toml) under the `[features]` table. To
|
||||
activate a feature, include its name like `cargo build --release --features feature1,feature2,...`.
|
||||
To disable the default features, add `--no-default-features` to the command.
|
||||
|
||||
## Other Provided Files
|
||||
The following is a list of other files that are provided by ncspot. Some of them need to be
|
||||
generated. Execute `cargo xtask --help` for more information.
|
||||
- LICENSE
|
||||
- images/logo.svg (optional)
|
||||
- misc/ncspot.desktop (for Linux systems)
|
||||
- misc/ncspot.1 (for Linux systems)
|
||||
- misc/ncspot.bash (bash completions)
|
||||
- misc/\_ncspot (zsh completions)
|
||||
- misc/ncspot.fish (fish completions)
|
||||
- misc/ncspot.elv (elvish completions)
|
||||
- misc/\_ncspot.ps1 (powershell completions)
|
||||
|
||||
## Building a Debian Package
|
||||
The [`cargo-deb`](https://github.com/kornelski/cargo-deb#readme) package can be used to build a
|
||||
Debian package with the following commands. The package will be generated in `target/debian/`.
|
||||
|
||||
```sh
|
||||
cargo install cargo-deb
|
||||
cargo deb
|
||||
```
|
||||
|
||||
8
doc/resource_footprint.md
Normal file
8
doc/resource_footprint.md
Normal file
@@ -0,0 +1,8 @@
|
||||
## 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 |
|
||||
|
||||
452
doc/users.md
Normal file
452
doc/users.md
Normal file
@@ -0,0 +1,452 @@
|
||||
# User Documentation
|
||||
|
||||
## Installation Instructions
|
||||
[](https://repology.org/project/ncspot/versions)
|
||||
|
||||
### 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
|
||||
<div>
|
||||
<a href="https://flathub.org/apps/details/io.github.hrkfdn.ncspot"><img width="130" alt="Download on Flathub" src="https://flathub.org/assets/badges/flathub-badge-en.png"/></a>
|
||||
<a href="https://snapcraft.io/ncspot"><img alt="Download on Snapcraft" src="https://snapcraft.io//ncspot/badge.svg"/></a>
|
||||
</div>
|
||||
|
||||
Your distribution may have packaged `ncspot` in its package repository.
|
||||
If so, simply install using your distribution's package manager - it
|
||||
is by far the easiest way. If not, you can build from source instead.
|
||||
See [Compiling](/doc/developers.md).
|
||||
|
||||
In case your package manager does not perform dependency resolution,
|
||||
here are the runtime dependencies:
|
||||
|
||||
- `dbus`, `libncurses`, `libssl`
|
||||
- `libpulse` (or `portaudio`, if built using the PortAudio backend)
|
||||
- `libxcb` (if built with the `clipboard` feature)
|
||||
- `ueberzug` (if built with the `cover` feature)
|
||||
|
||||
### On BSD's
|
||||
Your distribution may have packaged `ncspot` in its package repository.
|
||||
If so, simply install using your distribution's package manager - it
|
||||
is by far the easiest way. If not, you can build from source instead.
|
||||
See [Compiling](/doc/developers.md).
|
||||
|
||||
## Key Bindings
|
||||
The keybindings listed below are configured by default. Additionally, if you
|
||||
built `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 built 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 item to your library. |
|
||||
| <kbd>D</kbd> | Remove the currently playing item 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 by 1 second. |
|
||||
| <kbd>Shift</kbd>+<kbd>F</kbd> | Seek forward by 10 seconds. |
|
||||
| <kbd>B</kbd> | Seek backward by 1 second. |
|
||||
| <kbd>Shift</kbd>+<kbd>B</kbd> | Seek backward by 10 seconds. |
|
||||
| <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 (if built with the `share_clipboard` feature). |
|
||||
| <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:
|
||||
- "Artist(s)" (let's you show or (un)follow a track's artist(s))
|
||||
- "Show Album"
|
||||
- "Share" (if built with the `share_clipboard` feature)
|
||||
- "Add to playlist"
|
||||
- "Similar tracks"
|
||||
|
||||
### Sharing
|
||||
(if built with the `share_clipboard` feature)
|
||||
|
||||
| Key | Command |
|
||||
|-------------------------------|--------------------------------------------------------------------------|
|
||||
| <kbd>X</kbd> | Copy the URL to the **currently selected item** to the system clipboard. |
|
||||
| <kbd>Shift</kbd>+<kbd>X</kbd> | Copy the URL to 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 the more useful commands. For the full list, see [source code](/src/command.rs).
|
||||
|
||||
Note: \<FOO\> - mandatory arg; [BAR] - optional arg
|
||||
|
||||
| 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 `+`/`-`.<br/>\* TIME is anything accepted by [parse_duration](https://docs.rs/parse_duration/latest/parse_duration/)<br/>\* Default unit is `ms` for backward compatibility. |
|
||||
| `move` \<DIRECTION\> \<STEP_SIZE\> | Scroll the current view `up`/`down`/`left`/`right` with integer step sizes, or `pageup`/`pagedown`/`pageleft`/`pageright` with float step sizes.
|
||||
| `repeat` [REPEAT_MODE]<br/>Alias: `loop` | Set repeat mode. Omit argument to step through the available modes.<br/>\* Valid values for REPEAT_MODE: `list` (aliases: `playlist`, `queue`), `track` (aliases: `once`, `single`), `none` (alias: `off`) |
|
||||
| `shuffle` [`on`\|`off`] | Enable or disable shuffle. Omit argument to toggle. |
|
||||
| `previous` | Play the previous track. |
|
||||
| `next` | Play the next track. |
|
||||
| `focus` \<SCREEN\> | Switch to a different view.<br/>\* Valid values for SCREEN: `queue`, `search`, `library`, `cover` (if built with the `cover` feature) |
|
||||
| `search` \<SEARCH\> | Search for a song/artist/album/etc. |
|
||||
| `clear` | Clear the queue. |
|
||||
| `share` \<ITEM\> | Copy a shareable URL of the item to the system clipboard. Requires the `share_clipboard` feature.<br/>\* Valid values for ITEM: `selected`, `current` |
|
||||
| `newplaylist` \<NAME\> | Create a new playlist. |
|
||||
| `sort` \<SORT_KEY\> [SORT_DIRECTION] | Sort a playlist.<br/>\* Valid values for SORT_KEY: `title`, `album`, `artist`, `duration`, `added`<br/>\* Valid values for SORT_DIRECTION: `ascending` (default; aliases: `a`, `asc`), `descending` (aliases: `d`, `desc`) |
|
||||
| `exec` \<CMD\> | Execute a command in the system shell.<br/>\* Command output is printed to the terminal, so redirection (`2> /dev/null`) may be necessary. |
|
||||
| `noop` | Do nothing. Useful for disabling default keybindings. See [custom keybindings](#custom-keybindings). |
|
||||
| `reload` | Reload the configuration from disk. See [Configuration](#configuration). |
|
||||
| `reconnect` | Reconnect to Spotify (useful when session has expired or connection was lost |
|
||||
|
||||
## Remote control (IPC)
|
||||
Apart from MPRIS, ncspot will also create a domain socket on UNIX platforms
|
||||
(Linux, macOS, *BSD) at `~/.cache/ncspot/ncspot.sock`. Applications or scripts
|
||||
can connect to this socket to send commands or be notified of the currently
|
||||
playing track, i.e. with `netcat`:
|
||||
|
||||
```
|
||||
% nc -U ~/.cache/ncspot/ncspot.sock
|
||||
play
|
||||
{"mode":{"Playing":{"secs_since_epoch":1672249086,"nanos_since_epoch":547517730}},"playable":{"type":"Track","id":"2wcrQZ7ZJolYEfIaPP9yL4","uri":"spotify:track:2wcrQZ7ZJolYEfIaPP9yL4","title":"Hit Me Where It Hurts","track_number":4,"disc_number":1,"duration":184132,"artists":["Caroline Polachek"],"artist_ids":["4Ge8xMJNwt6EEXOzVXju9a"],"album":"Pang","album_id":"4ClyeVlAKJJViIyfVW0yQD","album_artists":["Caroline Polachek"],"cover_url":"https://i.scdn.co/image/ab67616d0000b2737d983e7bf67c2806218c2759","url":"https://open.spotify.com/track/2wcrQZ7ZJolYEfIaPP9yL4","added_at":"2022-12-19T22:41:05Z","list_index":0}}
|
||||
playpause
|
||||
{"mode":{"Paused":{"secs":25,"nanos":575000000}},"playable":{"type":"Track","id":"2wcrQZ7ZJolYEfIaPP9yL4","uri":"spotify:track:2wcrQZ7ZJolYEfIaPP9yL4","title":"Hit Me Where It Hurts","track_number":4,"disc_number":1,"duration":184132,"artists":["Caroline Polachek"],"artist_ids":["4Ge8xMJNwt6EEXOzVXju9a"],"album":"Pang","album_id":"4ClyeVlAKJJViIyfVW0yQD","album_artists":["Caroline Polachek"],"cover_url":"https://i.scdn.co/image/ab67616d0000b2737d983e7bf67c2806218c2759","url":"https://open.spotify.com/track/2wcrQZ7ZJolYEfIaPP9yL4","added_at":"2022-12-19T22:41:05Z","list_index":0}}
|
||||
```
|
||||
|
||||
Each time the playback status changes (i.e. after sending the `play`/`playpause`
|
||||
command or simply by playing the queue), the current status will be published as
|
||||
a JSON structure.
|
||||
|
||||
Possible use cases for this could be:
|
||||
- Controlling a detached ncspot session (in `tmux` for example)
|
||||
- Displaying the currently playing track in your favorite application/status bar (see below)
|
||||
- Setting up routines, i.e. to play specific songs/playlists when ncspot starts
|
||||
|
||||
### Extracting info on currently playing song
|
||||
Using `netcat` and the domain socket, you can query the currently playing track
|
||||
and other relevant information. Note that not all `netcat` versions are suitable,
|
||||
as they typically tend to keep the connection to the socket open. OpenBSD's
|
||||
`netcat` offers a work-around: by using the `-W` flag, it will close after a
|
||||
specific number of packets have been received.
|
||||
|
||||
```
|
||||
% nc -W 1 -U ~/.cache/ncspot/ncspot.sock
|
||||
{"mode":{"Playing":{"secs_since_epoch":1675188934,"nanos_since_epoch":50913345}},"playable":{"type":"Track","id":"5Cp6a1h2VnuOtsh1Nqxfv6","uri":"spotify:track:5Cp6a1h2VnuOtsh1Nqxfv6","title":"New Track","track_number":1,"disc_number":1,"duration":498358,"artists":["Francis Bebey"],"artist_ids":["0mdmrbu5UZ32uRcRp2z6mr"],"album":"African Electronic Music (1975-1982)","album_id":"7w99Aae1tYSTSb1OiDnxYY","album_artists":["Francis Bebey"],"cover_url":"https://i.scdn.co/image/ab67616d0000b2736ab57cedf27177fae1eaed87","url":"https://open.spotify.com/track/5Cp6a1h2VnuOtsh1Nqxfv6","added_at":"2020-12-22T09:57:17Z","list_index":0}}
|
||||
```
|
||||
|
||||
This results in a single output in `JSON` format, which can e.g. be parsed using [jq](https://stedolan.github.io/jq/).
|
||||
For example, you can get the currently playing artist and title in your
|
||||
terminal as follows:
|
||||
|
||||
```
|
||||
% nc -W 1 -U ~/.cache/ncspot/ncspot.sock | jq '.playable.title'
|
||||
"PUMPIN' JUMPIN'"
|
||||
|
||||
% nc -W 1 -U ~/.cache/ncspot/ncspot.sock | jq '.playable.artists[0]'
|
||||
"Hideki Naganuma"
|
||||
```
|
||||
|
||||
## Configuration
|
||||
Configuration is saved to `~/.config/ncspot/config.toml` (or
|
||||
`%AppData%\ncspot\config.toml` on Windows). To reload the configuration during
|
||||
runtime use the `reload` command.
|
||||
|
||||
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"`<sup>[1]</sup> | `"library"` |
|
||||
| `use_nerdfont` | Turn nerdfont glyphs on/off | `true`, `false` | `false` |
|
||||
| `flip_status_indicators` | Reverse play/pause icon meaning<sup>[2]</sup> | `true`, `false` | `false` |
|
||||
| `backend` | Audio backend to use | String<sup>[3]</sup> | |
|
||||
| `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 in dB (if enabled) | Number | `0.0` |
|
||||
| `default_keybindings` | Enable default keybindings | `true`, `false` | `false` |
|
||||
| `notify`<sup>[4]</sup> | Enable desktop notifications | `true`, `false` | `false` |
|
||||
| `bitrate` | Audio bitrate to use for streaming | `96`, `160`, `320` | `320` |
|
||||
| `gapless` | Enable gapless playback | `true`, `false` | `true` |
|
||||
| `shuffle` | Set default shuffle state | `true`, `false` | `false` |
|
||||
| `repeat` | Set default repeat mode | `off`, `track`, `playlist` | `off` |
|
||||
| `playback_state` | Set default playback state | `"Stopped"`, `"Paused"`, `"Playing"`, `"Default"` | `"Paused"` |
|
||||
| `library_tabs` | Tabs to show in library screen | Array of `"tracks"`, `"albums"`, `"artists"`, `"playlists"`, `"podcasts"` | All tabs |
|
||||
| `cover_max_scale`<sup>[1]</sup> | Set maximum scaling ratio for cover art | Number | `1.0` |
|
||||
| `hide_display_names` | Hides spotify usernames in the library header and on playlists | `true`, `false` | `false` |
|
||||
| `statusbar_format` | Formatting for tracks in the statusbar | See [track_formatting](#track-formatting) | `%artists - %track` |
|
||||
| `[track_format]` | Set active fields shown in Library/Queue views | See [track formatting](#track-formatting) | |
|
||||
| `[notification_format]` | Set the text displayed in notifications<sup>[4]</sup> | See [notification formatting](#notification-formatting) | |
|
||||
| `[theme]` | Custom theme | See [custom theme](#theming) | |
|
||||
| `[keybindings]` | Custom keybindings | See [custom keybindings](#custom-keybindings) | |
|
||||
|
||||
1. If built with the `cover` feature.
|
||||
2. 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.
|
||||
3. Run `ncspot -h` for a list of devices.
|
||||
4. If built with the `notify` feature.
|
||||
|
||||
### Custom Keybindings
|
||||
Keybindings can be configured in `[keybindings]` section in `config.toml`.
|
||||
|
||||
Each key-value pair specifies one keybinding, where the key is a string in the
|
||||
format of:
|
||||
|
||||
```
|
||||
[MODIFIER+]<CHAR|NAMED_KEY>
|
||||
where:
|
||||
MODIFIER: Shift|Alt|Ctrl
|
||||
CHAR: Any printable character
|
||||
NAMED_KEY: Enter|Space|Tab|Backspace|Esc|Left|Right|Up|Down
|
||||
|Ins|Del|Home|End|PageUp|PageDown|PauseBreak|NumpadCenter
|
||||
|F0|F1|F2|F3|F4|F5|F6|F7|F8|F9|F10|F11|F12
|
||||
```
|
||||
|
||||
For implementation see [commands::CommandManager::parse_key](/src/commands.rs).
|
||||
|
||||
Its value is a string that can be parsed as a command. See
|
||||
[Vim-Like Commands](#vim-like-commands).
|
||||
|
||||
<details>
|
||||
<summary>Examples: (Click to show/hide)</summary>
|
||||
|
||||
```toml
|
||||
[keybindings]
|
||||
# Bind "Shift+i" to "Seek forward 10 seconds"
|
||||
"Shift+i" = "seek +10s"
|
||||
```
|
||||
|
||||
To disable a default keybinding, set its command to `noop`:
|
||||
|
||||
```toml
|
||||
# Use "Shift+q" to quit instead of the default "q"
|
||||
[keybindings]
|
||||
"Shift+q" = "quit"
|
||||
"q" = "noop"
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### Proxy
|
||||
`ncspot` will respect system proxy settings defined via the `http_proxy`
|
||||
environment variable.
|
||||
|
||||
```sh
|
||||
# In sh-like shells
|
||||
http_proxy="http://foo.bar:4444" ncspot
|
||||
```
|
||||
|
||||
### 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).
|
||||
|
||||
### Track Formatting
|
||||
It's possible to customize how tracks are shown in Queue/Library views and the
|
||||
statusbar, whereas `statusbar_format` will hold the statusbar formatting and
|
||||
`[track_format]` the formatting for tracks in list views.
|
||||
If you don't define `center` for example, the default value will be used.
|
||||
Available options for tracks: `%artists`, `%title`, `%album`, `%saved`,
|
||||
`%duration`
|
||||
|
||||
Default configuration:
|
||||
|
||||
```toml
|
||||
statusbar_format = "%artists - %title"
|
||||
|
||||
[track_format]
|
||||
left = "%artists - %title"
|
||||
center = "%album"
|
||||
right = "%saved %duration"
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>Examples: (Click to show/hide)</summary>
|
||||
|
||||
Example 1 - Show only album name and track name after it:
|
||||
|
||||
```toml
|
||||
[track_format]
|
||||
left = "%album"
|
||||
center = "%title"
|
||||
right = ""
|
||||
```
|
||||
|
||||
Example 2 - Show track title before artists, and don't show album at all:
|
||||
|
||||
```toml
|
||||
[track_format]
|
||||
left = "%title - %artists"
|
||||
center = ""
|
||||
```
|
||||
|
||||
Example 3 - Show everything as default, but hide saved status and track length:
|
||||
|
||||
```toml
|
||||
[track_format]
|
||||
right = ""
|
||||
```
|
||||
|
||||
Example 4 - Show everything as default, except show title before artists:
|
||||
|
||||
```toml
|
||||
[track_format]
|
||||
left = "%title - %artists"
|
||||
```
|
||||
|
||||
Example 5 - Show saved status and duration first, followed by track title and artists, with the album last:
|
||||
|
||||
```toml
|
||||
[track_format]
|
||||
left = "|%saved| %duration | %title - %artists"
|
||||
center = ""
|
||||
right = "%album"
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### Notification Formatting
|
||||
`ncspot` also supports customizing the way notifications are displayed
|
||||
(which appear when compiled with the `notify` feature and `notify = true`).
|
||||
The title and body of the notification can be set, with `title` and `body`, or the default will be used.
|
||||
The formatting options are the same as those for [track formatting](#track-formatting) (`%artists`, `%title`, etc)
|
||||
|
||||
Default configuration:
|
||||
|
||||
```toml
|
||||
[notification_format]
|
||||
title = "%title"
|
||||
body = "%artists"
|
||||
```
|
||||
|
||||
### 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 up the album art beyond its native 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 remove cached credentials. See
|
||||
[Vim-Like Commands](#vim-like-commands).
|
||||
|
||||
### Using a Password Manager
|
||||
If you would like ncspot to retrieve your login data from command results,
|
||||
i.e. because you use a password manager like `pass`, you can add the following
|
||||
configuration:
|
||||
|
||||
```toml
|
||||
[credentials]
|
||||
username_cmd = "echo username"
|
||||
password_cmd = "pass spotify.com/username"
|
||||
```
|
||||
|
||||
Do note that this is only required for the initial login or when your credential
|
||||
token has expired.
|
||||
109
images/logo_text_dark.svg
Normal file
109
images/logo_text_dark.svg
Normal file
@@ -0,0 +1,109 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="28.398985mm"
|
||||
height="8.4666662mm"
|
||||
viewBox="0 0 28.398985 8.4666662"
|
||||
version="1.1"
|
||||
id="svg21"
|
||||
xml:space="preserve"
|
||||
inkscape:export-filename="logo-text-light.svg"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
|
||||
id="namedview23"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false" /><defs
|
||||
id="defs18"><linearGradient
|
||||
id="a"
|
||||
y1="24"
|
||||
x2="32"
|
||||
y2="24"
|
||||
gradientUnits="userSpaceOnUse"><stop
|
||||
offset="0"
|
||||
stop-color="#787878"
|
||||
id="stop97" /><stop
|
||||
offset=".067"
|
||||
stop-color="gray"
|
||||
id="stop99" /><stop
|
||||
offset=".196"
|
||||
stop-color="#878787"
|
||||
id="stop101" /><stop
|
||||
offset=".5"
|
||||
stop-color="#898989"
|
||||
id="stop103" /><stop
|
||||
offset=".804"
|
||||
stop-color="#878787"
|
||||
id="stop105" /><stop
|
||||
offset=".933"
|
||||
stop-color="gray"
|
||||
id="stop107" /><stop
|
||||
offset="1"
|
||||
stop-color="#787878"
|
||||
id="stop109" /></linearGradient><linearGradient
|
||||
id="b"
|
||||
x1="16"
|
||||
y1="29"
|
||||
x2="16"
|
||||
y2="2"
|
||||
gradientUnits="userSpaceOnUse"><stop
|
||||
offset="0"
|
||||
stop-color="#2d2d2d"
|
||||
id="stop112" /><stop
|
||||
offset="1"
|
||||
stop-color="#3c3c3c"
|
||||
id="stop114" /></linearGradient></defs><g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"><g
|
||||
id="g155"
|
||||
transform="scale(0.26458333)"><path
|
||||
d="m 0,16 h 32 v 12 a 4,4 0 0 1 -4,4 H 4 A 4,4 0 0 1 0,28 Z"
|
||||
fill="url(#a)"
|
||||
id="path119"
|
||||
style="fill:url(#a)" /><rect
|
||||
x="1"
|
||||
y="2"
|
||||
width="30"
|
||||
height="27"
|
||||
rx="4"
|
||||
ry="4"
|
||||
fill="url(#b)"
|
||||
id="rect121"
|
||||
style="fill:url(#b)" /><path
|
||||
d="m 27,4 a 3,3 0 0 1 3,3 v 18 a 3,3 0 0 1 -3,3 H 5 A 3,3 0 0 1 2,25 V 7 A 3,3 0 0 1 5,4 H 27 M 27,2 H 5 A 5.015,5.015 0 0 0 0,7 v 18 a 5.015,5.015 0 0 0 5,5 h 22 a 5.015,5.015 0 0 0 5,-5 V 7 A 5.015,5.015 0 0 0 27,2 Z"
|
||||
fill="#282828"
|
||||
id="path123" /><path
|
||||
d="m 27,2 a 3,3 0 0 1 3,3 v 20 a 3,3 0 0 1 -3,3 H 5 A 3,3 0 0 1 2,25 V 5 A 3,3 0 0 1 5,2 H 27 M 27,0 H 5 A 5.015,5.015 0 0 0 0,5 v 20 a 5.015,5.015 0 0 0 5,5 h 22 a 5.015,5.015 0 0 0 5,-5 V 5 A 5.015,5.015 0 0 0 27,0 Z"
|
||||
fill="#ededed"
|
||||
id="path125" /><path
|
||||
d="m 14.449,11.446 a 1,1 0 0 0 -0.724,0.961 v 4.424 a 1.79,1.79 0 1 0 0.858,1.527 v -4.827 l 4.559,-1.311 v 3.065 a 1.791,1.791 0 1 0 0.849,1.7 H 20 V 10.514 A 0.5,0.5 0 0 0 19.362,10.033 Z M 8.378,20.16 A 0.373,0.373 0 0 1 8.06,19.984 9.374,9.374 0 0 1 11.016,7.06 0.37524159,0.37524159 0 0 1 11.416,7.695 8.626,8.626 0 0 0 8.7,19.586 0.374,0.374 0 0 1 8.383,20.16 Z"
|
||||
fill="#1ed760"
|
||||
id="path127" /><path
|
||||
d="M 5.837,21.88 A 0.5,0.5 0 0 1 5.414,21.646 12.5,12.5 0 0 1 9.354,4.414 0.5,0.5 0 1 1 9.885,5.26 11.5,11.5 0 0 0 6.26,21.115 0.5,0.5 0 0 1 6.1,21.8 0.507,0.507 0 0 1 5.837,21.88 Z M 20.786,23 a 0.375,0.375 0 0 1 -0.2,-0.693 8.626,8.626 0 0 0 2.719,-11.891 0.37524159,0.37524159 0 1 1 0.635,-0.4 A 9.374,9.374 0 0 1 20.984,22.94 0.37,0.37 0 0 1 20.786,23 Z"
|
||||
fill="#1ed760"
|
||||
id="path129" /><path
|
||||
d="M 22.381,25.663 A 0.5,0.5 0 0 1 22.115,24.74 11.5,11.5 0 0 0 25.74,8.885 a 0.5,0.5 0 1 1 0.846,-0.531 12.5,12.5 0 0 1 -3.94,17.232 0.5,0.5 0 0 1 -0.265,0.077 z"
|
||||
fill="#1ed760"
|
||||
id="path131" /></g><text
|
||||
xml:space="preserve"
|
||||
style="font-size:5.64444px;fill:#000000;stroke-width:0.264583"
|
||||
x="9.6481657"
|
||||
y="5.6574197"
|
||||
id="text369"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan367"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:5.64444px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#ffffff;stroke-width:0.264583"
|
||||
x="9.6481657"
|
||||
y="5.6574197">ncspot</tspan></text></g></svg>
|
||||
|
After Width: | Height: | Size: 4.5 KiB |
106
images/logo_text_light.svg
Normal file
106
images/logo_text_light.svg
Normal file
@@ -0,0 +1,106 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="28.398985mm"
|
||||
height="8.4666662mm"
|
||||
viewBox="0 0 28.398985 8.4666662"
|
||||
version="1.1"
|
||||
id="svg21"
|
||||
xml:space="preserve"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
|
||||
id="namedview23"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false" /><defs
|
||||
id="defs18"><linearGradient
|
||||
id="a"
|
||||
y1="24"
|
||||
x2="32"
|
||||
y2="24"
|
||||
gradientUnits="userSpaceOnUse"><stop
|
||||
offset="0"
|
||||
stop-color="#787878"
|
||||
id="stop97" /><stop
|
||||
offset=".067"
|
||||
stop-color="gray"
|
||||
id="stop99" /><stop
|
||||
offset=".196"
|
||||
stop-color="#878787"
|
||||
id="stop101" /><stop
|
||||
offset=".5"
|
||||
stop-color="#898989"
|
||||
id="stop103" /><stop
|
||||
offset=".804"
|
||||
stop-color="#878787"
|
||||
id="stop105" /><stop
|
||||
offset=".933"
|
||||
stop-color="gray"
|
||||
id="stop107" /><stop
|
||||
offset="1"
|
||||
stop-color="#787878"
|
||||
id="stop109" /></linearGradient><linearGradient
|
||||
id="b"
|
||||
x1="16"
|
||||
y1="29"
|
||||
x2="16"
|
||||
y2="2"
|
||||
gradientUnits="userSpaceOnUse"><stop
|
||||
offset="0"
|
||||
stop-color="#2d2d2d"
|
||||
id="stop112" /><stop
|
||||
offset="1"
|
||||
stop-color="#3c3c3c"
|
||||
id="stop114" /></linearGradient></defs><g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"><g
|
||||
id="g155"
|
||||
transform="scale(0.26458333)"><path
|
||||
d="m 0,16 h 32 v 12 a 4,4 0 0 1 -4,4 H 4 A 4,4 0 0 1 0,28 Z"
|
||||
fill="url(#a)"
|
||||
id="path119"
|
||||
style="fill:url(#a)" /><rect
|
||||
x="1"
|
||||
y="2"
|
||||
width="30"
|
||||
height="27"
|
||||
rx="4"
|
||||
ry="4"
|
||||
fill="url(#b)"
|
||||
id="rect121"
|
||||
style="fill:url(#b)" /><path
|
||||
d="m 27,4 a 3,3 0 0 1 3,3 v 18 a 3,3 0 0 1 -3,3 H 5 A 3,3 0 0 1 2,25 V 7 A 3,3 0 0 1 5,4 H 27 M 27,2 H 5 A 5.015,5.015 0 0 0 0,7 v 18 a 5.015,5.015 0 0 0 5,5 h 22 a 5.015,5.015 0 0 0 5,-5 V 7 A 5.015,5.015 0 0 0 27,2 Z"
|
||||
fill="#282828"
|
||||
id="path123" /><path
|
||||
d="m 27,2 a 3,3 0 0 1 3,3 v 20 a 3,3 0 0 1 -3,3 H 5 A 3,3 0 0 1 2,25 V 5 A 3,3 0 0 1 5,2 H 27 M 27,0 H 5 A 5.015,5.015 0 0 0 0,5 v 20 a 5.015,5.015 0 0 0 5,5 h 22 a 5.015,5.015 0 0 0 5,-5 V 5 A 5.015,5.015 0 0 0 27,0 Z"
|
||||
fill="#ededed"
|
||||
id="path125" /><path
|
||||
d="m 14.449,11.446 a 1,1 0 0 0 -0.724,0.961 v 4.424 a 1.79,1.79 0 1 0 0.858,1.527 v -4.827 l 4.559,-1.311 v 3.065 a 1.791,1.791 0 1 0 0.849,1.7 H 20 V 10.514 A 0.5,0.5 0 0 0 19.362,10.033 Z M 8.378,20.16 A 0.373,0.373 0 0 1 8.06,19.984 9.374,9.374 0 0 1 11.016,7.06 0.37524159,0.37524159 0 0 1 11.416,7.695 8.626,8.626 0 0 0 8.7,19.586 0.374,0.374 0 0 1 8.383,20.16 Z"
|
||||
fill="#1ed760"
|
||||
id="path127" /><path
|
||||
d="M 5.837,21.88 A 0.5,0.5 0 0 1 5.414,21.646 12.5,12.5 0 0 1 9.354,4.414 0.5,0.5 0 1 1 9.885,5.26 11.5,11.5 0 0 0 6.26,21.115 0.5,0.5 0 0 1 6.1,21.8 0.507,0.507 0 0 1 5.837,21.88 Z M 20.786,23 a 0.375,0.375 0 0 1 -0.2,-0.693 8.626,8.626 0 0 0 2.719,-11.891 0.37524159,0.37524159 0 1 1 0.635,-0.4 A 9.374,9.374 0 0 1 20.984,22.94 0.37,0.37 0 0 1 20.786,23 Z"
|
||||
fill="#1ed760"
|
||||
id="path129" /><path
|
||||
d="M 22.381,25.663 A 0.5,0.5 0 0 1 22.115,24.74 11.5,11.5 0 0 0 25.74,8.885 a 0.5,0.5 0 1 1 0.846,-0.531 12.5,12.5 0 0 1 -3.94,17.232 0.5,0.5 0 0 1 -0.265,0.077 z"
|
||||
fill="#1ed760"
|
||||
id="path131" /></g><text
|
||||
xml:space="preserve"
|
||||
style="font-size:5.64444px;fill:#000000;stroke-width:0.264583"
|
||||
x="9.6481657"
|
||||
y="5.6574197"
|
||||
id="text369"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan367"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:5.64444px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';stroke-width:0.264583"
|
||||
x="9.6481657"
|
||||
y="5.6574197">ncspot</tspan></text></g></svg>
|
||||
|
After Width: | Height: | Size: 4.3 KiB |
Reference in New Issue
Block a user