use std::fmt; use std::error::Error; use std::collections::VecDeque; use std::sync::{Arc, Mutex}; use femtos::Instant; use crate::gfx::FrameReceiver; use crate::audio::Sample; use crate::keys::KeyEvent; use crate::controllers::ControllerEvent; use crate::mouse::MouseEvent; use crate::input::EventSender; #[derive(Clone, Debug, thiserror::Error)] pub enum HostError { TTYNotSupported, VideoSourceNotSupported, AudioSourceNotSupported, ControllerNotSupported, KeyboardNotSupported, MouseNotSupported, #[from(E)] Specific(E), } /* impl fmt::Display for HostError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { HostError::TTYNotSupported => write!(f, "This frontend doesn't support PTYs"), HostError::VideoSourceNotSupported => write!(f, "This frontend doesn't support windows"), HostError::AudioSourceNotSupported => write!(f, "This frontend doesn't support the sound"), HostError::ControllerNotSupported => write!(f, "This frontend doesn't support game controllers"), HostError::KeyboardNotSupported => write!(f, "This frontend doesn't support the keyboard"), HostError::MouseNotSupported => write!(f, "This frontend doesn't support the mouse"), HostError::Specific(err) => write!(f, "{}", err), } } } */ pub trait Host { type Error: Error; fn add_pty(&self) -> Result, HostError> { Err(HostError::TTYNotSupported) } fn add_video_source(&mut self, _receiver: FrameReceiver) -> Result<(), HostError> { Err(HostError::VideoSourceNotSupported) } fn add_audio_source(&mut self) -> Result, HostError> { Err(HostError::AudioSourceNotSupported) } fn register_controllers(&mut self, _sender: EventSender) -> Result<(), HostError> { Err(HostError::ControllerNotSupported) } fn register_keyboard(&mut self, _sender: EventSender) -> Result<(), HostError> { Err(HostError::KeyboardNotSupported) } fn register_mouse(&mut self, _sender: EventSender) -> Result<(), HostError> { Err(HostError::MouseNotSupported) } } pub trait Tty { fn device_name(&self) -> String; fn read(&mut self) -> Option; fn write(&mut self, output: u8) -> bool; } pub trait Audio { fn samples_per_second(&self) -> usize; fn write_samples(&mut self, clock: Instant, buffer: &[Sample]); } #[derive(Clone, Default)] pub struct ClockedQueue(Arc>>, usize); impl ClockedQueue { pub fn new(max: usize) -> Self { Self(Arc::new(Mutex::new(VecDeque::new())), max) } pub fn push(&self, clock: Instant, data: T) { let mut queue = self.0.lock().unwrap(); if queue.len() > self.1 { //log::warn!("dropping data from queue due to limit of {} items", self.1); queue.pop_front(); } queue.push_back((clock, data)); } pub fn pop_next(&self) -> Option<(Instant, T)> { self.0.lock().unwrap().pop_front() } pub fn pop_latest(&self) -> Option<(Instant, T)> { self.0.lock().unwrap().drain(..).last() } pub fn put_back(&self, clock: Instant, data: T) { self.0.lock().unwrap().push_front((clock, data)); } pub fn peek_clock(&self) -> Option { self.0.lock().unwrap().front().map(|(clock, _)| *clock) } pub fn is_empty(&self) -> bool { self.0.lock().unwrap().is_empty() } } pub struct DummyAudio(); impl Audio for DummyAudio { fn samples_per_second(&self) -> usize { 48000 } fn write_samples(&mut self, _clock: Instant, _buffer: &[Sample]) {} }