This commit is contained in:
Erica Z 2024-11-01 13:50:29 +01:00
parent 56d4057d87
commit b3a5fc146a
5 changed files with 100 additions and 29 deletions

View file

@ -24,23 +24,30 @@ mod imp {
let window = ui::Window::new(self.obj().as_ref());
window.present();
let mpris = crate::Mpris::new(&window);
let mpris_player = crate::mpris::Player::new();
glib::spawn_future_local(async {
glib::spawn_future_local(async move {
// run this in glib's main loop
let conn = zbus::connection::Builder::session()
.expect("could not create dbus connection builder")
.expect("could not connect to the session bus")
.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")
.serve_at("/org/mpris/MediaPlayer2", mpris_player)
.expect("could not serve mpris player")
.build()
.await
.expect("could not build dbus connection");
.expect("could not build connection to the session bus");
crate::Mpris::setup(conn.object_server(), &window)
.await
.expect("could not serve mpris");
crate::mpris::Player::setup(
conn.object_server(),
&window.playbin().unwrap(),
)
.await
.expect("could not serve mpris player");
// always set up handlers before requesting service name
conn.request_name("org.mpris.MediaPlayer2.audrey")
.await
.expect("could not register name in session bus");
loop {
conn.executor().tick().await;
}

View file

@ -9,22 +9,34 @@ pub struct Mpris {
}
impl Mpris {
pub fn new(window: &crate::ui::Window) -> Self {
Self {
pub async fn setup(
object_server: &zbus::ObjectServer,
window: &crate::ui::Window,
) -> Result<(), zbus::Error> {
let mpris = Self {
window: window.downgrade().into(),
}
};
object_server.at("/org/mpris/MediaPlayer2", mpris).await?;
//let _mpris = object_server.interface::<_, Self>("/org/mpris/MediaPlayer2").await?;
Ok(())
}
}
#[zbus::interface(name = "org.mpris.MediaPlayer2")]
impl Mpris {
fn raise(&self) {
self.window.upgrade().expect("main window was finalized").present();
self.window
.upgrade()
.expect("main window was finalized")
.present();
}
fn quit(&self) {
match self.window.upgrade() {
None => {}, // guess there's nothing to do
None => {} // guess there's nothing to do
Some(window) => window.close(),
}
}

View file

@ -1,11 +1,45 @@
use glib::SendWeakRef;
use gtk::glib;
use zbus::object_server::SignalEmitter;
use zbus::zvariant::{ObjectPath, Value};
pub struct Player {}
pub struct Player {
playbin: SendWeakRef<crate::Playbin>,
metadata: Vec<(String, String)>,
}
impl Player {
pub fn new() -> Self {
Self {}
pub async fn setup(
object_server: &zbus::ObjectServer,
playbin: &crate::Playbin,
) -> Result<(), zbus::Error> {
use adw::prelude::*;
let player = Self {
playbin: playbin.downgrade().into(),
metadata: Default::default(),
};
object_server.at("/org/mpris/MediaPlayer2", player).await?;
let player = object_server
.interface::<_, Self>("/org/mpris/MediaPlayer2")
.await?;
playbin.connect_closure(
"new-track",
false,
glib::closure_local!(
#[strong]
player,
move |_playbin: &crate::Playbin| {
let _player = player.get_mut();
// TODO
}
),
);
Ok(())
}
}
@ -52,7 +86,11 @@ impl Player {
#[zbus(property)]
fn playback_status(&self) -> String {
"Stopped".into() // TODO
match self.playbin.upgrade().unwrap().state() {
crate::playbin::State::Stopped => "Stopped".into(),
crate::playbin::State::Playing => "Playing".into(),
crate::playbin::State::Paused => "Paused".into(),
}
}
#[zbus(property)]
@ -76,18 +114,21 @@ impl Player {
}
#[zbus(property)]
fn shuffle(&self) -> zbus::fdo::Result<bool> {
Err(zbus::fdo::Error::NotSupported("Shuffle".into()))
fn shuffle(&self) -> bool {
false
}
#[zbus(property)]
fn set_shuffle(&self, _shuffle: bool) {
todo!()
fn set_shuffle(&self, _shuffle: bool) -> zbus::Result<()> {
Err(zbus::Error::Unsupported)
}
#[zbus(property)]
fn metadata(&self) -> Vec<(String, Value)> {
vec![] // TODO
self.metadata
.iter()
.map(|(k, v)| (k.clone(), v.into()))
.collect()
}
#[zbus(property)]
@ -102,7 +143,7 @@ impl Player {
#[zbus(property(emits_changed_signal = "false"))]
fn position(&self) -> i64 {
0 // TODO
(self.playbin.upgrade().unwrap().position() * 1e9) as i64
}
#[zbus(property)]

View file

@ -22,6 +22,7 @@ pub mod ffi {
pub fn audrey_playbin_get_state(self_: *mut AudreyPlaybin) -> super::state::ffi::State;
pub fn audrey_playbin_pause(self_: *mut AudreyPlaybin);
pub fn audrey_playbin_play(self_: *mut AudreyPlaybin);
pub fn audrey_playbin_stop(self_: *mut AudreyPlaybin);
pub fn audrey_playbin_get_volume(self_: *mut AudreyPlaybin) -> std::ffi::c_int;
pub fn audrey_playbin_set_volume(self_: *mut AudreyPlaybin, volume: std::ffi::c_int);
pub fn audrey_playbin_seek(self_: *mut AudreyPlaybin, position: f64);
@ -121,4 +122,8 @@ impl Playbin {
pub fn select_track(&self, position: u32) {
unsafe { ffi::audrey_playbin_select_track(self.to_glib_none().0, position) }
}
pub fn stop(&self) {
unsafe { ffi::audrey_playbin_stop(self.to_glib_none().0) }
}
}

View file

@ -14,10 +14,14 @@ pub mod ffi {
extern "C" {
pub fn audrey_ui_window_get_type() -> glib::ffi::GType;
pub fn audrey_ui_window_new(app: *mut gtk::ffi::GtkApplication) -> *mut AudreyUiWindow;
pub fn audrey_ui_window_get_playbin(
self_: *mut AudreyUiWindow,
) -> *mut crate::playbin::ffi::AudreyPlaybin;
}
}
use adw::prelude::*;
use glib::translate::{from_glib_none, ToGlibPtr};
use gtk::{gio, glib};
glib::wrapper! {
@ -32,8 +36,10 @@ glib::wrapper! {
impl Window {
pub fn new(app: &impl IsA<gtk::Application>) -> Self {
use glib::translate::*;
unsafe { from_glib_none(ffi::audrey_ui_window_new(app.as_ref().to_glib_none().0)) }
}
pub fn playbin(&self) -> Option<crate::Playbin> {
unsafe { from_glib_none(ffi::audrey_ui_window_get_playbin(self.to_glib_none().0)) }
}
}