Marc-André Lureau edaffdb868 Initial commit
2021-02-09 16:26:31 +04:00

122 lines
3.5 KiB
Rust

use std::cell::RefCell;
use std::os::unix::net::UnixStream;
use std::rc::Rc;
use std::sync::mpsc::{self, Receiver};
use std::{os::unix::io::AsRawFd, thread};
use zbus::{dbus_proxy, export::zvariant::Fd};
use crate::Result;
use crate::{Event, Listener};
#[dbus_proxy(default_service = "org.qemu", interface = "org.qemu.Display1.Console")]
pub trait Console {
/// RegisterListener method
fn register_listener(&self, listener: Fd) -> zbus::Result<()>;
#[dbus_proxy(property)]
fn label(&self) -> zbus::Result<String>;
#[dbus_proxy(property)]
fn head(&self) -> zbus::Result<u32>;
#[dbus_proxy(property)]
fn type_(&self) -> zbus::Result<String>;
#[dbus_proxy(property)]
fn width(&self) -> zbus::Result<u32>;
#[dbus_proxy(property)]
fn height(&self) -> zbus::Result<u32>;
}
#[derive(derivative::Derivative)]
#[derivative(Debug)]
pub struct Console<'c> {
#[derivative(Debug = "ignore")]
proxy: ConsoleProxy<'c>,
}
impl<'c> Console<'c> {
pub fn new(conn: &zbus::Connection, idx: u32) -> Result<Self> {
let proxy = ConsoleProxy::new_for_owned_path(
conn.clone(),
format!("/org/qemu/Display1/Console_{}", idx),
)?;
Ok(Self { proxy })
}
pub fn label(&self) -> Result<String> {
Ok(self.proxy.label()?)
}
pub fn width(&self) -> Result<u32> {
Ok(self.proxy.width()?)
}
pub fn height(&self) -> Result<u32> {
Ok(self.proxy.height()?)
}
pub fn listen(&self) -> Result<Receiver<Event>> {
let (p0, p1) = UnixStream::pair()?;
let (tx, rx) = mpsc::channel();
self.proxy.register_listener(p0.as_raw_fd().into())?;
let _thread = thread::spawn(move || {
let c = zbus::Connection::new_unix_client(p1, false).unwrap();
let mut s = zbus::ObjectServer::new(&c);
let err = Rc::new(RefCell::new(None));
s.at(
&zvariant::ObjectPath::from_str_unchecked("/org/qemu/Display1/Listener"),
Listener::new(tx, err.clone()),
)
.unwrap();
loop {
if let Err(e) = s.try_handle_next() {
eprintln!("Listener DBus error: {}", e);
return;
}
if let Some(e) = &*err.borrow() {
eprintln!("Listener channel error: {}", e);
return;
}
}
});
Ok(rx)
}
}
#[cfg(feature = "glib")]
impl<'c> Console<'c> {
pub fn glib_listen(&self) -> Result<glib::Receiver<Event>> {
let (p0, p1) = UnixStream::pair()?;
let (tx, rx) = glib::MainContext::channel(glib::source::Priority::default());
self.proxy.register_listener(p0.as_raw_fd().into())?;
let _thread = thread::spawn(move || {
let c = zbus::Connection::new_unix_client(p1, false).unwrap();
let mut s = zbus::ObjectServer::new(&c);
let err = Rc::new(RefCell::new(None));
s.at(
&zvariant::ObjectPath::from_str_unchecked("/org/qemu/Display1/Listener"),
Listener::new(tx, err.clone()),
)
.unwrap();
loop {
if let Err(e) = s.try_handle_next() {
eprintln!("Listener DBus error: {}", e);
return;
}
if let Some(e) = &*err.borrow() {
eprintln!("Listener channel error: {}", e);
return;
}
}
});
Ok(rx)
}
}