Skip to content

Backend API

The backend API is the interface that must be implemented when you create a backend. If you are working on a frontend and need to access the backends, see the Core API instead.

URIs and routing of requests to the backend

When Mopidy's core layer is processing a client request, it routes the request to one or more appropriate backends based on the URIs of the objects the request touches on. The objects' URIs are compared with the backends' mopidy.backend.Backend.uri_schemes to select the relevant backends.

An often used pattern when implementing Mopidy backends is to create your own URI scheme which you use for all tracks, playlists, etc. related to your backend. In most cases the Mopidy URI is translated to an actual URI that GStreamer knows how to play right before playback. For example:

  • Spotify already has its own URI scheme (spotify:track:..., spotify:playlist:..., etc.) used throughout their applications, and thus mopidy-spotify simply uses the same URI scheme.

  • mopidy-soundcloud created it's own URI scheme, after the model of Spotify, and uses URIs of the following forms: soundcloud:search, soundcloud:user-..., soundcloud:exp-..., and soundcloud:set-.... Playback is handled by converting the custom soundcloud:.. URIs to http:// URIs immediately before they are passed on to GStreamer for playback.

  • Mopidy differentiates between file://... URIs handled by mopidy-stream and local:... URIs handled by mopidy-local. mopidy-stream can play file://... URIs pointing to tracks and playlists located anywhere on your system, but it doesn't know a thing about the object before you play it. On the other hand, mopidy-local scans a predefined local/media_dir to build a meta data library of all known tracks. It is thus limited to playing tracks residing in the media library, but can provide additional features like directory browsing and search. In other words, we have two different ways of playing local music, handled by two different backends, and have thus created two different URI schemes to separate their handling. The local:... URIs are converted to file://... URIs immediately before they are passed on to GStreamer for playback.

If there isn't an existing URI scheme that fits for your backend's purpose, you should create your own, and name it after your extension's mopidy.ext.Extension.ext_name. Care should be taken not to conflict with already in use URI schemes. It is also recommended to design the format such that tracks, playlists and other entities can be distinguished easily.

However, it's important to note that outside of the backend that created them, URIs are opaque values that neither Mopidy's core layer or Mopidy frontends should attempt to derive any meaning from. The only valid exception to this is checking the scheme.

Backend implementations

See the extension registry.

mopidy.backend

Classes:

Backend

Backend(*, config: Config, audio: AudioProxy)

Backend API.

If the backend has problems during initialization it should raise BackendError with a descriptive error message. This will make Mopidy print the error message and exit so that the user can fix the issue.

Parameters:

  • config

    (Config) –

    The global config object.

  • audio

    (AudioProxy) –

    Actor proxy for the audio subsystem.

Methods:

  • ping

    Called to check if the actor is still alive.

Attributes:

library class-attribute instance-attribute

library: LibraryProvider | None = None

The library provider.

An instance of LibraryProvider, or None if the backend doesn't provide a library.

playback class-attribute instance-attribute

playback: PlaybackProvider | None = None

The playback provider.

An instance of PlaybackProvider, or None if the backend doesn't provide playback.

playlists class-attribute instance-attribute

playlists: PlaylistsProvider | None = None

The playlists provider.

An instance of PlaylistsProvider, or None if the backend doesn't provide playlists.

uri_schemes class-attribute

uri_schemes: list[UriScheme] = []

List of URI schemes this backend can handle.

ping

ping() -> bool

Called to check if the actor is still alive.

BackendListener

Bases: Listener

Marker interface for recipients of events sent by the backend actors.

Any Pykka actor that mixes in this class will receive calls to the methods defined here when the corresponding events happen in a backend actor. This interface is used both for looking up what actors to notify of the events, and for providing default implementations for those listeners that are not interested in all events.

Normally, only the Core actor should mix in this class.

Methods:

  • on_event

    Called on all events.

  • playlists_loaded

    Called when playlists are loaded or refreshed.

  • send

    Helper to allow calling of backend listener events.

on_event

on_event(event: Any, **kwargs: Any) -> None

Called on all events.

MAY be implemented by actor. By default, this method forwards the event to the specific event methods.

Parameters:

  • event
    (Any) –

    The event name.

  • kwargs
    (Any, default: {} ) –

    Any other arguments to the specific event handlers.

playlists_loaded

playlists_loaded() -> None

Called when playlists are loaded or refreshed.

MAY be implemented by actor.

send staticmethod

send(event: str, **kwargs: Any) -> None

Helper to allow calling of backend listener events.

BackendProxy

Bases: ActorMemberMixin, ActorProxy[BackendActor]

Backend wrapped in a Pykka actor proxy.

LibraryProvider

LibraryProvider(backend: Backend)

A library provider provides a library of music to Mopidy.

Methods:

Attributes:

root_directory class-attribute instance-attribute

root_directory: Ref | None = None

A Ref.directory with a URI and name set, representing the root of this library's browse tree. URIs must use one of the schemes supported by the backend, and name should be set to a human-friendly value.

MUST be set by any class that implements browse.

browse

browse(uri: Uri) -> list[Ref]

See mopidy.core.LibraryController.browse.

If you implement this method, make sure to also set root_directory.

MAY be implemented by subclass.

get_distinct

get_distinct(
    field: DistinctField, query: Query[SearchField] | None = None
) -> set[str]

See mopidy.core.LibraryController.get_distinct.

MAY be implemented by subclass.

Default implementation will simply return an empty set.

Note that backends should always return an empty set for unexpected field types.

get_images

get_images(uris: list[Uri]) -> dict[Uri, list[Image]]

See mopidy.core.LibraryController.get_images.

MAY be implemented by subclass.

Default implementation will simply return an empty dictionary.

lookup

lookup(uri: Uri) -> list[Track]

