use anyhow::Result;
use ddp_rs::packet::Packet;
use std::io::{self, Write};
use std::net::UdpSocket;
struct ConsoleRenderer {
num_pixels: usize,
pixels: Vec<u8>,
}
impl ConsoleRenderer {
fn new(num_pixels: usize) -> Self {
Self {
num_pixels,
pixels: vec![0; num_pixels * 3], }
}
fn update_from_packet(&mut self, packet: &Packet) {
let offset = packet.header.offset as usize;
let data = &packet.data;
let start_pixel_idx = offset;
if start_pixel_idx < self.pixels.len() {
let end_idx = (start_pixel_idx + data.len()).min(self.pixels.len());
let copy_len = end_idx - start_pixel_idx;
self.pixels[start_pixel_idx..end_idx].copy_from_slice(&data[..copy_len]);
}
}
fn render(&self) -> io::Result<()> {
let mut stdout = io::stdout();
write!(stdout, "\r\x1b[0m")?;
for i in 0..self.num_pixels {
let idx = i * 3;
if idx + 2 < self.pixels.len() {
let r = self.pixels[idx];
let g = self.pixels[idx + 1];
let b = self.pixels[idx + 2];
write!(stdout, "\x1b[48;2;{};{};{}m ", r, g, b)?;
}
}
write!(stdout, "\x1b[0m ")?;
stdout.flush()?;
Ok(())
}
fn clear(&mut self) -> io::Result<()> {
self.pixels.fill(0);
writeln!(io::stdout(), "\n\x1b[0m")?;
Ok(())
}
}
fn main() -> Result<()> {
println!("DDP Console Server");
println!("==================");
println!("Listening on 0.0.0.0:4048");
let socket = UdpSocket::bind("0.0.0.0:4048")?;
println!("Bound to {}\n", socket.local_addr()?);
let mut renderer = ConsoleRenderer::new(100);
let mut buf = [0u8; 2048];
loop {
match socket.recv_from(&mut buf) {
Ok((size, src)) => {
let packet = Packet::from_bytes(&buf[..size]);
renderer.update_from_packet(&packet);
if let Err(e) = renderer.render() {
eprintln!("Render error: {}", e);
}
}
Err(e) => {
eprintln!("Error receiving packet: {}", e);
}
}
}
#[allow(unreachable_code)]
{
renderer.clear()?;
Ok(())
}
}