1# Spotifyd <!-- omit in toc -->
2[![Cargo Downloads](https://img.shields.io/crates/d/spotifyd)](https://crates.io/crates/spotifyd)
3[![Dependabot Status][dependabot-badge]](https://dependabot.com)
4[![Github Actions - CD][cd-badge]][github-actions]
5[![Github Actions - CI][ci-badge]][github-actions]
6
7> An open source Spotify client running as a UNIX daemon.
8
9Spotifyd streams music just like the official client, but is more lightweight and supports more platforms. Spotifyd also supports the Spotify Connect protocol, which makes it show up as a device that can be controlled from the official clients.
10
11> __Note:__ Spotifyd requires a Spotify Premium account.
12
13- [Installation](#installation)
14  - [Provided binaries](#provided-binaries)
15  - [Compiling from source](#compiling-from-source)
16    - [Feature Flags](#feature-flags)
17      - [Media controls](#media-controls)
18      - [Audio Backends](#audio-backends)
19        - [PulseAudio](#pulseaudio)
20        - [PortAudio](#portaudio)
21        - [Rodio](#rodio)
22- [Configuration](#configuration)
23  - [CLI options](#cli-options)
24  - [Configuration file](#configuration-file)
25- [Running as a system service](#running-as-a-system-service)
26- [Common issues](#common-issues)
27- [Contributing](#contributing)
28- [Credits](#credits)
29
30## Installation
31
32### Provided binaries
33
34We provide pre-built binaries through GitHub Actions for the more popular platforms: Linux, macOS and ARMv7. You can find them [here](https://github.com/Spotifyd/spotifyd/releases). For extra integrity, the file's SHA-512 gets calculated and uploaded as well.
35
36The provided binaries come in two flavours, `slim` and `full`. Each are compiled with different features. `slim` only contains the platform's most used audio backend, `full` has also all optional features enabled (see [Feature Flags](#feature-flags)).
37
38### Compiling from source
39
40You can also compile `Spotifyd` yourself, allowing you to make use of feature flags. `Spotifyd` is written in Rust. You can download the toolchain (compiler and package manager) over at [rustup.rs](https://rustup.rs). Follow their instructions to get started.
41
42> __Note:__ Please make sure that you compile the package using the most recent `stable` verison of Rust available throug `rustup`. Some distro versions are quite outdated and might result in compilation errors.
43
44`Spotifyd` might require additional libraries during build and runtime, depending on your platform and the way to compile it (static or dynamic). The following table shows the libraries needed for each OS respectively.
45
46| Target Platform | Libraries                                            |
47|-----------------|------------------------------------------------------|
48| Fedora          | alsa-lib-devel, make, gcc                            |
49| openSUSE        | alsa-devel, make, gcc                                |
50| Debian          | libasound2-dev libssl-dev libpulse-dev libdbus-1-dev |
51| macOS           | dbus, pkg-config, portaudio                          |
52
53> __Note:__ The package names for Linux are the ones used on Debian based distributions (like Ubuntu). You will need to adapt the packages for your distribution respectively.
54
55To compile the binary, run
56
57```bash
58cargo build --release
59```
60
61To install the resulting binary, run
62
63```bash
64cargo install --path . --locked
65```
66
67### Installing with Cargo
68
69If you have `cargo` installed, you can directly install `spotifyd` by running:
70
71```bash
72cargo install spotifyd --locked
73```
74
75That will compile and install `spotifyd`'s latest version under `$HOME/.cargo/bin` for you.
76
77#### Building a Debian package
78
79You can use the `cargo-deb` create in order to build a Debian package from source.
80Install it by:
81```
82$ cargo install cargo-deb
83```
84
85Then you can build and install the Debian package with:
86```
87$ cargo deb --install
88```
89
90Note, that when building a Debian package, the `--release` is passed to the
91build command already and you do not need to specify it yourself.  See for the
92flags that are set by default in `Cargo.toml`.
93
94#### Feature Flags
95
96`Spotifyd` is split into a base package plus additional features that can be toggled on or off during compilation. Those can be split into two groups: The audio backend features that are responsible for playing back the music and additional functionality features, which enhance your experience using `spotifyd`.
97
98To enable an additional audio backend, pass `<audio_backend_name>_backend` as a feature flag. We currently support `alsa`, `pulseaudio` and `portaudio`.
99
100`Spotifyd` provides the following additional functionality:
101
102| Feature Flag | Description                                                                         |
103|--------------|-------------------------------------------------------------------------------------|
104| dbus_keyring | Provides password authentication over the system's keyring (supports all platforms) |
105| dbus_mpris   | Provides multimedia key support (Linux only)                                      |
106
107> __Note:__ Compiling Spotifyd with all features and the pulseaudio backend on Ubuntu would result in the following command: `cargo build --release --no-default-features --features pulseaudio_backend,dbus_keyring,dbus_mpris`
108
109##### Media controls
110
111Spotifyd implements the [MPRIS D-Bus Interface Specification][mpris-specification], meaning that it can be controlled by generic media playback controllers such as [playerctl][playerctl-homepage] as well as some tools specifically designed for use with the official Spotify client such as [sp][sp-homepage].
112
113> __Note:__ Make sure to rename the service name within the `sp` script to `spotifyd`!
114
115Although the code greatly improved, this feature is still considered experimental. Make sure to open an issue if you encounter any issues while using other players to control `spotifyd`.
116
117##### Audio Backends
118
119By default, the audio backend is ALSA, as ALSA is available by default on a lot of machines and usually doesn't require extra dependencies. There is also support for `pulseaudio` and `portaudio`.
120
121> __Note:__ To disable this audio backend, pass `--no-default-features` down during compilation.
122
123###### PulseAudio
124
125To use PulseAudio, compile with the `--features` flag to enable
126it:
127
128```bash
129cargo build --release --features "pulseaudio_backend"
130```
131
132You will need the development package for PulseAudio, as well
133as `build-essential` or the equivalent package of your distribution.
134
135###### PortAudio
136
137To use PortAudio (works on macOS), compile with the `--features` flag to enable it:
138
139```bash
140cargo build --release --no-default-features --features="portaudio_backend"
141```
142
143> __Note:__ It is important that you also pass down `--no-default-features` as macOS doesn't support the `alsa_backend` feature!
144
145###### Rodio
146
147To use Rodio (works on Windows, OSX, Linux), compile with the `--features` flag to enable it:
148
149```bash
150cargo build --release --no-default-features --features="rodio_backend"
151```
152
153On Linux you will need the development package for alsa and make/gcc. (`libasound2-dev`,`build-essential` on debian, `alsa-lib-devel`,`make`,`gcc` on fedora)
154
155## Configuration
156
157`Spotifyd` is able to run without configuration at all and will assume default values for most of the fields. However, running without configuration will only allow you to connect to it via Spotify Connect if you're on the same network as the daemon.
158
159### CLI options
160
161`Spotifyd` can be configured using CLI arguments. For a detailed description as well as possible values for each flag, run
162
163```bash
164spotifyd --help
165```
166
167### Configuration file
168
169`Spotifyd` is able to load configuration values from a [TOML](https://toml.io/en/v0.5.0) file too. The file has to be named `spotifyd.conf` and reside in the user's configuration directory (`~/.config/spotifyd`) or the system configuration directory (`/etc` or `/etc/xdg/spotifyd`). This also applies to macOS!
170
171The configuration file consists of two sections, `global` and `spotifyd`, whereas `spotifyd` takes priority over `global`.
172
173The configuration file has the following format:
174
175```toml
176[global]
177# Your Spotify account name.
178username = "username"
179
180# Your Spotify account password.
181password = "password"
182
183# A command that gets executed and can be used to
184# retrieve your password.
185# The command should return the password on stdout.
186#
187# This is an alternative to the `password` field. Both
188# can't be used simultaneously.
189password_cmd = "command_that_writes_password_to_stdout"
190
191# If set to true, `spotifyd` tries to look up your
192# password in the system's password storage.
193#
194# This is an alternative to the `password` field. Both
195# can't be used simultaneously.
196use_keyring = true
197
198#
199# If set to true, `spotifyd` tries to bind to the session dbus
200# and expose MPRIS controls. When running headless, without a dbus session,
201# then set this to false to avoid binding errors
202#
203use_mpris = true
204
205# The audio backend used to play the your music. To get
206# a list of possible backends, run `spotifyd --help`.
207backend = "alsa"
208
209# The alsa audio device to stream audio to. To get a
210# list of valid devices, run `aplay -L`,
211device = "alsa_audio_device"  # omit for macOS
212
213# The alsa control device. By default this is the same
214# name as the `device` field.
215control = "alsa_audio_device"  # omit for macOS
216
217# The alsa mixer used by `spotifyd`.
218mixer = "PCM"
219
220# The volume controller. Each one behaves different to
221# volume increases. For possible values, run
222# `spotifyd --help`.
223volume_controller = "alsa"  # use softvol for macOS
224
225# A command that gets executed in your shell after each song changes.
226on_song_change_hook = "command_to_run_on_playback_events"
227
228# The name that gets displayed under the connect tab on
229# official clients. Spaces are not allowed!
230device_name = "device_name_in_spotify_connect"
231
232# The audio bitrate. 96, 160 or 320 kbit/s
233bitrate = 160
234
235# The directory used to cache audio data. This setting can save
236# a lot of bandwidth when activated, as it will avoid re-downloading
237# audio files when replaying them.
238#
239# Note: The file path does not get expanded. Environment variables and
240# shell placeholders like $HOME or ~ don't work!
241cache_path = "cache_directory"
242
243# If set to true, audio data does NOT get cached.
244no_audio_cache = true
245
246# Volume on startup between 0 and 100
247initial_volume = 90
248
249# If set to true, enables volume normalisation between songs.
250volume_normalisation = true
251
252# The normalisation pregain that is applied for each song.
253normalisation_pregain = -10
254
255# The port `spotifyd` uses to announce its service over the network.
256zeroconf_port = 1234
257
258# The proxy `spotifyd` will use to connect to spotify.
259proxy = "http://proxy.example.org:8080"
260
261# The displayed device type in Spotify clients.
262# Can be unknown, computer, tablet, smartphone, speaker, tv,
263# avr (Audio/Video Receiver), stb (Set-Top Box), and audiodongle.
264device_type = "speaker"
265```
266
267#### Alternatives to storing your password in the config file <!-- omit in toc -->
268
269- **`password_cmd`** config entry
270
271  This feature allows you to provide a command that prints your password to `stdout`, which saves you from having to store your password in the config file directly. To use it, set the `password_cmd` config entry to the command you would like to use and remove the `password` config entry.
272
273  For example (using the password-management utility [pass][pass-homepage]).
274
275  ```toml
276  # ~/.config/spotifyd/spotifyd.conf
277  password_cmd = "pass spotify"
278  ```
279
280- **`use_keyring`** config entry / **`--use-keyring`** CLI flag <!-- omit in toc -->
281
282  This features leverages [Linux's DBus Secret Service API][secret-storage-specification] or native macOS keychain in order to forgo the need to store your password directly in the config file. To use it, complile with the `dbus_keyring` feature and set the `use-keyring` config entry to `true` or pass the `--use-keyring` CLI flag  during start to the daemon. Remove the `password` and/or `password_cmd` config entries.
283
284  Your keyring entry needs to have the following attributes set:
285
286  ```
287  application: rust-keyring
288  service: spotifyd
289  username: <your-spotify-username>
290  ```
291
292  To add such an entry into your keyring, you can use `secret-tool`, a CLI used to communicate with agents that support the Secret Service API:
293
294  ```bash
295  secret-tool store --label='name you choose' application rust-keyring service spotifyd username <your-username>
296  ```
297
298  You can use the keychain GUI on macOS to add an item respectively, or with the built-in `security` tool:
299
300  ```bash
301  security add-generic-password -s spotifyd -D rust-keyring -a <your username> -w
302  ```
303
304#### Shell used to run commands indicated by `password_cmd` or `on_song_changed_hook` <!-- omit in toc -->
305
306If either of these options is given, the shell `spotifyd` will use to run its commands is the shell indicated by the `SHELL` environment variable, if set. If the `SHELL` environment variable is not set, `spotifyd` will use the user's default shell, which, on Linux and BSD, is the shell listed in `/etc/passwd`. On macOS it is the shell listed in the output of `dscl . -read /Users/<username> UserShell`.
307
308## Running as a system service
309
310### on Linux
311
312A `systemd.service` unit file is provided to help run spotifyd as a service on systemd-based systems. The file `contrib/spotifyd.service` should be copied to either:
313
314```
315/etc/systemd/user/
316~/.config/systemd/user/
317```
318
319Packagers of systemd-based distributions are encouraged to include the file in the former location. End-user should prefer the latter. It should be noted that some targets are not available when running under the user directory, such as `network-online.target`.
320
321Control of the daemon is handed over to systemd. The following example commands will run the service once and enable the service to always run on login in the future respectively:
322
323```
324systemctl --user start spotifyd.service
325systemctl --user enable spotifyd.service
326```
327
328
329### on macOS
330
331On macOS the system wide and per-user daemon/agent manager is known as `launchd`. Interfacing with `launchd` is performed through `launchctl`.
332
333In order to use `spotifyd` as a service on macOS one must specify a `.plist` that represents the service, and place it in `/Library/LaunchDaemons`.
334
335Here is a .plist which works with macOS Catalina 10.15.3:
336
337```
338<?xml version="1.0" encoding="UTF-8"?>
339<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
340<plist version="1.0">
341	<dict>
342		<key>Label</key>
343		<string>rustlang.spotifyd</string>
344		<key>ProgramArguments</key>
345		<array>
346			<string>/usr/local/bin/spotifyd</string>
347			<string>--config-path=/users/YourUserName/.config/spotifyd/spotifyd.conf</string>
348			<string>--no-daemon</string>
349		</array>
350		<key>UserName</key>
351		<string>YourUserName</string>
352		<key>KeepAlive</key>
353		<true/>
354		<key>ThrottleInterval</key>
355		<integer>30</integer>
356	</dict>
357</plist>
358```
359
360
361Once present in the `/Library/LaunchDaemons` directory, the .plist must be loaded and started with the following commands.
362
363`sudo launchctl load -w /Library/LaunchDaemons/rustlang.spotifyd.plist`
364
365
366`sudo launchctl start /Library/LaunchDaemons/rustlang.spotifyd.plist`
367
368One may also unload/stop the service in a similar fashion replacing load/start with unload/stop.
369
370Note:
371
372* You should update "YourUserName" with your actual username for macOS (or remove "UserName" to run as root.
373
374
375* The string, <string>--no-daemon</string> is needed as launchd won't receive a PID for the process and will lose its remit over spotifyd. So it's best to include it, there will be no difference in use, nor will you see any log output.
376
377* macOS tries to start the daemon immediately on boot, and spotifyd fails if Wifi isn't connected. So one must have a keep alive (which retries if it fails to launch on boot), that retries after 30 seconds, which is enough for wifi etc to come up.
378
379## Common issues
380
381- Spotifyd will not work without Spotify Premium
382- The device name cannot contain spaces
383
384## Contributing
385
386We always appreciate help during the development of `spotifyd`! If you are new to programming, open source or Rust in general, take a look at issues tagged with [`good first issue`][good-first-issues]. These normally are easy to resolve and don't take much time to implement.
387
388## Credits
389
390This project would not have been possible without the amazing reverse engineering work done in [librespot](https://github.com/librespot-org/librespot), mostly by [plietar](https://github.com/plietar).
391
392<!-- This section contains all links used within the document. This prevents cluttering and makes reading the raw markdown a lot easier -->
393[github-actions]: https://github.com/Spotifyd/spotifyd/actions
394[good-first-issues]: https://github.com/Spotifyd/spotifyd/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22
395[mpris-specification]: https://specifications.freedesktop.org/mpris-spec/latest/
396[pass-homepage]: https://www.passwordstore.org/
397[playerctl-homepage]: https://github.com/altdesktop/playerctl
398[secret-storage-specification]: https://www.freedesktop.org/wiki/Specifications/secret-storage-spec/
399[sp-homepage]: https://gist.github.com/wandernauta/6800547
400
401[cd-badge]: https://github.com/Spotifyd/spotifyd/workflows/Continuous%20Deployment/badge.svg
402[ci-badge]: https://github.com/Spotifyd/spotifyd/workflows/Continuous%20Integration/badge.svg
403[dependabot-badge]: https://api.dependabot.com/badges/status?host=github&repo=Spotifyd/spotifyd
404