diff --git a/src-tauri/src/ambient_light/publisher.rs b/src-tauri/src/ambient_light/publisher.rs index 08c1cd1..899b33f 100644 --- a/src-tauri/src/ambient_light/publisher.rs +++ b/src-tauri/src/ambient_light/publisher.rs @@ -1,17 +1,20 @@ -use std::sync::Arc; +use std::{borrow::BorrowMut, collections::HashMap, sync::Arc, time::Duration}; use paris::warn; -use tauri::async_runtime::RwLock; -use tokio::sync::watch; +use tauri::async_runtime::{Mutex, RwLock}; +use tokio::{sync::watch, time::sleep}; use crate::{ ambient_light::{config, ConfigManager}, rpc::MqttRpc, + screenshot::Screenshot, screenshot_manager::ScreenshotManager, }; use itertools::Itertools; +use super::{LedStripConfigGroup, SamplePointConfig}; + pub struct LedColorsPublisher { rx: Arc>>>, tx: Arc>>>, @@ -37,76 +40,85 @@ impl LedColorsPublisher { pub fn start(&self) -> anyhow::Result<()> { let tx = self.tx.clone(); - tokio::spawn(async move { - let tx = tx.write().await; + let handler = tokio::spawn(async move { + loop { + log::info!("colors update loop AAA"); - let screenshot_manager = ScreenshotManager::global().await; + let tx = tx.write().await; + let screenshot_manager = ScreenshotManager::global().await; + + let config_manager = ConfigManager::global().await; + let config_receiver = config_manager.clone_config_update_receiver(); + let configs = config_receiver.borrow().clone(); + let configs = Self::get_colors_configs(&configs).await; + + let mut some_screenshot_receiver_is_none = false; + + loop { + let mut screenshots = Vec::new(); + + for rx in configs.screenshot_receivers.to_owned() { + let mut rx = rx.lock_owned().await; + if rx.is_none() { + some_screenshot_receiver_is_none = true; + warn!("screenshot receiver is none"); + continue; + } + + let rx = rx.as_mut().unwrap(); + + if let Err(err) = rx.changed().await { + warn!("rx changed error: {}", err); + continue; + } + log::info!("screenshot updated"); + + let screenshot = rx.borrow().clone(); + + screenshots.push(screenshot); + } + + let colors = screenshot_manager + .get_all_colors( + &configs.sample_point_groups, + &configs.mappers, + &screenshots, + ) + .await; + match tx.send(colors) { + Ok(_) => { + // log::info!("colors updated"); + } + Err(_) => { + warn!("colors update failed"); + } + } + + if some_screenshot_receiver_is_none + || config_receiver.has_changed().unwrap_or(true) + { + break; + } + } + } + }); + + tokio::spawn(async move { let config_manager = ConfigManager::global().await; + let mut config_receiver = config_manager.clone_config_update_receiver(); + loop { - let configs = config_manager.configs().await; - let channels = screenshot_manager.channels.read().await; - - let display_ids = configs - .strips - .iter() - .map(|c| c.display_id) - .unique().collect::>(); - - let mut colors_configs = Vec::new(); - - for display_id in display_ids { - let led_strip_configs: Vec<_> = configs - .strips - .iter() - .filter(|c| c.display_id == display_id) - .collect(); - - let rx = channels.get(&display_id); - - if rx.is_none() { - warn!("no channel for display_id: {}", display_id); - continue; - } - - let rx = rx.unwrap(); - - if led_strip_configs.len() == 0 { - warn!("no led strip config for display_id: {}", display_id); - continue; - } - - let mut rx = rx.clone(); - - if rx.changed().await.is_ok() { - let screenshot = rx.borrow().clone(); - // log::info!("screenshot updated: {:?}", display_id); - - let points: Vec<_> = led_strip_configs - .iter() - .map(|config| screenshot.get_sample_points(&config)) - .flatten() - .collect(); - - let colors_config = config::SamplePointConfig { - display_id, - points, - }; - - colors_configs.push(colors_config); - } - } - let colors = screenshot_manager - .get_all_colors(&colors_configs, &configs.mappers, &channels) - .await; - match tx.send(colors) { - Ok(_) => { - // log::info!("colors updated"); - } - Err(_) => { - warn!("colors update failed"); - } + if let Err(err) = config_receiver.changed().await { + warn!("config receiver changed error: {}", err); + continue; } + + let configs = config_receiver.borrow().clone(); + let configs = Self::get_colors_configs(&configs).await; + + handler.abort(); + break; } }); Ok(()) @@ -121,4 +133,78 @@ impl LedColorsPublisher { pub async fn clone_receiver(&self) -> watch::Receiver> { self.rx.read().await.clone() } + + pub async fn get_colors_configs(configs: &LedStripConfigGroup) -> AllColorConfig { + let screenshot_manager = ScreenshotManager::global().await; + + let channels = screenshot_manager.channels.read().await; + + let display_ids = configs + .strips + .iter() + .map(|c| c.display_id) + .unique() + .collect::>(); + + let mappers = configs.mappers.clone(); + + let mut local_rx_list = Vec::new(); + let mut colors_configs = Vec::new(); + + for display_id in display_ids.clone().iter() { + let display_id = *display_id; + + let channel = channels.get(&display_id); + let channel = match channel { + Some(channel) => Some(channel.clone()), + None => None, + }; + local_rx_list.push(Arc::new(Mutex::new(channel.clone()))); + + let led_strip_configs: Vec<_> = configs + .strips + .iter() + .filter(|c| c.display_id == display_id) + .collect(); + + let rx = channel; + if rx.is_none() { + warn!("no channel for display_id: {}", display_id); + continue; + } + + if led_strip_configs.len() == 0 { + warn!("no led strip config for display_id: {}", display_id); + continue; + } + let mut rx = rx.unwrap().to_owned(); + + if rx.changed().await.is_ok() { + let screenshot = rx.borrow().clone(); + log::info!("screenshot updated: {:?}", display_id); + + let points: Vec<_> = led_strip_configs + .iter() + .map(|config| screenshot.get_sample_points(&config)) + .flatten() + .collect(); + + let colors_config = config::SamplePointConfig { display_id, points }; + + colors_configs.push(colors_config); + } + } + + return AllColorConfig { + sample_point_groups: colors_configs, + mappers, + screenshot_receivers: local_rx_list, + }; + } +} + +pub struct AllColorConfig { + pub sample_point_groups: Vec, + pub mappers: Vec, + pub screenshot_receivers: Vec>>>>, } diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 06f2ecc..8732abe 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -130,21 +130,6 @@ async fn get_one_edge_colors( } } -#[tauri::command] -async fn get_all_colors( - configs: Vec, - mappers: Vec, -) -> Result, String> { - let screenshot_manager = ScreenshotManager::global().await; - - let channels = screenshot_manager.channels.to_owned(); - let channels = channels.read().await; - - Ok(screenshot_manager - .get_all_colors(&configs, &mappers, &channels) - .await) -} - #[tauri::command] async fn patch_led_strip_len(display_id: u32, border: Border, delta_len: i8) -> Result<(), String> { info!( @@ -195,7 +180,6 @@ async fn main() { get_one_edge_colors, patch_led_strip_len, send_colors, - get_all_colors ]) .register_uri_scheme_protocol("ambient-light", move |_app, request| { let response = ResponseBuilder::new().header("Access-Control-Allow-Origin", "*"); @@ -356,7 +340,9 @@ async fn main() { let publisher = publisher_update_receiver.borrow().clone(); - app_handle.emit_all("led_colors_changed", publisher).unwrap(); + app_handle + .emit_all("led_colors_changed", publisher) + .unwrap(); } }); diff --git a/src-tauri/src/screenshot_manager.rs b/src-tauri/src/screenshot_manager.rs index b0139ed..958dcf0 100644 --- a/src-tauri/src/screenshot_manager.rs +++ b/src-tauri/src/screenshot_manager.rs @@ -209,6 +209,7 @@ impl ScreenshotManager { let screenshot = take_screenshot(display_id, scale_factor); if let Ok(screenshot) = screenshot { tx.send(screenshot).unwrap(); + log::info!("take_screenshot_loop: send success. display#{}", display_id) } else { warn!("take_screenshot_loop: {}", screenshot.err().unwrap()); } @@ -218,7 +219,7 @@ impl ScreenshotManager { &self, configs: &Vec, mappers: &Vec, - channels: &HashMap>, + screenshots: &Vec, ) -> Vec { let total_leds = configs .iter() @@ -227,17 +228,8 @@ impl ScreenshotManager { let mut global_colors = vec![0u8; total_leds * 3]; let mut all_colors = vec![]; - for config in configs { - let rx = channels.get(&config.display_id); - if rx.is_none() { - error!( - "get_all_colors: can not find display_id {}", - config.display_id - ); - continue; - } - let rx = rx.unwrap(); - let screenshot = rx.borrow().clone(); + for (index, screenshot) in screenshots.iter().enumerate() { + let config = &configs[index]; let mut colors = screenshot.get_colors_by_sample_points(&config.points).await; all_colors.append(&mut colors); @@ -246,7 +238,12 @@ impl ScreenshotManager { let mut color_index = 0; mappers.iter().for_each(|group| { if group.end > all_colors.len() || group.start > all_colors.len() { - warn!("get_all_colors: group out of range. start: {}, end: {}, all_colors.len(): {}", group.start, group.end, all_colors.len()); + warn!( + "get_all_colors: group out of range. start: {}, end: {}, all_colors.len(): {}", + group.start, + group.end, + all_colors.len() + ); return; } if group.end > group.start { diff --git a/src/components/led-strip-parts-sorter.tsx b/src/components/led-strip-parts-sorter.tsx index 9fba54c..9b8f8af 100644 --- a/src/components/led-strip-parts-sorter.tsx +++ b/src/components/led-strip-parts-sorter.tsx @@ -18,34 +18,16 @@ const SorterItem: Component<{ mapper: LedStripPixelMapper; strip: LedStripConfig const [fullLeds, setFullLeds] = createSignal([]); createEffect(() => { - let stopped = false; - const frame = () => { - untrack(() => { - const strips = ledStripStore.strips; - const totalLedCount = strips.reduce((acc, strip) => acc + strip.len, 0); - const fullLeds = new Array(totalLedCount).fill('rgba(255,255,255,0.5)'); + const strips = ledStripStore.strips; + const totalLedCount = strips.reduce((acc, strip) => acc + strip.len, 0); + const fullLeds = new Array(totalLedCount).fill('rgba(255,255,255,0.5)'); - for (let i = props.mapper.start, j = 0; i < props.mapper.end; i++, j++) { - fullLeds[i] = `rgb(${ledStripStore.colors[i * 3]}, ${ - ledStripStore.colors[i * 3 + 1] - }, ${ledStripStore.colors[i * 3 + 2]})`; - } - setFullLeds(fullLeds); - }); - - if (!stopped) { - setTimeout(() => { - frame(); - }, 1000); - } - }; - - frame(); - - onCleanup(() => { - console.log('cleanup'); - stopped = true; - }); + for (let i = props.mapper.start, j = 0; i < props.mapper.end; i++, j++) { + fullLeds[i] = `rgb(${ledStripStore.colors[i * 3]}, ${ + ledStripStore.colors[i * 3 + 1] + }, ${ledStripStore.colors[i * 3 + 2]})`; + } + setFullLeds(fullLeds); }); return (