diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock
index 192af230c62d961efb68792671a137820998d8c8..7c769b63bc29f16b70b9fe28303e447aa6a50eb0 100644
--- a/src/rust/Cargo.lock
+++ b/src/rust/Cargo.lock
@@ -46,6 +46,15 @@ dependencies = [
  "version_check",
 ]
 
+[[package]]
+name = "aho-corasick"
+version = "0.7.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
+dependencies = [
+ "memchr",
+]
+
 [[package]]
 name = "amadeus"
 version = "0.1.0"
@@ -125,6 +134,78 @@ dependencies = [
  "libloading",
 ]
 
+[[package]]
+name = "async-broadcast"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b19760fa2b7301cf235360ffd6d3558b1ed4249edd16d6cca8d690cee265b95"
+dependencies = [
+ "event-listener",
+ "futures-core",
+ "parking_lot 0.12.1",
+]
+
+[[package]]
+name = "async-executor"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "17adb73da160dfb475c183343c8cccd80721ea5a605d3eb57125f0a7b7a92d0b"
+dependencies = [
+ "async-lock",
+ "async-task",
+ "concurrent-queue",
+ "fastrand",
+ "futures-lite",
+ "slab",
+]
+
+[[package]]
+name = "async-io"
+version = "1.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8c374dda1ed3e7d8f0d9ba58715f924862c63eae6849c92d3a18e7fbde9e2794"
+dependencies = [
+ "async-lock",
+ "autocfg",
+ "concurrent-queue",
+ "futures-lite",
+ "libc",
+ "log",
+ "parking",
+ "polling",
+ "slab",
+ "socket2",
+ "waker-fn",
+ "windows-sys 0.42.0",
+]
+
+[[package]]
+name = "async-lock"
+version = "2.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685"
+dependencies = [
+ "event-listener",
+ "futures-lite",
+]
+
+[[package]]
+name = "async-recursion"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b015a331cc64ebd1774ba119538573603427eaace0a1950c423ab971f903796"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "async-task"
+version = "4.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524"
+
 [[package]]
 name = "async-trait"
 version = "0.1.64"
@@ -181,6 +262,15 @@ version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
 
+[[package]]
+name = "block-buffer"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e"
+dependencies = [
+ "generic-array",
+]
+
 [[package]]
 name = "bumpalo"
 version = "3.12.0"
@@ -395,6 +485,15 @@ dependencies = [
  "toml 0.7.1",
 ]
 
+[[package]]
+name = "concurrent-queue"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c278839b831783b70278b14df4d45e1beb1aad306c07bb796637de9a0e323e8e"
+dependencies = [
+ "crossbeam-utils",
+]
+
 [[package]]
 name = "const_panic"
 version = "0.2.7"
@@ -454,6 +553,15 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "cpufeatures"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320"
+dependencies = [
+ "libc",
+]
+
 [[package]]
 name = "crc32fast"
 version = "1.3.2"
@@ -535,6 +643,16 @@ version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
 
+[[package]]
+name = "crypto-common"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
+dependencies = [
+ "generic-array",
+ "typenum",
+]
+
 [[package]]
 name = "cty"
 version = "0.2.2"
@@ -587,6 +705,17 @@ dependencies = [
  "syn",
 ]
 
+[[package]]
+name = "derivative"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "diesel"
 version = "2.0.3"
@@ -620,6 +749,36 @@ dependencies = [
  "migrations_macros",
 ]
 
+[[package]]
+name = "digest"
+version = "0.10.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
+dependencies = [
+ "block-buffer",
+ "crypto-common",
+]
+
+[[package]]
+name = "dirs"
+version = "4.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059"
+dependencies = [
+ "dirs-sys",
+]
+
+[[package]]
+name = "dirs-sys"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
+dependencies = [
+ "libc",
+ "redox_users",
+ "winapi",
+]
+
 [[package]]
 name = "dispatch"
 version = "0.2.0"
@@ -702,6 +861,27 @@ dependencies = [
  "cfg-if",
 ]
 
+[[package]]
+name = "enumflags2"
+version = "0.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e75d4cd21b95383444831539909fbb14b9dc3fdceb2a6f5d36577329a1f55ccb"
+dependencies = [
+ "enumflags2_derive",
+ "serde",
+]
+
+[[package]]
+name = "enumflags2_derive"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f58dc3c5e468259f19f2d46304a6b28f1c3d034442e14b322d2b850e36f6d5ae"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "errno"
 version = "0.2.8"
@@ -752,6 +932,12 @@ dependencies = [
  "num-traits",
 ]
 
