photonic/input/
sink.rs

1use std::pin::Pin;
2
3use anyhow::Result;
4use futures::{Stream, StreamExt};
5use palette::rgb::Rgb;
6use tokio::sync::{broadcast, mpsc, oneshot};
7use tokio_stream::wrappers::BroadcastStream;
8
9use crate::attr::Range;
10use crate::input::trigger::Trigger;
11
12use super::{InputValue, UpdateRequest};
13
14#[derive(Debug)]
15pub struct Sink<V>
16where V: InputValue
17{
18    pub(super) update_tx: mpsc::Sender<UpdateRequest<V>>,
19    pub(super) value_rx: broadcast::Receiver<V>,
20}
21
22impl<V> Sink<V>
23where V: InputValue + Sync
24{
25    pub async fn send(&self, next: V) -> Result<()> {
26        let (responder_tx, responder_rx) = oneshot::channel();
27
28        self.update_tx
29            .send(UpdateRequest {
30                value: next,
31                responder: responder_tx,
32            })
33            .await?;
34
35        return responder_rx.await?;
36    }
37
38    pub fn subscribe(&self) -> impl Stream<Item = V> + Send {
39        return BroadcastStream::new(self.value_rx.resubscribe()).filter_map(|r| async { r.ok() });
40        // Ignore lagging errors
41    }
42}
43
44pub enum InputSink {
45    Trigger(Sink<Trigger>),
46    Boolean(Sink<bool>),
47    Integer(Sink<i64>),
48    Decimal(Sink<f32>),
49    Color(Sink<Rgb>),
50    IntegerRange(Sink<Range<i64>>),
51    DecimalRange(Sink<Range<f32>>),
52    ColorRange(Sink<Range<Rgb>>),
53}
54
55impl std::fmt::Debug for InputSink {
56    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
57        return std::fmt::Display::fmt(self, f);
58    }
59}
60
61impl std::fmt::Display for InputSink {
62    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
63        return f.write_str(match self {
64            Self::Trigger(_) => "trigger",
65            Self::Boolean(_) => "boolean",
66            Self::Integer(_) => "integer",
67            Self::Decimal(_) => "decimal",
68            Self::Color(_) => "color",
69            Self::IntegerRange(_) => "range<integer>",
70            Self::DecimalRange(_) => "range<decimal>",
71            Self::ColorRange(_) => "range<color>",
72        });
73    }
74}
75
76impl<V> From<Sink<V>> for InputSink
77where V: InputValue
78{
79    fn from(sink: Sink<V>) -> Self {
80        return V::sink(sink);
81    }
82}
83
84impl InputSink {
85    pub fn subscribe(&self) -> impl Stream<Item = AnyInputValue> + Send + Unpin {
86        let result: Pin<Box<dyn Stream<Item = _> + Send>> = match self {
87            InputSink::Trigger(sink) => Box::pin(sink.subscribe().map(AnyInputValue::from)),
88            InputSink::Boolean(sink) => Box::pin(sink.subscribe().map(AnyInputValue::from)),
89            InputSink::Integer(sink) => Box::pin(sink.subscribe().map(AnyInputValue::from)),
90            InputSink::Decimal(sink) => Box::pin(sink.subscribe().map(AnyInputValue::from)),
91            InputSink::Color(sink) => Box::pin(sink.subscribe().map(AnyInputValue::from)),
92            InputSink::IntegerRange(sink) => Box::pin(sink.subscribe().map(AnyInputValue::from)),
93            InputSink::DecimalRange(sink) => Box::pin(sink.subscribe().map(AnyInputValue::from)),
94            InputSink::ColorRange(sink) => Box::pin(sink.subscribe().map(AnyInputValue::from)),
95        };
96
97        return result;
98    }
99}
100
101#[derive(Debug, Copy, Clone)]
102pub enum AnyInputValue {
103    Trigger,
104    Boolean(bool),
105    Integer(i64),
106    Decimal(f32),
107    Color(Rgb),
108    IntegerRange(Range<i64>),
109    DecimalRange(Range<f32>),
110    ColorRange(Range<Rgb>),
111}
112
113impl From<Trigger> for AnyInputValue {
114    fn from(_: Trigger) -> Self {
115        return Self::Trigger;
116    }
117}
118
119impl From<bool> for AnyInputValue {
120    fn from(value: bool) -> Self {
121        return Self::Boolean(value);
122    }
123}
124
125impl From<i64> for AnyInputValue {
126    fn from(value: i64) -> Self {
127        return Self::Integer(value);
128    }
129}
130
131impl From<f32> for AnyInputValue {
132    fn from(value: f32) -> Self {
133        return Self::Decimal(value);
134    }
135}
136
137impl From<Rgb> for AnyInputValue {
138    fn from(value: Rgb) -> Self {
139        return Self::Color(value);
140    }
141}
142
143impl From<Range<i64>> for AnyInputValue {
144    fn from(value: Range<i64>) -> Self {
145        return Self::IntegerRange(value);
146    }
147}
148
149impl From<Range<f32>> for AnyInputValue {
150    fn from(value: Range<f32>) -> Self {
151        return Self::DecimalRange(value);
152    }
153}
154
155impl From<Range<Rgb>> for AnyInputValue {
156    fn from(value: Range<Rgb>) -> Self {
157        return Self::ColorRange(value);
158    }
159}