Files
qbz/crates/qbz-slint/Cargo.toml
T
vicrodh 7a7e5f82c4 feat(slint): system media controls — MPRIS with GNOME app icon + SMTC/MediaRemote
New frontend-agnostic crate qbz-media-controls (ADR-006): one MediaIntegration
trait, cfg-split backends. Linux uses mpris-server and publishes the MPRIS
org.mpris.MediaPlayer2.DesktopEntry property as com.blitzfc.qbz — the only way
GNOME Shell resolves the app icon for its media widget (souvlaki, the old
cross-platform crate, never set it, so GNOME showed no icon; KDE is lenient).
macOS/Windows keep souvlaki (MediaRemote/SMTC), where the icon comes from the
app bundle, not a DesktopEntry. The Linux server runs on a dedicated thread
with its own tokio runtime; state arrives over an async channel.

Wired into qbz-slint via src/media_controls.rs: started on shell entry,
metadata/playback pushed from the playback paths (mirroring the tray), and
inbound control events (media keys, the desktop media widget, Now Playing)
dispatched to the player through the existing QConnect-aware helpers. Both
Linux and macOS compile clean.

cc
2026-06-06 11:03:11 -06:00

92 lines
3.5 KiB
TOML

[package]
name = "qbz-slint"
version.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true
description = "Slint functional MVP shell for QBZ (private branch only)"
[[bin]]
name = "qbz-slint"
path = "src/main.rs"
[dependencies]
# femtovg renderer, pinned >=1.16 for the femtovg text-rendering fixes
# (slint-ui/slint #5177 pixel-grid alignment + #11335 0.5px tearing /
# inconsistent glyph spacing). Skia never received that treatment.
slint = { version = "1.16", default-features = false, features = [
"std",
"backend-winit",
"renderer-femtovg",
"renderer-software",
"accessibility",
"compat-1-2",
] }
# Direct access to the winit backend for the system tray: WinitWindowAccessor
# (hide/show the OS window without quitting the event loop) and, later, the
# CustomApplicationHandler (tray event pump + close-to-tray intercept). MUST be
# pinned to the exact version Slint resolves (1.16.1) — i-slint-backend-winit
# does not follow semver, and a mismatch makes with_winit_window() return None.
i-slint-backend-winit = "=1.16.1"
log = { workspace = true }
env_logger = "0.11"
tokio = { workspace = true }
async-trait = { workspace = true }
reqwest = { workspace = true }
image = { version = "0.25", default-features = false, features = ["jpeg", "png"] }
urlencoding = "2"
open = "5"
arboard = "3"
rfd = { version = "0.15", default-features = false, features = ["xdg-portal", "tokio"] }
serde = { workspace = true }
serde_json = { workspace = true }
dirs = "5"
chrono = { workspace = true, features = ["unstable-locales"] }
qbz-app = { path = "../qbz-app" }
qbz-media-controls = { path = "../qbz-media-controls" }
qbz-audio = { path = "../qbz-audio" }
qbz-core = { path = "../qbz-core" }
qbz-player = { path = "../qbz-player" }
qconnect-app = { path = "../qconnect-app" }
qconnect-transport-ws = { path = "../qconnect-transport-ws" }
futures-util = { workspace = true }
uuid = { version = "1", features = ["v4"] }
qbz-library = { path = "../qbz-library" }
qbz-offline-cache = { path = "../qbz-offline-cache" }
qbz-models = { path = "../qbz-models" }
qbz-qobuz = { path = "../qbz-qobuz" }
qbz-integrations = { path = "../qbz-integrations" }
rusqlite = { version = "0.31", features = ["bundled"] }
qbz-cache = { path = "../qbz-cache" }
qbz-credentials = { path = "../qbz-credentials" }
# Linux system tray via StatusNotifierItem. Same crate + rationale as the
# Tauri build (src-tauri/Cargo.toml): libayatana-appindicator never dispatches
# primary-activate (left-click), so we use ksni's pure-Rust SNI which exposes
# Activate / SecondaryActivate / Scroll. macOS/Windows use `tray-icon` instead
# (added with the CustomApplicationHandler slice).
[target.'cfg(target_os = "linux")'.dependencies]
ksni = { version = "0.3", features = ["blocking"] }
# macOS (NSStatusItem) + Windows (Shell_NotifyIcon) tray via the tao team's
# tray-icon crate. Re-exports muda as tray_icon::menu. Windows is built but
# not shipped/tested.
[target.'cfg(any(target_os = "macos", target_os = "windows"))'.dependencies]
tray-icon = "0.24"
# macOS Dock-icon activation-policy toggle. Pinned to tray-icon's objc2 0.6 /
# app-kit 0.3 series (NOT winit's 0.5) so MainThreadMarker/NSApplication unify
# with tray-icon. setActivationPolicy is gated behind the NSRunningApplication
# feature.
[target.'cfg(target_os = "macos")'.dependencies]
objc2 = "0.6"
objc2-app-kit = { version = "0.3", default-features = false, features = [
"std",
"NSApplication",
"NSResponder",
"NSRunningApplication",
] }
[build-dependencies]
slint-build = "1.16"