use std::sync;
use unbounded_spsc;
use crate::interface::{self, view, View};
use crate::tree::{NodeId, Tree};
use super::{Audio, Presentation};
#[expect(clippy::type_complexity)]
static DISPLAY_RECEIVER : sync::LazyLock <
sync::Mutex <Option <unbounded_spsc::Receiver <Vec <(NodeId, view::Display)>>>>
> = sync::LazyLock::new (|| sync::Mutex::new (None));
#[derive(Debug)]
pub struct Remote {
display : unbounded_spsc::Sender <Vec <(NodeId, view::Display)>>,
}
pub struct Fmod {
pub inner : super::Fmod,
updates : unbounded_spsc::Receiver <Vec <(NodeId, view::Display)>>,
display_counter : u64,
frame : u64
}
impl Default for Remote {
fn default() -> Self {
let display = {
let (sender, receiver) =
unbounded_spsc::channel::<Vec <(NodeId, view::Display)>>();
{
let mut display_receiver_lock = DISPLAY_RECEIVER.lock().unwrap();
debug_assert!(display_receiver_lock.is_none());
*display_receiver_lock = Some (receiver);
}
sender
};
Remote { display }
}
}
impl Audio for Remote { }
impl Presentation for Remote {
fn with_root (root : View, root_id : NodeId) -> Self {
let remote = Self::default();
log::debug!("fmod remote with root: {remote:?}");
remote.display.send (vec![(
root_id.clone(),
view::Display::Create (root, root_id, interface::CreateOrder::Append)
)]).unwrap();
remote
}
fn get_input (&mut self, _ : &mut Vec <view::Input>) { }
fn display_view <V : AsRef <View>> (&mut self,
_view_tree : &Tree <V>,
display_values : std::vec::Drain <(NodeId, view::Display)>
) {
self.display.send (display_values.collect()).unwrap();
}
}
impl Fmod {
pub fn init() -> Self {
let inner = super::Fmod::default();
let updates = loop {
let maybe_receiver = (*DISPLAY_RECEIVER).lock().unwrap().take();
if let Some (receiver) = maybe_receiver {
break receiver
}
std::thread::sleep (std::time::Duration::from_millis (100));
};
Fmod {
inner, updates,
display_counter: 0,
frame: 0
}
}
#[inline]
pub const fn display_counter (&self) -> u64 {
self.display_counter
}
#[inline]
pub const fn reset_display_counter (&mut self) {
self.display_counter = 0;
}
pub fn process_display_events (&mut self) {
while self.process_display_events_single() { }
}
pub fn process_display_events_single (&mut self) -> bool {
if let Ok (updates) = self.updates.try_recv() {
for (node_id, display) in updates {
self.inner.display_value (node_id, display);
}
self.display_counter += 1;
true
} else {
false
}
}
pub fn update_audition (&mut self) {
self.inner.audition.update();
self.frame += 1;
}
pub fn display (&mut self) {
log::trace!("fmod remote display...");
self.process_display_events();
self.update_audition();
log::trace!("...fmod remote display");
}
}