diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock
index 7c769b63bc29f16b70b9fe28303e447aa6a50eb0..b16e87cffbf60211823ad6b863e5e536bdcda04a 100644
--- a/src/rust/Cargo.lock
+++ b/src/rust/Cargo.lock
@@ -3318,6 +3318,7 @@ dependencies = [
  "pin-project-lite",
  "socket2",
  "tokio-macros",
+ "tracing",
  "windows-sys 0.42.0",
 ]
 
@@ -4190,6 +4191,7 @@ dependencies = [
  "futures-sink",
  "futures-util",
  "hex",
+ "lazy_static",
  "nix 0.25.1",
  "once_cell",
  "ordered-stream",
@@ -4198,6 +4200,7 @@ dependencies = [
  "serde_repr",
  "sha1",
  "static_assertions",
+ "tokio",
  "tracing",
  "uds_windows",
  "winapi",
diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml
index 41cd93d93214cddc52d96397a989548c93aeaae5..b3e941283ed509941489cedff45742651dae107c 100644
--- a/src/rust/Cargo.toml
+++ b/src/rust/Cargo.toml
@@ -33,7 +33,10 @@ lazy_static = "^1"
 thiserror = "^1"
 
 # DBus interactions
-zbus = { version = "^3" }
+zbus = { version = "^3", default-features = false, features = [
+    "tokio",
+    "async-io",
+] }
 
 # Data Structures
 hashbrown = { version = "^0.13", features = ["serde"] }
diff --git a/src/rust/mpris/src/lib.rs b/src/rust/mpris/src/lib.rs
index d28c42369f2242ca0e4243259e9cf249c369b5d6..e728031c4d2f100f9c09dee0da006b0a47714aee 100644
--- a/src/rust/mpris/src/lib.rs
+++ b/src/rust/mpris/src/lib.rs
@@ -1,2 +1,2 @@
-pub mod traits;
+pub mod server;
 pub mod types;
diff --git a/src/rust/mpris/src/server.rs b/src/rust/mpris/src/server.rs
new file mode 100644
index 0000000000000000000000000000000000000000..993d31ca74d9caf7d7da0f5679bcf66582c30901
--- /dev/null
+++ b/src/rust/mpris/src/server.rs
@@ -0,0 +1,184 @@
+//! # DBus interface for: `org.mpris.MediaPlayer2`, `org.mpris.MediaPlayer2.Player`
+
+// use crate::types::*;
+use zbus::dbus_interface;
+
+pub struct MediaPlayer2 {
+    identity: String,
+}
+
+#[dbus_interface(name = "org.mpris.MediaPlayer2")]
+impl MediaPlayer2 {
+    /// Quit method
+    fn quit(&self) {}
+
+    /// Raise method
+    fn raise(&self) {}
+
+    /// CanQuit property
+    #[dbus_interface(property, name = "CanQuit")]
+    fn can_quit(&self) -> bool {
+        false
+    }
+
+    /// CanRaise property
+    #[dbus_interface(property, name = "CanRaise")]
+    fn can_raise(&self) -> bool {
+        false
+    }
+
+    /// CanSetFullscreen property
+    #[dbus_interface(property, name = "CanSetFullscreen")]
+    fn can_set_fullscreen(&self) -> bool {
+        false
+    }
+
+    /// DesktopEntry property
+    #[dbus_interface(property, name = "DesktopEntry")]
+    fn desktop_entry(&self) -> String {
+        todo!()
+    }
+
+    /// Fullscreen property
+    #[dbus_interface(property, name = "Fullscreen")]
+    fn fullscreen(&self) -> bool {
+        false
+    }
+    #[dbus_interface(property, name = "Fullscreen")]
+    fn set_fullscreen(&mut self, _value: bool) {}
+
+    /// HasTrackList property
+    #[dbus_interface(property, name = "HasTrackList")]
+    fn has_track_list(&self) -> bool {
+        false
+    }
+
+    /// Identity property
+    #[dbus_interface(property, name = "Identity")]
+    fn identity(&self) -> String {
+        self.identity.clone()
+    }
+
+    /// SupportedMimeTypes property
+    #[dbus_interface(property, name = "SupportedMimeTypes")]
+    fn supported_mime_types(&self) -> Vec<String> {
+        todo!()
+    }
+
+    /// SupportedUriSchemes property. It should be `id://` and `file://` for
+    /// lektord. Here we support `file://` for only files in the database to
+    /// enable the user to search the kara folder and drop the files to play
+    /// them imediatly.
+    #[dbus_interface(property, name = "SupportedUriSchemes")]
+    fn supported_uri_schemes(&self) -> Vec<String> {
+        vec![String::from("id://"), String::from("file://")]
+    }
+}
+
+// #[dbus_interface(
+//     interface = "org.mpris.MediaPlayer2.Player",
+//     default_path = "/org/mpris/MediaPlayer2",
+//     assume_defaults = true
+// )]
+// trait Player {
+//     /// Next method
+//     fn next(&self) -> zbus::Result<()>;
+//
+//     /// OpenUri method
+//     fn open_uri(&self, id_uri: &str) -> zbus::Result<()>;
+//
+//     /// Pause method
+//     fn pause(&self) -> zbus::Result<()>;
+//
+//     /// Play method
+//     fn play(&self) -> zbus::Result<()>;
+//
+//     /// PlayPause method
+//     fn play_pause(&self) -> zbus::Result<()>;
+//
+//     /// Previous method
+//     fn previous(&self) -> zbus::Result<()>;
+//
+//     /// Seek method
+//     fn seek(&self, time: TimeMicroSec) -> zbus::Result<()>;
+//
+//     /// SetPosition method
+//     fn set_position(
+//         &self,
+//         track_id: &MediaPlayerObjectPath,
+//         time: TimeMicroSec,
+//     ) -> zbus::Result<()>;
+//
+//     /// Stop method
+//     fn stop(&self) -> zbus::Result<()>;
+//
+//     /// CanControl property
+//     #[dbus_interface(property)]
+//     fn can_control(&self) -> zbus::Result<bool>;
+//
+//     /// CanPause property
+//     #[dbus_interface(property)]
+//     fn can_pause(&self) -> zbus::Result<bool>;
+//
+//     /// CanPlay property
+//     #[dbus_interface(property)]
+//     fn can_play(&self) -> zbus::Result<bool>;
+//
+//     /// CanSeek property
+//     #[dbus_interface(property)]
+//     fn can_seek(&self) -> zbus::Result<bool>;
+//
+//     /// LoopStatus property
+//     #[dbus_interface(property)]
+//     fn loop_status(&self) -> zbus::Result<MediaPlayerObjectPath>;
+//     fn set_loop_status(&self, value: &MediaPlayerObjectPath) -> zbus::Result<()>;
+//
+//     /// MaximumRate property. We will only set it to `1.0` here...
+//     #[dbus_interface(property)]
+//     fn maximum_rate(&self) -> zbus::Result<f64> {
+//         Ok(1.0)
+//     }
+//     fn set_maximum_rate(&self, _: f64) -> zbus::Result<()> {
+//         Ok(())
+//     }
+//
+//     /// Metadata property. If there is a current kara playing, there must be at
+//     /// least a `mpris:trackid` value of type `o` which is the object path of
+//     /// the current kara id.
+//     #[dbus_interface(property)]
+//     fn metadata(
+//         &self,
+//     ) -> zbus::Result<std::collections::HashMap<String, zbus::zvariant::OwnedValue>>;
+//
+//     /// MinimumRate property. We will only set it to `1.0` here...
+//     #[dbus_interface(property)]
+//     fn minimum_rate(&self) -> zbus::Result<f64> {
+//         Ok(1.0)
+//     }
+//     fn set_minimum_rate(&self, _: f64) -> zbus::Result<()> {
+//         Ok(())
+//     }
+//
+//     /// PlaybackStatus property
+//     #[dbus_interface(property)]
+//     fn playback_status(&self) -> zbus::Result<MediaPlayerPlaybackStatus>;
+//
+//     /// Position property
+//     #[dbus_interface(property)]
+//     fn position(&self) -> zbus::Result<TimeMicroSec>;
+//
+//     /// Rate property
+//     #[dbus_interface(property)]
+//     fn rate(&self) -> zbus::Result<f64>;
+//     fn set_rate(&self, value: f64) -> zbus::Result<()>;
+//
+//     /// Shuffle property
+//     #[dbus_interface(property)]
+//     fn shuffle(&self) -> zbus::Result<bool>;
+//     fn set_shuffle(&self, value: bool) -> zbus::Result<()>;
+//
+//     /// Volume property
+//     #[dbus_interface(property)]
+//     fn volume(&self) -> zbus::Result<f64>;
+//     fn set_volume(&self, value: f64) -> zbus::Result<()>;
+// }
diff --git a/src/rust/mpris/src/traits.rs b/src/rust/mpris/src/traits.rs
deleted file mode 100644
index e964c95393727d50d820e5dcb0ee3124d04110ef..0000000000000000000000000000000000000000
--- a/src/rust/mpris/src/traits.rs
+++ /dev/null
@@ -1,166 +0,0 @@
-//! # DBus interface proxies for: `org.mpris.MediaPlayer2`, `org.mpris.MediaPlayer2.Player`
-//!
-//! This code was generated by `zbus-xmlgen` `3.1.0` from DBus introspection data.
-//! Source: `mpris.xml`.
-//!
-//! You may prefer to adapt it, instead of using it verbatim.
-//!
-//! More information can be found in the
-//! [Writing a client proxy](https://dbus.pages.freedesktop.org/zbus/client.html)
-//! section of the zbus documentation.
-
-use crate::types::*;
-use zbus::dbus_proxy;
-
-#[dbus_proxy(interface = "org.mpris.MediaPlayer2", assume_defaults = true)]
-trait MediaPlayer2 {
-    /// Quit method
-    fn quit(&self) -> zbus::Result<()>;
-
-    /// Raise method
-    fn raise(&self) -> zbus::Result<()>;
-
-    /// CanQuit property
-    #[dbus_proxy(property)]
-    fn can_quit(&self) -> zbus::Result<bool>;
-
-    /// CanRaise property
-    #[dbus_proxy(property)]
-    fn can_raise(&self) -> zbus::Result<bool>;
-
-    /// CanSetFullscreen property
-    #[dbus_proxy(property)]
-    fn can_set_fullscreen(&self) -> zbus::Result<bool>;
-
-    /// DesktopEntry property
-    #[dbus_proxy(property)]
-    fn desktop_entry(&self) -> zbus::Result<String>;
-
-    /// Fullscreen property
-    #[dbus_proxy(property)]
-    fn fullscreen(&self) -> zbus::Result<bool>;
-    fn set_fullscreen(&self, value: bool) -> zbus::Result<()>;
-
-    /// HasTrackList property
-    #[dbus_proxy(property)]
-    fn has_track_list(&self) -> zbus::Result<bool>;
-
-    /// Identity property
-    #[dbus_proxy(property)]
-    fn identity(&self) -> zbus::Result<String>;
-
-    /// SupportedMimeTypes property
-    #[dbus_proxy(property)]
-    fn supported_mime_types(&self) -> zbus::Result<Vec<String>>;
-
-    /// SupportedUriSchemes property. It should be `id://` and `file://` for
-    /// lektord. Here we support `file://` for only files in the database to
-    /// enable the user to search the kara folder and drop the files to play
-    /// them imediatly.
-    #[dbus_proxy(property)]
-    fn supported_uri_schemes(&self) -> zbus::Result<Vec<String>>;
-}
-
-#[dbus_proxy(interface = "org.mpris.MediaPlayer2.Player", assume_defaults = true)]
-trait Player {
-    /// Next method
-    fn next(&self) -> zbus::Result<()>;
-
-    /// OpenUri method
-    fn open_uri(&self, id_uri: &str) -> zbus::Result<()>;
-
-    /// Pause method
-    fn pause(&self) -> zbus::Result<()>;
-
-    /// Play method
-    fn play(&self) -> zbus::Result<()>;
-
-    /// PlayPause method
-    fn play_pause(&self) -> zbus::Result<()>;
-
-    /// Previous method
-    fn previous(&self) -> zbus::Result<()>;
-
-    /// Seek method
-    fn seek(&self, time: TimeMicroSec) -> zbus::Result<()>;
-
-    /// SetPosition method
-    fn set_position(
-        &self,
-        track_id: &MediaPlayerObjectPath,
-        time: TimeMicroSec,
-    ) -> zbus::Result<()>;
-
-    /// Stop method
-    fn stop(&self) -> zbus::Result<()>;
-
-    /// CanControl property
-    #[dbus_proxy(property)]
-    fn can_control(&self) -> zbus::Result<bool>;
-
-    /// CanPause property
-    #[dbus_proxy(property)]
-    fn can_pause(&self) -> zbus::Result<bool>;
-
-    /// CanPlay property
-    #[dbus_proxy(property)]
-    fn can_play(&self) -> zbus::Result<bool>;
-
-    /// CanSeek property
-    #[dbus_proxy(property)]
-    fn can_seek(&self) -> zbus::Result<bool>;
-
-    /// LoopStatus property
-    #[dbus_proxy(property)]
-    fn loop_status(&self) -> zbus::Result<MediaPlayerObjectPath>;
-    fn set_loop_status(&self, value: &MediaPlayerObjectPath) -> zbus::Result<()>;
-
-    /// MaximumRate property. We will only set it to `1.0` here...
-    #[dbus_proxy(property)]
-    fn maximum_rate(&self) -> zbus::Result<f64> {
-        Ok(1.0)
-    }
-    fn set_maximum_rate(&self, _: f64) -> zbus::Result<()> {
-        Ok(())
-    }
-
-    /// Metadata property. If there is a current kara playing, there must be at
-    /// least a `mpris:trackid` value of type `o` which is the object path of
-    /// the current kara id.
-    #[dbus_proxy(property)]
-    fn metadata(
-        &self,
-    ) -> zbus::Result<std::collections::HashMap<String, zbus::zvariant::OwnedValue>>;
-
-    /// MinimumRate property. We will only set it to `1.0` here...
-    #[dbus_proxy(property)]
-    fn minimum_rate(&self) -> zbus::Result<f64> {
-        Ok(1.0)
-    }
-    fn set_minimum_rate(&self, _: f64) -> zbus::Result<()> {
-        Ok(())
-    }
-
-    /// PlaybackStatus property
-    #[dbus_proxy(property)]
-    fn playback_status(&self) -> zbus::Result<MediaPlayerPlaybackStatus>;
-
-    /// Position property
-    #[dbus_proxy(property)]
-    fn position(&self) -> zbus::Result<TimeMicroSec>;
-
-    /// Rate property
-    #[dbus_proxy(property)]
-    fn rate(&self) -> zbus::Result<f64>;
-    fn set_rate(&self, value: f64) -> zbus::Result<()>;
-
-    /// Shuffle property
-    #[dbus_proxy(property)]
-    fn shuffle(&self) -> zbus::Result<bool>;
-    fn set_shuffle(&self, value: bool) -> zbus::Result<()>;
-
-    /// Volume property
-    #[dbus_proxy(property)]
-    fn volume(&self) -> zbus::Result<f64>;
-    fn set_volume(&self, value: f64) -> zbus::Result<()>;
-}
diff --git a/src/rust/mpris/src/types.rs b/src/rust/mpris/src/types.rs
index 9d0067e44468427f5d594b923c9c6fae0fb1b6db..07af4a2bff2d05ee867c000f43f7f7b898af73f7 100644
--- a/src/rust/mpris/src/types.rs
+++ b/src/rust/mpris/src/types.rs
@@ -1,10 +1,9 @@
 use serde::{Deserialize, Serialize};
-use zbus::zvariant::{
-    ObjectPath as ZObjectPath, OwnedValue as ZOwnedValue, Signature as ZSignature, Type as ZType,
-};
+use zbus::zvariant::{ObjectPath as ZObjectPath, OwnedValue as ZOwnedValue, Type as ZType};
 
 /// The loop status.
-#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Deserialize, Serialize, ZType, Clone, Copy, PartialEq, Eq)]
+#[zvariant(signature = "s")]
 pub enum MediaPlayerLoopStatus {
     None,
     Track,
@@ -12,7 +11,8 @@ pub enum MediaPlayerLoopStatus {
 }
 
 /// The playback status.
-#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Serialize, Deserialize, ZType, Clone, Copy, PartialEq, Eq)]
+#[zvariant(signature = "s")]
 pub enum MediaPlayerPlaybackStatus {
     Playing,
     Paused,
@@ -20,20 +20,27 @@ pub enum MediaPlayerPlaybackStatus {
 }
 
 /// Force the time to be in µs.
-#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Serialize, Deserialize, ZType, Clone, Copy, PartialEq, Eq)]
 #[serde(transparent)]
+#[zvariant(signature = "x")]
 pub struct TimeMicroSec(i64);
 
-/// A valid path must be prefiexed by `/baka/lektor/`. After that we have the
-/// variant name in lower case, then a `/`, then the ascii only value. For
-/// example we can have:
-///     - `/baka/lektor/id/42`
-#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Default)]
+/// A valid path must be prefiexed by `/org/mpris/MediaPlayer2`. After that we
+/// have the variant name, then a `/`, then the ascii only value. For example
+/// we can have:
+///     - `/org/mpris/MediaPlayer2/Id/42`
+///     - `/org/mpris/MediaPlayer2/None`
+///     - `/org/mpris/MediaPlayer2/TrackList/NoTrack` is a special case...
+#[derive(Debug, Serialize, Deserialize, ZType, Clone, Copy, PartialEq, Eq, Default)]
+#[zvariant(signature = "o")]
 pub enum MediaPlayerObjectPath {
     /// Not an object, or nothing.
     #[default]
     None,
 
+    /// There is no track.
+    NoTrack,
+
     /// An id.
     Id(i64),
 }
@@ -82,32 +89,12 @@ impl<'a> From<ZOwnedValue> for MediaPlayerObjectPath {
         let value: ZObjectPath = value.try_into().unwrap_or_default();
         let value = value.trim_start_matches('/');
         match value.split('/').collect::<Vec<_>>()[..] {
-            ["baka", "lektor", "id", id] => id.parse::<i64>().map(Self::Id).unwrap_or_default(),
+            ["org", "mpris", "MediaPlayer2", "TrackList", "NoTrack"] => Self::NoTrack,
+            ["org", "mpris", "MediaPlayer2", "None"] => Self::None,
+            ["org", "mpris", "MediaPlayer2", "Id", id] => {
+                id.parse::<i64>().map(Self::Id).unwrap_or_default()
+            }
             _ => Default::default(),
         }
     }
 }
-
-impl ZType for MediaPlayerObjectPath {
-    fn signature() -> ZSignature<'static> {
-        ZSignature::try_from("o").expect("invalid signature")
-    }
-}
-
-impl ZType for MediaPlayerLoopStatus {
-    fn signature() -> ZSignature<'static> {
-        ZSignature::try_from("s").expect("invalid signature")
-    }
-}
-
-impl ZType for MediaPlayerPlaybackStatus {
-    fn signature() -> ZSignature<'static> {
-        ZSignature::try_from("s").expect("invalid signature")
-    }
-}
-
-impl ZType for TimeMicroSec {
-    fn signature() -> ZSignature<'static> {
-        ZSignature::try_from("x").expect("invalid signature")
-    }
-}