feat: 支持调整程序内存中暂存的显示器配置。
This commit is contained in:
parent
3a430716d6
commit
239144a446
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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!())
|
||||||
|
@ -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 {
|
||||||
@ -37,10 +39,28 @@ impl Board {
|
|||||||
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() {
|
||||||
|
26
src-tauri/src/rpc/channels.rs
Normal file
26
src-tauri/src/rpc/channels.rs
Normal 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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
src-tauri/src/rpc/display_setting_request.rs
Normal file
13
src-tauri/src/rpc/display_setting_request.rs
Normal 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,
|
||||||
|
}
|
@ -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::*;
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user