2023-03-26 10:48:50 +08:00
|
|
|
use std::{
|
|
|
|
borrow::Borrow,
|
|
|
|
collections::HashMap,
|
|
|
|
ops::Sub,
|
|
|
|
sync::Arc,
|
|
|
|
time::{Duration, SystemTime},
|
|
|
|
};
|
|
|
|
|
|
|
|
use base64::Config;
|
|
|
|
use ddc_hi::Display;
|
|
|
|
use paris::{error, info, warn};
|
|
|
|
use tauri::async_runtime::Mutex;
|
|
|
|
use tokio::sync::{broadcast, OwnedMutexGuard};
|
|
|
|
use tracing::warn;
|
|
|
|
|
|
|
|
use crate::{display::Brightness, models, rpc};
|
|
|
|
|
|
|
|
use super::{display_config::DisplayConfig, DisplayBrightness};
|
|
|
|
use ddc_hi::Ddc;
|
|
|
|
|
|
|
|
pub struct Manager {
|
|
|
|
displays: Arc<Mutex<HashMap<usize, Arc<Mutex<DisplayConfig>>>>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Manager {
|
|
|
|
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())
|
|
|
|
}
|
|
|
|
|
|
|
|
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 mut rx = rpc.client().subscribe_change_display_brightness_rx();
|
|
|
|
|
|
|
|
loop {
|
|
|
|
if let Ok(display_brightness) = rx.recv().await {
|
|
|
|
if let Err(err) = self.set_display_brightness(display_brightness).await {
|
|
|
|
error!("set_display_brightness failed. {:?}", err);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
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, target as u16)
|
|
|
|
.map_err(|err| anyhow::anyhow!("can not set brightness. {:?}", err))?;
|
|
|
|
|
|
|
|
let rpc = rpc::Manager::global().await;
|
|
|
|
|
|
|
|
rpc.publish_desktop_cmd(
|
2023-04-01 18:43:49 +08:00
|
|
|
format!("display{}/brightness", display_brightness.display_index)
|
|
|
|
.as_str(),
|
2023-03-26 10:48:50 +08:00
|
|
|
target.to_be_bytes().to_vec(),
|
|
|
|
)
|
|
|
|
.await;
|
|
|
|
}
|
|
|
|
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 => {
|
|
|
|
warn!("display#{} is not found.", display_brightness.display_index);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|