summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.rs129
1 files changed, 129 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..96455ac
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,129 @@
+use anyhow::Result;
+use async_trait::async_trait;
+// use clap::{Parser, ValueEnum};
+use env_logger;
+use image::GenericImageView;
+use image::ImageReader;
+use log::info;
+use rfb::encodings;
+use rfb::pixel_formats::rgb_888;
+use rfb::rfb::{
+ FramebufferUpdate, KeyEvent, PixelFormat, ProtoVersion, Rectangle, SecurityType, SecurityTypes,
+};
+use rfb::server::{Server, VncServer, VncServerConfig, VncServerData};
+use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+
+const WIDTH: usize = 1053;
+const HEIGHT: usize = 1053;
+
+#[derive(Clone)]
+struct AcheServer {
+ rgb_order: (u8, u8, u8),
+ big_endian: bool,
+}
+
+#[tokio::main]
+async fn main() -> Result<()> {
+ env_logger::init();
+ /*
+ TODO: Should add a CLI option to configure the port to listen to.
+
+ TODO: Should add a CLI option to configure the image to display.
+ */
+
+ let pf = PixelFormat::new_colorformat(
+ rgb_888::BITS_PER_PIXEL,
+ rgb_888::DEPTH,
+ false, // endianness = little-endian
+ order_to_shift(0),
+ rgb_888::MAX_VALUE,
+ order_to_shift(1),
+ rgb_888::MAX_VALUE,
+ order_to_shift(2),
+ rgb_888::MAX_VALUE,
+ );
+ info!("Starting server: pixel format; {:#?}", pf);
+
+ let config = VncServerConfig {
+ addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 5901),
+ version: ProtoVersion::Rfb38,
+ sec_types: SecurityTypes(vec![SecurityType::None, SecurityType::VncAuthentication]),
+ name: "rfb-ache-server".to_string(),
+ };
+ let data = VncServerData {
+ width: WIDTH as u16,
+ height: HEIGHT as u16,
+ input_pixel_format: pf.clone(),
+ };
+ let server = AcheServer {
+ rgb_order: (0, 1, 2),
+ big_endian: false,
+ };
+ let s = VncServer::new(server, config, data);
+ s.start().await?;
+
+ Ok(())
+}
+
+fn order_to_shift(order: u8) -> u8 {
+ assert!(order <= 3);
+ (3 - order) * rgb_888::BITS_PER_COLOR
+}
+
+fn order_to_index(order: u8, big_endian: bool) -> u8 {
+ assert!(order <= 3);
+
+ if big_endian {
+ order
+ } else {
+ 4 - order - 1
+ }
+}
+
+fn generate_image(name: &str, big_endian: bool, rgb_order: (u8, u8, u8)) -> Vec<u8> {
+ const LEN: usize = WIDTH * HEIGHT * rgb_888::BYTES_PER_PIXEL;
+ let mut pixels = vec![0xffu8; LEN];
+
+ let img = ImageReader::open(name).unwrap().decode().unwrap();
+
+ let (r, g, b) = rgb_order;
+ let r_idx = order_to_index(r, big_endian) as usize;
+ let g_idx = order_to_index(g, big_endian) as usize;
+ let b_idx = order_to_index(b, big_endian) as usize;
+ let x_idx = rgb_888::unused_index(r_idx, g_idx, b_idx);
+
+ // Convert the input image pixels to the requested pixel format.
+ for (x, y, pixel) in img.pixels() {
+ let ux = x as usize;
+ let uy = y as usize;
+
+ let y_offset = WIDTH * rgb_888::BYTES_PER_PIXEL;
+ let x_offset = ux * rgb_888::BYTES_PER_PIXEL;
+
+ pixels[uy * y_offset + x_offset + r_idx] = pixel[0];
+ pixels[uy * y_offset + x_offset + g_idx] = pixel[1];
+ pixels[uy * y_offset + x_offset + b_idx] = pixel[2];
+ pixels[uy * y_offset + x_offset + x_idx] = pixel[3];
+ }
+
+ pixels
+}
+
+#[async_trait]
+impl Server for AcheServer {
+ async fn get_framebuffer_update(&self) -> FramebufferUpdate {
+ let pixels_width = 1053;
+ let pixels_height = 1053;
+ let pixels = generate_image("screen-rfp.png", self.big_endian, self.rgb_order);
+ let r = Rectangle::new(
+ 0,
+ 0,
+ pixels_width,
+ pixels_height,
+ Box::new(encodings::RawEncoding::new(pixels)),
+ );
+ FramebufferUpdate::new(vec![r])
+ }
+
+ async fn key_event(&self, _ke: KeyEvent) {}
+}