pref: 缓存显示器参数读数。#5.
This commit is contained in:
25
src-tauri/src/db/db.rs
Normal file
25
src-tauri/src/db/db.rs
Normal file
@@ -0,0 +1,25 @@
|
||||
use std::env::current_dir;
|
||||
|
||||
use once_cell::sync::OnceCell;
|
||||
use redb::Database;
|
||||
use tauri::api::path::config_dir;
|
||||
|
||||
use crate::picker;
|
||||
|
||||
trait GlobalDatabase<T> {
|
||||
fn global() -> &'static T;
|
||||
}
|
||||
|
||||
impl GlobalDatabase<Database> for Database {
|
||||
fn global() -> &'static Database {
|
||||
static GLOBAL_DATABASE: OnceCell<Database> = OnceCell::new();
|
||||
|
||||
GLOBAL_DATABASE.get_or_init(|| {
|
||||
let path = config_dir()
|
||||
.unwrap_or(current_dir().unwrap())
|
||||
.join("main.redb");
|
||||
let db = Database::create(path).unwrap();
|
||||
return db;
|
||||
})
|
||||
}
|
||||
}
|
3
src-tauri/src/db/mod.rs
Normal file
3
src-tauri/src/db/mod.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
mod db;
|
||||
|
||||
pub use db::*;
|
@@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Copy, Serialize, Deserialize, Debug)]
|
||||
pub enum Brightness {
|
||||
Relative(u16),
|
||||
Relative(i16),
|
||||
Absolute(u16),
|
||||
}
|
||||
|
||||
|
36
src-tauri/src/display/display_config.rs
Normal file
36
src-tauri/src/display/display_config.rs
Normal file
@@ -0,0 +1,36 @@
|
||||
use std::time::SystemTime;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Copy, Serialize, Deserialize, Debug)]
|
||||
pub struct DisplayConfig {
|
||||
pub id: usize,
|
||||
pub brightness: u16,
|
||||
pub max_brightness: u16,
|
||||
pub min_brightness: u16,
|
||||
pub contrast: u16,
|
||||
pub max_contrast: u16,
|
||||
pub min_contrast: u16,
|
||||
pub mode: u16,
|
||||
pub max_mode: u16,
|
||||
pub min_mode: u16,
|
||||
pub last_modified_at: SystemTime,
|
||||
}
|
||||
|
||||
impl DisplayConfig {
|
||||
pub fn default(index: usize) -> Self {
|
||||
Self {
|
||||
id: index,
|
||||
brightness: 30,
|
||||
contrast: 50,
|
||||
mode: 0,
|
||||
last_modified_at: SystemTime::now(),
|
||||
max_brightness: 100,
|
||||
min_brightness: 0,
|
||||
max_contrast: 100,
|
||||
min_contrast: 0,
|
||||
max_mode: 15,
|
||||
min_mode: 0,
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,78 +1,175 @@
|
||||
use std::{
|
||||
borrow::Borrow,
|
||||
collections::HashMap,
|
||||
ops::Sub,
|
||||
sync::Arc,
|
||||
time::{Duration, SystemTime},
|
||||
};
|
||||
|
||||
use ddc_hi::Display;
|
||||
use paris::{error, info};
|
||||
use tokio::sync::{broadcast, OnceCell};
|
||||
use tauri::async_runtime::Mutex;
|
||||
use tokio::sync::{broadcast, OwnedMutexGuard};
|
||||
use tracing::warn;
|
||||
|
||||
use crate::{display::Brightness, rpc};
|
||||
|
||||
use super::DisplayBrightness;
|
||||
use super::{display_config::DisplayConfig, DisplayBrightness};
|
||||
use ddc_hi::Ddc;
|
||||
|
||||
pub struct Manager {}
|
||||
pub struct Manager {
|
||||
displays: Arc<Mutex<HashMap<usize, Arc<Mutex<DisplayConfig>>>>>,
|
||||
}
|
||||
|
||||
impl Manager {
|
||||
pub async fn global() -> &'static Self {
|
||||
static DISPLAY_MANAGER: OnceCell<Manager> = OnceCell::const_new();
|
||||
pub fn global() -> &'static Self {
|
||||
static DISPLAY_MANAGER: once_cell::sync::OnceCell<Manager> =
|
||||
once_cell::sync::OnceCell::new();
|
||||
|
||||
DISPLAY_MANAGER.get_or_init(|| Self::create()).await
|
||||
DISPLAY_MANAGER.get_or_init(|| Self::create())
|
||||
}
|
||||
|
||||
pub async fn create() -> Self {
|
||||
pub fn create() -> Self {
|
||||
let instance = Self {
|
||||
displays: Arc::new(Mutex::new(HashMap::new())),
|
||||
};
|
||||
instance
|
||||
}
|
||||
|
||||
pub async fn subscribe_display_brightness(&self) {
|
||||
let rpc = rpc::Manager::global().await;
|
||||
|
||||
let rx = rpc.client().subscribe_change_display_brightness_rx();
|
||||
tokio::spawn(Self::subscribe_display_brightness(rx));
|
||||
let mut rx = rpc.client().subscribe_change_display_brightness_rx();
|
||||
|
||||
Self {}
|
||||
}
|
||||
|
||||
pub async fn subscribe_display_brightness(mut rx: broadcast::Receiver<DisplayBrightness>) {
|
||||
loop {
|
||||
if let Ok(display_brightness) = rx.recv().await {
|
||||
if let Err(err) = Self::set_display_brightness(display_brightness) {
|
||||
if let Err(err) = self.set_display_brightness(display_brightness).await {
|
||||
error!("set_display_brightness failed. {:?}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_display_brightness(display_brightness: DisplayBrightness) -> anyhow::Result<()> {
|
||||
match Display::enumerate().get_mut(display_brightness.display_index) {
|
||||
Some(display) => match display.handle.get_vcp_feature(0x10) {
|
||||
Ok(curr_brightness) => {
|
||||
let curr = curr_brightness.value();
|
||||
info!("curr_brightness: {:?}", curr);
|
||||
let mut target = match display_brightness.brightness {
|
||||
Brightness::Relative(v) => v + curr,
|
||||
Brightness::Absolute(v) => v,
|
||||
};
|
||||
if target.gt(&curr_brightness.maximum()) {
|
||||
target = curr_brightness.maximum();
|
||||
} else if target.lt(&0) {
|
||||
target = 0;
|
||||
fn read_display_config_by_ddc(index: usize) -> anyhow::Result<DisplayConfig> {
|
||||
let mut displays = Display::enumerate();
|
||||
match displays.get_mut(index) {
|
||||
Some(display) => {
|
||||
let mut config = DisplayConfig::default(index);
|
||||
match display.handle.get_vcp_feature(0x10) {
|
||||
Ok(value) => {
|
||||
config.max_brightness = value.maximum();
|
||||
config.min_brightness = 0;
|
||||
config.brightness = value.value();
|
||||
}
|
||||
display
|
||||
.handle
|
||||
.set_vcp_feature(0x10, target)
|
||||
.map_err(|err| anyhow::anyhow!("can not set brightness. {:?}", err))?;
|
||||
Err(_) => {}
|
||||
};
|
||||
match display.handle.get_vcp_feature(0x12) {
|
||||
Ok(value) => {
|
||||
config.max_contrast = value.maximum();
|
||||
config.min_contrast = 0;
|
||||
config.contrast = value.value();
|
||||
}
|
||||
Err(_) => {}
|
||||
};
|
||||
match display.handle.get_vcp_feature(0xdc) {
|
||||
Ok(value) => {
|
||||
config.max_mode = value.maximum();
|
||||
config.min_mode = 0;
|
||||
config.mode = value.value();
|
||||
}
|
||||
Err(_) => {}
|
||||
};
|
||||
|
||||
Ok(config)
|
||||
}
|
||||
None => anyhow::bail!("display#{} is missed.", index),
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_display(&self, index: usize) -> anyhow::Result<OwnedMutexGuard<DisplayConfig>> {
|
||||
let mut displays = self.displays.lock().await;
|
||||
match displays.get_mut(&index) {
|
||||
Some(config) => {
|
||||
let mut config = config.to_owned().lock_owned().await;
|
||||
if config.last_modified_at > SystemTime::now().sub(Duration::from_secs(10)) {
|
||||
info!("cached");
|
||||
return Ok(config);
|
||||
}
|
||||
Err(err) => {
|
||||
info!(
|
||||
"can not get display#{} brightness. {:?}",
|
||||
display_brightness.display_index, err
|
||||
);
|
||||
if let Brightness::Absolute(v) = display_brightness.brightness {
|
||||
return match Self::read_display_config_by_ddc(index) {
|
||||
Ok(config) => {
|
||||
let id = config.id;
|
||||
let value = Arc::new(Mutex::new(config));
|
||||
let valueGuard = value.clone().lock_owned().await;
|
||||
displays.insert(id, value);
|
||||
info!("read form ddc");
|
||||
Ok(valueGuard)
|
||||
}
|
||||
Err(err) => {
|
||||
warn!(
|
||||
"can not read config from display by ddc, use CACHED value. {:?}",
|
||||
err
|
||||
);
|
||||
config.last_modified_at = SystemTime::now();
|
||||
Ok(config)
|
||||
}
|
||||
};
|
||||
}
|
||||
None => {
|
||||
let config = Self::read_display_config_by_ddc(index).map_err(|err| {
|
||||
anyhow::anyhow!(
|
||||
"can not read config from display by ddc,use DEFAULT value. {:?}",
|
||||
err
|
||||
)
|
||||
})?;
|
||||
let id = config.id;
|
||||
let value = Arc::new(Mutex::new(config));
|
||||
let valueGuard = value.clone().lock_owned().await;
|
||||
displays.insert(id, value);
|
||||
Ok(valueGuard)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn set_display_brightness(
|
||||
&self,
|
||||
display_brightness: DisplayBrightness,
|
||||
) -> anyhow::Result<()> {
|
||||
match Display::enumerate().get_mut(display_brightness.display_index) {
|
||||
Some(display) => {
|
||||
match self.get_display(display_brightness.display_index).await {
|
||||
Ok(mut config) => {
|
||||
let curr = config.brightness;
|
||||
info!("curr_brightness: {:?}", curr);
|
||||
let mut target = match display_brightness.brightness {
|
||||
Brightness::Relative(v) => curr.wrapping_add_signed(v),
|
||||
Brightness::Absolute(v) => v,
|
||||
};
|
||||
if target.gt(&config.max_brightness) {
|
||||
target = config.max_brightness;
|
||||
} else if target.lt(&config.min_brightness) {
|
||||
target = config.min_brightness;
|
||||
}
|
||||
config.brightness = target;
|
||||
display
|
||||
.handle
|
||||
.set_vcp_feature(0x10, v)
|
||||
.set_vcp_feature(0x10, target as u16)
|
||||
.map_err(|err| anyhow::anyhow!("can not set brightness. {:?}", err))?;
|
||||
};
|
||||
}
|
||||
},
|
||||
}
|
||||
Err(err) => {
|
||||
info!(
|
||||
"can not get display#{} brightness. {:?}",
|
||||
display_brightness.display_index, err
|
||||
);
|
||||
if let Brightness::Absolute(v) = display_brightness.brightness {
|
||||
display.handle.set_vcp_feature(0x10, v).map_err(|err| {
|
||||
anyhow::anyhow!("can not set brightness. {:?}", err)
|
||||
})?;
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
None => {
|
||||
anyhow::bail!(
|
||||
"display#{} was not found.",
|
||||
display_brightness.display_index
|
||||
);
|
||||
warn!("display#{} is not found.", display_brightness.display_index);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
@@ -1,5 +1,6 @@
|
||||
mod brightness;
|
||||
mod manager;
|
||||
mod display_config;
|
||||
|
||||
pub use brightness::*;
|
||||
pub use manager::*;
|
||||
|
@@ -5,6 +5,7 @@
|
||||
#![feature(bool_to_option)]
|
||||
|
||||
mod core;
|
||||
mod db;
|
||||
mod display;
|
||||
mod picker;
|
||||
mod rpc;
|
||||
@@ -92,7 +93,10 @@ async fn play_mode(target_mode: AmbientLightMode) {
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {display::Manager::global().await;
|
||||
async fn main() {
|
||||
let displayManager = display::Manager::global();
|
||||
tokio::spawn(displayManager.subscribe_display_brightness());
|
||||
|
||||
tauri::Builder::default()
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
take_snapshot,
|
||||
|
@@ -31,7 +31,7 @@ impl MqttRpc {
|
||||
match eventloop.poll().await {
|
||||
Ok(notification) => {
|
||||
let handled = || -> anyhow::Result<()> {
|
||||
println!("MQTT notification = {:?}", notification);
|
||||
// println!("MQTT notification = {:?}", notification);
|
||||
if let Event::Incoming(notification) = notification {
|
||||
if let Incoming::Publish(notification) = notification {
|
||||
match notification.topic.as_str() {
|
||||
|
Reference in New Issue
Block a user