+[[package]]
+name = "event-listener"
+version = "2.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
+
 [[package]]
 name = "expat-sys"
 version = "2.1.6"
@@ -777,6 +963,15 @@ dependencies = [
  "threadpool",
 ]
 
+[[package]]
+name = "fastrand"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499"
+dependencies = [
+ "instant",
+]
+
 [[package]]
 name = "find-crate"
 version = "0.6.3"
@@ -937,6 +1132,21 @@ version = "0.3.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531"
 
+[[package]]
+name = "futures-lite"
+version = "1.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48"
+dependencies = [
+ "fastrand",
+ "futures-core",
+ "futures-io",
+ "memchr",
+ "parking",
+ "pin-project-lite",
+ "waker-fn",
+]
+
 [[package]]
 name = "futures-macro"
 version = "0.3.26"
@@ -987,6 +1197,16 @@ dependencies = [
  "byteorder",
 ]
 
+[[package]]
+name = "generic-array"
+version = "0.14.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"
+dependencies = [
+ "typenum",
+ "version_check",
+]
+
 [[package]]
 name = "gethostname"
 version = "0.2.3"
@@ -1210,6 +1430,12 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "hex"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
+
 [[package]]
 name = "hexf-parse"
 version = "0.2.1"
@@ -1817,6 +2043,18 @@ dependencies = [
  "windows-sys 0.42.0",
 ]
 
+[[package]]
+name = "mpris"
+version = "0.1.0"
+dependencies = [
+ "commons",
+ "getset",
+ "hashbrown 0.13.2",
+ "serde",
+ "smallstring",
+ "zbus",
+]
+
 [[package]]
 name = "mutate_once"
 version = "0.1.1"
@@ -1946,6 +2184,7 @@ dependencies = [
  "cfg-if",
  "libc",
  "memoffset 0.6.5",
+ "pin-utils",
 ]
 
 [[package]]
@@ -2088,6 +2327,16 @@ dependencies = [
  "num-traits",
 ]
 
+[[package]]
+name = "ordered-stream"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "360a24bdacdb7801a1a6af8500392864791c130ebe8bd9a063158cab00040c90"
+dependencies = [
+ "futures-core",
+ "pin-project-lite",
+]
+
 [[package]]
 name = "os_str_bytes"
 version = "6.4.1"
@@ -2127,6 +2376,12 @@ dependencies = [
  "syn",
 ]
 
+[[package]]
+name = "parking"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72"
+
 [[package]]
 name = "parking_lot"
 version = "0.11.2"
@@ -2273,6 +2528,20 @@ dependencies = [
  "miniz_oxide",
 ]
 
+[[package]]
+name = "polling"
+version = "2.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22122d5ec4f9fe1b3916419b76be1e80bcb93f618d071d2edf841b137b2a2bd6"
+dependencies = [
+ "autocfg",
+ "cfg-if",
+ "libc",
+ "log",
+ "wepoll-ffi",
+ "windows-sys 0.42.0",
+]
+
 [[package]]
 name = "ppv-lite86"
 version = "0.2.17"
@@ -2432,6 +2701,43 @@ dependencies = [
  "bitflags",
 ]
 
+[[package]]
+name = "redox_users"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
+dependencies = [
+ "getrandom",
+ "redox_syscall",
+ "thiserror",
+]
+
+[[package]]
+name = "regex"
+version = "1.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
+
+[[package]]
+name = "remove_dir_all"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
+dependencies = [
+ "winapi",
+]
+
 [[package]]
 name = "renderdoc-sys"
 version = "0.7.1"
@@ -2680,6 +2986,17 @@ dependencies = [
  "serde",
 ]
 
+[[package]]
+name = "serde_repr"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a5ec9fa74a20ebbe5d9ac23dac1fc96ba0ecfe9f50f2843b52e537b10fbcb4e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "serde_spanned"
 version = "0.6.1"
@@ -2722,6 +3039,17 @@ dependencies = [
  "pkg-config",
 ]
 
+[[package]]
+name = "sha1"
+version = "0.10.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest",
+]
+
 [[package]]
 name = "siphasher"
 version = "0.3.10"
@@ -2862,6 +3190,20 @@ dependencies = [
  "unicode-ident",
 ]
 
+[[package]]
+name = "tempfile"
+version = "3.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
+dependencies = [
+ "cfg-if",
+ "fastrand",
+ "libc",
+ "redox_syscall",
+ "remove_dir_all",
+ "winapi",
+]
+
 [[package]]
 name = "termcolor"
 version = "1.2.0"
@@ -3090,9 +3432,21 @@ checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
 dependencies = [
  "cfg-if",
  "pin-project-lite",
+ "tracing-attributes",
  "tracing-core",
 ]
 
