zbus moment

This commit is contained in:
Erica Z 2024-11-01 12:11:49 +01:00
parent 3923635703
commit d808f30005
8 changed files with 246 additions and 38 deletions

119
Cargo.lock generated
View file

@ -214,6 +214,7 @@ dependencies = [
"serde",
"tokio",
"url",
"zbus 5.0.1",
]
[[package]]
@ -1596,9 +1597,9 @@ dependencies = [
"serde",
"sha2",
"subtle",
"zbus",
"zbus 4.4.0",
"zeroize",
"zvariant",
"zvariant 4.2.0",
]
[[package]]
@ -2740,9 +2741,44 @@ dependencies = [
"uds_windows",
"windows-sys 0.52.0",
"xdg-home",
"zbus_macros",
"zbus_names",
"zvariant",
"zbus_macros 4.4.0",
"zbus_names 3.0.0",
"zvariant 4.2.0",
]
[[package]]
name = "zbus"
version = "5.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "333be40ef37976542e10832ba961e3e44ea215a6b1e2673066b303ee3e0ede10"
dependencies = [
"async-broadcast",
"async-executor",
"async-fs",
"async-io",
"async-lock",
"async-process",
"async-recursion",
"async-task",
"async-trait",
"blocking",
"enumflags2",
"event-listener",
"futures-core",
"futures-util",
"hex",
"nix",
"ordered-stream",
"serde",
"serde_repr",
"static_assertions",
"tracing",
"uds_windows",
"windows-sys 0.59.0",
"xdg-home",
"zbus_macros 5.0.1",
"zbus_names 4.0.0",
"zvariant 5.0.1",
]
[[package]]
@ -2755,7 +2791,20 @@ dependencies = [
"proc-macro2",
"quote",
"syn",
"zvariant_utils",
"zvariant_utils 2.1.0",
]
[[package]]
name = "zbus_macros"
version = "5.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "381be624000c82e716c2a45d9213fabacf82177591fa8a6ff655d2825450601a"
dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn",
"zvariant_utils 3.0.1",
]
[[package]]
@ -2766,7 +2815,18 @@ checksum = "4b9b1fef7d021261cc16cba64c351d291b715febe0fa10dc3a443ac5a5022e6c"
dependencies = [
"serde",
"static_assertions",
"zvariant",
"zvariant 4.2.0",
]
[[package]]
name = "zbus_names"
version = "4.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdc27fbd3593ff015cef906527a2ec4115e2e3dbf6204a24d952ac4975c80614"
dependencies = [
"serde",
"static_assertions",
"zvariant 5.0.1",
]
[[package]]
@ -2820,7 +2880,21 @@ dependencies = [
"enumflags2",
"serde",
"static_assertions",
"zvariant_derive",
"zvariant_derive 4.2.0",
]
[[package]]
name = "zvariant"
version = "5.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c690a1da8858fd4377b8cc3134a753b0bea1d8ebd78ad6e5897fab821c5e184e"
dependencies = [
"endi",
"enumflags2",
"serde",
"static_assertions",
"zvariant_derive 5.0.1",
"zvariant_utils 3.0.1",
]
[[package]]
@ -2833,7 +2907,20 @@ dependencies = [
"proc-macro2",
"quote",
"syn",
"zvariant_utils",
"zvariant_utils 2.1.0",
]
[[package]]
name = "zvariant_derive"
version = "5.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83b6ddc1fed08493e4f2bd9350e7d00a3383467228735f3f169a9f8820fde755"
dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn",
"zvariant_utils 3.0.1",
]
[[package]]
@ -2846,3 +2933,17 @@ dependencies = [
"quote",
"syn",
]
[[package]]
name = "zvariant_utils"
version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f8d85190ba70bc7b9540430df078bb529620b1464ed4a606010de584e27094d"
dependencies = [
"proc-macro2",
"quote",
"serde",
"static_assertions",
"syn",
"winnow",
]

View file

@ -14,6 +14,7 @@ reqwest = { version = "0.12.9", features = ["json"] }
serde = { version = "1.0.214", features = ["derive"] }
tokio = { version = "1", features = ["rt-multi-thread"] }
url = "2.5.2"
zbus = "5.0.1"
[build-dependencies]
bindgen = "0.70.1"

View file