See mopidy.core.LibraryController.lookup.

MUST be implemented by subclass if lookup_many is not implemented.

Deprecated: Implement lookup_many instead. If lookup_many is implemented, Mopidy will never call this method on a backend.

lookup_many

lookup_many(uris: Iterable[Uri]) -> dict[Uri, list[Track]]

See mopidy.core.LibraryController.lookup.

MUST be implemented by subclass.

refresh

refresh(uri: Uri | None = None) -> None

See mopidy.core.LibraryController.refresh.

MAY be implemented by subclass.

search

search(
    query: Query[SearchField],
    uris: list[Uri] | None = None,
    exact: bool = False,
) -> SearchResult | None

See mopidy.core.LibraryController.search.

MAY be implemented by subclass.

PlaybackProvider

PlaybackProvider(audio: AudioProxy, backend: Backend)

A playback provider provides audio playback control.

Methods:

  • change_track

    Switch to provided track.

  • get_time_position

    Get the current time position in milliseconds.

  • is_live

    Decide if the URI should be treated as a live stream or not.

  • on_source_setup

    Called when a new GStreamer source is created, to allow configuration.

  • pause

    Pause playback.

  • play

    Start playback.

  • prepare_change

    Indicate that an URI change is about to happen.

  • resume

    Resume playback at the same time position playback was paused.

  • seek

    Seek to a given time position.

  • should_download

    Attempt progressive download buffering for the URI or not.

  • stop

    Stop playback.

  • translate_uri

    Convert custom URI scheme to real playable URI.

change_track

change_track(track: Track) -> bool

Switch to provided track.

MAY be reimplemented by subclass.

It is unlikely it makes sense for any backends to override this. For most practical purposes it should be considered an internal call between backends and core that backend authors should not touch.

The default implementation will call translate_uri, which is what you want to implement.

Parameters:

  • track
    (Track) –

    The track to play.

get_time_position

get_time_position() -> DurationMs

Get the current time position in milliseconds.

MAY be reimplemented by subclass.

is_live

is_live(uri: Uri) -> bool

Decide if the URI should be treated as a live stream or not.

MAY be reimplemented by subclass.

Playing a source as a live stream disables buffering, which reduces latency before playback starts, and discards data when paused.

on_source_setup

on_source_setup(source: Element) -> None

Called when a new GStreamer source is created, to allow configuration.

This runs in the audio thread so should not block.

MAY be reimplemented by subclass.

Parameters:

  • source
    (Element) –

    The GStreamer source element.

pause

pause() -> bool

Pause playback.

MAY be reimplemented by subclass.

Returns True if successful, else False.

play

play() -> bool

Start playback.

MAY be reimplemented by subclass.

Returns True if successful, else False.

prepare_change

prepare_change() -> None

Indicate that an URI change is about to happen.

MAY be reimplemented by subclass.

It is extremely unlikely it makes sense for any backends to override this. For most practical purposes it should be considered an internal call between backends and core that backend authors should not touch.

resume

resume() -> bool

Resume playback at the same time position playback was paused.

MAY be reimplemented by subclass.

Returns True if successful, else False.

seek

seek(time_position: DurationMs) -> bool

Seek to a given time position.

MAY be reimplemented by subclass.

Returns True if successful, else False.

should_download

should_download(uri: Uri) -> bool

Attempt progressive download buffering for the URI or not.

MAY be reimplemented by subclass.

When streaming a fixed length file, the entire file can be buffered to improve playback performance.

stop

stop() -> bool

Stop playback.

MAY be reimplemented by subclass.

Should not be used for tracking if tracks have been played or when we are done playing them.

Returns True if successful, else False.

translate_uri

translate_uri(uri: Uri) -> Uri | None

Convert custom URI scheme to real playable URI.

MAY be reimplemented by subclass.

This is very likely the only thing you need to override as a backend author. Typically this is where you convert any Mopidy-specific URI to a real URI and then return it. If you can't convert the URI just return None.

Parameters:

  • uri
    (Uri) –

    The URI to translate.

PlaylistsProvider

PlaylistsProvider(backend: Backend)

A playlist provider exposes a collection of playlists.

The methods can create/change/delete playlists in this collection, and look up any playlist the backend knows about.

Methods:

  • as_list

    Get a list of the currently available playlists.

  • create

    Create a new empty playlist with the given name.

  • delete

    Delete playlist identified by the URI.

  • get_items

    Get the items in a playlist specified by uri.

  • lookup

    Look up playlist with given URI.

  • refresh

    Refresh the playlists.

  • save

    Save the given playlist.

as_list

as_list() -> list[Ref]

Get a list of the currently available playlists.

Returns a list of Ref objects referring to the playlists. In other words, no information about the playlists' content is given.

create

create(name: str) -> Playlist | None

Create a new empty playlist with the given name.

Returns a new playlist with the given name and a URI, or None on failure.

MUST be implemented by subclass.

delete

delete(uri: Uri) -> bool

Delete playlist identified by the URI.

Returns True if deleted, False otherwise.

MUST be implemented by subclass.

get_items

get_items(uri: Uri) -> list[Ref] | None

Get the items in a playlist specified by uri.

Returns a list of Ref objects referring to the playlist's items, or None if the playlist doesn't exist.

lookup

lookup(uri: Uri) -> Playlist | None

Look up playlist with given URI.

Searches both the set of playlists and any other playlist sources. Returns the playlist or None if not found.

MUST be implemented by subclass.

refresh

refresh() -> None

Refresh the playlists.

MUST be implemented by subclass.

save

save(playlist: Playlist) -> Playlist | None

Save the given playlist.

The playlist must have a uri attribute set. To create a new playlist with a URI, use create.

Returns the saved playlist or None on failure.

MUST be implemented by subclass.