feat: 支持调整程序内存中暂存的显示器配置。

This commit is contained in:
Ivan Li 2023-05-07 14:32:31 +08:00
parent 3a430716d6
commit 239144a446
7 changed files with 155 additions and 28 deletions

View File

@ -5,14 +5,16 @@ use std::{
use ddc_hi::Display; use ddc_hi::Display;
use paris::{error, info, warn}; use paris::{error, info, warn};
use tokio::sync::{OnceCell, RwLock}; use tokio::{sync::{watch, OnceCell, RwLock}, task::yield_now};
use super::{display_state::DisplayState, display_handler::DisplayHandler};
use crate::rpc::{BoardMessageChannels, DisplaySetting};
use super::{display_handler::DisplayHandler, display_state::DisplayState};
pub struct DisplayManager { pub struct DisplayManager {
displays: Arc<RwLock<Vec<Arc<RwLock<DisplayHandler>>>>>, displays: Arc<RwLock<Vec<Arc<RwLock<DisplayHandler>>>>>,
setting_request_handler: Option<tokio::task::JoinHandle<()>>,
displays_changed_sender: Arc<watch::Sender<Vec<DisplayState>>>,
} }
impl DisplayManager { impl DisplayManager {
@ -23,10 +25,16 @@ impl DisplayManager {
} }
pub async fn create() -> Self { pub async fn create() -> Self {
let instance = Self { let (displays_changed_sender, _) = watch::channel(Vec::new());
let displays_changed_sender = Arc::new(displays_changed_sender);
let mut instance = Self {
displays: Arc::new(RwLock::new(Vec::new())), displays: Arc::new(RwLock::new(Vec::new())),
setting_request_handler: None,
displays_changed_sender,
}; };
instance.fetch_displays().await; instance.fetch_displays().await;
instance.subscribe_setting_request();
instance instance
} }
@ -60,19 +68,57 @@ impl DisplayManager {
states states
} }
// pub async fn subscribe_display_brightness(&self) { fn subscribe_setting_request(&mut self) {
// let rpc = rpc::Manager::global().await; let displays = self.displays.clone();
let displays_changed_sender = self.displays_changed_sender.clone();
log::info!("start display setting request handler");
let handler = tokio::spawn(async move {
let channels = BoardMessageChannels::global().await;
// let mut rx = rpc.client().subscribe_change_display_brightness_rx(); let mut request_rx = channels.display_setting_request_sender.subscribe();
// loop { log::info!("display setting request handler started");
// if let Ok(display_brightness) = rx.recv().await {
// if let Err(err) = self.set_display_brightness(display_brightness).await { while let Ok(message) = request_rx.recv().await {
// error!("set_display_brightness failed. {:?}", err); let displays = displays.write().await;
// }
// } let display = displays.get(message.display_index);
// } if display.is_none() {
// } warn!("display#{} not found", message.display_index);
continue;
}
log::info!("display setting request received. {:?}", message);
let display = display.unwrap().write().await;
match message.setting {
DisplaySetting::Brightness(value) => display.set_brightness(value as u16).await,
DisplaySetting::Contrast(value) => display.set_contrast(value as u16).await,
DisplaySetting::Mode(value) => display.set_mode(value as u16).await,
}
drop(display);
log::info!("display setting request handled. {:?}", message);
let mut states = Vec::new();
for display in displays.iter() {
let state = display.read().await.state.read().await.clone();
states.push(state);
}
if let Err(err) = displays_changed_sender.send(states) {
error!("failed to send displays changed event: {}", err);
}
yield_now().await;
}
});
self.setting_request_handler = Some(handler);
}
pub fn subscribe_displays_changed(&self) -> watch::Receiver<Vec<DisplayState>> {
self.displays_changed_sender.subscribe()
}
// fn read_display_config_by_ddc(index: usize) -> anyhow::Result<DisplayState> { // fn read_display_config_by_ddc(index: usize) -> anyhow::Result<DisplayState> {
// let mut displays = Display::enumerate(); // let mut displays = Display::enumerate();
@ -208,3 +254,11 @@ impl DisplayManager {
// Ok(()) // Ok(())
// } // }
} }
impl Drop for DisplayManager {
fn drop(&mut self) {
if let Some(handler) = self.setting_request_handler.take() {
handler.abort();
}
}
}

View File

@ -450,6 +450,20 @@ async fn main() {
} }
}); });
let app_handle = app.handle().clone();
tokio::spawn(async move {
let display_manager = DisplayManager::global().await;
let mut rx =display_manager.subscribe_displays_changed();
while rx.changed().await.is_ok() {
let displays = rx.borrow().clone();
log::info!("displays changed. emit displays_changed event.");
app_handle.emit_all("displays_changed", displays).unwrap();
}
});
Ok(()) Ok(())
}) })
.run(tauri::generate_context!()) .run(tauri::generate_context!())

View File

