Skip to content

Commit 25ba940

Browse files
committed
attempt to fix crash on amd
1 parent fd3c3d3 commit 25ba940

File tree

2 files changed

+146
-93
lines changed

2 files changed

+146
-93
lines changed

src/app.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use cosmic::app::{Core, Task};
44
use cosmic::applet::padded_control;
55
use cosmic::cosmic_config::CosmicConfigEntry;
66
use cosmic::cosmic_theme::{ThemeMode, THEME_MODE_ID};
7+
use cosmic::iced::futures::executor::block_on;
78
use cosmic::iced::window::Id;
89
use cosmic::iced::{Alignment, Length, Limits, Subscription};
910
use cosmic::iced_runtime::core::window;
@@ -15,7 +16,7 @@ use cosmic::{iced_runtime, Element};
1516
// use tokio::sync::mpsc::Sender;
1617
use crate::monitor::{DisplayId, EventToSub, Monitor};
1718
use crate::{fl, monitor};
18-
use tokio::sync::watch::Sender;
19+
use tokio::sync::mpsc::Sender;
1920

2021
const ID: &str = "io.github.maciekk64.CosmicExtAppletExternalMonitorBrightness";
2122
const ICON_HIGH: &str = "cosmic-applet-battery-display-brightness-high-symbolic";
@@ -41,15 +42,13 @@ pub enum Message {
4142
ThemeModeConfigChanged(ThemeMode),
4243
SetDarkMode(bool),
4344
Ready((HashMap<DisplayId, Monitor>, Sender<EventToSub>)),
44-
BrightnessWasUpdated(DisplayId, u16),
45+
BrightnessWasUpdated(HashMap<DisplayId, u16>),
4546
}
4647

