use std::path::Path;
use std::os::unix::io;
use nix::fcntl;
use nix::sys::stat;
use libdrm::drm_mode;
use dharma::event_kind;
use qualia::{DrmBundle, Illusion, EventHandling, HwGraphics, StatePublishing};
use graphics_manager::GraphicsManager;
use pageflip::PageFlipEventHandler;
pub struct OutputCollector<C>
where C: EventHandling + StatePublishing + HwGraphics + Clone
{
coordinator: C,
}
impl<C> OutputCollector<C>
where C: 'static + EventHandling + StatePublishing + HwGraphics + Send + Clone
{
pub fn new(coordinator: C) -> Self {
OutputCollector { coordinator: coordinator }
}
pub fn scan_device(&mut self, path: &Path) -> Result<(), Illusion> {
log_info1!("OutputCollector: scan device '{:?}'", path);
let fd = match fcntl::open(path, fcntl::O_RDWR | fcntl::O_CLOEXEC, stat::Mode::empty()) {
Ok(fd) => fd,
Err(err) => {
let text = format!("Could open output device {:?}: {}", path, err);
return Err(Illusion::General(text));
}
};
if let Some(resources) = drm_mode::get_resources(fd) {
for id in resources.get_connectors() {
if let Some(connector) = drm_mode::get_connector(fd, id) {
self.process_connector(fd, path, &connector);
} else {
log_warn1!("Failed to get connector info!");
}
}
} else {
log_warn1!("No resources for device {:?}", path);
}
let pageflip_handler = Box::new(PageFlipEventHandler::new(fd, self.coordinator.clone()));
self.coordinator.add_event_handler(pageflip_handler, event_kind::READ);
match GraphicsManager::new(fd) {
Ok(graphics_manager) => {
self.coordinator.set_graphics_manager(Box::new(graphics_manager));
}
Err(err) => {
log_warn1!("Failed to initialize graphics manager: {}", err);
}
}
Ok(())
}
fn process_connector(&mut self, fd: io::RawFd, path: &Path, connector: &drm_mode::Connector) {
log_info1!("{:?}", connector);
if connector.get_connection() == drm_mode::Connection::Connected {
if let Some(encoder) = drm_mode::get_encoder(fd, connector.get_encoder_id()) {
let bundle = DrmBundle {
path: path.to_owned(),
fd: fd,
connector_id: connector.get_connector_id(),
crtc_id: encoder.get_crtc_id(),
};
self.coordinator.publish_output(bundle);
} else {
log_warn1!("No encoder for connector '{:?}'", connector.get_connector_id());
}
}
}
}