@@ -9,7 +9,7 @@ use cosmic::iced::{
99 stream,
1010} ;
1111use ddc_hi:: { Ddc , Display } ;
12- use tokio:: sync :: watch :: Receiver ;
12+ use tokio:: time :: sleep ;
1313
1414use crate :: app:: Message ;
1515
@@ -30,110 +30,162 @@ pub enum EventToSub {
3030}
3131
3232enum 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+
3840pub 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