1use std::{marker::PhantomData, sync::Arc};
2
3use elgato_streamdeck::AsyncStreamDeck;
4
5use crate::{
6 button::RenderConfig, navigation::NavigationEntry, theme::Theme, view::DisplayManager,
7};
8
9pub async fn run<N, W, H, C>(
14 theme: Theme,
15 config: RenderConfig,
16 deck: Arc<AsyncStreamDeck>,
17 context: C,
18) -> Result<(), Box<dyn std::error::Error>>
19where
20 W: generic_array::ArrayLength,
21 H: generic_array::ArrayLength,
22 C: Send + Sync + Clone + 'static,
23 N: NavigationEntry<W, H, C>,
24{
25 let (display_manager, mut navigation_receiver) =
26 DisplayManager::<N, W, H, C>::new(deck.clone(), config, theme, context)?;
27
28 display_manager.fetch_all().await?;
29 display_manager.render().await?;
30
31 let reader = deck.get_reader();
32 loop {
33 let events_future = reader.read(10.0);
34 let navigation_future = navigation_receiver.recv();
35 tokio::select! {
36 events = events_future => {
37 let events = events?;
38 for event in events {
39 match event {
40 elgato_streamdeck::DeviceStateUpdate::ButtonDown(id) => {
41 display_manager.on_press(id).await?;
42 }
43 elgato_streamdeck::DeviceStateUpdate::ButtonUp(id) => {
44 display_manager.on_release(id).await?;
45 }
46 _ => {}
47 }
48 }
49 }
50 Some(navigation) = navigation_future => {
51 display_manager.navigate_to(navigation).await?;
52 display_manager.fetch_all().await?;
53 display_manager.render().await?;
54 }
55 }
56 }
57}
58
59pub struct ExternalTrigger<N, W, H, C> {
60 pub(crate) navigation: N,
62 pub(crate) switch_view: bool,
64 pub(crate) _marker: PhantomData<(W, H, C)>,
65}
66
67impl<N, W, H, C> ExternalTrigger<N, W, H, C> {
68 pub fn new(navigation: N, switch_view: bool) -> Self {
70 Self {
71 navigation,
72 switch_view,
73 _marker: PhantomData,
74 }
75 }
76}
77
78pub async fn run_with_external_triggers<N, W, H, C>(
83 theme: Theme,
84 config: RenderConfig,
85 deck: Arc<AsyncStreamDeck>,
86 context: C,
87 mut receiver: tokio::sync::mpsc::Receiver<ExternalTrigger<N, W, H, C>>,
88) -> Result<(), Box<dyn std::error::Error>>
89where
90 W: generic_array::ArrayLength,
91 H: generic_array::ArrayLength,
92 C: Send + Sync + Clone + 'static,
93 N: NavigationEntry<W, H, C>,
94{
95 let (display_manager, mut navigation_receiver) =
96 DisplayManager::<N, W, H, C>::new(deck.clone(), config, theme, context)?;
97
98 display_manager.fetch_all().await?;
99 display_manager.render().await?;
100
101 let reader = deck.get_reader();
102 loop {
103 let events_future = reader.read(10.0);
104 let navigation_future = navigation_receiver.recv();
105 let trigger_future = receiver.recv();
106 tokio::select! {
107 events = events_future => {
108 let events = events?;
109 for event in events {
110 match event {
111 elgato_streamdeck::DeviceStateUpdate::ButtonDown(id) => {
112 display_manager.on_press(id).await?;
113 }
114 elgato_streamdeck::DeviceStateUpdate::ButtonUp(id) => {
115 display_manager.on_release(id).await?;
116 }
117 _ => {}
118 }
119 }
120 }
121 Some(navigation) = navigation_future => {
122 display_manager.navigate_to(navigation).await?;
123 display_manager.fetch_all().await?;
124 display_manager.render().await?;
125 }
126 Some(trigger) = trigger_future => {
127 if trigger.switch_view || trigger.navigation == display_manager.get_current_navigation().await? {
128 display_manager.navigate_to(trigger.navigation).await?;
129 display_manager.fetch_all().await?;
130 display_manager.render().await?;
131 }
132 }
133 }
134 }
135}