1use crate::artnet::ArtnetInterface;
2use common::fixture::{MAX_CHANNEL, calculate_dmx_values, Fixture};
3use std::io;
4use std::net::UdpSocket;
5use std::sync::mpsc::Receiver;
6use std::thread::sleep;
7use std::time::{Duration, Instant};
8use common::logging::LogLevel::*;
9use common::r_log;
10
11const TARGET: &str = "255.255.255.255:6454";
12const FREQUENCY: u64 = 23;
13
14pub trait DmxInterface {
20 fn send_universe(
27 &self,
28 local_universe_index: u16,
29 data: &[u8; MAX_CHANNEL as usize],
30 ) -> Result<(), io::Error>;
31}
32
33pub fn dmx_output_loop(data_receiver: Receiver<(usize,Vec<Fixture>)>) -> io::Result<()> {
45 let socket = UdpSocket::bind("0.0.0.0:0")?;
46 socket.set_broadcast(true)?;
47
48 let artnet_interface: Box<dyn DmxInterface> =
49 Box::new(ArtnetInterface::new(socket, TARGET.to_string()));
50
51 r_log!(Info,"Starting artnet");
52
53 let mut universe_count: usize = 0;
54 let mut fixtures: Vec<Fixture> = vec![];
55
56 loop {
57 let start = Instant::now();
58
59 while let Ok((new_count, new_fixtures)) = data_receiver.try_recv() {
60 universe_count = new_count;
61 fixtures = new_fixtures;
62 }
63
64
65 let universes = calculate_dmx_values(universe_count, &fixtures);
66
67 for (universe_index, data) in universes.iter().enumerate() {
68 artnet_interface.send_universe(universe_index as u16, data)?;
69 }
70
71 let elapsed = start.elapsed();
72 if elapsed < Duration::from_millis(FREQUENCY) {
73 sleep(Duration::from_millis(FREQUENCY) - elapsed);
74 }
75 }
76}