@ -20,7 +20,28 @@ mod imp {
fn activate(&self) {
self.parent_activate();
match self.obj().active_window() {
None => ui::Window::new(self.obj().as_ref()).present(),
None => {
let window = ui::Window::new(self.obj().as_ref());
window.present();
let mpris = crate::Mpris::new(&window);
glib::spawn_future_local(async {
// run this in glib's main loop
let conn = zbus::connection::Builder::session()
.expect("could not create dbus connection builder")
.internal_executor(false)
.name("org.mpris.MediaPlayer2.audrey")
.expect("could not register name in session bus")
.serve_at("/org/mpris/MediaPlayer2", mpris)
.expect("could not serve mpris")
.build()
.await
.expect("could not build dbus connection");
loop {
conn.executor().tick().await;
}
});
}
Some(win) => win.present(),
}
}

View file

@ -1,30 +1,108 @@
mod player;
pub use player::Player;
mod ffi {
use gtk::glib;
#[repr(C)]
pub struct AudreyMpris {
parent_instance: glib::gobject_ffi::GObject,
}
#[repr(C)]
pub struct AudreyMprisClass {
parent_class: glib::gobject_ffi::GObjectClass,
}
extern "C" {
pub fn audrey_mpris_get_type() -> glib::ffi::GType;
}
}
use adw::prelude::*;
use async_channel::Sender;
use gtk::glib;
glib::wrapper! {
pub struct Mpris(Object<ffi::AudreyMpris, ffi::AudreyMprisClass>);
pub struct Mpris {
// needs to be Send, so can't store handle to the window...
raise_send: Sender<()>,
quit_send: Sender<()>,
}
match fn {
type_ => || ffi::audrey_mpris_get_type(),
impl Mpris {
pub fn new(window: &crate::ui::Window) -> Self {
let (raise_send, raise_recv) = async_channel::bounded(1);
let (quit_send, quit_recv) = async_channel::bounded(1);
glib::spawn_future_local(glib::clone!(
#[weak]
window,
async move {
while let Ok(()) = raise_recv.recv().await {
window.present();
}
}
));
glib::spawn_future_local(glib::clone!(
#[weak]
window,
async move {
while let Ok(()) = quit_recv.recv().await {
window.close();
}
}
));
Self {
raise_send: raise_send,
quit_send: quit_send,
}
}
}
#[zbus::interface(name = "org.mpris.MediaPlayer2")]
impl Mpris {
async fn raise(&self) {
// FIXME: don't unwrap
self.raise_send.send(()).await.unwrap()
}
async fn quit(&self) {
// FIXME: don't unwrap
self.quit_send.send(()).await.unwrap()
}
#[zbus(property)]
fn can_quit(&self) -> bool {
true
}
#[zbus(property)]
fn fullscreen(&self) -> bool {
false
}
#[zbus(property)]
// TODO: report that if the argument is just _ the attribute panics
async fn set_fullscreen(&self, _fullscreen: bool) -> zbus::Result<()> {
Err(zbus::Error::Unsupported)
}
#[zbus(property)]
fn can_set_fullscreen(&self) -> bool {
false
}
#[zbus(property)]
fn can_raise(&self) -> bool {
true
}
#[zbus(property)]
fn has_track_list(&self) -> bool {
false // TODO?
}
#[zbus(property)]
fn identity(&self) -> String {
"audrey".to_string()
}
#[zbus(property)]
fn desktop_entry(&self) -> String {
crate::APP_ID.to_string()
}
#[zbus(property)]
fn supported_uri_schemes(&self) -> Vec<String> {
vec![]
}
#[zbus(property)]
fn supported_mime_types(&self) -> Vec<String> {
vec![]
}
}

View file

@ -1,3 +1,4 @@
/*
[DBus (name = "org.mpris.MediaPlayer2")]
class Audrey.Mpris : Object {
internal signal void on_raise ();
@ -30,6 +31,7 @@ class Audrey.Mpris : Object {
debug ("destroying mpris");
}
}
*/
[DBus (name = "org.mpris.MediaPlayer2.Player")]
class Audrey.MprisPlayer : Object {

View file

@ -1,5 +1,6 @@
#include <glib-object.h>
#include <glib.h>
#include <gio/gio.h>
// ui::playbar
typedef void AudreyUiPlaybar;
@ -18,3 +19,8 @@ void audrey_ui_play_queue_song_unbind(AudreyUiPlayQueueSong *self);
// ui::PlayQueue
typedef void AudreyUiPlayQueue;
// Mpris
typedef void AudreyMpris;
AudreyMpris *audrey_mpris_new(void *window);
guint audrey_mpris_register_object(AudreyMpris *self, GDBusConnection *conn, const gchar *object_path, GError **error);

View file

@ -1,4 +1,4 @@
mod ffi {
pub mod ffi {
use gtk::glib;
#[repr(C)]

View file

@ -1,5 +1,5 @@
[GtkTemplate (ui = "/eu/callcc/audrey/window.ui")]
class Audrey.Ui.Window : Adw.ApplicationWindow {
public class Audrey.Ui.Window : Adw.ApplicationWindow {
[GtkChild] public unowned PlayQueue play_queue;
[GtkChild] public unowned Playbar playbar;
//[GtkChild] public unowned Adw.ButtonRow shuffle_all_tracks;
@ -29,7 +29,6 @@ class Audrey.Ui.Window : Adw.ApplicationWindow {
Object (application: app);
}
private Mpris mpris;
private MprisPlayer mpris_player;
private void now_playing (PlaybinSong song) {
@ -59,16 +58,15 @@ class Audrey.Ui.Window : Adw.ApplicationWindow {
}
construct {
/*
Bus.own_name (
BusType.SESSION,
"org.mpris.MediaPlayer2.audrey",
BusNameOwnerFlags.NONE,
(conn) => {
try {
this.mpris = new Mpris (this);
this.mpris_player = new MprisPlayer (conn, this.playbin);
conn.register_object ("/org/mpris/MediaPlayer2", this.mpris);
conn.register_object ("/org/mpris/MediaPlayer2", this.mpris_player);
} catch (IOError e) {
error ("could not register dbus service: %s", e.message);
@ -76,13 +74,14 @@ class Audrey.Ui.Window : Adw.ApplicationWindow {
},
() => {},
() => { error ("could not acquire dbus name"); });
*/
this.setup = new Setup ();
this.setup.connected.connect ((api) => {
this.api = api;
this.playbin.api = api;
this.mpris_player.api = api;
//this.mpris_player.api = api;
this.can_click_shuffle_all = true;
});
this.setup.load ();