use std::{collections::BTreeSet, sync::Arc};
use gled_protocol::midi::{MidiMonitorEvent, TestCommand};
use kanal::{Receiver, Sender};
use tracing::warn;
use super::{ClientId, LearnLog, MidiLog};
use crate::midi::{learn, monitor};
#[derive(Debug)]
pub(super) struct MidiTools {
monitor: Receiver<MidiMonitorEvent>,
learn: Receiver<[u8; 3]>,
test: Sender<TestCommand>,
watchers: BTreeSet<ClientId>,
learners: BTreeSet<ClientId>,
pub(super) monitor_log: Arc<MidiLog>,
pub(super) learn_log: Arc<LearnLog>,
}
impl MidiTools {
pub(super) fn new(
monitor: Receiver<MidiMonitorEvent>,
learn: Receiver<[u8; 3]>,
test: Sender<TestCommand>,
) -> Self {
Self {
monitor,
learn,
test,
watchers: BTreeSet::new(),
learners: BTreeSet::new(),
monitor_log: Arc::default(),
learn_log: Arc::default(),
}
}
pub(super) fn watch(&mut self, id: ClientId, watch: bool) {
set(&mut self.watchers, id, watch);
self.update();
}
pub(super) fn learning(&mut self, id: ClientId, learning: bool) {
set(&mut self.learners, id, learning);
self.update();
}
pub(super) fn disconnect(&mut self, id: ClientId) {
self.watchers.remove(&id);
self.learners.remove(&id);
self.update();
}
fn update(&self) {
let watched = !self.watchers.is_empty();
monitor::set_streaming_enabled(watched);
learn::set_streaming_enabled(watched);
learn::set_learn_active(watched && !self.learners.is_empty());
}
pub(super) fn test(&self, command: TestCommand) {
if let Err(err) = self.test.send(command) {
warn!("The MIDI runtime does not take test commands: {err}");
}
}
pub(super) fn tick(&mut self) {
while let Ok(Some(event)) = self.monitor.try_recv() {
Arc::make_mut(&mut self.monitor_log).push(event);
}
while let Ok(Some(message)) = self.learn.try_recv() {
Arc::make_mut(&mut self.learn_log).push(message);
}
}
}
fn set(clients: &mut BTreeSet<ClientId>, id: ClientId, member: bool) {
if member {
clients.insert(id);
} else {
clients.remove(&id);
}
}