use io::Write;
use std::fmt;
use std::io;
use std::time::Duration;
use thiserror::Error;
mod artnet;
mod enttec;
mod offline;
pub use artnet::ArtnetDmxPort;
pub use enttec::EnttecDmxPort;
pub use offline::{OfflineDmxPort, offline};
#[typetag::serde(tag = "type")]
pub trait DmxPort: fmt::Display + Send {
fn open(&mut self) -> Result<(), OpenError>;
fn close(&mut self);
fn write(&mut self, frame: &[u8]) -> Result<(), WriteError>;
}
type PortListing = Vec<Box<dyn DmxPort>>;
pub fn available_ports(browse_artnet: Option<Duration>) -> anyhow::Result<PortListing> {
let mut ports = Vec::new();
ports.extend(EnttecDmxPort::available_ports()?);
if let Some(wait) = browse_artnet {
ports.extend(ArtnetDmxPort::available_ports(wait)?);
}
Ok(ports)
}
pub fn select_port(browse_artnet: Option<Duration>) -> anyhow::Result<Box<dyn DmxPort>> {
let mut ports = available_ports(browse_artnet)?;
select_port_from(&mut ports)
}
pub fn select_port_from(ports: &mut PortListing) -> anyhow::Result<Box<dyn DmxPort>> {
println!("Available DMX ports:");
println!("0: offline");
for (i, port) in ports.iter().enumerate() {
println!("{}: {}", i + 1, port);
}
let mut port = loop {
print!("Select a port: ");
io::stdout().flush()?;
let input = read_string()?;
let index = match input.trim().parse::<usize>() {
Ok(num) => num,
Err(e) => {
println!("{}; please enter an integer.", e);
continue;
}
};
if index == 0 {
return Ok(offline());
}
let index = index - 1;
if index >= ports.len() {
println!("Please enter a value less than {}.", ports.len() + 1);
continue;
}
break ports.remove(index);
};
port.open()?;
Ok(port)
}
fn read_string() -> Result<String, io::Error> {
let mut line = String::new();
io::stdin().read_line(&mut line)?;
Ok(line.trim().to_string())
}
#[derive(Error, Debug)]
pub enum OpenError {
#[error("the DMX port is not connected")]
NotConnected,
#[error(transparent)]
Other(#[from] anyhow::Error),
}
#[derive(Error, Debug)]
pub enum WriteError {
#[error("the DMX port is not connected")]
Disconnected,
#[error(transparent)]
Other(#[from] anyhow::Error),
}