use gled_midi::client::Availability;
use gled_protocol::state::{ClientInput, Devices};
use std::{
cell::{Cell, RefCell},
collections::BTreeSet,
};
use uuid::Uuid;
use gled_model::asset::output_device::routing::OutputRouting;
thread_local! {
static HOVERED: RefCell<Option<OutputRouting>> = const { RefCell::new(None) };
static WATCH_DEVICES: Cell<bool> = const { Cell::new(false) };
static WATCH_MIDI: Cell<bool> = const { Cell::new(false) };
static WATCHED_TRIGGERS: RefCell<BTreeSet<Uuid>> = const { RefCell::new(BTreeSet::new()) };
static DEVICES: RefCell<Devices> = RefCell::new(Devices::default());
static LOCAL_MIDI: RefCell<LocalMidiStatus> = RefCell::new(LocalMidiStatus::default());
static MIDI_ACCESS_REQUESTED: Cell<bool> = const { Cell::new(false) };
}
#[derive(Debug, Clone, Default)]
pub(crate) struct LocalMidiStatus {
pub(crate) availability: Option<Availability>,
pub(crate) ports: BTreeSet<String>,
}
pub(crate) fn local_midi() -> LocalMidiStatus {
LOCAL_MIDI.with(|status| status.borrow().clone())
}
pub(crate) fn request_midi_access() {
MIDI_ACCESS_REQUESTED.with(|requested| requested.set(true));
}
pub(crate) fn hover_output_routing(routing: Option<OutputRouting>) {
if let Some(routing) = routing {
HOVERED.with(|hovered| *hovered.borrow_mut() = Some(routing));
}
}
pub(crate) fn devices() -> Devices {
WATCH_DEVICES.with(|watch| watch.set(true));
DEVICES.with(|devices| devices.borrow().clone())
}
pub(crate) fn watch_midi() {
WATCH_MIDI.with(|watch| watch.set(true));
}
pub(crate) fn watch_sound_trigger(id: Uuid) {
WATCHED_TRIGGERS.with(|watched| watched.borrow_mut().insert(id));
}
#[derive(Debug, Default)]
pub(crate) struct FrameRequests {
hovered: Option<OutputRouting>,
watch_devices: bool,
watch_midi: bool,
midi_learning: bool,
watched_triggers: BTreeSet<Uuid>,
}
impl FrameRequests {
pub(crate) fn begin(&self, devices: &Devices, local_midi: LocalMidiStatus) {
DEVICES.with(|current| *current.borrow_mut() = devices.clone());
LOCAL_MIDI.with(|current| *current.borrow_mut() = local_midi);
}
pub(crate) fn take_midi_access_request(&self) -> bool {
MIDI_ACCESS_REQUESTED.with(|requested| requested.replace(false))
}
pub(crate) fn midi_watching(&self) -> (bool, bool) {
(self.watch_midi, self.midi_learning)
}
pub(crate) fn end(&mut self, midi_learning: bool) {
let hovered = HOVERED.with(|hovered| hovered.borrow_mut().take());
if hovered != self.hovered {
self.hovered = hovered.clone();
ClientInput::HoverOutputRouting(hovered).enqueue();
}
let watch = WATCH_DEVICES.with(|watch| watch.replace(false));
if watch != self.watch_devices {
self.watch_devices = watch;
ClientInput::WatchDevices(watch).enqueue();
}
let watch = WATCH_MIDI.with(|watch| watch.replace(false));
if watch != self.watch_midi {
self.watch_midi = watch;
ClientInput::WatchMidi(watch).enqueue();
}
let triggers = WATCHED_TRIGGERS.with(|watched| std::mem::take(&mut *watched.borrow_mut()));
if triggers != self.watched_triggers {
self.watched_triggers = triggers.clone();
ClientInput::WatchSoundTriggers(triggers).enqueue();
}
if midi_learning != self.midi_learning {
self.midi_learning = midi_learning;
ClientInput::MidiLearning(midi_learning).enqueue();
}
}
}