pub mod capture {
use alloc::sync::Arc;
use crate::core::error::Result;
use crate::core::hosts::{Captured, HostKind, HostObjects};
use crate::dev::pc::video::{CLASS_NAME, Video, VideoScanout};
use crate::machine::BuildOptions;
pub fn install(options: &mut BuildOptions) -> Result<()> {
let seen: Arc<Captured<Video>> =
options
.realize
.hosts
.open(HostKind::CAPTURE, CLASS_NAME, Captured::new)?;
options.bindings.replace(CLASS_NAME, move |props| {
let video = Arc::new(Video::new(props)?);
seen.push(&video);
Ok(video)
});
Ok(())
}
#[must_use]
pub fn take(hosts: &HostObjects) -> Option<VideoScanout> {
let seen = hosts
.get::<Captured<Video>>(HostKind::CAPTURE, CLASS_NAME)
.ok()
.flatten()?;
seen.take().map(|video| video.scanout())
}
}
#[cfg(test)]
mod tests {
use super::capture;
use crate::host::display::{Scanout, Surface};
#[test]
fn an_intercepted_binding_hands_the_host_a_picture() {
let mut options = crate::machine::BuildOptions::new()
.with_classes(crate::machine::catalog::classes())
.with_bindings(crate::machine::catalog::bindings().expect("this build's bindings"));
assert!(
capture::take(&options.realize.hosts).is_none(),
"nothing has been built"
);
capture::install(&mut options).expect("the capture table is this build's");
let registry = crate::machine::catalog::registry().expect("this build's registry");
let machine = crate::machine::build(
"one-adapter.machine",
r#"
machine "one-adapter" {
osc dot = 28322000 Hz
space port { width = 16, unassigned = open-bus }
object vga "pc.video" { clock = dot / 9 }
map port 0x03d4 size 0x0002 = vga.crtc-colour
}
"#,
®istry,
&options,
)
.expect("a machine with nothing but a display");
assert_eq!(machine.name(), "one-adapter");
let scanout = capture::take(&options.realize.hosts).expect("the constructor kept a handle");
let mut surface = Surface::for_scanout(&scanout);
scanout.capture(&mut surface);
let info = scanout.info();
assert_eq!(surface.width(), info.width);
assert_eq!(surface.height(), info.height);
assert_eq!(info.width, 720, "80 columns of nine pixels");
}
}