Releases: librespot-org/librespot
v0.8.0
What's Changed
Added
- [connect] Add method
transfertoSpircto automatically transfer the playback to ourselves - [core] Add method
transfertoSpClient - [core] Add
SpotifyUritype to represent more types of URI thanSpotifyIdcan - [discovery] Add support for device aliases
- [main]
--local-file-dir/-loption added to binary to specify local file directories to pull from - [metadata]
Localvariant added toUniqueFieldsenum (breaking) - [playback] Local files can now be played with the following caveats:
- They must be sampled at 44,100 Hz
- They cannot be played from a Connect device using the dedicated 'Local Files' playlist; they must be added to another playlist first
- [playback]
local_file_directoriesfield added toPlayerConfigstruct (breaking)
Changed
- [contrib] Switched contrib/Dockerfile to new Debian stable (trixie)
- [core]
get_radio_for_trackfunction changed from accepting aSpotifyIdto accepting aSpotifyUri(breaking) - [core] Changed return type of
get_extended_metadatato returnBatchedExtensionResponse(breaking) - [core] Changed parameter of
get_<item>_metadatafromSpotifyIdtoSpotifyUri(breaking) - [metadata] Changed arguments for
Metadatatrait from&SpotifyIdto&SpotifyUri(breaking) - [playback] Changed type of
SpotifyIdfields inPlayerEventmembers toSpotifyUri(breaking) - [playback]
loadfunction changed from accepting aSpotifyIdto accepting aSpotifyUri(breaking) - [playback]
preloadfunction changed from accepting aSpotifyIdto accepting aSpotifyUri(breaking)
Fixed
- [connect] Fixed failed transferring with transfer data that had an empty context uri and no tracks
- [connect] Use the provided index or the first as fallback value to always play a track on loading
- [core] Fixed a problem where the metadata didn't include the audio file by switching to
get_extended_metadata - [core] Fixed connection issues after system suspend on Linux
Removed
- [core] Removed
SpotifyItemTypeenum; the newSpotifyUriis an enum over all item types and so which variant it is
describes its item type (breaking) - [core] Removed
NamedSpotifyIdstruct; it was made obsolete bySpotifyUri(breaking) - [core] The following methods have been removed from
SpotifyIdand moved toSpotifyUri(breaking):is_playablefrom_urito_uri
Commit Summary
- chore: update libmdns to 0.10.1 by @willstott101 in #1575
- docs: Document examples by @SapiensAnatis in #1567
- refactor: Introduce SpotifyUri struct by @SapiensAnatis in #1538
- refactor: remove parking_lot dependency and refine feature selections by @roderickvd in #1543
- Fix cross compilation (add required TLS backend selection) by @starypatyk in #1594
- chore: update alpine version to 3.20 and ensure openssl-dev is included by @matsch82 in #1608
- Add rustfmt and clippy to toolchain components by @kingosticks in #1607
- feat: add inital flac decoding support via the symphonia crate by @KernelFreeze in #1589
- Add pre-commit configuration by @paulfariello in #1606
- Add RoPieee to Related Projects by @spockfish in #1615
- feat: Add aliases to discovery by @lucasdrufva in #1602
- Fix: Use the provided index or the first track as fallback value by @photovoltex in #1599
- feat: Initiate transfer playback via spclient api by @photovoltex in #1530
- Fix: Harden the transfer flow for unexpected data by @photovoltex in #1581
- Fix: Add missing feature for
with-avahifeature by @photovoltex in #1600 - Fix: use extended-metadata endpoint to acquire metadata by @photovoltex in #1622
- fix: connection issues after system suspend on Linux by @zappolowski in #1626
- feat: Basic local file support by @SapiensAnatis in #1595
- fix: Fix build failure with passthrough-decoder by @SapiensAnatis in #1630
- update cross-compile oldstable debian to stable(trixie) by @tomodachi in #1619
- fix: correct dependabot config file by @mpsq in #1629
- CI: Add a release preparation and release workflow by @photovoltex in #1559
- CI: Create a PR for the release preparations by @photovoltex in #1631
- Preparations for v0.8.0 by @github-actions[bot] in #1632
New Contributors
- @SapiensAnatis made their first contribution in #1567
- @matsch82 made their first contribution in #1608
- @KernelFreeze made their first contribution in #1589
- @paulfariello made their first contribution in #1606
- @spockfish made their first contribution in #1615
- @lucasdrufva made their first contribution in #1602
- @zappolowski made their first contribution in #1626
- @mpsq made their first contribution in #1629
- @github-actions[bot] made their first contribution in #1632
Full Changelog: v0.7.1...v0.8.0
v0.7.1
Changed
- [connect] Shuffling was adjusted, so that shuffle and repeat can be used combined
Fixed
- [connect] Repeat context will not go into autoplay anymore and triggering autoplay while shuffling shouldn't reshuffle anymore
- [connect] Only deletes the connect state on dealer shutdown instead on disconnecting
- [core] Fixed a problem where in
spclientwhere an HTTP/411 error was thrown because the header was set wrong - [main] Use the config instead of the type default for values that are not provided by the user
v0.7.0
Changed
- [core] MSRV is now 1.85 with Rust edition 2024 (breaking)
- [core] AP connect and handshake have a combined 5 second timeout.
- [core]
stream_from_cdnnow accepts the URL asTryInto<Uri>instead ofCdnUrl(breaking) - [core] Add TLS backend selection with native-tls and rustls-tls options, defaulting to native-tls
- [connect] Replaced
has_volume_ctrlwithdisable_volumeinConnectConfig(breaking) - [connect] Changed
initial_volumefromOption<u16>tou16inConnectConfig(breaking) - [connect] Replaced
SpircLoadCommandwithLoadRequest,LoadRequestOptionsandLoadContextOptions(breaking) - [connect] Moved all public items to the highest level (breaking)
- [connect] Replaced Mercury usage in
Spircwith Dealer - [metadata] Replaced
AudioFileFormatwith own enum. (breaking) - [playback] Changed trait
Mixer::opento returnResult<Self, Error>instead ofSelf(breaking) - [playback] Changed type alias
MixerFnto returnResult<Arc<dyn Mixer>, Error>instead ofArc<dyn Mixer>(breaking) - [playback] Optimize audio conversion to always dither at 16-bit level, and improve performance
- [playback] Normalizer maintains better stereo imaging, while also being faster
- [oauth] Remove loopback address requirement from
redirect_uriwhen spawning callback handling server versus using stdin.
Added
- [connect] Add command line parameter for setting volume steps.
- [connect] Add support for
seek_to,repeat_trackandautoplayforSpircloading - [connect] Add
pauseparameter toSpirc::disconnectmethod (breaking) - [connect] Add
volume_stepstoConnectConfig(breaking) - [connect] Add and enforce rustdoc
- [playback] Add
trackfield toPlayerEvent::RepeatChanged(breaking) - [playback] Add
PlayerEvent::PositionChangedevent to notify about the current playback position - [core] Add
request_with_optionsandrequest_with_protobuf_and_optionstoSpClient - [core] Add
try_get_urlstoCdnUrl - [oauth] Add
OAuthClientandOAuthClientBuilderstructs to achieve a more customizable login process
Fixed
- [test] Missing bindgen breaks crossbuild on recent runners. Now installing latest bindgen in addition.
- [core] Fix "no native root CA certificates found" on platforms unsupported
byrustls-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. - [connect] Fix "play" command not handled if missing "offset" property
- [discovery] Fix libmdns zerconf setup errors not propagating to the main task.
- [metadata]
Show::trailer_uriis now optional since it isn't always present (breaking) - [metadata] Fix incorrect parsing of audio format
- [connect] Handle transfer of playback with empty "uri" field
- [connect] Correctly apply playing/paused state when transferring playback
- [player] Saturate invalid seek positions to track duration
- [audio] Fall back to other URLs in case of a failure when downloading from CDN
- [core] Metadata requests failing with 500 Internal Server Error
- [player] Rodio backend did not honor audio output format request
Deprecated
- [oauth]
get_access_token()function marked for deprecation - [core]
try_get_url()function marked for deprecation
Removed
- [core] Removed
get_canvasesfrom SpClient (breaking) - [core] DeviceType
homethingremoved due to crashes on Android (breaking) - [metadata] Removed
genresfrom Album (breaking) - [metadata] Removed
genrefrom Artists (breaking)
v0.6.0
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_tokenfor 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_tokenretrieval via login5 - [core] Add
OSandos_versiontoconfig.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
Contributors
v0.5.0
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
Resultor removed (breaking) - [all] Purge use of
unwrap,expectand returnResult(breaking) - [all]
chronoreplaced withtime(breaking) - [all]
timeupdated (CVE-2020-26235) - [all] Improve lock contention and performance (breaking)
- [all] Use a single player instance. Eliminates occasional player and audio 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]
DeviceTypemoved out ofconnectintocore(breaking) - [connect] Update and expose all
spirccontext fields (breaking) - [connect] Add
Clone,Defaulttraits tospirccontexts - [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::newand subsequentsession.connect. (breaking) - [core]
ConnectConfigmoved out ofcoreintoconnect(breaking) - [core]
client_idforget_tokenmoved toSessionConfig(breaking) - [core] Mercury code has been refactored for better legibility (breaking)
- [core] Cache resolved access points during runtime (breaking)
- [core]
FileIdis 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.usernameis now anOption(breaking) - [core]
Session::connecttries multiple access points, retrying each one. - [core] Each access point connection now timeout 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,librespotnow 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_externalprotobuf (breaking) - [metadata] Handle playlists that are sent with microsecond-based timestamps
- [playback] The audio decoder has been switched from
lewtontoSymphonia. 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: callplayandpause - [protocol] protobufs have been updated
Added
- [all] Check that array indexes are within bounds (panic safety)
- [all] Wrap errors in
librespotErrortype (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_msandset_volumetospirc.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
spclientanddealeraccess points (breaking) - [core] Get and cache tokens through new token provider (breaking)
- [core]
spclientis 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
SpotifyIdfor local files - [core] Support parsing
SpotifyIdfor 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
librespotas a library without Connect should use the 'filter-explicit-content' user attribute in the session. - [playback] Add metadata support via a
TrackChangedevent - [connect] Add activate and load functions to Spirc, allowing control over local connect sessions
- [metadata] Add Lyrics
- [discovery] Add discovery initialisation retries if within the 1st min of uptime
Fixed
- [connect] Set
PlayStatusto the correct value when Player is loading to avoid blanking out the controls whenself.play_statusisLoadingPlayorLoadingPauseinspirc.rs - [connect] Handle attempts to play local files better by basically ignoring attempts to load them in
handle_remote_updateinspirc.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
v0.4.2
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.
Changelog
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=valueline argument logging - [playback]
alsamixer: make--volume-ctrl fixedwork as expected when combined with--mixer alsa
v0.4.1
This release fixes dependency issues when installing from crates. v0.4.0 has been yanked.
v0.4.0
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 others. 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.
Changelog
Changed
- [chore] The MSRV is now 1.53
- [contrib] Hardened security of the
systemdservice 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,--quietoption that changes the logging level to WARN - [main] Add
disable-credential-cacheflag (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.nameenvironment variable (user set env var value takes precedence) (breaking) - [playback]
pulseaudio: set icon toaudio-x-genericso we get an icon instead of a placeholder viaPULSE_PROP_application.icon_nameenvironment 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.softwareandPULSE_PROP_media.roleenvironment 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-deviceand--alsa-mixer-indexnow fallback to the card and index specified in--device. - [playback] Adhere to ReplayGain spec when calculating gain normalisation factor
- [playback]
alsa: make--volume-rangeoverrides apply to Alsa softvol controls
Removed
- [playback]
alsamixer: previously deprecated optionsmixer-card,mixer-nameandmixer-indexhave been removed
v0.3.1
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
v0.3.0
Added
- [discovery] The crate
librespot-discoveryfor discovery in LAN was created. Its functionality was previously part oflibrespot-connect. - [playback] Add support for dithering with
--ditherfor lower requantization error (breaking) - [playback] Add
--volume-rangeoption to set dB range and controllogandcubicvolume 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 autothat switches between album and track automatically
Changed
- [audio, playback] Moved
VorbisDecoder,VorbisError,AudioPacket,PassthroughDecoder,PassthroughError,DecoderError,AudioDecoderand theconvertmodule fromlibrespot-audiotolibrespot-playback. The underlying cratesvorbis,librespot-tremor,lewtonandoggshould be used directly. (breaking) - [audio, playback] Use
Durationfor time constants and functions (breaking) - [connect, playback] Moved volume controls from
librespot-connecttolibrespot-playbackcrate - [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--devicename for--mixer-cardunless specified otherwise - [playback]
player: consider errors insink.start,sink.stopandsink.writefatal andexit(1)(breaking) - [playback]
player: makeconvertanddecoderpublic 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
discoverymodule was deprecated in favor of thelibrespot-discoverycrate - [playback]
alsamixer: renamedmixer-cardtoalsa-mixer-device - [playback]
alsamixer: renamedmixer-nametoalsa-mixer-control - [playback]
alsamixer: renamedmixer-indextoalsa-mixer-index
Removed
- [connect] Removed no-op mixer started/stopped logic (breaking)
- [playback] Removed
with-vorbisandwith-tremorfeatures - [playback]
alsamixer: removed--mixer-linear-volumeoption, now that--volume-ctrl {linear|log}work as expected on Alsa
Fixed
- [connect] Fix step size on volume up/down events
- [playback] Incorrect
PlayerConfig::default().normalisation_thresholdcaused distortion when using dynamic volume normalisation downstream - [playback] Fix
logandcubicvolume controls to be mute at zero volume - [playback] Fix
S24_3format on big-endian systems - [playback]
alsamixer: makecubicconsistent 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)