mirror of
https://github.com/rustdesk/qemu-display.git
synced 2025-07-01 15:25:29 +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 futures::stream::{self, StreamExt};
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
use std::convert::TryInto;
|
||||||
use zbus::azync::Connection;
|
use zbus::azync::Connection;
|
||||||
|
use zbus::fdo;
|
||||||
use zbus::fdo::ManagedObjects;
|
use zbus::fdo::ManagedObjects;
|
||||||
|
use zbus::names::BusName;
|
||||||
|
use zbus::names::OwnedUniqueName;
|
||||||
|
use zbus::names::UniqueName;
|
||||||
|
use zbus::names::WellKnownName;
|
||||||
use zvariant::OwnedObjectPath;
|
use zvariant::OwnedObjectPath;
|
||||||
|
|
||||||
use crate::{Audio, Chardev, Clipboard, Result, UsbRedir};
|
use crate::{AsyncVMProxy, Audio, Chardev, Clipboard, Error, Result, UsbRedir};
|
||||||
|
|
||||||
pub struct Display {
|
pub struct Display {
|
||||||
conn: Connection,
|
conn: Connection,
|
||||||
@ -12,9 +19,36 @@ pub struct Display {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Display {
|
impl Display {
|
||||||
pub async fn new(conn: &Connection) -> Result<Self> {
|
pub async fn by_name(conn: &Connection) -> Result<HashMap<String, OwnedUniqueName>> {
|
||||||
let objects = zbus::fdo::AsyncObjectManagerProxy::builder(&conn)
|
let mut hm = HashMap::new();
|
||||||
.destination("org.qemu")?
|
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")?
|
.path("/org/qemu/Display1")?
|
||||||
.build()
|
.build()
|
||||||
.await?
|
.await?
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use usbredirhost::rusb;
|
use usbredirhost::rusb;
|
||||||
|
|
||||||
|
use std::convert::Infallible;
|
||||||
use std::error;
|
use std::error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io;
|
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 {
|
impl From<rusb::Error> for Error {
|
||||||
fn from(e: rusb::Error) -> Self {
|
fn from(e: rusb::Error) -> Self {
|
||||||
Error::Rusb(e)
|
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>;
|
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
|
// We should do better and watch for owner properties changes, but this would require tasks
|
||||||
let _ = inner
|
let _ = inner.channel.0.broadcast(Event::NFreeChannels(nfree)).await;
|
||||||
.channel
|
|
||||||
.0
|
|
||||||
.broadcast(Event::NFreeChannels(nfree))
|
|
||||||
.await;
|
|
||||||
|
|
||||||
Ok(state)
|
Ok(state)
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,37 @@ struct App {
|
|||||||
impl App {
|
impl App {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
let app = gtk::Application::new(Some("org.qemu.rdw.demo"), ApplicationFlags::NON_UNIQUE);
|
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()
|
let conn = Connection::session()
|
||||||
.expect("Failed to connect to DBus")
|
.expect("Failed to connect to DBus")
|
||||||
.into();
|
.into();
|
||||||
@ -53,8 +84,21 @@ impl App {
|
|||||||
window.set_application(Some(app));
|
window.set_application(Some(app));
|
||||||
|
|
||||||
let app_clone = app_clone.clone();
|
let app_clone = app_clone.clone();
|
||||||
|
let opt_name = opt_name.clone();
|
||||||
MainContext::default().spawn_local(async move {
|
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)
|
let console = Console::new(app_clone.connection(), 0)
|
||||||
.await
|
.await
|
||||||
|
Loading…
x
Reference in New Issue
Block a user