4748
impl Window {
4849
pub fn send(&self, e: EventToSub) {
4950
if let Some(sender) = &self.sender {
50-
sender.send(e).unwrap();
51-
52-
// block_on(sender.send(e)).unwrap();
51+
block_on(sender.send(e)).unwrap();
5352
}
5453
}
5554
}
@@ -139,9 +138,11 @@ impl cosmic::Application for Window {
139138
self.monitors = mon;
140139
self.sender.replace(sender);
141140
}
142-
Message::BrightnessWasUpdated(id, value) => {
143-
if let Some(monitor) = self.monitors.get_mut(&id) {
144-
monitor.brightness = value;
141+
Message::BrightnessWasUpdated(updates) => {
142+
for (id, value) in updates {
143+
if let Some(monitor) = self.monitors.get_mut(&id) {
144+
monitor.brightness = value;
145+
}
145146
}
146147
}
147148
}

src/monitor.rs

Lines changed: 137 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use cosmic::iced::{
99
stream,
1010
};
1111
use ddc_hi::{Ddc, Display};
12-
use tokio::sync::watch::Receiver;
12+
use tokio::time::sleep;
1313

1414
use crate::app::Message;
1515

@@ -30,110 +30,162 @@ pub enum EventToSub {
3030
}
3131

3232
enum State {
33-
Waiting,
34-
Fetch,
35-
Ready(HashMap<String, Arc<Mutex<Display>>>, Receiver<EventToSub>),
33+
Fetching,
34+
Ready,
3635
}
3736

37+
const MAX_WAITING: Duration = Duration::from_secs(4);
38+
const DEFAULT_WAITING: Duration = Duration::from_millis(50);
39+
3840
pub fn sub() -> impl Stream<Item = Message> {
3941
stream::channel(100, |mut output| async move {
40-
let mut state = State::Waiting;
42+
let displays = Arc::new(Mutex::new(HashMap::new()));
43+
44+
let mut rx = {
45+
let mut res = HashMap::new();
46+
47+
for display in Display::enumerate() {
48+
let mon = Monitor {
49+
name: display.info.model_name.clone().unwrap_or_default(),
50+
brightness: 0,
51+
};
52+
53+
res.insert(display.info.id.clone(), mon);
54+
displays
55+
.lock()
56+
.unwrap()
57+
.insert(display.info.id.clone(), display);
58+
}
59+
60+
let (tx, rx) = tokio::sync::mpsc::channel(100);
61+
output.send(Message::Ready((res, tx))).await.unwrap();
62+
rx
63+
};
64+
65+
let mut state = State::Fetching;
66+
let mut duration = DEFAULT_WAITING;
4167

42-
let mut duration = Duration::from_millis(50);
68+
let mut request_buff = Vec::new();
4369

4470
loop {
4571
match &mut state {
46-
State::Waiting => {
72+
State::Fetching => {
4773
tokio::time::sleep(duration).await;
48-
duration *= 2;
49-
state = State::Fetch;
50-
}
51-
State::Fetch => {
52-
let mut res = HashMap::new();
53-
54-
let mut displays = HashMap::new();
55-
56-
debug!("start enumerate");
57-
58-
for mut display in Display::enumerate() {
59-
let brightness = match display.handle.get_vcp_feature(BRIGHTNESS_CODE) {
60-
Ok(v) => v.value(),
61-
Err(e) => {
62-
// on my machine, i get this error when starting the session
63-
// can't get_vcp_feature: DDC/CI error: Expected DDC/CI length bit
64-
// This go away after the third attempt
65-
error!("can't get_vcp_feature: {e}");
66-
state = State::Waiting;
67-
break;
68-
}
69-
};
7074

71-
let mon = Monitor {
72-
name: display.info.model_name.clone().unwrap_or_default(),
73-
brightness,
74-
};
75+
let (error, res) = {
76+
let displays = displays.clone();
77+
78+
let j = tokio::task::spawn_blocking(move || {
79+
let mut res = HashMap::new();
80+
81+
let mut displays = displays.lock().unwrap();
7582

76-
res.insert(display.info.id.clone(), mon);
77-
displays.insert(display.info.id.clone(), Arc::new(Mutex::new(display)));
83+
debug!("start enumerate");
84+
for (id, display) in displays.iter_mut() {
85+
match display.handle.get_vcp_feature(BRIGHTNESS_CODE) {
86+
Ok(v) => {
87+
res.insert(id.clone(), v.value());
88+
}
89+
Err(e) => {
90+
// on my machine, i get this error when starting the session
91+
// can't get_vcp_feature: DDC/CI error: Expected DDC/CI length bit
92+
// This go away after the third attempt
93+
error!("can't get_vcp_feature: {e}");
94+
continue;
95+
}
96+
};
97+
}
98+
(res.len() != displays.len(), res)
99+
});
100+
101+
j.await.unwrap()
102+
};
103+
104+
output
105+
.send(Message::BrightnessWasUpdated(res))
106+
.await
107+
.unwrap();
108+
109+
if error {
110+
duration *= 2;
111+
if duration > MAX_WAITING {
112+
state = State::Ready;
113+
duration = DEFAULT_WAITING;
114+
}
115+
} else {
116+
duration = DEFAULT_WAITING;
117+
state = State::Ready;
118+
}
119+
}
120+
State::Ready => {
121+
if let Some(e) = rx.recv().await {
122+
request_buff.push(e);
78123
}
79124

80-
if let State::Waiting = state {
81-
continue;
125+
while let Ok(e) = rx.try_recv() {
126+
request_buff.push(e);
82127
}
83128

84-
debug!("end enumerate");
129+
let mut set = HashMap::new();
130+
let mut refresh = false;
85131

86-
let (tx, mut rx) = tokio::sync::watch::channel(EventToSub::Refresh);
87-
rx.mark_unchanged();
132+
for request in request_buff.drain(..) {
133+
match request {
134+
EventToSub::Refresh => refresh = true,
135+
EventToSub::Set(id, value) => {
136+
set.insert(id, value);
137+
}
138+
}
139+
}
88140

89-
output.send(Message::Ready((res, tx))).await.unwrap();
90-
state = State::Ready(displays, rx);
91-
}
92-
State::Ready(displays, rx) => {
93-
rx.changed().await.unwrap();
94-
95-
let last = rx.borrow_and_update().clone();
96-
match last {
97-
EventToSub::Refresh => {
98-
for (id, display) in displays {
99-
let res = display
100-
.lock()
101-
.unwrap()
102-
.handle
103-
.get_vcp_feature(BRIGHTNESS_CODE);
104-
105-
match res {
106-
Ok(value) => {
107-
output
108-
.send(Message::BrightnessWasUpdated(
109-
id.clone(),
110-
value.value(),
111-
))
112-
.await
113-
.unwrap();
141+
if refresh {
142+
let displays = displays.clone();
143+
144+
let j = tokio::task::spawn_blocking(move || {
145+
let mut res = HashMap::new();
146+
147+
for (id, display) in displays.lock().unwrap().iter_mut() {
148+
match display.handle.get_vcp_feature(BRIGHTNESS_CODE) {
149+
Ok(v) => {
150+
res.insert(id.clone(), v.value());
114151
}
115-
Err(err) => error!("{:?}", err),
116-
}
152+
Err(e) => {
153+
// on my machine, i get this error when starting the session
154+
// can't get_vcp_feature: DDC/CI error: Expected DDC/CI length bit
155+
// This go away after the third attempt
156+
error!("can't get_vcp_feature: {e}");
157+
continue;
158+
}
159+
};
117160
}
118-
}
119-
EventToSub::Set(id, value) => {
120-
let display = displays.get_mut(&id).unwrap().clone();
121-
122-
let j = tokio::task::spawn_blocking(move || {
123-
if let Err(err) = display
124-
.lock()
125-
.unwrap()
126-
.handle
127-
.set_vcp_feature(BRIGHTNESS_CODE, value)
128-
{
129-
error!("{:?}", err);
130-
}
131-
});
132-
133-
j.await.unwrap();
134-
tokio::time::sleep(Duration::from_millis(50)).await;
135-
}
161+
res
162+
});
163+
164+
let res = j.await.unwrap();
165+
166+
output
167+
.send(Message::BrightnessWasUpdated(res))
168+
.await
169+
.unwrap();
136170
}
171+
172+
let displays = displays.clone();
173+
174+
let j = tokio::task::spawn_blocking(move || {
175+
for (id, value) in set.drain() {
176+
let mut displays = displays.lock().unwrap();
177+
178+
let display = displays.get_mut(&id).unwrap();
179+
180+
debug!("set {} to {}", id, value);
181+
if let Err(err) = display.handle.set_vcp_feature(BRIGHTNESS_CODE, value)
182+
{
183+
error!("{:?}", err);
184+
}
185+
}
186+
});
187+
j.await.unwrap();
188+
sleep(Duration::from_millis(50)).await;
137189
}
138190
}
139191
}

0 commit comments

Comments
 (0)