From 98509250d654c879b19e348fd5abef85d590c55e Mon Sep 17 00:00:00 2001 From: 4yn Date: Mon, 7 Feb 2022 10:10:36 +0800 Subject: [PATCH] timer --- public/global.css | 16 ++++++++- public/index.html | 9 +---- src-tauri/Cargo.lock | 20 ++++++++++- src-tauri/Cargo.toml | 5 ++- src-tauri/src/main.rs | 9 +++-- src-tauri/src/slider_io/context.rs | 54 +++++++++++++++++++++++------- src-tauri/src/slider_io/device.rs | 15 +++++---- src-tauri/src/slider_io/led.rs | 7 ++-- src-tauri/src/slider_io/manager.rs | 10 ++++++ src-tauri/src/slider_io/output.rs | 7 ++-- src-tauri/src/slider_io/utils.rs | 50 ++++++++++++++++++++++++++- src-tauri/src/slider_io/worker.rs | 10 ++++-- src-tauri/tauri.conf.json | 2 +- src/App.svelte | 38 ++++++++++++++------- 14 files changed, 199 insertions(+), 53 deletions(-) diff --git a/public/global.css b/public/global.css index faf38f0..3a665ee 100644 --- a/public/global.css +++ b/public/global.css @@ -33,7 +33,7 @@ body { background: #333; display: flex; align-items: center; - justify-content: flex-start; + justify-content: space-between; position: fixed; top: 0; left: 0; @@ -42,8 +42,13 @@ body { height: 2rem; } +.titlebar-front { + background: #0000; +} + .header-icon { max-height: 100%; + flex: 0 0 auto; } .header-icon img { @@ -54,6 +59,15 @@ body { .header { font-size: 1.5rem; font-weight: 500; + flex: 0 0 auto; +} + +.header-space { + flex: 1 0 auto; +} + +.header-timer { + flex: 0 0 auto; } /* main */ diff --git a/public/index.html b/public/index.html index c05072b..0d21921 100644 --- a/public/index.html +++ b/public/index.html @@ -13,12 +13,5 @@ - -
-
- -
-
 slidershim
-
- + diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index e861488..2cf8b44 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -115,6 +115,12 @@ dependencies = [ "system-deps 3.2.0", ] +[[package]] +name = "atomic_float" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62af46d040ba9df09edc6528dae9d8e49f5f3e82f55b7d2ec31a733c38dbc49d" + [[package]] name = "attohttpc" version = "0.17.0" @@ -2933,9 +2939,10 @@ checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" [[package]] name = "slidershim" -version = "0.1.2" +version = "0.1.3" dependencies = [ "async-trait", + "atomic_float", "base64", "directories", "env_logger", @@ -2954,6 +2961,7 @@ dependencies = [ "serde_json", "serialport", "simple-logging", + "spin_sleep", "tauri", "tauri-build", "tokio", @@ -2995,6 +3003,16 @@ dependencies = [ "system-deps 1.3.2", ] +[[package]] +name = "spin_sleep" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a98101bdc3833e192713c2af0b0dd2614f50d1cf1f7a97c5221b7aac052acc7" +dependencies = [ + "once_cell", + "winapi", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index cfccfff..48af9fc 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "slidershim" -version = "0.1.2" +version = "0.1.3" description = "slidershim" authors = ["4yn"] license = "" @@ -21,8 +21,11 @@ log = "0.4.14" env_logger = "0.9.0" simple-logging = "2.0.2" open = "2.0.2" +atomic_float = "0.1.0" +spin_sleep = "1.0.0" tauri = { version = "1.0.0-beta.8", features = ["shell-open", "system-tray"] } + futures = "0.3.19" futures-util = "0.3.19" async-trait = "0.1.52" diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 4523094..30f93fa 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -140,9 +140,12 @@ fn main() { let manager_clone = Arc::clone(&manager); app.listen_global("queryState", move |_| { // app_handle.emit_all("showState", "@@@"); - let snapshot = { + let (snapshot, timer) = { let manager_handle = manager_clone.lock().unwrap(); - manager_handle.try_get_state().map(|x| x.snapshot()) + ( + manager_handle.try_get_state().map(|x| x.snapshot()), + manager_handle.get_timer_state(), + ) }; match snapshot { Some(snapshot) => { @@ -150,6 +153,8 @@ fn main() { } _ => {} } + + app_handle.emit_all("showTimerState", timer).ok(); }); // Config set event diff --git a/src-tauri/src/slider_io/context.rs b/src-tauri/src/slider_io/context.rs index 9725590..1731b2c 100644 --- a/src-tauri/src/slider_io/context.rs +++ b/src-tauri/src/slider_io/context.rs @@ -1,4 +1,6 @@ +use atomic_float::AtomicF64; use log::info; +use std::sync::{atomic::Ordering, Arc}; use crate::slider_io::{ brokenithm::BrokenithmJob, @@ -7,6 +9,7 @@ use crate::slider_io::{ device::HidDeviceJob, led::LedJob, output::OutputJob, + utils::LoopTimer, worker::{AsyncWorker, ThreadWorker}, }; @@ -18,6 +21,7 @@ pub struct Context { brokenithm_worker: Option, output_worker: Option, led_worker: Option, + timers: Vec<(&'static str, Arc)>, } impl Context { @@ -28,6 +32,7 @@ impl Context { info!("LED config {:?}", config.led_mode); let state = FullState::new(); + let mut timers = vec![]; let (device_worker, brokenithm_worker) = match &config.device_mode { DeviceMode::None => (None, None), @@ -42,26 +47,41 @@ impl Context { )), ), _ => ( - Some(ThreadWorker::new( - "device", - HidDeviceJob::from_config(&state, &config.device_mode), - )), + { + let timer = LoopTimer::new(); + timers.push(("d", timer.fork())); + Some(ThreadWorker::new( + "device", + HidDeviceJob::from_config(&state, &config.device_mode), + timer, + )) + }, None, ), }; let output_worker = match &config.output_mode { OutputMode::None => None, - _ => Some(ThreadWorker::new( - "output", - OutputJob::new(&state, &config.output_mode), - )), + _ => { + let timer = LoopTimer::new(); + timers.push(("o", timer.fork())); + Some(ThreadWorker::new( + "output", + OutputJob::new(&state, &config.output_mode), + timer, + )) + } }; let led_worker = match &config.led_mode { LedMode::None => None, - _ => Some(ThreadWorker::new( - "led", - LedJob::new(&state, &config.led_mode), - )), + _ => { + let timer = LoopTimer::new(); + timers.push(("l", timer.fork())); + Some(ThreadWorker::new( + "led", + LedJob::new(&state, &config.led_mode), + timer, + )) + } }; Self { @@ -71,10 +91,20 @@ impl Context { brokenithm_worker, output_worker, led_worker, + timers, } } pub fn clone_state(&self) -> FullState { self.state.clone() } + + pub fn timer_state(&self) -> String { + self + .timers + .iter() + .map(|(s, f)| format!("{}:{:.1}/s", s, f.load(Ordering::SeqCst))) + .collect::>() + .join(" ") + } } diff --git a/src-tauri/src/slider_io/device.rs b/src-tauri/src/slider_io/device.rs index 0706456..8847e35 100644 --- a/src-tauri/src/slider_io/device.rs +++ b/src-tauri/src/slider_io/device.rs @@ -101,9 +101,9 @@ impl HidDeviceJob { .take(31) .zip(led_state.led_state.chunks(3).rev()) { - buf_chunk[0] = state_chunk[2]; + buf_chunk[0] = state_chunk[1]; buf_chunk[1] = state_chunk[0]; - buf_chunk[2] = state_chunk[1]; + buf_chunk[2] = state_chunk[2]; } buf.data[96..240].fill(0); }, @@ -139,9 +139,9 @@ impl HidDeviceJob { .take(31) .zip(led_state.led_state.chunks(3).rev()) { - buf_chunk[0] = state_chunk[2]; + buf_chunk[0] = state_chunk[1]; buf_chunk[1] = state_chunk[0]; - buf_chunk[2] = state_chunk[1]; + buf_chunk[2] = state_chunk[2]; } buf.data[96..240].fill(0); }, @@ -224,9 +224,10 @@ impl ThreadJob for HidDeviceJob { } } - fn tick(&mut self) { + fn tick(&mut self) -> bool { // Input loop let handle = self.handle.as_mut().unwrap(); + let mut work = false; { let res = handle @@ -239,6 +240,7 @@ impl ThreadJob for HidDeviceJob { self.read_buf.len = res; // debug!("{:?}", self.read_buf.slice()); if self.read_buf.len != 0 { + work = true; let mut controller_state_handle = self.state.controller_state.lock().unwrap(); (self.read_callback)(&self.read_buf, controller_state_handle.deref_mut()); } @@ -267,12 +269,13 @@ impl ThreadJob for HidDeviceJob { }) .unwrap_or(0); if res == self.led_buf.len + 1 { + work = true; self.led_buf.len = 0; } } } - // thread::sleep(Duration::from_millis(10)); + work } fn teardown(&mut self) { diff --git a/src-tauri/src/slider_io/led.rs b/src-tauri/src/slider_io/led.rs index c70b6cd..5995d1d 100644 --- a/src-tauri/src/slider_io/led.rs +++ b/src-tauri/src/slider_io/led.rs @@ -174,7 +174,7 @@ impl ThreadJob for LedJob { } } - fn tick(&mut self) { + fn tick(&mut self) -> bool { let mut flat_controller_state: Option> = None; let mut serial_buffer: Option = None; @@ -217,7 +217,10 @@ impl ThreadJob for LedJob { led_state_handle.deref_mut(), ); } - thread::sleep(Duration::from_millis(30)); + // thread::sleep(Duration::from_millis(30)); + spin_sleep::sleep(Duration::from_millis(30)); + + true } fn teardown(&mut self) {} diff --git a/src-tauri/src/slider_io/manager.rs b/src-tauri/src/slider_io/manager.rs index 1266c11..2b8a1c8 100644 --- a/src-tauri/src/slider_io/manager.rs +++ b/src-tauri/src/slider_io/manager.rs @@ -14,6 +14,7 @@ use super::controller_state::FullState; pub struct Manager { state: Arc>>, + context: Arc>>, join_handle: Option>, tx_config: mpsc::UnboundedSender, tx_stop: Option>, @@ -70,6 +71,7 @@ impl Manager { Self { state, + context, join_handle: Some(join_handle), tx_config, tx_stop: Some(tx_stop), @@ -84,6 +86,14 @@ impl Manager { let state_handle = self.state.lock().unwrap(); state_handle.as_ref().map(|x| x.clone()) } + + pub fn get_timer_state(&self) -> String { + let context_handle = self.context.lock().unwrap(); + context_handle + .as_ref() + .map(|context| context.timer_state()) + .unwrap_or("".to_string()) + } } impl Drop for Manager { diff --git a/src-tauri/src/slider_io/output.rs b/src-tauri/src/slider_io/output.rs index 8f13f30..f12da4e 100644 --- a/src-tauri/src/slider_io/output.rs +++ b/src-tauri/src/slider_io/output.rs @@ -50,7 +50,7 @@ impl ThreadJob for OutputJob { true } - fn tick(&mut self) { + fn tick(&mut self) -> bool { let flat_controller_state: Vec; { let controller_state_handle = self.state.controller_state.lock().unwrap(); @@ -58,7 +58,10 @@ impl ThreadJob for OutputJob { } self.handler.tick(&flat_controller_state); - thread::sleep(Duration::from_millis(self.t)); + // thread::sleep(Duration::from_millis(self.t)); + spin_sleep::sleep(Duration::from_millis(self.t)); + + true } fn teardown(&mut self) { diff --git a/src-tauri/src/slider_io/utils.rs b/src-tauri/src/slider_io/utils.rs index 7cc42ba..95b9446 100644 --- a/src-tauri/src/slider_io/utils.rs +++ b/src-tauri/src/slider_io/utils.rs @@ -1,4 +1,10 @@ -use std::{error::Error, fmt}; +use atomic_float::AtomicF64; +use std::{ + error::Error, + fmt, + sync::{atomic::Ordering, Arc}, + time::{Duration, Instant}, +}; pub struct Buffer { pub data: [u8; 256], @@ -44,3 +50,45 @@ pub fn list_ips() -> Result, Box> { Ok(ips) } + +pub struct LoopTimer { + cap: usize, + cur: usize, + buf: Vec, + freq: Arc, +} + +impl LoopTimer { + pub fn new() -> Self { + Self { + cap: 100, + cur: 0, + buf: vec![Instant::now() - Duration::from_secs(10); 100], + freq: Arc::new(AtomicF64::new(0.0)), + } + } + pub fn tick(&mut self) { + let last = self.buf[self.cur]; + let now = Instant::now(); + self.buf[self.cur] = now; + + let delta = (now - last) / 100 + Duration::from_micros(1); + let freq = Duration::from_millis(1000) + .div_duration_f64(delta) + .clamp(0.0, 9999.0); + self.freq.store(freq, Ordering::SeqCst); + + self.cur = match self.cur + 1 { + cur if cur == self.cap => 0, + cur => cur, + } + } + + // pub fn reset(&mut self) { + // self.buf = vec![Instant::now(); 100]; + // } + + pub fn fork(&self) -> Arc { + Arc::clone(&self.freq) + } +} diff --git a/src-tauri/src/slider_io/worker.rs b/src-tauri/src/slider_io/worker.rs index b0145da..4828193 100644 --- a/src-tauri/src/slider_io/worker.rs +++ b/src-tauri/src/slider_io/worker.rs @@ -11,9 +11,11 @@ use std::{ use tokio::{sync::oneshot, task}; +use crate::slider_io::utils::LoopTimer; + pub trait ThreadJob: Send { fn setup(&mut self) -> bool; - fn tick(&mut self); + fn tick(&mut self) -> bool; fn teardown(&mut self); } @@ -24,7 +26,7 @@ pub struct ThreadWorker { } impl ThreadWorker { - pub fn new(name: &'static str, mut job: T) -> Self { + pub fn new(name: &'static str, mut job: T, mut timer: LoopTimer) -> Self { info!("Thread worker starting {}", name); let stop_signal = Arc::new(AtomicBool::new(false)); @@ -40,7 +42,9 @@ impl ThreadWorker { if stop_signal_clone.load(Ordering::SeqCst) { break; } - job.tick(); + if job.tick() { + timer.tick(); + } } info!("Thread worker stopping internal {}", name); job.teardown(); diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index dcd38c4..a803871 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "package": { "productName": "slidershim", - "version": "0.1.2" + "version": "0.1.3" }, "build": { "distDir": "../public", diff --git a/src/App.svelte b/src/App.svelte index e3a85d4..d62202f 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -1,7 +1,7 @@ +
+
+ +
+
+  slidershim{versionString} +
+
+
+ {timerData} +
+
+
- - - - - - -
@@ -148,7 +158,9 @@ - +
@@ -192,7 +204,7 @@ - +