use async_channel::Sender;
use endbasic_std::Signal;
use endbasic_std::console::{Console, ConsoleFactory, ConsoleHost, ConsoleSpec, NoopConsoleHost};
use std::cell::RefCell;
use std::io;
use std::rc::Rc;
type ConsoleHandles = (Box<dyn ConsoleHost>, Box<dyn ConsoleFactory>);
struct TextConsoleFactory {
signals_tx: Sender<Signal>,
}
impl ConsoleFactory for TextConsoleFactory {
#[cfg(feature = "crossterm")]
fn build(self: Box<Self>) -> io::Result<Rc<RefCell<dyn Console>>> {
Ok(Rc::from(RefCell::from(endbasic_terminal::TerminalConsole::from_stdio(
self.signals_tx,
)?)))
}
#[cfg(not(feature = "crossterm"))]
fn build(self: Box<Self>) -> io::Result<Rc<RefCell<dyn Console>>> {
Ok(Rc::from(RefCell::from(endbasic_std::console::TrivialConsole::default())))
}
}
fn setup_text_console(signals_tx: Sender<Signal>) -> ConsoleHandles {
(Box::from(NoopConsoleHost), Box::from(TextConsoleFactory { signals_tx }))
}
#[cfg(feature = "sdl")]
pub fn setup_sdl_console(
spec: &mut ConsoleSpec,
signals_tx: Sender<Signal>,
) -> io::Result<ConsoleHandles> {
endbasic_sdl::setup(spec, signals_tx, &endbasic_std::gfx::lcd::fonts::Fonts::all())
}
#[cfg(not(feature = "sdl"))]
pub fn setup_sdl_console(
_spec: &mut ConsoleSpec,
_signals_tx: Sender<Signal>,
) -> io::Result<ConsoleHandles> {
Err(io::Error::new(io::ErrorKind::InvalidInput, "SDL support not compiled in"))
}
#[cfg(feature = "rpi")]
fn setup_st7735s_console(
spec: &mut ConsoleSpec,
signals_tx: Sender<Signal>,
) -> io::Result<ConsoleHandles> {
let factory = endbasic_st7735s::St7735sConsoleFactory::new(
endbasic_rpi::RppalPins::default(),
endbasic_rpi::spi_bus_open,
endbasic_terminal::TerminalConsole::from_stdio,
spec,
&endbasic_std::gfx::lcd::fonts::Fonts::all(),
signals_tx,
)?;
Ok((Box::from(NoopConsoleHost), Box::from(factory)))
}
#[cfg(not(feature = "rpi"))]
fn setup_st7735s_console(
_spec: &mut ConsoleSpec,
_signals_tx: Sender<Signal>,
) -> io::Result<ConsoleHandles> {
Err(io::Error::new(io::ErrorKind::InvalidInput, "ST7735S support not compiled in"))
}
pub fn setup_console(
console_spec: Option<&str>,
signals_tx: Sender<Signal>,
) -> io::Result<ConsoleHandles> {
let mut console_spec = ConsoleSpec::init(console_spec.unwrap_or("text"));
let handles: ConsoleHandles = match console_spec.driver {
"sdl" => setup_sdl_console(&mut console_spec, signals_tx)?,
"st7735s" => setup_st7735s_console(&mut console_spec, signals_tx)?,
"text" => setup_text_console(signals_tx),
driver => {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
format!("Unknown console driver {}", driver),
));
}
};
console_spec.finish().map_err(|e| {
io::Error::new(io::ErrorKind::InvalidInput, format!("Invalid --console flag: {}", e))
})?;
Ok(handles)
}