Skip to content

connect: publish context-less sessions with an empty context, as official clients do - #1769

Open
joel-trumper wants to merge 1 commit into
librespot-org:devfrom
joel-trumper:connect-bare-context-transfer
Open

joel-trumper wants to merge 1 commit into
librespot-org:devfrom
joel-trumper:connect-bare-context-transfer

Conversation

@joel-trumper

Copy link
Copy Markdown

Problem

When librespot plays a list of tracks without a context (a Web API PUT /me/player/play with uris), the session cannot be transferred to the official Spotify desktop client. The transfer request is accepted (the Web API returns 204, and picking the desktop client in a phone's device menu shows no error), but the desktop client never takes over and playback stays on librespot. librespot itself receives nothing during the attempt.

Transfers from librespot to the desktop client work normally when the session has a real context (a playlist, an album, spotify:user:<id>:collection). Transfers between librespot instances work in both cases.

Cause

load_context_from_tracks stores such a list under the placeholder context spotify:web-api (context_url context://spotify:web-api), and librespot publishes that in its PutStateRequest: context_uri, context_url, and the context_uri/entity_uri metadata of the current, next and previous tracks.

Capturing the cluster state the desktop client (1.2.92.147, Linux) publishes for the same Web API uris play shows it leaves all of these empty. A client taking over a session resolves the context it is given, and spotify:web-api does not resolve, so it drops the transfer.

The same happens with a context-less session that was transferred to librespot from an official client: transfer.rs stores it under spotify:unknown (while the tracks' metadata still say spotify:web-api), and it cannot be transferred back.

Fix

In ConnectState::send_state, when the context is one of these placeholders (spotify:web-api, spotify:unknown), publish a copy of the player state with context_uri/context_url cleared and the placeholder values in the tracks' context_uri/entity_uri metadata cleared. Only the published copy changes: librespot's own state keeps the placeholder, which the context handling relies on.

The comment on load_context_from_tracks says the placeholder keeps official clients' players from freezing. With this change the desktop client's now-playing bar still shows the track, artist and a running progress bar while librespot plays a bare list. I have only checked the Linux desktop client.

Testing

On Debian 13, librespot built from dev (939dc5e) plus this change, with the pipe backend:

  • uris play of two tracks on librespot, then Web API transfer to the desktop client: before, nothing happens; after, the desktop client takes over at the same position (0:21 into the track) and plays.
  • Same from a second librespot instance: same result. (Transfers were made with the Web API; a transfer from a phone's device menu showed the same failure before the change but has not been retested after it.)
  • uris play with an offset, then repeated transfers librespot → desktop → librespot → desktop, paused: before, the transfer back to the desktop client is ignored; after, every step works.
  • Playlist and spotify:user:<id>:collection contexts: unchanged, transfer works before and after.
  • Desktop client to librespot with a uris session: unchanged, works.
  • cargo fmt --all --check and cargo clippy are clean.

The investigation, the fix and this description were done by Claude Code working on my setup, where the patched librespot now runs all my speakers.

🤖 Generated with Claude Code

https://claude.ai/code/session_01TEwfiUtH64EfC6qzuvjRhz

…cial clients do

A list of tracks without a context is kept under a placeholder context:
spotify:web-api for a Web API play with uris, spotify:unknown for such a
session transferred in from another device. Published as is, an official
client taking over the session tries to resolve the placeholder, fails, and
drops the transfer without an error, so the session cannot be moved to the
Spotify desktop client.

Official clients publish such a session with an empty context_uri and
context_url, and empty context_uri/entity_uri track metadata. Do the same in
the published copy of the player state only; librespot's own state keeps the
placeholder, which its context handling relies on.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TEwfiUtH64EfC6qzuvjRhz
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant