Adds plyr.fm as a public music provider through the existing MusicProvider / ProviderFactory interface. Selecting it in the shared server picker makes the existing library and search screens browse public tracks, artists, and albums; no login or pre-existing likes are required.
Scope and architecture
The implementation is now confined to provider/src/backends/plyr.rs, its registry entry, and provider registration tests. It uses the shared HTTP client and returns the existing track, artist, and album models. Track AT URIs remain queue identities and can be resolved again through the provider.
The dedicated desktop browse view, PlyrFetch / PlyrPlay commands, plyr_* UI state, README section, and generic playback change have been removed from the contribution. There are no playback or dependency changes relative to current upstream.
We are happy to narrow or adjust the adapter further to fit the project's direction.
API behavior and remaining limitations
- Catalog cursors are translated into the provider's offset/limit pages, counting playable tracks. Later pages walk earlier cursors again. Artist browsing derives unique artists from the public track catalog because the API has no artist directory endpoint.
- Native search supports titles, artists, and handles, with up to 50 results per type. Track results are resolved with at most eight requests in flight; unavailable or restricted tracks are omitted.
- Album IDs use the handle/slug pair required by the album detail endpoint. Album detail and artist discographies carry artwork; the global album-list endpoint does not supply cover URLs.
- A separate shared GraphQL issue remains:
playArtistTracksconverts a provider artist throughentity::artist::Model::from, which currently drops its songs and yields an empty queue. This revision leaves that generic conversion unchanged. - Private, unlisted, gated, and missing streams are omitted. Likes and playlists use the trait's unsupported/empty defaults.
- Upstream now includes
rockbox-playback 0.6.1,rockbox-codecs 0.2.2, androckbox-metadata 0.1.1. The earlier M4A rejection was a container-parsing bug. The previously failing “Time and Again” stream now advances through the unmodified playback path. Track duration still appears as null in the daemon's GraphQL response when absent from the API; this provider does not add duration backfilling.
Validation
cargo test -p music-player-provider --lib: 64 passed, two live tests ignored.- Explicit live plyr provider test: catalog pagination, native search, AT-URI lookup, artist details, and album details.
cargo clippy -p music-player-provider --all-targets --no-deps -- -D warnings: passed.cargo build -p music-player-desktop: passed on macOS.MUSIC_PLAYER_AUDIO_OUTPUT=fifo:/dev/null cargo test -p music-player-playback --lib -- --test-threads=1: 11 passed.- Isolated desktop daemon: registry discovery, saving/connecting the source without credentials, shared GraphQL search and catalog reads, and the desktop gRPC
Search→LoadTrackspath playing “Time and Again” without skipping. Audio was decoded to the null output.
An additional seek check failed: on macOS with MUSIC_PLAYER_AUDIO_OUTPUT=fifo:/dev/null, gRPC Search("Time and Again") → LoadTracks played normally; after seven seconds, Seek(position_ms=30000) was followed by the desktop daemon exiting with code 139. The cause has not been isolated. This is recorded for separate playback investigation; the integration contains no workaround.
Full workspace/Linux CI and a visual UI review were not run for this revision.
generated with Codex (GPT-6)