This was a huge effort by photovoltex@gmail.com with help from the community. Over 140 commits were squashed. Below, their commit messages are kept unchanged. --- * dealer wrapper for ease of use * improve sending protobuf requests * replace connect config with connect_state config * start integrating dealer into spirc * payload handling, gzip support * put connect state consistent * formatting * request payload handling, gzip support * expose dealer::protocol, move request in own file * integrate handle of connect-state commands * spirc: remove ident field * transfer playing state better * spirc: remove remote_update stream * spirc: replace command sender with connect state update * spirc: remove device state and remaining unused methods * spirc: remove mercury sender * add repeat track state * ConnectState: add methods to replace state in spirc * spirc: move context into connect_state, update load and next * spirc: remove state, adjust remaining methods * spirc: handle more dealer request commands * revert rustfmt.toml * spirc: impl shuffle - impl shuffle again - extracted fill up of next tracks in own method - moved queue revision update into next track fill up - removed unused method `set_playing_track_index` - added option to specify index when resetting the playback context - reshuffle after repeat context * spirc: handle device became inactive * dealer: adjust payload handling * spirc: better set volume handling * dealer: box PlayCommand (clippy warning) * dealer: always respect queued tracks * spirc: update duration of track * ConnectState: update more restrictions * cleanup * spirc: handle queue requests * spirc: skip next with track * proto: exclude spirc.proto - move "deserialize_with" functions into own file - replace TrackRef with ProvidedTrack * spirc: stabilize transfer/context handling * core: cleanup some remains * connect: improvements to code structure and performance - use VecDeque for next and prev tracks * connect: delayed volume update * connect: move context resolve into own function * connect: load context asynchronous * connect: handle reconnect - might currently steal the active devices playback * connect: some fixes and adjustments - fix wrong offset when transferring playback - fix missing displayed context in web-player - remove access_token from log - send correct state reason when updating volume - queue track correctly - fix wrong assumption for skip_to * connect: replace error case with option * connect: use own context state * connect: more stabilising - handle SkipTo having no Index - handle no transferred restrictions - handle no transferred index - update state before shutdown, for smoother reacquiring * connect: working autoplay * connect: handle repeat context/track * connect: some quick fixes - found self-named uid in collection after reconnecting * connect: handle add_to_queue via set_queue * fix clippy warnings * fix check errors, fix/update example * fix 1.75 specific error * connect: position update improvements * connect: handle unavailable * connect: fix incorrect status handling for desktop and mobile * core: fix dealer reconnect - actually acquire new token - use login5 token retrieval * connect: split state into multiple files * connect: encapsulate provider logic * connect: remove public access to next and prev tracks * connect: remove public access to player * connect: move state only commands into own file * connect: improve logging * connect: handle transferred queue again * connect: fix all-features specific error * connect: extract transfer handling into own file * connect: remove old context model * connect: handle more transfer cases correctly * connect: do auth_token pre-acquiring earlier * connect: handle play with skip_to by uid * connect: simplified cluster update log * core/connect: add remaining set value commands * connect: position update workaround/fix * connect: some queue cleanups * connect: add uid to queue * connect: duration as volume delay const * connect: some adjustments and todo cleanups - send volume update before general update - simplify queue revision to use the track uri - argument why copying the prev/next tracks is fine * connect: handle shuffle from set_options * connect: handle context update * connect: move other structs into model.rs * connect: reduce SpircCommand visibility * connect: fix visibility of model * connect: fix: shuffle on startup isn't applied * connect: prevent loading a context with no tracks * connect: use the first page of a context * connect: improve context resolving - support multiple pages - support page_url of context - handle single track * connect: prevent integer underflow * connect: rename method for better clarity * connect: handle mutate and update messages * connect: fix 1.75 problems * connect: fill, instead of replace next page * connect: reduce context update to single method * connect: remove unused SpircError, handle local files * connect: reduce nesting, adjust initial transfer handling * connect: don't update volume initially * core: disable trace logging of handled mercury responses * core/connect: prevent takeover from other clients, handle session-update * connect: add queue-uid for set_queue command * connect: adjust fields for PlayCommand * connect: preserve context position after update_context * connect: unify metadata modification - only handle `is_queued` `true` items for queue * connect: polish request command handling - reply to all request endpoints - adjust some naming - add some docs * connect: add uid to tracks without * connect: simpler update of current index * core/connect: update log msg, fix wrong behavior - handle became inactive separately - remove duplicate stop - adjust docs for websocket request * core: add option to request without metrics and salt * core/context: adjust context requests and update - search should now return the expected context - removed workaround for single track playback - move local playback check into update_context - check track uri for invalid characters - early return with `?` * connect: handle possible search context uri * connect: remove logout support - handle logout command - disable support for logout - add todos for logout * connect: adjust detailed tracks/context handling - always allow next - handle no prev track available - separate active and fill up context * connect: adjust context resolve handling, again * connect: add autoplay metadata to tracks - transfer into autoplay again * core/connect: cleanup session after spirc stops * update CHANGELOG.md * playback: fix clippy warnings * connect: adjust metadata - unify naming - move more metadata infos into metadata.rs * connect: add delimiter between context and autoplay playback * connect: stop and resume correctly * connect: adjust context resolving - improved certain logging parts - preload autoplay when autoplay attribute mutates - fix transfer context uri - fix typo - handle empty strings for resolve uri - fix unexpected stop of playback * connect: ignore failure during stop * connect: revert resolve_uri changes * connect: correct context reset * connect: reduce boiler code * connect: fix some incorrect states - uid getting replaced by empty value - shuffle/repeat clearing autoplay context - fill_up updating and using incorrect index * core: adjust incorrect separator * connect: move `add_to_queue` and `mark_unavailable` into tracks.rs * connect: refactor - directly modify PutStateRequest - replace `next_tracks`, `prev_tracks`, `player` and `device` with `request` - provide helper methods for the removed fields * connect: adjust handling of context metadata/restrictions * connect: fix incorrect context states * connect: become inactive when no cluster is reported * update CHANGELOG.md * core/playback: preemptively fix clippy warnings * connect: minor adjustment to session changed * connect: change return type changing active context * connect: handle unavailable contexts * connect: fix previous restrictions blocking load with shuffle * connect: update comments and logging * core/connect: reduce some more duplicate code * more docs around the dealer
19 KiB
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning since v0.2.0.
Unreleased - YYYY-MM-DD
Changed
- [connect] Replaced
ConnectConfig
withConnectStateConfig
(breaking) - [connect] Replaced
playing_track_index
field ofSpircLoadCommand
withplaying_track
(breaking) - [connect] Replaced Mercury usage in
Spirc
with Dealer
Added
- [connect] Add
seek_to
field toSpircLoadCommand
(breaking) - [connect] Add
repeat_track
field toSpircLoadCommand
(breaking) - [playback] Add
track
field toPlayerEvent::RepeatChanged
(breaking) - [core] Add
request_with_options
andrequest_with_protobuf_and_options
toSpClient
Fixed
- [core] Fix "no native root CA certificates found" on platforms unsupported
by
rustls-native-certs
. - [core] Fix all APs rejecting with "TryAnotherAP" when connecting session on Android platform.
- [core] Fix "Invalid Credentials" when using a Keymaster access token and client ID on Android platform.
Removed
0.6.0 - 2024-10-30
This version takes another step into the direction of the HTTP API, fixes a couple of bugs, and makes it easier for developers to mock a certain platform. Also it adds the option to choose avahi, dnssd or libmdns as your zeroconf backend for Spotify Connect discovery.
Changed
- [core] The
access_token
for http requests is now acquired bylogin5
- [core] MSRV is now 1.75 (breaking)
- [discovery] librespot can now be compiled with multiple MDNS/DNS-SD backends (avahi, dns_sd, libmdns) which can be selected using a CLI flag. The defaults are unchanged (breaking).
Added
- [core] Add
get_token_with_client_id()
to get a token for a specific client ID - [core] Add
login
(mobile) andauth_token
retrieval via login5 - [core] Add
OS
andos_version
toconfig.rs
- [discovery] Added a new MDNS/DNS-SD backend which connects to Avahi via D-Bus.
Fixed
- [connect] Fixes initial volume showing zero despite playing in full volume instead
- [core] Fix "source slice length (16) does not match destination slice length (20)" panic on some tracks
0.5.0 - 2024-10-15
This version is be a major departure from the architecture up until now. It focuses on implementing the "new Spotify API". This means moving large parts of the Spotify protocol from Mercury to HTTP. A lot of this was reverse engineered before by @devgianlu of librespot-java. It was long overdue that we started implementing it too, not in the least because new features like the hopefully upcoming Spotify HiFi depend on it.
Splitting up the work on the new Spotify API, v0.5.0 brings HTTP-based file downloads and metadata access. Implementing the "dealer" (replacing the current Mercury-based SPIRC message bus with WebSockets, also required for social plays) is a large and separate effort, slated for some later release.
While at it, we are taking the liberty to do some major refactoring to make librespot more robust. Consequently not only the Spotify API changed but large parts of the librespot API too. For downstream maintainers, we realise that it can be a lot to move from the current codebase to this one, but believe us it will be well worth it.
All these changes are likely to introduce new bugs as well as some regressions. We appreciate all your testing and contributions to the repository: https://github.com/librespot-org/librespot
Changed
- [all] Assertions were changed into
Result
or removed (breaking) - [all] Purge use of
unwrap
,expect
and returnResult
(breaking) - [all]
chrono
replaced withtime
(breaking) - [all]
time
updated (CVE-2020-26235) - [all] Improve lock contention and performance (breaking)
- [all] Use a single
player
instance. Eliminates occasionalplayer
andaudio backend
restarts, which can cause issues with some playback configurations. - [all] Updated and removed unused dependencies
- [audio] Files are now downloaded over the HTTPS CDN (breaking)
- [audio] Improve file opening and seeking performance (breaking)
- [core] MSRV is now 1.74 (breaking)
- [connect]
DeviceType
moved out ofconnect
intocore
(breaking) - [connect] Update and expose all
spirc
context fields (breaking) - [connect] Add
Clone, Defaut
traits tospirc
contexts - [connect] Autoplay contexts are now retrieved with the
spclient
(breaking) - [contrib] Updated Docker image
- [core] Message listeners are registered before authenticating. As a result
there now is a separate
Session::new
and subsequentsession.connect
. (breaking) - [core]
ConnectConfig
moved out ofcore
intoconnect
(breaking) - [core]
client_id
forget_token
moved toSessionConfig
(breaking) - [core] Mercury code has been refactored for better legibility (breaking)
- [core] Cache resolved access points during runtime (breaking)
- [core]
FileId
is moved out ofSpotifyId
. For now it will be re-exported. - [core] Report actual platform data on login
- [core] Support
Session
authentication with a Spotify access token - [core]
Credentials.username
is now anOption
(breaking) - [core]
Session::connect
tries multiple access points, retrying each one. - [core] Each access point connection now timesout after 3 seconds.
- [core] Listen on both IPV4 and IPV6 on non-windows hosts
- [main]
autoplay {on|off}
now acts as an override. If unspecified,librespot
now follows the setting in the Connect client that controls it. (breaking) - [metadata] Most metadata is now retrieved with the
spclient
(breaking) - [metadata] Playlists are moved to the
playlist4_external
protobuf (breaking) - [metadata] Handle playlists that are sent with microsecond-based timestamps
- [playback] The audio decoder has been switched from
lewton
toSymphonia
. This improves the Vorbis sound quality, adds support for MP3 as well as for FLAC in the future. (breaking) - [playback] Improve reporting of actual playback cursor
- [playback] The passthrough decoder is now feature-gated (breaking)
- [playback]
rodio
: call play and pause - [protocol] protobufs have been updated
Added
- [all] Check that array indexes are within bounds (panic safety)
- [all] Wrap errors in librespot
Error
type (breaking) - [audio] Make audio fetch parameters tunable
- [connect] Add option on which zeroconf will bind. Defaults to all interfaces. Ignored by DNS-SD.
- [connect] Add session events
- [connect] Add
repeat
,set_position_ms
andset_volume
tospirc.rs
- [contrib] Add
event_handler_example.py
- [core] Send metrics with metadata queries: client ID, country & product
- [core] Verify Spotify server certificates (prevents man-in-the-middle attacks)
- [core] User attributes are stored in
Session
upon login, accessible with a getter and setter, and automatically updated as changes are pushed by the Spotify infrastructure (breaking) - [core] HTTPS is now supported, including for proxies (breaking)
- [core] Resolve
spclient
anddealer
access points (breaking) - [core] Get and cache tokens through new token provider (breaking)
- [core]
spclient
is the API for HTTP-based calls to the Spotify servers. It supports a lot of functionality, including audio previews and image downloads even if librespot doesn't use that for playback itself. - [core] Support downloading of lyrics
- [core] Support parsing
SpotifyId
for local files - [core] Support parsing
SpotifyId
for named playlists - [core] Add checks and handling for stale server connections.
- [core] Fix potential deadlock waiting for audio decryption keys.
- [discovery] Add option to show playback device as a group
- [main] Add all player events to
player_event_handler.rs
- [main] Add an event worker thread that runs async to the main thread(s) but sync to itself to prevent potential data races for event consumers
- [metadata] All metadata fields in the protobufs are now exposed (breaking)
- [oauth] Standalone module to obtain Spotify access token using OAuth authorization code flow.
- [playback] Explicit tracks are skipped if the controlling Connect client has disabled such content. Applications that use librespot as a library without Connect should use the 'filter-explicit-content' user attribute in the session.
- [playback] Add metadata support via a
TrackChanged
event - [connect] Add
activate
andload
functions toSpirc
, allowing control over local connect sessions - [metadata] Add
Lyrics
- [discovery] Add discovery initialisation retries if within the 1st min of uptime
Fixed
- [connect] Set
PlayStatus
to the correct value when Player is loading to avoid blanking out the controls whenself.play_status
isLoadingPlay
orLoadingPause
inspirc.rs
- [connect] Handle attempts to play local files better by basically ignoring
attempts to load them in
handle_remote_update
inspirc.rs
- [connect] Loading previous or next tracks, or looping back on repeat, will only start playback when we were already playing
- [connect, playback] Clean up and de-noise events and event firing
- [core] Fixed frequent disconnections for some users
- [core] More strict Spotify ID parsing
- [discovery] Update active user field upon connection
- [playback] Handle invalid track start positions by just starting the track from the beginning
- [playback] Handle disappearing and invalid devices better
- [playback] Handle seek, pause, and play commands while loading
- [playback] Handle disabled normalisation correctly when using fixed volume
- [playback] Do not stop sink in gapless mode
- [metadata] Fix missing colon when converting named spotify IDs to URIs
0.4.2 - 2022-07-29
Besides a couple of small fixes, this point release is mainly to blacklist the ap-gew4 and ap-gue1 access points that caused librespot to fail to playback anything.
Development will now shift to the new HTTP-based API, targeted for a future v0.5.0 release. The new-api branch will therefore be promoted to dev. This is a major departure from the old API and although it brings many exciting new things, it is also likely to introduce new bugs and some regressions.
Long story short, this v0.4.2 release is the most stable that librespot has yet to offer. But, unless anything big comes up, it is also intended as the last release to be based on the old API. Happy listening.
Changed
- [playback]
pipe
: Better error handling - [playback]
subprocess
: Better error handling
Added
- [core]
apresolve
: Blacklist ap-gew4 and ap-gue1 access points that cause channel errors - [playback]
pipe
: Implement stop
Fixed
- [main] fix
--opt=value
line argument logging - [playback]
alsamixer
: make--volume-ctrl fixed
work as expected when combined with--mixer alsa
0.4.1 - 2022-05-23
This release fixes dependency issues when installing from crates.
Changed
- [chore] The MSRV is now 1.56
Fixed
- [playback] Fixed dependency issues when installing from crate
0.4.0 - 2022-05-21
Note: This version was yanked, because a corrupt package was uploaded and failed to install.
This is a polishing release, adding a few little extras and improving on many thers. We had to break a couple of API's to do so, and therefore bumped the minor version number. v0.4.x may be the last in series before we migrate from the current channel-based Spotify backend to a more HTTP-based backend. Targeting that major effort for a v0.5 release sometime, we intend to maintain v0.4.x as a stable branch until then.
Changed
- [chore] The MSRV is now 1.53
- [contrib] Hardened security of the
systemd
service units - [core]
Session
:connect()
now returns the long-term credentials - [core]
Session
:connect()
now accepts a flag if the credentails should be stored via the cache - [main] Different option descriptions and error messages based on what backends are enabled at build time
- [playback] More robust dynamic limiter for very wide dynamic range (breaking)
- [playback]
alsa
: improve--device ?
output for the Alsa backend - [playback]
gstreamer
: create own context, set correct states and use sync handler - [playback]
pipe
: create file if it doesn't already exist - [playback]
Sink
:write()
now receives ownership of the packet (breaking)
Added
- [main] Enforce reasonable ranges for option values (breaking)
- [main] Add the ability to parse environment variables
- [main] Log now emits warning when trying to use options that would otherwise have no effect
- [main] Verbose logging now logs all parsed environment variables and command line arguments (credentials are redacted)
- [main] Add a
-q
,--quiet
option that changes the logging level to WARN - [main] Add
disable-credential-cache
flag (breaking) - [main] Add a short name for every flag and option
- [playback]
pulseaudio
: set the PulseAudio name to match librespot's device name viaPULSE_PROP_application.name
environment variable (user set env var value takes precedence) (breaking) - [playback]
pulseaudio
: set icon toaudio-x-generic
so we get an icon instead of a placeholder viaPULSE_PROP_application.icon_name
environment variable (user set env var value takes precedence) (breaking) - [playback]
pulseaudio
: set values to:PULSE_PROP_application.version
,PULSE_PROP_application.process.binary
,PULSE_PROP_stream.description
,PULSE_PROP_media.software
andPULSE_PROP_media.role
environment variables (user set env var values take precedence) (breaking)
Fixed
- [connect] Don't panic when activating shuffle without previous interaction
- [core] Removed unsafe code (breaking)
- [main] Fix crash when built with Avahi support but Avahi is locally unavailable
- [main] Prevent hang when discovery is disabled and there are no credentials or when bad credentials are given
- [main] Don't panic when parsing options, instead list valid values and exit
- [main]
--alsa-mixer-device
and--alsa-mixer-index
now fallback to the card and index specified in--device
. - [playback] Adhere to ReplayGain spec when calculating gain normalisation factor
- [playback]
alsa
: make--volume-range
overrides apply to Alsa softvol controls
Removed
- [playback]
alsamixer
: previously deprecated optionsmixer-card
,mixer-name
andmixer-index
have been removed
0.3.1 - 2021-10-24
Changed
- Include build profile in the displayed version information
- [playback] Improve dithering CPU usage by about 33%
Fixed
- [connect] Partly fix behavior after last track of an album/playlist
0.3.0 - 2021-10-13
Added
- [discovery] The crate
librespot-discovery
for discovery in LAN was created. Its functionality was previously part oflibrespot-connect
. - [playback] Add support for dithering with
--dither
for lower requantization error (breaking) - [playback] Add
--volume-range
option to set dB range and controllog
andcubic
volume control curves - [playback]
alsamixer
: support for querying dB range from Alsa softvol - [playback] Add
--format F64
(supported by Alsa and GStreamer only) - [playback] Add
--normalisation-gain-type auto
that switches between album and track automatically
Changed
- [audio, playback] Moved
VorbisDecoder
,VorbisError
,AudioPacket
,PassthroughDecoder
,PassthroughError
,DecoderError
,AudioDecoder
and theconvert
module fromlibrespot-audio
tolibrespot-playback
. The underlying cratesvorbis
,librespot-tremor
,lewton
andogg
should be used directly. (breaking) - [audio, playback] Use
Duration
for time constants and functions (breaking) - [connect, playback] Moved volume controls from
librespot-connect
tolibrespot-playback
crate - [connect] Synchronize player volume with mixer volume on playback
- [playback] Store and pass samples in 64-bit floating point
- [playback] Make cubic volume control available to all mixers with
--volume-ctrl cubic
- [playback] Normalize volumes to
[0.0..1.0]
instead of[0..65535]
for greater precision and performance (breaking) - [playback]
alsamixer
: complete rewrite (breaking) - [playback]
alsamixer
: query card dB range for the volume control unless specified otherwise - [playback]
alsamixer
: use--device
name for--mixer-card
unless specified otherwise - [playback]
player
: consider errors insink.start
,sink.stop
andsink.write
fatal andexit(1)
(breaking) - [playback]
player
: makeconvert
anddecoder
public so you can implement your ownSink
- [playback]
player
: update default normalisation threshold to -2 dBFS - [playback]
player
: default normalisation type is nowauto
Deprecated
- [connect] The
discovery
module was deprecated in favor of thelibrespot-discovery
crate - [playback]
alsamixer
: renamedmixer-card
toalsa-mixer-device
- [playback]
alsamixer
: renamedmixer-name
toalsa-mixer-control
- [playback]
alsamixer
: renamedmixer-index
toalsa-mixer-index
Removed
- [connect] Removed no-op mixer started/stopped logic (breaking)
- [playback] Removed
with-vorbis
andwith-tremor
features - [playback]
alsamixer
: removed--mixer-linear-volume
option, now that--volume-ctrl {linear|log}
work as expected on Alsa
Fixed
- [connect] Fix step size on volume up/down events
- [connect] Fix looping back to the first track after the last track of an album or playlist
- [playback] Incorrect
PlayerConfig::default().normalisation_threshold
caused distortion when using dynamic volume normalisation downstream - [playback] Fix
log
andcubic
volume controls to be mute at zero volume - [playback] Fix
S24_3
format on big-endian systems - [playback]
alsamixer
: makecubic
consistent between cards that report minimum volume as mute, and cards that report some dB value - [playback]
alsamixer
: make--volume-ctrl {linear|log}
work as expected - [playback]
alsa
,gstreamer
,pulseaudio
: always output in native endianness - [playback]
alsa
: revert buffer size to ~500 ms - [playback]
alsa
,pipe
,pulseaudio
: better error handling - [metadata] Skip tracks whose Spotify ID's can't be found (e.g. local files, which aren't supported)