WIP: reconnect

This commit is contained in:
Marc-André Lureau 2021-12-17 18:22:30 +04:00
parent 5bee9ea7f3
commit 13db197622
2 changed files with 42 additions and 14 deletions

View File

@ -2,23 +2,30 @@ use futures::stream::{self, StreamExt};
use std::{ use std::{
collections::HashMap, collections::HashMap,
convert::{TryFrom, TryInto}, convert::{TryFrom, TryInto},
sync::Arc,
}; };
use zbus::{ use zbus::{
fdo, fdo,
fdo::ManagedObjects, fdo::ManagedObjects,
names::{BusName, OwnedUniqueName, UniqueName, WellKnownName}, names::{BusName, OwnedUniqueName, UniqueName, WellKnownName},
Connection, Connection, OwnerChangedStream,
}; };
use zvariant::OwnedObjectPath; use zvariant::OwnedObjectPath;
use crate::{Audio, Chardev, Clipboard, Error, Result, UsbRedir, VMProxy}; use crate::{Audio, Chardev, Clipboard, Error, Result, UsbRedir, VMProxy};
pub struct Display { struct Inner<'d> {
proxy: fdo::ObjectManagerProxy<'d>,
conn: Connection, conn: Connection,
objects: ManagedObjects, objects: ManagedObjects,
} }
impl Display { #[derive(Clone)]
pub struct Display<'d> {
inner: Arc<Inner<'d>>,
}
impl<'d> Display<'d> {
pub async fn lookup( pub async fn lookup(
conn: &Connection, conn: &Connection,
wait: bool, wait: bool,
@ -68,7 +75,7 @@ impl Display {
Ok(hm) Ok(hm)
} }
pub async fn new<'d, D>(conn: &Connection, dest: Option<D>) -> Result<Self> pub async fn new<D>(conn: &Connection, dest: Option<D>) -> Result<Display<'d>>
where where
D: TryInto<BusName<'d>>, D: TryInto<BusName<'d>>,
D::Error: Into<Error>, D::Error: Into<Error>,
@ -78,47 +85,58 @@ impl Display {
} else { } else {
"org.qemu".try_into().unwrap() "org.qemu".try_into().unwrap()
}; };
let objects = fdo::ObjectManagerProxy::builder(conn) let proxy = fdo::ObjectManagerProxy::builder(conn)
.destination(dest)? .destination(dest)?
.path("/org/qemu/Display1")? .path("/org/qemu/Display1")?
.build() .build()
.await?
.get_managed_objects()
.await?; .await?;
// TODO: listen for changes ? let objects = proxy.get_managed_objects().await?;
Ok(Self { // TODO: listen for changes
let inner = Inner {
// owner_changed,
proxy,
conn: conn.clone(), conn: conn.clone(),
objects, objects,
};
Ok(Self {
inner: Arc::new(inner),
}) })
} }
pub async fn receive_owner_changed(&self) -> Result<OwnerChangedStream<'_>> {
Ok(self.inner.proxy.receive_owner_changed().await?)
}
pub async fn audio(&self) -> Result<Option<Audio>> { pub async fn audio(&self) -> Result<Option<Audio>> {
if !self if !self
.inner
.objects .objects
.contains_key(&OwnedObjectPath::try_from("/org/qemu/Display1/Audio").unwrap()) .contains_key(&OwnedObjectPath::try_from("/org/qemu/Display1/Audio").unwrap())
{ {
return Ok(None); return Ok(None);
} }
Ok(Some(Audio::new(&self.conn).await?)) Ok(Some(Audio::new(&self.inner.conn).await?))
} }
pub async fn clipboard(&self) -> Result<Option<Clipboard>> { pub async fn clipboard(&self) -> Result<Option<Clipboard>> {
if !self if !self
.inner
.objects .objects
.contains_key(&OwnedObjectPath::try_from("/org/qemu/Display1/Clipboard").unwrap()) .contains_key(&OwnedObjectPath::try_from("/org/qemu/Display1/Clipboard").unwrap())
{ {
return Ok(None); return Ok(None);
} }
Ok(Some(Clipboard::new(&self.conn).await?)) Ok(Some(Clipboard::new(&self.inner.conn).await?))
} }
pub async fn chardevs(&self) -> Vec<Chardev> { pub async fn chardevs(&self) -> Vec<Chardev> {
stream::iter(&self.objects) stream::iter(&self.inner.objects)
.filter_map(|(p, _ifaces)| async move { .filter_map(|(p, _ifaces)| async move {
match p.strip_prefix("/org/qemu/Display1/Chardev_") { match p.strip_prefix("/org/qemu/Display1/Chardev_") {
Some(id) => Chardev::new(&self.conn, id).await.ok(), Some(id) => Chardev::new(&self.inner.conn, id).await.ok(),
_ => None, _ => None,
} }
}) })

View File

@ -1,3 +1,4 @@
use futures_util::StreamExt;
use gio::ApplicationFlags; use gio::ApplicationFlags;
use glib::MainContext; use glib::MainContext;
use gtk::{gio, glib, prelude::*}; use gtk::{gio, glib, prelude::*};
@ -153,7 +154,16 @@ impl App {
Display::lookup(&conn, wait, name.as_deref()).await.unwrap() Display::lookup(&conn, wait, name.as_deref()).await.unwrap()
}; };
let display = Display::new(&conn, dest.as_ref()).await.unwrap();
let display = Display::new(&conn, dest).await.unwrap();
let disp = display.clone();
MainContext::default().spawn_local(async move {
let mut changed = disp.receive_owner_changed().await.unwrap();
while let Some(name) = changed.next().await {
dbg!(name);
}
});
let console = Console::new(&conn, 0) let console = Console::new(&conn, 0)
.await .await