@ -1,9 +1,11 @@
use std::{sync::Arc, time::Duration}; use std::{sync::Arc, time::Duration};
use paris::{info, warn, error}; use paris::{error, info, warn};
use tokio::{net::UdpSocket, sync::RwLock, time::timeout, io}; use tokio::{io, net::UdpSocket, sync::RwLock, time::timeout, task::yield_now};
use super::{BoardConnectStatus, BoardInfo}; use crate::rpc::DisplaySettingRequest;
use super::{BoardConnectStatus, BoardInfo, UdpRpc};
#[derive(Debug)] #[derive(Debug)]
pub struct Board { pub struct Board {
@ -31,16 +33,34 @@ impl Board {
let info = self.info.clone(); let info = self.info.clone();
let handler=tokio::spawn(async move { let handler = tokio::spawn(async move {
let mut buf = [0u8; 128]; let mut buf = [0u8; 128];
if let Err(err) = socket.readable().await { if let Err(err) = socket.readable().await {
error!("socket read error: {:?}", err); error!("socket read error: {:?}", err);
return; return;
} }
let board_message_channels = crate::rpc::channels::BoardMessageChannels::global().await;
let display_setting_request_sender = board_message_channels.display_setting_request_sender.clone();
loop { loop {
match socket.try_recv(&mut buf) { match socket.try_recv(&mut buf) {
Ok(len) => { Ok(len) => {
log::info!("recv: {:?}", &buf[..len]); log::info!("recv: {:?}", &buf[..len]);
if buf[0] == 3 {
let result = display_setting_request_sender.send(DisplaySettingRequest {
display_index: buf[1] as usize,
setting: crate::rpc::DisplaySetting::Brightness(buf[2]),
});
if let Err(err) = result {
error!("send display setting request to channel failed: {:?}", err);
} else {
info!("send display setting request to channel success");
yield_now().await;
}
}
} }
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
continue; continue;
@ -125,7 +145,6 @@ impl Board {
} }
} }
impl Drop for Board { impl Drop for Board {
fn drop(&mut self) { fn drop(&mut self) {
if let Some(handler) = self.listen_handler.take() { if let Some(handler) = self.listen_handler.take() {
@ -136,4 +155,4 @@ impl Drop for Board {
info!("listen handler aborted"); info!("listen handler aborted");
} }
} }
} }

View File

@ -0,0 +1,26 @@
use std::sync::Arc;
use tokio::sync::{broadcast, OnceCell};
use super::DisplaySettingRequest;
pub struct BoardMessageChannels {
pub display_setting_request_sender: Arc<broadcast::Sender<DisplaySettingRequest>>,
}
impl BoardMessageChannels {
pub async fn global() -> &'static Self {
static BOARD_MESSAGE_CHANNELS: OnceCell<BoardMessageChannels> = OnceCell::const_new();
BOARD_MESSAGE_CHANNELS.get_or_init(|| async {Self::new()}).await
}
pub fn new() -> Self {
let (display_setting_request_sender, _) = broadcast::channel(16);
let display_setting_request_sender = Arc::new(display_setting_request_sender);
Self {
display_setting_request_sender,
}
}
}

View File

@ -0,0 +1,13 @@
#[derive(Clone, Debug)]
pub enum DisplaySetting {
Brightness(u8),
Contrast(u8),
Mode(u8),
}
#[derive(Clone, Debug)]
pub struct DisplaySettingRequest {
pub display_index: usize,
pub setting: DisplaySetting,
}

View File

@ -2,8 +2,12 @@ mod board_info;
mod mqtt; mod mqtt;
mod udp; mod udp;
mod board; mod board;
mod display_setting_request;
mod channels;
pub use board_info::*; pub use board_info::*;
pub use mqtt::*; pub use mqtt::*;
pub use udp::*; pub use udp::*;
pub use board::*; pub use board::*;
pub use display_setting_request::*;
pub use channels::*;

View File

@ -1,14 +1,11 @@
use std::{collections::HashMap, net::Ipv4Addr, sync::Arc, time::Duration}; use std::{collections::HashMap, sync::Arc, time::Duration};
use futures::future::join_all; use futures::future::join_all;
use mdns_sd::{ServiceDaemon, ServiceEvent}; use mdns_sd::{ServiceDaemon, ServiceEvent};
use paris::{error, info, warn}; use paris::{error, info, warn};
use tokio::{ use tokio::sync::{watch, OnceCell, RwLock, broadcast};
net::UdpSocket,
sync::{watch, OnceCell, RwLock},
};
use super::{Board, BoardInfo}; use super::{Board, BoardInfo, DisplaySettingRequest};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct UdpRpc { pub struct UdpRpc {
@ -212,7 +209,7 @@ impl UdpRpc {
if let Err(err) = board_change_sender.send(tx_boards) { if let Err(err) = board_change_sender.send(tx_boards) {
error!("failed to send board change: {:?}", err); error!("failed to send board change: {:?}", err);
} }
drop(board_change_sender); drop(board_change_sender);
} }
} }