macOS fetch track -> push to lastfm
README.md

Vivienne #

macOS Spotify (and maybe not only Spotify) scrobbler for a self-hosted Last.fm-compatible instance

listens to Spotify playback notifications and pushes now playing + scrobble to the instances' Last.fm 2.0 API

how it even works #

  • reads track metadata directly from Spotify.app playback notifications via NSDistributedNotificationCenter
  • authenticates once with auth.getMobileSession (your instance username + password), caches the session key in .vivienne_session
  • sends track.updateNowPlaying when a track starts
  • sends track.scrobble once per play, using the standard Last.fm threshold: track longer than 30s, played to half its length or 4 minutes (whichever comes first)

setup #

cp config.example.toml config.toml   # then edit username/password
cargo build --release
./target/release/vivienne

config is looked up in this order: $VIVIENNE_CONFIG, ./config.toml, ~/.config/vivienne/config.toml

install #

cargo install --path .

run in the background (launchd) #

~/Library/LaunchAgents/rs.cuddles.vivienne.plist (pls adjust the two absolute paths):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>            <string>rs.cuddles.vivienne</string>
    <key>ProgramArguments</key>
    <array>
        <string>/Users/USERNAME/.local/bin/vivienne</string>
    </array>
    <key>EnvironmentVariables</key>
    <dict>
        <key>VIVIENNE_CONFIG</key>
        <string>/Users/USERNAME/.config/vivienne/config.toml</string>
    </dict>
    <key>RunAtLoad</key>        <true/>
    <key>KeepAlive</key>        <true/>
    <key>StandardOutPath</key>  <string>/tmp/vivienne.log</string>
    <key>StandardErrorPath</key><string>/tmp/vivienne.log</string>
</dict>
</plist>
launchctl load ~/Library/LaunchAgents/rs.cuddles.vivienne.plist
# also stop:  launchctl unload ~/Library/LaunchAgents/rs.cuddles.vivienne.plist

TODO #