streamduck_core/core/
mod.rs1use std::collections::HashMap;
2use std::sync::Arc;
3
4use serde::{Deserialize, Serialize};
5use serde_json::Value;
6use streamdeck::{Kind, StreamDeck};
7use tokio::sync::{Mutex, RwLock};
8use tokio::sync::mpsc::unbounded_channel;
9
10pub use methods::check_feature_list_for_feature;
11pub use methods::CoreHandle;
12pub use methods::warn_for_feature;
13
14use crate::ImageCollection;
15use crate::config::{Config, UniqueDeviceConfig};
16use crate::core::button::Button;
17use crate::modules::events::SDGlobalEvent;
18use crate::modules::ModuleManager;
19use crate::socket::SocketManager;
20use crate::thread::{DeviceThreadCommunication, DeviceThreadHandle, spawn_device_thread};
21use crate::thread::rendering::custom::RenderingManager;
22
23pub mod button;
25
26mod methods;
28pub mod manager;
29
30pub type UniqueButton = Arc<RwLock<Button>>;
32
33pub type UniqueButtonMap = HashMap<u8, UniqueButton>;
35
36pub type ButtonMap = HashMap<u8, Button>;
38
39pub type ButtonPanel = Arc<RwLock<Panel<UniqueButtonMap>>>;
41
42pub type RawButtonPanel = Panel<ButtonMap>;
44
45#[derive(Serialize, Deserialize, Clone, Default, Debug)]
47pub struct Panel<T> {
48 #[serde(default)]
50 pub display_name: String,
51 #[serde(default)]
53 pub data: Value,
54 #[serde(default)]
56 pub buttons: T
57}
58
59impl Into<ButtonMap> for Panel<ButtonMap> {
60 fn into(self) -> ButtonMap {
61 self.buttons
62 }
63}
64
65impl Into<ButtonMap> for &Panel<ButtonMap> {
66 fn into(self) -> ButtonMap {
67 self.buttons.clone()
68 }
69}
70
71impl Into<UniqueButtonMap> for Panel<UniqueButtonMap> {
72 fn into(self) -> UniqueButtonMap {
73 self.buttons
74 }
75}
76
77impl Into<UniqueButtonMap> for &Panel<UniqueButtonMap> {
78 fn into(self) -> UniqueButtonMap {
79 self.buttons.clone()
80 }
81}
82
83#[allow(dead_code)]
85pub struct SDCore {
86 pub serial_number: String,
88
89 pub module_manager: Arc<ModuleManager>,
91
92 pub render_manager: Arc<RenderingManager>,
94
95 pub socket_manager: Arc<SocketManager>,
97
98 pub config: Arc<Config>,
100
101 pub device_config: UniqueDeviceConfig,
103
104 pub current_stack: Mutex<Vec<ButtonPanel>>,
106
107 pub image_size: (usize, usize),
109
110 pub image_collection: ImageCollection,
112
113 pub kind: Kind,
115
116 pub key_count: u8,
118
119 pub frame_rate: u32,
121
122 pub should_close: RwLock<bool>,
124
125 handles: Mutex<Option<ThreadHandles>>
126}
127
128impl SDCore {
129 pub async fn blank(module_manager: Arc<ModuleManager>, render_manager: Arc<RenderingManager>, socket_manager: Arc<SocketManager>, config: Arc<Config>, device_config: UniqueDeviceConfig, image_collection: ImageCollection) -> Arc<SDCore> {
131 let serial_number = device_config.read().await.serial.to_string();
132 Arc::new(SDCore {
133 serial_number,
134 module_manager,
135 render_manager,
136 socket_manager,
137 config,
138 device_config,
139 current_stack: Mutex::new(vec![]),
140 handles: Mutex::new(None),
141 image_size: (0, 0),
142 image_collection,
143 kind: Kind::Original,
144 key_count: 0,
145 frame_rate: 0,
146 should_close: RwLock::new(true)
147 })
148 }
149
150 pub async fn new(module_manager: Arc<ModuleManager>, render_manager: Arc<RenderingManager>, socket_manager: Arc<SocketManager>, config: Arc<Config>, device_config: UniqueDeviceConfig, image_collection: ImageCollection, mut connection: StreamDeck, frame_rate: u32) -> Arc<SDCore> {
152 let (key_tx, mut key_rx) = unbounded_channel();
153
154 let serial_number = device_config.read().await.serial.to_string();
155 let serial_number = connection.serial().unwrap_or_else(|_| serial_number);
156
157 module_manager.send_global_event_to_modules(SDGlobalEvent::DeviceConnected {
158 serial_number: serial_number.clone()
159 }).await;
160
161 let core = Arc::new(SDCore {
162 serial_number,
163 module_manager,
164 render_manager,
165 socket_manager,
166 config,
167 device_config,
168 current_stack: Mutex::new(vec![]),
169 handles: Mutex::new(None),
170 image_size: connection.image_size(),
171 image_collection,
172 kind: connection.kind(),
173 key_count: connection.kind().keys(),
174 frame_rate,
175 should_close: RwLock::new(false)
176 });
177
178 let renderer = spawn_device_thread(core.clone(), connection, key_tx);
179
180 *core.handles.lock().await = Some(
181 ThreadHandles {
182 renderer
183 }
184 );
185
186 let task_core = CoreHandle::wrap(core.clone());
187 tokio::spawn(async move {
188 loop {
189 if task_core.core().is_closed().await {
190 break
191 }
192
193 if let Some((key, state)) = key_rx.recv().await {
194 if state {
195 task_core.button_down(key).await;
196 } else {
197 task_core.button_up(key).await;
198 }
199 } else {
200 break;
201 }
202 }
203 });
204
205 core
206 }
207
208 pub async fn mark_for_redraw(&self) {
210 let handles = self.handles.lock().await;
211
212 handles.as_ref().unwrap().renderer.send(vec![DeviceThreadCommunication::RefreshScreen]);
213 }
214
215 pub async fn send_commands(&self, commands: Vec<DeviceThreadCommunication>) {
217 let handles = self.handles.lock().await;
218
219 handles.as_ref().unwrap().renderer.send(commands);
220 }
221
222 pub async fn serial_number(&self) -> String {
224 self.device_config.read().await.serial.to_string()
225 }
226
227 pub async fn is_closed(&self) -> bool {
229 *self.should_close.read().await
230 }
231
232 pub async fn close(&self) {
234 self.module_manager.send_global_event_to_modules(SDGlobalEvent::DeviceDisconnected {
235 serial_number: self.serial_number.to_string()
236 }).await;
237
238 let mut lock = self.should_close.write().await;
239 *lock = true;
240 }
241}
242
243struct ThreadHandles {
244 pub renderer: DeviceThreadHandle
245}