#mpris #dbus


Implement MPRIS D-Bus interface in your application

8 unstable releases (3 breaking)

0.4.1 Sep 17, 2023
0.4.0 Sep 17, 2023
0.3.2 Sep 16, 2023
0.2.1 Sep 15, 2023
0.1.0 Sep 10, 2023

#134 in Unix APIs

Download history 33/week @ 2023-09-08 180/week @ 2023-09-15 26/week @ 2023-09-22

240 downloads per month

MPL-2.0 license

3.5K SLoC

MPRIS Server

github crates.io docs CI

Implement MPRIS D-Bus interface in your application.

This library provides the essential functionalities for implementing the MPRIS D-Bus interface on the service side. This enables your application to become discoverable and controllable by other MPRIS-compatible media controllers, including but not limited to GNOME Shell, KDE Plasma, and other libraries such as mpris.

This library supports all the following interfaces as defined in the specification:

To implement these interfaces, this crate offers two flavors: you can either create your own struct and implement RootInterface and PlayerInterface (or with optional TrackListInterface and PlaylistsInterface), or you can use the ready-to-use mutable Player struct.


For more detailed examples, see also the examples directory.

There is also a real-word example of this library being used in Mousai, a music recognizer application for Linux.

Manual Implementation (via Server or LocalServer)

It is recommended to manually create your own implementation of the interfaces if you want to have more control. You can do this by creating your own struct and implementing the required interfaces, then passing your struct as implementation in Server. You can also use LocalServer and the local version of the interfaces if your struct can't be sent and shared across threads.

use std::future;

use mpris_server::{
    zbus::{fdo, Result},
    Metadata, PlayerInterface, Property, RootInterface, Server, Signal, Time, Volume,

pub struct MyPlayer;

impl RootInterface for MyPlayer {
    async fn identity(&self) -> fdo::Result<String> {

    // Other methods...

impl PlayerInterface for MyPlayer {
    async fn set_volume(&self, volume: Volume) -> Result<()> {

    async fn metadata(&self) -> fdo::Result<Metadata> {
        let metadata = Metadata::builder()
            .title("My Song")
            .artist(["My Artist"])
            .album("My Album")

    // Other methods...

async fn main() -> Result<()> {
    let server = Server::new("com.my.Application", MyPlayer)?;

    // Initialize server's connection to the session bus

    // Emit `PropertiesChanged` signal for `CanSeek` and `Metadata` properties
    server.properties_changed(Property::CanSeek | Property::Metadata).await?;

    // Emit `Seeked` signal
        .emit(Signal::Seeked {
            position: Time::from_micros(124),

    // Prevent the program from exiting.


Ready-to-use Implementation (via Player)

If you want to create a simple player without having to implement the interfaces, you can use the ready-to-use Player struct that implements those interfaces internally. This struct is mutable, automatically emits properties changed signal, and allows you to connect to method and property setter calls.

However, Player currently only supports the more commonly used org.mpris.MediaPlayer2 and org.mpris.MediaPlayer2.Player interfaces.

use std::future;

use mpris_server::{zbus::Result, Player, Time};

async fn main() -> Result<()> {
    let player = Player::builder("com.my.Application")

    // Handle `PlayPause` method call
    player.connect_play_pause(|| {

    // Initialize connection and run event handler task
    let task = player.init_and_run();
    async_std::task::spawn_local(async move {

    // Update `CanPlay` property and emit `PropertiesChanged` signal for it

    // Emit `Seeked` signal

    // Prevent the program from exiting.



Copyright 2023 Dave Patrick Caberto

This software is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at this site.


~328K SLoC