+[[package]]
+name = "tracing-attributes"
+version = "0.1.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "tracing-core"
 version = "0.1.30"
@@ -3125,6 +3479,22 @@ dependencies = [
  "static_assertions",
 ]
 
+[[package]]
+name = "typenum"
+version = "1.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
+
+[[package]]
+name = "uds_windows"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce65604324d3cce9b966701489fbd0cf318cb1f7bd9dd07ac9a4ee6fb791930d"
+dependencies = [
+ "tempfile",
+ "winapi",
+]
+
 [[package]]
 name = "unicode-bidi"
 version = "0.3.10"
@@ -3199,6 +3569,12 @@ version = "0.9.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
 
+[[package]]
+name = "waker-fn"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca"
+
 [[package]]
 name = "want"
 version = "0.3.0"
@@ -3404,6 +3780,15 @@ version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb"
 
+[[package]]
+name = "wepoll-ffi"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb"
+dependencies = [
+ "cc",
+]
+
 [[package]]
 name = "wgpu"
 version = "0.14.2"
@@ -3782,3 +4167,91 @@ name = "xml-rs"
 version = "0.8.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3"
+
+[[package]]
+name = "zbus"
+version = "3.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23eaeb1859a3cd5c5f780b101dfe626bf250a5f34873c3c0226d6d9f7a4d107c"
+dependencies = [
+ "async-broadcast",
+ "async-executor",
+ "async-io",
+ "async-lock",
+ "async-recursion",
+ "async-task",
+ "async-trait",
+ "byteorder",
+ "derivative",
+ "dirs",
+ "enumflags2",
+ "event-listener",
+ "futures-core",
+ "futures-sink",
+ "futures-util",
+ "hex",
+ "nix 0.25.1",
+ "once_cell",
+ "ordered-stream",
+ "rand",
+ "serde",
+ "serde_repr",
+ "sha1",
+ "static_assertions",
+ "tracing",
+ "uds_windows",
+ "winapi",
+ "zbus_macros",
+ "zbus_names",
+ "zvariant",
+]
+
+[[package]]
+name = "zbus_macros"
+version = "3.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e83c1c6d669caa4773ebe8cb2ebea2a8d0c6ea27fc6c5c8916c7308cbf1db3b1"
+dependencies = [
+ "proc-macro-crate",
+ "proc-macro2",
+ "quote",
+ "regex",
+ "syn",
+]
+
+[[package]]
+name = "zbus_names"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f34f314916bd89bdb9934154627fab152f4f28acdda03e7c4c68181b214fe7e3"
+dependencies = [
+ "serde",
+ "static_assertions",
+ "zvariant",
+]
+
+[[package]]
+name = "zvariant"
+version = "3.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "576cc41e65c7f283e5460f5818073e68fb1f1631502b969ef228c2e03c862efb"
+dependencies = [
+ "byteorder",
+ "enumflags2",
+ "libc",
+ "serde",
+ "static_assertions",
+ "zvariant_derive",
+]
+
+[[package]]
+name = "zvariant_derive"
+version = "3.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fd4aafc0dee96ae7242a24249ce9babf21e1562822f03df650d4e68c20e41ed"
+dependencies = [
+ "proc-macro-crate",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml
index 1bab32ff0ea30992aff0fe37ffd4a9d7deee0f4c..41cd93d93214cddc52d96397a989548c93aeaae5 100644
--- a/src/rust/Cargo.toml
+++ b/src/rust/Cargo.toml
@@ -13,6 +13,7 @@ members = [
     "commons",
     "getset",
     "smallstring",
+    "mpris",
 
     # Clients
     "amadeus",
@@ -30,8 +31,11 @@ license = "MIT"
 libc = "0.2"
 lazy_static = "^1"
 thiserror = "^1"
-async-trait = "^0.1"
 
+# DBus interactions
+zbus = { version = "^3" }
+
+# Data Structures
 hashbrown = { version = "^0.13", features = ["serde"] }
 smallvec = { version = "^1", default-features = false, features = [
     "serde",
@@ -41,6 +45,7 @@ smallvec = { version = "^1", default-features = false, features = [
     "const_new",
 ] }
 
+# Serialization & Deserialization
 serde_json = { version = "^1", default-features = false, features = [
     "std",
     "preserve_order",
@@ -50,7 +55,14 @@ serde = { version = "^1", default-features = false, features = [
     "std",
     "derive",
 ] }
+reqwest = { version = "0.11", default-features = false, features = [
+    "rustls-tls",
+    "rustls-tls-native-roots",
+    "json",
+] }
 
+# Async stuff
+async-trait = "^0.1"
 tokio = { version = "1", features = [
     "rt",
     "rt-multi-thread",
@@ -61,12 +73,7 @@ tokio = { version = "1", features = [
     "io-util",
 ] }
 
-reqwest = { version = "0.11", default-features = false, features = [
-    "rustls-tls",
-    "rustls-tls-native-roots",
-    "json",
-] }
-
+# Arguments
 clap = { version = "^4", default-features = false, features = [
     "usage",
     "help",
@@ -77,6 +84,7 @@ clap = { version = "^4", default-features = false, features = [
     "derive",
 ] }
 
+# GUI
 iced = { version = "0.7", features = ["image", "tokio"] }
 
 [profile.release]
diff --git a/src/rust/mpris/Cargo.toml b/src/rust/mpris/Cargo.toml
new file mode 100644
index 0000000000000000000000000000000000000000..9701120a9c15b54cdeef3bc06948e3b84e398e90
--- /dev/null
+++ b/src/rust/mpris/Cargo.toml
@@ -0,0 +1,18 @@
+[package]
+name = "mpris"
+version.workspace = true
+edition.workspace = true
+authors.workspace = true
+license.workspace = true
+
+[lib]
+doctest = false
+
+[dependencies]
+hashbrown.workspace = true
+serde.workspace = true
+zbus.workspace = true
+
+smallstring = { path = "../smallstring" }
+commons = { path = "../commons" }
+getset = { path = "../getset" }
diff --git a/src/rust/mpris/src/lib.rs b/src/rust/mpris/src/lib.rs
new file mode 100644
index 0000000000000000000000000000000000000000..d28c42369f2242ca0e4243259e9cf249c369b5d6
--- /dev/null
+++ b/src/rust/mpris/src/lib.rs
@@ -0,0 +1,2 @@
+pub mod traits;
+pub mod types;
diff --git a/src/rust/mpris/src/traits.rs b/src/rust/mpris/src/traits.rs
new file mode 100644
index 0000000000000000000000000000000000000000..e964c95393727d50d820e5dcb0ee3124d04110ef
--- /dev/null
+++ b/src/rust/mpris/src/traits.rs
@@ -0,0 +1,166 @@
+//! # 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
new file mode 100644
index 0000000000000000000000000000000000000000..9d0067e44468427f5d594b923c9c6fae0fb1b6db
--- /dev/null
+++ b/src/rust/mpris/src/types.rs
@@ -0,0 +1,113 @@
+use serde::{Deserialize, Serialize};
+use zbus::zvariant::{
+    ObjectPath as ZObjectPath, OwnedValue as ZOwnedValue, Signature as ZSignature, Type as ZType,
+};
+
+/// The loop status.
+#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
+pub enum MediaPlayerLoopStatus {
+    None,
+    Track,
+    Playlist,
+}
+
+/// The playback status.
+#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
+pub enum MediaPlayerPlaybackStatus {
+    Playing,
+    Paused,
+    Stopped,
+}
+
+/// Force the time to be in µs.
+#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
+#[serde(transparent)]
+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)]
+pub enum MediaPlayerObjectPath {
+    /// Not an object, or nothing.
+    #[default]
+    None,
+
+    /// An id.
+    Id(i64),
+}
+
+// Implementations
+
+impl From<i64> for TimeMicroSec {
+    fn from(value: i64) -> Self {
+        Self(value)
+    }
+}
+
+impl From<ZOwnedValue> for TimeMicroSec {
+    fn from(value: ZOwnedValue) -> Self {
+        let value: i64 = value.try_into().unwrap_or_default();
+        Self(value)
+    }
+}
+
+impl From<ZOwnedValue> for MediaPlayerLoopStatus {
+    fn from(value: ZOwnedValue) -> Self {
+        let value: String = value.try_into().unwrap_or_default();
+        match &value[..] {
+            "None" => Self::None,
+            "Track" => Self::Track,
+            "Playlist" => Self::Playlist,
+            _ => Self::None,
+        }
+    }
+}
+
+impl From<ZOwnedValue> for MediaPlayerPlaybackStatus {
+    fn from(value: ZOwnedValue) -> Self {
+        let value: String = value.try_into().unwrap_or_default();
+        match &value[..] {
+            "Paused" => Self::Paused,
+            "Playing" => Self::Playing,
+            "Stopped" => Self::Stopped,
+            _ => Self::Stopped,
+        }
+    }
+}
+
+impl<'a> From<ZOwnedValue> for MediaPlayerObjectPath {
+    fn from(value: ZOwnedValue) -> Self {
+        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(),
+            _ => 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")
+    }
+}