Irrelevant preamble: When weighing up Spotify vs Apple Music I went with Spotify owing to it being cross platform. I have a NetBSD desktop (I may have mentioned) and it meant I could use the (now defunct) Flash based web player and all was good. Then the Flash player got discontinued for one that uses widevine which doesn’t work on BSD and for awhile I was out of luck on NetBSD (I tried a few things like running the Linux client using compatibility). I wasn’t even aware of Spotify Connect clients, but stumbled across raspotify which lead me librespot which led me to spotifyd.

These are the steps I went through to build and run Spotifyd (this commit at the time of writing) on NetBSD AMD64. It’s a Spotify Connect client so it means I still need to control Spotify from another device (typically my phone), but the audio is played through my desktop… which is where my speakers and headphones are plugged in - it means I don’t have to unplug stuff and re-plug into my phone, work laptop, etc. This is 100% a “good enough for now solution” for me; I have had a quick play with the Go based microcontroller from spotcontrol and that allows a completely NetBSD only experience (although it is just an example application so doesn’t provide many features - great as a basis to build on though).

  1. Install Rust via pkgsrc/pkgin. I used version 1.29 for this
  2. Clone the spotifyd repo
  3. Try to build with cargo build --release --no-default-features --features pulseaudio_backend; Is there a way to do something like cargo fetch-dependencies and avoid having to try an initial build?
  4. You machine will act like a bit of a jet engine… and fail on these which need patching (links to the commit in my forks):
    • termios-0.2.2
    • daemonize-0.2.3
    • [get\_if\_addrs-0.5.3](https://github.com/atomicules/get_if_addrs/commit/601a0cb22e852bf9a88fb522010daf2dbee9f525)

      Fixed upstream

    • tokio-uds-0.2.2 ](https://github.com/atomicules/tokio-uds/commit/27558941953202df50d80fe124cc3275bb3b77c7)

      See EDIT at bottom

    The files are all in $HOME/.cargo/registry/src/github.com-xxxxxxxxxxxx/....

  5. Build properly (so everything links) with:

     RUSTFLAGS='-C link-args=-Wl,-rpath,/usr/lib,-rpath,/usr/pkg/lib' cargo build --release --no-default-features --features pulseaudio_backend --verbose
    

    It takes some minutes to build on my machine: There are lots of dependencies.

  6. (optional) Make sure your firewalls are ok so you can discover the client. I use npf and so ended up with something like this:

     # Simple npf.conf for Desktop
     #
     #set bpf.jit off;
    
     $ext4_if = inet4(bge0)
     $ext6_if = inet6(bge0)
    
     $services_tcp = { domain, ssh }
     $services_udp = { domain, ntp }
     $services_spotify = { 5353 }
     $services_spotify_local = { 57621, 57622 }
     $localnet4 = { 192.168.1.0/24 }
     $localnet6 = { fe80::/10 }
    
     alg "icmp"
    
     procedure "log" {
             log: npflog0
     }
    
     group "external4" on $ext4_if {
             # Stateful passing of all outgoing traffic
             pass stateful out final all
    
             # Stateful passing of inbound services
             pass stateful in final proto tcp to $ext4_if port $services_tcp
             pass stateful in final proto udp to $ext4_if port $services_udp
    
             # Spotify
             pass stateful in final proto tcp from any port $services_spotify to any port $services_spotify
             pass stateful in final proto udp from any port $services_spotify to any port $services_spotify
             pass stateful in final proto tcp from $localnet4 port $services_spotify_local to $localnet4 port $services_spotify_local
             pass stateful in final proto udp from $localnet4 port $services_spotify_local to $localnet4 port $services_spotify_local
             # Spotify uses random unprivileged port. No longer seems like can restrict source to 1900 or 5353 per ArchLinux wiki
             pass stateful in final proto tcp from $localnet4 port 1025-65535 to $localnet4 port 1025-65535
    

    Similarly for ipv6 as well (although I’ve only seen it use ipv4).

  7. (optional) Create a config. I’ve only been able to get it to recognise the config when in /etc/spotifyd.conf. I only use the config to set the name.
  8. (optional) Launch at startup. I haven’t yet created a /etc/rc.d/spotifyd, I just launch when required.

That’s it. Right now under my github I also forked [nix with a tiny change to build 0.9.0](https://github.com/atomicules/nix/commit/30ddcdc4bf79711f5ecb8ced34482ec596897140)~, but this isn't needed with the "pulse audio no default features thing"; In case you are wondering if I'd missed that above (fixed upstream and SpotifyD moved to a more recent version with that fix). Owing to the fact I just don’t have enough time for stuff like this at the time of writing I haven’t even PR’d the ones that are needed; tokio-uds is archived anyway, so not really possible to PR that, get_if_addrs needs a nightly cargo for me to test so might not PR that either and termios-rs I haven’t actually checked the OpenBSD stuff I’ve copied is applicable (it builds and seems to work).

I started with the plan of doing a pkgsrc-wip package for it, but owning to all the dependencies I’m not sure if that’s possible… maybe in a hacky way that probably makes it not worth it.

It’s super cool to have Spotify on BSD, kind of surprised it’s not more known about.

If you look at the tweaks I had to make you’ll see there are all very simple and pretty much copying whatever change someone made for OpenBSD, etc. That means it really must be trivial to get this to build on OpenBSD and probably not difficult on FreeBSD; As a rough guide looking through Rust stuff there are nearly always FreeBSD fixes, then quite often OpenBSD fixes and rarely NetBSD fixes.


[EDIT: 2019-01-17]

[EDIT: 2019-01-17]