From 73f524c95e79d8f636d279443d9d4d978207e71f Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 18 Jan 2025 08:47:47 -0700 Subject: [PATCH] Implement MPRIS and album art, fixes #57, fixes #59, part of #56 --- Cargo.lock | 29 +++- Cargo.toml | 8 +- src/main.rs | 225 ++++++++++++++++++++++++-- src/mpris.rs | 440 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 687 insertions(+), 15 deletions(-) create mode 100644 src/mpris.rs diff --git a/Cargo.lock b/Cargo.lock index 7da94a5..cc2301e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1075,12 +1075,15 @@ dependencies = [ "i18n-embed", "i18n-embed-fl", "iced_video_player", + "image", "lazy_static", "libcosmic", "log", + "mpris-server", "rust-embed", "serde", "smol_str", + "tempfile", "tokio", "url", ] @@ -2695,7 +2698,7 @@ dependencies = [ [[package]] name = "iced_video_player" version = "0.6.0" -source = "git+https://github.com/jackpot51/iced_video_player.git?branch=prev-cosmic#4c921bfe57f6cc91b8b5cc63373ce78cb1c1f922" +source = "git+https://github.com/jackpot51/iced_video_player.git?branch=prev-cosmic#3f9a1b690a41171d212e79fd6c8488dc9b1b8f4c" dependencies = [ "glib", "gstreamer", @@ -3486,6 +3489,19 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "mpris-server" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "058bc2227727af394f34aa51da3e36aeecf2c808f39315d35f754872660750ae" +dependencies = [ + "async-channel", + "futures-channel", + "serde", + "trait-variant", + "zbus 4.4.0", +] + [[package]] name = "muldiv" version = "1.0.1" @@ -5258,6 +5274,17 @@ dependencies = [ "once_cell", ] +[[package]] +name = "trait-variant" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70977707304198400eb4835a78f6a9f928bf41bba420deb8fdb175cd965d77a7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + [[package]] name = "ttf-parser" version = "0.20.0" diff --git a/Cargo.toml b/Cargo.toml index b37c070..a182ca6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,8 +5,10 @@ edition = "2021" [dependencies] gstreamer-tag = "0.23" +image = "0.24.9" lazy_static = "1" serde = { version = "1", features = ["serde_derive"] } +tempfile = "3" tokio = "1" url = "2" # Internationalization @@ -28,12 +30,16 @@ branch = "prev-master" default-features = false features = ["tokio", "winit"] +[dependencies.mpris-server] +version = "0.8.1" +optional = true + [dependencies.smol_str] version = "0.2.1" features = ["serde"] [features] -default = ["xdg-portal", "wgpu"] +default = ["mpris-server", "xdg-portal", "wgpu"] xdg-portal = ["libcosmic/xdg-portal"] wgpu = ["iced_video_player/wgpu", "libcosmic/wgpu"] diff --git a/src/main.rs b/src/main.rs index a9b3763..f65cb4a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,6 +27,7 @@ use std::{ fs, process, thread, time::{Duration, Instant}, }; +use tokio::sync::mpsc; use crate::{ config::{Config, CONFIG_VERSION}, @@ -37,6 +38,8 @@ mod config; mod key_bind; mod localize; mod menu; +#[cfg(feature = "mpris-server")] +mod mpris; static CONTROLS_TIMEOUT: Duration = Duration::new(2, 0); @@ -156,6 +159,33 @@ pub enum DropdownKind { Subtitle, } +#[derive(Clone, Debug, Default, PartialEq)] +pub struct MprisMeta { + url_opt: Option, + album: String, + album_art_opt: Option, + album_artist: String, + artists: Vec, + title: String, + disc_number: i32, + track_number: i32, + duration_micros: i64, +} + +#[derive(Clone, Debug, Default, PartialEq)] +pub struct MprisState { + fullscreen: bool, + position_micros: i64, + paused: bool, + volume: f64, +} + +#[derive(Clone, Debug)] +pub enum MprisEvent { + Meta(MprisMeta), + State(MprisState), +} + /// Messages that are used specifically by our [`App`]. #[derive(Clone, Debug)] pub enum Message { @@ -171,12 +201,15 @@ pub enum Message { AudioToggle, AudioVolume(f64), TextCode(usize), + Pause, + Play, PlayPause, Seek(f64), SeekRelative(f64), SeekRelease, EndOfStream, MissingPlugin(gst::Message), + MprisChannel(MprisMeta, MprisState, mpsc::UnboundedSender), NewFrame, Reload, ShowControls, @@ -188,16 +221,19 @@ pub enum Message { pub struct App { core: Core, flags: Flags, + album_art_opt: Option, controls: bool, controls_time: Instant, dropdown_opt: Option, fullscreen: bool, key_binds: HashMap, + mpris_opt: Option<(MprisMeta, MprisState, mpsc::UnboundedSender)>, video_opt: Option