hyperion/global/
input_source.rs

1use std::sync::Arc;
2
3use parse_display::Display;
4use thiserror::Error;
5use tokio::sync::broadcast;
6
7use super::{Global, InputSourceName, Message};
8use crate::component::ComponentName;
9
10#[derive(Display)]
11#[display("`{name}` (id = {id}, priority = {priority:?})")]
12pub struct InputSource<T: Message> {
13    id: usize,
14    name: InputSourceName,
15    priority: Option<i32>,
16    tx: broadcast::Sender<T>,
17}
18
19impl<T: Message> InputSource<T> {
20    pub fn new(
21        id: usize,
22        name: InputSourceName,
23        priority: Option<i32>,
24        tx: broadcast::Sender<T>,
25    ) -> Self {
26        Self {
27            id,
28            name,
29            priority,
30            tx,
31        }
32    }
33
34    pub fn id(&self) -> usize {
35        self.id
36    }
37
38    pub fn name(&self) -> &InputSourceName {
39        &self.name
40    }
41
42    pub fn priority(&self) -> Option<i32> {
43        self.priority
44    }
45
46    pub fn send(
47        &self,
48        component: ComponentName,
49        message: T::Data,
50    ) -> Result<usize, broadcast::error::SendError<T>> {
51        self.tx.send(T::new(self.id, component, message))
52    }
53
54    pub fn channel(&self) -> &broadcast::Sender<T> {
55        &self.tx
56    }
57}
58
59pub struct InputSourceHandle<T: Message> {
60    input_source: Arc<InputSource<T>>,
61    global: Global,
62}
63
64impl<T: Message> InputSourceHandle<T> {
65    pub fn new(input_source: Arc<InputSource<T>>, global: Global) -> Self {
66        Self {
67            input_source,
68            global,
69        }
70    }
71}
72
73impl<T: Message> std::ops::Deref for InputSourceHandle<T> {
74    type Target = InputSource<T>;
75
76    fn deref(&self) -> &Self::Target {
77        &self.input_source
78    }
79}
80
81impl<T: Message> Drop for InputSourceHandle<T> {
82    fn drop(&mut self) {
83        // TODO: Can this block?
84        futures::executor::block_on(async {
85            T::unregister_source(&mut *self.global.0.write().await, &*self.input_source);
86        });
87    }
88}
89
90#[derive(Debug, Error)]
91pub enum InputSourceError {
92    #[error("invalid priority: {0}")]
93    InvalidPriority(i32),
94}