hyperion/global/
input_source.rs1use 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 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}