mopidy.backend — Backend API — Mopidy 4.0.0a2 documentation

# `mopidy.backend` — 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 mopidy.core — 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’ `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 `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 class

class mopidy.backend.Backend

  Backend API.

  If the backend has problems during initialization it should raise `mopidy.exceptions.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 – the entire Mopidy configuration

    - audio – actor proxy for the audio subsystem

  audio: AudioProxy

    Actor proxy to an instance of `mopidy.audio.Audio`.

    Should be passed to the backend constructor as the kwarg `audio`, which will then set this field.

  library: LibraryProvider | None = None

    The library provider. An instance of `LibraryProvider`, or `None` if the backend doesn’t provide a library.

  ping() → bool

    Called to check if the actor is still alive.

    Return type:

      `bool`

  playback: PlaybackProvider | None = None

    The playback provider. An instance of `PlaybackProvider`, or `None` if the backend doesn’t provide playback.

  playlists: PlaylistsProvider | None = None

    The playlists provider. An instance of `PlaylistsProvider`, or class:None if the backend doesn’t provide playlists.

  uri_schemes: ClassVar[list[UriScheme]] = []

    List of URI schemes this backend can handle.

## Playback provider

class mopidy.backend.PlaybackProvider(audio, backend) → None

  A playback provider provides audio playback control.

  Parameters:

    - audio (`AudioProxy`) – the audio actor

    - backend (`Backend`) – the backend

  change_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

    Return type:

      `bool`

  get_time_position() → DurationMs

    Get the current time position in milliseconds.

    MAY be reimplemented by subclass.

    Return type:

      `NewType`(`DurationMs`, `int`)

  is_live(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.

    Parameters:

      uri (`NewType`(`Uri`, `str`)) – the URI

    Return type:

      `bool`

  on_source_setup(source) → None

    Called when a new GStreamer source is created, allowing us to configure the source. This runs in the audio thread so should not block.

    MAY be reimplemented by subclass.

    Parameters:

      source (`Element`) – the GStreamer source element

    Return type:

      `None`

    Added in version 3.4.

  pause() → bool

    Pause playback.

    MAY be reimplemented by subclass.

    Returns `True` if successful, else `False`.

    Return type:

      `bool`

  play() → bool

    Start playback.

    MAY be reimplemented by subclass.

    Returns `True` if successful, else `False`.

    Return type:

      `bool`

  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.

    Return type:

      `None`

  resume() → bool

    Resume playback at the same time position playback was paused.

    MAY be reimplemented by subclass.

    Returns `True` if successful, else `False`.

    Return type:

      `bool`

  seek(time_position) → bool

    Seek to a given time position.

    MAY be reimplemented by subclass.

    Returns `True` if successful, else `False`.

    Parameters:

      time_position (`NewType`(`DurationMs`, `int`)) – time position in milliseconds

    Return type:

      `bool`

  should_download(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.

    Parameters:

      uri (`NewType`(`Uri`, `str`)) – the URI

    Return type:

      `bool`

  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`.

    Return type:

      `bool`

  translate_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 (`NewType`(`Uri`, `str`)) – the URI to translate

    Return type:

      `NewType`(`Uri`, `str`) | `None`

## Playlists provider

class mopidy.backend.PlaylistsProvider(backend) → None

  A playlist provider exposes a collection of playlists.

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

  Parameters:

    backend (`Backend`) – backend the controller is a part of

  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.

    Added in version 1.0.

    Return type:

      `list`[`Ref`]

  create(name) → Playlist | None

    Create a new empty playlist with the given name.

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

    MUST be implemented by subclass.

    Parameters:

      name (`str`) – name of the new playlist

    Return type:

      `Playlist` | `None`

  delete(uri) → bool

    Delete playlist identified by the URI.

    Returns `True` if deleted, `False` otherwise.

    MUST be implemented by subclass.

    Parameters:

      uri (`NewType`(`Uri`, `str`)) – URI of the playlist to delete

    Return type:

      `bool`

    Changed in version 2.2: Return type defined.

  get_items(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.

    If a playlist with the given `uri` doesn’t exist, it returns `None`.

    Added in version 1.0.

    Return type:

      `list`[`Ref`] | `None`

  lookup(uri) → Playlist | None

    Lookup playlist with given URI in both the set of playlists and in any other playlist source.

    Returns the playlists or `None` if not found.

    MUST be implemented by subclass.

    Parameters:

      uri (`NewType`(`Uri`, `str`)) – playlist URI

    Return type:

      `Playlist` | `None`

  refresh() → None

    Refresh the playlists in `playlists`.

    MUST be implemented by subclass.

    Return type:

      `None`

  save(playlist) → Playlist | None

    Save the given playlist.

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

    Returns the saved playlist or `None` on failure.

    MUST be implemented by subclass.

    Parameters:

      playlist (`Playlist`) – the playlist to save

    Return type:

      `Playlist` | `None`

## Library provider

class mopidy.backend.LibraryProvider(backend) → None

  A library provider provides a library of music to Mopidy.

  Parameters:

    backend (`Backend`) – backend the controller is a part of

  browse(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.

    Return type:

      `list`[`Ref`]

  get_distinct(field, query=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.

    Return type:

      `set`[`str`]

  get_images(uris) → dict[Uri, list[Image]]

    See `mopidy.core.LibraryController.get_images()`.

    MAY be implemented by subclass.

    Default implementation will simply return an empty dictionary.

    Return type:

      `dict`[`NewType`(`Uri`, `str`), `list`[`Image`]]

  lookup(uri) → list[Track]

    See `mopidy.core.LibraryController.lookup()`.

    MUST be implemented by subclass if :meth:`lookup_many` is not implemented.

    Deprecated since version 4.0: Implement `lookup_many()` instead. If `lookup_many()` is implemented, Mopidy will never call this method on a backend.

    Return type:

      `list`[`Track`]

  lookup_many(uris) → dict[Uri, list[Track]]

    See `mopidy.core.LibraryController.lookup()`.

    MUST be implemented by subclass.

    Return type:

      `dict`[`NewType`(`Uri`, `str`), `list`[`Track`]]

  refresh(uri=None) → None

    See `mopidy.core.LibraryController.refresh()`.

    MAY be implemented by subclass.

    Return type:

      `None`

  root_directory: Ref | None = None

    `mopidy.models.Ref.directory` instance 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 `LibraryProvider.browse()`.

  search(query, uris=None, exact=False) → SearchResult | None

    See `mopidy.core.LibraryController.search()`.

    MAY be implemented by subclass.

    Added in version 1.0: The `exact` param which replaces the old `find_exact`.

    Return type:

      `SearchResult` | `None`

## Backend listener

class mopidy.backend.BackendListener

  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.

  playlists_loaded() → None

    Called when playlists are loaded or refreshed.

    MAY be implemented by actor.

    Return type:

      `None`

  static send(event, **kwargs) → None

    Helper to allow calling of backend listener events.

    Return type:

      `None`

## Backend implementations

See the extension registry.