diff --git a/src-tauri/src/ambient_light/publisher.rs b/src-tauri/src/ambient_light/publisher.rs index 406fbcc..5445b1d 100644 --- a/src-tauri/src/ambient_light/publisher.rs +++ b/src-tauri/src/ambient_light/publisher.rs @@ -1,6 +1,6 @@ use std::{sync::Arc, time::Duration}; -use paris::warn; +use paris::{info, warn}; use tauri::async_runtime::{Mutex, RwLock}; use tokio::{sync::watch, time::sleep}; @@ -8,7 +8,7 @@ use crate::{ ambient_light::{config, ConfigManager}, rpc::MqttRpc, screenshot::Screenshot, - screenshot_manager::ScreenshotManager, + screenshot_manager::ScreenshotManager, led_color::LedColor, }; use itertools::Itertools; @@ -16,8 +16,10 @@ use itertools::Itertools; use super::{LedStripConfigGroup, SamplePointConfig}; pub struct LedColorsPublisher { - rx: Arc>>>, - tx: Arc>>>, + sorted_colors_rx: Arc>>>, + sorted_colors_tx: Arc>>>, + colors_rx: Arc>>>, + colors_tx: Arc>>>, } impl LedColorsPublisher { @@ -25,26 +27,29 @@ impl LedColorsPublisher { static LED_COLORS_PUBLISHER_GLOBAL: tokio::sync::OnceCell = tokio::sync::OnceCell::const_new(); + let (sorted_tx, sorted_rx) = watch::channel(Vec::new()); let (tx, rx) = watch::channel(Vec::new()); LED_COLORS_PUBLISHER_GLOBAL .get_or_init(|| async { LedColorsPublisher { - rx: Arc::new(RwLock::new(rx)), - tx: Arc::new(RwLock::new(tx)), + sorted_colors_rx: Arc::new(RwLock::new(sorted_rx)), + sorted_colors_tx: Arc::new(RwLock::new(sorted_tx)), + colors_rx: Arc::new(RwLock::new(rx)), + colors_tx: Arc::new(RwLock::new(tx)), } }) .await } pub fn start(&self) { - let tx = self.tx.clone(); + let sorted_colors_tx = self.sorted_colors_tx.clone(); + let colors_tx = self.colors_tx.clone(); tokio::spawn(async move { loop { - log::info!("colors update loop AAA"); - - let tx = tx.write().await; + let sorted_colors_tx = sorted_colors_tx.write().await; + let colors_tx = colors_tx.write().await; let screenshot_manager = ScreenshotManager::global().await; let config_manager = ConfigManager::global().await; @@ -79,13 +84,13 @@ impl LedColorsPublisher { } let colors = screenshot_manager - .get_all_colors( - &configs.sample_point_groups, - &configs.mappers, - &screenshots, - ) + .get_all_colors(&configs.sample_point_groups, &screenshots) .await; - match tx.send(colors) { + + let sorted_colors = + ScreenshotManager::get_sorted_colors(&colors, &configs.mappers).await; + + match colors_tx.send(colors) { Ok(_) => { // log::info!("colors updated"); } @@ -94,17 +99,31 @@ impl LedColorsPublisher { } } - if some_screenshot_receiver_is_none - || config_receiver.has_changed().unwrap_or(true) - { + match sorted_colors_tx.send(sorted_colors) { + Ok(_) => { + // log::info!("colors updated"); + } + Err(_) => { + warn!("colors update failed"); + } + } + + if some_screenshot_receiver_is_none { + info!("some screenshot receiver is none. reload."); sleep(Duration::from_millis(1000)).await; break; } + + if config_receiver.has_changed().unwrap_or(true) { + info!("config changed. reload."); + sleep(Duration::from_millis(100)).await; + break; + } } } }); - let rx = self.rx.clone(); + let rx = self.sorted_colors_rx.clone(); tokio::spawn(async move { let mut rx = rx.read().await.clone(); loop { @@ -136,8 +155,8 @@ impl LedColorsPublisher { mqtt.publish_led_sub_pixels(payload).await } - pub async fn clone_receiver(&self) -> watch::Receiver> { - self.rx.read().await.clone() + pub async fn clone_sorted_colors_receiver(&self) -> watch::Receiver> { + self.sorted_colors_rx.read().await.clone() } pub async fn get_colors_configs(configs: &LedStripConfigGroup) -> AllColorConfig { @@ -207,6 +226,10 @@ impl LedColorsPublisher { screenshot_receivers: local_rx_list, }; } + + pub async fn clone_colors_receiver(&self) -> watch::Receiver> { + self.colors_rx.read().await.clone() + } } pub struct AllColorConfig { diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 39a9e07..d20fc17 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -348,7 +348,24 @@ async fn main() { let app_handle = app.handle().clone(); tokio::spawn(async move { let publisher = ambient_light::LedColorsPublisher::global().await; - let mut publisher_update_receiver = publisher.clone_receiver().await; + let mut publisher_update_receiver = publisher.clone_sorted_colors_receiver().await; + loop { + if let Err(err) = publisher_update_receiver.changed().await { + error!("publisher update receiver changed error: {}", err); + return; + } + + let publisher = publisher_update_receiver.borrow().clone(); + + app_handle + .emit_all("led_sorted_colors_changed", publisher) + .unwrap(); + } + }); + let app_handle = app.handle().clone(); + tokio::spawn(async move { + let publisher = ambient_light::LedColorsPublisher::global().await; + let mut publisher_update_receiver = publisher.clone_colors_receiver().await; loop { if let Err(err) = publisher_update_receiver.changed().await { error!("publisher update receiver changed error: {}", err); diff --git a/src-tauri/src/screenshot_manager.rs b/src-tauri/src/screenshot_manager.rs index 8f9305d..ecd92a4 100644 --- a/src-tauri/src/screenshot_manager.rs +++ b/src-tauri/src/screenshot_manager.rs @@ -10,7 +10,7 @@ use tokio::sync::{watch, OnceCell}; use crate::{ ambient_light::{SamplePointConfig, SamplePointMapper}, - screenshot::{LedSamplePoints, ScreenSamplePoints, Screenshot, ScreenshotPayload}, + screenshot::{LedSamplePoints, ScreenSamplePoints, Screenshot, ScreenshotPayload}, led_color::LedColor, }; pub fn take_screenshot(display_id: u32, scale_factor: f32) -> anyhow::Result { @@ -218,14 +218,9 @@ impl ScreenshotManager { pub async fn get_all_colors( &self, configs: &Vec, - mappers: &Vec, screenshots: &Vec, - ) -> Vec { - let total_leds = configs - .iter() - .fold(0, |acc, config| acc + config.points.len()); + ) -> Vec { - let mut global_colors = vec![0u8; total_leds * 3]; let mut all_colors = vec![]; for (index, screenshot) in screenshots.iter().enumerate() { @@ -235,20 +230,31 @@ impl ScreenshotManager { all_colors.append(&mut colors); } + all_colors + } + + pub async fn get_sorted_colors(colors: &Vec, mappers: &Vec) -> Vec { + let total_leds = mappers + .iter() + .map(|mapper| mapper.end) + .max() + .unwrap_or(0) as usize; + let mut global_colors = vec![0u8; total_leds * 3]; + let mut color_index = 0; mappers.iter().for_each(|group| { - if group.end > all_colors.len() || group.start > all_colors.len() { + if group.end > colors.len() || group.start > colors.len() { warn!( - "get_all_colors: group out of range. start: {}, end: {}, all_colors.len(): {}", + "get_sorted_colors: group out of range. start: {}, end: {}, colors.len(): {}", group.start, group.end, - all_colors.len() + colors.len() ); return; } if group.end > group.start { for i in group.start..group.end { - let rgb = all_colors[color_index].get_rgb(); + let rgb = colors[color_index].get_rgb(); color_index += 1; global_colors[i * 3] = rgb[0]; @@ -257,7 +263,7 @@ impl ScreenshotManager { } } else { for i in (group.end..group.start).rev() { - let rgb = all_colors[color_index].get_rgb(); + let rgb = colors[color_index].get_rgb(); color_index += 1; global_colors[i * 3] = rgb[0]; diff --git a/src/App.tsx b/src/App.tsx index 16a1cbb..e8d509b 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -57,6 +57,21 @@ function App() { }); }); + // listen to led_sorted_colors_changed event + createEffect(() => { + const unlisten = listen>('led_sorted_colors_changed', (event) => { + const sortedColors = event.payload; + + setLedStripStore({ + sortedColors, + }); + }); + + onCleanup(() => { + unlisten.then((unlisten) => unlisten()); + }); + }); + const [ledStripConfiguration, setLedStripConfiguration] = createStore< LedStripConfigurationContextType[0] >({ diff --git a/src/components/led-strip-parts-sorter.tsx b/src/components/led-strip-parts-sorter.tsx index 68e01fb..b4e763a 100644 --- a/src/components/led-strip-parts-sorter.tsx +++ b/src/components/led-strip-parts-sorter.tsx @@ -88,9 +88,7 @@ const SorterItem: Component<{ strip: LedStripConfig; mapper: LedStripPixelMapper 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]})`; + fullLeds[i] = ledStripStore.colors[j]; } setFullLeds(fullLeds); }); @@ -131,15 +129,14 @@ const SorterResult: Component = () => { const [fullLeds, setFullLeds] = createSignal([]); createEffect(() => { - const strips = ledStripStore.strips; - const totalLedCount = strips.reduce((acc, strip) => acc + strip.len, 0); + const totalLedCount = Math.max(0, ...ledStripStore.mappers.map((m) => m.end)); const fullLeds = new Array(totalLedCount).fill('rgba(255,255,255,0.5)'); ledStripStore.mappers.forEach((mapper) => { for (let i = mapper.start, j = 0; i < mapper.end; i++, j++) { - fullLeds[i] = `rgb(${ledStripStore.colors[i * 3]}, ${ - ledStripStore.colors[i * 3 + 1] - }, ${ledStripStore.colors[i * 3 + 2]})`; + fullLeds[i] = `rgb(${ledStripStore.sortedColors[i * 3]}, ${ + ledStripStore.sortedColors[i * 3 + 1] + }, ${ledStripStore.sortedColors[i * 3 + 2]})`; } }); setFullLeds(fullLeds); diff --git a/src/stores/led-strip.store.tsx b/src/stores/led-strip.store.tsx index b5c69b1..e4a2d2b 100644 --- a/src/stores/led-strip.store.tsx +++ b/src/stores/led-strip.store.tsx @@ -7,4 +7,5 @@ export const [ledStripStore, setLedStripStore] = createStore({ strips: new Array(), mappers: new Array(), colors: new Uint8ClampedArray(), + sortedColors: new Array(), });