diff --git a/README.md b/README.md
index ab1986ce..06cd78ac 100644
--- a/README.md
+++ b/README.md
@@ -97,27 +97,47 @@ Run `scoop install spotify-player` to install the application.
### Cargo
-Run `cargo install spotify_player --locked` to install the application from [crates.io](https://crates.io/crates/spotify_player).
+Install via Cargo:
+
+```
+cargo install spotify_player --locked
+```
### Arch Linux
-Run `pacman -S spotify-player` to install the application.
+Install via Arch Linux:
+
+```
+pacman -S spotify-player
+```
-**Note**: Defaults to PulseAudio / Pipewire audio backend. For a different one, please consider modifying the [official PKGBUILD](https://gitlab.archlinux.org/archlinux/packaging/packages/spotify-player) and rebuilding it manually. See [Audio Backends](#audio-backend) for a list of options.
+**Note**: Defaults to PulseAudio/Pipewire. For a different backend, modify the [official PKGBUILD](https://gitlab.archlinux.org/archlinux/packaging/packages/spotify-player) and rebuild manually. See [Audio Backends](#audio-backend).
### Void Linux
-Run `xbps-install -S spotify-player` to install the application.
+Install via Void Linux:
+
+```
+xbps-install -S spotify-player
+```
### FreeBSD
-Run `pkg install spotify-player` to install the `spotify_player` binary from FreeBSD ports.
+Install via FreeBSD:
+
+```
+pkg install spotify-player
+```
### NetBSD
-Using the package manager, run `pkgin install spotify-player` to install from the official repositories.
+Install via NetBSD:
+
+```
+pkgin install spotify-player
+```
-Building from source,
+Build from source on NetBSD:
```
cd /usr/pkgsrc/audio/spotify-player
@@ -126,29 +146,31 @@ make install
### NixOS
-[spotify-player](https://search.nixos.org/packages?channel=unstable&show=spotify-player&from=0&size=50&sort=relevance&type=packages&query=spotify-player) is available as a Nix package and can be installed via `nix-shell -p spotify-player` or as part of your system configuration.
+[spotify-player](https://search.nixos.org/packages?channel=unstable&show=spotify-player&from=0&size=50&sort=relevance&type=packages&query=spotify-player) is available as a Nix package. Install via:
-If you want to build the source locally you can run `nix-shell` in the root of a checkout of the source code. The provided `shell.nix` file will install the build prerequisites.
+```
+nix-shell -p spotify-player
+```
+
+To build from source locally, run `nix-shell` in the root of the source checkout. The provided `shell.nix` will install prerequisites.
### Docker
-**Note**: [streaming](#streaming) feature is disabled when using the docker image.
+**Note**: The streaming feature is disabled in the Docker image.
-You can download the binary image of the latest build from the `master` branch by running
+Download the latest Docker image:
```
docker pull aome510/spotify_player:latest
```
-then run
+Run the Docker container:
```
docker run --rm -it aome510/spotify_player:latest
```
-to run the application.
-
-You can also use your local config folder to configure the application or your local cache folder to store the application's cache data when running the docker image:
+To use your local config and cache folders:
```
docker run --rm \
@@ -161,17 +183,17 @@ docker run --rm \
### Spotify Connect
-`spotify-player` supports remote control with [Spotify Connect](https://support.spotify.com/us/article/spotify-connect/). To connect to a device running Spotify, press **D** (default shortcut for `SwitchDevice` command) to get the list of available devices, then press **enter** (default shortcut for `ChooseSelected` command) to connect to the selected device.
+Control Spotify remotely with [Spotify Connect](https://support.spotify.com/us/article/spotify-connect/). Press **D** to list devices, then **enter** to connect.
### Streaming
-`spotify_player` supports streaming, which needs to be built/installed with `streaming` feature (**enabled** by default) **and** with an audio backend (`rodio-backend` by default). The streaming feature allows to `spotify_player` to play music directly from terminal.
+Stream music directly from the terminal. The streaming feature is enabled by default and uses the `rodio-backend` audio backend unless otherwise specified.
-The application uses [librespot](https://github.com/librespot-org/librespot) library to create an integrated Spotify client while running. The integrated client will register a Spotify speaker device under the `spotify-player` name, which is accessible on the [Spotify connect](#spotify-connect) device list.
+The app uses [librespot](https://github.com/librespot-org/librespot) to create an integrated Spotify client, registering a `spotify-player` device accessible via Spotify Connect.
#### Audio backend
-`spotify_player` uses [rodio](https://github.com/RustAudio/rodio) as the default [audio backend](https://github.com/librespot-org/librespot/wiki/Audio-Backends). List of available audio backends:
+Default audio backend is [rodio](https://github.com/RustAudio/rodio). Available backends:
- `alsa-backend`
- `pulseaudio-backend`
@@ -182,18 +204,18 @@ The application uses [librespot](https://github.com/librespot-org/librespot) lib
- `sdl-backend`
- `gstreamer-backend`
-User can change the audio backend when building/installing the application by specifying the `--features` option. For example, to install `spotify_player` with `pulseaudio-backend`, run
+To use a different audio backend, specify the `--features` option when building. For example:
```shell
cargo install spotify_player --no-default-features --features pulseaudio-backend
```
-**Note**:
+**Notes**:
-- needs to specify `--no-default-features` here because `rodio-backend` is one of the default features.
-- user will need to install additional dependencies depending on the selected audio backend. More details can be found in the [Librespot documentation](https://github.com/librespot-org/librespot/wiki/Compiling#general-dependencies).
+- Use `--no-default-features` to disable the default `rodio-backend`.
+- Additional dependencies may be required for some backends. See [Librespot documentation](https://github.com/librespot-org/librespot/wiki/Compiling#general-dependencies).
-The `streaming` feature can be also disabled upon installing by running
+To disable streaming, build with:
```shell
cargo install spotify_player --no-default-features
@@ -201,21 +223,21 @@ cargo install spotify_player --no-default-features
### Media Control
-To enable media control support, `spotify_player` needs to be built/installed with `media-control` feature (**enabled** by default) and set the `enable_media_control` config option to `true` in the [general configuration file](https://github.com/aome510/spotify-player/blob/master/docs/config.md#media-control).
+Media control is enabled by default. Set `enable_media_control` to `true` in your config to use it. See [config docs](https://github.com/aome510/spotify-player/blob/master/docs/config.md#media-control).
-Media control support is implemented using [MPRIS DBus](https://wiki.archlinux.org/title/MPRIS) on Linux and OS window event listener on Windows and MacOS.
+Media control uses [MPRIS DBus](https://wiki.archlinux.org/title/MPRIS) on Linux and OS window events on Windows and macOS.
### Image
-To enable image rendering support, `spotify_player` needs to be built/installed with `image` feature (**disabled** by default). To install the application with `image` feature included, run:
+To enable image rendering, build with the `image` feature (disabled by default):
```shell
cargo install spotify_player --features image
```
-`spotify_player` supports rendering image in a full resolution if the application is run on either [Kitty](https://sw.kovidgoyal.net/kitty/graphics-protocol/) or [iTerm2](https://iterm2.com/documentation-images.html). Otherwise, the image will be displayed as [block characters](https://en.wikipedia.org/wiki/Block_Elements).
+Full-resolution images are supported in [Kitty](https://sw.kovidgoyal.net/kitty/graphics-protocol/) and [iTerm2](https://iterm2.com/documentation-images.html). Other terminals display images as [block characters](https://en.wikipedia.org/wiki/Block_Elements).
-`spotify_player` also supports rendering images with `sixel` behind `sixel` feature flag, which also enables `image` feature:
+To use sixel graphics, build with the `sixel` feature (also enables `image`):
```shell
cargo install spotify_player --features sixel
@@ -223,10 +245,10 @@ cargo install spotify_player --features sixel
**Notes**:
-- Not all terminals supported by [libsixel](https://github.com/saitoha/libsixel) are supported by `spotify_player` as it relies on a [third-party library](https://github.com/atanunq/viuer) for image rendering. A possible list of supported terminals can be found in [here](https://github.com/atanunq/viuer/blob/dc81f44a97727e04be0b000712e9233c92116ff8/src/printer/sixel.rs#L83-L95).
-- Images rendered by `sixel` can have a _weird_ scale. It's recommended to tweak the `cover_img_scale` config option to get the best result as the scaling works differently with different terminals and fonts.
+- Not all terminals supported by [libsixel](https://github.com/saitoha/libsixel) are supported by `spotify_player` (see [viuer supported terminals](https://github.com/atanunq/viuer/blob/dc81f44a97727e04be0b000712e9233c92116ff8/src/printer/sixel.rs#L83-L95)).
+- Sixel images may scale oddly; adjust `cover_img_scale` for best results.
-Examples of image rendering:
+Image rendering examples:
- iTerm2:
@@ -246,49 +268,49 @@ Examples of image rendering:
#### Pixelate
-If your terminal supports high-res images, but you like the pixelated look you can enable the `pixelate` feature, which also enables the `image` feature:
+For a pixelated look, enable the `pixelate` feature (also enables `image`):
```shell
cargo install spotify_player --features pixelate
```
-The amount of pixels can be tweaked via the `cover_img_pixels` config option.
+Adjust the pixelation with the `cover_img_pixels` config option.
| `cover_img_pixels` | `8` | `16` | `32` | `64` |
| ------------------ | ------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| example |
|
|
|
|
-To temporarily disable the `pixelate` feature just set `cover_img_pixels` to a high value like `512`.
+To temporarily disable pixelation, set `cover_img_pixels` to a high value (e.g., `512`).
### Notify
-To enable desktop notification support, `spotify_player` needs to be built/installed with `notify` feature (**disabled** by default). To install the application with `notify` feature included, run:
+To enable desktop notifications, build with the `notify` feature (disabled by default):
```shell
cargo install spotify_player --features notify
```
-**Note**: the notification support in `MacOS` and `Windows` are quite restricted compared to `Linux`.
+**Note**: Notification support is limited on macOS and Windows compared to Linux.
### Mouse support
-Currently, the only supported use case for mouse is to seek to a position of the current playback by left-clicking to such position in the playback's progress bar.
+Mouse support: You can seek to a position in the playback by left-clicking the progress bar.
### Daemon
-To enable a [daemon]() support, `spotify_player` needs to be built/installed with `daemon` feature (**disabled** by default). To install the application with `daemon` feature included, run:
+To enable daemon mode, build with the `daemon` feature (disabled by default):
```shell
cargo install spotify_player --features daemon
```
-You can run the application as a daemon by specifying the `-d` or `--daemon` option: `spotify_player -d`.
+Run as a daemon with `-d` or `--daemon`: `spotify_player -d`.
**Notes**:
-- `daemon` feature is not supported on Windows
-- `daemon` feature requires the `streaming` feature to be enabled and the application to be built with [an audio backend](#audio-backend)
-- because of the OS's restrictions, `daemon` feature doesn't work with the `media-control` feature on MacOS, which is **enabled by default**. In other words, if you want to use the `daemon` feature on MacOS, you must install the application with `media-control` feature **disabled**:
+- Daemon mode is not supported on Windows.
+- Daemon mode requires streaming and an audio backend.
+- On macOS, daemon mode does not work with media control (enabled by default). To use daemon mode on macOS, disable media control:
```shell
cargo install spotify_player --no-default-features --features daemon,rodio-backend
@@ -296,11 +318,11 @@ You can run the application as a daemon by specifying the `-d` or `--daemon` opt
### Fuzzy search
-To enable [fuzzy search](https://en.wikipedia.org/wiki/Approximate_string_matching) support, `spotify_player` needs to be built/installed with `fzf` feature (**disabled** by default).
+To enable [fuzzy search](https://en.wikipedia.org/wiki/Approximate_string_matching), build with the `fzf` feature (disabled by default).
### CLI Commands
-`spotify_player` offers several CLI commands to interact with Spotify:
+`spotify_player` provides several CLI commands for interacting with Spotify:
- `get`: Get Spotify data (playlist/album/artist data, user's data, etc)
- `playback`: Interact with the playback (start a playback, play-pause, next, etc)
@@ -310,19 +332,18 @@ To enable [fuzzy search](https://en.wikipedia.org/wiki/Approximate_string_matchi
- `authenticate`: Authenticate the application
- `playlist`: Playlist editing (new, delete, import, fork, etc)
-For more details, run `spotify_player -h` or `spotify_player {command} -h`, in which `{command}` is a CLI command.
+For more details, run `spotify_player -h` or `spotify_player {command} -h`.
**Notes**
-- When using the CLI for the first time, you'll need to run `spotify_player authenticate` to authenticate the application beforehand.
-- Under the hood, CLI command is handled by sending requests to a `spotify_player` client socket running on port `client_port`, [a general application configuration](https://github.com/aome510/spotify-player/blob/master/docs/config.md#general) with a default value of `8080`. If there is no running application's instance, a new client will be created upon handling the CLI commands, which increases the latency of the command.
+- On first use, run `spotify_player authenticate` to authenticate the app.
+- CLI commands communicate with a client socket on port `client_port` (default: `8080`). If no instance is running, a new client is started, which may increase latency.
#### Scripting
-The `spotify_player` command-line interface makes scripting easy.
-With the `search` subcommand, you can search Spotify and retrieve data in JSON format, enabling queries with tools like [jq](https://jqlang.github.io/jq/).
+The command-line interface is script-friendly. Use the `search` subcommand to retrieve Spotify data in JSON format, which can be processed with tools like [jq](https://jqlang.github.io/jq/).
-Here’s an example of starting playback for the first track from a search query:
+Example: Start playback for the first track from a search query:
```sh
read -p "Search spotify: " query
@@ -331,13 +352,13 @@ spotify_player playback start track --id $(spotify_player search "$query" | jq '
## Commands
-To go to the shortcut help page, press `?` or `C-h` (default shortcuts for `OpenCommandHelp` command).
+Press `?` or `C-h` to open the shortcut help page (default for `OpenCommandHelp`).
**Tips**:
-- you can search in the shortcut help page (and some other pages) using `Search` command
-- `RefreshPlayback` can be used to manually update the playback status.
-- `RestartIntegratedClient` is useful when user wants to switch to another audio device (headphone, earphone, etc) without restarting the application, as the integrated client will be re-initialized with the new device.
+- Use the `Search` command to search in the shortcut help page and other pages.
+- `RefreshPlayback` manually updates playback status.
+- `RestartIntegratedClient` is useful for switching audio devices without restarting the app.
List of supported commands:
@@ -403,11 +424,11 @@ List of supported commands:
| `JumpToCurrentTrackInContext` | jump to the current track in the context | `g c` |
| `JumpToHighlightTrackInContext` | jump to the currently highlighted search result in the context | `C-g` |
-To add new shortcuts or modify the default shortcuts, please refer to the [keymaps section](https://github.com/aome510/spotify-player/blob/master/docs/config.md#keymaps) in the configuration documentation.
+To add or modify shortcuts, see the [keymaps section](https://github.com/aome510/spotify-player/blob/master/docs/config.md#keymaps).
### Actions
-A general list of actions is available; however, not all Spotify items (track, album, artist, or playlist) implement each action. To get the list of available actions on an item, call the `ShowActionsOnCurrentTrack` command or the `ShowActionsOnSelectedItem` command, then press enter (default binding for the `ChooseSelected` command) to initiate the selected action. Some actions may not appear in the popup but can be bound to a shortcut.
+Not all actions are available for every Spotify item. To see available actions, use `ShowActionsOnCurrentTrack` or `ShowActionsOnSelectedItem`, then press enter to trigger the action. Some actions may not appear in the popup but can be bound to shortcuts.
List of available actions:
@@ -429,32 +450,32 @@ List of available actions:
- `Follow`
- `Unfollow`
-These actions can also be bound to a shortcut. To add new shortcuts, please refer to the [actions section](https://github.com/aome510/spotify-player/blob/master/docs/config.md#actions) in the configuration documentation.
+Actions can also be bound to shortcuts. To add new shortcuts, see the [actions section](https://github.com/aome510/spotify-player/blob/master/docs/config.md#actions).
### Search Page
-When first entering the search page, the application focuses on the search input. User can then input text, delete one character backward using `backspace`, or search the text using `enter`.
+When entering the search page, focus is on the search input. Enter text, use `backspace` to delete, and `enter` to search.
-To move the focus from the search input to the other windows such as track results, album results, etc, use `FocusNextWindow` or `FocusPreviousWindow`.
+To move focus from the search input to other windows (track results, album results, etc.), use `FocusNextWindow` or `FocusPreviousWindow`.
## Configurations
-By default, `spotify_player` will look into `$HOME/.config/spotify-player` for application's configuration files. This can be changed by either specifying `-c ` or `--config-folder ` option.
+By default, configuration files are located in `$HOME/.config/spotify-player`. Change this with `-c ` or `--config-folder `.
-If an application configuration file is not found, one will be created with default values.
+If no configuration file is found, one will be created with default values.
-Please refer to [the configuration documentation](https://github.com/aome510/spotify-player/blob/master/docs/config.md) for more details on the configuration options.
+See [configuration documentation](https://github.com/aome510/spotify-player/blob/master/docs/config.md) for details on available options.
## Caches
-By default, `spotify_player` will look into `$HOME/.cache/spotify-player` for application's cache files, which include log files, Spotify's authorization credentials, audio cache files, etc. This can be changed by either specifying `-C ` or `--cache-folder ` option.
+By default, cache files are stored in `$HOME/.cache/spotify-player` (logs, credentials, audio cache, etc.). Change this with `-C ` or `--cache-folder `.
### Logging
-The application stores logs inside the `$APP_CACHE_FOLDER/spotify-player-*.log` file. For debugging or submitting an issue, user can also refer to the backtrace file in `$APP_CACHE_FOLDER/spotify-player-*.backtrace`, which includes the application's backtrace in case of panics/unexpected errors.
+Logs are stored in `$APP_CACHE_FOLDER/spotify-player-*.log`. For debugging or issues, check the backtrace file in `$APP_CACHE_FOLDER/spotify-player-*.backtrace`.
-`spotify_player` uses `RUST_LOG` environment variable to define the application's [logging level](https://docs.rs/log/0.4.14/log/enum.Level.html). `RUST_LOG` is default to be `spotify_player=INFO`, which only shows the application's logs.
+Set the `RUST_LOG` environment variable to control [logging level](https://docs.rs/log/0.4.14/log/enum.Level.html). Default is `spotify_player=INFO`.
## Acknowledgement
-`spotify_player` is written in [Rust](https://www.rust-lang.org) and is built on top of awesome libraries such as [ratatui](https://github.com/ratatui/ratatui), [rspotify](https://github.com/ramsayleung/rspotify), [librespot](https://github.com/librespot-org/librespot), and [many more](https://github.com/aome510/spotify-player/blob/master/spotify_player/Cargo.toml). It's highly inspired by [spotify-tui](https://github.com/Rigellute/spotify-tui) and [ncspot](https://github.com/hrkfdn/ncspot).
+`spotify_player` is written in [Rust](https://www.rust-lang.org) and built on top of libraries like [ratatui](https://github.com/ratatui/ratatui), [rspotify](https://github.com/ramsayleung/rspotify), [librespot](https://github.com/librespot-org/librespot), and more. It is inspired by [spotify-tui](https://github.com/Rigellute/spotify-tui) and [ncspot](https://github.com/hrkfdn/ncspot).
diff --git a/docs/config.md b/docs/config.md
index 641fdb41..a3eb4da9 100644
--- a/docs/config.md
+++ b/docs/config.md
@@ -15,90 +15,73 @@
- [Component Styles](#component-styles)
- [Keymaps](#keymaps)
-All configuration files should be placed inside the application's configuration folder (default to be `$HOME/.config/spotify-player`).
+Configuration files are located in the application's configuration directory, which defaults to `$HOME/.config/spotify-player`.
## General
-**The default `app.toml` can be found in the example [`app.toml`](../examples/app.toml) file.**
-
-`spotify_player` uses `app.toml` to configure general application configurations:
-
-| Option | Description | Default |
-| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------- |
-| `client_id` | user-provided client's ID (required for interacting with Spotify Web APIs) | `d420a117a32841c2b3474932e49fb54b` |
-| `client_id_command` | a shell command that prints user client ID to stdout (overrides `client_id`) | `None` |
-| `login_redirect_uri` | the redirect URI for authenticating the application | `http://127.0.0.1:8989/login` |
-| `client_port` | the port that the application's client is running on to handle CLI commands | `8080` |
-| `tracks_playback_limit` | the limit for the number of tracks played in a **tracks** playback | `50` |
-| `playback_format` | the format of the text in the playback's window | `{status} {track} • {artists}\n{album} • {genres}\n{metadata}` |
-| `playback_metadata_fields` | list of ordered metadata fields to display in the playback UI's `{metadata}` section. Possible values: `"repeat"`, `"shuffle"`, `"volume"`, `"device"` | `["repeat", "shuffle", "volume", "device"]` |
-| `notify_format` | the format of a notification (`notify` feature only) | `{ summary = "{track} • {artists}", body = "{album}" }` |
-| `notify_timeout_in_secs` | the timeout (in seconds) of a notification (`notify` feature only) | `0` (no timeout) |
-| `notify_transient` | notify sends a transient notification that doesn't stay in history (Linux only) | `false` |
-| `player_event_hook_command` | the hook command executed when there is a new player event | `None` |
-| `ap_port` | the application's Spotify session connection port | `None` |
-| `proxy` | the application's Spotify session connection proxy | `None` |
-| `theme` | the application's theme | `default` |
-| `app_refresh_duration_in_ms` | the duration (in ms) between two consecutive application refreshes | `32` |
-| `playback_refresh_duration_in_ms` | the duration (in ms) between two consecutive playback refreshes | `0` |
-| `page_size_in_rows` | a page's size expressed as a number of rows (for page-navigation commands) | `20` |
-| `enable_media_control` | enable application media control support (`media-control` feature only) | `true` (Linux), `false` (Windows and MacOS) |
-| `enable_streaming` | enable streaming (`streaming` feature only) | `Always` |
-| `enable_notify` | enable notification (`notify` feature only) | `true` |
-| `enable_cover_image_cache` | store album's cover images in the cache folder | `true` |
-| `notify_streaming_only` | only send notification when streaming is enabled (`streaming` and `notify` feature only) | `false` |
-| `default_device` | the default device to connect to on startup if no playing device found | `spotify-player` |
-| `play_icon` | the icon to indicate playing state of a Spotify item | `▶` |
-| `pause_icon` | the icon to indicate pause state of a Spotify item | `▌▌` |
-| `liked_icon` | the icon to indicate the liked state of a song | `♥` |
-| `explicit_icon` | the icon indicating that a song is explicit | `(E)` |
-| `border_type` | the type of the application's borders | `Plain` |
-| `progress_bar_type` | the type of the playback progress bar | `Rectangle` |
-| `progress_bar_position` | the position of the playback progress bar | `Bottom` |
-| `genre_num` | the maximum number of genres to display in the playback text (if `{genres}` is used) | `2` |
-| `cover_img_width` | the width of the cover image (`image` feature only) | `5` |
-| `cover_img_length` | the length of the cover image (`image` feature only) | `9` |
-| `cover_img_scale` | the scale of the cover image (`image` feature only) | `1.0` |
-| `cover_img_pixels` | the amount of pixels per side of the cover image (`image` and `pixelate` feature only) | `16` |
-| `seek_duration_secs` | the duration (in seconds) to seek when using `SeekForward` and `SeekBackward` commands | `5` |
-| `sort_artist_albums_by_type` | sort albums on artist's pages by type, i.e. album or single | `false` |
+A sample `app.toml` is available at [examples/app.toml](../examples/app.toml).
+
+`spotify_player` uses `app.toml` for application settings. Available options:
+
+| Option | Description | Default |
+| --------------------------------- | ---------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
+| `client_id` | Spotify client ID for API access. Uses a default if not specified. | See code (default: ncspot's client ID) |
+| `client_id_command` | Shell command that outputs client ID to stdout (overrides `client_id`). | `None` |
+| `login_redirect_uri` | Redirect URI for authentication. | `http://127.0.0.1:8989/login` |
+| `client_port` | Port for the application's client to handle CLI commands. | `8080` |
+| `log_folder` | Path to store log files. | `None` |
+| `tracks_playback_limit` | Maximum number of tracks in a playback session. | `50` |
+| `playback_format` | Format string for the playback window. | `{status} {track} • {artists} {liked}\n{album} • {genres}\n{metadata}` |
+| `playback_metadata_fields` | Ordered list of metadata fields displayed in the playback UI `{metadata}` placeholder. | `["repeat", "shuffle", "volume", "device"]` |
+| `notify_format` | Notification format (if `notify` feature enabled). | `{ summary = "{track} • {artists}", body = "{album}" }` |
+| `notify_timeout_in_secs` | Notification timeout in seconds (if `notify` feature enabled). | `0` |
+| `notify_transient` | Send transient notifications (Linux only, if `notify` feature enabled). | `false` |
+| `player_event_hook_command` | Command to execute on player events. | `None` |
+| `ap_port` | Spotify session connection port. | `None` |
+| `proxy` | Spotify session connection proxy. | `None` |
+| `theme` | Name of the theme to use. | `default` |
+| `app_refresh_duration_in_ms` | Interval (ms) between application refreshes. | `32` |
+| `playback_refresh_duration_in_ms` | Interval (ms) between playback refreshes. | `0` |
+| `page_size_in_rows` | Number of rows per page for navigation. | `20` |
+| `enable_media_control` | Enable media control support (requires `media-control` feature). | `true` (Linux), `false` (macOS/Windows) |
+| `enable_streaming` | Enable streaming (`Always`, `Never`, or `DaemonOnly`). | `Always` |
+| `enable_notify` | Enable notifications (requires `notify` feature). | `true` |
+| `enable_cover_image_cache` | Cache album cover images. | `true` |
+| `notify_streaming_only` | Send notifications only when streaming is active (requires `streaming` and `notify` features). | `false` |
+| `default_device` | Default device to connect to on startup. | `spotify-player` |
+| `play_icon` | Icon for playing state. | `▶` |
+| `pause_icon` | Icon for paused state. | `▌▌` |
+| `liked_icon` | Icon for liked songs. | `♥` |
+| `explicit_icon` | Icon for explicit songs. | `(E)` |
+| `border_type` | Border style: `Hidden`, `Plain`, `Rounded`, `Double`, or `Thick`. | `Plain` |
+| `progress_bar_type` | Progress bar style: `Rectangle` or `Line`. | `Rectangle` |
+| `progress_bar_position` | Progress bar position: `Bottom` or `Right`. | `Bottom` |
+| `layout` | Layout configuration (see below). | See below |
+| `genre_num` | Max number of genres to display in playback text. | `2` |
+| `cover_img_length` | Cover image length (requires `image` feature). | `9` |
+| `cover_img_width` | Cover image width (requires `image` feature). | `5` |
+| `cover_img_scale` | Cover image scale (requires `image` feature). | `1.0` |
+| `cover_img_pixels` | Pixels per side for cover image (requires `pixelate` feature). | `16` |
+| `seek_duration_secs` | Seek duration in seconds for seek commands. | `5` |
+| `sort_artist_albums_by_type` | Sort albums by type on artist pages. | `false` |
+| `device` | Device configuration (see below). | See below |
### Notes
-- by default, `spotify-player` uses [ncspot](https://github.com/hrkfdn/ncspot)'s client ID to interact with Spotify Web APIs
- - this is due to a Spotify API restriction that would otherwise break the app's functionality. Using ncspot's client ID is currently the best available option without sacrificing user experience. For more details, see [this issue](https://github.com/aome510/spotify-player/issues/890).
-- `ap_port` and `proxy` are [Librespot's session configurations](https://github.com/librespot-org/librespot/wiki/Behind-web-proxy). By default, `spotify_player` doesn't set those values, which means the Librespot library will fallback to use its default options.
-- Positive-value `app_refresh_duration_in_ms` is used to refresh the playback periodically. This can result in hitting a Spotify rate limit if the application is running for a long time.
-- To prevent the rate limit, `spotify_player` sets `playback_refresh_duration_in_ms=0` by default and makes additional API calls when there is an event or a command triggering a playback update.
-- List of commands that triggers a playback update:
- - `NextTrack`
- - `PreviousTrack`
- - `ResumePause`
- - `PlayRandom`
- - `Repeat`
- - `Shuffle`
- - `SeekTrack` (left-clicking the playback's progress bar)
- - `ChooseSelected` (for a track, a device, etc)
-
- **Note**: the above list might not be up-to-date.
-
-- An example of event that triggers a playback update is the one happening when the current track ends.
-- `enable_streaming` can be either `Always`, `Never` or `DaemonOnly`. For backwards compatibility, `true` and `false` are still accepted as aliases for `Always` and `Never`.
-- `playback_window_position` can only be either `Top` or `Bottom`.
-- `border_type` can be either `Hidden`, `Plain`, `Rounded`, `Double` or `Thick`.
-- `progress_bar_type` can be either `Rectangle` or `Line`.
-- `progress_bar_position` can be either `Bottom` or `Right`.
-- `notify_streaming_only=true` and `enable_streaming=DaemonOnly` can be set to avoid sending multiple notifications when both daemon and UI are running.
-- `explicit_icon` can be set to some unicode char like `🅴` or `🇪` (depending on what looks good in your terminal) or to an empty string to deactivate markers for explicit songs entirely
-#### Media control
+- By default, `spotify-player` uses [ncspot](https://github.com/hrkfdn/ncspot)'s client ID for compatibility with Spotify's API. See [this issue](https://github.com/aome510/spotify-player/issues/890) for details.
+- `ap_port` and `proxy` are passed to Librespot for session configuration. Librespot uses its defaults if unset.
+- Setting a positive `app_refresh_duration_in_ms` increases API usage and may trigger rate limits. By default, `playback_refresh_duration_in_ms=0` refreshes playback only on events or commands.
+- `enable_streaming` accepts `Always`, `Never`, or `DaemonOnly`. For backward compatibility, `true`/`false` are also accepted.
+- `border_type`, `progress_bar_type`, and `progress_bar_position` accept only the values listed in the table above.
+- `explicit_icon` can be set to any Unicode character or an empty string to disable explicit markers.
-Media control support (`enable_media_control` option) is enabled by default on Linux but disabled by default on MacOS and Windows.
+#### Media control
-MacOS and Windows require **an open window** to listen to OS media event. As a result, `spotify_player` needs to spawn an invisible window on startup, which may steal focus from the running terminal. To interact with `spotify_player`, which is run on the terminal, user will need to re-focus the terminal. Because of this extra re-focus step, the media control support is disabled by default on MacOS and Windows to avoid possible confusion for first-time users.
+Media control (`enable_media_control`) is enabled by default on Linux but disabled on macOS and Windows. On these platforms, the OS requires an open window to receive media events, which may cause the terminal to lose focus on startup.
### Player event hook command
-If specified, `player_event_hook_command` should be an object with two fields `command` and `args`. Each time `spotify_player` receives a new player event, `player_event_hook_command` is executed with the event's data as the script's arguments.
+`player_event_hook_command` is an object with `command` and `args` fields. On each player event, the command executes with the event data passed as arguments.
A player event is represented as a list of arguments with either of the following values:
@@ -107,15 +90,15 @@ A player event is represented as a list of arguments with either of the followin
- `"Paused" TRACK_ID POSITION_MS`
- `"EndOfTrack" TRACK_ID`
-**Note**: if `args` is specified, such arguments will be called before the event's arguments.
+**Note**: If `args` is specified, these arguments precede the event arguments.
-For example, if `player_event_hook_command = { command = "a.sh", args = ["-b", "c", "-d"] }`, upon receiving a `Changed` event with `NEW_TRACK_ID=id`, the following command will be run
+For example, with `player_event_hook_command = { command = "a.sh", args = ["-b", "c", "-d"] }`, a `Changed` event with `NEW_TRACK_ID=id` executes:
```shell
a.sh -b c -d Changed id
```
-Example script that reads event's data from arguments and prints them to a file:
+Example script that reads event data from arguments and logs to a file:
```sh
#!/bin/bash
@@ -132,41 +115,40 @@ esac
### Client id command
-If you prefer not to include your own `client_id` directly in your configuration, you can retrieve it at runtime using the `client_id_command` option.
+To securely store your `client_id`, use `client_id_command` with a `command` and optional `args`. Example:
-If specified, `client_id_command` should be an object with two fields `command` and `args`, just like `player_event_hook_command`.
-For example to read your client_id from a file your could use `client_id_command = { command = "cat", args = ["/path/to/file"] }`
+```toml
+client_id_command = { command = "cat", args = ["/full/path/to/file"] }
+```
-> [!NOTE]
-> When passing a path as an argument, always use the full path.
-> The `~` symbol will not automatically expand to your home directory.
+**Note**: Use absolute paths; `~` is not expanded.
-### Device configurations
+### Device configuration
-The configuration options for the [Librespot](https://github.com/librespot-org/librespot) integrated device are specified under the `[device]` section in the `app.toml` file:
+Device options are configured in the `[device]` section:
-| Option | Description | Default |
-| --------------- | ----------------------------------------------------------------------- | ---------------- |
-| `name` | The librespot device's name | `spotify-player` |
-| `device_type` | The librespot device's type | `speaker` |
-| `volume` | Initial volume (in percentage) of the device | `70` |
-| `bitrate` | Bitrate in kbps (`96`, `160`, or `320`) | `320` |
-| `audio_cache` | Enable caching audio files (store in `$APP_CACHE_FOLDER/audio/` folder) | `false` |
-| `normalization` | Enable audio normalization | `false` |
-| `autoplay` | Enable autoplay similar songs | `false` |
+| Option | Description | Default |
+| --------------- | ---------------------------------------- | ---------------- |
+| `name` | Device name. | `spotify-player` |
+| `device_type` | Device type. | `speaker` |
+| `volume` | Initial volume (percent). | `70` |
+| `bitrate` | Bitrate in kbps (`96`, `160`, or `320`). | `320` |
+| `audio_cache` | Enable audio file caching. | `false` |
+| `normalization` | Enable audio normalization. | `false` |
+| `autoplay` | Enable autoplay of similar songs. | `false` |
-More details on the above configuration options can be found under the [Librespot wiki page](https://github.com/librespot-org/librespot/wiki/Options).
+See the [Librespot wiki](https://github.com/librespot-org/librespot/wiki/Options) for more details on these options.
-### Layout configurations
+### Layout configuration
-The layout of the application can be adjusted via these options.
+The `[layout]` section configures the UI layout:
| Option | Description | Default |
| -------------------------- | ---------------------------------------------------- | ------- |
-| `library.album_percent` | The percentage of the album window in the library | `40` |
-| `library.playlist_percent` | The percentage of the playlist window in the library | `40` |
-| `playback_window_position` | The position of the playback window | `Top` |
-| `playback_window_height` | The height of the playback window | `6` |
+| `library.album_percent` | Percentage of the album window in the library. | `40` |
+| `library.playlist_percent` | Percentage of the playlist window in the library. | `40` |
+| `playback_window_position` | Position of the playback window (`Top` or `Bottom`). | `Top` |
+| `playback_window_height` | Height of the playback window. | `6` |
Example:
@@ -180,31 +162,127 @@ playback_window_position = "Top"
## Themes
-`spotify_player` uses the `theme.toml` config file to look for user-defined themes.
+`spotify_player` uses `theme.toml` for custom themes.
+
+Sample themes are available at [examples/theme.toml](../examples/theme.toml).
-**An example of user-defined themes can be found in the example [`theme.toml`](../examples/theme.toml) file.**
+Select a theme by setting `theme` in `app.toml` or using the `-t ` / `--theme ` CLI flag.
-The application's theme can be modified by setting the `theme` config option in `app.toml` or by specifying the `-t ` (`--theme `) CLI option when running the player.
+A theme consists of:
+
+- `name` (required): Theme name.
+- `palette` (optional): Color palette.
+- `component_style` (optional): Styles for UI components.
+
+Omitted `palette` values use terminal colors. Omitted `component_style` values use default styles.
+
+### Component Styles
+
+The `component_style` table customizes UI component appearance. All fields are optional:
+
+| Field | Description |
+| -------------------------------- | --------------------------------------------------------- |
+| `block_title` | Style for block titles |
+| `border` | Style for borders |
+| `playback_status` | Style for the playback status indicator |
+| `playback_track` | Style for the currently playing track name |
+| `playback_artists` | Style for the artist(s) of the current track |
+| `playback_album` | Style for the album name of the current track |
+| `playback_genres` | Style for the genres of the current track |
+| `playback_metadata` | Style for the metadata section in playback |
+| `playback_progress_bar` | Style for the filled portion of the playback progress bar |
+| `playback_progress_bar_unfilled` | Style for the unfilled portion (only for `Line` type) |
+| `current_playing` | Style for the currently playing item in lists |
+| `page_desc` | Style for the page description |
+| `playlist_desc` | Style for the playlist description |
+| `table_header` | Style for table headers |
+| `selection` | Style for selected items |
+| `secondary_row` | Style for secondary rows in tables/lists |
+| `like` | Style for the like indicator |
+| `lyrics_played` | Style for played lyrics lines |
+| `lyrics_playing` | Style for the currently playing lyrics line |
+
+Each style accepts optional fields:
+
+- `fg`: Foreground color
+- `bg`: Background color
+- `modifiers`: List of style modifiers
+
+Defaults use palette values or remain unset if not specified.
+
+#### Example
+
+```toml
+[[themes]]
+name = "my_theme"
+[themes.component_style]
+block_title = { fg = "Magenta", modifiers = ["Bold"] }
+border = { fg = "White" }
+selection = { modifiers = ["Reversed", "Bold"] }
+```
+
+#### Default Component Styles
+
+```toml
+block_title = { fg = "Magenta" }
+border = {}
+playback_status = { fg = "Cyan", modifiers = ["Bold"] }
+playback_track = { fg = "Cyan", modifiers = ["Bold"] }
+playback_artists = { fg = "Cyan", modifiers = ["Bold"] }
+playback_album = { fg = "Yellow" }
+playback_genres = { fg = "BrightBlack", modifiers = ["Italic"] }
+playback_metadata = { fg = "BrightBlack" }
+playback_progress_bar = { bg = "BrightBlack", fg = "Green" }
+playback_progress_bar_unfilled = { bg = "BrightBlack" }
+current_playing = { fg = "Green", modifiers = ["Bold"] }
+page_desc = { fg = "Cyan", modifiers = ["Bold"] }
+playlist_desc = { fg = "BrightBlack", modifiers = ["Dim"] }
+table_header = { fg = "Blue" }
+selection = { modifiers = ["Reversed", "Bold"] }
+secondary_row = {}
+like = {}
+lyrics_played = { modifiers = ["Dim"] }
+lyrics_playing = { fg = "Green", modifiers = ["Bold"] }
+```
-A theme has three main components: `name` (the theme's name), `palette` (the theme's color palette), `component_style` (styles for specific application's components).
+#### Accepted Colors
-`name` is required when defining a new theme. If `palette` is not set, a palette based on the terminal's colors will be used. If `component_style` is not set, a set of predefined component styles will be used.
+Colors can be:
+
+- Black, Blue, Cyan, Green, Magenta, Red, White, Yellow
+- BrightBlack, BrightWhite, BrightRed, BrightMagenta, BrightGreen, BrightCyan, BrightBlue, BrightYellow
+- Hex codes: `#RRGGBB` (e.g., `#ff0000`)
+
+#### Style Modifiers
+
+Supported modifiers:
+
+- Bold
+- Dim
+- Italic
+- Underlined
+- RapidBlink
+- Reversed
+- Hidden
+- CrossedOut
+
+Specify multiple modifiers as a list: `modifiers = ["Bold", "Underlined"]`.
### Use script to add theme
-[a `theme_parse` python script](../scripts/theme_parse) (require `toml` and `requests` libraries) can be used to parse [Iterm2 alacritty's color schemes](https://github.com/mbadolato/iTerm2-Color-Schemes/tree/master/alacritty) into a `spotify_player` compatible theme format.
+The [`theme_parse`](../scripts/theme_parse) Python script (requires `toml` and `requests`) converts [iTerm2/alacritty color schemes](https://github.com/mbadolato/iTerm2-Color-Schemes/tree/master/alacritty) to compatible theme format.
-For example, you can run
+Example:
```
./theme_parse "Builtin Solarized Dark" "solarized_dark" >> ~/.config/spotify-player/theme.toml
```
-to parse [Builtin Solarized Dark](https://github.com/mbadolato/iTerm2-Color-Schemes/blob/master/alacritty/Builtin%20Solarized%20Dark.yml) color scheme into a new theme with `name = "solarized_dark"`.
+This converts the [Builtin Solarized Dark](https://github.com/mbadolato/iTerm2-Color-Schemes/blob/master/alacritty/Builtin%20Solarized%20Dark.yml) color scheme to a theme named `solarized_dark`.
### Palette
-A theme's palette consists of the following fields:
+A theme's `palette` table can include:
- `background`
- `foreground`
@@ -225,74 +303,11 @@ A theme's palette consists of the following fields:
- `bright_white`
- `bright_yellow`
-If a field is not specified, a default value based on the terminal's corresponding color will be used.
-
-A field's value can be set to be either a hex representation of a RGB color (e.g, `background = "#1e1f29"`) or a string representation of the color (e.g `red`, `bright_blue`, etc).
-
-More details about the palette's field naming can be found in the table in the [3-bit and 4-bit section](https://en.wikipedia.org/wiki/ANSI_escape_code#3-bit_and_4-bit).
-
-### Component Styles
-
-To define application's component styles, the user can specify any of the below fields:
-
-- `block_title`
-- `border`
-- `playback_status`
-- `playback_track`
-- `playback_artists`
-- `playback_album`
-- `playback_genres`
-- `playback_metadata`
-- `playback_progress_bar`
-- `playback_progress_bar_unfilled` (Specific to `progress_bar_type` as `Line`)
-- `current_playing`
-- `page_desc`
-- `table_header`
-- `selection`
-- `secondary_row`
-- `like`
-- `lyrics_played`
-- `lyrics_playing`
-
-A field in `component_style` is a struct with three **optional** fields: `fg` (foreground), `bg` (background) and `modifiers` (terminal effects):
-
-- `fg` and `bg` can be either a palette's color in a pascal case (e.g, `BrightBlack`, `Blue`, etc) or a hex representation of a RGB color (e.g, `"#1e1f29"`). The default values for `fg` and `bg` are the `palette`'s `foreground` and `background`.
-- The default value for `modifiers` is `[]`. `modifiers` can consist of
- - `Bold`
- - `Dim`
- - `Italic`
- - `Underlined`
- - `SlowBlink`
- - `Reversed`
- - `RapidBlink`
- - `Hidden`
- - `CrossedOut`
-
-Default value for application's component styles:
-
-```toml
-block_title = { fg = "Magenta" }
-border = {}
-playback_status = { fg = "Cyan", modifiers = ["Bold"] }
-playback_track = { fg = "Cyan", modifiers = ["Bold"] }
-playback_artists = { fg = "Cyan", modifiers = ["Bold"] }
-playback_album = { fg = "Yellow" }
-playback_genres = { fg = "BrightBlack", modifiers = ["Italic"] }
-playback_metadata = { fg = "BrightBlack" }
-playback_progress_bar = { bg = "BrightBlack", fg = "Green" }
-current_playing = { fg = "Green", modifiers = ["Bold"] }
-page_desc = { fg = "Cyan", modifiers = ["Bold"] }
-playlist_desc = { fg = "BrightBlack", modifiers = ["Dim"] }
-table_header = { fg = "Blue" }
-secondary_row = {}
-like = {}
-lyrics_played = { modifiers = ["Dim"] }
-lyrics_playing = { fg = "Green", modifiers = ["Bold"] }
-```
+Omitted fields use terminal defaults. Values can be color names or hex codes. See [ANSI color reference](https://en.wikipedia.org/wiki/ANSI_escape_code#3-bit_and_4-bit).
## Keymaps
-`spotify_player` uses `keymap.toml` to add or override new key mappings in additional to [the default key mappings](../README.md#commands). To define a new key mapping, simply add a `keymaps` entry. To remove a key mapping, set its command to `None`. For example,
+`spotify_player` uses `keymap.toml` to add or override [default key mappings](../README.md#commands). Add a `keymaps` entry to define a new mapping, or set the command to `None` to remove one. Example:
```toml
[[keymaps]]
@@ -321,12 +336,13 @@ command = { SeekBackward = { } }
key_sequence = "Q"
```
+A complete list of actions is available [here](../README.md#actions).
+
## Actions
-Actions are located in the same `keymap.toml` file as keymaps. An action can be triggered by a key sequence that is not bound to any command. Once the mapped key sequence is pressed, the corresponding action will be triggered. By default actions will act upon the currently selected item, you can change this behaviour by setting the `target` field for a keymap to either `PlayingTrack` or `SelectedItem`.
-a list of actions can be found [here](../README.md#actions).
+Actions are defined in `keymap.toml` and triggered by unbound key sequences. Actions target the selected item by default, but can be configured with `target` set to `PlayingTrack` or `SelectedItem`. See the [README](../README.md#actions) for available actions.
-For example,
+Example:
```toml
[[actions]]