Changelog
This changelog is used to track all major changes to Mopidy.
For older releases, see History.
v4.0.0 (UNRELEASED)
Mopidy 4.0 is a major release because we’ve dropped support for old versions of our dependencies, removed a number of deprecated APIs, and rebuilt both our data models and app startup sequence.
Dependencies
In general, we require the version of each dependency that is available in the latest Debian stable release, Debian 13 Trixie.
Python >= 3.13 is now required. Support for 3.7-3.12 has been dropped, while Python 3.13-3.14 has been added to the testing matrix.
Replaced
pkg_resourceswithimportlib.metadatafrom Python’s standard library, removing the runtime dependency on setuptools.GStreamer >= 1.26.2 is now required.
PyGObject >= 3.50 is now an explicit Python dependency. Previously we assumed that you would install this together with your GStreamer installation.
Pykka >= 4.1 is now required.
Pydantic >= 2.10 is now required. This is a new dependency for Mopidy to replace our custom data models.
Cyclopts >= 3.12 is now required. This is a new dependency for Mopidy to build the command line interfaces, replacing our use of
argparse.Rich >= 3.9 is now required. This is a new dependency for Mopidy transitively via Cyclopts, which we’ve started to use directly as well to handle colorized log output.
Requests >= 2.32 is now required.
Tornado >= 6.4 is now required.
Data models
Changes to the data models may affect any Mopidy extension or client.
The
TrackandPlaylistmodels now requires theurifield to always be set. (Fixes: #2190, PR: #2229)The models are now based on Pydantic data classes, which means:
All models fields and the
replace()method should work as before, so unless your extension modifies or adds models, this should not affect you.Models are now type-checked at runtime. This should help catch bugs early.
Since we now use Pydantic to convert data models to and from JSON, the old model machinery has been removed. This includes the following:
mopidy.models.ImmutableObject– Not used by Mopidy since v1.0.5 ten years ago.mopidy.models.ValidatedImmutableObject– The old base class for all models.mopidy.models.ModelJSONEncodermopidy.models.model_json_decoder()mopidy.models.fields.Collectionmopidy.models.fields.Datemopidy.models.fields.Fieldmopidy.models.fields.Identifiermopidy.models.fields.Integermopidy.models.fields.Stringmopidy.models.fields.URI
Core API
Changes to the Core API may affect Mopidy clients.
Some of the changes in the Core API are related to replacing the use of
full TlTrack objects as API arguments with tracklist IDs, tlid.
This is especially relevant for remote clients, like web clients, which may
pass a lot less data over the network when using tracklist IDs in API calls.
The core API is no longer exported from submodules, just from
mopidy.core. Update your imports accordingly. (PR: #2221)The removed modules are:
mopidy.core.actormopidy.core.historymopidy.core.librarymopidy.core.listenermopidy.core.mixermopidy.core.playbackmopidy.core.playlistsmopidy.core.tracklist
Moved
mopidy.core.PlaybackStatetomopidy.types.PlaybackState.
Root object
The
mopidy.core.Coreclass now requires theconfigargument to be present. As this argument is provided by Mopidy itself at runtime, this should only affect the setup of extension’s test suites.
Library controller
No changes.
Playback controller
mopidy.core.PlaybackController.play()no longer acceptsTlTrackobjects, which has been deprecated since Mopidy 3.0. Use tracklist IDs (tlid) instead. (Fixes #1855, PR: #2150)
Playlist controller
No changes.
Tracklist controller
No changes.
Backend API
Changes to the Backend API may affect Mopidy backend extensions.
Added
mopidy.backend.LibraryProvider.lookup_many()to take a list of URIs and return a mapping of URIs to tracks. If this method is not implemented then repeated calls tomopidy.backend.LibraryProvider.lookup()will be used as a fallback.Deprecated
mopidy.backend.LibraryProvider.lookup(). Extensions should implementmopidy.backend.LibraryProvider.lookup_many()instead.
Audio API
Changes to the Audio API may affect a few Mopidy backend extensions.
The old audio actor has been split into a
mopidy.audio.Audiointerface with the API used by core and backends, and amopidy.audio.GstAudioimplementation using GStreamer. The API is still very specific to GStreamer, but this split makes it a bit easier to mock out the audio layer in tests. (PR: #2224)The audio API is no longer exported from submodules, just from
mopidy.audio. Update your imports accordingly. The removed modules are:mopidy.audio.actormopidy.audio.listenermopidy.audio.utils
Moved
mopidy.audio.PlaybackStatetomopidy.types.PlaybackState.The
mopidy.audio.tags.convert_tags_to_track()function now requires the trackurias an argument, so that it can construct validTrackobjects.Removed APIs only used by Mopidy-Spotify’s bespoke audio delivery mechanism, which has not been used since Spotify shut down their libspotify APIs in May 2022. The removed functions/methods are:
mopidy.audio.Audio.emit_data()mopidy.audio.Audio.set_appsrc()mopidy.audio.Audio.set_metadata()mopidy.audio.calculate_duration()mopidy.audio.create_buffer()mopidy.audio.millisecond_to_clocktime()
Commands API
Breaking change for extensions with their own CLI commands:
The
mopidy.commandsmodule which extended onargparseto let extensions add their own CLI subcommands has been removed. We now use new dependency Cyclopts to build command line interfaces. The extensions maintained by the core team, includingmopidy-localandmopidy-spotify, has been updated to use Cyclopts. The migration is pretty straight forward, but feel free to reach out for help with migrating your extension. (PR: #2234)
CLI
Everything in the the app startup from CLI invocation to having a running server has been rebuilt. The code is now hopefully a lot easier to follow and maintain going forwards. (PR: #2234)
Previously, different commands had different default logging levels. Now all commands, including mopidy itself, only emits logs from warning level and higher by default. To decrease the logging level and get more verbose log output, add -v to the root command one or more times. (PR: #2239)
Support for custom log colors via the
logcolorsconfig section has been removed. Log output to terminals are now colorized using Rich, which hopefully leads to a more pleasant and readable log output. Log colors can still be disabled by changingloggging/colors. (PR: #2241)The command mopidy deps no longer repeats transitive dependencies that have already been listed. This reduces the length of the command’s output drastically. (PR: #2152)
Audio
Workaround GStreamer
Gst.Structure().get_name()regression for versions v1.26.0 to v1.26.2 (inclusive). (PR: #2094)
Type hints
Added type hints to most of the source code. We now have a public
mopidy.typesmodule with types that are useful both for Mopidy core and extensions. This module will probably see tweaks going forward, and should not be considered entirely stable yet, but feel free to use the module’s types inif TYPE_CHECKING:code blocks to aid the type checking of your extensions.Switched from mypy to pyright and ty for type checking. The jury is still out on which we’ll use long-term. (PR: #2226)
Internals
Dropped split between the
mainanddevelopbranches in our development process. We now usemainfor all development, and have removed thedevelopbranch.Moved bundled extensions to the private package
mopidy._exts. (PR: #2218)The removed modules are:
mopidy.filemopidy.httpmopidy.m3umopidy.softwaremixermopidy.stream
Renamed modules to be explicitly private. (PR: #2227)
The removed modules are:
mopidy.config.keyringmopidy.internal.*