1use std::collections::HashMap;
2use std::ops::DerefMut;
3use std::sync::Arc;
4use std::time::Instant;
5
6use image::{DynamicImage, Rgba};
7use serde::de::Error as DeError;
8use serde_json::{Map, Value};
9use serde_json::Error as JSONError;
10use tokio::sync::MutexGuard;
11
12use crate::{Config, ModuleManager, SDCore, SocketManager};
13use crate::core::{ButtonPanel, UniqueButton};
14use crate::core::button::{Button, parse_unique_button_to_component};
15use crate::modules::{features_to_vec, UniqueSDModule};
16use crate::modules::components::{UIPathValue, UIValue};
17use crate::modules::core_module::CoreSettings;
18use crate::modules::events::SDCoreEvent;
19use crate::thread::DeviceThreadCommunication;
20use crate::thread::rendering::{draw_background, draw_custom_renderer_texture, draw_foreground, draw_missing_texture, RendererComponent};
21use crate::thread::util::image_from_solid;
22use crate::util::{add_array_function, button_to_raw, change_from_path, convert_value_to_path, deserialize_panel, make_button_unique, panel_to_raw, remove_array_function, serialize_panel, set_value_function};
23use crate::versions::SUPPORTED_FEATURES;
24
25#[derive(Clone)]
27pub struct CoreHandle {
28 pub(crate) core: Arc<SDCore>,
29 pub(crate) module_name: String,
30 pub(crate) module_features: Vec<(String, String)>,
31}
32
33pub fn check_feature_list_for_feature(features: &Vec<(String, String)>, feature: &str) -> bool {
35 for (feat, _) in features {
36 if *feat == feature {
37 return true;
38 }
39 }
40
41 false
42}
43
44pub fn warn_for_feature(module_name: &str, features: &Vec<(String, String)>, feature: &str) {
46 if !check_feature_list_for_feature(features, feature) {
47 log::warn!("Module '{}' is using unreported feature '{}', please add the feature into plugin metadata to prevent any future crashes due to version incompatibility", module_name, feature);
48 }
49}
50
51impl CoreHandle {
52 pub fn wrap(core: Arc<SDCore>) -> CoreHandle {
54 CoreHandle {
55 core,
56 module_name: "-system-".to_string(),
57 module_features: features_to_vec(SUPPORTED_FEATURES)
58 }
59 }
60
61 pub fn check_for_feature(&self, feature: &str) -> bool {
63 check_feature_list_for_feature(&self.module_features, feature)
64 }
65
66 pub fn required_feature(&self, feature: &str) {
68 warn_for_feature(&self.module_name, &self.module_features, feature)
69 }
70
71 pub fn clone_for(&self, module: &UniqueSDModule) -> CoreHandle {
73 CoreHandle {
74 core: self.core.clone(),
75 module_name: module.name(),
76 module_features: module.metadata().used_features
77 }
78 }
79
80 pub fn core(&self) -> Arc<SDCore> {
82 self.required_feature("core");
83 self.core.clone()
84 }
85
86 pub fn config(&self) -> Arc<Config> {
88 self.required_feature("config");
89 self.core.config.clone()
90 }
91
92 pub fn module_manager(&self) -> Arc<ModuleManager> {
94 self.required_feature("module_manager");
95 self.core.module_manager.clone()
96 }
97
98 pub fn socket_manager(&self) -> Arc<SocketManager> {
100 self.required_feature("socket_api");
101 self.core.socket_manager.clone()
102 }
103
104 pub async fn current_stack(&self) -> MutexGuard<'_, Vec<ButtonPanel>> {
106 self.required_feature("core");
107 self.core.current_stack.lock().await
108 }
109
110 pub async fn send_core_event_to_modules<T: Iterator<Item=UniqueSDModule> + Send + 'static>(&self, event: SDCoreEvent, modules: T) {
112 let core = self.clone();
113 for module in modules {
114 if module.name() == core.module_name {
115 continue;
116 }
117
118 let task_core = core.clone_for(&module);
119 let task_event = event.clone();
120 tokio::spawn(async move {
121 module.event(task_core, task_event).await;
122 });
123 }
124 }
125
126 pub async fn get_stack(&self) -> Vec<ButtonPanel> {
128 self.required_feature("core_methods");
129 let stack = self.current_stack().await;
130
131 stack.iter().map(|x| x.clone()).collect()
132 }
133
134 pub async fn get_current_screen(&self) -> Option<ButtonPanel> {
136 self.required_feature("core_methods");
137 let stack = self.current_stack().await;
138
139 if let Some(screen) = stack.last() {
140 Some(screen.clone())
141 } else {
142 None
143 }
144 }
145
146 pub async fn get_button(&self, key: u8) -> Option<UniqueButton> {
148 self.required_feature("core_methods");
149 if let Some(screen) = self.get_current_screen().await {
150 let handle = screen.read().await;
151 handle.buttons.get(&key).cloned()
152 } else {
153 None
154 }
155 }
156
157 pub async fn set_button(&self, key: u8, button: UniqueButton) -> bool {
159 self.required_feature("core_methods");
160 if let Some(screen) = self.get_current_screen().await {
161 let mut handle = screen.write().await;
162 let previous_button = handle.buttons.get(&key).cloned();
163
164 handle.buttons.insert(key, button.clone());
165
166 drop(handle);
167
168 if let Some(previous_button) = previous_button {
169 self.send_core_event_to_modules(SDCoreEvent::ButtonUpdated {
170 key,
171 panel: screen.clone(),
172 new_button: button.clone(),
173 old_button: previous_button.clone()
174 }, self.module_manager().get_module_list().await.into_iter()).await;
175 } else {
176 self.send_core_event_to_modules( SDCoreEvent::ButtonAdded {
177 key,
178 panel: screen.clone(),
179 added_button: button.clone()
180 }, self.module_manager().get_module_list().await.into_iter()).await;
181 }
182
183 self.core.mark_for_redraw().await;
184
185 true
186 } else {
187 false
188 }
189 }
190
191 pub async fn clear_button(&self, key: u8) -> bool {
193 self.required_feature("core_methods");
194 if let Some(screen) = self.get_current_screen().await {
195 let mut handle = screen.write().await;
196 if let Some(button) = handle.buttons.remove(&key) {
197 drop(handle);
198
199 self.send_core_event_to_modules( SDCoreEvent::ButtonDeleted {
200 key,
201 panel: screen.clone(),
202 deleted_button: button.clone()
203 }, self.module_manager().get_module_list().await.into_iter()).await;
204
205 self.core.mark_for_redraw().await;
206
207 true
208 } else {
209 false
210 }
211 } else {
212 false
213 }
214 }
215
216 pub async fn add_component(&self, key: u8, component_name: &str) -> bool {
218 self.required_feature("core_methods");
219
220 let module_manager = self.module_manager();
221
222 if let Some(screen) = self.get_current_screen().await {
223 let handle = screen.read().await;
224 if let Some(button) = handle.buttons.get(&key).cloned() {
225 let previous = make_button_unique(button_to_raw(&button).await);
226
227 let mut button_handle = button.write().await;
228 drop(handle);
229
230 if !button_handle.component_names().contains(&component_name.to_string()) {
231 let components = module_manager.read_component_map().await;
232
233 if let Some((_, module)) = components.get(component_name) {
234 module.add_component(self.clone_for(&module), button_handle.deref_mut(), component_name).await;
235
236 drop(button_handle);
237 drop(components);
238
239 self.send_core_event_to_modules(SDCoreEvent::ButtonUpdated {
240 key,
241 panel: screen.clone(),
242 new_button: button.clone(),
243 old_button: previous.clone()
244 }, self.module_manager().get_module_list().await.into_iter()).await;
245
246 self.core.mark_for_redraw().await;
247
248 return true;
249 }
250 }
251 }
252 }
253
254 false
255 }
256
257 pub async fn get_component_values(&self, key: u8, component_name: &str) -> Option<Vec<UIValue>> {
259 self.required_feature("core_methods");
260
261 let module_manager = self.module_manager();
262
263 if let Some(screen) = self.get_current_screen().await {
264 let handle = screen.read().await;
265 if let Some(button) = handle.buttons.get(&key).cloned() {
266 let mut button_handle = button.write().await;
267 drop(handle);
268
269 if button_handle.component_names().contains(&component_name.to_string()) {
270 let components = module_manager.read_component_map().await;
271
272 if let Some((_, module)) = components.get(component_name) {
273 return Some(module.component_values(self.clone_for(&module), button_handle.deref_mut(), component_name).await);
274 }
275 }
276 }
277 }
278
279 None
280 }
281
282 pub async fn get_component_values_with_paths(&self, key: u8, component_name: &str) -> Option<Vec<UIPathValue>> {
284 self.required_feature("core_methods");
285
286 if let Some(values) = self.get_component_values(key, component_name).await {
287 Some(values.into_iter().map(|x| convert_value_to_path(x, "")).collect())
288 } else {
289 None
290 }
291 }
292
293 pub async fn set_component_value(&self, key: u8, component_name: &str, value: Vec<UIValue>) -> bool {
295 self.required_feature("core_methods");
296
297 let module_manager = self.module_manager();
298
299 if let Some(screen) = self.get_current_screen().await {
300 let handle = screen.read().await;
301 if let Some(button) = handle.buttons.get(&key).cloned() {
302 let previous = make_button_unique(button_to_raw(&button).await);
303
304 let mut button_handle = button.write().await;
305 drop(handle);
306
307 if button_handle.component_names().contains(&component_name.to_string()) {
308 let components = module_manager.read_component_map().await;
309
310 if let Some((_, module)) = components.get(component_name) {
311 module.set_component_value(self.clone_for(&module), button_handle.deref_mut(), component_name, value).await;
312 drop(button_handle);
313 drop(components);
314
315 self.send_core_event_to_modules(SDCoreEvent::ButtonUpdated {
316 key,
317 panel: screen.clone(),
318 new_button: button.clone(),
319 old_button: previous.clone()
320 }, self.module_manager().get_module_list().await.into_iter()).await;
321
322 self.core.mark_for_redraw().await;
323
324 return true;
325 }
326 }
327 }
328 }
329
330 false
331 }
332
333 pub async fn add_element_component_value(&self, key: u8, component_name: &str, path: &str) -> bool {
335 self.required_feature("core_methods");
336
337 if let Some(values) = self.get_component_values(key, component_name).await {
338 let (changes, success) = change_from_path(path, values, &add_array_function(), false);
339
340 if success {
341 if !changes.is_empty() {
342 self.set_component_value(key, component_name, changes).await
343 } else {
344 false
345 }
346 } else {
347 false
348 }
349 } else {
350 false
351 }
352 }
353
354 pub async fn remove_element_component_value(&self, key: u8, component_name: &str, path: &str, index: usize) -> bool {
356 self.required_feature("core_methods");
357
358 if let Some(values) = self.get_component_values(key, component_name).await {
359 let (changes, success) = change_from_path(path, values, &remove_array_function(index), false);
360
361 if success {
362 if !changes.is_empty() {
363 self.set_component_value(key, component_name, changes).await
364 } else {
365 false
366 }
367 } else {
368 false
369 }
370 } else {
371 false
372 }
373 }
374
375 pub async fn set_component_value_by_path(&self, key: u8, component_name: &str, value: UIPathValue) -> bool {
377 self.required_feature("core_methods");
378
379 if let Some(values) = self.get_component_values(key, component_name).await {
380 let (changes, success) = change_from_path(&value.path, values, &set_value_function(value.clone()), false);
381
382 if success {
383 if !changes.is_empty() {
384 self.set_component_value(key, component_name, changes).await
385 } else {
386 false
387 }
388 } else {
389 false
390 }
391 } else {
392 false
393 }
394 }
395
396 pub async fn remove_component(&self, key: u8, component_name: &str) -> bool {
398 self.required_feature("core_methods");
399
400 let module_manager = self.module_manager();
401
402 if let Some(screen) = self.get_current_screen().await {
403 let handle = screen.read().await;
404 if let Some(button) = handle.buttons.get(&key).cloned() {
405 let previous = make_button_unique(button_to_raw(&button).await);
406
407 let mut button_handle = button.write().await;
408 drop(handle);
409
410 if button_handle.component_names().contains(&component_name.to_string()) {
411 let components = module_manager.read_component_map().await;
412
413 if let Some((_, module)) = components.get(component_name) {
414 module.remove_component(self.clone_for(&module), button_handle.deref_mut(), component_name).await;
415
416 drop(button_handle);
417 drop(components);
418
419 self.send_core_event_to_modules(SDCoreEvent::ButtonUpdated {
420 key,
421 panel: screen.clone(),
422 new_button: button.clone(),
423 old_button: previous.clone()
424 }, self.module_manager().get_module_list().await.into_iter()).await;
425
426 self.core.mark_for_redraw().await;
427
428 return true;
429 }
430 }
431 }
432 }
433
434 false
435 }
436
437 pub async fn paste_button(&self, key: u8, reference_button: &Button) -> bool {
439 let mut new_button = Button::new();
440
441 let responsible_modules = self.module_manager().get_modules_for_declared_components(reference_button.component_names().as_slice()).await;
442 for module in responsible_modules {
443 module.paste_component(self.clone_for(&module), reference_button, &mut new_button).await;
444 }
445
446 println!("resulting button: {:?}", new_button);
447
448 self.set_button(key, make_button_unique(new_button)).await
449 }
450
451 pub async fn push_screen(&self, screen: ButtonPanel) {
453 self.required_feature("core_methods");
454 let mut stack = self.current_stack().await;
455
456 stack.push(screen.clone());
457 drop(stack);
458
459 self.send_core_event_to_modules(SDCoreEvent::PanelPushed {
460 new_panel: screen.clone()
461 }, self.module_manager().get_module_list().await.into_iter()).await;
462
463 self.core.mark_for_redraw().await;
464 }
465
466 pub async fn pop_screen(&self) {
468 self.required_feature("core_methods");
469 let mut stack = self.current_stack().await;
470
471 let old_panel = stack.pop();
472 drop(stack);
473
474 if let Some(old_panel) = old_panel {
475 self.send_core_event_to_modules(SDCoreEvent::PanelPopped {
476 popped_panel: old_panel.clone()
477 }, self.module_manager().get_module_list().await.into_iter()).await;
478 }
479
480 self.core.mark_for_redraw().await;
481 }
482
483 pub async fn get_root_screen(&self) -> ButtonPanel {
485 self.required_feature("core_methods");
486 let stack = self.current_stack().await;
487 stack.get(0).unwrap().clone()
488 }
489
490 pub async fn save_panels_to_value(&self) -> Value {
492 self.required_feature("core_methods");
493 let stack = self.current_stack().await;
494
495 if let Some(panel) = stack.get(0) {
496 let serialized_panel = serialize_panel(panel.clone()).await.unwrap();
497 serde_json::to_value(&serialized_panel).unwrap()
498 } else {
499 Value::Object(Map::new())
500 }
501 }
502
503 pub async fn reset_stack(&self, panel: ButtonPanel) {
505 self.required_feature("core_methods");
506 let mut stack = self.current_stack().await;
507
508 stack.clear();
509 stack.push(panel.clone());
510 drop(stack);
511
512 self.send_core_event_to_modules(SDCoreEvent::StackReset {
513 new_panel: panel.clone()
514 }, self.module_manager().get_module_list().await.into_iter()).await;
515
516 self.core.mark_for_redraw().await;
517 }
518
519 pub async fn load_panels_from_value(&self, panels: Value) -> Result<(), JSONError> {
521 self.required_feature("core_methods");
522 match deserialize_panel(panels) {
523 Ok(panel) => {
524 let mut stack = self.current_stack().await;
525
526 stack.clear();
527 stack.push(panel.clone());
528 drop(stack);
529
530 self.send_core_event_to_modules(SDCoreEvent::StackReset {
531 new_panel: panel.clone()
532 }, self.module_manager().get_module_list().await.into_iter()).await;
533
534 self.core.mark_for_redraw().await;
535
536 Ok(())
537 }
538 Err(err) => {
539 Err(DeError::custom(format!("Failed to load panels: {}", err)))
540 }
541 }
542 }
543
544 pub async fn button_down(&self, key: u8) {
546 self.required_feature("core_methods");
547 self.send_core_event_to_modules(SDCoreEvent::ButtonDown {
548 key
549 }, self.module_manager().get_module_list().await.into_iter()).await;
550 }
551
552 pub async fn button_up(&self, key: u8) {
554 self.required_feature("core_methods");
555 self.send_core_event_to_modules(SDCoreEvent::ButtonUp {
556 key
557 }, self.module_manager().get_module_list().await.into_iter()).await;
558
559 self.button_action(key).await;
560 }
561
562 pub async fn button_action(&self, key: u8) {
564 self.required_feature("core_methods");
565 if let Some(screen) = self.get_current_screen().await {
566 let handle = screen.read().await;
567 if let Some(button) = handle.buttons.get(&key).cloned() {
568 drop(handle);
569
570 let event = SDCoreEvent::ButtonAction {
571 key,
572 panel: screen.clone(),
573 pressed_button: button.clone()
574 };
575
576 self.send_core_event_to_modules(
577 event.clone(),
578 self.module_manager()
579 .get_modules_for_components(button.read().await.component_names().as_slice()).await
580 .into_iter()
581 ).await;
582 self.core.mark_for_redraw().await;
585 }
586 }
587 }
588
589 pub async fn get_button_images(&self) -> Option<HashMap<u8, DynamicImage>> {
591 let missing = draw_missing_texture(self.core.image_size);
592 let custom = draw_custom_renderer_texture(self.core.image_size);
593 let blank = image_from_solid(self.core.image_size, Rgba([0, 0, 0, 255]));
594
595 let panel = self.get_current_screen().await?;
596 let current_screen = panel.read().await;
597 let buttons = current_screen.buttons.clone();
598
599 let renderers = self.core.render_manager.read_renderers().await;
600
601 let core_settings: CoreSettings = self.core.config.get_plugin_settings().await.unwrap_or_default();
602
603
604 let mut images = HashMap::new();
605
606 for (key, button) in buttons {
607 if let Ok(component) = parse_unique_button_to_component::<RendererComponent>(&button).await {
608 let modules = self.module_manager()
609 .get_modules_for_rendering(
610 &button.read().await.component_names()
611 ).await;
612 let modules = modules.into_values()
613 .filter(|x| !component.plugin_blacklist.contains(&x.name()))
614 .filter(|x| !core_settings.renderer.plugin_blacklist.contains(&x.name()))
615 .collect::<Vec<UniqueSDModule>>();
616
617 let image = if component.renderer.is_empty() {
618 draw_foreground(
619 &component,
620 &button,
621 &modules,
622 draw_background(
623 &component,
624 self,
625 &missing
626 ).await,
627 self
628 ).await
629 } else {
630 if let Some(renderer) = renderers.get(&component.renderer) {
631 if let Some(image) = renderer.representation(key, &button, self).await {
632 image
633 } else {
634 custom.clone()
635 }
636 } else {
637 custom.clone()
638 }
639 };
640
641 images.insert(key, image);
642 } else {
643 images.insert(key, blank.clone());
644 }
645 }
646
647
648 Some(images)
649 }
650
651 pub async fn get_button_image(&self, key: u8) -> Option<DynamicImage> {
653 let missing = draw_missing_texture(self.core.image_size);
654 let custom = draw_custom_renderer_texture(self.core.image_size);
655 let blank = image_from_solid(self.core.image_size, Rgba([0, 0, 0, 255]));
656
657 let button = self.get_button(key).await?;
658 let renderers = self.core.render_manager.read_renderers().await;
659
660 let core_settings: CoreSettings = self.core.config.get_plugin_settings().await.unwrap_or_default();
661
662 if let Ok(component) = parse_unique_button_to_component::<RendererComponent>(&button).await {
663 let modules = self.module_manager().get_modules_for_rendering(&button.read().await.component_names()).await;
664 let modules = modules.into_values()
665 .filter(|x| !component.plugin_blacklist.contains(&x.name()))
666 .filter(|x| !core_settings.renderer.plugin_blacklist.contains(&x.name()))
667 .collect::<Vec<UniqueSDModule>>();
668
669 let image = if component.renderer.is_empty() {
670 draw_foreground(
671 &component,
672 &button,
673 &modules,
674 draw_background(
675 &component,
676 self,
677 &missing
678 ).await,
679 self
680 ).await
681 } else {
682 if let Some(renderer) = renderers.get(&component.renderer) {
683 if let Some(image) = renderer.representation(key, &button, self).await {
684 image
685 } else {
686 custom.clone()
687 }
688 } else {
689 custom.clone()
690 }
691 };
692
693 Some(image)
694 } else {
695 Some(blank)
696 }
697 }
698
699 pub async fn replace_screen(&self, screen: ButtonPanel) {
701 self.required_feature("core_methods");
702 let mut stack = self.current_stack().await;
703
704 let old_panel = stack.pop();
705 stack.push(screen.clone());
706
707 self.send_core_event_to_modules(SDCoreEvent::PanelReplaced {
708 old_panel,
709 new_panel: screen
710 }, self.module_manager().get_module_list().await.into_iter()).await;
711
712 self.core.mark_for_redraw().await;
713 }
714
715 pub async fn set_brightness(&self, brightness: u8) {
717 self.required_feature("core_methods");
718 self.core.send_commands(vec![DeviceThreadCommunication::SetBrightness(brightness)]).await;
719
720 let mut handle = self.core.device_config.write().await;
721 handle.brightness = brightness;
722 }
723
724 pub async fn commit_changes(&self) {
726 self.required_feature("core_methods");
727 let stack = self.get_root_screen().await;
728
729 let mut handle = self.core.device_config.write().await;
730 handle.layout = panel_to_raw(&stack).await;
731
732 handle.dirty_state = true;
733 handle.commit_time = Some(Instant::now());
734 log::debug!("new commit to {}", handle.serial);
735 }
736}