mirror of
https://gitlab.com/marcandre.lureau/qemu-display.git
synced 2024-12-22 05:35:20 +00:00
demo: learn to connect to a specific VM
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
This commit is contained in:
parent
fe6906e996
commit
06c8554023
@ -1,10 +1,17 @@
|
||||
use futures::stream::{self, StreamExt};
|
||||
use std::collections::HashMap;
|
||||
use std::convert::TryFrom;
|
||||
use std::convert::TryInto;
|
||||
use zbus::azync::Connection;
|
||||
use zbus::fdo;
|
||||
use zbus::fdo::ManagedObjects;
|
||||
use zbus::names::BusName;
|
||||
use zbus::names::OwnedUniqueName;
|
||||
use zbus::names::UniqueName;
|
||||
use zbus::names::WellKnownName;
|
||||
use zvariant::OwnedObjectPath;
|
||||
|
||||
use crate::{Audio, Chardev, Clipboard, Result, UsbRedir};
|
||||
use crate::{AsyncVMProxy, Audio, Chardev, Clipboard, Error, Result, UsbRedir};
|
||||
|
||||
pub struct Display {
|
||||
conn: Connection,
|
||||
@ -12,9 +19,36 @@ pub struct Display {
|
||||
}
|
||||
|
||||
impl Display {
|
||||
pub async fn new(conn: &Connection) -> Result<Self> {
|
||||
let objects = zbus::fdo::AsyncObjectManagerProxy::builder(&conn)
|
||||
.destination("org.qemu")?
|
||||
pub async fn by_name(conn: &Connection) -> Result<HashMap<String, OwnedUniqueName>> {
|
||||
let mut hm = HashMap::new();
|
||||
let list = fdo::AsyncDBusProxy::new(conn)
|
||||
.await?
|
||||
.list_queued_owners(WellKnownName::from_str_unchecked("org.qemu"))
|
||||
.await?;
|
||||
for dest in list.into_iter() {
|
||||
let name = AsyncVMProxy::builder(conn)
|
||||
.destination(UniqueName::from(&dest))?
|
||||
.build()
|
||||
.await?
|
||||
.name()
|
||||
.await?;
|
||||
hm.insert(name, dest);
|
||||
}
|
||||
Ok(hm)
|
||||
}
|
||||
|
||||
pub async fn new<'d, D>(conn: &Connection, dest: Option<D>) -> Result<Self>
|
||||
where
|
||||
D: TryInto<BusName<'d>>,
|
||||
D::Error: Into<Error>,
|
||||
{
|
||||
let dest: BusName = if let Some(dest) = dest {
|
||||
dest.try_into().map_err(Into::into)?
|
||||
} else {
|
||||
"org.qemu".try_into().unwrap()
|
||||
};
|
||||
let objects = fdo::AsyncObjectManagerProxy::builder(&conn)
|
||||
.destination(dest)?
|
||||
.path("/org/qemu/Display1")?
|
||||
.build()
|
||||
.await?
|
||||
|
@ -1,5 +1,6 @@
|
||||
use usbredirhost::rusb;
|
||||
|
||||
use std::convert::Infallible;
|
||||
use std::error;
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
@ -61,6 +62,12 @@ impl From<zvariant::Error> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<zbus::names::Error> for Error {
|
||||
fn from(e: zbus::names::Error) -> Self {
|
||||
Error::Zbus(e.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<rusb::Error> for Error {
|
||||
fn from(e: rusb::Error) -> Self {
|
||||
Error::Rusb(e)
|
||||
@ -73,4 +80,10 @@ impl From<usbredirhost::Error> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Infallible> for Error {
|
||||
fn from(_: Infallible) -> Self {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
@ -252,11 +252,7 @@ impl UsbRedir {
|
||||
}
|
||||
|
||||
// We should do better and watch for owner properties changes, but this would require tasks
|
||||
let _ = inner
|
||||
.channel
|
||||
.0
|
||||
.broadcast(Event::NFreeChannels(nfree))
|
||||
.await;
|
||||
let _ = inner.channel.0.broadcast(Event::NFreeChannels(nfree)).await;
|
||||
|
||||
Ok(state)
|
||||
}
|
||||
|
@ -27,6 +27,37 @@ struct App {
|
||||
impl App {
|
||||
fn new() -> Self {
|
||||
let app = gtk::Application::new(Some("org.qemu.rdw.demo"), ApplicationFlags::NON_UNIQUE);
|
||||
app.add_main_option(
|
||||
&glib::OPTION_REMAINING,
|
||||
glib::Char(0),
|
||||
glib::OptionFlags::NONE,
|
||||
glib::OptionArg::StringArray,
|
||||
"VM-NAME",
|
||||
Some("VM name"),
|
||||
);
|
||||
app.add_main_option(
|
||||
"version",
|
||||
glib::Char(0),
|
||||
glib::OptionFlags::NONE,
|
||||
glib::OptionArg::None,
|
||||
"Show program version",
|
||||
None,
|
||||
);
|
||||
|
||||
let opt_name: Arc<RefCell<Option<String>>> = Default::default();
|
||||
let name = opt_name.clone();
|
||||
app.connect_handle_local_options(move |_, opt| {
|
||||
if opt.lookup_value("version", None).is_some() {
|
||||
println!("Version: {}", env!("CARGO_PKG_VERSION"));
|
||||
return 0;
|
||||
}
|
||||
name.replace(
|
||||
opt.lookup_value(&glib::OPTION_REMAINING, None)
|
||||
.and_then(|args| args.child_value(0).get::<String>()),
|
||||
);
|
||||
-1
|
||||
});
|
||||
|
||||
let conn = Connection::session()
|
||||
.expect("Failed to connect to DBus")
|
||||
.into();
|
||||
@ -53,8 +84,21 @@ impl App {
|
||||
window.set_application(Some(app));
|
||||
|
||||
let app_clone = app_clone.clone();
|
||||
let opt_name = opt_name.clone();
|
||||
MainContext::default().spawn_local(async move {
|
||||
let display = Display::new(app_clone.connection()).await.unwrap();
|
||||
let name = if let Some(name) = opt_name.borrow().as_ref() {
|
||||
let list = Display::by_name(app_clone.connection()).await.unwrap();
|
||||
Some(
|
||||
list.get(name)
|
||||
.expect(&format!("Can't find VM name: {}", name))
|
||||
.clone(),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let display = Display::new(app_clone.connection(), name.as_ref())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let console = Console::new(app_clone.connection(), 0)
|
||||
.await
|
||||
|
Loading…
Reference in New Issue
Block a user